/* 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); }
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); }
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; }
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; } }
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); }