public static calculateRotatedPosition ( CelestialBody body, Vector3 relativePosition, double time ) : Vector3 | ||
body | CelestialBody | |
relativePosition | Vector3 | |
time | double | |
Результат | Vector3 |
private static Vector2 GetCorrection() { var vessel = FlightGlobals.ActiveVessel; if (vessel == null) { return(new Vector2(0, 0)); } Vector3? targetPosition = Trajectory.fetch.targetPosition; var patch = Trajectory.fetch.patches.LastOrDefault(); CelestialBody body = Trajectory.fetch.targetBody; if (!targetPosition.HasValue || patch == null || !patch.impactPosition.HasValue || patch.startingState.referenceBody != body || !patch.isAtmospheric) { return(new Vector2(0, 0)); } // Get impact position, or, if some point over the trajectory has not enough clearance, smoothly interpolate to that point depending on how much clearance is missing Vector3 impactPosition = patch.impactPosition.Value; foreach (var p in patch.atmosphericTrajectory) { float neededClearance = 600.0f; float missingClearance = neededClearance - (p.pos.magnitude - (float)body.Radius - p.groundAltitude); if (missingClearance > 0.0f) { if (Vector3.Distance(p.pos, patch.rawImpactPosition.Value) > 3000.0f) { float coeff = missingClearance / neededClearance; Vector3 rotatedPos = p.pos; if (!Settings.fetch.BodyFixedMode) { rotatedPos = Trajectory.calculateRotatedPosition(body, p.pos, p.time); } impactPosition = impactPosition * (1.0f - coeff) + rotatedPos * coeff; } break; } } Vector3 right = Vector3.Cross(patch.impactVelocity.Value, impactPosition).normalized; Vector3 behind = Vector3.Cross(right, impactPosition).normalized; Vector3 offset = targetPosition.Value - impactPosition; Vector2 offsetDir = new Vector2(Vector3.Dot(right, offset), Vector3.Dot(behind, offset)); offsetDir *= 0.00005f; // 20km <-> 1 <-> 45° (this is purely indicative, no physical meaning, it would be very complicated to compute an actual correction angle as it depends on the spacecraft behavior in the atmosphere ; a small angle will suffice for a plane, but even a big angle might do almost nothing for a rocket) Vector3d pos = vessel.GetWorldPos3D() - body.position; Vector3d vel = vessel.obt_velocity - body.getRFrmVel(body.position + pos); // air velocity float plannedAngleOfAttack = (float)DescentProfile.fetch.GetAngleOfAttack(body, pos, vel); if (plannedAngleOfAttack < Math.PI * 0.5f) { offsetDir.y = -offsetDir.y; // behavior is different for prograde or retrograde entry } float maxCorrection = 1.0f; offsetDir.x = Mathf.Clamp(offsetDir.x, -maxCorrection, maxCorrection); offsetDir.y = Mathf.Clamp(offsetDir.y, -maxCorrection, maxCorrection); return(offsetDir); }
private void initMeshFromOrbit(Vector3 bodyPosition, Mesh mesh, Orbit orbit, double startTime, double duration, Color color) { int steps = 128; Vector3 camPos = ScaledSpace.ScaledToLocalSpace(MapView.MapCamera.transform.position) - bodyPosition; double prevTA = orbit.TrueAnomalyAtUT(startTime); double prevTime = startTime; double[] stepUT = new double[steps * 4]; int utIdx = 0; double maxDT = Math.Max(1.0, duration / (double)steps); double maxDTA = 2.0 * Math.PI / (double)steps; stepUT[utIdx++] = startTime; while (true) { double time = prevTime + maxDT; for (int count = 0; count < 100; ++count) { if (count == 99) { Debug.Log("WARNING: infinite loop? (Trajectories.MapOverlay.initMeshFromOrbit)"); } double ta = orbit.TrueAnomalyAtUT(time); while (ta < prevTA) { ta += 2.0 * Math.PI; } if (ta - prevTA <= maxDTA) { prevTA = ta; break; } time = (prevTime + time) * 0.5; } if (time > startTime + duration - (time - prevTime) * 0.5) { break; } prevTime = time; stepUT[utIdx++] = time; if (utIdx >= stepUT.Length - 1) { //Util.PostSingleScreenMessage("ut overflow", "ut overflow"); break; // this should never happen, but better stop than overflow if it does } } stepUT[utIdx++] = startTime + duration; var vertices = new Vector3[utIdx * 2 + 2]; var triangles = new int[utIdx * 6]; Vector3 prevMeshPos = Util.SwapYZ(orbit.getRelativePositionAtUT(startTime - duration / (double)steps)); for (int i = 0; i < utIdx; ++i) { double time = stepUT[i]; Vector3 curMeshPos = Util.SwapYZ(orbit.getRelativePositionAtUT(time)); if (Settings.fetch.BodyFixedMode) { curMeshPos = Trajectory.calculateRotatedPosition(orbit.referenceBody, curMeshPos, time); } // compute an "up" vector that is orthogonal to the trajectory orientation and to the camera vector (used to correctly orient quads to always face the camera) Vector3 up = Vector3.Cross(curMeshPos - prevMeshPos, camPos - curMeshPos).normalized *(lineWidth * Vector3.Distance(camPos, curMeshPos)); // add a segment to the trajectory mesh vertices[i * 2 + 0] = curMeshPos - up; vertices[i * 2 + 1] = curMeshPos + up; if (i > 0) { int idx = (i - 1) * 6; triangles[idx + 0] = (i - 1) * 2 + 0; triangles[idx + 1] = (i - 1) * 2 + 1; triangles[idx + 2] = i * 2 + 1; triangles[idx + 3] = (i - 1) * 2 + 0; triangles[idx + 4] = i * 2 + 1; triangles[idx + 5] = i * 2 + 0; } prevMeshPos = curMeshPos; } var colors = new Color[vertices.Length]; for (int i = 0; i < colors.Length; ++i) { //if (color.g < 0.5) colors[i] = color; /*else * colors[i] = new Color(0, (float)i / (float)colors.Length, 1.0f - (float)i / (float)colors.Length);*/ } for (int i = 0; i < vertices.Length; ++i) { vertices[i] = ScaledSpace.LocalToScaledSpace(vertices[i] + bodyPosition); } mesh.Clear(); mesh.vertices = vertices; mesh.colors = colors; mesh.triangles = triangles; mesh.RecalculateBounds(); }
private void initMeshFromOrbit(Vector3 bodyPosition, Mesh mesh, Orbit orbit, double startTime, double duration, Color color) { int steps = 128; double prevTA = orbit.TrueAnomalyAtUT(startTime); double prevTime = startTime; double[] stepUT = new double[steps * 4]; int utIdx = 0; double maxDT = Math.Max(1.0, duration / (double)steps); double maxDTA = 2.0 * Math.PI / (double)steps; stepUT[utIdx++] = startTime; while (true) { double time = prevTime + maxDT; for (int count = 0; count < 100; ++count) { if (count == 99) { Debug.Log("WARNING: infinite loop? (Trajectories.MapOverlay.initMeshFromOrbit)"); } double ta = orbit.TrueAnomalyAtUT(time); while (ta < prevTA) { ta += 2.0 * Math.PI; } if (ta - prevTA <= maxDTA) { prevTA = ta; break; } time = (prevTime + time) * 0.5; } if (time > startTime + duration - (time - prevTime) * 0.5) { break; } prevTime = time; stepUT[utIdx++] = time; if (utIdx >= stepUT.Length - 1) { //Util.PostSingleScreenMessage("ut overflow", "ut overflow"); break; // this should never happen, but better stop than overflow if it does } } stepUT[utIdx++] = startTime + duration; var vertices = new Vector3[utIdx * 2 + 2]; var uvs = new Vector2[utIdx * 2 + 2]; var triangles = new int[utIdx * 6]; Vector3 prevMeshPos = Util.SwapYZ(orbit.getRelativePositionAtUT(startTime - duration / (double)steps)) + bodyPosition; for (int i = 0; i < utIdx; ++i) { double time = stepUT[i]; Vector3 curMeshPos = Util.SwapYZ(orbit.getRelativePositionAtUT(time)); if (Settings.fetch.BodyFixedMode) { curMeshPos = Trajectory.calculateRotatedPosition(orbit.referenceBody, curMeshPos, time); } curMeshPos += bodyPosition; // add a segment to the trajectory mesh MakeRibbonEdge(prevMeshPos, curMeshPos, lineWidth, vertices, i * 2); uvs[i * 2 + 0] = new Vector2(0.8f, 0); uvs[i * 2 + 1] = new Vector2(0.8f, 1); if (i > 0) { int idx = (i - 1) * 6; triangles[idx + 0] = (i - 1) * 2 + 0; triangles[idx + 1] = (i - 1) * 2 + 1; triangles[idx + 2] = i * 2 + 1; triangles[idx + 3] = (i - 1) * 2 + 0; triangles[idx + 4] = i * 2 + 1; triangles[idx + 5] = i * 2 + 0; } prevMeshPos = curMeshPos; } var colors = new Color[vertices.Length]; for (int i = 0; i < colors.Length; ++i) { //if (color.g < 0.5) colors[i] = color; /*else * colors[i] = new Color(0, (float)i / (float)colors.Length, 1.0f - (float)i / (float)colors.Length);*/ } mesh.Clear(); mesh.vertices = vertices; mesh.uv = uvs; mesh.colors = colors; mesh.triangles = triangles; mesh.RecalculateBounds(); mesh.MarkDynamic(); }
private void FixedUpdate() { line.enabled = false; targetingCross.enabled = false; if (!Settings.fetch.DisplayTrajectories || Util.IsMap || !Settings.fetch.DisplayTrajectoriesInFlight || Trajectory.fetch.patches.Count == 0) { return; } line.Vertices.Clear(); Trajectory.Patch lastPatch = Trajectory.fetch.patches[Trajectory.fetch.patches.Count - 1]; Vector3d bodyPosition = lastPatch.startingState.referenceBody.position; if (lastPatch.isAtmospheric) { for (uint i = 0; i < lastPatch.atmosphericTrajectory.Length; ++i) { Vector3 vertex = lastPatch.atmosphericTrajectory[i].pos + bodyPosition; line.Vertices.Add(vertex); } } else { double time = lastPatch.startingState.time; double time_increment = (lastPatch.endTime - lastPatch.startingState.time) / defaultVertexCount; Orbit orbit = lastPatch.spaceOrbit; for (uint i = 0; i < defaultVertexCount; ++i) { Vector3 vertex = Util.SwapYZ(orbit.getRelativePositionAtUT(time)); if (Settings.fetch.BodyFixedMode) { vertex = Trajectory.calculateRotatedPosition(orbit.referenceBody, vertex, time); } vertex += bodyPosition; line.Vertices.Add(vertex); time += time_increment; } } line.Body = lastPatch.startingState.referenceBody; line.enabled = true; if (lastPatch.impactPosition != null) { targetingCross.ImpactPosition = lastPatch.impactPosition.Value; targetingCross.ImpactBody = lastPatch.startingState.referenceBody; targetingCross.enabled = true; } else { targetingCross.ImpactPosition = null; targetingCross.ImpactBody = null; } }