bw logo

Chapter 10. Models

For the purposes of the BigWorld client, a model is a self-contained unit of geometry that can draw itself into a 3D scene at the location of a world-space transform matrix. Moreover, all models may have animations that alter their appearance over time — some models explicitly support animations of their nodes (which are skinned), whereas the others are animated by displaying alternate geometries.

Moo, the BigWorld 3D engine, currently exports three kinds of objects that may be used as models:

  • Meshes with skeletons.

  • Meshes without skeletons.

  • Billboards (a special form of simple geometry).

However, the model concept in the BigWorld client encapsulates anything that fits into the definition above, and the implementation is easily extended to incorporate new kinds of objects.

Moo names its meshes visuals (visuals actually include a good deal more than a simple polygon mesh. They can have groups of meshes, bones, envelopes, materials, and a hierarchical skeleton too) and .visual files can be readily created from a 3ds Max model using a BigWorld exporter. Node-based animations can also be created with the exporter. A .model file can then be created with the tool Model Editor, so that the visual and its animations are tied together. Model files that are billboards or static meshes (and their animations) can also be created with Model Editor.

A model file can also specify a simpler parent file to be used when drawn in the distance. Chains of parent model files thus formed are known as level-of-detail (LOD) chains.

10.1. Performance

In order to improve rendering performance, a model can be flagged in Model Editor to be batch rendered, which results in the creation of the batched tag in the generated model file (for details, see the document Content Tools Reference Guide's section Model Editor Panel summary Object Properties panel).

The batch rendering works by caching per-instance data (essentially lighting conditions and transforms) at traverse time, and once the scene has been traversed, rendering all instances at the same time, only updating the data necessary for each render. This saves the engine from setting vertices, indices, and textures multiple times for batched models. It does use a bit more memory, but gives a considerable performance boost.

It is advisable to use the batch flag on models with many instances of it in the scene. In FantasyDemo, the batch flag is used on trees, guards, striffs, chickens, and the guard's guns. Please note that the flag does not affect models that use tints.

10.2. Hard Points

Hard points, or attachment points, can be conceived as logical patches of Velcro that allow us to stick a gun in a hand, sling a backpack over a shoulder, or place a security camera on a turret. The artists must embed hard points in their .visual files using dummy nodes.

Hard points use well-defined names, preceded by 'HP_' prefix, so that entities can scan for hard point nodes. The significant information is:

  • Name.

  • Position.

  • Orientation.

This information allows the developer to attach any object to any other, within the constraints of game logic.

Examples of hard points include:

  • HP_LeftHand

  • HP_RightHand

  • HP_Shoulder

  • HP_Belt1

10.2.1. Naming scheme

In order to avoid the need for an intermediate step, there needs to be an explicit pairing between character hard points and item hard points. Every item needs a hard point for every specific way that it can be held.

As an example, listed below are the hard points for a human character and a gun.

  • In human.model:

    • HP_Left_Hand

    • HP_Right_Hand

    • HP_Belt_1

    • HP_Belt_2

    • HP_Belt_3

    • HP_Belt_4

    • HP_Shoulder

    • HP_Blade_Lower

    • HP_Blade_Upper

  • In gun.model:

    • HP_Left_Hand

    • HP_Right_Hand

    • HP_Belt_2

    • HP_Shoulder

10.2.2. How it works

The (client-side) Entity class provides a list of hard points, but only if asked by the specializing class. For example, when a model is loaded, it will find all nodes prefixed with (for instance) 'HP_'. These are then stored in a hardPoint list that is owned by the model.

When an item is equipped, the entity/game arbiter will be asked to match up the item with the correct hard point. For example, if the 'next weapon' button is pressed, the next weapon in the inventory can be attached to the right hand hard point.

10.2.3. Syntax

The syntax for using hard points from Python is elegant and powerful. To attach model gun to model avatar on hard point hand, use the following syntax:

avatar.hand = gun

A model is checked when it is attached to ensure that it is not attached elsewhere. To retrieve the model attached to avatar's hand, simply use:

model = avatar.hand

If no model is attached, then None is returned.

The model is attached by reference, not by copy, so anything that can be done to the original model reference can be done to the reference retrieved from a hard point.

For example, gun.Shoot() and avatar.hand.Shoot() have the same effect.

10.2.4. Data

A model definition is an XML file specifying:

  • A base model definition reference (optional).

  • The visual defining the mesh.

  • The animations the mesh can use.

  • The actions that the model can perform (for more details, see Action Queue).

The Model Editor tool is used to create a .model file that links an object's geometry to its animations and defines the sets of animations/actions that are possible to play on this object.

As with all resource files in the BigWorld framework, .model files are in XML format. They are hierarchical and inherit data from their parent(s), in this way basic animations that apply to a large set of characters can be isolated from more character-specific animations without having to be duplicated.

The example below defines a very simple model:

<jogger.model>

  <nodefullVisual>  jogger  </nodefullVisual>
  <parent>          biped   </parent>

  <animation>
    <name>      jog         </name>
    <frameRate> 30.0        </frameRate>
    <nodes>     jogAnim     </nodes>
    <alpha>
      <Torso>   0.0  </Torso>
      <Pelvis>  1.0  </Pelvis>
    </alpha>
  </animation>

  <action>
    <name>          BIPED_JOG  </name>
    <animation>     jog        </animation>
    <blendInTime>   0.300000   </blendInTime>
    <blendOutTime>  0.300000   </blendOutTime>
    <filler>        false      </filler>
    <blended>       false      </blended>
    <isMovement>    true       </isMovement>
    <isCoordinated> false      </isCoordinated>
    <isImpacting>   true       </isImpacting>
    <match>
      <trigger>
        <minEntitySpeed> 1.0  </minEntitySpeed>
        <maxEntitySpeed> 3.0  </maxEntitySpeed>
        <capsOn>         16   </capsOn>
      </trigger>
    </match>
  </action>
<jogger.model>

Example of .model file

This file describes a character (jogger) which has a geometry defined by the visual file jogger and has a standard set of biped actions via the <parent> tag, which may include walk, run, and jump animations, but also specifies a jog animation.

The animation section includes:

  • Name of the animation.

  • Frame rate at which the animation should normally be played at.

  • Tag <nodes>, which refers to the name of the animation file that contains the raw keyframe data.

The <action> section describes the action name that is used to play this action from the Python code.

10.3. SuperModel

A SuperModel is a collection of models that need to function as one. The SuperModel class is a utility class that forms a flexible basis for modules that want to use models. It is used for the static models specified in chunks, and the dynamic models that entities can manipulate.

The SuperModel provides an efficient representation (both in memory and in CPU) of a conceptual model. The supermodel is made up of selectable parts, and these parts have an inheritance tree for specifying animations, actions, material overrides, and most importantly, lower level of detail (LOD) parts that may be substituted at appropriate distances.

The supermodel brings all these parts and their adornments together into one conceptual model that automatically takes care of the complexity that arises from the multi-part and LODing features.

An example of the most basic SuperModel is a single mesh, which has been exported from 3ds Max using the BigWorld exporter; into the format understood by the 3D engine Moo.

SuperModels do not live in the scene graph or in chunks, and provide no interfaces to the scripting system. These matters are left up to higher-level classes, which are encouraged to use SuperModel for all their model needs.

10.3.1. Design

There are model files, with the .model extension, but there are no explicit SuperModel files.

There is the SuperModel class, which holds together and controls the animation and rendering of a number of models. A SuperModel is created based on information in chunk and model files (these are instance-like classes — there is nothing analogous to PyModelInfo.).

Using LOD ratios, the SuperModel class can manage the transition between, say, an avatar being rendered at a high LOD using three separate models, to it being rendered at a low LOD using just one.

Animations are accumulated on the same inheritance hierarchy, and the animation most appropriate to the current LOD level is used. All the animations for all the LOD levels are interpreted and selected from a flat namespace. Attempting to play an animation that does not exist (or does not exist at the current LOD level) selects an infinite length animation of the model's initial pose. Care must be taken to ensure that multi-model SuperModels do not waste time animating unnecessarily (e.g., when all the small parts have an animation overriding the whole part's animation, it would be a waste of time to apply the whole part's animation).

The mesh files themselves specify how a part is connected to others for multi-part supermodels.

10.3.2. SuperModel classes

The SuperModel class implements the basic functionality of the BigWorld model definition, using the objects provided by Moo. It combines a number of the .model files created by Model Editor (but usually just one) into one conceptual model, managing any animations and level-of-detail chains. The SuperModel class is detailed in SuperModel.

Two classes currently use SuperModels in the BigWorld client, for two different needs:

  • ChunkModel

  • PyModel

Both are described in the following subsections.

10.3.2.1. ChunkModel

A ChunkModel is a model that inhabits the static scene base (e.g., rocks, trees). Together with the terrain, it populates the client world and forms the majority of interesting scenery.

All ChunkModels are added to the collision scene for their chunk, unless flagged otherwise. They may optionally play one animation, at a specified speed multiplier — otherwise they are static.

They depend heavily upon the services of their SuperModel, supplying only the interface required to live in a chunk, and the simple instructions to play back their single animation.

10.3.2.2. PyModel

This class implements the model as it appears to the scripting environment.

It allows scripts to perform the following operations:

  • Fetch bound actions sourced from the model's definition.

  • Reference hard points (for details, see Hard Points).

  • Specify position, rotation, and scaling.

  • Add motors to move itself around in the scene (such as an Action Matcher).

  • Add trackers for inverse kinematics.

  • Add particle systems tied to any node.

  • Control the generation of footsteps and dust particles.

  • Control visibility and shadows.