diff options
author | Erwin Coumans <blender@erwincoumans.com> | 2006-05-23 01:03:43 +0400 |
---|---|---|
committer | Erwin Coumans <blender@erwincoumans.com> | 2006-05-23 01:03:43 +0400 |
commit | ab71e2a9b55e0982d1134792d10af55464c7ac9e (patch) | |
tree | 4a53791a67d3234360107a33c5365d4de4844bb7 | |
parent | 677cf7f1333c634a52227a15d6dcb3351b39febc (diff) |
-added basic support for GameActuator 'load game', relative paths were broken, just load file into memory and load blend from memory.
-near sensor support
- python binding for PhysicsConstraints.setNumTimeSubSteps (dividing the physics timestep to tradeoff quality for performance)
20 files changed, 609 insertions, 72 deletions
diff --git a/extern/bullet/Bullet/CollisionDispatch/ConvexConvexAlgorithm.cpp b/extern/bullet/Bullet/CollisionDispatch/ConvexConvexAlgorithm.cpp index c3ca2ef6be9..9c20f28d1ec 100644 --- a/extern/bullet/Bullet/CollisionDispatch/ConvexConvexAlgorithm.cpp +++ b/extern/bullet/Bullet/CollisionDispatch/ConvexConvexAlgorithm.cpp @@ -307,26 +307,14 @@ void ConvexConvexAlgorithm ::ProcessCollision (BroadphaseProxy* ,BroadphaseProxy GjkPairDetector::ClosestPointInput input; - SphereShape sphere(0.2f); - MinkowskiSumShape expanded0(min0,&sphere); - MinkowskiSumShape expanded1(min1,&sphere); - if (dispatchInfo.m_useContinuous) - { - m_gjkPairDetector.SetMinkowskiA(&expanded0); - m_gjkPairDetector.SetMinkowskiB(&expanded1); - input.m_maximumDistanceSquared = expanded0.GetMargin()+expanded1.GetMargin(); - input.m_maximumDistanceSquared *= input.m_maximumDistanceSquared; - } - else - { - m_gjkPairDetector.SetMinkowskiA(min0); - m_gjkPairDetector.SetMinkowskiB(min1); - input.m_maximumDistanceSquared = min0->GetMargin() + min1->GetMargin() + m_manifoldPtr->GetContactBreakingTreshold(); - input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; - } - - input.m_maximumDistanceSquared = 1e30f;// + //TODO: if (dispatchInfo.m_useContinuous) + m_gjkPairDetector.SetMinkowskiA(min0); + m_gjkPairDetector.SetMinkowskiB(min1); + input.m_maximumDistanceSquared = min0->GetMargin() + min1->GetMargin() + m_manifoldPtr->GetContactBreakingTreshold(); + input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; + + //input.m_maximumDistanceSquared = 1e30f;// input.m_transformA = col0->m_worldTransform; input.m_transformB = col1->m_worldTransform; diff --git a/extern/bullet/BulletDynamics/ConstraintSolver/SimpleConstraintSolver.cpp b/extern/bullet/BulletDynamics/ConstraintSolver/SimpleConstraintSolver.cpp index 9f7d360f7eb..fe59a40683a 100644 --- a/extern/bullet/BulletDynamics/ConstraintSolver/SimpleConstraintSolver.cpp +++ b/extern/bullet/BulletDynamics/ConstraintSolver/SimpleConstraintSolver.cpp @@ -112,6 +112,7 @@ SimdScalar restitutionCurve(SimdScalar rel_vel, SimdScalar restitution) + float SimpleConstraintSolver::Solve(PersistentManifold* manifoldPtr, const ContactSolverInfo& info,int iter,IDebugDraw* debugDrawer) { @@ -125,7 +126,7 @@ float SimpleConstraintSolver::Solve(PersistentManifold* manifoldPtr, const Conta { manifoldPtr->RefreshContactPoints(body0->getCenterOfMassTransform(),body1->getCenterOfMassTransform()); - const int numpoints = manifoldPtr->GetNumContacts(); + int numpoints = manifoldPtr->GetNumContacts(); SimdVector3 color(0,1,0); for (int i=0;i<numpoints ;i++) diff --git a/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsController.cpp b/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsController.cpp index 043d5be802e..cddc780aff4 100644 --- a/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsController.cpp +++ b/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsController.cpp @@ -23,6 +23,9 @@ subject to the following restrictions: #include "CcdPhysicsEnvironment.h" #include "SimdTransformUtil.h" +#include "CollisionShapes/SphereShape.h" +#include "CollisionShapes/ConeShape.h" + class BP_Proxy; ///todo: fill all the empty CcdPhysicsController methods, hook them up to the RigidBody class @@ -31,7 +34,7 @@ class BP_Proxy; float gDeactivationTime = 2.f; bool gDisableDeactivation = false; -float gLinearSleepingTreshold = 0.8f; +float gLinearSleepingTreshold = 0.4f; float gAngularSleepingTreshold = 1.0f; #include "Dynamics/MassProps.h" @@ -486,3 +489,96 @@ bool CcdPhysicsController::wantsSleeping() return false; } +PHY_IPhysicsController* CcdPhysicsController::GetReplica() +{ + //very experimental, shape sharing is not implemented yet. + //just support SphereShape/ConeShape for now + + CcdConstructionInfo cinfo = m_cci; + if (cinfo.m_collisionShape) + { + switch (cinfo.m_collisionShape->GetShapeType()) + { + case SPHERE_SHAPE_PROXYTYPE: + { + SphereShape* orgShape = (SphereShape*)cinfo.m_collisionShape; + cinfo.m_collisionShape = new SphereShape(*orgShape); + break; + } + + case CONE_SHAPE_PROXYTYPE: + { + ConeShape* orgShape = (ConeShape*)cinfo.m_collisionShape; + cinfo.m_collisionShape = new ConeShape(*orgShape); + break; + } + + + default: + { + return 0; + } + } + } + + cinfo.m_MotionState = new DefaultMotionState(); + + CcdPhysicsController* replica = new CcdPhysicsController(cinfo); + return replica; +} + +/////////////////////////////////////////////////////////// +///A small utility class, DefaultMotionState +/// +/////////////////////////////////////////////////////////// + +DefaultMotionState::DefaultMotionState() +{ + m_worldTransform.setIdentity(); +} + + +DefaultMotionState::~DefaultMotionState() +{ + +} + +void DefaultMotionState::getWorldPosition(float& posX,float& posY,float& posZ) +{ + posX = m_worldTransform.getOrigin().x(); + posY = m_worldTransform.getOrigin().y(); + posZ = m_worldTransform.getOrigin().z(); +} + +void DefaultMotionState::getWorldScaling(float& scaleX,float& scaleY,float& scaleZ) +{ + scaleX = 1.; + scaleY = 1.; + scaleZ = 1.; +} + +void DefaultMotionState::getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal) +{ + quatIma0 = m_worldTransform.getRotation().x(); + quatIma1 = m_worldTransform.getRotation().y(); + quatIma2 = m_worldTransform.getRotation().z(); + quatReal = m_worldTransform.getRotation()[3]; +} + +void DefaultMotionState::setWorldPosition(float posX,float posY,float posZ) +{ + SimdPoint3 pos(posX,posY,posZ); + m_worldTransform.setOrigin( pos ); +} + +void DefaultMotionState::setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal) +{ + SimdQuaternion orn(quatIma0,quatIma1,quatIma2,quatReal); + m_worldTransform.setRotation( orn ); +} + +void DefaultMotionState::calculateWorldTransformations() +{ + +} + diff --git a/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsController.h b/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsController.h index 646b21f285e..056feba652c 100644 --- a/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsController.h +++ b/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsController.h @@ -27,6 +27,7 @@ subject to the following restrictions: #include "SimdTransform.h" #include "Dynamics/RigidBody.h" +#include "PHY_IMotionState.h" #include "BroadphaseCollision/BroadphaseProxy.h" //for CollisionShape access class CollisionShape; @@ -155,7 +156,8 @@ class CcdPhysicsController : public PHY_IPhysicsController // clientinfo for raycasts for example virtual void* getNewClientInfo(); virtual void setNewClientInfo(void* clientinfo); - virtual PHY_IPhysicsController* GetReplica() {return 0;} + virtual PHY_IPhysicsController* GetReplica(); + virtual void calcXform() {} ; virtual void SetMargin(float margin) {}; @@ -184,4 +186,30 @@ class CcdPhysicsController : public PHY_IPhysicsController }; + + + +///DefaultMotionState implements standard motionstate, using SimdTransform +class DefaultMotionState : public PHY_IMotionState + +{ + public: + DefaultMotionState(); + + virtual ~DefaultMotionState(); + + virtual void getWorldPosition(float& posX,float& posY,float& posZ); + virtual void getWorldScaling(float& scaleX,float& scaleY,float& scaleZ); + virtual void getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal); + + virtual void setWorldPosition(float posX,float posY,float posZ); + virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal); + + virtual void calculateWorldTransformations(); + + SimdTransform m_worldTransform; + +}; + + #endif //BULLET2_PHYSICSCONTROLLER_H diff --git a/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsEnvironment.cpp b/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsEnvironment.cpp index cb4adc77d76..4b4d3f15dae 100644 --- a/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsEnvironment.cpp +++ b/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsEnvironment.cpp @@ -29,6 +29,10 @@ subject to the following restrictions: #include "CollisionDispatch/CollisionWorld.h" #include "CollisionShapes/ConvexShape.h" +#include "CollisionShapes/ConeShape.h" + + + #include "BroadphaseCollision/Dispatcher.h" #include "NarrowPhaseCollision/PersistentManifold.h" #include "CollisionShapes/TriangleMeshShape.h" @@ -321,6 +325,7 @@ static void DrawAabb(IDebugDraw* debugDrawer,const SimdVector3& from,const SimdV CcdPhysicsEnvironment::CcdPhysicsEnvironment(CollisionDispatcher* dispatcher,BroadphaseInterface* broadphase) :m_scalingPropagated(false), m_numIterations(10), +m_numTimeSubSteps(1), m_ccdMode(0), m_solverType(-1), m_profileTimings(0), @@ -342,9 +347,9 @@ m_enableSatCollisionDetection(false) SimdVector3 worldMin(-10000,-10000,-10000); SimdVector3 worldMax(10000,10000,10000); - //broadphase = new AxisSweep3(worldMin,worldMax); + broadphase = new AxisSweep3(worldMin,worldMax); - broadphase = new SimpleBroadphase(); + //broadphase = new SimpleBroadphase(); } @@ -498,6 +503,8 @@ void CcdPhysicsEnvironment::beginFrame() bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) { + //printf("proceedDeltaTime\n"); + #ifdef USE_QUICKPROF //toggle Profiler @@ -528,16 +535,38 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) 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++) + { - // define this in blender, the stepsize is 30 hertz, 60 hertz works much better -//#define SPLIT_TIMESTEP 1 + CcdPhysicsController* ctrl = *i; -#ifdef SPLIT_TIMESTEP - proceedDeltaTimeOneStep(0.5f*timeStep); - proceedDeltaTimeOneStep(0.5f*timeStep); -#else - proceedDeltaTimeOneStep(timeStep); -#endif + 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 @@ -563,7 +592,7 @@ bool CcdPhysicsEnvironment::proceedDeltaTimeOneStep(float timeStep) { - // printf("CcdPhysicsEnvironment::proceedDeltaTime\n"); + //printf("CcdPhysicsEnvironment::proceedDeltaTime\n"); if (SimdFuzzyZero(timeStep)) return true; @@ -811,11 +840,7 @@ bool CcdPhysicsEnvironment::proceedDeltaTimeOneStep(float timeStep) if (body->GetActivationState() != ISLAND_SLEEPING) { - if (body->IsStatic()) - { - //to calculate velocities next frame - body->saveKinematicState(timeStep); - } else + if (!body->IsStatic()) { body->predictIntegratedTransform(timeStep* toi, predictedTrans); body->proceedToTransform( predictedTrans); @@ -1392,10 +1417,34 @@ TypedConstraint* CcdPhysicsEnvironment::getConstraintById(int constraintId) void CcdPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl) { + + CcdPhysicsController* ctrl1 = (CcdPhysicsController* )ctrl; + std::vector<CcdPhysicsController*>::iterator i = + std::find(m_controllers.begin(), m_controllers.end(), ctrl); + if ((i == m_controllers.end())) + { + addCcdPhysicsController(ctrl1); + } + + requestCollisionCallback(ctrl); //printf("addSensor\n"); } + +void CcdPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl) +{ + std::vector<CcdPhysicsController*>::iterator i = + std::find(m_triggerControllers.begin(), m_triggerControllers.end(), ctrl); + if (!(i == m_triggerControllers.end())) + { + std::swap(*i, m_triggerControllers.back()); + m_triggerControllers.pop_back(); + } +} + + void CcdPhysicsEnvironment::removeSensor(PHY_IPhysicsController* ctrl) { + removeCollisionCallback(ctrl); //printf("removeSensor\n"); } void CcdPhysicsEnvironment::addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user) @@ -1584,3 +1633,41 @@ void CcdPhysicsEnvironment::UpdateAabbs(float timeStep) } } } + +PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radius,const PHY__Vector3& position) +{ + + CcdConstructionInfo cinfo; + cinfo.m_collisionShape = new SphereShape(radius); + cinfo.m_MotionState = 0; + cinfo.m_physicsEnv = this; + cinfo.m_collisionFlags |= CollisionObject::noContactResponse; + DefaultMotionState* motionState = new DefaultMotionState(); + cinfo.m_MotionState = motionState; + motionState->m_worldTransform.setIdentity(); + motionState->m_worldTransform.setOrigin(SimdVector3(position[0],position[1],position[2])); + + CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo); + + + return sphereController; +} + + +PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float coneradius,float coneheight) +{ + CcdConstructionInfo cinfo; + cinfo.m_collisionShape = new ConeShape(coneradius,coneheight); + cinfo.m_MotionState = 0; + cinfo.m_physicsEnv = this; + DefaultMotionState* motionState = new DefaultMotionState(); + cinfo.m_MotionState = motionState; + motionState->m_worldTransform.setIdentity(); +// motionState->m_worldTransform.setOrigin(SimdVector3(position[0],position[1],position[2])); + + CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo); + + + return sphereController; +} + diff --git a/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsEnvironment.h b/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsEnvironment.h index 08dff62e236..9de7053d271 100644 --- a/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsEnvironment.h +++ b/extern/bullet/Extras/PhysicsInterface/CcdPhysics/CcdPhysicsEnvironment.h @@ -48,7 +48,11 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment SimdVector3 m_gravity; IDebugDraw* m_debugDrawer; + //solver iterations int m_numIterations; + + //timestep subdivisions + int m_numTimeSubSteps; int m_ccdMode; int m_solverType; int m_profileTimings; @@ -74,6 +78,10 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment } virtual void setNumIterations(int numIter); + virtual void setNumTimeSubSteps(int numTimeSubSteps) + { + m_numTimeSubSteps = numTimeSubSteps; + } virtual void setDeactivationTime(float dTime); virtual void setDeactivationLinearTreshold(float linTresh) ; virtual void setDeactivationAngularTreshold(float angTresh) ; @@ -131,8 +139,10 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment virtual void removeSensor(PHY_IPhysicsController* ctrl); virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user); virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl); - virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) {return 0;}; - virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight){ return 0;}; + virtual void removeCollisionCallback(PHY_IPhysicsController* ctrl); + + virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position); + virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight); virtual int getNumContactPoints(); diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 9fcbabba546..a270b73c80d 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -85,8 +85,24 @@ static BlendFileData *load_game_data(char *filename) { BlendReadError error; - BlendFileData *bfd= BLO_read_from_file(filename, &error); - + //this doesn't work anymore for relative paths, so use BLO_read_from_memory instead + //BlendFileData *bfd= BLO_read_from_file(filename, &error); + FILE* file = fopen(filename,"rb"); + BlendFileData *bfd = 0; + if (file) + { + fseek(file, 0L, SEEK_END); + int len= ftell(file); + fseek(file, 0L, SEEK_SET); + char* filebuffer= new char[len];//MEM_mallocN(len, "text_buffer"); + int sizeread = fread(filebuffer,len,1,file); + if (sizeread==1) + { + bfd = BLO_read_from_memory(filebuffer, len, &error); + } + fclose(file); + } + if (!bfd) { printf("Loading %s failed: %s\n", filename, BLO_bre_as_string(error)); } @@ -96,17 +112,17 @@ static BlendFileData *load_game_data(char *filename) { extern "C" void StartKetsjiShell(struct ScrArea *area, char* scenename, - struct Main* maggie, + struct Main* maggie1, struct SpaceIpo *sipo, int always_use_expand_framing) { int exitrequested = KX_EXIT_REQUEST_NO_REQUEST; - Main* blenderdata = maggie; + Main* blenderdata = maggie1; char* startscenename = scenename; char pathname[160]; - strcpy (pathname, maggie->name); + strcpy (pathname, blenderdata->name); STR_String exitstring = ""; BlendFileData *bfd= NULL; @@ -257,8 +273,8 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, Scene *blscene = NULL; if (!bfd) { - blscene = (Scene*) maggie->scene.first; - for (Scene *sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next) + blscene = (Scene*) blenderdata->scene.first; + for (Scene *sce= (Scene*) blenderdata->scene.first; sce; sce= (Scene*) sce->id.next) { if (startscenename == (sce->id.name+2)) { @@ -292,7 +308,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, } // create a scene converter, create and convert the startingscene - KX_ISceneConverter* sceneconverter = new KX_BlenderSceneConverter(maggie,sipo, ketsjiengine); + KX_ISceneConverter* sceneconverter = new KX_BlenderSceneConverter(blenderdata,sipo, ketsjiengine); ketsjiengine->SetSceneConverter(sceneconverter); if (always_use_expand_framing) diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index eb91427f2d3..40c15302553 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -386,6 +386,11 @@ void BL_ConvertSensors(struct Object* blenderobject, bool bFindMaterial = false; PHY_IPhysicsController* physCtrl = kxscene->GetPhysicsEnvironment()->CreateSphereController(radius,pos); + if (isInActiveLayer) + kxscene->GetPhysicsEnvironment()->addSensor(physCtrl); + + + gamesensor = new KX_NearSensor(eventmgr,gameobj, blendernearsensor->dist, blendernearsensor->resetdist, diff --git a/source/gameengine/GameLogic/SCA_IScene.h b/source/gameengine/GameLogic/SCA_IScene.h index d77c1dd6483..3c62ec91515 100644 --- a/source/gameengine/GameLogic/SCA_IScene.h +++ b/source/gameengine/GameLogic/SCA_IScene.h @@ -53,6 +53,8 @@ public: int lifespan=0)=0; virtual void RemoveObject(class CValue* gameobj)=0; virtual void DelayedRemoveObject(class CValue* gameobj)=0; + virtual void DelayedReleaseObject(class CValue* gameobj)=0; + virtual void ReplaceMesh(class CValue* gameobj, void* meshobj)=0; std::vector<SCA_DebugProp*>& GetDebugProperties(); diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index 5c6f038e23d..fac2302b85e 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -80,7 +80,10 @@ KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr, void KX_NearSensor::RegisterSumo(KX_TouchEventManager *touchman) { - touchman->GetPhysicsEnvironment()->addSensor(m_physCtrl); + if (m_physCtrl) + { + touchman->GetPhysicsEnvironment()->addSensor(m_physCtrl); + } } CValue* KX_NearSensor::GetReplica() @@ -96,7 +99,18 @@ CValue* KX_NearSensor::GetReplica() replica->m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::NEAR); - replica->m_physCtrl = replica->m_physCtrl->GetReplica(); + if (replica->m_physCtrl) + { + replica->m_physCtrl = replica->m_physCtrl->GetReplica(); + if (replica->m_physCtrl) + { + //static_cast<KX_TouchEventManager*>(m_eventmgr)->GetPhysicsEnvironment()->addSensor(replica->m_physCtrl); + replica->m_physCtrl->SetMargin(m_Margin); + replica->m_physCtrl->setNewClientInfo(replica->m_client_info); + } + + } + //static_cast<KX_TouchEventManager*>(m_eventmgr)->RegisterSensor(this); //todo: make sure replication works fine //>m_sumoObj = new SM_Object(DT_NewSphere(0.0),NULL,NULL,NULL); //replica->m_sumoObj->setMargin(m_Margin); @@ -111,11 +125,21 @@ CValue* KX_NearSensor::GetReplica() void KX_NearSensor::ReParent(SCA_IObject* parent) { + SCA_ISensor::ReParent(parent); m_client_info->m_gameobject = static_cast<KX_GameObject*>(parent); m_client_info->m_sensors.push_back(this); + +/* KX_ClientObjectInfo *client_info = gameobj->getClientInfo(); + client_info->m_gameobject = gameobj; + client_info->m_auxilary_info = NULL; + + client_info->m_sensors.push_back(this); + SCA_ISensor::ReParent(parent); +*/ + SynchronizeTransform(); } @@ -127,10 +151,11 @@ KX_NearSensor::~KX_NearSensor() // for touchsensor, it's the parent if (m_physCtrl) { - static_cast<KX_TouchEventManager*>(m_eventmgr)->GetPhysicsEnvironment()->removeSensor(m_physCtrl); + //static_cast<KX_TouchEventManager*>(m_eventmgr)->GetPhysicsEnvironment()->removeSensor(m_physCtrl); delete m_physCtrl; m_physCtrl = NULL; } + if (m_client_info) delete m_client_info; diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index e9c71fe02c9..28138195a5e 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -53,6 +53,9 @@ static char gPySetGravity__doc__[] = "setGravity(float x,float y,float z)"; static char gPySetDebugMode__doc__[] = "setDebugMode(int mode)"; static char gPySetNumIterations__doc__[] = "setNumIterations(int numiter) This sets the number of iterations for an iterative constraint solver"; +static char gPySetNumTimeSubSteps__doc__[] = "setNumTimeSubSteps(int numsubstep) This sets the number of substeps for each physics proceed. Tradeoff quality for performance."; + + static char gPySetDeactivationTime__doc__[] = "setDeactivationTime(float time) This sets the time after which a resting rigidbody gets deactived"; static char gPySetDeactivationLinearTreshold__doc__[] = "setDeactivationLinearTreshold(float linearTreshold)"; static char gPySetDeactivationAngularTreshold__doc__[] = "setDeactivationAngularTreshold(float angularTreshold)"; @@ -106,6 +109,24 @@ static PyObject* gPySetDebugMode(PyObject* self, Py_INCREF(Py_None); return Py_None; } + + +static PyObject* gPySetNumTimeSubSteps(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + int substep; + if (PyArg_ParseTuple(args,"i",&substep)) + { + if (PHY_GetActiveEnvironment()) + { + PHY_GetActiveEnvironment()->setNumTimeSubSteps(substep); + } + } + Py_INCREF(Py_None); return Py_None; +} + + static PyObject* gPySetNumIterations(PyObject* self, PyObject* args, PyObject* kwds) @@ -411,6 +432,9 @@ static struct PyMethodDef physicsconstraints_methods[] = { {"setNumIterations",(PyCFunction) gPySetNumIterations, METH_VARARGS, gPySetNumIterations__doc__}, + {"setNumTimeSubSteps",(PyCFunction) gPySetNumTimeSubSteps, + METH_VARARGS, gPySetNumTimeSubSteps__doc__}, + {"setDeactivationTime",(PyCFunction) gPySetDeactivationTime, METH_VARARGS, gPySetDeactivationTime__doc__}, diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index 322f41e11a3..45b2db10b33 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -318,7 +318,11 @@ void KX_SCA_AddObjectActuator::InstantAddObject() // keep a copy of the last object, to allow python scripters to change it if (m_lastCreatedObject) + { + //careful with destruction, it might still have outstanding collision callbacks + m_scene->DelayedReleaseObject(m_lastCreatedObject); m_lastCreatedObject->Release(); + } m_lastCreatedObject = replica; m_lastCreatedObject->AddRef(); diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 1706937f8df..a5bbfa41e3e 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -125,6 +125,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_parentlist = new CListValue(); m_lightlist= new CListValue(); m_euthanasyobjects = new CListValue(); + m_delayReleaseObjects = new CListValue(); m_logicmgr = new SCA_LogicManager(); @@ -193,6 +194,8 @@ KX_Scene::~KX_Scene() if (m_euthanasyobjects) m_euthanasyobjects->Release(); + if (m_delayReleaseObjects) + m_delayReleaseObjects->Release(); if (m_logicmgr) delete m_logicmgr; @@ -654,8 +657,13 @@ void KX_Scene::RemoveObject(class CValue* gameobj) // recursively destruct node->Destruct(); } + newobj->SetSGNode(0); } +void KX_Scene::DelayedReleaseObject(CValue* gameobj) +{ + m_delayReleaseObjects->Add(gameobj->AddRef()); +} void KX_Scene::DelayedRemoveObject(class CValue* gameobj) @@ -1087,12 +1095,22 @@ void KX_Scene::LogicEndFrame() { m_logicmgr->EndFrame(); int numobj = m_euthanasyobjects->GetCount(); - - for (int i = numobj - 1; i >= 0; i--) + int i; + for (i = numobj - 1; i >= 0; i--) { KX_GameObject* gameobj = (KX_GameObject*)m_euthanasyobjects->GetValue(i); this->RemoveObject(gameobj); } + + numobj= m_delayReleaseObjects->GetCount(); + for (i = numobj-1;i>=0;i--) + { + KX_GameObject* gameobj = (KX_GameObject*)m_delayReleaseObjects->GetValue(i); + m_delayReleaseObjects->RemoveValue(gameobj); + + } + + } diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 4bcfb3ee194..ba479c5e543 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -101,6 +101,11 @@ protected: * LogicEndFrame() via a call to RemoveObject(). */ CListValue* m_euthanasyobjects; + /** + * The list of objects that couldn't be released during logic update. + * for example, AddObject actuator sometimes releases an object that was cached from previous frame + */ + CListValue* m_delayReleaseObjects; CListValue* m_objectlist; CListValue* m_parentlist; // all 'root' parents @@ -288,6 +293,9 @@ public: CValue* gameobj); void RemoveObject(CValue* gameobj); void DelayedRemoveObject(CValue* gameobj); + + void DelayedReleaseObject(CValue* gameobj); + void NewRemoveObject(CValue* gameobj); void ReplaceMesh(CValue* gameobj, void* meshobj); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index b8ce09729c2..cddc780aff4 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -23,6 +23,9 @@ subject to the following restrictions: #include "CcdPhysicsEnvironment.h" #include "SimdTransformUtil.h" +#include "CollisionShapes/SphereShape.h" +#include "CollisionShapes/ConeShape.h" + class BP_Proxy; ///todo: fill all the empty CcdPhysicsController methods, hook them up to the RigidBody class @@ -486,3 +489,96 @@ bool CcdPhysicsController::wantsSleeping() return false; } +PHY_IPhysicsController* CcdPhysicsController::GetReplica() +{ + //very experimental, shape sharing is not implemented yet. + //just support SphereShape/ConeShape for now + + CcdConstructionInfo cinfo = m_cci; + if (cinfo.m_collisionShape) + { + switch (cinfo.m_collisionShape->GetShapeType()) + { + case SPHERE_SHAPE_PROXYTYPE: + { + SphereShape* orgShape = (SphereShape*)cinfo.m_collisionShape; + cinfo.m_collisionShape = new SphereShape(*orgShape); + break; + } + + case CONE_SHAPE_PROXYTYPE: + { + ConeShape* orgShape = (ConeShape*)cinfo.m_collisionShape; + cinfo.m_collisionShape = new ConeShape(*orgShape); + break; + } + + + default: + { + return 0; + } + } + } + + cinfo.m_MotionState = new DefaultMotionState(); + + CcdPhysicsController* replica = new CcdPhysicsController(cinfo); + return replica; +} + +/////////////////////////////////////////////////////////// +///A small utility class, DefaultMotionState +/// +/////////////////////////////////////////////////////////// + +DefaultMotionState::DefaultMotionState() +{ + m_worldTransform.setIdentity(); +} + + +DefaultMotionState::~DefaultMotionState() +{ + +} + +void DefaultMotionState::getWorldPosition(float& posX,float& posY,float& posZ) +{ + posX = m_worldTransform.getOrigin().x(); + posY = m_worldTransform.getOrigin().y(); + posZ = m_worldTransform.getOrigin().z(); +} + +void DefaultMotionState::getWorldScaling(float& scaleX,float& scaleY,float& scaleZ) +{ + scaleX = 1.; + scaleY = 1.; + scaleZ = 1.; +} + +void DefaultMotionState::getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal) +{ + quatIma0 = m_worldTransform.getRotation().x(); + quatIma1 = m_worldTransform.getRotation().y(); + quatIma2 = m_worldTransform.getRotation().z(); + quatReal = m_worldTransform.getRotation()[3]; +} + +void DefaultMotionState::setWorldPosition(float posX,float posY,float posZ) +{ + SimdPoint3 pos(posX,posY,posZ); + m_worldTransform.setOrigin( pos ); +} + +void DefaultMotionState::setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal) +{ + SimdQuaternion orn(quatIma0,quatIma1,quatIma2,quatReal); + m_worldTransform.setRotation( orn ); +} + +void DefaultMotionState::calculateWorldTransformations() +{ + +} + diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 646b21f285e..056feba652c 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -27,6 +27,7 @@ subject to the following restrictions: #include "SimdTransform.h" #include "Dynamics/RigidBody.h" +#include "PHY_IMotionState.h" #include "BroadphaseCollision/BroadphaseProxy.h" //for CollisionShape access class CollisionShape; @@ -155,7 +156,8 @@ class CcdPhysicsController : public PHY_IPhysicsController // clientinfo for raycasts for example virtual void* getNewClientInfo(); virtual void setNewClientInfo(void* clientinfo); - virtual PHY_IPhysicsController* GetReplica() {return 0;} + virtual PHY_IPhysicsController* GetReplica(); + virtual void calcXform() {} ; virtual void SetMargin(float margin) {}; @@ -184,4 +186,30 @@ class CcdPhysicsController : public PHY_IPhysicsController }; + + + +///DefaultMotionState implements standard motionstate, using SimdTransform +class DefaultMotionState : public PHY_IMotionState + +{ + public: + DefaultMotionState(); + + virtual ~DefaultMotionState(); + + virtual void getWorldPosition(float& posX,float& posY,float& posZ); + virtual void getWorldScaling(float& scaleX,float& scaleY,float& scaleZ); + virtual void getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal); + + virtual void setWorldPosition(float posX,float posY,float posZ); + virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal); + + virtual void calculateWorldTransformations(); + + SimdTransform m_worldTransform; + +}; + + #endif //BULLET2_PHYSICSCONTROLLER_H diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index e24bc1653af..4b4d3f15dae 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -29,6 +29,10 @@ subject to the following restrictions: #include "CollisionDispatch/CollisionWorld.h" #include "CollisionShapes/ConvexShape.h" +#include "CollisionShapes/ConeShape.h" + + + #include "BroadphaseCollision/Dispatcher.h" #include "NarrowPhaseCollision/PersistentManifold.h" #include "CollisionShapes/TriangleMeshShape.h" @@ -321,6 +325,7 @@ static void DrawAabb(IDebugDraw* debugDrawer,const SimdVector3& from,const SimdV CcdPhysicsEnvironment::CcdPhysicsEnvironment(CollisionDispatcher* dispatcher,BroadphaseInterface* broadphase) :m_scalingPropagated(false), m_numIterations(10), +m_numTimeSubSteps(1), m_ccdMode(0), m_solverType(-1), m_profileTimings(0), @@ -342,9 +347,9 @@ m_enableSatCollisionDetection(false) SimdVector3 worldMin(-10000,-10000,-10000); SimdVector3 worldMax(10000,10000,10000); - //broadphase = new AxisSweep3(worldMin,worldMax); + broadphase = new AxisSweep3(worldMin,worldMax); - broadphase = new SimpleBroadphase(); + //broadphase = new SimpleBroadphase(); } @@ -498,6 +503,8 @@ void CcdPhysicsEnvironment::beginFrame() bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) { + //printf("proceedDeltaTime\n"); + #ifdef USE_QUICKPROF //toggle Profiler @@ -529,16 +536,37 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) 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++) + { - // define this in blender, the stepsize is 30 hertz, 60 hertz works much better -//#define SPLIT_TIMESTEP 1 + CcdPhysicsController* ctrl = *i; -#ifdef SPLIT_TIMESTEP - proceedDeltaTimeOneStep(0.5f*timeStep); - proceedDeltaTimeOneStep(0.5f*timeStep); -#else - proceedDeltaTimeOneStep(timeStep); -#endif + 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 @@ -564,7 +592,7 @@ bool CcdPhysicsEnvironment::proceedDeltaTimeOneStep(float timeStep) { - // printf("CcdPhysicsEnvironment::proceedDeltaTime\n"); + //printf("CcdPhysicsEnvironment::proceedDeltaTime\n"); if (SimdFuzzyZero(timeStep)) return true; @@ -812,11 +840,7 @@ bool CcdPhysicsEnvironment::proceedDeltaTimeOneStep(float timeStep) if (body->GetActivationState() != ISLAND_SLEEPING) { - if (body->IsStatic()) - { - //to calculate velocities next frame - body->saveKinematicState(timeStep); - } else + if (!body->IsStatic()) { body->predictIntegratedTransform(timeStep* toi, predictedTrans); body->proceedToTransform( predictedTrans); @@ -1393,10 +1417,34 @@ TypedConstraint* CcdPhysicsEnvironment::getConstraintById(int constraintId) void CcdPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl) { + + CcdPhysicsController* ctrl1 = (CcdPhysicsController* )ctrl; + std::vector<CcdPhysicsController*>::iterator i = + std::find(m_controllers.begin(), m_controllers.end(), ctrl); + if ((i == m_controllers.end())) + { + addCcdPhysicsController(ctrl1); + } + + requestCollisionCallback(ctrl); //printf("addSensor\n"); } + +void CcdPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl) +{ + std::vector<CcdPhysicsController*>::iterator i = + std::find(m_triggerControllers.begin(), m_triggerControllers.end(), ctrl); + if (!(i == m_triggerControllers.end())) + { + std::swap(*i, m_triggerControllers.back()); + m_triggerControllers.pop_back(); + } +} + + void CcdPhysicsEnvironment::removeSensor(PHY_IPhysicsController* ctrl) { + removeCollisionCallback(ctrl); //printf("removeSensor\n"); } void CcdPhysicsEnvironment::addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user) @@ -1585,3 +1633,41 @@ void CcdPhysicsEnvironment::UpdateAabbs(float timeStep) } } } + +PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radius,const PHY__Vector3& position) +{ + + CcdConstructionInfo cinfo; + cinfo.m_collisionShape = new SphereShape(radius); + cinfo.m_MotionState = 0; + cinfo.m_physicsEnv = this; + cinfo.m_collisionFlags |= CollisionObject::noContactResponse; + DefaultMotionState* motionState = new DefaultMotionState(); + cinfo.m_MotionState = motionState; + motionState->m_worldTransform.setIdentity(); + motionState->m_worldTransform.setOrigin(SimdVector3(position[0],position[1],position[2])); + + CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo); + + + return sphereController; +} + + +PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float coneradius,float coneheight) +{ + CcdConstructionInfo cinfo; + cinfo.m_collisionShape = new ConeShape(coneradius,coneheight); + cinfo.m_MotionState = 0; + cinfo.m_physicsEnv = this; + DefaultMotionState* motionState = new DefaultMotionState(); + cinfo.m_MotionState = motionState; + motionState->m_worldTransform.setIdentity(); +// motionState->m_worldTransform.setOrigin(SimdVector3(position[0],position[1],position[2])); + + CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo); + + + return sphereController; +} + diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 08dff62e236..9de7053d271 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -48,7 +48,11 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment SimdVector3 m_gravity; IDebugDraw* m_debugDrawer; + //solver iterations int m_numIterations; + + //timestep subdivisions + int m_numTimeSubSteps; int m_ccdMode; int m_solverType; int m_profileTimings; @@ -74,6 +78,10 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment } virtual void setNumIterations(int numIter); + virtual void setNumTimeSubSteps(int numTimeSubSteps) + { + m_numTimeSubSteps = numTimeSubSteps; + } virtual void setDeactivationTime(float dTime); virtual void setDeactivationLinearTreshold(float linTresh) ; virtual void setDeactivationAngularTreshold(float angTresh) ; @@ -131,8 +139,10 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment virtual void removeSensor(PHY_IPhysicsController* ctrl); virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user); virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl); - virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) {return 0;}; - virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight){ return 0;}; + virtual void removeCollisionCallback(PHY_IPhysicsController* ctrl); + + virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position); + virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight); virtual int getNumContactPoints(); diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index 6b40b51eba7..cdd67257de2 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -57,6 +57,8 @@ class PHY_IPhysicsEnvironment virtual void setDebugMode(int debugMode) {} ///setNumIterations set the number of iterations for iterative solvers virtual void setNumIterations(int numIter) {} + ///setNumTimeSubSteps set the number of divisions of the timestep. Tradeoff quality versus performance. + virtual void setNumTimeSubSteps(int numTimeSubSteps){} ///setDeactivationTime sets the minimum time that an objects has to stay within the velocity tresholds until it gets fully deactivated virtual void setDeactivationTime(float dTime) {} ///setDeactivationLinearTreshold sets the linear velocity treshold, see setDeactivationTime diff --git a/source/gameengine/SceneGraph/SG_Node.cpp b/source/gameengine/SceneGraph/SG_Node.cpp index c2a662c1fa2..aaacd43646b 100644 --- a/source/gameengine/SceneGraph/SG_Node.cpp +++ b/source/gameengine/SceneGraph/SG_Node.cpp @@ -186,6 +186,9 @@ void SG_Node::RemoveChild(SG_Node* child) void SG_Node::UpdateWorldData(double time) { + //if (!GetSGParent()) + // return; + if (UpdateSpatialData(GetSGParent(),time)) ActivateUpdateTransformCallback(); |