void OpenSteer::Camera::smoothCameraMove (const Vec3& newPosition, const Vec3& newTarget, const Vec3& newUp, const float elapsedTime) { if (smoothNextMove) { const float smoothRate = elapsedTime * smoothMoveSpeed; Vec3 tempPosition = position(); Vec3 tempUp = up(); blendIntoAccumulator (smoothRate, newPosition, tempPosition); blendIntoAccumulator (smoothRate, newTarget, target); blendIntoAccumulator (smoothRate, newUp, tempUp); setPosition (tempPosition); setUp (tempUp); // xxx not sure if these are needed, seems like a good idea // xxx (also if either up or oldUP are zero, use the other?) // xxx (even better: force up to be perp to target-position axis)) if (up() == Vec3::zero) setUp (Vec3::up); else setUp (up().normalize ()); } else { smoothNextMove = true; setPosition (newPosition); target = newTarget; setUp (newUp); } }
void OpenSteer::SimpleVehicle::applySteeringForce (const Vec3& force, const float elapsedTime) { const Vec3 adjustedForce = adjustRawSteeringForce (force, elapsedTime); // enforce limit on magnitude of steering force const Vec3 clippedForce = adjustedForce.truncateLength (maxForce ()); // compute acceleration and velocity Vec3 newAcceleration = (clippedForce / mass()); Vec3 newVelocity = velocity(); // damp out abrupt changes and oscillations in steering acceleration // (rate is proportional to time step, then clipped into useful range) if (elapsedTime > 0) { const float smoothRate = clip (9 * elapsedTime, 0.15f, 0.4f); blendIntoAccumulator (smoothRate, newAcceleration, _smoothedAcceleration); } // Euler integrate (per frame) acceleration into velocity newVelocity += _smoothedAcceleration * elapsedTime; // enforce speed limit newVelocity = newVelocity.truncateLength (maxSpeed ()); // update Speed setSpeed (newVelocity.length()); // Euler integrate (per frame) velocity into position setPosition (position() + (newVelocity * elapsedTime)); // regenerate local space (by default: align vehicle's forward axis with // new velocity, but this behavior may be overridden by derived classes.) regenerateLocalSpace (newVelocity, elapsedTime); // maintain path curvature information measurePathCurvature (elapsedTime); // running average of recent positions blendIntoAccumulator (elapsedTime * 0.06f, // QQQ position (), _smoothedPosition); }
void OpenSteer::SimpleVehicle::regenerateLocalSpaceForBanking (const Vec3& newVelocity, const float elapsedTime) { // the length of this global-upward-pointing vector controls the vehicle's // tendency to right itself as it is rolled over from turning acceleration const Vec3 globalUp (0, 0.2f, 0); // acceleration points toward the center of local path curvature, the // length determines how much the vehicle will roll while turning const Vec3 accelUp = _smoothedAcceleration * 0.05f; // combined banking, sum of UP due to turning and global UP const Vec3 bankUp = accelUp + globalUp; // blend bankUp into vehicle's UP basis vector const float smoothRate = elapsedTime * 3; Vec3 tempUp = up(); blendIntoAccumulator (smoothRate, bankUp, tempUp); setUp (tempUp.normalize()); // annotationLine (position(), position() + (globalUp * 4), gWhite); // XXX // annotationLine (position(), position() + (bankUp * 4), gOrange); // XXX // annotationLine (position(), position() + (accelUp * 4), gRed); // XXX // annotationLine (position(), position() + (up () * 1), gYellow); // XXX // adjust orthonormal basis vectors to be aligned with new velocity if (speed() > 0) regenerateOrthonormalBasisUF (newVelocity / speed()); }
void OpenSteer::SimpleVehicle::measurePathCurvature (const float elapsedTime) { if (elapsedTime > 0) { const Vec3 dP = _lastPosition - position (); const Vec3 dF = (_lastForward - forward ()) / dP.length (); const Vec3 lateral = dF.perpendicularComponent (forward ()); const float sign = (lateral.dot (side ()) < 0) ? 1.0f : -1.0f; _curvature = lateral.length() * sign; blendIntoAccumulator (elapsedTime * 4.0f, _curvature, _smoothedCurvature); _lastForward = forward (); _lastPosition = position (); } }
void OpenSteer::SimpleVehicle::measurePathCurvature (const float elapsedTime) { if (elapsedTime > 0) { const Vector3 dP = _lastPosition - getPosition(); const Vector3 dF = (_lastForward - getForward()) / dP.length(); const Vector3 lateral = Vec3Utils::perpendicularComponent(dF, getForward()); const float sign = (lateral.dotProduct(getSide()) < 0) ? 1.0f : -1.0f; _curvature = lateral.length() * sign; blendIntoAccumulator (elapsedTime * 4.0f, _curvature, _smoothedCurvature); _lastForward = getForward(); _lastPosition = getPosition(); } }