Просмотр исходного кода

Merge pull request #442 from kwhatmough/next

Move control logic from racer sample into framework for general use
Sean Paul Taylor 13 лет назад
Родитель
Сommit
0423cf9d3d
2 измененных файлов с 417 добавлено и 8 удалено
  1. 202 8
      gameplay/src/PhysicsVehicle.cpp
  2. 215 0
      gameplay/src/PhysicsVehicle.h

+ 202 - 8
gameplay/src/PhysicsVehicle.cpp

@@ -1,9 +1,13 @@
 #include "Base.h"
 #include "Game.h"
+#include "MathUtil.h"
 #include "Node.h"
 #include "PhysicsVehicle.h"
 #include "PhysicsVehicleWheel.h"
 
+#define AIR_DENSITY (1.2f)
+#define KPH_TO_MPS (1.0f / 3.6f)
+
 namespace gameplay
 {
 
@@ -76,7 +80,7 @@ private:
 };
 
 PhysicsVehicle::PhysicsVehicle(Node* node, const PhysicsCollisionShape::Definition& shape, const PhysicsRigidBody::Parameters& parameters)
-    : PhysicsCollisionObject(node)
+    : PhysicsCollisionObject(node), _speedSmoothed(0)
 {
     // Note that the constructor for PhysicsRigidBody calls addCollisionObject and so
     // that is where the rigid body gets added to the dynamics world.
@@ -86,7 +90,7 @@ PhysicsVehicle::PhysicsVehicle(Node* node, const PhysicsCollisionShape::Definiti
 }
 
 PhysicsVehicle::PhysicsVehicle(Node* node, PhysicsRigidBody* rigidBody)
-    : PhysicsCollisionObject(node)
+    : PhysicsCollisionObject(node), _speedSmoothed(0)
 {
     _rigidBody = rigidBody;
 
@@ -117,6 +121,42 @@ PhysicsVehicle* PhysicsVehicle::create(Node* node, Properties* properties)
         {
             vehicle->setDrivingForce(properties->getFloat());
         }
+        else if (strcmp(name, "steerdownSpeed") == 0)
+        {
+            vehicle->_steerdownSpeed = properties->getFloat();
+        }
+        else if (strcmp(name, "steerdownGain") == 0)
+        {
+            vehicle->_steerdownGain = properties->getFloat();
+        }
+        else if (strcmp(name, "brakedownStart") == 0)
+        {
+            vehicle->_brakedownStart = properties->getFloat();
+        }
+        else if (strcmp(name, "brakedownFull") == 0)
+        {
+            vehicle->_brakedownFull = properties->getFloat();
+        }
+        else if (strcmp(name, "drivedownStart") == 0)
+        {
+            vehicle->_drivedownStart = properties->getFloat();
+        }
+        else if (strcmp(name, "drivedownFull") == 0)
+        {
+            vehicle->_drivedownFull = properties->getFloat();
+        }
+        else if (strcmp(name, "boostSpeed") == 0)
+        {
+            vehicle->_boostSpeed = properties->getFloat();
+        }
+        else if (strcmp(name, "boostGain") == 0)
+        {
+            vehicle->_boostGain = properties->getFloat();
+        }
+        else if (strcmp(name, "downforce") == 0)
+        {
+            vehicle->_downforce = properties->getFloat();
+        }
         else
         {
             // Ignore this case (we've already parsed the rigid body parameters).
@@ -134,6 +174,11 @@ void PhysicsVehicle::initialize()
     setSteeringGain(0.5f);
     setBrakingForce(350.0f);
     setDrivingForce(2000.0f);
+    setSteerdown(0, 1);
+    setBrakedown(1000, 0);
+    setDrivedown(1000, 0);
+    setBoost(0, 1);
+    setDownforce(0);
 
     // Create the vehicle and add it to world
     btRigidBody* body = static_cast<btRigidBody*>(_rigidBody->getCollisionObject());
@@ -204,8 +249,28 @@ float PhysicsVehicle::getSpeedKph() const
     return _vehicle->getCurrentSpeedKmHour();
 }
 
+float PhysicsVehicle::getSpeedSmoothKph() const
+{
+    return _speedSmoothed;
+}
+
 void PhysicsVehicle::update(float elapsedTime, float steering, float braking, float driving)
 {
+    float v = getSpeedKph();
+    MathUtil::smooth(&_speedSmoothed, v, elapsedTime, 0, 1200);
+    applyDownforce();
+
+    // Adjust control inputs based on vehicle speed.
+    steering = getSteering(v, steering);
+    driving = getDriving(v, driving, braking);
+    braking = getBraking(v, braking);
+
+    // Allow braking to take precedence over driving.
+    if (driving > 0 && braking > 0)
+    {
+        driving = 0;
+    }
+
     PhysicsVehicleWheel* wheel;
     for (int i = 0; i < _vehicle->getNumWheels(); i++)
     {
@@ -217,12 +282,6 @@ void PhysicsVehicle::update(float elapsedTime, float steering, float braking, fl
         }
         else
         {
-            // Allow braking to take precedence over driving.
-            if (driving > 0 && braking > 0)
-            {
-                driving = 0;
-            }
-
             _vehicle->applyEngineForce(driving * _drivingForce, i);
             _vehicle->setBrake(braking * _brakingForce, i);
         }
@@ -232,6 +291,67 @@ void PhysicsVehicle::update(float elapsedTime, float steering, float braking, fl
     }
 }
 
+void PhysicsVehicle::reset()
+{
+    _rigidBody->setLinearVelocity(Vector3::zero());
+    _rigidBody->setAngularVelocity(Vector3::zero());
+    _speedSmoothed = 0;
+}
+
+float PhysicsVehicle::getSteering(float v, float rawSteering) const
+{
+    float gain = 1;
+    if (_steerdownSpeed > MATH_FLOAT_SMALL)
+    {
+        gain = max(_steerdownGain, 1 - (1 - _steerdownGain) * fabs(v) / _steerdownSpeed);
+    }
+
+    return rawSteering * gain;
+}
+
+float PhysicsVehicle::getBraking(float v, float rawBraking) const
+{
+    float reduc = 0;
+    float delta = _brakedownFull - _brakedownStart;
+    if (delta > MATH_FLOAT_SMALL)
+    {
+        reduc = max(0.0f, (v - _brakedownStart) / delta);
+        reduc *= reduc;
+    }
+
+    return max(0.0f, rawBraking - reduc);
+}
+
+float PhysicsVehicle::getDriving(float v, float rawDriving, float rawBraking) const
+{
+    float reduc = 0;
+    float delta = _drivedownFull - _drivedownStart;
+    if (rawBraking == 0 && delta > MATH_FLOAT_SMALL)
+    {
+        reduc = max(0.0f, (v - _drivedownStart) / delta);
+        reduc *= reduc;
+    }
+
+    float gain = 1;
+    if (_boostSpeed > MATH_FLOAT_SMALL)
+    {
+        gain = max(1.0f, _boostGain - (_boostGain - 1) * fabs(v) / _boostSpeed);
+    }
+
+    return gain * rawDriving - reduc;
+}
+
+void PhysicsVehicle::applyDownforce()
+{
+    float v = _speedSmoothed * KPH_TO_MPS;
+
+    // dynamic pressure
+    float q = 0.5f * AIR_DENSITY * v * v;
+
+    // _downforce is the product of reference area and the aerodynamic coefficient
+    _rigidBody->applyForce(Vector3(0, -_downforce * q, 0));
+}
+
 float PhysicsVehicle::getSteeringGain() const
 {
     return _steeringGain;
@@ -262,4 +382,78 @@ void PhysicsVehicle::setDrivingForce(float drivingForce)
     _drivingForce = drivingForce;
 }
 
+float PhysicsVehicle::getSteerdownSpeed() const
+{
+    return _steerdownSpeed;
+}
+
+float PhysicsVehicle::getSteerdownGain() const
+{
+    return _steerdownGain;
+}
+
+void PhysicsVehicle::setSteerdown(float steerdownSpeed, float steerdownGain)
+{
+    _steerdownSpeed = steerdownSpeed;
+    _steerdownGain = steerdownGain;
+}
+
+float PhysicsVehicle::getBrakedownStart() const
+{
+    return _brakedownStart;
+}
+
+float PhysicsVehicle::getBrakedownFull() const
+{
+    return _brakedownFull;
+}
+
+void PhysicsVehicle::setBrakedown(float brakedownStart, float brakedownFull)
+{
+    _brakedownStart = brakedownStart;
+    _brakedownFull = brakedownFull;
+}
+
+float PhysicsVehicle::getDrivedownStart() const
+{
+    return _drivedownStart;
+}
+
+float PhysicsVehicle::getDrivedownFull() const
+{
+    return _drivedownFull;
+}
+
+void PhysicsVehicle::setDrivedown(float drivedownStart, float drivedownFull)
+{
+    _drivedownStart = drivedownStart;
+    _drivedownFull = drivedownFull;
+}
+
+float PhysicsVehicle::getBoostSpeed() const
+{
+    return _boostSpeed;
+}
+
+float PhysicsVehicle::getBoostGain() const
+{
+    return _boostGain;
+}
+
+void PhysicsVehicle::setBoost(float boostSpeed, float boostGain)
+{
+    _boostSpeed = boostSpeed;
+    _boostGain = boostGain;
+}
+
+float PhysicsVehicle::getDownforce() const
+{
+    return _downforce;
+}
+
+void PhysicsVehicle::setDownforce(float downforce)
+{
+    _downforce = downforce;
+}
+
 }

+ 215 - 0
gameplay/src/PhysicsVehicle.h

@@ -33,6 +33,25 @@ class PhysicsVehicleWheel;
         steeringGain   = <float>    // steering at full deflection
         brakingForce   = <float>    // braking force at full braking
         drivingForce   = <float>    // driving force at full throttle
+
+        // Steering gain reduction with speed (optional)
+        steerdownSpeed = <float>    // steering gain fades to this point
+        steerdownGain  = <float>    // gain value at that point (less than 1)
+
+        // Brake force reduction at high speeds (optional)
+        brakedownStart = <float>    // braking fades above this speed
+        brakedownFull  = <float>    // braking is fully faded at this speed
+
+        // Driving force reduction at high speeds (optional)
+        drivedownStart = <float>    // driving force fades above this speed
+        drivedownFull  = <float>    // driving force is fully faded at this speed
+
+        // Driving force boost at low speeds (optional)
+        boostSpeed     = <float>    // Boost fades to 1 at this point
+        boostGain      = <float>    // Boost at zero speed (greater than 1)
+
+        // Aerodynamic downforce effect (optional)
+        downforce      = <float>    // proportional control of downforce
     }
  @endverbatim
  */
@@ -80,6 +99,12 @@ public:
      */
     float getSpeedKph() const;
 
+    /**
+     * Returns a lagged version of vehicle speed in kilometers per hour,
+     * for example that might be used to control engine sounds.
+     */
+    float getSpeedSmoothKph() const;
+
     /**
      * Updates the vehicle state using the specified normalized command
      * inputs, and updates the transform on the visual node for each wheel.
@@ -91,6 +116,11 @@ public:
      */
     void update(float elapsedTime, float steering, float braking, float driving);
 
+    /**
+     * Resets the vehicle's state, for example in preparation for a reposition.
+     */
+    void reset();
+
     /**
      * Gets steering gain at full deflection.
      *
@@ -133,6 +163,151 @@ public:
      */
     void setDrivingForce(float drivingForce);
 
+    /**
+     * Returns speed at the point of reduced steering, in km/h.
+     * A point of reduced steering is defined by speed and gain.
+     * Steering authority will reduce linearly with speed up to
+     * this point, and remain constant above that.
+     *
+     * @return speed at the point of reduced steering, in km/h.
+     */
+    float getSteerdownSpeed() const;
+
+    /**
+     * Returns gain at the point of reduced steering, typically
+     * less than 1.
+     * A point of reduced steering is defined by speed and gain.
+     * Steering authority will reduce linearly with speed up to
+     * this point, and remain constant above that.
+     *
+     * @return gain at the point of reduced steering.
+     */
+    float getSteerdownGain() const;
+
+    /**
+     * Sets the point of reduced steering, defined by speed and
+     * gain. Typically the gain value is less than 1.
+     * Steering authority will reduce linearly with speed up to
+     * this point, and remain constant above that.
+     *
+     * @param steerdownSpeed speed at the point of reduced steering,
+     *     in km/h.
+     * @param steerdownGain gain at the point of reduced steering.
+     *     A gain of 1 will effectively disable the feature.
+     */
+    void setSteerdown(float steerdownSpeed, float steerdownGain);
+
+    /**
+     * Returns speed where braking starts to fade, in km/h.
+     *
+     * @return speed where braking starts to fade, in km/h.
+     */
+    float getBrakedownStart() const;
+
+    /**
+     * Returns speed where braking is fully faded, in km/h.
+     * This speed is typically greater than the brakedownStart
+     * speed.
+     *
+     * @return speed where braking is fully faded, in km/h.
+     */
+    float getBrakedownFull() const;
+
+    /**
+     * Sets points that control fade of brake force with speed,
+     * in km/h.
+     *
+     * @param brakedownStart braking fades above this speed.
+     *     A very large value will effectively disable the feature.
+     * @param brakedownFull braking is fully faded at this speed.
+     *     This speed is typically greater than the brakedownStart
+     *     speed.
+     */
+    void setBrakedown(float brakedownStart, float brakedownFull);
+
+    /**
+     * Returns speed where driving force starts to fade, in km/h.
+     *
+     * @return speed where driving force starts to fade, in km/h.
+     */
+    float getDrivedownStart() const;
+
+    /**
+     * Returns speed where driving force is fully faded, in km/h.
+     * This speed is typically greater than the drivedownStart
+     * speed.
+     *
+     * @return speed where driving force is fully faded, in km/h.
+     */
+    float getDrivedownFull() const;
+
+    /**
+     * Sets points that control fade of driving force with speed,
+     * in km/h.
+     *
+     * @param drivedownStart driving force fades above this speed.
+     *     A very large value will effectively disable the feature.
+     * @param drivedownFull driving force is fully faded at this speed.
+     *     This speed is typically greater than the drivedownStart
+     *     speed.
+     */
+    void setDrivedown(float drivedownStart, float drivedownFull);
+
+    /**
+     * Returns upper limit of low-speed boost effect, in km/h.
+     * Driving force is boosted by a specified factor at zero speed,
+     * and that factor fades linearly with speed reaching 1 at
+     * this speed.
+     *
+     * @return upper limit of low-speed boost effect, in km/h.
+     */
+    float getBoostSpeed() const;
+
+    /**
+     * Returns boost gain at zero speed, typically greater than 1.
+     * Driving force is boosted by this factor at zero speed, and
+     * that factor fades linearly with speed reaching 1 at a
+     * specified speed.
+     *
+     * @return boost gain at zero speed.
+     */
+    float getBoostGain() const;
+
+    /**
+     * Sets parameters that define low-speed boost of the driving force.
+     * Driving force is boosted by the specified factor at zero speed,
+     * and that factor fades linearly with speed reaching 1 at the
+     * specified speed.
+     *
+     * @param boostSpeed upper limit of low-speed boost effect, in km/h.
+     * @param boostGain boost gain at zero speed, typically greater than 1.
+     *     A gain of 1 will effectively disable the feature.
+     */
+    void setBoost(float boostSpeed, float boostGain);
+
+    /**
+     * Returns the lumped constant that controls aerodynamic downforce.
+     * Technically speaking, this constant lumps together the reference
+     * area and the down-force coefficient, and is in world-units squared.
+     * The actual aerodynamic down-force is calculated as a function of
+     * current speed, and is proportional to this constant.
+     *
+     * @return the lumped constant that controls aerodynamic downforce.
+     */
+    float getDownforce() const;
+
+    /**
+     * Sets the lumped constant that controls aerodynamic downforce.
+     * Technically speaking, this constant lumps together the reference
+     * area and the down-force coefficient, and is in world-units squared.
+     * The actual aerodynamic down-force is calculated as a function of
+     * current speed, and is proportional to this constant.
+     *
+     * @param downforce the lumped constant that controls aerodynamic downforce.
+     *     A value of 0 will effectively disable this feature.
+     */
+    void setDownforce(float downforce);
+
 protected:
 
     /**
@@ -186,6 +361,36 @@ private:
      */
     void initialize();
 
+    /**
+     * Returns adjusted steering value.
+     *
+     * @param v vehicle speed.
+     * @param rawSteering raw steering command.
+     */
+    float getSteering(float v, float rawSteering) const;
+
+    /**
+     * Returns adjusted braking force value.
+     *
+     * @param v vehicle speed.
+     * @param rawBraking raw braking force command.
+     */
+    float getBraking(float v, float rawBraking) const;
+
+    /**
+     * Returns adjusted driving force value.
+     *
+     * @param v vehicle speed.
+     * @param rawDriving raw driving force command.
+     * @param rawBraking raw braking force command.
+     */
+    float getDriving(float v, float rawDriving, float rawBraking) const;
+
+    /**
+     * Applies effect of aerodynamic downforce.
+     */
+    void applyDownforce();
+
     /**
      * Destructor.
      */
@@ -194,6 +399,16 @@ private:
     float _steeringGain;
     float _brakingForce;
     float _drivingForce;
+    float _steerdownSpeed;
+    float _steerdownGain;
+    float _brakedownStart;
+    float _brakedownFull;
+    float _drivedownStart;
+    float _drivedownFull;
+    float _boostSpeed;
+    float _boostGain;
+    float _downforce;
+    float _speedSmoothed;
     PhysicsRigidBody* _rigidBody;
     btRaycastVehicle::btVehicleTuning _vehicleTuning;
     btVehicleRaycaster* _vehicleRaycaster;