// 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; } } }
// 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); } }