private void updateCameraCommon() { speedCoeff = MathR.Max(veh.Speed, veh.Velocity.Magnitude() * 0.045454f); pointAt = veh.Position + fullHeightOffset + (veh.ForwardVector * computeLookFrontOffset(speedCoeff, script.smoothIsInAir)); fullLongitudeOffset = (distanceOffset + currentVehicleLongitudeOffset) /* + vehDummyOffset*/ + towedVehicleLongitude; finalDummyOffset = MathR.Lerp(vehDummyOffset, vehDummyOffsetHighSpeed, speedCoeff / (maxHighSpeed * 1.6f)); // no offset if car is in the air finalDummyOffset = MathR.Lerp(finalDummyOffset, 0f, script.smoothIsInAir); currentDistanceIncrement = 0f; if (increaseDistanceAtHighSpeed) { var factor = veh.Speed / maxHighSpeed; currentDistanceIncrement = MathR.Lerp(0f, maxHighSpeedDistanceIncrement, Easing.EaseOut(factor, useEasingForCamDistance ? EasingType.Cubic : EasingType.Linear)); } if (accelerationAffectsCamDistance) { var factor = getVehicleAcceleration() / (maxHighSpeed * 10f); currentDistanceIncrement += MathR.Lerp(0f, accelerationCamDistanceMultiplier, Easing.EaseOut(factor, useEasingForCamDistance ? EasingType.Quadratic : EasingType.Linear)); } }
private float getFixedVsVelocityFactor(float speedCoeff) { // If the car isn't moving, default to looking forwards if (veh.Velocity.Magnitude() < nearlySttopedSpeed) { return(0f); } else { // for bikes, always look at velocity if (isCycleOrByke) { return(1f); } // if veh is in air, look at is velocity if (veh.IsInAir || veh.CurrentGear == 0) { return(1f); } else // if is on the ground. fit camera (mostly) behind vehicle (for better drift control) { // Different factors for low/high speed return(MathR.Lerp(velocityInfluenceLowSpeed, velocityInfluence, MathR.Clamp(speedCoeff / lowSpeedLimit, 0f, 1f))); } } }
public void PointAt(Vector3 target) { var res = MathR.LookAt(position, target); quaternion = res; rotation = res.ToEulerAngles(); }
public static Quaternion XLookRotation(Vector3 direction, Vector3 up) { Quaternion rightToForward = Quaternion.Euler(0f, 90f, 0f); Quaternion forwardToTarget = MathR.LookRotationInternalY(direction, up); return(forwardToTarget * rightToForward); }
private void updateCameraCommon() { smoothIsInAir = MathR.Lerp(smoothIsInAir, veh.IsInAir || veh.IsUpsideDown ? 1f : 0f, 2f * getDeltaTime()); smoothIsRearGear = MathR.Lerp(smoothIsRearGear, veh.CurrentGear == 0 ? 1f : 0f, 1.3f * getDeltaTime()); //speedCoeff = MathR.Max(veh.Speed, veh.Velocity.Magnitude() * 0.045454f); //pointAt = veh.Position + fullHeightOffset + (veh.ForwardVector * computeLookFrontOffset(veh, speedCoeff, smoothIsInAir)); }
public static float LerpAngle(float a, float b, float t) { float num = MathR.Repeat(b - a, 360f); if ((double)num > 180.0) { num -= 360f; } return(a + num * MathR.Clamp01(t)); }
private Quaternion getRotationFromAverageWheelPosBike() { // Front var fPos = veh.GetBoneCoord("wheel_lf"); // Rear var rPos = veh.GetBoneCoord("wheel_lr"); var dir = fPos - rPos; return MathR.XLookRotation(dir); }
private float computeLookFrontOffset(float speedCoeff, float smoothIsInAir) { var speed = speedCoeff; var factor = MathR.InverseLerp(lookLowSpeedStart, lookLowSpeedEnd, speedCoeff); var res = MathR.Lerp(lookFrontOffsetLowSpeed, lookFrontOffset, factor); // No offset while in air res = MathR.Lerp(res, 0f, script.smoothIsInAir); return(res); }
public static Quaternion QuaternionFromMatrix(Matrix m) { // Adapted from: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm Quaternion q = new Quaternion(); q.W = MathR.Sqrt(MathR.Max(0, 1 + m[0, 0] + m[1, 1] + m[2, 2])) / 2; q.X = MathR.Sqrt(MathR.Max(0, 1 + m[0, 0] - m[1, 1] - m[2, 2])) / 2; q.Y = MathR.Sqrt(MathR.Max(0, 1 - m[0, 0] + m[1, 1] - m[2, 2])) / 2; q.Z = MathR.Sqrt(MathR.Max(0, 1 - m[0, 0] - m[1, 1] + m[2, 2])) / 2; q.X *= MathR.Sign(q.X * (m[2, 1] - m[1, 2])); q.Y *= MathR.Sign(q.Y * (m[0, 2] - m[2, 0])); q.Z *= MathR.Sign(q.Z * (m[1, 0] - m[0, 1])); return(q); }
public void updateCameraCommon() { fullLongitudeOffset = distanceOffset + currentVehicleLongitudeOffset + towedVehicleLongitude; currentDistanceIncrement = 0f; if (increaseDistanceAtHighSpeed) { var factor = veh.Speed / maxHighSpeed; currentDistanceIncrement = MathR.Lerp(0f, maxHighSpeedDistanceIncrement, Easing.EaseOut(factor, useEasingForCamDistance ? EasingType.Cubic : EasingType.Linear)); } if (accelerationAffectsCamDistance) { var factor = getVehicleAcceleration() / (maxHighSpeed * 10f); currentDistanceIncrement += MathR.Lerp(0f, accelerationCamDistanceMultiplier, Easing.EaseOut(factor, useEasingForCamDistance ? EasingType.Quadratic : EasingType.Linear)); } }
private Quaternion getSurfaceNormalRotation() { frameCounter++; bool proccess = frameCounter % 3 == 0; // Only proccess every 3 frames (Raycast seems to be slow on SHVDN) frameCounter = frameCounter % 9; if(proccess) { var raycast = World.Raycast(veh.Position, Vector3.WorldDown, 2f, IntersectOptions.Map, veh); if (raycast.DitHitAnything) { cachedRaycastDir = MathR.OrthoNormalize(raycast.SurfaceNormal, veh.ForwardVector); //cachedRaycastDir = Vector3.Cross(raycast.SurfaceNormal, veh.RightVector).Normalized; } } return MathR.XLookRotation(cachedRaycastDir); }
private Quaternion getRotationFromAverageWheelPosCar() { // Front Left var flPos = veh.GetBoneCoord("wheel_lf"); // Front Right var frPos = veh.GetBoneCoord("wheel_rf"); var frontAverage = (flPos + frPos) * 0.5f; // Rear Left var rlPos = veh.GetBoneCoord("wheel_lr"); // Rear Right var rrPos = veh.GetBoneCoord("wheel_rr"); var rearAverage = (rlPos + rrPos) * 0.5f; var dir = frontAverage - rearAverage; return MathR.XLookRotation(dir); }
public static float Repeat(float t, float length) { return(t - MathR.Floor(t / length) * length); }
private Transform UpdateCameraRear() { // smooth out current rotation and position currentRotation = MathR.EulerNlerp(currentRotation, rearCamCurrentTransform.quaternion, (responsivenessMultiplier * generalMovementSpeed) * Time.getDeltaTime()); currentPos = Vector3.Lerp(currentPos, rearCamCurrentTransform.position, MathR.Clamp01((responsivenessMultiplier * generalMovementSpeed) * Time.getDeltaTime())); Quaternion look; var wantedPos = veh.Position + (veh.ForwardVector * finalDummyOffset); // If veh has towed vehicle, increase camera distance by towed vehicle longitude // should camera be attached to vehicle's back or back his velocity var fixedVsVelocity = getFixedVsVelocityFactor(speedCoeff); Quaternion vehQuat = veh.Quaternion; // Compute camera position rear the vechicle var wantedPosFixed = wantedPos - veh.Quaternion * Vector3.RelativeFront * fullLongitudeOffset; // smooth out velocity // Compute camera postition rear the direction of the vehcle if (speedCoeff >= stoppedSpeed) { wantedPosVelocity = wantedPos + MathR.QuaternionLookRotation(smoothVelocity) * Vector3.RelativeBottom * fullLongitudeOffset; } // Smooth factor between two above cam positions smoothFixedVsVelocity = MathR.Lerp(smoothFixedVsVelocity, fixedVsVelocity, (fixedVsVelocitySpeed) * Time.getDeltaTime()); if (!isCycleOrByke) { tempSmoothVsVl = MathR.Lerp(tempSmoothVsVl, MathR.Clamp(speedCoeff * 0.4347826f, 0.025f, 1f), (fixedVsVelocitySpeed * 0.05f)); smoothFixedVsVelocity = MathR.Lerp(0f, smoothFixedVsVelocity, tempSmoothVsVl); } wantedPos = Vector3.Lerp(wantedPosFixed, wantedPosVelocity, MathR.Clamp01(smoothFixedVsVelocity)); //currentPos = Vector3.Lerp(currentPos, wantedPos, Mathr.Clamp01((responsivenessMultiplier * cameraStickiness) * Time.getDeltaTime())); currentPos = Vector3.Lerp(currentPos, wantedPos, MathR.Clamp01((responsivenessMultiplier * cameraStickiness) * Time.getDeltaTime())); //rearCamCurrentTransform.position = currentPos; targetCamera.PointAt(pointAt); look = Quaternion.Euler(targetCamera.Rotation); // Rotate the camera towards the velocity vector. var finalCamRotationSpeed = MathR.Lerp(cameraRotationSpeedLowSpeed, cameraRotationSpeed, ((speedCoeff / lowSpeedLimit) * 1.32f) * Time.getDeltaTime() * 51f); look = MathR.EulerNlerp(currentRotation, look, (1.8f * finalCamRotationSpeed) * Time.getDeltaTime()); // Fix stuttering (mantain camera distance fixed in local space) Transform fixedDistanceTr = new Transform(currentPos + fullHeightOffset + (Vector3.WorldUp * extraCamHeight), Quaternion.Identity); fixedDistanceTr.PointAt(pointAt); Quaternion finalQuat = fixedDistanceTr.quaternion; if (script.isMouseLooking) { finalQuat = Quaternion.Lerp(finalQuat, getFreelookQuaternion(), script.smoothIsFreeLooking); } fixedDistanceTr.position = veh.Position + fullHeightOffset + (Vector3.WorldUp * extraCamHeight) + (finalQuat * Vector3.RelativeBack * (fullLongitudeOffset + currentDistanceIncrement)); //fixedDistanceTr.position = fixedDistanceTr.position + fullHeightOffset; var transform = new Transform(); transform.position = fixedDistanceTr.position; //transform.position = currentPos + fullHeightOffset; transform.rotation = look.ToEulerAngles(); transform.quaternion = look; rearCamCurrentTransform = transform; return(transform); }
public static float Lerp(float value1, float value2, float ammount) { return(value1 + (value2 - value1) * MathR.Clamp01(ammount)); }
// Cheaper than Slerp public static Quaternion EulerNlerp(Quaternion start, Quaternion end, float ammount) { return(QuaternionFromEuler(Vector3.Lerp(start.ToEulerAngles(), end.ToEulerAngles(), MathR.Clamp01(ammount)).Normalized)); }
public override void updateCamera() { base.updateCamera(); updateCameraCommon(); var camExtraHeightV3 = Vector3.WorldUp * extraCamHeight; var posCenter = veh.Position + fullHeightOffset; float rotSpeed = rotationSpeed; if(useVariableRotSpeed) { var desiredRootSpeed = MathR.SmoothStep(minRotSpeed, maxRotSpeed, MathR.Clamp01(AngleInDeg(veh.ForwardVector, veh.Velocity) / 90)); currentRootSpeed = MathR.Lerp(currentRootSpeed, desiredRootSpeed, 2f * Time.getDeltaTime()); } if (veh.Speed > 1f) { //velQuat = MathR.LookRotation(veh.Velocity, Vector3.WorldUp); velocityQuat = MathR.XLookRotation(smoothVelocity); } Quaternion vehQuat; if(isCycleOrByke) { // Bykes / cycles (avoid unwanted cam rotations during wheelies/stoppies) if (veh.Speed < 3f) { if(veh.IsOnAllWheels) vehQuat = getRotationFromAverageWheelPosBike(); else vehQuat = getSurfaceNormalRotation(); // Possibly unperformant (using it only for wheelie/stoppie al low speeds) } else vehQuat = velocityQuat; } else // cars { if(avoidCameraBouncinessCar && veh.IsOnAllWheels) { vehQuat = getRotationFromAverageWheelPosCar(); // Avoid camera movements caused by car suspension movement (wheels are on the floor) } else { vehQuat = veh.Quaternion; } } //smoothQuat = MathR.QuatNlerp(smoothQuat, veh.Quaternion, MathR.Clamp01(rotationSpeed * Time.getDeltaTime())); smoothQuat = Quaternion.SlerpUnclamped(smoothQuat, vehQuat, rotationSpeed * Time.getDeltaTime()); smoothVelQuat = Quaternion.Lerp(smoothVelQuat, velocityQuat, 2f * Time.getDeltaTime()); finalQuat = Quaternion.Lerp(smoothQuat, velocityQuat, script.smoothIsInAir); float finalDistMult = 1f; if (veh.Speed > 0.15f) { // TODO Optimize? finalDistMult = Vector3.Angle(finalQuat * Vector3.RelativeFront, veh.Velocity) / 180f; finalDistMult = MathR.Lerp(1f, -1f, finalDistMult); } if(script.isMouseLooking) { finalQuat = Quaternion.Lerp(finalQuat, getFreelookQuaternion(), script.smoothIsFreeLooking); } targetCamera.Position = posCenter + camExtraHeightV3 + (finalQuat * Vector3.RelativeBack * (fullLongitudeOffset + ( currentDistanceIncrement * finalDistMult ))); var pointAt = posCenter - finalQuat * Vector3.RelativeBack * (currentDistanceIncrement + 2f); targetCamera.PointAt(pointAt); }
public float AngleInRad(Vector3 vec1, Vector3 vec2) { return MathR.Atan2(vec2.Y - vec1.Y, vec2.X - vec1.X); }
public Quaternion getFreelookQuaternion() { return(MathR.LookAt(Vector3.Zero, GameplayCamera.Direction)); }