[game tech] 

World Modeling


EDITOR'S NOTE  

This page makes frequent references to commercial games that exemplify the modeling techiques described. For more information on these games, see the Game Development Resources page. 


Foundations

The first stage of any graphics pipeline must be the world model. This stage is responsible for representing the objects in a simulation in some way that is efficient to process into pixels. Since the subsequent stages of the pipeline will vary based on the type of rendering being done, the world model must be chosen to accomodate the style of game being built. 

As we shall see, the two stages which have the greatest impact on world modeling design are hidden surface removal and texture mapping. For example, if the texture mapper is limited to working with scaled vertical spans (sometimes called slivers) a la Wolfenstein 3D, then the world model will necessarily be limited in certain ways. 

Styles of World Models

If we restrict ourselves to just first person 3D primarily indoor simulations (e.g. Wolfenstein 3D, Doom, Duke Nukem 3D, Descent, Quake), there are basically four main styles of world modeling being used today: 
Occupancy Grid Supports only flat maps with orthogonal walls of uniform height. Suitable for raycasting and sliver renderering. Used in Wolfenstein 3D, Blake Stone, etc.
Sector Based Supports multiple height maps with non-orthogonal walls. Walls are usually limited in terms of vertically-aligned portals. Often prevented from having one floor over another. Suitable for 2D BSP tree based hidden surface removal. Used in Doom, Dark Forces, Duke Nukem 3D, etc.
Connected Cubes Supports almost any world shape and point of view. Uses cube connectivity to store sector adjacency for hidden surface removal. Used only by the Descent game engine.
CSG or Brush Based Supports almost any world shape and point of view. Suitable for 3D BSP tree based hidden surface removal, usually in conjunction with other HSR stages. Used in Quake and UNREAL.
Each style of modeling is more powerful but also more complex than the last. Thus, in designing a graphics pipeline it is important to choose a modeling style that supports the rendering style needed for gameplay, while minimizing programming complexity and maximizing performance.  


Occupancy Grid

The occupancy grid model divides the level up into a two dimensional rectangular array (often of a convenient size like 64 x 64). Each element of the array defines the contents of a square region of space in the level (often encoded into a single byte value). Each element may contain a wall or door, an impassable object such as a table or bookcase, an enemy or powerup, or just empty floor. Because of the regularity of the grid, all objects in the world are exactly the same size (e.g. four feet by four feet), and the walls are limited to right angles. Usually the simple occupancy coding does not provide for variable heights, so all walls and rooms are exactly the same height (usually about eight feet). 
Figure 1. Occupancy Grid Figure 2. Raycast View
The regularity of the grid makes this model suitable for a simple and efficient graphics pipeline. The pipeline is basically reduced to determining the distance to the first cell to block the player's vision in each column of the display. This is a simplified version of raytracing called raycasting

Another distinct advantage to the occupancy grid model is the ease of creating level editors. A basic graphic level editor needs only to support placing different object types in a rectangular grid -- essentially, this is a fancy bitmap editor. It would even be possible to use an ASCII text file for the level data, with simple codes for the map cells. 

Although raycasting engines are simple and efficient, they are becoming less and less common in mainstream gaming. The limitations of the world model are just too severe for adequate visual realism, and today's hardware can easily cope with more complex environments.  


Sector Based

Sector based models are most commonly used in the commercial 3D games available today. Sector based models are often deprecated for being "flat" -- indeed Descent's curving mineshaft architecture can not be supported by a sector based model. Most next generation games (e.g. Quake) are switching to a more flexible CSG approach. 

IMHO, sector based models have not quite out-lived their usefulness. They offer several advantages over more complex schemes. They are well understood and easy to work with. Level editing programs are easier to write and use than 3D CSG modeling programs. Finally, most real-world architecture is designed using a "flat" floor plan that is very similar to the sector based model. 

Sector based models use a 2D polygonal map annotated with height information to define a game level. The fundamental unit of modeling is a polygonal sector, which defines a flat area of the map with a given floor height, ceiling height, and usually light level. The edges of the sector polygons (often referred to as segments) form the walls of the 3D world. Unlike the coarse grained occupancy grid model, each sector and segment are defined by a list of 2D vertices in a fine grained coordinate system. Each unit of the coordinate system is on the order of one inch (or about two to four centimeters) in real world metrics. 
Figure 3. Sector Map Figure 4. Sector View
Since the floors and ceilings are strictly horizontal and the walls are strictly vertical, the sector based model can be used with a relatively simple "constant-z" texture mapping renderer. If the player is restricted from tilting or tipping his head, and all surfaces are either strictly horizontal or strictly vertical, then each row of the floors and ceilings and each column of the walls are at a constant depth from the viewer. This simplifies perspective correct texture mapping greatly, which is one reason why these limitations were placed on the Doom universe. See the Texture Mapping page for more details. 

In general, the walls (i.e. sides) that surround a sector extend from the floor to the ceiling. Whenever two adjacent sectors share a common edge, a portal exists between the two spaces. In this case, the opening extends vertically from the maximum of the two floor heights to the minimum of the two ceiling heights. As a result, two polygons are needed instead of one: 
Figure 5. Sector Portal

Sector Data Structures

There are four basic data structures used to encode the level design information: Vertex, Segment, Side, and Sector: 

The Vertex structure simply encodes a map location in 3D world space using two coordinates x, and y. Height information (the z coordinate) is encoded separately as needed by the other data structures. 

struct Vertex
{
   int            x, y;                // world coordinates
};
The Segment structure describes one line segment of a sector. Each segment connects exactly two vertices, "from" and "to". The normal vector of the line connecting the "from" vertex to the "to" vertex points to the interior of the sector. This is called the "right" side. If the segment is shared by two sectors, then the side opposite the normal vector is used to surround the second sector. This side is called the "left" side. All segments have at least a "right" side. Two-sided segments also have a "left" side. 
struct Segment
{
   Vertex*        verts[2];            // "from" and "to" verts
   Side*          sides[2];            // "right" and "left" sides
};
The Side structure defines the textured polygons that hang on the sides of segments. In addition to reiterating the segment information, the side structures identify the sector that they help surround. Most importantly they contain pointers to the textures that will be used to render the resulting polygons. 
struct Side
{
   short          index;               // unique identifier
   Vertex*        verts[2];            // "from" and "to" verts
   Segment*       segment;             // segment that side is attached to
   Sector*        sector;              // sector that side helps surround
   
   Texture*       texture_hi;          // upper texture
   Texture*       texture_rg;          // normal texture
   Texture*       texture_lo;          // lower texture
};
Sectors are polygonal areas of uniform height and brightness. The Sector structure contains floor and ceiling height values as well as an ambient brightness level. They also contain texture pointers that describe how to render the floor and ceiling polygons. Finally, they must contain pointers to the Side structures that define the sector boundaries. Notice that the Sector structure does not contain its own corner vertices, as these can be derived from the Sides and Segments. 

The Sector structure shown below also contains vertical adjustments (i.e. z values) for the floor and ceiling polygons at each corner vertex. This information allows the engine to support "sloped" floors in addition to flat ones. 

struct Sector
{
   short          index;               // unique identifier
   short          floor;               // floor height
   short          ceil;                // ceiling height
   short          bright;              // ambient light level

   Texture*       tex_ceil;            // ceiling texture
   Texture*       tex_floor;           // floor texture

   Side*          sides[MAX_VERTS];    // sides

   short          vfloor[MAX_VERTS];   // vertical adjustments for
   short          vceil[MAX_VERTS];    // floor and ceiling vertices
   
   Sector*        next;                // link for sector list
};

Extensions to the Sector Model

The Sector data structure above shows one common extension to the basic sector model: sloped floors and ceilings. Several additional extensions are possible, and will be briefly outlined. 
Sloped Walls Analogous to the sloped floors technique shown above, add horizontal adjustments to sides or segments. As with sloped floors, this model enhancement requires a free-direction texture mapper in the rendering pipeline. 
Solid Objects Create a new data structure to describe solid objects that inhabit sector space. These objects can be constructed from polygons in a BSP tree, or as simple graphic primitives such as cubes, cylinders, and pyramids. 
Sector-Over-Sector Permit sectors to overlap provided their vertical extents are discontinuous. This does not require any changes to the modeling structures, but only to the rules governing their use. Alternatively enhance the Vertex structure to support a third dimension. 
Layers Create a new data structure, the Layer, which contains all of the Sectors within a given vertical extent. This technique is analogous to the way architectural floor plans are constructed. This also requires special handling for sectors that extend between layers (e.g. ramps, elevator shafts, and exteriors). 
Some of these extensions introduce additional complexity into the HSR stage and texture mapping portions of the renderer. Any extension which causes surfaces to deviate from strictly horizontal or strictly vertical (including true perspective head tilting or tipping) requires use of a more complex free direction or perspective correct texture mapper. Likewise, extensions which allow sector spaces to overlap (e.g. sector-over-sector or layering) cause great problems for the use of 2D BSP trees in the HSR stage. 

The Alpha engine currently uses an extended sector model including sloped floors, solid objects, and sector-over-sector. In addition, the Alpha engine allows full six degrees of freedom for the player's viewpoint, and so requires a perspective correct texture mapper.  


Connected Cubes

The Connected Cubes world model goes a step beyond sector based approaches to model space as a collection of connected hollow volumes. Each volume is a simple convex polyhedron of six faces and eight vertices. Each cube is connected to at least one other by sharing a common face. As in the sector based model, shared faces form portals between adjacent volumes. 
Figure 6. Cube Model
This model was developed by Parallax Software for the Descent engine, and has not been seen elsewhere. The data structures below are from the Descent Level Specs v0.10, copyright Parallax Software, 1995. Cryptically enough, Parallax refer to their sectors as "segments" and to neighboring sectors as "children": 
typedef struct segment {
   side    sides[6];          // 6 sides
   short   children[6];       // indices of 6 children segments:
                              //   front, left, top, right, bottom, back
   short   verts[8];          // vertex ids of 4 front and 4 back vertices
   short   objects;           // index of objects in this segment
   ubyte   special;
   byte    matcen_num;
   short   value;
   fix     static_light;
   short   pad;
} segment;
The connected cube model offers several advantages over the simpler sector based model. Since each vertex is truly three dimensional, the cube model allows for much more complex level design than sector based models. All floors, walls, and ceilings are inherently sloped, and there is no limit to the number or organization of portals in a "wall". 

At the same time the connected cube model avoids the complex and espensive preprocessing phase of 3D BSP construction that is often needed for the brush based model. The cube adjacency information is sufficent to establish a valid drawing order for all polygons and all points of view as long as all of the cubes are convex. Also, the well defined four-sided portals implicit in the connections between neighboring cubes provide for an efficient screen-space beam tree HSR approach

About the only real disadvantages to this model are that it puts more burden on the level designer, and that it is not more widely supported. The first problem is that constructing simple architectural models is generally more work because the only graphic primitive is the six-sided polyhedron. The second problem is that since the model is not more widely used, it is not very widely written about. Therefore developing an efficient graphics pipeline for this model is a more speculative exercise.  


CSG or Brush Based

The final model we will examine is considered by many to be the "most 3D" of all. This family of models is called collectively CSG (Constructive Solid Geometry) or in the case of Quake "brush" based. 

In the general case, CSG models combine simple 3D primitives (e.g. cubes, tetraherda, cylinders, spheres) into more complex shapes by means of regularized Boolean set operators (e.g. union, intersection, negation, etc.). CSG models are typically stored as binary trees whose leaves are primitives and whose nodes are the operators that combine the subtrees: 
Figure 7. CSG Tree
CSG is a very efficient and flexible means of modeling a 3D object, but is relatively expensive computationally to render. This modeling technique is commonly used in professional 3D CAD/CAM systems. Based on some preliminary screen shots, it appears that the game UNREAL uses a polyhedral CSG world model (i.e. all primitives are polyhedra -- no real spheres or cylinders). 

The Quake engine uses a much more limited world model of "brushes" for its MAP files. The brush based model is similar to the CSG model, except that the only Boolean operator used is "union". Each primitive object in the world is a three dimensional "brush", which is itself a collection of textured polygons. 

Each brush is defined by a set of intersecting planes (not polygons). The BSP compiler calculates the polygon boundaries from the 3D plane intersections. This simplifies brush definition in that each plane can be defined by three nocolinear points, regardless of the number of vertices needed to describe the resulting polygon: 


EDITOR'S NOTE: 
The following is an excerpt from Niklata's Quake MAP Specs. The full page is available at the Quake Technical Resources

Each brush statement looks like this:  

 {
  ( 128 0 0 ) ( 128 1 0 ) ( 128 0 1 ) GROUND1_6 0 0 0 1.0 1.0
  ( 256 0 0 ) ( 256 0 1 ) ( 256 1 0 ) GROUND1_6 0 0 0 1.0 1.0
  ( 0 128 0 ) ( 0 128 1 ) ( 1 128 0 ) GROUND1_6 0 0 0 1.0 1.0
  ( 0 384 0 ) ( 1 384 0 ) ( 0 384 1 ) GROUND1_6 0 0 0 1.0 1.0
  ( 0 0  64 ) ( 1 0  64 ) ( 0 1  64 ) GROUND1_6 0 0 0 1.0 1.0
  ( 0 0 128 ) ( 0 1 128 ) ( 1 0 128 ) GROUND1_6 0 0 0 1.0 1.0
 }
That's probably just a bit confusing when you first see it. It defines a rectangular region that extends from (128,128,64) to (256,384,128). Here's what a single line means:  
  ( 128 0 0 ) ( 128 1 0 ) ( 128 0 1 ) GROUND1_6 0 0 0 1.0 1.0
   1st Point   2nd Point   3rd Point  Texture  

The Quake world model appears to allow for the translation of each brush along any axis, but not for rotation or overall scaling. 

Needless to say, constructing a complex world from a collection of polyhedral primitives is no small task. Much of the challenge of using such a flexible world model lies in creating efficient tools for level designers. It will be interesting to see the solutions provided by Quake and UNREAL level editors as they become available. 


Conclusions

As with everything in game engine design, selecting a world model is a matter of balancing tradeoffs between flexibility, efficiency, and complexity. As hardware grows more capable, and as gamers grow ever more demanding, level designers need ever greater flexibility to construct their imaginary realms. At the same time, complexity for its own sake becomes tiresome for both the designer and the player. 

As raycasting engines die out, so one would imagine will spacial occupancy grid models. Likewise, connected cube models have never really caught on, despite their interesting capabilities. Most new game engines are abandoning the venerable sector based model for some flavor of CSG. Perhaps the best approach is some sort of hybrid. It all depends on the needs of a particular game. 


back to milo's home page | e-mail milod@netcom.com 
This page is designed and implemented by John DiCamillo 
Copyright © 1995-1997 John DiCamillo. All rights reserved. 
 

Hosted by Irth Networks - http://www.irth.net