From c96601138dfe08705fd4375527d322176b8fa126 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Thu, 26 Dec 2013 17:49:08 +0100 Subject: 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. --- intern/rigidbody/RBI_api.h | 6 +- intern/rigidbody/rb_bullet_api.cpp | 85 +++++++++++++++++++--------- source/blender/blenkernel/intern/rigidbody.c | 28 ++++----- 3 files changed, 76 insertions(+), 43 deletions(-) diff --git a/intern/rigidbody/RBI_api.h b/intern/rigidbody/RBI_api.h index 7a04961f99d..97e8e6891ff 100644 --- a/intern/rigidbody/RBI_api.h +++ b/intern/rigidbody/RBI_api.h @@ -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 */ diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp index ecb07c628d2..31f7f386663 100644 --- a/intern/rigidbody/rb_bullet_api.cpp +++ b/intern/rigidbody/rb_bullet_api.cpp @@ -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(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(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(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; } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index fa455fad090..22126b7e45d 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -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 * -- cgit v1.2.3