Merge pull request #13 from xen-42/common-resources

Common resources
This commit is contained in:
Nick 2022-01-04 15:52:22 -05:00 committed by GitHub
commit 338baf21ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 626 additions and 480 deletions

5
.gitignore vendored
View File

@ -3,4 +3,7 @@ packages
.vs
bin
obj
Build
zip
*.zip
*/Build/*

View File

@ -23,8 +23,6 @@ namespace NewHorizons.Builder.Body
int count = (int)(2f * Mathf.PI * belt.InnerRadius / (10f * maxSize));
if (count > 200) count = 200;
Logger.Log($"Making {count} asteroids around {bodyName}");
Random.InitState(belt.RandomSeed);
for (int i = 0; i < count; i++)

View File

@ -17,7 +17,7 @@ namespace NewHorizons.Builder.Body
cometTail.transform.localPosition = Vector3.zero;
cometTail.name = "CometTail";
cometTail.transform.localScale = Vector3.one * module.SurfaceSize / 110;
cometTail.transform.localRotation = Quaternion.Euler(0, 180, 90);
cometTail.transform.localRotation = Quaternion.Euler(0, 90, 90);
/*
var alignment = cometTail.AddComponent<AlignWithTargetBody>();
alignment.SetTargetBody(primary.GetAttachedOWRigidbody());

View File

@ -36,7 +36,7 @@ namespace NewHorizons.Builder.General
ParameterizedAstroObject astroObject = body.AddComponent<ParameterizedAstroObject>();
if (config.Orbit != null) astroObject.keplerElements = KeplerElements.FromOrbitModule(config.Orbit);
if (config.Orbit != null) astroObject.SetKeplerCoordinatesFromOrbitModule(config.Orbit);
var type = AstroObject.Type.Planet;
if (config.Orbit.IsMoon) type = AstroObject.Type.Moon;

View File

@ -79,7 +79,6 @@ namespace NewHorizons.Builder.General
var secondary = point.Secondary;
var planets = point.Planets;
// Binaries have to use the same gravity exponent
var primaryGV = primary.GetGravityVolume();
var secondaryGV = secondary.GetGravityVolume();
@ -90,123 +89,26 @@ namespace NewHorizons.Builder.General
return;
}
// Have to use fall off type rn instead of exponent since it the exponent doesnt update until the Awake method I think
var exponent = 0f;
if (primaryGV.GetFalloffType() == OrbitalHelper.FalloffType.linear) exponent = 1f;
if (primaryGV.GetFalloffType() == OrbitalHelper.FalloffType.inverseSquared) exponent = 2f;
// Very specific distance between them
Vector3 separation = primary.transform.position - secondary.transform.position;
var Gm1 = primaryGV.GetStandardGravitationalParameter();
var Gm2 = secondaryGV.GetStandardGravitationalParameter();
// One of the two is zero if it just loaded
if (Gm1 == 0) Gm1 = GravityVolume.GRAVITATIONAL_CONSTANT * primaryGV.GetValue<float>("_surfaceAcceleration") * Mathf.Pow(primaryGV.GetValue<float>("_upperSurfaceRadius"), exponent) / 0.001f;
if (Gm2 == 0) Gm2 = GravityVolume.GRAVITATIONAL_CONSTANT * secondaryGV.GetValue<float>("_surfaceAcceleration") * Mathf.Pow(secondaryGV.GetValue<float>("_upperSurfaceRadius"), exponent) / 0.001f;
float r1 = separation.magnitude * Gm2 / (Gm1 + Gm2);
float r2 = separation.magnitude * Gm1 / (Gm1 + Gm2);
primary.transform.position = point.transform.position + r1 * separation.normalized;
secondary.transform.position = point.transform.position - r2 * separation.normalized;
var pointForceDetector = point.GetAttachedOWRigidbody().GetAttachedForceDetector();
// Set detectable fields
primaryCFD.SetValue("_detectableFields", new ForceVolume[] { secondaryGV });
primaryCFD.SetValue("_inheritDetector", point.GetAttachedOWRigidbody().GetAttachedForceDetector());
primaryCFD.SetValue("_activeInheritedDetector", point.GetAttachedOWRigidbody().GetAttachedForceDetector());
primaryCFD.SetValue("_inheritDetector", pointForceDetector);
primaryCFD.SetValue("_activeInheritedDetector", pointForceDetector);
primaryCFD.SetValue("_inheritElement0", false);
secondaryCFD.SetValue("_detectableFields", new ForceVolume[] { primaryGV });
secondaryCFD.SetValue("_inheritDetector", point.GetAttachedOWRigidbody().GetAttachedForceDetector());
secondaryCFD.SetValue("_activeInheritedDetector", point.GetAttachedOWRigidbody().GetAttachedForceDetector());
secondaryCFD.SetValue("_inheritDetector", pointForceDetector);
secondaryCFD.SetValue("_activeInheritedDetector", pointForceDetector);
secondaryCFD.SetValue("_inheritElement0", false);
// They must have the same eccentricity
var parameterizedAstroObject = primary.GetComponent<ParameterizedAstroObject>();
var parameterizedAstroObject2 = secondary.GetComponent<ParameterizedAstroObject>();
float ecc = 0;
float i = 0;
float l = 0;
float p = 0;
if (parameterizedAstroObject != null)
foreach(var planet in planets)
{
ecc = parameterizedAstroObject.keplerElements.Eccentricity;
i = parameterizedAstroObject.keplerElements.Inclination;
l = parameterizedAstroObject.keplerElements.LongitudeOfAscendingNode;
p = parameterizedAstroObject.keplerElements.ArgumentOfPeriapsis;
}
// Update speeds
var direction = Vector3.Cross(separation, Vector3.up).normalized;
if (direction.sqrMagnitude == 0) direction = Vector3.left;
var m1 = Gm1 / GravityVolume.GRAVITATIONAL_CONSTANT;
var m2 = Gm2 / GravityVolume.GRAVITATIONAL_CONSTANT;
var reducedMass = m1 * m2 / (m1 + m2);
var totalMass = m1 + m2;
var r = separation.magnitude;
// Start them off at their periapsis
var primaryKeplerElements = KeplerElements.FromTrueAnomaly(ecc, r1 / (1f - ecc), i, l, p, 0);
var secondaryKeplerElements = KeplerElements.FromTrueAnomaly(ecc, r2 / (1f - ecc), i, l, p, 180);
// Maybe we'll need these orbital parameters later
if(parameterizedAstroObject != null) parameterizedAstroObject.keplerElements = primaryKeplerElements;
if(parameterizedAstroObject2 != null) parameterizedAstroObject2.keplerElements = secondaryKeplerElements;
// Finally we update the speeds
float v = Mathf.Sqrt(GravityVolume.GRAVITATIONAL_CONSTANT * totalMass * (1 - ecc * ecc) / Mathf.Pow(r, exponent - 1));
var v2 = v / (1f + (m2 / m1));
var v1 = v - v2;
// Rotate
var rot = Quaternion.AngleAxis(l + p + 180f, Vector3.up);
var incAxis = Quaternion.AngleAxis(l, Vector3.up) * Vector3.left;
var incRot = Quaternion.AngleAxis(i, incAxis);
//Do this next tick for... reasons?
var focalPointMotion = point.gameObject.GetComponent<InitialMotion>();
var focalPointVelocity = focalPointMotion == null ? Vector3.zero : focalPointMotion.GetInitVelocity();
var d1 = Vector3.Cross(OrbitalHelper.RotateTo(Vector3.up, primaryKeplerElements), separation.normalized);
var d2 = Vector3.Cross(OrbitalHelper.RotateTo(Vector3.up, primaryKeplerElements), separation.normalized);
var primaryInitialMotion = primary.gameObject.GetComponent<InitialMotion>();
primaryInitialMotion.SetValue("_initLinearDirection", d1);
primaryInitialMotion.SetValue("_initLinearSpeed", v1);
var secondaryInitialMotion = secondary.gameObject.GetComponent<InitialMotion>();
secondaryInitialMotion.SetValue("_initLinearDirection", d2);
secondaryInitialMotion.SetValue("_initLinearSpeed", -v2);
// InitialMotion already set its speed so we overwrite that
if (!primaryInitialMotion.GetValue<bool>("_isInitVelocityDirty"))
{
Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => primaryRB.SetVelocity(d1 * v1 + focalPointVelocity));
}
if (!secondaryInitialMotion.GetValue<bool>("_isInitVelocityDirty"))
{
Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => primaryRB.SetVelocity(d2 * -v2 + focalPointVelocity));
}
// If they have tracking orbits set the period
var period = 2 * Mathf.PI * Mathf.Sqrt(Mathf.Pow(r, exponent + 1) / (GravityVolume.GRAVITATIONAL_CONSTANT * totalMass));
if (exponent == 1) period /= 3f;
// Only one of these won't be null, the other one gets done next tick
var trackingOrbitPrimary = primary.GetComponentInChildren<TrackingOrbitLine>();
if (trackingOrbitPrimary != null)
{
trackingOrbitPrimary.TrailTime = period;
}
var trackingOrbitSecondary = secondary.GetComponentInChildren<TrackingOrbitLine>();
if (trackingOrbitSecondary != null)
{
trackingOrbitSecondary.TrailTime = period;
var planetCFD = planet.GetAttachedOWRigidbody().GetAttachedForceDetector() as ConstantForceDetector;
planetCFD._detectableFields = new ForceVolume[] { primaryGV, secondaryGV };
planetCFD._inheritDetector = pointForceDetector;
planetCFD._activeInheritedDetector = pointForceDetector;
planetCFD._inheritElement0 = false;
}
}
}

View File

@ -19,6 +19,11 @@ namespace NewHorizons.Builder.General
var gravityRadius = GM / 0.1f;
if (exponent == 2f) gravityRadius = Mathf.Sqrt(gravityRadius);
// To let you actually orbit things the way you would expect we cap this at 4x the diameter if its not a star or black hole (this is what giants deep has)
if (config.Star != null || config.Singularity != null) gravityRadius = Mathf.Min(gravityRadius, 4 * config.Base.SurfaceSize);
else gravityRadius = Mathf.Min(gravityRadius, 15 * config.Base.SurfaceSize);
if (config.Base.SphereOfInfluence != 0f) gravityRadius = config.Base.SphereOfInfluence;
GameObject gravityGO = new GameObject("GravityWell");
gravityGO.transform.parent = body.transform;
gravityGO.transform.localPosition = Vector3.zero;

View File

@ -0,0 +1,251 @@
using NewHorizons.External;
using NewHorizons.OrbitalPhysics;
using NewHorizons.Utility;
using OWML.Common;
using OWML.Utils;
using PacificEngine.OW_CommonResources.Game;
using PacificEngine.OW_CommonResources.Game.Resource;
using PacificEngine.OW_CommonResources.Game.State;
using PacificEngine.OW_CommonResources.Geometry.Orbits;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.General
{
public static class HeavenlyBodyBuilder
{
private static readonly Dictionary<string, HeavenlyBody> _bodyMap = new Dictionary<string, HeavenlyBody>();
public static void Make(GameObject body, IPlanetConfig config, float SOI, GravityVolume bodyGravity, InitialMotion initialMotion)
{
var size = new Position.Size(config.Base.SurfaceSize, SOI);
var gravity = GetGravity(bodyGravity);
var parent = config.Orbit.PrimaryBody != null ? GetBody(config.Orbit.PrimaryBody) : HeavenlyBody.None;
if (config.Orbit.PrimaryBody != null && parent == HeavenlyBody.None)
Logger.LogWarning($"Could not find [{config.Orbit.PrimaryBody}] parent of [{config.Name}]");
var orbit = OrbitalHelper.KeplerCoordinatesFromOrbitModule(config.Orbit);
var hb = GetBody(config.Name);
if (hb == null) hb = AddHeavenlyBody(config.Name, config.FocalPoint != null);
Planet.Plantoid planetoid;
if (!config.Orbit.IsStatic) planetoid = new Planet.Plantoid(size, gravity, body.transform.rotation, initialMotion._initAngularSpeed, parent, orbit);
else planetoid = new Planet.Plantoid(size, gravity, body.transform.rotation, 0f, HeavenlyBody.None, body.transform.position, Vector3.zero);
var mapping = Planet.defaultMapping;
mapping[hb] = planetoid;
// Fix for binary focal points
if(parent != HeavenlyBody.None)
{
var focalPoint = Position.AstroLookup[parent].Invoke()?.gameObject.GetComponent<BinaryFocalPoint>();
if (focalPoint != null && mapping.ContainsKey(parent))
{
GameObject primary = null;
GameObject secondary = null;
Gravity primaryGravity = null;
Gravity secondaryGravity = null;
// One of them is null if it's the one being loaded
if(config.Name.Equals(focalPoint.PrimaryName))
{
primary = body;
primaryGravity = GetGravity(bodyGravity);
secondary = Position.getBody(GetBody(focalPoint.SecondaryName))?.gameObject;
var secondaryGV = Position.getBody(GetBody(focalPoint.SecondaryName))?.GetAttachedGravityVolume();
if (secondaryGV != null) secondaryGravity = GetGravity(secondaryGV);
}
else if (config.Name.Equals(focalPoint.SecondaryName))
{
secondary = body;
secondaryGravity = GetGravity(bodyGravity);
primary = Position.getBody(GetBody(focalPoint.PrimaryName))?.gameObject;
var primaryGV = Position.getBody(GetBody(focalPoint.PrimaryName))?.GetAttachedGravityVolume();
if (primaryGV != null) primaryGravity = GetGravity(primaryGV);
}
if (primaryGravity != null && secondaryGravity != null)
{
// Also have to fix the children
var primaryHB = GetBody(focalPoint.PrimaryName);
var secondaryHB = GetBody(focalPoint.SecondaryName);
var r = primary.transform.position - secondary.transform.position;
var m1 = primaryGravity.mass;
var m2 = secondaryGravity.mass;
float r1 = r.magnitude * m2 / (m1 + m2);
float r2 = r.magnitude * m1 / (m1 + m2);
ParameterizedAstroObject primaryAO = Position.AstroLookup[primaryHB].Invoke() as ParameterizedAstroObject;
ParameterizedAstroObject secondaryAO = Position.AstroLookup[secondaryHB].Invoke() as ParameterizedAstroObject;
float ecc = primaryAO.Eccentricity;
float i = primaryAO.Inclination;
float l = primaryAO.LongitudeOfAscendingNode;
float p = primaryAO.ArgumentOfPeriapsis;
var primaryKeplerCoordinates = KeplerCoordinates.fromEccentricAnomaly(ecc, r1 / (1 - ecc), i, p, l, 0);
var secondaryKeplerCoordinates = KeplerCoordinates.fromEccentricAnomaly(ecc, r2 / (1 - ecc), i, p, l, 180);
var totalMass = m1 + m2;
var exponent = (primaryGravity.exponent + secondaryGravity.exponent) / 2f;
var primaryCartesianState = OrbitHelper.toCartesian(Gravity.of(exponent, totalMass), 0, primaryKeplerCoordinates);
var secondaryCartesianState = OrbitHelper.toCartesian(Gravity.of(exponent, totalMass), 0, secondaryKeplerCoordinates);
var point = Position.AstroLookup[parent].Invoke();
primary.transform.position = point.transform.position + primaryCartesianState.Item1;
secondary.transform.position = point.transform.position + secondaryCartesianState.Item1;
Logger.Log($"Positions: {primary.transform.position}, {secondary.transform.position}");
var primaryOriginal = mapping[primaryHB];
var secondaryOriginal = mapping[secondaryHB];
// TODO: Idk if this works at all... probably not
var primaryRotation = 0f;
try
{
primaryRotation = primaryOriginal.state.relative.angularVelocity.magnitude;
}
catch (Exception) { };
var secondaryRotation = 0f;
try
{
secondaryRotation = secondaryOriginal.state.relative.angularVelocity.magnitude;
}
catch (Exception) { };
mapping[primaryHB] = new Planet.Plantoid(
primaryOriginal.size,
primaryOriginal.gravity,
primary.transform.rotation,
primaryRotation,
parent,
primaryKeplerCoordinates);
mapping[secondaryHB] = new Planet.Plantoid(
secondaryOriginal.size,
secondaryOriginal.gravity,
secondary.transform.rotation,
secondaryRotation,
parent,
secondaryKeplerCoordinates);
var period = 2 * Mathf.PI * Mathf.Sqrt(Mathf.Pow(r.magnitude, exponent + 1) / (GravityVolume.GRAVITATIONAL_CONSTANT * totalMass));
var trackingOrbitPrimary = primary.GetComponentInChildren<TrackingOrbitLine>();
if (trackingOrbitPrimary != null)
{
trackingOrbitPrimary.TrailTime = period;
}
var trackingOrbitSecondary = secondary.GetComponentInChildren<TrackingOrbitLine>();
if (trackingOrbitSecondary != null)
{
trackingOrbitSecondary.TrailTime = period;
}
Logger.Log($"{parent}: {mapping[parent]}");
Logger.Log($"{primaryHB}: {mapping[primaryHB]}");
Logger.Log($"{secondaryHB}: {mapping[secondaryHB]}");
}
}
}
Planet.defaultMapping = mapping;
Planet.mapping = mapping;
}
public static void Remove(AstroObject obj)
{
var astro = Position.find(obj);
var mapping = Planet.defaultMapping;
mapping.Remove(astro);
Planet.defaultMapping = mapping;
Planet.mapping = mapping;
}
private static Gravity GetGravity(GravityVolume volume)
{
if (volume == null)
{
return Gravity.of(2, 0);
}
var exponent = volume._falloffType != GravityVolume.FalloffType.linear ? 2f : 1f;
var mass = (volume._surfaceAcceleration * Mathf.Pow(volume._upperSurfaceRadius, exponent)) / GravityVolume.GRAVITATIONAL_CONSTANT;
return Gravity.of(exponent, mass);
}
private static HeavenlyBody AddHeavenlyBody(string name, bool isFocalPoint)
{
var hb = new HeavenlyBody(name, isFocalPoint);
_bodyMap.Add(name, hb);
var astroLookup = Position.AstroLookup;
var bodyLookup = Position.BodyLookup;
astroLookup.Add(hb, () => GetAstroObject(name));
bodyLookup.Add(hb, () => GetOWRigidbody(name));
Position.AstroLookup = astroLookup;
Position.BodyLookup = bodyLookup;
return hb;
}
private static HeavenlyBody GetBody(string name)
{
if (_bodyMap.ContainsKey(name))
{
return _bodyMap[name];
}
var hb = Position.find(AstroObjectLocator.GetAstroObject(name));
if (hb != null)
{
_bodyMap.Add(name, hb);
}
return hb;
}
public static void Reset()
{
Planet.defaultMapping = Planet.standardMapping;
}
private static AstroObject GetAstroObject(string name)
{
var astroBody = AstroObjectLocator.GetAstroObject(name);
if (astroBody == null
|| astroBody.gameObject == null)
{
return null;
}
return astroBody;
}
private static OWRigidbody GetOWRigidbody(string name)
{
var astroBody = GetAstroObject(name);
return astroBody?.GetOWRigidbody();
}
}
}

View File

@ -128,6 +128,8 @@ namespace NewHorizons.Builder.General
Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => RemoveProxy(ao.name.Replace("_Body", "")));
ao.transform.root.gameObject.SetActive(false);
HeavenlyBodyBuilder.Remove(ao);
}
public static void RemoveDistantProxyClones()

View File

@ -20,10 +20,10 @@ namespace NewHorizons.Builder.General
spawnGO.transform.localPosition = module.PlayerSpawnPoint;
// Move it up a bit more
spawnGO.transform.position = spawnGO.transform.position + spawnGO.transform.TransformDirection(Vector3.up) * 1f;
playerSpawn = spawnGO.AddComponent<SpawnPoint>();
spawnGO.transform.rotation = Quaternion.FromToRotation(Vector3.up, (playerSpawn.transform.position - body.transform.position).normalized);
spawnGO.transform.position = spawnGO.transform.position + spawnGO.transform.TransformDirection(Vector3.up) * 2f;
GameObject.FindObjectOfType<PlayerSpawner>().SetInitialSpawnPoint(playerSpawn);
}
if(module.ShipSpawnPoint != null)

View File

@ -23,29 +23,30 @@ namespace NewHorizons.Builder.Orbital
public static InitialMotion Update(InitialMotion initialMotion, GameObject body, AstroObject primaryBody, OWRigidbody OWRB, OrbitModule orbit)
{
if (!orbit.IsStatic)
{
initialMotion.SetPrimaryBody(primaryBody?.GetAttachedOWRigidbody());
initialMotion.SetValue("_orbitAngle", orbit.Inclination);
initialMotion.SetValue("_isGlobalAxis", false);
if (orbit.Eccentricity != 0 && primaryBody?.GetGravityVolume() != null)
{
// Calculate speed at apoapsis
KeplerElements kepler = KeplerElements.FromOrbitModule(orbit);
Gravity gravity = new Gravity(primaryBody.GetGravityVolume());
var eccSpeed = OrbitalHelper.GetOrbitalVelocity(kepler.Apoapsis, gravity, kepler);
var circularSpeed = OWPhysics.CalculateOrbitVelocity(primaryBody.GetAttachedOWRigidbody(), OWRB).magnitude;
initialMotion.SetValue("_orbitImpulseScalar", eccSpeed / circularSpeed);
}
}
// Rotation
initialMotion.SetValue("_initAngularSpeed", orbit.SiderealPeriod == 0 ? 0f : 1.0f / orbit.SiderealPeriod);
var rotationAxis = Quaternion.AngleAxis(orbit.AxialTilt + orbit.Inclination, Vector3.right) * Vector3.up;
var rotationAxis = Quaternion.AngleAxis(orbit.AxialTilt + orbit.Inclination + 90f, Vector3.right) * Vector3.up;
body.transform.rotation = Quaternion.FromToRotation(Vector3.up, rotationAxis);
initialMotion._orbitImpulseScalar = 0f;
if (!orbit.IsStatic)
{
if(primaryBody != null)
{
initialMotion.SetPrimaryBody(primaryBody.GetAttachedOWRigidbody());
var gv = primaryBody.GetGravityVolume();
if(gv != null)
{
var velocity = OrbitalHelper.GetCartesian(new OrbitalHelper.Gravity(primaryBody.GetGravityVolume()), orbit).Item2;
// For some stupid reason the InitialMotion awake method transforms the perfectly fine direction vector you give it so we preemptively do the inverse so it all cancels out
initialMotion._initLinearDirection = body.transform.InverseTransformDirection(velocity.normalized);
initialMotion._initLinearSpeed = velocity.magnitude;
}
}
}
return initialMotion;
}
}

View File

@ -21,15 +21,18 @@ namespace NewHorizons.Builder.Orbital
lineRenderer.useWorldSpace = false;
lineRenderer.loop = false;
var ecc = config.Orbit.Eccentricity;
var parentGravity = astroobject.GetPrimaryBody()?.GetGravityVolume();
OrbitLine orbitLine;
if (config.Orbit.Eccentricity == 0)
{
if (ecc == 0)
orbitLine = orbitGO.AddComponent<OrbitLine>();
}
else
{
// Doesn't work for linear eccentric falloff
else if (ecc > 0 && ecc < 1 && (parentGravity != null && parentGravity._falloffType == GravityVolume.FalloffType.inverseSquared))
orbitLine = orbitGO.AddComponent<EllipticOrbitLine>();
else
orbitLine = orbitGO.AddComponent<TrackingOrbitLine>();
}
var color = Color.white;
if (config.Orbit.Tint != null) color = config.Orbit.Tint.ToColor32();

View File

@ -94,8 +94,8 @@ namespace NewHorizons.Builder.Props
prop.transform.parent = go.transform;
prop.transform.localPosition = position == null ? Vector3.zero : (Vector3)position;
Quaternion rot = rotation == null ? prefab.transform.rotation : Quaternion.Euler((Vector3)rotation);
prop.transform.rotation = rot;
Quaternion rot = rotation == null ? Quaternion.identity : Quaternion.Euler((Vector3)rotation);
prop.transform.localRotation = rot;
if (alignWithNormal)
{
var up = prop.transform.localPosition.normalized;
@ -116,7 +116,7 @@ namespace NewHorizons.Builder.Props
private static void MakeScatter(GameObject go, PropModule.ScatterInfo[] scatterInfo, float radius, Sector sector, IModAssets assets, string uniqueModName)
{
var area = 4f * Mathf.PI * radius * radius;
var points = FibonacciSphere((int)area);
var points = RandomUtility.FibonacciSphere((int)area);
foreach (var propInfo in scatterInfo)
{
@ -136,27 +136,6 @@ namespace NewHorizons.Builder.Props
}
}
private static List<Vector3> FibonacciSphere(int samples)
{
List<Vector3> points = new List<Vector3>();
var phi = Mathf.PI * (3f - Mathf.Sqrt(5f));
for(int i = 0; i < samples; i++)
{
var y = 1 - (i / (float)(samples - 1)) * 2f;
var radius = Mathf.Sqrt(1 - y * y);
var theta = phi * i;
var x = Mathf.Cos(theta) * radius;
var z = Mathf.Sin(theta) * radius;
points.Add(new Vector3(x, y, z));
}
return points;
}
private static GameObject LoadPrefab(string assetBundle, string path, string uniqueModName, IModAssets assets)
{
string key = uniqueModName + "." + assetBundle;

View File

@ -0,0 +1,22 @@
using NewHorizons.Builder.General;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Components
{
public class MapSatelliteOrbitFix : MonoBehaviour
{
public void Awake()
{
var detector = base.transform.GetComponentInChildren<DynamicForceDetector>();
var ao = base.GetComponent<AstroObject>();
var newDetector = DetectorBuilder.Make(base.gameObject, ao.GetAttachedOWRigidbody(), ao.GetPrimaryBody(), ao);
newDetector.transform.parent = detector.transform.parent;
GameObject.Destroy(detector);
}
}
}

View File

@ -14,6 +14,7 @@ namespace NewHorizons.External
public float SurfaceGravity { get; set; }
public string GravityFallOff { get; set; } = "linear";
public float SurfaceSize { get; set; }
public float SphereOfInfluence { get; set; }
public float WaterSize { get; set; }
public float GroundSize { get; set; }
public float LavaSize { get; set; }

View File

@ -4,6 +4,7 @@ using NewHorizons.Builder.Body;
using NewHorizons.Builder.General;
using NewHorizons.Builder.Orbital;
using NewHorizons.Builder.Props;
using NewHorizons.Components;
using NewHorizons.External;
using NewHorizons.OrbitalPhysics;
using NewHorizons.Utility;
@ -24,7 +25,6 @@ namespace NewHorizons
{
public class Main : ModBehaviour
{
public static AssetBundle ShaderBundle;
public static Main Instance { get; private set; }
@ -34,7 +34,8 @@ namespace NewHorizons
public static float FurthestOrbit { get; set; } = 50000f;
public StarLightController StarLightController { get; private set; }
private static string _currentStarSystem = "SolarSystem";
private string _currentStarSystem = "SolarSystem";
private bool _isChangingStarSystem = false;
public override object GetApi()
{
@ -45,6 +46,7 @@ namespace NewHorizons
{
SceneManager.sceneLoaded += OnSceneLoaded;
Instance = this;
GlobalMessenger<DeathType>.AddListener("PlayerDeath", OnDeath);
ShaderBundle = Main.Instance.ModHelper.Assets.LoadBundle("AssetBundle/shader");
Utility.Patches.Apply();
@ -60,7 +62,7 @@ namespace NewHorizons
Logger.LogWarning("Couldn't find planets folder");
}
//UnityEngine.Random.InitState();
UnityEngine.Random.InitState((int)DateTime.Now.Ticks);
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => OnSceneLoaded(SceneManager.GetActiveScene(), LoadSceneMode.Single));
}
@ -68,19 +70,36 @@ namespace NewHorizons
{
Logger.Log($"Destroying NewHorizons");
SceneManager.sceneLoaded -= OnSceneLoaded;
GlobalMessenger<DeathType>.RemoveListener("PlayerDeath", OnDeath);
}
void OnDeath(DeathType _)
{
// We reset the solar system on death (unless we just killed the player)
if (!_isChangingStarSystem) _currentStarSystem = "SolarSystem";
}
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
Logger.Log($"Scene Loaded: {scene.name} {mode}");
_isChangingStarSystem = false;
HeavenlyBodyBuilder.Reset();
if (scene.name.Equals("TitleScreen")) DisplayBodyOnTitleScreen();
if (scene.name != "SolarSystem") return;
if (scene.name != "SolarSystem")
{
// Reset back to original solar system after going to main menu.
_currentStarSystem = "SolarSystem";
return;
}
NewHorizonsData.Load();
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => ShipLogBuilder.Init());
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => AstroObjectLocator.GetAstroObject("MapSatellite").gameObject.AddComponent<MapSatelliteOrbitFix>());
// Need to manage this when there are multiple stars
var sun = GameObject.Find("Sun_Body");
@ -186,60 +205,84 @@ namespace NewHorizons
public void DisplayBodyOnTitleScreen()
{
//Try loading one planet why not
GameObject titleScreenGO = new GameObject("TitleScreenPlanet");
var eligible = BodyList.Where(b => b.Config.Ring != null && (b.Config.HeightMap != null || (b.Config.Atmosphere?.Cloud != null))).ToArray();
var body = eligible[UnityEngine.Random.Range(0, eligible.Count())];
var eligible = BodyList.Where(b => b.Config.HeightMap != null || b.Config.Atmosphere?.Cloud != null).ToArray();
var eligibleCount = eligible.Count();
if (eligibleCount == 0) return;
var selectionCount = Mathf.Min(eligibleCount, 3);
var indices = RandomUtility.GetUniqueRandomArray(0, eligible.Count(), selectionCount);
Logger.Log($"Displaying {selectionCount} bodies on the title screen");
GameObject body1, body2, body3;
body1 = LoadTitleScreenBody(eligible[indices[0]]);
Logger.LogPath(body1);
if (selectionCount > 1)
{
body1.transform.localScale = Vector3.one * (body1.transform.localScale.x) * 0.3f;
body1.transform.localPosition = new Vector3(0, -20, 0);
body2 = LoadTitleScreenBody(eligible[indices[1]]);
body2.transform.localScale = Vector3.one * (body2.transform.localScale.x) * 0.3f;
body2.transform.localPosition = new Vector3(7, 40, 0);
}
if (selectionCount > 2)
{
body3 = LoadTitleScreenBody(eligible[indices[2]]);
body3.transform.localScale = Vector3.one * (body3.transform.localScale.x) * 0.3f;
body3.transform.localPosition = new Vector3(-5, 10, 0);
}
GameObject.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire").SetActive(false);
GameObject.Find("Scene/Background/PlanetPivot/PlanetRoot").SetActive(false);
var lightGO = new GameObject("Light");
lightGO.transform.parent = GameObject.Find("Scene/Background").transform;
lightGO.transform.localPosition = new Vector3(-47.9203f, 145.7596f, 43.1802f);
var light = lightGO.AddComponent<Light>();
light.color = new Color(1f, 1f, 1f, 1f);
light.range = 100;
light.intensity = 0.8f;
}
private GameObject LoadTitleScreenBody(NewHorizonsBody body)
{
Logger.Log($"Displaying {body.Config.Name} on the title screen");
var flag = false;
GameObject titleScreenGO = new GameObject(body.Config.Name + "_TitleScreen");
HeightMapModule heightMap = new HeightMapModule();
var minSize = 20;
var maxSize = 35;
var minSize = 15;
var maxSize = 30;
float size = minSize;
if (body.Config.HeightMap != null)
{
size = Mathf.Clamp(body.Config.HeightMap.MaxHeight / 10, minSize, maxSize);
size = Mathf.Clamp(body.Config.HeightMap.MaxHeight / 10, minSize, maxSize);
heightMap.TextureMap = body.Config.HeightMap.TextureMap;
heightMap.HeightMap = body.Config.HeightMap.HeightMap;
heightMap.MaxHeight = size;
heightMap.MinHeight = body.Config.HeightMap.MinHeight * size / body.Config.HeightMap.MaxHeight;
flag = true;
}
if (body.Config.Atmosphere != null && body.Config.Atmosphere.Cloud != null)
{
// Hacky but whatever I just want a sphere
size = Mathf.Clamp(body.Config.Atmosphere.Size / 10, minSize, maxSize);
heightMap.MaxHeight = heightMap.MinHeight = size+1;
heightMap.MaxHeight = heightMap.MinHeight = size + 1;
heightMap.TextureMap = body.Config.Atmosphere.Cloud;
flag = true;
}
if (flag)
HeightMapBuilder.Make(titleScreenGO, heightMap, body.Assets);
if (body.Config.Ring != null)
{
HeightMapBuilder.Make(titleScreenGO, heightMap, body.Assets);
if (body.Config.Ring != null)
{
RingModule newRing = new RingModule();
newRing.InnerRadius = size * 1.2f;
newRing.OuterRadius = size * 2f;
newRing.Texture = body.Config.Ring.Texture;
RingBuilder.Make(titleScreenGO, newRing, body.Assets);
titleScreenGO.transform.localScale = Vector3.one * 0.8f;
}
GameObject.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire").SetActive(false);
GameObject.Find("Scene/Background/PlanetPivot/PlanetRoot").SetActive(false);
titleScreenGO.transform.parent = GameObject.Find("Scene/Background/PlanetPivot/").transform;
titleScreenGO.transform.localPosition = Vector3.zero;
var lightGO = new GameObject("Light");
lightGO.transform.parent = titleScreenGO.transform.parent.parent;
lightGO.transform.localPosition = new Vector3(-47.9203f, 145.7596f, 43.1802f);
var light = lightGO.AddComponent<Light>();
light.color = new Color(1f, 1f, 1f, 1f);
light.range = 100;
light.intensity = 0.8f;
RingModule newRing = new RingModule();
newRing.InnerRadius = size * 1.2f;
newRing.OuterRadius = size * 2f;
newRing.Texture = body.Config.Ring.Texture;
RingBuilder.Make(titleScreenGO, newRing, body.Assets);
titleScreenGO.transform.localScale = Vector3.one * 0.8f;
}
titleScreenGO.transform.parent = GameObject.Find("Scene/Background/PlanetPivot/").transform;
titleScreenGO.transform.localPosition = Vector3.zero;
return titleScreenGO;
}
private bool LoadBody(NewHorizonsBody body, bool defaultPrimaryToSun = false)
@ -401,8 +444,7 @@ namespace NewHorizons
// Now that we're done move the planet into place
go.transform.parent = Locator.GetRootTransform();
var positionVector = OrbitalHelper.RotateTo(Vector3.left * body.Config.Orbit.SemiMajorAxis * (1 + body.Config.Orbit.Eccentricity), body.Config.Orbit);
go.transform.position = positionVector + (primaryBody == null ? Vector3.zero : primaryBody.transform.position);
go.transform.position = OrbitalHelper.GetCartesian(new OrbitalHelper.Gravity(1, 100), body.Config.Orbit).Item1 + (primaryBody == null ? Vector3.zero : primaryBody.transform.position);
if (go.transform.position.magnitude > FurthestOrbit)
{
@ -424,6 +466,8 @@ namespace NewHorizons
if (ao.GetAstroObjectName() == AstroObject.Name.CustomString) AstroObjectLocator.RegisterCustomAstroObject(ao);
HeavenlyBodyBuilder.Make(go, body.Config, sphereOfInfluence, gv, initialMotion);
return go;
}
@ -477,6 +521,8 @@ namespace NewHorizons
public void ChangeCurrentStarSystem(string newStarSystem)
{
_currentStarSystem = newStarSystem;
_isChangingStarSystem = true;
Locator.GetDeathManager().KillPlayer(DeathType.Meditation);
LoadManager.LoadSceneAsync(OWScene.SolarSystem, true, LoadManager.FadeType.ToBlack, 0.1f, true);
}
}

View File

@ -30,6 +30,12 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Reference Include="PacificEngine.OW_CommonResources">
<HintPath>$(OuterWildsModsDirectory)\PacificEngine.OW_CommonResources\PacificEngine.OW_CommonResources.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Content Include="NewHorizons.csproj.user" />
</ItemGroup>

View File

@ -2,6 +2,7 @@
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectView>ProjectFiles</ProjectView>
<OutputPath>C:\Users\Nicholas\AppData\Roaming\OuterWildsModManager\OWML\Mods\xen.NewHorizons</OutputPath>
<OutputPath>$(AppData)\OuterWildsModManager\OWML\Mods\xen.NewHorizons</OutputPath>
<OuterWildsModsDirectory>$(AppData)\OuterWildsModManager\OWML\Mods</OuterWildsModsDirectory>
</PropertyGroup>
</Project>

View File

@ -1,27 +0,0 @@
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;
}
}
}

View File

@ -1,27 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NewHorizons.Utility;
namespace NewHorizons.OrbitalPhysics
{
public class Gravity
{
public float Exponent { get; }
public float Mass { get; }
public Gravity(float exponent, float mass)
{
Exponent = exponent;
Mass = mass;
}
public Gravity(GravityVolume gv)
{
Exponent = gv.GetFalloffExponent();
Mass = gv.GetStandardGravitationalParameter() / GravityVolume.GRAVITATIONAL_CONSTANT;
}
}
}

View File

@ -1,127 +0,0 @@
using NewHorizons.External;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.OrbitalPhysics
{
public class KeplerElements
{
public float LongitudeOfAscendingNode { get; }
public float Eccentricity { get; }
public float SemiMajorAxis { get; }
public float Inclination { get; }
public float ArgumentOfPeriapsis { get; }
public float TrueAnomaly { get; private set; }
public float EccentricAnomaly { get; private set; }
public float MeanAnomaly { get; private set; }
public float SemiMinorAxis { get; }
public float Focus { get; }
public float Apoapsis { get; }
public float Periapsis { get; }
private KeplerElements(float e, float a, float i, float longitudeOfAscendingNode, float argumentOfPeriapsis, float trueAnomaly, float eccentricAnomaly, float meanAnomaly)
{
LongitudeOfAscendingNode = longitudeOfAscendingNode;
Eccentricity = e;
SemiMajorAxis = a;
Inclination = i;
ArgumentOfPeriapsis = argumentOfPeriapsis;
TrueAnomaly = trueAnomaly;
SemiMinorAxis = SemiMajorAxis * Mathf.Sqrt(1 - Eccentricity * Eccentricity);
Focus = Mathf.Sqrt((SemiMajorAxis * SemiMajorAxis) - (SemiMinorAxis * SemiMinorAxis));
Apoapsis = SemiMajorAxis + Focus;
Periapsis = SemiMajorAxis - Focus;
EccentricAnomaly = eccentricAnomaly;
MeanAnomaly = meanAnomaly;
}
public static KeplerElements FromOrbitModule(OrbitModule module)
{
return FromTrueAnomaly(module.Eccentricity, module.SemiMajorAxis, module.Inclination, module.LongitudeOfAscendingNode, module.ArgumentOfPeriapsis, module.TrueAnomaly);
}
public static KeplerElements FromTrueAnomaly(float e, float a, float i, float longitudeOfAscendingNode, float argumentOfPeriapsis, float trueAnomaly)
{
var newKeplerElements = new KeplerElements(e, a, i, longitudeOfAscendingNode, argumentOfPeriapsis, 0, 0, 0);
newKeplerElements.SetTrueAnomaly(trueAnomaly);
return newKeplerElements;
}
public static KeplerElements FromMeanAnomaly(float e, float a, float i, float longitudeOfAscendingNode, float argumentOfPeriapsis, float meanAnomaly)
{
var newKeplerElements = new KeplerElements(e, a, i, longitudeOfAscendingNode, argumentOfPeriapsis, 0, 0, 0);
newKeplerElements.SetMeanAnomaly(meanAnomaly);
return newKeplerElements;
}
public static KeplerElements FromEccentricAnomaly(float e, float a, float i, float longitudeOfAscendingNode, float argumentOfPeriapsis, float eccentricAnomaly)
{
var newKeplerElements = new KeplerElements(e, a, i, longitudeOfAscendingNode, argumentOfPeriapsis, 0, 0, 0);
newKeplerElements.SetEccentricAnomaly(eccentricAnomaly);
return newKeplerElements;
}
public static KeplerElements Copy(KeplerElements original)
{
return KeplerElements.FromTrueAnomaly(original.Eccentricity, original.SemiMajorAxis, original.Inclination, original.LongitudeOfAscendingNode, original.ArgumentOfPeriapsis, original.TrueAnomaly);
}
public void SetTrueAnomaly(float trueAnomaly)
{
TrueAnomaly = trueAnomaly;
EccentricAnomaly = EccentricAnomalyFromTrueAnomaly(trueAnomaly, Eccentricity);
MeanAnomaly = MeanAnomalyFromEccentricAnomaly(EccentricAnomaly, Eccentricity);
}
public void SetMeanAnomaly(float meanAnomaly)
{
MeanAnomaly = meanAnomaly;
TrueAnomaly = TrueAnomalyFromMeanAnomaly(meanAnomaly, Eccentricity);
EccentricAnomaly = EccentricAnomalyFromTrueAnomaly(TrueAnomaly, Eccentricity);
}
public void SetEccentricAnomaly(float eccentricAnomaly)
{
EccentricAnomaly = eccentricAnomaly;
TrueAnomaly = TrueAnomalyFromEccentricAnomaly(eccentricAnomaly, Eccentricity);
MeanAnomaly = MeanAnomalyFromEccentricAnomaly(eccentricAnomaly, Eccentricity);
}
private static float MeanAnomalyFromEccentricAnomaly(float eccentricAnomaly, float eccentricity)
{
return eccentricAnomaly - eccentricity * Mathf.Sin(eccentricAnomaly);
}
private static float TrueAnomalyFromEccentricAnomaly(float eccentricAnomaly, float eccentricity)
{
var a = Mathf.Cos(eccentricAnomaly) - eccentricity;
var h = 1 - eccentricity * Mathf.Cos(eccentricAnomaly);
var o = h * h - a * a;
return Mathf.Atan2(o, a);
}
private static float EccentricAnomalyFromTrueAnomaly(float trueAnomaly, float eccentricity)
{
var a = Mathf.Cos(trueAnomaly) + eccentricity;
var h = 1 + eccentricity * Mathf.Cos(trueAnomaly);
var o = h * h - a * a;
return Mathf.Atan2(o, a);
}
private static float TrueAnomalyFromMeanAnomaly(float meanAnomaly, float eccentricity)
{
// Fourier expansion
var term1 = meanAnomaly;
var term2 = (2 * eccentricity - eccentricity * eccentricity * eccentricity / 4f) * Mathf.Sin(meanAnomaly);
var term3 = (eccentricity * eccentricity * Mathf.Sin(2 * meanAnomaly) * 5f / 4f);
var term4 = (eccentricity * eccentricity * eccentricity * Mathf.Sin(3 * meanAnomaly) * 13f / 12f);
return term1 + term2 + term3 + term4;
}
}
}

View File

@ -1,86 +1,88 @@
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;
using NewHorizons.External;
namespace NewHorizons.OrbitalPhysics
{
public static class OrbitalHelper
{
public enum FalloffType
{
inverseSquared,
linear,
none
}
public static Vector3 RotateTo(Vector3 vector, KeplerElements elements)
{
// For now, eccentric orbits gotta start at apoapsis and cant be inclined
var rot = Quaternion.AngleAxis(elements.LongitudeOfAscendingNode + elements.TrueAnomaly + elements.ArgumentOfPeriapsis + 180f, Vector3.up);
if (elements.Eccentricity != 0)
{
rot = Quaternion.AngleAxis(elements.LongitudeOfAscendingNode + elements.ArgumentOfPeriapsis + 180f, Vector3.up);
}
var incAxis = Quaternion.AngleAxis(elements.LongitudeOfAscendingNode, Vector3.up) * Vector3.left;
var incRot = Quaternion.AngleAxis(elements.Inclination, incAxis);
return rot * incRot * vector;
}
public static Vector3 RotateTo(Vector3 vector, OrbitModule module)
{
return RotateTo(vector, KeplerElements.FromOrbitModule(module));
}
public static Vector3 VelocityDirection(Vector3 separation, KeplerElements elements)
{
var incAxis = Quaternion.AngleAxis(elements.LongitudeOfAscendingNode, Vector3.up) * Vector3.left;
var incRot = Quaternion.AngleAxis(elements.Inclination, incAxis);
return Vector3.Cross(RotateTo(Vector3.up, elements), separation);
}
public static float GetOrbitalVelocity(float distance, Gravity gravity, KeplerElements kepler)
{
if (kepler.Eccentricity == 0) return GetCircularOrbitVelocity(distance, gravity, kepler);
if (gravity.Exponent == 2)
{
return Mathf.Sqrt(GravityVolume.GRAVITATIONAL_CONSTANT * gravity.Mass * (2f / distance - 1f / kepler.SemiMajorAxis));
}
if(gravity.Exponent == 1)
{
var mu = GravityVolume.GRAVITATIONAL_CONSTANT * gravity.Mass;
var rp2 = kepler.Periapsis * kepler.Periapsis;
var ra2 = kepler.Apoapsis * kepler.Apoapsis;
float term1 = 0;
if(kepler.Eccentricity < 1)
term1 = mu * Mathf.Log(kepler.Periapsis / kepler.Apoapsis) * rp2 / (rp2 - ra2);
var term2 = mu * Mathf.Log(kepler.Apoapsis / distance);
return Mathf.Sqrt(2 * (term1 + term2));
}
Logger.LogError($"Invalid exponent {gravity.Exponent}");
return 0f;
}
public static float GetCircularOrbitVelocity(float distance, Gravity gravity, KeplerElements kepler)
{
if (gravity.Exponent == 2)
{
return Mathf.Sqrt(GravityVolume.GRAVITATIONAL_CONSTANT * gravity.Mass / distance);
}
if(gravity.Exponent == 1)
{
return Mathf.Sqrt(GravityVolume.GRAVITATIONAL_CONSTANT * gravity.Mass);
}
Logger.LogError($"Invalid exponent {gravity.Exponent}");
return 0f;
}
}
}
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;
using NewHorizons.External;
using CRGravity = PacificEngine.OW_CommonResources.Geometry.Orbits.Gravity;
using KeplerCoordinates = PacificEngine.OW_CommonResources.Geometry.Orbits.KeplerCoordinates;
/*
* Wrapper class for OW_CommonResources.Geometry.Orbits functions
*/
namespace NewHorizons.OrbitalPhysics
{
public static class OrbitalHelper
{
public enum FalloffType
{
inverseSquared,
linear,
none
}
public static Tuple<Vector3, Vector3> GetCartesian(Gravity gravity, OrbitModule orbit)
{
if (orbit.SemiMajorAxis == 0)
{
return Tuple.Create(Vector3.zero, Vector3.zero);
}
var crGravity = new CRGravity(GravityVolume.GRAVITATIONAL_CONSTANT, gravity.Exponent, gravity.Mass);
var kepler = KeplerCoordinates.fromTrueAnomaly(orbit.Eccentricity, orbit.SemiMajorAxis, orbit.Inclination, orbit.ArgumentOfPeriapsis, orbit.LongitudeOfAscendingNode, orbit.TrueAnomaly);
var cartesian = PacificEngine.OW_CommonResources.Geometry.Orbits.OrbitHelper.toCartesian(crGravity, 0f, kepler);
if (cartesian == null)
{
cartesian = Tuple.Create(Vector3.zero, Vector3.zero);
}
return cartesian;
}
public static Tuple<Vector3, Vector3> GetCartesian(Gravity gravity, ParameterizedAstroObject ao)
{
if (ao.SemiMajorAxis == 0)
{
return Tuple.Create(Vector3.zero, Vector3.zero);
}
var crGravity = new CRGravity(GravityVolume.GRAVITATIONAL_CONSTANT, gravity.Exponent, gravity.Mass);
var kepler = KeplerCoordinates.fromTrueAnomaly(ao.Eccentricity, ao.SemiMajorAxis, ao.Inclination, ao.ArgumentOfPeriapsis, ao.LongitudeOfAscendingNode, ao.TrueAnomaly);
var cartesian = PacificEngine.OW_CommonResources.Geometry.Orbits.OrbitHelper.toCartesian(crGravity, 0f, kepler);
if (cartesian == null)
{
cartesian = Tuple.Create(Vector3.zero, Vector3.zero);
}
return cartesian;
}
public static KeplerCoordinates KeplerCoordinatesFromOrbitModule(OrbitModule orbit)
{
return KeplerCoordinates.fromTrueAnomaly(orbit.Eccentricity, orbit.SemiMajorAxis, orbit.Inclination, orbit.ArgumentOfPeriapsis, orbit.LongitudeOfAscendingNode, orbit.TrueAnomaly);
}
public class Gravity
{
public float Exponent { get; }
public float Mass { get; }
public Gravity(float exponent, float mass)
{
Exponent = exponent;
Mass = mass;
}
public Gravity(GravityVolume gv)
{
Exponent = gv.GetFalloffExponent();
Mass = gv.GetStandardGravitationalParameter() / GravityVolume.GRAVITATIONAL_CONSTANT;
}
}
}
}

View File

@ -1,4 +1,6 @@
using System;
using NewHorizons.External;
using PacificEngine.OW_CommonResources.Geometry.Orbits;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -8,6 +10,51 @@ namespace NewHorizons.OrbitalPhysics
{
public class ParameterizedAstroObject : AstroObject
{
public KeplerElements keplerElements;
private KeplerCoordinates _keplerCoordinates;
public float Eccentricity
{
get { return _keplerCoordinates.eccentricity; }
}
public float SemiMajorAxis
{
get { return _keplerCoordinates.semiMajorRadius; }
}
public float Inclination
{
get { return _keplerCoordinates.inclinationAngle; }
}
public float ArgumentOfPeriapsis
{
get { return _keplerCoordinates.periapseAngle; }
}
public float LongitudeOfAscendingNode
{
get { return _keplerCoordinates.ascendingAngle; }
}
public float TrueAnomaly
{
get { return _keplerCoordinates.trueAnomaly; }
}
public void SetKeplerCoordinatesFromOrbitModule(OrbitModule orbit)
{
_keplerCoordinates = KeplerCoordinates.fromTrueAnomaly(orbit.Eccentricity, orbit.SemiMajorAxis, orbit.Inclination, orbit.ArgumentOfPeriapsis, orbit.LongitudeOfAscendingNode, orbit.TrueAnomaly);
}
public void SetKeplerCoordinatesFromTrueAnomaly(float ecc, float a, float i, float p, float l, float trueAnomaly)
{
_keplerCoordinates = KeplerCoordinates.fromTrueAnomaly(ecc, a, i, p, l, trueAnomaly);
}
public override string ToString()
{
return $"ParameterizedAstroObject: Eccentricity {Eccentricity}, SemiMajorAxis {SemiMajorAxis}, Inclination {Inclination}, ArgumentOfPeriapsis {ArgumentOfPeriapsis}, LongitudeOfAscendingNode {LongitudeOfAscendingNode}, TrueAnomaly {TrueAnomaly}";
}
}
}

View File

@ -19,7 +19,7 @@ namespace NewHorizons.Utility
public static AstroObject GetAstroObject(string name)
{
if (name.Equals("MAP_SATELLITE"))
if (name.ToUpper().Replace("_", "").Equals("MAPSATELLITE"))
return GetAstroObject(AstroObject.Name.MapSatellite);
var aoName = AstroObject.StringIDToAstroObjectName(name);
if(aoName == AstroObject.Name.None) aoName = AstroObject.StringIDToAstroObjectName(name.ToUpper().Replace(" ", "_"));

View File

@ -30,7 +30,10 @@ namespace NewHorizons.Utility
public static float GetFalloffExponent(this GravityVolume gv)
{
if (gv == null) return 0;
return (float)typeof(GravityVolume).GetField("_falloffExponent", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(gv);
if (gv._falloffType == GravityVolume.FalloffType.linear) return 1;
if (gv._falloffType == GravityVolume.FalloffType.inverseSquared) return 2;
return 0;
}
public static string ToCamelCase(this string str)

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Utility
{
public static class RandomUtility
{
public static int[] GetUniqueRandomArray(int min, int max, int count)
{
int[] result = new int[count];
List<int> numbersInOrder = new List<int>();
for (var x = min; x < max; x++)
{
numbersInOrder.Add(x);
}
for (var x = 0; x < count; x++)
{
var randomIndex = UnityEngine.Random.Range(0, numbersInOrder.Count);
result[x] = numbersInOrder[randomIndex];
numbersInOrder.RemoveAt(randomIndex);
}
return result;
}
public static List<Vector3> FibonacciSphere(int samples)
{
List<Vector3> points = new List<Vector3>();
var phi = Mathf.PI * (3f - Mathf.Sqrt(5f));
for (int i = 0; i < samples; i++)
{
var y = 1 - (i / (float)(samples - 1)) * 2f;
var radius = Mathf.Sqrt(1 - y * y);
var theta = phi * i;
var x = Mathf.Cos(theta) * radius;
var z = Mathf.Sin(theta) * radius;
points.Add(new Vector3(x, y, z));
}
return points;
}
}
}

View File

@ -3,6 +3,7 @@
"author": "xen",
"name": "New Horizons",
"uniqueName": "xen.NewHorizons",
"version": "0.4.0",
"owmlVersion": "2.1.0"
"version": "0.5.0",
"owmlVersion": "2.1.0",
"dependencies": [ "PacificEngine.OW_CommonResources" ]
}

View File

@ -453,6 +453,9 @@ Authors:
- xen (from New Horizons v0.1.0 onwards)
- Mister_Nebula (created original titled Marshmallow)
New Horizons contributors:
- salomj (Implemented [OW_CommonResources](https://github.com/PacificEngine/OW_CommonResources) support)
Marshmallow was made with help from:
- TAImatem
- AmazingAlek