diff options
author | Kester Maddock <Christopher.Maddock.1@uni.massey.ac.nz> | 2004-11-22 13:19:19 +0300 |
---|---|---|
committer | Kester Maddock <Christopher.Maddock.1@uni.massey.ac.nz> | 2004-11-22 13:19:19 +0300 |
commit | 46fbe6b01e095ddb66f3bf6e0516569cfdca8f74 (patch) | |
tree | e7a7754188ef9b290eca479df6ac59b00ea7478b /source/gameengine/Physics/Sumo/Fuzzics | |
parent | cf91617d7829647629c8ce04b9f047dfbdf3d910 (diff) |
Fix for bugs: 1788 (forces) and 1799 (python delattr on game objects)
Use Polytope collision for faster mesh intersection tests, so SOLID can actually use that qhull lib now.
Diffstat (limited to 'source/gameengine/Physics/Sumo/Fuzzics')
7 files changed, 173 insertions, 71 deletions
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h index 116eed12cea..4db531d945d 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h +++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h @@ -40,7 +40,7 @@ public: SM_FhObject(DT_ShapeHandle rayshape, MT_Vector3 ray, SM_Object *parent_object); const MT_Vector3& getRay() const { return m_ray; } - MT_Point3 getSpot() const { return m_pos + m_ray; } + MT_Point3 getSpot() const { return getPosition() + m_ray; } const MT_Vector3& getRayDirection() const { return m_ray_direction; } SM_Object *getParentObject() const { return m_parent_object; } diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h index e7fbf3cdacc..b0e0717cf8c 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h +++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h @@ -1,3 +1,34 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ #ifndef SM_MOTIONSTATE_H #define SM_MOTIONSTATE_H @@ -6,6 +37,7 @@ class SM_MotionState { public: SM_MotionState() : + m_time(0.0), m_pos(0.0, 0.0, 0.0), m_orn(0.0, 0.0, 0.0, 1.0), m_lin_vel(0.0, 0.0, 0.0), @@ -16,17 +48,27 @@ public: void setOrientation(const MT_Quaternion& orn) { m_orn = orn; } void setLinearVelocity(const MT_Vector3& lin_vel) { m_lin_vel = lin_vel; } void setAngularVelocity(const MT_Vector3& ang_vel) { m_ang_vel = ang_vel; } + void setTime(MT_Scalar time) { m_time = time; } const MT_Point3& getPosition() const { return m_pos; } const MT_Quaternion& getOrientation() const { return m_orn; } const MT_Vector3& getLinearVelocity() const { return m_lin_vel; } const MT_Vector3& getAngularVelocity() const { return m_ang_vel; } + MT_Scalar getTime() const { return m_time; } + + void integrateMidpoint(MT_Scalar timeStep, const SM_MotionState &prev_state, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel); + void integrateBackward(MT_Scalar timeStep, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel); + void integrateForward(MT_Scalar timeStep, const SM_MotionState &prev_state); + + void lerp(MT_Scalar t, const SM_MotionState &other); + virtual MT_Transform getTransform() const { return MT_Transform(m_pos, m_orn); } protected: + MT_Scalar m_time; MT_Point3 m_pos; MT_Quaternion m_orn; MT_Vector3 m_lin_vel; diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h index 4a69f7e2990..b37e1a5466b 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h +++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h @@ -144,7 +144,6 @@ public: void setOrientation(const MT_Quaternion& orn); void setScaling(const MT_Vector3& scaling); - /** * set an external velocity. This velocity complements * the physics velocity. So setting it does not override the @@ -267,13 +266,7 @@ public: void relax(); - void backup() { - m_pos = m_prev_state.getPosition(); - m_orn = m_prev_state.getOrientation(); - m_xform = m_prev_xform; - } private: - // Tweak parameters static MT_Scalar ImpulseThreshold; diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h index 0b429a3c1a4..80e8c635cbb 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h +++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h @@ -88,13 +88,7 @@ public: void add(SM_Object& object); void remove(SM_Object& object); - void addPair(SM_Object *obj1, SM_Object *obj2) { - m_pairList.insert(std::make_pair(obj1, obj2)); - } - - void clearPairs() { - m_pairList.clear(); - } + void notifyCollision(SM_Object *obj1, SM_Object *obj2); void setSecondaryRespTable(DT_RespTableHandle secondaryRespTable); DT_RespTableHandle getSecondaryRespTable() { return m_secondaryRespTable; } @@ -146,8 +140,6 @@ private: /** internal type */ typedef std::vector<SM_Object *> T_ObjectList; - /** internal type */ - typedef std::set<std::pair<SM_Object *, SM_Object *> > T_PairList; /** Handle to the scene in SOLID */ DT_SceneHandle m_scene; @@ -174,12 +166,6 @@ private: * The list of objects that receive motion updates and do * collision tests. */ T_ObjectList m_objectList; - - /** - * A list with pairs of objects that collided the previous - * timestep. The list is built during the proceed(). During that - * time, it is not valid. */ - T_PairList m_pairList; MT_Scalar m_lastTime; }; diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp new file mode 100644 index 00000000000..a3285b19116 --- /dev/null +++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp @@ -0,0 +1,71 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <MT_Vector3.h> +#include <MT_Quaternion.h> + +#include "SM_MotionState.h" + +void SM_MotionState::integrateMidpoint(MT_Scalar timeStep, const SM_MotionState &prev_state, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel) +{ + m_pos += (prev_state.getLinearVelocity() + velocity) * (timeStep * 0.5); + m_orn += (prev_state.getAngularVelocity() * prev_state.getOrientation() + ang_vel * m_orn) * (timeStep * 0.25); + m_orn.normalize(); +} + +void SM_MotionState::integrateBackward(MT_Scalar timeStep, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel) +{ + m_pos += velocity * timeStep; + m_orn += ang_vel * m_orn * (timeStep * 0.5); + m_orn.normalize(); +} + +void SM_MotionState::integrateForward(MT_Scalar timeStep, const SM_MotionState &prev_state) +{ + m_pos += prev_state.getLinearVelocity() * timeStep; + m_orn += prev_state.getAngularVelocity() * m_orn * (timeStep * 0.5); + m_orn.normalize(); +} + +void SM_MotionState::lerp(MT_Scalar t, const SM_MotionState &other) +{ + MT_Scalar x = (t - getTime())/(other.getTime() - getTime()); + m_pos = x*m_pos + (1-x)*other.getPosition(); + + m_orn = m_orn.slerp(other.getOrientation(), x); + + m_lin_vel = x*m_lin_vel + (1-x)*other.getLinearVelocity(); + m_ang_vel = x*m_ang_vel + (1-x)*other.getAngularVelocity(); + + m_time = t; +} + diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp index 42adfcd4d9e..ed5171a87a2 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp +++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp @@ -65,7 +65,6 @@ SM_Object::SM_Object( m_materialPropsBackup(0), m_shapeProps(shapeProps), m_shapePropsBackup(0), - m_object(DT_CreateObject(this, shape)), m_margin(0.0), m_scaling(1.0, 1.0, 1.0), m_reaction_impulse(0.0, 0.0, 0.0), @@ -84,6 +83,7 @@ SM_Object::SM_Object( m_inv_mass(0.0), m_inv_inertia(0., 0., 0.) { + m_object = DT_CreateObject(this, shape); m_xform.setIdentity(); m_xform.getValue(m_ogl_matrix); if (shapeProps) @@ -146,19 +146,14 @@ integrateMomentum( //#define BACKWARD #ifdef MIDPOINT // Midpoint rule - m_pos += (m_prev_state.getLinearVelocity() + actualLinVelocity()) * (timeStep * 0.5); - m_orn += (m_prev_state.getAngularVelocity() * m_prev_state.getOrientation() + actualAngVelocity() * m_orn) * (timeStep * 0.25); + integrateMidpoint(timeStep, m_prev_state, actualLinVelocity(), actualAngVelocity()); #elif defined BACKWARD // Backward Euler - m_pos += actualLinVelocity() * timeStep; - m_orn += actualAngVelocity() * m_orn * (timeStep * 0.5); + integrateBackward(timeStep, actualLinVelocity(), actualAngVelocity()); #else // Forward Euler - - m_pos += m_prev_state.getLinearVelocity() * timeStep; - m_orn += m_prev_state.getAngularVelocity() * m_orn * (timeStep * 0.5); + integrateForward(timeStep, m_prev_state); #endif - m_orn.normalize(); // I might not be necessary to do this every call calcXform(); notifyClient(); @@ -212,7 +207,7 @@ void SM_Object::dynamicCollision(const MT_Point3 &local2, * Apply impulse at the collision point. * Take rotational inertia into account. */ - applyImpulse(local2 + m_pos, impulse * normal); + applyImpulse(local2 + getPosition(), impulse * normal); } else { /** * Apply impulse through object centre. (no rotation.) @@ -323,7 +318,7 @@ void SM_Object::dynamicCollision(const MT_Point3 &local2, (invMass + lateral.dot(temp.cross(local2))); MT_Scalar friction = MT_min(impulse_lateral, max_friction); - applyImpulse(local2 + m_pos, -lateral * friction); + applyImpulse(local2 + getPosition(), -lateral * friction); } else { MT_Scalar impulse_lateral = rel_vel_lateral / invMass; @@ -349,7 +344,7 @@ static void AddCallback(SM_Scene *scene, SM_Object *obj1, SM_Object *obj2) if ((obj1->getClientObject() && obj1->getClientObject()->hasCollisionCallback()) || (obj2->getClientObject() && obj2->getClientObject()->hasCollisionCallback()) && DT_GetIntersect(obj1->getObjectHandle(), obj2->getObjectHandle(), v)) - scene->addPair(obj1, obj2); + scene->notifyCollision(obj1, obj2); } DT_Bool SM_Object::boing( @@ -402,10 +397,10 @@ DT_Bool SM_Object::boing( // Set callbacks for game engine. if ((obj1->getClientObject() && obj1->getClientObject()->hasCollisionCallback()) || (obj2->getClientObject() && obj2->getClientObject()->hasCollisionCallback())) - scene->addPair(obj1, obj2); + scene->notifyCollision(obj1, obj2); - local1 -= obj1->m_pos; - local2 -= obj2->m_pos; + local1 -= obj1->getPosition(); + local2 -= obj2->getPosition(); // Calculate collision parameters MT_Vector3 rel_vel = obj1->getVelocity(local1) - obj2->getVelocity(local2); @@ -492,7 +487,7 @@ void SM_Object::relax(void) return; //std::cout << "SM_Object::relax: { " << m_error << " }" << std::endl; - m_pos += m_error; + setPosition(getPosition() + m_error); m_error.setValue(0., 0., 0.); calcXform(); notifyClient(); @@ -641,15 +636,15 @@ calcXform() { printf(" m_scaling = { %-0.5f, %-0.5f, %-0.5f }\n", m_scaling[0], m_scaling[1], m_scaling[2]); #endif - m_xform.setOrigin(m_pos); - m_xform.setBasis(MT_Matrix3x3(m_orn, m_scaling)); + m_xform.setOrigin(getPosition()); + m_xform.setBasis(MT_Matrix3x3(getOrientation(), m_scaling)); m_xform.getValue(m_ogl_matrix); /* Blender has been known to crash here. This usually means SM_Object *this has been deleted more than once. */ DT_SetMatrixd(m_object, m_ogl_matrix); if (m_fh_object) { - m_fh_object->setPosition(m_pos); + m_fh_object->setPosition(getPosition()); m_fh_object->calcXform(); } updateInvInertiaTensor(); @@ -765,9 +760,9 @@ setPosition( const MT_Point3& pos ){ m_kinematic = true; - m_pos = pos; + SM_MotionState::setPosition(pos); } - + void SM_Object:: setOrientation( @@ -775,7 +770,7 @@ setOrientation( ){ assert(!orn.fuzzyZero()); m_kinematic = true; - m_orn = orn; + SM_MotionState::setOrientation(orn); } void diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp index 1ea19c56336..c29be228d64 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp +++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp @@ -65,21 +65,21 @@ SM_Scene::SM_Scene() : /* Sensor */ DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], 0, DT_NO_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Scene::boing, DT_BROAD_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Scene::boing, DT_BROAD_RESPONSE, this); + DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this); + DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this); DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[FH_RESPONSE], 0, DT_NO_RESPONSE, this); /* Static */ - DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_BROAD_RESPONSE, this); + DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this); DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[STATIC_RESPONSE], 0, DT_NO_RESPONSE, this); DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_BROAD_RESPONSE, this); + DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this); /* Object */ - DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_BROAD_RESPONSE, this); + DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this); DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this); DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_BROAD_RESPONSE, this); + DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this); /* Fh Object */ DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], 0, DT_NO_RESPONSE, this); @@ -187,8 +187,30 @@ bool SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) { // Divide the timeStep into a number of subsamples of size roughly // equal to subS (might be a little smaller). MT_Scalar timeStep = curtime - m_lastTime; - MT_Scalar subStep = 1.0/ticrate; - int num_samples = int(timeStep * ticrate); + MT_Scalar subStep; + int num_samples; + + if (ticrate > 0.0) + { + subStep = 1.0/ticrate; + num_samples = int(timeStep * ticrate); + + if (num_samples > 4) + { + std::cout << "Dropping physics frames! step: " << timeStep << " frames:" << num_samples << std::endl; + num_samples /= 4; + subStep *= 4.0; + } + } + else + { + // Variable time step. (old update) + // Integrate at least 100 Hz + subStep = timeStep > 0.01 ? 0.01 : timeStep; + num_samples = int(timeStep * 0.01); + if (num_samples < 1) + num_samples = 1; + } T_ObjectList::iterator i; @@ -209,7 +231,7 @@ bool SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) { #endif return false; } - + m_lastTime += MT_Scalar(num_samples)*subStep; // Do the integration steps per object. @@ -253,24 +275,17 @@ bool SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) { //(*i)->clearForce(); } } - // For each pair of object that collided, call the corresponding callback. - // Additional collisions of a pair within the same time step are ignored. - - if (m_secondaryRespTable) { - T_PairList::iterator p; - for (p = m_pairList.begin(); p != m_pairList.end(); ++p) { - DT_CallResponse(m_secondaryRespTable, - (*p).first->getObjectHandle(), - (*p).second->getObjectHandle(), - 0); - } - } - - clearPairs(); - return true; } +void SM_Scene::notifyCollision(SM_Object *obj1, SM_Object *obj2) +{ + // For each pair of object that collided, call the corresponding callback. + if (m_secondaryRespTable) + DT_CallResponse(m_secondaryRespTable, obj1->getObjectHandle(), obj2->getObjectHandle(), 0); +} + + SM_Object *SM_Scene::rayTest(void *ignore_client, const MT_Point3& from, const MT_Point3& to, MT_Point3& result, MT_Vector3& normal) const { @@ -320,13 +335,13 @@ DT_Bool SM_Scene::boing( void *client_data, void *object1, void *object2, - const DT_CollData *coll_data + const DT_CollData * ){ SM_Scene *scene = (SM_Scene *)client_data; SM_Object *obj1 = (SM_Object *)object1; SM_Object *obj2 = (SM_Object *)object2; - scene->addPair(obj1, obj2); // Record this collision for client callbacks + scene->notifyCollision(obj1, obj2); // Record this collision for client callbacks #ifdef SM_DEBUG_BOING printf("SM_Scene::boing\n"); |