diff options
-rw-r--r-- | source/blender/makesdna/DNA_object_types.h | 4 | ||||
-rw-r--r-- | source/blender/src/buttons_logic.c | 18 | ||||
-rw-r--r-- | source/blender/src/editobject.c | 13 | ||||
-rw-r--r-- | source/gameengine/Converter/BL_BlenderDataConversion.cpp | 4 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_BulletPhysicsController.cpp | 27 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_BulletPhysicsController.h | 6 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp | 2 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.cpp | 49 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.h | 4 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_IPhysicsController.h | 6 | ||||
-rw-r--r-- | source/gameengine/Physics/Bullet/CcdPhysicsController.cpp | 14 | ||||
-rw-r--r-- | source/gameengine/Physics/Bullet/CcdPhysicsController.h | 23 | ||||
-rw-r--r-- | source/gameengine/Physics/common/PHY_IPhysicsController.h | 6 | ||||
-rw-r--r-- | source/gameengine/Physics/common/PHY_Pro.h | 6 | ||||
-rw-r--r-- | source/gameengine/PyDoc/KX_GameObject.py | 14 |
15 files changed, 176 insertions, 20 deletions
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 3a408404b0b..82da883df4a 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -157,7 +157,9 @@ typedef struct Object { float formfactor; float rdamping, sizefac; float margin; - int pad3; + float max_vel; /* clamp the maximum velocity 0.0 is disabled */ + float min_vel; /* clamp the maximum velocity 0.0 is disabled */ + float pad3; /* clamp the maximum velocity 0.0 is disabled */ char dt, dtx; char totcol; /* copy of mesh or curve or meta */ diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 2f68720acb0..67531e9b3b8 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -3139,6 +3139,7 @@ static uiBlock *advanced_bullet_menu(void *arg_ob) uiDefButF(block, NUM, 0, "Margin", xco, yco, 180, 19, &ob->margin, 0.001, 1.0, 1, 0, "Collision margin"); + yco -= 20; if (ob->gameflag & OB_RIGID_BODY) @@ -3166,7 +3167,24 @@ static uiBlock *advanced_bullet_menu(void *arg_ob) uiDefButBitI(block, TOG, OB_LOCK_RIGID_BODY_Z_ROT_AXIS, 0, "Lock Z Rot Axis", xco+=180, yco, 180, 19, &ob->gameflag2, 0, 0, 0, 0, "Disable simulation of angular motion along the Z axis"); + yco -= 20; } + xco = 0; + + uiBlockEndAlign(block); + + uiDefBut(block, LABEL, 0, "Clamp Velocity (zero disables)", xco, yco, 180*2, 19, NULL, 0, 0, 0, 0, ""); + + uiBlockBeginAlign(block); + + uiDefButF(block, NUM, 0, "Min", + xco+=180, yco, 90, 19, &ob->min_vel, 0.0, 1000.0, 1, 0, + "Clamp velocity to this minimum speed (except when totally still)"); + uiDefButF(block, NUM, 0, "Max", + xco+=90, yco, 90, 19, &ob->max_vel, 0.0, 1000.0, 1, 0, + "Clamp velocity to this maximum speed"); + uiBlockEndAlign(block); + /* uiDefButBitI(block, TOG, OB_BSB_COL_CL_RS, 0, "Cluster Collision RS", xco, yco, 180, 19, &ob->bsoft->collisionflags, 0, 0, 0, 0, diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index bb9be49c347..2f127f9a3ec 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -3205,14 +3205,12 @@ static void copymenu_properties(Object *ob) prop= prop->next; } - if(tot==0) { - error("No properties in the active object to copy"); - return; - } - str= MEM_callocN(50 + 33*tot, "copymenu prop"); - strcpy(str, "Copy Property %t|Replace All|Merge All|%l"); + if (tot) + strcpy(str, "Copy Property %t|Replace All|Merge All|%l"); + else + strcpy(str, "Copy Property %t|Clear All (no properties on active)"); tot= 0; prop= ob->prop.first; @@ -3526,7 +3524,8 @@ void copy_attr(short event) base->object->formfactor = ob->formfactor; base->object->damping= ob->damping; base->object->rdamping= ob->rdamping; - base->object->mass= ob->mass; + base->object->min_vel= ob->min_vel; + base->object->max_vel= ob->max_vel; if (ob->gameflag & OB_BOUNDS) { base->object->boundtype = ob->boundtype; } diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 5de2c4a2fe7..2ae47e47d74 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1107,6 +1107,10 @@ static PHY_ShapeProps *CreateShapePropsFromBlenderObject(struct Object* blendero shapeProps->m_do_fh = (blenderobject->gameflag & OB_DO_FH) != 0; shapeProps->m_do_rot_fh = (blenderobject->gameflag & OB_ROT_FH) != 0; +// velocity clamping XXX + shapeProps->m_clamp_vel_min = blenderobject->min_vel; + shapeProps->m_clamp_vel_max = blenderobject->max_vel; + return shapeProps; } diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index c621f11994a..831f9241fec 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -59,6 +59,24 @@ void KX_BulletPhysicsController::applyImpulse(const MT_Point3& attach, const MT_ } +float KX_BulletPhysicsController::GetLinVelocityMin() +{ + return (float)CcdPhysicsController::GetLinVelocityMin(); +} +void KX_BulletPhysicsController::SetLinVelocityMin(float val) +{ + CcdPhysicsController::SetLinVelocityMin(val); +} + +float KX_BulletPhysicsController::GetLinVelocityMax() +{ + return (float)CcdPhysicsController::GetLinVelocityMax(); +} +void KX_BulletPhysicsController::SetLinVelocityMax(float val) +{ + CcdPhysicsController::SetLinVelocityMax(val); +} + void KX_BulletPhysicsController::SetObject (SG_IObject* object) { SG_Controller::SetObject(object); @@ -73,6 +91,10 @@ void KX_BulletPhysicsController::SetObject (SG_IObject* object) } +MT_Scalar KX_BulletPhysicsController::GetRadius() +{ + return MT_Scalar(CcdPhysicsController::GetRadius()); +} void KX_BulletPhysicsController::setMargin (float collisionMargin) { @@ -176,11 +198,6 @@ MT_Vector3 KX_BulletPhysicsController::GetLocalInertia() return inertia; } -MT_Scalar KX_BulletPhysicsController::GetRadius() -{ - return MT_Scalar(CcdPhysicsController::GetRadius()); -} - MT_Vector3 KX_BulletPhysicsController::getReactionForce() { assert(0); diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h index 9821b3fd253..b39098206f7 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h @@ -56,7 +56,11 @@ public: virtual SG_Controller* GetReplica(class SG_Node* destnode); virtual MT_Scalar GetRadius(); - + + virtual float GetLinVelocityMin(); + virtual void SetLinVelocityMin(float val); + virtual float GetLinVelocityMax(); + virtual void SetLinVelocityMax(float val); virtual void SetSumoTransform(bool nondynaonly); // todo: remove next line ! diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 03149859f4d..08e2ea30414 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -801,6 +801,8 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, ci.m_gravity = btVector3(0,0,0); ci.m_localInertiaTensor =btVector3(0,0,0); ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f; + ci.m_clamp_vel_min = shapeprops->m_clamp_vel_min; + ci.m_clamp_vel_max = shapeprops->m_clamp_vel_max; ci.m_margin = objprop->m_margin; shapeInfo->m_radius = objprop->m_radius; isbulletdyna = objprop->m_dyna; diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 16cf3d9ae32..a399d3b477a 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1086,6 +1086,8 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("name", KX_GameObject, pyattr_get_name), KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent), KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass), + KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin", KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min), + KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax", KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max), KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible), KX_PYATTRIBUTE_BOOL_RW ("occlusion", KX_GameObject, m_bOccluder), KX_PYATTRIBUTE_RW_FUNCTION("position", KX_GameObject, pyattr_get_position, pyattr_set_position), @@ -1364,6 +1366,53 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd return 0; } +PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_IPhysicsController *spc = self->GetPhysicsController(); + return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f); +} + +int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_IPhysicsController *spc = self->GetPhysicsController(); + MT_Scalar val = PyFloat_AsDouble(value); + if (val < 0.0f) { /* also accounts for non float */ + PyErr_SetString(PyExc_AttributeError, "expected a float zero or above"); + return 1; + } + + if (spc) + spc->SetLinVelocityMin(val); + + return 0; +} + +PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_IPhysicsController *spc = self->GetPhysicsController(); + return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f); +} + +int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_IPhysicsController *spc = self->GetPhysicsController(); + MT_Scalar val = PyFloat_AsDouble(value); + if (val < 0.0f) { /* also accounts for non float */ + PyErr_SetString(PyExc_AttributeError, "expected a float zero or above"); + return 1; + } + + if (spc) + spc->SetLinVelocityMax(val); + + return 0; +} + + PyObject* KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self= static_cast<KX_GameObject*>(self_v); diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index c389d6cc776..94192580859 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -960,6 +960,10 @@ public: static PyObject* pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h index b7603203241..10b66da7b76 100644 --- a/source/gameengine/Ketsji/KX_IPhysicsController.h +++ b/source/gameengine/Ketsji/KX_IPhysicsController.h @@ -79,6 +79,12 @@ public: virtual void setScaling(const MT_Vector3& scaling)=0; virtual MT_Scalar GetMass()=0; virtual void SetMass(MT_Scalar newmass)=0; + + virtual float GetLinVelocityMin()=0; + virtual void SetLinVelocityMin(float newmass)=0; + virtual float GetLinVelocityMax()=0; + virtual void SetLinVelocityMax(float newmass)=0; + virtual MT_Vector3 GetLocalInertia()=0; virtual MT_Vector3 getReactionForce()=0; virtual void setRigidBody(bool rigid)=0; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 2283968801f..0b9da8f46d3 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -584,7 +584,19 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time) if (body && !body->isStaticObject()) { - + + if ((m_cci.m_clamp_vel_max>0.0) || (m_cci.m_clamp_vel_min>0.0)) + { + const btVector3& linvel = body->getLinearVelocity(); + float len= linvel.length(); + + if((m_cci.m_clamp_vel_max>0.0) && (len > m_cci.m_clamp_vel_max)) + body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_max / len)); + + else if ((m_cci.m_clamp_vel_min>0.0) && btFuzzyZero(len)==0 && (len < m_cci.m_clamp_vel_min)) + body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len)); + } + const btVector3& worldPos = body->getCenterOfMassPosition(); m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 245cde2baaa..c7638b36728 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -214,6 +214,8 @@ struct CcdConstructionInfo m_gravity(0,0,0), m_scaling(1.f,1.f,1.f), m_mass(0.f), + m_clamp_vel_min(-1.f), + m_clamp_vel_max(-1.f), m_restitution(0.1f), m_friction(0.5f), m_linearDamping(0.1f), @@ -239,6 +241,8 @@ struct CcdConstructionInfo btVector3 m_gravity; btVector3 m_scaling; btScalar m_mass; + btScalar m_clamp_vel_min; + btScalar m_clamp_vel_max; btScalar m_restitution; btScalar m_friction; btScalar m_linearDamping; @@ -479,7 +483,24 @@ class CcdPhysicsController : public PHY_IPhysicsController } m_cci.m_radius = margin; } - + + // velocity clamping + virtual void SetLinVelocityMin(float val) + { + m_cci.m_clamp_vel_min= val; + } + virtual float GetLinVelocityMin() const + { + return m_cci.m_clamp_vel_min; + } + virtual void SetLinVelocityMax(float val) + { + m_cci.m_clamp_vel_max= val; + } + virtual float GetLinVelocityMax() const + { + return m_cci.m_clamp_vel_max; + } bool wantsSleeping(); diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h index 6cba6fa88af..770426b48db 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsController.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h @@ -90,6 +90,12 @@ class PHY_IPhysicsController : public PHY_IController virtual float GetMargin() const=0; virtual float GetRadius() const=0; virtual void SetRadius(float margin) = 0; + + virtual float GetLinVelocityMin() const=0; + virtual void SetLinVelocityMin(float val) = 0; + virtual float GetLinVelocityMax() const=0; + virtual void SetLinVelocityMax(float val) = 0; + PHY__Vector3 GetWorldPosition(PHY__Vector3& localpos); }; diff --git a/source/gameengine/Physics/common/PHY_Pro.h b/source/gameengine/Physics/common/PHY_Pro.h index 32e63ac2f6d..0249fc3118a 100644 --- a/source/gameengine/Physics/common/PHY_Pro.h +++ b/source/gameengine/Physics/common/PHY_Pro.h @@ -35,9 +35,11 @@ struct PHY_ShapeProps { MT_Scalar m_mass; // Total mass MT_Scalar m_inertia; // Inertia, should be a tensor some time - MT_Scalar m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum - MT_Scalar m_ang_drag; // Angular drag + MT_Scalar m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum, inverted and called dampening in blenders UI + MT_Scalar m_ang_drag; // Angular drag, inverted and called dampening in blenders UI MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1] + MT_Scalar m_clamp_vel_min; // Clamp the minimum velocity, this ensures an object moves at a minimum speed unless its stationary + MT_Scalar m_clamp_vel_max; // Clamp max velocity bool m_do_anisotropic; // Should I do anisotropic friction? bool m_do_fh; // Should the object have a linear Fh spring? bool m_do_rot_fh; // Should the object have an angular Fh spring? diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py index fa4641c3e2f..44b84d44d8d 100644 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ b/source/gameengine/PyDoc/KX_GameObject.py @@ -16,8 +16,18 @@ class KX_GameObject: # (SCA_IObject) @ivar name: The object's name. (Read only) - note: Currently (Blender 2.49) the prefix "OB" is added to all objects name. This may change in blender 2.5. @type name: string. - @ivar mass: The object's mass (provided the object has a physics controller). + @ivar mass: The object's mass + - note: The object must have a physics controller for the mass to be applied, otherwise the mass value will be returned as 0.0 @type mass: float + @ivar linVelocityMin: Enforces the object keeps moving at a minimum velocity. + - note: Applies to dynamic and rigid body objects only. + - note: A value of 0.0 disables this option. + - note: While objects are stationary the minimum velocity will not be applied. + @type linVelocityMin: float + @ivar linVelocityMax: Clamp the maximum linear velocity to prevent objects moving beyond a set speed. + - note: Applies to dynamic and rigid body objects only. + - note: A value of 0.0 disables this option (rather then setting it stationary). + @type linVelocityMax: float @ivar localInertia: the object's inertia vector in local coordinates. Read only. @type localInertia: list [ix, iy, iz] @ivar parent: The object's parent object. (Read only) @@ -35,7 +45,7 @@ class KX_GameObject: # (SCA_IObject) @type scaling: list [sx, sy, sz] @ivar timeOffset: adjust the slowparent delay at runtime. @type timeOffset: float - @ivar state: the game object's state bitmask. + @ivar state: the game object's state bitmask, using the first 30 bits, one bit must always be set. @type state: int @ivar meshes: a list meshes for this object. - note: Most objects use only 1 mesh. |