diff --git a/NewHorizons/Atmosphere/CloudsBuilder.cs b/NewHorizons/Atmosphere/CloudsBuilder.cs index 850016b2..7188b6bb 100644 --- a/NewHorizons/Atmosphere/CloudsBuilder.cs +++ b/NewHorizons/Atmosphere/CloudsBuilder.cs @@ -1,5 +1,6 @@ using NewHorizons.External; using NewHorizons.Utility; +using OWML.Common; using OWML.Utils; using System; using UnityEngine; @@ -9,15 +10,20 @@ namespace NewHorizons.Atmosphere { static class CloudsBuilder { - public static void Make(GameObject body, Sector sector, AtmosphereModule atmo) + public static void Make(GameObject body, Sector sector, AtmosphereModule atmo, IModAssets assets) { Texture2D image, cap, ramp; try { - image = Main.Instance.CurrentAssets.GetTexture(atmo.Cloud); - cap = Main.Instance.CurrentAssets.GetTexture(atmo.CloudCap); - ramp = Main.Instance.CurrentAssets.GetTexture(atmo.CloudRamp); + image = assets.GetTexture(atmo.Cloud); + + if (atmo.CloudCap == null) cap = ImageUtilities.ClearTexture(128, 128); + else cap = assets.GetTexture(atmo.CloudCap); + + //if(atmo.CloudRamp == null) ramp = ImageUtilities.Scaled(image, 1, 128); + if(atmo.CloudRamp == null) ramp = ImageUtilities.CanvasScaled(image, 1, image.height); + else ramp = assets.GetTexture(atmo.CloudRamp); } catch(Exception e) { @@ -112,7 +118,11 @@ namespace NewHorizons.Atmosphere // Fix the rotations once the rest is done cloudsMainGO.transform.localRotation = Quaternion.Euler(0, 0, 0); + cloudsMainGO.transform.localPosition = Vector3.zero; + cloudsBottomGO.transform.localPosition = Vector3.zero; + cloudsFluidGO.transform.localPosition = Vector3.zero; + cloudsTopGO.transform.localPosition = Vector3.zero; cloudsTopGO.SetActive(true); cloudsBottomGO.SetActive(true); diff --git a/NewHorizons/Atmosphere/EffectsBuilder.cs b/NewHorizons/Atmosphere/EffectsBuilder.cs index 14310bfa..da935252 100644 --- a/NewHorizons/Atmosphere/EffectsBuilder.cs +++ b/NewHorizons/Atmosphere/EffectsBuilder.cs @@ -35,19 +35,22 @@ namespace NewHorizons.Atmosphere if(hasSnow) { - var snowGO = GameObject.Instantiate(GameObject.Find("/BrittleHollow_Body/Sector_BH/Effects_BH/Effects_BH_Snowflakes"), effectsGO.transform); + var snowGO = new GameObject("SnowEffects"); + snowGO.transform.parent = effectsGO.transform; snowGO.transform.localPosition = Vector3.zero; + for(int i = 0; i < 5; i++) + { + var snowEmitter = GameObject.Instantiate(GameObject.Find("/BrittleHollow_Body/Sector_BH/Effects_BH/Effects_BH_Snowflakes"), snowGO.transform); + snowEmitter.name = "SnowEmitter"; + snowEmitter.transform.localPosition = Vector3.zero; - var pvc = snowGO.GetComponent(); - pvc.SetValue("_densityByHeight", new AnimationCurve(new Keyframe[] { new Keyframe(surfaceSize, 10f), new Keyframe(atmoSize, 0f) })); + var pvc = snowEmitter.GetComponent(); + pvc.SetValue("_densityByHeight", new AnimationCurve(new Keyframe[] { new Keyframe(surfaceSize, 10f), new Keyframe(atmoSize, 0f) })); - var particleSystem = snowGO.GetComponent(); - var e = particleSystem.emission; - e.rateOverTime = 50; - - snowGO.GetComponent().SetValue("_activeInSector", sector); - snowGO.GetComponent().SetValue("_exclusionSectors", new Sector[] { }); - snowGO.SetActive(true); + snowEmitter.GetComponent().SetValue("_activeInSector", sector); + snowEmitter.GetComponent().SetValue("_exclusionSectors", new Sector[] { }); + snowEmitter.SetActive(true); + } } effectsGO.transform.localPosition = Vector3.zero; diff --git a/NewHorizons/Atmosphere/FogBuilder.cs b/NewHorizons/Atmosphere/FogBuilder.cs index 8665413f..96f8ed37 100644 --- a/NewHorizons/Atmosphere/FogBuilder.cs +++ b/NewHorizons/Atmosphere/FogBuilder.cs @@ -66,6 +66,7 @@ namespace NewHorizons.Atmosphere fogGO.transform.localPosition = Vector3.zero; lodFogGO.transform.localPosition = Vector3.zero; + fogGO.SetActive(true); lodFogGO.SetActive(true); } diff --git a/NewHorizons/Body/AsteroidBeltBuilder.cs b/NewHorizons/Body/AsteroidBeltBuilder.cs index b3779a7e..3a872b18 100644 --- a/NewHorizons/Body/AsteroidBeltBuilder.cs +++ b/NewHorizons/Body/AsteroidBeltBuilder.cs @@ -1,5 +1,6 @@ using NewHorizons.External; using NewHorizons.Utility; +using OWML.Common; using System; using System.Collections.Generic; using System.Linq; @@ -13,7 +14,7 @@ namespace NewHorizons.Body { static class AsteroidBeltBuilder { - public static void Make(string bodyName, AsteroidBeltModule belt) + public static void Make(string bodyName, AsteroidBeltModule belt, IModAssets assets) { var minSize = 20; var maxSize = 50; @@ -33,7 +34,8 @@ namespace NewHorizons.Body {"HasMapMarker", false }, {"SurfaceGravity", 1 }, {"SurfaceSize", size }, - {"HasReferenceFrame", false } + {"HasReferenceFrame", false }, + {"GravityFallOff", "inverseSquared" } } }, {"Orbit", new Dictionary() @@ -57,7 +59,7 @@ namespace NewHorizons.Body Logger.Log($"{config}"); - var asteroid = new NewHorizonsBody(new PlanetConfig(config)); + var asteroid = new NewHorizonsBody(new PlanetConfig(config), assets); Main.AdditionalBodies.Add(asteroid); } } diff --git a/NewHorizons/Body/BlackHoleBuilder.cs b/NewHorizons/Body/BlackHoleBuilder.cs index 3c57c005..65b86a43 100644 --- a/NewHorizons/Body/BlackHoleBuilder.cs +++ b/NewHorizons/Body/BlackHoleBuilder.cs @@ -1,4 +1,5 @@ -using System; +using NewHorizons.External; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -9,12 +10,27 @@ namespace NewHorizons.General { static class BlackHoleBuilder { - public static void Make(GameObject body) + public static void Make(GameObject body, BaseModule module, Sector sector) { var blackHole = GameObject.Instantiate(GameObject.Find("BrittleHollow_Body/BlackHole_BH"), body.transform); blackHole.name = "BlackHole"; - blackHole.GetComponentInChildren().material.renderQueue = 3001; blackHole.transform.localPosition = Vector3.zero; + //blackHole.transform.localScale = Vector3.one; //* module.BlackHoleSize; + + var blackHoleRenderer = blackHole.transform.Find("BlackHoleRenderer"); + //blackHoleRenderer.transform.localScale = Vector3.one; + + var singularityLOD = blackHoleRenderer.GetComponent(); + singularityLOD.SetSector(sector); + + /* + var meshRenderer = blackHoleRenderer.GetComponent(); + meshRenderer.material.SetFloat("_Radius", module.BlackHoleSize * 0.4f); + + var owRenderer = blackHoleRenderer.gameObject.AddComponent(); + var propID_Radius = Shader.PropertyToID("_Radius"); + owRenderer.SetMaterialProperty(propID_Radius, module.BlackHoleSize * 0.4f); + */ } } } diff --git a/NewHorizons/Body/CometTailBuilder.cs b/NewHorizons/Body/CometTailBuilder.cs new file mode 100644 index 00000000..f7b61510 --- /dev/null +++ b/NewHorizons/Body/CometTailBuilder.cs @@ -0,0 +1,28 @@ +using NewHorizons.External; +using OWML.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.Body +{ + public static class CometTailBuilder + { + public static void Make(GameObject go, BaseModule module, AstroObject primary) + { + var cometTail = GameObject.Instantiate(GameObject.Find("Comet_Body/Sector_CO/Effects_CO/Effects_CO_TailMeshes"), go.transform); + cometTail.transform.localPosition = Vector3.zero; + cometTail.name = "CometTail"; + cometTail.transform.localScale = Vector3.one * 110 / module.SurfaceSize; + cometTail.transform.localRotation = Quaternion.Euler(0, 180, 90); + /* + var alignment = cometTail.AddComponent(); + alignment.SetTargetBody(primary.GetAttachedOWRigidbody()); + alignment.SetValue("_usePhysicsToRotate", true); + */ + } + } +} diff --git a/NewHorizons/Body/HeightMapBuilder.cs b/NewHorizons/Body/HeightMapBuilder.cs index dad29cd1..c4f6c66e 100644 --- a/NewHorizons/Body/HeightMapBuilder.cs +++ b/NewHorizons/Body/HeightMapBuilder.cs @@ -1,5 +1,6 @@ using NewHorizons.Body.Geometry; using NewHorizons.External; +using OWML.Common; using System; using System.Collections.Generic; using System.Linq; @@ -14,13 +15,15 @@ namespace NewHorizons.Body { public static Shader PlanetShader; - public static void Make(GameObject go, HeightMapModule module) + public static void Make(GameObject go, HeightMapModule module, IModAssets assets) { Texture2D heightMap, textureMap; try { - heightMap = Main.Instance.CurrentAssets.GetTexture(module.HeightMap); - textureMap = Main.Instance.CurrentAssets.GetTexture(module.TextureMap); + if (module.HeightMap == null) heightMap = Texture2D.whiteTexture; + else heightMap = assets.GetTexture(module.HeightMap); + if (module.TextureMap == null) textureMap = Texture2D.whiteTexture; + else textureMap = assets.GetTexture(module.TextureMap); } catch(Exception e) { diff --git a/NewHorizons/Body/RingBuilder.cs b/NewHorizons/Body/RingBuilder.cs index 02b39a70..e5234a28 100644 --- a/NewHorizons/Body/RingBuilder.cs +++ b/NewHorizons/Body/RingBuilder.cs @@ -1,4 +1,5 @@ using NewHorizons.External; +using OWML.Common; using System; using System.Collections.Generic; using System.Linq; @@ -13,12 +14,12 @@ namespace NewHorizons.General { public static Shader RingShader; - public static void Make(GameObject body, RingModule ring) + public static void Make(GameObject body, RingModule ring, IModAssets assets) { Texture2D ringTexture; try { - ringTexture = Main.Instance.CurrentAssets.GetTexture(ring.Texture); + ringTexture = assets.GetTexture(ring.Texture); } catch (Exception e) { diff --git a/NewHorizons/Body/StarBuilder.cs b/NewHorizons/Body/StarBuilder.cs new file mode 100644 index 00000000..dbbae741 --- /dev/null +++ b/NewHorizons/Body/StarBuilder.cs @@ -0,0 +1,56 @@ +using NewHorizons.External; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.Body +{ + static class StarBuilder + { + public static void Make(GameObject body, Sector sector, StarModule starModule) + { + var sunGO = new GameObject("Star"); + sunGO.transform.parent = body.transform; + + var sunSurface = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Geometry_SUN/Surface"), sunGO.transform); + sunSurface.transform.localPosition = Vector3.zero; + sunSurface.transform.localScale = Vector3.one; + sunSurface.name = "Surface"; + + var sunLight = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight"), sunGO.transform); + sunSurface.transform.localPosition = Vector3.zero; + sunSurface.transform.localScale = Vector3.one; + sunLight.name = "StarLight"; + + var solarFlareEmitter = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SolarFlareEmitter"), sunGO.transform); + sunSurface.transform.localPosition = Vector3.zero; + sunSurface.transform.localScale = Vector3.one; + solarFlareEmitter.name = "SolarFlareEmitter"; + + var sunAudio = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Audio_SUN"), sunGO.transform); + sunSurface.transform.localPosition = Vector3.zero; + sunSurface.transform.localScale = Vector3.one; + sunAudio.transform.Find("SurfaceAudio_Sun").GetComponent().maxDistance = starModule.Size * 2f; + sunAudio.name = "Audio_Star"; + + var sunAtmosphere = GameObject.Instantiate(GameObject.Find("Sun_Body/Atmosphere_SUN"), sunGO.transform); + sunSurface.transform.localPosition = Vector3.zero; + sunSurface.transform.localScale = Vector3.one * 1.5f; + sunAtmosphere.name = "Atmosphere_Star"; + + var ambientLightGO = GameObject.Instantiate(GameObject.Find("Sun_Body/AmbientLight_SUN"), sunGO.transform); + ambientLightGO.transform.localPosition = Vector3.zero; + ambientLightGO.name = "AmbientLight_Star"; + + PlanetaryFogController fog = sunAtmosphere.transform.Find("FogSphere").GetComponent(); + TessellatedSphereRenderer surface = sunSurface.GetComponent(); + Light ambientLight = ambientLightGO.GetComponent(); + + sunGO.transform.localPosition = Vector3.zero; + sunGO.transform.localScale = starModule.Size * Vector3.one; + } + } +} diff --git a/NewHorizons/Body/SunBuilder.cs b/NewHorizons/Body/SunBuilder.cs deleted file mode 100644 index 79dab1bc..00000000 --- a/NewHorizons/Body/SunBuilder.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace NewHorizons.Body -{ - static class SunBuilder - { - public static void Make(GameObject body, Sector sector) - { - } - } -} diff --git a/NewHorizons/External/BaseModule.cs b/NewHorizons/External/BaseModule.cs index dbda9c03..dc31cfb9 100644 --- a/NewHorizons/External/BaseModule.cs +++ b/NewHorizons/External/BaseModule.cs @@ -12,11 +12,13 @@ namespace NewHorizons.External public bool HasMapMarker { get; set; } public bool HasAmbientLight { get; set; } public float SurfaceGravity { get; set; } + public string GravityFallOff { get; set; } = "linear"; public float SurfaceSize { get; set; } public float WaterSize { get; set; } public float GroundSize { get; set; } public float BlackHoleSize { get; set; } public float LavaSize { get; set; } + public bool HasCometTail { get; set; } public bool HasReferenceFrame { get; set; } = true; } } diff --git a/NewHorizons/External/IPlanetConfig.cs b/NewHorizons/External/IPlanetConfig.cs index e16215a6..df204a5a 100644 --- a/NewHorizons/External/IPlanetConfig.cs +++ b/NewHorizons/External/IPlanetConfig.cs @@ -6,6 +6,7 @@ namespace NewHorizons.External { string Name { get; } bool Destroy { get; } + int BuildPriority { get; } BaseModule Base {get;} AtmosphereModule Atmosphere { get; } OrbitModule Orbit { get; } @@ -13,6 +14,7 @@ namespace NewHorizons.External HeightMapModule HeightMap { get; } ProcGenModule ProcGen { get; } AsteroidBeltModule AsteroidBelt { get; } + StarModule Star { get; } SpawnModule Spawn { get; } } } diff --git a/NewHorizons/External/OrbitModule.cs b/NewHorizons/External/OrbitModule.cs index 35d6a7f2..869bf0cd 100644 --- a/NewHorizons/External/OrbitModule.cs +++ b/NewHorizons/External/OrbitModule.cs @@ -8,7 +8,7 @@ namespace NewHorizons.External { public class OrbitModule : Module { - public int SemiMajorAxis { get; set; } + public int SemiMajorAxis { get; set; } = 5000; public int Inclination { get; set; } public string PrimaryBody { get; set; } public bool IsMoon { get; set; } diff --git a/NewHorizons/External/PlanetConfig.cs b/NewHorizons/External/PlanetConfig.cs index 2ce82ac9..76dddcdc 100644 --- a/NewHorizons/External/PlanetConfig.cs +++ b/NewHorizons/External/PlanetConfig.cs @@ -8,6 +8,7 @@ namespace NewHorizons.External { public string Name { get; set; } public bool Destroy { get; set; } + public int BuildPriority { get; set; } = -1; public MVector3 SpawnPoint { get; set; } public BaseModule Base { get; set; } public AtmosphereModule Atmosphere { get; set; } @@ -16,6 +17,7 @@ namespace NewHorizons.External public HeightMapModule HeightMap { get; set; } public ProcGenModule ProcGen { get; set; } public AsteroidBeltModule AsteroidBelt { get; set; } + public StarModule Star { get; set; } public SpawnModule Spawn { get; set; } public PlanetConfig(Dictionary dict) diff --git a/NewHorizons/External/StarModule.cs b/NewHorizons/External/StarModule.cs new file mode 100644 index 00000000..23511f17 --- /dev/null +++ b/NewHorizons/External/StarModule.cs @@ -0,0 +1,15 @@ +using NewHorizons.Utility; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewHorizons.External +{ + public class StarModule : Module + { + public float Size { get; set; } + public MColor32 Tint { get; set; } + } +} diff --git a/NewHorizons/General/BaseBuilder.cs b/NewHorizons/General/BaseBuilder.cs index a6fb2fc1..275cb77d 100644 --- a/NewHorizons/General/BaseBuilder.cs +++ b/NewHorizons/General/BaseBuilder.cs @@ -1,4 +1,5 @@ using NewHorizons.External; +using NewHorizons.OrbitalPhysics; using NewHorizons.Utility; using OWML.Utils; using UnityEngine; @@ -19,12 +20,16 @@ namespace NewHorizons.General RB.interpolation = RigidbodyInterpolation.None; RB.collisionDetectionMode = CollisionDetectionMode.Discrete; + KinematicRigidbody KRB = body.AddComponent(); + KRB.centerOfMass = Vector3.zero; + OWRigidbody OWRB = body.AddComponent(); OWRB.SetValue("_kinematicSimulation", true); OWRB.SetValue("_autoGenerateCenterOfMass", true); OWRB.SetIsTargetable(true); OWRB.SetValue("_maintainOriginalCenterOfMass", true); OWRB.SetValue("_rigidbody", RB); + OWRB.SetValue("_kinematicRigidbody", KRB); DetectorBuilder.Make(body, primaryBody); @@ -36,11 +41,9 @@ namespace NewHorizons.General if (config.Orbit.IsTidallyLocked) { - // Just manually match it fr - /* - RotateToAstroObject RTAO = body.AddComponent(); - RTAO.SetValue("_astroObjectLock", primaryBody); - */ + var alignment = body.AddComponent(); + alignment.SetTargetBody(primaryBody.GetAttachedOWRigidbody()); + alignment.SetValue("_usePhysicsToRotate", true); } return new MTuple(AO, OWRB); diff --git a/NewHorizons/General/GravityBuilder.cs b/NewHorizons/General/GravityBuilder.cs index b894a5c9..2489c1c8 100644 --- a/NewHorizons/General/GravityBuilder.cs +++ b/NewHorizons/General/GravityBuilder.cs @@ -1,4 +1,5 @@ -using OWML.Utils; +using NewHorizons.External; +using OWML.Utils; using System.Reflection; using UnityEngine; using Logger = NewHorizons.Utility.Logger; @@ -7,7 +8,7 @@ namespace NewHorizons.General { static class GravityBuilder { - public static void Make(GameObject body, AstroObject ao, float surfaceAccel, float upperSurface, float lowerSurface) + public static void Make(GameObject body, AstroObject ao, float surfaceAccel, float upperSurface, float lowerSurface, string falloffType) { GameObject gravityGO = new GameObject("GravityWell"); gravityGO.transform.parent = body.transform; @@ -26,7 +27,7 @@ namespace NewHorizons.General GravityVolume GV = gravityGO.AddComponent(); GV.SetValue("_cutoffAcceleration", 0.1f); - GV.SetValue("_falloffType", GV.GetType().GetNestedType("FalloffType", BindingFlags.NonPublic).GetField("linear").GetValue(GV)); + GV.SetValue("_falloffType", GV.GetType().GetNestedType("FalloffType", BindingFlags.NonPublic).GetField(falloffType).GetValue(GV)); GV.SetValue("_alignmentRadius", 0.75f * upperSurface); GV.SetValue("_upperSurfaceRadius", lowerSurface); GV.SetValue("_lowerSurfaceRadius", 0); diff --git a/NewHorizons/General/InitialMotionBuilder.cs b/NewHorizons/General/InitialMotionBuilder.cs index 8b0b755f..c7b94d93 100644 --- a/NewHorizons/General/InitialMotionBuilder.cs +++ b/NewHorizons/General/InitialMotionBuilder.cs @@ -6,49 +6,54 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; +using NewHorizons.OrbitalPhysics; using Logger = NewHorizons.Utility.Logger; +using System.Reflection; +using NewHorizons.Utility; namespace NewHorizons.General { static class InitialMotionBuilder { - public static InitialMotion Make(GameObject body, AstroObject primaryBody, OWRigidbody OWRB, Vector3 positionVector, OrbitModule orbit) + public static InitialMotion Make(GameObject body, AstroObject primaryBody, OWRigidbody OWRB, OrbitModule orbit) { - InitialMotion IM = body.AddComponent(); - IM.SetPrimaryBody(primaryBody.GetAttachedOWRigidbody()); - IM.SetValue("_orbitAngle", orbit.Inclination); - IM.SetValue("_isGlobalAxis", false); - IM.SetValue("_initAngularSpeed", orbit.SiderealPeriod == 0 ? 0.02f : 1.0f / orbit.SiderealPeriod); - // Initial velocity - var distance = positionVector - primaryBody.transform.position; - var speed = Kepler.OrbitalHelper.VisViva(primaryBody.GetGravityVolume().GetStandardGravitationalParameter(), distance, orbit.SemiMajorAxis); - var direction = Kepler.OrbitalHelper.EllipseTangent(orbit.Eccentricity, orbit.SemiMajorAxis, orbit.Inclination, orbit.LongitudeOfAscendingNode, orbit.ArgumentOfPeriapsis, orbit.TrueAnomaly); - var velocity = speed * direction; - // Cancel out what the game does + /* + ParameterizedInitialMotion initialMotion = body.AddComponent(); + initialMotion.SetPrimary(primaryBody); + initialMotion.SetOrbitalParameters( + orbit.Eccentricity, + orbit.SemiMajorAxis, + orbit.Inclination, + orbit.LongitudeOfAscendingNode, + orbit.ArgumentOfPeriapsis, + orbit.TrueAnomaly); + initialMotion.SetValue("_initAngularSpeed", orbit.SiderealPeriod == 0 ? 0.02f : 1.0f / orbit.SiderealPeriod); + */ + + InitialMotion initialMotion = body.AddComponent(); + initialMotion.SetPrimaryBody(primaryBody.GetAttachedOWRigidbody()); + initialMotion.SetValue("_orbitAngle", orbit.Inclination); + initialMotion.SetValue("_isGlobalAxis", false); + initialMotion.SetValue("_initAngularSpeed", orbit.SiderealPeriod == 0 ? 0.02f : 1.0f / orbit.SiderealPeriod); if(orbit.Eccentricity != 0) { - var oldVelocity = Kepler.OrbitalHelper.CalculateOrbitVelocity(primaryBody.GetAttachedOWRigidbody(), distance, orbit.Inclination); - if (!float.IsNaN(oldVelocity.magnitude)) velocity -= oldVelocity; - else Logger.LogError($"The original orbital velocity for {body.name} was calculated to be NaN?"); - - var trueSpeed = velocity.magnitude; - var trueDirection = velocity.normalized; - - Logger.Log($"Setting initial motion {velocity.magnitude} in direction {velocity.normalized}"); - if (!float.IsNaN(trueSpeed) && trueDirection != Vector3.zero) - { - IM.SetValue("_initLinearDirection", velocity.normalized); - IM.SetValue("_initLinearSpeed", velocity.magnitude); - } - else Logger.LogError($"Could not set velocity ({speed}, {direction}) -> ({trueSpeed}, {trueDirection}) for {body.name}"); + // Calculate speed at apoapsis + var eccSpeed = OrbitalHelper.Visviva(primaryBody.GetGravityVolume().GetFalloffType(), + primaryBody.GetGravityVolume().GetStandardGravitationalParameter(), + orbit.SemiMajorAxis * (1 + orbit.Eccentricity), + orbit.SemiMajorAxis, + orbit.Eccentricity + ); + var circularSpeed = OWPhysics.CalculateOrbitVelocity(primaryBody.GetAttachedOWRigidbody(), OWRB).magnitude; + initialMotion.SetValue("_orbitImpulseScalar", eccSpeed / circularSpeed); } var rotationAxis = Quaternion.AngleAxis(orbit.AxialTilt + orbit.Inclination, Vector3.right) * Vector3.up; body.transform.rotation = Quaternion.FromToRotation(Vector3.up, rotationAxis); - return IM; + return initialMotion; } } } diff --git a/NewHorizons/General/OrbitlineBuilder.cs b/NewHorizons/General/OrbitlineBuilder.cs index 7596387e..56b9885f 100644 --- a/NewHorizons/General/OrbitlineBuilder.cs +++ b/NewHorizons/General/OrbitlineBuilder.cs @@ -1,4 +1,5 @@ using NewHorizons.External; +using NewHorizons.OrbitalPhysics; using NewHorizons.Utility; using OWML.Utils; using UnityEngine; @@ -22,12 +23,40 @@ namespace NewHorizons.General LR.useWorldSpace = false; LR.loop = false; - OrbitLine ol = orbit.Eccentricity != 0 ? orbitGO.AddComponent() : orbitGO.AddComponent(); - ol.SetValue("_astroObject", astroobject); - ol.SetValue("_fade", isMoon); - ol.SetValue("_lineWidth", 0.5f); - //ol.SetOrbitalParameters(orbit.Eccentricity, orbit.SemiMajorAxis, orbit.Inclination, orbit.LongitudeOfAscendingNode, orbit.ArgumentOfPeriapsis, orbit.TrueAnomaly); - typeof(OrbitLine).GetMethod("InitializeLineRenderer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Invoke(ol, new object[] { }); + if(orbit.Eccentricity == 0) + { + OrbitLine ol = orbitGO.AddComponent(); + ol.SetValue("_astroObject", astroobject); + ol.SetValue("_fade", isMoon); + ol.SetValue("_lineWidth", 0.5f); + typeof(OrbitLine).GetMethod("InitializeLineRenderer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Invoke(ol, new object[] { }); + } + else + { + OrbitLine ol = orbitGO.AddComponent(); + ol.SetValue("_astroObject", astroobject); + ol.SetValue("_fade", isMoon); + ol.SetValue("_lineWidth", 0.5f); + typeof(OrbitLine).GetMethod("InitializeLineRenderer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Invoke(ol, new object[] { }); + } + + /* + ParameterizedOrbitLine orbitLine = orbitGO.AddComponent(); + + orbitLine.SetValue("_astroObject", astroobject); + orbitLine.SetValue("_fade", isMoon); + orbitLine.SetValue("_lineWidth", 0.5f); + + orbitLine.SetOrbitalParameters( + orbit.Eccentricity, + orbit.SemiMajorAxis, + orbit.Inclination, + orbit.LongitudeOfAscendingNode, + orbit.ArgumentOfPeriapsis, + orbit.TrueAnomaly); + + typeof(OrbitLine).GetMethod("InitializeLineRenderer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Invoke(orbitLine, new object[] { }); + */ } } } diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index e7b369b5..c96b4c6e 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -2,6 +2,7 @@ using NewHorizons.Body; using NewHorizons.External; using NewHorizons.General; +using NewHorizons.OrbitalPhysics; using NewHorizons.Utility; using OWML.Common; using OWML.ModHelper; @@ -10,6 +11,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using UnityEngine; using UnityEngine.SceneManagement; using Logger = NewHorizons.Utility.Logger; @@ -25,8 +27,6 @@ namespace NewHorizons public static List BodyList = new List(); public static List AdditionalBodies = new List(); - public IModAssets CurrentAssets { get; private set; } - public override object GetApi() { return new NewHorizonsApi(); @@ -50,7 +50,11 @@ namespace NewHorizons { Logger.LogWarning("Couldn't find planets folder"); } + } + void Destroy() + { + SceneManager.sceneLoaded -= OnSceneLoaded; } void OnSceneLoaded(Scene scene, LoadSceneMode mode) @@ -65,8 +69,11 @@ namespace NewHorizons AstroObjectLocator.AddAstroObject(ao); } - // Should make moons come after planets - BodyList = BodyList.OrderBy(b => (b.Config?.Orbit?.IsMoon)).ToList(); + // Stars then planets then moons + BodyList = BodyList.OrderBy(b => + (b.Config.BuildPriority != -1 ? b.Config.BuildPriority : (b.Config.Star != null) ? 0 : + (b.Config.Orbit.IsMoon ? 2 : 1) + )).ToList(); while(BodyList.Count != 0) { @@ -132,7 +139,6 @@ namespace NewHorizons public void LoadConfigs(IModBehaviour mod) { - CurrentAssets = mod.ModHelper.Assets; var folder = mod.ModHelper.Manifest.ModFolderPath; foreach (var file in Directory.GetFiles(folder + @"planets\")) { @@ -140,11 +146,11 @@ namespace NewHorizons { var config = mod.ModHelper.Storage.Load(file.Replace(folder, "")); Logger.Log($"Loaded {config.Name}"); - BodyList.Add(new NewHorizonsBody(config)); + BodyList.Add(new NewHorizonsBody(config, mod.ModHelper.Assets)); } catch (Exception e) { - Logger.LogError($"Couldn't load {file}: {e.Message}, {e.StackTrace}"); + Logger.LogError($"Couldn't load {file}: {e.Message}, is your Json formatted correctly?"); } } } @@ -182,19 +188,41 @@ namespace NewHorizons float sphereOfInfluence = Mathf.Max(atmoSize, body.Config.Base.SurfaceSize * 2f); // Get initial position but set it at the end - //var a = body.Config.Orbit.SemiMajorAxis; - //var omega = Mathf.Deg2Rad * body.Config.Orbit.LongitudeOfAscendingNode; - //var positionVector = primaryBody.gameObject.transform.position + new Vector3(a * Mathf.Sin(omega), 0, a * Mathf.Cos(omega)); - var positionVector = Kepler.OrbitalHelper.CartesianFromOrbitalElements(body.Config.Orbit.Eccentricity, body.Config.Orbit.SemiMajorAxis, body.Config.Orbit.Inclination, - body.Config.Orbit.LongitudeOfAscendingNode, body.Config.Orbit.ArgumentOfPeriapsis, body.Config.Orbit.TrueAnomaly); + var falloffType = primaryBody.GetGravityVolume().GetFalloffType(); + + /* + var positionVector = OrbitalHelper.CartesianStateVectorsFromTrueAnomaly( + 0f, + body.Config.Orbit.Eccentricity, + body.Config.Orbit.SemiMajorAxis, + body.Config.Orbit.Inclination, + body.Config.Orbit.LongitudeOfAscendingNode, + body.Config.Orbit.ArgumentOfPeriapsis, + body.Config.Orbit.TrueAnomaly, + falloffType).Position; + */ + + var rot = Quaternion.AngleAxis(body.Config.Orbit.LongitudeOfAscendingNode + body.Config.Orbit.TrueAnomaly + body.Config.Orbit.ArgumentOfPeriapsis + 180f, Vector3.up); + + // For now, eccentric orbits gotta start at apoapsis and cant be inclined + if(body.Config.Orbit.Eccentricity != 0) + { + rot = Quaternion.AngleAxis(body.Config.Orbit.LongitudeOfAscendingNode + body.Config.Orbit.ArgumentOfPeriapsis + 180f, Vector3.up); + body.Config.Orbit.Inclination = 0; + } + + + var incAxis = Quaternion.AngleAxis(body.Config.Orbit.LongitudeOfAscendingNode, Vector3.up) * Vector3.left; + var incRot = Quaternion.AngleAxis(body.Config.Orbit.Inclination, incAxis); + + var positionVector = rot * incRot * Vector3.left * body.Config.Orbit.SemiMajorAxis * (1 + body.Config.Orbit.Eccentricity); var outputTuple = BaseBuilder.Make(go, primaryBody, positionVector, body.Config); var ao = (AstroObject)outputTuple.Items[0]; var rb = (OWRigidbody)outputTuple.Items[1]; if (body.Config.Base.SurfaceGravity != 0) - GravityBuilder.Make(go, ao, body.Config.Base.SurfaceGravity, sphereOfInfluence, body.Config.Base.SurfaceSize); - else Logger.Log("No gravity?"); + GravityBuilder.Make(go, ao, body.Config.Base.SurfaceGravity, sphereOfInfluence, body.Config.Base.SurfaceSize, body.Config.Base.GravityFallOff); if(body.Config.Base.HasReferenceFrame) RFVolumeBuilder.Make(go, rb, sphereOfInfluence); @@ -202,17 +230,26 @@ namespace NewHorizons if (body.Config.Base.HasMapMarker) MarkerBuilder.Make(go, body.Config.Name, body.Config.Orbit.IsMoon); + if (body.Config.Base.HasAmbientLight) + AmbientLightBuilder.Make(go, sphereOfInfluence); + var sector = MakeSector.Make(go, rb, sphereOfInfluence); VolumesBuilder.Make(go, body.Config.Base.SurfaceSize, sphereOfInfluence); if (body.Config.HeightMap != null) - HeightMapBuilder.Make(go, body.Config.HeightMap); + HeightMapBuilder.Make(go, body.Config.HeightMap, body.Assets); if (body.Config.ProcGen != null) ProcGenBuilder.Make(go, body.Config.ProcGen); - InitialMotionBuilder.Make(go, primaryBody, rb, positionVector, body.Config.Orbit); + if (body.Config.Base.BlackHoleSize != 0) + BlackHoleBuilder.Make(go, body.Config.Base, sector); + + /* + if (body.Config.Star != null) + StarBuilder.Make(go, sector, body.Config.Star); + */ // Do stuff that's shared between generating new planets and updating old ones go = SharedGenerateBody(body, go, sector, rb); @@ -227,6 +264,9 @@ namespace NewHorizons go.transform.parent = Locator.GetRootTransform(); go.transform.position = positionVector + primaryBody.transform.position; + // Have to do this after setting position + InitialMotionBuilder.Make(go, primaryBody, rb, body.Config.Orbit); + // Spawning on other planets is a bit hacky so we do it last if (body.Config.Spawn != null) { @@ -243,10 +283,13 @@ namespace NewHorizons private static GameObject SharedGenerateBody(NewHorizonsBody body, GameObject go, Sector sector, OWRigidbody rb) { if (body.Config.Ring != null) - RingBuilder.Make(go, body.Config.Ring); + RingBuilder.Make(go, body.Config.Ring, body.Assets); if (body.Config.AsteroidBelt != null) - AsteroidBeltBuilder.Make(body.Config.Name, body.Config.AsteroidBelt); + AsteroidBeltBuilder.Make(body.Config.Name, body.Config.AsteroidBelt, body.Assets); + + if (body.Config.Base.HasCometTail) + CometTailBuilder.Make(go, body.Config.Base, go.GetComponent().GetPrimaryBody()); if(body.Config.Base != null) { @@ -262,7 +305,7 @@ namespace NewHorizons if (body.Config.Atmosphere.Cloud != null) { - CloudsBuilder.Make(go, sector, body.Config.Atmosphere); + CloudsBuilder.Make(go, sector, body.Config.Atmosphere, body.Assets); SunOverrideBuilder.Make(go, sector, body.Config.Base.SurfaceSize, body.Config.Atmosphere); } @@ -281,12 +324,18 @@ namespace NewHorizons public class NewHorizonsApi { + [Obsolete("Create(Dictionary config) is deprecated, please use Create(Dictionary config, IModBehaviour mod) instead")] public void Create(Dictionary config) { - Logger.Log("Recieved API request to create planet " + (string)config["Name"] + " at position " + (Vector3)config["Position"], Logger.LogType.Log); + Create(config, null); + } + + public void Create(Dictionary config, IModBehaviour mod) + { + Logger.Log("Recieved API request to create planet " + (string)config["Name"], Logger.LogType.Log); var planetConfig = new PlanetConfig(config); - var body = new NewHorizonsBody(planetConfig); + var body = new NewHorizonsBody(planetConfig, mod != null ? mod.ModHelper.Assets : Main.Instance.ModHelper.Assets); Main.BodyList.Add(body); } diff --git a/NewHorizons/NewHorizons.csproj b/NewHorizons/NewHorizons.csproj index 65b42e33..95b34c81 100644 --- a/NewHorizons/NewHorizons.csproj +++ b/NewHorizons/NewHorizons.csproj @@ -231,12 +231,13 @@ + - + @@ -246,6 +247,7 @@ + @@ -259,7 +261,9 @@ - + + + @@ -278,7 +282,7 @@ - + diff --git a/NewHorizons/OrbitalPhysics/CartesianStateVectors.cs b/NewHorizons/OrbitalPhysics/CartesianStateVectors.cs new file mode 100644 index 00000000..7442bbba --- /dev/null +++ b/NewHorizons/OrbitalPhysics/CartesianStateVectors.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.OrbitalPhysics +{ + public class CartesianStateVectors + { + public Vector3 Position { get; set; } + public Vector3 Velocity { get; set; } + + public CartesianStateVectors() + { + Position = Vector3.zero; + Velocity = Vector3.zero; + } + + public CartesianStateVectors(Vector3 pos, Vector3 vel) + { + Position = pos; + Velocity = vel; + } + } +} diff --git a/NewHorizons/OrbitalPhysics/OrbitalHelper.cs b/NewHorizons/OrbitalPhysics/OrbitalHelper.cs new file mode 100644 index 00000000..a0b1e0a9 --- /dev/null +++ b/NewHorizons/OrbitalPhysics/OrbitalHelper.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using NewHorizons.Utility; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.OrbitalPhysics +{ + public static class OrbitalHelper + { + public enum FalloffType + { + inverseSquared, + linear + } + + public static CartesianStateVectors CartesianStateVectorsFromTrueAnomaly(float standardGraviationalParameter, float eccentricity, float semiMajorAxis, float inclination, + float longitudeOfAscendingNode, float argumentOfPeriapsis, float trueAnomaly, FalloffType falloffType) + { + var nu = Mathf.Deg2Rad * trueAnomaly; + var E = Mathf.Atan2(Mathf.Sqrt(1 - eccentricity * eccentricity) * Mathf.Sin(nu), (eccentricity + Mathf.Cos(nu))); + + return CartesianStateVectorsFromOrbitalElements(standardGraviationalParameter, eccentricity, semiMajorAxis, inclination, longitudeOfAscendingNode, argumentOfPeriapsis, E, nu, falloffType); + } + + public static CartesianStateVectors CartesianStateVectorsFromEccentricAnomaly(float standardGraviationalParameter, float eccentricity, float semiMajorAxis, float inclination, + float longitudeOfAscendingNode, float argumentOfPeriapsis, float eccentricAnomaly, FalloffType falloffType) + { + var E = Mathf.Deg2Rad * eccentricAnomaly; + var nu = 2f * Mathf.Atan2(Mathf.Sqrt(1 + eccentricity) * Mathf.Sin(E)/2f, Mathf.Sqrt(1 - eccentricity) * Mathf.Cos(E) / 2f); + + return CartesianStateVectorsFromOrbitalElements(standardGraviationalParameter, eccentricity, semiMajorAxis, inclination, longitudeOfAscendingNode, argumentOfPeriapsis, E, nu, falloffType); + } + + private static CartesianStateVectors CartesianStateVectorsFromOrbitalElements(float standardGraviationalParameter, float eccentricity, float semiMajorAxis, float inclination, + float longitudeOfAscendingNode, float argumentOfPeriapsis, float E, float nu, FalloffType falloffType) + { + //Keplerian Orbit Elements −→ Cartesian State Vectors (Memorandum #1) Rene Schwarz + + if (semiMajorAxis == 0) return new CartesianStateVectors(); + + // POS + var r = semiMajorAxis * (1 - eccentricity * Mathf.Cos(E)); + + Vector3 position = r * new Vector3(Mathf.Cos(nu), 0, Mathf.Sin(nu)); + + // VEL + var speed = Visviva(falloffType, standardGraviationalParameter, position.magnitude, semiMajorAxis, eccentricity); + Vector3 velocity = speed * (new Vector3(-Mathf.Sin(E), 0, Mathf.Sqrt(1 - (eccentricity * eccentricity)) * Mathf.Cos(E))).normalized; + + Quaternion periapsisRot = Quaternion.AngleAxis(Mathf.Deg2Rad * argumentOfPeriapsis, Vector3.up); + var inclinationAxis = Quaternion.AngleAxis(Mathf.Repeat(Mathf.Deg2Rad * longitudeOfAscendingNode, 2f * Mathf.PI), Vector3.up) * Vector3.left; + Quaternion inclinationRot = Quaternion.AngleAxis(inclination, inclinationAxis); + + position = periapsisRot * inclinationRot * position; + velocity = periapsisRot * inclinationRot * velocity; + + return new CartesianStateVectors(position, velocity); + } + + public static float Visviva(FalloffType falloffType, float standardGravitationalParameter, float dist, float semiMajorAxis, float eccentricity) + { + switch(falloffType) + { + case FalloffType.inverseSquared: + return Mathf.Sqrt(standardGravitationalParameter * (2f / dist - 1f / semiMajorAxis)); + case FalloffType.linear: + if (eccentricity == 0f) return Mathf.Sqrt(standardGravitationalParameter); + + var ra = semiMajorAxis * (1 + eccentricity); + var rp = semiMajorAxis * (1 - eccentricity); + + var kineticEneregyAtApoapsis = standardGravitationalParameter * Mathf.Log(ra / rp) * (rp * rp) / ((rp * rp) - (ra * ra)); + var gravitationalEnergy = standardGravitationalParameter * Mathf.Log(dist / ra); + var v = Mathf.Sqrt(2 * (kineticEneregyAtApoapsis + gravitationalEnergy)); + + return v; + } + Logger.LogError($"Invalid falloffType {falloffType}"); + return 0f; + } + + private static Vector3 RotateToOrbitalPlane(Vector3 vector, float longitudeOfAscendingNode, float argumentOfPeriapsis, float inclination) + { + vector = Quaternion.AngleAxis(Mathf.Deg2Rad * argumentOfPeriapsis, Vector3.up) * vector; + + var inclinationAxis = Quaternion.AngleAxis(Mathf.Repeat(Mathf.Deg2Rad * longitudeOfAscendingNode, 2f * Mathf.PI), Vector3.up) * new Vector3(1, 0, 0); + vector = Quaternion.AngleAxis(Mathf.Repeat(Mathf.Deg2Rad * inclination, 2f * Mathf.PI), inclinationAxis) * vector; + + return vector; + } + } +} diff --git a/NewHorizons/OrbitalPhysics/ParameterizedInitialMotion.cs b/NewHorizons/OrbitalPhysics/ParameterizedInitialMotion.cs new file mode 100644 index 00000000..197300ea --- /dev/null +++ b/NewHorizons/OrbitalPhysics/ParameterizedInitialMotion.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using NewHorizons.Utility; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.OrbitalPhysics +{ + public class ParameterizedInitialMotion : InitialMotion + { + private new void Awake() + { + _rotationAxis = base.transform.TransformDirection(_rotationAxis); + _satelliteBody = this.GetRequiredComponent(); + } + + private new void Start() + { + _satelliteBody.UpdateCenterOfMass(); + _satelliteBody.AddVelocityChange(GetInitVelocity()); + _satelliteBody.AddAngularVelocityChange(GetInitAngularVelocity()); + } + + public new Vector2 GetOrbitEllipseSemiAxes() + { + var x = _semiMajorAxis; + var y = _semiMajorAxis * Mathf.Sqrt(1 - _eccentricity * _eccentricity); + + return new Vector2(x, y); + } + + public new Vector3 GetInitAngularVelocity() + { + return _rotationAxis.normalized * _initAngularSpeed; + } + + public new OWRigidbody GetPrimaryBody() + { + return _primary.GetAttachedOWRigidbody(); + } + + public new void SetPrimaryBody(OWRigidbody primaryBody) + { + _primary = primaryBody.gameObject.GetComponent(); + } + + public new Vector3 GetInitVelocity() + { + if(_initVelocityDirty) + { + var state = OrbitalHelper.CartesianStateVectorsFromTrueAnomaly( + _primary.GetGravityVolume().GetStandardGravitationalParameter(), + _eccentricity, + _semiMajorAxis, + _inclination, + _longitudeOfAscendingNode, + _argumentOfPeriapsis, + _trueAnomaly, + _primary.GetGravityVolume().GetFalloffType() + ); + _initVelocity = state.Velocity; + + if(_primary?.GetComponent() != null) + { + var primaryVel = _primary.GetComponent().GetInitVelocity(); + Logger.Log($"{primaryVel}"); + _initVelocity += primaryVel; + } + + _initVelocityDirty = false; + } + return _initVelocity; + } + + public void SetOrbitalParameters(float eccentricity, float semiMajorAxis, float inclination, float longitudeOfAscendingNode, float argumentOfPeriapsis, float trueAnomaly) + { + _eccentricity = eccentricity; + _semiMajorAxis = semiMajorAxis; + _inclination = inclination; + _longitudeOfAscendingNode = longitudeOfAscendingNode; + _argumentOfPeriapsis = argumentOfPeriapsis; + _trueAnomaly = trueAnomaly; + } + + public void SetPrimary(AstroObject primary) + { + _primary = primary; + } + + private float _eccentricity; + private float _semiMajorAxis; + private float _inclination; + private float _longitudeOfAscendingNode; + private float _argumentOfPeriapsis; + private float _trueAnomaly; + + private AstroObject _primary; + + private bool _initVelocityDirty = true; + private Vector3 _initVelocity; + private Vector3 _rotationAxis = Vector3.up; + + private float _initAngularSpeed; + + private OWRigidbody _satelliteBody; + } +} diff --git a/NewHorizons/Physics/ParameterizedOrbitLine.cs b/NewHorizons/OrbitalPhysics/ParameterizedOrbitLine.cs similarity index 64% rename from NewHorizons/Physics/ParameterizedOrbitLine.cs rename to NewHorizons/OrbitalPhysics/ParameterizedOrbitLine.cs index 4df18206..bfd00a14 100644 --- a/NewHorizons/Physics/ParameterizedOrbitLine.cs +++ b/NewHorizons/OrbitalPhysics/ParameterizedOrbitLine.cs @@ -1,12 +1,15 @@ -using NewHorizons.Kepler; +using OWML.Utils; using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; using UnityEngine; +using NewHorizons.Utility; +using Logger = NewHorizons.Utility.Logger; -namespace NewHorizons.Utility +namespace NewHorizons.OrbitalPhysics { public class ParameterizedOrbitLine : OrbitLine { @@ -17,20 +20,20 @@ namespace NewHorizons.Utility protected override void OnValidate() { - if (this._numVerts < 0 || this._numVerts > 4096) + if (_numVerts < 0 || _numVerts > 4096) { - this._numVerts = Mathf.Clamp(this._numVerts, 0, 4096); + _numVerts = Mathf.Clamp(this._numVerts, 0, 4096); } - if (base.GetComponent().positionCount != this._numVerts) + if (base.GetComponent().positionCount != _numVerts) { - this.InitializeLineRenderer(); + InitializeLineRenderer(); } } protected override void Start() { base.Start(); - this._verts = new Vector3[this._numVerts]; + _verts = new Vector3[_numVerts]; base.enabled = false; } @@ -43,23 +46,17 @@ namespace NewHorizons.Utility _argumentOfPeriapsis = argumentOfPeriapsis; _trueAnomaly = trueAnomaly; - _initialMotion = (this._astroObject != null) ? this._astroObject.GetComponent() : null; - _primary = (this._astroObject != null) ? this._astroObject.GetPrimaryBody() : null; + _initialMotion = (_astroObject != null) ? _astroObject.GetComponent() : null; + _primary = (_astroObject != null) ? _astroObject.GetPrimaryBody() : null; + _falloffType = _primary.GetGravityVolume().GetFalloffType(); if (_initialMotion && _primary) { - var periapsisAngle = longitudeOfAscendingNode + argumentOfPeriapsis; - var apoapsisAngle = periapsisAngle + 90f; + _vSemiMajorAxis = OrbitalHelper.CartesianStateVectorsFromEccentricAnomaly(0f, _eccentricity, _semiMajorAxis, _inclination, _longitudeOfAscendingNode, _argumentOfPeriapsis, 0, _falloffType).Position; + _vSemiMinorAxis = OrbitalHelper.CartesianStateVectorsFromEccentricAnomaly(0f, _eccentricity, _semiMajorAxis, _inclination, _longitudeOfAscendingNode, _argumentOfPeriapsis, 90, _falloffType).Position; + _upAxisDir = Vector3.Cross(_vSemiMajorAxis, _vSemiMinorAxis); - _vSemiMinorAxis = OrbitalHelper.CartesianFromOrbitalElements(_eccentricity, _semiMajorAxis, _inclination, _longitudeOfAscendingNode, _argumentOfPeriapsis, periapsisAngle); - _vSemiMajorAxis = OrbitalHelper.CartesianFromOrbitalElements(_eccentricity, _semiMajorAxis, _inclination, _longitudeOfAscendingNode, _argumentOfPeriapsis, apoapsisAngle); - - Vector3 rhs = this._astroObject.transform.position - _primary.transform.position; - Vector3 initVelocity = _initialMotion.GetInitVelocity(); - Vector3 vector = Vector3.Cross(initVelocity, rhs); - this._upAxisDir = vector.normalized; var semiMinorAxis = semiMajorAxis * Mathf.Sqrt(1 - (eccentricity * eccentricity)); - _fociDistance = Mathf.Sqrt((semiMajorAxis * semiMajorAxis) - (semiMinorAxis * semiMinorAxis)); base.enabled = true; @@ -72,18 +69,21 @@ namespace NewHorizons.Utility protected override void Update() { - Vector3 vector = _primary.transform.position + _vSemiMajorAxis * _fociDistance; - float num = CalcProjectedAngleToCenter(vector, _vSemiMajorAxis, _vSemiMinorAxis, _astroObject.transform.position); + Vector3 vector = _primary.transform.position + _vSemiMajorAxis.normalized * _fociDistance; + float nu = CalcProjectedAngleToCenter(vector, _vSemiMajorAxis, _vSemiMinorAxis, _astroObject.transform.position); + for (int i = 0; i < _numVerts; i++) { - var angle = ((float)i / (float)(_numVerts - 1)) * 360f - Mathf.Rad2Deg * num; - _verts[i] = OrbitalHelper.CartesianFromOrbitalElements(_eccentricity, _semiMajorAxis, _inclination, _longitudeOfAscendingNode, _argumentOfPeriapsis, angle); + var angle = Mathf.Rad2Deg * _trueAnomaly + (Mathf.Rad2Deg * nu) - ((float)i / (float)(_numVerts - 1)) * 360f; + _verts[i] = OrbitalHelper.CartesianStateVectorsFromTrueAnomaly(0f, _eccentricity, _semiMajorAxis, _inclination, _longitudeOfAscendingNode, _argumentOfPeriapsis, angle, _falloffType).Position; } _lineRenderer.SetPositions(_verts); // From EllipticalOrbitLine base.transform.position = vector; - base.transform.rotation = Quaternion.LookRotation(Quaternion.AngleAxis(-48f, Vector3.up) * _vSemiMajorAxis, -_upAxisDir); + base.transform.rotation = Quaternion.AngleAxis(0f, Vector3.up); + //base.transform.rotation = Quaternion.AngleAxis(_trueAnomaly + _longitudeOfAscendingNode + _argumentOfPeriapsis, Vector3.up); + float num2 = DistanceToEllipticalOrbitLine(vector, _vSemiMajorAxis, _vSemiMinorAxis, _upAxisDir, Locator.GetActiveCamera().transform.position); float widthMultiplier = Mathf.Min(num2 * (_lineWidth / 1000f), _maxLineWidth); float num3 = _fade ? (1f - Mathf.Clamp01((num2 - _fadeStartDist) / (_fadeEndDist - _fadeStartDist))) : 1f; @@ -121,5 +121,6 @@ namespace NewHorizons.Utility private Vector3[] _verts; private InitialMotion _initialMotion; private AstroObject _primary; + private OrbitalHelper.FalloffType _falloffType; } } diff --git a/NewHorizons/Physics/OrbitalHelper.cs b/NewHorizons/Physics/OrbitalHelper.cs deleted file mode 100644 index 3643b259..00000000 --- a/NewHorizons/Physics/OrbitalHelper.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace NewHorizons.Kepler -{ - public static class OrbitalHelper - { - public static Vector3 CartesianFromOrbitalElements(float e, float a, float inclination, float ascending, float periapsis, float angle) - { - float b = a * Mathf.Sqrt(1f - (e * e)); - - // Get point on ellipse - // Angle starts at apoapsis, shift by 90 degrees to get to periapsis and add true anomaly - float ellipseAngle = Mathf.Repeat(Mathf.PI / 4f + Mathf.Deg2Rad * angle, 2 * Mathf.PI); - - float tAngle = Mathf.Tan(ellipseAngle); - float x = (a * b) / Mathf.Sqrt(b * b + a * a * tAngle * tAngle); - if (ellipseAngle > Mathf.PI / 2f && ellipseAngle < 3f * Mathf.PI / 2f) x *= -1; - float y = x * tAngle; - - // Fix limits - if (float.IsNaN(x)) { - x = 0; - if (angle < 180) y = b; - else y = -b; - } - - var position = new Vector3(x, 0, y); - - return RotateToOrbitalPlane(position, ascending, periapsis, inclination); - } - - public static float VisViva(float standardGravitationalParameter, Vector3 relativePosition, float semiMajorAxis) - { - return Mathf.Sqrt(standardGravitationalParameter * (2f / relativePosition.magnitude - 1f / semiMajorAxis)); - } - - public static Vector3 EllipseTangent(float e, float a, float inclination, float ascending, float periapsis, float angle) - { - float b = a * Mathf.Sqrt(1f - (e * e)); - float ellipseAngle = Mathf.Repeat(Mathf.PI / 4f + Mathf.Deg2Rad * angle, 2 * Mathf.PI); - - var tan = Mathf.Tan(ellipseAngle); - - float x = (a * b) / Mathf.Sqrt(b * b + a * a * tan * tan); - - var sec2 = 1f / (tan * tan); - float dxdt = -a * a * a * b * sec2 * tan / Mathf.Pow(a * a * tan * tan + b * b, 3f / 2f); - - if (ellipseAngle > Mathf.PI / 2f && ellipseAngle < 3f * Mathf.PI / 2f) - { - dxdt *= -1; - x *= -1; - } - - // Product rule - var dydt = sec2 * x + dxdt * tan; - - // Fix limits - if(float.IsNaN(dxdt)) - { - dydt = 0; - if (angle == Mathf.PI / 2f) dxdt = -1; - else dxdt = 1; - } - - var vector = new Vector3(dxdt, 0, dydt).normalized; - return RotateToOrbitalPlane(vector, ascending, periapsis, inclination); - } - - private static Vector3 RotateToOrbitalPlane(Vector3 vector, float ascending, float periapsis, float inclination) - { - // Periapsis is at 90 degrees - vector = Quaternion.AngleAxis(Mathf.Deg2Rad * (ascending + periapsis) + Mathf.PI / 2f, Vector3.up) * vector; - - var inclinationAxis = Quaternion.AngleAxis(Mathf.Repeat(Mathf.Deg2Rad * ascending, 2f * Mathf.PI), Vector3.up) * new Vector3(1, 0, 0); - vector = Quaternion.AngleAxis(Mathf.Repeat(Mathf.Deg2Rad * inclination, 2f * Mathf.PI), inclinationAxis) * vector; - - return vector; - } - - public static Vector3 CalculateOrbitVelocity(OWRigidbody primaryBody, Vector3 relativePosition, float inclination = 0f) - { - GravityVolume attachedGravityVolume = primaryBody.GetAttachedGravityVolume(); - if (attachedGravityVolume == null) - { - return Vector3.zero; - } - Vector3 vector2 = Vector3.Cross(relativePosition, Vector3.up).normalized; - vector2 = Quaternion.AngleAxis(inclination, relativePosition) * vector2; - float d = Mathf.Sqrt(attachedGravityVolume.CalculateForceAccelerationAtPoint(relativePosition + primaryBody.transform.position).magnitude * relativePosition.magnitude); - return vector2 * d; - } - } -} diff --git a/NewHorizons/Utility/ImageUtilities.cs b/NewHorizons/Utility/ImageUtilities.cs index cd376b5f..2a885efe 100644 --- a/NewHorizons/Utility/ImageUtilities.cs +++ b/NewHorizons/Utility/ImageUtilities.cs @@ -26,5 +26,80 @@ namespace NewHorizons.Utility tex.LoadRawTextureData(File.ReadAllBytes(filepath)); return tex; } + + public static Texture2D ClearTexture(int width, int height) + { + var tex = (new Texture2D(1, 1, TextureFormat.ARGB32, false)); + Color fillColor = Color.clear; + Color[] fillPixels = new Color[tex.width * tex.height]; + for(int i = 0; i < fillPixels.Length; i++) + { + fillPixels[i] = fillColor; + } + tex.SetPixels(fillPixels); + tex.Apply(); + return tex; + } + + public static Texture2D CanvasScaled(Texture2D src, int width, int height) + { + var tex = (new Texture2D(width, height, TextureFormat.ARGB32, false)); + Color[] fillPixels = new Color[tex.width * tex.height]; + for (int i = 0; i < tex.width; i++) + { + for(int j = 0; j < tex.height; j++) + { + fillPixels[i + j * tex.width] = src.GetPixel(i, j); + } + } + tex.SetPixels(fillPixels); + tex.Apply(); + return tex; + } + + // Thank you PETERSVP + public static Texture2D Scaled(Texture2D src, int width, int height, FilterMode mode = FilterMode.Trilinear) + { + Rect texR = new Rect(0, 0, width, height); + _gpu_scale(src, width, height, mode); + + //Get rendered data back to a new texture + Texture2D result = new Texture2D(width, height, TextureFormat.ARGB32, true); + result.Resize(width, height); + result.ReadPixels(texR, 0, 0, true); + return result; + } + + public static void Scale(Texture2D tex, int width, int height, FilterMode mode = FilterMode.Trilinear) + { + Rect texR = new Rect(0, 0, width, height); + _gpu_scale(tex, width, height, mode); + + // Update new texture + tex.Resize(width, height); + tex.ReadPixels(texR, 0, 0, true); + tex.Apply(true); //Remove this if you hate us applying textures for you :) + } + + // Internal unility that renders the source texture into the RTT - the scaling method itself. + static void _gpu_scale(Texture2D src, int width, int height, FilterMode fmode) + { + //We need the source texture in VRAM because we render with it + src.filterMode = fmode; + src.Apply(true); + + //Using RTT for best quality and performance. Thanks, Unity 5 + RenderTexture rtt = new RenderTexture(width, height, 32); + + //Set the RTT in order to render to it + Graphics.SetRenderTarget(rtt); + + //Setup 2D matrix in range 0..1, so nobody needs to care about sized + GL.LoadPixelMatrix(0, 1, 1, 0); + + //Then clear & draw the texture to fill the entire RTT. + GL.Clear(true, true, new Color(0, 0, 0, 0)); + Graphics.DrawTexture(new Rect(0, 0, 1, 1), src); + } } } diff --git a/NewHorizons/Utility/NewHorizonBody.cs b/NewHorizons/Utility/NewHorizonBody.cs index 2c6549fc..39bb008b 100644 --- a/NewHorizons/Utility/NewHorizonBody.cs +++ b/NewHorizons/Utility/NewHorizonBody.cs @@ -1,16 +1,19 @@ using NewHorizons.External; +using OWML.Common; using UnityEngine; namespace NewHorizons.Utility { public class NewHorizonsBody { - public NewHorizonsBody(IPlanetConfig config) + public NewHorizonsBody(IPlanetConfig config, IModAssets assets) { Config = config; + Assets = assets; } public IPlanetConfig Config; + public IModAssets Assets; public GameObject Object; } diff --git a/NewHorizons/Utility/NewHorizonExtensions.cs b/NewHorizons/Utility/NewHorizonExtensions.cs index b68ee91e..e8a59d35 100644 --- a/NewHorizons/Utility/NewHorizonExtensions.cs +++ b/NewHorizons/Utility/NewHorizonExtensions.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using NewHorizons.OrbitalPhysics; +using System.Collections.Generic; +using System.Reflection; using UnityEngine; namespace NewHorizons.Utility @@ -14,5 +16,12 @@ namespace NewHorizons.Utility { return (T)dict[settingName]; } + + public static OrbitalHelper.FalloffType GetFalloffType(this GravityVolume gv) + { + var falloffTypeString = typeof(GravityVolume).GetField("_falloffType", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(gv).ToString(); + var falloffType = falloffTypeString.Equals("linear") ? OrbitalHelper.FalloffType.linear : OrbitalHelper.FalloffType.inverseSquared; + return falloffType; + } } } diff --git a/NewHorizons/Utility/Patches.cs b/NewHorizons/Utility/Patches.cs index 92af0d52..32cfcbd9 100644 --- a/NewHorizons/Utility/Patches.cs +++ b/NewHorizons/Utility/Patches.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using UnityEngine; namespace NewHorizons.Utility { @@ -12,17 +13,33 @@ namespace NewHorizons.Utility public static void Apply() { Main.Instance.ModHelper.HarmonyHelper.AddPrefix("GetHUDDisplayName", typeof(Patches), nameof(Patches.GetHUDDisplayName)); + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("CheckShipOutsideSolarSystem", typeof(Patches), nameof(Patches.CheckShipOutersideSolarSystem)); + Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Start", typeof(Patches), nameof(Patches.OnEllipticOrbitLineStart)); } public static bool GetHUDDisplayName(ReferenceFrame __instance, ref string __result) { var ao = __instance.GetAstroObject(); - if (ao.GetAstroObjectName() == AstroObject.Name.CustomString) + if (ao != null && ao.GetAstroObjectName() == AstroObject.Name.CustomString) { __result = ao.GetCustomName(); return false; } return true; } + + public static bool CheckShipOutersideSolarSystem(PlayerState __instance, bool __result) + { + __result = false; + return false; + } + + public static void OnEllipticOrbitLineStart(EllipticOrbitLine __instance, ref Vector3 ____upAxisDir, AstroObject ____astroObject) + { + if (____astroObject.GetAstroObjectName() == AstroObject.Name.Comet) return; + + // For some reason other planets do this idk + ____upAxisDir *= -1f; + } } } diff --git a/NewHorizons/manifest.json b/NewHorizons/manifest.json index 92420264..a12fee53 100644 --- a/NewHorizons/manifest.json +++ b/NewHorizons/manifest.json @@ -3,6 +3,6 @@ "author": "xen", "name": "New Horizons", "uniqueName": "xen.NewHorizons", - "version": "0.1.0", + "version": "0.1.2", "owmlVersion": "2.1.0" }