Wednesday 25 September 2013

Getting Started : Newton


Newton Game Dynamics. An open source engine, claiming to be easy to use, but perhaps due to my inexperience this game me much more trouble than anticipated. Nevertheless, after manipulating and removing unnecessary elements from some of the simpler demos I was able to produce a working example.

0) Setting up the Environment

If you're using Premake then this is a relatively simple swap from an earlier posting. Otherwise you will need to be sure to include the following.

--Include Directories
   newtonSDK .. 'source/newton'
   newtonSDK .. 'source/core'
   newtonSDK .. 'source/physics'
   newtonSDK .. 'source/cuda'
--Libraries to Link
   newtonSDK .. 'windows/project_vs2008/Win32/newton/debug/newton_d'
   newtonSDK .. 'windows/project_vs2008/Win32/physics/debug/physics'
   newtonSDK .. 'windows/project_vs2008/Win32/core/debug/core'

This assumes that newtonSDK points to the appropriate ./newton-dynamics-2.33/coreLibrary_200/ folder.

1) Including the Headers

Even if you are using some of the "dg" prefixed classes like dgMatrix or dgVector, we can still get away with this one include.

   #include "NewtonClass.h"

2) Initialization

There is not much needed here but to set up the memory system

   NewtonSetMemorySystem (AllocMemory, FreeMemory);

However, these two functions will need to be defined by the user and can be as simple as this.

   void* AllocMemory (int size)
   {
      return malloc (size);
   }

   void FreeMemory (void *ptr, int size)
   {
      free (ptr);
   }


3) Creating the World

   static NewtonWorld* sgpWorld = NewtonCreate();
   NewtonSetPlatformArchitecture (sgpWorld, 0);


   float pfMinSize[3] = {-50.0f,-50.0f,-50.0f};
   float pfMaxSize[3] = {50.0f, 50.0f, 50.0f};

   NewtonSetWorldSize (sgpWorld, &pfMinSize[0], &pfMaxSize[0]); 
   NewtonSetSolverModel (sgpWorld, 1);

4) Creating Newton Bodies and Collision Shapes

   NewtonBody* pCubeBody;
   NewtonCollision* pCubeShape;
   dgMatrix offset (dgQuaternion(),dgVector(0.0f, 0.0f, 5.0f, 1.0f));

The size of the box is given in its full dimensions, not the half height, or half extents like in other engines.

   pCubeShape = NewtonCreateBox (sgpWorld, 1.0,1.0,1.0, 0, NULL);

The shape offset matrix parameter may be left as Null for the NewtonCollision, defaulting to the local origin of the body, but the NewtonBody will result in an error without it.


   dgMatrix offset (dgQuaternion(),dgVector(0.0f, 5.0f ,0.0f, 1.0f));
   pCubeBody = NewtonCreateBody (sgpWorldpCubeShape, &offset[0][0]);

If we stop now, this NewtonBody will be a static member of the world. If we provide it with a mass then it will begin at rest, and respond only to collision from other bodies. This is not the same as sleeping, since it will become stationary again once a contact force is removed.

   dFloat fMass = 1.0f;
   dFloat fInertia = 1.0/6/0;
   NewtonBodySetMassMatrix(pCubeBody, fMass, fInertia, fInertia, fInertia);

The diagonal elements of the inertia matrix for a solid cube happen to be 1/6. Having this mass matrix is essential, but it is not sufficient even if we use NewtonBodySetForce. We will also need a callback for any forces applied. This is used mostly for applying gravity, but we must associate each NewtonBody with the desired callback.

    NewtonBodySetForceAndTorqueCallback(pCubeBody, ForceCallback);

Implementing this callback is not difficult, but the user must provide one.

   void  ForceCallback(const NewtonBody* pBody, dFloat fTimestep, int iThreadIndex)
   {
      dFloat Ixx;
      dFloat Iyy;
      dFloat Izz;
      dFloat fMass;

      NewtonBodyGetMassMatrix (pBody, &fMass, &Ixx, &Iyy, &Izz);
      dgVector force (0.0f, 0.0f, fMass* -9.8, 0.0f);
      NewtonBodySetForce (pBody, &force.m_x);
   }


Since NewtonBodySetForce is applied within the force callback there is no need to try setting the force again. This implementation of gravity will activate at the start of the simulation.

5) Simulation

   NewtonUpdate (sgpWorld, fTimestep); //fTimestep = 1/60

6) Shutdown

Once we are done applying a collision shape to any bodies we can release it without the body losing it's shape.

   NewtonReleaseCollision(sgpWorld, pCubeShape);

At the end of our simulation we can remove everything else we've created.

   NewtonDestroyAllBodies (sgpWorld);
   NewtonDestroy (sgpWorld);

In the end I don't despise Newton Dynamics. It makes sense once its working, but leaves much to be desired in terms of documentation, and co-operation with Visual Studio Intellisense (If you happen to use an Integrated Development Environment like me). This is partly because, like ODE, objects are manipulated through calling C-style functions instead of through member functions. Furthermore, the wiki system is mysteriously uninformative at some points, and unreadable inline code. In future evaluations, perhaps Newton will redeem itself with exceptional performance, or portability.

Happy Coding!

No comments:

Post a Comment