예제 #1
0
        /* MAP: build: map to Texture2D */
        public Texture2D getPartialMap()
        {
            SCANdata data = SCANUtil.getData(body);

            Color[] pix;

            /* init cache if necessary */
            if (body != big_heightmap_body)
            {
                switch (mapType)
                {
                case 0: big_heightmap = new float [mapwidth, mapheight, 3]; big_heightmap_body = body; break;

                default: break;
                }
            }

            if (map == null)
            {
                map = new Texture2D(mapwidth, mapheight, TextureFormat.ARGB32, false);
                pix = map.GetPixels();
                for (int i = 0; i < pix.Length; ++i)
                {
                    pix [i] = Color.clear;
                }
                map.SetPixels(pix);
            }
            else if (mapstep >= map.height)
            {
                return(map);
            }
            if (redline == null || redline.Length != map.width)
            {
                redline = new Color[map.width];
                for (int i = 0; i < redline.Length; ++i)
                {
                    redline [i] = Color.red;
                }
            }
            if (mapstep < map.height - 1)
            {
                map.SetPixels(0, mapstep + 1, map.width, 1, redline);
            }
            if (mapstep <= 0)
            {
                mapstep = 0;
                mapline = new double[map.width];
            }
            pix = map.GetPixels(0, mapstep, map.width, 1);
            for (int i = 0; i < map.width; i++)
            {
                int    scheme = 0;
                double lat = (mapstep * 1.0f / mapscale) - 90f + lat_offset;
                double lon = (i * 1.0f / mapscale) - 180f + lon_offset;
                double la = lat, lo = lon;
                lat     = unprojectLatitude(lo, la);
                lon     = unprojectLongitude(lo, la);
                pix [i] = Color.grey;
                if (double.IsNaN(lat) || double.IsNaN(lon) || lat < -90 || lat > 90 || lon < -180 || lon > 180)
                {
                    pix [i] = Color.clear;
                    continue;
                }
                if (mapmode == 0)
                {
                    if (!data.isCovered(lon, lat, SCANdata.SCANtype.Altimetry))
                    {
                        continue;
                    }
                    if (body.pqsController == null)
                    {
                        pix [i] = Color.Lerp(Color.black, Color.white, UnityEngine.Random.value);
                        //big_heightmap[i, mapstep, SCANcontroller.controller.projection] = 0;
                        continue;
                    }
                    float val = 0f;
                    if (mapType == 0)
                    {
                        val = big_heightmap[i, mapstep, SCANcontroller.controller.projection];
                    }
                    if (val == 0)
                    {
                        if (data.isCovered(lon, lat, SCANdata.SCANtype.AltimetryHiRes))
                        {
                            // high resolution gets a coloured pixel for the actual position
                            val    = (float)data.getElevation(lon, lat);
                            pix[i] = heightToColor(val, scheme);
                            heightMapArray(val, mapstep, i, mapType);
                        }
                        else
                        {
                            // basic altimetry gets forced greyscale with lower resolution
                            val    = (float)data.getElevation(((int)(lon * 5)) / 5, ((int)(lat * 5)) / 5);
                            pix[i] = heightToColor(val, 1);
                            heightMapArray(val, mapstep, i, mapType);
                        }
                    }
                    else if (val != 0)
                    {
                        if (data.isCovered(lon, lat, SCANdata.SCANtype.AltimetryHiRes))
                        {
                            pix[i] = heightToColor(val, scheme);
                        }
                        else
                        {
                            pix[i] = heightToColor(val, 1);
                        }
                    }

                    /* draw height lines - works, but mostly useless...
                     * int step = (int)(val / 1000);
                     * int step_h = step, step_v = step;
                     * if(i > 0) step_h = (int)(bigline[i - 1] / 1000);
                     * if(bigstep > 0) step_v = (int)(bigline[i] / 1000);
                     * if(step != step_h || step != step_v) {
                     * pix[i] = Color.white;
                     * }
                     */
                    mapline [i] = val;
                }
                else if (mapmode == 1)
                {
                    if (!data.isCovered(lon, lat, SCANdata.SCANtype.Altimetry))
                    {
                        continue;
                    }
                    if (body.pqsController == null)
                    {
                        pix [i] = Color.Lerp(Color.black, Color.white, UnityEngine.Random.value);
                        continue;
                    }
                    float val = 0f;
                    if (mapType == 0)
                    {
                        val = big_heightmap[i, mapstep, SCANcontroller.controller.projection];
                    }
                    if (val == 0)
                    {
                        if (data.isCovered(lon, lat, SCANdata.SCANtype.AltimetryHiRes))
                        {
                            val = (float)data.getElevation(lon, lat);
                            heightMapArray(val, mapstep, i, mapType);
                        }
                        else
                        {
                            val = (float)data.getElevation(((int)(lon * 5)) / 5, ((int)(lat * 5)) / 5);
                            heightMapArray(val, mapstep, i, mapType);
                        }
                    }
                    if (mapstep == 0)
                    {
                        pix [i] = Color.grey;
                    }
                    else
                    {
                        // This doesn't actually calculate the slope per se, but it's faster
                        // than asking for yet more elevation data. Please don't use this
                        // code to operate nuclear power plants or rockets.
                        double v1 = mapline [i];
                        if (i > 0)
                        {
                            v1 = Math.Max(v1, mapline [i - 1]);
                        }
                        if (i < mapline.Length - 1)
                        {
                            v1 = Math.Max(v1, mapline [i + 1]);
                        }
                        float v = Mathf.Clamp((float)Math.Abs(val - v1) / 1000f, 0, 2f);
                        if (SCANcontroller.controller.colours == 1)
                        {
                            pix [i] = Color.Lerp(Color.black, Color.white, v / 2f);
                        }
                        else
                        {
                            if (v < 1)
                            {
                                pix [i] = Color.Lerp(XKCDColors.PukeGreen, XKCDColors.Lemon, v);
                            }
                            else
                            {
                                pix [i] = Color.Lerp(XKCDColors.Lemon, XKCDColors.OrangeRed, v - 1);
                            }
                        }
                    }
                    mapline [i] = val;
                }
                else if (mapmode == 2)
                {
                    if (!data.isCovered(lon, lat, SCANdata.SCANtype.Biome))
                    {
                        continue;
                    }
                    if (body.BiomeMap == null || body.BiomeMap.Map == null)
                    {
                        pix [i] = Color.Lerp(Color.black, Color.white, UnityEngine.Random.value);
                        continue;
                    }

                    /* // this just basically stretches the actual biome map to fit... it looks horrible
                     * float u = ((lon + 360 + 180 + 90)) % 360;
                     * float v = ((lat + 180 + 90)) % 180;
                     * if(u < 0 || v < 0 || u >= 360 || v >= 180) continue;
                     * u /= 360f; v /= 180f;
                     * pix[i] = body.BiomeMap.Map.GetPixelBilinear(u, v);
                     */
                    double bio   = data.getBiomeIndexFraction(lon, lat);
                    Color  biome = Color.grey;
                    if (SCANcontroller.controller.colours == 1)
                    {
                        if ((i > 0 && mapline [i - 1] != bio) || (mapstep > 0 && mapline [i] != bio))
                        {
                            biome = Color.white;
                        }
                        else
                        {
                            biome = Color.Lerp(Color.black, Color.white, (float)bio);
                        }
                    }
                    else
                    {
                        Color elevation = Color.gray;
                        if (data.isCovered(lon, lat, SCANdata.SCANtype.Altimetry))
                        {
                            float val = 0f;
                            if (mapType == 0)
                            {
                                val = big_heightmap[i, mapstep, SCANcontroller.controller.projection];
                            }
                            if (val == 0)
                            {
                                if (data.isCovered(lon, lat, SCANdata.SCANtype.AltimetryHiRes))
                                {
                                    val = (float)data.getElevation(lon, lat);
                                    heightMapArray(val, mapstep, i, mapType);
                                }
                                else
                                {
                                    val = (float)data.getElevation(((int)(lon * 5)) / 5, ((int)(lat * 5)) / 5);
                                    heightMapArray(val, mapstep, i, mapType);
                                }
                            }
                            elevation = Color.Lerp(Color.black, Color.white, Mathf.Clamp(val + 1500f, 0, 9000) / 9000f);
                        }
                        Color bio1 = XKCDColors.CamoGreen;
                        Color bio2 = XKCDColors.Marigold;
                        if ((i > 0 && mapline [i - 1] != bio) || (mapstep > 0 && mapline [i] != bio))
                        {
                            //biome = Color.Lerp(XKCDColors.Puce, elevation, 0.5f);
                            biome = Color.white;
                        }
                        else
                        {
                            biome = Color.Lerp(Color.Lerp(bio1, bio2, (float)bio), elevation, 0.5f);
                        }
                    }

                    pix [i]     = biome;
                    mapline [i] = bio;
                }
            }
            map.SetPixels(0, mapstep, map.width, 1, pix);
            mapstep++;
            if (mapstep % 10 == 0 || mapstep >= map.height)
            {
                map.Apply();
            }
            return(map);
        }
예제 #2
0
        private ScienceData getAvailableScience(SCANtype sensor, bool notZero)
        {
            SCANdata data = SCANUtil.getData(vessel.mainBody);

            if (data == null)
            {
                return(null);
            }
            ScienceData       sd = null;
            ScienceExperiment se = null;
            ScienceSubject    su = null;
            bool   found         = false;
            string id            = null;
            double coverage      = 0f;
            float  multiplier    = 1f;

            if (!found && (sensor & SCANtype.AltimetryLoRes) != SCANtype.Nothing)
            {
                found = true;
                if (vessel.mainBody.pqsController == null)
                {
                    multiplier = 0.5f;
                }
                id       = "SCANsatAltimetryLoRes";
                coverage = SCANUtil.getCoveragePercentage(data, SCANtype.AltimetryLoRes);
            }
            else if (!found && (sensor & SCANtype.AltimetryHiRes) != SCANtype.Nothing)
            {
                found = true;
                if (vessel.mainBody.pqsController == null)
                {
                    multiplier = 0.5f;
                }
                id       = "SCANsatAltimetryHiRes";
                coverage = SCANUtil.getCoveragePercentage(data, SCANtype.AltimetryHiRes);
            }
            else if (!found && (sensor & SCANtype.Biome) != SCANtype.Nothing)
            {
                found = true;
                if (vessel.mainBody.BiomeMap == null)
                {
                    multiplier = 0.5f;
                }
                id       = "SCANsatBiomeAnomaly";
                coverage = SCANUtil.getCoveragePercentage(data, SCANtype.Biome);
            }
            if (!found)
            {
                return(null);
            }
            se = ResearchAndDevelopment.GetExperiment(id);
            if (se == null)
            {
                return(null);
            }

            su = ResearchAndDevelopment.GetExperimentSubject(se, ExperimentSituations.InSpaceHigh, vessel.mainBody, "surface");
            if (su == null)
            {
                return(null);
            }

            su.scienceCap *= multiplier;

            SCANUtil.SCANlog("Coverage: {0}, Science cap: {1}, Subject value: {2}, Scientific value: {3}, Science: {4}", new object[5] {
                coverage.ToString("F1"), su.scienceCap.ToString("F1"), su.subjectValue.ToString("F2"), su.scientificValue.ToString("F2"), su.science.ToString("F2")
            });

            su.scientificValue = 1;

            float science = (float)coverage;

            if (science > 95)
            {
                science = 100;
            }
            if (science < 30)
            {
                science = 0;
            }
            science = science / 100f;
            science = Mathf.Max(0, (science * su.scienceCap) - su.science);

            SCANUtil.SCANlog("Remaining science: {0}, Base value: {1}", new object[2] {
                science.ToString("F1"), se.baseValue.ToString("F1")
            });

            science /= Mathf.Max(0.1f, su.scientificValue);             //look 10 lines up; this is always 1...
            science /= su.subjectValue;

            SCANUtil.SCANlog("Resulting science value: {0}", new object[1] {
                science.ToString("F2")
            });

            if (notZero && science <= 0)
            {
                science = 0.00001f;
            }

            sd       = new ScienceData(science * su.dataScale, 1f, 0f, su.id, se.experimentTitle + " of " + vessel.mainBody.theName);
            su.title = sd.title;
            return(sd);
        }
예제 #3
0
        protected void doScanPass(SCANvessel vessel, double UT, double startUT, double lastUT, double llat, double llon)
        {
            Vessel   v = vessel.vessel;
            SCANdata data = SCANUtil.getData(v.mainBody);
            double   soi_radius = v.mainBody.sphereOfInfluence - v.mainBody.Radius;
            double   alt = v.altitude, lat = fixLatitude(v.latitude), lon = fixLongitude(v.longitude);
            double   res = 0;
            Orbit    o   = v.orbit;
            bool     uncovered;

            if (scanQueue == null)
            {
                scanQueue = new Queue <double>();
            }
            if (scanQueue.Count != 0)
            {
                scanQueue.Clear();
            }

loop:       // don't look at me like that, I just unrolled the recursion
            if (res > 0)
            {
                if (double.IsNaN(UT))
                {
                    goto dequeue;
                }
                if (o.ObT <= 0)
                {
                    goto dequeue;
                }
                if (double.IsNaN(o.getObtAtUT(UT)))
                {
                    goto dequeue;
                }
                Vector3d pos      = o.getPositionAtUT(UT);
                double   rotation = 0;
                if (v.mainBody.rotates)
                {
                    rotation = (360 * ((UT - scan_UT) / v.mainBody.rotationPeriod)) % 360;
                }
                alt = v.mainBody.GetAltitude(pos);
                lat = fixLatitude(v.mainBody.GetLatitude(pos));
                lon = fixLongitude(v.mainBody.GetLongitude(pos) - rotation);
                if (alt < 0)
                {
                    alt = 0;
                }
                if (res > maxRes)
                {
                    maxRes = (int)res;
                }
            }
            else
            {
                alt = v.heightFromTerrain;
                if (alt < 0)
                {
                    alt = v.altitude;
                }
            }

            if (Math.Abs(lat - llat) < 1 && Math.Abs(lon - llon) < 1 && res > 0)
            {
                goto dequeue;
            }
            actualPasses++;

            uncovered = res <= 0;
            foreach (SCANsensor sensor in knownVessels[v.id].sensors.Values)
            {
                if (res <= 0)
                {
                    if (data.getCoverage(sensor.sensor) > 0)
                    {
                        uncovered = false;
                    }
                }

                sensor.inRange   = false;
                sensor.bestRange = false;
                if (alt < sensor.min_alt)
                {
                    continue;
                }
                if (alt > Math.Min(sensor.max_alt, soi_radius))
                {
                    continue;
                }
                sensor.inRange = true;

                double fov = sensor.fov;
                double ba  = Math.Min(sensor.best_alt, soi_radius);
                if (alt < ba)
                {
                    fov = (alt / ba) * fov;
                }
                else
                {
                    sensor.bestRange = true;
                }

                double surfscale = 600000d / v.mainBody.Radius;
                if (surfscale < 1)
                {
                    surfscale = 1;
                }
                surfscale = Math.Sqrt(surfscale);
                fov      *= surfscale;
                if (fov > 20)
                {
                    fov = 20;
                }

                int f  = (int)Math.Truncate(fov);
                int f1 = f + (int)Math.Round(fov - f);

                double clampLat;
                double clampLon;
                for (int x = -f; x <= f1; ++x)
                {
                    clampLon = lon + x;                         // longitude does not need clamping
                    /*if (clampLon < 0  ) clampLon = 0; */
                    /*if (clampLon > 360) clampLon = 360; */
                    for (int y = -f; y <= f1; ++y)
                    {
                        clampLat = lat + y;
                        if (clampLat > 90)
                        {
                            clampLat = 90;
                        }
                        if (clampLat < -90)
                        {
                            clampLat = -90;
                        }
                        data.registerPass(clampLon, clampLat, sensor.sensor);
                    }
                }
            }
            if (uncovered)
            {
                return;
            }

            /*
             * if(v.mainBody == FlightGlobals.currentMainBody) {
             *      if(res > 0) data.map_small.SetPixel((int)Math.Round(lon) + 180, (int)Math.Round(lat) + 90, Color.magenta);
             *      else data.map_small.SetPixel((int)Math.Round(lon) + 180, (int)Math.Round(lat) + 90, Color.yellow);
             * }
             */

            if (vessel.lastUT <= 0)
            {
                return;
            }
            if (vessel.frame <= 0)
            {
                return;
            }
            if (v.LandedOrSplashed)
            {
                return;
            }
            if (res >= timeWarpResolution)
            {
                goto dequeue;
            }

            if (startUT > UT)
            {
                scanQueue.Enqueue((startUT + UT) / 2);
                scanQueue.Enqueue(startUT);
                scanQueue.Enqueue(UT);
                scanQueue.Enqueue(lat);
                scanQueue.Enqueue(lon);
                scanQueue.Enqueue(res + 1);
            }
            startUT = UT;
            UT      = (lastUT + UT) / 2;
            llat    = lat;
            llon    = lon;
            res     = res + 1;
            goto loop;

dequeue:
            if (scanQueue.Count <= 0)
            {
                return;
            }
            UT      = scanQueue.Dequeue();
            startUT = scanQueue.Dequeue();
            lastUT  = scanQueue.Dequeue();
            llat    = scanQueue.Dequeue();
            llon    = scanQueue.Dequeue();
            res     = scanQueue.Dequeue();
            goto loop;
        }
예제 #4
0
        public override void OnLoad(ConfigNode node)
        {
            body_data.Clear();
            ConfigNode node_vessels = node.GetNode("Scanners");

            if (node_vessels != null)
            {
                print("SCANsat Controller: Loading " + node_vessels.CountNodes.ToString() + " known vessels");
                foreach (ConfigNode node_vessel in node_vessels.GetNodes("Vessel"))
                {
                    Guid   id    = new Guid(node_vessel.GetValue("guid"));
                    string stext = node_vessel.GetValue("sensors");
                    if (stext != null && stext != "")
                    {
                        int sensors = Convert.ToInt32(stext);
                        if (sensors != 0)
                        {
                            registerSensor(id, (SCANdata.SCANtype)sensors, 0, 0, 0, 0);
                        }
                    }
                    foreach (ConfigNode node_sensor in node_vessel.GetNodes("Sensor"))
                    {
                        int    sensor   = Convert.ToInt32(node_sensor.GetValue("type"));
                        double fov      = Convert.ToDouble(node_sensor.GetValue("fov"));
                        double min_alt  = Convert.ToDouble(node_sensor.GetValue("min_alt"));
                        double max_alt  = Convert.ToDouble(node_sensor.GetValue("max_alt"));
                        double best_alt = Convert.ToDouble(node_sensor.GetValue("best_alt"));
                        registerSensor(id, (SCANdata.SCANtype)sensor, fov, min_alt, max_alt, best_alt);
                    }
                }
            }
            ConfigNode node_progress = node.GetNode("Progress");

            if (node_progress != null)
            {
                foreach (ConfigNode node_body in node_progress.GetNodes("Body"))
                {
                    string body_name = node_body.GetValue("Name");
                    print("SCANsat Controller: Loading map for " + body_name);
                    CelestialBody body = FlightGlobals.Bodies.FirstOrDefault(b => b.name == body_name);
                    if (body != null)
                    {
                        SCANdata data = SCANUtil.getData(body);
                        try {
                            string mapdata = node_body.GetValue("Map");
                            data.deserialize(mapdata);
                        } catch (Exception e) {
                            print(e.ToString());
                            print(e.StackTrace);
                            // fail somewhat gracefully; don't make the save unloadable
                        }
                        data.disabled = Convert.ToBoolean(node_body.GetValue("Disabled"));
                    }
                }
            }
            if (!warned && SCANversions.SCANurl != "SCANsat/Plugins" && !string.IsNullOrEmpty(SCANversions.SCANurl))
            {             //Complain if SCANsat is installed in the wrong place
                ScreenMessages.PostScreenMessage(string.Format("SCANsat plugin installed in the wrong directory: {0}. Installation location should be:/nKerbal Space Program/GameData/SCANsat/Plugins/SCANsat.dll", SCANversions.SCANurl), 15f, ScreenMessageStyle.UPPER_CENTER);
                warned = true;
            }
        }
예제 #5
0
        public ScienceData getAvailableScience(Vessel v, SCANdata.SCANtype sensor, bool notZero)
        {
            SCANdata          data = SCANUtil.getData(v.mainBody);
            ScienceData       sd   = null;
            ScienceExperiment se   = null;
            ScienceSubject    su   = null;
            bool   found           = false;
            string id       = null;
            double coverage = 0f;

            if (v.mainBody.pqsController != null)
            {
                if (!found && (sensor & SCANdata.SCANtype.AltimetryLoRes) != SCANdata.SCANtype.Nothing)
                {
                    found    = true;
                    id       = "SCANsatAltimetryLoRes";
                    coverage = data.getCoveragePercentage(SCANdata.SCANtype.AltimetryLoRes);
                }
                if (!found && (sensor & SCANdata.SCANtype.AltimetryHiRes) != SCANdata.SCANtype.Nothing)
                {
                    found    = true;
                    id       = "SCANsatAltimetryHiRes";
                    coverage = data.getCoveragePercentage(SCANdata.SCANtype.AltimetryHiRes);
                }
            }
            if (v.mainBody.BiomeMap != null)
            {
                if (!found && (sensor & SCANdata.SCANtype.Biome) != SCANdata.SCANtype.Nothing)
                {
                    found    = true;
                    id       = "SCANsatBiomeAnomaly";
                    coverage = data.getCoveragePercentage(SCANdata.SCANtype.Biome | SCANdata.SCANtype.Anomaly);
                }
            }

            if (!found)
            {
                return(null);
            }

            se = ResearchAndDevelopment.GetExperiment(id);
            if (se == null)
            {
                return(null);
            }

            su = ResearchAndDevelopment.GetExperimentSubject(se, ExperimentSituations.InSpaceHigh, v.mainBody, "surface");
            if (su == null)
            {
                return(null);
            }

            print("[SCANsat] coverage " + coverage.ToString("F1") + ", science cap " + su.scienceCap.ToString("F1") + ", subject value " + su.subjectValue.ToString("F2") + ", science value " + su.scientificValue.ToString("F2") + ", science " + su.science.ToString("F2"));
            su.scientificValue = 1;

            float science = (float)coverage;

            if (science > 95)
            {
                science = 100;
            }
            if (science < 30)
            {
                science = 0;
            }
            science = science / 100f;
            science = Mathf.Max(0, (science * su.scienceCap) - su.science);

            print("[SCANsat] remaining science: " + science.ToString("F1") + ", base = " + (se.baseValue).ToString("F1"));

            science /= Mathf.Max(0.1f, su.scientificValue);
            science /= su.subjectValue;

            print("[SCANsat] result = " + science.ToString("F2"));

            if (notZero && science <= 0)
            {
                science = 0.00001f;
            }

            sd           = new ScienceData(science, 1f, 0f, id, se.experimentTitle + " of " + v.mainBody.theName);
            sd.subjectID = su.id;
            return(sd);
        }