GAME PROGRAMMING RESOURCES

MODELING FOR 3IMPACT

In this tutorial we assume you have read this article and that you know how to use your 3d modeler to make your own 3d texture mapped models.

Tips about exporting 3d models to DirectX® (.x) file format are available for 3D Studio Max®, Lightwave®.

Before starting modeling for 3Impact, you need to understand the concept of closed hull. A 3d model, made of just triangles, is a closed hull if:

  • it completely encloses a portion of space.
  • all triangle-edges are shared by two triangles.



  • For example, the second mesh in the picture above is NOT a closed hull because it breaks both the rules. It doesn't completely encloses a portion of space and three edges aren't shared by two triangles.


    Note that despite the 'hole', the torus on the left, in the picture above, IS a closed hull, because it completely encloses the space inside the 'looping-pipe'. While the torus on the right is not a closed hull due to the missing triangles.


    The open box on the left, above, is a closed hull. As a matter of fact, the dimension (thickness) of the box sides is not null, and the narrow space inside them is completely enclosed. Also, all edges are shared by two triangles.

    Instead, the box on the right is not a closed hull because the sides are flat. And there are four edges that aren't shared by two triangles.


    Another confusing case is depicted above. The box completely encloses a portion of space, but there are six edges that aren't shared by two triangles. The vertical edge on the left and the one in the middle of the picture are degenerate triangles really. The long edge is half-shared by 3 triangles, so the second condition for a closed-hull is not met.

    OVERVIEW

    When making your own 3d models, keep in mind that:

  • the world center in your modeler will be the so called source-model-center when the 3d model is imported to 3Impact space. It is used as a reference by many engine functions, like for example iMeshLocationSet() and iBodyLocationSet().


  • the so called center-of-mass is automatically assigned by the engine on body creation. It is another reference point used by some functions, like for example iBodyLocationCMSet(). It has nothing to do with source-model-center.


  • the side you consider the front of your models should face towards world's +Z axis, when the object is not rotated, in 3Impact space. Make sure that your models are oriented to match this guideline, in your 3d modeler. Failing to match this guideline will generate a lot of confusion when dealing with object orientations, in your games' code. Note that some modelers don't use the same coordinate system as 3Impact, so, for instance, 3Impact's +Z world axis is +Y world axis in 3D Studio Max®.


  • IMPORT YOUR OWN 3D MODELS

    3Impact engine can interactively play your own 3d models as bodies in a space that obeys physics laws. You just have to apply forces and torques to your objects and the engine will bother checking for collision detection and response for you.

    There are two types of bodies: static and dynamic.

    1. Let's start by turning your own 3d object into a dynamic body. In your favorite 3d modeler, make a simple object to use in place of the ball, in the interactive-ball game (see above).


    Make sure that the model:
  • is made of triangles only. Any quad or superior polygon must be split to triangles. Most modelers provide a 'triangulate' function.
  • has a texture map assigned to all triangles (non-textured faces are not supported). Texture images should be power-of-two sized. For example 256x256, 512x256, 128x1024, etc. Image format must be .bmp, .dds, .dib, .jpg, .png or .tga.
  • does not include isolated vertices, degenerated faces, etc.
  • does not include very big triangles. Triangle side length should never be greater than 10-20 meters, in order to ensure proper computation and rendering.
  • does not have more than 65536 faces.


  • 2. In the C:\Program Files\3impact5\3ImpactWork folder, create a new folder named, for example, 'mygame_res'. Save your new model into it as an .x file, named, for example, 'mymodel.x'.

    NOTE: make sure that DirectX® templates, texture mapping, material and vertex normal data are actually exported to the destination .x file, and also that companion texture image files are present in the destination folder with the .x file.

    3. By using your 3d model as a reference,


    make a new model made of just spheres.


    The resulting model will be used by the engine for collision detection. Consider it as an additional and invisible component of the body.

    As a matter of fact, dynamic bodies are sphere groups. They are fast to process for collision checking, even when they happen to collide with polyhedron-based (static) bodies. Don't worry, nobody will realize that it is made of spheres in your final game

    Make sure that the model:
  • is made of just spheres, made of triangles only (triangulate). The number of vertices for each sphere should be between 20 and 400.
  • has no texture.
  • does not have more than 65536 faces.


  • 4. Save the sphere-group model to 'mygame_res' folder as an .x file, named, for example, 'mymodel_.x'. It should be the same name of the previous model followed by '_' (underscore).

    NOTE: make sure that DirectX® templates and material data are actually exported to the destination .x file.

    NOTE: using spheres that are smaller than 1 centimeter is not recommended. Very small spheres may not be properly detected by the conversion utility (3Impact converter, .spg creation option). Use no more than 30/40 vertices to model very small spheres, to increase the chances for a successful detection.

    5. From the original texture-mapped model, make a third model. It will be used by the engine as a reference to compute mass data for the new dynamic body. In order to properly compute dynamics behavior, the engine must know how the mass is distributed in the body.


    Make sure that the model:
  • is made of triangles only (triangulate).
  • has no texture.
  • is made of perfectly closed hulls.
  • does not include very big triangles.
  • does not have more than 65536 faces.


  • 6. Save the mass model to 'mygame_res' folder as an .x file, named, for example, 'mymodel__.x'. It must be the same name of the previous sphere-group model ending with '__' (two underscores).

    NOTE: make sure that DirectX® templates and material data are actually exported to the destination .x file.

    7. Run 3Impact Converter
  • choose a rendering device, click OK
  • click 'Generate sphere-group based body...' button
  • browse to 'mygame_res' folder and double-click 'mymodel_.x' file
  • browse to 'mygame_res' folder and click OK


  • 8. Open your compiler and, in the source code for the interactive-ball game, replace the

    Ball=iBodySGCreate("default_res\\ball_.spg",0.13f);
    BallMesh=iBodyMeshCreate("default_res\\ball.x",Ball);

    lines with

    Ball=iBodySGCreate("mygame_res\\mymodel_.spg",0.13f);
    BallMesh=iBodyMeshCreate("mygame_res\\mymodel.x",Ball);

    and then compile and run.

    REMARKS

  • The invisible body is derived from two different source models in .x format: a collision detection model, made of just spheres, and a mass distribution model, made of just closed hulls. The two source.x files are packed to one single .spg file by the 3Impact Converter utility. The invisible body is created by calling the iBodySGCreate() function for the .spg file.
  • The visible mesh is derived from a texture mapped model of any complexity, in .x file format. This source model must use one single texture image and must have all triangles mapped with it. You can attach an unlimited number of meshes to a given invisible body, by calling the iBodyMeshCreate() many times for the same body.
  • There is no need for the collision detection model to match all details of the visible mesh model. A rule of thumb is to use bigger spheres to form a rough shape and then add smaller spheres to fill corners and small details that are likely to collide with other objects and the scenery.
  • There is no need for the mass distribution model to match the shape of the visible mesh model either. Actually, you may often want to model it as a different geometry. Keep in mind that the engine will use the mass model as a reference to determine how the mass is distributed in the body. For example, the mass model for a plane can be like


    As a matter of fact, the mass of the fuselage is bigger than the mass of the wings. Where the mass model provides a bigger volume, the engine will assign a denser mass to the body.


  • Remember, the mass model has nothing to do with collision detection. It is the collision detection model (sphere-group) that determines where a body is solid and where it is not. The mass model, instead, only determines what parts of the body weight more and what parts are light.

    MODELING THE SCENERY

    You can model any scenery by using your favorite modeler and directly use it in your games as a solid environment. Your characters, vehicles and all other dynamic objects will properly collide with it, automatically!

    1. Let's turn your own 3d level (outdoor/indoor scenery, dungeon, land, race-track, planet, anything) into a static, collision-capable, body. In your favorite 3d modeler, make a simple object to use in place of the terrain, in the interactive-ball game.


    The geometry can be of any complexity, provided that a texture map is assigned to all triangles forming the model.

    Make sure that the model:
  • is made of triangles only. Any quad or superior polygon must be split to triangles. Most modelers provide a 'triangulate' function.
  • has a texture map assigned to all triangles (non-textured faces are not supported). Texture images should be power-of-two sized. For example 256x256, 512x256, 128x1024, etc. Image format must be .bmp, .dds, .dib, .jpg, .png or .tga.
  • does not include isolated vertices, degenerated faces, etc.
  • does not include very big triangles. Triangle side length should never be greater than 10-20 meters, in order to ensure proper rendering.
  • does not have more than 65536 faces.


  • For this example, make also sure that the model is about 250 meters wide, and that the world center, in your modeler, lies above the 'ground'.


    2. If you haven't done it already, in the
    C:\Program Files\3impact5\3ImpactWork folder, create a new folder named, for example, 'mygame_res'. Save your new model into it as an .x file, named, for example, 'mylevel.x'.

    NOTE: make sure that DirectX® templates, texture mapping, material and vertex normal data are actually exported to the destination .x file, and also that companion texture image files are present in the destination folder with the .x file.

    3. In order to create a new file, in your modeler, save your 3d level model again, with a new name. For example 'mylevel_5.00.x'.

    Note that the name must end with '_XX.x', where XX is a value. For more about this value, see iBodyCreate() function in Reference document.

    In your modeler, remove texture mapping information from the model and save it again.


    The resulting model will be used by the engine for collision detection. Consider it as an additional and invisible component of the scenery.

    Unlike dynamic bodies, that must be made of spheres, static bodies can be made of polygons. This allows for an accurate and detailed collision detection between moving objects and the scenery.

    Note that there is no need for an additional mass model for static bodies, as their mass is assumed uniform and infinite.

    5. Run 3Impact Converter
  • choose a rendering device, click OK
  • click 'Generate polyhedron-based body...' button
  • browse to 'mygame_res' folder and double-click 'mylevel_5.00.x' file
  • browse to 'mygame_res' folder and click OK


  • 6. Open your compiler and, in the source code for the interactive-ball game, replace the

    Terrain=iBodyCreate("default_res\\terrain_5.00.ply");
    TerrainMesh=iBodyMeshCreate("default_res\\terrain.x",Terrain);

    lines with

    Terrain=iBodyCreate("mygame_res\\mylevel_5.00.ply");
    TerrainMesh=iBodyMeshCreate("mygame_res\\mylevel.x",Terrain);

    and then compile and run.

    REMARKS

    1. Make sure the collision detection, static body, model does not include big triangles. Triangle side length should never be greater than 10-20 meters. Due to finite CPU math, collision detection for big triangles may be inexact, causing unstable simulation. A typical problem caused by big triangles are 'jittering' bodies when they are supposed to rest on the ground instead.

  • Make also sure that the collision detection model is exported to .x without any hierarchy. Some 3d tools can export geometry as a hierarchy of meshes. Some of the meshes in the hierarchy can be null and this may cause collision detection problems.


  • 2. Dynamic, sphere-group based bodies will successfully collide with all triangles in the static body geometry, however they will not properly collide with triangle edges, if they are not shared with another triangle.

    For example, consider the case of an one-triangle static body colliding with an one-ball dynamic body.


    The collision will not be detected properly if the sphere hits the edge of the triangle. The problem depicted above can be fixed by modeling the triangular static body as follows instead:


    A rule of thumb is to try to model your static body geometry as a closed hull or as a group of closed hulls.

    3. Static bodies may require huge amount of memory. The amount of memory used by a static body is more or less proportional to the volume of the bounding box enclosing its geometry.

    Using one single static body for a wide scenery isn't recommended.

    You should always try to split the source model of a very big scenery body to a number of smaller models, each saved as a different .x file and converted to distinct .ply resources.

    Each body can then be loaded by calling iBodyCreate(), to compose the whole scenery.

    4. Collision detection models can be made of different parts. See for example iBodyBodyFeedback(), in Functions Reference document.
  • For sphere-group-based (dynamic) bodies, each sphere defines a single part.
  • For polyhedron-based (static) bodies, in order to define different parts, you must assign a different material to each part (group of faces), in your 3d modeling application. The engine will see the parts in alphabetical order, using the name you have assigned to each material as a reference. So, if you have a collision detection model made of 3 materials named for example m01_paved, m03_grass and m02_sand, the engine will consider m01_paved as sub-part 0, m02_sand as sub-part 1 and m03_grass as subpart 2.
  • SURFACE MATERIALS

    Meshes, the visible part of your objects, have default surface properties that depend on how you modeled the source geometry, in your modeler.

    SMOOTHNESS

    Because surface smoothness depends on vertex normals, surfaces that are smooth (non-faceted) in your modeler, will look smooth when rendered by 3Impact engine.


    Above, the same object with a faceted surface (left) and a smooth surface (right). In order to preserve surface smoothness, make sure that normal information is exported to your DirectX® (.x) files.

    SPECULARITY

    Specularity makes a surface look shiny. In general, if a surface looks shiny in your modeler, it will look shiny when rendered by 3Impact engine. However if the specular effect rendered by 3Impact doesn't look the same, you can fine-tune it by calling the iMeshSpecularitySet() function for your mesh.


    Above, the same object with a zero specular (left) and with some specular (right).

    LUMINOSITY

    A mesh can be rendered as glowing by calling the iMeshEmissiveSet() function for it. Please see function reference documentation for details.

    TEXTURE-MIXING

    You can add details to your meshes by applying a secondary texture to them. By calling the iMeshSecondaryTextureSet() function you can also set the blending factor between the primary and the secondary texture. Please see function reference documentation for details.

    REFLECTIVITY

    Reflectivity, the ability to reflect the surrounding environment, isn't directly exported from your modeler to 3Impact engine as a surface property. But you can add such a property to your meshes by calling a couple of functions in your DLL code.


    For a working example of the technique, see the source code named EnvironmentMap.

    REFRACTION

    Making your solids look like they are made of glass is easy. With one simple function call you can even adjust the index of refraction and blend transparency with main texture colors, to simulate tinted crystal.


    For a working example of the technique, see the source code named GlassEffect and TintedGlass.

    BUMPINESS

    By calling a few functions in your DLL code you can also add bumpiness to mesh surfaces. Bumpiness is rendered by computing, for each single pixel, how the light is reflected by a surface. An image, called bump-map, is used as a reference for the computation.


    Bump-mapping dramatically improves rendering quality without basically affecting frame-rate because you can perform detailed surfaces for low-poly meshes. See BumpMapping source code for a working example.

    Even, with the help of specific utilities called normal mappers, you can automatically generate bump-maps (also known as normal-maps) from hi-poly-count meshes, so that, when they are applied to a low-poly-count version of the same meshes, the geometry looks almost identical to their original hi-poly-count version, but is rendered at the speed of light as they are low-poly-count models!


    In the picture above, a bump map is applied to a reflective surface. For a working example of this technique, see the source code named BumpMappedEnvironmentDynamicMap.

    MULTI-SURFACE MESHES

    The sample code named 'BallGameV5' (or 'MultiTextureMesh', if you still use the old regular meshes from version 4 of the engine) will show you how to load and render meshes that are mapped by using two or more distinct textures or materials.

    However, keep in mind that your game will load faster if you split your objects to parts (one distinct .x file for each group of faces using the same texture).


    Imagine that you have modeled an object with 3 different textures and surface materials, like the one in the picture above.

    All you have to to, is saving it as 3 different models. Basically, split the object by material and by texture, and generate 3 different .x files.

    After that, you can load the 3 meshes by calling iMeshCreate() or iBodyMeshCreate() 3 times to have all parts put together, and all different surface materials rendered fast and accurately.