Here's what I use. These are modified versions of functions I found on the internet. You will need to include <vector.h>
Classes:
class MemoryWriteBuffer : public NxStream
{
public:
MemoryWriteBuffer();
virtual ~MemoryWriteBuffer();
void clear();
virtual NxU8 readByte() const { NX_ASSERT(0); return 0; }
virtual NxU16 readWord() const { NX_ASSERT(0); return 0; }
virtual NxU32 readDword() const { NX_ASSERT(0); return 0; }
virtual float readFloat() const { NX_ASSERT(0); return 0.0f;}
virtual double readDouble() const { NX_ASSERT(0); return 0.0; }
virtual void readBuffer(void* buffer, NxU32 size) const { NX_ASSERT(0); }
virtual NxStream& storeByte(NxU8 b);
virtual NxStream& storeWord(NxU16 w);
virtual NxStream& storeDword(NxU32 d);
virtual NxStream& storeFloat(NxReal f);
virtual NxStream& storeDouble(NxF64 f);
virtual NxStream& storeBuffer(const void* buffer, NxU32 size);
NxU32 currentSize;
NxU32 maxSize;
NxU8* data;
};
class MemoryReadBuffer : public NxStream
{
public:
MemoryReadBuffer(const NxU8* data);
virtual ~MemoryReadBuffer();
virtual NxU8 readByte() const;
virtual NxU16 readWord() const;
virtual NxU32 readDword() const;
virtual float readFloat() const;
virtual double readDouble() const;
virtual void readBuffer(void* buffer, NxU32 size) const;
virtual NxStream& storeByte(NxU8 b) { NX_ASSERT(0); return *this; }
virtual NxStream& storeWord(NxU16 w) { NX_ASSERT(0); return *this; }
virtual NxStream& storeDword(NxU32 d) { NX_ASSERT(0); return *this; }
virtual NxStream& storeFloat(NxReal f) { NX_ASSERT(0); return *this; }
virtual NxStream& storeDouble(NxF64 f) { NX_ASSERT(0); return *this; }
virtual NxStream& storeBuffer(const void* buffer, NxU32 size) { NX_ASSERT(0); return *this; }
mutable const NxU8* buffer;
};
Functions for those classes:
/*********************************
READ/WRITE BUFFER CLASS FUNCTIONS
These Read and write certain numbers
of bytes. Needed by physX
**********************************/
MemoryWriteBuffer::MemoryWriteBuffer() : currentSize(0), maxSize(0), data(NULL)
{
}
MemoryWriteBuffer::~MemoryWriteBuffer()
{
NX_DELETE_ARRAY(data);
}
void MemoryWriteBuffer::clear()
{
currentSize = 0;
}
NxStream& MemoryWriteBuffer::storeByte(NxU8 b)
{
storeBuffer(&b, sizeof(NxU8));
return *this;
}
NxStream& MemoryWriteBuffer::storeWord(NxU16 w)
{
storeBuffer(&w, sizeof(NxU16));
return *this;
}
NxStream& MemoryWriteBuffer::storeDword(NxU32 d)
{
storeBuffer(&d, sizeof(NxU32));
return *this;
}
NxStream& MemoryWriteBuffer::storeFloat(NxReal f)
{
storeBuffer(&f, sizeof(NxReal));
return *this;
}
NxStream& MemoryWriteBuffer::storeDouble(NxF64 f)
{
storeBuffer(&f, sizeof(NxF64));
return *this;
}
NxStream& MemoryWriteBuffer::storeBuffer(const void* buffer, NxU32 size)
{
NxU32 expectedSize = currentSize + size;
if(expectedSize > maxSize)
{
maxSize = expectedSize + 4096;
NxU8* newData = new NxU8[maxSize];
NX_ASSERT(newData!=NULL);
if(data)
{
memcpy(newData, data, currentSize);
delete[] data;
}
data = newData;
}
memcpy(data+currentSize, buffer, size);
currentSize += size;
return *this;
}
MemoryReadBuffer::MemoryReadBuffer(const NxU8* data) : buffer(data)
{
}
MemoryReadBuffer::~MemoryReadBuffer()
{
}
NxU8 MemoryReadBuffer::readByte() const
{
NxU8 b;
memcpy(&b, buffer, sizeof(NxU8));
buffer += sizeof(NxU8);
return b;
}
NxU16 MemoryReadBuffer::readWord() const
{
NxU16 w;
memcpy(&w, buffer, sizeof(NxU16));
buffer += sizeof(NxU16);
return w;
}
NxU32 MemoryReadBuffer::readDword() const
{
NxU32 d;
memcpy(&d, buffer, sizeof(NxU32));
buffer += sizeof(NxU32);
return d;
}
float MemoryReadBuffer::readFloat() const
{
float f;
memcpy(&f, buffer, sizeof(float));
buffer += sizeof(float);
return f;
}
double MemoryReadBuffer::readDouble() const
{
double f;
memcpy(&f, buffer, sizeof(double));
buffer += sizeof(double);
return f;
}
void MemoryReadBuffer::readBuffer(void* dest, NxU32 size) const
{
memcpy(dest, buffer, size);
buffer += size;
}
Helper functions:
/*********************************
-- pdGetIndices --
Returns a vector containing the
indices from a D3D mesh.
**********************************/
std::vector<short> pdGetIndices(LPD3DXMESH model)
{
DWORD stride = sizeof(short);
BYTE* ibptr = NULL;
short* indices = new short[model->GetNumFaces() * 3];
std::vector<short> copy;
model->LockIndexBuffer(0, (LPVOID*)&indices);
for(int i = 0; (unsigned int)i < model->GetNumFaces() * 3; i++)
{
copy.push_back(indices[i]);
}
model->UnlockIndexBuffer();
//delete indices;
return copy;
}
/*********************************
-- pdGetVertices --
Returns a vector containing the
vertices from a D3D mesh.
**********************************/
std::vector<float> pdGetVertices(LPD3DXMESH model)
{
std::vector<float> vertices;
DWORD stride = D3DXGetFVFVertexSize(model->GetFVF());
BYTE* vbptr = NULL;
model->LockVertexBuffer(0, (LPVOID*)&vbptr);
int ii = -1;
for(int i = 0; (unsigned int)i < model->GetNumVertices(); i++)
{
ii++;
D3DXVECTOR3* pos = (D3DXVECTOR3*)vbptr;
vertices.push_back(pos->x);
vertices.push_back(pos->y);
vertices.push_back(pos->z);
vbptr += stride;
}
model->UnlockVertexBuffer();
return vertices;
}
Actual Function:
/*********************************
-- pdMakeMeshFromX --
Returns a physX actor cooked from
a D3D mesh. This is slow to use.
**********************************/
NxActor *pdMakeMeshFromX(PD_SYSTEM *sys, ID3DXMesh* Mesh, float friction, float bounce, bool dynamic)
{
std::vector<short> indices = pdGetIndices(Mesh);
std::vector<float> vertices = pdGetVertices(Mesh);
int NumVerticies = Mesh->GetNumVertices();
int NumTriangles = Mesh->GetNumFaces();
DWORD FVFSize = D3DXGetFVFVertexSize(Mesh->GetFVF());
//Create pointer for vertices
NxVec3* verts = new NxVec3[Mesh->GetNumVertices()];
int ii = -1;
for(int i = 0; (unsigned int)i < Mesh->GetNumVertices(); i++)
{
++ii;
verts[i].x = vertices[ii]/2;
verts[i].y = vertices[++ii]/2;
verts[i].z = vertices[++ii]/2;
}
//Create pointer for indices
NxU16 *tris = new NxU16[NumTriangles * 3];
ii = 0;
for(int NumInd = 0; NumInd < NumTriangles * 3; NumInd++)
{
tris[NumInd] = indices[ii];
NumInd++;
tris[NumInd] = indices[++ii];
NumInd++;
tris[NumInd] = indices[++ii];
++ii;
}
// Build physical model
NxTriangleMeshDesc TriMeshDesc;
TriMeshDesc.numVertices = NumVerticies;
TriMeshDesc.numTriangles = NumTriangles;
TriMeshDesc.pointStrideBytes = sizeof(NxVec3);
TriMeshDesc.triangleStrideBytes = 3*sizeof(NxU16);
TriMeshDesc.points = verts;
TriMeshDesc.triangles = tris;
TriMeshDesc.flags = NX_MF_16_BIT_INDICES;
NxTriangleMeshShapeDesc ShapeDesc;
NxInitCooking();
// Cooking from memory
MemoryWriteBuffer buf;
bool status = NxCookTriangleMesh(TriMeshDesc, buf);
ShapeDesc.meshData = sys->PhysSDK->createTriangleMesh(MemoryReadBuffer(buf.data));
NxMaterialDesc materialDesc;
materialDesc.staticFriction = friction;
materialDesc.dynamicFriction = friction;
materialDesc.restitution = bounce;
NxMaterial *newMaterial=sys->PhysScene->createMaterial(materialDesc);
ShapeDesc.materialIndex= newMaterial->getMaterialIndex();
NxActorDesc actorDesc;
actorDesc.shapes.pushBack(&ShapeDesc);
NxBodyDesc bodyDesc;
bodyDesc.angularDamping = 0.5f;
if(dynamic)
actorDesc.body=&bodyDesc;
actorDesc.density = 10;
actorDesc.globalPose.t = NxVec3(0.0f,10.0f,-20.0f);
actorDesc.globalPose.M.rotX(-D3DX_PI/2);
if(sys->PhysScene == NULL) MessageBox(NULL, "no scene", "error", NULL);
NxActor* act = sys->PhysScene->createActor(actorDesc);
delete[] verts;
delete[] tris;
return act;
}
My class PD_SYSTEM contains these relevant things:
NxPhysicsSDK *PhysSDK;
NxScene *PhysScene;
NxCookingInterface *CookingInterface;
LPDIRECT3DDEVICE9 Device;
LPDIRECT3D9 d3d;
There is some undocumented funciton I cannot remember in DarkGDK to get the Device. To use this function you first need the actual mesh, you can load it from a .x file using D3DXLoadMeshFromX