Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2009-04-14 16:34:39 +0400
committerCampbell Barton <ideasman42@gmail.com>2009-04-14 16:34:39 +0400
commit3511f8ef9fe6a2a6491fbae3a44a407f280a19e0 (patch)
tree886dfd87cd3b9b05245f8e900f2e98c82ff376a2 /source
parent1bc31fc7f901334f0ed20317985b2a84d51714ca (diff)
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)
Diffstat (limited to 'source')
-rw-r--r--source/blender/makesdna/DNA_object_types.h4
-rw-r--r--source/blender/src/buttons_logic.c18
-rw-r--r--source/blender/src/editobject.c13
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_BulletPhysicsController.cpp27
-rw-r--r--source/gameengine/Ketsji/KX_BulletPhysicsController.h6
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp49
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h4
-rw-r--r--source/gameengine/Ketsji/KX_IPhysicsController.h6
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp14
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h23
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsController.h6
-rw-r--r--source/gameengine/Physics/common/PHY_Pro.h6
-rw-r--r--source/gameengine/PyDoc/KX_GameObject.py14
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.