private float getFixedVsVelocityFactor(Vehicle veh, 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))); } } }
private float computeLookFrontOffset(Vehicle veh, 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, this.smoothIsInAir); return(res); }
private void processCameraCommon(Ped player, Vehicle veh) { smoothIsInAir = Mathr.Lerp(smoothIsInAir, veh.IsInAir ? 1f : 0f, 1.3f * getDeltaTime()); smoothIsRearGear = Mathr.Lerp(smoothIsRearGear, veh.CurrentGear == 0 ? 1f : 0f, 1.3f * getDeltaTime()); speedCoeff = Mathr.Max(veh.Speed, veh.Velocity.Magnitude() / 22f); pointAt = veh.Position + fullHeightOffset + (veh.ForwardVector * computeLookFrontOffset(veh, speedCoeff, smoothIsInAir)); finalDummyOffset = Mathr.Lerp(vehDummyOffset, vehDummyOffsetHighSpeed, speedCoeff / (maxHighSpeed * 1.6f)); // no offset if car is in the air finalDummyOffset = Mathr.Lerp(finalDummyOffset, 0f, smoothIsInAir); if (veh.TowedVehicle != null) { towedVehicleLongitude = veh.TowedVehicle.Model.GetDimensions().Y; } else { towedVehicleLongitude = 0f; } fullLongitudeOffset = (distanceOffset + currentVehicleLongitude / 2f) /* + vehDummyOffset*/ + 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(veh) / (maxHighSpeed * 10f); currentDistanceIncrement += Mathr.Lerp(0f, accelerationCamDistanceMultiplier, Easing.EaseOut(factor, useEasingForCamDistance ? EasingType.Quadratic : EasingType.Linear)); } }
private Transform UpdateCameraRear(Ped player, Vehicle veh) { // smooth out current rotation and position currentRotation = Mathr.QuaternionNLerp(currentRotation, rearCamCurrentTransform.quaternion, (responsivenessMultiplier * generalMovementSpeed) * getDeltaTime()); currentPos = Vector3.Lerp(currentPos, rearCamCurrentTransform.position, Mathr.Clamp01((responsivenessMultiplier * generalMovementSpeed) * 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(veh, speedCoeff); // Compute camera position rear the vechicle var wantedPosFixed = wantedPos - Vector3.Transform(Extensions.RelativeFront, veh.Quaternion) * fullLongitudeOffset; // smooth out velocity smoothVelocity = Mathr.Vector3SmoothDamp(smoothVelocity, Vector3.Normalize(veh.Velocity), ref smoothVelocitySmDamp, generalMovementSpeed, 9999999f, responsivenessMultiplier * getDeltaTime()); // Compute camera postition rear the direction of the vehcle if (speedCoeff >= stoppedSpeed) { wantedPosVelocity = wantedPos + Vector3.Transform(Extensions.RelativeBottom, Mathr.QuaternionLookRotation(smoothVelocity)) * fullLongitudeOffset; } // Smooth factor between two above cam positions smoothFixedVsVelocity = Mathr.Lerp(smoothFixedVsVelocity, fixedVsVelocity, (fixedVsVelocitySpeed) * getDeltaTime()); if (!isCycleOrByke) { tempSmoothVsVl = Mathr.Lerp(tempSmoothVsVl, Mathr.Clamp(speedCoeff / 2.3f, 0.025f, 1f), (fixedVsVelocitySpeed / 20f)); smoothFixedVsVelocity = Mathr.Lerp(0f, smoothFixedVsVelocity, tempSmoothVsVl); } wantedPos = Vector3.Lerp(wantedPosFixed, wantedPosVelocity, Mathr.Clamp01(smoothFixedVsVelocity)); //currentPos = Vector3.Lerp(currentPos, wantedPos, Mathr.Clamp01((responsivenessMultiplier * cameraStickiness) * getDeltaTime())); currentPos = Vector3.Lerp(currentPos, wantedPos, Mathr.Clamp01((responsivenessMultiplier * cameraStickiness) * getDeltaTime())); //rearCamCurrentTransform.position = currentPos; mainCamera.PointAt(pointAt); look = Extensions.Euler(mainCamera.Rotation); // Rotate the camera towards the velocity vector. var finalCamRotationSpeed = Mathr.Lerp(cameraRotationSpeedLowSpeed, cameraRotationSpeed, ((speedCoeff / lowSpeedLimit) * 1.32f) * getDeltaTime() * 51f); look = Mathr.QuaternionNLerp(currentRotation, look, (1.8f * finalCamRotationSpeed) * getDeltaTime()); //// Auto align over time //if (alignmentSpeed > 0.001f) //{ // var wantedRot = veh.Rotation; // //wantedRot.y = 0f; // //look = Mathr.QuaternionNLerp(look, Quaternion.Euler(wantedRot), (alignmentSpeed * getDeltaTime()) * (1 - smoothIsInAir)); // Transform alignTr = new Transform(currentPos + fullHeightOffset, Quaternion.Identity); // alignTr.PointAt(pointAt); // alignTr.quaternion = Quaternion.Lerp(alignTr.quaternion, Quaternion.Euler(wantedRot), alignmentSpeed * getDeltaTime() * (1 - smoothIsInAir)); // currentPos = veh.Position + fullHeightOffset + (alignTr.quaternion * Vector3.RelativeBack * (fullLongitudeOffset + currentDistanceIncrement)); //} // Fix stuttering (mantain camera distance fixed in local space) Transform fixedDistanceTr = new Transform(currentPos + fullHeightOffset + (Extensions.WorldUp * extraCamHeight), Quaternion.Identity); fixedDistanceTr.PointAt(pointAt); Quaternion rotInitial = fixedDistanceTr.quaternion; // Auto alignment (WIP) //Vector3 rotBehindVector = veh.Position + fullHeightOffset - (veh.Quaternion * Vector3.RelativeFront * (fullLongitudeOffset + currentDistanceIncrement)); //rotBehindVector.Z = fixedDistanceTr.position.Z; //Quaternion rotBehind = Mathr.LookAt(rotBehindVector, pointAt); //Quaternion finalRot = Quaternion.Lerp(rotInitial, rotBehind, alignmentSpeed * (1 - smoothIsInAir) * (1 - smoothIsRearGear)); //fixedDistanceTr.position = veh.Position + fullHeightOffset + (finalRot * Vector3.RelativeBack * (fullLongitudeOffset + currentDistanceIncrement)); // End Autoalignment fixedDistanceTr.position = veh.Position + fullHeightOffset + (Extensions.WorldUp * extraCamHeight) + (Vector3.Transform(Extensions.RelativeBack, rotInitial) * (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); }