If you are a game developer and need a very powerful physics engine why not choose Newton? Newton Game Dynamics is a very scalable real time physics engine capable of most of today’s must-haves for games. I started playing with Newton Game Dynamics while I was developing the blueEngine in early G-Productions days. It’s no secret that I started to develop a game engine again. This time a full shader driven engine but back to the topic.
I want to point out that I did not develop the source myself. Credits go to the team who released the Newton Game Dynamics SDK. I simply changed it to work with the DirectX objects so users have some help when integrating Newton into their DirectX game engine. Most of the code found here was taken directly from the NewtonSDK samples or from the DirectX SDK samples.
In this post we will learn how to use Newton with DirectX mesh files. You will see how easy it is to integrate Newton with a DirectX based game. I assume you are already familiar with C++, DirectX and have a basic knowledge how to use a compiler. If you don’t already have go and download the latest Newton version at Newton Game Dynamics. At the time this post was written the latest version was 2.07. I will still use the version 1.53 but the code is the same and we will talk about the differences. For simplicity reasons we will build upon the mesh tutorial shipped with the DirectX SDK.
1. Initialize Newton in our app
To initialize Newton Game Dynamics you only need four functions. After having set the correct include and library paths within your application let’s start. The complete code for the physics stuff can be found in the physics.cpp and physics.h of the NewtonTutorial1 project which you can download here. Let’s take a look what those functions do.
DWORD g_dwNumBytes; // our pointer to the Newtonworld. Here is all the action :) NewtonWorld* nWorld; //----------------------------------------------------------------------------- // PhysicsMemAlloc feeds the Newtonworld with all the memory needed // PhysicsMemFree releases the memory again. These functions can // easily be changed to meet the needs of your own memory manager so // your game engine can easily take control of this. //----------------------------------------------------------------------------- void* PhysicsMemAlloc( int sizeInBytes ) { g_dwNumBytes += sizeInBytes; return malloc (sizeInBytes); } void PhysicsMemFree( void *ptr, int sizeInBytes ) { g_dwNumBytes -= sizeInBytes; free (ptr); } //----------------------------------------------------------------------------- // InitPhysics is our main entry point. If we want physics we have // to call the the function NewtonCreate. As parameters the memory // allocation/deallocation methods are accepted. We also need to tell // Newton how "big" our world is so the function accepts as parameters // the bounding box of our world //----------------------------------------------------------------------------- HRESULT InitPhysics(D3DXVECTOR3 vMin, D3DXVECTOR3 vMax) { HRESULT hr= S_OK; nWorld = NewtonCreate (PhysicsMemAlloc, PhysicsMemFree); NewtonSetWorldSize( nWorld, (float*)&vMin, (float*)&vMax ); return hr; } //----------------------------------------------------------------------------- // Just release everything and destroy our physics world :( //----------------------------------------------------------------------------- void CleanUpPhysics() { NewtonDestroyAllBodies( nWorld ); NewtonDestroy (nWorld); }
As you can see the whole magic is within InitPhysics and CleanUpPhysics. The piece of code should be self-explanatory so I won’t go into detail. If you have questions please refer to the samples shipped with the NewtonSDK. Most of the code is explained there in detail.
2. Create a simple mesh
Now that we know how to set up our physics world let’s start with adding some action to our scene. Take a look at the class CD3DXMesh. This is a simple mesh class which creates box, sphere or cylinder meshes with the D3DX library. We will use this for starting. Let’s take a look into the method CD3DXMesh->Init
if( m_type == BOX ) { hr = D3DXCreateBox(g_pd3dDevice, m_vecSize.x, m_vecSize.y, m_vecSize.z, &pMeshSys, NULL); } else if( m_type == SPHERE ) { hr = D3DXCreateSphere( g_pd3dDevice, m_vecSize.x, 50, 50, &pMeshSys, NULL); } else if( m_type == CYLINDER ) { hr = D3DXCreateCylinder( g_pd3dDevice, m_vecSize.x, m_vecSize.z, m_vecSize.y, 50, 50, &pMeshSys, NULL); } else return E_FAIL;
As you can see depending on the parameter we are creating our desired mesh and saving it. The method Init does some cloning of the mesh to get it into the right format for texturing. Now where is all the physics? Here is the method in our file physics.cpp.
HRESULT CreatePhysicsBody( CD3DXMesh* pMesh ) { NewtonCollision* collision; NewtonBody* body; D3DXVECTOR3 vSize; vSize = pMesh->GetSize(); switch( pMesh->GetMeshType()) { case BOX: collision = NewtonCreateBox( nWorld, vSize.x, vSize.y, vSize.z, NULL ); body = CreateRigidBody( pMesh, collision ); break; case SPHERE: collision = NewtonCreateSphere( nWorld, vSize.x, vSize.x, vSize.x, NULL ); body = CreateRigidBody( pMesh, collision); break; default: break; }; NewtonReleaseCollision( nWorld, collision ); return S_OK; }
After successfully creating a mesh and applying the physics properties we call this method so Newton Game Dynamics is able to do something useful with the data provided. Watch the lines 9-29. They are nearly identical with our DirectX function above for creating the graphical object. You see how easy it is? NewtonCreateSphere and NewtonCreateBox are methods of the Newton Game Dynamics library which create the collision shape of the desired body. Of course same sizes should be used like the graphical object so that it looks realistic.
The method CreateRigidBody is the important call in this code. Let’s take a look what it does:
NewtonBody* CreateRigidBody( CD3DXMesh* pObject, NewtonCollision* collision ) { D3DXVECTOR3 minBox; D3DXVECTOR3 maxBox; D3DXVECTOR3 origin; D3DXVECTOR3 inertia; NewtonBody* body; float mass; mass = pObject->GetMass(); body = NewtonCreateBody (nWorld, collision); NewtonBodySetDestructorCallback (body, PhysicsBodyDestructor); NewtonBodySetUserData (body, pObject); D3DXMATRIX matrix = pObject->GetMatrix(); NewtonBodySetMatrix (body, (float*)&matrix); NewtonConvexCollisionCalculateInertialMatrix (collision, (float*)&inertia, (float*)&origin); NewtonBodySetMassMatrix (body, mass, mass * inertia.x, mass * inertia.y, mass * inertia.z); NewtonBodySetCentreOfMass (body, (float*)&origin); NewtonBodySetForceAndTorqueCallback (body, PhysicsApplyForceAndTorque); NewtonBodySetTransformCallback (body, PhysicsSetTransform); return body; }
Very simple. It creates the rigid body in physics world and sets the various parameters like mass, matrices and callbacks. As you see there are three callbacks set. These callbacks control the behavior of the physic bodies. Let’s take a closer look.
PhysicsBodyDestructor:
void PhysicsBodyDestructor ( const NewtonBody* body ) { CD3DXMesh* primitive; primitive = (CD3DXMesh*) NewtonBodyGetUserData (body); SAFE_DELETE( primitive ); }
This method is called to destroy our object.
PhysicsSetTransform:
void PhysicsSetTransform( const NewtonBody* body, const float* matrix ) { CD3DXMesh* primitive; D3DXMATRIX mat; memcpy(mat.m, matrix, sizeof(float)*16); // get the graphic object form the rigid body primitive = (CD3DXMesh*) NewtonBodyGetUserData (body); // set the transformation matrix for this rigid body primitive->SetMatrix ( mat ); }
This method is called every time to set the new matrix to our models. Every time the matrix of the body changes (transformation, translation etc.) this function is called to update the matrix so that the graphical part knows what happened and is able to render the transformed graphical object.
PhysicsApplyForceAndTorque
void PhysicsApplyForceAndTorque (const NewtonBody* body) { float mass; float Ixx; float Iyy; float Izz; NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz); D3DXVECTOR3 force (0.0f, mass * NEWTON_GRAVITY, 0.0f); NewtonBodySetForce (body, (float*)&force); }
This method simply applies gravity force to the rigid body.
Note: All the methods of the Newton Game Dynamics library accept float pointers for accessing data. If you use your own vector or matrix class make sure you include a float* casting to your vector/matrix class. If you store your members in an array of floats for example float m[3] you could simply pass &vec.m[0] to Newton. If you use the DirectX D3DXVECTOR3 and/or D3DXMATRIX classes make sure you cast the parameter with a float pointer like
D3DXVECTOR3 vecForce; NewtonBodySetForce( body, (float*)&vecForce);
For detailed reference refer to the DirectX SDK documentation.
That’s all. We simply have to do a call to update the physics world with the current passed time and voila we have some action. What did we do here? We just created with DirectX internal functions some basic meshes to render and create rigid bodies out of them to simulate physics. The result should look like this:
3. Using DirectX mesh for level geometry
What did we learn so far? We learned how easily it is to integrate Newton to any type of DirectX based game engine and we learned how easy it is to create rigid bodies with simple primitives using the DirectX D3DX library. Now we want to go a step further. The DirectX mesh file (x mesh) is maybe not the preferred mesh format a developer would choose but it’s easy to handle since D3DX ships with nearly any helper method you could imagine of, what makes work easier. For this example we will choose the x mesh as level geometry and add some more complex meshes to the scene to see if Newton Game Dynamics can handle this.
For this tutorial a new mesh class is used to load meshes from files. For now we will take a look what happens while initializing the mesh object:
m_iNumTriangles = m_pMesh->GetNumFaces(); m_iNumVertices = m_pMesh->GetNumVertices(); m_pVerts = new D3DXVECTOR3[m_iNumVertices * sizeof(D3DXVECTOR3)]; m_pIndices = new WORD[m_iNumTriangles * sizeof(WORD) * 3]; MeshVertex2* pVertexBuffer = NULL; hr = m_pMesh->LockVertexBuffer( 0, (void**) &pVertexBuffer ); if( FAILED(hr) ) return E_FAIL; for( int iCol = 0; iCol < m_iNumVertices; iCol+=4) { m_pVerts[iCol] = pVertexBuffer->vPos; pVertexBuffer++; m_pVerts[iCol+1] = pVertexBuffer->vPos; pVertexBuffer++; m_pVerts[iCol+2] = pVertexBuffer->vPos; pVertexBuffer++; m_pVerts[iCol+3] = pVertexBuffer->vPos; pVertexBuffer++; } hr = m_pMesh->UnlockVertexBuffer(); if( FAILED(hr) ) return E_FAIL; WORD* pIndexBuffer=NULL; hr = m_pMesh->LockIndexBuffer( D3DLOCK_READONLY , (void**)&pIndexBuffer ); if( FAILED( hr )) return E_FAIL; for( int i = 0; i < m_iNumTriangles*3; i++) { m_pIndices[i] = pIndexBuffer[i]; } hr = m_pMesh->UnlockIndexBuffer(); if( FAILED( hr )) return E_FAIL;
This should be nothing new for you. After loading your mesh and doing things with it you want to do like optimization and stuff simply load the vertices and indices separate into buffers. We are doing this only once in our example after loading the mesh from file and preparing it for the application. Therefore it is no problem to lock the vertex- and index buffer of the mesh since it’s only done once. Why did we do the things above? you should ask now. Well simply because we will pass this data to Newton Game Dynamics. You will see that this work will pay off later.
Now we are loading a big mesh file (the castle model of the example was taken from the samples of DelEd editor) and want it to behave as our static geometry. Why this? First of all it’s good to go this way since we can now simulate exact collisions with all other objects of the game. Second is we can write a player controller and control it via physics (an example of a character controller ships with Newton Game Dynamics) what means that we don’t have to calculate collisions between player and level geometry separately but let Newton Game Dynamics do this for us. And the third reason is simply because we want to be cool and implement it that way to point out how important the two reasons above are 😉
Now that we loaded the our big mesh we have to tell Newton Game Dynamics to use our vertices and indices to build our world. This is done in the method CreateLevelCollision
HRESULT CreateLevelCollision( D3DXVECTOR3* vVertexArray, int vertcount, WORD* vIndexArray, int indexcount, D3DXMATRIX matLevel ) { HRESULT hr=S_OK; NewtonCollision* collision; D3DXVECTOR3 vArray[3]; NewtonBody* m_levelBody; int m_nLevelID; collision = NewtonCreateTreeCollision( nWorld, 0); NewtonTreeCollisionBeginBuild( collision ); for( int i = 0; i < indexcount; i+=3) { WORD d1 = vIndexArray[i]; WORD d2 = vIndexArray[i+1]; WORD d3 = vIndexArray[i+2]; vArray[0] = vVertexArray[d1]; vArray[1] = vVertexArray[d2]; vArray[2] = vVertexArray[d3]; D3DXVECTOR3 e0 = vArray[1] - vArray[0]; D3DXVECTOR3 e1 = vArray[2] - vArray[0]; NewtonTreeCollisionAddFace( collision, 3, (float*)vArray[0], sizeof(D3DXVECTOR3), 0); } NewtonTreeCollisionEndBuild( collision, 1); m_levelBody = NewtonCreateBody( nWorld, collision); NewtonReleaseCollision ( nWorld, collision); NewtonBodySetMatrix( m_levelBody, matLevel); D3DXVECTOR3 boxP0; D3DXVECTOR3 boxP1; NewtonCollisionCalculateAABB (collision, matLevel, &boxP0.x, &boxP1.x); boxP0.x -= 10.0f; boxP0.y -= 10.0f; boxP0.z -= 10.0f; boxP1.x += 10.0f; boxP1.y += 100.0f; boxP1.z += 10.0f; // if this mesh is used for level geometry we could increase the // NewtonWorld size by the bounding box of the level geometry. Above some // padding was added. I think a good idea is to add more padding to y since // we might be "outdoor" and might want to let some boxes fall down ;) NewtonSetWorldSize ( nWorld, (float*)&boxP0, (float*)&boxP1); return hr; }
Wow damn nice function. This is the bread and butter of our game. In line 10 you see that we build an empty collision object. After that we tell Newton that we want to add the polygons to the collision tree. So now we loop through our vertices and the the faces via NewtonTreeCollisionAddFace. On finish we call NewtonTreeCollisionEndBuild, note the second parameter. We passed 1 here telling Newton to optimize our collision tree. After passing our complete mesh geometry to Newton we create the body set the matrix and calculate the bounding box. We did that in order to re-set the world size. Note that we added some padding to the world to make sure even objects at borders behave as they should. That’s all, no callbacks are needed this time since this is our (static) world and we don’t want it to move around 😉
We should test this stuff we did until now but let’s go a step further. Do you have only boxes, spheres and cylinders in your game? No you don’t. I bet 80% of the meshes are of complex geometry. What if you want to have collisions with the real shape they are rendered? Newton Game Dynamics helps us out. Take a look here:
HRESULT CreateComplexPhysicsBody( CMesh *pMesh ) { HRESULT hr = S_OK; NewtonCollision* collision; NewtonBody* body; float Ixx, Iyy, Izz; D3DXMATRIX mat; mat = pMesh->GetMatrix(); collision = NewtonCreateConvexHull (nWorld, pMesh->GetNumVertices(), (float*)pMesh->GetVerts(), pMesh->GetVertexSize(), NULL); body = CreateRigidBody( pMesh, collision ); NewtonReleaseCollision( nWorld, collision ); return hr; }
Sick. Just pass your mesh object to this method. What happens then? Remember the vertex and index buffers which we calculated when initializing the mesh and which we used after that to build level geometry? Just use them here once again to pass the detailed geometry of your graphical object so Newton can build the collision geometry out of it. The method NewtonCreateConvexHull does all the work for us. After having build the collision geometry we continue to create the body like in the examples above where all the callbacks and properties are set. Nothing new here.
So what will the result be? Let’s watch the video:
As you can see it’s quite easy to implement Newton Game Dynamics into your game engine project. The good thing is that Newton accepts the matrix and vertex parameters in major row order what makes it possible for OpenGL and DirectX game engine to use Newton Game Dynamics. There is also a documentation available which ships with the download and there are a couple of great samples and tutorials which are included with the SDK. The forums at www.newtondynamics.com is visited very frequently and should be the place to start. The website has also a new wiki which makes the package complete. I can recommend Newton Game Dynamics. The integration of Newton in any engine is more than easy and developers reach fast and very good results and most important of all: you don’t loose too much time. We could start a discussion whether to use Newton methods for computing a bounding box or use the DirectX integrated functions but that’s more than philosophic since the result (in my tests) was the same.
But that’s not all. The Newton Game Dynamics SDK ships with some great methods for ragdoll and more. Check out there website for a full feature list. Thanks for reading this.
Please note: As stated above the source on how to use Newton was taken mainly from the samples which ship with the NewtonSDK. Also the mesh classes contain portions of the DirectX SDK. I just put these together to work. The code is of course not best practice but good enough for the examples above.
Downloads: