public void SystemTick() { Matrix4[] bodymats = new Matrix4[bodyinfo.Count]; Vector3d[] positions = new Vector3d[bodyinfo.Count]; for (int i = 0; i < bodyinfo.Count; i++) { var bi = bodyinfo[i]; Vector3 pos = Vector3.Zero; if (bi.kepler != null) // this body is orbiting { if (i > 0) // not the root node, so a normal orbit { positions[i] = bi.kepler.ToCartesian(currentjd); // in meters around 0,0,0 var cbpos = positions[bi.parentindex]; // central body position positions[i] += cbpos; // offset bi.orbitpos.WorldPosition = new Vector3((float)cbpos.X, (float)cbpos.Z, (float)cbpos.Y) * mscaling; } else { // node 0 is the root node, always displayed at 0,0,0 // If we remove the root node, and just display a body or barycentre which is in orbit around the root node // the orbit of this node body is calculated at T0, and then the orbit position of offset so the line passes thru 0,0,0 var orbitpos = bi.kepler.ToCartesian(bi.kepler.T0); // find the orbit of the root at T0 (fixed so it does not move) bi.orbitpos.WorldPosition = new Vector3((float)-orbitpos.X, (float)-orbitpos.Z, (float)-orbitpos.Y) * mscaling; } } double axialtilt = (bi.scannode.scandata?.nAxialTilt ?? 0).Radians(); pos = new Vector3((float)(positions[i].X * mscaling), (float)(positions[i].Z * mscaling), (float)(positions[i].Y * mscaling)); bi.bodypos.WorldPosition = pos; float imageradius = bi.scannode.scandata != null && bi.scannode.scandata.nRadius.HasValue ? (float)bi.scannode.scandata.nRadius.Value : 1000e3f; imageradius *= mscaling; bool planet = bi.scannode.scandata != null && bi.scannode.scandata.PlanetClass.HasChars(); bool bary = bi.scannode.scandata == null || bi.scannode.scandata.nRadius == null; bodymats[i] = GLStaticsMatrix4.CreateMatrixPlanetRot(pos, new Vector3(1, 1, 1), 23f.Radians(), planetrot.Radians()); planetrot += 0.1f; // more clever, knowing orbit paras bodymats[i].M14 = (bary ? 100000 : planet ? 100000 : 1000000) * 1000 * mscaling; // min size in km bodymats[i].M24 = (bary ? 100000 : planet ? 10000000 : 3e6f) * 1000 * mscaling; // maximum size in scaling bodymats[i].M34 = imageradius; bodymats[i].M44 = planet ? 1 : bary ? 2 : 0; // select image } bodymatrixbuffer.ResetFillPos(); bodymatrixbuffer.Fill(bodymats); if (track != -1) { Vector3d pos = positions[track]; gl3dcontroller.MoveLookAt(new Vector3d(pos.X, pos.Z, pos.Y) * mscaling, false); } // datalabel.Text = $"{bodypositionscaling[1].Position/mscaling/1000}" + Environment.NewLine; gl3dcontroller.HandleKeyboardSlewsAndInvalidateIfMoved(true, OtherKeys, 0.0001f, 0.0001f); timedisplay.Text = $"JD {currentjd:#0000000.00000} {currentjd.JulianToDateTime()}" + (track >= 0 ? " Tracking " + bodyinfo[track].scannode.FullName : ""); status.Text = $"Looking at {gl3dcontroller.PosCamera.LookAt.X / mscaling / 1000:0.0},{gl3dcontroller.PosCamera.LookAt.Y / mscaling / 1000:0.0},{gl3dcontroller.PosCamera.LookAt.Z / mscaling / 1000:0.0} " + $"from {gl3dcontroller.PosCamera.EyePosition.X / mscaling / 1000:0.0},{gl3dcontroller.PosCamera.EyePosition.Y / mscaling / 1000:0.0},{gl3dcontroller.PosCamera.EyePosition.Z / mscaling / 1000:0.0} " + $"cdir {gl3dcontroller.PosCamera.CameraDirection.X:0.0},{gl3dcontroller.PosCamera.CameraDirection.Y:0.0} zoom {gl3dcontroller.PosCamera.ZoomFactor:0.0000} " + $"dist {gl3dcontroller.PosCamera.EyeDistance / mscaling / 1000:N0}km FOV {gl3dcontroller.MatrixCalc.FovDeg}"; //float sr = gl3dcontroller.MatrixCalc.EyeDistance / (0.05e6f * 1000 * mscaling); //status.Text += $" eye units {gl3dcontroller.MatrixCalc.EyeDistance} sr {sr}"; // System.Diagnostics.Debug.WriteLine("Tick"); gl3dcontroller.Redraw(); }