forked from bartvdbraak/blender
BGE: added clamping of angular velocity.
Angular velocity clamping was missing from the BGE. It is implemented similarly to the linear velocity clamping. It is needed to be able to drive physical simulations of systems that have a limited rotational speed. Reviewed by: campbellbarton, panzergame, ton Differential Revision: https://developer.blender.org/D1365
This commit is contained in:
parent
c5c2883ce0
commit
9f48aa45ad
@ -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.
|
||||
|
@ -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:")
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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?
|
||||
|
Loading…
Reference in New Issue
Block a user