[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [59232] branches/soc-2013-rigid_body_sim: rigidbody: Add convex decomposition collision shape

Sergej Reich sergej.reich at googlemail.com
Sun Aug 18 14:29:25 CEST 2013


Revision: 59232
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=59232
Author:   sergof
Date:     2013-08-18 12:29:24 +0000 (Sun, 18 Aug 2013)
Log Message:
-----------
rigidbody: Add convex decomposition collision shape

Uses HACD to break concave meshes into convex chunks and stores them in
a compound shape.

There is a lot of room for optimization. Right now performing convex
decomposition can be very slow for complex meshes.

Modified Paths:
--------------
    branches/soc-2013-rigid_body_sim/intern/rigidbody/CMakeLists.txt
    branches/soc-2013-rigid_body_sim/intern/rigidbody/RBI_api.h
    branches/soc-2013-rigid_body_sim/intern/rigidbody/rb_bullet_api.cpp
    branches/soc-2013-rigid_body_sim/source/blender/blenkernel/intern/rigidbody.c
    branches/soc-2013-rigid_body_sim/source/blender/editors/physics/rigidbody_object.c
    branches/soc-2013-rigid_body_sim/source/blender/makesdna/DNA_rigidbody_types.h
    branches/soc-2013-rigid_body_sim/source/blender/makesrna/intern/rna_rigidbody.c
    branches/soc-2013-rigid_body_sim/source/creator/CMakeLists.txt

Modified: branches/soc-2013-rigid_body_sim/intern/rigidbody/CMakeLists.txt
===================================================================
--- branches/soc-2013-rigid_body_sim/intern/rigidbody/CMakeLists.txt	2013-08-18 12:29:22 UTC (rev 59231)
+++ branches/soc-2013-rigid_body_sim/intern/rigidbody/CMakeLists.txt	2013-08-18 12:29:24 UTC (rev 59232)
@@ -25,6 +25,7 @@
 	.
 	../../source/blender/gpu
 	../../extern/bullet2/src
+	../../extern/HACD
 )
 
 set(INC_SYS

Modified: branches/soc-2013-rigid_body_sim/intern/rigidbody/RBI_api.h
===================================================================
--- branches/soc-2013-rigid_body_sim/intern/rigidbody/RBI_api.h	2013-08-18 12:29:22 UTC (rev 59231)
+++ branches/soc-2013-rigid_body_sim/intern/rigidbody/RBI_api.h	2013-08-18 12:29:24 UTC (rev 59232)
@@ -62,6 +62,7 @@
 
 /* Mesh Data (for Collision Shapes of Meshes) */
 typedef struct rbMeshData rbMeshData;
+typedef struct rbHACDMeshData rbHACDMeshData;
 
 /* Constraint */
 typedef struct rbConstraint rbConstraint;
@@ -236,6 +237,12 @@
 /* 2b - GImpact Meshes */
 extern rbCollisionShape *RB_shape_new_gimpact_mesh(rbMeshData *mesh);
 
+
+extern rbHACDMeshData *RB_hacd_mesh_new(int num_tris, int num_verts);
+extern void RB_hacd_mesh_add_triangle(rbHACDMeshData *mesh, const float v1[3], const float v2[3], const float v3[3]);
+
+extern rbCollisionShape *RB_shape_new_convex_decomp(rbHACDMeshData *mesh);
+
 /* Compound Shapes ------------------- */
 extern void RB_shape_add_compound_child(rbRigidBody *parent, rbCollisionShape *child, float child_pos[3], float child_orn[4]);
 

Modified: branches/soc-2013-rigid_body_sim/intern/rigidbody/rb_bullet_api.cpp
===================================================================
--- branches/soc-2013-rigid_body_sim/intern/rigidbody/rb_bullet_api.cpp	2013-08-18 12:29:22 UTC (rev 59231)
+++ branches/soc-2013-rigid_body_sim/intern/rigidbody/rb_bullet_api.cpp	2013-08-18 12:29:24 UTC (rev 59232)
@@ -75,6 +75,8 @@
 #include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h"
 #include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
 
+#include "hacdHACD.h"
+
 struct rbDynamicsWorld {
 	btDiscreteDynamicsWorld *dynamicsWorld;
 	btDefaultCollisionConfiguration *collisionConfiguration;
@@ -860,6 +862,73 @@
 	return shape;
 }
 
+struct rbHACDMeshData {
+	std::vector< HACD::Vec3<HACD::Real> > verts;
+	std::vector< HACD::Vec3<long> > tris;
+};
+
+rbHACDMeshData *RB_hacd_mesh_new(int num_tris, int num_verts)
+{
+	rbHACDMeshData *mesh = new rbHACDMeshData;
+	
+	mesh->verts.reserve(num_verts);
+	mesh->tris.reserve(num_tris);
+	
+	return mesh;
+}
+ 
+void RB_hacd_mesh_add_triangle(rbHACDMeshData *mesh, const float v1[3], const float v2[3], const float v3[3])
+{
+	mesh->tris.push_back(HACD::Vec3<long>(mesh->verts.size(), mesh->verts.size()+1, mesh->verts.size()+2));
+	mesh->verts.push_back(HACD::Vec3<HACD::Real>(v1[0], v1[1], v1[2]));
+	mesh->verts.push_back(HACD::Vec3<HACD::Real>(v2[0], v2[1], v2[2]));
+	mesh->verts.push_back(HACD::Vec3<HACD::Real>(v3[0], v3[1], v3[2]));
+}
+
+rbCollisionShape *RB_shape_new_convex_decomp(rbHACDMeshData *mesh)
+{
+	rbCollisionShape *shape = new rbCollisionShape;
+	btCompoundShape *compound = new btCompoundShape();
+	
+	HACD::HACD hacd;
+	hacd.SetPoints(&mesh->verts[0]);
+	hacd.SetNPoints(mesh->verts.size());
+	hacd.SetTriangles(&mesh->tris[0]);
+	hacd.SetNTriangles(mesh->tris.size());
+
+	hacd.Compute();
+	
+	int num_clusters = hacd.GetNClusters();
+	
+	for (int i = 0; i < num_clusters; i++) {
+		int num_verts = hacd.GetNPointsCH(i);
+		int num_tris = hacd.GetNTrianglesCH(i);
+		HACD::Vec3<HACD::Real> verts[num_verts];
+		HACD::Vec3<long> tris[num_tris];
+		hacd.GetCH(i, verts, tris);
+		
+		btVector3 hull_verts[num_verts];
+		for (int i = 0; i < num_verts; i++) {
+			hull_verts[i].setX(verts[i].X());
+			hull_verts[i].setY(verts[i].Y());
+			hull_verts[i].setZ(verts[i].Z());
+		}
+		
+		btTransform transform;
+		transform.setIdentity();
+		btConvexHullShape *hull = new btConvexHullShape(&hull_verts[0].getX(), num_verts);
+		compound->addChildShape(transform, hull);
+	}
+	
+	shape->mesh = NULL;
+	shape->compound = compound;
+	shape->cshape = compound;
+	
+	delete mesh;
+	
+	return shape;
+}
+
 void RB_shape_add_compound_child(rbRigidBody *parent, rbCollisionShape *child, float child_pos[3], float child_orn[4])
 {
 	btCompoundShape *compound = (btCompoundShape*)parent->body->getCollisionShape();
@@ -882,7 +951,8 @@
 	}
 	if (shape->mesh)
 		delete shape->mesh;
-	delete shape->cshape;
+	if (shape->cshape != shape->compound)
+		delete shape->cshape;
 	delete shape->compound;
 	delete shape;
 }

Modified: branches/soc-2013-rigid_body_sim/source/blender/blenkernel/intern/rigidbody.c
===================================================================
--- branches/soc-2013-rigid_body_sim/source/blender/blenkernel/intern/rigidbody.c	2013-08-18 12:29:22 UTC (rev 59231)
+++ branches/soc-2013-rigid_body_sim/source/blender/blenkernel/intern/rigidbody.c	2013-08-18 12:29:24 UTC (rev 59232)
@@ -341,6 +341,79 @@
 	return shape;
 }
 
+/* create collision shape of mesh - convex decomposition
+ * returns NULL if creation fails.
+ */
+static rbCollisionShape *rigidbody_get_shape_convex_decomp_from_mesh(Object *ob)
+{
+	rbCollisionShape *shape = NULL;
+
+	if (ob->type == OB_MESH) {
+		DerivedMesh *dm = ob->derivedDeform;
+
+		MVert *mvert;
+		MFace *mface;
+		int totvert;
+		int totface;
+		int tottris = 0;
+
+		/* ensure mesh validity, then grab data */
+		BLI_assert(dm!= NULL); // RB_TODO need to make sure there's no case where deform derived mesh doesn't exist
+		DM_ensure_tessface(dm);
+
+		mvert   = (dm) ? dm->getVertArray(dm) : NULL;
+		totvert = (dm) ? dm->getNumVerts(dm) : 0;
+		mface   = (dm) ? dm->getTessFaceArray(dm) : NULL;
+		totface = (dm) ? dm->getNumTessFaces(dm) : 0;
+
+		/* sanity checking - potential case when no data will be present */
+		if ((totvert == 0) || (totface == 0)) {
+			printf("WARNING: no geometry data converted for Mesh Collision Shape (ob = %s)\n", ob->id.name + 2);
+		}
+		else {
+			rbHACDMeshData *mdata;
+			int i;
+
+			/* count triangles */
+			for (i = 0; (i < totface) && (mface); i++) {
+				(mface->v4) ? (tottris += 2) : (tottris += 1);
+			}
+
+			/* init mesh data for collision shape */
+			mdata = RB_hacd_mesh_new(tottris, totvert);
+
+			/* 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_hacd_mesh_add_triangle(mdata, va->co, vb->co, vc->co);
+				}
+
+				/* 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_hacd_mesh_add_triangle(mdata, va->co, vb->co, vc->co);
+				}
+			}
+			shape = RB_shape_new_convex_decomp(mdata);
+		}
+	}
+	else {
+		printf("ERROR: cannot make Triangular Mesh collision shape for non-Mesh object\n");
+	}
+
+	return shape;
+}
+
 /* check parent child relationships to construct compound shapes */
 static void rigidbody_prepare_compounds(RigidBodyWorld *rbw)
 {
@@ -486,6 +559,9 @@
 		case RB_SHAPE_TRIMESH:
 			new_shape = rigidbody_get_shape_trimesh_from_mesh(ob);
 			break;
+		case RB_SHAPE_APPROX:
+			new_shape = rigidbody_get_shape_convex_decomp_from_mesh(ob);
+			break;
 	}
 	/* assign new collision shape if creation was successful */
 	if (new_shape) {

Modified: branches/soc-2013-rigid_body_sim/source/blender/editors/physics/rigidbody_object.c
===================================================================
--- branches/soc-2013-rigid_body_sim/source/blender/editors/physics/rigidbody_object.c	2013-08-18 12:29:22 UTC (rev 59231)
+++ branches/soc-2013-rigid_body_sim/source/blender/editors/physics/rigidbody_object.c	2013-08-18 12:29:24 UTC (rev 59232)
@@ -535,6 +535,7 @@
 		 */
 		case RB_SHAPE_CONVEXH:
 		case RB_SHAPE_TRIMESH:
+		case RB_SHAPE_APPROX:
 			volume = size[0] * size[1] * size[2];
 			break;
 

Modified: branches/soc-2013-rigid_body_sim/source/blender/makesdna/DNA_rigidbody_types.h
===================================================================
--- branches/soc-2013-rigid_body_sim/source/blender/makesdna/DNA_rigidbody_types.h	2013-08-18 12:29:22 UTC (rev 59231)
+++ branches/soc-2013-rigid_body_sim/source/blender/makesdna/DNA_rigidbody_types.h	2013-08-18 12:29:24 UTC (rev 59232)
@@ -171,9 +171,8 @@
 	RB_SHAPE_CONVEXH,
 		/* triangulated mesh */
 	RB_SHAPE_TRIMESH,
-	
-		/* concave mesh approximated using primitives */
-	//RB_SHAPE_COMPOUND,
+		/* concave mesh approximated using convex hulls */
+	RB_SHAPE_APPROX
 } eRigidBody_Shape;
 
 /* ******************************** */

Modified: branches/soc-2013-rigid_body_sim/source/blender/makesrna/intern/rna_rigidbody.c
===================================================================
--- branches/soc-2013-rigid_body_sim/source/blender/makesrna/intern/rna_rigidbody.c	2013-08-18 12:29:22 UTC (rev 59231)
+++ branches/soc-2013-rigid_body_sim/source/blender/makesrna/intern/rna_rigidbody.c	2013-08-18 12:29:24 UTC (rev 59232)
@@ -60,6 +60,8 @@
 	                   "fewer vertices)"},
 	{RB_SHAPE_TRIMESH, "MESH", ICON_MESH_MONKEY, "Mesh",
 	                   "Mesh consisting of triangles only, allowing for more detailed interactions than convex hulls"},
+	{RB_SHAPE_APPROX, "APPROX", ICON_MESH_MONKEY, "Approx",
+	 "Approximation of the mesh using convex decomposition"},
 	{0, NULL, 0, NULL, NULL}};
 
 /* collision shapes of constraints in rigid body sim */

Modified: branches/soc-2013-rigid_body_sim/source/creator/CMakeLists.txt
===================================================================
--- branches/soc-2013-rigid_body_sim/source/creator/CMakeLists.txt	2013-08-18 12:29:22 UTC (rev 59231)
+++ branches/soc-2013-rigid_body_sim/source/creator/CMakeLists.txt	2013-08-18 12:29:24 UTC (rev 59232)
@@ -1010,6 +1010,7 @@
 
 	if(WITH_BULLET)
 		list_insert_after(BLENDER_SORTED_LIBS "bf_blenkernel" "bf_intern_rigidbody")

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list