| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209 |
- /**
- \page ObjectTypes %Object types and factories
- Classes that derive from Object contain type-identification, they can be created through object factories, and they can send and receive \ref Events "events". Examples of these are all Component, Resource and UIElement subclasses. To be able to be constructed by a factory, they need to have a constructor that takes a Context pointer as the only parameter.
- %Object factory registration and object creation through factories are directly accessible only in C++, not in script.
- The definition of an Object subclass must contain the OBJECT(className) macro. Type identification is available both as text (GetTypeName() or GetTypeNameStatic()) and as a 16-bit hash of the type name (GetType() or GetTypeStatic()).
- In addition the OBJECTTYPESTATIC(className) macro must appear in a .cpp file to actually define the type identification data. The reason for doing this instead of defining the data directly inside the OBJECT macro as function-static data is thread safety: if the first invocation to an object's GetTypeStatic() or GetTypeNameStatic() was started on several threads simultaneously, the results of function-static data initialization would be erratic.
- To register an object factory for a specific type, call the \ref Context::RegisterFactory() "RegisterFactory()" template function on Context. You can get its pointer from any Object either via the \ref Object::context_ "context_" member variable, or by calling \ref Object::GetContext() "GetContext()". An example:
- \code
- context_->RegisterFactory<Camera>();
- \endcode
- To create an object using a factory, call Context's \ref Context::CreateObject() "CreateObject()" function. This takes the 16-bit hash of the type name as a parameter. The created object (or null if there was no matching factory registered) will be returned inside a SharedPtr<Object>. For example:
- \code
- SharedPtr<Object> newComponent = context_->CreateObject(type));
- \endcode
- \page Subsystems Subsystems
- Any Object can be registered to the Context as a subsystem, by using the function \ref Context::RegisterSubsystem() "RegisterSubsystem()". They can then be accessed by any other Object inside the same context by calling \ref Object::GetSubsystem() "GetSubsystem()". Only one instance of each object type can exist as a subsystem.
- After Engine initialization, the following subsystems will always exist:
- - Time: manages frame updates, frame number and elapsed time counting, and controls the frequency of the operating system low-resolution timer.
- - FileSystem: provides directory operations.
- - Log: provides logging services.
- - ResourceCache: loads resources and keeps them cached for later access.
- - Network: provides UDP networking.
- - Input: handles keyboard and mouse input. Will be inactive in headless mode.
- - UI: the graphical user interface. Will be inactive in headless mode.
- - Audio: provides sound output. Will be inactive if sound disabled.
- - Engine: creates the other subsystems and controls the main loop iteration and framerate limiting.
- The following subsystems are optional, so GetSubsystem() may return null if they have not been created:
- - Profiler: Provides hierarchical function execution time measurement using the operating system performance counter. Exists if profiling has been compiled in (configurable from the root CMakeLists.txt)
- - Graphics: Manages the application window and the Direct3D9 device and resources. Exists if not in headless mode.
- - Renderer: Renders scenes in 3D and manages rendering quality settings. Exists if not in headless mode.
- - Script: Provides the AngelScript execution environment. Created by calling \ref Engine::InitializeScripting() "InitializeScripting()".
- - Console: provides an interactive AngelScript console and log display. Created by calling \ref Engine::CreateConsole() "CreateConsole()".
- - DebugHud: displays rendering mode information and statistics and profiling data. Created by calling \ref Engine::CreateDebugHud() "CreateDebugHud()".
- In script, the subsystems are available through the following global properties:
- time, fileSystem, log, cache, network, input, ui, audio, engine, graphics, renderer, script, console, debugHud. Note that Profiler is not available to script due to its low-level nature.
- \page Events Events
- The Urho3D event system allows for data transport and function invocation without the sender and receiver having to explicitly know of each other. It supports both broadcast and targeted events. Both the event sender and receiver must derive from Object. An event receiver must subscribe to each event type it wishes to receive: one can either subscribe to the event coming from any sender, or from a specific sender. The latter is useful for example when handling events from the user interface elements.
- Events themselves do not need to be registered. They are identified by 32-bit hashes of their names. Event parameters (the data payload) are optional and are contained inside a VariantMap, identified by 16-bit parameter name hashes. For the inbuilt Urho3D events, event type (E_UPDATE, E_KEYDOWN, E_MOUSEMOVE etc.) and parameter hashes (P_TIMESTEP, P_DX, P_DY etc.) are defined as constants inside include files such as CoreEvents.h or InputEvents.h.
- When subscribing to an event, a handler function must be specified. In C++ these must have the signature void HandleEvent(StringHash eventType, VariantMap& eventData). The HANDLER(className, function) macro helps in defining the required class-specific function pointers. For example:
- \code
- SubscribeToEvent(E_UPDATE, HANDLER(MyClass, MyEventHandler));
- \endcode
- In script events are identified by their string names instead of name hashes (though these are internally converted to hashes.) Script event handlers can either have the same signature as in C++, or a simplified signature void HandleEvent() when event type and parameters are not required. The same event subscription would look like:
- \code
- SubscribeToEvent("Update", "MyEventHandler");
- \endcode
- In C++ events must always be handled by a member function. In script procedural event handling is also possible; in this case the ScriptFile where the event handler function is located becomes the event receiver. See \ref Scripting "Scripting" for more details.
- To send an event, fill the event parameters (if necessary) and call \ref Object::SendEvent "SendEvent()". For example, this (in C++) is how the Time subsystem sends the Update event. Note how for the inbuilt Urho3D events, the parameter name hashes are always put inside a namespace (the event's name) to prevent name clashes:
- \code
- using namespace Update;
- VariantMap eventData;
- eventData[P_TIMESTEP] = timeStep_;
- SendEvent(E_UPDATE, eventData);
- \endcode
- In script event parameters, like event types, are referred to with strings, so the same code would look like:
- \code
- VariantMap eventData;
- eventData["TimeStep"] = timeStep;
- SendEvent("Update", eventData);
- \endcode
- Events can also be unsubscribed from. See \ref Object::UnsubscribeFromEvent "UnsubscribeFromEvent()" for details.
- \page MainLoop Main loop and frame update
- The main loop iteration (also called a frame) is driven by the Engine. In contrast it is the program's (for example Urho3D.exe) responsibility to continuously loop this iteration. The iteration consists of the Engine calling the Time subsystem's \ref Time::BeginFrame "BeginFrame()" and \ref Time::EndFrame "EndFrame()" functions, which causes several events to be sent:
- - E_BEGINFRAME: signals the beginning of the new frame. Input and Network react to this to check for operating system window messages and arrived network packets.
- - E_UPDATE: application-wide logic update event. By default each active Scene reacts to this and triggers the scene update (more on this below.)
- - E_POSTUPDATE: application-wide logic post-update event. The UI subsystem updates its logic here.
- - E_RENDERUPDATE: Renderer updates its viewports here to prepare for rendering, and the UI generates render commands necessary to render the user interface.
- - E_POSTRENDERUPDATE: by default nothing hooks to this. This can be used to implement logic that requires the rendering views to be up-to-date (for example to do accurate raycasts.) Scenes may not be modified at this point (especially scene objects may not be deleted or crashes may occur.)
- - E_ENDFRAME: signals the end of the frame. Before this, rendering the frame and measuring the next frame's timestep will have occurred.
- The update of each Scene causes further events to be sent:
- - E_SCENEUPDATE: variable timestep scene update. This is a good place to implement any scene logic that does not need to happen at a fixed step.
- - E_SCENESUBSYSTEMUPDATE: update scene-wide subsystems. Currently only the PhysicsWorld component listens to this, which causes it to step the physics simulation and send the following two events for each simulation step:
- - E_PHYSICSPRESTEP: called before the simulation iteration. Happens at a fixed rate (the physics FPS.) If fixed timestep logic updates are needed, this is a good event to listen to.
- - E_PHYSICSPOSTSTEP: called after the simulation iteration. Happens at the same rate as E_PHYSICSPRESTEP.
- - E_SCENEPOSTUPDATE: variable timestep scene post-update. ParticleEmitter and AnimationController update themselves as a response to this event.
- Variable timestep logic updates are preferable to fixed timestep, because they are only executed once per frame. In contrast, if the rendering framerate is low, several physics world simulation steps will be performed on each frame to keep up the apparent passage if time, and if this also causes a lot of logic code to be executed for each step, the program may bog down further if the CPU can not handle the load.
- \page SceneModel %Scene model
- Urho3D's scene model can be described as a component-based scene graph. The Scene consists of a hierarchy of scene nodes, starting from the root node, which also represents the whole scene. Each Node has a 3D transform (position, rotation and scale) and a name, but no other functionality. Rendering 3D objects, sound playback, physics and scripted logic updates are all enabled by creating different \ref Component "Components" into the nodes by calling \ref Node::CreateComponent "CreateComponent()".
- Components do not have names; components inside the same node are only identified by their type, and index in the node's component list, which is filled in creation order. See the various overloads of \ref Node::GetComponent "GetComponent()" or \ref Node::GetComponents "GetComponents()" for details.
- As with events, in C++ components are identified by type name hashes, and template forms of the component creation and retrieval functions exist for convenience. For example:
- \code
- Light* light = lightNode->CreateComponent<Light>();
- \endcode
- In script, strings are used to identify component types instead, so the same code would look like:
- \code
- Light@ light = lightNode.CreateComponent("Light");
- \endcode
- Because components are created using \ref ObjectTypes "object factories", a factory must be registered for each component type.
- When created, nodes and components get scene-global integer IDs starting from 1. They can be queried from the Scene by using the functions \ref Scene::GetNodeByID "GetNodeByID()" and \ref Scene::GetComponentByID "GetComponentByID()". This is much faster than for example doing recursive name-based scene node queries.
- There is no inbuilt concept of an entity or a game object; rather it is up to the programmer to decide the node hierarchy, and to decide in which nodes to place any scripted logic. Typically, free-moving objects in the 3D world would be created as children of the root node. Nodes can be created either with or without a name, see \ref Node::CreateChild "CreateChild()". Uniqueness of node names is not enforced.
- Whenever there is some hierarchical composition, it is recommended (and in fact necessary, because components do not have their own 3D transforms) to create a child node. For example if a character was holding an object in his hand, the object should have its own node, which would be parented to the character's hand bone (also a Node.) The exception is the physics CollisionShape, which can be offsetted and rotated individually in relation to the node. See \ref Physics "Physics" for more details.
- %Scene nodes can be freely reparented. In contrast components are always created to the node they belong to, and can not be moved between nodes. Both child nodes and components are stored using SharedPtr containers; this means that detaching a child node from its parent or removing a component will also destroy it, if no other references to it exist. Both Node & Component provide the \ref Node::Remove() "Remove()" function to accomplish this without having to go through the parent. Note that no operations on the node or component in question are safe after calling that function.
- Components created into the Scene itself have a special role: to implement scene-wide functionality. They should be created before all other components, and include the following:
- - Octree: implements spatial partitioning and accelerated visibility queries. Without this 3D objects can not be rendered.
- - PhysicsWorld: implements physics simulation. Physics components such as RigidBody or CollisionShape can not function properly without this.
- - DebugRenderer: implements debug geometry rendering.
- "Ordinary" components like Light, Camera or StaticModel should not be created directly into the Scene, but rather into child nodes.
- A Scene can be either active or inactive (paused.) Active scenes will be automatically updated on each main loop iteration. Scenes can be loaded and saved in either binary or XML format; see \ref Serialization "Serialization" for details.
- It is also legal to create a Node that does not belong to a scene. This particularly useful with cameras, because then the Camera will not be serialized along with the actual scene, which is perhaps not always wanted.
- For more information on the component-based scene model, see for example http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/.
- \page Resources Resources
- Resources include most things in Urho3D that are loaded from mass storage during initialization or runtime:
- - Animation
- - Image
- - Model
- - Material
- - ScriptFile
- - Sound
- - Texture2D
- - TextureCube
- - XMLFile
- They are managed and loaded by the ResourceCache subsystem. Like with all other \ref ObjectTypes "typed objects", resource types are identified by 16-bit type name hashes (C++) or type names (script). An object factory must be registered for each resource type.
- The resources themselves are identified by their file paths, relative to the registered resource directories or \ref PackageFile "package files". By default, Urho3D.exe registers the resource directories Data and CoreData, or the packages Data.pak and CoreData.pak if they exist, plus the system font directory.
- If loading a resource fails, an error will be logged and a null pointer is returned.
- Typical C++ example of requesting a resource from the cache, in this case, a texture for a UI element. Note the use of a convenience template argument to specify the resource type, instead of using the type hash.
- \code
- healthBar->SetTexture(GetSubsystem<ResourceCache>()->GetResource<Texture2D>("Textures/HealthBarBorder.png"));
- \endcode
- The same in script would look like this (note the use of a property instead of a setter function):
- \code
- healthBar.texture = cache.GetResource("Texture2D", "Textures/HealthBarBorder.png");
- \endcode
- Resources can also be created manually and stored to the resource cache as if they had been loaded from disk.
- \page Scripting Scripting
- There are three ways the AngelScript language can be interacted with in Urho3D:
- \section Scripting_Immediate Immediate execution
- Immediate execution takes one line of AngelScript, compiles it, and executes. This is not recommended for anything that needs high performance, but can be used for example to implement a developer console. Call the Script subsystem's \ref Script::Execute "Execute()" function to use. For example:
- \code
- GetSubsystem<Script>()->Execute("Print(\"Hello World!\");");
- \endcode
- It may be useful to be able to access a specific scene or a script file while executing immediate script code. These can be set on the Script subsystem by calling \ref Script::SetDefaultScene "SetDefaultScene()" and \ref Script::SetDefaultScriptFile "SetDefaultScriptFile()".
- \section Scripting_Procedural Calling a function from a script file
- This requires a successfully loaded ScriptFile resource, whose \ref ScriptFile::Execute "Execute()" function will be used. To identify the function to be called, its full declaration is needed. Parameters are passed in a VariantVector. For example:
- \code
- ScriptFile* file = GetSubsystem<ResourceCache>()->GetResource<ScriptFile>("Scripts/MyScript.as");
- VariantVector parameters;
- parameters.push_back(Variant(100)); // Add an int parameter
- file->Execute("void MyFunction(int)", parameters); // Execute
- \endcode
- \ref ScriptFile::Execute "Execute()" also has an overload which takes a function pointer instead of querying by declaration. Using a pointer is naturally faster than a query, but note that the query results are also stored to an internal cache, so repeated queries for the same declaration do not need to go to the AngelScript module level each time. Storing function pointers is risky in case the ScriptFile resource is reloaded, because then the pointers will be invalidated.
- \section Scripting_Object Instantiating a script object
- The component ScriptInstance can be used to instantiate a specific class from within a script file. After this the script object can respond to scene updates, \ref Events "events" and \ref Serialization "serialization" much like a component written in C++ would do, if it has the appropriate methods implemented. For example:
- \code
- ScriptInstance* instance = node->CreateComponent<ScriptInstance>();
- instance->CreateObject(GetSubsystem<ResourceCache>()->GetResource<ScriptFile>("Scripts/MyClass.as"), "MyClass");
- \endcode
- The class must implement the empty interface ScriptObject, so that the object can also be accessed from script using ScriptInstance's \ref ScriptInstance::GetScriptObject "GetScriptObject()" function.
- The following methods that implement the component behaviour will be checked for. None of them are required.
- - void Start()
- - void Stop()
- - void Update(float)
- - void PostUpdate(float)
- - void FixedUpdate(float)
- - void FixedPostUpdate(float)
- - void Save(Serializer&)
- - void Load(Deserializer&)
- The update methods above correspond to the variable timestep scene update and post-update, and the fixed timestep physics world update and post-update. The application-wide update events are not handled by default.
- The Start() and Stop() methods do not have direct counterparts in C++ components. Start() is called just after the script object has been created. Stop() is called just before the script object is destroyed. This happens when the ScriptInstance is destroyed, or if the script class is changed.
- Subscribing to \ref Events "events" in script behaves differently depending on whether \ref Object::SubscribeToEvent "SubscribeToEvent()" is called from a script object's method, or from a procedural script function. If called from an object method, the ScriptInstance becomes the event receiver on the C++ side, and forwards the events to the script object. If called from a function, the ScriptFile will be the event receiver.
- The script object's active/inactive state can be controlled through the \ref ScriptInstance::SetActive "SetActive()" function. When inactive, the scripted update methods or event handlers will not be called. This can be used to reduce CPU load in a large or densely populated scene.
- There are shortcut methods on the script side for creating and accessing a node's script object: node.CreateScriptObject() and node.GetScriptObject(). These are not actual Node member functions on the C++ side. CreateScriptObject() takes the script file name (or alternatively, a ScriptFile object handle) and class name as parameters and creates a ScriptInstance component automatically, then creates the script object. For example:
- \code
- ScriptObject@ object = node.CreateScriptObject("Scripts/MyClass.as", "MyClass");
- \endcode
- \section Script_ScriptAPI The script API
- Much of the Urho3D classes are exposed to scripts, however things that require low-level access or high performance (like direct vertex buffer access or immediate rendering) are not. Also for scripting convenience some things have been changed from the C++ API:
- - The template array and std::string types are exposed as Array<type> and String.
- - Public member variables are exposed without the underscore appended. For example x, y, z in Vector3.
- - Whenever only a single parameter is needed, setter and getter functions are replaced with properties. Such properties start with a lowercase letter. If an index parameter is needed, the property will be indexed. Indexed properties are in plural.
- - Subsystems exist as global properties: time, fileSystem, log, cache, network, input, ui, audio, engine, graphics, renderer, script, console, debugHud.
- - Additional global properties exist for accessing the script object's node, the scene and the scene-wide components: node, scene, octree, physicsWorld, debugRenderer. When an object method is not executing, these are null. An exception: when the default scene for immediate execution has been set by calling \ref Script::SetDefaultScene "SetDefaultScene()", it is always available as "scene".
- - The first script object created to a node is available as its scriptObject property.
- - The script file that is currently executing is available through the scriptFile property.
- - Printing raw output to the log is simply called Print(). The rest of the logging functions are accessed by calling log.Debug(), log.Info(), log.Warning() and log.Error().
- - Functions that would take a StringHash or ShortStringHash parameter usually take a string instead. For example sending events, requesting resources and accessing components.
- - Most of StringUtils have been exposed as methods of the string class or the corresponding classes. For example String.ToLower(), Vector3.ToString().
- - Template functions for getting components or resources by type are not supported. Instead automatic type casts are performed as necessary.
- \section Scripting_Limitations Limitations
- There are some complexities of the scripting system one has to watch out for:
- - During the execution of the script object's constructor, the object is not yet associated with the ScriptInstance, and therefore subscribing to events, or trying to access the node or scene will fail. The use of the constructor is best reserved for initializing member variables only.
- - There is a maximum allowed nesting level (currently 32) for execution that moves between C++ & AngelScript. Nested execution typically occurs if you send an event to another ScriptInstance from a scripted event handler. If the nesting level is exceeded, an error will be logged and the script code that would have required the extra nesting level will not be executed.
- - When the resource request for a particular ScriptFile is initially made, the script file and the files it includes are compiled into an AngelScript script module. Each script module has its own class hierarchy that is not usable from other script modules. Particularly casts to/from base classes will not work across script modules as you would expect, as the base class will actually be uniquely defined within each script module. Interfaces should work across modules. If access to a class hierarchy is needed, and using interfaces is not sufficient, it is best to ensure that only a single script module, which includes all the necessary classes, will be compiled. This could be for example the game's main program class, which would simply #include all the game object classes it needs. It may sound ugly to include a large number of files, but actually it is more memory-optimal to make one large script module, than several smaller ones which would duplicate the definition for eg. a game object base class.
- - If a ScriptFile resource is reloaded, all the script objects created from it will be destroyed, then recreated. They will lose any stored state as their constructors and Start() methods will be run again. This is rarely useful when running an actual game, but may be helpful during development.
- \section Scripting_Modifications AngelScript modifications
- The following changes have been made to AngelScript in Urho3D:
- - For performance reasons and to guarantee immediate removal of expired objects, AngelScript garbage collection has been disabled for script classes and the Array type. This has the downside that circular references will not be detected. Therefore, whenever you have object handles in your script, think of them as if they were C++ shared pointers and avoid creating circular references with them.
- - %Object handle assignment can be done without the @ symbol if the object in question does not support value assignment. All exposed Urho3D C++ classes that derive from RefCounted never support value assignment. For example, when assigning the Model and Material of a StaticModel component:
- \code
- object.model = cache.GetResource("Model", "Models/Mushroom.mdl");
- object.material = cache.GetResource("Material", "Materials/Mushroom.xml");
- \endcode
- In unmodified AngelScript, this would have to be written as:
- \code
- @object.model = cache.GetResource("Model", "Models/Mushroom.mdl");
- @object.material = cache.GetResource("Material", "Materials/Mushroom.xml");
- \endcode
- \page Rendering Rendering
- Much of the rendering functionality in Urho3D is built on two subsystems, Graphics and Renderer, contained within the %Graphics library.
- \section Rendering_Graphics Graphics
- Graphics implements the low-level functionality:
- - Creating the window and the Direct3D device
- - Setting the screen mode
- - Keeping track of GPU resources
- - Keeping track of Direct3D state (current rendertarget, vertex and index buffers, textures, shaders and renderstates)
- - Handling lost device
- - Performing primitive rendering operations
- It also provides a low-performance, immediate-like interface for manually defining small amounts of geometry to be rendered. This interface is used for rendering the debug geometry and the user interface.
- Screen resolution, fullscreen/windowed, vertical sync, forward/light pre-pass/deferred mode, and hardware multisampling level are all set at once by calling Graphics's \ref Graphics::SetMode "SetMode()" function. Hardware multisampling will be disabled in deferred rendering modes as incompatible, instead it is replaced by manual temporal antialiasing.
- When setting the initial screen mode, Graphics does a few checks:
- - Which shader model is supported? 2.0 is minimum, but 3.0 will be used if available. Shader model 2.0 can be forced by calling setForceSM2() before calling setMode() for the first time.
- - Are multiple render targets supported? If not, only forward rendering will be available.
- - Are hardware shadow maps supported? Both ATI & NVIDIA style shadow maps can be used. If neither are available, shadow rendering will be disabled.
- \section Rendering_Renderer Renderer
- Renderer implements the rendering of 3D scene(s) each frame. To do this, it needs a Scene with an Octree component, and a Camera that does not necessarily have to belong to the scene. The octree stores all visible components (derived from Drawable) to allow querying for them in an accelerated manner. Global rendering quality settings such as texture quality, material quality, specular lighting and shadow rendering are controlled from this subsystem.
- The scene, camera and screen rectangle to use are set with Renderer's \ref Renderer::SetViewport "SetViewport()" function. By default there is one viewport, but the amount can be increased with the function \ref Renderer::SetNumViewports "SetNumViewports()". The viewport(s) should cover the entire screen or otherwise hall-of-mirrors artifacts may occur. By specifying a zero screen rectangle the whole window will be used automatically. The viewports will be rendered in ascending order, so if you want for example to have a small overlay window on top of the main viewport, use viewport index 0 for the main view, and 1 for the overlay.
- The steps for rendering each viewport on each frame are roughly the following:
- - Query the octree for visible objects and lights in the camera's view frustum.
- - Optimize the visible objects using software rasterized occlusion (can be switched off if this sounds scary and time-wasting, but practically it allows for a huge performance increase in more complex & occluded scenes.)
- - Check the influence of each visible light on the objects. If the light casts shadows, query the octree for shadowcaster geometries.
- - Construct render operations (batches) for the visible objects.
- - Perform these render operations during the rendering step at the end of the frame.
- For opaque, non-skinned geometry, batches using the same material and same vertex/index buffers are automatically grouped together for hardware instancing when SM3.0 hardware is available. This reduces the actual draw call count needed.
- The rendering operations are divided into passes in the following order:
- - Opaque geometry ambient pass (forward) or filling the G-buffer with opaque geometry (light pre-pass & deferred.)
- - Lighting opaque geometry. For shadow casting lights, the shadow map is rendered first.
- - Post-opaque or "extra" rendering pass for materials that define that.
- - Transparent geometry rendering pass. Transparent, alpha-blended objects are sorted according to distance and rendered back-to-front to ensure correct blending.
- \section Rendering_Drawable Rendering components
- The rendering-related components defined by the %Graphics library are:
- - Octree: spatial partitioning of Drawables for accelerated visibility queries. Needs to be created to the Scene (root node.)
- - Camera: describes a viewpoint for rendering, including projection parameters (FOV, near/far distance, perspective/orthographic)
- - Drawable: Base class for anything visible.
- - StaticModel: non-skinned geometry. Can LOD transition according to distance.
- - Skybox: a subclass of StaticModel that appears to always stay in place.
- - AnimatedModel: skinned geometry that can do skeletal and vertex morph animation.
- - AnimationController: drives AnimatedModel's animations forward automatically and controls animation fade-in/out.
- - BillboardSet: a group of camera-facing billboards, which can have varying sizes, rotations and texture coordinates.
- - ParticleEmitter: a subclass of BillboardSet that emits particle billboards.
- - Light: illuminates the scene. Can optionally cast shadows.
- - Zone: defines global properties like fogging and background color. The active zone is the one the Camera is currently in.
- \section Rendering_Further Further details
- See also \ref Materials "Materials", \ref Lights "Lights and shadows", \ref Particles "Particle systems" and \ref AuxiliaryViews "Auxiliary views".
- For details on how lighting opaque geometry differs between forward and deferred rendering, see \ref ForwardDeferred "Comparision of forward, light pre-pass and deferred rendering".
- \page Materials Materials
- Material and Technique resources define how to render 3D scene geometry. On the disk, they are XML data. By default, materials exist in the CoreData/Materials & Data/Materials subdirectories, and techniques exist in the CoreData/Techniques subdirectory.
- A material defines the textures, shader parameters and culling mode to use, and refers to techniques. A technique defines the actual rendering passes, the shaders to use in each, and all other rendering states such as depth test, depth write, and blending.
- A material definition looks like this:
- \code
- <material>
- <technique name="TechniqueName" quality="q" loddistance="d" sm3="true|false" />
- <texture unit="diffuse|normal|specular|detail|environment|emissive" name="TextureName" />
- <texture ... />
- <parameter name="name" value="x y z w" />
- <parameter ... />
- <cull value="cw|ccw|none" />
- <shadowcull value="cw|ccw|none" />
- </material>
- \endcode
- The shadowcull element is optional and specifies the culling mode to use in the shadow pass. If omitted, the culling mode when drawing shadows is the same as the normal culling mode.
- %Material quality levels are specified from 0 (low) to 2 (high). The quality level that will be chosen is the highest available according to the Renderer's material quality setting (see \ref Renderer::SetMaterialQuality() SetMaterialQuality()). If a technique requires SM3.0-only shaders, it can be marked as such by the "sm3" attribute.
- When a material defines several techniques for LOD levels and quality settings, they must appear in a specific order:
- - Most distant & highest quality
- - ...
- - Most distant & lowest quality
- - Second most distant & highest quality
- - ...
- A technique definition looks like this:
- \code
- <technique>
- <pass name="deferred|prepass|material|base|litbase|light|extra|shadow"
- vs="VertexShaderName" ps="PixelShaderName" alphamask="true|false"
- alphatest="true|false" blend="replace|add|multiply|alpha|addalpha|premulalpha|invdestalpha"
- depthtest="always|equal|less|lessequal|greater|greaterequal" depthwrite="true|false" />
- <pass ... />
- <pass ... />
- </technique>
- \endcode
- "Alphamask" is not an actual renderstate. It is a hint that the pixel shader will do discard(), and should therefore be rendered after geometry that does not use discard(), to ensure optimal depth buffer performance.
- The passes are:
- - deferred: deferred rendering G-buffer pass for opaque geometery. Writes material albedo, normals, specular power and depth.
- - prepass: light pre-pass rendering G-buffer pass for opaque geometry. Writes normals, specular power and depth only.
- - material: light pre-pass rendering material pass. Renders the opaque object using the light accumulation result.
- - base: forward rendering base pass. Renders the ambient light.
- - litbase: forward rendering base pass. Renders the ambient light and the first light affecting the object for optimization.
- - light: forward rendering light pass. Renders one light's contribution additively.
- - extra: custom rendering pass. Rendered after the opaque geometry.
- - shadow: shadow map rendering pass. Renders depth only.
- Note that the technique does not need to enumerate shaders used for different geometry types (non-skinned, skinned, instanced, billboard) and light types (directional, point and spot, shadowed and non-shadowed.) Instead specific hardcoded shader variations are assumed to exist.
- \page Lights Lights and shadows
- Lights in Urho3D can be directional, point, or spot lights. Shadow mapping is supported for all light types.
- A directional light's position has no effect, as it's assumed to be infinitely far away, only its rotation matters. It casts orthographically projected shadows. For increasing the shadow quality, cascaded shadow mapping (splitting the view into several shadow maps along the Z-axis) can be used.
- Point lights are spherical in shape. When a point light casts shadows, it will be internally split into 6 spot lights with a 90 degree FOV each. This is very expensive rendering-wise, so shadow casting point lights should be used sparingly.
- Spot lights have FOV & aspect ratio values like cameras to define the shape of the light cone.
- Both point and spot lights use an attenuation ramp texture to determine how the intensity varies with distance. In addition they have a shape texture, 2D for spot lights, and an optional cube texture for point lights. It is important that the spot light's shape texture has black at the borders, and has mipmapping disabled, otherwise there will be "bleeding" artifacts at the edges of the light cone.
- \section Lights_LightCulling Light culling
- When occlusion is used, a light will automatically be culled if its bounding box is fully behind an occluder. However, directional lights have an infinite bounding box, and can not be culled this way.
- In forward rendering, it is possible to limit which objects are affected by each light, by calling \ref Drawable::SetLightMask "SetLightMask()" on both the light and the objects. The lightmasks of the light and objects are ANDed to check whether the light should have effect: the light will only illuminate an object if the result is nonzero. By default objects and lights have all bits set in their lightmask, thus passing this test always.
- \ref Zone "Zones" can also be used for light culling in a similar manner. The lightmask of the zone the camera is in will be ANDed with each light's lightmask to see whether the light should be included in rendering. This method of light culling works equally in deferred and forward rendering. By default a zone has all bits set in its lightmask.
- Care must be utilized when doing light culling with lightmasks, because they easily create situations where a light's influence is cut off unnaturally. However, they can be a great performance boost: for example if you imagine a multi-store building with lights, lights would normally need to have shadows enabled to not "bleed" into the lower floors, which would cost performance. The bleeding could also be prevented by using unique lightmask bits on the objects and lights of each floor.
- \section Lights_ShadowedLights Shadowed lights
- Shadow rendering is easily the most complex aspect of using lights, and therefore a wide range of parameters exists for controlling the shadows:
- - BiasParameters: define constant and slope-scaled depth bias values for preventing self-shadowing artifacts. In practice, need to be determined experimentally. Also, these can be different for orthographic (directional) and projective (point and spot) shadows. Another way of fighting self-shadowing issues is to render shadowcaster backfaces, see \ref Rendering_Materials "Materials".
- - CascadeParameters: these have effect only for directional lights, and they consist of the number of splits, split lambda parameter, split fade range, and shadow maximum range. Lambda is between 0.0 - 1.0. Higher values create more high-resolution splits near the viewer. Split fade range determines to what degree the splits overlap, creating a smooth fade effect. For example fade range of 0.1 would use 10% of the full depth range to fade each split to the next. Geometry beyond shadow maximum range will be unshadowed (practically, an extra unshadowed split will be rendered, if maximum range is less than the far clip distance.)
- - FocusParameters: these have effect for directional and spot lights, and control techniques to increase shadow map resolution. They consist of focus enable flag (allows focusing the shadow camera on the visible shadow casters & receivers), nonuniform scale enable flag (allows better resolution), out-zooming enable flag (reduces fillrate of distant spot lights by not using the whole shadow map when not necessary), and quantization & minimum size parameters for the shadow camera view.
- Additionally, there exist shadow fade distance, shadow intensity, shadow resolution and shadow near/far ratio parameters:
- - If both shadow distance and shadow fade distance are greater than zero, shadows start to fade at the shadow fade distance, and vanish completely at the shadow distance.
- - Shadow intensity defines how dark the shadows are, between 0.0 (maximum darkness, the default) and 1.0 (fully lit.)
- - The shadow resolution parameter allows choosing between a fullsize (1.0), half-size (0.5) and quarter-size (0.25) shadow map. Choose according to the size and importance of the light; smaller shadow maps will be much less performance hungry.
- - The shadow near/far ratio controls shadow camera near clip distance for point & spot lights. The default ratio is 0.002, which means a light with range 100 would have its shadow camera near plane set at the distance of 0.2. Set this as high as you can for better shadow depth resolution, but note that the bias parameters will likely have to be adjusted as well.
- \section Lights_ShadowMapReuse Shadow map reuse
- The Renderer can be configured to either reuse shadow maps, or not. To reuse is the default, use \ref Renderer::SetReuseShadowMaps "SetReuseShadowMaps()" to change.
- When reuse is enabled, only one shadow texture of each shadow map size (full, half and quarter) needs to be reserved, and shadow maps are rendered "on the fly" before rendering a single shadowed light's contribution onto opaque geometry. This has the downside that shadow maps are no longer available during transparent geometry rendering, so transparent objects will not receive shadows.
- When reuse is disabled, all shadow maps are rendered before the actual scene rendering. Now multiple shadow textures need to be reserved based on the desired number of simultaneous shadow casting lights. See the function \ref Renderer::SetNumShadowMaps "SetNumShadowMaps()". If there are not enough shadow textures, they will be assigned to the closest/brightest lights, and the rest will be rendered unshadowed. Now more texture memory is needed, but the advantage is that also transparent objects can receive shadows. The exception is shadowed point lights: they need stencil masking to split into the 6 shadow map sides, which conflicts with the need to render transparent objects back-to-front, instead of rendering per light.
- \page Particles %Particle systems
- The ParticleEmitter class derives from BillboardSet to implement a particle system that updates automatically.
- The particle system's properties can be set through a XML description file, see \ref ParticleEmitter::LoadParameters "LoadParameters()".
- Most of the parameters can take either a single value, or minimum and maximum values to allow for random variation. See below for all supported parameters:s
- \code
- <particleemitter>
- <material name="MaterialName" />
- <sorting enable="true|false" />
- <updateinvisible enable="true|false" />
- <relative enable="true|false" />
- <emittertype value="point|box|sphere" />
- <emittersize value="x y z" />
- <direction min="x1 y1 z1" max="x2 y2 z2" />
- <constantforce value="x y z" />
- <dampingforce value="x" />
- <activetime value="t" />
- <inactivetime value="t" />
- <interval min="t1" max="t2" />
- <particlesize min="x1 y1" max="x2 y2" />
- <timetolive min="t1" max="t2" />
- <velocity min="x1" max="x2" />
- <rotation min="x1" max="x2" />
- <rotationspeed min="x1" max="x2" />
- <sizedelta add="x" mul="y" />
- <color value="r g b a" />
- <colorfade color="r g b a" time="t" />
- </particleemitter>
- \endcode
- Note: zero active or inactive time period means infinite. Instead of defining a single color element, several colorfade elements can be defined in time order to describe how the particles change color over time.
- \page AuxiliaryViews Auxiliary views
- Auxiliary views are viewports defined into a RenderSurface. These will be rendered whenever the texture containing the surface is visible, and can be typically used to implement for example reflections. The texture in question must have been created in rendertarget mode, see Texture's \ref Texture2D::SetSize "SetSize()" function.
- The viewport is not assigned directly to the texture because of cube map support: a cubic rendertarget has 6 render surfaces, and done this way, a different camera could be assigned to each.
- A "backup texture" can be assigned to the rendertarget texture: because it is illegal to sample a texture that is also being simultaneously rendered to (in cases where the rendertarget texture becomes "recursively" visible in the auxiliary view), the backup texture can be used to specify which texture should be used in place instead.
- When using deferred rendering, there is currently a limitation that the auxiliary view rendertarget can not be bigger in either width or height than the rendering window, due to the G-buffer's size. Overcoming this would require reserving an additional G-buffer for large auxiliary views.
- Rendering detailed auxiliary views can easily have a large performance impact. Some things you can do for optimization with the auxiliary view camera:
- - Set the far clip distance as small as possible.
- - Set the camera's viewmask to for example VIEW_REFLECTION, then clear that viewmask bit from objects you don't need rendered.
- - Use the camera's \ref Camera::SetViewOverrideFlags "SetViewOverrideFlags()" function to disable shadows, to disable occlusion, or force the lowest material quality.
- \page ForwardDeferred Comparision of forward, light pre-pass and deferred rendering
- The rendering mode configured to the Graphics subsystem determines whether forward, light pre-pass, or deferred rendering is used for opaque objects. Transparent objects are always rendered using forward rendering.
- \section ForwardDeferred_Forward Forward rendering
- For each light that influences the object in question, the object is redrawn with additive blending. Multiple lights per pass are not used to not explode the shader permutation count, and to not go over SM2.0 instruction limits. Scissor optimization is used to reduce pixel count in case of small lights / large geometries.
- \section ForwardDeferred_Prepass Light pre-pass rendering
- %Light pre-pass creates the following lightweight G-buffer, using 2 render targets:
- - World-space normal and specular power (D3DFMT_A8R8G8B8)
- - Linear depth (D3DFMT_R32F)
- The normals, specular power and depth of opaque objects are rendered first to the G-buffer. After this, a D3DFMT_A8R8G8B8 light accumulation buffer is cleared to black, and light volumes are rendered to it with additive blending, using stencil masking to optimize the light volume depth range if possible. The diffuse light color is rendered to the RGB channels, and monochromatic specular intensity is rendered to the A channel. Only half the intensity of lights is used to allow up to 2x "overburn" for the total accumulated lighting.
- When the light accumulation buffer is ready, opaque objects are rendered for the second time (the "material" pass), using the light accumulation buffer to calculate diffuse and specular lighting. Ambient color is also added at this point. The color of specular lighting is resolved by modulating the monochromatic specular intensity with the diffuse light color. This will not result in correct specular lighting when multiple lights combine, but is a reasonable approximation in most cases. Emissive and environment mapping effects can be added during the material pass.
- \section ForwardDeferred_Deferred Deferred rendering
- Deferred rendering creates the following G-buffer, using 3 render targets:
- - Diffuse albedo and specular intensity (D3DFMT_A8R8G8B8)
- - World-space normal and specular power (D3DFMT_A8R8G8B8)
- - Linear depth (D3DFMT_R32F)
- Opaque objects are rendered to the G-buffer first, then an initial full-screen quad is drawn to initialize the backbuffer, using the G-buffer information to blend between ambient lighting and fog color. After this, light volumes are rendered with additive blending, using stencil masking to optimize the light volume depth range if possible.
- After light accumulation, emissive properties of materials as well as effects like environment mapping need to be rendered in an additional "emissive" pass for objects that need them.
- \section ForwardDeferred_TemporalAA Temporal antialiasing
- When multisampling is enabled, both light pre-pass and deferred rendering use subpixel projection jittering to render temporal antialiasing that should look similar to 2x MSAA. Reprojection based on the previous frame's camera view transform is used to eliminate "ghosting" effects when the camera rotates, and additional ghosting prevention is done by analyzing the depth of each pixel compared to the previous frame. Depending on the GPU speed, this form of antialiasing has a low-to-moderate performance impact.
- \section ForwardDeferred_Conclusion Conclusion
- Deferred rendering will win particularly in vertex-heavy scenes, as the actual geometries need to be rendered only once. However, in simple scenes the cost of filling the G-buffer may be substantial and outweight the benefit. Light pre-pass does not consume as much texture sampling bandwidth when accumulating the lighting, so it may have a performance advantage over deferred when the lighting environment is complex. In the simplest scenes, forward rendering can still be assumed to be fastest.
- Note that it is not possible to specify the material's specular color in deferred rendering, only the specular intensity. The default forward rendering shaders have also been written in the same way to match the output of deferred rendering, but more material variety could in fact be achieved with forward-shaded materials, or with the material pass of light pre-pass rendering.
- \page Input %Input
- The Input subsystem provides keyboard and mouse input via both a polled interface and events. It is always instantiated, even in headless mode, but is active only once the application window has been created.
- Once active, the subsystem takes over the application mouse cursor. It will be hidden, so the UI should be used to render a software cursor if necessary. The cursor can be in either confined or non-confined mode. In confined mode (default) it is always forcibly centered to the window, so that mouse delta motion can be read "infinitely" in each direction. Non-confined mode is set by calling \ref Input::SetClipCursor "SetClipCursor(false)". In this case the cursor may freely travel out of the application window, which also means that infinite mouse delta motion can no longer be relied upon.
- The input events include:
- - E_MOUSEBUTTONUP: a mouse button has been released.
- - E_MOUSEBUTTONDOWN: a mouse button has been pressed.
- - E_MOUSEMOVE: the mouse has been moved. Both movement and cursor position will be sent, but the position is only useful in non-confined mode.
- - E_MOUSEWHEEL: the mouse wheel has been moved.
- - E_KEYUP: a key has been released.
- - E_KEYDOWN: a key has been pressed.
- - E_CHAR: translation of a keypress to Latin-1 charset for text entry. This is currently the only way to get translated key input.
- The input polling API differentiates between the initiation of a key/mouse button press, and holding the key or button down. \ref Input::GetKeyPress "GetKeyPress()" and \ref Input::GetMouseButtonPress "GetMouseButtonPress()" return true only for one frame (the initiation) while \ref Input::GetKeyDown "GetKeyDown()" and \ref Input::GetMouseButtonDown "GetMouseButtonDown()" return true as long as the key or button is held down.
- From the input subsystem you can also query whether the application is active/inactive, or minimized.
- In script, the polling API is accessed via properties: input.keyDown[], input.keyPress[], input.mouseButtonDown[], input.mouseButtonPress[], input.mouseMove.
- \page Audio %Audio
- The Audio subsystem implements an audio output stream using DirectSound. DirectSound requires a window handle, so sound can not be played back before the application window has been opened. Once playing, the following operations are supported:
- - Playing raw audio, Ogg Vorbis or WAV Sound resources using the SoundSource component. This allows manual stereo panning of mono sounds; stereo sounds will be output with their original stereo mix.
- - Playing the above sound formats in pseudo-3D using the SoundSource3D component. It has stereo positioning and distance attenuation, but does not (at least yet) filter the sound depending on the direction.
- For pseudo-3D positional sounds, the listener position and rotation have to be updated by calling \ref Audio::SetListenerPosition() "SetListenerPosition()" and \ref Audio::SetListenerRotation() "SetListenerRotation()".
- The output is software mixed for an unlimited amount of simultaneous sounds. Ogg Vorbis sounds are decoded on the fly, and decoding them can be memory- and CPU-intensive, so WAV files are recommended when a large number of short sound effects need to be played.
- For purposes of volume control, each SoundSource is classified into one of three categories:
- - %Sound effects
- - Music
- - Voice
- A master gain category also exists that affects the final output level. To control the category volumes, use \ref Audio::SetMasterGain "SetMasterGain()".
- The SoundSource components support automatic removal from the node they belong to, once playback is finished. To use, call \ref SoundSource::SetAutoRemove "SetAutoRemove()" on them. This may be useful when a game object plays several "fire and forget" sound effects.
- \section Audio_Parameters Sound parameters
- A standard WAV file can not tell whether it should loop, and raw audio does not contain any header information. Parameters for the Sound resource can optionally be specified through an XML file that has the same name as the sound, but .xml extension. Possible elements and attributes are described below:
- \code
- <sound>
- <format frequency="x" sixteenbit="true|false" stereo="true|false" />
- <loop enable="true|false" start="x" end="x" />
- </sound>
- \endcode
- The frequency is in Hz, and loop start and end are bytes from the start of audio data. If a loop is enabled without specifying the start and end, it is assumed to be the whole sound. Ogg Vorbis compressed sounds do not support specifying the loop range, only whether whole sound looping is enabled or disabled.
- The Audio subsystem is always instantiated, but in headless mode it is not active. In headless mode the playback of sounds is simulated, taking the sound length and frequency into account. This allows basing logic on whether a specific sound is still playing or not, even in server code.
- \page Physics Physics
- The %Physics library in Urho3D implements rigid body physics simulation using Open Dynamics %Engine.
- To use, a PhysicsWorld component must first be created to the Scene.
- The physics simulation has its own, fixed update rate. By default it is 60Hz. For higher rendering frame rates, physics motion is interpolated so that it always appears smooth. The update rate can be changed with \ref PhysicsWorld::SetFps "SetFps()" function. The physics update rate also determines the frequency of fixed timestep scene logic updates.
- The other physics components are:
- - CollisionShape: defines physics collision geometry. The supported shapes are sphere, box, cylinder, capsule, triangle mesh, convex hull and heightfield.
- - RigidBody: this component is necessary to create moving physics objects. Its parameters include mass and linear/angular velocities.
- - Joint: connects two RigidBodies together, or one RigidBody to a static point in the world. Currently ball and hinge joints are supported.
- Triangle meshes, convex hulls and heightfields are created by specifying a Model resource.
- Several collision shapes may exist in the same scene node to create compound shapes. An offset position and rotation relative to the node's transform can be specified for each. The shape (instead of RigidBody) also contains collision behaviour parameters: which other objects to collide with (see \ref CollisionShape::SetCollisionGroup "SetCollisionGroup()" and \ref CollisionShape::SetCollisionMask "SetCollisionMask()"), the friction coefficient, and the bounce coefficient.
- Note that static physics objects such as unmoving level geometry should not have RigidBody components at all.
- The physics simulation does all calculations in world space. Therefore nodes containing a RigidBody component should only be parented to the Scene (root node) to operate correctly. Hierarchically parented rigid bodies might be supported in the future.
- The physics world sends 3 types of events during its update step:
- - E_PHYSICSPRESTEP before the simulation is stepped.
- - E_PHYSICSCOLLISION (and E_NODECOLLISION to the participating scene nodes) for each collision during the simulation step.
- - E_PHYSICSPOSTSTEP after the simulation has been stepped.
- Note that if the rendering framerate is high, the physics might not be stepped at all on each frame: in that case those events will not be sent.
- \page UI User interface
- Urho3D implements a simple, hierarchical user interface system based on rectangular elements. The elements provided by default are:
- - BorderImage: a texture image with an optional border
- - Button: a pushbutton
- - CheckBox: a button that can be toggled on/off
- - Cursor: a mouse cursor
- - DropDownList: shows a vertical list of items (optionally scrollable) as a popup
- - LineEdit: a single-line text editor
- - ListView: shows a scrollable vertical list of items
- - Menu: a button which can show a popup element
- - ScrollBar: a slider with back and forward buttons
- - ScrollView: a scrollable view of child elements
- - Slider: a horizontal or vertical slider bar
- - Text: static text that can be multiline
- - UIElement: container for other elements, renders nothing by itself
- - Window: a movable and resizable window
- From the UI subsystem you can query the root element, which is an empty canvas (UIElement) as large as the application window, into which other elements can be added.
- Elements are added into each other similarly as scene nodes, using the \ref UIElement::AddChild "AddChild()" and \ref UIElement::RemoveChild "RemoveChild()" functions.
- \section UI_Defining Defining UI elements in XML
- Each UI element knows to load its properties from an XML file. There are two distinct use cases for this: either defining just the UI element style and leaving the actual position and dimensions to be filled in later, or fully defining a set of UI elements. For an example of defining element styles, see the file Data/UI/DefaultStyle.xml.
- The function \ref UI::LoadLayout "LoadLayout()" in UI will take an XML file and instantiate the elements defined in it. To be valid XML, there should be one root UI element. An optional style XML file can be specified; the idea is to first read the element's style from that file, then fill in the rest from the actual layout XML file. This way the layout file can be relatively simple, as the majority of the data is already defined.
- The XML data for each UI element follows. Everything is optional and defaults will be used if missing. Note the redundant ways in which to define element size. Also note the element class hierarchy; for example a Button derives from BorderImage, and all elements derive from UIElement. See the comments in the elements' header files for descriptions of each property.
- \subsection UI_UIElement UIElement
- \code
- <element name="ElementName" type="Element" >
- <position value="x y" />
- <size value="x y" />
- <width value="x" />
- <height value="y" />
- <minsize value="x y" />
- <minwidth value="x" />
- <minheight value="y" />
- <maxsize value="x y" />
- <maxwidth value="x" />
- <maxheight value="y" />
- <fixedsize value="x y" />
- <fixedwidth value="x" />
- <fixedheight value="y" />
- <alignment horizontal="left|center|right" vertical="top|center|bottom" />
- <clipborder value="l t r b" />
- <priority value="p" />
- <opacity value="o" />
- <color value="r g b a" | topleft="r g b a" topright="r g b a" bottomleft="r g b a" bottomright="r g b a" />
- <bringtofront enable="true|false" />
- <bringtoback enable="true|false" />
- <clipchildren enable="true|false" />
- <enabled enable="true|false" />
- <selected enable="true|false" />
- <visible enable="true|false" />
- <focusmode value="notfocusable|resetfocus|focusable|focusabledefocusable" />
- <layout mode="free|horizontal|vertical" spacing="s" border="l t r b" />
- <vars>
- <variant name="n" type="t" value="v" />
- ...
- </vars>
- </element>
- \endcode
- \subsection UI_BorderImage BorderImage
- \code
- <element type="BorderImage">
- <texture name="TextureName" />
- <imagerect value="l t r b" />
- <border value="l t r b" />
- <hoveroffset value="x y" />
- </element>
- \endcode
- \subsection UI_Button Button
- \code
- <element type="Button">
- <pressedoffset value="x y" />
- <labeloffset value="x y" />
- <repeat delay="d" rate="r" />
- </element>
- \endcode
- \subsection UI_Checkbox Checkbox
- \code
- <element type="Checkbox">
- <checkedoffset value="x y" />
- </element>
- \endcode
- \subsection UI_Cursor Cursor
- \code
- <element type="Cursor">
- <shape name="normal|resizevertical|resizediagonal_topright|resizehorizontal|resizediagonal_topleft|acceptdrop|rejectdrop"
- texture="TextureName" imagerect="l t r b" hotspot="x y" />
- ...
- </element>
- \endcode
- \subsection UI_Menu Menu
- If a popup element is specified, it will be searched for by name from the UI element hierarchy.
- \code
- <element type="Menu">
- <popup name="ElementName" />
- <popupoffset value="x y" />
- </element>
- \endcode
- \subsection UI_Text Text
- \code
- <element type="Text">
- <font name="FontName" size="s" />
- <text value="..." />
- <textalignment value="left|center|right" />
- <rowspacing value="s" />
- <selection start="s" length="l" />
- <selectioncolor value="r g b a" />
- <hovercolor value="r g b a" />
- </element>
- \endcode
- \subsection UI_Window Window
- \code
- <element type="Window">
- <resizeborder value="l t r b" />
- <movable enable="true|false" />
- <resizable enable="true|false" />
- </element>
- \endcode
- \subsection UI_DropDownList DropDownList
- The styles of the listview, popup and placeholder sub-elements can be specified within the respective XML elements. The listview can be pre-filled by specifying popup items; they will be searched for by name from the UI element hierarchy.
- \code
- <element type="DropDownList">
- <selection value="s" />
- <resizepopup enable="true|false" />
- <listview />
- <popup />
- <placeholder />
- <popupitem name="ElementName" />
- ...
- </element>
- \endcode
- \subsection UI_LineEdit LineEdit
- The style of the cursor sub-element can specified with the "cursor" XML element.
- \code
- <element type="LineEdit">
- <maxlength value="l" />
- <cursormovable enable="true|false" />
- <textselectable enable="true|false" />
- <textcopyable enable="true|false" />
- <text value="..." />
- <cursorposition value="p" />
- <cursorblinkrate value="r" />
- <echocharacter value="c" />
- <cursor />
- </element>
- \endcode
- \subsection UI_Slider Slider
- The style of the knob sub-element can specified with the "knob" XML element.
- \code
- <element type="Slider">
- <orientation value="horizontal|vertical" />
- <range max="m" value="v" />
- <knob />
- </element>
- \endcode
- \subsection UI_ScrollBar ScrollBar
- The styles of the back button, forward button and the slider can be specified with the respective XML elements. Note the buttons' nonstandard imagerect element, which specifies the image to use for both a horizontal and a vertical button.
- \code
- <element type="ScrollBar">
- <orientation value="horizontal|vertical" />
- <range max="m" value="v" />
- <scrollstep value="s" />
- <stepfactor value="f" />
- <backbutton>
- <imagerect horizontal="l t r b" vertical="l t r b" />
- </backbutton>
- <forwardbutton>
- <imagerect horizontal="l t r b" vertical="l t r b" />
- </forwardbutton>
- <slider />
- </element>
- \endcode
- \subsection UI_ScrollView ScrollView
- The styles of the horizontal and vertical scrollbars can be specified with the respective XML elements. If a content element is specified, it will be searched for by name from the UI element hierarchy.
- \code
- <element type="ScrollView">
- <viewposition value="x y" />
- <scrollstep value="s" />
- <pagestep value="p" />
- <horizontalscrollbar />
- <verticalscrollbar />
- <contentelement name="ElementName" />
- </element>
- \endcode
- \subsection UI_ListView ListView
- \code
- <element type="ListView">
- <selection value="s" />
- <highlight value="never|focus|always" />
- <multiselect enable="true|false" />
- <hierarchy enable="true|false" />
- <clearselection enable="true|false" />
- <doubleclickinterval value="i" />
- </element>
- \endcode
- \section UI_Layouts UI element layout
- By default %UI elements operate in a "free" layout mode, where child elements' positions can be specified relative to any of the parent element corners, but they are not automatically positioned or resized.
- To create automatically adjusting layouts, the layout mode can be switched to either "horizontal" or "vertical". Now the child elements will be positioned left to right or top to bottom, based on the order in which they were added. They will be preferably resized to fit the parent element, taking into account their minimum and maximum sizes, but failing to do that, the parent element will be resized.
- Left, top, right & bottom border widths and spacing between elements can also be specified for the layout. A grid layout is not directly supported, but it can be manually created with a horizontal layout inside a vertical layout, or vice versa.
- \page Serialization Serialization
- Classes that derive from Serializable can perform automatic serialization to binary or XML format by defining attributes. Attributes are stored to the Context per class. Scene load/save is implemented by Node and Component both deriving from Serializable.
- The supported attribute types are all those supported by Variant. Attributes can either define a direct memory offset into the object, or setter & getter functions. Zero-based enumerations are also supported, so that the enum values can be stored as text into XML files instead of just numbers.
- To serialize complex structures or other data where simple memory access or calling a setter or getter function is not enough, the default attribute access functions in Serializable can be overridden. See \ref Serializable::OnSetAttribute "OnSetAttribute()" and \ref Serializable::OnGetAttribute "OnGetAttribute()". For example, the components serialize their Resource pointers as ResourceRef or ResourceRefList this way.
- The attribute system also supports editing by providing human-readable names.
- \page Network Networking
- The Network library provides reliable and unreliable UDP messaging using ENet. A server can be created that listens for incoming connections, and client connections can be made to server(s).
- Packets are sent using a fixed number of channels (4 by default); packet order is guaranteed within each channel. If received out-of-order, reliable packets will be stalled until all in a sequence have been received, while older unreliable packets will simply be dropped if a newer packet has already been received. There is also an option to send unsequenced unreliable packets.
- Note that by default the Network library itself does not care of what is being sent (low-level networking.) The high-level networking protocol for multiplayer currently needs reimplementation.
- Outgoing packets are queued by calling \ref Peer::Send "Send()" on the networking peer. Packets can be received from networking peers by calling \ref Peer::Receive "Receive()". Events will be sent to notify of peer connections and disconnections, see NetworkEvents.h for the event definitions:
- * E_PEERCONNECTED
- * E_PEERDISCONNECTED
- All network packets are compressed using ENet's built-in compression.
- \page Tools Tools
- \section Tools_AssetImporter AssetImporter
- Tool that loads various 3D formats supported by Open Asset Import Library (http://assimp.sourceforge.net/) and saves Urho3D model, animation, material and scene files out of them. For the list of supported formats, look at
- http://assimp.sourceforge.net/main_features_formats.html.
- Usage:
- \verbatim
- AssetImporter <command> <input file> <output file> [options]
- Commands:
- model Export a model and animations
- scene Export a scene and its models
- dumpnodes Dump scene node structure. No output file is generated
- lod Combine several Urho3D models as LOD levels of the output model
- Syntax: lod <dist0> <mdl0> <dist1> <mdl1> ... <output file>
- Options:
- -b Save scene in binary format, default format is XML
- -i Use local IDs for scene nodes
- -na Do not export animations
- -ne Do not create Octree & PhysicsWorld extensions to the scene
- -nm Do not export materials
- -pX Use base path X for resources in the scene file
- -rX Use scene node X as root node
- -t Generate tangents to model(s)
- \endverbatim
- \section Tools_NormalMapTool NormalMapTool
- NormalMapTool converts normal map images into DXT5 format, with an encoding that preserves quality better than simply compressing the original, unmodified image. The encoding is:
- - X axis (red in the original normal map) goes into the alpha channel
- - Y axis (green in the original normal map) goes into the color channels
- - Z axis will be reconstructed in the pixel shader
- Usage:
- \verbatim
- NormalMapTool <input image file>
- \endverbatim
- The texconv tool from the DirectX SDK needs to be available through the system PATH.
- \section Tools_OgreImporter OgreImporter
- Tool that loads OGRE .mesh.xml and .skeleton.xml files and saves them as Urho3D .mdl (model) and .ani (animation) files. For other 3D formats and whole scene importing, see AssetImporter instead. However that tool does not handle the OGRE formats as completely as this.
- Usage:
- \verbatim
- OgreImporter <input file> <output file> [options]
- Options:
- -a Export animations
- -m Export morphs
- -r Export only rotations from animations
- -s Split each submesh into own vertex buffer
- -t Generate tangents
- \endverbatim
- Note: exporting only bone rotations may help when using an animation in a different model, but if bone position changes have been used for effect, the animation may become less lively. Unpredictable mutilations might result from using an animation in a model not originally intended for, as Urho3D does not specifically attempt to retarget animations.
- \section Tools_PackageTool PackageTool
- PackageTool examines a directory recursively for files and subdirectories, and creates a PackageFile. The package file can be added to the ResourceCache and used as if the files were on a (read-only) filesystem.
- Usage:
- \verbatim
- PackageTool <directory to process> <package name> [basepath]
- \endverbatim
- When PackageTool runs, it will go inside the source directory, then look for subdirectories and any files. Paths inside the package will by default be relative to the source directory, but if an extra path prefix is desired, it can be specified by the optional basepath argument.
- For example, this would convert all the resource files inside the Urho3D Data directory into a package called Data.pak (execute the command from the Bin directory)
- \verbatim
- PackageTool Data Data.pak
- \endverbatim
- \section Tools_RampGenerator RampGenerator
- RampGenerator creates 1D and 2D ramp textures for use in light attenuation and spotlight spot shapes.
- Usage:
- \verbatim
- RampGenerator <output file> <width> <power> [dimensions]
- \endverbatim
- The output is saved in PNG format. The power parameter is fed into the pow() function to determine ramp shape; higher value gives more brightness and more abrupt fade at the edge.
- The texconv tool from the DirectX SDK needs to be available through the system PATH.
- \section Tools_ShaderCompiler ShaderCompiler
- This tool generates HLSL shader permutations using an XML definition file that describes the permutations, and their associated HLSL preprocessor defines.
- The output consists of shader bytecode for each permutation, generated using fxc from the DirectX SDK, as well as an output XML file that describes the constant parameters and texture units (for pixel shaders only) used by each.
- Usage:
- \verbatim
- ShaderCompiler <definitionfile> <outputpath> [SM3] [define1] [define2] ..
- HLSL files will be loaded from definition file directory, and binary code will
- be output to same directory as the output file.
- \endverbatim
- It is possible to give additional defines from the command line. These will then be present in each permutation. SM3 is a special define which enables compilation of VS3.0 and PS3.0 code, otherwise VS2.0 and PS2.0 code is generated.
- fxc needs to be available through the system PATH.
- \page FileFormats Custom file formats
- Urho3D tries to use existing file formats whenever possible, and define custom file formats only when absolutely necessary. Currently used custom file formats are:
- \section FileFormats_Model Binary model format (.mdl)
- \verbatim
- Model geometry and vertex morph data
- byte[4] Identifier "UMDL"
- uint Number of vertex buffers
- For each vertex buffer:
- uint Vertex count
- uint Vertex element mask (determines vertex size)
- uint Morphable vertex range start index
- uint Morphable vertex count
- byte[] Vertex data (vertex count * vertex size)
- uint Number of index buffers
- For each index buffer:
- uint Index count
- uint Index size (2 for 16-bit indices, 4 for 32-bit indices)
- byte[] Index data (index count * index size)
- uint Number of geometries
- For each geometry:
- uint Number of bone mapping entries
- uint[] Bone mapping data, Maps geometry bone indices to global bone indices for HW skinning.
- May be empty, in this case identity mapping will be used.
- uint Number of LOD levels
- For each LOD level:
- float LOD distance
- uint Primitive type (0 = triangle list, 1 = line list)
- uint Vertex buffer index, starting from 0
- uint Index buffer index, starting from 0
- uint Draw range: index start
- uint Draw range: index count
- uint Number of vertex morphs (may be 0)
- For each vertex morph:
- cstring Name of morph
- uint Number of affected vertex buffers
-
- For each affected vertex buffer:
- uint Vertex buffer index, starting from 0
- uint Vertex element mask for morph data. Only positions, normals & tangents are supported.
- uint Vertex count
- For each vertex:
- uint Vertex index
- Vector3 Position (if included in the mask)
- Vector3 Normal (if included in the mask)
- Vector3 Tangent (if included in the mask)
- Skeleton data
- uint Number of bones (may be 0)
- For each bone:
- cstring Bone name
- uint Parent bone index starting from 0. Same as own bone index for the root bone
- Vector3 Initial position
- Quaternion Initial rotation
- Vector3 Initial scale
- float[12] 4x3 offset matrix for skinning
- byte Bone collision info bitmask. 1 = bounding sphere 2 = bounding box
-
- If bounding sphere data included:
- float Bone radius
- If bounding box data included:
- Vector3 Bone bounding box minimum
- Vector3 Bone bounding box maximum
- Bounding box data
- Vector3 Model bounding box minimum
- Vector3 Model bounding box maximum
- \endverbatim
- \section FileFormats_Animation Binary animation format (.ani)
- \verbatim
- byte[4] Identifier "UANI"
- cstring Animation name
- float Length in seconds
- uint Number of tracks
- For each track:
- cstring Track name (practically same as the bone name that should be driven)
- byte Mask of included animation data. 1 = bone positions 2 = bone rotations 4 = bone scaling
- uint Number of keyframes
- For each keyframe:
- float Time position in seconds
- Vector3 Position (if included in data)
- Quaternion Rotation (if included in data)
- Vector3 Scale (if included in data)
- \endverbatim
- Note: animations are stored using absolute bone transformations. Therefore only lerp-blending between animations is supported; additive pose modification is not.
- \page CodingConventions Coding conventions
- - Class and struct names are in camelcase beginning with an uppercase letter. They should be nouns. For example DebugRenderer, FreeTypeLibrary, Graphics.
- - Functions are likewise in upper-camelcase. For example CreateComponent, SetLinearRestThreshold.
- - Variables are in lower-camelcase. Member variables have an underscore appended. For example numContacts, randomSeed_.
- - Constants and enumerations are in uppercase. For example Vector3::ZERO or PASS_SHADOW.
- - Pointers and references append the * or & symbol to the type without a space in between. For example Drawable* drawable, Serializer& dest.
- - Class definitions in header files proceed in the following order:
- - public constructors and destructors
- - public virtual functions
- - public non-virtual member functions
- - public static functions
- - public member variables
- - public static variables
- - repeat all of the above in order for protected definitions, and finally private
- - Header files are commented using one-line comments beginning with /// to mark the comments for Doxygen.
- - Inline functions are defined inside the class definitions where possible, without using the inline keyword.
- */
|