shown in other instead.
Virtual World Structure
Every Unigine-based virtual world is a set of different objects with certain properties. Almost all of the objects can be seen in the virtual world, however some of them are pseudo-objects, which can't be displayed in a normal mode (physical primitives, sectors, occluders, etc.).
The 3D space in Unigine is represented by the right-handed Cartesian coordinate system: X and Y axes form a horizontal plane, Z axis points up. When exporting an animation from 3D editors, Y is considered a forward direction.
Positive rotation angle sets the rotation counterclockwise. It corresponds to the right-hand rule (if you set right hand thumb along the axis, other fingers wrapped will show rotation direction).
In terms of Unigine, a virtual world, or a scene, is everything that is included in this world:
- All objects, which are called nodes
- Materials on these objects
- A number of general rendering and physics settings
Worlds can be as large as the level designer wishes, if not limitless. This is not a problem, as Unigine supports data streaming, and required resources — meshes, textures, animations, sounds — are dynamically loaded in run-time. Resources that are no longer needed are unloaded from memory.
Also, for common outdoor scenes, we recommend you to use the scale 1 unit = 1 meter, when you export objects from a 3D modeling application.
A large world may not be convenient for designing and editing. In this case, the world can be split in parts and developed as a set of scenes. After being edited, the scenes can be smoothly merged in Unigine Editor or using scripts, as one scene can be appended to another, and all the objects (nodes) and used materials from the second scene will be added to the first, while the rendering and physics settings of the host world remain unchanged. Worlds can also be merged in the same manner in run-time, but it won't give any advantage over usage of one large world, because:
- The merging should be performed by the game application itself.
- It will not fix the accuracy problem of coordinates stored as floats.
Of course, separate worlds can be loaded in turn, one by one, as conventional levels.
If the level designer wishes, they may divide the world into sectors. If the world can't be divided this way, a spatial partitioning (based on dynamic binary trees) will be automatically performed for the world by Unigine in run-time.
Unigine provides a set of built-in objects allowing you to create a world containing practically all of the objects present in real life. For convenience, they are formed into several groups that are responsible for different kinds of operations
Hierarchy of Nodes and Surfaces
All nodes are organized into a hierarchy. Each node can have multiple children. Usually coordinates and orientation of the first-level nodes are set in the global (world) coordinate system, while coordinates and orientation of their child nodes are in local coordinate systems of their parents (if not chosen otherwise). This allows easy transformation and rotation of the whole hierarchy tree branch only by transforming and rotating the root node.
Each node is a root for the hierarchy of its surfaces. The surface serves as the atomic rendering unit. It can represent:
- A part of the object that needs to have its own separate material.
- Different levels of details (LODs). In this case, they represent the same object or its part in more or less detailed variants (a high-polygonal and a low-polygonal model). Which one of these surfaces is visible at any given time is determined by the surface properties.
The number of surfaces depends on how a mesh was exported and cannot be changed dynamically in the runtime. Each surface usually requires a separate DIP request to the GPU.
Surfaces also participate in culling of invisible parts of the object when it is hidden by some other objects on the foreground. Moreover, they are used to calculate collision detection with physically simulated objects.
All objects share common options for their surfaces. Each surface can be enabled or disabled for rendering, as needed. They are organized in a hierarchy, with their node being a root. While the surfaces' hierarchal order can be freely changed (by dragging the node with ALT pressed), they themselves cannot be added, deleted, or otherwise altered in Unigine editor. The reason is that surfaces are formed during object creation in an external 3D editor. So to change them, one needs to re-export the object.
The surfaces use a separate material and a property, both of which are loaded from their libraries.
|Clicking this icon allows to edit a instanced material or a property on the spot. That means, a child material/property is created, and only its changed parameters (if compared to the parent) are stored in the world file.|
Surfaces often represent LODs of the same object. For the detailed description of Min parent, Max parent, Visible and Fade distances parameters, see Level of detail.
Physical Simulation of Objects
Besides being only a noninteractive environment, objects can take part in physical simulation. To be effective and at the same time keep the overall framerate high, physics is always a very rough approximation of the real world. Its main aim is to detect collisions between the objects.
For that, an object should be assigned a body that describes how it can behave and what physical properties it possesses. For example, whether it is a rigid body that always stays solid and undeformed or a cloth which can be folded and torn.
The type of the object, however, is not enough for an object to start interacting. Its volume should be approximated using some kind of a physical primitive (or a set of them) — a shape. Unigine provides several types of such primitives: a box, a sphere, a capsule, a cylinder, a convex hull, or an arbitrary mesh shape. This shape is used to compute collisions between the objects.
A couple of shapes can be connected with one of the joints: fixed, ball, hinge, prismatic, cylindrical, wheel or suspension. They describe how two shapes can possibly move relative each other.
Nodes themselves do not say anything about how the node object is to be rendered. This information is stored in the materials associated with particular object surfaces. Materials provide a set of properties, based on which surfaces are rendered. Here they are:
- Options. The set of options is pre-defined and invariable for all materials. Each option either enables or disables some kind of behavior. Option values for standard materials, which are contained in the "unigine" library, are hard-coded; values for all other materials can be changed.
- States. They define conditions, basing on which Unigine selects appropriate shaders, textures, and parameters among all defined. For example, one can define a state turning on and off drawing of foam in water simulation and provide different shaders for both states (with and without foam).
Textures. They are an important part of a material. Usually, the material has several textures defined. The common reasons for it are the following:
- A shader may need more than one texture for processing.
- Usually, different textures are used on different render passes.
- States also may influence the number of textures, for example, each state may require its own texture.
- Parameters. They are passed as arguments to shaders, which require them.
- Shaders. They are the very core of materials. It is shaders who actually draw the material based on different conditions. Each material is usually equipped with several shaders, and the appropriate one is chosen according to the current render pass and state.
In Unigine, materials are organized in a hierarchy, like nodes, but are completely independent from the node hierarchy. There is a set of base materials provided by Unigine by default, which are at the top of the material hierarchy. Such organization makes it easy to create new materials based on previously defined. Base materials pass their properties to derived materials; but this is not enough, another material with the same properties is useless, that is why derived materials extend base materials by adding new properties or modify it by overriding the existing ones. All inherited and non-overridden properties will be updated automatically, if they are updated in the parent material.
Look at the picture below, for example.
The left cube is rendered using one of the base materials from the "unigine" library. The right cube inherits its material from that base and simply changes one of the textures. There is no need to think about other properties, as they are inherited. However, if one needs, they may change any property, just like we've changed the texture for the cube.
All material properties (except shaders) can easily be overridden in Unigine Editor. However, if you need to extend the set of existing properties or override shaders, you need to edit the XML file with your material definition by hand. In this case, refer to the Materials article, as it contains a thorough description of material declarations in XML.
In order for a set of materials to be used in the scene, it should be organized in a library, which, in its turn, should be imported in the world configuration file. A material library is an XML file, which simply lists required materials with their properties. There is no need to include the default material library, it is always included implicitly.
The proper order of materials loading is important. If library A has materials that inherit from materials in library B, library B should be included first. Say, you have two libraries, custom1.mat and custom2.mat. If a material in custom2.mat (F in the picture below) inherits from a material in custom1.mat (C in the picture below), the library custom1.mat should be loaded first.
For the object to be properly integrated in the world, defining its position, inherent characteristics and outside appearance will be insufficient. The properties specify the way the object will behave and interact with other objects and the scene environment. For example, they specify if the object is interactive and whether it is a switch. For a character, properties can specify the character health points or gold amount. Thus, the properties make the nodes comply with the game/application logic.
Properties are organized according to the same principles as materials.
Properties Hierarchy is represented by the hierarchically organized list of the properties, that can be assigned to the nodes used in the scene. It is independent of node and material hierarchies. Creating a child allows to change the particular setting for the property, while its other options will fully correspond to the parent ones. There is no need to manually edit the basic child settings, if the parent is modified later - they are be updated automatically. The hierarchy is easily edited in the desired way: the inheritance relations can be changed simply by dragging, properties can be cloned, assigned or removed with one button click. Besides cloning the whole property, it is also possible to copy separately all its settings, choose another property, to which they will be applied, and merely paste them.
Properties Libraries describe the properties states and parameters as well as the parent-child relations. They are stored in the XML file with ".prop" extension, that should be declared in the world file for library preloading. Please note that the preloading order is of importance, just like for materials.