|
@@ -11,6 +11,7 @@
|
|
|
#undef new
|
|
#undef new
|
|
|
#endif
|
|
#endif
|
|
|
#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
|
|
#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
|
|
|
|
|
+#include "BulletCollision/CollisionShapes/btShapeHull.h"
|
|
|
#ifdef GAMEPLAY_MEM_LEAK_DETECTION
|
|
#ifdef GAMEPLAY_MEM_LEAK_DETECTION
|
|
|
#define new DEBUG_NEW
|
|
#define new DEBUG_NEW
|
|
|
#endif
|
|
#endif
|
|
@@ -762,7 +763,7 @@ static void computeCenterOfMass(const Vector3& center, const Vector3& scale, Vec
|
|
|
centerOfMassOffset->negate();
|
|
centerOfMassOffset->negate();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-PhysicsCollisionShape* PhysicsController::createShape(Node* node, const PhysicsCollisionShape::Definition& shape, Vector3* centerOfMassOffset)
|
|
|
|
|
|
|
+PhysicsCollisionShape* PhysicsController::createShape(Node* node, const PhysicsCollisionShape::Definition& shape, Vector3* centerOfMassOffset, bool dynamic)
|
|
|
{
|
|
{
|
|
|
GP_ASSERT(node);
|
|
GP_ASSERT(node);
|
|
|
|
|
|
|
@@ -887,7 +888,7 @@ PhysicsCollisionShape* PhysicsController::createShape(Node* node, const PhysicsC
|
|
|
case PhysicsCollisionShape::SHAPE_MESH:
|
|
case PhysicsCollisionShape::SHAPE_MESH:
|
|
|
{
|
|
{
|
|
|
// Build mesh from passed in shape.
|
|
// Build mesh from passed in shape.
|
|
|
- collisionShape = createMesh(shape.data.mesh, scale);
|
|
|
|
|
|
|
+ collisionShape = createMesh(shape.data.mesh, scale, dynamic);
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
@@ -1055,34 +1056,10 @@ PhysicsCollisionShape* PhysicsController::createHeightfield(Node* node, HeightFi
|
|
|
return shape;
|
|
return shape;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-PhysicsCollisionShape* PhysicsController::createMesh(Mesh* mesh, const Vector3& scale)
|
|
|
|
|
|
|
+PhysicsCollisionShape* PhysicsController::createMesh(Mesh* mesh, const Vector3& scale, bool dynamic)
|
|
|
{
|
|
{
|
|
|
GP_ASSERT(mesh);
|
|
GP_ASSERT(mesh);
|
|
|
|
|
|
|
|
- // Only support meshes with triangle list primitive types.
|
|
|
|
|
- bool triMesh = true;
|
|
|
|
|
- if (mesh->getPartCount() > 0)
|
|
|
|
|
- {
|
|
|
|
|
- for (unsigned int i = 0; i < mesh->getPartCount(); ++i)
|
|
|
|
|
- {
|
|
|
|
|
- if (mesh->getPart(i)->getPrimitiveType() != Mesh::TRIANGLES)
|
|
|
|
|
- {
|
|
|
|
|
- triMesh = false;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- triMesh = mesh->getPrimitiveType() == Mesh::TRIANGLES;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!triMesh)
|
|
|
|
|
- {
|
|
|
|
|
- GP_ERROR("Mesh rigid bodies are currently only supported on meshes with TRIANGLES primitive type.");
|
|
|
|
|
- return NULL;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
// The mesh must have a valid URL (i.e. it must have been loaded from a Bundle)
|
|
// The mesh must have a valid URL (i.e. it must have been loaded from a Bundle)
|
|
|
// in order to fetch mesh data for computing mesh rigid body.
|
|
// in order to fetch mesh data for computing mesh rigid body.
|
|
|
if (strlen(mesh->getUrl()) == 0)
|
|
if (strlen(mesh->getUrl()) == 0)
|
|
@@ -1091,6 +1068,36 @@ PhysicsCollisionShape* PhysicsController::createMesh(Mesh* mesh, const Vector3&
|
|
|
return NULL;
|
|
return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (!dynamic)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Static meshes use btBvhTriangleMeshShape and therefore only support triangle mesh shapes.
|
|
|
|
|
+ // Dynamic meshes are approximated with a btConvexHullShape (convex wrapper on cloud of vertices)
|
|
|
|
|
+ // and therefore can support any primitive type.
|
|
|
|
|
+ bool triMesh = true;
|
|
|
|
|
+ if (mesh->getPartCount() > 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ for (unsigned int i = 0; i < mesh->getPartCount(); ++i)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (mesh->getPart(i)->getPrimitiveType() != Mesh::TRIANGLES)
|
|
|
|
|
+ {
|
|
|
|
|
+ triMesh = false;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ triMesh = mesh->getPrimitiveType() == Mesh::TRIANGLES;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!triMesh)
|
|
|
|
|
+ {
|
|
|
|
|
+ GP_ERROR("Mesh rigid bodies are currently only supported on meshes with TRIANGLES primitive type.");
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Read mesh data from URL
|
|
|
Bundle::MeshData* data = Bundle::readMeshData(mesh->getUrl());
|
|
Bundle::MeshData* data = Bundle::readMeshData(mesh->getUrl());
|
|
|
if (data == NULL)
|
|
if (data == NULL)
|
|
|
{
|
|
{
|
|
@@ -1112,96 +1119,118 @@ PhysicsCollisionShape* PhysicsController::createMesh(Mesh* mesh, const Vector3&
|
|
|
for (unsigned int i = 0; i < data->vertexCount; i++)
|
|
for (unsigned int i = 0; i < data->vertexCount; i++)
|
|
|
{
|
|
{
|
|
|
v.set(*((float*)&data->vertexData[i * vertexStride + 0 * sizeof(float)]),
|
|
v.set(*((float*)&data->vertexData[i * vertexStride + 0 * sizeof(float)]),
|
|
|
- *((float*)&data->vertexData[i * vertexStride + 1 * sizeof(float)]),
|
|
|
|
|
- *((float*)&data->vertexData[i * vertexStride + 2 * sizeof(float)]));
|
|
|
|
|
|
|
+ *((float*)&data->vertexData[i * vertexStride + 1 * sizeof(float)]),
|
|
|
|
|
+ *((float*)&data->vertexData[i * vertexStride + 2 * sizeof(float)]));
|
|
|
v *= m;
|
|
v *= m;
|
|
|
memcpy(&(shapeMeshData->vertexData[i * 3]), &v, sizeof(float) * 3);
|
|
memcpy(&(shapeMeshData->vertexData[i * 3]), &v, sizeof(float) * 3);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- btTriangleIndexVertexArray* meshInterface = bullet_new<btTriangleIndexVertexArray>();
|
|
|
|
|
|
|
+ btCollisionShape* collisionShape = NULL;
|
|
|
|
|
+ btTriangleIndexVertexArray* meshInterface = NULL;
|
|
|
|
|
|
|
|
- size_t partCount = data->parts.size();
|
|
|
|
|
- if (partCount > 0)
|
|
|
|
|
|
|
+ if (dynamic)
|
|
|
|
|
+ {
|
|
|
|
|
+ // For dynamic meshes, use a btConvexHullShape approximation
|
|
|
|
|
+ btConvexHullShape* originalConvexShape = bullet_new<btConvexHullShape>(shapeMeshData->vertexData, data->vertexCount, sizeof(float)*3);
|
|
|
|
|
+
|
|
|
|
|
+ // Create a hull approximation for better performance
|
|
|
|
|
+ btShapeHull* hull = bullet_new<btShapeHull>(originalConvexShape);
|
|
|
|
|
+ hull->buildHull(originalConvexShape->getMargin());
|
|
|
|
|
+ collisionShape = bullet_new<btConvexHullShape>((btScalar*)hull->getVertexPointer(), hull->numVertices());
|
|
|
|
|
+
|
|
|
|
|
+ SAFE_DELETE(hull);
|
|
|
|
|
+ SAFE_DELETE(originalConvexShape);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
{
|
|
{
|
|
|
- PHY_ScalarType indexType = PHY_UCHAR;
|
|
|
|
|
- int indexStride = 0;
|
|
|
|
|
- Bundle::MeshPartData* meshPart = NULL;
|
|
|
|
|
- for (size_t i = 0; i < partCount; i++)
|
|
|
|
|
|
|
+ // For static meshes, use btBvhTriangleMeshShape
|
|
|
|
|
+ meshInterface = bullet_new<btTriangleIndexVertexArray>();
|
|
|
|
|
+
|
|
|
|
|
+ size_t partCount = data->parts.size();
|
|
|
|
|
+ if (partCount > 0)
|
|
|
{
|
|
{
|
|
|
- meshPart = data->parts[i];
|
|
|
|
|
- GP_ASSERT(meshPart);
|
|
|
|
|
|
|
+ PHY_ScalarType indexType = PHY_UCHAR;
|
|
|
|
|
+ int indexStride = 0;
|
|
|
|
|
+ Bundle::MeshPartData* meshPart = NULL;
|
|
|
|
|
+ for (size_t i = 0; i < partCount; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ meshPart = data->parts[i];
|
|
|
|
|
+ GP_ASSERT(meshPart);
|
|
|
|
|
|
|
|
- switch (meshPart->indexFormat)
|
|
|
|
|
|
|
+ switch (meshPart->indexFormat)
|
|
|
|
|
+ {
|
|
|
|
|
+ case Mesh::INDEX8:
|
|
|
|
|
+ indexType = PHY_UCHAR;
|
|
|
|
|
+ indexStride = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case Mesh::INDEX16:
|
|
|
|
|
+ indexType = PHY_SHORT;
|
|
|
|
|
+ indexStride = 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case Mesh::INDEX32:
|
|
|
|
|
+ indexType = PHY_INTEGER;
|
|
|
|
|
+ indexStride = 4;
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ GP_ERROR("Unsupported index format (%d).", meshPart->indexFormat);
|
|
|
|
|
+ SAFE_DELETE(meshInterface);
|
|
|
|
|
+ SAFE_DELETE_ARRAY(shapeMeshData->vertexData);
|
|
|
|
|
+ SAFE_DELETE(shapeMeshData);
|
|
|
|
|
+ SAFE_DELETE(data);
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Move the index data into the rigid body's local buffer.
|
|
|
|
|
+ // Set it to NULL in the MeshPartData so it is not released when the data is freed.
|
|
|
|
|
+ shapeMeshData->indexData.push_back(meshPart->indexData);
|
|
|
|
|
+ meshPart->indexData = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ // Create a btIndexedMesh object for the current mesh part.
|
|
|
|
|
+ btIndexedMesh indexedMesh;
|
|
|
|
|
+ indexedMesh.m_indexType = indexType;
|
|
|
|
|
+ indexedMesh.m_numTriangles = meshPart->indexCount / 3; // assume TRIANGLES primitive type
|
|
|
|
|
+ indexedMesh.m_numVertices = meshPart->indexCount;
|
|
|
|
|
+ indexedMesh.m_triangleIndexBase = (const unsigned char*)shapeMeshData->indexData[i];
|
|
|
|
|
+ indexedMesh.m_triangleIndexStride = indexStride*3;
|
|
|
|
|
+ indexedMesh.m_vertexBase = (const unsigned char*)shapeMeshData->vertexData;
|
|
|
|
|
+ indexedMesh.m_vertexStride = sizeof(float)*3;
|
|
|
|
|
+ indexedMesh.m_vertexType = PHY_FLOAT;
|
|
|
|
|
+
|
|
|
|
|
+ // Add the indexed mesh data to the mesh interface.
|
|
|
|
|
+ meshInterface->addIndexedMesh(indexedMesh, indexType);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Generate index data for the mesh locally in the rigid body.
|
|
|
|
|
+ unsigned int* indexData = new unsigned int[data->vertexCount];
|
|
|
|
|
+ for (unsigned int i = 0; i < data->vertexCount; i++)
|
|
|
{
|
|
{
|
|
|
- case Mesh::INDEX8:
|
|
|
|
|
- indexType = PHY_UCHAR;
|
|
|
|
|
- indexStride = 1;
|
|
|
|
|
- break;
|
|
|
|
|
- case Mesh::INDEX16:
|
|
|
|
|
- indexType = PHY_SHORT;
|
|
|
|
|
- indexStride = 2;
|
|
|
|
|
- break;
|
|
|
|
|
- case Mesh::INDEX32:
|
|
|
|
|
- indexType = PHY_INTEGER;
|
|
|
|
|
- indexStride = 4;
|
|
|
|
|
- break;
|
|
|
|
|
- default:
|
|
|
|
|
- GP_ERROR("Unsupported index format (%d).", meshPart->indexFormat);
|
|
|
|
|
- SAFE_DELETE(meshInterface);
|
|
|
|
|
- SAFE_DELETE_ARRAY(shapeMeshData->vertexData);
|
|
|
|
|
- SAFE_DELETE(shapeMeshData);
|
|
|
|
|
- SAFE_DELETE(data);
|
|
|
|
|
- return NULL;
|
|
|
|
|
|
|
+ indexData[i] = i;
|
|
|
}
|
|
}
|
|
|
|
|
+ shapeMeshData->indexData.push_back((unsigned char*)indexData);
|
|
|
|
|
|
|
|
- // Move the index data into the rigid body's local buffer.
|
|
|
|
|
- // Set it to NULL in the MeshPartData so it is not released when the data is freed.
|
|
|
|
|
- shapeMeshData->indexData.push_back(meshPart->indexData);
|
|
|
|
|
- meshPart->indexData = NULL;
|
|
|
|
|
-
|
|
|
|
|
- // Create a btIndexedMesh object for the current mesh part.
|
|
|
|
|
|
|
+ // Create a single btIndexedMesh object for the mesh interface.
|
|
|
btIndexedMesh indexedMesh;
|
|
btIndexedMesh indexedMesh;
|
|
|
- indexedMesh.m_indexType = indexType;
|
|
|
|
|
- indexedMesh.m_numTriangles = meshPart->indexCount / 3; // assume TRIANGLES primitive type
|
|
|
|
|
- indexedMesh.m_numVertices = meshPart->indexCount;
|
|
|
|
|
- indexedMesh.m_triangleIndexBase = (const unsigned char*)shapeMeshData->indexData[i];
|
|
|
|
|
- indexedMesh.m_triangleIndexStride = indexStride*3;
|
|
|
|
|
|
|
+ indexedMesh.m_indexType = PHY_INTEGER;
|
|
|
|
|
+ indexedMesh.m_numTriangles = data->vertexCount / 3; // assume TRIANGLES primitive type
|
|
|
|
|
+ indexedMesh.m_numVertices = data->vertexCount;
|
|
|
|
|
+ indexedMesh.m_triangleIndexBase = shapeMeshData->indexData[0];
|
|
|
|
|
+ indexedMesh.m_triangleIndexStride = sizeof(unsigned int);
|
|
|
indexedMesh.m_vertexBase = (const unsigned char*)shapeMeshData->vertexData;
|
|
indexedMesh.m_vertexBase = (const unsigned char*)shapeMeshData->vertexData;
|
|
|
indexedMesh.m_vertexStride = sizeof(float)*3;
|
|
indexedMesh.m_vertexStride = sizeof(float)*3;
|
|
|
indexedMesh.m_vertexType = PHY_FLOAT;
|
|
indexedMesh.m_vertexType = PHY_FLOAT;
|
|
|
|
|
|
|
|
- // Add the indexed mesh data to the mesh interface.
|
|
|
|
|
- meshInterface->addIndexedMesh(indexedMesh, indexType);
|
|
|
|
|
|
|
+ // Set the data in the mesh interface.
|
|
|
|
|
+ meshInterface->addIndexedMesh(indexedMesh, indexedMesh.m_indexType);
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- // Generate index data for the mesh locally in the rigid body.
|
|
|
|
|
- unsigned int* indexData = new unsigned int[data->vertexCount];
|
|
|
|
|
- for (unsigned int i = 0; i < data->vertexCount; i++)
|
|
|
|
|
- {
|
|
|
|
|
- indexData[i] = i;
|
|
|
|
|
- }
|
|
|
|
|
- shapeMeshData->indexData.push_back((unsigned char*)indexData);
|
|
|
|
|
-
|
|
|
|
|
- // Create a single btIndexedMesh object for the mesh interface.
|
|
|
|
|
- btIndexedMesh indexedMesh;
|
|
|
|
|
- indexedMesh.m_indexType = PHY_INTEGER;
|
|
|
|
|
- indexedMesh.m_numTriangles = data->vertexCount / 3; // assume TRIANGLES primitive type
|
|
|
|
|
- indexedMesh.m_numVertices = data->vertexCount;
|
|
|
|
|
- indexedMesh.m_triangleIndexBase = shapeMeshData->indexData[0];
|
|
|
|
|
- indexedMesh.m_triangleIndexStride = sizeof(unsigned int);
|
|
|
|
|
- indexedMesh.m_vertexBase = (const unsigned char*)shapeMeshData->vertexData;
|
|
|
|
|
- indexedMesh.m_vertexStride = sizeof(float)*3;
|
|
|
|
|
- indexedMesh.m_vertexType = PHY_FLOAT;
|
|
|
|
|
-
|
|
|
|
|
- // Set the data in the mesh interface.
|
|
|
|
|
- meshInterface->addIndexedMesh(indexedMesh, indexedMesh.m_indexType);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // Create our collision shape object and store shapeMeshData in it.
|
|
|
|
|
+ collisionShape = bullet_new<btBvhTriangleMeshShape>(meshInterface, true);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Create our collision shape object and store shapeMeshData in it.
|
|
// Create our collision shape object and store shapeMeshData in it.
|
|
|
- PhysicsCollisionShape* shape =
|
|
|
|
|
- new PhysicsCollisionShape(PhysicsCollisionShape::SHAPE_MESH, bullet_new<btBvhTriangleMeshShape>(meshInterface, true), meshInterface);
|
|
|
|
|
|
|
+ PhysicsCollisionShape* shape = new PhysicsCollisionShape(PhysicsCollisionShape::SHAPE_MESH, collisionShape, meshInterface);
|
|
|
shape->_shapeData.meshData = shapeMeshData;
|
|
shape->_shapeData.meshData = shapeMeshData;
|
|
|
|
|
|
|
|
_shapes.push_back(shape);
|
|
_shapes.push_back(shape);
|