I have fully intergrated newton with darkgdk. the problem is a complete newtonian engine can be a) big and b) game specific. My newtonian class is 1,400+ lines and probably not much use to anyone else because its specific for my game - i've kinda tweaked values like gravity etc because i have an arcade style game that doesnt want COMPLETELY releastic phsyics.
However, what the hell, you can have the source code. Its more of my engine than I would ever like to give away, but just this once, on the off chance it helps someone or at least prooves im not talking BS, you can have it.
This code is dodgey though because back when i wrote it a few years ago (yeah, that long) i couldnt decide wether to use MAP containers or VECTORS so.. i used them both and used variable to switch hahaha xD So im rewriting this whole thing over time now so, no harm to share.
header file:
#ifndef _CNEWTON_H_
#define _CNEWTON_H_
#include "Newton.h"
#include "NewtonToolbox/dVector.h"
#include <vector>
#include <map>
#include "NewtonToolbox/dMatrix.h"
enum COLLISION_TYPE {
COL_BOX = 1,
COL_SPHERE,
COL_CONVEX,
COL_CONE,
COL_TREE
};
enum RETURN_VALUES {
R_OKAY = 0,
R_OBJ_EXISTS = -1,
R_FILE_NOT_FOUND = -2,
R_NOT_READY = -3,
R_INVALID_OPTION = -4,
R_ID_INVALID = -5
};
enum OBJECT_STORAGE_TYPE {
OST_VECTOR = 1,
OST_MAP
};
enum PRIMITIVE_TYPE {
P_CONE = 1,
P_BOX,
P_SPHERE
};
class CNewtonObject {
public:
CNewtonObject() {
nObjectID = -1;
nCollisionType = -1;
bUseGravity = true;
newtonObjectBody = NULL;
fUserForceX = 0.0f;
fUserForceY = 0.0f;
fUserForceZ = 0.0f;
fUserTorque = 0.0f;
mat = GetIdentityMatrix();
};
int nObjectID;
int nCollisionType;
bool bUseGravity;
float fUserForceX;
float fUserForceY;
float fUserForceZ;
float fUserTorque;
NewtonBody *newtonObjectBody;
dMatrix mat;
};
class CNewton {
public:
CNewton();
~CNewton();
void UpdateWorld();
int LoadStaticWorld(int nObjectID, char *szObjectFile);
int LoadStaticWorld(int nObjectID, const char *szObjectFile);
int LoadDynamicObject(int nObjectID, char *szObjectFile, int nCollisionType);
int LoadDynamicObject(int nObjectID, char *szObjectFile, float fPosX, float fPosY, float fPosZ, int nCollisionType);
int CreateObject(int nObjectID, PRIMITIVE_TYPE nObjectType, float fSize);
int CreateObject(int nObjectID, PRIMITIVE_TYPE nObjectType, float fSizeX, float fSizeY, float fSizeZ);
int CloneDynamicObject(int nObjectID, int nObjectSource, int nCollisionType);
int CloneDynamicObject(int nObjectID, int nObjectSource, float fPosX, float fPosY, float fPosZ, int nCollisionType);
int ConstrainUpVector(int nObjectID);
int SetObjectGravity(int nObjectID, bool bEnable);
int SetObjectMass(int nObjectID, float fMass);
int ZeroAllForces(int nObjectID);
int ApplyForce(int nObjectID, float fForceX, float fForceY, float fForceZ);
int ApplyForceDirect(int nObjectID, float fForceX, float fForceY, float fForceZ);
int RotateObjectLeft(int nObjectID, float fTorque);
int RotateObjectRight(int nObjectID, float fTorque);
int SetYTorque(int nObjectID, float fTorque);
void RenderWireframe(DWORD nColour);
int PositionObject(int nObjectID, float fX, float fY, float fZ);
int RotateObject(int nObjectID, float fXA, float fYA, float fZA);
float GetObjectPositionX(int nObjectID);
float GetObjectPositionY(int nObjectID);
float GetObjectPositionZ(int nObjectID);
float GetObjectAngleX(int nObjectID);
float GetObjectAngleY(int nObjectID);
float GetObjectAngleZ(int nObjectID);
float GetYaw(int nObjectID);
float GetSpeed(int nObjectID);
dVector GetForces(int nObjectID);
float GetTimeStep();
dVector GetObjectPosition(int nObjectID);
dVector GetObjectAngles(int nObjectID);
dVector GetObjectVelocity(int nObjectID);
NewtonWorld* newtonWorld;
private:
std::map<int, CNewtonObject*> NewtonObjectsMap;
std::vector<CNewtonObject*> NewtonObjectsVector;
OBJECT_STORAGE_TYPE nObjectStorageType;
NewtonCollision* newtonTreeCol;
NewtonBody* newtonWorldBody;
dFloat nLastUpdate;
dFloat nTimeToUpdate;
bool bInitialised;
int nLastTime;
int nDefaultMaterialID;
int nStaticWorldID;
float fTimeStep;
dFloat HiResTimer();
static void DestroyUserData(const NewtonBody* body);
static void SetForceAndTorque(const NewtonBody* body);
static void SetGdkObjectMatrix(const NewtonBody* body, const dFloat* matrix);
#define TICKS2SEC 1.0e-3f;
};
DWORD nWireframeColour;
int nWireframeBodysDrawn;
int nWireframePolysDrawn;
void PolyWireframeCallback(const NewtonBody* body, int vertexCount, const dFloat* faceVertec, int id);
void BodyWireframeCallback(const NewtonBody* body);
#endif
and now the cpp:
#include "DarkGDK.h"
#include "Newton.h"
#include "CNewton.h"
#include "NewtonToolbox/dVector.h"
#include "NewtonToolbox/dMatrix.h"
#include "NewtonToolbox/dQuaternion.h"
#include "SdkExtras.h"
//#include "Vector3.h"
//using namespace std;
#ifndef M_PI
#define M_PI 3.14159265358979323846264338327950288
#endif
void *dbNewtMalloc(int n) { return malloc(n); }
void dbNewtFree(void *p, int s) { free(p); }
//####################//
//## Constructors ##//
//####################//
//=========================================================================//
//Constructor, might be wise to move newton initilisation else where though//
//=========================================================================//
CNewton::CNewton() {
newtonWorld = NULL;
newtonTreeCol = NULL;
nObjectStorageType = OST_MAP;
newtonWorld = NewtonCreate(dbNewtMalloc, dbNewtFree);
nDefaultMaterialID = NewtonMaterialGetDefaultGroupID(newtonWorld);
//NewtonMaterialSetDefaultFriction(newtonWorld, nDefaultMaterialID, nDefaultMaterialID, 1.0f, 0.9f);
NewtonMaterialSetDefaultFriction(newtonWorld, nDefaultMaterialID, nDefaultMaterialID, 0.0f, 0.9f);
// NewtonMaterialSetContinuousCollisionMode(newtonWorld, nDefaultMaterialID, nDefaultMaterialID, 1);
NewtonSetMinimumFrameRate(newtonWorld, 80);
bInitialised = true;
}
//==========================================//
//Destructor, make sure newton is cleaned up//
//==========================================//
CNewton::~CNewton() {
NewtonDestroy(newtonWorld);
}
//######################//
//## Timer Function ##//
//######################//
//==============================================//
//Timer to get time steps between newton updates//
//==============================================//
dFloat CNewton::HiResTimer() {
dFloat timeStep;
unsigned ms;
ms = dbTimer();
timeStep = dFloat (ms - nLastTime) * TICKS2SEC;
nLastTime = ms;
if (timeStep > 0.1f) {
timeStep = 0.1f;
}
if (timeStep < 0.005f) {
timeStep = 0.005f;
}
return timeStep;
}
//########################//
//## Static Callbacks ##//
//########################//
//==============================//
//Callback to clean up user data//
//==============================//
void CNewton::DestroyUserData(const NewtonBody* body) {
CNewtonObject* cUserData;
cUserData = (CNewtonObject*)NewtonBodyGetUserData(body);
delete cUserData;
}
//====================================================//
//Callback to apply forces to objectings being updated//
//====================================================//
void CNewton::SetForceAndTorque(const NewtonBody* body) {
dFloat Ixx;
dFloat Iyy;
dFloat Izz;
dFloat mass;
dVector force(0.0f, 0.0f, 0.0f);
dVector torque(0.0f, 0.0f, 0.0f);
CNewtonObject *cUserData = (CNewtonObject*) NewtonBodyGetUserData(body);
dVector userforce(cUserData->fUserForceX, cUserData->fUserForceY, cUserData->fUserForceZ);
dVector usertorque(0.0f, cUserData->fUserTorque, 0.0f);
NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz);
if (cUserData->bUseGravity) {
// force.m_y = -9.8f * mass;
force.m_y = -19.8f * mass;
}
NewtonBodyAddForce(body, &force.m_x);
NewtonBodyAddForce(body, &userforce.m_x);
NewtonBodySetTorque(body, &torque.m_x);
// NewtonBodyAddTorque(body, &usertorque.m_x);
//usertorque.Scale(3.14159f / 180.0f);
NewtonBodySetOmega(body, &usertorque.m_x);
}
//==========================================================//
//Callback to update a DarkGDK object to match newton's data//
//==========================================================//
void CNewton::SetGdkObjectMatrix(const NewtonBody* body, const dFloat* matrix) {
CNewtonObject *cUserData = (CNewtonObject*) NewtonBodyGetUserData(body);
dVector vEAngle;
dVector vPos(matrix[12], matrix[13], matrix[14]);
NewtonGetEulerAngle(matrix, &vEAngle.m_x);
vEAngle = vEAngle.Scale(180.0f / 3.14159f); //convert to degrees
dbPositionObject(cUserData->nObjectID, vPos.m_x, vPos.m_y, vPos.m_z);
dbRotateObject(cUserData->nObjectID, vEAngle.m_x, vEAngle.m_y, vEAngle.m_z);
}
//####################//
//## World Update ##//
//####################//
//Updates the newton world moving objects according to their forces etc
void CNewton::UpdateWorld() {
fTimeStep = HiResTimer();
NewtonUpdate(newtonWorld, fTimeStep);
//NewtonWorldForEachBodyDo(newtonWorld, UpdateGdkObjects);
}
float CNewton::GetTimeStep() {
return fTimeStep;
}
//######################//
//## Object Loading ##//
//######################//
//Loads an object into the DarkGDK and creates a static collision tree from the object data
//The collision meshes made in this way will be polygon PERFECT but static, you cannot move them
//or alter them once created!
int CNewton::LoadStaticWorld(int nObjectID, char *szObjectFile) {
return LoadStaticWorld(nObjectID, (const char *)szObjectFile);
}
int CNewton::LoadStaticWorld(int nObjectID, const char *szObjectFile) {
switch(nObjectStorageType) {
case OST_MAP:
if (NewtonObjectsMap.find(nObjectID) != NewtonObjectsMap.end()) {
return R_OBJ_EXISTS;
}
break;
case OST_VECTOR:
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
return R_OBJ_EXISTS;
}
}
break;
}
if (!bInitialised) {
return R_NOT_READY;
}
CNewtonObject* cUserData = new CNewtonObject();
char szFile[1024]; //bah
sprintf_s(szFile, "%s", szObjectFile); //these two lines are gay, dbLoadObject() should take const char!
dbLoadObject(szFile, nObjectID);
if (!dbObjectExist(nObjectID)) {
return -1;
}
dbMakeMeshFromObject(1, nObjectID);
newtonTreeCol = NewtonCreateTreeCollision(newtonWorld, NULL);
NewtonTreeCollisionBeginBuild(newtonTreeCol);
dbLockVertexDataForMesh(1);
int nIndices = dbGetVertexDataIndexCount();
dVector facePoints[3];
for (int i = 0; i < nIndices; i += 3) {
facePoints[0].m_x = dbGetVertexDataPositionX(dbGetIndexData(i));
facePoints[0].m_y = dbGetVertexDataPositionY(dbGetIndexData(i));
facePoints[0].m_z = dbGetVertexDataPositionZ(dbGetIndexData(i));
facePoints[1].m_x = dbGetVertexDataPositionX(dbGetIndexData(i + 1));
facePoints[1].m_y = dbGetVertexDataPositionY(dbGetIndexData(i + 1));
facePoints[1].m_z = dbGetVertexDataPositionZ(dbGetIndexData(i + 1));
facePoints[2].m_x = dbGetVertexDataPositionX(dbGetIndexData(i + 2));
facePoints[2].m_y = dbGetVertexDataPositionY(dbGetIndexData(i + 2));
facePoints[2].m_z = dbGetVertexDataPositionZ(dbGetIndexData(i + 2));
NewtonTreeCollisionAddFace(newtonTreeCol, 3, &facePoints[0].m_x, sizeof(dVector), 0);
}
dbUnlockVertexData();
dbDeleteMesh(1);
NewtonTreeCollisionEndBuild(newtonTreeCol, 0);
newtonWorldBody = NewtonCreateBody(newtonWorld, newtonTreeCol);
dMatrix m(GetIdentityMatrix());
NewtonBodySetMatrix(newtonWorldBody, &m[0][0]);
dVector boxP0;
dVector boxP1;
NewtonCollisionCalculateAABB(newtonTreeCol, &m[0][0], &boxP0.m_x, &boxP1.m_x);
// add some extra padding the world size
boxP0.m_x -= 400.0f;
boxP0.m_y -= 400.0f;
boxP0.m_z -= 400.0f;
boxP1.m_x += 400.0f;
boxP1.m_y += 400.0f;
boxP1.m_z += 400.0f;
// set the world size
NewtonSetWorldSize(newtonWorld, &boxP0.m_x, &boxP1.m_x);
NewtonReleaseCollision(newtonWorld, newtonTreeCol);
cUserData->bUseGravity = false;
cUserData->nCollisionType = COL_TREE;
cUserData->nObjectID = nObjectID;
switch(nObjectStorageType) {
case OST_MAP:
NewtonObjectsMap[nObjectID] = cUserData;
break;
case OST_VECTOR:
NewtonObjectsVector.push_back(cUserData);
break;
};
return R_OKAY;
}
int CNewton::CreateObject(int nObjectID, PRIMITIVE_TYPE nObjectType, float fSize) {
return CreateObject(nObjectID, nObjectType, fSize, fSize, fSize);
}
int CNewton::CreateObject(int nObjectID, PRIMITIVE_TYPE nObjectType, float fSizeX, float fSizeY, float fSizeZ) {
switch(nObjectStorageType) {
case OST_MAP:
if (NewtonObjectsMap.find(nObjectID) != NewtonObjectsMap.end()) {
return R_OBJ_EXISTS;
}
break;
case OST_VECTOR:
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
return R_OBJ_EXISTS;
}
}
break;
}
if (!bInitialised) {
return R_NOT_READY;
}
NewtonCollision* newtonObjectCollision;
CNewtonObject* cUserData = new CNewtonObject();
dVector vCollisionSize;
switch (nObjectType) {
case P_BOX:
dbMakeObjectBox(nObjectID, fSizeX, fSizeY, fSizeZ);
vCollisionSize.m_x = dbObjectSizeX(nObjectID);
vCollisionSize.m_y = dbObjectSizeY(nObjectID);
vCollisionSize.m_z = dbObjectSizeZ(nObjectID);
newtonObjectCollision = NewtonCreateBox(newtonWorld, vCollisionSize.m_x, vCollisionSize.m_y, vCollisionSize.m_z, NULL);
cUserData->nCollisionType = COL_BOX;
break;
case P_SPHERE:
dbMakeObjectSphere(nObjectID, 2.0f);
vCollisionSize.m_x = fSizeX;
vCollisionSize.m_y = fSizeY;
vCollisionSize.m_z = fSizeZ;
dbScaleObject(nObjectID, fSizeX * 100.0f, fSizeY * 100.0f, fSizeZ * 100.0f);
newtonObjectCollision = NewtonCreateSphere(newtonWorld, vCollisionSize.m_x, vCollisionSize.m_y, vCollisionSize.m_z, NULL);
cUserData->nCollisionType = COL_SPHERE;
break;
case P_CONE:
dbMakeObjectCone(nObjectID, fSizeX);
vCollisionSize.m_x = dbObjectSizeX(nObjectID);
vCollisionSize.m_y = dbObjectSizeY(nObjectID);
vCollisionSize.m_z = dbObjectSizeZ(nObjectID);
newtonObjectCollision = NewtonCreateCone(newtonWorld, vCollisionSize.m_x, vCollisionSize.m_y, NULL);
cUserData->nCollisionType = COL_CONE;
break;
}
dMatrix mLocation(GetIdentityMatrix());
mLocation.m_posit.m_x = 0.0f;
mLocation.m_posit.m_y = 0.0f;
mLocation.m_posit.m_z = 0.0f;
dbPositionObject(nObjectID, 0.0f, 0.0f, 0.0f);
cUserData->newtonObjectBody = NewtonCreateBody(newtonWorld, newtonObjectCollision);
cUserData->bUseGravity = true;
cUserData->nObjectID = nObjectID;
NewtonBodySetLinearDamping(cUserData->newtonObjectBody, 0.00001f);
NewtonBodySetUserData(cUserData->newtonObjectBody, cUserData);
NewtonBodySetMassMatrix(cUserData->newtonObjectBody, vCollisionSize.m_x * vCollisionSize.m_y * vCollisionSize.m_z, 1.0f, 1.0f, 1.0f);
NewtonBodySetMatrix(cUserData->newtonObjectBody, &mLocation[0][0]);
NewtonBodySetForceAndTorqueCallback(cUserData->newtonObjectBody, SetForceAndTorque);
NewtonBodySetTransformCallback(cUserData->newtonObjectBody, SetGdkObjectMatrix);
NewtonBodySetDestructorCallback(cUserData->newtonObjectBody, DestroyUserData);
//NewtonBodySetContinuousCollisionMode(cUserData->newtonObjectBody, 1);
NewtonReleaseCollision(newtonWorld, newtonObjectCollision);
switch(nObjectStorageType) {
case OST_MAP:
NewtonObjectsMap[nObjectID] = cUserData;
break;
case OST_VECTOR:
NewtonObjectsVector.push_back(cUserData);
break;
};
return R_OKAY;
}
int CNewton::LoadDynamicObject(int nObjectID, char *szObjectFile, int nCollisionType) {
return LoadDynamicObject(nObjectID, szObjectFile, 0.0f, 0.0f, 0.0f, nCollisionType);
}
int CNewton::LoadDynamicObject(int nObjectID, char *szObjectFile, float fPosX, float fPosY, float fPosZ, int nCollisionType) {
switch(nObjectStorageType) {
case OST_MAP:
if (NewtonObjectsMap.find(nObjectID) != NewtonObjectsMap.end()) {
return R_OBJ_EXISTS;
}
break;
case OST_VECTOR:
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
return R_OBJ_EXISTS;
}
}
break;
}
if (!bInitialised) {
return R_NOT_READY;
}
if (nCollisionType == COL_TREE) {
return R_INVALID_OPTION;
}
NewtonCollision* newtonObjectCollision;
CNewtonObject* cUserData = new CNewtonObject();
//dbMakeObjectCube(nObjectID, 10); //just make a test cube for now
dbLoadObject(szObjectFile, nObjectID);
dVector vCollisionSize(dbObjectSizeX(nObjectID), dbObjectSizeY(nObjectID), dbObjectSizeZ(nObjectID));
dMatrix mLocation(GetIdentityMatrix());
mLocation.m_posit.m_x = fPosX;
mLocation.m_posit.m_y = fPosY;
mLocation.m_posit.m_z = fPosZ;
dbPositionObject(nObjectID, fPosX, fPosY, fPosZ);
switch (nCollisionType) {
case COL_BOX:
newtonObjectCollision = NewtonCreateBox(newtonWorld, vCollisionSize.m_x, vCollisionSize.m_y, vCollisionSize.m_z, NULL);
break;
case COL_SPHERE:
newtonObjectCollision = NewtonCreateSphere(newtonWorld, vCollisionSize.m_x, vCollisionSize.m_y, vCollisionSize.m_z, NULL);
break;
}
cUserData->newtonObjectBody = NewtonCreateBody(newtonWorld, newtonObjectCollision);
cUserData->bUseGravity = true;
cUserData->nObjectID = nObjectID;
cUserData->nCollisionType = nCollisionType;
NewtonBodySetLinearDamping(cUserData->newtonObjectBody, 0.00001f);
NewtonBodySetUserData(cUserData->newtonObjectBody, cUserData);
NewtonBodySetMassMatrix(cUserData->newtonObjectBody, (vCollisionSize.m_x * vCollisionSize.m_y * vCollisionSize.m_z) * 5, 1.0f, 1.0f, 1.0f);
NewtonBodySetMatrix(cUserData->newtonObjectBody, &mLocation[0][0]);
NewtonBodySetForceAndTorqueCallback(cUserData->newtonObjectBody, SetForceAndTorque);
NewtonBodySetTransformCallback(cUserData->newtonObjectBody, SetGdkObjectMatrix);
NewtonBodySetDestructorCallback(cUserData->newtonObjectBody, DestroyUserData);
NewtonReleaseCollision(newtonWorld, newtonObjectCollision);
switch(nObjectStorageType) {
case OST_MAP:
NewtonObjectsMap[nObjectID] = cUserData;
break;
case OST_VECTOR:
NewtonObjectsVector.push_back(cUserData);
break;
};
return R_OKAY;
}
int CNewton::CloneDynamicObject(int nObjectID, int nObjectSource, int nCollisionType) {
return CloneDynamicObject(nObjectID, nObjectSource, 0.0f, 0.0f, 0.0f, nCollisionType);
}
int CNewton::CloneDynamicObject(int nObjectID, int nObjectSource, float fPosX, float fPosY, float fPosZ, int nCollisionType) {
switch(nObjectStorageType) {
case OST_MAP:
if (NewtonObjectsMap.find(nObjectID) != NewtonObjectsMap.end()) {
return R_OBJ_EXISTS;
}
break;
case OST_VECTOR:
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
return R_OBJ_EXISTS;
}
}
break;
}
if (!bInitialised) {
return R_NOT_READY;
}
if (nCollisionType == COL_TREE) {
return R_INVALID_OPTION;
}
NewtonCollision* newtonObjectCollision;
CNewtonObject* cUserData = new CNewtonObject();
dbCloneObject(nObjectID, nObjectSource);
//dbMakeObjectCube(nObjectID, 10); //just make a test cube for now
dVector vCollisionSize(dbObjectSizeX(nObjectID), dbObjectSizeY(nObjectID), dbObjectSizeZ(nObjectID));
dMatrix mLocation(GetIdentityMatrix());
mLocation.m_posit.m_x = fPosX;
mLocation.m_posit.m_y = fPosY;
mLocation.m_posit.m_z = fPosZ;
dbPositionObject(nObjectID, fPosX, fPosY, fPosZ);
switch (nCollisionType) {
case COL_BOX:
newtonObjectCollision = NewtonCreateBox(newtonWorld, vCollisionSize.m_x, vCollisionSize.m_y, vCollisionSize.m_z, NULL);
break;
case COL_SPHERE:
newtonObjectCollision = NewtonCreateSphere(newtonWorld, vCollisionSize.m_x / 2.0f, vCollisionSize.m_y / 2.0f, vCollisionSize.m_z / 2.0f, NULL);
break;
case COL_CONVEX:
dbMakeMeshFromObject(1, nObjectID);
dbLockVertexDataForMesh(1);
dbUnlockVertexData();
dbDeleteMesh(1);
break;
}
cUserData->newtonObjectBody = NewtonCreateBody(newtonWorld, newtonObjectCollision);
cUserData->bUseGravity = true;
cUserData->nObjectID = nObjectID;
cUserData->nCollisionType = nCollisionType;
NewtonBodySetLinearDamping(cUserData->newtonObjectBody, 0.00001f);
NewtonBodySetUserData(cUserData->newtonObjectBody, cUserData);
NewtonBodySetMassMatrix(cUserData->newtonObjectBody, vCollisionSize.m_x * vCollisionSize.m_y * vCollisionSize.m_z, 1.0f, 1.0f, 1.0f);
NewtonBodySetMatrix(cUserData->newtonObjectBody, &mLocation[0][0]);
NewtonBodySetForceAndTorqueCallback(cUserData->newtonObjectBody, SetForceAndTorque);
NewtonBodySetTransformCallback(cUserData->newtonObjectBody, SetGdkObjectMatrix);
NewtonBodySetDestructorCallback(cUserData->newtonObjectBody, DestroyUserData);
NewtonBodySetAutoFreeze(cUserData->newtonObjectBody, 0);
NewtonReleaseCollision(newtonWorld, newtonObjectCollision);
switch(nObjectStorageType) {
case OST_MAP:
NewtonObjectsMap[nObjectID] = cUserData;
break;
case OST_VECTOR:
NewtonObjectsVector.push_back(cUserData);
break;
};
return R_OKAY;
}
int CNewton::PositionObject(int nObjectID, float fX, float fY, float fZ) {
if (!bInitialised) {
return R_NOT_READY;
}
switch(nObjectStorageType) {
case OST_MAP:
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return R_ID_INVALID;
}
float mPosition[16];
NewtonBodyGetMatrix(NewtonObjectsMap[nObjectID]->newtonObjectBody, mPosition);
mPosition[12] = fX;
mPosition[13] = fY;
mPosition[14] = fZ;
NewtonBodySetMatrix(NewtonObjectsMap[nObjectID]->newtonObjectBody, mPosition);
dbPositionObject(nObjectID, fX, fY, fZ);
break;
case OST_VECTOR:
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
float mPosition[16];
NewtonBodyGetMatrix(NewtonObjectsVector[i]->newtonObjectBody, mPosition);
mPosition[12] = fX;
mPosition[13] = fY;
mPosition[14] = fZ;
NewtonBodySetMatrix(NewtonObjectsVector[i]->newtonObjectBody, mPosition);
dbPositionObject(nObjectID, fX, fY, fZ);
bSuccess = true;
}
}
if (!bSuccess) {
return R_ID_INVALID;
}
break;
}
return R_OKAY;
}
int CNewton::ConstrainUpVector(int nObjectID) {
if (!bInitialised) {
return R_NOT_READY;
}
switch(nObjectStorageType) {
case OST_MAP: {
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return R_ID_INVALID;
}
dVector UpVector(0.0f, 1.0f, 0.0f);
NewtonConstraintCreateUpVector(newtonWorld, &UpVector.m_x, NewtonObjectsMap[nObjectID]->newtonObjectBody);
break;
}
case OST_VECTOR: {
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
dVector UpVector(0.0f, 1.0f, 0.0f);
NewtonConstraintCreateUpVector(newtonWorld, &UpVector.m_x, NewtonObjectsVector[i]->newtonObjectBody);
bSuccess = true;
break;
}
}
if (!bSuccess) {
return R_ID_INVALID;
}
break;
}
}
return R_OKAY;
}
int CNewton::ApplyForceDirect(int nObjectID, float fForceX, float fForceY, float fForceZ) {
if (!bInitialised) {
return R_NOT_READY;
}
switch(nObjectStorageType) {
case OST_MAP: {
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return R_ID_INVALID;
}
dVector bodyForce(fForceX, fForceY, fForceZ);
NewtonBodyAddForce(NewtonObjectsMap[nObjectID]->newtonObjectBody, &bodyForce.m_x);
break;
}
case OST_VECTOR: {
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
//dVector bodyForce(fForceX, fForceY, fForceZ);
//NewtonBodySetForce(NewtonObjectsVector[i]->newtonObjectBody, &bodyForce.m_x);
NewtonObjectsVector[i]->fUserForceX = fForceX;
NewtonObjectsVector[i]->fUserForceY = fForceY;
NewtonObjectsVector[i]->fUserForceZ = fForceZ;
bSuccess = true;
break;
}
}
if (!bSuccess) {
return R_ID_INVALID;
}
break;
}
}
return R_OKAY;
}
int CNewton::ApplyForce(int nObjectID, float fForceX, float fForceY, float fForceZ) {
if (!bInitialised) {
return R_NOT_READY;
}
switch(nObjectStorageType) {
case OST_MAP: {
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return R_ID_INVALID;
}
//dVector bodyForce(fForceX, fForceY, fForceZ);
//NewtonBodySetForce(NewtonObjectsMap[nObjectID]->newtonObjectBody, &bodyForce.m_x);
NewtonObjectsMap[nObjectID]->fUserForceX = fForceX;
NewtonObjectsMap[nObjectID]->fUserForceY = fForceY;
NewtonObjectsMap[nObjectID]->fUserForceZ = fForceZ;
break;
}
case OST_VECTOR: {
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
//dVector bodyForce(fForceX, fForceY, fForceZ);
//NewtonBodySetForce(NewtonObjectsVector[i]->newtonObjectBody, &bodyForce.m_x);
NewtonObjectsVector[i]->fUserForceX = fForceX;
NewtonObjectsVector[i]->fUserForceY = fForceY;
NewtonObjectsVector[i]->fUserForceZ = fForceZ;
bSuccess = true;
break;
}
}
if (!bSuccess) {
return R_ID_INVALID;
}
break;
}
}
return R_OKAY;
}
dVector CNewton::GetObjectPosition(int nObjectID) {
dVector vResult;
vResult.m_x = -1;
vResult.m_y = -1;
vResult.m_z = -1;
vResult.m_w = -1;
if (!bInitialised) {
return vResult;
}
switch(nObjectStorageType) {
case OST_MAP:
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return vResult;
}
float mPosition[16];
NewtonBodyGetMatrix(NewtonObjectsMap[nObjectID]->newtonObjectBody, mPosition);
vResult.m_x = mPosition[12];
vResult.m_y = mPosition[13];
vResult.m_z = mPosition[14];
break;
case OST_VECTOR:
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
float mPosition[16];
NewtonBodyGetMatrix(NewtonObjectsVector[i]->newtonObjectBody, mPosition);
vResult.m_x = mPosition[12];
vResult.m_y = mPosition[13];
vResult.m_z = mPosition[14];
return vResult;
}
}
if (!bSuccess) {
return vResult;
}
break;
}
return vResult;
}
dVector CNewton::GetForces(int nObjectID) {
dVector vResult;
vResult.m_x = -1;
vResult.m_y = -1;
vResult.m_z = -1;
vResult.m_w = -1;
if (!bInitialised) {
return vResult;
}
switch(nObjectStorageType) {
case OST_MAP:
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return vResult;
}
float mPosition[16];
NewtonBodyGetMatrix(NewtonObjectsMap[nObjectID]->newtonObjectBody, mPosition);
vResult.m_x = NewtonObjectsMap[nObjectID]->fUserForceX;
vResult.m_y = NewtonObjectsMap[nObjectID]->fUserForceY;
vResult.m_z = NewtonObjectsMap[nObjectID]->fUserForceZ;
break;
case OST_VECTOR:
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
float mPosition[16];
NewtonBodyGetMatrix(NewtonObjectsVector[i]->newtonObjectBody, mPosition);
vResult.m_x = NewtonObjectsVector[i]->fUserForceX;
vResult.m_y = NewtonObjectsVector[i]->fUserForceY;
vResult.m_z = NewtonObjectsVector[i]->fUserForceZ;
return vResult;
}
}
if (!bSuccess) {
return vResult;
}
break;
}
return vResult;
}
dVector CNewton::GetObjectVelocity(int nObjectID) {
dVector vResult;
vResult.m_x = -1;
vResult.m_y = -1;
vResult.m_z = -1;
vResult.m_w = -1;
if (!bInitialised) {
return vResult;
}
switch(nObjectStorageType) {
case OST_MAP:
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return vResult;
}
NewtonBodyGetVelocity(NewtonObjectsMap[nObjectID]->newtonObjectBody, &vResult.m_x);
break;
case OST_VECTOR:
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
NewtonBodyGetVelocity(NewtonObjectsVector[i]->newtonObjectBody, &vResult.m_x);
return vResult;
}
}
if (!bSuccess) {
return vResult;
}
break;
}
return vResult;
}
float CNewton::GetObjectPositionX(int nObjectID) {
dVector mPos = GetObjectPosition(nObjectID);
return mPos.m_x;
}
float CNewton::GetObjectPositionY(int nObjectID) {
dVector mPos = GetObjectPosition(nObjectID);
return mPos.m_y;
}
float CNewton::GetObjectPositionZ(int nObjectID) {
dVector mPos = GetObjectPosition(nObjectID);
return mPos.m_z;
}
float CNewton::GetObjectAngleX(int nObjectID) {
if (!bInitialised) {
return -1.0;
}
dVector vAngles = GetObjectAngles(nObjectID);
return vAngles.m_x;
}
float CNewton::GetObjectAngleY(int nObjectID) {
if (!bInitialised) {
return -1.0;
}
dVector vAngles = GetObjectAngles(nObjectID);
dFloat matrix[16];
NewtonBodyGetMatrix(NewtonObjectsMap[nObjectID]->newtonObjectBody, matrix);
return atan2f(matrix[0], matrix[2]);
//return vAngles.m_y;
}
float CNewton::GetObjectAngleZ(int nObjectID) {
if (!bInitialised) {
return -1.0;
}
dVector vAngles = GetObjectAngles(nObjectID);
return vAngles.m_z;
}
dVector CNewton::GetObjectAngles(int nObjectID) {
dVector vAngles(-1.0f, -1.0f, -1.0f);
switch(nObjectStorageType) {
case OST_MAP: {
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return vAngles;
}
dFloat mat[16];
NewtonBodyGetMatrix(NewtonObjectsMap[nObjectID]->newtonObjectBody, mat);
NewtonGetEulerAngle(mat, &vAngles.m_x);
// vAngles = vAngles.Scale(180.0f / 3.14159f); //convert to degrees
return vAngles;
break;
}
case OST_VECTOR: {
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
dFloat mat[16];
NewtonBodyGetMatrix(NewtonObjectsVector[i]->newtonObjectBody, mat);
NewtonGetEulerAngle(mat, &vAngles.m_x);
vAngles = vAngles.Scale(180.0f / 3.14159f); //convert to degrees
return vAngles;
}
}
break;
}
}
return vAngles;
}
int CNewton::RotateObjectLeft(int nObjectID, float fTorque) {
if (!bInitialised) {
return R_NOT_READY;
}
switch(nObjectStorageType) {
case OST_MAP:
{
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return R_ID_INVALID;
}
NewtonObjectsMap[nObjectID]->fUserTorque = -fTorque;
break;
}
case OST_VECTOR:
{
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
NewtonObjectsVector[i]->fUserTorque = -fTorque;
bSuccess = true;
break;
}
}
if (!bSuccess) {
return R_ID_INVALID;
}
break;
}
}
return R_OKAY;
}
int CNewton::RotateObjectRight(int nObjectID, float fTorque) {
if (!bInitialised) {
return R_NOT_READY;
}
switch(nObjectStorageType) {
case OST_MAP:
{
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return R_ID_INVALID;
}
NewtonObjectsMap[nObjectID]->fUserTorque = fTorque;
break;
}
case OST_VECTOR:
{
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
NewtonObjectsVector[i]->fUserTorque = -fTorque;
bSuccess = true;
break;
}
}
if (!bSuccess) {
return R_ID_INVALID;
}
break;
}
}
return R_OKAY;
}
float CNewton::GetYaw(int nObjectID) {
if (!bInitialised) {
return 0.0f;
}
switch(nObjectStorageType) {
case OST_MAP: {
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return 0.0f;
}
dFloat mat[16];
NewtonBodyGetMatrix(NewtonObjectsMap[nObjectID]->newtonObjectBody, mat);
float yaw = atan2f(mat[0], mat[2]) * (180.0f / M_PI);
yaw -= 90.0f;
if (yaw < 0.0f) {
yaw += 360.0f;
}
return yaw;
}
case OST_VECTOR:
{
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
dFloat mat[16];
NewtonBodyGetMatrix(NewtonObjectsVector[i]->newtonObjectBody, mat);
float yaw = atan2f(mat[0], mat[2]) * (180.0f / M_PI);
yaw -= 90.0f;
if (yaw < 0.0f) {
yaw += 360.0f;
}
return yaw;
}
}
if (!bSuccess) {
return 0.0f;
}
break;
}
}
return 0.0f;
}
float CNewton::GetSpeed(int nObjectID) {
if (!bInitialised) {
return 0.0f;
}
switch(nObjectStorageType) {
case OST_MAP: {
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return 0.0f;
}
dVector Velocity;
dVector CarDirectionNormal;
float SpeedKMH;
dMatrix mat;
NewtonBodyGetMatrix(NewtonObjectsMap[nObjectID]->newtonObjectBody, &mat[0].m_x);
NewtonBodyGetVelocity(NewtonObjectsMap[nObjectID]->newtonObjectBody, &Velocity.m_x);
//CarDirectionNormal = mat * dVector(1.0f, 0.0f, 0.0f);
CarDirectionNormal = dVector(1.0f, 0.0f, 1.0f);
mat.RotateVector(CarDirectionNormal);
Velocity = Velocity * CarDirectionNormal;
float length = FastSqrt((Velocity.m_x * Velocity.m_x) + (Velocity.m_y * Velocity.m_y) + (Velocity.m_z * Velocity.m_z));
SpeedKMH = length * 3.6f;
return SpeedKMH;
}
case OST_VECTOR:
{
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
dMatrix mat(GetIdentityMatrix());
dVector vVel;
NewtonBodyGetVelocity(NewtonObjectsVector[i]->newtonObjectBody, &vVel[0]);
return mat.m_front % vVel;
}
}
if (!bSuccess) {
return 0.0f;
}
break;
}
}
return 0.0f;
}
int CNewton::SetObjectMass(int nObjectID, float fMass) {
if (!bInitialised) {
return R_NOT_READY;
}
switch(nObjectStorageType) {
case OST_MAP:
{
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return R_ID_INVALID;
}
NewtonBodySetMassMatrix(NewtonObjectsMap[nObjectID]->newtonObjectBody, fMass, 1.0f, 1.0f, 1.0f);
break;
}
case OST_VECTOR:
{
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
NewtonBodySetMassMatrix(NewtonObjectsVector[i]->newtonObjectBody, fMass, 1.0f, 1.0f, 1.0f);
return R_OKAY;
}
}
if (!bSuccess) {
return R_ID_INVALID;
}
break;
}
}
return R_OKAY;
}
int CNewton::ZeroAllForces(int nObjectID) {
if (!bInitialised) {
return R_NOT_READY;
}
switch(nObjectStorageType) {
case OST_MAP:
{
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return R_ID_INVALID;
}
dVector vVelocity(0.0f, 0.0f, 0.0f);
NewtonBodySetVelocity(NewtonObjectsMap[nObjectID]->newtonObjectBody, &vVelocity.m_x);
NewtonBodySetOmega(NewtonObjectsMap[nObjectID]->newtonObjectBody, &vVelocity.m_x);
NewtonBodySetForce(NewtonObjectsMap[nObjectID]->newtonObjectBody, &vVelocity.m_x);
NewtonBodySetTorque(NewtonObjectsMap[nObjectID]->newtonObjectBody, &vVelocity.m_x);
//NewtonObjectsMap[nObjectID]->bUseGravity = bEnable;
NewtonObjectsMap[nObjectID]->fUserForceX = 0.0f;
NewtonObjectsMap[nObjectID]->fUserForceY = 0.0f;
NewtonObjectsMap[nObjectID]->fUserForceZ = 0.0f;
break;
}
case OST_VECTOR:
{
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
//NewtonObjectsVector[i]->bUseGravity = bEnable;
return R_OKAY;
}
}
if (!bSuccess) {
return R_ID_INVALID;
}
break;
}
}
return R_OKAY;
}
int CNewton::SetObjectGravity(int nObjectID, bool bEnable) {
if (!bInitialised) {
return R_NOT_READY;
}
switch(nObjectStorageType) {
case OST_MAP:
{
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return R_ID_INVALID;
}
NewtonObjectsMap[nObjectID]->bUseGravity = bEnable;
break;
}
case OST_VECTOR:
{
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
NewtonObjectsVector[i]->bUseGravity = bEnable;
return R_OKAY;
}
}
if (!bSuccess) {
return R_ID_INVALID;
}
break;
}
}
return R_OKAY;
}
int CNewton::SetYTorque(int nObjectID, float fTorque) {
if (!bInitialised) {
return R_NOT_READY;
}
switch(nObjectStorageType) {
case OST_MAP:
{
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return R_ID_INVALID;
}
NewtonObjectsMap[nObjectID]->fUserTorque = fTorque;
break;
}
case OST_VECTOR:
{
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
NewtonObjectsVector[i]->fUserTorque = -fTorque;
bSuccess = true;
break;
}
}
if (!bSuccess) {
return R_ID_INVALID;
}
break;
}
}
return R_OKAY;
}
int CNewton::RotateObject(int nObjectID, float fXA, float fYA, float fZA) {
if (!bInitialised) {
return R_NOT_READY;
}
switch(nObjectStorageType) {
case OST_MAP:
{
if (NewtonObjectsMap.find(nObjectID) == NewtonObjectsMap.end()) {
return R_ID_INVALID;
}
dQuaternion qRotation;
dVector UpVector, LookVector, RightVector, PositionVector;
// fYA = 90.0f;
float xRad, yRad, zRad;
xRad = fXA * (M_PI / 180.0);
yRad = fYA * (M_PI / 180.0);
zRad = fZA * (M_PI / 180.0);
UpVector.m_x = 0.0f;
UpVector.m_y = 1.0f;
UpVector.m_z = 0.0f;
UpVector.m_w = 1.0f;
RightVector.m_x = 1.0f;
RightVector.m_y = 0.0f;
RightVector.m_z = 0.0f;
RightVector.m_w = 1.0f;
LookVector.m_x = 0.0f;
LookVector.m_y = 0.0f;
LookVector.m_z = 1.0f;
LookVector.m_w = 1.0f;
dQuaternion qRotX(RightVector, xRad);
dQuaternion qRotY(UpVector, yRad);
dQuaternion qRotZ(LookVector, zRad);
bool bStep = false;
if (fXA != 0.0) {
qRotation = qRotX;
bStep = true;
}
if (fYA != 0.0) {
if (bStep) {
qRotation = qRotation * qRotY;
} else {
qRotation = qRotY;
bStep = true;
}
}
if (fZA != 0.0) {
if (bStep) {
qRotation = qRotation * qRotZ;
} else {
qRotation = qRotZ;
}
}
float mPosition[16];
NewtonBodyGetMatrix(NewtonObjectsMap[nObjectID]->newtonObjectBody, mPosition);
PositionVector.m_x = mPosition[12];
PositionVector.m_y = mPosition[13];
PositionVector.m_z = mPosition[14];
dMatrix newMat(qRotation, PositionVector);
NewtonBodySetMatrix(NewtonObjectsMap[nObjectID]->newtonObjectBody, &newMat[0][0]);
break;
}
case OST_VECTOR:
{
bool bSuccess = false;
for (unsigned int i = 0; i < NewtonObjectsVector.size(); i++) {
if (NewtonObjectsVector[i]->nObjectID == nObjectID) {
dVector vAngles;
vAngles.m_x = fXA;
vAngles.m_y = fYA;
vAngles.m_z = fZA;
vAngles.Scale(M_PI / 180.0f); //radiens to degrees
float mPosition[16];
dVector vPos = GetObjectPosition(nObjectID);
mPosition[12] = vPos.m_x;
mPosition[13] = vPos.m_y;
mPosition[14] = vPos.m_z;
NewtonBodySetMatrix(NewtonObjectsMap[nObjectID]->newtonObjectBody, mPosition);
dbPositionObject(nObjectID, mPosition[12], mPosition[13], mPosition[14]);
bSuccess = true;
break;
}
}
if (!bSuccess) {
return R_ID_INVALID;
}
break;
}
}
return R_OKAY;
}
//###########################//
//## Wireframe Rendering ##//
//###########################//
//Set of three functions to perform a wireframe render of the entire world as NEWTON sees it.
//If things arnt acting how you expect, compare this render of what newton sees to the world as
//DarkGDK sees it
void CNewton::RenderWireframe(DWORD nColour) {
nWireframeColour = nColour;
nWireframeBodysDrawn = 0;
nWireframePolysDrawn = 0;
StartNewLineBatch();
NewtonWorldForEachBodyDo(newtonWorld, BodyWireframeCallback);
RenderBatchLineList(0, 1);
}
void BodyWireframeCallback(const NewtonBody *body) {
nWireframeBodysDrawn++;
NewtonBodyForEachPolygonDo(body, PolyWireframeCallback);
// NewtonCollisionForEachPolygonDo();
}
void PolyWireframeCallback(const NewtonBody *body, int vertexCount, const dFloat *faceVertec, int id) {
int i;
// CNewtonObject *cUserData = (CNewtonObject*) NewtonBodyGetUserData(body);
// if (!dbObjectInScreen(cUserData->nObjectID)) {
// return;
// }
i = vertexCount - 1;
dVector p0 (faceVertec[i * 3 + 0], faceVertec[i * 3 + 1], faceVertec[i * 3 + 2]);
for (i = 0; i < vertexCount; i ++) {
dVector p1 (faceVertec[i * 3 + 0], faceVertec[i * 3 + 1], faceVertec[i * 3 + 2]);
//Line3DCamera(0, p0.m_x, p0.m_y, p0.m_z, p1.m_x, p1.m_y, p1.m_z, nWireframeColour, 1);
AddLineToBatch(p0.m_x, p0.m_y, p0.m_z, p1.m_x, p1.m_y, p1.m_z, nWireframeColour);
p0 = p1;
}
}
yeah... gl with that its a mess xD