Browse Source

- The PointForceController now has the ability to use both linear and non-linear force (approx inverse-sqaure law). It also now has both a linear and angular drag feature for simulating drag friction i.e. atmosphere etc.
- Added missing method script-bindings.

MelvMay-GG 12 years ago
parent
commit
793688c

+ 63 - 10
engine/source/2d/controllers/PointForceController.cc

@@ -39,6 +39,9 @@ PointForceController::PointForceController()
     mPosition.SetZero();
     mRadius = 1.0f;
     mForce = 0.0f;
+    mNonLinear = true;
+    mLinearDrag = 0.0f;
+    mAngularDrag = 0.0f;
 }
 
 //------------------------------------------------------------------------------
@@ -56,9 +59,12 @@ void PointForceController::initPersistFields()
     Parent::initPersistFields();
 
     // Force.
-    addProtectedField("Position", TypeVector2, Offset( mPosition, PointForceController), &defaultProtectedSetFn, &defaultProtectedGetFn, "The position of the attractor controller.");
-    addProtectedField("Radius", TypeF32, Offset( mRadius, PointForceController), &defaultProtectedSetFn, &defaultProtectedGetFn, "The radius of the attractor circle centered on the attractors position.");
-    addProtectedField("Force", TypeF32, Offset( mForce, PointForceController), &defaultProtectedSetFn, &defaultProtectedGetFn, "The force to apply to attact to the controller position.");
+    addField( "Position", TypeVector2, Offset( mPosition, PointForceController), "The position of the attractor controller.");
+    addField( "Radius", TypeF32, Offset( mRadius, PointForceController), "The radius of the attractor circle centered on the attractors position.");
+    addField( "Force", TypeF32, Offset( mForce, PointForceController), "The force to apply to attact to the controller position.");
+    addField( "NonLinear", TypeBool, Offset( mNonLinear, PointForceController), "Whether to apply the force non-linearly (using the inverse square law) or linearly.");
+    addField( "LinearDrag", TypeF32, Offset(mLinearDrag, PointForceController), "The linear drag co-efficient for the fluid." );
+    addField( "AngularDrag", TypeF32, Offset(mAngularDrag, PointForceController), "The angular drag co-efficient for the fluid." );
 }
 
 //------------------------------------------------------------------------------
@@ -100,8 +106,20 @@ void PointForceController::integrate( Scene* pScene, const F32 totalTime, const
     // Fetch results.
     typeWorldQueryResultVector& queryResults = pWorldQuery->getQueryResults();
 
+    // Fetch result count.
+    const U32 resultCount = (U32)queryResults.size();
+
+    // Calculate the force squared in-case we need it.
+    const F32 forceSqr = mForce * mForce;
+
+    // Calculate drag coefficients (time-integrated).
+    const F32 linearDrag = mClampF( mLinearDrag, 0.0f, 1.0f ) * elapsedTime;
+    const F32 angularDrag = mClampF( mAngularDrag, 0.0f, 1.0f ) * elapsedTime;
+
+    // Calculate 
+
     // Iterate the results.
-    for ( U32 n = 0; n < (U32)queryResults.size(); n++ )
+    for ( U32 n = 0; n < resultCount; n++ )
     {
         // Fetch the scene object.
         SceneObject* pSceneObject = queryResults[n].mpSceneObject;
@@ -110,18 +128,53 @@ void PointForceController::integrate( Scene* pScene, const F32 totalTime, const
         if ( pSceneObject->getBodyType() == b2_staticBody )
             continue;
 
-        // Calculate the force direction to the controllers position.
-        Vector2 forceDirection = mPosition - pSceneObject->getPosition();
+        // Calculate the force distance to the controllers position.
+        Vector2 distanceForce = mPosition - pSceneObject->getPosition();
 
         // Skip if the position is outside the radius.
-        if ( forceDirection.Length() > mRadius )
+        if ( distanceForce.Length() > mRadius )
             continue;
 
-        // Normalize to the specified force.
-        forceDirection.Normalize( mForce );
+        // Non-Linear force?
+        if ( mNonLinear )
+        {
+            // Yes, so use an approximation of the inverse-square law.
+            distanceForce *= (1.0f / distanceForce.LengthSquared()) * forceSqr;
+        }
+        else
+        {
+            // No, so normalize to the specified force (linear).
+            distanceForce.Normalize( mForce );
+        }
 
         // Apply the force.
-        pSceneObject->applyForce( forceDirection, true );
+        pSceneObject->applyForce( distanceForce, true );
+
+        // Linear drag?
+        if ( linearDrag > 0.0f )
+        {
+            // Yes, so fetch linear velocity.
+            Vector2 linearVelocity = pSceneObject->getLinearVelocity();
+
+            // Calculate linear velocity change.
+            const Vector2 linearVelocityDelta = linearVelocity * linearDrag;
+
+            // Set linear velocity.
+            pSceneObject->setLinearVelocity( linearVelocity - linearVelocityDelta );
+        }
+
+        // Angular drag?
+        if ( angularDrag > 0.0f )
+        {
+            // Yes, so fetch angular velocity.
+            F32 angularVelocity = pSceneObject->getAngularVelocity();
+
+            // Calculate angular velocity change.
+            const F32 angularVelocityDelta = angularVelocity * angularDrag;
+
+            // Set angular velocity.
+            pSceneObject->setAngularVelocity( angularVelocity - angularVelocityDelta );
+        }
     }
 }
 

+ 20 - 0
engine/source/2d/controllers/PointForceController.h

@@ -38,10 +38,24 @@ class PointForceController : public PickingSceneController
 private:
     typedef PickingSceneController Parent;
 
+    /// Controller position.
     Vector2 mPosition;
+
+    /// Controller radius.
     F32 mRadius;
+
+    /// Controller force.
     F32 mForce;
 
+    /// Whether to apply the force non-linearly (using the inverse square law) or linearly.
+    bool mNonLinear;
+
+	/// Linear drag co-efficient.
+	F32 mLinearDrag;
+
+	/// Linear drag co-efficient.
+	F32 mAngularDrag;
+
 public:
     PointForceController();
     virtual ~PointForceController();
@@ -55,6 +69,12 @@ public:
     inline F32 getRadius( void ) const { return mRadius; }
     inline void setForce( const F32 force ) { mForce = force; }
     inline F32 getForce( void ) const { return mForce; }
+    inline void setNonLinear( const bool nonLinear ) { mNonLinear = nonLinear; }
+    inline bool getNonLinear( void ) const { return mNonLinear; }
+    inline void setLinearDrag( const F32 linearDrag ) { mLinearDrag = linearDrag; }
+    inline F32 getLinearDrag( void ) const { return mLinearDrag; }
+    inline void setAngularDrag( const F32 angularDrag ) { mAngularDrag = angularDrag; }
+    inline F32 getAngularDrag( void ) const { return mAngularDrag; }
 
     /// Integration.
     virtual void integrate( Scene* pScene, const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats );

+ 52 - 0
engine/source/2d/controllers/PointForceController_ScriptBinding.h

@@ -92,3 +92,55 @@ ConsoleMethod(PointForceController, getForce, F32, 2, 2,        "() Gets the poi
 {
     return object->getForce();
 }
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(PointForceController, setLinearDrag, void, 3, 3,  "(linearDrag) - Sets the linear drag coefficient (0.0 to 1.0).\n"
+                                                                "@param linearDrag The linear drag coefficient\n"
+                                                                "@return No return value.")
+{
+    object->setLinearDrag( dAtof(argv[2]) );
+} 
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(PointForceController, getLinearDrag, F32, 2, 2,   "() Gets the linear drag coefficient.\n"
+                                                                "@return The linear drag coefficient.")
+{
+    return object->getLinearDrag();
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(PointForceController, setAngularDrag, void, 3, 3, "(angularDrag) - Sets the angular drag coefficient (0.0 to 1.0).\n"
+                                                                "@param angularDrag The angular drag coefficient\n"
+                                                                "@return No return value.")
+{
+    object->setAngularDrag( dAtof(argv[2]) );
+} 
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(PointForceController, getAngularDrag, F32, 2, 2,  "() Gets the angular drag coefficient.\n"
+                                                                "@return The angular drag coefficient.")
+{
+    return object->getAngularDrag();
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(PointForceController, setNonLinear, void, 3, 3,   "(nonLinear) - Sets whether to apply the force non-linearly (using the inverse square law) or linearly.\n"
+                                                                "@param nonLinear whether to apply the force non-linearly (using the inverse square law) or linearly.\n"
+                                                                "@return No return value.")
+{
+    object->setNonLinear( dAtob(argv[2]) );
+} 
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(PointForceController, getNonLinear, bool, 2, 2,  "() Gets whether to apply the force non-linearly (using the inverse square law) or linearly.\n"
+                                                                "@return Whether to apply the force non-linearly (using the inverse square law) or linearly.")
+{
+    return object->getNonLinear();
+}
+