[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [30457] branches/soc-2010-aligorith-2/ source/blender: Bullet SoC - Mesh Collision Shapes (Triangle Mesh)

Joshua Leung aligorith at gmail.com
Sun Jul 18 07:00:13 CEST 2010


Revision: 30457
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=30457
Author:   aligorith
Date:     2010-07-18 07:00:11 +0200 (Sun, 18 Jul 2010)

Log Message:
-----------
Bullet SoC - Mesh Collision Shapes (Triangle Mesh)

This commit introduces a second method for creating collision shapes or arbitrary shapes: (Triangle) Meshes.

This method creates collision shapes consisting of triangles only. It is most/only suitable for irregular shapes with concave parts as part of their surface OR for chain-like assemblies (i.e. tori linked together to form a chain).

However, it is NOT suitable for convex shapes (i.e. spheres) or objects with large planar collision surfaces (i.e. ground planes, cubes/cube-like shapes), as the collisions will be completely ignored. Convex Hulls are better in these types of shapes.

Also, beware that choosing the 'Mesh' option can be really slow (only really a problem when changing the option to this, or when rebuilding the simulation after resetting it or reloading the file). It's probably due to either the DerivedMesh rebuilding or the duplicate vert merging being performed by Bullet. Either way, I'll optimise this later.

---

'Convex Hulls' is the new name for the former 'Mesh' option in this branch, since that's what they really were. 

By default, all newly created rigid bodies are now made as convex hulls. 
- I've removed the stop-gap measure to take collision shape defaults from the boundbox of objects, which included code which tried to guess the best choice. 
- I've chosen Convex Hulls over Meshes for this purpose for 2 reasons: 
1) (re)building speed, 
2) convex hulls will let even the most basic test situations work out of the box, while tri-meshes only work under very specific situations only

---

I'll make a post later tonight on my blog detailing the situations that work/don't work, with demonstration videos to better illustrate how to choose collision shapes. Probably later on this should also be added to the Wiki docs (when everything settles down too)

Modified Paths:
--------------
    branches/soc-2010-aligorith-2/source/blender/blenkernel/intern/rigidbody.c
    branches/soc-2010-aligorith-2/source/blender/makesdna/DNA_rigidbody_types.h
    branches/soc-2010-aligorith-2/source/blender/makesrna/intern/rna_rigidbody.c
    branches/soc-2010-aligorith-2/source/blender/rigidbody/RBI_api.h
    branches/soc-2010-aligorith-2/source/blender/rigidbody/rb_bullet_api.cpp

Modified: branches/soc-2010-aligorith-2/source/blender/blenkernel/intern/rigidbody.c
===================================================================
--- branches/soc-2010-aligorith-2/source/blender/blenkernel/intern/rigidbody.c	2010-07-18 02:47:45 UTC (rev 30456)
+++ branches/soc-2010-aligorith-2/source/blender/blenkernel/intern/rigidbody.c	2010-07-18 05:00:11 UTC (rev 30457)
@@ -42,11 +42,15 @@
 
 #include "DNA_anim_types.h"
 #include "DNA_group_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
 #include "DNA_object_types.h"
 #include "DNA_rigidbody_types.h"
 #include "DNA_scene_types.h"
 
 #include "BKE_animsys.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_DerivedMesh.h"
 #include "BKE_group.h"
 #include "BKE_object.h"
 #include "BKE_mesh.h"
@@ -141,8 +145,8 @@
 /* ************************************** */
 /* Setup Utilities - Validate Sim Instances */
 
-/* create collision shape of mesh */
-static rbCollisionShape *rigidbody_get_shape_from_mesh (Object *ob)
+/* create collision shape of mesh - convex hull */
+static rbCollisionShape *rigidbody_get_shape_convexhull_from_mesh (Object *ob)
 {
 	rbCollisionShape *shape = rbShapeNewConvexHull();
 	float (*vertCos)[3] = NULL;
@@ -173,6 +177,61 @@
 	return shape;
 }
 
+/* create collision shape of mesh - triangulated mesh */
+static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh (Object *ob)
+{
+	rbCollisionShape *shape = NULL;
+	
+	if (ob->type == OB_MESH) {
+		DerivedMesh *dm = CDDM_from_mesh(ob->data, ob);
+		
+		MVert *mvert = (dm)? dm->getVertArray(dm) : NULL;
+		int totvert = (dm)? dm->getNumVerts(dm) : 0;
+		MFace *mface = (dm)? dm->getFaceArray(dm) : NULL;
+		int totface = (dm)? dm->getNumFaces(dm) : 0;
+		
+		rbMeshData *mdata;
+		int i;
+		
+		/* init mesh data for collision shape */
+		mdata = rbTriMeshNewData();
+		
+		/* 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 = (IN_RANGE(mface->v1, 0,totvert))? (mvert + mface->v1) : (mvert);
+				MVert *vb = (IN_RANGE(mface->v2, 0,totvert))? (mvert + mface->v2) : (mvert);
+				MVert *vc = (IN_RANGE(mface->v3, 0,totvert))? (mvert + mface->v3) : (mvert);
+				
+				rbTriMeshAddTriangle(mdata, va->co, vb->co, vc->co);
+			}
+			
+			/* add second triangle if needed - verts 2,3,4 */
+			if (mface->v4) {
+				MVert *va = (IN_RANGE(mface->v2, 0,totvert))? (mvert + mface->v2) : (mvert);
+				MVert *vb = (IN_RANGE(mface->v3, 0,totvert))? (mvert + mface->v3) : (mvert);
+				MVert *vc = (IN_RANGE(mface->v4, 0,totvert))? (mvert + mface->v4) : (mvert);
+				
+				rbTriMeshAddTriangle(mdata, va->co, vb->co, vc->co);
+			}
+		}
+		
+		/* construct collision shape */
+		shape = rbShapeNewTriMesh(mdata);
+		
+		/* cleanup temp data */
+		if (dm)
+			dm->release(dm);
+	}
+	else 
+		printf("ERROR: cannot make Triangule Mesh collision shape for non-Mesh object\n");
+	
+	return shape;
+}
+
 /* Create new physics sim collision shape for object and store it,
  * or remove the existing one first and replace...
  */
@@ -235,13 +294,20 @@
 			rbo->physics_shape = rbShapeNewCone(radius, height);
 			break;
 		
+		case RB_SHAPE_CONVEXH:
+			// TODO: this may fail if the object is wrong type...
+			rbo->physics_shape = rigidbody_get_shape_convexhull_from_mesh(ob);
+			break;
 		case RB_SHAPE_TRIMESH:
 			// TODO: this may fail if the object is wrong type...
-			rbo->physics_shape = rigidbody_get_shape_from_mesh(ob);
+			rbo->physics_shape = rigidbody_get_shape_trimesh_from_mesh(ob);
 			break;
+		
+#if 0 // XXX: not defined yet
 		case RB_SHAPE_COMPOUND:
 			rbo->physics_shape = NULL; // xxx!
 			break;
+#endif
 	}
 }
 
@@ -341,39 +407,6 @@
 	return rbw;
 }
 
-
-/* helper for BKE_rigidbody_create_object() - determines the collision shape from the boundbox type */
-static int get_shape_from_boundbox (Object *ob)
-{
-	switch (ob->boundtype) {
-		/* 1:1 mapping */
-		case OB_BOUND_SPHERE:
-			return RB_SHAPE_SPHERE;
-		case OB_BOUND_CYLINDER:
-			return RB_SHAPE_CYLINDER;
-		case OB_BOUND_CONE:
-			return RB_SHAPE_CONE;
-		
-		/* some fancy stuff */
-		case OB_BOUND_BOX:
-			/* this happens in threee cases:
-			 * 	1) assume that if draw_bounds is enabled, then user explicitly wants box
-			 *	2) assume that if not a mesh (i.e. a curve), then box is the only safe option
-			 *		for now, despite boundboxes not being drawn
-			 */
-			if ((ob->dtx & OB_BOUNDBOX) || (ob->type != OB_MESH))
-				return RB_SHAPE_BOX;
-			/* else 
-			 *	3) user hasn't touched this setting, so assume that a fancy default of 'mesh'
-			 *		should be used to get nicely functioning collisions working by default, so...
-			 *
-			 * !!!PASSTHROUGH!!!
-			 */
-		default:
-			return RB_SHAPE_TRIMESH;
-	}
-}
-
 /* Add RigidBody settings to the specified object */
 RigidBodyOb *BKE_rigidbody_create_object (RigidBodyWorld *rbw, Object *ob, short type)
 {
@@ -407,7 +440,8 @@
 	
 	rbo->margin = 0.04; // 0.04 (in meters) is Bullet default
 	
-	rbo->shape = get_shape_from_boundbox(ob);
+		/* convex hull offers the best performance for general cases */
+	rbo->shape = RB_SHAPE_CONVEXH;
 	
 	/* return this object */
 	return rbo;

Modified: branches/soc-2010-aligorith-2/source/blender/makesdna/DNA_rigidbody_types.h
===================================================================
--- branches/soc-2010-aligorith-2/source/blender/makesdna/DNA_rigidbody_types.h	2010-07-18 02:47:45 UTC (rev 30456)
+++ branches/soc-2010-aligorith-2/source/blender/makesdna/DNA_rigidbody_types.h	2010-07-18 05:00:11 UTC (rev 30457)
@@ -147,10 +147,13 @@
 		/* cone (i.e. party hat) */
 	RB_SHAPE_CONE,
 	
-		/* convex mesh with triangles only */
+		/* convex hull (minimal shrinkwrap encompassing all verts) */
+	RB_SHAPE_CONVEXH,
+		/* triangulated mesh */
 	RB_SHAPE_TRIMESH,
+	
 		/* concave mesh approximated using primatives */
-	RB_SHAPE_COMPOUND,
+	//RB_SHAPE_COMPOUND,
 } eRigidBody_Shape;
 
 /* Options for transforms to use from Bullet */

Modified: branches/soc-2010-aligorith-2/source/blender/makesrna/intern/rna_rigidbody.c
===================================================================
--- branches/soc-2010-aligorith-2/source/blender/makesrna/intern/rna_rigidbody.c	2010-07-18 02:47:45 UTC (rev 30456)
+++ branches/soc-2010-aligorith-2/source/blender/makesrna/intern/rna_rigidbody.c	2010-07-18 05:00:11 UTC (rev 30457)
@@ -52,7 +52,8 @@
 	{RB_SHAPE_CYLINDER, "CYLINDER", ICON_MESH_TUBE, "Cylinder", ""},
 	{RB_SHAPE_CONE, "CONE", ICON_MESH_CONE, "Cone", ""},
 	//{0, "", 0, "", ""},
-	{RB_SHAPE_TRIMESH, "MESH", ICON_MESH_MONKEY, "Mesh", "Convex Hull defined from vertices of mesh only. Best results with fewer vertices"},
+	{RB_SHAPE_CONVEXH, "CONVEX_HULL", ICON_MESH_ICOSPHERE, "Convex Hull", "A mesh-like surface encompassing (i.e. shrinkwrap over) all verts. Best results with fewer vertices"},
+	{RB_SHAPE_TRIMESH, "MESH", ICON_MESH_MONKEY, "Mesh", "Mesh consisting of triangles only, allowing for more detailed interactions than convex hulls"},
 	// XXX: compound shapes have yet to be implemented
 	{0, NULL, 0, NULL, NULL}};
 

Modified: branches/soc-2010-aligorith-2/source/blender/rigidbody/RBI_api.h
===================================================================
--- branches/soc-2010-aligorith-2/source/blender/rigidbody/RBI_api.h	2010-07-18 02:47:45 UTC (rev 30456)
+++ branches/soc-2010-aligorith-2/source/blender/rigidbody/RBI_api.h	2010-07-18 05:00:11 UTC (rev 30457)
@@ -59,6 +59,9 @@
 /* Collision Shape */
 typedef struct _rbCollisionShape rbCollisionShape;
 
+/* Mesh Data (for Collision Shapes of Meshes) */
+typedef struct _rbMeshData rbMeshData;
+
 /* Constraint */
 typedef struct _rbConstraint rbConstraint;
 
@@ -192,12 +195,21 @@
 extern rbCollisionShape *rbShapeNewCone(float radius, float height);
 extern rbCollisionShape *rbShapeNewCylinder(float radius, float height);
 
-/* Setup (Special Shapes) ------------ */
+/* Setup (Convex Hull) ------------ */
 
-/* Convex Hull */
 extern rbCollisionShape *rbShapeNewConvexHull();
+
 extern void rbConvexHullAddVert(rbCollisionShape *cshape, const float co[3]);
 
+/* Setup (Triangle Mesh) ---------- */
+
+/* 1 */
+extern rbMeshData *rbTriMeshNewData();
+extern void rbTriMeshAddTriangle(rbMeshData *mesh, const float v1[3], const float v2[3], const float v3[3]);
+/* 2*/
+extern rbCollisionShape *rbShapeNewTriMesh(rbMeshData *mesh);
+
+
 /* Cleanup --------------------------- */
 
 extern void rbShapeDelete(rbCollisionShape *cshape);

Modified: branches/soc-2010-aligorith-2/source/blender/rigidbody/rb_bullet_api.cpp
===================================================================
--- branches/soc-2010-aligorith-2/source/blender/rigidbody/rb_bullet_api.cpp	2010-07-18 02:47:45 UTC (rev 30456)
+++ branches/soc-2010-aligorith-2/source/blender/rigidbody/rb_bullet_api.cpp	2010-07-18 05:00:11 UTC (rev 30457)
@@ -71,6 +71,8 @@
 #include "LinearMath/btMatrix3x3.h"
 #include "LinearMath/btTransform.h"
 
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
+
 /* ********************************** */
 /* Dynamics World Methods */
 
@@ -509,7 +511,7 @@
 	return (rbCollisionShape*) new(mem) btCylinderShapeZ(btVector3(radius,height,radius));
 }
 
-/* Setup (Special Shapes) ------------ */
+/* Setup (Convex Hull) ------------ */
 
 rbCollisionShape *rbShapeNewConvexHull()
 {
@@ -523,6 +525,55 @@
 	convexHullShape->addPoint(btVector3(co[0], co[1], co[2]));
 }
 
+/* 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...
+ */
+
+rbMeshData *rbTriMeshNewData()
+{
+	void *mem = btAlignedAlloc(sizeof(btTriangleMesh), 16);
+	// XXX: welding threshold?
+	return (rbMeshData*) new(mem) btTriangleMesh(true, false);
+}
+ 
+void rbTriMeshAddTriangle(rbMeshData *mesh, const float v1[3], const float v2[3], const float v3[3])
+{
+	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]);
+	
+	printf("\t\tpre-add - %d\n", meshData->getNumTriangles());
+	
+	/* add to the mesh 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list