public static void SetupGravityEngine(GameObject centerBody, GameObject orbitingBody) { GravityEngine ge = GravityEngine.Instance(); if (ge == null) { Debug.LogError("No GE in scene"); } if (ge.evolveAtStart) { Debug.LogError("Evolve at start set. Are you in the TestRunner scene?"); } else if (ge.detectNbodies) { Debug.LogError("Detect NBodies at start set. Are you in the TestRunner scene?"); } ge.UnitTestAwake(); ge.Clear(); ge.AddBody(centerBody); if (orbitingBody != null) { ge.AddBody(orbitingBody); } ge.Setup(); ge.LogDump(); }
private void TestRV(OrbitData od, GameObject planet, NBody starNbody, float orbitRadius) { GameObject testPlanet = TestSetupUtils.CreatePlanetInOrbitUniversal(starNbody, 1f, orbitRadius); OrbitUniversal orbitU = testPlanet.GetComponent <OrbitUniversal>(); // Run init explicitly to update transform details orbitU.InitFromOrbitData(od, 0); // Awkward but previously could not add a new object to GE when it is stopped, so re-add all three // Leave as is, since it works! GravityEngine ge = GravityEngine.Instance(); ge.Clear(); ge.AddBody(starNbody.gameObject); ge.AddBody(planet); ge.AddBody(testPlanet); ge.Setup(); ge.LogDump(); Vector3 r_od = ge.GetPhysicsPosition(testPlanet.GetComponent <NBody>()); Vector3 v_od = ge.GetVelocity(testPlanet); Vector3 r_i = ge.GetPhysicsPosition(planet.GetComponent <NBody>()); Vector3 v_i = ge.GetVelocity(planet); Debug.Log(" r_i=" + r_i + " r_od=" + r_od + " delta=" + Vector3.Distance(r_i, r_od)); Debug.Log(" v_i=" + v_i + " v_od=" + v_od + " delta=" + Vector3.Distance(v_i, v_od)); Assert.IsTrue(GEUnit.FloatEqual(Vector3.Distance(r_i, r_od), 0f, 1E-2)); Assert.IsTrue(GEUnit.FloatEqual(Vector3.Distance(v_i, v_od), 0f, 1E-2)); }
private void TestRV(OrbitData od, GameObject planet, GameObject star) { GameObject testPlanet = TestSetupUtils.CreatePlanetInHyper(star, 1f); testPlanet.name = "TestPlanet"; OrbitHyper testHyper = testPlanet.GetComponent <OrbitHyper>(); testHyper.InitFromOrbitData(od); planet.name = "Planet"; // Awkward but cannot add a new object to GE when it is stopped, so re-add all three GravityEngine ge = GravityEngine.Instance(); ge.Clear(); ge.AddBody(star); ge.AddBody(planet); ge.AddBody(testPlanet); ge.Setup(); ge.LogDump(); Vector3 r_od = ge.GetPhysicsPosition(testPlanet.GetComponent <NBody>()); Vector3 v_od = ge.GetVelocity(testPlanet); Vector3 r_i = ge.GetPhysicsPosition(planet.GetComponent <NBody>()); Vector3 v_i = ge.GetVelocity(planet); Debug.Log(" r_i=" + r_i + " r_od=" + r_od + " delta=" + Vector3.Distance(r_i, r_od)); Debug.Log(" v_i=" + v_i + " v_od=" + v_od + " delta=" + Vector3.Distance(v_i, v_od)); Assert.IsTrue(FloatEqual(Vector3.Distance(r_i, r_od), 0f, 5E-2)); Assert.IsTrue(FloatEqual(Vector3.Distance(v_i, v_od), 0f, 5E-2)); }
private void TestRV(OrbitData od, GameObject planet, GameObject star, float orbitRadius) { GameObject testPlanet = TestSetupUtils.CreatePlanetInOrbit(star, 1f, orbitRadius); OrbitEllipse testEllipse = testPlanet.GetComponent <OrbitEllipse>(); // Run init explicitly to update transform details testEllipse.InitFromOrbitData(od); // Awkward but cannot add a new object to GE when it is stopped, so re-add all three GravityEngine ge = GravityEngine.Instance(); ge.Clear(); ge.AddBody(star); ge.AddBody(planet); ge.AddBody(testPlanet); ge.Setup(); ge.LogDump(); Vector3 r_od = ge.GetPhysicsPosition(testPlanet.GetComponent <NBody>()); Vector3 v_od = ge.GetVelocity(testPlanet); Vector3 r_i = ge.GetPhysicsPosition(planet.GetComponent <NBody>()); Vector3 v_i = ge.GetVelocity(planet); Debug.Log(" r_i=" + r_i + " r_od=" + r_od + " delta=" + Vector3.Distance(r_i, r_od)); Debug.Log(" v_i=" + v_i + " v_od=" + v_od + " delta=" + Vector3.Distance(v_i, v_od)); Assert.IsTrue(FloatEqual(Vector3.Distance(r_i, r_od), 0f, 1E-2)); Assert.IsTrue(FloatEqual(Vector3.Distance(v_i, v_od), 0f, 1E-2)); }
private void AddGhostBodies() { // Create a ghost moon and put soiEnter/Exit ships into orbit around it. Add all to GE // (ghost moon does not have an OrbitPredictor) ghostMoon = new NBody[2]; ghostMoonOrbit = new OrbitUniversal[2]; for (int i = 0; i < 2; i++) { GameObject ghostMoonGO = Instantiate(moonBody.gameObject); ghostMoon[i] = ghostMoonGO.GetComponent <NBody>(); ghostMoonOrbit[i] = ghostMoonGO.GetComponent <OrbitUniversal>(); } ghostMoon[MOON_SOI_ENTER].gameObject.name = "GhostMoon (SOI enter)"; ghostMoon[MOON_SOI_EXIT].gameObject.name = "GhostMoon (SOI exit)"; ghostMoonSoiEnterOrbitPredictor = ghostMoon[MOON_SOI_ENTER].GetComponentInChildren <OrbitPredictor>(); ghostMoon[MOON_SOI_ENTER].GetComponentInChildren <LineRenderer>().material = toMoonMaterial; ghostMoon[MOON_SOI_EXIT].GetComponentInChildren <LineRenderer>().material = fromMoonMaterial; ghostShip = new NBody[NUM_GHOST_SHIPS]; ghostShipOrbit = new OrbitUniversal[NUM_GHOST_SHIPS]; ghostShipOrbitPredictor = new OrbitPredictor[NUM_GHOST_SHIPS]; GameObject ghostShipGO; for (int i = 0; i < NUM_GHOST_SHIPS; i++) { ghostShipGO = Instantiate(shipSOIPrefab); ghostShip[i] = ghostShipGO.GetComponent <NBody>(); ghostShipOrbit[i] = ghostShipGO.GetComponent <OrbitUniversal>(); ghostShipOrbit[i].p_inspector = soiRadius; ghostShipOrbit[i].centerNbody = planet; ghostShipOrbitPredictor[i] = ghostShipGO.GetComponentInChildren <OrbitPredictor>(); ghostShipOrbitPredictor[i].body = ghostShipGO; ghostShipOrbitPredictor[i].centerBody = planet.gameObject; LineRenderer lineR = ghostShipOrbitPredictor[i].GetComponent <LineRenderer>(); lineR.startWidth = lineWidth; lineR.endWidth = lineWidth; ghostShipGO.transform.SetParent(planet.gameObject.transform); } // check prefab has orbitU in Kepler mode if (ghostShipOrbit[0].evolveMode != OrbitUniversal.EvolveMode.KEPLERS_EQN) { Debug.LogError("ShipSoi prefab must have an on-rails OrbitU"); return; } ghostShip[TLI].gameObject.name = "Ghost TLI"; ghostShipOrbit[TLI].p_inspector = shipRadius; ghostShipOrbitPredictor[TLI].GetComponent <LineRenderer>().material = toMoonMaterial; // customize ghost ships as necessary // ENTER_SOI ghostShip[TO_MOON].gameObject.name = "Ghost To Moon"; ghostShipOrbit[TO_MOON].p_inspector = shipRadius; ghostShipOrbitPredictor[TO_MOON].GetComponent <LineRenderer>().material = toMoonMaterial; // SOI Enter ghostShip[ENTER_SOI].gameObject.name = "Ghost SOI Enter"; ghostShip[ENTER_SOI].gameObject.transform.SetParent(ghostMoon[MOON_SOI_ENTER].gameObject.transform); Destroy(ghostShipOrbitPredictor[ENTER_SOI]); // Use OrbitPredictor to show SOI at entry //ghostShipOrbitPredictor[ENTER_SOI].centerBody = ghostMoon[MOON_SOI_ENTER].gameObject; //ghostShipOrbitPredictor[ENTER_SOI].GetComponent<LineRenderer>().material = aroundMoonMaterial; ghostShipOrbit[ENTER_SOI].centerNbody = ghostMoon[MOON_SOI_ENTER]; // HYPER_SOI ghostShip[SOI_HYPER].gameObject.name = "Ghost SOI Hyper"; ghostShip[SOI_HYPER].gameObject.transform.SetParent(ghostMoon[MOON_SOI_ENTER].gameObject.transform); ghostShipOrbitPredictor[SOI_HYPER].centerBody = ghostMoon[MOON_SOI_ENTER].gameObject; ghostShipOrbitPredictor[SOI_HYPER].hyperDisplayRadius = soiRadius; ghostShipOrbit[SOI_HYPER].centerNbody = ghostMoon[MOON_SOI_ENTER]; ghostShipOrbitPredictor[SOI_HYPER].GetComponent <LineRenderer>().material = aroundMoonMaterial; // EXIT_SOI ghostShip[EXIT_SOI].gameObject.name = "Ghost SOI Exit"; ghostShipOrbitPredictor[EXIT_SOI].GetComponent <LineRenderer>().material = fromMoonMaterial; // Tell GE about everything ge.AddBody(ghostMoon[MOON_SOI_ENTER].gameObject); // also adds ENTER_SOI ge.AddBody(ghostShip[TLI].gameObject); ge.AddBody(ghostShip[TO_MOON].gameObject); ge.AddBody(ghostShip[EXIT_SOI].gameObject); ge.AddBody(ghostMoon[MOON_SOI_EXIT].gameObject); // set TLI ship to inactive and control pos/vel in ComputeTransfer ge.InactivateBody(ghostShip[TO_MOON].gameObject); }
/// <summary> /// Take the Nbody objects in the nbodies list set them inactive and make them children of a new /// NBody object moving as the CM of the nbodies. This allows RigidBody mechanics during close /// encounters. /// </summary> private void Activate() { if (nbodies.Length < 2) { Debug.LogError("Need two or more nbodies"); return; } GravityEngine ge = GravityEngine.Instance(); // Step 1: calculate CM position and velocity Vector3d cmPos = new Vector3d(0, 0, 0); Vector3d cmVel = new Vector3d(0, 0, 0); float mass = 0f; rigidBodies = new Rigidbody[nbodies.Length]; // RigidBody is assumed to be attached to one of the children (to keep model scale independent) int i = 0; foreach (NBody nbody in nbodies) { rigidBodies[i] = nbody.GetComponentInChildren <Rigidbody>(); //rigidBodies[i] = nbody.GetComponent<Rigidbody>(); if (rigidBodies[i] == null) { Debug.LogError("Abort - No rigidbody detected on " + nbody.gameObject.name); return; } mass += rigidBodies[i].mass; cmPos += rigidBodies[i].mass * ge.GetPositionDoubleV3(nbody); cmVel += rigidBodies[i].mass * ge.GetVelocityDoubleV3(nbody); i++; } cmPos /= mass; cmVel /= mass; Debug.LogFormat("CM p={0} v={1} mass={2}", cmPos.ToVector3(), cmVel.ToVector3(), mass); // Step2: Inactivate the NBodies and make children of a new NBody object priorParents = new Transform[nbodies.Length]; cmObject = new GameObject("DockingGroupCM"); cmNbody = cmObject.AddComponent <NBody>(); // Set cm pos/vel // NBody InitPosition will use transform or initialPos base on units. Set both. cmNbody.initialPos = cmPos.ToVector3() * ge.physToWorldFactor; cmNbody.transform.position = cmNbody.initialPos; ge.AddBody(cmObject); ge.SetVelocity(cmNbody, cmVel.ToVector3()); Debug.LogFormat("set pos={0} actual={1}", cmPos.ToVector3(), ge.GetPhysicsPosition(cmNbody)); i = 0; foreach (NBody nbody in nbodies) { Vector3d pos = ge.GetPositionDoubleV3(nbody); Vector3d vel = ge.GetVelocityDoubleV3(nbody); priorParents[i] = nbody.gameObject.transform.parent; ge.InactivateBody(nbody.gameObject); nbody.gameObject.transform.parent = cmObject.transform; // position wrt to CM. Need to convert to Unity scene units from GE Internal pos = (pos - cmPos) * ge.physToWorldFactor; vel = GravityScaler.ScaleVelPhysToScene(vel - cmVel); nbody.transform.localPosition = pos.ToVector3(); rigidBodies[i].velocity = vel.ToVector3(); // rigidBodies[i].isKinematic = false; i++; Debug.LogFormat("body {0} p={1} v={2}", nbody.gameObject.name, pos.ToVector3(), vel.ToVector3()); } // activate any RCS elements foreach (ReactionControlSystem r in rcs) { if (r != null) { r.SetRigidBodyEnabled(true); } } }