/// <summary> /// Calculate an array of points that describe the specified orbit /// </summary> /// <returns>The positions.</returns> /// <param name="numPoints">Number points.</param> public Vector3[] OrbitPositions(int numPoints, Vector3 centerPos, bool doSceneMapping) { GravityEngine ge = GravityEngine.Instance(); Vector3[] points = new Vector3[numPoints]; UpdateOrbitParams(); CalculateRotation(); float dtheta = 2f * Mathf.PI / numPoints; float theta = 0; // add a fudge factor to ensure we go all the way around the circle for (int i = 0; i < numPoints; i++) { points[i] = PositionForTheta(theta, centerPos); if (NUtils.VectorNaN(points[i])) { Debug.LogError("Vector NaN + " + points[i]); points[i] = Vector3.zero; } else if (doSceneMapping && ge.mapToScene) { points[i] = ge.MapToScene(points[i]); } theta += dtheta; } // close the path (credit for fix to R. Vincent) points[numPoints - 1] = points[0]; return(points); }
/// <summary> /// Calculate an array of orbit positions. Used by the OrbitPredictor, OrbitRenderer and Editor /// Gimzo to illustrate the hyperbola. /// </summary> /// <returns>The positions.</returns> /// <param name="numPoints">Number points.</param> public Vector3[] OrbitPositions(int numPoints, Vector3 centerPos, bool doSceneMapping) { CalculateRotation(); Vector3[] emptyArray = { new Vector3(0, 0, 0), new Vector3(0, 0, 0) }; // need to have a center to create positions. if (centerObject == null) { centerObject = transform.parent.gameObject; if (centerObject == null) { return(emptyArray); } } Vector3[] points = new Vector3[numPoints]; float theta = -1f * branchDisplayFactor * Mathf.PI; float dTheta = 2f * Mathf.Abs(theta) / (float)numPoints; GravityEngine ge = GravityEngine.Instance(); for (int i = 0; i < numPoints; i++) { points[i] = PositionForThetaLeftBranch(theta, centerPos); if (NUtils.VectorNaN(points[i])) { points[i] = Vector3.zero; } else if (doSceneMapping && ge.mapToScene) { points[i] = ge.MapToScene(points[i]); } theta += dTheta; } return(points); }
/// <summary> /// Determine points from body through closest approach the same distance on the other side /// </summary> /// <param name="numPoints"></param> /// <param name="centerPos"></param> /// <param name="startPos"></param> /// <returns></returns> public Vector3[] OrbitSegmentSymmetricPositions(int numPoints, Vector3 centerPos, Vector3 startPos) { GravityEngine ge = GravityEngine.Instance(); CalculateRotation(); // map points into xy plane Vector3 start_xy = Quaternion.Inverse(hyper_orientation) * (startPos - centerPos); // symmetric around origin float start_y = -start_xy.y; float end_y = start_xy.y; if (start_y > end_y) { float temp = start_y; start_y = end_y; end_y = temp; } float dy = Mathf.Abs(end_y - start_y) / (float)numPoints; float y = start_y; int i = 0; Vector3[] points = new Vector3[numPoints]; while (y < end_y) { points[i] = PositionForY(y, centerPos); if (NUtils.VectorNaN(points[i])) { Debug.LogError(string.Format("Vector NaN = {0} y={1} ecc={2} ", points[i], y, ecc)); points[i] = Vector3.zero; } else if (ge.mapToScene) { points[i] = ge.MapToScene(points[i]); } y += dy; i++; if (i > numPoints - 1) { break; } } // fill to end with last point int last = i - 1; if (last < 0) { last = 0; } while (i < numPoints) { points[i++] = points[last]; } return(points); }
/// <summary> /// Update called from GE to set new position/velocity based on gravity evolution. /// The NBody referance frame moves so that the local axis points along the path. /// </summary> /// /// <param name="position">The position</param> /// <param name="velocity">The velocity</param> public void GEUpdate(Vector3 position, Vector3 velocity, GravityEngine ge) { transform.position = ge.MapToScene(position); vel_phys = velocity; if (rotateFrame) { Quaternion q = new Quaternion(); q.SetFromToRotation(lastVelocity, velocity); transform.rotation = transform.rotation * q; } lastVelocity = velocity; }
private void UpdateLineRenderer() { if (points != null) { // TODO - performance. Specify a point limit and allocate once positions = new Vector3[points.Count]; for (int i = 0; i < points.Count; i++) { positions[i] = ge.MapToScene(points[i].p); } lineRenderer.positionCount = points.Count; lineRenderer.SetPositions(positions); } }
#pragma warning restore 414 /// <summary> /// Updates the particles positions in world space. /// /// UpdateParticles is called from the GravityEngine. Do not call from other scripts. /// </summary> /// <param name="physicalScale">Physical scale.</param> public void UpdateParticles(float physicalScale, GravityEngine ge) { if (allInactive) { return; } for (int i = 0; i < lastParticleCount; i++) { particles[i].position = ge.MapToScene(new Vector3((float)r[i, 0] * physicalScale, (float)r[i, 1] * physicalScale, (float)r[i, 2] * physicalScale)); } gravityParticles.SetParticles(particles, particleCount); // must be after display - so final inactivated particles are removed if (oneTimeBurst && burstDone && ((ejectCount + inactiveCount) >= particleCount)) { allInactive = true; #pragma warning disable 162 // disable unreachable code warning if (debugLogs) { Debug.Log("All particles inactive! time = " + Time.time + " ejected=" + ejectCount + " inactive=" + inactiveCount + " remaining=" + (particleCount - inactiveCount - ejectCount)); } #pragma warning restore 162 } #pragma warning disable 162, 429 // disable unreachable code warning if (debugLogs && debugCnt++ > 30) { debugCnt = 0; string log = "time = " + Time.time + " ejected=" + ejectCount + " inactive=" + inactiveCount + " remaining=" + (particleCount - inactiveCount - ejectCount); log += " is Stopped " + gravityParticles.isStopped + " num=" + gravityParticles.particleCount + " pcount=" + particleCount + "\n"; int logTo = (gravityParticles.main.maxParticles < 10) ? gravityParticles.main.maxParticles : 10; for (int i = 0; i < logTo; i++) { log += string.Format("{0} rand={1} life={2} inactive={3} ", i, particles[i].randomSeed, particles[i].remainingLifetime, inactive[i]); log += " pos=" + particles[i].position; log += " phyPos= " + r[i, 0] + " " + r[i, 1] + " " + r[i, 2]; log += "\n"; } Debug.Log(log); } #pragma warning restore 162, 429 }
public void GEUpdate(GravityEngine ge) { // MapToScene may change things,so need to map every frame transform.position = ge.MapToScene(phyPosition); }
/// <summary> /// Generate the points for an orbit segment given the start and end positions. If shortPath then /// the short path between the points will be shown, otherwise the long way around. /// /// The points are used to determine an angle from the main axis of the ellipse and although they /// should be on the ellipse for best results, the code will do it's best if they are not. /// </summary> /// <param name="numPoints"></param> /// <param name="centerPos"></param> /// <param name="startPos"></param> /// <param name="endPos"></param> /// <param name="shortPath"></param> /// <returns></returns> public Vector3[] OrbitSegmentPositions(int numPoints, Vector3 centerPos, Vector3 startPos, Vector3 endPos, bool shortPath) { GravityEngine ge = GravityEngine.Instance(); Vector3[] points = new Vector3[numPoints]; UpdateOrbitParams(); CalculateRotation(); float dtheta = 2f * Mathf.PI / numPoints; float theta = 0; // find the vector to theta=0 on the ellipse, with no offset Vector3 ellipseAxis = PositionForTheta(0f, Vector3.zero); Vector3 normal = ellipse_orientation * Vector3.forward; float theta1 = NUtils.AngleFullCircleRadians(ellipseAxis, startPos - centerPos, normal); float theta2 = NUtils.AngleFullCircleRadians(ellipseAxis, endPos - centerPos, normal); if (inclination > 90) { float temp = theta1; theta1 = theta2; theta2 = temp; } if (theta1 > theta2) { float temp = theta1; theta1 = theta2; theta2 = temp; } if (!shortPath) { float temp = theta1; theta1 = theta2; // ok to go beyond 2 Pi, since will increment to theta2 theta2 = temp + 2f * Mathf.PI; } // Debug.LogFormat("theta1={0} theta2={1} start={2} end={3} axis={4}", theta1, theta2, startPos, endPos, ellipseAxis); int i = 0; for (theta = theta1; theta < theta2; theta += dtheta) { points[i] = PositionForTheta(theta, centerPos); if (NUtils.VectorNaN(points[i])) { Debug.LogError("Vector NaN + " + points[i]); points[i] = Vector3.zero; } else if (ge.mapToScene) { points[i] = ge.MapToScene(points[i]); } i++; if (i > numPoints - 1) { break; } } // fill to end with last point int last = i - 1; if (last < 0) { last = 0; } while (i < numPoints) { points[i++] = points[last]; } return(points); }