Urho3D
|
In the following example, a minimal "Hello World" application with both 3D and user interface content will be built.
We start by defining the Start() function required in all Urho3D script applications. When Urho3D.exe executes it, all the engine subsystems are already in place, so any initialization that needs to be done is specific to the application itself.
Even before Start(), we define the object handle for the 3D scene we are going to create. This must be outside the function so that the Scene will remain after the function execution ends. Angelscript uses the @ symbol for object handles, which correspond to SharedPtr's on C++ side (ie. they keep alive the object pointed to.)
In the Start() function itself, first of all we create the 3D scene. Note the lack of "new" keyword. Then we branch off to further initialization functions that will be defined below.
Note that Urho3D has modified AngelScript to allow object handle assignment without the @ symbol, if the object in question does not support value assignment. None of the Urho3D reference-counted objects, such as Scene, support value assignment. In unmodified AngelScript the first line of Start() would have to read "@helloScene = Scene()".
In CreateObjects(), which we define next, the scene will be filled with some content. The Urho3D scene model is basically a scene graph; the Scene object serves also as the root node.
First of all we need to create an Octree component into the root node. This is used for accelerated visibility queries to check what the camera "sees", and without it nothing would be visible.
Three child nodes are then created: one for a 3D model object, one for a directional light, and one for the camera. The scene nodes themselves display nothing in the 3D world; components need to be created into them for the actual visible content.
Child nodes can be created with or without names; uniqueness of names is not enforced. In this case we opt to not use names, as we do not need to find the nodes later after creation.
As animation is not needed, we use a StaticModel component for the 3D model. Its scene node remains at the origin (default position of each scene node.) The ResourceCache subsystem is used to load the needed Model & Material resources.
The light scene node also remains at the origin. Position does not matter for directional lights, but the node's forward direction is adjusted so that the light will shine down diagonally.
The camera's scene node is pulled back along the Z-axis to be able to see the object.
Finally we define a fullscreen Viewport into the Renderer subsystem so that the scene can be shown. The viewport needs Scene and Camera object handles. Note the indexing; multiple viewports could be defined (for example to use split screen rendering) if necessary.
The 3D content is now finished. Next, we create the user interface content in CreateText().
We display a "Hello World" message on the screen with the help of a Text user interface element. We use the included Anonymous Pro font with point size 30. For the text to actually become visible, it needs to be added as a child of the user interface root element (the UI can be thought of as a 2D scene graph.) It is also centered both horizontally and vertically in relation to the parent element.
Finally we subscribe to necessary Urho3D events in the SubscribeToEvents() function.
If no events would be responded to, the application would just be left running with no possibility to interact with it, until it was forcibly exited with Alt-F4. In this case, we are interested of the frame update event, which will be sent on each iteration of the main loop. When subscribing, we need to give the name of the event, and the name of the event handler function. We could also require the event to be sent by a specific sender, but in this case that is unnecessary.
The event handler function needs to have a specific signature. If event type and parameters are not needed, "void HandleEvent()", or if they are, "void HandleEvent(StringHash eventType, VariantMap& eventData)". We might want to expand the application later, so we use the latter form.
The current frame's delta time is sent in the update event's parameters, and that will be useful when animating the scene. For now the event handler simply checks from the Input subsystem if the ESC key has been pressed; if it is, it calls the Engine subsystem's Exit() function. This closes the application window and causes Urho3D.exe to exit after the current main loop iteration finishes.
Note that to get the ESC keypress without having to poll it for each frame, we could also subscribe to the "KeyDown" event sent by the Input subsystem.
The example application is now complete. To try it out, save it as HelloWorld.as in the Bin/Data/Scripts directory, then run Urho3D.exe Scripts/HelloWorld.as