Reorganization + linear falloff equal mass binaries work

This commit is contained in:
Nick J. Connors 2021-12-22 12:25:52 -05:00
parent fae11fc162
commit f721781ef2
47 changed files with 552 additions and 217 deletions

View File

@ -10,7 +10,7 @@ using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
using Random = UnityEngine.Random;
namespace NewHorizons.Body
namespace NewHorizons.Builder.Body
{
static class AsteroidBeltBuilder
{

View File

@ -6,7 +6,7 @@ using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.General
namespace NewHorizons.Builder.Body
{
static class BlackHoleBuilder
{

View File

@ -7,7 +7,7 @@ using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Body
namespace NewHorizons.Builder.Body
{
public static class CometTailBuilder
{

View File

@ -1,7 +1,7 @@
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Body
namespace NewHorizons.Builder.Body
{
static class GeometryBuilder
{

View File

@ -1,4 +1,5 @@
using NewHorizons.Body.Geometry;
using NewHorizons.Body;
using NewHorizons.Body.Geometry;
using NewHorizons.External;
using OWML.Common;
using System;
@ -9,7 +10,7 @@ using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Body
namespace NewHorizons.Builder.Body
{
static class HeightMapBuilder
{

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.General
namespace NewHorizons.Builder.Body
{
static class LavaBuilder
{

View File

@ -7,7 +7,7 @@ using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Body
namespace NewHorizons.Builder.Body
{
static class ProcGenBuilder
{

View File

@ -8,7 +8,7 @@ using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.General
namespace NewHorizons.Builder.Body
{
static class RingBuilder
{

View File

@ -8,7 +8,7 @@ using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Body
namespace NewHorizons.Builder.Body
{
static class StarBuilder
{
@ -74,10 +74,10 @@ namespace NewHorizons.Body
var giantMaterial = sun.GetComponent<SunController>().GetValue<Material>("_endSurfaceMaterial");
surface.sharedMaterial = new Material(starModule.Size >= 3000 ? giantMaterial : mainSequenceMaterial);
surface.sharedMaterial.color = new Color(colour.r * 4f / 255f, colour.g * 4f / 255f, colour.b * 4f / 255f);
surface.sharedMaterial.color = new Color(colour.r * 8f / 255f, colour.g * 8f / 255f, colour.b * 8f / 255f);
surface.sharedMaterial.SetTexture("_ColorRamp", Utility.ImageUtilities.TintImage(_colorOverTime, colour));
sunAtmosphere.transform.Find("AtmoSphere").transform.localScale = Vector3.one * 2f;
sunAtmosphere.transform.Find("AtmoSphere").transform.localScale = Vector3.one * (starModule.Size + 1000)/starModule.Size;
foreach (var lod in sunAtmosphere.transform.Find("AtmoSphere").GetComponentsInChildren<MeshRenderer>())
{
lod.material.SetColor("_SkyColor", colour);

View File

@ -3,7 +3,7 @@ using OWML.Utils;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Body
namespace NewHorizons.Builder.Body
{
static class WaterBuilder
{

View File

@ -4,7 +4,7 @@ using OWML.Utils;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.General
namespace NewHorizons.Builder.General
{
static class AmbientLightBuilder
{

View File

@ -2,14 +2,15 @@
using NewHorizons.OrbitalPhysics;
using NewHorizons.Utility;
using OWML.Utils;
using System;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.General
namespace NewHorizons.Builder.General
{
static class BaseBuilder
{
public static MTuple Make(GameObject body, AstroObject primaryBody, Vector3 positionVector, IPlanetConfig config)
public static Tuple<AstroObject, OWRigidbody> Make(GameObject body, AstroObject primaryBody, Vector3 positionVector, IPlanetConfig config)
{
Rigidbody RB = body.AddComponent<Rigidbody>();
RB.mass = 10000;
@ -31,10 +32,14 @@ namespace NewHorizons.General
OWRB.SetValue("_rigidbody", RB);
OWRB.SetValue("_kinematicRigidbody", KRB);
DetectorBuilder.Make(body, primaryBody);
AstroObject AO = body.AddComponent<AstroObject>();
AO.SetValue("_type", config.Orbit.IsMoon ? AstroObject.Type.Moon : AstroObject.Type.Planet);
var type = AstroObject.Type.Planet;
if (config.Orbit.IsMoon) type = AstroObject.Type.Moon;
else if (config.Base.HasCometTail) type = AstroObject.Type.Comet;
else if (config.Star != null) type = AstroObject.Type.Star;
else if (config.FocalPoint != null) type = AstroObject.Type.None;
AO.SetValue("_type", type);
AO.SetValue("_name", AstroObject.Name.CustomString);
AO.SetValue("_customName", config.Name);
AO.SetValue("_primaryBody", primaryBody);
@ -46,7 +51,7 @@ namespace NewHorizons.General
alignment.SetValue("_usePhysicsToRotate", true);
}
return new MTuple(AO, OWRB);
return new Tuple<AstroObject, OWRigidbody>(AO, OWRB);
}
}
}

View File

@ -0,0 +1,147 @@
using NewHorizons.Builder.Orbital;
using NewHorizons.External;
using NewHorizons.OrbitalPhysics;
using OWML.Utils;
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using NewHorizons.Utility;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.General
{
static class DetectorBuilder
{
public static void Make(GameObject body, OWRigidbody OWRB, AstroObject primaryBody, AstroObject astroObject)
{
GameObject detectorGO = new GameObject("FieldDetector");
detectorGO.SetActive(false);
detectorGO.transform.parent = body.transform;
detectorGO.transform.localPosition = Vector3.zero;
detectorGO.layer = 20;
ConstantForceDetector forceDetector = detectorGO.AddComponent<ConstantForceDetector>();
forceDetector.SetValue("_inheritElement0", true);
OWRB.RegisterAttachedForceDetector(forceDetector);
GravityVolume parentGravityVolume = primaryBody.GetAttachedOWRigidbody().GetAttachedGravityVolume();
if (parentGravityVolume != null)
{
forceDetector.SetValue("_detectableFields", new ForceVolume[] { parentGravityVolume });
}
else
{
// It's probably a focal point (or its just broken)
var binaryFocalPoint = primaryBody.gameObject.GetComponent<BinaryFocalPoint>();
if(binaryFocalPoint != null)
{
if(astroObject.GetCustomName().Equals(binaryFocalPoint.PrimaryName)) {
binaryFocalPoint.Primary = astroObject;
if (binaryFocalPoint.Secondary != null)
{
var secondaryRB = binaryFocalPoint.Secondary.GetAttachedOWRigidbody();
SetBinaryForceDetectableFields(binaryFocalPoint, forceDetector, secondaryRB.GetAttachedForceDetector(), OWRB, secondaryRB);
}
}
else if (astroObject.GetCustomName().Equals(binaryFocalPoint.SecondaryName))
{
binaryFocalPoint.Secondary = astroObject;
if (binaryFocalPoint.Primary != null)
{
var primaryRB = binaryFocalPoint.Primary.GetAttachedOWRigidbody();
SetBinaryForceDetectableFields(binaryFocalPoint, primaryRB.GetAttachedForceDetector(), forceDetector, primaryRB, OWRB);
}
}
else
{
// It's a planet
binaryFocalPoint.Planets.Add(astroObject);
if(binaryFocalPoint.Primary != null && binaryFocalPoint.Secondary != null)
{
var primaryGravityVolume = binaryFocalPoint.Primary.GetGravityVolume();
var secondaryGravityVolume = binaryFocalPoint.Secondary.GetGravityVolume();
forceDetector.SetValue("_detectableFields", new ForceVolume[] { primaryGravityVolume, secondaryGravityVolume });
}
}
}
}
detectorGO.SetActive(true);
}
private static void SetBinaryForceDetectableFields(BinaryFocalPoint point, ForceDetector primaryCFD, ForceDetector secondaryCFD, OWRigidbody primaryRB, OWRigidbody secondaryRB)
{
Logger.Log($"Setting up binary focal point for {point.name}");
var primary = point.Primary;
var secondary = point.Secondary;
var planets = point.Planets;
// Binaries have to use inverse square gravity so overwrite it now
var primaryGV = primary.GetGravityVolume();
//primaryGV.SetValue("_falloffType", primaryGV.GetType().GetNestedType("FalloffType", BindingFlags.NonPublic).GetField("inverseSquared").GetValue(primaryGV));
//primaryGV.SetValue("_falloffExponent", 2);
var secondaryGV = secondary.GetGravityVolume();
//secondaryGV.SetValue("_falloffType", secondaryGV.GetType().GetNestedType("FalloffType", BindingFlags.NonPublic).GetField("inverseSquared").GetValue(secondaryGV));
//secondaryGV.SetValue("_falloffExponent", 2);
// Very specific distance between them
Vector3 separation = primary.transform.position - secondary.transform.position;
var Gm1 = primaryGV.GetStandardGravitationalParameter();
var Gm2 = secondaryGV.GetStandardGravitationalParameter();
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;
// Set detectable fields
primaryCFD.SetValue("_detectableFields", new ForceVolume[] { secondaryGV });
primaryCFD.SetValue("_inheritDetector", point.GetAttachedOWRigidbody().GetAttachedForceDetector());
primaryCFD.SetValue("_activeInheritedDetector", point.GetAttachedOWRigidbody().GetAttachedForceDetector());
primaryCFD.SetValue("_inheritElement0", false);
secondaryCFD.SetValue("_detectableFields", new ForceVolume[] { primaryGV });
secondaryCFD.SetValue("_inheritDetector", point.GetAttachedOWRigidbody().GetAttachedForceDetector());
secondaryCFD.SetValue("_activeInheritedDetector", point.GetAttachedOWRigidbody().GetAttachedForceDetector());
secondaryCFD.SetValue("_inheritElement0", false);
// Update speeds
var direction = Vector3.Cross(separation, Vector3.up).normalized;
var m1 = primaryRB.GetMass();
var m2 = secondaryRB.GetMass();
var reducedMass = m1 * m2 / (m1 + m2);
var r = separation.magnitude;
float v1 = OrbitalHelper.GetOrbitalVelocity(r, new Gravity(secondaryGV.GetFalloffExponent(), reducedMass), KeplerElements.FromTrueAnomaly(0.5f, r, 0, 0, 0, 0));
float v2 = OrbitalHelper.GetOrbitalVelocity(r, new Gravity(primaryGV.GetFalloffExponent(), reducedMass), KeplerElements.FromTrueAnomaly(0.5f, r, 0, 0, 0, 180));
Logger.Log($"Speed: {v1} {v2}");
primaryRB.UpdateCenterOfMass();
primaryRB.AddVelocityChange(direction * v1);
secondaryRB.UpdateCenterOfMass();
secondaryRB.AddVelocityChange(direction * -v2);
/*
//Hacky but whatever
var primaryInitialMotion = primary.gameObject.GetComponent<InitialMotion>();
if(primaryInitialMotion.GetValue<bool>("_isInitVelocityDirty"))
primaryInitialMotion.SetValue("_cachedInitVelocity", OWPhysics.CalculateOrbitVelocity(secondaryRB, primaryRB, 0f));
else
primaryInitialMotion.SetPrimaryBody(secondaryRB);
var secondaryInitialMotion = primary.gameObject.GetComponent<InitialMotion>();
if (secondaryInitialMotion.GetValue<bool>("_isInitVelocityDirty"))
secondaryInitialMotion.SetValue("_cachedInitVelocity", OWPhysics.CalculateOrbitVelocity(primaryRB, secondaryRB, 0f));
else
secondaryInitialMotion.SetPrimaryBody(primaryRB);
*/
}
}
}

View File

@ -4,7 +4,7 @@ using System.Reflection;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.General
namespace NewHorizons.Builder.General
{
static class GravityBuilder
{

View File

@ -4,7 +4,7 @@ using System.Reflection;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.General
namespace NewHorizons.Builder.General
{
static class MarkerBuilder
{

View File

@ -8,7 +8,7 @@ using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.General
namespace NewHorizons.Builder.General
{
static class PlanetDestroyer
{

View File

@ -3,7 +3,7 @@ using OWML.Utils;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.General
namespace NewHorizons.Builder.General
{
static class RFVolumeBuilder
{

View File

@ -4,7 +4,7 @@ using System.Collections.Generic;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Body
namespace NewHorizons.Builder.General
{
static class MakeSector
{

View File

@ -4,7 +4,7 @@ using System;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.General
namespace NewHorizons.Builder.General
{
static class SpawnPointBuilder
{

View File

@ -0,0 +1,21 @@
using NewHorizons.External;
using NewHorizons.OrbitalPhysics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Builder.Orbital
{
static class FocalPointBuilder
{
public static void Make(GameObject go, FocalPointModule module)
{
var binary = go.AddComponent<BinaryFocalPoint>();
binary.PrimaryName = module.Primary;
binary.SecondaryName = module.Secondary;
}
}
}

View File

@ -11,7 +11,7 @@ using Logger = NewHorizons.Utility.Logger;
using System.Reflection;
using NewHorizons.Utility;
namespace NewHorizons.General
namespace NewHorizons.Builder.Orbital
{
static class InitialMotionBuilder
{
@ -33,23 +33,31 @@ namespace NewHorizons.General
*/
InitialMotion initialMotion = body.AddComponent<InitialMotion>();
return Update(initialMotion, body, primaryBody, OWRB, orbit);
}
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);
initialMotion.SetValue("_initAngularSpeed", orbit.SiderealPeriod == 0 ? 0.02f : 1.0f / orbit.SiderealPeriod);
if(orbit.Eccentricity != 0)
if (orbit.Eccentricity != 0 && primaryBody.GetGravityVolume() != null)
{
// Calculate speed at apoapsis
var eccSpeed = OrbitalHelper.Visviva(primaryBody.GetGravityVolume().GetFalloffType(),
primaryBody.GetGravityVolume().GetStandardGravitationalParameter(),
orbit.SemiMajorAxis * (1 + orbit.Eccentricity),
orbit.SemiMajorAxis,
orbit.Eccentricity
);
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;
body.transform.rotation = Quaternion.FromToRotation(Vector3.up, rotationAxis);

View File

@ -5,7 +5,7 @@ using OWML.Utils;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.General
namespace NewHorizons.Builder.Orbital
{
static class OrbitlineBuilder
{
@ -15,29 +15,27 @@ namespace NewHorizons.General
orbitGO.transform.parent = body.transform;
orbitGO.transform.localPosition = Vector3.zero;
var LR = orbitGO.AddComponent<LineRenderer>();
var lineRenderer = orbitGO.AddComponent<LineRenderer>();
var thLR = GameObject.Find("OrbitLine_CO").GetComponent<LineRenderer>();
LR.material = thLR.material;
LR.useWorldSpace = false;
LR.loop = false;
lineRenderer.material = GameObject.Find("OrbitLine_CO").GetComponent<LineRenderer>().material;
lineRenderer.useWorldSpace = false;
lineRenderer.loop = false;
if(orbit.Eccentricity == 0)
{
OrbitLine ol = orbitGO.AddComponent<OrbitLine>();
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[] { });
OrbitLine orbitLine = orbitGO.AddComponent<OrbitLine>();
orbitLine.SetValue("_astroObject", astroobject);
orbitLine.SetValue("_fade", isMoon);
orbitLine.SetValue("_lineWidth", 0.3f);
typeof(OrbitLine).GetMethod("InitializeLineRenderer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Invoke(orbitLine, new object[] { });
}
else
{
OrbitLine ol = orbitGO.AddComponent<EllipticOrbitLine>();
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[] { });
OrbitLine orbitLine = orbitGO.AddComponent<EllipticOrbitLine>();
orbitLine.SetValue("_astroObject", astroobject);
orbitLine.SetValue("_fade", isMoon);
orbitLine.SetValue("_lineWidth", 0.3f);
typeof(OrbitLine).GetMethod("InitializeLineRenderer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Invoke(orbitLine, new object[] { });
}
/*

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NewHorizons.External
{
public class FocalPointModule
{
public string Primary { get; set; }
public string Secondary { get; set; }
}
}

View File

@ -15,6 +15,7 @@ namespace NewHorizons.External
ProcGenModule ProcGen { get; }
AsteroidBeltModule AsteroidBelt { get; }
StarModule Star { get; }
FocalPointModule FocalPoint { get; }
SpawnModule Spawn { get; }
}
}

View File

@ -20,5 +20,6 @@ namespace NewHorizons.External
public float SiderealPeriod { get; set; }
public bool IsTidallyLocked { get; set; }
public bool ShowOrbitLine { get; set; } = true;
public bool IsStatic { get; set; }
}
}

View File

@ -1,6 +1,7 @@
using NewHorizons.Utility;
using System;
using System.Collections.Generic;
using System.Globalization;
namespace NewHorizons.External
{
@ -18,6 +19,7 @@ namespace NewHorizons.External
public ProcGenModule ProcGen { get; set; }
public AsteroidBeltModule AsteroidBelt { get; set; }
public StarModule Star { get; set; }
public FocalPointModule FocalPoint { get; set; }
public SpawnModule Spawn { get; set; }
public PlanetConfig(Dictionary<string, object> dict)
@ -30,6 +32,31 @@ namespace NewHorizons.External
foreach (var item in dict)
{
var property = typeof(PlanetConfig).GetProperty(item.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
if(property == null)
property = typeof(PlanetConfig).GetProperty(item.Key.ToCamelCase(), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
if (property == null)
property = typeof(PlanetConfig).GetProperty(item.Key.ToTitleCase(), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
if (property != null)
{
if (property.PropertyType.BaseType == typeof(Module))
{
if (property.GetValue(this) == null)
{
var module = Activator.CreateInstance(property.PropertyType);
property.SetValue(this, module);
}
((Module)property.GetValue(this)).Build(item.Value as Dictionary<string, object>);
}
else
{
property.SetValue(this, Convert.ChangeType(item.Value, property.PropertyType));
}
}
else Logger.LogError($"{item.Key} {item.Value} is not valid. Is your config formatted correctly?");
/*
switch(item.Key)
{
case "Base":
@ -68,6 +95,7 @@ namespace NewHorizons.External
else Logger.LogError($"{item.Key} {item.Value} is not valid. Is your config formatted correctly?");
break;
}
*/
}
}
}

View File

@ -1,28 +0,0 @@
using OWML.Utils;
using System;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.General
{
static class DetectorBuilder
{
public static void Make(GameObject body, AstroObject primaryBody)
{
GameObject detectorGO = new GameObject("FieldDetector");
detectorGO.SetActive(false);
detectorGO.transform.parent = body.transform;
detectorGO.transform.localPosition = Vector3.zero;
detectorGO.layer = 20;
ConstantForceDetector CFD = detectorGO.AddComponent<ConstantForceDetector>();
GravityVolume parentGravityVolume = primaryBody.GetAttachedOWRigidbody().GetAttachedGravityVolume();
CFD.SetValue("_detectableFields", new ForceVolume[] { parentGravityVolume });
CFD.SetValue("_inheritElement0", true);
detectorGO.SetActive(true);
}
}
}

View File

@ -1,7 +1,9 @@
using NewHorizons.Atmosphere;
using NewHorizons.Body;
using NewHorizons.Builder.Body;
using NewHorizons.Builder.General;
using NewHorizons.Builder.Orbital;
using NewHorizons.External;
using NewHorizons.General;
using NewHorizons.OrbitalPhysics;
using NewHorizons.Utility;
using OWML.Common;
@ -34,7 +36,7 @@ namespace NewHorizons
return new NewHorizonsApi();
}
void Start()
public void Start()
{
SceneManager.sceneLoaded += OnSceneLoaded;
Instance = this;
@ -54,8 +56,9 @@ namespace NewHorizons
}
}
void Destroy()
public void Destroy()
{
Logger.Log($"Destroying NewHorizons");
SceneManager.sceneLoaded -= OnSceneLoaded;
}
@ -73,9 +76,11 @@ namespace NewHorizons
// Stars then planets then moons
BodyList = BodyList.OrderBy(b =>
(b.Config.BuildPriority != -1 ? b.Config.BuildPriority : (b.Config.Star != null) ? 0 :
(b.Config.BuildPriority != -1 ? b.Config.BuildPriority :
(b.Config.FocalPoint != null ? 0 :
(b.Config.Star != null) ? 0 :
(b.Config.Orbit.IsMoon ? 2 : 1)
)).ToList();
))).ToList();
var flagNoneLoadedThisPass = true;
while(BodyList.Count != 0)
@ -248,14 +253,14 @@ namespace NewHorizons
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];
var ao = (AstroObject)outputTuple.Item1;
var owRigidBody = (OWRigidbody)outputTuple.Item2;
if (body.Config.Base.SurfaceGravity != 0)
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);
RFVolumeBuilder.Make(go, owRigidBody, sphereOfInfluence);
if (body.Config.Base.HasMapMarker)
MarkerBuilder.Make(go, body.Config.Name, body.Config.Orbit.IsMoon, body.Config.Star != null);
@ -263,7 +268,8 @@ namespace NewHorizons
if (body.Config.Base.HasAmbientLight)
AmbientLightBuilder.Make(go, sphereOfInfluence);
var sector = MakeSector.Make(go, rb, sphereOfInfluence);
var sector = MakeSector.Make(go, owRigidBody, sphereOfInfluence);
ao.SetValue("_rootSector", sector);
VolumesBuilder.Make(go, body.Config.Base.SurfaceSize, sphereOfInfluence);
@ -279,15 +285,14 @@ namespace NewHorizons
if (body.Config.Star != null)
StarBuilder.Make(go, sector, body.Config.Star);
if (body.Config.FocalPoint != null)
FocalPointBuilder.Make(go, body.Config.FocalPoint);
// Do stuff that's shared between generating new planets and updating old ones
go = SharedGenerateBody(body, go, sector, rb);
go = SharedGenerateBody(body, go, sector, owRigidBody);
body.Object = go;
// Some things have to be done the second tick
if(body.Config.Orbit != null && body.Config.Orbit.ShowOrbitLine)
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => OrbitlineBuilder.Make(body.Object, ao, body.Config.Orbit.IsMoon, body.Config.Orbit));
// Now that we're done move the planet into place
go.transform.parent = Locator.GetRootTransform();
go.transform.position = positionVector + primaryBody.transform.position;
@ -298,14 +303,22 @@ namespace NewHorizons
}
// Have to do this after setting position
InitialMotionBuilder.Make(go, primaryBody, rb, body.Config.Orbit);
InitialMotionBuilder.Make(go, primaryBody, owRigidBody, body.Config.Orbit);
//if (!body.Config.Orbit.IsStatic) DetectorBuilder.Make(go, owRigidBody, primaryBody, ao);
if (!body.Config.Orbit.IsStatic) Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => DetectorBuilder.Make(go, owRigidBody, primaryBody, ao));
// Spawning on other planets is a bit hacky so we do it last
if (body.Config.Spawn != null)
{
SpawnPointBuilder.Make(go, body.Config.Spawn, rb);
SpawnPointBuilder.Make(go, body.Config.Spawn, owRigidBody);
}
// Some things have to be done the second tick
if (body.Config.Orbit != null && body.Config.Orbit.ShowOrbitLine)
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => OrbitlineBuilder.Make(body.Object, ao, body.Config.Orbit.IsMoon, body.Config.Orbit));
if (ao.GetAstroObjectName() == AstroObject.Name.CustomString) AstroObjectLocator.RegisterCustomAstroObject(ao);
Logger.Log("Generation of [" + body.Config.Name + "] completed.", Logger.LogType.Log);

View File

@ -229,18 +229,20 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Atmosphere\FogBuilder.cs" />
<Compile Include="Body\AsteroidBeltBuilder.cs" />
<Compile Include="Body\CometTailBuilder.cs" />
<Compile Include="Body\Geometry\CubeSphere.cs" />
<Compile Include="Body\Geometry\Icosphere.cs" />
<Compile Include="Body\Geometry\Perlin.cs" />
<Compile Include="Body\HeightMapBuilder.cs" />
<Compile Include="Body\ProcGenBuilder.cs" />
<Compile Include="Body\StarBuilder.cs" />
<Compile Include="Builder\Atmosphere\FogBuilder.cs" />
<Compile Include="Builder\Body\AsteroidBeltBuilder.cs" />
<Compile Include="Builder\Body\CometTailBuilder.cs" />
<Compile Include="Builder\Body\Geometry\CubeSphere.cs" />
<Compile Include="Builder\Body\Geometry\Icosphere.cs" />
<Compile Include="Builder\Body\Geometry\Perlin.cs" />
<Compile Include="Builder\Body\HeightMapBuilder.cs" />
<Compile Include="Builder\Body\ProcGenBuilder.cs" />
<Compile Include="Builder\Body\StarBuilder.cs" />
<Compile Include="Builder\Orbital\FocalPointBuilder.cs" />
<Compile Include="External\AsteroidBeltModule.cs" />
<Compile Include="External\AtmosphereModule.cs" />
<Compile Include="External\BaseModule.cs" />
<Compile Include="External\FocalPointModule.cs" />
<Compile Include="External\HeightMapModule.cs" />
<Compile Include="External\Module.cs" />
<Compile Include="External\OrbitModule.cs" />
@ -248,34 +250,37 @@
<Compile Include="External\RingModule.cs" />
<Compile Include="External\SpawnModule.cs" />
<Compile Include="External\StarModule.cs" />
<Compile Include="General\BaseBuilder.cs" />
<Compile Include="Body\BlackHoleBuilder.cs" />
<Compile Include="General\DetectorBuilder.cs" />
<Compile Include="General\GravityBuilder.cs" />
<Compile Include="Body\LavaBuilder.cs" />
<Compile Include="General\InitialMotionBuilder.cs" />
<Compile Include="General\MarkerBuilder.cs" />
<Compile Include="General\OrbitlineBuilder.cs" />
<Compile Include="General\PlanetDestroyer.cs" />
<Compile Include="General\RFVolumeBuilder.cs" />
<Compile Include="Body\RingBuilder.cs" />
<Compile Include="General\SectorBuilder.cs" />
<Compile Include="General\SpawnPointBuilder.cs" />
<Compile Include="Builder\General\BaseBuilder.cs" />
<Compile Include="Builder\Body\BlackHoleBuilder.cs" />
<Compile Include="Builder\General\DetectorBuilder.cs" />
<Compile Include="Builder\General\GravityBuilder.cs" />
<Compile Include="Builder\Body\LavaBuilder.cs" />
<Compile Include="Builder\Orbital\InitialMotionBuilder.cs" />
<Compile Include="Builder\General\MarkerBuilder.cs" />
<Compile Include="Builder\Orbital\OrbitlineBuilder.cs" />
<Compile Include="Builder\General\PlanetDestroyer.cs" />
<Compile Include="Builder\General\RFVolumeBuilder.cs" />
<Compile Include="Builder\Body\RingBuilder.cs" />
<Compile Include="Builder\General\SectorBuilder.cs" />
<Compile Include="Builder\General\SpawnPointBuilder.cs" />
<Compile Include="OrbitalPhysics\BinaryFocalPoint.cs" />
<Compile Include="OrbitalPhysics\CartesianStateVectors.cs" />
<Compile Include="OrbitalPhysics\Gravity.cs" />
<Compile Include="OrbitalPhysics\KeplerElements.cs" />
<Compile Include="OrbitalPhysics\ParameterizedInitialMotion.cs" />
<Compile Include="OrbitalPhysics\OrbitalHelper.cs" />
<Compile Include="Utility\AddDebugShape.cs" />
<Compile Include="General\AmbientLightBuilder.cs" />
<Compile Include="Builder\General\AmbientLightBuilder.cs" />
<Compile Include="External\IPlanetConfig.cs" />
<Compile Include="External\PlanetConfig.cs" />
<Compile Include="Body\GeometryBuilder.cs" />
<Compile Include="Body\WaterBuilder.cs" />
<Compile Include="Atmosphere\AirBuilder.cs" />
<Compile Include="Atmosphere\AtmosphereBuilder.cs" />
<Compile Include="Atmosphere\CloudsBuilder.cs" />
<Compile Include="Atmosphere\EffectsBuilder.cs" />
<Compile Include="Atmosphere\SunOverrideBuilder.cs" />
<Compile Include="Atmosphere\VolumesBuilder.cs" />
<Compile Include="Builder\Body\GeometryBuilder.cs" />
<Compile Include="Builder\Body\WaterBuilder.cs" />
<Compile Include="Builder\Atmosphere\AirBuilder.cs" />
<Compile Include="Builder\Atmosphere\AtmosphereBuilder.cs" />
<Compile Include="Builder\Atmosphere\CloudsBuilder.cs" />
<Compile Include="Builder\Atmosphere\EffectsBuilder.cs" />
<Compile Include="Builder\Atmosphere\SunOverrideBuilder.cs" />
<Compile Include="Builder\Atmosphere\VolumesBuilder.cs" />
<Compile Include="Main.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utility\AddToUITable.cs" />
@ -288,7 +293,6 @@
<Compile Include="Utility\NewHorizonBody.cs" />
<Compile Include="Utility\NewHorizonExtensions.cs" />
<Compile Include="Utility\MColor32.cs" />
<Compile Include="Utility\MTuple.cs" />
<Compile Include="Utility\MVector3.cs" />
<Compile Include="Utility\Patches.cs" />
</ItemGroup>

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.OrbitalPhysics
{
public class BinaryFocalPoint : MonoBehaviour
{
public string PrimaryName = null;
public string SecondaryName = null;
public AstroObject Primary = null;
public AstroObject Secondary = null;
public List<AstroObject> Planets { get; private set; } = new List<AstroObject>();
}
}

View File

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

@ -0,0 +1,101 @@
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; }
public float EccentricAnomaly { get; }
public float MeanAnomaly { get; }
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 eccentricAnomaly = EccentricAnomalyFromTrueAnomaly(trueAnomaly, e);
var meanAnomaly = MeanAnomalyFromEccentricAnomaly(eccentricAnomaly, e);
return new KeplerElements(e, a, i, longitudeOfAscendingNode, argumentOfPeriapsis, trueAnomaly, eccentricAnomaly, meanAnomaly);
}
public static KeplerElements FromMeanAnomaly(float e, float a, float i, float longitudeOfAscendingNode, float argumentOfPeriapsis, float meanAnomaly)
{
var trueAnomaly = TrueAnomalyFromMeanAnomaly(meanAnomaly, e);
var eccentricAnomaly = EccentricAnomalyFromTrueAnomaly(trueAnomaly, e);
return new KeplerElements(e, a, i, longitudeOfAscendingNode, argumentOfPeriapsis, trueAnomaly, eccentricAnomaly, meanAnomaly);
}
public static KeplerElements FromEccentricAnomaly(float e, float a, float i, float longitudeOfAscendingNode, float argumentOfPeriapsis, float eccentricAnomaly)
{
var trueAnomaly = TrueAnomalyFromEccentricAnomaly(eccentricAnomaly, e);
var meanAnomaly = MeanAnomalyFromEccentricAnomaly(eccentricAnomaly, e);
return new KeplerElements(e, a, i, longitudeOfAscendingNode, argumentOfPeriapsis, trueAnomaly, eccentricAnomaly, meanAnomaly);
}
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

@ -14,83 +14,46 @@ namespace NewHorizons.OrbitalPhysics
public enum FalloffType
{
inverseSquared,
linear
linear,
none
}
public static CartesianStateVectors CartesianStateVectorsFromTrueAnomaly(float standardGraviationalParameter, float eccentricity, float semiMajorAxis, float inclination,
float longitudeOfAscendingNode, float argumentOfPeriapsis, float trueAnomaly, FalloffType falloffType)
public static float GetOrbitalVelocity(float distance, Gravity gravity, KeplerElements kepler)
{
var nu = Mathf.Deg2Rad * trueAnomaly;
var E = Mathf.Atan2(Mathf.Sqrt(1 - eccentricity * eccentricity) * Mathf.Sin(nu), (eccentricity + Mathf.Cos(nu)));
if (kepler.Eccentricity == 0) return GetCircularOrbitVelocity(distance, gravity, kepler);
return CartesianStateVectorsFromOrbitalElements(standardGraviationalParameter, eccentricity, semiMajorAxis, inclination, longitudeOfAscendingNode, argumentOfPeriapsis, E, nu, falloffType);
if (gravity.Exponent == 2)
{
return Mathf.Sqrt(GravityVolume.GRAVITATIONAL_CONSTANT * gravity.Mass * (2f / distance - 1f / kepler.SemiMajorAxis));
}
public static CartesianStateVectors CartesianStateVectorsFromEccentricAnomaly(float standardGraviationalParameter, float eccentricity, float semiMajorAxis, float inclination,
float longitudeOfAscendingNode, float argumentOfPeriapsis, float eccentricAnomaly, FalloffType falloffType)
if(gravity.Exponent == 1)
{
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);
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);
Logger.Log($"{term1}, {term2}, {kepler.Periapsis} {kepler.Apoapsis}, {kepler.SemiMajorAxis}, {kepler.SemiMinorAxis}");
return Mathf.Sqrt(2 * (term1 + term2));
}
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}");
Logger.LogError($"Invalid exponent {gravity.Exponent}");
return 0f;
}
private static Vector3 RotateToOrbitalPlane(Vector3 vector, float longitudeOfAscendingNode, float argumentOfPeriapsis, float inclination)
public static float GetCircularOrbitVelocity(float distance, Gravity gravity, KeplerElements kepler)
{
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;
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;
}
}
}

View File

@ -11,6 +11,7 @@ namespace NewHorizons.OrbitalPhysics
{
public class ParameterizedInitialMotion : InitialMotion
{
/*
private new void Awake()
{
_rotationAxis = base.transform.TransformDirection(_rotationAxis);
@ -106,5 +107,6 @@ namespace NewHorizons.OrbitalPhysics
private float _initAngularSpeed;
private OWRigidbody _satelliteBody;
*/
}
}

View File

@ -13,6 +13,7 @@ namespace NewHorizons.OrbitalPhysics
{
public class ParameterizedOrbitLine : OrbitLine
{
/*
protected override void InitializeLineRenderer()
{
base.GetComponent<LineRenderer>().positionCount = this._numVerts;
@ -122,5 +123,6 @@ namespace NewHorizons.OrbitalPhysics
private InitialMotion _initialMotion;
private AstroObject _primary;
private OrbitalHelper.FalloffType _falloffType;
*/
}
}

View File

@ -1,15 +0,0 @@
using System.Collections.Generic;
using System.Linq;
namespace NewHorizons.Utility
{
public class MTuple
{
public MTuple(params object[] _items)
{
Items = _items.ToList();
}
public List<object> Items { get; }
}
}

View File

@ -1,6 +1,7 @@
using NewHorizons.OrbitalPhysics;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using UnityEngine;
namespace NewHorizons.Utility
@ -19,9 +20,30 @@ namespace NewHorizons.Utility
public static OrbitalHelper.FalloffType GetFalloffType(this GravityVolume gv)
{
if (gv == null) return OrbitalHelper.FalloffType.none;
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;
}
public static float GetFalloffExponent(this GravityVolume gv)
{
if (gv == null) return 0;
return (float)typeof(GravityVolume).GetField("_falloffExponent", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(gv);
}
public static string ToCamelCase(this string str)
{
StringBuilder strBuilder = new StringBuilder(str);
strBuilder[0] = strBuilder[0].ToString().ToLower().ToCharArray()[0];
return strBuilder.ToString();
}
public static string ToTitleCase(this string str)
{
StringBuilder strBuilder = new StringBuilder(str);
strBuilder[0] = strBuilder[0].ToString().ToUpper().ToCharArray()[0];
return strBuilder.ToString();
}
}
}