diff options
author | Erwin Coumans <blender@erwincoumans.com> | 2008-09-26 06:27:59 +0400 |
---|---|---|
committer | Erwin Coumans <blender@erwincoumans.com> | 2008-09-26 06:27:59 +0400 |
commit | a1bef84ea859cf85487d4cac8664402dd86f4465 (patch) | |
tree | aab43249487d338e39e9df721a5675536ffb65ff /source | |
parent | 6732718ef1b7f212e2368cf237c08d72f13d06ab (diff) |
Allow Bullet soft bodies to be created using a AddObject actuator. Added a fake world coordinate system to game soft bodies, although the vertices are already in world space.
Added Bullet/Gimpact concave collision detection to Blender. If your build system isn't updated yet, please add extern/bullet2/src/BulletCollision/Gimpact/*
This allows moving/dynamic concave triangle meshes (decomposing meshes into compound convex shapes, and using 'compound' shapes is still preferred)
Diffstat (limited to 'source')
12 files changed, 120 insertions, 45 deletions
diff --git a/source/gameengine/Converter/BL_DeformableGameObject.cpp b/source/gameengine/Converter/BL_DeformableGameObject.cpp index 1d62a41cce9..e2610d2b405 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.cpp +++ b/source/gameengine/Converter/BL_DeformableGameObject.cpp @@ -47,7 +47,7 @@ void BL_DeformableGameObject::ProcessReplica(KX_GameObject* replica) KX_GameObject::ProcessReplica(replica); if (m_pDeformer) { - deformer = (BL_MeshDeformer*)m_pDeformer->GetReplica(); + deformer = (BL_MeshDeformer*)m_pDeformer->GetReplica(replica); ((BL_DeformableGameObject*)replica)->m_pDeformer = deformer; } diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h index 9d3d2e78123..8de59c1cdf3 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.h +++ b/source/gameengine/Converter/BL_MeshDeformer.h @@ -64,7 +64,7 @@ public: virtual void SetSimulatedTime(double time){}; virtual bool Apply(class RAS_IPolyMaterial *mat); virtual bool Update(void){ return false; }; - virtual RAS_Deformer* GetReplica(){return NULL;}; + virtual RAS_Deformer* GetReplica(class KX_GameObject* replica){return NULL;}; struct Mesh* GetMesh() { return m_bmesh; }; // virtual void InitDeform(double time){}; diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index dfd33e45fef..fc6498579ad 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -68,7 +68,7 @@ BL_ShapeDeformer::~BL_ShapeDeformer() { }; -RAS_Deformer *BL_ShapeDeformer::GetReplica() +RAS_Deformer *BL_ShapeDeformer::GetReplica(class KX_GameObject* replica) { BL_ShapeDeformer *result; diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h index 1465bb01e22..90b9f5caea1 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.h +++ b/source/gameengine/Converter/BL_ShapeDeformer.h @@ -66,7 +66,7 @@ public: }; virtual void ProcessReplica(); - virtual RAS_Deformer *GetReplica(); + virtual RAS_Deformer *GetReplica(class KX_GameObject* replica); virtual ~BL_ShapeDeformer(); bool Update (void); diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index b7b39ad7fbf..d8563763954 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -146,7 +146,7 @@ bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) return true; } -RAS_Deformer *BL_SkinDeformer::GetReplica() +RAS_Deformer *BL_SkinDeformer::GetReplica(class KX_GameObject* replica) { BL_SkinDeformer *result; diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index e08de8c478a..f87860021c6 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -67,7 +67,7 @@ public: BL_ArmatureObject* arma = NULL); virtual void ProcessReplica(); - virtual RAS_Deformer *GetReplica(); + virtual RAS_Deformer *GetReplica(class KX_GameObject* replica); virtual ~BL_SkinDeformer(); bool Update (void); bool Apply (class RAS_IPolyMaterial *polymat); diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 7e684e5d5b7..ddf1f402431 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -670,15 +670,12 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, class KX_SoftBodyDeformer : public RAS_Deformer { - btSoftBody* m_softBody; class RAS_MeshObject* m_pMeshObject; class KX_GameObject* m_gameobj; - public: - KX_SoftBodyDeformer(btSoftBody* softBody,RAS_MeshObject* pMeshObject,KX_GameObject* gameobj) - : m_softBody(softBody), - m_pMeshObject(pMeshObject), + KX_SoftBodyDeformer(RAS_MeshObject* pMeshObject,KX_GameObject* gameobj) + :m_pMeshObject(pMeshObject), m_gameobj(gameobj) { //printf("KX_SoftBodyDeformer\n"); @@ -694,6 +691,14 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, } virtual bool Apply(class RAS_IPolyMaterial *polymat) { + KX_BulletPhysicsController* ctrl = (KX_BulletPhysicsController*) m_gameobj->GetPhysicsController(); + if (!ctrl) + return false; + + btSoftBody* softBody= ctrl->GetSoftBody(); + if (!softBody) + return false; + //printf("apply\n"); RAS_MeshSlot::iterator it; RAS_MeshMaterial *mmat; @@ -718,11 +723,12 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, // for each array for(slot->begin(it); !slot->end(it); slot->next(it)) { - btSoftBody::tNodeArray& nodes(m_softBody->m_nodes); + btSoftBody::tNodeArray& nodes(softBody->m_nodes); int index = 0; for(i=it.startvertex; i<it.endvertex; i++,index++) { RAS_TexVert& v = it.vertex[i]; + btAssert(v.getSoftBodyIndex() >= 0); MT_Point3 pt ( nodes[v.getSoftBodyIndex()].m_x.getX(), @@ -745,10 +751,10 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, //printf("update\n"); return true;//?? } - virtual RAS_Deformer *GetReplica() + virtual RAS_Deformer *GetReplica(class KX_GameObject* replica) { - //printf("getReplica\n"); - return 0; + KX_SoftBodyDeformer* deformer = new KX_SoftBodyDeformer(replica->GetMesh(0),replica); + return deformer; } virtual bool SkipVertexTransform() @@ -855,12 +861,13 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, } case KX_BOUNDPOLYTOPE: { - shapeInfo->SetMesh(meshobj, true); + shapeInfo->SetMesh(meshobj, true,false); bm = shapeInfo->CreateBulletShape(); break; } case KX_BOUNDMESH: { + if (!ci.m_mass ||objprop->m_softbody) { // mesh shapes can be shared, check first if we already have a shape on that mesh @@ -872,11 +879,15 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, shapeInfo->AddRef(); } else { - shapeInfo->SetMesh(meshobj, false); + shapeInfo->SetMesh(meshobj, false,false); } bm = shapeInfo->CreateBulletShape(); //no moving concave meshes, so don't bother calculating inertia //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor); + } else + { + shapeInfo->SetMesh(meshobj, false,true); + bm = shapeInfo->CreateBulletShape(); } break; @@ -1097,7 +1108,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, if (softBody && gameobj->GetMesh(0))//only the first mesh, if any { //should be a mesh then, so add a soft body deformer - KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer(softBody, gameobj->GetMesh(0),gameobj); + KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer( gameobj->GetMesh(0),gameobj); gameobj->SetDeformer(softbodyDeformer); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 29ee0310c58..d552cb3dc9e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -23,6 +23,8 @@ subject to the following restrictions: #include "BulletSoftBody//btSoftBodyInternals.h" #include "BulletSoftBody/btSoftBodyHelpers.h" #include "LinearMath/btConvexHull.h" +#include "BulletCollision/Gimpact/btGImpactShape.h" + #include "BulletSoftBody/btSoftRigidDynamicsWorld.h" @@ -46,10 +48,13 @@ btVector3 startVel(0,0,0);//-10000); CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) :m_cci(ci) { + m_prototypeTransformInitialized = false; + m_softbodyMappingDone = false; m_collisionDelay = 0; m_newClientInfo = 0; m_registerCount = 0; - + m_softBodyTransformInitialized = false; + // copy pointers locally to allow smart release m_MotionState = ci.m_MotionState; m_collisionShape = ci.m_collisionShape; @@ -144,7 +149,7 @@ btSoftBody* CcdPhysicsController::GetSoftBody() void CcdPhysicsController::CreateRigidbody() { - btTransform trans = GetTransformFromMotionState(m_MotionState); + //btTransform trans = GetTransformFromMotionState(m_MotionState); m_bulletMotionState = new BlenderBulletMotionState(m_MotionState); ///either create a btCollisionObject, btRigidBody or btSoftBody @@ -189,18 +194,12 @@ void CcdPhysicsController::CreateRigidbody() if (m_cci.m_collisionShape->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE) { btConvexHullShape* convexHull = (btConvexHullShape* )m_cci.m_collisionShape; - btAlignedObjectArray<btVector3> transformedVertices; - transformedVertices.resize(convexHull->getNumPoints()); - for (int i=0;i<convexHull->getNumPoints();i++) - { - transformedVertices[i] = trans(convexHull->getPoints()[i]); - } //psb = btSoftBodyHelpers::CreateFromConvexHull(sbi,&transformedVertices[0],convexHull->getNumPoints()); { int nvertices = convexHull->getNumPoints(); - const btVector3* vertices = &transformedVertices[0]; + const btVector3* vertices = convexHull->getPoints(); btSoftBodyWorldInfo& worldInfo = softDynaWorld->getWorldInfo(); HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); @@ -226,7 +225,7 @@ void CcdPhysicsController::CreateRigidbody() { RAS_MeshObject* rasMesh= GetShapeInfo()->GetMesh(); - if (rasMesh) + if (rasMesh && !m_softbodyMappingDone) { //printf("apply\n"); @@ -251,17 +250,20 @@ void CcdPhysicsController::CreateRigidbody() for(i=it.startvertex; i<it.endvertex; i++,index++) { RAS_TexVert* vertex = &it.vertex[i]; + + //search closest index, and store it in vertex vertex->setSoftBodyIndex(0); btScalar maxDistSqr = 1e30; btSoftBody::tNodeArray& nodes(psb->m_nodes); - btVector3 xyz = trans(btVector3(vertex->getXYZ()[0],vertex->getXYZ()[1],vertex->getXYZ()[2])); + btVector3 xyz = btVector3(vertex->getXYZ()[0],vertex->getXYZ()[1],vertex->getXYZ()[2]); for (int n=0;n<nodes.size();n++) { btScalar distSqr = (nodes[n].m_x - xyz).length2(); if (distSqr<maxDistSqr) { maxDistSqr = distSqr; + vertex->setSoftBodyIndex(n); } } @@ -330,6 +332,7 @@ void CcdPhysicsController::CreateRigidbody() } + m_softbodyMappingDone = true; m_object = psb; @@ -408,6 +411,13 @@ void CcdPhysicsController::CreateRigidbody() m_MotionState->setWorldPosition(startTrans.getOrigin().getX(),startTrans.getOrigin().getY(),startTrans.getOrigin().getZ()); m_MotionState->setWorldOrientation(0,0,0,1); + if (!m_prototypeTransformInitialized) + { + m_prototypeTransformInitialized = true; + m_softBodyTransformInitialized = true; + GetSoftBody()->transform(startTrans); + } + // btVector3 wp = m_softBody->getWorldTransform().getOrigin(); // MT_Point3 center(wp.getX(),wp.getY(),wp.getZ()); // m_gameobj->NodeSetWorldPosition(center); @@ -572,6 +582,7 @@ void CcdPhysicsController::WriteDynamicsToMotionState() // controller replication void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl) { + m_softBodyTransformInitialized=false; m_MotionState = motionstate; m_registerCount = 0; m_collisionShape = NULL; @@ -652,7 +663,7 @@ void CcdPhysicsController::SetCenterOfMassTransform(btTransform& xform) //either collision object or soft body? if (GetSoftBody()) { - //not yet + } else { @@ -761,6 +772,9 @@ void CcdPhysicsController::setOrientation(float quatImag0,float quatImag1,float SetCenterOfMassTransform(xform); // not required //m_bulletMotionState->setWorldTransform(xform); + + + } } @@ -781,6 +795,15 @@ void CcdPhysicsController::setWorldOrientation(const btMatrix3x3& orn) SetCenterOfMassTransform(xform); // not required //m_bulletMotionState->setWorldTransform(xform); + //only once! + if (!m_softBodyTransformInitialized && GetSoftBody()) + { + m_softbodyStartTrans.setBasis(orn); + xform.setOrigin(m_softbodyStartTrans.getOrigin()); + GetSoftBody()->transform(xform); + m_softBodyTransformInitialized = true; + } + } } @@ -799,6 +822,8 @@ void CcdPhysicsController::setPosition(float posX,float posY,float posZ) btTransform xform = m_object->getWorldTransform(); xform.setOrigin(btVector3(posX,posY,posZ)); SetCenterOfMassTransform(xform); + if (!m_softBodyTransformInitialized) + m_softbodyStartTrans.setOrigin(xform.getOrigin()); // not required //m_bulletMotionState->setWorldTransform(xform); } @@ -931,6 +956,15 @@ void CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,floa m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } + btSoftBody* soft = GetSoftBody(); + if (soft) + { + if (local) + { + linVel = m_softbodyStartTrans.getBasis()*linVel; + } + soft->setVelocity(linVel); + } else { btTransform xform = m_object->getWorldTransform(); if (local) @@ -940,7 +974,6 @@ void CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,floa btRigidBody* body = GetRigidBody(); if (body) body->setLinearVelocity(linVel); - } } } @@ -1186,8 +1219,10 @@ CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mes return NULL; } -bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) +bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bool useGimpact) { + m_useGimpact = useGimpact; + // assume no shape information // no support for dynamic change of shape yet assert(m_meshObject == NULL); @@ -1353,19 +1388,35 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() // 9 multiplications/additions and one function call for each triangle that passes the mid phase filtering // One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1 // and btScaledBvhTriangleMeshShape otherwise. - if (!m_unscaledShape) + if (m_useGimpact) { - collisionMeshData = new btTriangleMesh(); - // m_vertexArray is necessarily a multiple of 3 - for (std::vector<btPoint3>::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) + collisionMeshData = new btTriangleMesh(); + // m_vertexArray is necessarily a multiple of 3 + for (std::vector<btPoint3>::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) + { + collisionMeshData->addTriangle(*it++,*it++,*it++); + } + btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(collisionMeshData); + + collisionShape = gimpactShape; + gimpactShape->updateBound(); + + } else + { + if (!m_unscaledShape) { - collisionMeshData->addTriangle(*it++,*it++,*it++); + collisionMeshData = new btTriangleMesh(); + // m_vertexArray is necessarily a multiple of 3 + for (std::vector<btPoint3>::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) + { + collisionMeshData->addTriangle(*it++,*it++,*it++); + } + // this shape will be shared and not deleted until shapeInfo is deleted + m_unscaledShape = new btBvhTriangleMeshShape( collisionMeshData, true ); + m_unscaledShape->recalcLocalAabb(); } - // this shape will be shared and not deleted until shapeInfo is deleted - m_unscaledShape = new btBvhTriangleMeshShape( collisionMeshData, true ); - m_unscaledShape->recalcLocalAabb(); + collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f)); } - collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f)); break; case PHY_SHAPE_COMPOUND: diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 65c23eb2543..5d35482dd46 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -53,7 +53,8 @@ public: m_childScale(1.0f,1.0f,1.0f), m_refCount(1), m_meshObject(NULL), - m_unscaledShape(NULL) + m_unscaledShape(NULL), + m_useGimpact(false) { m_childTrans.setIdentity(); } @@ -88,7 +89,7 @@ public: return m_shapeArray.at(i); } - bool SetMesh(RAS_MeshObject* mesh, bool polytope); + bool SetMesh(RAS_MeshObject* mesh, bool polytope,bool useGimpact); RAS_MeshObject* GetMesh(void) { return m_meshObject; @@ -118,6 +119,7 @@ protected: btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape, // the actual shape is of type btScaledBvhTriangleMeshShape std::vector<CcdShapeConstructionInfo*> m_shapeArray; // for compound shapes + bool m_useGimpact; }; struct CcdConstructionInfo @@ -211,6 +213,7 @@ class CcdPhysicsController : public PHY_IPhysicsController { btCollisionObject* m_object; + class PHY_IMotionState* m_MotionState; btMotionState* m_bulletMotionState; @@ -219,6 +222,12 @@ class CcdPhysicsController : public PHY_IPhysicsController friend class CcdPhysicsEnvironment; // needed when updating the controller + //some book keeping for replication + bool m_softbodyMappingDone; + bool m_softBodyTransformInitialized; + bool m_prototypeTransformInitialized; + btTransform m_softbodyStartTrans; + void* m_newClientInfo; int m_registerCount; // needed when multiple sensors use the same controller diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 8c5aae3f8c9..3593aecf3d5 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -25,6 +25,7 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" #include "BulletSoftBody/btSoftRigidDynamicsWorld.h" #include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h" +#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h" //profiling/timings #include "LinearMath/btQuickprof.h" @@ -338,7 +339,9 @@ m_filterCallback(NULL) if (!dispatcher) { - dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + btCollisionDispatcher* disp = new btCollisionDispatcher(m_collisionConfiguration); + dispatcher = disp; + btGImpactCollisionAlgorithm::registerAlgorithm(disp); m_ownDispatcher = dispatcher; } diff --git a/source/gameengine/Rasterizer/RAS_Deformer.h b/source/gameengine/Rasterizer/RAS_Deformer.h index 6665e1926cf..3332ac4c0a7 100644 --- a/source/gameengine/Rasterizer/RAS_Deformer.h +++ b/source/gameengine/Rasterizer/RAS_Deformer.h @@ -44,7 +44,7 @@ public: virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map)=0; virtual bool Apply(class RAS_IPolyMaterial *polymat)=0; virtual bool Update(void)=0; - virtual RAS_Deformer *GetReplica()=0; + virtual RAS_Deformer *GetReplica(class KX_GameObject* replica)=0; virtual bool SkipVertexTransform() { return false; diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index d6f1fe912be..b92965ed1cc 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -47,6 +47,7 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, m_flag = (flat)? FLAT: 0; m_origindex = origindex; m_unit = 2; + m_softBodyIndex = -1; } const MT_Point3& RAS_TexVert::xyz() |