- slide 1 of 4
While it is possible to create a number of basic shapes like boxes, cones and spheres with Sandy-HX, anything more complicated is almost always going to have to be loaded from a file created by an external 3D modelling application. Fortunately, Sandy-HX has the ability to load these files and display them in the 3D scene.
This tutorial will look at the process of loading and displaying a Collada file. Collada is an open XML based 3D format, and Collada files have the dae extension.
First we need to load the Collada file. Loading is done asynchronously, meaning that the actual process of loading the file is done in the background while the main program continues on. Normally this allows you to set a file to be loaded, continue on with the application, and then perform an action when the loading is finished. We don’t really want to run our 3D application while the 3D models are being loaded in the background – the whole point of the application is to display the models held in these files, so until they are loaded and ready there isn’t much the application can do.
In practical terms this means that we don’t want to initialize the ApplicationManager or enter the render loop until the resources have been loaded. The EngineManager has been modified slightly to implement this.
Previously the Sandy-HX engine was initialised, the ApplicationManager started and the set to run in the EngineManagers constructor. Now we initialise the Sandy-HX engine and then create a new instance of a class called ResourceManager. The ResourceManager is responsible for loading the resources, and when done it will call either the EngineMaangers resourcesLoaded or resourceLoadError functions, depending on whether or not all the resources successfully loaded. You will see that it is only once the resourcesLoaded function has been called that the ApplicationManager is started and the render loop set to run. [code]
This change ensures that any object created by the ApplicationManager can access the resources loaded by the ResourceManager without having to worry about the asynchronous nature of the loading process.
- slide 2 of 4
- slide 3 of 4
The ResourceManager is where the resources needed by the application are defined and loaded. In this application we are loading one 3D model from the fighter1.dae collada file.
In the constructor we initialise the properties. The static instance property is set to the current instance of the ResourceManager. This property is used later in the some anonymous functions. [code]
The successCount property holds a count of the number of resources that were successfully loaded. The failureCount hold a count of the number of resources that failed to load. The resourceCount defines how many resources are to be loaded. These variables are used to determine if all the resources were successfully loaded. [code]
Next we actually load the resources. A Parser is created, specifying the location of the resource to load, and the type of resource (defined by Parser.COLLADA in our case). Sandy-HX can load a number of file types, each defined by a constant in the Parser class (ASE, MD2, MAX_3DS and COLLADA formats are currently supported). [code]
Functions are then set to be triggered on either the ParserEvent.FAIL event (where the resource was not loaded) or the ParserEvent.INIT event (where the resource was loaded successfully). In order to save typing we have used some anonymous functions to deal with these events. Unlike other languages, Haxe anonymous functions are essentially static functions, so in order for them to interact with the current instance of the ResourceManager they reference the static instance property we initialised earlier.
If the resource is successfully loaded it is assigned to a property of the ResourceManager, and the updateLoadCount function is called to notify the ResourceManager that a resource has finished loading. We set the success parameter to true to indicate that the resource loaded successfully. [code]
If the resource failed to load the updateLoadCount function is called with the success parameter set to false. [code]
Finally the parse function is called on the Parser, telling it to go ahead and load the resources. [code]
The updateLoadCount is called every time a resource finishes loading, successfully or otherwise. Once all the resources has been loaded (by checking the total of the successCount and failureCount properties) either the EngineManagers resourcesLoaded or resourceLoadError functions are called, depending on whether or not all the resources loaded properly. [code].
The Application manager makes use of the loaded resources to create a new RotatingMeshObject (a very simple class that extends the MeshObject and rotates the model). You can see that the ApplicationManager doesn’t need to worry about the asynchronous resource loading process, because by the time it is initialised the resources have been loaded and are ready to use.
The ResourceManager provides a very easy way to load additional resources in a manner that allows any other class to ignore the fact that the resources are loaded asynchronously. This simplifies what would otherwise be a fairly error prone procedure.