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);
    }
Esempio n. 2
0
    /// <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);
            }
        }
    }