/// <summary>
        /// Updates the static instance with new settings
        /// </summary>
        public void Update()
        {
            RefLatitude    = (float)CelestialBody.GetLatitudeAndLongitude(gameObject.transform.position).x;
            RefLongitude   = (float)(CelestialBody.GetLatitudeAndLongitude(gameObject.transform.position).y);
            RadialPosition = radialPosition;

            gameObject.transform.localScale = origScale * ModelScale;

            RelativePosition = gameObject.transform.localPosition;
            Orientation      = gameObject.transform.localEulerAngles;
            RadiusOffset     = (float)((surfaceHeight - groupCenter.surfaceHeight) + RelativePosition.y);


            // Notify modules about update
            gameObject.BroadcastMessage("StaticObjectUpdate");
        }
Example #2
0
		// return terrain height at point specified
		// - body terrain must be loaded for this to work: use it only for loaded vessels
		public static double TerrainHeight(CelestialBody body, Vector3d pos)
		{
			PQS pqs = body.pqsController;
			if (pqs == null) return 0.0;
			Vector2d latlong = body.GetLatitudeAndLongitude(pos);
			Vector3d radial = QuaternionD.AngleAxis(latlong.y, Vector3d.down) * QuaternionD.AngleAxis(latlong.x, Vector3d.forward) * Vector3d.right;
			return (pos - body.position).magnitude - pqs.GetSurfaceHeight(radial);
		}
        /// <summary>
        /// Updates the static instance with new settings
        /// </summary>
        public void Update()
        {
            RefLatitude    = (float)CelestialBody.GetLatitudeAndLongitude(gameObject.transform.position).x;
            RefLongitude   = (float)(CelestialBody.GetLatitudeAndLongitude(gameObject.transform.position).y);
            RadialPosition = radialPosition;

            gameObject.transform.localScale = origScale * ModelScale;

            RelativePosition = gameObject.transform.localPosition;
            Orientation      = gameObject.transform.localEulerAngles;
            RadiusOffset     = (float)((surfaceHeight - groupCenter.surfaceHeight) + RelativePosition.y);


            // Notify modules about update
            foreach (StaticModule module in gameObject.GetComponents <StaticModule>())
            {
                module.StaticObjectUpdate();
            }
        }
Example #4
0
        /// <summary>
        /// Coroutine for adding scripts to the Lua context.  Paced to load one
        /// string per frame.
        ///
        /// It also looks for existing global RasterPropMonitor COLOR_ definitions.
        /// </summary>
        /// <returns>null when done</returns>
        private IEnumerator LoadAvionicsSystemAssets()
        {
            userScripts.Clear();
            ConfigNode[] userScriptNodes = GameDatabase.Instance.GetConfigNodes("MAS_LUA");
            if (userScriptNodes.Length > 0)
            {
                for (int nodeIdx = 0; nodeIdx < userScriptNodes.Length; ++nodeIdx)
                {
                    if (userScriptNodes[nodeIdx].HasValue("name"))
                    {
                        ConfigNode node    = userScriptNodes[nodeIdx];
                        string[]   scripts = node.GetValues("script");
                        Utility.LogMessage(this, "Parsing MAS_LUA node \"{0}\" ({1} script references)", node.GetValue("name"), scripts.Length);

                        for (int scriptIdx = 0; scriptIdx < scripts.Length; ++scriptIdx)
                        {
                            userScripts.Add(string.Join(Environment.NewLine, File.ReadAllLines(KSPUtil.ApplicationRootPath + "GameData/" + scripts[scriptIdx], Encoding.UTF8)));
                        }
                        yield return(new WaitForEndOfFrame());
                    }
                }
            }

            namedColors.Clear();
            ConfigNode[] rpmColorNodes = GameDatabase.Instance.GetConfigNodes("RPM_GLOBALCOLORSETUP");
            for (int colorNodeIdx = 0; colorNodeIdx < rpmColorNodes.Length; ++colorNodeIdx)
            {
                ConfigNode[] colorDef = rpmColorNodes[colorNodeIdx].GetNodes("COLORDEFINITION");
                for (int defIdx = 0; defIdx < colorDef.Length; ++defIdx)
                {
                    if (colorDef[defIdx].HasValue("name") && colorDef[defIdx].HasValue("color"))
                    {
                        string  name  = "COLOR_" + (colorDef[defIdx].GetValue("name").Trim());
                        Color32 color = ConfigNode.ParseColor32(colorDef[defIdx].GetValue("color").Trim());
                        if (namedColors.ContainsKey(name))
                        {
                            namedColors[name] = color;
                        }
                        else
                        {
                            namedColors.Add(name, color);
                        }

                        //Utility.LogMessage(this, "{0} = {1}", name, color);
                    }
                }
                yield return(new WaitForEndOfFrame());
            }

            // Add XKCD colors
            Type t = typeof(XKCDColors);

            PropertyInfo[] properties    = t.GetProperties();
            int            numProperties = properties.Length;

            for (int i = 0; i < numProperties; ++i)
            {
                try
                {
                    // This is probably overkill in terms of checks.
                    if (properties[i].PropertyType == typeof(Color) && properties[i].CanRead)
                    {
                        MethodInfo[] accessor = properties[i].GetAccessors();
                        for (int j = 0; j < accessor.Length; ++j)
                        {
                            if (accessor[j].ReturnType == typeof(Color))
                            {
                                object o     = accessor[j].Invoke(null, null);
                                Color  color = (Color)o;

                                StringBuilder sb = StringBuilderCache.Acquire();
                                sb.Append("COLOR_XKCD_").Append(properties[i].Name.ToUpperInvariant());
                                string name = sb.ToStringAndRelease();
                                if (namedColors.ContainsKey(name))
                                {
                                    namedColors[name] = color;
                                }
                                else
                                {
                                    namedColors.Add(name, color);
                                }
                            }
                        }
                    }
                }
                catch { }
            }
            yield return(new WaitForEndOfFrame());

            deepSpaceNetwork.Clear();
            var dsn = UnityEngine.Object.FindObjectsOfType <CommNet.CommNetHome>();

            if (dsn != null)
            {
                CelestialBody kerbin = Planetarium.fetch.Home;

                for (int i = 0; i < dsn.Length; ++i)
                {
                    // Unfortunately, the lat/lon/alt/body fields are all protected, so I have
                    // to do this, instead:
                    Vector3d position = dsn[i].nodeTransform.position;
                    Vector2d ll       = kerbin.GetLatitudeAndLongitude(position);

                    if (deepSpaceNetwork.ContainsKey(dsn[i].nodeName))
                    {
                        deepSpaceNetwork[dsn[i].nodeName] = ll;
                    }
                    else
                    {
                        deepSpaceNetwork.Add(dsn[i].nodeName, ll);
                    }
                }
            }
        }
Example #5
0
        public void Update()
        {
            timeSpentInIllumination  = TimeSpan.Zero;
            timeSpentInTextureUpdate = TimeSpan.Zero;
            DateTime      start  = DateTime.UtcNow;
            CelestialBody kerbin = FlightGlobals.GetHomeBody();

            if (reset)
            {
                reset          = false;
                kerbin_imaging = null;
                lastUpdateUT   = null;
                window.width   = 0;
                window.height  = 0;
                return;
            }
            if (pause)
            {
                return;
            }
            if (kerbin_imaging == null)
            {
                UnityEngine.Debug.LogWarning("Rebuilding map...");
                x_size         = small ? 256 : 512;
                y_size         = small ? 128 : 256;
                kerbin_imaging = new ImagingParallel[y_size];
                minimap        = new UnityEngine.Texture2D(x_size, y_size);
                for (int y = 0; y < y_size; ++y)
                {
                    // Mollweide on [-2, 2] × [-1, 1].
                    double y_normalized = 2.0 * y / y_size - 1;
                    double θ            = Math.Asin(y_normalized);
                    double sinφ         = (2 * θ + Math.Sin(2 * θ)) / Math.PI;
                    double φ            = Math.Asin(sinφ);
                    double φ_deg        = φ * (180 / Math.PI);
                    var    parallel     = kerbin_imaging[y] = new ImagingParallel
                    {
                        cosLatitude = Math.Cos(φ),
                        sinLatitude = sinφ,
                        map         = new MapPoint[x_size],
                        midInfrared = new ImagingStatus[x_size],
                        nightVisNIR = new ImagingStatus[x_size],
                        unglintedReflectiveVisNIR = new ImagingStatus[x_size],
                        glintedReflectiveVisNIR   = new ImagingStatus[x_size],
                        sun     = new SunSurfaceGeometry[x_size],
                        surface = new SurfacePoint[x_size]
                    };
                    bool entered_map = false;
                    parallel.x_end = x_size;
                    for (int x = 0; x < x_size; ++x)
                    {
                        double x_normalized = 4.0 * x / x_size - 2;
                        double λ            = Math.PI * x_normalized / (2 * Math.Cos(θ));
                        double λ_deg        = λ * (180 / Math.PI);

                        if (double.IsNaN(φ) || double.IsNaN(λ) || Math.Abs(λ) > Math.PI)
                        {
                            parallel.map[x].on_map = false;
                            if (entered_map && parallel.x_end == x_size)
                            {
                                parallel.x_end = x;
                            }
                        }
                        else
                        {
                            parallel.map[x].on_map = true;
                            if (!entered_map)
                            {
                                parallel.x_begin = x;
                            }
                            entered_map = true;
                            double altitude = kerbin.TerrainAltitude(φ_deg, λ_deg);
                            parallel.surface[x] = new SurfacePoint(
                                kerbin.scaledBody.transform.rotation.Inverse() *
                                (kerbin.GetWorldSurfacePosition(φ_deg, λ_deg, altitude) - kerbin.position));
                            parallel.map[x].ocean = altitude == 0;
                            parallel.midInfrared[x].lastImagingTime               = new double[resolutionThresholds.Length];
                            parallel.nightVisNIR[x].lastImagingTime               = new double[resolutionThresholds.Length];
                            parallel.glintedReflectiveVisNIR[x].lastImagingTime   = new double[resolutionThresholds.Length];
                            parallel.unglintedReflectiveVisNIR[x].lastImagingTime = new double[resolutionThresholds.Length];
                            for (int i = 0; i < resolutionThresholds.Length; ++i)
                            {
                                parallel.midInfrared[x].lastImagingTime[i]               = double.NegativeInfinity;
                                parallel.nightVisNIR[x].lastImagingTime[i]               = double.NegativeInfinity;
                                parallel.glintedReflectiveVisNIR[x].lastImagingTime[i]   = double.NegativeInfinity;
                                parallel.unglintedReflectiveVisNIR[x].lastImagingTime[i] = double.NegativeInfinity;
                            }
                        }
                    }
                }
            }
            var    imagers = activeImagers.ToArray();
            double Δt      = 30;

            if (lastUpdateUT == null || kerbin.scaledBody.transform.rotation == null)
            {
                lastUpdateUT       = Planetarium.GetUniversalTime();
                lastKerbinRotation = kerbin.scaledBody.transform.rotation;
            }
            var current_kerbin_to_world = kerbin.scaledBody.transform.rotation;

            for (int n = (int)Math.Floor((Planetarium.GetUniversalTime() - lastUpdateUT.Value) / Δt); n >= 0; --n)
            {
                double t = Planetarium.GetUniversalTime() - n * Δt;
                // TODO(egg): This will fail hilariously if the interval between updates is greater than half a day.
                // It is probably broken in other ways.
                var kerbin_to_world = UnityEngine.Quaternion.Slerp(
                    lastKerbinRotation.Value, current_kerbin_to_world,
                    (float)((t - lastUpdateUT) / (Planetarium.GetUniversalTime() - lastUpdateUT)));
                var      world_to_kerbin       = kerbin_to_world.Inverse();
                double   kerbin_radius         = kerbin.Radius;
                var      kerbin_world_position = kerbin.orbit.getPositionAtUT(t);
                Vector3d sunInSurfaceFrame     = world_to_kerbin *
                                                 (kerbin.referenceBody.getPositionAtUT(t) - kerbin_world_position);
                Vector3d sunDirection = sunInSurfaceFrame.normalized;
                for (int y = 0; y != y_size; ++y)
                {
                    var parallel = kerbin_imaging[y];
                    for (int x = parallel.x_begin; x != parallel.x_end; ++x)
                    {
                        if (solarParallax)
                        {
                            parallel.sun[x] = SunSurfaceGeometry.FromSunPosition(
                                parallel.surface[x],
                                sunInSurfaceFrame);
                        }
                        else
                        {
                            parallel.sun[x] = SunSurfaceGeometry.FromSunDirection(
                                parallel.surface[x],
                                sunDirection);
                        }
                    }
                }
                foreach (var imager in imagers)
                {
                    Vessel           platform = FlightGlobals.FindVessel(imager.Key);
                    ImagingProduct[] products = imager.Value;
                    Vector3d         vesselFromKerbinInWorld;
                    Vector3d         kerbinCentredVesselVelocityInWorld;
                    if (platform.orbit.referenceBody == kerbin)
                    {
                        var vesselFromKerbinInAlice            = platform.orbit.getRelativePositionAtUT(t);
                        var kerbinCentredVesselVelocityInAlice = platform.orbit.getOrbitalVelocityAtUT(t);
                        vesselFromKerbinInWorld            = vesselFromKerbinInAlice.xzy;
                        kerbinCentredVesselVelocityInWorld = kerbinCentredVesselVelocityInAlice.xzy;
                    }
                    else
                    {
                        Vector3d vesselFromSunInAlice = Vector3d.zero;
                        Vector3d kerbinFromSunInAlice = Vector3d.zero;
                        Vector3d heliocentricVesselVelocityInAlice = Vector3d.zero;
                        Vector3d heliocentricKerbinVelocityInAlice = Vector3d.zero;
                        for (var orbit = platform.orbit; orbit != null; orbit = orbit.referenceBody?.orbit)
                        {
                            vesselFromSunInAlice += orbit.getRelativePositionAtUT(t);
                            heliocentricVesselVelocityInAlice += orbit.getOrbitalVelocityAtUT(t);
                        }
                        for (var orbit = kerbin.orbit; orbit != null; orbit = orbit.referenceBody?.orbit)
                        {
                            kerbinFromSunInAlice += orbit.getRelativePositionAtUT(t);
                            heliocentricKerbinVelocityInAlice += orbit.getOrbitalVelocityAtUT(t);
                        }
                        vesselFromKerbinInWorld            = (vesselFromSunInAlice - kerbinFromSunInAlice).xzy;
                        kerbinCentredVesselVelocityInWorld =
                            (heliocentricVesselVelocityInAlice - heliocentricKerbinVelocityInAlice).xzy;
                    }
                    Vector3d swathNormal;
                    if (platform.loaded)
                    {
                        // The rotation transforms from part coordinates to
                        // world coordinates.
                        // TODO(egg): that products[0] is a hack.
                        swathNormal = world_to_kerbin *
                                      (products[0].part.rb.rotation * Vector3d.up);
                    }
                    else
                    {
                        // TODO(egg): Fetch from Principia if available.
                        swathNormal = world_to_kerbin * kerbinCentredVesselVelocityInWorld.normalized;
                    }
                    Vector3d             vesselInSurfaceFrame = world_to_kerbin * vesselFromKerbinInWorld;
                    UnityEngine.Vector2d subsatellitePoint    = kerbin.GetLatitudeAndLongitude(
                        kerbin.position + current_kerbin_to_world * world_to_kerbin * vesselFromKerbinInWorld);
                    double latitude  = subsatellitePoint.x;
                    double longitude = subsatellitePoint.y;
                    double xVessel   = (0.5 + longitude / 360) % 1;
                    double yVessel   = (0.5 + latitude / 180) % 1;
                    for (int y = (int)(yVessel * y_size); y < y_size; ++y)
                    {
                        var parallel = kerbin_imaging[y];
                        UpdateParallel(
                            t, parallel, vesselInSurfaceFrame, swathNormal, products,
                            out bool parallelVisibleAtRelevantResolution);
                        if (!parallelVisibleAtRelevantResolution)
                        {
                            break;
                        }
                    }
                    for (int y = (int)(yVessel * y_size) - 1; y >= 0; --y)
                    {
                        var parallel = kerbin_imaging[y];
                        UpdateParallel(
                            t, parallel, vesselInSurfaceFrame, swathNormal, products,
                            out bool parallelVisibleAtRelevantResolution);
                        if (!parallelVisibleAtRelevantResolution)
                        {
                            break;
                        }
                    }
                }
                lastUpdateUT       = t;
                lastKerbinRotation = current_kerbin_to_world;
            }

            RefreshMap();

            minimap.Apply(updateMipmaps: false);
            timeSpentInUpdate = DateTime.UtcNow - start;
        }