Browse Source

Tweaked ragdoll parameters in TestScene & TestSceneOld.
Expose constraint's ERP & CFM parameters directly, instead of trying to derive them from a "softness" value.

Lasse Öörni 12 years ago
parent
commit
3989849c55

+ 15 - 15
Bin/Data/Scripts/TestScene.as

@@ -489,8 +489,8 @@ void CreateRagdoll(AnimatedModel@ model)
 {
     Node@ root = model.node;
 
-    CreateRagdollBone(root, "Bip01_Pelvis", SHAPE_CAPSULE, Vector3(0.3, 0.3, 0.3), Vector3(0.0, 0, 0), Quaternion(0, 0, 0));
-    CreateRagdollBone(root, "Bip01_Spine1", SHAPE_CAPSULE, Vector3(0.3, 0.4, 0.3), Vector3(0.15, 0, 0), Quaternion(0, 0, 90));
+    CreateRagdollBone(root, "Bip01_Pelvis", SHAPE_BOX, Vector3(0.2, 0.25, 0.2), Vector3(0.15, 0, 0), Quaternion(0, 0, 0));
+    CreateRagdollBone(root, "Bip01_Spine1", SHAPE_BOX, Vector3(0.3, 0.2, 0.25), Vector3(0.15, 0, 0), Quaternion(0, 0, 0));
     CreateRagdollBone(root, "Bip01_L_Thigh", SHAPE_CAPSULE, Vector3(0.175, 0.45, 0.175), Vector3(0.25, 0, 0), Quaternion(0, 0, 90));
     CreateRagdollBone(root, "Bip01_R_Thigh", SHAPE_CAPSULE, Vector3(0.175, 0.45, 0.175), Vector3(0.25, 0, 0), Quaternion(0, 0, 90));
     CreateRagdollBone(root, "Bip01_L_Calf", SHAPE_CAPSULE, Vector3(0.15, 0.55, 0.15), Vector3(0.25, 0, 0), Quaternion(0, 0, 90));
@@ -500,17 +500,17 @@ void CreateRagdoll(AnimatedModel@ model)
     CreateRagdollBone(root, "Bip01_R_UpperArm", SHAPE_CAPSULE, Vector3(0.125, 0.35, 0.125), Vector3(0.1, 0, 0), Quaternion(0, 0, 90));
     CreateRagdollBone(root, "Bip01_L_Forearm", SHAPE_CAPSULE, Vector3(0.1, 0.3, 0.1), Vector3(0.15, 0, 0), Quaternion(0, 0, 90));
     CreateRagdollBone(root, "Bip01_R_Forearm", SHAPE_CAPSULE, Vector3(0.1, 0.3, 0.1), Vector3(0.15, 0, 0), Quaternion(0, 0, 90));
-
-    CreateRagdollConstraint(root, "Bip01_L_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(45, 25), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_R_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(45, 25), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_L_Calf", "Bip01_L_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_R_Calf", "Bip01_R_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_Spine1", "Bip01_Pelvis", CONSTRAINT_HINGE, Vector3(0, 0, 1), Vector3(0, 0, 1), Vector2(90, 0), Vector2(-25, 0));
-    CreateRagdollConstraint(root, "Bip01_Head", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, 0, 1), Vector3(0, 0, 1), Vector2(45, 25), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_L_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(45, 45), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_R_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(45, 45), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_L_Forearm", "Bip01_L_UpperArm", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_R_Forearm", "Bip01_R_UpperArm", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
+    
+    CreateRagdollConstraint(root, "Bip01_L_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(35, 25), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_R_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(35, 25), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_L_Calf", "Bip01_L_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(45, 0), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_R_Calf", "Bip01_R_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(45, 0), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_Spine1", "Bip01_Pelvis", CONSTRAINT_HINGE, Vector3(0, 0, 1), Vector3(0, 0, 1), Vector2(25, 0), Vector2(-10, 0));
+    CreateRagdollConstraint(root, "Bip01_Head", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, 0, 1), Vector3(0, 0, 1), Vector2(35, 25), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_L_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(35, 25), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_R_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(35, 25), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_L_Forearm", "Bip01_L_UpperArm", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(45, 0), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_R_Forearm", "Bip01_R_UpperArm", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(45, 0), Vector2(0, 0));
 
     // Disable animation from all bones (both physical and non-physical) to not interfere
     Skeleton@ skel = model.skeleton;
@@ -530,8 +530,8 @@ void CreateRagdollBone(Node@ root, const String&in boneName, ShapeType type, con
     // any components, it is important that the LOCAL creation mode is specified.
     RigidBody@ body = boneNode.CreateComponent("RigidBody", LOCAL);
     body.mass = 1.0;
-    body.linearDamping = 0.05;
-    body.angularDamping = 0.85;
+    body.linearDamping = 0.2;
+    body.angularDamping = 0.9;
     body.linearRestThreshold = 1.5;
     body.angularRestThreshold = 2.5;
 

+ 18 - 15
Bin/Data/Scripts/TestSceneOld.as

@@ -628,8 +628,8 @@ void CreateRagdoll(AnimatedModel@ model)
 {
     Node@ root = model.node;
 
-    CreateRagdollBone(root, "Bip01_Pelvis", SHAPE_CAPSULE, Vector3(0.3, 0.3, 0.3), Vector3(0.0, 0, 0), Quaternion(0, 0, 0));
-    CreateRagdollBone(root, "Bip01_Spine1", SHAPE_CAPSULE, Vector3(0.3, 0.4, 0.3), Vector3(0.15, 0, 0), Quaternion(0, 0, 90));
+    CreateRagdollBone(root, "Bip01_Pelvis", SHAPE_BOX, Vector3(0.2, 0.25, 0.2), Vector3(0.15, 0, 0), Quaternion(0, 0, 0));
+    CreateRagdollBone(root, "Bip01_Spine1", SHAPE_BOX, Vector3(0.3, 0.2, 0.25), Vector3(0.15, 0, 0), Quaternion(0, 0, 0));
     CreateRagdollBone(root, "Bip01_L_Thigh", SHAPE_CAPSULE, Vector3(0.175, 0.45, 0.175), Vector3(0.25, 0, 0), Quaternion(0, 0, 90));
     CreateRagdollBone(root, "Bip01_R_Thigh", SHAPE_CAPSULE, Vector3(0.175, 0.45, 0.175), Vector3(0.25, 0, 0), Quaternion(0, 0, 90));
     CreateRagdollBone(root, "Bip01_L_Calf", SHAPE_CAPSULE, Vector3(0.15, 0.55, 0.15), Vector3(0.25, 0, 0), Quaternion(0, 0, 90));
@@ -639,17 +639,17 @@ void CreateRagdoll(AnimatedModel@ model)
     CreateRagdollBone(root, "Bip01_R_UpperArm", SHAPE_CAPSULE, Vector3(0.125, 0.35, 0.125), Vector3(0.1, 0, 0), Quaternion(0, 0, 90));
     CreateRagdollBone(root, "Bip01_L_Forearm", SHAPE_CAPSULE, Vector3(0.1, 0.3, 0.1), Vector3(0.15, 0, 0), Quaternion(0, 0, 90));
     CreateRagdollBone(root, "Bip01_R_Forearm", SHAPE_CAPSULE, Vector3(0.1, 0.3, 0.1), Vector3(0.15, 0, 0), Quaternion(0, 0, 90));
-
-    CreateRagdollConstraint(root, "Bip01_L_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(45, 25), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_R_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(45, 25), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_L_Calf", "Bip01_L_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_R_Calf", "Bip01_R_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_Spine1", "Bip01_Pelvis", CONSTRAINT_HINGE, Vector3(0, 0, 1), Vector3(0, 0, 1), Vector2(90, 0), Vector2(-25, 0));
-    CreateRagdollConstraint(root, "Bip01_Head", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, 0, 1), Vector3(0, 0, 1), Vector2(45, 25), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_L_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(45, 45), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_R_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(45, 45), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_L_Forearm", "Bip01_L_UpperArm", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
-    CreateRagdollConstraint(root, "Bip01_R_Forearm", "Bip01_R_UpperArm", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0));
+    
+    CreateRagdollConstraint(root, "Bip01_L_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(35, 25), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_R_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(35, 25), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_L_Calf", "Bip01_L_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(45, 0), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_R_Calf", "Bip01_R_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(45, 0), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_Spine1", "Bip01_Pelvis", CONSTRAINT_HINGE, Vector3(0, 0, 1), Vector3(0, 0, 1), Vector2(25, 0), Vector2(-10, 0));
+    CreateRagdollConstraint(root, "Bip01_Head", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, 0, 1), Vector3(0, 0, 1), Vector2(35, 25), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_L_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(35, 25), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_R_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(35, 25), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_L_Forearm", "Bip01_L_UpperArm", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(45, 0), Vector2(0, 0));
+    CreateRagdollConstraint(root, "Bip01_R_Forearm", "Bip01_R_UpperArm", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(45, 0), Vector2(0, 0));
 
     // Disable animation from all bones (both physical and non-physical) to not interfere
     Skeleton@ skel = model.skeleton;
@@ -664,10 +664,13 @@ void CreateRagdollBone(Node@ root, const String&in boneName, ShapeType type, con
     if (boneNode is null || boneNode.HasComponent("RigidBody"))
         return;
 
+    // In networked operation both client and server detect collisions separately, and create ragdolls on their own
+    // (bones are not synced over network.) To prevent replicated component ID range clashes when the client creates
+    // any components, it is important that the LOCAL creation mode is specified.
     RigidBody@ body = boneNode.CreateComponent("RigidBody", LOCAL);
     body.mass = 1.0;
-    body.linearDamping = 0.05;
-    body.angularDamping = 0.85;
+    body.linearDamping = 0.2;
+    body.angularDamping = 0.9;
     body.linearRestThreshold = 1.5;
     body.angularRestThreshold = 2.5;
 

+ 1 - 1
Bin/Data/Scripts/Vehicle.as

@@ -91,7 +91,7 @@ void InitScene()
         light.lightType = LIGHT_DIRECTIONAL;
         light.castShadows = true;
         light.shadowBias = BiasParameters(0.0001, 0.5);
-        light.shadowCascade = CascadeParameters(10.0, 50.0, 200.0, 0.0, 0.8);
+        light.shadowCascade = CascadeParameters(15.0, 50.0, 200.0, 0.0, 0.8);
         light.specularIntensity = 0.5;
     }
 

+ 2 - 1
Docs/ScriptAPI.dox

@@ -5793,7 +5793,8 @@ Properties:<br>
 - Vector3 worldPosition
 - Vector2 highLimit
 - Vector2 lowLimit
-- float softness
+- float erp
+- float cfm
 - bool disableCollision
 - RigidBody@ ownBody (readonly)
 - RigidBody@ otherBody

+ 4 - 2
Engine/Engine/PhysicsAPI.cpp

@@ -205,8 +205,10 @@ static void RegisterConstraint(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Constraint", "const Vector2& get_highLimit() const", asMETHOD(Constraint, GetHighLimit), asCALL_THISCALL);
     engine->RegisterObjectMethod("Constraint", "void set_lowLimit(const Vector2&in)", asMETHOD(Constraint, SetLowLimit), asCALL_THISCALL);
     engine->RegisterObjectMethod("Constraint", "const Vector2& get_lowLimit() const", asMETHOD(Constraint, GetLowLimit), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Constraint", "void set_softness(float)", asMETHOD(Constraint, SetSoftness), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Constraint", "float get_softness() const", asMETHOD(Constraint, GetSoftness), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Constraint", "void set_erp(float)", asMETHOD(Constraint, SetERP), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Constraint", "float get_erp() const", asMETHOD(Constraint, GetERP), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Constraint", "void set_cfm(float)", asMETHOD(Constraint, SetCFM), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Constraint", "float get_cfm() const", asMETHOD(Constraint, GetCFM), asCALL_THISCALL);
     engine->RegisterObjectMethod("Constraint", "void set_disableCollision(bool)", asMETHOD(Constraint, SetDisableCollision), asCALL_THISCALL);
     engine->RegisterObjectMethod("Constraint", "bool get_disableCollision() const" ,asMETHOD(Constraint, GetDisableCollision), asCALL_THISCALL);
     engine->RegisterObjectMethod("Constraint", "RigidBody@+ get_ownBody() const", asMETHOD(Constraint, GetOwnBody), asCALL_THISCALL);

+ 26 - 7
Engine/Physics/Constraint.cpp

@@ -65,7 +65,8 @@ Constraint::Constraint(Context* context) :
     otherRotation_(Quaternion::IDENTITY),
     highLimit_(Vector2::ZERO),
     lowLimit_(Vector2::ZERO),
-    softness_(0.0f),
+    erp_(0.0f),
+    cfm_(0.0f),
     otherBodyNodeID_(0),
     disableCollision_(false),
     recreateConstraint_(true),
@@ -94,7 +95,8 @@ void Constraint::RegisterObject(Context* context)
     ATTRIBUTE(Constraint, VAR_INT, "Other Body NodeID", otherBodyNodeID_, 0, AM_DEFAULT | AM_NODEID);
     REF_ACCESSOR_ATTRIBUTE(Constraint, VAR_VECTOR2, "High Limit", GetHighLimit, SetHighLimit, Vector2, Vector2::ZERO, AM_DEFAULT);
     REF_ACCESSOR_ATTRIBUTE(Constraint, VAR_VECTOR2, "Low Limit", GetLowLimit, SetLowLimit, Vector2, Vector2::ZERO, AM_DEFAULT);
-    ACCESSOR_ATTRIBUTE(Constraint, VAR_FLOAT, "Softness", GetSoftness, SetSoftness, float, 0.0f, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(Constraint, VAR_FLOAT, "ERP Parameter", GetERP, SetERP, float, 0.0f, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(Constraint, VAR_FLOAT, "CFM Parameter", GetCFM, SetCFM, float, 0.0f, AM_DEFAULT);
     ATTRIBUTE(Constraint, VAR_BOOL, "Disable Collision", disableCollision_, false, AM_DEFAULT);
 }
 
@@ -322,11 +324,25 @@ void Constraint::SetLowLimit(const Vector2& limit)
     }
 }
 
-void Constraint::SetSoftness(float softness)
+void Constraint::SetERP(float erp)
 {
-    if (softness != softness_)
+    erp = Max(erp, 0.0f);
+    
+    if (erp != erp_)
     {
-        softness_ = softness;
+        erp_ = erp;
+        ApplyLimits();
+        MarkNetworkUpdate();
+    }
+}
+
+void Constraint::SetCFM(float cfm)
+{
+    cfm = Max(cfm, 0.0f);
+    
+    if (cfm != cfm_)
+    {
+        cfm_ = cfm;
         ApplyLimits();
         MarkNetworkUpdate();
     }
@@ -536,8 +552,6 @@ void Constraint::ApplyLimits()
     if (!constraint_)
         return;
     
-    constraint_->setParam(BT_CONSTRAINT_CFM, softness_);
-    
     switch (constraint_->getConstraintType())
     {
     case HINGE_CONSTRAINT_TYPE:
@@ -567,6 +581,11 @@ void Constraint::ApplyLimits()
     default:
         break;
     }
+    
+    if (erp_ != 0.0f)
+        constraint_->setParam(BT_CONSTRAINT_STOP_ERP, erp_);
+    if (cfm_ != 0.0f)
+        constraint_->setParam(BT_CONSTRAINT_STOP_CFM, cfm_);
 }
 
 }

+ 12 - 6
Engine/Physics/Constraint.h

@@ -90,8 +90,10 @@ public:
     void SetHighLimit(const Vector2& limit);
     /// Set low limit. Interpretation is constraint type specific.
     void SetLowLimit(const Vector2& limit);
-    /// Set constraint softness. Default 0 (hard).
-    void SetSoftness(float softness);
+    /// Set constraint error reduction parameter. Zero = leave to default.
+    void SetERP(float erp);
+    /// Set constraint force mixing parameter. Zero = leave to default.
+    void SetCFM(float cfm);
     /// Set whether to disable collisions between connected bodies.
     void SetDisableCollision(bool disable);
     
@@ -119,8 +121,10 @@ public:
     const Vector2& GetHighLimit() const { return highLimit_; }
     /// Return low limit.
     const Vector2& GetLowLimit() const { return lowLimit_; }
-    /// Return constraint softness.
-    float GetSoftness() const { return softness_; }
+    /// Return constraint error reduction parameter.
+    float GetERP() const { return erp_; }
+    /// Return constraint force mixing parameter.
+    float GetCFM() const { return cfm_; }
     /// Return whether collisions between connected bodies are disabled.
     bool GetDisableCollision() const { return disableCollision_; }
     
@@ -165,8 +169,10 @@ private:
     Vector2 highLimit_;
     /// Low limit.
     Vector2 lowLimit_;
-    /// Softness value.
-    float softness_;
+    /// Error reduction parameter.
+    float erp_;
+    /// Constraint force mixing parameter.
+    float cfm_;
     /// Other body node ID for pending constraint recreation.
     int otherBodyNodeID_;
     /// Disable collision between connected bodies flag.