diff options
Diffstat (limited to 'source/gameengine/Physics/Bullet/CcdPhysicsController.cpp')
-rw-r--r-- | source/gameengine/Physics/Bullet/CcdPhysicsController.cpp | 338 |
1 files changed, 241 insertions, 97 deletions
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index eecdea55349..0b9da8f46d3 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -16,6 +16,9 @@ subject to the following restrictions: #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" @@ -24,10 +27,14 @@ subject to the following restrictions: #include "BulletSoftBody/btSoftBodyHelpers.h" #include "LinearMath/btConvexHull.h" #include "BulletCollision/Gimpact/btGImpactShape.h" +#include "BulletCollision/Gimpact/btGImpactShape.h" #include "BulletSoftBody/btSoftRigidDynamicsWorld.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + class BP_Proxy; ///todo: fill all the empty CcdPhysicsController methods, hook them up to the btRigidBody class @@ -577,7 +584,19 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time) if (body && !body->isStaticObject()) { - + + if ((m_cci.m_clamp_vel_max>0.0) || (m_cci.m_clamp_vel_min>0.0)) + { + const btVector3& linvel = body->getLinearVelocity(); + float len= linvel.length(); + + if((m_cci.m_clamp_vel_max>0.0) && (len > m_cci.m_clamp_vel_max)) + body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_max / len)); + + else if ((m_cci.m_clamp_vel_min>0.0) && btFuzzyZero(len)==0 && (len < m_cci.m_clamp_vel_min)) + body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len)); + } + const btVector3& worldPos = body->getCenterOfMassPosition(); m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]); @@ -1238,6 +1257,22 @@ void DefaultMotionState::getWorldOrientation(float& quatIma0,float& quatIma1,flo quatReal = m_worldTransform.getRotation()[3]; } +void DefaultMotionState::getWorldOrientation(float* ori) +{ + *ori++ = m_worldTransform.getBasis()[0].x(); + *ori++ = m_worldTransform.getBasis()[1].x(); + *ori++ = m_worldTransform.getBasis()[1].x(); + *ori++ = 0.f; + *ori++ = m_worldTransform.getBasis()[0].y(); + *ori++ = m_worldTransform.getBasis()[1].y(); + *ori++ = m_worldTransform.getBasis()[1].y(); + *ori++ = 0.f; + *ori++ = m_worldTransform.getBasis()[0].z(); + *ori++ = m_worldTransform.getBasis()[1].z(); + *ori++ = m_worldTransform.getBasis()[1].z(); + *ori++ = 0.f; +} + void DefaultMotionState::setWorldPosition(float posX,float posY,float posZ) { btVector3 pos(posX,posY,posZ); @@ -1272,123 +1307,212 @@ CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mes 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) - return false; - - // Mesh has no polygons! - int numpolys = meshobj->NumPolygons(); - if (!numpolys) - { + // No mesh object or mesh has no polys + if (!meshobj || meshobj->HasColliderPolygon()==false) { + m_vertexArray.clear(); + m_polygonIndexArray.clear(); + m_triFaceArray.clear(); 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); + m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH; - // only add polygons that have the collisionflag set - if (poly->IsCollider()) + /* 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) + { + // Tag verts we're using + for (int p2=0; p2<numpolys; p2++) { - numvalidpolys++; - break; - } - } + RAS_Polygon* poly= meshobj->GetPolygon(p2); - // No collision polygons - if (numvalidpolys < 1) - return false; + // 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; + tot_bt_verts++; + } + } + } + } - m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH; + m_vertexArray.resize(tot_bt_verts); - numvalidpolys = 0; + btVector3 *bt= &m_vertexArray[0]; - for (int p2=0; p2<numpolys; p2++) - { - RAS_Polygon* poly = meshobj->GetPolygon(p2); + 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 - if (polytope) + // only add polygons that have the collisionflag set + if (poly->IsCollider()) { - for (int i=0;i<poly->VertexCount();i++) - { - const float* vtx = poly->GetVertex(i)->getXYZ(); - btVector3 point(vtx[0],vtx[1],vtx[2]); - //avoid duplicates (could better directly use vertex offsets, rather than a vertex compare) - bool found = false; - for (int j=0;j<m_vertexArray.size();j++) + for(i=0; i<poly->VertexCount(); i++) { + RAS_TexVert *v= poly->GetVertex(i); + orig_index= v->getOrigIndex(); + + if (vert_tag_array[orig_index]==true) { - if (m_vertexArray[j]==point) - { - found = true; - break; - } - } - if (!found) - m_vertexArray.push_back(point); + const float* vtx = v->getXYZ(); + vert_tag_array[orig_index]= false; - numvalidpolys++; + bt->setX(vtx[0]); bt->setY(vtx[1]); bt->setZ(vtx[2]); + bt++; + } } - } else + } + } + } + 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); + + // only add polygons that have the collision flag set + if (poly->IsCollider()) { - { - const float* vtx = poly->GetVertex(2)->getXYZ(); - btVector3 vertex0(vtx[0],vtx[1],vtx[2]); + 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 */ + } + } - vtx = poly->GetVertex(1)->getXYZ(); - btVector3 vertex1(vtx[0],vtx[1],vtx[2]); + m_vertexArray.resize(tot_bt_verts); + m_polygonIndexArray.resize(tot_bt_tris); + m_triFaceArray.resize(tot_bt_tris*3); - vtx = poly->GetVertex(0)->getXYZ(); - btVector3 vertex2(vtx[0],vtx[1],vtx[2]); + btVector3 *bt= &m_vertexArray[0]; + int *poly_index_pt= &m_polygonIndexArray[0]; + int *tri_pt= &m_triFaceArray[0]; - m_vertexArray.push_back(vertex0); - m_vertexArray.push_back(vertex1); - m_vertexArray.push_back(vertex2); - m_polygonIndexArray.push_back(p2); - numvalidpolys++; + + for (int p2=0; p2<numpolys; p2++) + { + RAS_Polygon* poly= meshobj->GetPolygon(p2); + + // only add polygons that have the collisionflag set + if (poly->IsCollider()) + { + 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; + + // 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; + + // m_polygonIndexArray + *poly_index_pt= p2; + poly_index_pt++; + + // 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 (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 (poly->VertexCount() == 4) + 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(); + + 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; + + // m_polygonIndexArray + *poly_index_pt= p2; + poly_index_pt++; + + // 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++; + } + } + } + } - vtx = poly->GetVertex(2)->getXYZ(); - btVector3 vertex1(vtx[0],vtx[1],vtx[2]); - vtx = poly->GetVertex(0)->getXYZ(); - btVector3 vertex2(vtx[0],vtx[1],vtx[2]); + /* 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()); + } - m_vertexArray.push_back(vertex0); - m_vertexArray.push_back(vertex1); - m_vertexArray.push_back(vertex2); - m_polygonIndexArray.push_back(p2); - numvalidpolys++; - } - } + 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) { @@ -1413,7 +1537,6 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() { btCollisionShape* collisionShape = 0; btTriangleMeshShape* concaveShape = 0; - btTriangleMesh* collisionMeshData = 0; btCompoundShape* compoundShape = 0; CcdShapeConstructionInfo* nextShapeInfo; @@ -1454,18 +1577,17 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() // 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(); - - bool removeDuplicateVertices=true; - - // 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); - } + { + btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray( + m_polygonIndexArray.size(), + &m_triFaceArray[0], + 3*sizeof(int), + m_vertexArray.size(), + (btScalar*) &m_vertexArray[0].x(), + sizeof(btVector3) + ); - btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(collisionMeshData); + btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(indexVertexArrays); collisionShape = gimpactShape; gimpactShape->updateBound(); @@ -1474,17 +1596,39 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() { if (!m_unscaledShape) { - collisionMeshData = new btTriangleMesh(true,false); - collisionMeshData->m_weldingThreshold = m_weldingThreshold; + + btTriangleIndexVertexArray* indexVertexArrays = 0; - bool removeDuplicateVertices=true; - // m_vertexArray is necessarily a multiple of 3 - for (int i=0;i<m_vertexArray.size(); i+=3 ) + ///enable welding, only for the objects that need it (such as soft bodies) + if (0.f != m_weldingThreshold1) { - collisionMeshData->addTriangle(m_vertexArray[i+2],m_vertexArray[i+1],m_vertexArray[i],removeDuplicateVertices); + btTriangleMesh* collisionMeshData = new btTriangleMesh(true,false); + collisionMeshData->m_weldingThreshold = m_weldingThreshold1; + bool removeDuplicateVertices=true; + // m_vertexArray not in multiple of 3 anymore, use m_triFaceArray + for(int i=0; i<m_triFaceArray.size(); i+=3) { + collisionMeshData->addTriangle( + m_vertexArray[m_triFaceArray[i]], + m_vertexArray[m_triFaceArray[i+1]], + m_vertexArray[m_triFaceArray[i+2]], + removeDuplicateVertices + ); + } + indexVertexArrays = collisionMeshData; + + } else + { + indexVertexArrays = new btTriangleIndexVertexArray( + m_polygonIndexArray.size(), + &m_triFaceArray[0], + 3*sizeof(int), + m_vertexArray.size(), + (btScalar*) &m_vertexArray[0].x(), + sizeof(btVector3)); } + // this shape will be shared and not deleted until shapeInfo is deleted - m_unscaledShape = new btBvhTriangleMeshShape( collisionMeshData, true ); + m_unscaledShape = new btBvhTriangleMeshShape( indexVertexArrays, true ); m_unscaledShape->recalcLocalAabb(); } collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f)); |