Thanks in advance.
Code: Select all
#include <Irrlicht.h>
#include "newton.h"
#include <memory.h>
static NewtonWorld* nWorld;
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(lib, "Newton.lib")
IrrlichtDevice *device = NULL;
IVideoDriver* driver = NULL;
ISceneManager* smgr = NULL;
float NewtonToIrr = 32.0f;
float IrrToNewton = 1/NewtonToIrr;
IGUIStaticText* pText = NULL;
bool debugOn = true;
class MyEventReceiver : public IEventReceiver
{
public:
///////////////////////////
virtual bool OnEvent(SEvent event)
{
if (event.EventType == irr::EET_KEY_INPUT_EVENT&&
event.KeyInput.PressedDown)
{
switch(event.KeyInput.Key)
{
case KEY_ESCAPE:
device->closeDevice();
break;
case KEY_KEY_D:
debugOn = !debugOn;
break;
}
}// pressdown
return 0;
}
};
MyEventReceiver receiver;
// allocation of memory from Newton
void* _cdecl
NewtonAlloc (int sizeInBytes)
{
return new char[sizeInBytes];
}
// destruction of memory from Newton
void _cdecl
NewtonFree (void *ptr, int sizeInBytes)
{
char *tmp;
tmp = (char*) ptr;
delete[] tmp;
}
/*
Function: AddGlobalForce (vector3df Force, vector3df Point, matrix4 BodyMatrix,const NewtonBody* body)
Returns: Nothing
Parameters: vector3df Force -- the force you want to apply
vector3df Point -- global space location to apply the force
matrix4 BodyMatrix -- Newton Matrix describing object
NewtonBody* body -- the body in question
Purpose: Add a force to an object displaced from the center of mass
Note: Because of the displacement, you will get a spin or torque, and
you have to tell Newton what that spin is. Thats what this function
does.
*/
void AddGlobalForce (vector3df Force, vector3df Point, matrix4 BodyMatrix,const NewtonBody* body)
{
vector3df R = Point - BodyMatrix.getTranslation();
vector3df Torque = R.crossProduct(Force);
NewtonBodyAddForce (body,&Force.X);
NewtonBodyAddTorque (body,&Torque.X);
}
/*
Function: AddLocalForce (vector3df Force, vector3df LocalPoint, matrix4 BodyMatrix,const NewtonBody* body)
Returns: Nothing
Parameters: vector3df Force -- the force you want to apply, in local space
vector3df Point -- local space location to apply the force
matrix4 BodyMatrix -- Newton Matrix describing object
NewtonBody* body -- the body in question
Purpose: Takes a local force and displacement and translates it into a global
force request
Note: Because of the displacement, you will get a spin or torque, and
you have to tell Newton what that spin is. Thats what this function
does.Called only from within ApplyTorqueandForceHandler
*/
void AddLocalForce (vector3df LocalForce, vector3df LocalPoint, matrix4 BodyMatrix,const NewtonBody* body)
{
vector3df GlobalForce,GlobalPoint;
BodyMatrix.transformVect(LocalForce,GlobalForce);
BodyMatrix.transformVect(LocalPoint,GlobalPoint);
if (LocalForce.X == 0.0f && LocalForce.Y == 0.0f && LocalForce.Z == 0.0f)
{
}
else
{
AddGlobalForce (GlobalForce, GlobalPoint,BodyMatrix,body);
}
}
void _cdecl NewtonDebugCollision(const NewtonBody* body, int vertexCount, const float* FaceArray, int faceId)
{
core::vector3df p0 (FaceArray[0], FaceArray[1], FaceArray[2] );
const video::SColor c0(255,55,255,0);
for (int i = 2; i < vertexCount; i ++)
{
core::vector3df p1( FaceArray[(i-1) * 3 + 0], FaceArray[(i-1) * 3 + 1], FaceArray[(i-1) * 3 + 2] );
core::vector3df p2( FaceArray[i * 3 + 0], FaceArray[i * 3 + 1], FaceArray[i * 3 + 2] );
core::triangle3df t;
t.set(p1*NewtonToIrr,
p2*NewtonToIrr,
p0*NewtonToIrr);
driver->draw3DTriangle(t, c0);
}
}
void _cdecl NewtonDebugBody (const NewtonBody* body)
{
matrix4 mat;
SMaterial material;
material.Texture1 = 0;
material.Lighting = false;
driver->setTransform(video::ETS_WORLD, mat);
driver->setMaterial(material);
NewtonBodyForEachPolygonDo(body,NewtonDebugCollision);
}
static void setTransform(const NewtonBody* body, const float* matrix)
{
//get graphic object
ISceneNode* node = (ISceneNode*) NewtonBodyGetUserData(body);
//copy matrix to an irrlicht matrix
matrix4 mat;
memcpy(mat.M, matrix, sizeof(float)*16);
//set transformation
node->setPosition(mat.getTranslation() * NewtonToIrr);
node->setRotation(mat.getRotationDegrees());
}
static void setForceAndTorque(const NewtonBody* body)
{
float mass;
float Ixx;
float Iyy;
float Izz;
matrix4 mat;
mat.makeIdentity();
NewtonBodyGetMatrix(body,mat.M);
NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz);
vector3df force(0, -mass* 9.8f, 0.0);
vector3df torque(0, 00.0f, 0);
vector3df mforce(0,0,5);
vector3df displace(2,0,0);
NewtonBodyAddForce(body, &force.X);
AddLocalForce(mforce,displace,mat,body);
}
int main()
{
device = createDevice(EDT_DIRECT3D9,
dimension2d<s32>(640,480), 32,false,false,false,&receiver);
driver = device->getVideoDriver();
smgr = device->getSceneManager();
IGUIEnvironment* env = device->getGUIEnvironment();
pText = env->addStaticText(L"fred",core::rect<int>(20,20,440,200), false);
pText->setOverrideColor(video::SColor(255,240,240,235));
pText->setOverrideFont(
env->getFont("midfont.bmp"));
//1. Create Newtonworld
nWorld = NewtonCreate(NewtonAlloc, NewtonFree);
// Set up default material properties for newton
int i = NewtonMaterialGetDefaultGroupID(nWorld);
NewtonMaterialSetDefaultFriction (nWorld, i, i, 0.8f, 0.4f);
NewtonMaterialSetDefaultElasticity (nWorld, i, i, 0.3f);
NewtonMaterialSetDefaultSoftness (nWorld, i, i, 0.05f);
NewtonMaterialSetCollisionCallback (nWorld, i, i, NULL, NULL, NULL, NULL);
//MESH
//ISceneNode* node = smgr->addTestSceneNode();
core::aabbox3d<f32> sbox;
vector3df ssize;
float sss = 2.0f;
IAnimatedMesh* mesh = smgr->getMesh("sydney.md2");
IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh );
if (node)
{
node->setMaterialFlag(EMF_LIGHTING, false);
node->setFrameLoop(320, 368);
node->setScale(vector3df(sss,sss,sss));
node->setMaterialTexture( 0, driver->getTexture("sydney.bmp") );
node->setPosition(core::vector3df(0,530,30));
node->setAnimationSpeed(50);
//size the box in Newton units
sbox = mesh->getMesh(0)->getBoundingBox();
ssize = sbox.getExtent()*IrrToNewton*sss;
}
//2.a Define Newtoncollision
NewtonCollision* myShape = NewtonCreateSphere(nWorld, ssize.X/2, ssize.Y/2, ssize.Z/2, NULL);
//b. Create NewtonBody
NewtonBody* myBody = NewtonCreateBody(nWorld, myShape);
//c. Set Body Properties
NewtonBodySetMassMatrix(myBody, 1.0f, 1.0f, 1.0f, 1.0f);
NewtonBodySetForceAndTorqueCallback(myBody, setForceAndTorque);
NewtonBodySetUserData(myBody, (void*) node); //with this you are sending your graphic pointer to Newton.
NewtonBodySetTransformCallback(myBody, setTransform);
NewtonBodySetLinearDamping(myBody,1);
vector3df rd(1,1,1);
NewtonBodySetAngularDamping(myBody,&rd.X);
NewtonJoint* upVector;
vector3df upDirection (0.0f, 1.0f, 0.0f);
upVector = NewtonConstraintCreateUpVector (nWorld, &upDirection.X, myBody);
ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0, 200.0f, 250.0f);
camera->setPosition(vector3df(0,10,-120));
camera->setTarget(vector3df(0,0,0));
//Level
device->getFileSystem()->addZipFileArchive
("map-20kdm2.pk3");
scene::IAnimatedMesh* q3levelmesh = smgr->getMesh("20kdm2.bsp");
scene::ISceneNode* q3node = 0;
if (q3levelmesh)
q3node = smgr->addOctTreeSceneNode(q3levelmesh->getMesh(0));
q3node->setPosition(core::vector3df(-1370,-130,-1400));
//LevelNewtonCollision
NewtonCollision* nmapcollision = NewtonCreateTreeCollision(nWorld, NULL);
NewtonTreeCollisionBeginBuild(nmapcollision);
int cMeshBuffer, j;
int v1i, v2i, v3i;
IMeshBuffer *mb;
float vArray[9]; // vertex array (3*3 floats)
int tmpCount = 0;
core::aabbox3d<f32> box;
//size the box in Newton units
box = q3levelmesh->getMesh(0)->getBoundingBox();
vector3df size = box.getExtent()*IrrToNewton;
for (cMeshBuffer=0; cMeshBuffer<q3levelmesh->getMesh(0)->getMeshBufferCount(); cMeshBuffer++)
{
mb = q3levelmesh->getMesh(0)->getMeshBuffer(cMeshBuffer);
S3DVertex2TCoords* mb_vertices = (S3DVertex2TCoords*)mb->getVertices();
u16* mb_indices = mb->getIndices();
// add each triangle from the mesh
for (j=0; j<mb->getIndexCount(); j+=3)
{
// printf("buff %d count %d\n",cMeshBuffer,j);
v1i = mb_indices[j];
v2i = mb_indices[j+1];
v3i = mb_indices[j+2];
vArray[0] = mb_vertices[v1i].Pos.X* IrrToNewton;
vArray[1] = mb_vertices[v1i].Pos.Y* IrrToNewton;
vArray[2] = mb_vertices[v1i].Pos.Z* IrrToNewton;
vArray[3] = mb_vertices[v2i].Pos.X* IrrToNewton;
vArray[4] = mb_vertices[v2i].Pos.Y* IrrToNewton;
vArray[5] = mb_vertices[v2i].Pos.Z* IrrToNewton;
vArray[6] = mb_vertices[v3i].Pos.X* IrrToNewton;
vArray[7] = mb_vertices[v3i].Pos.Y* IrrToNewton;
vArray[8] = mb_vertices[v3i].Pos.Z* IrrToNewton;
NewtonTreeCollisionAddFace(nmapcollision, 3, &vArray[0], 12, 1);
}
}
NewtonTreeCollisionEndBuild(nmapcollision, 0);
NewtonBody* nmapbody = NewtonCreateBody(nWorld, nmapcollision);
// set the newton world size based on the bsp size
float boxP0[3];
float boxP1[3];
float matrix[4][4];
matrix4 mmm;
mmm.setTranslation(vector3df(-1370,-130,-1400)*IrrToNewton);
NewtonBodySetMatrix(nmapbody,&mmm.M[0]);
NewtonCollisionCalculateAABB (nmapcollision, &matrix[0][0], &boxP0[0], &boxP1[0]);
NewtonSetWorldSize (nWorld, (float*)boxP0, (float*)boxP1);
int rate;
wchar_t tmp[1024];
while(device->run())
{
NewtonUpdate(nWorld, 0.01f);
//camera->setTarget(node->getPosition());
driver->beginScene(true, true, video::SColor(0,0,0,0));
if (debugOn)
{
NewtonWorldForEachBodyDo (nWorld, NewtonDebugBody);
}
rate = driver->getFPS();
vector3df cPos = camera->getAbsolutePosition();
swprintf(tmp, 1024, L"camera[%2.1f,%2.1f,%2.1f] fps %d\nD toggle Debug",cPos.X,cPos.Y,cPos.Z,rate);
pText->setText(tmp);
smgr->drawAll();
env->drawAll();
driver->endScene();
}
device->drop();
// 4. Destroy World
NewtonDestroy(nWorld);
return 0;
}
Oh and its the latest version of Irrlicht and Newton that i'm using (1.0 and 1.53 respectively)