private void MoveAngular(float timestep) { /* * private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor * private int m_angularMotorApply = 0; // application frame counter * private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down) * private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate * private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate * private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate * private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body */ // Get what the body is doing, this includes 'external' influences btVector3 angularVelocity = m_body.getInterpolationAngularVelocity(); // Vector3 angularVelocity = Vector3.Zero; if (m_angularMotorApply > 0) { // ramp up to new value // current velocity += error / (time to get there / step interval) // requested speed - last motor speed m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / timestep); m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / timestep); m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / timestep); m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected // velocity may still be acheived. } else { // no motor recently applied, keep the body velocity /* m_angularMotorVelocity.X = angularVelocity.X; * m_angularMotorVelocity.Y = angularVelocity.Y; * m_angularMotorVelocity.Z = angularVelocity.Z; */ // and decay the velocity m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / timestep); } // end motor section // Vertical attractor section Vector3 vertattr = Vector3.Zero; if (m_verticalAttractionTimescale < 300) { float VAservo = 0.2f / (m_verticalAttractionTimescale * timestep); // get present body rotation btQuaternion rot = m_body.getWorldTransform().getRotation(); Quaternion rotq = new Quaternion(rot.getX(), rot.getY(), rot.getZ(), rot.getW()); // make a vector pointing up Vector3 verterr = Vector3.Zero; verterr.Z = 1.0f; // rotate it to Body Angle verterr = verterr * rotq; // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. if (verterr.Z < 0.0f) { verterr.X = 2.0f - verterr.X; verterr.Y = 2.0f - verterr.Y; } // Error is 0 (no error) to +/- 2 (max error) // scale it by VAservo verterr = verterr * VAservo; //if (frcount == 0) Console.WriteLine("VAerr=" + verterr); // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. vertattr.X = verterr.Y; vertattr.Y = -verterr.X; vertattr.Z = 0f; // scaling appears better usingsquare-law float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); vertattr.X += bounce * angularVelocity.getX(); vertattr.Y += bounce * angularVelocity.getY(); } // else vertical attractor is off // m_lastVertAttractor = vertattr; // Bank section tba // Deflection section tba // Sum velocities m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) { m_lastAngularVelocity.X = 0; m_lastAngularVelocity.Y = 0; } // apply friction Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / timestep); m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; // Apply to the body m_body.setAngularVelocity(new btVector3(m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z)); }