diff options
Diffstat (limited to 'source/gameengine/Physics/Bullet/CcdPhysicsController.cpp')
-rw-r--r-- | source/gameengine/Physics/Bullet/CcdPhysicsController.cpp | 2668 |
1 files changed, 0 insertions, 2668 deletions
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp deleted file mode 100644 index b3cee944880..00000000000 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ /dev/null @@ -1,2668 +0,0 @@ -/** \file gameengine/Physics/Bullet/CcdPhysicsController.cpp - * \ingroup physbullet - */ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef WIN32 -#include <stdint.h> -#endif - -#include "CcdPhysicsController.h" -#include "btBulletDynamicsCommon.h" -#include "BulletCollision/CollisionDispatch/btGhostObject.h" -#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" -#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" - -#include "PHY_IMotionState.h" -#include "CcdPhysicsEnvironment.h" -#include "RAS_MeshObject.h" -#include "RAS_Polygon.h" -#include "RAS_Deformer.h" -#include "KX_GameObject.h" - -#include "BulletSoftBody/btSoftBody.h" -#include "BulletSoftBody/btSoftBodyInternals.h" -#include "BulletSoftBody/btSoftBodyHelpers.h" -#include "LinearMath/btConvexHull.h" -#include "BulletCollision/Gimpact/btGImpactShape.h" - -#include "BulletSoftBody/btSoftRigidDynamicsWorld.h" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" - -extern "C"{ - #include "BLI_utildefines.h" - #include "BKE_cdderivedmesh.h" -} - - -class BP_Proxy; - -///todo: fill all the empty CcdPhysicsController methods, hook them up to the btRigidBody class - -//'temporarily' global variables -//float gDeactivationTime = 2.f; -//bool gDisableDeactivation = false; -extern float gDeactivationTime; -extern bool gDisableDeactivation; - - -float gLinearSleepingTreshold; -float gAngularSleepingTreshold; - -BlenderBulletCharacterController::BlenderBulletCharacterController(btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape* shape, float stepHeight) - : btKinematicCharacterController(ghost,shape,stepHeight,2), - m_motionState(motionState), - m_jumps(0), - m_maxJumps(1) -{ -} - -void BlenderBulletCharacterController::updateAction(btCollisionWorld *collisionWorld, btScalar dt) -{ - if (onGround()) - m_jumps = 0; - - btKinematicCharacterController::updateAction(collisionWorld,dt); - m_motionState->setWorldTransform(getGhostObject()->getWorldTransform()); -} - -unsigned char BlenderBulletCharacterController::getMaxJumps() const -{ - return m_maxJumps; -} - -void BlenderBulletCharacterController::setMaxJumps(unsigned char maxJumps) -{ - m_maxJumps = maxJumps; -} - -unsigned char BlenderBulletCharacterController::getJumpCount() const -{ - return m_jumps; -} - -bool BlenderBulletCharacterController::canJump() const -{ - return (onGround() && m_maxJumps > 0) || m_jumps < m_maxJumps; -} - -void BlenderBulletCharacterController::jump() -{ - if (!canJump()) - return; - - m_verticalVelocity = m_jumpSpeed; - m_wasJumping = true; - m_jumps++; -} - -const btVector3& BlenderBulletCharacterController::getWalkDirection() -{ - return m_walkDirection; -} - -bool CleanPairCallback::processOverlap(btBroadphasePair &pair) -{ - if ((pair.m_pProxy0 == m_cleanProxy) || (pair.m_pProxy1 == m_cleanProxy)) { - m_pairCache->cleanOverlappingPair(pair, m_dispatcher); - CcdPhysicsController *ctrl0 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy0->m_clientObject)->getUserPointer()); - CcdPhysicsController *ctrl1 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy1->m_clientObject)->getUserPointer()); - ctrl0->GetCollisionObject()->activate(false); - ctrl1->GetCollisionObject()->activate(false); - } - return false; -} - -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; - m_parentCtrl = 0; - // copy pointers locally to allow smart release - m_MotionState = ci.m_MotionState; - m_collisionShape = ci.m_collisionShape; - // apply scaling before creating rigid body - m_collisionShape->setLocalScaling(m_cci.m_scaling); - if (m_cci.m_mass) - m_collisionShape->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor); - // shape info is shared, increment ref count - m_shapeInfo = ci.m_shapeInfo; - if (m_shapeInfo) - m_shapeInfo->AddRef(); - - m_bulletChildShape = NULL; - - m_bulletMotionState = 0; - m_characterController = 0; - m_savedCollisionFlags = 0; - m_savedCollisionFilterGroup = 0; - m_savedCollisionFilterMask = 0; - m_savedMass = 0.0f; - m_savedDyna = false; - m_suspended = false; - - CreateRigidbody(); -} - -void CcdPhysicsController::addCcdConstraintRef(btTypedConstraint* c) -{ - int index = m_ccdConstraintRefs.findLinearSearch(c); - if (index == m_ccdConstraintRefs.size()) - m_ccdConstraintRefs.push_back(c); -} - -void CcdPhysicsController::removeCcdConstraintRef(btTypedConstraint* c) -{ - m_ccdConstraintRefs.remove(c); -} - -btTypedConstraint* CcdPhysicsController::getCcdConstraintRef(int index) -{ - return m_ccdConstraintRefs[index]; -} - -int CcdPhysicsController::getNumCcdConstraintRefs() const -{ - return m_ccdConstraintRefs.size(); -} - -btTransform& CcdPhysicsController::GetTransformFromMotionState(PHY_IMotionState* motionState) -{ - static btTransform trans; - btVector3 tmp; - motionState->GetWorldPosition(tmp.m_floats[0], tmp.m_floats[1], tmp.m_floats[2]); - trans.setOrigin(tmp); - - float ori[12]; - motionState->GetWorldOrientation(ori); - trans.getBasis().setFromOpenGLSubMatrix(ori); - //btQuaternion orn; - //motionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]); - //trans.setRotation(orn); - return trans; - -} - -class BlenderBulletMotionState : public btMotionState -{ - PHY_IMotionState* m_blenderMotionState; - -public: - - BlenderBulletMotionState(PHY_IMotionState* bms) - :m_blenderMotionState(bms) - { - - } - - void getWorldTransform(btTransform& worldTrans ) const - { - btVector3 pos; - float ori[12]; - - m_blenderMotionState->GetWorldPosition(pos.m_floats[0],pos.m_floats[1],pos.m_floats[2]); - m_blenderMotionState->GetWorldOrientation(ori); - worldTrans.setOrigin(pos); - worldTrans.getBasis().setFromOpenGLSubMatrix(ori); - } - - void setWorldTransform(const btTransform& worldTrans) - { - m_blenderMotionState->SetWorldPosition(worldTrans.getOrigin().getX(),worldTrans.getOrigin().getY(),worldTrans.getOrigin().getZ()); - btQuaternion rotQuat = worldTrans.getRotation(); - m_blenderMotionState->SetWorldOrientation(rotQuat[0],rotQuat[1],rotQuat[2],rotQuat[3]); - m_blenderMotionState->CalculateWorldTransformations(); - } - -}; - -btRigidBody* CcdPhysicsController::GetRigidBody() -{ - return btRigidBody::upcast(m_object); -} -const btRigidBody* CcdPhysicsController::GetRigidBody() const -{ - return btRigidBody::upcast(m_object); -} - -btCollisionObject* CcdPhysicsController::GetCollisionObject() -{ - return m_object; -} -btSoftBody* CcdPhysicsController::GetSoftBody() -{ - return btSoftBody::upcast(m_object); -} -btKinematicCharacterController* CcdPhysicsController::GetCharacterController() -{ - return m_characterController; -} - -#include "BulletSoftBody/btSoftBodyHelpers.h" - - -bool CcdPhysicsController::CreateSoftbody() -{ - int shapeType = m_cci.m_collisionShape ? m_cci.m_collisionShape->getShapeType() : 0; - - //disable soft body until first sneak preview is ready - if (!m_cci.m_bSoft || !m_cci.m_collisionShape || - ((shapeType != CONVEX_HULL_SHAPE_PROXYTYPE)&& - (shapeType != TRIANGLE_MESH_SHAPE_PROXYTYPE) && - (shapeType != SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE))) - { - return false; - } - - btRigidBody::btRigidBodyConstructionInfo rbci(m_cci.m_mass,m_bulletMotionState,m_collisionShape,m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); - rbci.m_linearDamping = m_cci.m_linearDamping; - rbci.m_angularDamping = m_cci.m_angularDamping; - rbci.m_friction = m_cci.m_friction; - rbci.m_restitution = m_cci.m_restitution; - - btVector3 p(0.0f,0.0f,0.0f);// = getOrigin(); - //btSoftBody* psb=btSoftBodyHelpers::CreateRope(worldInfo, btVector3(-10,0,i*0.25),btVector3(10,0,i*0.25), 16,1+2); - btSoftBody* psb = 0; - btSoftBodyWorldInfo& worldInfo = m_cci.m_physicsEnv->GetDynamicsWorld()->getWorldInfo(); - - if (m_cci.m_collisionShape->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE) { - btConvexHullShape* convexHull = (btConvexHullShape* )m_cci.m_collisionShape; - { - int nvertices = convexHull->getNumPoints(); - const btVector3* vertices = convexHull->getPoints(); - - HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); - HullResult hres; - HullLibrary hlib; /*??*/ - hdsc.mMaxVertices=nvertices; - hlib.CreateConvexHull(hdsc,hres); - - psb = new btSoftBody(&worldInfo, (int)hres.mNumOutputVertices, - &hres.m_OutputVertices[0], 0); - for (int i = 0; i < (int)hres.mNumFaces; ++i) { - const unsigned int idx[3] = {hres.m_Indices[i * 3 + 0], - hres.m_Indices[i * 3 + 1], - hres.m_Indices[i * 3 + 2]}; - if (idx[0] < idx[1]) psb->appendLink(idx[0], idx[1]); - if (idx[1] < idx[2]) psb->appendLink(idx[1], idx[2]); - if (idx[2] < idx[0]) psb->appendLink(idx[2], idx[0]); - psb->appendFace(idx[0], idx[1], idx[2]); - } - hlib.ReleaseResult(hres); - } - } - else { - int numtris = 0; - if (m_cci.m_collisionShape->getShapeType() ==SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) - { - btScaledBvhTriangleMeshShape* scaledtrimeshshape = (btScaledBvhTriangleMeshShape*) m_cci.m_collisionShape; - btBvhTriangleMeshShape* trimeshshape = scaledtrimeshshape->getChildShape(); - - ///only deal with meshes that have 1 sub part/component, for now - if (trimeshshape->getMeshInterface()->getNumSubParts()==1) - { - unsigned char* vertexBase; - btScalar* scaledVertexBase; - btVector3 localScaling; - PHY_ScalarType vertexType; - int numverts; - int vertexstride; - unsigned char* indexbase; - int indexstride; - PHY_ScalarType indexType; - trimeshshape->getMeshInterface()->getLockedVertexIndexBase(&vertexBase,numverts,vertexType,vertexstride,&indexbase,indexstride,numtris,indexType); - localScaling = scaledtrimeshshape->getLocalScaling(); - scaledVertexBase = new btScalar[numverts*3]; - for (int i=0; i<numverts*3; i+=3) - { - scaledVertexBase[i] = ((const btScalar*)vertexBase)[i] * localScaling.getX(); - scaledVertexBase[i+1] = ((const btScalar*)vertexBase)[i+1] * localScaling.getY(); - scaledVertexBase[i+2] = ((const btScalar*)vertexBase)[i+2] * localScaling.getZ(); - } - psb = btSoftBodyHelpers::CreateFromTriMesh(worldInfo,scaledVertexBase,(const int*)indexbase,numtris,false); - delete [] scaledVertexBase; - } - } else - { - btTriangleMeshShape* trimeshshape = (btTriangleMeshShape*) m_cci.m_collisionShape; - ///only deal with meshes that have 1 sub part/component, for now - if (trimeshshape->getMeshInterface()->getNumSubParts()==1) - { - unsigned char* vertexBase; - PHY_ScalarType vertexType; - int numverts; - int vertexstride; - unsigned char* indexbase; - int indexstride; - PHY_ScalarType indexType; - trimeshshape->getMeshInterface()->getLockedVertexIndexBase(&vertexBase,numverts,vertexType,vertexstride,&indexbase,indexstride,numtris,indexType); - - psb = btSoftBodyHelpers::CreateFromTriMesh(worldInfo,(const btScalar*)vertexBase,(const int*)indexbase,numtris,false); - } - } - // store face tag so that we can find our original face when doing ray casting - btSoftBody::Face* ft; - int i; - for (i=0, ft=&psb->m_faces[0]; i<numtris; ++i, ++ft) - { - // Hack!! use m_tag to store the face number, normally it is a pointer - // add 1 to make sure it is never 0 - ft->m_tag = (void*)((uintptr_t)(i+1)); - } - } - if (m_cci.m_margin > 0.f) - { - psb->getCollisionShape()->setMargin(m_cci.m_margin); - psb->updateBounds(); - } - m_object = psb; - - //btSoftBody::Material* pm=psb->appendMaterial(); - btSoftBody::Material* pm=psb->m_materials[0]; - pm->m_kLST = m_cci.m_soft_linStiff; - pm->m_kAST = m_cci.m_soft_angStiff; - pm->m_kVST = m_cci.m_soft_volume; - psb->m_cfg.collisions = 0; - - if (m_cci.m_soft_collisionflags & CCD_BSB_COL_CL_RS) - { - psb->m_cfg.collisions += btSoftBody::fCollision::CL_RS; - } else - { - psb->m_cfg.collisions += btSoftBody::fCollision::SDF_RS; - } - if (m_cci.m_soft_collisionflags & CCD_BSB_COL_CL_SS) - { - psb->m_cfg.collisions += btSoftBody::fCollision::CL_SS; - } else - { - psb->m_cfg.collisions += btSoftBody::fCollision::VF_SS; - } - - - psb->m_cfg.kSRHR_CL = m_cci.m_soft_kSRHR_CL; /* Soft vs rigid hardness [0,1] (cluster only) */ - psb->m_cfg.kSKHR_CL = m_cci.m_soft_kSKHR_CL; /* Soft vs kinetic hardness [0,1] (cluster only) */ - psb->m_cfg.kSSHR_CL = m_cci.m_soft_kSSHR_CL; /* Soft vs soft hardness [0,1] (cluster only) */ - psb->m_cfg.kSR_SPLT_CL = m_cci.m_soft_kSR_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */ - - psb->m_cfg.kSK_SPLT_CL = m_cci.m_soft_kSK_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */ - psb->m_cfg.kSS_SPLT_CL = m_cci.m_soft_kSS_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */ - psb->m_cfg.kVCF = m_cci.m_soft_kVCF; /* Velocities correction factor (Baumgarte) */ - psb->m_cfg.kDP = m_cci.m_soft_kDP; /* Damping coefficient [0,1] */ - - psb->m_cfg.kDG = m_cci.m_soft_kDG; /* Drag coefficient [0,+inf] */ - psb->m_cfg.kLF = m_cci.m_soft_kLF; /* Lift coefficient [0,+inf] */ - psb->m_cfg.kPR = m_cci.m_soft_kPR; /* Pressure coefficient [-inf,+inf] */ - psb->m_cfg.kVC = m_cci.m_soft_kVC; /* Volume conversation coefficient [0,+inf] */ - - psb->m_cfg.kDF = m_cci.m_soft_kDF; /* Dynamic friction coefficient [0,1] */ - psb->m_cfg.kMT = m_cci.m_soft_kMT; /* Pose matching coefficient [0,1] */ - psb->m_cfg.kCHR = m_cci.m_soft_kCHR; /* Rigid contacts hardness [0,1] */ - psb->m_cfg.kKHR = m_cci.m_soft_kKHR; /* Kinetic contacts hardness [0,1] */ - - psb->m_cfg.kSHR = m_cci.m_soft_kSHR; /* Soft contacts hardness [0,1] */ - psb->m_cfg.kAHR = m_cci.m_soft_kAHR; /* Anchors hardness [0,1] */ - - if (m_cci.m_gamesoftFlag & CCD_BSB_BENDING_CONSTRAINTS)//OB_SB_GOAL) - { - psb->generateBendingConstraints(2,pm); - } - - psb->m_cfg.piterations = m_cci.m_soft_piterations; - psb->m_cfg.viterations = m_cci.m_soft_viterations; - psb->m_cfg.diterations = m_cci.m_soft_diterations; - psb->m_cfg.citerations = m_cci.m_soft_citerations; - - if (m_cci.m_gamesoftFlag & CCD_BSB_SHAPE_MATCHING)//OB_SB_GOAL) - { - psb->setPose(false,true);// - } else - { - psb->setPose(true,false); - } - - psb->randomizeConstraints(); - - if (m_cci.m_soft_collisionflags & (CCD_BSB_COL_CL_RS+CCD_BSB_COL_CL_SS)) - { - psb->generateClusters(m_cci.m_soft_numclusteriterations); - } - - psb->setTotalMass(m_cci.m_mass); - - psb->setCollisionFlags(0); - - ///create a mapping between graphics mesh vertices and soft body vertices - { - RAS_MeshObject* rasMesh= GetShapeInfo()->GetMesh(); - - if (rasMesh && !m_softbodyMappingDone) - { - //printf("apply\n"); - RAS_MeshSlot::iterator it; - RAS_MeshMaterial *mmat; - RAS_MeshSlot *slot; - size_t i; - - //for each material - for (int m=0;m<rasMesh->NumMaterials();m++) - { - mmat = rasMesh->GetMeshMaterial(m); - - slot = mmat->m_baseslot; - for (slot->begin(it); !slot->end(it); slot->next(it)) - { - int index = 0; - 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 = 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); - } - } - } - } - } - } - } - m_softbodyMappingDone = true; - - btTransform startTrans; - rbci.m_motionState->getWorldTransform(startTrans); - - 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; - psb->transform(startTrans); - } - m_object->setCollisionFlags(m_object->getCollisionFlags() | m_cci.m_collisionFlags); - if (m_cci.m_do_anisotropic) - m_object->setAnisotropicFriction(m_cci.m_anisotropicFriction); - return true; -} - -bool CcdPhysicsController::CreateCharacterController() -{ - if (!m_cci.m_bCharacter) - return false; - - m_object = new btPairCachingGhostObject(); - m_object->setCollisionShape(m_collisionShape); - m_object->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT); - - btTransform trans; - m_bulletMotionState->getWorldTransform(trans); - m_object->setWorldTransform(trans); - - m_characterController = new BlenderBulletCharacterController(m_bulletMotionState,(btPairCachingGhostObject*)m_object,(btConvexShape*)m_collisionShape,m_cci.m_stepHeight); - - m_characterController->setJumpSpeed(m_cci.m_jumpSpeed); - m_characterController->setFallSpeed(m_cci.m_fallSpeed); - m_characterController->setMaxJumps(m_cci.m_maxJumps); - - return true; -} - -void CcdPhysicsController::CreateRigidbody() -{ - - //btTransform trans = GetTransformFromMotionState(m_MotionState); - m_bulletMotionState = new BlenderBulletMotionState(m_MotionState); - - ///either create a btCollisionObject, btRigidBody or btSoftBody - if (CreateSoftbody() || CreateCharacterController()) - // soft body created, done - return; - - //create a rgid collision object - btRigidBody::btRigidBodyConstructionInfo rbci(m_cci.m_mass,m_bulletMotionState,m_collisionShape,m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); - rbci.m_linearDamping = m_cci.m_linearDamping; - rbci.m_angularDamping = m_cci.m_angularDamping; - rbci.m_friction = m_cci.m_friction; - rbci.m_restitution = m_cci.m_restitution; - m_object = new btRigidBody(rbci); - - // - // init the rigidbody properly - // - - //setMassProps this also sets collisionFlags - //convert collision flags! - //special case: a near/radar sensor controller should not be defined static or it will - //generate loads of static-static collision messages on the console - if (m_cci.m_bSensor) - { - // reset the flags that have been set so far - GetCollisionObject()->setCollisionFlags(0); - // sensor must never go to sleep: they need to detect continously - GetCollisionObject()->setActivationState(DISABLE_DEACTIVATION); - } - GetCollisionObject()->setCollisionFlags(m_object->getCollisionFlags() | m_cci.m_collisionFlags); - btRigidBody* body = GetRigidBody(); - - if (body) - { - body->setGravity( m_cci.m_gravity); - body->setDamping(m_cci.m_linearDamping, m_cci.m_angularDamping); - - if (!m_cci.m_bRigid) - { - body->setAngularFactor(0.f); - } - // use bullet's default contact processing theshold, blender's old default of 1 is too small here. - // if there's really a need to change this, it should be exposed in the ui first. -// body->setContactProcessingThreshold(m_cci.m_contactProcessingThreshold); - body->setSleepingThresholds(gLinearSleepingTreshold, gAngularSleepingTreshold); - - } - if (m_object && m_cci.m_do_anisotropic) - { - m_object->setAnisotropicFriction(m_cci.m_anisotropicFriction); - } - -} - -static void DeleteBulletShape(btCollisionShape* shape, bool free) -{ - if (shape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) { - /* If we use Bullet scaled shape (btScaledBvhTriangleMeshShape) we have to - * free the child of the unscaled shape (btTriangleMeshShape) here. - */ - btTriangleMeshShape *meshShape = ((btScaledBvhTriangleMeshShape *)shape)->getChildShape(); - if (meshShape) - delete meshShape; - } - if (free) { - delete shape; - } -} - -bool CcdPhysicsController::DeleteControllerShape( ) -{ - if (m_collisionShape) - { - // collision shape is always unique to the controller, can delete it here - if (m_collisionShape->isCompound()) - { - // bullet does not delete the child shape, must do it here - btCompoundShape* compoundShape = (btCompoundShape*)m_collisionShape; - int numChild = compoundShape->getNumChildShapes(); - for (int i=numChild-1 ; i >= 0; i--) - { - btCollisionShape* childShape = compoundShape->getChildShape(i); - DeleteBulletShape(childShape, true); - } - } - DeleteBulletShape(m_collisionShape, true); - - return true; - } - - return false; -} - -bool CcdPhysicsController::ReplaceControllerShape(btCollisionShape *newShape) -{ - if (m_collisionShape) - DeleteControllerShape(); - - // If newShape is NULL it means to create a new Bullet shape. - if (!newShape) - newShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin, m_cci.m_bGimpact, !m_cci.m_bSoft); - - m_object->setCollisionShape(newShape); - m_collisionShape = newShape; - m_cci.m_collisionShape = newShape; - - btSoftBody *softBody = GetSoftBody(); - if (softBody) { - btSoftRigidDynamicsWorld *world = GetPhysicsEnvironment()->GetDynamicsWorld(); - // remove the old softBody - world->removeSoftBody(softBody); - - // soft body must be recreated - delete m_object; - m_object = NULL; - // force complete reinitialization - m_softbodyMappingDone = false; - m_prototypeTransformInitialized = false; - m_softBodyTransformInitialized = false; - - CreateSoftbody(); - assert(m_object); - - btSoftBody *newSoftBody = GetSoftBody(); - // set the user - newSoftBody->setUserPointer(this); - // add the new softbody - world->addSoftBody(newSoftBody); - } - - return true; -} - -CcdPhysicsController::~CcdPhysicsController() -{ - //will be reference counted, due to sharing - if (m_cci.m_physicsEnv) - m_cci.m_physicsEnv->RemoveCcdPhysicsController(this); - - if (m_MotionState) - delete m_MotionState; - if (m_bulletMotionState) - delete m_bulletMotionState; - if (m_characterController) - delete m_characterController; - delete m_object; - - DeleteControllerShape(); - - if (m_shapeInfo) - { - m_shapeInfo->Release(); - } -} - -void CcdPhysicsController::SimulationTick(float timestep) -{ - btRigidBody *body = GetRigidBody(); - if (!body || body->isStaticObject()) - return; - - // Clamp linear velocity - if (m_cci.m_clamp_vel_max > 0.0f || m_cci.m_clamp_vel_min > 0.0f) { - const btVector3 &linvel = body->getLinearVelocity(); - btScalar len = linvel.length(); - - if (m_cci.m_clamp_vel_max > 0.0f && 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.0f && !btFuzzyZero(len) && len < m_cci.m_clamp_vel_min) - body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len)); - } - - // Clamp angular velocity - if (m_cci.m_clamp_angvel_max > 0.0f || m_cci.m_clamp_angvel_min > 0.0f) { - const btVector3 &angvel = body->getAngularVelocity(); - btScalar len = angvel.length(); - - if (m_cci.m_clamp_angvel_max > 0.0f && len > m_cci.m_clamp_angvel_max) - body->setAngularVelocity(angvel * (m_cci.m_clamp_angvel_max / len)); - else if (m_cci.m_clamp_angvel_min > 0.0f && !btFuzzyZero(len) && len < m_cci.m_clamp_angvel_min) - body->setAngularVelocity(angvel * (m_cci.m_clamp_angvel_min / len)); - } -} - - -/** - * SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding') - */ -bool CcdPhysicsController::SynchronizeMotionStates(float time) -{ - //sync non-static to motionstate, and static from motionstate (todo: add kinematic etc.) - - btSoftBody* sb = GetSoftBody(); - if (sb) - { - if (sb->m_pose.m_bframe) - { - btVector3 worldPos = sb->m_pose.m_com; - btQuaternion worldquat; - btMatrix3x3 trs = sb->m_pose.m_rot*sb->m_pose.m_scl; - trs.getRotation(worldquat); - m_MotionState->SetWorldPosition(worldPos[0],worldPos[1],worldPos[2]); - m_MotionState->SetWorldOrientation(worldquat[0],worldquat[1],worldquat[2],worldquat[3]); - } - else - { - btVector3 aabbMin,aabbMax; - sb->getAabb(aabbMin,aabbMax); - btVector3 worldPos = (aabbMax+aabbMin)*0.5f; - m_MotionState->SetWorldPosition(worldPos[0],worldPos[1],worldPos[2]); - } - m_MotionState->CalculateWorldTransformations(); - return true; - } - - btRigidBody* body = GetRigidBody(); - - if (body && !body->isStaticObject()) - { - const btTransform& xform = body->getCenterOfMassTransform(); - const btMatrix3x3& worldOri = xform.getBasis(); - const btVector3& worldPos = xform.getOrigin(); - float ori[12]; - worldOri.getOpenGLSubMatrix(ori); - m_MotionState->SetWorldOrientation(ori); - m_MotionState->SetWorldPosition(worldPos[0],worldPos[1],worldPos[2]); - m_MotionState->CalculateWorldTransformations(); - - float scale[3]; - m_MotionState->GetWorldScaling(scale[0],scale[1],scale[2]); - btVector3 scaling(scale[0],scale[1],scale[2]); - GetCollisionShape()->setLocalScaling(scaling); - } else - { - btVector3 worldPos; - btQuaternion worldquat; - -/* m_MotionState->getWorldPosition(worldPos[0],worldPos[1],worldPos[2]); - m_MotionState->getWorldOrientation(worldquat[0],worldquat[1],worldquat[2],worldquat[3]); - btTransform oldTrans = m_body->getCenterOfMassTransform(); - btTransform newTrans(worldquat,worldPos); - - SetCenterOfMassTransform(newTrans); - //need to keep track of previous position for friction effects... - - m_MotionState->calculateWorldTransformations(); -*/ - float scale[3]; - m_MotionState->GetWorldScaling(scale[0],scale[1],scale[2]); - btVector3 scaling(scale[0],scale[1],scale[2]); - GetCollisionShape()->setLocalScaling(scaling); - } - return true; - -} - - /** - * WriteMotionStateToDynamics synchronizes dynas, kinematic and deformable entities (and do 'late binding') - */ - -void CcdPhysicsController::WriteMotionStateToDynamics(bool nondynaonly) -{ - btTransform& xform = CcdPhysicsController::GetTransformFromMotionState(m_MotionState); - SetCenterOfMassTransform(xform); -} - -void CcdPhysicsController::WriteDynamicsToMotionState() -{ -} - // controller replication -void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl) -{ - SetParentCtrl((CcdPhysicsController*)parentctrl); - m_softBodyTransformInitialized=false; - m_MotionState = motionstate; - m_registerCount = 0; - m_collisionShape = NULL; - - // Clear all old constraints. - m_ccdConstraintRefs.clear(); - - // always create a new shape to avoid scaling bug - if (m_shapeInfo) - { - m_shapeInfo->AddRef(); - m_collisionShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin, m_cci.m_bGimpact, !m_cci.m_bSoft); - - if (m_collisionShape) - { - // new shape has no scaling, apply initial scaling - //m_collisionShape->setMargin(m_cci.m_margin); - m_collisionShape->setLocalScaling(m_cci.m_scaling); - - if (m_cci.m_mass) - m_collisionShape->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor); - } - } - - // load some characterists that are not - btRigidBody* oldbody = GetRigidBody(); - m_object = 0; - CreateRigidbody(); - btRigidBody* body = GetRigidBody(); - if (body) - { - if (m_cci.m_mass) - { - body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); - } - - if (oldbody) - { - body->setLinearFactor(oldbody->getLinearFactor()); - body->setAngularFactor(oldbody->getAngularFactor()); - if (oldbody->getActivationState() == DISABLE_DEACTIVATION) - body->setActivationState(DISABLE_DEACTIVATION); - } - } - // sensor object are added when needed - if (!m_cci.m_bSensor) - m_cci.m_physicsEnv->AddCcdPhysicsController(this); - - -} - -void CcdPhysicsController::SetPhysicsEnvironment(class PHY_IPhysicsEnvironment *env) -{ - // can safely assume CCD environment - CcdPhysicsEnvironment *physicsEnv = static_cast<CcdPhysicsEnvironment*>(env); - - if (m_cci.m_physicsEnv != physicsEnv) - { - // since the environment is changing, we must also move the controler to the - // new environment. Note that we don't handle sensor explicitly: this - // function can be called on sensor but only when they are not registered - if (m_cci.m_physicsEnv->RemoveCcdPhysicsController(this)) - { - physicsEnv->AddCcdPhysicsController(this); - - // Set the object to be active so it can at least by evaluated once. - // This fixes issues with static objects not having their physics meshes - // in the right spot when lib loading. - this->GetCollisionObject()->setActivationState(ACTIVE_TAG); - } - m_cci.m_physicsEnv = physicsEnv; - } -} - -void CcdPhysicsController::SetCenterOfMassTransform(btTransform& xform) -{ - btRigidBody* body = GetRigidBody(); - if (body) - { - body->setCenterOfMassTransform(xform); - } else - { - //either collision object or soft body? - if (GetSoftBody()) - { - - } else - { - - if (m_object->isStaticOrKinematicObject()) - { - m_object->setInterpolationWorldTransform(m_object->getWorldTransform()); - } else - { - m_object->setInterpolationWorldTransform(xform); - } - m_object->setWorldTransform(xform); - } - } -} - - // kinematic methods -void CcdPhysicsController::RelativeTranslate(const MT_Vector3& dlocin,bool local) -{ - if (m_object) - { - m_object->activate(true); - if (m_object->isStaticObject()) - { - if (!m_cci.m_bSensor) - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - // kinematic object should not set the transform, it disturbs the velocity interpolation - return; - } - - btVector3 dloc(dlocin.x(), dlocin.y(), dlocin.z()); - btTransform xform = m_object->getWorldTransform(); - - if (local) - dloc = xform.getBasis()*dloc; - - xform.setOrigin(xform.getOrigin() + dloc); - SetCenterOfMassTransform(xform); - } - -} - -void CcdPhysicsController::RelativeRotate(const MT_Matrix3x3& rotval,bool local) -{ - if (m_object) - { - m_object->activate(true); - if (m_object->isStaticObject()) - { - if (!m_cci.m_bSensor) - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - // kinematic object should not set the transform, it disturbs the velocity interpolation - return; - } - - btMatrix3x3 drotmat(rotval[0].x(), rotval[0].y(), rotval[0].z(), - rotval[1].x(), rotval[1].y(), rotval[1].z(), - rotval[2].x(), rotval[2].y(), rotval[2].z()); - - - btMatrix3x3 currentOrn; - GetWorldOrientation(currentOrn); - - btTransform xform = m_object->getWorldTransform(); - - xform.setBasis(xform.getBasis()*(local ? - drotmat : (currentOrn.inverse() * drotmat * currentOrn))); - - SetCenterOfMassTransform(xform); - } -} - - -void CcdPhysicsController::GetWorldOrientation(btMatrix3x3& mat) -{ - float ori[12]; - m_MotionState->GetWorldOrientation(ori); - mat.setFromOpenGLSubMatrix(ori); -} - -MT_Matrix3x3 CcdPhysicsController::GetOrientation() -{ - btMatrix3x3 orn = m_object->getWorldTransform().getBasis(); - return MT_Matrix3x3(orn[0][0], orn[0][1], orn[0][2], orn[1][0], orn[1][1], orn[1][2], orn[2][0], orn[2][1], orn[2][2]); -} - -void CcdPhysicsController::SetOrientation(const MT_Matrix3x3& orn) -{ - btMatrix3x3 btmat(orn[0][0], orn[0][1], orn[0][2], orn[1][0], orn[1][1], orn[1][2], orn[2][0], orn[2][1], orn[2][2]); - SetWorldOrientation(btmat); -} - -void CcdPhysicsController::SetWorldOrientation(const btMatrix3x3& orn) -{ - if (m_object) - { - m_object->activate(true); - if (m_object->isStaticObject() && !m_cci.m_bSensor) - { - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - } - // not required - //m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal); - btTransform xform = m_object->getWorldTransform(); - xform.setBasis(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; - } - - } - -} - -void CcdPhysicsController::SetPosition(const MT_Vector3& pos) -{ - if (m_object) - { - m_object->activate(true); - if (m_object->isStaticObject()) - { - if (!m_cci.m_bSensor) - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - // kinematic object should not set the transform, it disturbs the velocity interpolation - return; - } - // not required, this function is only used to update the physic controller - //m_MotionState->setWorldPosition(posX,posY,posZ); - btTransform xform = m_object->getWorldTransform(); - xform.setOrigin(btVector3(pos.x(), pos.y(), pos.z())); - SetCenterOfMassTransform(xform); - if (!m_softBodyTransformInitialized) - m_softbodyStartTrans.setOrigin(xform.getOrigin()); - // not required - //m_bulletMotionState->setWorldTransform(xform); - } -} - -void CcdPhysicsController::ForceWorldTransform(const btMatrix3x3& mat, const btVector3& pos) -{ - if (m_object) - { - btTransform& xform = m_object->getWorldTransform(); - xform.setBasis(mat); - xform.setOrigin(pos); - } -} - - -void CcdPhysicsController::ResolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ) -{ -} - -void CcdPhysicsController::RefreshCollisions() -{ - // the object is in an inactive layer so it's useless to update it and can cause problems - if (!GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this)) - return; - - btSoftRigidDynamicsWorld *dw = GetPhysicsEnvironment()->GetDynamicsWorld(); - btBroadphaseProxy *proxy = m_object->getBroadphaseHandle(); - btDispatcher *dispatcher = dw->getDispatcher(); - btOverlappingPairCache *pairCache = dw->getPairCache(); - - CleanPairCallback cleanPairs(proxy, pairCache, dispatcher); - pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher); - - // Forcibly recreate the physics object - btBroadphaseProxy* handle = m_object->getBroadphaseHandle(); - GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, GetMass(), m_object->getCollisionFlags(), handle->m_collisionFilterGroup, handle->m_collisionFilterMask); -} - -void CcdPhysicsController::SuspendDynamics(bool ghost) -{ - btRigidBody *body = GetRigidBody(); - if (body && !m_suspended && !GetConstructionInfo().m_bSensor && GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this)) - { - btBroadphaseProxy* handle = body->getBroadphaseHandle(); - - m_savedCollisionFlags = body->getCollisionFlags(); - m_savedMass = GetMass(); - m_savedDyna = m_cci.m_bDyna; - m_savedCollisionFilterGroup = handle->m_collisionFilterGroup; - m_savedCollisionFilterMask = handle->m_collisionFilterMask; - m_suspended = true; - GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, - 0.0f, - btCollisionObject::CF_STATIC_OBJECT|((ghost)?btCollisionObject::CF_NO_CONTACT_RESPONSE:(m_savedCollisionFlags&btCollisionObject::CF_NO_CONTACT_RESPONSE)), - btBroadphaseProxy::StaticFilter, - btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); - m_cci.m_bDyna = false; - } -} - -void CcdPhysicsController::RestoreDynamics() -{ - btRigidBody *body = GetRigidBody(); - if (body && m_suspended && GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this)) - { - // before make sure any position change that was done in this logic frame are accounted for - SetTransform(); - GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, - m_savedMass, - m_savedCollisionFlags, - m_savedCollisionFilterGroup, - m_savedCollisionFilterMask); - body->activate(); - m_cci.m_bDyna = m_savedDyna; - m_suspended = false; - } -} - -void CcdPhysicsController::GetPosition(MT_Vector3& pos) const -{ - const btTransform& xform = m_object->getWorldTransform(); - pos[0] = xform.getOrigin().x(); - pos[1] = xform.getOrigin().y(); - pos[2] = xform.getOrigin().z(); -} - -void CcdPhysicsController::SetScaling(const MT_Vector3& scale) -{ - if (!btFuzzyZero(m_cci.m_scaling.x()-scale.x()) || - !btFuzzyZero(m_cci.m_scaling.y()-scale.y()) || - !btFuzzyZero(m_cci.m_scaling.z()-scale.z())) - { - m_cci.m_scaling = btVector3(scale.x(),scale.y(),scale.z()); - - if (m_object && m_object->getCollisionShape()) - { - m_object->activate(true); // without this, sleeping objects scale wont be applied in bullet if python changes the scale - Campbell. - m_object->getCollisionShape()->setLocalScaling(m_cci.m_scaling); - - //printf("no inertia recalc for fixed objects with mass=0\n"); - btRigidBody* body = GetRigidBody(); - if (body && m_cci.m_mass) - { - body->getCollisionShape()->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor); - body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); - } - - } - } -} - -void CcdPhysicsController::SetTransform() -{ - btVector3 pos; - btVector3 scale; - float ori[12]; - m_MotionState->GetWorldPosition(pos.m_floats[0],pos.m_floats[1],pos.m_floats[2]); - m_MotionState->GetWorldScaling(scale.m_floats[0],scale.m_floats[1],scale.m_floats[2]); - m_MotionState->GetWorldOrientation(ori); - btMatrix3x3 rot(ori[0], ori[4], ori[8], - ori[1], ori[5], ori[9], - ori[2], ori[6], ori[10]); - ForceWorldTransform(rot, pos); - - if (!IsDynamic() && !GetConstructionInfo().m_bSensor && !GetCharacterController()) - { - btCollisionObject* object = GetRigidBody(); - object->setActivationState(ACTIVE_TAG); - object->setCollisionFlags(object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - } -} - -MT_Scalar CcdPhysicsController::GetMass() -{ - if (GetSoftBody()) - return GetSoftBody()->getTotalMass(); - - MT_Scalar invmass = 0.f; - if (GetRigidBody()) - invmass = GetRigidBody()->getInvMass(); - if (invmass) - return 1.f/invmass; - return 0.f; - -} - -void CcdPhysicsController::SetMass(MT_Scalar newmass) -{ - btRigidBody *body = GetRigidBody(); - if (body && !m_suspended && newmass>MT_EPSILON && GetMass()>MT_EPSILON) - { - btBroadphaseProxy* handle = body->getBroadphaseHandle(); - GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, - newmass, - body->getCollisionFlags(), - handle->m_collisionFilterGroup, - handle->m_collisionFilterMask); - } -} - - // physics methods -void CcdPhysicsController::ApplyTorque(const MT_Vector3& torquein,bool local) -{ - btVector3 torque(torquein.x(),torquein.y(),torquein.z()); - btTransform xform = m_object->getWorldTransform(); - - - if (m_object && torque.length2() > (SIMD_EPSILON*SIMD_EPSILON)) - { - btRigidBody* body = GetRigidBody(); - m_object->activate(); - if (m_object->isStaticObject()) - { - if (!m_cci.m_bSensor) - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - return; - } - if (local) - { - torque = xform.getBasis()*torque; - } - if (body) - { - if (m_cci.m_bRigid) - { - body->applyTorque(torque); - } - else - { - //workaround for incompatibility between 'DYNAMIC' game object, and angular factor - //a DYNAMIC object has some inconsistency: it has no angular effect due to collisions, but still has torque - const btVector3 angFac = body->getAngularFactor(); - btVector3 tmpFac(1,1,1); - body->setAngularFactor(tmpFac); - body->applyTorque(torque); - body->setAngularFactor(angFac); - } - } - } -} - -void CcdPhysicsController::ApplyForce(const MT_Vector3& forcein,bool local) -{ - btVector3 force(forcein.x(),forcein.y(),forcein.z()); - - - if (m_object && force.length2() > (SIMD_EPSILON*SIMD_EPSILON)) - { - m_object->activate(); - if (m_object->isStaticObject()) - { - if (!m_cci.m_bSensor) - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - return; - } - btTransform xform = m_object->getWorldTransform(); - - if (local) - { - force = xform.getBasis()*force; - } - btRigidBody* body = GetRigidBody(); - if (body) - body->applyCentralForce(force); - btSoftBody* soft = GetSoftBody(); - if (soft) - { - // the force is applied on each node, must reduce it in the same extend - if (soft->m_nodes.size() > 0) - force /= soft->m_nodes.size(); - soft->addForce(force); - } - } -} -void CcdPhysicsController::SetAngularVelocity(const MT_Vector3& ang_vel,bool local) -{ - btVector3 angvel(ang_vel.x(),ang_vel.y(),ang_vel.z()); - - /* Refuse tiny tiny velocities, as they might cause instabilities. */ - float vel_squared = angvel.length2(); - if (vel_squared > 0 && vel_squared <= (SIMD_EPSILON*SIMD_EPSILON)) - angvel = btVector3(0, 0, 0); - - if (m_object) - { - m_object->activate(true); - if (m_object->isStaticObject()) - { - if (!m_cci.m_bSensor) - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - return; - } - btTransform xform = m_object->getWorldTransform(); - if (local) - { - angvel = xform.getBasis()*angvel; - } - btRigidBody* body = GetRigidBody(); - if (body) - body->setAngularVelocity(angvel); - } - -} -void CcdPhysicsController::SetLinearVelocity(const MT_Vector3& lin_vel,bool local) -{ - btVector3 linVel(lin_vel.x(),lin_vel.y(),lin_vel.z()); - - /* Refuse tiny tiny velocities, as they might cause instabilities. */ - float vel_squared = linVel.length2(); - if (vel_squared > 0 && vel_squared <= (SIMD_EPSILON*SIMD_EPSILON)) - linVel = btVector3(0, 0, 0); - - if (m_object) - { - m_object->activate(true); - if (m_object->isStaticObject()) - { - if (!m_cci.m_bSensor) - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - return; - } - - btSoftBody* soft = GetSoftBody(); - if (soft) - { - if (local) - { - linVel = m_softbodyStartTrans.getBasis()*linVel; - } - soft->setVelocity(linVel); - } else - { - btTransform xform = m_object->getWorldTransform(); - if (local) - { - linVel = xform.getBasis()*linVel; - } - btRigidBody* body = GetRigidBody(); - if (body) - body->setLinearVelocity(linVel); - } - } -} -void CcdPhysicsController::ApplyImpulse(const MT_Point3& attach, const MT_Vector3& impulsein, bool local) -{ - btVector3 pos; - btVector3 impulse(impulsein.x(), impulsein.y(), impulsein.z()); - - if (m_object && impulse.length2() > (SIMD_EPSILON*SIMD_EPSILON)) - { - m_object->activate(); - if (m_object->isStaticObject()) - { - if (!m_cci.m_bSensor) - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - return; - } - - btTransform xform = m_object->getWorldTransform(); - - if (local) - { - pos = btVector3(attach.x(), attach.y(), attach.z()); - impulse = xform.getBasis() * impulse; - } - else { - /* If the point of impulse application is not equal to the object position - * then an angular momentum is generated in the object*/ - pos = btVector3(attach.x()-xform.getOrigin().x(), attach.y()-xform.getOrigin().y(), attach.z()-xform.getOrigin().z()); - } - - btRigidBody* body = GetRigidBody(); - if (body) - body->applyImpulse(impulse,pos); - - } - -} - -void CcdPhysicsController::Jump() -{ - if (m_object && m_characterController) - m_characterController->jump(); -} - -void CcdPhysicsController::SetActive(bool active) -{ -} - -float CcdPhysicsController::GetLinearDamping() const -{ - const btRigidBody* body = GetRigidBody(); - if (body) - return body->getLinearDamping(); - return 0; -} - -float CcdPhysicsController::GetAngularDamping() const -{ - const btRigidBody* body = GetRigidBody(); - if (body) - return body->getAngularDamping(); - return 0; -} - -void CcdPhysicsController::SetLinearDamping(float damping) -{ - SetDamping(damping, GetAngularDamping()); -} - -void CcdPhysicsController::SetAngularDamping(float damping) -{ - SetDamping(GetLinearDamping(), damping); -} - -void CcdPhysicsController::SetDamping(float linear, float angular) -{ - btRigidBody* body = GetRigidBody(); - if (!body) return; - - body->setDamping(linear, angular); -} - - - // reading out information from physics -MT_Vector3 CcdPhysicsController::GetLinearVelocity() -{ - btRigidBody* body = GetRigidBody(); - if (body) - { - const btVector3& linvel = body->getLinearVelocity(); - return MT_Vector3(linvel.x(), linvel.y(), linvel.z()); - } - - return MT_Vector3(0.f, 0.f, 0.f); -} - -MT_Vector3 CcdPhysicsController::GetAngularVelocity() -{ - btRigidBody* body = GetRigidBody(); - if (body) - { - const btVector3& angvel= body->getAngularVelocity(); - return MT_Vector3(angvel.x(), angvel.y(), angvel.z()); - } - - return MT_Vector3(0.f, 0.f, 0.f); -} - -MT_Vector3 CcdPhysicsController::GetVelocity(const MT_Point3 &posin) -{ - btVector3 pos(posin.x(), posin.y(), posin.z()); - btRigidBody* body = GetRigidBody(); - if (body) - { - btVector3 linvel = body->getVelocityInLocalPoint(pos); - return MT_Vector3(linvel.x(), linvel.y(), linvel.z()); - } - - return MT_Vector3(0.f, 0.f, 0.f); -} - -MT_Vector3 CcdPhysicsController::GetLocalInertia() -{ - MT_Vector3 inertia(0.f, 0.f, 0.f); - btVector3 inv_inertia; - if (GetRigidBody()) { - inv_inertia = GetRigidBody()->getInvInertiaDiagLocal(); - if (!btFuzzyZero(inv_inertia.getX()) && - !btFuzzyZero(inv_inertia.getY()) && - !btFuzzyZero(inv_inertia.getZ())) - inertia = MT_Vector3(1.f/inv_inertia.getX(), 1.f/inv_inertia.getY(), 1.f/inv_inertia.getZ()); - } - return inertia; -} - - // dyna's that are rigidbody are free in orientation, dyna's with non-rigidbody are restricted -void CcdPhysicsController::SetRigidBody(bool rigid) -{ - btRigidBody* body = GetRigidBody(); - if (body) - { - m_cci.m_bRigid = rigid; - if (!rigid) { - body->setAngularFactor(0.f); - body->setAngularVelocity(btVector3(0.f, 0.f, 0.f)); - } - else - body->setAngularFactor(m_cci.m_angularFactor); - } -} - - // clientinfo for raycasts for example -void* CcdPhysicsController::GetNewClientInfo() -{ - return m_newClientInfo; -} -void CcdPhysicsController::SetNewClientInfo(void* clientinfo) -{ - m_newClientInfo = clientinfo; - - if (m_cci.m_bSensor) - { - // use a different callback function for sensor object, - // bullet will not synchronize, we must do it explicitly - SG_Callbacks& callbacks = KX_GameObject::GetClientObject((KX_ClientObjectInfo*)clientinfo)->GetSGNode()->GetCallBackFunctions(); - callbacks.m_updatefunc = KX_GameObject::SynchronizeTransformFunc; - } -} - - -void CcdPhysicsController::UpdateDeactivation(float timeStep) -{ - btRigidBody* body = GetRigidBody(); - if (body) - { - body->updateDeactivation( timeStep); - } -} - -bool CcdPhysicsController::WantsSleeping() -{ - btRigidBody* body = GetRigidBody(); - if (body) - { - return body->wantsSleeping(); - } - //check it out - return true; -} -/* This function dynamically adds the collision shape of another controller to - * the current controller shape provided it is a compound shape. - * The idea is that dynamic parenting on a compound object will dynamically extend the shape - */ -void CcdPhysicsController::AddCompoundChild(PHY_IPhysicsController* child) -{ - if (child == NULL || !IsCompound()) - return; - // other controller must be a bullet controller too - // verify that body and shape exist and match - CcdPhysicsController* childCtrl = dynamic_cast<CcdPhysicsController*>(child); - btRigidBody* rootBody = GetRigidBody(); - btRigidBody* childBody = childCtrl->GetRigidBody(); - if (!rootBody || !childBody) - return; - const btCollisionShape* rootShape = rootBody->getCollisionShape(); - const btCollisionShape* childShape = childBody->getCollisionShape(); - if (!rootShape || - !childShape || - rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE) - return; - btCompoundShape* compoundShape = (btCompoundShape*)rootShape; - // compute relative transformation between parent and child - btTransform rootTrans; - btTransform childTrans; - rootBody->getMotionState()->getWorldTransform(rootTrans); - childBody->getMotionState()->getWorldTransform(childTrans); - btVector3 rootScale = rootShape->getLocalScaling(); - rootScale[0] = 1.0f/rootScale[0]; - rootScale[1] = 1.0f/rootScale[1]; - rootScale[2] = 1.0f/rootScale[2]; - // relative scale = child_scale/parent_scale - btVector3 relativeScale = childShape->getLocalScaling()*rootScale; - btMatrix3x3 rootRotInverse = rootTrans.getBasis().transpose(); - // relative pos = parent_rot^-1 * ((parent_pos-child_pos)/parent_scale) - btVector3 relativePos = rootRotInverse*((childTrans.getOrigin()-rootTrans.getOrigin())*rootScale); - // relative rot = parent_rot^-1 * child_rot - btMatrix3x3 relativeRot = rootRotInverse*childTrans.getBasis(); - // create a proxy shape info to store the transformation - CcdShapeConstructionInfo* proxyShapeInfo = new CcdShapeConstructionInfo(); - // store the transformation to this object shapeinfo - proxyShapeInfo->m_childTrans.setOrigin(relativePos); - proxyShapeInfo->m_childTrans.setBasis(relativeRot); - proxyShapeInfo->m_childScale.setValue(relativeScale[0], relativeScale[1], relativeScale[2]); - // we will need this to make sure that we remove the right proxy later when unparenting - proxyShapeInfo->m_userData = childCtrl; - proxyShapeInfo->SetProxy(childCtrl->GetShapeInfo()->AddRef()); - // add to parent compound shapeinfo (increments ref count) - GetShapeInfo()->AddShape(proxyShapeInfo); - // create new bullet collision shape from the object shapeinfo and set scaling - btCollisionShape* newChildShape = proxyShapeInfo->CreateBulletShape(childCtrl->GetMargin(), childCtrl->GetConstructionInfo().m_bGimpact, true); - newChildShape->setLocalScaling(relativeScale); - // add bullet collision shape to parent compound collision shape - compoundShape->addChildShape(proxyShapeInfo->m_childTrans,newChildShape); - // proxyShapeInfo is not needed anymore, release it - proxyShapeInfo->Release(); - // remember we created this shape - childCtrl->m_bulletChildShape = newChildShape; - // recompute inertia of parent - if (!rootBody->isStaticOrKinematicObject()) - { - btVector3 localInertia; - float mass = 1.f/rootBody->getInvMass(); - compoundShape->calculateLocalInertia(mass,localInertia); - rootBody->setMassProps(mass,localInertia); - } - // must update the broadphase cache, - GetPhysicsEnvironment()->RefreshCcdPhysicsController(this); - // remove the children - GetPhysicsEnvironment()->RemoveCcdPhysicsController(childCtrl); -} - -/* Reverse function of the above, it will remove a shape from a compound shape - * provided that the former was added to the later using AddCompoundChild() - */ -void CcdPhysicsController::RemoveCompoundChild(PHY_IPhysicsController* child) -{ - if (child == NULL || !IsCompound()) - return; - // other controller must be a bullet controller too - // verify that body and shape exist and match - CcdPhysicsController* childCtrl = dynamic_cast<CcdPhysicsController*>(child); - btRigidBody* rootBody = GetRigidBody(); - btRigidBody* childBody = childCtrl->GetRigidBody(); - if (!rootBody || !childBody) - return; - const btCollisionShape* rootShape = rootBody->getCollisionShape(); - if (!rootShape || - rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE) - return; - btCompoundShape* compoundShape = (btCompoundShape*)rootShape; - // retrieve the shapeInfo - CcdShapeConstructionInfo* childShapeInfo = childCtrl->GetShapeInfo(); - CcdShapeConstructionInfo* rootShapeInfo = GetShapeInfo(); - // and verify that the child is part of the parent - int i = rootShapeInfo->FindChildShape(childShapeInfo, childCtrl); - if (i < 0) - return; - rootShapeInfo->RemoveChildShape(i); - if (childCtrl->m_bulletChildShape) - { - int numChildren = compoundShape->getNumChildShapes(); - for (i=0; i<numChildren; i++) - { - if (compoundShape->getChildShape(i) == childCtrl->m_bulletChildShape) - { - compoundShape->removeChildShapeByIndex(i); - compoundShape->recalculateLocalAabb(); - break; - } - } - delete childCtrl->m_bulletChildShape; - childCtrl->m_bulletChildShape = NULL; - } - // recompute inertia of parent - if (!rootBody->isStaticOrKinematicObject()) - { - btVector3 localInertia; - float mass = 1.f/rootBody->getInvMass(); - compoundShape->calculateLocalInertia(mass,localInertia); - rootBody->setMassProps(mass,localInertia); - } - // must update the broadphase cache, - GetPhysicsEnvironment()->RefreshCcdPhysicsController(this); - // reactivate the children - GetPhysicsEnvironment()->AddCcdPhysicsController(childCtrl); -} - -PHY_IPhysicsController* CcdPhysicsController::GetReplica() -{ - CcdPhysicsController* replica = new CcdPhysicsController(*this); - return replica; -} - -// Keeping this separate for now, maybe we can combine it with GetReplica()... -PHY_IPhysicsController* CcdPhysicsController::GetReplicaForSensors() -{ - // This is used only to replicate Near and Radar sensor controllers - // The replication of object physics controller is done in KX_BulletPhysicsController::GetReplica() - CcdConstructionInfo cinfo = m_cci; - if (m_shapeInfo) - { - // This situation does not normally happen - cinfo.m_collisionShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin, m_cci.m_bGimpact, !m_cci.m_bSoft); - } - else if (m_collisionShape) - { - switch (m_collisionShape->getShapeType()) - { - case SPHERE_SHAPE_PROXYTYPE: - { - btSphereShape* orgShape = (btSphereShape*)m_collisionShape; - cinfo.m_collisionShape = new btSphereShape(*orgShape); - break; - } - - case CONE_SHAPE_PROXYTYPE: - { - btConeShape* orgShape = (btConeShape*)m_collisionShape; - cinfo.m_collisionShape = new btConeShape(*orgShape); - break; - } - - default: - { - return 0; - } - } - } - - cinfo.m_MotionState = new DefaultMotionState(); - cinfo.m_shapeInfo = m_shapeInfo; - - CcdPhysicsController* replica = new CcdPhysicsController(cinfo); - return replica; -} - -/* Refresh the physics object from either an object or a mesh. - * from_gameobj and from_meshobj can be NULL - * - * when setting the mesh, the following vars get priority - * 1) from_meshobj - creates the phys mesh from RAS_MeshObject - * 2) from_gameobj - creates the phys mesh from the DerivedMesh where possible, else the RAS_MeshObject - * 3) this - update the phys mesh from DerivedMesh or RAS_MeshObject - * - * Most of the logic behind this is in m_shapeInfo->UpdateMesh(...) - */ -bool CcdPhysicsController::ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject *from_meshobj) -{ - if (m_shapeInfo->m_shapeType != PHY_SHAPE_MESH) - return false; - - if (!from_gameobj && !from_meshobj) - from_gameobj = KX_GameObject::GetClientObject((KX_ClientObjectInfo*)GetNewClientInfo()); - - /* updates the arrays used for making the new bullet mesh */ - m_shapeInfo->UpdateMesh(from_gameobj, from_meshobj); - - /* create the new bullet mesh */ - GetPhysicsEnvironment()->UpdateCcdPhysicsControllerShape(m_shapeInfo); - - return true; -} - -void CcdPhysicsController::ReplicateConstraints(KX_GameObject *replica, std::vector<KX_GameObject*> constobj) -{ - if (replica->GetConstraints().size() == 0 || !replica->GetPhysicsController()) - return; - - PHY_IPhysicsEnvironment *physEnv = GetPhysicsEnvironment(); - - vector<bRigidBodyJointConstraint*> constraints = replica->GetConstraints(); - vector<bRigidBodyJointConstraint*>::iterator consit; - - /* Object could have some constraints, iterate over all of theme to ensure that every constraint is recreated. */ - for (consit = constraints.begin(); consit != constraints.end(); ++consit) { - /* Try to find the constraint targets in the list of group objects. */ - bRigidBodyJointConstraint *dat = (*consit); - vector<KX_GameObject*>::iterator memit; - for (memit = constobj.begin(); memit != constobj.end(); ++memit) { - KX_GameObject *member = (*memit); - /* If the group member is the actual target for the constraint. */ - if (dat->tar->id.name + 2 == member->GetName() && member->GetPhysicsController()) - physEnv->SetupObjectConstraints(replica, member, dat); - } - } - -} - -/////////////////////////////////////////////////////////// -///A small utility class, DefaultMotionState -/// -/////////////////////////////////////////////////////////// - -DefaultMotionState::DefaultMotionState() -{ - m_worldTransform.setIdentity(); - m_localScaling.setValue(1.f,1.f,1.f); -} - - -DefaultMotionState::~DefaultMotionState() -{ - -} - -void DefaultMotionState::GetWorldPosition(float& posX,float& posY,float& posZ) -{ - posX = m_worldTransform.getOrigin().x(); - posY = m_worldTransform.getOrigin().y(); - posZ = m_worldTransform.getOrigin().z(); -} - -void DefaultMotionState::GetWorldScaling(float& scaleX,float& scaleY,float& scaleZ) -{ - scaleX = m_localScaling.getX(); - scaleY = m_localScaling.getY(); - scaleZ = m_localScaling.getZ(); -} - -void DefaultMotionState::GetWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal) -{ - btQuaternion quat = m_worldTransform.getRotation(); - quatIma0 = quat.x(); - quatIma1 = quat.y(); - quatIma2 = quat.z(); - quatReal = quat[3]; -} - -void DefaultMotionState::GetWorldOrientation(float* ori) -{ - m_worldTransform.getBasis().getOpenGLSubMatrix(ori); -} - -void DefaultMotionState::SetWorldOrientation(const float* ori) -{ - m_worldTransform.getBasis().setFromOpenGLSubMatrix(ori); -} -void DefaultMotionState::SetWorldPosition(float posX,float posY,float posZ) -{ - btVector3 pos(posX,posY,posZ); - m_worldTransform.setOrigin( pos ); -} - -void DefaultMotionState::SetWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal) -{ - btQuaternion orn(quatIma0,quatIma1,quatIma2,quatReal); - m_worldTransform.setRotation( orn ); -} - -void DefaultMotionState::CalculateWorldTransformations() -{ - -} - -// Shape constructor -std::map<RAS_MeshObject*, CcdShapeConstructionInfo*> CcdShapeConstructionInfo::m_meshShapeMap; - -CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mesh, struct DerivedMesh* dm, bool polytope) -{ - if (polytope || dm) - // not yet supported - return NULL; - - std::map<RAS_MeshObject*,CcdShapeConstructionInfo*>::const_iterator mit = m_meshShapeMap.find(mesh); - if (mit != m_meshShapeMap.end()) - return mit->second; - return NULL; -} - -bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject *meshobj, DerivedMesh *dm, bool polytope) -{ - int numpolys, numverts; - - // assume no shape information - // no support for dynamic change of shape yet - assert(IsUnused()); - m_shapeType = PHY_SHAPE_NONE; - m_meshObject = NULL; - bool free_dm = false; - - // No mesh object or mesh has no polys - if (!meshobj || !meshobj->HasColliderPolygon()) { - m_vertexArray.clear(); - m_polygonIndexArray.clear(); - m_triFaceArray.clear(); - m_triFaceUVcoArray.clear(); - return false; - } - - if (!dm) { - free_dm = true; - dm = CDDM_from_mesh(meshobj->GetMesh()); - } - - // Some meshes with modifiers returns 0 polys, call DM_ensure_tessface avoid this. - DM_ensure_tessface(dm); - - MVert *mvert = dm->getVertArray(dm); - MFace *mface = dm->getTessFaceArray(dm); - numpolys = dm->getNumTessFaces(dm); - numverts = dm->getNumVerts(dm); - MTFace *tface = (MTFace *)dm->getTessFaceDataArray(dm, CD_MTFACE); - - /* double lookup */ - const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); - if (!index_mf_to_mpoly) { - index_mp_to_orig = NULL; - } - - m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH; - - /* Convert blender geometry into bullet mesh, need these vars for mapping */ - std::vector<bool> vert_tag_array(numverts, false); - unsigned int tot_bt_verts = 0; - - if (polytope) { - // Tag verts we're using - for (int p2 = 0; p2 < numpolys; p2++) { - MFace *mf = &mface[p2]; - const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; - RAS_Polygon *poly = (origi != ORIGINDEX_NONE) ? meshobj->GetPolygon(origi) : NULL; - - // only add polygons that have the collision flag set - if (poly && poly->IsCollider()) { - if (!vert_tag_array[mf->v1]) { - vert_tag_array[mf->v1] = true; - tot_bt_verts++; - } - if (!vert_tag_array[mf->v2]) { - vert_tag_array[mf->v2] = true; - tot_bt_verts++; - } - if (!vert_tag_array[mf->v3]) { - vert_tag_array[mf->v3] = true; - tot_bt_verts++; - } - if (mf->v4 && !vert_tag_array[mf->v4]) { - vert_tag_array[mf->v4] = true; - tot_bt_verts++; - } - } - } - - /* Can happen with ngons */ - if (!tot_bt_verts) { - goto cleanup_empty_mesh; - } - - m_vertexArray.resize(tot_bt_verts * 3); - - btScalar *bt = &m_vertexArray[0]; - - for (int p2 = 0; p2 < numpolys; p2++) { - MFace *mf = &mface[p2]; - const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; - RAS_Polygon *poly = (origi != ORIGINDEX_NONE) ? meshobj->GetPolygon(origi) : NULL; - - // only add polygons that have the collisionflag set - if (poly->IsCollider()) { - if (vert_tag_array[mf->v1]) { - const float *vtx = mvert[mf->v1].co; - vert_tag_array[mf->v1] = false; - *bt++ = vtx[0]; - *bt++ = vtx[1]; - *bt++ = vtx[2]; - } - if (vert_tag_array[mf->v2]) { - const float *vtx = mvert[mf->v2].co; - vert_tag_array[mf->v2] = false; - *bt++ = vtx[0]; - *bt++ = vtx[1]; - *bt++ = vtx[2]; - } - if (vert_tag_array[mf->v3]) { - const float *vtx = mvert[mf->v3].co; - vert_tag_array[mf->v3] = false; - *bt++ = vtx[0]; - *bt++ = vtx[1]; - *bt++ = vtx[2]; - } - if (mf->v4 && vert_tag_array[mf->v4]) { - const float *vtx = mvert[mf->v4].co; - vert_tag_array[mf->v4] = false; - *bt++ = vtx[0]; - *bt++ = vtx[1]; - *bt++ = vtx[2]; - } - } - } - } - else { - unsigned int tot_bt_tris = 0; - std::vector<int> vert_remap_array(numverts, 0); - - // Tag verts we're using - for (int p2 = 0; p2 < numpolys; p2++) { - MFace *mf = &mface[p2]; - const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; - RAS_Polygon *poly = (origi != ORIGINDEX_NONE) ? meshobj->GetPolygon(origi) : NULL; - - // only add polygons that have the collision flag set - if (poly && poly->IsCollider()) { - if (!vert_tag_array[mf->v1]) { - vert_tag_array[mf->v1] = true; - vert_remap_array[mf->v1] = tot_bt_verts; - tot_bt_verts++; - } - if (!vert_tag_array[mf->v2]) { - vert_tag_array[mf->v2] = true; - vert_remap_array[mf->v2] = tot_bt_verts; - tot_bt_verts++; - } - if (!vert_tag_array[mf->v3]) { - vert_tag_array[mf->v3] = true; - vert_remap_array[mf->v3] = tot_bt_verts; - tot_bt_verts++; - } - if (mf->v4 && !vert_tag_array[mf->v4]) { - vert_tag_array[mf->v4] = true; - vert_remap_array[mf->v4] = tot_bt_verts; - tot_bt_verts++; - } - tot_bt_tris += (mf->v4 ? 2 : 1); /* a quad or a tri */ - } - } - - /* Can happen with ngons */ - if (!tot_bt_verts) { - goto cleanup_empty_mesh; - } - - m_vertexArray.resize(tot_bt_verts * 3); - m_polygonIndexArray.resize(tot_bt_tris); - m_triFaceArray.resize(tot_bt_tris * 3); - btScalar *bt = &m_vertexArray[0]; - int *poly_index_pt = &m_polygonIndexArray[0]; - int *tri_pt = &m_triFaceArray[0]; - - UVco *uv_pt = NULL; - if (tface) { - m_triFaceUVcoArray.resize(tot_bt_tris * 3); - uv_pt = &m_triFaceUVcoArray[0]; - } - else - m_triFaceUVcoArray.clear(); - - for (int p2 = 0; p2 < numpolys; p2++) { - MFace *mf = &mface[p2]; - MTFace *tf = (tface) ? &tface[p2] : NULL; - const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; - RAS_Polygon *poly = (origi != ORIGINDEX_NONE) ? meshobj->GetPolygon(origi) : NULL; - - // only add polygons that have the collisionflag set - if (poly && poly->IsCollider()) { - MVert *v1 = &mvert[mf->v1]; - MVert *v2 = &mvert[mf->v2]; - MVert *v3 = &mvert[mf->v3]; - - // the face indices - tri_pt[0] = vert_remap_array[mf->v1]; - tri_pt[1] = vert_remap_array[mf->v2]; - tri_pt[2] = vert_remap_array[mf->v3]; - tri_pt = tri_pt + 3; - if (tf) { - uv_pt[0].uv[0] = tf->uv[0][0]; - uv_pt[0].uv[1] = tf->uv[0][1]; - uv_pt[1].uv[0] = tf->uv[1][0]; - uv_pt[1].uv[1] = tf->uv[1][1]; - uv_pt[2].uv[0] = tf->uv[2][0]; - uv_pt[2].uv[1] = tf->uv[2][1]; - uv_pt += 3; - } - - // m_polygonIndexArray - *poly_index_pt = origi; - poly_index_pt++; - - // the vertex location - if (vert_tag_array[mf->v1]) { /* *** v1 *** */ - vert_tag_array[mf->v1] = false; - *bt++ = v1->co[0]; - *bt++ = v1->co[1]; - *bt++ = v1->co[2]; - } - if (vert_tag_array[mf->v2]) { /* *** v2 *** */ - vert_tag_array[mf->v2] = false; - *bt++ = v2->co[0]; - *bt++ = v2->co[1]; - *bt++ = v2->co[2]; - } - if (vert_tag_array[mf->v3]) { /* *** v3 *** */ - vert_tag_array[mf->v3] = false; - *bt++ = v3->co[0]; - *bt++ = v3->co[1]; - *bt++ = v3->co[2]; - } - - if (mf->v4) - { - MVert *v4 = &mvert[mf->v4]; - - tri_pt[0] = vert_remap_array[mf->v1]; - tri_pt[1] = vert_remap_array[mf->v3]; - tri_pt[2] = vert_remap_array[mf->v4]; - tri_pt = tri_pt + 3; - if (tf) - { - uv_pt[0].uv[0] = tf->uv[0][0]; - uv_pt[0].uv[1] = tf->uv[0][1]; - uv_pt[1].uv[0] = tf->uv[2][0]; - uv_pt[1].uv[1] = tf->uv[2][1]; - uv_pt[2].uv[0] = tf->uv[3][0]; - uv_pt[2].uv[1] = tf->uv[3][1]; - uv_pt += 3; - } - - // m_polygonIndexArray - *poly_index_pt = origi; - poly_index_pt++; - - // the vertex location - if (vert_tag_array[mf->v4]) { /* *** v4 *** */ - vert_tag_array[mf->v4] = false; - *bt++ = v4->co[0]; - *bt++ = v4->co[1]; - *bt++ = v4->co[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()); - } - - 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 0 - if (validpolys == false) - { - // should not happen - m_shapeType = PHY_SHAPE_NONE; - return false; - } -#endif - - m_meshObject = meshobj; - if (free_dm) { - dm->release(dm); - dm = NULL; - } - - // sharing only on static mesh at present, if you change that, you must also change in FindMesh - if (!polytope && !dm) { - // triangle shape can be shared, store the mesh object in the map - m_meshShapeMap.insert(std::pair<RAS_MeshObject *, CcdShapeConstructionInfo *>(meshobj, this)); - } - return true; - - -cleanup_empty_mesh: - m_shapeType = PHY_SHAPE_NONE; - m_meshObject = NULL; - m_vertexArray.clear(); - m_polygonIndexArray.clear(); - m_triFaceArray.clear(); - m_triFaceUVcoArray.clear(); - if (free_dm) { - dm->release(dm); - } - return false; -} - -#include <cstdio> - -/* Updates the arrays used by CreateBulletShape(), - * take care that recalcLocalAabb() runs after CreateBulletShape is called. - * */ -bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RAS_MeshObject *meshobj) -{ - int numpolys; - int numverts; - - unsigned int tot_bt_tris = 0; - unsigned int tot_bt_verts = 0; - - int i, j; - int v_orig; - - /* Use for looping over verts in a face as a try or 2 tris */ - const int quad_verts[7] = {0, 1, 2, 0, 2, 3, -1}; - const int tri_verts[4] = {0, 1, 2, -1}; - const int *fv_pt; - - if (!gameobj && !meshobj) - return false; - - if (m_shapeType != PHY_SHAPE_MESH) - return false; - - RAS_Deformer *deformer = gameobj ? gameobj->GetDeformer() : NULL; - DerivedMesh *dm = NULL; - - if (deformer) - dm = deformer->GetPhysicsMesh(); - - /* get the mesh from the object if not defined */ - if (!meshobj) { - /* modifier mesh */ - if (dm) - meshobj = deformer->GetRasMesh(); - - /* game object first mesh */ - if (!meshobj) { - if (gameobj->GetMeshCount() > 0) { - meshobj = gameobj->GetMesh(0); - } - } - } - - if (dm && deformer->GetRasMesh() == meshobj) { - /* - * Derived Mesh Update - * - * */ - - MVert *mvert = dm->getVertArray(dm); - MFace *mface = dm->getTessFaceArray(dm); - numpolys = dm->getNumTessFaces(dm); - numverts = dm->getNumVerts(dm); - - /* double lookup */ - const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); - if (!index_mf_to_mpoly) { - index_mp_to_orig = NULL; - } - - MFace *mf; - MVert *mv; - - if (CustomData_has_layer(&dm->faceData, CD_MTFACE)) { - MTFace *tface = (MTFace *)dm->getTessFaceDataArray(dm, CD_MTFACE); - MTFace *tf; - - std::vector<bool> vert_tag_array(numverts, false); - std::vector<int> vert_remap_array(numverts, 0); - - for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) { - // 2.8x TODO: use GEMAT_NOPHYSICS. - // if (tf->mode & TF_DYNAMIC) - { - int flen; - - if (mf->v4) { - tot_bt_tris += 2; - flen = 4; - } - else { - tot_bt_tris++; - flen = 3; - } - - for (j = 0; j < flen; j++) { - v_orig = (*(&mf->v1 + j)); - - if (!vert_tag_array[v_orig]) { - vert_tag_array[v_orig] = true; - vert_remap_array[v_orig] = tot_bt_verts; - tot_bt_verts++; - } - } - } - } - - m_vertexArray.resize(tot_bt_verts * 3); - btScalar *bt = &m_vertexArray[0]; - - m_triFaceArray.resize(tot_bt_tris * 3); - int *tri_pt = &m_triFaceArray[0]; - - m_triFaceUVcoArray.resize(tot_bt_tris * 3); - UVco *uv_pt = &m_triFaceUVcoArray[0]; - - m_polygonIndexArray.resize(tot_bt_tris); - int *poly_index_pt = &m_polygonIndexArray[0]; - - for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) { - // 2.8x TODO: use GEMAT_NOPHYSICS. - // if (tf->mode & TF_DYNAMIC) - { - int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i; - - if (mf->v4) { - fv_pt = quad_verts; - *poly_index_pt++ = origi; - *poly_index_pt++ = origi; - } - else { - fv_pt = tri_verts; - *poly_index_pt++ = origi; - } - - for (; *fv_pt > -1; fv_pt++) { - v_orig = (*(&mf->v1 + (*fv_pt))); - - if (vert_tag_array[v_orig]) - { - mv = mvert + v_orig; - *bt++ = mv->co[0]; - *bt++ = mv->co[1]; - *bt++ = mv->co[2]; - - vert_tag_array[v_orig] = false; - } - *tri_pt++ = vert_remap_array[v_orig]; - uv_pt->uv[0] = tf->uv[*fv_pt][0]; - uv_pt->uv[1] = tf->uv[*fv_pt][1]; - uv_pt++; - } - } - } - } - else { - /* no need for a vertex mapping. simple/fast */ - - tot_bt_verts = numverts; - - for (mf = mface, i = 0; i < numpolys; mf++, i++) { - tot_bt_tris += (mf->v4 ? 2 : 1); - } - - m_vertexArray.resize(tot_bt_verts * 3); - btScalar *bt = &m_vertexArray[0]; - - m_triFaceArray.resize(tot_bt_tris * 3); - int *tri_pt = &m_triFaceArray[0]; - - m_polygonIndexArray.resize(tot_bt_tris); - int *poly_index_pt = &m_polygonIndexArray[0]; - - m_triFaceUVcoArray.clear(); - - for (mv = mvert, i = 0; i < numverts; mv++, i++) { - *bt++ = mv->co[0]; *bt++ = mv->co[1]; *bt++ = mv->co[2]; - } - - for (mf = mface, i = 0; i < numpolys; mf++, i++) { - int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i; - - if (mf->v4) { - fv_pt = quad_verts; - *poly_index_pt++ = origi; - *poly_index_pt++ = origi; - } - else { - fv_pt = tri_verts; - *poly_index_pt++ = origi; - } - - for (; *fv_pt > -1; fv_pt++) - *tri_pt++ = (*(&mf->v1 + (*fv_pt))); - } - } - } - else { /* - * RAS Mesh Update - * - * */ - /* Note!, gameobj can be NULL here */ - - /* transverts are only used for deformed RAS_Meshes, the RAS_TexVert data - * is too hard to get at, see below for details */ - float(*transverts)[3] = NULL; - int transverts_tot = 0; /* with deformed meshes - should always be greater than the max orginal index, or we get crashes */ - - if (deformer) { - /* map locations from the deformed array - * - * Could call deformer->Update(); but rely on redraw updating. - * */ - transverts = deformer->GetTransVerts(&transverts_tot); - } - - // Tag verts we're using - numpolys = meshobj->NumPolygons(); - numverts = meshobj->m_sharedvertex_map.size(); - const float *xyz; - - - std::vector<bool> vert_tag_array(numverts, false); - std::vector<int> vert_remap_array(numverts, 0); - - for (int p = 0; p < numpolys; p++) { - RAS_Polygon *poly = meshobj->GetPolygon(p); - if (poly->IsCollider()) { - for (i = 0; i < poly->VertexCount(); i++) { - v_orig = poly->GetVertex(i)->getOrigIndex(); - if (!vert_tag_array[v_orig]) { - vert_tag_array[v_orig] = true; - vert_remap_array[v_orig] = tot_bt_verts; - tot_bt_verts++; - } - } - tot_bt_tris += (poly->VertexCount() == 4 ? 2 : 1); - } - } - - // This case happens when none of the polys are colliders - if (tot_bt_tris == 0 || tot_bt_verts == 0) - return false; - - m_vertexArray.resize(tot_bt_verts * 3); - btScalar *bt = &m_vertexArray[0]; - - m_triFaceArray.resize(tot_bt_tris * 3); - int *tri_pt = &m_triFaceArray[0]; - - /* cant be used for anything useful in this case, since we don't rely on the original mesh - * will just be an array like pythons range(tot_bt_tris) */ - m_polygonIndexArray.resize(tot_bt_tris); - - - int p = 0; - int t = 0; - while (t < tot_bt_tris) { - RAS_Polygon *poly = meshobj->GetPolygon(p); - - if (poly->IsCollider()) { - /* quad or tri loop */ - fv_pt = (poly->VertexCount() == 3 ? tri_verts : quad_verts); - - for (; *fv_pt > -1; fv_pt++) { - v_orig = poly->GetVertex(*fv_pt)->getOrigIndex(); - if (vert_tag_array[v_orig]) { - if (transverts) { - /* deformed mesh, using RAS_TexVert locations would be too troublesome - * because they are use the gameob as a hash in the material slot */ - *bt++ = transverts[v_orig][0]; - *bt++ = transverts[v_orig][1]; - *bt++ = transverts[v_orig][2]; - } - else { - /* static mesh python may have modified */ - xyz = meshobj->GetVertexLocation(v_orig); - *bt++ = xyz[0]; - *bt++ = xyz[1]; - *bt++ = xyz[2]; - } - vert_tag_array[v_orig] = false; - } - *tri_pt++ = vert_remap_array[v_orig]; - } - } - // first triangle - m_polygonIndexArray[t] = p; - - // if the poly is a quad we transform it in two triangles - if (poly->VertexCount() == 4) { - t++; - // second triangle - m_polygonIndexArray[t] = p; - } - t++; - p++; - } - } - -#if 0 - /* needs #include <cstdio> */ - printf("# vert count %d\n", m_vertexArray.size()); - for (int i = 0; i < m_vertexArray.size(); i += 3) { - printf("v %.6f %.6f %.6f\n", m_vertexArray[i], m_vertexArray[i + 1], m_vertexArray[i + 2]); - } - - printf("# face count %d\n", m_triFaceArray.size()); - for (int 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 - - /* force recreation of the m_triangleIndexVertexArray. - * If this has multiple users we cant delete */ - if (m_triangleIndexVertexArray) { - m_forceReInstance = true; - } - - // Make sure to also replace the mesh in the shape map! Otherwise we leave dangling references when we free. - // Note, this whole business could cause issues with shared meshes. If we update one mesh, do we replace - // them all? - std::map<RAS_MeshObject *, CcdShapeConstructionInfo *>::iterator mit = m_meshShapeMap.find(m_meshObject); - if (mit != m_meshShapeMap.end()) { - m_meshShapeMap.erase(mit); - m_meshShapeMap[meshobj] = this; - } - - m_meshObject = meshobj; - - if (dm) { - dm->needsFree = 1; - dm->release(dm); - } - return true; -} - -bool CcdShapeConstructionInfo::SetProxy(CcdShapeConstructionInfo* shapeInfo) -{ - if (shapeInfo == NULL) - return false; - // no support for dynamic change - assert(IsUnused()); - m_shapeType = PHY_SHAPE_PROXY; - m_shapeProxy = shapeInfo; - return true; -} - -btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin, bool useGimpact, bool useBvh) -{ - btCollisionShape* collisionShape = 0; - btCompoundShape* compoundShape = 0; - - if (m_shapeType == PHY_SHAPE_PROXY && m_shapeProxy != NULL) - return m_shapeProxy->CreateBulletShape(margin, useGimpact, useBvh); - - switch (m_shapeType) - { - default: - break; - - case PHY_SHAPE_BOX: - collisionShape = new btBoxShape(m_halfExtend); - collisionShape->setMargin(margin); - break; - - case PHY_SHAPE_SPHERE: - collisionShape = new btSphereShape(m_radius); - collisionShape->setMargin(margin); - break; - - case PHY_SHAPE_CYLINDER: - collisionShape = new btCylinderShapeZ(m_halfExtend); - collisionShape->setMargin(margin); - break; - - case PHY_SHAPE_CONE: - collisionShape = new btConeShapeZ(m_radius, m_height); - collisionShape->setMargin(margin); - break; - - case PHY_SHAPE_POLYTOPE: - collisionShape = new btConvexHullShape(&m_vertexArray[0], m_vertexArray.size()/3, 3*sizeof(btScalar)); - collisionShape->setMargin(margin); - break; - - case PHY_SHAPE_CAPSULE: - collisionShape = new btCapsuleShapeZ(m_radius, m_height); - collisionShape->setMargin(margin); - break; - - case PHY_SHAPE_MESH: - // Let's use the latest btScaledBvhTriangleMeshShape: it allows true sharing of - // triangle mesh information between duplicates => drastic performance increase when - // duplicating complex mesh objects. - // BUT it causes a small performance decrease when sharing is not required: - // 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 (useGimpact) { - if (!m_triangleIndexVertexArray || m_forceReInstance) { - if (m_triangleIndexVertexArray) - delete m_triangleIndexVertexArray; - - m_triangleIndexVertexArray = new btTriangleIndexVertexArray( - m_polygonIndexArray.size(), - m_triFaceArray.data(), - 3 * sizeof(int), - m_vertexArray.size() / 3, - &m_vertexArray[0], - 3 * sizeof(btScalar)); - m_forceReInstance = false; - } - - btGImpactMeshShape *gimpactShape = new btGImpactMeshShape(m_triangleIndexVertexArray); - gimpactShape->setMargin(margin); - gimpactShape->updateBound(); - collisionShape = gimpactShape; - } - else { - if (!m_triangleIndexVertexArray || m_forceReInstance) { - ///enable welding, only for the objects that need it (such as soft bodies) - if (0.0f != m_weldingThreshold1) { - 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 (unsigned int i = 0; i < m_triFaceArray.size(); i += 3) { - btScalar *bt = &m_vertexArray[3 * m_triFaceArray[i]]; - btVector3 v1(bt[0], bt[1], bt[2]); - bt = &m_vertexArray[3 * m_triFaceArray[i + 1]]; - btVector3 v2(bt[0], bt[1], bt[2]); - bt = &m_vertexArray[3 * m_triFaceArray[i + 2]]; - btVector3 v3(bt[0], bt[1], bt[2]); - collisionMeshData->addTriangle(v1, v2, v3, removeDuplicateVertices); - } - m_triangleIndexVertexArray = collisionMeshData; - } - else { - m_triangleIndexVertexArray = new btTriangleIndexVertexArray( - m_polygonIndexArray.size(), - m_triFaceArray.data(), - 3 * sizeof(int), - m_vertexArray.size() / 3, - &m_vertexArray[0], - 3 * sizeof(btScalar)); - } - - m_forceReInstance = false; - } - - btBvhTriangleMeshShape *unscaledShape = new btBvhTriangleMeshShape(m_triangleIndexVertexArray, true, useBvh); - unscaledShape->setMargin(margin); - collisionShape = new btScaledBvhTriangleMeshShape(unscaledShape, btVector3(1.0f, 1.0f, 1.0f)); - collisionShape->setMargin(margin); - } - break; - - case PHY_SHAPE_COMPOUND: - if (m_shapeArray.size() > 0) - { - compoundShape = new btCompoundShape(); - for (std::vector<CcdShapeConstructionInfo*>::iterator sit = m_shapeArray.begin(); - sit != m_shapeArray.end(); - sit++) - { - collisionShape = (*sit)->CreateBulletShape(margin, useGimpact, useBvh); - if (collisionShape) - { - collisionShape->setLocalScaling((*sit)->m_childScale); - compoundShape->addChildShape((*sit)->m_childTrans, collisionShape); - } - } - collisionShape = compoundShape; - } - break; - } - return collisionShape; -} - -void CcdShapeConstructionInfo::AddShape(CcdShapeConstructionInfo* shapeInfo) -{ - m_shapeArray.push_back(shapeInfo); - shapeInfo->AddRef(); -} - -CcdShapeConstructionInfo::~CcdShapeConstructionInfo() -{ - for (std::vector<CcdShapeConstructionInfo*>::iterator sit = m_shapeArray.begin(); - sit != m_shapeArray.end(); - sit++) - { - (*sit)->Release(); - } - m_shapeArray.clear(); - - if (m_triangleIndexVertexArray) - delete m_triangleIndexVertexArray; - m_vertexArray.clear(); - if (m_shapeType == PHY_SHAPE_MESH && m_meshObject != NULL) - { - std::map<RAS_MeshObject*,CcdShapeConstructionInfo*>::iterator mit = m_meshShapeMap.find(m_meshObject); - if (mit != m_meshShapeMap.end() && mit->second == this) - { - m_meshShapeMap.erase(mit); - } - } - if (m_shapeType == PHY_SHAPE_PROXY && m_shapeProxy != NULL) - { - m_shapeProxy->Release(); - } -} - |