public void Update(TimeStep timeStep) { double rotation = _parent.Rotation -_offsetRotation; DVector2 offset = new DVector2(Math.Cos(rotation), Math.Sin(rotation)) * _offsetLength; double throttle = (IsActive && _parent.PropellantMass > 0) ? Throttle : 0; _engineFlame.Update(timeStep, _parent.Position - offset, _parent.Velocity, _parent.Rotation, throttle); }
public void Update(TimeStep timeStep, DVector2 shipPosition, DVector2 shipVelocity, double pitch, double heatingRate) { double rotation = pitch - _offsetAngle; DVector2 offset = new DVector2(Math.Cos(rotation), Math.Sin(rotation)) * _offsetLength; DVector2 shockPosition = shipPosition - offset; double normalizedHeating = Math.Max((heatingRate - 500000) * 0.0005, 0); int particles = (int)(normalizedHeating * _particleRate) / timeStep.UpdateLoops; // Add new particles if nessecary for (int i = 0; i < particles; i++) { if (_availableParticles.Count > 0) { double velocityFactor = _random.Next(50, 200); double spread = _random.NextDouble() * 2.5 - 1.25; DVector2 velocity = DVector2.FromAngle(rotation + spread); int id = _availableParticles.Dequeue(); Particle particle = _particles[id]; particle.IsActive = true; particle.Age = 0; particle.MaxAge = _random.NextDouble()*0.01 + 0.02; particle.Position = shockPosition.Clone(); particle.Velocity = shipVelocity.Clone() + velocity*velocityFactor; } } // Update the particles for (int i = 0; i < _particles.Length; i++) { Particle particle = _particles[i]; if (particle.IsActive) { particle.Position += particle.Velocity*timeStep.Dt; particle.Age += timeStep.Dt; if (particle.Age > particle.MaxAge) { particle.IsActive = false; _availableParticles.Enqueue(i); } } } }
public void Update(TimeStep timeStep, DVector2 enginePosition, DVector2 shipVelocity, double rotation, double throttle) { double retrograde = rotation + Math.PI; int particles = (int)((throttle * _particleRate) / timeStep.UpdateLoops); // Add new particles if nessecary for (int i = 0; i < particles; i++) { if (_availableParticles.Count > 0) { double velocityFactor = _random.Next(150, 250); double spread = _random.NextDouble() - 0.5; DVector2 velocity = DVector2.FromAngle(retrograde + spread * _spreadFactor); int id = _availableParticles.Dequeue(); Particle particle = _particles[id]; particle.IsActive = true; particle.Age = 0; particle.MaxAge = _random.NextDouble() * 0.1 + 0.05; particle.Position = enginePosition.Clone(); particle.Velocity = shipVelocity.Clone() + velocity * velocityFactor; } } // Update the particles for (int i = 0; i < _particles.Length; i++) { Particle particle = _particles[i]; if (particle.IsActive) { particle.Position += particle.Velocity * timeStep.Dt; particle.Age += timeStep.Dt; if (particle.Age > particle.MaxAge) { particle.IsActive = false; _availableParticles.Enqueue(i); } } } }
/// <summary> /// Updates the physics bodies and resolves all forces. /// </summary> private void Update(TimeStep timeStep) { ResolveMassiveBodyParents(); ResolveSpaceCraftParents(); double targetDt = (_isPaused) ? 0 : timeStep.Dt; // Update all bodies according to the timestep for (int i = 0; i < timeStep.UpdateLoops; i++) { // Resolve n body massive body forces foreach (IMassiveBody bodyA in _massiveBodies) { bodyA.ResetAccelerations(); foreach (IMassiveBody bodyB in _massiveBodies) { if (bodyA == bodyB) continue; bodyA.ResolveGravitation(bodyB); } } // Reslove spacecraft forces foreach (SpaceCraftBase spaceCraft in _spaceCrafts) { spaceCraft.ResetAccelerations(); foreach (MassiveBodyBase massiveBody in _massiveBodies) { spaceCraft.ResolveGravitation(massiveBody); if (spaceCraft.GravitationalParent == massiveBody) { spaceCraft.ResolveAtmopsherics(massiveBody); } } } // Don't update the animations every frame if (timeStep.UpdateLoops < 16) { foreach (ISpaceCraft spaceCraft in _spaceCrafts) { spaceCraft.UpdateAnimations(timeStep); } } // Update oribitng bodies foreach (IGravitationalBody gravitationalBody in _gravitationalBodies) { gravitationalBody.Update(targetDt); } foreach (ISpaceCraft spaceCraft in _spaceCrafts) { spaceCraft.UpdateController(targetDt); } _camera.Update(targetDt); _eventManager.Update(targetDt); _totalElapsedSeconds += targetDt; } // Fixed update all gravitational bodies foreach (IGravitationalBody body in _gravitationalBodies) { body.FixedUpdate(timeStep); } var targetSpaceCraft = _gravitationalBodies[_targetIndex] as ISpaceCraft; if (targetSpaceCraft != null) { if (targetSpaceCraft.Controller.IsPrograde) { _progradeButton.Enable(); } else { _progradeButton.Disable(); } if (targetSpaceCraft.Controller.IsRetrograde) { _retrogradeButton.Enable(); } else { _retrogradeButton.Disable(); } } _scrollRate = MathHelper.Lerp(_scrollRate, _targetScrollRate, 0.1f); _targetScrollRate = MathHelper.Lerp(_targetScrollRate, 0, 0.1f); if (_camera.Zoom > 1) { double scroll = Math.Pow(_camera.Zoom, 1.05f)*_scrollRate; _camera.ChangeZoom(scroll); } else { _camera.ChangeZoom(_scrollRate); } }
/// <summary> /// Draws all the physics bodies and UI elements. /// </summary> private unsafe void DrawFrame(TimeStep timeStep, FpsManager frameTimer) { var font = new Font("Verdana Bold", 14); var brush = new SolidBrush(Color.White); RectangleD cameraBounds = _camera.GetBounds(); IGravitationalBody target = _gravitationalBodies[_targetIndex]; var targetSpaceCraft = target as SpaceCraftBase; // If openCL is supported render all cl bodies if (_renderingType == RenderingType.OpenCLHardware || _renderingType == RenderingType.OpenCLSoftware) { _gpuClear.RenderCl(_clProxy); foreach (MassiveBodyBase renderable in _massiveBodies) { if (renderable.Visibility(cameraBounds) > 0) { renderable.RenderCl(_clProxy, cameraBounds, _sun); } } int[] frameData = _clProxy.ReadIntBuffer("image", RenderUtils.ScreenArea); var rect = new Rectangle(0, 0, _imageBitmap.Width, _imageBitmap.Height); BitmapData bmpData = _imageBitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); Marshal.Copy(frameData, 0, bmpData.Scan0, RenderUtils.ScreenArea); var ptr = (byte*)bmpData.Scan0; // Hack to force full alpha for now for (int i = 0; i < RenderUtils.ScreenArea; i++) { ptr[i * 4 + 3] = 255; } _imageBitmap.UnlockBits(bmpData); } else { // Fall back to gdi for cl renderables using (var graphics = Graphics.FromImage(_imageBitmap)) { graphics.Clear(Color.Black); foreach (MassiveBodyBase renderable in _massiveBodies) { if (renderable.Visibility(cameraBounds) > 0) { renderable.RenderGdiFallback(graphics, cameraBounds, _sun); } } } } // Draw all orbit traces, spacecrafts, and GDI objects using (Graphics graphics = RenderUtils.GetContext(false, _imageBitmap)) { RenderUtils.DrawLine(graphics, cameraBounds, new DVector2(0, -10e12), new DVector2(0, 10e12), Color.FromArgb(40, 255, 255, 255)); RenderUtils.DrawLine(graphics, cameraBounds, new DVector2(-10e12, 0), new DVector2(10e12, 0), Color.FromArgb(40, 255, 255, 255)); // Draw all massive body orbit traces foreach (MassiveBodyBase massiveBody in _massiveBodies) { if (massiveBody is Sun) continue; massiveBody.RenderGdi(graphics, cameraBounds); } // Draw spacecraft foreach (SpaceCraftBase spaceCraft in _spaceCrafts) { spaceCraft.RenderGdi(graphics, cameraBounds); } // Draw structures foreach (StructureBase structure in _structures) { structure.RenderGdi(graphics, cameraBounds); } } // Draw all GUI elements (higher quality) using (Graphics graphics = RenderUtils.GetContext(true, _imageBitmap)) { double throttle = 0; if (targetSpaceCraft != null) { throttle = targetSpaceCraft.Throttle; } foreach (IGauge gauge in _gauges) { if (targetSpaceCraft != null) { gauge.Update(_gravitationalBodies[_targetIndex].Pitch, throttle / 100.0); } gauge.Render(graphics, cameraBounds); } _eventManager.Render(graphics); var elapsedTime = TimeSpan.FromSeconds(_totalElapsedSeconds - ClockDelayInSeconds); int elapsedYears = elapsedTime.Days / 365; int elapsedDays = elapsedTime.Days % 365; graphics.DrawString("Elapsed Time: " + string.Format("Y: {0} D: {1} H: {2} M: {3} S: {4}", elapsedYears, elapsedDays, elapsedTime.Hours, elapsedTime.Minutes, elapsedTime.Seconds), font, brush, 5, 5); graphics.DrawString("Update Speed: " + timeStep.Multiplier + " X", font, brush, 5, 35); double altitude = target.GetRelativeAltitude(); graphics.DrawString("Altitude: " + UnitDisplay.Distance(altitude), font, brush, 5, 90); graphics.DrawString(string.Format("Target: {0}", target), font, brush, RenderUtils.ScreenWidth / 2.0f, 5, new StringFormat { Alignment = StringAlignment.Center }); double targetVelocity = target.GetRelativeVelocity().Length(); graphics.DrawString("Relative Speed: " + UnitDisplay.Speed(targetVelocity, false), font, brush, 5, 175); graphics.DrawString("Relative Acceleration: " + UnitDisplay.Acceleration(target.GetRelativeAcceleration().Length()), font, brush, 5, 205); if (!(target is Sun)) { graphics.DrawString("Apogee: " + UnitDisplay.Distance(target.Apogee), font, brush, 5, 455); graphics.DrawString("Perigee: " + UnitDisplay.Distance(target.Perigee), font, brush, 5, 485); } graphics.DrawString("Mass: " + UnitDisplay.Mass(target.Mass), font, brush, 5, 290); if (targetSpaceCraft != null) { double alpha = targetSpaceCraft.GetAlpha(); graphics.DrawString("Angle of Attack: " + UnitDisplay.Degrees(alpha), font, brush, 5, 235); double downrangeDistance = targetSpaceCraft.GetDownrangeDistance(_structures[0].Position); graphics.DrawString("Downrange: " + UnitDisplay.Distance(downrangeDistance), font, brush, 5, 120); graphics.DrawString("Thrust: " + UnitDisplay.Force(targetSpaceCraft.Thrust), font, brush, 5, 320); DVector2 dragForce = targetSpaceCraft.AccelerationD * targetSpaceCraft.Mass; DVector2 liftForce = targetSpaceCraft.AccelerationL * targetSpaceCraft.Mass * Math.Cos(targetSpaceCraft.Roll); DVector2 turnForce = targetSpaceCraft.AccelerationL * targetSpaceCraft.Mass * Math.Sin(targetSpaceCraft.Roll); graphics.DrawString("Drag: " + UnitDisplay.Force(dragForce.Length()), font, brush, 5, 350); graphics.DrawString("Lift: " + UnitDisplay.Force(liftForce.Length()), font, brush, 5, 380); graphics.DrawString("Turn: " + UnitDisplay.Force(turnForce.Length()), font, brush, 5, 410); double density = targetSpaceCraft.GravitationalParent.GetAtmosphericDensity(altitude); graphics.DrawString("Air Density: " + UnitDisplay.Density(density), font, brush, 5, 535); double dynamicPressure = 0.5 * density * targetVelocity * targetVelocity; graphics.DrawString("Dynamic Pressure: " + UnitDisplay.Pressure(dynamicPressure), font, brush, 5, 565); graphics.DrawString("Heating Rate: " + UnitDisplay.Heat(targetSpaceCraft.HeatingRate), font, brush, 5, 595); } graphics.DrawString("FPS: " + frameTimer.CurrentFps, font, brush, RenderUtils.ScreenWidth - 80, 5); } }
public virtual void UpdateAnimations(TimeStep timeStep) { foreach (IEngine engine in Engines) { engine.Update(timeStep); } }
public override void FixedUpdate(TimeStep timeStep) { throw new NotImplementedException(); }
/// <summary> /// Draws all the physics bodies and UI elements. /// </summary> private unsafe void DrawFrame(TimeStep timeStep, FpsManager frameTimer) { var font = new Font("Verdana Bold", 14); var brush = new SolidBrush(Color.White); RectangleD cameraBounds = _camera.GetBounds(); IGravitationalBody target = _gravitationalBodies[_targetIndex]; var targetSpaceCraft = target as ISpaceCraft; // If openCL is supported render all cl bodies if (_renderingType == RenderingType.OpenCLHardware || _renderingType == RenderingType.OpenCLSoftware) { _gpuClear.RenderCl(_clProxy); foreach (MassiveBodyBase renderable in _massiveBodies) { if (renderable.Visibility(cameraBounds) > 0) { renderable.RenderCl(_clProxy, cameraBounds, _sun); } } int[] frameData = _clProxy.ReadIntBuffer("image", RenderUtils.ScreenArea); var rect = new Rectangle(0, 0, _imageBitmap.Width, _imageBitmap.Height); BitmapData bmpData = _imageBitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); Marshal.Copy(frameData, 0, bmpData.Scan0, RenderUtils.ScreenArea); var ptr = (byte*)bmpData.Scan0; // Hack to force full alpha for now for (int i = 0; i < RenderUtils.ScreenArea; i++) { ptr[i * 4 + 3] = 255; } _imageBitmap.UnlockBits(bmpData); } else { // Fall back to gdi for cl renderables using (var graphics = Graphics.FromImage(_imageBitmap)) { graphics.Clear(Color.Black); foreach (MassiveBodyBase renderable in _massiveBodies) { if (renderable.Visibility(cameraBounds) > 0) { renderable.RenderGdiFallback(graphics, cameraBounds, _sun); } } } } // Draw all orbit traces, spacecrafts, and GDI objects using (var graphics = Graphics.FromImage(_imageBitmap)) { graphics.SmoothingMode = SmoothingMode.HighSpeed; graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed; graphics.CompositingQuality = CompositingQuality.HighSpeed; graphics.InterpolationMode = InterpolationMode.NearestNeighbor; RenderUtils.DrawLine(graphics, cameraBounds, new DVector2(0, -10e12), new DVector2(0, 10e12), Color.FromArgb(40, 255, 255, 255)); RenderUtils.DrawLine(graphics, cameraBounds, new DVector2(-10e12, 0), new DVector2(10e12, 0), Color.FromArgb(40, 255, 255, 255)); double apogee = 0; double perigee = 0; // Draw orbit traces foreach (MassiveBodyBase massiveBody in _massiveBodies) { if (massiveBody is Sun) continue; OrbitTrace trace = OrbitHelper.TraceMassiveBody(massiveBody); if (target == massiveBody) { apogee = trace.Apogee; perigee = trace.Perigee; } trace.Draw(graphics, cameraBounds, massiveBody); } // Draw structures foreach (StructureBase structure in _structures) { structure.RenderGdi(graphics, cameraBounds); } // Draw spacecraft foreach (SpaceCraftBase spaceCraft in _spaceCrafts) { if (spaceCraft.Visibility(cameraBounds) > 0) { RectangleD bounds = spaceCraft.ComputeBoundingBox(); // In range for render if (cameraBounds.IntersectsWith(bounds)) { spaceCraft.RenderGdi(graphics, cameraBounds); } } if (spaceCraft.Parent != null) continue; OrbitTrace trace = OrbitHelper.TraceSpaceCraft(spaceCraft); if (target == spaceCraft) { apogee = trace.Apogee; perigee = trace.Perigee; } trace.Draw(graphics, cameraBounds, spaceCraft); } var elapsedTime = TimeSpan.FromSeconds(_totalElapsedSeconds); int elapsedYears = elapsedTime.Days / 365; int elapsedDays = elapsedTime.Days % 365; graphics.DrawString("Elapsed Time: " + string.Format("Y: {0} D: {1} H: {2} M: {3} S: {4}", elapsedYears, elapsedDays, elapsedTime.Hours, elapsedTime.Minutes, elapsedTime.Seconds), font, brush, 5, 5); graphics.DrawString("Update Speed: " + timeStep.Multiplier + " X", font, brush, 5, 35); double altitude = target.GetRelativeAltitude(); graphics.DrawString("Altitude: " + UnitDisplay.Distance(altitude), font, brush, 5, 100); graphics.DrawString(string.Format("Target: {0}", target), font, brush, RenderUtils.ScreenWidth / 2 - 35, 5); graphics.DrawString("Relative Speed: " + UnitDisplay.Speed(target.GetRelativeVelocity().Length()), font, brush, 5, 225); graphics.DrawString("Relative Acceleration: " + UnitDisplay.Acceleration(target.GetRelativeAcceleration().Length()), font, brush, 5, 255); graphics.DrawString("Apogee: " + UnitDisplay.Distance(apogee), font, brush, 5, 320); graphics.DrawString("Perigee: " + UnitDisplay.Distance(perigee), font, brush, 5, 350); graphics.DrawString("Mass: " + UnitDisplay.Mass(target.Mass), font, brush, 5, 410); if (targetSpaceCraft != null) { graphics.DrawString("Thrust: " + UnitDisplay.Force(targetSpaceCraft.Thrust), font, brush, 5, 440); double downrangeDistance = targetSpaceCraft.GetDownrangeDistance(_strongback.Position); graphics.DrawString("Downrange: " + UnitDisplay.Distance(downrangeDistance), font, brush, 5, 130); double density = targetSpaceCraft.GravitationalParent.GetAtmosphericDensity(altitude); graphics.DrawString("Air Density: " + UnitDisplay.Density(density), font, brush, 5, 160); } graphics.DrawString("FPS: " + frameTimer.CurrentFps, font, brush, RenderUtils.ScreenWidth - 80, 5); } // Draw all GUI elements (higher quality) using (var graphics = Graphics.FromImage(_imageBitmap)) { graphics.SmoothingMode = SmoothingMode.HighQuality; double throttle = 0; if (targetSpaceCraft != null) { var throttleValues = new List<double>(); targetSpaceCraft.SumTotalThrottle(throttleValues); if (throttleValues.Count > 0) { throttle = throttleValues.Average(); } } foreach (IGauge gauge in _gauges) { if (targetSpaceCraft != null) { gauge.Update(_gravitationalBodies[_targetIndex].Rotation, throttle / 100.0); } gauge.Render(graphics, cameraBounds); } } }
public void Update(TimeStep timeStep, DVector2 enginePosition, DVector2 shipVelocity, double rotation, double throttle, double ispMultiplier) { double retrograde = rotation + Math.PI + _angle; int particles = (int)((throttle * _particleRate) / timeStep.UpdateLoops); // Interpolate between spreads based on ISP double spreadMultiplier = (1.0 - ispMultiplier) * _minSpread + ispMultiplier * _maxSpread; // Add new particles if nessecary for (int i = 0; i < particles; i++) { if (_availableParticles.Count > 0) { double velocityFactor = _random.Next(200, 300); double spread = _random.NextDouble() - 0.5; DVector2 velocity = DVector2.FromAngle(retrograde + spread * spreadMultiplier); int id = _availableParticles.Dequeue(); Particle particle = _particles[id]; particle.IsActive = true; particle.Age = 0; particle.MaxAge = _random.NextDouble() * 0.05 + _maxAge; particle.Position = enginePosition.Clone(); particle.Velocity = shipVelocity.Clone() + velocity * velocityFactor; } } // Update the particles for (int i = 0; i < _particles.Length; i++) { Particle particle = _particles[i]; if (particle.IsActive) { particle.Position += particle.Velocity * timeStep.Dt; particle.Age += timeStep.Dt; if (particle.Age > particle.MaxAge) { particle.IsActive = false; _availableParticles.Enqueue(i); } } } }
public void Update(TimeStep timeStep, double ispMultiplier) { double rotation = Parent.Pitch -_offsetRotation; DVector2 offset = new DVector2(Math.Cos(rotation), Math.Sin(rotation)) * _offsetLength; double throttle = (IsActive && Parent.PropellantMass > 0) ? Throttle : 0; _engineFlame.Update(timeStep, Parent.Position - offset, Parent.Velocity, Parent.Pitch, throttle, ispMultiplier); }
public virtual void UpdateAnimations(TimeStep timeStep) { // Only use re-entry flames for separated bodies if (EntryFlame != null && Children.Count == 0) { EntryFlame.Update(timeStep, Position, Velocity, Pitch, HeatingRate); } foreach (IEngine engine in Engines) { engine.Update(timeStep, IspMultiplier); } }
public override void FixedUpdate(TimeStep timeStep) { if (Parent == null) { OrbitHelper.TraceSpaceCraft(this, OrbitTrace); } }
public abstract void FixedUpdate(TimeStep timeStep);
public override void FixedUpdate(TimeStep timeStep) { OrbitHelper.TraceMassiveBody(this, OrbitTrace); }
public abstract void FixedUpdate(TimeStep timeStep);