Пример #1
0
        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);
        }
Пример #2
0
        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);
                    }
                }
            }
        }
Пример #3
0
        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);
                    }
                }
            }
        }
Пример #4
0
        /// <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);
            }
        }
Пример #5
0
        /// <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);
            }
        }
Пример #6
0
 public virtual void UpdateAnimations(TimeStep timeStep)
 {
     foreach (IEngine engine in Engines)
     {
         engine.Update(timeStep);
     }
 }
Пример #7
0
 public override void FixedUpdate(TimeStep timeStep)
 {
     throw new NotImplementedException();
 }
Пример #8
0
        /// <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);
                }
            }
        }
Пример #9
0
        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);
                    }
                }
            }
        }
Пример #10
0
        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);
        }
Пример #11
0
        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);
            }
        }
Пример #12
0
 public override void FixedUpdate(TimeStep timeStep)
 {
     if (Parent == null)
     {
         OrbitHelper.TraceSpaceCraft(this, OrbitTrace);
     }
 }
Пример #13
0
 public abstract void FixedUpdate(TimeStep timeStep);
Пример #14
0
 public override void FixedUpdate(TimeStep timeStep)
 {
     OrbitHelper.TraceMassiveBody(this, OrbitTrace);
 }
Пример #15
0
 public abstract void FixedUpdate(TimeStep timeStep);