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