[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [19379] trunk/blender/source/gameengine: Speedup for bullet physics mesh conversion

Campbell Barton ideasman42 at gmail.com
Mon Mar 23 07:00:22 CET 2009


Revision: 19379
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=19379
Author:   campbellbarton
Date:     2009-03-23 07:00:21 +0100 (Mon, 23 Mar 2009)

Log Message:
-----------
Speedup for bullet physics mesh conversion
Was adding each face with a remove doubles option that made conversion increasingly slower for larger meshes, this would often hang blender when starting with the BGE with larger meshes.

Replace btTriangleMesh()->addTriangle() with btTriangleIndexVertexArray()

YoFrankie level_1_home.blend starts a third faster, level_nut about twice as fast.

- previous commit was also incorrect using the original meshes vert locations rather then the vert locations that came from the derived mesh.
- Softbody is relying on removing doubles at 0.01 to give stable results, this no longer works but seems a bit dodgy anyway. Maybe some post-processing filter could fix up a mesh for bullet softbody.

Modified Paths:
--------------
    trunk/blender/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
    trunk/blender/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
    trunk/blender/source/gameengine/Physics/Bullet/CcdPhysicsController.h
    trunk/blender/source/gameengine/Rasterizer/RAS_MeshObject.h

Modified: trunk/blender/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp	2009-03-23 03:14:56 UTC (rev 19378)
+++ trunk/blender/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp	2009-03-23 06:00:21 UTC (rev 19379)
@@ -881,6 +881,9 @@
 				{
 					shapeInfo->SetMesh(meshobj, false,false);
 				}
+
+				// Note! since 2.48a bullet mesh conversion has been sped up not to remove doubles
+				// if softbody needs this there should be some post processing filter for softbody meshes.
 				if (objprop->m_softbody)
 					shapeInfo->setVertexWeldingThreshold(0.01f); //todo: expose this to the UI
 

Modified: trunk/blender/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
===================================================================
--- trunk/blender/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp	2009-03-23 03:14:56 UTC (rev 19378)
+++ trunk/blender/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp	2009-03-23 06:00:21 UTC (rev 19379)
@@ -16,6 +16,9 @@
 #include "CcdPhysicsController.h"
 #include "btBulletDynamicsCommon.h"
 #include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
+
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
+
 #include "PHY_IMotionState.h"
 #include "CcdPhysicsEnvironment.h"
 #include "RAS_MeshObject.h"
@@ -1276,150 +1279,212 @@
 
 bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bool useGimpact)
 {
+	int numpolys;
+
 	m_useGimpact = useGimpact;
 
 	// assume no shape information
 	// no support for dynamic change of shape yet
 	assert(IsUnused());
 	m_shapeType = PHY_SHAPE_NONE;
-	m_vertexArray.clear();
-	m_polygonIndexArray.clear();
 	m_meshObject = NULL;
 
-	if (!meshobj)
+	// No mesh object or mesh has no polys
+	if (!meshobj || meshobj->HasColliderPolygon()==false) {
+		m_vertexArray.clear();
+		m_polygonIndexArray.clear();
+		m_triFaceArray.clear();
 		return false;
-
-	// Mesh has no polygons!
-	int numpolys = meshobj->NumPolygons();
-	if (!numpolys)
-	{
-		return false;
 	}
 
-	// check that we have at least one colliding polygon
-	int numvalidpolys = 0;
+	numpolys = meshobj->NumPolygons();
 
-	for (int p=0; p<numpolys; p++)
-	{
-		RAS_Polygon* poly = meshobj->GetPolygon(p);
-
-		// only add polygons that have the collisionflag set
-		if (poly->IsCollider())
-		{
-			numvalidpolys++;
-			break;
-		}
-	}
-
-	// No collision polygons
-	if (numvalidpolys < 1)
-		return false;
-
 	m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH;
 
-	numvalidpolys = 0;
+	/* Convert blender geometry into bullet mesh, need these vars for mapping */
+	vector<bool> vert_tag_array(meshobj->GetMesh()->totvert, false);
+	unsigned int tot_bt_verts= 0;
+	unsigned int orig_index;
+	int i;
 
 	if (polytope)
 	{
-		Mesh *blen_mesh= meshobj->GetMesh();
-		vector<bool> vuser_array(blen_mesh->totvert, false);
-		
-		unsigned int tot_bt_verts= 0;
-		unsigned int orig_index;
-		int i;
-		
 		// Tag verts we're using
 		for (int p2=0; p2<numpolys; p2++)
 		{
 			RAS_Polygon* poly= meshobj->GetPolygon(p2);
-			
-			// only add polygons that have the collisionflag set
+
+			// only add polygons that have the collision flag set
 			if (poly->IsCollider())
 			{
-				for (i=0;i<poly->VertexCount();i++)
-				{
+				for(i=0; i<poly->VertexCount(); i++) {
 					orig_index= poly->GetVertex(i)->getOrigIndex();
-					
-					if (vuser_array[orig_index]==false)
+					if (vert_tag_array[orig_index]==false)
 					{
-						vuser_array[orig_index]= true;
+						vert_tag_array[orig_index]= true;
 						tot_bt_verts++;
 					}
 				}
 			}
 		}
-		
+
 		m_vertexArray.resize(tot_bt_verts);
-		
-		// Copy used verts directly from the meshes vert location to the bullet vector array
-		MVert *mv= blen_mesh->mvert;
+
 		btVector3 *bt= &m_vertexArray[0];
-		
-		for (i=0;i<vuser_array.size();i++, mv++)
+
+		for (int p2=0; p2<numpolys; p2++)
 		{
-			if (vuser_array[i]==true)
+			RAS_Polygon* poly= meshobj->GetPolygon(p2);
+
+			// only add polygons that have the collisionflag set
+			if (poly->IsCollider())
 			{
-				bt->setX( mv->co[0] );
-				bt->setY( mv->co[1] );
-				bt->setZ( mv->co[2] );
-				bt++;
+				for(i=0; i<poly->VertexCount(); i++) {
+					RAS_TexVert *v= poly->GetVertex(i);
+					orig_index= v->getOrigIndex();
+
+					if (vert_tag_array[orig_index]==true)
+					{
+						const float* vtx = v->getXYZ();
+						vert_tag_array[orig_index]= false;
+
+						bt->setX(vtx[0]);  bt->setY(vtx[1]);  bt->setZ(vtx[2]);
+						bt++;
+					}
+				}
 			}
 		}
-		numvalidpolys++;
 	}
 	else {
+		unsigned int tot_bt_tris= 0;
+		vector<int> vert_remap_array(meshobj->GetMesh()->totvert, 0);
+		
+		// Tag verts we're using
 		for (int p2=0; p2<numpolys; p2++)
 		{
-			RAS_Polygon* poly = meshobj->GetPolygon(p2);
+			RAS_Polygon* poly= meshobj->GetPolygon(p2);
 
+			// only add polygons that have the collision flag set
+			if (poly->IsCollider())
+			{
+				for(i=0; i<poly->VertexCount(); i++) {
+					orig_index= poly->GetVertex(i)->getOrigIndex();
+					if (vert_tag_array[orig_index]==false)
+					{
+						vert_tag_array[orig_index]= true;
+						vert_remap_array[orig_index]= tot_bt_verts;
+						tot_bt_verts++;
+					}
+				}
+
+				tot_bt_tris += (i==4 ? 2:1); /* a quad or a tri */
+			}
+		}
+
+		m_vertexArray.resize(tot_bt_verts);
+		m_polygonIndexArray.resize(tot_bt_tris);
+		m_triFaceArray.resize(tot_bt_tris*3);
+
+		btVector3 *bt= &m_vertexArray[0];
+		int *poly_index_pt= &m_polygonIndexArray[0];
+		int *tri_pt= &m_triFaceArray[0];
+
+
+		for (int p2=0; p2<numpolys; p2++)
+		{
+			RAS_Polygon* poly= meshobj->GetPolygon(p2);
+
 			// only add polygons that have the collisionflag set
 			if (poly->IsCollider())
-			{   
-				//Bullet can raycast any shape, so
-			
-				{
-					const float* vtx = poly->GetVertex(2)->getXYZ();
-					btVector3 vertex0(vtx[0],vtx[1],vtx[2]);
+			{
+				RAS_TexVert *v1= poly->GetVertex(0);
+				RAS_TexVert *v2= poly->GetVertex(1);
+				RAS_TexVert *v3= poly->GetVertex(2);
+				int i1= v1->getOrigIndex();
+				int i2= v2->getOrigIndex();
+				int i3= v3->getOrigIndex();
+				const float* vtx;
 
-					vtx = poly->GetVertex(1)->getXYZ();
-					btVector3 vertex1(vtx[0],vtx[1],vtx[2]);
+				// the face indicies
+				tri_pt[0]= vert_remap_array[i1];
+				tri_pt[1]= vert_remap_array[i2];
+				tri_pt[2]= vert_remap_array[i3];
+				tri_pt= tri_pt+3;
 
-					vtx = poly->GetVertex(0)->getXYZ();
-					btVector3 vertex2(vtx[0],vtx[1],vtx[2]);
+				// m_polygonIndexArray
+				*poly_index_pt= p2;
+				poly_index_pt++;
 
-					m_vertexArray.push_back(vertex0);
-					m_vertexArray.push_back(vertex1);
-					m_vertexArray.push_back(vertex2);
-					m_polygonIndexArray.push_back(p2);
-					numvalidpolys++;
+				// the vertex location
+				if (vert_tag_array[i1]==true) { /* *** v1 *** */
+					vert_tag_array[i1]= false;
+					vtx = v1->getXYZ();
+					bt->setX(vtx[0]);	bt->setY( vtx[1]);	bt->setZ(vtx[2]);
+					bt++;
 				}
-				if (poly->VertexCount() == 4)
+				if (vert_tag_array[i2]==true) { /* *** v2 *** */
+					vert_tag_array[i2]= false;
+					vtx = v2->getXYZ();
+					bt->setX(vtx[0]);	bt->setY(vtx[1]);	bt->setZ(vtx[2]);
+					bt++;
+				}
+				if (vert_tag_array[i3]==true) { /* *** v3 *** */
+					vert_tag_array[i3]= false;
+					vtx = v3->getXYZ();
+					bt->setX(vtx[0]);	bt->setY(vtx[1]);	bt->setZ(vtx[2]);
+					bt++;
+				}
+
+				if (poly->VertexCount()==4)
 				{
-					const float* vtx = poly->GetVertex(3)->getXYZ();
-					btVector3 vertex0(vtx[0],vtx[1],vtx[2]);
+					RAS_TexVert *v4= poly->GetVertex(3);
+					int i4= v4->getOrigIndex();
 
-					vtx = poly->GetVertex(2)->getXYZ();
-					btVector3 vertex1(vtx[0],vtx[1],vtx[2]);
+					tri_pt[0]= vert_remap_array[i1];
+					tri_pt[1]= vert_remap_array[i3];
+					tri_pt[2]= vert_remap_array[i4];
+					tri_pt= tri_pt+3;
 
-					vtx = poly->GetVertex(0)->getXYZ();
-					btVector3 vertex2(vtx[0],vtx[1],vtx[2]);
+					// m_polygonIndexArray
+					*poly_index_pt= p2;
+					poly_index_pt++;
 
-					m_vertexArray.push_back(vertex0);
-					m_vertexArray.push_back(vertex1);
-					m_vertexArray.push_back(vertex2);
-					m_polygonIndexArray.push_back(p2);
-					numvalidpolys++;
+					// the vertex location
+					if (vert_tag_array[i4]==true) { /* *** v4 *** */
+						vert_tag_array[i4]= false;
+						vtx = v4->getXYZ();
+						bt->setX(vtx[0]);	bt->setY(vtx[1]);	bt->setZ(vtx[2]);
+						bt++;
+					}
 				}
 			}
 		}
+
+
+		/* If this ever gets confusing, print out an OBJ file for debugging */
+#if 0
+		printf("# vert count %d\n", m_vertexArray.size());
+		for(i=0; i<m_vertexArray.size(); i+=1) {
+			printf("v %.6f %.6f %.6f\n", m_vertexArray[i].x(), m_vertexArray[i].y(), m_vertexArray[i].z());
+		}
+
+		printf("# face count %d\n", m_triFaceArray.size());
+		for(i=0; i<m_triFaceArray.size(); i+=3) {
+			printf("f %d %d %d\n", m_triFaceArray[i]+1, m_triFaceArray[i+1]+1, m_triFaceArray[i+2]+1);
+		}
+#endif
+
 	}
 
-	if (!numvalidpolys)
+#if 0
+	if (validpolys==false)
 	{
 		// should not happen
 		m_shapeType = PHY_SHAPE_NONE;
 		return false;
 	}
+#endif
+	
 	m_meshObject = meshobj;
 	if (!polytope)
 	{
@@ -1444,7 +1509,6 @@
 {
 	btCollisionShape* collisionShape = 0;
 	btTriangleMeshShape* concaveShape = 0;
-	btTriangleMesh* collisionMeshData = 0;
 	btCompoundShape* compoundShape = 0;
 	CcdShapeConstructionInfo* nextShapeInfo;
 
@@ -1485,19 +1549,18 @@
 		// One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1
 		// and btScaledBvhTriangleMeshShape otherwise.
 		if (m_useGimpact)
-		{
-				collisionMeshData = new btTriangleMesh();
+		{				
+				btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray(
+						m_polygonIndexArray.size(),
+						&m_triFaceArray[0],
+						3*sizeof(int),
+						m_vertexArray.size(),
+						(btScalar*) &m_vertexArray[0].x(),
+						sizeof(btVector3)
+				);
 				
-				bool removeDuplicateVertices=true;
+				btGImpactMeshShape* gimpactShape =  new btGImpactMeshShape(indexVertexArrays);
 
-				// m_vertexArray is necessarily a multiple of 3
-				for (int i=0;i<m_vertexArray.size(); i+=3 )
-				{
-					collisionMeshData->addTriangle(m_vertexArray[i+2],m_vertexArray[i+1],m_vertexArray[i],removeDuplicateVertices);
-				}
-				
-				btGImpactMeshShape* gimpactShape =  new btGImpactMeshShape(collisionMeshData);
-
 				collisionShape = gimpactShape;
 				gimpactShape->updateBound();
 
@@ -1505,17 +1568,18 @@
 		{
 			if (!m_unscaledShape)

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list