calculateRotatedPosition() public static method

public static calculateRotatedPosition ( CelestialBody body, Vector3 relativePosition, double time ) : Vector3
body CelestialBody
relativePosition Vector3
time double
return Vector3
Beispiel #1
0
        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);
        }
Beispiel #2
0
        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();
        }
Beispiel #3
0
        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();
        }
Beispiel #4
0
        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;
            }
        }