If you remember, we ended our coding excercises at place, where we almost created our first Newtonian body, but we did not actually have enough models.
We discussed collision shapes a bit. So let’s create one for our brand new model!
We have a nice ramp to work with. But how we can reconstruct the same shape in the terms of Newton? Newton offers a set of collision shapes for us:
-
Sphere
-
Box
-
Cone
-
Capsule
-
Cylinder
-
Chamfer Cylinder
-
Convex Hull
-
Trimesh
Obviously, not sphere, cone, capsule, nor cylinder make sense for us. We could use box shape, but then we simply ignore our inner faces (inside walls):
A bit better, but still the same situation with convex hull shape:
Generally, the way we create our Newtonian body is:
- create collision shape
- create blank Newtonian body
- set body properties like collision shape, mass, inertia parameters, etc.
- store the pointer to the graphical entity for that body in the
userData
property
And then Newton Game Dynamics will take your body into account when processing other objects
in the NewtonWorld
.
Tree mesh collision shape
So we gonna use the triangle mesh shape. What we gonna do is loop through all the triangles of our mesh and build its copy, but in the world of “physic” bodies.
To loop through all the triangles, we need to take each 3 edges of our mesh and the corresponding vertices (because each edge is represented by two its vertices - their indexes in the list of vertices) and create Newtonian triangle. Irrlicht stores vertices in one of three formats:
- plain vertex, represented by its three coordinates; the
irr::video::S3DVertex
class in Irrlicht - vertex with texture coordinates;
irr::video::S3DVertex2TCoords
class - vertex with its tangent information;
irr::video::S3DVertexTangents
class
All those are represented by irr::video::S3DVertex
class or its children. Moreover, we do not
need nothing but the information on vertex’ coordinates in our case, so we may use only the
base class’ properties.
The code, creating trimesh collision shape is quite simple and straightforward:
We take the edges (indices), find their vertices, create a triangle - and we’re done! You may have noticed, we do not actually create the collision shape here - we take it as an argument for our function. You will see why this is done that way in a moment.
Now it’s body’s turn! But we need to extend our Entity
class with the NewtonBody
field so that we can seamlesly integrate it to our engine:
And now we are ready to set our NewtonBody
:
There is an interesting piece here, though: we used recursion to create collision shape…
But if you remember, we did not create collision shape with our createTrimeshShape
method -
all we do in that method is that we add new triangles to the existing shape. That’s because meshes
in Irrlicht are stored as a tree structure - they may have sub-meshes, which are still
parts of the whole mesh. And they can have their sub-meshes too. So we created a blank
collision shape and fill it with new parts of the mesh.
Doing it that way prevents us from overcomplicating the task and building a composite mesh, made of a set of trimeshes. That would be really hard to calculate in real-time! And our really simple scene would work with the speed of 5x5 battle in Unreal Tournament 3…
Looking back to our list, we should now fill out all the fields for our NewtonBody
. And since
we are making the static model, we will set its mass to zero. This is enough for Newton to
treat our body as the static one. I placed the other code to show the other fields, we need
to fill in case we have a “usual” body.
So the other fields of NewtonBody
are:
massMatrix
, which determines how the mass is spread along the bodytransformCallback
andforceAndTorqueCallback
are two mandatory fields, required by NewtonuserData
, which will hold the pointer to the whole entity
massMatrix
could be calculated automatically from the collision shape, like in our case.
Without digging much into details, we will simply set it so the mass of our body is distributed
uniformely.
transformCallback
is the function, which will be called for our body each time it changes its
position due to the interaction with other bodies inside NewtonWorld
.
forceAndTorqueCallback
is the function, which applies forces and torques to our body. This is
a bit tricky, but you need to keep track of each force and torque by yourself and then apply
them in a way that they summ up and create the final force, influencing the body. We will
talk about it later, when we will deal with impulses.
So, the transformCallback
:
Nothing tricky here.
To put everything in place, let’s add a sphere to our scene. The process is totally same, except of the collision shape creation - in case of primitives like box, sphere or cylinder, it is much more easy than with trimeshes - you do not need to loop through any indices or vertices - just set shape params like dimensions or radius. And body creation process is totally same.
Have no fear about code duplication - we will remove it later. When you are done, you should get picture like this one:
Congrats! That’s our first completed dynamic scene!