From cab75b53ecc5783568f131b865e345f0e75a37c9 Mon Sep 17 00:00:00 2001 From: ejcoumans Date: Wed, 21 Nov 2007 03:00:40 +0000 Subject: [PATCH] added hierarchical profiling (needs more cleanup) avoid dynamic allocations in btRaycastVehicle --- Demos/AllBulletDemos/Main.cpp | 36 ++- Demos/BasicDemo/BasicDemo.cpp | 3 - Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp | 10 +- .../ConvexDecompositionDemo.cpp | 2 +- Demos/OpenGL/DemoApplication.cpp | 86 ++++++ Demos/OpenGL/DemoApplication.h | 12 +- Demos/RagdollDemo/RagdollDemo.cpp | 3 - Demos/VehicleDemo/VehicleDemo.cpp | 14 +- .../BulletMultiThreaded/SpuParallelSolver.cpp | 51 ++-- .../SpuSolverTask/SpuParallellSolverTask.cpp | 2 + .../CollisionDispatch/btCollisionWorld.cpp | 29 +- .../btSequentialImpulseConstraintSolver.cpp | 9 +- .../Dynamics/btContinuousDynamicsWorld.cpp | 1 + .../Dynamics/btDiscreteDynamicsWorld.cpp | 99 ++++--- .../Dynamics/btDiscreteDynamicsWorld.h | 2 + .../Vehicle/btRaycastVehicle.cpp | 62 ++--- src/BulletDynamics/Vehicle/btRaycastVehicle.h | 6 + src/LinearMath/btQuickprof.cpp | 263 ++++++++++++++++++ src/LinearMath/btQuickprof.h | 133 +++++++++ 19 files changed, 695 insertions(+), 128 deletions(-) diff --git a/Demos/AllBulletDemos/Main.cpp b/Demos/AllBulletDemos/Main.cpp index c18f8e53a..dfccb0992 100644 --- a/Demos/AllBulletDemos/Main.cpp +++ b/Demos/AllBulletDemos/Main.cpp @@ -29,6 +29,9 @@ #include "GLDebugDrawer.h" static GLDebugDrawer gDebugDrawer; +#include "LinearMath/btQuickProf.h" + +CProfileIterator * gProfileIterator=0; namespace @@ -80,6 +83,9 @@ DemoApplication* CreatDemo(btDemoEntry* entry) { demo->getDynamicsWorld()->setDebugDrawer(&gDebugDrawer); } + + CProfileManager::Reset(); + return demo; } @@ -107,6 +113,9 @@ void Timer(int) void SimulationLoop() { + + + if (gDrawAabb) { demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_DrawAabb); @@ -146,10 +155,15 @@ void SimulationLoop() if (!demo->isIdle()) + { demo->clientMoveAndDisplay(); - else - demo->displayCallback(); + + } + else + { + demo->displayCallback(); + } if (testSelection != testIndex) { testIndex = testSelection; @@ -161,11 +175,24 @@ void SimulationLoop() viewY = 0.0f; Resize(width, height); } -} +} void Keyboard(unsigned char key, int x, int y) { + if (key >= 0x31 && key < 0x37) + { + int child = key-0x31; + gProfileIterator->Enter_Child(child); + } + if (key==0x30) + { + gProfileIterator->Enter_Parent(); + return; + } + + + switch (key) { case 27: @@ -211,7 +238,10 @@ void MouseMotion(int x, int y) int main(int argc, char** argv) { + + gProfileIterator = CProfileManager::Get_Iterator(); + int bulletVersion = btGetVersion(); printf("Bullet version %d\n",bulletVersion); diff --git a/Demos/BasicDemo/BasicDemo.cpp b/Demos/BasicDemo/BasicDemo.cpp index e9a0b9497..9faa6b1c8 100644 --- a/Demos/BasicDemo/BasicDemo.cpp +++ b/Demos/BasicDemo/BasicDemo.cpp @@ -104,9 +104,6 @@ void BasicDemo::clientMoveAndDisplay() void BasicDemo::displayCallback(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - if (m_dynamicsWorld) - m_dynamicsWorld->updateAabbs(); renderme(); diff --git a/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp b/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp index 5a09c1c0e..5e16df134 100644 --- a/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp +++ b/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp @@ -300,8 +300,6 @@ void CcdPhysicsDemo::displayCallback(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - m_dynamicsWorld->updateAabbs(); - renderme(); @@ -431,11 +429,13 @@ int maxNumOutstandingTasks = 4; createSolverLocalStoreMemory, maxNumOutstandingTasks)); - m_solver = new btParallelSequentialImpulseSolver(threadSupportSolver,maxNumOutstandingTasks); + m_solver = new btParallelSequentialImpulseSolver(m_threadSupportSolver,maxNumOutstandingTasks); #else - m_solver = new btSequentialImpulseConstraintSolver; + btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver(); + + m_solver = solver; //default solverMode is SOLVER_RANDMIZE_ORDER. Warmstarting seems not to improve convergence, see - //m_solver->setSolverMode(btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER); + //solver->setSolverMode(0);//btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER); #endif //USE_PARALLEL_SOLVER diff --git a/Demos/ConvexDecompositionDemo/ConvexDecompositionDemo.cpp b/Demos/ConvexDecompositionDemo/ConvexDecompositionDemo.cpp index 6d8e95d26..2142c6dd6 100644 --- a/Demos/ConvexDecompositionDemo/ConvexDecompositionDemo.cpp +++ b/Demos/ConvexDecompositionDemo/ConvexDecompositionDemo.cpp @@ -90,7 +90,7 @@ void ConvexDecompositionDemo::initPhysics(const char* filename) ///you can hook it up to your custom task scheduler by deriving from btThreadSupportInterface #endif - m_dispatcher = new SpuGatheringCollisionDispatcher(threadSupport,maxNumOutstandingTasks,collisionConfiguration); + m_dispatcher = new SpuGatheringCollisionDispatcher(threadSupport,maxNumOutstandingTasks,m_collisionConfiguration); #else m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); #endif//USE_PARALLEL_DISPATCHER diff --git a/Demos/OpenGL/DemoApplication.cpp b/Demos/OpenGL/DemoApplication.cpp index 66b4ae2e7..18c6deab3 100644 --- a/Demos/OpenGL/DemoApplication.cpp +++ b/Demos/OpenGL/DemoApplication.cpp @@ -29,6 +29,7 @@ subject to the following restrictions: #include "LinearMath/btQuickprof.h" #include "LinearMath/btDefaultMotionState.h" + #include "BMF_Api.h" extern bool gDisableDeactivation; @@ -77,6 +78,7 @@ m_shootBoxShape(0), DemoApplication::~DemoApplication() { + if (m_shootBoxShape) delete m_shootBoxShape; @@ -756,6 +758,88 @@ void DemoApplication::resetPerspectiveProjection() } + + +extern CProfileIterator * gProfileIterator; + +void DemoApplication::displayProfileString(int xOffset,int yStart,char* message) +{ + glRasterPos3f(xOffset,yStart,0); + BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),message); +} + + +void DemoApplication::showProfileInfo(float& xOffset,float& yStart, float yIncr) +{ + + static double time_since_reset = 0.f; + if (!m_idle) + { + time_since_reset = CProfileManager::Get_Time_Since_Reset(); + } + + + { + //recompute profiling data, and store profile strings + + char blockTime[128]; + + double totalTime = 0; + + int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset(); + + gProfileIterator->First(); + + double parent_time = gProfileIterator->Is_Root() ? time_since_reset : gProfileIterator->Get_Current_Parent_Total_Time(); + + { + sprintf(blockTime,"--- Profiling: %s (total running time: %.3f m) ---", gProfileIterator->Get_Current_Parent_Name(), parent_time ); + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + sprintf(blockTime,"press number (1,2...) to display child timings, or 0 to go up to parent" ); + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + + } + + + double accumulated_time = 0.f; + + for (int i = 0; !gProfileIterator->Is_Done(); gProfileIterator->Next()) + { + double current_total_time = gProfileIterator->Get_Current_Total_Time(); + accumulated_time += current_total_time; + double fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f; + + sprintf(blockTime,"%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)", + ++i, gProfileIterator->Get_Current_Name(), fraction, + (current_total_time / (double)frames_since_reset),gProfileIterator->Get_Current_Total_Calls()); + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + totalTime += current_total_time; + } + + sprintf(blockTime,"%s (%.3f %%) :: %.3f ms", "Unaccounted", + // (min(0, time_since_reset - totalTime) / time_since_reset) * 100); + parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time); + + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + + + + sprintf(blockTime,"-------------------------------------------------"); + displayProfileString(xOffset,yStart,blockTime); + yStart += yIncr; + + } + + + + +} + + void DemoApplication::renderme() { updateCamera(); @@ -823,6 +907,8 @@ void DemoApplication::renderme() { setOrthographicProjection(); + showProfileInfo(xOffset,yStart,yIncr); + #ifdef USE_QUICKPROF diff --git a/Demos/OpenGL/DemoApplication.h b/Demos/OpenGL/DemoApplication.h index 0c4585b54..c690913ae 100644 --- a/Demos/OpenGL/DemoApplication.h +++ b/Demos/OpenGL/DemoApplication.h @@ -39,15 +39,20 @@ subject to the following restrictions: #include "LinearMath/btMatrix3x3.h" #include "LinearMath/btTransform.h" #include "LinearMath/btQuickprof.h" +#include "LinearMath/btAlignedObjectArray.h" class btCollisionShape; class btDynamicsWorld; class btRigidBody; class btTypedConstraint; + + + class DemoApplication { - + void displayProfileString(int xOffset,int yStart,char* message); + protected: btClock m_clock; @@ -82,7 +87,10 @@ class DemoApplication bool m_singleStep; bool m_idle; int m_lastKey; - + + void showProfileInfo(float& xOffset,float& yStart, float yIncr); + + public: DemoApplication(); diff --git a/Demos/RagdollDemo/RagdollDemo.cpp b/Demos/RagdollDemo/RagdollDemo.cpp index e05f0fb0f..34a954473 100644 --- a/Demos/RagdollDemo/RagdollDemo.cpp +++ b/Demos/RagdollDemo/RagdollDemo.cpp @@ -372,9 +372,6 @@ void RagdollDemo::displayCallback() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - if (m_dynamicsWorld) - m_dynamicsWorld->updateAabbs(); - renderme(); glFlush(); diff --git a/Demos/VehicleDemo/VehicleDemo.cpp b/Demos/VehicleDemo/VehicleDemo.cpp index 3c9ef5e05..beba3b626 100644 --- a/Demos/VehicleDemo/VehicleDemo.cpp +++ b/Demos/VehicleDemo/VehicleDemo.cpp @@ -449,21 +449,9 @@ void VehicleDemo::clientMoveAndDisplay() void VehicleDemo::displayCallback(void) { - - clientMoveAndDisplay(); - return; - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - - //m_dynamicsWorld->updateAabbs(); - - //draw contactpoints - //m_physicsEnvironmentPtr->CallbackTriggers(); - - - //renderme(); + renderme(); glFlush(); diff --git a/Extras/BulletMultiThreaded/SpuParallelSolver.cpp b/Extras/BulletMultiThreaded/SpuParallelSolver.cpp index 182ad30d4..9e0167d54 100644 --- a/Extras/BulletMultiThreaded/SpuParallelSolver.cpp +++ b/Extras/BulletMultiThreaded/SpuParallelSolver.cpp @@ -28,6 +28,7 @@ Written by: Marten Svanfeldt #include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "LinearMath/profile.h" #include "SpuSolverTask/SpuParallellSolverTask.h" @@ -108,6 +109,8 @@ void btParallelSequentialImpulseSolver::prepareSolve(int numBodies, int numManif btScalar btParallelSequentialImpulseSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher) { + PROFILE("parallel_solveGroup"); + if (!numManifolds && !numConstraints) return 0; int i; @@ -259,6 +262,8 @@ btAlignedObjectArray solverConstraintPool_persist; void btParallelSequentialImpulseSolver::allSolved (const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc) { + PROFILE("parallel_allSolved"); + if (!m_numberOfContacts && !m_sortedConstraints.size()) { m_sortedManifolds.clear(); @@ -348,6 +353,8 @@ void btParallelSequentialImpulseSolver::allSolved (const btContactSolverInfo& in // Setup all the moving rigid bodies { + PROFILE("setup moving rigidbodies"); + int bodiesPerTask = PARALLEL_SOLVER_BODIES_PER_TASK; int bodiesToSchedule = numBodies; int startBody = 0; @@ -409,33 +416,37 @@ void btParallelSequentialImpulseSolver::allSolved (const btContactSolverInfo& in m_taskScheduler.flushTasks(); } - btSpinlock::SpinVariable* spinVar = (btSpinlock::SpinVariable*)btAlignedAlloc(sizeof(btSpinlock::SpinVariable), 128); - for (int iter = 0; iter < info.m_numIterations; ++iter) { - btSpinlock lock (spinVar); - lock.Init(); + PROFILE("parallel_solve_iterations"); - // Clear the "processed cells" part of the hash - memcpy(m_solverHash->m_currentMask[0], emptyCellMask, sizeof(uint32_t)*SPU_HASH_NUMCELLDWORDS); - - for (int task = 0; task < m_taskScheduler.getMaxOutstandingTasks(); ++task) + btSpinlock::SpinVariable* spinVar = (btSpinlock::SpinVariable*)btAlignedAlloc(sizeof(btSpinlock::SpinVariable), 128); + for (int iter = 0; iter < info.m_numIterations; ++iter) { - SpuSolverTaskDesc* desc = m_taskScheduler.getTask(); - desc->m_solverCommand = CMD_SOLVER_SOLVE_ITERATE; + btSpinlock lock (spinVar); + lock.Init(); - desc->m_solverData.m_solverHash = m_solverHash; - desc->m_solverData.m_solverBodyList = solverBodyPool; - desc->m_solverData.m_solverBodyOffsetList = solverBodyOffsetList; - desc->m_solverData.m_solverInternalConstraintList = solverInternalConstraintPool; - desc->m_solverData.m_solverConstraintList = solverConstraintPool; + // Clear the "processed cells" part of the hash + memcpy(m_solverHash->m_currentMask[0], emptyCellMask, sizeof(uint32_t)*SPU_HASH_NUMCELLDWORDS); - desc->m_commandData.m_iterate.m_spinLockVar = spinVar; + for (int task = 0; task < m_taskScheduler.getMaxOutstandingTasks(); ++task) + { + SpuSolverTaskDesc* desc = m_taskScheduler.getTask(); + desc->m_solverCommand = CMD_SOLVER_SOLVE_ITERATE; - m_taskScheduler.issueTask(); - } - m_taskScheduler.flushTasks(); + desc->m_solverData.m_solverHash = m_solverHash; + desc->m_solverData.m_solverBodyList = solverBodyPool; + desc->m_solverData.m_solverBodyOffsetList = solverBodyOffsetList; + desc->m_solverData.m_solverInternalConstraintList = solverInternalConstraintPool; + desc->m_solverData.m_solverConstraintList = solverConstraintPool; + + desc->m_commandData.m_iterate.m_spinLockVar = spinVar; + + m_taskScheduler.issueTask(); + } + m_taskScheduler.flushTasks(); + } + btAlignedFree((void*)spinVar); } - btAlignedFree((void*)spinVar); // Write back velocity { diff --git a/Extras/BulletMultiThreaded/SpuSolverTask/SpuParallellSolverTask.cpp b/Extras/BulletMultiThreaded/SpuSolverTask/SpuParallellSolverTask.cpp index 3bd8fc859..957c17e85 100644 --- a/Extras/BulletMultiThreaded/SpuSolverTask/SpuParallellSolverTask.cpp +++ b/Extras/BulletMultiThreaded/SpuSolverTask/SpuParallellSolverTask.cpp @@ -809,6 +809,8 @@ static int getConstraintSize (btTypedConstraintType type) //-- MAIN METHOD void processSolverTask(void* userPtr, void* lsMemory) { +// PROFILE("processSolverTask"); + SolverTask_LocalStoreMemory* localMemory = (SolverTask_LocalStoreMemory*)lsMemory; SpuSolverTaskDesc* taskDescPtr = (SpuSolverTaskDesc*)userPtr; diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index b4828508b..f0d567eb8 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -32,6 +32,7 @@ subject to the following restrictions: #include "LinearMath/btQuickprof.h" #include "LinearMath/btStackAlloc.h" + //When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor) #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" @@ -116,30 +117,38 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho void btCollisionWorld::performDiscreteCollisionDetection() { + PROFILE("performDiscreteCollisionDetection"); + btDispatcherInfo& dispatchInfo = getDispatchInfo(); BEGIN_PROFILE("perform Broadphase Collision Detection"); //update aabb (of all moved objects) - - btVector3 aabbMin,aabbMax; - for (int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax); - m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax,m_dispatcher1); + PROFILE("setAabb"); + btVector3 aabbMin,aabbMax; + for (int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax); + m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax,m_dispatcher1); + } + } + { + PROFILE("calculateOverlappingPairs"); + m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); } - m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); - END_PROFILE("perform Broadphase Collision Detection"); BEGIN_PROFILE("performDiscreteCollisionDetection"); btDispatcher* dispatcher = getDispatcher(); - if (dispatcher) - dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); - + { + PROFILE("dispatchAllCollisionPairs"); + if (dispatcher) + dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); + } END_PROFILE("performDiscreteCollisionDetection"); } diff --git a/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp index 7d4ed7856..39faf7527 100644 --- a/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ b/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -33,6 +33,7 @@ subject to the following restrictions: #include "btSolverBody.h" #include "btSolverConstraint.h" + #include "LinearMath/btAlignedObjectArray.h" #ifdef USE_PROFILE @@ -415,6 +416,7 @@ void btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) { + PROFILE("solveGroupCacheFriendlySetup"); (void)stackAlloc; (void)debugDrawer; @@ -718,6 +720,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) { + PROFILE("solveGroupCacheFriendlyIterations"); BEGIN_PROFILE("solveConstraintsIterations"); int numConstraintPool = m_tmpSolverConstraintPool.size(); int numFrictionPool = m_tmpSolverFrictionConstraintPool.size(); @@ -750,6 +753,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations( for (j=0;jgetDebugMode() & btIDebugDraw::DBG_DrawWireframe) { + int i; + //todo: iterate over awake simulation islands! - for ( int i=0;igetDebugMode() & btIDebugDraw::DBG_DrawWireframe) @@ -155,6 +156,47 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates() debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color); } + } + + for ( i=0;im_vehicles.size();i++) + { + for (int v=0;vgetNumWheels();v++) + { + btVector3 wheelColor(0,255,255); + if (m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_isInContact) + { + wheelColor.setValue(0,0,255); + } else + { + wheelColor.setValue(255,0,255); + } + + btVector3 wheelPosWS = m_vehicles[i]->getWheelInfo(v).m_worldTransform.getOrigin(); + + btVector3 axle = btVector3( + m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[0][m_vehicles[i]->getRightAxis()], + m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[1][m_vehicles[i]->getRightAxis()], + m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[2][m_vehicles[i]->getRightAxis()]); + + + //m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_wheelAxleWS + //debug wheels (cylinders) + m_debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor); + m_debugDrawer->drawLine(wheelPosWS,m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor); + + } + } + } +} + +void btDiscreteDynamicsWorld::synchronizeMotionStates() +{ + { + //todo: iterate over awake simulation islands! + for ( int i=0;igetMotionState() && !body->isStaticOrKinematicObject()) { @@ -178,31 +220,8 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates() { for (int v=0;vgetNumWheels();v++) { - btVector3 wheelColor(0,255,255); - if (m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_isInContact) - { - wheelColor.setValue(0,0,255); - } else - { - wheelColor.setValue(255,0,255); - } - //synchronize the wheels with the (interpolated) chassis worldtransform m_vehicles[i]->updateWheelTransform(v,true); - - btVector3 wheelPosWS = m_vehicles[i]->getWheelInfo(v).m_worldTransform.getOrigin(); - - btVector3 axle = btVector3( - m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[0][m_vehicles[i]->getRightAxis()], - m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[1][m_vehicles[i]->getRightAxis()], - m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[2][m_vehicles[i]->getRightAxis()]); - - - //m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_wheelAxleWS - //debug wheels (cylinders) - m_debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor); - m_debugDrawer->drawLine(wheelPosWS,m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor); - } } } @@ -212,6 +231,10 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates() int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) { + startProfiling(timeStep); + + PROFILE("stepSimulation"); + int numSimulationSubSteps = 0; if (maxSubSteps) @@ -262,13 +285,16 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, synchronizeMotionStates(); + CProfileManager::Increment_Frame_Counter(); + return numSimulationSubSteps; } void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep) { - startProfiling(timeStep); + PROFILE("internalSingleStepSimulation"); + ///update aabbs information updateAabbs(); @@ -306,8 +332,6 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep) updateActivationState( timeStep ); - - } void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity) @@ -363,6 +387,7 @@ void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep) { + PROFILE("updateVehicles"); BEGIN_PROFILE("updateVehicles"); for ( int i=0;iupdateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher()); @@ -606,7 +634,8 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands() void btDiscreteDynamicsWorld::updateAabbs() { - BEGIN_PROFILE("updateAabbs"); + PROFILE("updateAabbs"); + btVector3 colorvec(1,0,0); btTransform predictedTrans; @@ -658,6 +687,7 @@ void btDiscreteDynamicsWorld::updateAabbs() void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) { + PROFILE("integrateTransforms"); BEGIN_PROFILE("integrateTransforms"); btTransform predictedTrans; for ( int i=0;igetCenterOfMassPosition(); - if (forwardImpulse[wheel] != btScalar(0.)) + if (m_forwardImpulse[wheel] != btScalar(0.)) { - m_chassisBody->applyImpulse(forwardWS[wheel]*(forwardImpulse[wheel]),rel_pos); + m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos); } - if (sideImpulse[wheel] != btScalar(0.)) + if (m_sideImpulse[wheel] != btScalar(0.)) { class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject; @@ -695,7 +690,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) groundObject->getCenterOfMassPosition(); - btVector3 sideImp = axle[wheel] * sideImpulse[wheel]; + btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel]; rel_pos[2] *= wheelInfo.m_rollInfluence; m_chassisBody->applyImpulse(sideImp,rel_pos); @@ -706,10 +701,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) } } - btAlignedFree(forwardWS); - btAlignedFree(axle); - btAlignedFree(forwardImpulse); - btAlignedFree(sideImpulse); + } diff --git a/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/src/BulletDynamics/Vehicle/btRaycastVehicle.h index a84b185e9..836e79d51 100644 --- a/src/BulletDynamics/Vehicle/btRaycastVehicle.h +++ b/src/BulletDynamics/Vehicle/btRaycastVehicle.h @@ -23,6 +23,12 @@ class btVehicleTuning; ///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle. class btRaycastVehicle : public btTypedConstraint { + + btAlignedObjectArray m_forwardWS; + btAlignedObjectArray m_axle; + btAlignedObjectArray m_forwardImpulse; + btAlignedObjectArray m_sideImpulse; + public: class btVehicleTuning { diff --git a/src/LinearMath/btQuickprof.cpp b/src/LinearMath/btQuickprof.cpp index 37a0c8c3b..6d10ebc9f 100644 --- a/src/LinearMath/btQuickprof.cpp +++ b/src/LinearMath/btQuickprof.cpp @@ -36,3 +36,266 @@ bool btProfiler::mFirstFileOutput = true; btProfiler::BlockTimingMethod btProfiler::mFileOutputMethod; unsigned long int btProfiler::mCycleNumber = 0; #endif //USE_QUICKPROF + + +/*************************************************************************************************** +** +** profile.cpp +** +** Real-Time Hierarchical Profiling for Game Programming Gems 3 +** +** by Greg Hjelstrom & Byon Garrabrant +** +***************************************************************************************************/ + +static btClock gProfileClock; + +inline void Profile_Get_Ticks(_int64 * ticks) +{ + *ticks = gProfileClock.getTimeMicroseconds(); +} + +inline float Profile_Get_Tick_Rate(void) +{ +// return 1000000.f; + return 1000.f; + +} + +/*************************************************************************************************** +** +** CProfileNode +** +***************************************************************************************************/ + +/*********************************************************************************************** + * INPUT: * + * name - pointer to a static string which is the name of this profile node * + * parent - parent pointer * + * * + * WARNINGS: * + * The name is assumed to be a static pointer, only the pointer is stored and compared for * + * efficiency reasons. * + *=============================================================================================*/ +CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) : + Name( name ), + TotalCalls( 0 ), + TotalTime( 0 ), + StartTime( 0 ), + RecursionCounter( 0 ), + Parent( parent ), + Child( NULL ), + Sibling( NULL ) +{ + Reset(); +} + + +CProfileNode::~CProfileNode( void ) +{ + delete Child; + delete Sibling; +} + + +/*********************************************************************************************** + * INPUT: * + * name - static string pointer to the name of the node we are searching for * + * * + * WARNINGS: * + * All profile names are assumed to be static strings so this function uses pointer compares * + * to find the named node. * + *=============================================================================================*/ +CProfileNode * CProfileNode::Get_Sub_Node( const char * name ) +{ + // Try to find this sub node + CProfileNode * child = Child; + while ( child ) { + if ( child->Name == name ) { + return child; + } + child = child->Sibling; + } + + // We didn't find it, so add it + CProfileNode * node = new CProfileNode( name, this ); + node->Sibling = Child; + Child = node; + return node; +} + + +void CProfileNode::Reset( void ) +{ + TotalCalls = 0; + TotalTime = 0.0f; + gProfileClock.reset(); + + if ( Child ) { + Child->Reset(); + } + if ( Sibling ) { + Sibling->Reset(); + } +} + + +void CProfileNode::Call( void ) +{ + TotalCalls++; + if (RecursionCounter++ == 0) { + Profile_Get_Ticks(&StartTime); + } +} + + +bool CProfileNode::Return( void ) +{ + if ( --RecursionCounter == 0 && TotalCalls != 0 ) { + __int64 time; + Profile_Get_Ticks(&time); + time-=StartTime; + TotalTime += (float)time / Profile_Get_Tick_Rate(); + } + return ( RecursionCounter == 0 ); +} + + +/*************************************************************************************************** +** +** CProfileIterator +** +***************************************************************************************************/ +CProfileIterator::CProfileIterator( CProfileNode * start ) +{ + CurrentParent = start; + CurrentChild = CurrentParent->Get_Child(); +} + + +void CProfileIterator::First(void) +{ + CurrentChild = CurrentParent->Get_Child(); +} + + +void CProfileIterator::Next(void) +{ + CurrentChild = CurrentChild->Get_Sibling(); +} + + +bool CProfileIterator::Is_Done(void) +{ + return CurrentChild == NULL; +} + + +void CProfileIterator::Enter_Child( int index ) +{ + CurrentChild = CurrentParent->Get_Child(); + while ( (CurrentChild != NULL) && (index != 0) ) { + index--; + CurrentChild = CurrentChild->Get_Sibling(); + } + + if ( CurrentChild != NULL ) { + CurrentParent = CurrentChild; + CurrentChild = CurrentParent->Get_Child(); + } +} + + +void CProfileIterator::Enter_Parent( void ) +{ + if ( CurrentParent->Get_Parent() != NULL ) { + CurrentParent = CurrentParent->Get_Parent(); + } + CurrentChild = CurrentParent->Get_Child(); +} + + +/*************************************************************************************************** +** +** CProfileManager +** +***************************************************************************************************/ + +CProfileNode CProfileManager::Root( "Root", NULL ); +CProfileNode * CProfileManager::CurrentNode = &CProfileManager::Root; +int CProfileManager::FrameCounter = 0; +__int64 CProfileManager::ResetTime = 0; + + +/*********************************************************************************************** + * CProfileManager::Start_Profile -- Begin a named profile * + * * + * Steps one level deeper into the tree, if a child already exists with the specified name * + * then it accumulates the profiling; otherwise a new child node is added to the profile tree. * + * * + * INPUT: * + * name - name of this profiling record * + * * + * WARNINGS: * + * The string used is assumed to be a static string; pointer compares are used throughout * + * the profiling code for efficiency. * + *=============================================================================================*/ +void CProfileManager::Start_Profile( const char * name ) +{ + if (name != CurrentNode->Get_Name()) { + CurrentNode = CurrentNode->Get_Sub_Node( name ); + } + + CurrentNode->Call(); +} + + +/*********************************************************************************************** + * CProfileManager::Stop_Profile -- Stop timing and record the results. * + *=============================================================================================*/ +void CProfileManager::Stop_Profile( void ) +{ + // Return will indicate whether we should back up to our parent (we may + // be profiling a recursive function) + if (CurrentNode->Return()) { + CurrentNode = CurrentNode->Get_Parent(); + } +} + + +/*********************************************************************************************** + * CProfileManager::Reset -- Reset the contents of the profiling system * + * * + * This resets everything except for the tree structure. All of the timing data is reset. * + *=============================================================================================*/ +void CProfileManager::Reset( void ) +{ + Root.Reset(); + Root.Call(); + FrameCounter = 0; + Profile_Get_Ticks(&ResetTime); +} + + +/*********************************************************************************************** + * CProfileManager::Increment_Frame_Counter -- Increment the frame counter * + *=============================================================================================*/ +void CProfileManager::Increment_Frame_Counter( void ) +{ + FrameCounter++; +} + + +/*********************************************************************************************** + * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset * + *=============================================================================================*/ +float CProfileManager::Get_Time_Since_Reset( void ) +{ + __int64 time; + Profile_Get_Ticks(&time); + time -= ResetTime; + return (float)time / Profile_Get_Tick_Rate(); +} + + + diff --git a/src/LinearMath/btQuickprof.h b/src/LinearMath/btQuickprof.h index a885967c5..9b0289e88 100644 --- a/src/LinearMath/btQuickprof.h +++ b/src/LinearMath/btQuickprof.h @@ -707,6 +707,139 @@ std::string btProfiler::createStatsString(BlockTimingMethod method) #endif //USE_QUICKPROF + +/*************************************************************************************************** +** +** profile.h +** +** Real-Time Hierarchical Profiling for Game Programming Gems 3 +** +** by Greg Hjelstrom & Byon Garrabrant +** +***************************************************************************************************/ + +/* +** A node in the Profile Hierarchy Tree +*/ +class CProfileNode { + +public: + CProfileNode( const char * name, CProfileNode * parent ); + ~CProfileNode( void ); + + CProfileNode * Get_Sub_Node( const char * name ); + + CProfileNode * Get_Parent( void ) { return Parent; } + CProfileNode * Get_Sibling( void ) { return Sibling; } + CProfileNode * Get_Child( void ) { return Child; } + + void Reset( void ); + void Call( void ); + bool Return( void ); + + const char * Get_Name( void ) { return Name; } + int Get_Total_Calls( void ) { return TotalCalls; } + float Get_Total_Time( void ) { return TotalTime; } + +protected: + + const char * Name; + int TotalCalls; + float TotalTime; + __int64 StartTime; + int RecursionCounter; + + CProfileNode * Parent; + CProfileNode * Child; + CProfileNode * Sibling; +}; + +/* +** An iterator to navigate through the tree +*/ +class CProfileIterator +{ +public: + // Access all the children of the current parent + void First(void); + void Next(void); + bool Is_Done(void); + bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); } + + void Enter_Child( int index ); // Make the given child the new parent + void Enter_Largest_Child( void ); // Make the largest child the new parent + void Enter_Parent( void ); // Make the current parent's parent the new parent + + // Access the current child + const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); } + int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); } + float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); } + + // Access the current parent + const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); } + int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); } + float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); } + +protected: + + CProfileNode * CurrentParent; + CProfileNode * CurrentChild; + + CProfileIterator( CProfileNode * start ); + friend class CProfileManager; +}; + + +/* +** The Manager for the Profile system +*/ +class CProfileManager { +public: + static void Start_Profile( const char * name ); + static void Stop_Profile( void ); + + static void Reset( void ); + static void Increment_Frame_Counter( void ); + static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; } + static float Get_Time_Since_Reset( void ); + + static CProfileIterator * Get_Iterator( void ) { return new CProfileIterator( &Root ); } + static void Release_Iterator( CProfileIterator * iterator ) { delete iterator; } + +private: + static CProfileNode Root; + static CProfileNode * CurrentNode; + static int FrameCounter; + static __int64 ResetTime; +}; + + +/* +** ProfileSampleClass is a simple way to profile a function's scope +** Use the PROFILE macro at the start of scope to time +*/ +class CProfileSample { +public: + CProfileSample( const char * name ) + { + CProfileManager::Start_Profile( name ); + } + + ~CProfileSample( void ) + { + CProfileManager::Stop_Profile(); + } +}; + +#if !defined(NO_PROFILE) +#define PROFILE( name ) CProfileSample __profile( name ) +#else +#define PROFILE( name ) +#endif + + + + #endif //QUICK_PROF_H