/// <summary> /// Sample a bunch of points along a parabolic curve until you hit gnd. At that point, cut off the parabola /// </summary> /// /// <param name="p0">starting point of parabola</param> /// <param name="v0">initial parabola velocity</param> /// <param name="a">initial acceleration</param> /// <param name="dist">distance between sample points</param> /// <param name="points">number of sample points</param> /// <param name="tnm">Vive Nav Mesh used to teleport</param> /// <param name="outPts">List that will be populated by new points</param> /// <param name="normal">normal of hit point</param> /// /// <returns>true if the the parabole is at the end of the NavMesh</returns> private static bool CalculateParabolicCurve(float3 p0, Vector3 v0, Vector3 a, float dist, int points, TeleportNavMesh tnm, int excludedLayer, out NativeArray <Translation> outPts, out float3 normal, out int lastPointIndex) { // Init new list of points with p0 as the first point outPts = new NativeArray <Translation>(points, Allocator.TempJob); outPts[0] = new Translation { Value = p0 }; float3 last = p0; float t = 0; for (int i = 0; i < points; i++) { t += dist / ParabolicCurveDeriv(v0, a, t).magnitude; float3 next = ParabolicCurve(p0, v0, a, t); if (TeleportNavMeshHelper.Linecast(last, next, out bool endOnNavmesh, excludedLayer, out float3 castHit, out float3 norm, tnm)) { outPts[i] = new Translation { Value = castHit }; normal = norm; lastPointIndex = i; return(endOnNavmesh); }
private bool UserIsOnNavMesh(StepByStepComponent sbs, TeleportNavMesh tnm, VRRaycastOutputs raycastOutputs, LayerMask excludedLayers, out float3 newCameraRigPos) { Transform vrCamTransform = VRSF_Components.VRCamera.transform; Transform cameraRigTransform = VRSF_Components.CameraRig.transform; // We calculate the direction and the distance Vectors var directionVector = raycastOutputs.RayVar.direction; float distanceVector = cameraRigTransform.localScale.y * sbs.DistanceStepByStep; // Check if we hit a collider on the way. If it's the case, we reduce the distance. if (Physics.Raycast(vrCamTransform.position, directionVector, out RaycastHit hit, distanceVector, ~excludedLayers)) { distanceVector = hit.distance - 0.1f; } // We multiply the direction vector by the distance to which the user should be going directionVector *= distanceVector; // We check the theoritic position for the cameraRig newCameraRigPos = GetNewTheoriticPos(directionVector, true); // We check the theoritic new user pos float3 newCameraPos = GetNewTheoriticPos(directionVector, false); // We calculate a vector down based on the new Camera Pos. var downVectorDistance = Mathf.Abs(vrCamTransform.localPosition.y + VRSF_Components.FloorOffset.transform.localPosition.y) + sbs.StepHeight; var downVector = newCameraPos + (new float3(0.0f, -1.0f, 0.0f) * downVectorDistance); // We calculate the linecast between the newUserPos and the downVector and check if it hits the NavMesh TeleportNavMeshHelper.Linecast ( newCameraPos, downVector, out bool endOnNavmesh, excludedLayers, out newCameraPos, out _, tnm ); // We set the camera rig pos in y to the camera pos in y newCameraRigPos.y = newCameraPos.y; return(endOnNavmesh); /// <summary> /// We get the theoritic position for the CameraRig and the VRCamera based on the scaled direction (direction * distance) /// </summary> /// <param name="scaledDirection">The direction multiplied by the distance to go to</param> /// <param name="isCheckingCameraRig">Whether the check is for the CameraRig or the VRCamera</param> /// <returns>The new Theoritic position</returns> float3 GetNewTheoriticPos(Vector3 scaledDirection, bool isCheckingCameraRig) { float3 origin = isCheckingCameraRig ? cameraRigTransform.position : vrCamTransform.position; return(origin + new float3(scaledDirection.x, 0.0f, scaledDirection.z)); } }