Cross-Platform Game Development for C++ Developers, Part V: OGRE 3D, Page 2
Looking at OGRE Objects
A Mesh object represents a discrete model or a set of geometry, which is self-contained and is typically fairly small on a world scale. Mesh objects are assumed to represent movable objects as opposed to the static geometry that makes up the background of the level. As you might guess, Mesh objects are managed by the MeshManager and are loaded from the OGRE ".mesh" file format. Many translators are available for importing meshes from popular design packages, though most developers use MilkShape 3D. Mesh objects can also be animated using skeletal animation.
Mesh objects are the templates for Entities: the individual movable objects in the world.
You might have one Mesh of a zombie and then instantiate eight zombie entities from that for a particular room. SceneManager::createEntity() handles the details of naming the mesh and indicating its resource (for example, "zombie.mesh"). To make them appear, you still have to attach them to a SceneNode. By attaching entities to SceneNodes, you can create complex hierarchical relationships between the positions and orientations of entities. You then can modify the positions of the nodes to indirectly affect the entity positions later. This allows the zombie to pick up a chainsaw, for example.
When a Mesh is loaded, it comes with a number of materials defined. A Mesh can have more than one material attached to it (in other words, different parts of the mesh may use different materials). This is because a Mesh is composed of many SubMesh objects, each of which can each have its own material.
The Material object specifies what basic surface properties objects have, such as reflectance of colors, shininess, Goraud shading, texture layers, texture maps, blending, environment mapping, culling mode, and filters. Materials can either be set up programmatically by calling SceneManager::createMaterial() and tweaking the settings, or by specifying it in a dynamically run script.
Overlays and 2D Elements
Overlays allow you to render 2D and 3D elements on top of the normal scene contents to create effects like heads-up displays (HUDs), menu systems, status panels, and frame rates, or just to show you how many zombies you've slain. Overlays can contain 2D or 3D elements. While 2D elements are used for HUDs, 3D elements can be used to create realistic cockpit details (see Figure 2). You can create overlays either through the SceneManager::createOverlay(), or you can define them in an overlay script. You can also show multiple overlays at once, and the Overlay::setZOrder() method determines their Z order.
Figure 2. Overlay of a 2D Speedometer on the Game FragFist
The OverlayElement class abstracts the details of 2D elements, which are added to overlays. All items that can be added to overlays are derived from this class. The key common features of all OverlayElements are things like size, position, and basic material name. GuiManager::createOverlayElement() adds a 2D element to an overlay or overlay container. OGRE features an event-based GUI system that allows you to build overlays using buttons, scrollbars, text boxes, and the usual suspects.
Skeletal animation (or "skinning") occurs by moving a set of hierarchical bones within the mesh, which in turn moves the vertices of the model according to the bone assignments stored in each vertex. These animations are configured in your modeling tool of choice. OGRE supports the following skeletal animation modes:
- One mesh per single skeleton
- Unlimited bones per skeleton
- Hierarchical forward-kinematics on bones
- Multiple named animations per skeleton (for example, "Walk," "Run," "Jump," "Shoot," and the like)
- Unlimited keyframes per animation
- Linear or spline-based interpolation between keyframes
- A vertex can be assigned to multiple bones and weighted for smoother skinning
- Multiple animations can be combined with a blended weighting
Skeletons and the animations that go with them are held in .skeleton files, which are produced by the OGRE exporters. These files are loaded automatically when you create an Entity based on a Mesh, which is linked to the skeleton in question. The entity is then given an "animation state" object per animation on the skeleton. An entity's AnimationState object then can be used to control where it is in the loop by calling addTime().
Shadows are an important part of rendering a believable scene. They both provide drama and clarify spatial relationships. Unfortunately, shadows are also one of the most challenging aspects of 3D rendering, and they are still very much an active area of research. Because no single shadow-rendering method is perfect, OGRE provides stencil, texture-based, and modulative shadows. It also supports additive light masking, which builds up light contribution in non-shadowed areas (see Figure 3).
Figure 3. The ShortHike Space Station Simulator
Although shadows are disabled by default, you can activate them through various means:
- Use SceneManager:setShadowTechnique();.
- Create one or more lights (which cast shadows by default).
- Use setCastShadows(false) on objects you don't want to cast shadows.
- Use SceneManager::setShadowFarDistance to limit the distance at which shadows are considered to improve performance.
- Use Material::setReceiveShadows(false) on self-illuminating objects (you don't want your torch to be obscured by shadow).
About the Author
Victor Volkman has been writing for C/C++ Users Journal and other programming journals since the late 1980s. He is a graduate of Michigan Tech and a faculty advisor board member for the Washtenaw Community College CIS department. Volkman is the editor of numerous books, including C/C++ Treasure Chest and is the owner of Loving Healing Press. He can help you in your quest for open source tools and libraries, just drop an e-mail to sysop@HAL9K.com.