Getting Started - A Small Tutorial


In this section we will create a simple application that loads a character and animates it using a walk cycle. You will see how straightforward it is to use the Horde3D API. As a first step you have to create an application that opens a window which can be used for rendering. This is a pretty standard task and if you are a novice and have problems with that on your platform use google to find one of the numerous good tutorials on the net or have a look at the samples that come with the Horde3D SDK. The next step is to initialize an OpenGL context for our rendering window. After that is done we can finally get to the engine related part.


#include <Horde3D.h>
#include <Horde3DUtils.h>

H3DNode model = 0, cam = 0;

void initGame( int winWidth, int winHeight )
{
    // Initialize engine
    h3dInit( H3DRenderDevice::OpenGL4 );
   
    // Add pipeline resource
    H3DRes pipeRes = h3dAddResource( H3DResTypes::Pipeline, "pipelines/forward.pipeline.xml", 0 );
    // Add model resource
    H3DRes modelRes = h3dAddResource( H3DResTypes::SceneGraph, "models/man/man.scene.xml", 0 );
    // Add animation resource
    H3DRes animRes = h3dAddResource( H3DResTypes::Animation, "animations/man.anim", 0 );
    // Load added resources
    h3dutLoadResourcesFromDisk( "" );
    
    // Add model to scene
    model = h3dAddNodes( H3DRootNode, modelRes );
    // Apply animation
    h3dSetupModelAnimStage( model, 0, animRes, 0, "", false );
    
    // Add light source
    H3DNode light = h3dAddLightNode( H3DRootNode, "Light1", 0, "LIGHTING", "SHADOWMAP" );
    // Set light position and radius
    h3dSetNodeTransform( light, 0, 20, 0, 0, 0, 0, 1, 1, 1 );
    h3dSetNodeParamF( light, H3DLight::RadiusF, 0, 50.0f );
	
    // Add camera
    H3DNode cam = h3dAddCameraNode( H3DRootNode, "Camera", pipeRes );

    // Setup viewport and render target sizes
    h3dSetNodeParamI( cam, H3DCamera::ViewportXI, 0 );
    h3dSetNodeParamI( cam, H3DCamera::ViewportYI, 0 );
    h3dSetNodeParamI( cam, H3DCamera::ViewportWidthI, winWidth );
    h3dSetNodeParamI( cam, H3DCamera::ViewportHeightI, winHeight );
    h3dSetupCameraView( cam, 45.0f, (float)winWidth / winHeight, 0.5f, 2048.0f );
    h3dResizePipelineBuffers( pipeRes, winWidth, winHeight );
}

The first line of the code above declares two global handles to Horde scene graph nodes. All objects in Horde are accessible via handles, a concept similar to pointers. The first thing we need to do in our initGame function to use Horde3D is initializing the engine. This happens with the function h3dInit.

The next step is to load the required resources. In Horde resources are data files that are loaded once and can be referenced by several objects for rendering. The function h3dAddResource takes the resource type we want to add and the name of the resource (usually the filename) as parameters and returns a handle to the created resource object. In our case we want a model which is represented as a scene graph file in Horde and additionally an animation. Now the resources are created but we still need to load them. Horde supports loading from any sources including encrypted archives or a network but in this case we just want to load our resources from the local hard disk which is done with the utility function h3dutLoadResourcesFromDisk. Besides our model and animation we also load a pipeline resource. A pipeline defines how the the scene is rendered and can be used to realize post-processing effects or high dynamic range rendering. For the beginning you can just use the files that come with the SDK samples.

After we have loaded the required resources we can finally build up the scene graph. The scene graph represents the objects in our virtual world in a hierachical tree structure. First we add the model that we have loaded before. We use the function h3dAddNodes for doing this which takes a scene graph resource and a parent node. The parent is the scene object to which the new node is attached, in our case just the root node which is the base of the virtual world. Similar to h3dAddResource, this function also returns a handle to the created scene graph subtree. After that we assign the loaded animation to our model node with the function h3dSetupModelAnimStage. Horde allows you to apply several different animations to a model and makes it possible to blend and mix them but for the beginning one should be enough. Now that adding the model is finished we still need a light source. It would be possible to load another scene graph file which contains the light source but we want to add it manually by using the h3dAddLightNode function. This function requires several parameters specifying the shaders used for rendering. More information on this can be found in other sections of the manual. The next step is to set the position and orientation which is done with h3dSetNodeTransform. After that we specify the light radius which defines the zone of influence using h3dSetNodeParamF. Finally we still need a camera which represents the viewer. It is added with the function h3dAddCameraNode and takes our loaded pipeline resource as parameter. The view parameters of the camera and the render targets of the pipeline resource depend on the size of the rendering window. So in the last step we apply the viewport settings to the camera node and resize the output buffers of the pipeline.


void gameLoop( float fps )
{
    static float t = 0;
    
    // Increase animation time
    t = t + 10.0f * (1 / fps);
    
    // Play animation
    h3dSetModelAnimParams( model, 0, t, 1.0f );
    h3dUpdateModel( model, H3DModelUpdateFlags::Animation | H3DModelUpdateFlags::Geometry );
	
    // Set new model position
    h3dSetNodeTransform( model, t * 10, 0, 0,  // Translation
                         0, 0, 0,              // Rotation
                         1, 1, 1 );            // Scale
										   
    // Render scene
    h3dRender( cam );
    
    // Finish rendering of frame
    h3dFinalizeFrame();
}


void releaseGame()
{
    // Release engine
    h3dRelease();
}

The next function in our sample is the game loop which is called once every frame. Here we will animate our character model. For doing this we define a time counter which is increased in every frame. To make the animation speed independent from the framerate, we scale the time step by the inverse of the current frames per second value. After that we tell the engine to update the model animation using the h3dSetModelAnimParams function. You can call h3dSetModelAnimParams multiple times per frame, and skinning will be updated with h3dUpdateModel function. We could also specify a blend weight for combining animations here but since we have only one animation we don't need that. Now we can displace our character a bit so that it moves through the scene. This is achieved by updating the model node transformation. Finally we need to tell the engine to render the scene and recalculate the model animation. This happens with the function h3dRender that expects the camera from which the scene is viewed. The very last step is to inform the engine that rendering for the current frame is finished now.

The last function releaseGame is called when the application is closed. All we have to do here is freeing the engine with the h3dRelease function.

That's it so far with the basic tutorial. You can have a look at the Usage Guide now to learn more details.