diff options
-rw-r--r-- | doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst | 23 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/properties_game.py | 6 | ||||
-rw-r--r-- | source/blender/editors/object/object_edit.c | 4 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_object_types.h | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_object.c | 11 | ||||
-rw-r--r-- | source/gameengine/Converter/BL_BlenderDataConversion.cpp | 4 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.cpp | 50 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.h | 4 | ||||
-rw-r--r-- | source/gameengine/Physics/Bullet/CcdPhysicsController.cpp | 11 | ||||
-rw-r--r-- | source/gameengine/Physics/Bullet/CcdPhysicsController.h | 21 | ||||
-rw-r--r-- | source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp | 2 | ||||
-rw-r--r-- | source/gameengine/Physics/common/PHY_IPhysicsController.h | 5 | ||||
-rw-r--r-- | source/gameengine/Physics/common/PHY_Pro.h | 2 |
13 files changed, 143 insertions, 2 deletions
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst index 672df3728a9..a24aa546cb9 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst @@ -139,6 +139,29 @@ base class --- :class:`SCA_IObject` A value of 0.0 disables this option (rather then setting it stationary). + .. attribute:: angularVelocityMin + + Enforces the object keeps rotating at a minimum velocity. A value of 0.0 disables this. + + :type: non-negative float + + .. note:: + + Applies to dynamic and rigid body objects only. + While objects are stationary the minimum velocity will not be applied. + + + .. attribute:: angularVelocityMax + + Clamp the maximum angular velocity to prevent objects rotating beyond a set speed. + A value of 0.0 disables clamping; it does not stop rotation. + + :type: non-negative float + + .. note:: + + Applies to dynamic and rigid body objects only. + .. attribute:: localInertia the object's inertia vector in local coordinates. Read only. diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index ceeb45ac485..fa57bf2115f 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -89,10 +89,14 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel): split = layout.split() col = split.column() - col.label(text="Velocity:") + col.label(text="Linear velocity:") sub = col.column(align=True) sub.prop(game, "velocity_min", text="Minimum") sub.prop(game, "velocity_max", text="Maximum") + col.label(text="Angular velocity:") + sub = col.column(align=True) + sub.prop(game, "angular_velocity_min", text="Minimum") + sub.prop(game, "angular_velocity_max", text="Maximum") col = split.column() col.label(text="Damping:") diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 2681a1f8de0..3499a3cc364 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -905,6 +905,8 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) base->object->rdamping = ob->rdamping; base->object->min_vel = ob->min_vel; base->object->max_vel = ob->max_vel; + base->object->min_angvel = ob->min_angvel; + base->object->max_angvel = ob->max_angvel; if (ob->gameflag & OB_BOUNDS) { base->object->collision_boundtype = ob->collision_boundtype; } @@ -2044,6 +2046,8 @@ static int game_physics_copy_exec(bContext *C, wmOperator *UNUSED(op)) ob_iter->rdamping = ob->rdamping; ob_iter->min_vel = ob->min_vel; ob_iter->max_vel = ob->max_vel; + ob_iter->min_angvel = ob->min_angvel; + ob_iter->max_angvel = ob->max_angvel; ob_iter->obstacleRad = ob->obstacleRad; ob_iter->mass = ob->mass; copy_v3_v3(ob_iter->anisotropicFriction, ob->anisotropicFriction); diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 978a97f4b49..2daba6a3f0d 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -214,6 +214,8 @@ typedef struct Object { float margin; float max_vel; /* clamp the maximum velocity 0.0 is disabled */ float min_vel; /* clamp the minimum velocity 0.0 is disabled */ + float max_angvel; /* clamp the maximum angular velocity, 0.0 is disabled */ + float min_angvel; /* clamp the minimum angular velocity, 0.0 is disabled */ float obstacleRad; /* "Character" physics properties */ diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 3113b702dad..f433c2c36a8 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1737,6 +1737,17 @@ static void rna_def_object_game_settings(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 1000.0); RNA_def_property_ui_text(prop, "Velocity Max", "Clamp velocity to this maximum speed"); + prop = RNA_def_property(srna, "angular_velocity_min", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "min_angvel"); + RNA_def_property_range(prop, 0.0, 1000.0); + RNA_def_property_ui_text(prop, "Angular Velocity Min", + "Clamp angular velocity to this minimum speed (except when totally still)"); + + prop = RNA_def_property(srna, "angular_velocity_max", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "max_angvel"); + RNA_def_property_range(prop, 0.0, 1000.0); + RNA_def_property_ui_text(prop, "Angular Velocity Max", "Clamp angular velocity to this maximum speed"); + /* Character physics */ prop = RNA_def_property(srna, "step_height", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "step_height"); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 3da0863508b..4899eafd84c 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1200,7 +1200,9 @@ static PHY_ShapeProps *CreateShapePropsFromBlenderObject(struct Object* blendero // velocity clamping XXX shapeProps->m_clamp_vel_min = blenderobject->min_vel; shapeProps->m_clamp_vel_max = blenderobject->max_vel; - + shapeProps->m_clamp_angvel_min = blenderobject->min_angvel; + shapeProps->m_clamp_angvel_max = blenderobject->max_angvel; + // Character physics properties shapeProps->m_step_height = blenderobject->step_height; shapeProps->m_jump_speed = blenderobject->jump_speed; diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 34d50e24741..5701d0e54a0 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1965,6 +1965,8 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("isSuspendDynamics", KX_GameObject, pyattr_get_is_suspend_dynamics), 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("angularVelocityMin", KX_GameObject, pyattr_get_ang_vel_min, pyattr_set_ang_vel_min), + KX_PYATTRIBUTE_RW_FUNCTION("angularVelocityMax", KX_GameObject, pyattr_get_ang_vel_max, pyattr_set_ang_vel_max), KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible), KX_PYATTRIBUTE_RW_FUNCTION("record_animation", KX_GameObject, pyattr_get_record_animation, pyattr_set_record_animation), KX_PYATTRIBUTE_BOOL_RW ("occlusion", KX_GameObject, m_bOccluder), @@ -2487,6 +2489,54 @@ int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF return PY_SET_ATTR_SUCCESS; } +PyObject *KX_GameObject::pyattr_get_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject *self = static_cast<KX_GameObject*>(self_v); + PHY_IPhysicsController *spc = self->GetPhysicsController(); + return PyFloat_FromDouble(spc ? spc->GetAngularVelocityMin() : 0.0f); +} + +int KX_GameObject::pyattr_set_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject *self = static_cast<KX_GameObject*>(self_v); + PHY_IPhysicsController *spc = self->GetPhysicsController(); + MT_Scalar val = PyFloat_AsDouble(value); + if (val < 0.0f) { /* also accounts for non float */ + PyErr_SetString(PyExc_AttributeError, + "gameOb.angularVelocityMin = float: KX_GameObject, expected a nonnegative float"); + return PY_SET_ATTR_FAIL; + } + + if (spc) + spc->SetAngularVelocityMin(val); + + return PY_SET_ATTR_SUCCESS; +} + +PyObject *KX_GameObject::pyattr_get_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject *self = static_cast<KX_GameObject*>(self_v); + PHY_IPhysicsController *spc = self->GetPhysicsController(); + return PyFloat_FromDouble(spc ? spc->GetAngularVelocityMax() : 0.0f); +} + +int KX_GameObject::pyattr_set_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject *self = static_cast<KX_GameObject*>(self_v); + PHY_IPhysicsController *spc = self->GetPhysicsController(); + MT_Scalar val = PyFloat_AsDouble(value); + if (val < 0.0f) { /* also accounts for non float */ + PyErr_SetString(PyExc_AttributeError, + "gameOb.angularVelocityMax = float: KX_GameObject, expected a nonnegative float"); + return PY_SET_ATTR_FAIL; + } + + if (spc) + spc->SetAngularVelocityMax(val); + + return PY_SET_ATTR_SUCCESS; +} + PyObject *KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 9c081b449ec..670fcd6fb6e 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -1054,6 +1054,10 @@ public: 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_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_ang_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_record_animation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 4306d6d0cd7..692704b5080 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -713,6 +713,17 @@ void CcdPhysicsController::SimulationTick(float timestep) else if (m_cci.m_clamp_vel_min > 0.0f && !btFuzzyZero(len) && len < m_cci.m_clamp_vel_min) body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len)); } + + // Clamp angular velocity + if (m_cci.m_clamp_angvel_max > 0.0f || m_cci.m_clamp_angvel_min > 0.0f) { + const btVector3 &angvel = body->getAngularVelocity(); + btScalar len = angvel.length(); + + if (m_cci.m_clamp_angvel_max > 0.0f && len > m_cci.m_clamp_angvel_max) + body->setAngularVelocity(angvel * (m_cci.m_clamp_angvel_max / len)); + else if (m_cci.m_clamp_angvel_min > 0.0f && !btFuzzyZero(len) && len < m_cci.m_clamp_angvel_min) + body->setAngularVelocity(angvel * (m_cci.m_clamp_angvel_min / len)); + } } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 2a15b6136e4..c49ae8d20e1 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -236,6 +236,8 @@ struct CcdConstructionInfo m_mass(0.f), m_clamp_vel_min(-1.f), m_clamp_vel_max(-1.f), + m_clamp_angvel_min(0.0f), + m_clamp_angvel_max(0.0f), m_restitution(0.1f), m_friction(0.5f), m_linearDamping(0.1f), @@ -302,6 +304,8 @@ struct CcdConstructionInfo btScalar m_mass; btScalar m_clamp_vel_min; btScalar m_clamp_vel_max; + btScalar m_clamp_angvel_min; // Minimum angular velocity, in radians/sec. + btScalar m_clamp_angvel_max; // Maximum angular velocity, in radians/sec. btScalar m_restitution; btScalar m_friction; btScalar m_linearDamping; @@ -708,6 +712,23 @@ protected: return m_cci.m_clamp_vel_max; } + virtual void SetAngularVelocityMin(float val) + { + m_cci.m_clamp_angvel_min = val; + } + virtual float GetAngularVelocityMin() const + { + return m_cci.m_clamp_angvel_min; + } + virtual void SetAngularVelocityMax(float val) + { + m_cci.m_clamp_angvel_max = val; + } + virtual float GetAngularVelocityMax() const + { + return m_cci.m_clamp_angvel_max; + } + bool WantsSleeping(); void UpdateDeactivation(float timeStep); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 14a19fdfb41..82451e6a3ed 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -3111,6 +3111,8 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject ci.m_mass = isbulletdyna ? 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_clamp_angvel_min = shapeprops->m_clamp_angvel_min; + ci.m_clamp_angvel_max = shapeprops->m_clamp_angvel_max; ci.m_stepHeight = isbulletchar ? shapeprops->m_step_height : 0.f; ci.m_jumpSpeed = isbulletchar ? shapeprops->m_jump_speed : 0.f; ci.m_fallSpeed = isbulletchar ? shapeprops->m_fall_speed : 0.f; diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h index 3e2337f01ea..62b163536dd 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsController.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h @@ -125,6 +125,11 @@ class PHY_IPhysicsController : public PHY_IController virtual float GetLinVelocityMax() const=0; virtual void SetLinVelocityMax(float val) = 0; + virtual void SetAngularVelocityMin(float val) = 0; + virtual float GetAngularVelocityMin() const = 0; + virtual void SetAngularVelocityMax(float val) = 0; + virtual float GetAngularVelocityMax() const = 0; + MT_Vector3 GetWorldPosition(MT_Vector3& localpos); // Shape control diff --git a/source/gameengine/Physics/common/PHY_Pro.h b/source/gameengine/Physics/common/PHY_Pro.h index 7c5d9c9638e..c9b91b06a3c 100644 --- a/source/gameengine/Physics/common/PHY_Pro.h +++ b/source/gameengine/Physics/common/PHY_Pro.h @@ -43,6 +43,8 @@ struct PHY_ShapeProps { 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 + MT_Scalar m_clamp_angvel_min; // Clamp the minimum angular velocity. + MT_Scalar m_clamp_angvel_max; // Clamp the maximum angular 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? |