forked from bartvdbraak/blender
Rigidbody: Use own structure to store mesh data for collision shapes
This gives us better access to the data and should also be faster to create.
This commit is contained in:
parent
2260a7dbc0
commit
c96601138d
@ -227,8 +227,10 @@ extern rbCollisionShape *RB_shape_new_convex_hull(float *verts, int stride, int
|
|||||||
/* Setup (Triangle Mesh) ---------- */
|
/* Setup (Triangle Mesh) ---------- */
|
||||||
|
|
||||||
/* 1 */
|
/* 1 */
|
||||||
extern rbMeshData *RB_trimesh_data_new(void);
|
extern rbMeshData *RB_trimesh_data_new(int num_tris, int num_verts);
|
||||||
extern void RB_trimesh_add_triangle(rbMeshData *mesh, const float v1[3], const float v2[3], const float v3[3]);
|
extern void RB_trimesh_add_vertices(rbMeshData *mesh, float *vertices, int num_verts, int vert_stride);
|
||||||
|
extern void RB_trimesh_add_triangle_indices(rbMeshData *mesh, int num, int index0, int index1, int index2);
|
||||||
|
extern void RB_trimesh_finish(rbMeshData *mesh);
|
||||||
/* 2a - Triangle Meshes */
|
/* 2a - Triangle Meshes */
|
||||||
extern rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh);
|
extern rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh);
|
||||||
/* 2b - GImpact Meshes */
|
/* 2b - GImpact Meshes */
|
||||||
|
@ -86,9 +86,24 @@ struct rbRigidBody {
|
|||||||
int col_groups;
|
int col_groups;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct rbVert {
|
||||||
|
float x, y, z;
|
||||||
|
};
|
||||||
|
struct rbTri {
|
||||||
|
int v0, v1, v2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rbMeshData {
|
||||||
|
btTriangleIndexVertexArray *index_array;
|
||||||
|
rbVert *vertices;
|
||||||
|
rbTri *triangles;
|
||||||
|
int num_vertices;
|
||||||
|
int num_triangles;
|
||||||
|
};
|
||||||
|
|
||||||
struct rbCollisionShape {
|
struct rbCollisionShape {
|
||||||
btCollisionShape *cshape;
|
btCollisionShape *cshape;
|
||||||
btTriangleMesh *mesh;
|
rbMeshData *mesh;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rbFilterCallback : public btOverlapFilterCallback
|
struct rbFilterCallback : public btOverlapFilterCallback
|
||||||
@ -692,57 +707,71 @@ rbCollisionShape *RB_shape_new_convex_hull(float *verts, int stride, int count,
|
|||||||
|
|
||||||
/* Setup (Triangle Mesh) ---------- */
|
/* Setup (Triangle Mesh) ---------- */
|
||||||
|
|
||||||
/* Need to call rbTriMeshNewData() followed by rbTriMeshAddTriangle() several times
|
/* Need to call RB_trimesh_finish() after creating triangle mesh and adding vertices and triangles */
|
||||||
* to set up the mesh buffer BEFORE calling rbShapeNewTriMesh(). Otherwise,
|
|
||||||
* we get nasty crashes...
|
|
||||||
*/
|
|
||||||
|
|
||||||
rbMeshData *RB_trimesh_data_new()
|
rbMeshData *RB_trimesh_data_new(int num_tris, int num_verts)
|
||||||
{
|
{
|
||||||
// XXX: welding threshold?
|
rbMeshData *mesh = new rbMeshData;
|
||||||
return (rbMeshData *) new btTriangleMesh(true, false);
|
mesh->vertices = new rbVert[num_verts];
|
||||||
|
mesh->triangles = new rbTri[num_tris];
|
||||||
|
mesh->num_vertices = num_verts;
|
||||||
|
mesh->num_triangles = num_tris;
|
||||||
|
|
||||||
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RB_trimesh_add_triangle(rbMeshData *mesh, const float v1[3], const float v2[3], const float v3[3])
|
static void RB_trimesh_data_delete(rbMeshData *mesh)
|
||||||
{
|
{
|
||||||
btTriangleMesh *meshData = reinterpret_cast<btTriangleMesh*>(mesh);
|
delete mesh->index_array;
|
||||||
|
delete mesh->vertices;
|
||||||
|
delete mesh->triangles;
|
||||||
|
delete mesh;
|
||||||
|
}
|
||||||
|
|
||||||
/* cast vertices to usable forms for Bt-API */
|
void RB_trimesh_add_vertices(rbMeshData *mesh, float *vertices, int num_verts, int vert_stride)
|
||||||
btVector3 vtx1((btScalar)v1[0], (btScalar)v1[1], (btScalar)v1[2]);
|
{
|
||||||
btVector3 vtx2((btScalar)v2[0], (btScalar)v2[1], (btScalar)v2[2]);
|
for (int i = 0; i < num_verts; i++) {
|
||||||
btVector3 vtx3((btScalar)v3[0], (btScalar)v3[1], (btScalar)v3[2]);
|
float *vert = (float*)(((char*)vertices + i * vert_stride));
|
||||||
|
mesh->vertices[i].x = vert[0];
|
||||||
|
mesh->vertices[i].y = vert[1];
|
||||||
|
mesh->vertices[i].z = vert[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void RB_trimesh_add_triangle_indices(rbMeshData *mesh, int num, int index0, int index1, int index2)
|
||||||
|
{
|
||||||
|
mesh->triangles[num].v0 = index0;
|
||||||
|
mesh->triangles[num].v1 = index1;
|
||||||
|
mesh->triangles[num].v2 = index2;
|
||||||
|
}
|
||||||
|
|
||||||
/* add to the mesh
|
void RB_trimesh_finish(rbMeshData *mesh)
|
||||||
* - remove duplicated verts is enabled
|
{
|
||||||
*/
|
mesh->index_array = new btTriangleIndexVertexArray(mesh->num_triangles, (int*)mesh->triangles, sizeof(rbTri),
|
||||||
meshData->addTriangle(vtx1, vtx2, vtx3, false);
|
mesh->num_vertices, (float*)mesh->vertices, sizeof(rbVert));
|
||||||
}
|
}
|
||||||
|
|
||||||
rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh)
|
rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh)
|
||||||
{
|
{
|
||||||
rbCollisionShape *shape = new rbCollisionShape;
|
rbCollisionShape *shape = new rbCollisionShape;
|
||||||
btTriangleMesh *tmesh = reinterpret_cast<btTriangleMesh*>(mesh);
|
|
||||||
|
|
||||||
/* triangle-mesh we create is a BVH wrapper for triangle mesh data (for faster lookups) */
|
/* triangle-mesh we create is a BVH wrapper for triangle mesh data (for faster lookups) */
|
||||||
// RB_TODO perhaps we need to allow saving out this for performance when rebuilding?
|
// RB_TODO perhaps we need to allow saving out this for performance when rebuilding?
|
||||||
btBvhTriangleMeshShape *unscaledShape = new btBvhTriangleMeshShape(tmesh, true, true);
|
btBvhTriangleMeshShape *unscaledShape = new btBvhTriangleMeshShape(mesh->index_array, true, true);
|
||||||
|
|
||||||
shape->cshape = new btScaledBvhTriangleMeshShape(unscaledShape, btVector3(1.0f, 1.0f, 1.0f));
|
shape->cshape = new btScaledBvhTriangleMeshShape(unscaledShape, btVector3(1.0f, 1.0f, 1.0f));
|
||||||
shape->mesh = tmesh;
|
shape->mesh = mesh;
|
||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
rbCollisionShape *RB_shape_new_gimpact_mesh(rbMeshData *mesh)
|
rbCollisionShape *RB_shape_new_gimpact_mesh(rbMeshData *mesh)
|
||||||
{
|
{
|
||||||
rbCollisionShape *shape = new rbCollisionShape;
|
rbCollisionShape *shape = new rbCollisionShape;
|
||||||
/* interpret mesh buffer as btTriangleIndexVertexArray (i.e. an impl of btStridingMeshInterface) */
|
|
||||||
btTriangleMesh *tmesh = reinterpret_cast<btTriangleMesh*>(mesh);
|
|
||||||
|
|
||||||
btGImpactMeshShape *gimpactShape = new btGImpactMeshShape(tmesh);
|
btGImpactMeshShape *gimpactShape = new btGImpactMeshShape(mesh->index_array);
|
||||||
gimpactShape->updateBound(); // TODO: add this to the update collision margin call?
|
gimpactShape->updateBound(); // TODO: add this to the update collision margin call?
|
||||||
|
|
||||||
shape->cshape = gimpactShape;
|
shape->cshape = gimpactShape;
|
||||||
shape->mesh = tmesh;
|
shape->mesh = mesh;
|
||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,7 +785,7 @@ void RB_shape_delete(rbCollisionShape *shape)
|
|||||||
delete child_shape;
|
delete child_shape;
|
||||||
}
|
}
|
||||||
if (shape->mesh)
|
if (shape->mesh)
|
||||||
delete shape->mesh;
|
RB_trimesh_data_delete(shape->mesh);
|
||||||
delete shape->cshape;
|
delete shape->cshape;
|
||||||
delete shape;
|
delete shape;
|
||||||
}
|
}
|
||||||
|
@ -282,6 +282,8 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
|
|||||||
MFace *mface;
|
MFace *mface;
|
||||||
int totvert;
|
int totvert;
|
||||||
int totface;
|
int totface;
|
||||||
|
int tottris = 0;
|
||||||
|
int triangle_index = 0;
|
||||||
|
|
||||||
dm = rigidbody_get_mesh(ob);
|
dm = rigidbody_get_mesh(ob);
|
||||||
|
|
||||||
@ -304,31 +306,31 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
|
|||||||
rbMeshData *mdata;
|
rbMeshData *mdata;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* count triangles */
|
||||||
|
for (i = 0; i < totface; i++) {
|
||||||
|
(mface[i].v4) ? (tottris += 2) : (tottris += 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* init mesh data for collision shape */
|
/* init mesh data for collision shape */
|
||||||
mdata = RB_trimesh_data_new();
|
mdata = RB_trimesh_data_new(tottris, totvert);
|
||||||
|
|
||||||
|
RB_trimesh_add_vertices(mdata, (float*)mvert, totvert, sizeof(MVert));
|
||||||
|
|
||||||
/* loop over all faces, adding them as triangles to the collision shape
|
/* loop over all faces, adding them as triangles to the collision shape
|
||||||
* (so for some faces, more than triangle will get added)
|
* (so for some faces, more than triangle will get added)
|
||||||
*/
|
*/
|
||||||
for (i = 0; (i < totface) && (mface) && (mvert); i++, mface++) {
|
for (i = 0; (i < totface) && (mface) && (mvert); i++, mface++) {
|
||||||
/* add first triangle - verts 1,2,3 */
|
/* add first triangle - verts 1,2,3 */
|
||||||
{
|
RB_trimesh_add_triangle_indices(mdata, triangle_index, mface->v1, mface->v2, mface->v3);
|
||||||
MVert *va = (mface->v1 < totvert) ? (mvert + mface->v1) : (mvert);
|
triangle_index++;
|
||||||
MVert *vb = (mface->v2 < totvert) ? (mvert + mface->v2) : (mvert);
|
|
||||||
MVert *vc = (mface->v3 < totvert) ? (mvert + mface->v3) : (mvert);
|
|
||||||
|
|
||||||
RB_trimesh_add_triangle(mdata, va->co, vb->co, vc->co);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add second triangle if needed - verts 1,3,4 */
|
/* add second triangle if needed - verts 1,3,4 */
|
||||||
if (mface->v4) {
|
if (mface->v4) {
|
||||||
MVert *va = (mface->v1 < totvert) ? (mvert + mface->v1) : (mvert);
|
RB_trimesh_add_triangle_indices(mdata, triangle_index, mface->v1, mface->v3, mface->v4);
|
||||||
MVert *vb = (mface->v3 < totvert) ? (mvert + mface->v3) : (mvert);
|
triangle_index++;
|
||||||
MVert *vc = (mface->v4 < totvert) ? (mvert + mface->v4) : (mvert);
|
|
||||||
|
|
||||||
RB_trimesh_add_triangle(mdata, va->co, vb->co, vc->co);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RB_trimesh_finish(mdata);
|
||||||
|
|
||||||
/* construct collision shape
|
/* construct collision shape
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user