BGE Physics
Clamp objects min/max velocity. Accessed with bullet physics from the advanced button with dynamic and rigid body objects. - useful for preventing unstable physics in cases where objects move too fast. - can add linear velocity with the motion actuator to give smooth motion transitions, without moving too fast. - minimum velocity means objects don't stop moving. - python scripts can adjust these values speedup or throttle velocity in the existing direction. Also made copy properties from an object with no properties work (in case you want to clear all props)
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 !
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
};
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user