// Scaling:
    // Setting the size of the ellipse is done via the ellipse base "a". This is
    // entered by the user in the units selected in the GE units chooser. Additionaly the
    // GE inspector may indicate a Unity Units per [km|AU] and this needs to be taken into account
    // in the Gizmo that draws the orbit.
    //

    /// <summary>
    /// Inits the N body position and velocity based on the ellipse parameters and the
    /// position and velocity of the parent.
    /// </summary>
    /// <param name="physicalScale">Physical scale.</param>
    public void InitNBody(float physicalScale, float massScale)
    {
        base.Init();
        float a_phy = a_scaled / physicalScale;

        if (nbody == null)
        {
            nbody = GetComponent <NBody>();
        }

        // Phase is TRUE anomoly f
        float f = phase * Mathf.Deg2Rad;
        // Murray and Dermot
        // (2.26)
        // This should really be (M+m), but assume m << M
        // (massScale is added in at the GE level)
        float n = Mathf.Sqrt((float)(centerNbody.mass * massScale) / (a_phy * a_phy * a_phy));
        // (2.36)
        float denom = Mathf.Sqrt(1f - ecc * ecc);
        float xdot  = -1f * n * a_phy * Mathf.Sin(f) / denom;
        float ydot  = n * a_phy * (ecc + Mathf.Cos(f)) / denom;

        // Init functions are called in the engine by SetupOneBody and calls of parent vs children/grandchildren etc.
        // can be in arbitrary order. A child will need info from parent for position and velocity. Ensure parent
        // has inited. Init may get called more than once.
        centerNbody.InitPosition(GravityEngine.Instance());

        Vector3 v_xy = new Vector3(xdot, ydot, 0);

        // if we're evolving, get the latest velocity
        if (centerNbody.engineRef != null)
        {
            centerNbody.UpdateVelocity();
        }
        Vector3 vphy = ellipse_orientation * v_xy + centerNbody.vel_phys;

        nbody.vel_phys = vphy;
        SetInitialPosition(nbody);
        if (evolveMode == evolveType.KEPLERS_EQN)
        {
            if (Application.isPlaying)
            {
                // Need to force an evolve to update position and velocity so that
                // dependent objects get the correct values.
                GravityEngine ge = GravityEngine.Instance();
                double[]      r  = new double[] { 0, 0, 0 };
                PreEvolve(ge.GetLengthScale(), ge.massScale);
                Evolve(ge.GetPhysicalTime(), ref r);
            }
            else
            {
                // if in the editor/DrawGizmos all we care about is position and above clause
                // causes exceptions, since it asks GE for position/velocity
                position = nbody.initialPhysPosition;
            }
        }
    }
Example #2
0
    // Use this for initialization
    void Start()
    {
        GravityEngine ge = GravityEngine.Instance();

        if (ge.units != GravityScaler.Units.DIMENSIONLESS)
        {
            transform.localScale *= ge.GetLengthScale();
        }
    }
    public override void OnInspectorGUI()
    {
        GUI.changed = false;

        NBody   nbody       = (NBody)target;
        float   mass        = 0f;
        float   size        = 0.1f;
        bool    autoSize    = true;
        Vector3 velocity    = Vector3.zero;
        Vector3 initialPos  = Vector3.zero;
        bool    rotateFrame = false;

        if (GravityEngine.Instance() == null)
        {
            EditorGUILayout.LabelField("Require a GravityEngine in the scene to", EditorStyles.boldLabel);
            EditorGUILayout.LabelField("display NBody component.", EditorStyles.boldLabel);
        }

        GravityEngine ge = GravityEngine.Instance();

        GravityScaler.Units units = ge.units;
        string mass_prompt        = string.Format("Mass ({0})", GravityScaler.MassUnits(units));

        mass = EditorGUILayout.FloatField(new GUIContent(mass_prompt, mTip), (float)nbody.mass);

        // If the velocity is controlled by an EllipseBase, or this NBody is the direct child of
        // BinaryPair or ThreeeBodySolution then don't allowit to be controlled.
        string controlledBy = null;

        if (nbody.transform.gameObject.GetComponent <OrbitEllipse>() != null)
        {
            controlledBy = "Initial position/velocity is set by ellipse parameters.";
        }
        else if (nbody.transform.gameObject.GetComponent <OrbitHyper>() != null)
        {
            controlledBy = "Initial position/velocity is set by hyperbola parameters.";
        }
        else if (nbody.transform.gameObject.GetComponent <OrbitUniversal>() != null)
        {
            controlledBy = "Initial position/velocity is set by OrbitUniversal parameters.";
        }
        else if (nbody.transform.parent != null)
        {
            if (nbody.transform.parent.gameObject.GetComponent <BinaryPair>() != null)
            {
                controlledBy = "Initial position/velocity is set by BinaryPair parent.";
            }
            else if (nbody.transform.parent.gameObject.GetComponent <ThreeBodySolution>() != null)
            {
                controlledBy = "Initial position/velocity is set by ThreeBodySolution parent.";
            }
        }
        if (controlledBy == null)
        {
            switch (units)
            {
            case GravityScaler.Units.DIMENSIONLESS:
                EditorGUILayout.LabelField("Initial position set via transform");
                velocity   = EditorGUILayout.Vector3Field(new GUIContent("Velocity", velTip), nbody.vel);
                initialPos = nbody.transform.position;
                break;

            default:
                string prompt = string.Format("Initial Pos ({0})", GravityScaler.LengthUnits(units));
                initialPos = EditorGUILayout.Vector3Field(new GUIContent(prompt, iposTip), nbody.initialPos);

                prompt   = string.Format("Velocity ({0})", GravityScaler.VelocityUnits(units));
                velocity = EditorGUILayout.Vector3Field(new GUIContent(prompt, velTip), nbody.vel);
                break;
            }
        }
        else
        {
            EditorGUILayout.LabelField(controlledBy, EditorStyles.boldLabel);
            //EditorGUILayout.LabelField(string.Format("vel= {0:F2} {1:F2} {2:F2}", nbody.vel.x, nbody.vel.y, nbody.vel.z));
        }


        // particle capture size
        EditorGUIUtility.labelWidth = 200f;
        EditorGUIUtility.fieldWidth = 20f;
        rotateFrame = EditorGUILayout.Toggle(new GUIContent("Maintain prograde orientation", rotateTip), nbody.rotateFrame);
        autoSize    = EditorGUILayout.Toggle(new GUIContent("Automatic particle capture size", autoTip), nbody.automaticParticleCapture);
        EditorGUIUtility.labelWidth = 0;
        EditorGUIUtility.fieldWidth = 0;
        if (!autoSize)
        {
            EditorGUIUtility.labelWidth = 200f;
            EditorGUIUtility.fieldWidth = 40f;
            size = EditorGUILayout.FloatField(new GUIContent("Particle capture radius", sizeTip), (float)nbody.size);
            EditorGUIUtility.labelWidth = 0;
            EditorGUIUtility.fieldWidth = 0;
        }
        else
        {
            float detectedSize = nbody.CalculateSize();
            if (detectedSize < 0)
            {
                EditorGUILayout.LabelField("Did not detect a child with a MeshFilter.", EditorStyles.boldLabel);
                EditorGUILayout.LabelField("Using size=" + size);
            }
            else
            {
                EditorGUILayout.LabelField("Particle Capture radius=" + detectedSize);
                size = detectedSize;
            }
        }
        //if (nbody.transform.hasChanged) {
        //	// User has dragged the object and the transform has changed, need
        //	// to change the initial Pos to correspond to this position in the correct units
        //	if (units != GravityScaler.Units.DIMENSIONLESS) {
        //		initialPos = nbody.transform.position/ge.GetLengthScale();
        //	}
        //	nbody.initialPos = initialPos;
        //	nbody.transform.hasChanged = false;
        //}

        if (GUI.changed)
        {
            Undo.RecordObject(nbody, "NBody Change");
            nbody.mass        = FixNaN.FixIfNaN(mass);
            nbody.vel         = FixNaN.FixIfNaN(velocity);
            nbody.size        = size;
            nbody.rotateFrame = rotateFrame;
            nbody.automaticParticleCapture = autoSize;
            nbody.initialPos = initialPos;
            Debug.Log("new v=" + velocity);
            // must be after initialPos is updated
            nbody.ApplyScale(ge.GetLengthScale(),
                             ge.GetVelocityScale());
            nbody.EditorUpdate(GravityEngine.Instance());
            EditorUtility.SetDirty(nbody);
        }
    }