User Tools


There were many changes to the engine and I'm only starting to rewrite this documentation

Quickstart Tutorial

This tutorial assume you have installed Annwvyn on your computer. The simplest way to do this it to

  1. On windows, install Visual Studio 2017 from Microsoft (Free community edition)
  2. Install latest version of CMake (Windows win64-x64 Installer) from here
  3. Install the Annwvyn SDK from here

Project creation

To create a new Annwvyn project, simply locate your Annwvyn installation and open the “Annwvyn” folder.

  1. Copy the “template” folder and paste it somewhere convenient,
  2. open the CMakeList file, change the “project name” on top of the file.
  3. Use CMake(-gui) to generate a Visual Studio solution (or a Makefile on Linux) and open/build it

Engine presentation

The strictly minimal code for your Annwvyn application is :

#include <Annwvyn.h>
 
using namespace Annwvyn; 
AnnMain()
{
	//Initialize the engine and give the name of the application
	AnnInit("NameOfGame");
 
	//Start the main program loop. Loop will break if engine get signal to quit
	AnnGetEngine()->startGameplayLoop();
 
	//Quit the engine
	AnnQuit();
	return EXIT_SUCCESS;
}

The code that you'll get with the template contains a little bit more details, and explanations in comments.

Beside loading the engine and starting the render loop, this code does nothing really special. You absolutely have to specify a name for your application. This string of text is used to create the window of the application, and by other components, like the AnnFileSystemManager

Including libs

The only header you are required to include is Annwvyn.h.

#include <Annwvyn.h>

But, to speed up build times, the template uses a feature called pre-compiled headers. Visual Studio's compiler is pretty slow at pre-processing header files. If they doesn't change, we don't need to do this every single time we build the game.

This feature require every single .cpp file in the project to include a file called “stdafx.h” on top of it, and it must be the first one.

#include "stdafx.h"

The first time you hit compile, it will pre-built the headers via the stdafx.cpp file. This can take some time, but it should do it only once.

Initialize the engine

main function declaration

For diverse reasons (command line argument parsing. Selection of the entry point between multiple OSes, hook for pre-initialization of development facilities…), the main function declaration is overridden by a macro when using Annwvyn. You application entry point should be defined as this:

AnnMain()
{
//...
}

Using this construct permit you to start and stop the engine with the AnnInit() and AnnQuit() macros. This is not mandadory but permit to hide some rough edges of the initialization process.

namespace

All Annwvyn classes, functions, types and other things are in the Annwvyn namespace. If you want you can declaring you use this namespace

using namespace Annwvyn;

Starting the engine the engine

VR Renderer

There's a number of VR runtimes and API Annwvyn can use. At the time of writing theses lines, there are two renderers Annwvyn ships with.

These works as a “plugin” system. On Windows they are .dll files you ship with your application, on linux the by default renderers are installable on the system in /usr/local/lib/

Annwvyn ships with two renderer plugins

  • Oculus
  • OpenVR

To be able to load one of them, the library must be findable by your program by following the dynamicly loadable library rules of your platform.

Then, in your application you can load them before calling AnnInit.

//This is what the template application do. Oculus only exists on Windows. 
#ifdef _WIN32
AnnEngine::registerVRRenderer("Oculus");
#endif
AnnEngine::registerVRRenderer("OpenVR");

Theses are static functions and must be called before AnnInit().

Renderer selection

By default, the renderer that will be used is the one defined in the static string AnnEngine::defaultRenderer. You can change it's value before calling AnnInit if you want to force a specific renderer by default.

Some command line arguments can also set the renderer to use, these are -oculus and -vive. They override the default renderer string. You still need to have registered the renderer they are attached to for them to be valid.

AnnEngine object

The main class of Annwvyn is AnnEngine. AnnEngine initialize all Annwyvn's internal components.

AnnEngine is also the central access point for talking to other Annwvyn components. It's like the conductor of the Annwvyn orchestra ;-)

First thing you should do is to create an AnnEngine object. This can be done with the macro AnnInit().

You absolutely need to give your application a name, as a string, passed to AnnInit

AnnInit("MyVirtualRealityApp");

The AnnEngine class is following the “Singleton” design pattern. You're program will crash if you dare to declare two different AnnEngine instance.

You can access the unique instance of AnnEngine via AnnEngine::Instance(), or (preferably since it's shorter) the getter function AnnGetEngine(). This call will return nullptr if the engine is not running

You can acces pointers to the important parts of Annwvyn via AnnEngine's getters. Notable mentions are the AnnPlayer, AnnPhysicsEngine, AnnAudioEngine, AnnLevelManager, AnnEventManager (more information on the API documentation). They are all avalable as AnnGetSomething

Loading Resources

Before anything else, you should load the resources you will use into the engine.

Resources are all the assets your game will use. 3D objects, textures, sound effects, script files, etc…

Currently, you have 2 choices :

  • Put your resources on directories and load them with AnnGetResourceManager()→addFileLocation(const char path[])
  • put them on a zip files and load them with AnnGetResourceManager()→addZipLocation(const char path[]). Note that you don't need that file to terminate with the .zip extension

Example :

AnnGetResourceManager()->addFileLocation("path/to/folder");
AnnGetResourceManager()->addZipLocation("path/to/file.zip");

The “media” sub directory is loaded by default by the engine, as the CORE.zip file in it.

This file contains vital data that Annwvyn itself need to initialize, and the data for the sample program.

When you are done adding the resource locations, don't forget to call;

AnnGetResourceManager()->initResources();

Resources will not be available before this.

Annwvyn will load the resources in memory as the are used. There's a way for you to put them in “named groups”, and to pre-load them at will.

Annwvyn uses Ogre's own “resource group manager” internally. You still have access to it. Annwvyn also employ simple custom “Resource Manager” for Ogre internally to load audio file and gameplay scripts written in ChaiScript. All of your game resources are pulled from Ogre's system.

Annwvyn will always add ./media and ./media/CORE.zip as resource locations. CORE.zip contains various elements that are expected to always be available for the game engine. Theses places are called Annwvyn Core resources

Resource format

Annwvyn uses Ogre for rendering graphics and handling most of the 3D geometry it needs to process, compiled with freeimage. Ogre is compatible with almost any image file format but 3D object needs to uses Ogre's own filetype.

Putted simply:

  • 3D Object: Ogre .mesh binary format, in version 1.x, with their accompanying skeleton format.
  • Material description: Ogre .material script, containing HLMS PBS or HLMS UNLIT materials. They can also be JSON scripts.
  • Textures: 2D image
  • Audio: Any file format readable by libsndfile. Basically everything relevant, except MP3, because patent laws.
  • Scripts: File written in ChaiScript. Notably Object “Behavior Scripts” that can be attached to them.

The Game loop

Annwvyn has an internal loop that will, by default, run infinitely until the user press ESC

You can start this loop by calling

	AnnGetEngine()->startGameplayLoop();

If you haven't created and jumped to a level, or manually created GameObjects before, you'll be on an empty scene with a blue-sky background. This is normal and indicate that everything is working properly. And we will change that soon. but before that, you may want to control the gameplay loop yourself to add you own stuff (like if you need to put integration code for some weird peripheral like a LEAP motion or something).

Although, Annwvyn is a framework that support being you to register subsystems that will be updated by the engine. So you can insert arbitrary code inside the default gameplay loop. The mindset to have is “I give code to be called by Annwvyn” once the loop started, not the other way around.

But, you are free to do what you want. And you can set-up that loop manually by doing :

//--Use the built-in termination check (has ESC been pressed)
do
{
//Custom stuff
}while(AnnGetEngine()->refresh());
 
//--Use you own termination
do
{
//Custom stuff
 
//Last thing to do: call engine refresh
AnnGetEngine()->refresh();
}while(conditionToContinue);

Level Manager

Annwvyn abstract the notions of multiple “environment” you can be in into separate “levels”. A level describe the content of the world and run some of the logic behind.

A level is, in code, a class that inherit from AnnLevel, it's basic declaration is pretty simple :

class MyLevel : LEVEL
{
public:
	MyLevel();
	void load() override;
	void runLogic() override;
};

Levels has to be registered with the AnnLevelManager

	AnnGetLevelManager()->addLevel<MyLevel>();

Level are inserted into the list of known level by the manager. You can reference them by index, or by a pointer to them.

The manager is also capable of retrieving the first and the last level loaded. It has multiple “switchTo” methods that permit you to load one level to the other

	AnnGetLevelManager()->switchToFirstLoadedLevel();

Note: Annwvyn's level manager may take up to two frames to engage the level loading. This is due to the fact that level loading is a slow operation, and priority was given to the event processing. The LevelManager deffer the level loading to let all event-related call terminate. Thus, you may see that your selected first level isn't running for one or two loop iteration.

Level are loaded by running their “load()” methods. The Level object keep track of what object where inserted in the scene using it's onw “addSomething()” method. AnnLevel::unload() will remove all of theses objects for you. If you need to do something special at level unloading, you can overload that method.

	//Insert some object that will be in the scene
	auto Sinbad(addGameObject("Sinbad.mesh", "Sinbad"));
	Sinbad->setScale(0.5f * AnnVect3::UNIT_SCALE);
	Sinbad->setPosition({ 0, 1, 0 });
	Sinbad->setupPhysics(250, boxShape);
 
	//Add a plane to be the floor
	auto Ground(addGameObject("floorplane.mesh"));
	Ground->setPosition({ 0, 0, 0 });
	Ground->setupPhysics();
 
	//Add a light source
	auto Sun(addLightObject("MySun"));
	Sun->setType(AnnLightObject::ANN_LIGHT_DIRECTIONAL);
	Sun->setDirection(AnnVect3{ -1, -1.5f, -1 }.normalisedCopy());
	Sun->setPower(97);
 
	//set player position in level
	auto player{ AnnGetPlayer() };
	player->setPosition({ 0, 1, 10 });
	player->setOrientation(0);
	player->resetPlayerPhysics();
	player->regroundOnPhysicsBody();