Tutorial - Newton Callbacks tutorial with Irrlicht
An adaptation of Newton 1.5.3 Tutorial 2 - Using Callbacks. It uses Irrlicht 1.3.1 for the graphics engine.
#include <stdafx.h> #include "newton.h" #include "tutorial.h" #include "HiResTimer.h" #include "RenderPrimitive.h" #include "Irrlicht.h" #pragma comment(lib,"Irrlicht.lib") #pragma comment(lib, "Newton.lib") using namespace irr; CHiResTimer timer; //not actually used in the tutorial #define GRAVITY -9.8f #define NEWTONTOIRR 32.0f; //conversion factor between the two #define IRRTONEWTON 1.0f/NEWTONTOIRR; core::vector3df cameraDir (320.0, -160.0, -160.0); core::vector3df cameraEyepoint (-640.0f, 160.0, 160.0); static NewtonWorld* nWorld; irr::IrrlichtDevice* device; static void CleanUp (); static void* PhysicsAlloc (int sizeInBytes); static void PhysicsFree (void *ptr, int sizeInBytes); static void PhysicsBodyDestructor (const NewtonBody* body); static void PhysicsApplyForceAndTorque (const NewtonBody* body); static void PhysicsSetTransform (const NewtonBody* body, const dFloat* matrix); //******************************************************************** // // Newton Tutorial 2 Using Callbacks // //******************************************************************** int main(int argc, char **argv) { // initialize irrLicht //This, of course, is set up for Directx 9, substitute //EDT_SOFTWARE for the software renderer. However, I don't recommend it as it will be deadly slow device = irr::createDevice(video::EDT_DIRECT3D9, core::dimension2d<s32>(800,600), 16, false, false, false, 0); //Set the working directory for the location of the graphics files. device->getFileSystem()->changeWorkingDirectoryTo("c:/sdk/irrlicht-1.3.1/media"); scene::ISceneManager* smgr = device->getSceneManager(); video::IVideoDriver* driver = device->getVideoDriver(); // create the physics scene InitScene(); // Execute irrLicht main loop for ever int lastFPS = -1; while (device->run()) { //Simple default to make the physics update 60 times a second. //Seems to work pretty well NewtonUpdate (nWorld,1.0f/60.0f); driver->beginScene(true, true, video::SColor(255,255,255,255)); smgr->drawAll(); driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Irrlicht Engine - Newton tutorial 2. FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } return 0; } // memory allocation for Newton void* PhysicsAlloc (int sizeInBytes) { return malloc (sizeInBytes); } // memory de-allocation for Newton void PhysicsFree (void *ptr, int sizeInBytes) { free (ptr); } // add force and torque to rigid body void PhysicsApplyForceAndTorque (const NewtonBody* body) { dFloat Ixx; dFloat Iyy; dFloat Izz; dFloat mass; NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz); dVector force (0.0f, mass * GRAVITY, 0.0f); NewtonBodySetForce (body, &force.m_x); } // set the transformation of a rigid body //You have to do this so that the Newton body and irrLicht scene node are in sync, //and you actually see the changes created by the physics simulation void PhysicsSetTransform (const NewtonBody* body, const dFloat* matrix) { scene::ISceneNode* primitive; // get the graphic object form the rigid body //Newton can store a pointer to the scene node in the body object. primitive = (scene::ISceneNode*) NewtonBodyGetUserData (body); // set the transformation matrix for this rigid body dMatrix& mat = *((dMatrix*)matrix); //Create a matrix to store the irrLicht transformation that will correspond //to the Newton transformation core::matrix4 irrMatrix; //There's no easy way to get the information from one to the other, so a memory copy is required. //The matrix is a 4x4 float memcpy (irrMatrix.pointer(), &mat, 16*sizeof(float)); //In order to get the transform right, you have to apply the translation and the rotation //from the Newton body to the irrLicht scene node. core::vector3df position (irrMatrix.getTranslation()); position *=NEWTONTOIRR; core::vector3df rotation; NewtonGetEulerAngle(irrMatrix.pointer(), &rotation.X); rotation = rotation * (180.0/3.1416); primitive->setPosition (position); primitive->setRotation(rotation); } // rigid body destructor void PhysicsBodyDestructor (const NewtonBody* body) { scene::ISceneNode* primitive; // get the graphic object form the rigid body primitive = (scene::ISceneNode*) NewtonBodyGetUserData (body); // destroy the graphic object primitive->drop(); } // destroy the world and every thing in it void CleanUp () { // destroy the Newton world NewtonDestroy (nWorld); } // create physics scene void InitScene() { scene::ISceneManager* smgr = device->getSceneManager(); video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneNode* sphere; scene::ISceneNode* floor; NewtonBody* sphereBody; NewtonBody* floorBody; NewtonCollision* collision; // create the newton world nWorld = NewtonCreate (PhysicsAlloc, PhysicsFree); // set the linear solver model for faster speed // NewtonSetSolverModel (nWorld, 10); // set the adaptive friction model for faster speed // NewtonSetFrictionModel (nWorld, 1); // Set the termination function atexit(CleanUp); // create the sky box smgr->addSkyBoxSceneNode( driver->getTexture("irrlicht2_up.jpg"), driver->getTexture("irrlicht2_dn.jpg"), driver->getTexture("irrlicht2_lf.jpg"), driver->getTexture("irrlicht2_rt.jpg"), driver->getTexture("irrlicht2_ft.jpg"), driver->getTexture("irrlicht2_bk.jpg")); // create the the floor graphic objects dVector size (100.0f, 2.0f, 100.0f); dMatrix location (GetIdentityMatrix()); location.m_posit.m_y = -5.0f; // create a box for floor //Uses the addCubeSceneNode function, but since it only takes one size parameter, //you have to squish it using the scale vector core::vector3df position (location.m_posit.m_x, location.m_posit.m_y, location.m_posit.m_z); position *= NEWTONTOIRR; float irrSize = size.m_x*NEWTONTOIRR; floor = smgr->addCubeSceneNode(irrSize, 0,-1, position, core::vector3df(0.0,0.0,0.0), core::vector3df(1.0,2.0/100.0,1.0)); if (floor) { floor->setMaterialFlag(video::EMF_LIGHTING, false); floor->setMaterialTexture(0, driver->getTexture("terrain-texture.jpg")); } // create the the floor collision, and body with default values collision = NewtonCreateBox (nWorld, size.m_x, size.m_y, size.m_z, NULL); floorBody = NewtonCreateBody (nWorld, collision); NewtonReleaseCollision (nWorld, collision); // set the transformation for this rigid body NewtonBodySetMatrix (floorBody, &location[0][0]); // save the pointer to the graphic object with the body. NewtonBodySetUserData (floorBody, floor); // set a destructor for this rigid body NewtonBodySetDestructorCallback (floorBody, PhysicsBodyDestructor); // set the initial size for the spheres size = dVector(0.5f, 0.5f, 0.5f); irrSize = size.m_x*NEWTONTOIRR; // create the collision collision = NewtonCreateSphere (nWorld, size.m_x, size.m_y, size.m_z, NULL); // create 100 stacks of 10 spheres each location.m_posit.m_x = -16.0f; for (int k = 0; k < 8; k ++) { location.m_posit.m_z = 0.0f; for (int j = 0; j < 4; j ++) { location.m_posit.m_y = -3.75f - 0.01f; for (int i = 0; i < 8; i ++) { // create a graphic sphere. // Boxes are fun, but spheres scatter so much better. sphere = smgr->addSphereSceneNode(irrSize); if (sphere) { sphere->setMaterialFlag(video::EMF_LIGHTING, false); sphere->setMaterialTexture(0, driver->getTexture("earth.bmp")); } //create the rigid body sphereBody = NewtonCreateBody (nWorld, collision); // save the pointer to the graphic object with the body. NewtonBodySetUserData (sphereBody, sphere); // set a destructor for this rigid body NewtonBodySetDestructorCallback (sphereBody, PhysicsBodyDestructor); // set the transform call back function NewtonBodySetTransformCallback (sphereBody, PhysicsSetTransform); // set the force and torque call back function NewtonBodySetForceAndTorqueCallback (sphereBody, PhysicsApplyForceAndTorque); // set the mass matrix NewtonBodySetMassMatrix (sphereBody, 1.0f, 1.0f, 1.0f, 1.0f); // set the matrix for both the rigid body and the graphic body NewtonBodySetMatrix (sphereBody, &location[0][0]); PhysicsSetTransform (sphereBody, &location[0][0]); location.m_posit.m_y += size.m_y * 2.0f; } //Randomize the locations a little bit, or else the spheres //will stack perfectly on top of one another and won't fall down! location.m_posit.m_z -= size.m_z * 4.0f*rand()/32767; } location.m_posit.m_x += size.m_x * 4.0f*rand()/32767; } // release the collision geometry when not needed NewtonReleaseCollision (nWorld, collision); //Add an irrLicht FPS camera, and turn off the cursor visibility float cameraRotateSpeed = 100.0; float cameraMoveSpeed = 500.0; scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0, cameraRotateSpeed, cameraMoveSpeed, -1, 0, 0, false, 0.0); if (camera) { camera->setPosition(cameraEyepoint); camera->setTarget(cameraEyepoint+cameraDir); } device->getCursorControl()->setVisible(false); }