[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