void CcdPhysicsEnvironment::setGravity(float x,float y,float z) { m_gravity = SimdVector3(x,y,z); std::vector<CcdPhysicsController*>::iterator i; //todo: review this gravity stuff for (i=m_controllers.begin(); !(i==m_controllers.end()); i++) { CcdPhysicsController* ctrl = (*i); ctrl->GetRigidBody()->setGravity(m_gravity); } }
void SimulationIsland::UpdateAabbs(IDebugDraw* debugDrawer,BroadphaseInterface* scene,float timeStep) { std::vector<CcdPhysicsController*>::iterator i; // // update aabbs, only for moving objects (!) // for (i=m_controllers.begin(); !(i==m_controllers.end()); i++) { CcdPhysicsController* ctrl = (*i); RigidBody* body = ctrl->GetRigidBody(); SimdPoint3 minAabb,maxAabb; CollisionShape* shapeinterface = ctrl->GetCollisionShape(); shapeinterface->CalculateTemporalAabb(body->getCenterOfMassTransform(), body->getLinearVelocity(), //body->getAngularVelocity(), SimdVector3(0.f,0.f,0.f),//no angular effect for now //body->getAngularVelocity(), timeStep,minAabb,maxAabb); SimdVector3 manifoldExtraExtents(gContactBreakingTreshold,gContactBreakingTreshold,gContactBreakingTreshold); minAabb -= manifoldExtraExtents; maxAabb += manifoldExtraExtents; BroadphaseProxy* bp = body->m_broadphaseHandle; if (bp) { SimdVector3 color (1,1,0); class IDebugDraw* m_debugDrawer = 0; /* if (m_debugDrawer) { //draw aabb switch (body->GetActivationState()) { case ISLAND_SLEEPING: { color.setValue(1,1,1); break; } case WANTS_DEACTIVATION: { color.setValue(0,0,1); break; } case ACTIVE_TAG: { break; } case DISABLE_DEACTIVATION: { color.setValue(1,0,1); }; }; if (m_debugDrawer->GetDebugMode() & IDebugDraw::DBG_DrawAabb) { DrawAabb(m_debugDrawer,minAabb,maxAabb,color); } } */ if ( (maxAabb-minAabb).length2() < 1e12f) { scene->SetAabb(bp,minAabb,maxAabb); } else { //something went wrong, investigate //removeCcdPhysicsController(ctrl); body->SetActivationState(DISABLE_SIMULATION); static bool reportMe = true; if (reportMe) { reportMe = false; printf("Overflow in AABB, object removed from simulation \n"); printf("If you can reproduce this, please email [email protected]\n"); printf("Please include above information, your Platform, version of OS.\n"); printf("Thanks.\n"); } } } } }
bool SimulationIsland::Simulate(IDebugDraw* debugDrawer,int numSolverIterations,TypedConstraint** constraintsBaseAddress,BroadphasePair* overlappingPairBaseAddress, Dispatcher* dispatcher,BroadphaseInterface* broadphase,class ConstraintSolver* solver,float timeStep) { #ifdef USE_QUICKPROF Profiler::beginBlock("predictIntegratedTransform"); #endif //USE_QUICKPROF { // std::vector<CcdPhysicsController*>::iterator i; int k; for (k=0;k<GetNumControllers();k++) { CcdPhysicsController* ctrl = m_controllers[k]; // SimdTransform predictedTrans; RigidBody* body = ctrl->GetRigidBody(); //todo: only do this when necessary, it's used for contact points body->m_cachedInvertedWorldTransform = body->m_worldTransform.inverse(); if (body->IsActive()) { if (!body->IsStatic()) { body->applyForces( timeStep); body->integrateVelocities( timeStep); body->predictIntegratedTransform(timeStep,body->m_interpolationWorldTransform); } } } } #ifdef USE_QUICKPROF Profiler::endBlock("predictIntegratedTransform"); #endif //USE_QUICKPROF //BroadphaseInterface* scene = GetBroadphase(); // // collision detection (?) // #ifdef USE_QUICKPROF Profiler::beginBlock("DispatchAllCollisionPairs"); #endif //USE_QUICKPROF // int numsubstep = m_numIterations; DispatcherInfo dispatchInfo; dispatchInfo.m_timeStep = timeStep; dispatchInfo.m_stepCount = 0; dispatchInfo.m_enableSatConvex = false;//m_enableSatCollisionDetection; dispatchInfo.m_debugDraw = debugDrawer; std::vector<BroadphasePair> overlappingPairs; overlappingPairs.resize(this->m_overlappingPairIndices.size()); //gather overlapping pair info int i; for (i=0;i<m_overlappingPairIndices.size();i++) { overlappingPairs[i] = overlappingPairBaseAddress[m_overlappingPairIndices[i]]; } //pairCache->RefreshOverlappingPairs(); if (overlappingPairs.size()) { dispatcher->DispatchAllCollisionPairs(&overlappingPairs[0],overlappingPairs.size(),dispatchInfo);///numsubstep,g); } //scatter overlapping pair info, mainly the created algorithms/contact caches for (i=0;i<m_overlappingPairIndices.size();i++) { overlappingPairBaseAddress[m_overlappingPairIndices[i]] = overlappingPairs[i]; } #ifdef USE_QUICKPROF Profiler::endBlock("DispatchAllCollisionPairs"); #endif //USE_QUICKPROF int numRigidBodies = m_controllers.size(); //contacts #ifdef USE_QUICKPROF Profiler::beginBlock("SolveConstraint"); #endif //USE_QUICKPROF //solve the regular constraints (point 2 point, hinge, etc) for (int g=0;g<numSolverIterations;g++) { // // constraint solving // int i; int numConstraints = m_constraintIndices.size(); //point to point constraints for (i=0;i< numConstraints ; i++ ) { TypedConstraint* constraint = constraintsBaseAddress[m_constraintIndices[i]]; constraint->BuildJacobian(); constraint->SolveConstraint( timeStep ); } } #ifdef USE_QUICKPROF Profiler::endBlock("SolveConstraint"); #endif //USE_QUICKPROF /* //solve the vehicles #ifdef NEW_BULLET_VEHICLE_SUPPORT //vehicles int numVehicles = m_wrapperVehicles.size(); for (int i=0;i<numVehicles;i++) { WrapperVehicle* wrapperVehicle = m_wrapperVehicles[i]; RaycastVehicle* vehicle = wrapperVehicle->GetVehicle(); vehicle->UpdateVehicle( timeStep); } #endif //NEW_BULLET_VEHICLE_SUPPORT */ /* Profiler::beginBlock("CallbackTriggers"); #endif //USE_QUICKPROF CallbackTriggers(); #ifdef USE_QUICKPROF Profiler::endBlock("CallbackTriggers"); } */ //OverlappingPairCache* scene = GetCollisionWorld()->GetPairCache(); ContactSolverInfo solverInfo; solverInfo.m_friction = 0.9f; solverInfo.m_numIterations = numSolverIterations; solverInfo.m_timeStep = timeStep; solverInfo.m_restitution = 0.f;//m_restitution; if (m_manifolds.size()) { solver->SolveGroup( &m_manifolds[0],m_manifolds.size(),solverInfo,0); } #ifdef USE_QUICKPROF Profiler::beginBlock("proceedToTransform"); #endif //USE_QUICKPROF { { UpdateAabbs(debugDrawer,broadphase,timeStep); float toi = 1.f; //experimental continuous collision detection /* if (m_ccdMode == 3) { DispatcherInfo dispatchInfo; dispatchInfo.m_timeStep = timeStep; dispatchInfo.m_stepCount = 0; dispatchInfo.m_dispatchFunc = DispatcherInfo::DISPATCH_CONTINUOUS; // GetCollisionWorld()->GetDispatcher()->DispatchAllCollisionPairs(scene,dispatchInfo); toi = dispatchInfo.m_timeOfImpact; } */ // // integrating solution // { std::vector<CcdPhysicsController*>::iterator i; for (i=m_controllers.begin(); !(i==m_controllers.end()); i++) { CcdPhysicsController* ctrl = *i; SimdTransform predictedTrans; RigidBody* body = ctrl->GetRigidBody(); if (body->IsActive()) { if (!body->IsStatic()) { body->predictIntegratedTransform(timeStep* toi, predictedTrans); body->proceedToTransform( predictedTrans); } } } } // // disable sleeping physics objects // std::vector<CcdPhysicsController*> m_sleepingControllers; std::vector<CcdPhysicsController*>::iterator i; for (i=m_controllers.begin(); !(i==m_controllers.end()); i++) { CcdPhysicsController* ctrl = (*i); RigidBody* body = ctrl->GetRigidBody(); ctrl->UpdateDeactivation(timeStep); if (ctrl->wantsSleeping()) { if (body->GetActivationState() == ACTIVE_TAG) body->SetActivationState( WANTS_DEACTIVATION ); } else { if (body->GetActivationState() != DISABLE_DEACTIVATION) body->SetActivationState( ACTIVE_TAG ); } if (true) { if (body->GetActivationState() == ISLAND_SLEEPING) { m_sleepingControllers.push_back(ctrl); } } else { if (ctrl->wantsSleeping()) { m_sleepingControllers.push_back(ctrl); } } } } #ifdef USE_QUICKPROF Profiler::endBlock("proceedToTransform"); Profiler::beginBlock("SyncMotionStates"); #endif //USE_QUICKPROF SyncMotionStates(timeStep); #ifdef USE_QUICKPROF Profiler::endBlock("SyncMotionStates"); #endif //USE_QUICKPROF #ifdef NEW_BULLET_VEHICLE_SUPPORT //sync wheels for vehicles int numVehicles = m_wrapperVehicles.size(); for (int i=0;i<numVehicles;i++) { WrapperVehicle* wrapperVehicle = m_wrapperVehicles[i]; wrapperVehicle->SyncWheels(); } #endif //NEW_BULLET_VEHICLE_SUPPORT return true; } }
void KX_ConvertBulletObject( class KX_GameObject* gameobj, class RAS_MeshObject* meshobj, struct DerivedMesh* dm, class KX_Scene* kxscene, struct PHY_ShapeProps* shapeprops, struct PHY_MaterialProps* smmaterial, struct KX_ObjectProperties* objprop) { CcdPhysicsEnvironment* env = (CcdPhysicsEnvironment*)kxscene->GetPhysicsEnvironment(); assert(env); bool isbulletdyna = false; bool isbulletsensor = false; bool isbulletchar = false; bool useGimpact = false; CcdConstructionInfo ci; class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode()); class CcdShapeConstructionInfo *shapeInfo = new CcdShapeConstructionInfo(); if (!objprop->m_dyna) { ci.m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT; } if (objprop->m_ghost) { ci.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE; } ci.m_MotionState = motionstate; ci.m_gravity = btVector3(0,0,0); ci.m_linearFactor = btVector3(objprop->m_lockXaxis? 0 : 1, objprop->m_lockYaxis? 0 : 1, objprop->m_lockZaxis? 0 : 1); ci.m_angularFactor = btVector3(objprop->m_lockXRotaxis? 0 : 1, objprop->m_lockYRotaxis? 0 : 1, objprop->m_lockZRotaxis? 0 : 1); ci.m_localInertiaTensor =btVector3(0,0,0); ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f; ci.m_clamp_vel_min = shapeprops->m_clamp_vel_min; ci.m_clamp_vel_max = shapeprops->m_clamp_vel_max; ci.m_margin = objprop->m_margin; ci.m_stepHeight = objprop->m_character ? shapeprops->m_step_height : 0.f; ci.m_jumpSpeed = objprop->m_character ? shapeprops->m_jump_speed : 0.f; ci.m_fallSpeed = objprop->m_character ? shapeprops->m_fall_speed : 0.f; shapeInfo->m_radius = objprop->m_radius; isbulletdyna = objprop->m_dyna; isbulletsensor = objprop->m_sensor; isbulletchar = objprop->m_character; useGimpact = ((isbulletdyna || isbulletsensor) && !objprop->m_softbody); ci.m_localInertiaTensor = btVector3(ci.m_mass/3.f,ci.m_mass/3.f,ci.m_mass/3.f); btCollisionShape* bm = 0; switch (objprop->m_boundclass) { case KX_BOUNDSPHERE: { //float radius = objprop->m_radius; //btVector3 inertiaHalfExtents ( // radius, // radius, // radius); //blender doesn't support multisphere, but for testing: //bm = new MultiSphereShape(inertiaHalfExtents,,&trans.getOrigin(),&radius,1); shapeInfo->m_shapeType = PHY_SHAPE_SPHERE; bm = shapeInfo->CreateBulletShape(ci.m_margin); break; }; case KX_BOUNDBOX: { shapeInfo->m_halfExtend.setValue( objprop->m_boundobject.box.m_extends[0], objprop->m_boundobject.box.m_extends[1], objprop->m_boundobject.box.m_extends[2]); shapeInfo->m_halfExtend /= 2.0; shapeInfo->m_halfExtend = shapeInfo->m_halfExtend.absolute(); shapeInfo->m_shapeType = PHY_SHAPE_BOX; bm = shapeInfo->CreateBulletShape(ci.m_margin); break; }; case KX_BOUNDCYLINDER: { shapeInfo->m_halfExtend.setValue( objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height * 0.5f ); shapeInfo->m_shapeType = PHY_SHAPE_CYLINDER; bm = shapeInfo->CreateBulletShape(ci.m_margin); break; } case KX_BOUNDCONE: { shapeInfo->m_radius = objprop->m_boundobject.c.m_radius; shapeInfo->m_height = objprop->m_boundobject.c.m_height; shapeInfo->m_shapeType = PHY_SHAPE_CONE; bm = shapeInfo->CreateBulletShape(ci.m_margin); break; } case KX_BOUNDPOLYTOPE: { shapeInfo->SetMesh(meshobj, dm,true); bm = shapeInfo->CreateBulletShape(ci.m_margin); break; } case KX_BOUNDCAPSULE: { shapeInfo->m_radius = objprop->m_boundobject.c.m_radius; shapeInfo->m_height = objprop->m_boundobject.c.m_height; shapeInfo->m_shapeType = PHY_SHAPE_CAPSULE; bm = shapeInfo->CreateBulletShape(ci.m_margin); break; } case KX_BOUNDMESH: { // mesh shapes can be shared, check first if we already have a shape on that mesh class CcdShapeConstructionInfo *sharedShapeInfo = CcdShapeConstructionInfo::FindMesh(meshobj, dm, false); if (sharedShapeInfo != NULL) { shapeInfo->Release(); shapeInfo = sharedShapeInfo; shapeInfo->AddRef(); } else { shapeInfo->SetMesh(meshobj, dm, false); } // Soft bodies can benefit from welding, don't do it on non-soft bodies if (objprop->m_softbody) { shapeInfo->setVertexWeldingThreshold1(objprop->m_soft_welding); //todo: expose this to the UI } bm = shapeInfo->CreateBulletShape(ci.m_margin, useGimpact, !objprop->m_softbody); //should we compute inertia for dynamic shape? //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor); break; } case KX_BOUND_DYN_MESH: /* do nothing */ break; } // ci.m_localInertiaTensor.setValue(0.1f,0.1f,0.1f); if (!bm) { delete motionstate; shapeInfo->Release(); return; } //bm->setMargin(ci.m_margin); if (objprop->m_isCompoundChild) { //find parent, compound shape and add to it //take relative transform into account! CcdPhysicsController* parentCtrl = (CcdPhysicsController*)objprop->m_dynamic_parent->GetPhysicsController(); assert(parentCtrl); CcdShapeConstructionInfo* parentShapeInfo = parentCtrl->GetShapeInfo(); btRigidBody* rigidbody = parentCtrl->GetRigidBody(); btCollisionShape* colShape = rigidbody->getCollisionShape(); assert(colShape->isCompound()); btCompoundShape* compoundShape = (btCompoundShape*)colShape; // compute the local transform from parent, this may include several node in the chain SG_Node* gameNode = gameobj->GetSGNode(); SG_Node* parentNode = objprop->m_dynamic_parent->GetSGNode(); // relative transform MT_Vector3 parentScale = parentNode->GetWorldScaling(); parentScale[0] = MT_Scalar(1.0)/parentScale[0]; parentScale[1] = MT_Scalar(1.0)/parentScale[1]; parentScale[2] = MT_Scalar(1.0)/parentScale[2]; MT_Vector3 relativeScale = gameNode->GetWorldScaling() * parentScale; MT_Matrix3x3 parentInvRot = parentNode->GetWorldOrientation().transposed(); MT_Vector3 relativePos = parentInvRot*((gameNode->GetWorldPosition()-parentNode->GetWorldPosition())*parentScale); MT_Matrix3x3 relativeRot = parentInvRot*gameNode->GetWorldOrientation(); shapeInfo->m_childScale.setValue(relativeScale[0],relativeScale[1],relativeScale[2]); bm->setLocalScaling(shapeInfo->m_childScale); shapeInfo->m_childTrans.getOrigin().setValue(relativePos[0],relativePos[1],relativePos[2]); float rot[12]; relativeRot.getValue(rot); shapeInfo->m_childTrans.getBasis().setFromOpenGLSubMatrix(rot); parentShapeInfo->AddShape(shapeInfo); compoundShape->addChildShape(shapeInfo->m_childTrans,bm); //do some recalc? //recalc inertia for rigidbody if (!rigidbody->isStaticOrKinematicObject()) { btVector3 localInertia; float mass = 1.f/rigidbody->getInvMass(); compoundShape->calculateLocalInertia(mass,localInertia); rigidbody->setMassProps(mass,localInertia); } shapeInfo->Release(); // delete motionstate as it's not used delete motionstate; return; } if (objprop->m_hasCompoundChildren) { // create a compound shape info CcdShapeConstructionInfo *compoundShapeInfo = new CcdShapeConstructionInfo(); compoundShapeInfo->m_shapeType = PHY_SHAPE_COMPOUND; compoundShapeInfo->AddShape(shapeInfo); // create the compound shape manually as we already have the child shape btCompoundShape* compoundShape = new btCompoundShape(); compoundShape->addChildShape(shapeInfo->m_childTrans,bm); // now replace the shape bm = compoundShape; shapeInfo->Release(); shapeInfo = compoundShapeInfo; } #ifdef TEST_SIMD_HULL if (bm->IsPolyhedral()) { PolyhedralConvexShape* polyhedron = static_cast<PolyhedralConvexShape*>(bm); if (!polyhedron->m_optionalHull) { //first convert vertices in 'Point3' format int numPoints = polyhedron->GetNumVertices(); Point3* points = new Point3[numPoints+1]; //first 4 points should not be co-planar, so add central point to satisfy MakeHull points[0] = Point3(0.f,0.f,0.f); btVector3 vertex; for (int p=0;p<numPoints;p++) { polyhedron->GetVertex(p,vertex); points[p+1] = Point3(vertex.getX(),vertex.getY(),vertex.getZ()); } Hull* hull = Hull::MakeHull(numPoints+1,points); polyhedron->m_optionalHull = hull; } } #endif //TEST_SIMD_HULL ci.m_collisionShape = bm; ci.m_shapeInfo = shapeInfo; ci.m_friction = smmaterial->m_friction;//tweak the friction a bit, so the default 0.5 works nice ci.m_restitution = smmaterial->m_restitution; ci.m_physicsEnv = env; // drag / damping is inverted ci.m_linearDamping = 1.f - shapeprops->m_lin_drag; ci.m_angularDamping = 1.f - shapeprops->m_ang_drag; //need a bit of damping, else system doesn't behave well ci.m_inertiaFactor = shapeprops->m_inertia/0.4f;//defaults to 0.4, don't want to change behavior ci.m_do_anisotropic = shapeprops->m_do_anisotropic; ci.m_anisotropicFriction.setValue(shapeprops->m_friction_scaling[0],shapeprops->m_friction_scaling[1],shapeprops->m_friction_scaling[2]); ////////// //do Fh, do Rot Fh ci.m_do_fh = shapeprops->m_do_fh; ci.m_do_rot_fh = shapeprops->m_do_rot_fh; ci.m_fh_damping = smmaterial->m_fh_damping; ci.m_fh_distance = smmaterial->m_fh_distance; ci.m_fh_normal = smmaterial->m_fh_normal; ci.m_fh_spring = smmaterial->m_fh_spring; ci.m_radius = objprop->m_radius; /////////////////// ci.m_gamesoftFlag = objprop->m_gamesoftFlag; ci.m_soft_linStiff = objprop->m_soft_linStiff; ci.m_soft_angStiff = objprop->m_soft_angStiff; /* angular stiffness 0..1 */ ci.m_soft_volume= objprop->m_soft_volume; /* volume preservation 0..1 */ ci.m_soft_viterations= objprop->m_soft_viterations; /* Velocities solver iterations */ ci.m_soft_piterations= objprop->m_soft_piterations; /* Positions solver iterations */ ci.m_soft_diterations= objprop->m_soft_diterations; /* Drift solver iterations */ ci.m_soft_citerations= objprop->m_soft_citerations; /* Cluster solver iterations */ ci.m_soft_kSRHR_CL= objprop->m_soft_kSRHR_CL; /* Soft vs rigid hardness [0,1] (cluster only) */ ci.m_soft_kSKHR_CL= objprop->m_soft_kSKHR_CL; /* Soft vs kinetic hardness [0,1] (cluster only) */ ci.m_soft_kSSHR_CL= objprop->m_soft_kSSHR_CL; /* Soft vs soft hardness [0,1] (cluster only) */ ci.m_soft_kSR_SPLT_CL= objprop->m_soft_kSR_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */ ci.m_soft_kSK_SPLT_CL= objprop->m_soft_kSK_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */ ci.m_soft_kSS_SPLT_CL= objprop->m_soft_kSS_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */ ci.m_soft_kVCF= objprop->m_soft_kVCF; /* Velocities correction factor (Baumgarte) */ ci.m_soft_kDP= objprop->m_soft_kDP; /* Damping coefficient [0,1] */ ci.m_soft_kDG= objprop->m_soft_kDG; /* Drag coefficient [0,+inf] */ ci.m_soft_kLF= objprop->m_soft_kLF; /* Lift coefficient [0,+inf] */ ci.m_soft_kPR= objprop->m_soft_kPR; /* Pressure coefficient [-inf,+inf] */ ci.m_soft_kVC= objprop->m_soft_kVC; /* Volume conversation coefficient [0,+inf] */ ci.m_soft_kDF= objprop->m_soft_kDF; /* Dynamic friction coefficient [0,1] */ ci.m_soft_kMT= objprop->m_soft_kMT; /* Pose matching coefficient [0,1] */ ci.m_soft_kCHR= objprop->m_soft_kCHR; /* Rigid contacts hardness [0,1] */ ci.m_soft_kKHR= objprop->m_soft_kKHR; /* Kinetic contacts hardness [0,1] */ ci.m_soft_kSHR= objprop->m_soft_kSHR; /* Soft contacts hardness [0,1] */ ci.m_soft_kAHR= objprop->m_soft_kAHR; /* Anchors hardness [0,1] */ ci.m_soft_collisionflags= objprop->m_soft_collisionflags; /* Vertex/Face or Signed Distance Field(SDF) or Clusters, Soft versus Soft or Rigid */ ci.m_soft_numclusteriterations= objprop->m_soft_numclusteriterations; /* number of iterations to refine collision clusters*/ //////////////////// ci.m_collisionFilterGroup = (isbulletsensor) ? short(CcdConstructionInfo::SensorFilter) : (isbulletdyna) ? short(CcdConstructionInfo::DefaultFilter) : (isbulletchar) ? short(CcdConstructionInfo::CharacterFilter) : short(CcdConstructionInfo::StaticFilter); ci.m_collisionFilterMask = (isbulletsensor) ? short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter) : (isbulletdyna) ? short(CcdConstructionInfo::AllFilter) : (isbulletchar) ? short(CcdConstructionInfo::AllFilter) : short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter); ci.m_bRigid = objprop->m_dyna && objprop->m_angular_rigidbody; ci.m_contactProcessingThreshold = objprop->m_contactProcessingThreshold;//todo: expose this in advanced settings, just like margin, default to 10000 or so ci.m_bSoft = objprop->m_softbody; ci.m_bDyna = isbulletdyna; ci.m_bSensor = isbulletsensor; ci.m_bCharacter = isbulletchar; ci.m_bGimpact = useGimpact; MT_Vector3 scaling = gameobj->NodeGetWorldScaling(); ci.m_scaling.setValue(scaling[0], scaling[1], scaling[2]); CcdPhysicsController* physicscontroller = new CcdPhysicsController(ci); // shapeInfo is reference counted, decrement now as we don't use it anymore if (shapeInfo) shapeInfo->Release(); gameobj->SetPhysicsController(physicscontroller,isbulletdyna); // don't add automatically sensor object, they are added when a collision sensor is registered if (!isbulletsensor && objprop->m_in_active_layer) { env->AddCcdPhysicsController( physicscontroller); } physicscontroller->SetNewClientInfo(gameobj->getClientInfo()); { btRigidBody* rbody = physicscontroller->GetRigidBody(); if (rbody) { if (objprop->m_angular_rigidbody) { rbody->setLinearFactor(ci.m_linearFactor); rbody->setAngularFactor(ci.m_angularFactor); } if (rbody && objprop->m_disableSleeping) { rbody->setActivationState(DISABLE_DEACTIVATION); } } } CcdPhysicsController* parentCtrl = objprop->m_dynamic_parent ? (CcdPhysicsController*)objprop->m_dynamic_parent->GetPhysicsController() : 0; physicscontroller->SetParentCtrl(parentCtrl); //Now done directly in ci.m_collisionFlags so that it propagates to replica //if (objprop->m_ghost) //{ // rbody->setCollisionFlags(rbody->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE); //} if (objprop->m_dyna && !objprop->m_angular_rigidbody) { #if 0 //setting the inertia could achieve similar results to constraint the up //but it is prone to instability, so use special 'Angular' constraint btVector3 inertia = physicscontroller->GetRigidBody()->getInvInertiaDiagLocal(); inertia.setX(0.f); inertia.setZ(0.f); physicscontroller->GetRigidBody()->setInvInertiaDiagLocal(inertia); physicscontroller->GetRigidBody()->updateInertiaTensor(); #endif //env->createConstraint(physicscontroller,0,PHY_ANGULAR_CONSTRAINT,0,0,0,0,0,1); //Now done directly in ci.m_bRigid so that it propagates to replica //physicscontroller->GetRigidBody()->setAngularFactor(0.f); ; } bool isActor = objprop->m_isactor; gameobj->getClientInfo()->m_type = (isbulletsensor) ? ((isActor) ? KX_ClientObjectInfo::OBACTORSENSOR : KX_ClientObjectInfo::OBSENSOR) : (isActor) ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC; // store materialname in auxinfo, needed for touchsensors if (meshobj) { const STR_String& matname=meshobj->GetMaterialName(0); gameobj->getClientInfo()->m_auxilary_info = (matname.Length() ? (void*)(matname.ReadPtr()+2) : NULL); } else { gameobj->getClientInfo()->m_auxilary_info = 0; } STR_String materialname; if (meshobj) materialname = meshobj->GetMaterialName(0); #if 0 ///test for soft bodies if (objprop->m_softbody && physicscontroller) { btSoftBody* softBody = physicscontroller->GetSoftBody(); 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( gameobj->GetMesh(0),(BL_DeformableGameObject*)gameobj); gameobj->SetDeformer(softbodyDeformer); } } #endif }
/// Perform an integration step of duration 'timeStep'. bool CcdPhysicsEnvironment::proceedDeltaTimeOneStep(float timeStep) { //printf("CcdPhysicsEnvironment::proceedDeltaTime\n"); if (SimdFuzzyZero(timeStep)) return true; if (m_debugDrawer) { gDisableDeactivation = (m_debugDrawer->GetDebugMode() & IDebugDraw::DBG_NoDeactivation); } #ifdef USE_QUICKPROF Profiler::beginBlock("SyncMotionStates"); #endif //USE_QUICKPROF //this is needed because scaling is not known in advance, and scaling has to propagate to the shape if (!m_scalingPropagated) { SyncMotionStates(timeStep); m_scalingPropagated = true; } #ifdef USE_QUICKPROF Profiler::endBlock("SyncMotionStates"); Profiler::beginBlock("predictIntegratedTransform"); #endif //USE_QUICKPROF { // std::vector<CcdPhysicsController*>::iterator i; int k; for (k=0;k<GetNumControllers();k++) { CcdPhysicsController* ctrl = m_controllers[k]; // SimdTransform predictedTrans; RigidBody* body = ctrl->GetRigidBody(); body->m_cachedInvertedWorldTransform = body->m_worldTransform.inverse(); if (body->IsActive()) { if (!body->IsStatic()) { body->applyForces( timeStep); body->integrateVelocities( timeStep); body->predictIntegratedTransform(timeStep,body->m_interpolationWorldTransform); } } } } #ifdef USE_QUICKPROF Profiler::endBlock("predictIntegratedTransform"); #endif //USE_QUICKPROF OverlappingPairCache* scene = m_collisionWorld->GetPairCache(); // // collision detection (?) // #ifdef USE_QUICKPROF Profiler::beginBlock("DispatchAllCollisionPairs"); #endif //USE_QUICKPROF int numsubstep = m_numIterations; DispatcherInfo dispatchInfo; dispatchInfo.m_timeStep = timeStep; dispatchInfo.m_stepCount = 0; dispatchInfo.m_enableSatConvex = m_enableSatCollisionDetection; dispatchInfo.m_debugDraw = this->m_debugDrawer; scene->RefreshOverlappingPairs(); GetCollisionWorld()->GetDispatcher()->DispatchAllCollisionPairs(&scene->GetOverlappingPair(0),scene->GetNumOverlappingPairs(),dispatchInfo); #ifdef USE_QUICKPROF Profiler::endBlock("DispatchAllCollisionPairs"); #endif //USE_QUICKPROF int numRigidBodies = m_controllers.size(); m_islandManager->UpdateActivationState(GetCollisionWorld(),GetCollisionWorld()->GetDispatcher()); { int i; int numConstraints = m_constraints.size(); for (i=0;i< numConstraints ; i++ ) { TypedConstraint* constraint = m_constraints[i]; const RigidBody* colObj0 = &constraint->GetRigidBodyA(); const RigidBody* colObj1 = &constraint->GetRigidBodyB(); if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && ((colObj1) && ((colObj1)->mergesSimulationIslands()))) { if (colObj0->IsActive() || colObj1->IsActive()) { m_islandManager->GetUnionFind().unite((colObj0)->m_islandTag1, (colObj1)->m_islandTag1); } } } } m_islandManager->StoreIslandActivationState(GetCollisionWorld()); //contacts #ifdef USE_QUICKPROF Profiler::beginBlock("SolveConstraint"); #endif //USE_QUICKPROF //solve the regular constraints (point 2 point, hinge, etc) for (int g=0;g<numsubstep;g++) { // // constraint solving // int i; int numConstraints = m_constraints.size(); //point to point constraints for (i=0;i< numConstraints ; i++ ) { TypedConstraint* constraint = m_constraints[i]; constraint->BuildJacobian(); constraint->SolveConstraint( timeStep ); } } #ifdef USE_QUICKPROF Profiler::endBlock("SolveConstraint"); #endif //USE_QUICKPROF //solve the vehicles #ifdef NEW_BULLET_VEHICLE_SUPPORT //vehicles int numVehicles = m_wrapperVehicles.size(); for (int i=0;i<numVehicles;i++) { WrapperVehicle* wrapperVehicle = m_wrapperVehicles[i]; RaycastVehicle* vehicle = wrapperVehicle->GetVehicle(); vehicle->UpdateVehicle( timeStep); } #endif //NEW_BULLET_VEHICLE_SUPPORT struct InplaceSolverIslandCallback : public SimulationIslandManager::IslandCallback { ContactSolverInfo& m_solverInfo; ConstraintSolver* m_solver; IDebugDraw* m_debugDrawer; InplaceSolverIslandCallback( ContactSolverInfo& solverInfo, ConstraintSolver* solver, IDebugDraw* debugDrawer) :m_solverInfo(solverInfo), m_solver(solver), m_debugDrawer(debugDrawer) { } virtual void ProcessIsland(PersistentManifold** manifolds,int numManifolds) { m_solver->SolveGroup( manifolds, numManifolds,m_solverInfo,m_debugDrawer); } }; m_solverInfo.m_friction = 0.9f; m_solverInfo.m_numIterations = m_numIterations; m_solverInfo.m_timeStep = timeStep; m_solverInfo.m_restitution = 0.f;//m_restitution; InplaceSolverIslandCallback solverCallback( m_solverInfo, m_solver, m_debugDrawer); #ifdef USE_QUICKPROF Profiler::beginBlock("BuildAndProcessIslands"); #endif //USE_QUICKPROF /// solve all the contact points and contact friction m_islandManager->BuildAndProcessIslands(GetCollisionWorld()->GetDispatcher(),m_collisionWorld->GetCollisionObjectArray(),&solverCallback); #ifdef USE_QUICKPROF Profiler::endBlock("BuildAndProcessIslands"); Profiler::beginBlock("CallbackTriggers"); #endif //USE_QUICKPROF CallbackTriggers(); #ifdef USE_QUICKPROF Profiler::endBlock("CallbackTriggers"); Profiler::beginBlock("proceedToTransform"); #endif //USE_QUICKPROF { { UpdateAabbs(timeStep); float toi = 1.f; if (m_ccdMode == 3) { DispatcherInfo dispatchInfo; dispatchInfo.m_timeStep = timeStep; dispatchInfo.m_stepCount = 0; dispatchInfo.m_dispatchFunc = DispatcherInfo::DISPATCH_CONTINUOUS; //pairCache->RefreshOverlappingPairs();//?? GetCollisionWorld()->GetDispatcher()->DispatchAllCollisionPairs(&scene->GetOverlappingPair(0),scene->GetNumOverlappingPairs(),dispatchInfo); toi = dispatchInfo.m_timeOfImpact; } // // integrating solution // { std::vector<CcdPhysicsController*>::iterator i; for (i=m_controllers.begin(); !(i==m_controllers.end()); i++) { CcdPhysicsController* ctrl = *i; SimdTransform predictedTrans; RigidBody* body = ctrl->GetRigidBody(); if (body->IsActive()) { if (!body->IsStatic()) { body->predictIntegratedTransform(timeStep* toi, predictedTrans); body->proceedToTransform( predictedTrans); } } } } // // disable sleeping physics objects // std::vector<CcdPhysicsController*> m_sleepingControllers; std::vector<CcdPhysicsController*>::iterator i; for (i=m_controllers.begin(); !(i==m_controllers.end()); i++) { CcdPhysicsController* ctrl = (*i); RigidBody* body = ctrl->GetRigidBody(); ctrl->UpdateDeactivation(timeStep); if (ctrl->wantsSleeping()) { if (body->GetActivationState() == ACTIVE_TAG) body->SetActivationState( WANTS_DEACTIVATION ); } else { if (body->GetActivationState() != DISABLE_DEACTIVATION) body->SetActivationState( ACTIVE_TAG ); } if (useIslands) { if (body->GetActivationState() == ISLAND_SLEEPING) { m_sleepingControllers.push_back(ctrl); } } else { if (ctrl->wantsSleeping()) { m_sleepingControllers.push_back(ctrl); } } } } #ifdef USE_QUICKPROF Profiler::endBlock("proceedToTransform"); Profiler::beginBlock("SyncMotionStates"); #endif //USE_QUICKPROF SyncMotionStates(timeStep); #ifdef USE_QUICKPROF Profiler::endBlock("SyncMotionStates"); Profiler::endProfilingCycle(); #endif //USE_QUICKPROF #ifdef NEW_BULLET_VEHICLE_SUPPORT //sync wheels for vehicles int numVehicles = m_wrapperVehicles.size(); for (int i=0;i<numVehicles;i++) { WrapperVehicle* wrapperVehicle = m_wrapperVehicles[i]; wrapperVehicle->SyncWheels(); } #endif //NEW_BULLET_VEHICLE_SUPPORT } return true; }
bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) { //don't simulate without timesubsteps if (m_numTimeSubSteps<1) return true; //printf("proceedDeltaTime\n"); #ifdef USE_QUICKPROF //toggle Profiler if ( m_debugDrawer->GetDebugMode() & IDebugDraw::DBG_ProfileTimings) { if (!m_profileTimings) { m_profileTimings = 1; // To disable profiling, simply comment out the following line. static int counter = 0; char filename[128]; sprintf(filename,"quickprof_bullet_timings%i.csv",counter++); Profiler::init(filename, Profiler::BLOCK_CYCLE_SECONDS);//BLOCK_TOTAL_MICROSECONDS } } else { if (m_profileTimings) { m_profileTimings = 0; Profiler::destroy(); } } #endif //USE_QUICKPROF if (!SimdFuzzyZero(timeStep)) { { //do the kinematic calculation here, over the full timestep std::vector<CcdPhysicsController*>::iterator i; for (i=m_controllers.begin(); !(i==m_controllers.end()); i++) { CcdPhysicsController* ctrl = *i; SimdTransform predictedTrans; RigidBody* body = ctrl->GetRigidBody(); if (body->GetActivationState() != ISLAND_SLEEPING) { if (body->IsStatic()) { //to calculate velocities next frame body->saveKinematicState(timeStep); } } } } int i; float subTimeStep = timeStep / float(m_numTimeSubSteps); for (i=0;i<this->m_numTimeSubSteps;i++) { proceedDeltaTimeOneStep(subTimeStep); } } else { //todo: interpolate } return true; }
void clientMouseFunc(int button, int state, int x, int y) { //printf("button %i, state %i, x=%i,y=%i\n",button,state,x,y); //button 0, state 0 means left mouse down SimdVector3 rayTo = GetRayTo(x,y); switch (button) { case 2: { if (state==0) { shootBox(rayTo); } break; }; case 1: { if (state==0) { //apply an impulse if (physicsEnvironmentPtr) { float hit[3]; float normal[3]; PHY_IPhysicsController* hitObj = physicsEnvironmentPtr->rayTest(0,eye[0],eye[1],eye[2],rayTo.getX(),rayTo.getY(),rayTo.getZ(),hit[0],hit[1],hit[2],normal[0],normal[1],normal[2]); if (hitObj) { CcdPhysicsController* physCtrl = static_cast<CcdPhysicsController*>(hitObj); RigidBody* body = physCtrl->GetRigidBody(); if (body) { body->SetActivationState(ACTIVE_TAG); SimdVector3 impulse = rayTo; impulse.normalize(); float impulseStrength = 10.f; impulse *= impulseStrength; SimdVector3 relPos( hit[0] - body->getCenterOfMassPosition().getX(), hit[1] - body->getCenterOfMassPosition().getY(), hit[2] - body->getCenterOfMassPosition().getZ()); body->applyImpulse(impulse,relPos); } } } } else { } break; } case 0: { if (state==0) { //add a point to point constraint for picking if (physicsEnvironmentPtr) { float hit[3]; float normal[3]; PHY_IPhysicsController* hitObj = physicsEnvironmentPtr->rayTest(0,eye[0],eye[1],eye[2],rayTo.getX(),rayTo.getY(),rayTo.getZ(),hit[0],hit[1],hit[2],normal[0],normal[1],normal[2]); if (hitObj) { CcdPhysicsController* physCtrl = static_cast<CcdPhysicsController*>(hitObj); RigidBody* body = physCtrl->GetRigidBody(); if (body) { pickedBody = body; pickedBody->SetActivationState(DISABLE_DEACTIVATION); SimdVector3 pickPos(hit[0],hit[1],hit[2]); SimdVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos; gPickingConstraintId = physicsEnvironmentPtr->createConstraint(physCtrl,0,PHY_POINT2POINT_CONSTRAINT, localPivot.getX(), localPivot.getY(), localPivot.getZ(), 0,0,0); //printf("created constraint %i",gPickingConstraintId); //save mouse position for dragging gOldPickingPos = rayTo; SimdVector3 eyePos(eye[0],eye[1],eye[2]); gOldPickingDist = (pickPos-eyePos).length(); Point2PointConstraint* p2p = static_cast<Point2PointConstraint*>(physicsEnvironmentPtr->getConstraintById(gPickingConstraintId)); if (p2p) { //very weak constraint for picking p2p->m_setting.m_tau = 0.1f; } } } } } else { if (gPickingConstraintId && physicsEnvironmentPtr) { physicsEnvironmentPtr->removeConstraint(gPickingConstraintId); //printf("removed constraint %i",gPickingConstraintId); gPickingConstraintId = 0; pickedBody->ForceActivationState(ACTIVE_TAG); pickedBody->m_deactivationTime = 0.f; pickedBody = 0; } } break; } default: { } } }