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 }
//to be implemented by the demo void renderme() { debugDrawer.SetDebugMode(getDebugMode()); //render the hinge axis if (createConstraint) { SimdVector3 color(1,0,0); SimdVector3 dirLocal(0,1,0); SimdVector3 pivotInA(CUBE_HALF_EXTENTS,-CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS); SimdVector3 pivotInB(-CUBE_HALF_EXTENTS,-CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS); SimdVector3 from = physObjects[1]->GetRigidBody()->getCenterOfMassTransform()(pivotInA); SimdVector3 fromB = physObjects[2]->GetRigidBody()->getCenterOfMassTransform()(pivotInB); SimdVector3 dirWorldA = physObjects[1]->GetRigidBody()->getCenterOfMassTransform().getBasis() * dirLocal ; SimdVector3 dirWorldB = physObjects[2]->GetRigidBody()->getCenterOfMassTransform().getBasis() * dirLocal ; debugDrawer.DrawLine(from,from+dirWorldA,color); debugDrawer.DrawLine(fromB,fromB+dirWorldB,color); } float m[16]; int i; if (getDebugMode() & IDebugDraw::DBG_DisableBulletLCP) { //don't use Bullet, use quickstep physicsEnvironmentPtr->setSolverType(0); } else { //Bullet LCP solver physicsEnvironmentPtr->setSolverType(1); } if (getDebugMode() & IDebugDraw::DBG_EnableCCD) { physicsEnvironmentPtr->setCcdMode(3); } else { physicsEnvironmentPtr->setCcdMode(0); } bool isSatEnabled = (getDebugMode() & IDebugDraw::DBG_EnableSatComparison); physicsEnvironmentPtr->EnableSatCollisionDetection(isSatEnabled); #ifdef USE_HULL //some testing code for SAT if (isSatEnabled) { for (int s=0;s<numShapes;s++) { CollisionShape* shape = shapePtr[s]; if (shape->IsPolyhedral()) { PolyhedralConvexShape* polyhedron = static_cast<PolyhedralConvexShape*>(shape); 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); SimdVector3 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 //USE_HULL for (i=0;i<numObjects;i++) { SimdTransform transA; transA.setIdentity(); float pos[3]; float rot[4]; ms[i].getWorldPosition(pos[0],pos[1],pos[2]); ms[i].getWorldOrientation(rot[0],rot[1],rot[2],rot[3]); SimdQuaternion q(rot[0],rot[1],rot[2],rot[3]); transA.setRotation(q); SimdPoint3 dpos; dpos.setValue(pos[0],pos[1],pos[2]); transA.setOrigin( dpos ); transA.getOpenGLMatrix( m ); SimdVector3 wireColor(1.f,1.0f,0.5f); //wants deactivation if (i & 1) { wireColor = SimdVector3(0.f,0.0f,1.f); } ///color differently for active, sleeping, wantsdeactivation states if (physObjects[i]->GetRigidBody()->GetActivationState() == 1) //active { if (i & 1) { wireColor += SimdVector3 (1.f,0.f,0.f); } else { wireColor += SimdVector3 (.5f,0.f,0.f); } } if (physObjects[i]->GetRigidBody()->GetActivationState() == 2) //ISLAND_SLEEPING { if (i & 1) { wireColor += SimdVector3 (0.f,1.f, 0.f); } else { wireColor += SimdVector3 (0.f,0.5f,0.f); } } char extraDebug[125]; sprintf(extraDebug,"islId, Body=%i , %i",physObjects[i]->GetRigidBody()->m_islandTag1,physObjects[i]->GetRigidBody()->m_debugBodyId); physObjects[i]->GetRigidBody()->GetCollisionShape()->SetExtraDebugInfo(extraDebug); GL_ShapeDrawer::DrawOpenGL(m,physObjects[i]->GetRigidBody()->GetCollisionShape(),wireColor,getDebugMode()); ///this block is just experimental code to show some internal issues with replacing shapes on the fly. if (getDebugMode()!=0 && (i>0)) { if (physObjects[i]->GetRigidBody()->GetCollisionShape()->GetShapeType() == EMPTY_SHAPE_PROXYTYPE) { physObjects[i]->GetRigidBody()->SetCollisionShape(shapePtr[1]); //remove the persistent collision pairs that were created based on the previous shape BroadphaseProxy* bpproxy = physObjects[i]->GetRigidBody()->m_broadphaseHandle; physicsEnvironmentPtr->GetBroadphase()->CleanProxyFromPairs(bpproxy); SimdVector3 newinertia; SimdScalar newmass = 10.f; physObjects[i]->GetRigidBody()->GetCollisionShape()->CalculateLocalInertia(newmass,newinertia); physObjects[i]->GetRigidBody()->setMassProps(newmass,newinertia); physObjects[i]->GetRigidBody()->updateInertiaTensor(); } } } if (!(getDebugMode() & IDebugDraw::DBG_NoHelpText)) { float xOffset = 10.f; float yStart = 20.f; float yIncr = -2.f; char buf[124]; glColor3f(0, 0, 0); #ifdef USE_QUICKPROF if ( getDebugMode() & IDebugDraw::DBG_ProfileTimings) { static int counter = 0; counter++; std::map<std::string, hidden::ProfileBlock*>::iterator iter; for (iter = Profiler::mProfileBlocks.begin(); iter != Profiler::mProfileBlocks.end(); ++iter) { char blockTime[128]; sprintf(blockTime, "%s: %lf",&((*iter).first[0]),Profiler::getBlockTime((*iter).first, Profiler::BLOCK_CYCLE_SECONDS));//BLOCK_TOTAL_PERCENT)); glRasterPos3f(xOffset,yStart,0); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),blockTime); yStart += yIncr; } } #endif //USE_QUICKPROF //profiling << Profiler::createStatsString(Profiler::BLOCK_TOTAL_PERCENT); //<< std::endl; glRasterPos3f(xOffset,yStart,0); sprintf(buf,"mouse to interact"); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); yStart += yIncr; glRasterPos3f(xOffset,yStart,0); sprintf(buf,"space to reset"); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); yStart += yIncr; glRasterPos3f(xOffset,yStart,0); sprintf(buf,"cursor keys and z,x to navigate"); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); yStart += yIncr; glRasterPos3f(xOffset,yStart,0); sprintf(buf,"i to toggle simulation, s single step"); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); yStart += yIncr; glRasterPos3f(xOffset,yStart,0); sprintf(buf,"q to quit"); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); yStart += yIncr; glRasterPos3f(xOffset,yStart,0); sprintf(buf,"d to toggle deactivation"); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); yStart += yIncr; glRasterPos3f(xOffset,yStart,0); sprintf(buf,"a to draw temporal AABBs"); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); yStart += yIncr; glRasterPos3f(xOffset,yStart,0); sprintf(buf,"h to toggle help text"); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); yStart += yIncr; bool useBulletLCP = !(getDebugMode() & IDebugDraw::DBG_DisableBulletLCP); bool useCCD = (getDebugMode() & IDebugDraw::DBG_EnableCCD); glRasterPos3f(xOffset,yStart,0); sprintf(buf,"m Bullet GJK = %i",!isSatEnabled); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); yStart += yIncr; glRasterPos3f(xOffset,yStart,0); sprintf(buf,"n Bullet LCP = %i",useBulletLCP); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); yStart += yIncr; glRasterPos3f(xOffset,yStart,0); sprintf(buf,"1 CCD mode (adhoc) = %i",useCCD); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); yStart += yIncr; glRasterPos3f(xOffset,yStart,0); sprintf(buf,"+- shooting speed = %10.2f",bulletSpeed); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf); yStart += yIncr; } }