Rigidbody: Use own structure to store mesh data for collision shapes
authorSergej Reich <sergej.reich@googlemail.com>
Thu, 26 Dec 2013 16:49:08 +0000 (17:49 +0100)
committerSergej Reich <sergej.reich@googlemail.com>
Thu, 26 Dec 2013 17:38:06 +0000 (18:38 +0100)
This gives us better access to the data and should also be faster to
create.

intern/rigidbody/RBI_api.h
intern/rigidbody/rb_bullet_api.cpp
source/blender/blenkernel/intern/rigidbody.c

index 7a04961..97e8e68 100644 (file)
@@ -227,8 +227,10 @@ extern rbCollisionShape *RB_shape_new_convex_hull(float *verts, int stride, int
 /* Setup (Triangle Mesh) ---------- */
 
 /* 1 */
-extern rbMeshData *RB_trimesh_data_new(void);
-extern void RB_trimesh_add_triangle(rbMeshData *mesh, const float v1[3], const float v2[3], const float v3[3]);
+extern rbMeshData *RB_trimesh_data_new(int num_tris, int num_verts);
+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 */
 extern rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh);
 /* 2b - GImpact Meshes */
index ecb07c6..31f7f38 100644 (file)
@@ -86,9 +86,24 @@ struct rbRigidBody {
        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 {
        btCollisionShape *cshape;
-       btTriangleMesh *mesh;
+       rbMeshData *mesh;
 };
 
 struct rbFilterCallback : public btOverlapFilterCallback
@@ -692,57 +707,71 @@ rbCollisionShape *RB_shape_new_convex_hull(float *verts, int stride, int count,
 
 /* Setup (Triangle Mesh) ---------- */
 
-/* Need to call rbTriMeshNewData() followed by rbTriMeshAddTriangle() several times 
- * to set up the mesh buffer BEFORE calling rbShapeNewTriMesh(). Otherwise,
- * we get nasty crashes...
- */
+/* Need to call RB_trimesh_finish() after creating triangle mesh and adding vertices and triangles */
+
+rbMeshData *RB_trimesh_data_new(int num_tris, int num_verts)
+{
+       rbMeshData *mesh = new rbMeshData;
+       mesh->vertices = new rbVert[num_verts];
+       mesh->triangles = new rbTri[num_tris];
+       mesh->num_vertices = num_verts;
+       mesh->num_triangles = num_tris;
+       
+       return mesh;
+}
 
-rbMeshData *RB_trimesh_data_new()
+static void RB_trimesh_data_delete(rbMeshData *mesh)
 {
-       // XXX: welding threshold?
-       return (rbMeshData *) new btTriangleMesh(true, false);
+       delete mesh->index_array;
+       delete mesh->vertices;
+       delete mesh->triangles;
+       delete mesh;
 }
  
-void RB_trimesh_add_triangle(rbMeshData *mesh, const float v1[3], const float v2[3], const float v3[3])
+void RB_trimesh_add_vertices(rbMeshData *mesh, float *vertices, int num_verts, int vert_stride)
 {
-       btTriangleMesh *meshData = reinterpret_cast<btTriangleMesh*>(mesh);
-       
-       /* cast vertices to usable forms for Bt-API */
-       btVector3 vtx1((btScalar)v1[0], (btScalar)v1[1], (btScalar)v1[2]);
-       btVector3 vtx2((btScalar)v2[0], (btScalar)v2[1], (btScalar)v2[2]);
-       btVector3 vtx3((btScalar)v3[0], (btScalar)v3[1], (btScalar)v3[2]);
-       
-       /* add to the mesh 
-        *      - remove duplicated verts is enabled
-        */
-       meshData->addTriangle(vtx1, vtx2, vtx3, false);
+       for (int i = 0; i < num_verts; i++) {
+               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;
+}
+
+void RB_trimesh_finish(rbMeshData *mesh)
+{
+       mesh->index_array = new btTriangleIndexVertexArray(mesh->num_triangles, (int*)mesh->triangles, sizeof(rbTri),
+                                                          mesh->num_vertices, (float*)mesh->vertices, sizeof(rbVert));
 }
  
 rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh)
 {
        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) */
        // 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->mesh = tmesh;
+       shape->mesh = mesh;
        return shape;
 }
 
 rbCollisionShape *RB_shape_new_gimpact_mesh(rbMeshData *mesh)
 {
        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?
        
        shape->cshape = gimpactShape;
-       shape->mesh = tmesh;
+       shape->mesh = mesh;
        return shape;
 }
 
@@ -756,7 +785,7 @@ void RB_shape_delete(rbCollisionShape *shape)
                        delete child_shape;
        }
        if (shape->mesh)
-               delete shape->mesh;
+               RB_trimesh_data_delete(shape->mesh);
        delete shape->cshape;
        delete shape;
 }
index fa455fa..22126b7 100644 (file)
@@ -282,6 +282,8 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
                MFace *mface;
                int totvert;
                int totface;
+               int tottris = 0;
+               int triangle_index = 0;
 
                dm = rigidbody_get_mesh(ob);
 
@@ -303,32 +305,32 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
                else {
                        rbMeshData *mdata;
                        int i;
+                       
+                       /* count triangles */
+                       for (i = 0; i < totface; i++) {
+                               (mface[i].v4) ? (tottris += 2) : (tottris += 1);
+                       }
 
                        /* 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
                         * (so for some faces, more than triangle will get added)
                         */
                        for (i = 0; (i < totface) && (mface) && (mvert); i++, mface++) {
                                /* add first triangle - verts 1,2,3 */
-                               {
-                                       MVert *va = (mface->v1 < totvert) ? (mvert + mface->v1) : (mvert);
-                                       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);
-                               }
+                               RB_trimesh_add_triangle_indices(mdata, triangle_index, mface->v1, mface->v2, mface->v3);
+                               triangle_index++;
 
                                /* add second triangle if needed - verts 1,3,4 */
                                if (mface->v4) {
-                                       MVert *va = (mface->v1 < totvert) ? (mvert + mface->v1) : (mvert);
-                                       MVert *vb = (mface->v3 < totvert) ? (mvert + mface->v3) : (mvert);
-                                       MVert *vc = (mface->v4 < totvert) ? (mvert + mface->v4) : (mvert);
-
-                                       RB_trimesh_add_triangle(mdata, va->co, vb->co, vc->co);
+                                       RB_trimesh_add_triangle_indices(mdata, triangle_index, mface->v1, mface->v3, mface->v4);
+                                       triangle_index++;
                                }
                        }
+                       RB_trimesh_finish(mdata);
 
                        /* construct collision shape
                         *