diff options
13 files changed, 135 insertions, 84 deletions
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 764c3c2dfec..d6747bd1ba4 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -97,6 +97,7 @@ const char KX_KetsjiEngine::m_profileLabels[tc_numCategories][15] = { }; double KX_KetsjiEngine::m_ticrate = DEFAULT_LOGIC_TIC_RATE; +int KX_KetsjiEngine::m_maxLogicFrame = 5; double KX_KetsjiEngine::m_anim_framerate = 25.0; double KX_KetsjiEngine::m_suspendedtime = 0.0; double KX_KetsjiEngine::m_suspendeddelta = 0.0; @@ -399,6 +400,7 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo) m_firstframe = true; m_bInitialized = true; m_ticrate = DEFAULT_LOGIC_TIC_RATE; + m_maxLogicFrame = 5; if (m_game2ipo) { @@ -511,7 +513,8 @@ void KX_KetsjiEngine::EndFrame() bool KX_KetsjiEngine::NextFrame() { - + double timestep = 1.0/m_ticrate; + double framestep = timestep; // static hidden::Clock sClock; m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true); @@ -520,7 +523,7 @@ m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true); //sClock.reset(); if (m_bFixedTime) - m_clockTime += 1./m_ticrate; + m_clockTime += timestep; else { @@ -554,18 +557,24 @@ else { // printf("framedOut: %d\n",frames); - m_frameTime+=(frames-frameOut)*(1.0/m_ticrate); + m_frameTime+=(frames-frameOut)*timestep; frames = frameOut; } bool doRender = frames>0; + if (frames > m_maxLogicFrame) + { + framestep = (frames*timestep)/m_maxLogicFrame; + frames = m_maxLogicFrame; + } + while (frames) { - m_frameTime += 1.0/m_ticrate; + m_frameTime += framestep; for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit) // for each scene, call the proceed functions @@ -644,7 +653,7 @@ else // Perform physics calculations on the scene. This can involve // many iterations of the physics solver. - scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,1.0/m_ticrate);//m_deltatimerealDeltaTime); + scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,timestep,framestep);//m_deltatimerealDeltaTime); m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS2_UPDATE); @@ -717,7 +726,7 @@ else // Perform physics calculations on the scene. This can involve // many iterations of the physics solver. m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); - scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,0.f); + scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,timestep,timestep); // Update scenegraph after physics step. This maps physics calculations // into node positions. m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); @@ -1729,6 +1738,16 @@ void KX_KetsjiEngine::SetTicRate(double ticrate) m_ticrate = ticrate; } +int KX_KetsjiEngine::GetMaxLogicFrame() +{ + return m_maxLogicFrame; +} + +void KX_KetsjiEngine::SetMaxLogicFrame(int frame) +{ + m_maxLogicFrame = frame; +} + double KX_KetsjiEngine::GetAnimFrameRate() { return m_anim_framerate; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index a8ccd6100d7..791c5d24daa 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -103,6 +103,7 @@ private: double m_previousClockTime;//previous clock time double m_remainingTime; + static int m_maxLogicFrame; /* maximum number of consecutive logic frame */ static double m_ticrate; static double m_anim_framerate; /* for animation playback only - ipo and action */ @@ -283,6 +284,14 @@ public: * Sets the number of logic updates per second. */ static void SetTicRate(double ticrate); + /** + * Gets the maximum number of logic frame before render frame + */ + static int KX_KetsjiEngine::GetMaxLogicFrame(); + /** + * Sets the maximum number of logic frame before render frame + */ + static void KX_KetsjiEngine::SetMaxLogicFrame(int frame); /** * Gets the framerate for playing animations. (actions and ipos) diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index d774d8ed5f8..01c1382a6d1 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -288,6 +288,21 @@ static PyObject* gPyGetLogicTicRate(PyObject*) return PyFloat_FromDouble(KX_KetsjiEngine::GetTicRate()); } +static PyObject* gPySetMaxLogicFrame(PyObject*, PyObject* args) +{ + int frame; + if (!PyArg_ParseTuple(args, "i:setMaxLogicFrame", &frame)) + return NULL; + + KX_KetsjiEngine::SetMaxLogicFrame(frame); + Py_RETURN_NONE; +} + +static PyObject* gPyGetMaxLogicFrame(PyObject*) +{ + return PyInt_FromLong(KX_KetsjiEngine::GetMaxLogicFrame()); +} + static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args) { float ticrate; @@ -479,6 +494,8 @@ static struct PyMethodDef game_methods[] = { {"setGravity",(PyCFunction) gPySetGravity, METH_O, (PY_METHODCHAR)"set Gravitation"}, {"getSpectrum",(PyCFunction) gPyGetSpectrum, METH_NOARGS, (PY_METHODCHAR)"get audio spectrum"}, {"stopDSP",(PyCFunction) gPyStopDSP, METH_VARARGS, (PY_METHODCHAR)"stop using the audio dsp (for performance reasons)"}, + {"getMaxLogicFrame", (PyCFunction) gPyGetMaxLogicFrame, METH_NOARGS, (PY_METHODCHAR)"Gets the max number of logic frame per render frame"}, + {"setMaxLogicFrame", (PyCFunction) gPySetMaxLogicFrame, METH_VARARGS, (PY_METHODCHAR)"Sets the max number of logic frame per render frame"}, {"getLogicTicRate", (PyCFunction) gPyGetLogicTicRate, METH_NOARGS, (PY_METHODCHAR)"Gets the logic tic rate"}, {"setLogicTicRate", (PyCFunction) gPySetLogicTicRate, METH_VARARGS, (PY_METHODCHAR)"Sets the logic tic rate"}, {"getPhysicsTicRate", (PyCFunction) gPyGetPhysicsTicRate, METH_NOARGS, (PY_METHODCHAR)"Gets the physics tic rate"}, diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp index 2e8ee31058f..54e97858b7f 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp +++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp @@ -75,7 +75,7 @@ float ODEPhysicsEnvironment::getFixedTimeStep() -bool ODEPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep1) +bool ODEPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep1,float interval) { float deltaTime = timeStep1; diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h index 2e4709cf420..82e26e01460 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h +++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h @@ -44,7 +44,7 @@ public: // Perform an integration step of duration 'timeStep'. - virtual bool proceedDeltaTime(double curTime,float timeStep); + virtual bool proceedDeltaTime(double curTime,float timeStep,float interval); virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep); virtual float getFixedTimeStep(); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index a0bf0448e3e..bcf83e25d84 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -623,7 +623,7 @@ void CcdPhysicsEnvironment::debugDrawWorld() m_dynamicsWorld->debugDrawWorld(); } -bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) +bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep,float interval) { std::set<CcdPhysicsController*>::iterator it; int i; @@ -633,14 +633,9 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) (*it)->SynchronizeMotionStates(timeStep); } - processFhSprings(curTime,timeStep); - float subStep = timeStep / float(m_numTimeSubSteps); - for (i=0;i<m_numTimeSubSteps;i++) - { -// m_dynamicsWorld->stepSimulation(subStep,20,1./240.);//perform always a full simulation step - m_dynamicsWorld->stepSimulation(subStep,0);//perform always a full simulation step - } + i = m_dynamicsWorld->stepSimulation(interval,25,subStep);//perform always a full simulation step + processFhSprings(curTime,i*subStep); for (it=m_controllers.begin(); it!=m_controllers.end(); it++) { @@ -692,9 +687,11 @@ public: }; -void CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep) +void CcdPhysicsEnvironment::processFhSprings(double curTime,float interval) { std::set<CcdPhysicsController*>::iterator it; + // dynamic of Fh spring is based on a timestep of 1/60 + int numIter = (int)(interval*60.0001f); for (it=m_controllers.begin(); it!=m_controllers.end(); it++) { @@ -706,8 +703,6 @@ void CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep) //printf("has Fh or RotFh\n"); //re-implement SM_FhObject.cpp using btCollisionWorld::rayTest and info from ctrl->getConstructionInfo() //send a ray from {0.0, 0.0, 0.0} towards {0.0, 0.0, -10.0}, in local coordinates - - CcdPhysicsController* parentCtrl = ctrl->getParentCtrl(); btRigidBody* parentBody = parentCtrl?parentCtrl->GetRigidBody() : 0; btRigidBody* cl_object = parentBody ? parentBody : body; @@ -754,82 +749,78 @@ void CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep) btVector3 normal = resultCallback.m_hitNormalWorld; normal.normalize(); - - if (ctrl->getConstructionInfo().m_do_fh) + for (int i=0; i<numIter; i++) { - btVector3 lspot = cl_object->getCenterOfMassPosition() - + rayDirLocal * resultCallback.m_closestHitFraction; + if (ctrl->getConstructionInfo().m_do_fh) + { + btVector3 lspot = cl_object->getCenterOfMassPosition() + + rayDirLocal * resultCallback.m_closestHitFraction; + + + lspot -= hit_object->getCenterOfMassPosition(); + btVector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocityInLocalPoint(lspot); + btScalar rel_vel_ray = ray_dir.dot(rel_vel); + btScalar spring_extent = 1.0 - distance / hitObjShapeProps.m_fh_distance; + btScalar i_spring = spring_extent * hitObjShapeProps.m_fh_spring; + btScalar i_damp = rel_vel_ray * hitObjShapeProps.m_fh_damping; + + cl_object->setLinearVelocity(cl_object->getLinearVelocity() + (-(i_spring + i_damp) * ray_dir)); + if (hitObjShapeProps.m_fh_normal) + { + cl_object->setLinearVelocity(cl_object->getLinearVelocity()+(i_spring + i_damp) *(normal - normal.dot(ray_dir) * ray_dir)); + } + + btVector3 lateral = rel_vel - rel_vel_ray * ray_dir; + + + if (ctrl->getConstructionInfo().m_do_anisotropic) { + //Bullet basis contains no scaling/shear etc. + const btMatrix3x3& lcs = cl_object->getCenterOfMassTransform().getBasis(); + btVector3 loc_lateral = lateral * lcs; + const btVector3& friction_scaling = cl_object->getAnisotropicFriction(); + loc_lateral *= friction_scaling; + lateral = lcs * loc_lateral; + } - lspot -= hit_object->getCenterOfMassPosition(); - btVector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocityInLocalPoint(lspot); - btScalar rel_vel_ray = ray_dir.dot(rel_vel); - btScalar spring_extent = 1.0 - distance / hitObjShapeProps.m_fh_distance; - - btScalar i_spring = spring_extent * hitObjShapeProps.m_fh_spring; - btScalar i_damp = rel_vel_ray * hitObjShapeProps.m_fh_damping; - - cl_object->setLinearVelocity(cl_object->getLinearVelocity() + (-(i_spring + i_damp) * ray_dir)); - if (hitObjShapeProps.m_fh_normal) - { - cl_object->setLinearVelocity(cl_object->getLinearVelocity()+(i_spring + i_damp) *(normal - normal.dot(ray_dir) * ray_dir)); - } - - btVector3 lateral = rel_vel - rel_vel_ray * ray_dir; - - - if (ctrl->getConstructionInfo().m_do_anisotropic) { - //Bullet basis contains no scaling/shear etc. - const btMatrix3x3& lcs = cl_object->getCenterOfMassTransform().getBasis(); - btVector3 loc_lateral = lateral * lcs; - const btVector3& friction_scaling = cl_object->getAnisotropicFriction(); - loc_lateral *= friction_scaling; - lateral = lcs * loc_lateral; + btScalar rel_vel_lateral = lateral.length(); + + if (rel_vel_lateral > SIMD_EPSILON) { + btScalar friction_factor = hit_object->getFriction();//cl_object->getFriction(); + + btScalar max_friction = friction_factor * btMax(btScalar(0.0), i_spring); + + btScalar rel_mom_lateral = rel_vel_lateral / cl_object->getInvMass(); + + btVector3 friction = (rel_mom_lateral > max_friction) ? + -lateral * (max_friction / rel_vel_lateral) : + -lateral; + + cl_object->applyCentralImpulse(friction); + } } - btScalar rel_vel_lateral = lateral.length(); - if (rel_vel_lateral > SIMD_EPSILON) { - btScalar friction_factor = hit_object->getFriction();//cl_object->getFriction(); + if (ctrl->getConstructionInfo().m_do_rot_fh) { + btVector3 up2 = cl_object->getWorldTransform().getBasis().getColumn(2); - btScalar max_friction = friction_factor * btMax(btScalar(0.0), i_spring); + btVector3 t_spring = up2.cross(normal) * hitObjShapeProps.m_fh_spring; + btVector3 ang_vel = cl_object->getAngularVelocity(); - btScalar rel_mom_lateral = rel_vel_lateral / cl_object->getInvMass(); + // only rotations that tilt relative to the normal are damped + ang_vel -= ang_vel.dot(normal) * normal; - btVector3 friction = (rel_mom_lateral > max_friction) ? - -lateral * (max_friction / rel_vel_lateral) : - -lateral; + btVector3 t_damp = ang_vel * hitObjShapeProps.m_fh_damping; - cl_object->applyCentralImpulse(friction); + cl_object->setAngularVelocity(cl_object->getAngularVelocity() + (t_spring - t_damp)); } } - - - if (ctrl->getConstructionInfo().m_do_rot_fh) { - btVector3 up2 = cl_object->getWorldTransform().getBasis().getColumn(2); - - btVector3 t_spring = up2.cross(normal) * hitObjShapeProps.m_fh_spring; - btVector3 ang_vel = cl_object->getAngularVelocity(); - - // only rotations that tilt relative to the normal are damped - ang_vel -= ang_vel.dot(normal) * normal; - - btVector3 t_damp = ang_vel * hitObjShapeProps.m_fh_damping; - - cl_object->setAngularVelocity(cl_object->getAngularVelocity() + (t_spring - t_damp)); - } - } - - } - - } } - } void CcdPhysicsEnvironment::setDebugMode(int debugMode) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index f861621ae37..5f9fb9511d6 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -114,7 +114,7 @@ protected: virtual void beginFrame(); virtual void endFrame() {}; /// Perform an integration step of duration 'timeStep'. - virtual bool proceedDeltaTime(double curTime,float timeStep); + virtual bool proceedDeltaTime(double curTime,float timeStep,float interval); virtual void debugDrawWorld(); // virtual bool proceedDeltaTimeOneStep(float timeStep); diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp index ba196b5cf55..e41574ff181 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp @@ -57,7 +57,7 @@ void DummyPhysicsEnvironment::endFrame() -bool DummyPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) +bool DummyPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep,float interval) { //step physics simulation, typically perform diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h index 4e15e6ec130..397a1ba4218 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h @@ -48,7 +48,7 @@ public: virtual void beginFrame(); virtual void endFrame(); // Perform an integration step of duration 'timeStep'. - virtual bool proceedDeltaTime(double curTime,float timeStep); + virtual bool proceedDeltaTime(double curTime,float timeStep,float interval); virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep); virtual float getFixedTimeStep(); diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp index 3be5e027345..cc6d5654ec9 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp @@ -81,7 +81,7 @@ float SumoPhysicsEnvironment::getFixedTimeStep() } -bool SumoPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) +bool SumoPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep,float interval) { bool result = false; diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h index 418a361a065..c2b443a2b38 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h @@ -54,7 +54,7 @@ public: virtual void beginFrame(); virtual void endFrame(); // Perform an integration step of duration 'timeStep'. - virtual bool proceedDeltaTime(double curTime,float timeStep); + virtual bool proceedDeltaTime(double curTime,float timeStep,float interval); virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep); virtual float getFixedTimeStep(); diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index 9a4500c3214..a3605669f70 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -89,7 +89,7 @@ class PHY_IPhysicsEnvironment virtual void beginFrame() = 0; virtual void endFrame() = 0; /// Perform an integration step of duration 'timeStep'. - virtual bool proceedDeltaTime(double curTime,float timeStep)=0; + virtual bool proceedDeltaTime(double curTime,float timeStep,float interval)=0; ///draw debug lines (make sure to call this during the render phase, otherwise lines are not drawn properly) virtual void debugDrawWorld(){} virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep)=0; diff --git a/source/gameengine/PyDoc/GameLogic.py b/source/gameengine/PyDoc/GameLogic.py index 74e7f852018..85e94e63416 100644 --- a/source/gameengine/PyDoc/GameLogic.py +++ b/source/gameengine/PyDoc/GameLogic.py @@ -360,6 +360,21 @@ def stopDSP(): Only the fmod sound driver supports this. DSP can be computationally expensive. """ +def getMaxLogicFrame(): + """ + Gets the maximum number of logic frame per render frame. + + @return: The maximum number of logic frame per render frame + @rtype: interger + """ +def setMaxLogicFrame(maxlogic): + """ + Sets the maximum number of logic frame that are executed per render frame. + This does not affect the physic system that still runs at full frame rate. + + @param maxlogic: The new maximum number of logic frame per render frame. Valid values: 1..5 + @type maxlogic: integer + """ def getLogicTicRate(): """ Gets the logic update frequency. @@ -372,7 +387,7 @@ def setLogicTicRate(ticrate): Sets the logic update frequency. The logic update frequency is the number of times logic bricks are executed every second. - The default is 30 Hz. + The default is 60 Hz. @param ticrate: The new logic update frequency (in Hz). @type ticrate: float |