physx有很多用户类需要自己写,很麻烦,比如NxStream,NxUserAllocator,不过他带的例子中有现成了,拿来用好了 :)
physx的plane类型和character不能进行碰撞,这点非常奇怪,网上问了很多人,都不得要领,在他的官方论坛上问,也没有回应,好在他的NxtriangleMesh支持和character的碰撞。
physx除了对固定形状的碰撞判定外,还支持任意形状物体的判定,不过效率不知道如何,我也没有做过专门的测试,等以后有机会在做吧。
使用ogre的mesh的顶点数据导入physx,其实方法很简单,physx中有一个NxTriangleMeshDesc专门用于处理mesh数据。
physx感兴趣的数据只有2个,vertex和index,所以,mesh我们只需要得到这2种数据就可以了,没有什么难度,直接看代码吧
NxTriangleMesh *BuildNxTriangleMesh( MeshPtr mesh )
{
unsigned short submeshNum = mesh->getNumSubMeshes();
SubMesh *ghm_submesh = mesh->getSubMesh( 0 ); //还没想好sub mesh的问题,以后再说
//read vertex buffer
Ogre::VertexBufferBinding::VertexBufferBindingMap ghm_VBBM = ghm_submesh->vertexData->vertexBufferBinding->getBindings();
int iPositonIndex = -1;
//find position buffer
for ( int i = 0; i < ghm_submesh->vertexData->vertexDeclaration->getElementCount(); i++)
{
const VertexElement *ghm_VE = ghm_submesh->vertexData->vertexDeclaration->getElement( i );
if ( ghm_VE->getSemantic() == VES_POSITION ) //we are just interested in position
{
//bingo,get it
iPositonIndex = i;
break;
}
}
if ( iPositonIndex == -1 ) //can't find position buffer
return false;
Ogre::VertexBufferBinding::VertexBufferBindingMap::iterator vbbm_interator = ghm_VBBM.find( iPositonIndex );
size_t vertexbuffersize = vbbm_interator->second->getNumVertices() * vbbm_interator->second->getVertexSize(); //buffer size
BYTE *VertexBuffer = new BYTE[vertexbuffersize]; //build buffer
vbbm_interator->second->readData( 0, vertexbuffersize, VertexBuffer ); //read data
//read index buffer
size_t indexbuffersize = ghm_submesh->indexData->indexBuffer->getNumIndexes() * ghm_submesh->indexData->indexBuffer->getIndexSize(); //buffer size
BYTE *IndexBuffer = new BYTE[indexbuffersize]; //build buffer
ghm_submesh->indexData->indexBuffer->readData( 0, indexbuffersize, IndexBuffer ); //read data
// Build physical model
NxTriangleMeshDesc terrainDesc;
terrainDesc.numVertices = vbbm_interator->second->getNumVertices();
terrainDesc.numTriangles = ghm_submesh->indexData->indexBuffer->getNumIndexes() / 3;
terrainDesc.pointStrideBytes = sizeof(NxVec3);
if(ghm_submesh->indexData->indexBuffer->getType() == Ogre::HardwareIndexBuffer::IT_16BIT )
{
terrainDesc.triangleStrideBytes = 3*sizeof(NxU16);
}
else
{
terrainDesc.triangleStrideBytes = 3*sizeof(NxU32);
}
terrainDesc.points = VertexBuffer;
terrainDesc.triangles = IndexBuffer;
terrainDesc.flags = NX_MF_16_BIT_INDICES | NX_MF_HARDWARE_MESH ;
terrainDesc.heightFieldVerticalAxis = NX_Y;
terrainDesc.heightFieldVerticalExtent = -1000.0f;
NxTriangleMeshShapeDesc terrainShapeDesc;
MemoryWriteBuffer writeBuffer;
bool rt = m_CookingInterface->NxCookTriangleMesh( terrainDesc,writeBuffer );
return m_PhysicsSDK->createTriangleMesh(MemoryReadBuffer(writeBuffer.data));
}
一般来说用作碰撞的物体,不会含有多个sub mesh所以我直接读0,这个函数返回一个NxTriangleMesh的指针,通过赋给NxTriangleMeshShapeDesc的meshdata就可以了。
关于碰撞:一个character可以在一个mesh内部,或者上部,这个mesh可以是不缝合的mesh,另外注意skinwidth的设置,如果过小,碰撞会检测不到。