public void SimulateAeroProperties(out Vector3 aeroForce, out Vector3 aeroTorque, Vector3 velocityWorldVector, double altitude)
        {
            // Rodhern: It seems that this method, 'SimulateAeroProperties', is only used in FARAPI, which in turn can be used by say KSPTrajectories.
            //          The parameter 'FARCenterQuery dummy' is from a code fix by Benjamin Chung (commit 18fbb9d29431679a4de9dfc22a443f400d2d4f8b).

            FARCenterQuery center = new FARCenterQuery();
            FARCenterQuery dummy  = new FARCenterQuery();

            float pressure;
            float density;
            float temperature;
            float speedOfSound;

            CelestialBody body = vessel.mainBody;      //Calculate main gas properties

            pressure     = (float)body.GetPressure(altitude);
            temperature  = (float)body.GetTemperature(altitude);
            density      = (float)body.GetDensity(pressure, temperature);
            speedOfSound = (float)body.GetSpeedOfSound(pressure, density);

            if (pressure <= 0 || temperature <= 0 || density <= 0 || speedOfSound <= 0)
            {
                aeroForce  = Vector3.zero;
                aeroTorque = Vector3.zero;
                return;
            }

            float     velocityMag         = velocityWorldVector.magnitude;
            float     machNumber          = velocityMag / speedOfSound;
            float     reynoldsNumber      = (float)FARAeroUtil.CalculateReynoldsNumber(density, Length, velocityMag, machNumber, temperature, body.atmosphereAdiabaticIndex);
            float     reynoldsPerLength   = reynoldsNumber / (float)Length;
            float     pseudoKnudsenNumber = machNumber / (reynoldsNumber + machNumber);
            float     skinFriction        = (float)FARAeroUtil.SkinFrictionDrag(reynoldsNumber, machNumber);
            FlightEnv fenv = FlightEnv.NewPredicted(vessel.mainBody, altitude, machNumber);

            if (_currentAeroSections != null)
            {
                for (int i = 0; i < _currentAeroSections.Count; i++)
                {
                    FARAeroSection curSection = _currentAeroSections[i];
                    if (curSection != null)
                    {
                        curSection.PredictionCalculateAeroForces(density, machNumber, reynoldsPerLength, pseudoKnudsenNumber, skinFriction, velocityWorldVector, center);
                    }
                }

                for (int i = 0; i < _legacyWingModels.Count; i++)
                {
                    FARWingAerodynamicModel curWing = _legacyWingModels[i];
                    if ((object)curWing != null)
                    {
                        Vector3d force = curWing.PrecomputeCenterOfLift(velocityWorldVector, fenv, dummy);
                        center.AddForce(curWing.transform.position, force);
                    }
                }
            }

            aeroForce  = center.force;
            aeroTorque = center.TorqueAt(vessel.CoM);
        }
        public void SimulateAeroProperties(out Vector3 aeroForce, out Vector3 aeroTorque, Vector3 velocityWorldVector, double altitude)
        {
            FARCenterQuery center = new FARCenterQuery();

            float pressure;
            float density;
            float temperature;
            float speedOfSound;

            CelestialBody body = vessel.mainBody;      //Calculate main gas properties

            pressure     = (float)body.GetPressure(altitude);
            temperature  = (float)body.GetTemperature(altitude);
            density      = (float)body.GetDensity(pressure, temperature);
            speedOfSound = (float)body.GetSpeedOfSound(pressure, density);

            if (pressure <= 0 || temperature <= 0 || density <= 0 || speedOfSound <= 0)
            {
                aeroForce  = Vector3.zero;
                aeroTorque = Vector3.zero;
                return;
            }

            float velocityMag    = velocityWorldVector.magnitude;
            float machNumber     = velocityMag / speedOfSound;
            float reynoldsNumber = (float)FARAeroUtil.CalculateReynoldsNumber(density, Length, velocityMag, machNumber, temperature, body.atmosphereAdiabaticIndex);

            float reynoldsPerLength = reynoldsNumber / (float)Length;
            float skinFriction      = (float)FARAeroUtil.SkinFrictionDrag(reynoldsNumber, machNumber);

            float pseudoKnudsenNumber = machNumber / (reynoldsNumber + machNumber);

            if (_currentAeroSections != null)
            {
                for (int i = 0; i < _currentAeroSections.Count; i++)
                {
                    FARAeroSection curSection = _currentAeroSections[i];
                    if (curSection != null)
                    {
                        curSection.PredictionCalculateAeroForces(density, machNumber, reynoldsPerLength, pseudoKnudsenNumber, skinFriction, velocityWorldVector, center);
                    }
                }

                for (int i = 0; i < _legacyWingModels.Count; i++)
                {
                    FARWingAerodynamicModel curWing = _legacyWingModels[i];
                    if ((object)curWing != null)
                    {
                        curWing.PrecomputeCenterOfLift(velocityWorldVector, machNumber, density, center);
                    }
                }
            }

            aeroForce  = center.force;
            aeroTorque = center.TorqueAt(vessel.CoM);
        }
        private void CalculateAndApplyVesselAeroProperties()
        {
            float atmDensity = (float)vessel.atmDensity;

            if (atmDensity <= 0)
            {
                MachNumber     = 0;
                ReynoldsNumber = 0;
                return;
            }

            MachNumber     = vessel.mach;
            ReynoldsNumber = FARAeroUtil.CalculateReynoldsNumber(vessel.atmDensity,
                                                                 Length,
                                                                 vessel.srfSpeed,
                                                                 MachNumber,
                                                                 FlightGlobals.getExternalTemperature((float)vessel
                                                                                                      .altitude,
                                                                                                      vessel.mainBody),
                                                                 vessel.mainBody.atmosphereAdiabaticIndex);
            float skinFrictionDragCoefficient = (float)FARAeroUtil.SkinFrictionDrag(ReynoldsNumber, MachNumber);

            float pseudoKnudsenNumber = (float)(MachNumber / (ReynoldsNumber + MachNumber));

            Vector3 frameVel = Krakensbane.GetFrameVelocityV3f();

            //start from the top and come down to improve performance if it needs to remove anything
            for (int i = _currentAeroModules.Count - 1; i >= 0; i--)
            {
                FARAeroPartModule m = _currentAeroModules[i];
                if (m != null && m.part != null && m.part.partTransform != null)
                {
                    m.UpdateVelocityAndAngVelocity(frameVel);
                }
                else
                {
                    _currentAeroModules.RemoveAt(i);
                }
            }

            foreach (FARAeroSection aeroSection in _currentAeroSections)
            {
                aeroSection.FlightCalculateAeroForces((float)MachNumber,
                                                      (float)(ReynoldsNumber / Length),
                                                      pseudoKnudsenNumber,
                                                      skinFrictionDragCoefficient);
            }

            _vesselIntakeRamDrag.ApplyIntakeRamDrag((float)MachNumber, vessel.srf_velocity.normalized);

            foreach (FARAeroPartModule m in _currentAeroModules)
            {
                m.ApplyForces();
            }
        }
Пример #4
0
        private void CalculateAndApplyVesselAeroProperties()
        {
            float atmDensity = (float)_vessel.atmDensity;

            if (atmDensity <= 0)
            {
                machNumber     = 0;
                reynoldsNumber = 0;
                return;
            }

            machNumber     = _vessel.mach;
            reynoldsNumber = FARAeroUtil.CalculateReynoldsNumber(_vessel.atmDensity, Length, _vessel.srfSpeed, machNumber, FlightGlobals.getExternalTemperature((float)_vessel.altitude, _vessel.mainBody), _vessel.mainBody.atmosphereAdiabaticIndex);
            float skinFrictionDragCoefficient = (float)FARAeroUtil.SkinFrictionDrag(reynoldsNumber, machNumber);

            Vector3 frameVel = Krakensbane.GetFrameVelocityV3f();

            if (_updateQueued)                                           //only happens if we have an voxelization scheduled, then we need to check for null
            {
                for (int i = _currentAeroModules.Count - 1; i >= 0; i--) //start from the top and come down to improve performance if it needs to remove anything
                {
                    FARAeroPartModule m = _currentAeroModules[i];
                    if (m != null)
                    {
                        m.UpdateVelocityAndAngVelocity(frameVel);
                    }
                    else
                    {
                        _currentAeroModules.RemoveAt(i);
                        i++;
                    }
                }
            }
            else                                                         //otherwise, we don't need to do Unity's expensive "is this part dead" null-check
            {
                for (int i = _currentAeroModules.Count - 1; i >= 0; i--) //start from the top and come down to improve performance if it needs to remove anything
                {
                    FARAeroPartModule m = _currentAeroModules[i];
                    m.UpdateVelocityAndAngVelocity(frameVel);
                }
            }

            for (int i = 0; i < _currentAeroSections.Count; i++)
            {
                _currentAeroSections[i].FlightCalculateAeroForces(atmDensity, (float)machNumber, (float)(reynoldsNumber / Length), skinFrictionDragCoefficient);
            }

            _vesselIntakeRamDrag.ApplyIntakeRamDrag((float)machNumber, _vessel.srf_velocity.normalized, (float)_vessel.dynamicPressurekPa);

            for (int i = 0; i < _currentAeroModules.Count; i++)
            {
                FARAeroPartModule m = _currentAeroModules[i];
                m.ApplyForces();
            }
        }
Пример #5
0
        private void CalculateAndApplyVesselAeroProperties()
        {
            float atmDensity = (float)_vessel.atmDensity;

            if (atmDensity <= 0)
            {
                machNumber     = 0;
                reynoldsNumber = 0;
                return;
            }

            machNumber     = _vessel.mach;
            reynoldsNumber = FARAeroUtil.CalculateReynoldsNumber(_vessel.atmDensity, Length, _vessel.srfSpeed, machNumber, FlightGlobals.getExternalTemperature((float)_vessel.altitude, _vessel.mainBody), _vessel.mainBody.atmosphereAdiabaticIndex);
            float skinFrictionDragCoefficient = (float)FARAeroUtil.SkinFrictionDrag(reynoldsNumber, machNumber);

            Vector3 frameVel = Krakensbane.GetFrameVelocityV3f();

            for (int i = 0; i < _currentAeroModules.Count; i++)
            {
                FARAeroPartModule m = _currentAeroModules[i];
                if (m != null)
                {
                    m.UpdateVelocityAndAngVelocity(frameVel);
                }
                else
                {
                    _currentAeroModules.RemoveAt(i);
                    i--;
                }
            }

            for (int i = 0; i < _currentAeroSections.Count; i++)
            {
                _currentAeroSections[i].FlightCalculateAeroForces(atmDensity, (float)machNumber, (float)(reynoldsNumber / Length), skinFrictionDragCoefficient);
            }

            _vesselIntakeRamDrag.ApplyIntakeRamDrag((float)machNumber, _vessel.srf_velocity.normalized, (float)_vessel.dynamicPressurekPa);

            for (int i = 0; i < _currentAeroModules.Count; i++)
            {
                FARAeroPartModule m = _currentAeroModules[i];
                if ((object)m != null)
                {
                    m.ApplyForces();
                }
            }
        }
Пример #6
0
        public void SimulateAeroProperties(out Vector3 aeroForce, out Vector3 aeroTorque, Vector3 velocityWorldVector, double altitude)
        {
            FARCenterQuery center = new FARCenterQuery();

            float pressure;
            float density;
            float temperature;
            float speedOfSound;

            CelestialBody body = _vessel.mainBody;      //Calculate main gas properties

            pressure     = (float)body.GetPressure(altitude);
            temperature  = (float)body.GetTemperature(altitude);
            density      = (float)body.GetDensity(pressure, temperature);
            speedOfSound = (float)body.GetSpeedOfSound(pressure, density);

            float velocityMag    = velocityWorldVector.magnitude;
            float machNumber     = velocityMag / speedOfSound;
            float reynoldsNumber = (float)FARAeroUtil.CalculateReynoldsNumber(density, Length, velocityMag, machNumber, temperature, body.atmosphereAdiabaticIndex);

            float reynoldsPerLength = reynoldsNumber / (float)Length;
            float skinFriction      = (float)FARAeroUtil.SkinFrictionDrag(reynoldsNumber, machNumber);

            float pseudoLanchesterNumber = machNumber / (reynoldsNumber + machNumber);

            for (int i = 0; i < _currentAeroSections.Count; i++)
            {
                _currentAeroSections[i].PredictionCalculateAeroForces(density, machNumber, reynoldsPerLength, pseudoLanchesterNumber, skinFriction, velocityWorldVector, center);
            }

            for (int i = 0; i < _legacyWingModels.Count; i++)
            {
                _legacyWingModels[i].PrecomputeCenterOfLift(velocityWorldVector, machNumber, density, center);
            }

            aeroForce  = center.force;
            aeroTorque = center.TorqueAt(_vessel.CoM);
        }
Пример #7
0
        /// <summary>
        /// These are just a few different attempts to figure drag for various blunt bodies
        /// </summary>
        private void DragModel(Vector3d local_velocity, double M, double rho)
        {
            // Has the same x/y/z as the vertices in PartMaxBoundaries etc
            Vector3d model_velocity = to_model_rotation * local_velocity;

            double viscousLift, potentialLift, newtonianLift;

            viscousLift = potentialLift = newtonianLift = 0;
            double CdAdd = 0;
            //float AxialProportion = Vector3.Dot(localUpVector, local_velocity);
            double AxialProportion     = model_velocity.y;
            float  AxialProportion_flt = (float)model_velocity.y;
            double AxialProportion_2   = AxialProportion * AxialProportion;
            double OneMinusAxial_2     = Math.Abs(1 - AxialProportion_2);
            double M_2       = M * M;
            double M_2_recip = 1 / M_2;
            double maxPressureCoeff;

            if (FARDebugValues.useSplinesForSupersonicMath)
            {
                maxPressureCoeff = FARAeroUtil.MaxPressureCoefficient.Evaluate((float)M);
            }
            else
            {
                maxPressureCoeff = FARAeroUtil.MaxPressureCoefficientCalc(M);
            }

            double sepFlowCd = SeparatedFlowDrag(M, M_2, M_2_recip);

            //This handles elliptical and other non-circular cross sections
            //float crossflowParameter = Vector3.Dot(localForwardVector, Vector3.Exclude(localUpVector, local_velocity).normalized);
            //crossflowParameter *= crossflowParameter;
            double crossflowParameter = model_velocity.z * model_velocity.z;
            double crossflow          = model_velocity.x * model_velocity.x + crossflowParameter;

            if (crossflow != 0)
            {
                crossflowParameter /= crossflow;
            }

            crossflowParameter = crossflowParameter * majorMinorAxisRatio + (1 - crossflowParameter) / majorMinorAxisRatio;
            if (AxialProportion_2 > 0.98)
            {
                crossflowParameter *= 50 * OneMinusAxial_2;
            }

            Cd += CdCurve.Evaluate(AxialProportion_flt);



            viscousLift = ClViscousCurve.Evaluate(AxialProportion_flt);

            double axialDirectionFactor = cosAngleCutoff * AxialProportion;

            if (axialDirectionFactor > 0)
            {
                Cd = Math.Min(Cd, sepFlowCd * taperCrossSectionAreaRatio) * AxialProportion_2 + Cd * OneMinusAxial_2;
            }
            else
            {
                Cd = Math.Min(Cd, maxPressureCoeff * taperCrossSectionAreaRatio) * AxialProportion_2 + Cd * OneMinusAxial_2;
            }

            if (M_2 > 1)
            {
                potentialLift = ClPotentialCurve.Evaluate(AxialProportion_flt) * M_2_recip;
            }
            else
            {
                potentialLift = ClPotentialCurve.Evaluate(AxialProportion_flt);
            }


            Cm = CmCurve.Evaluate(AxialProportion_flt) * 0.1;

            CoDshift = CenterOfDrag;

            double MachMultiplier = MachDragEffect(M);

            Cd *= MachMultiplier;

            if (HighLogic.LoadedSceneIsFlight)
            {
                Cd += FARAeroUtil.SkinFrictionDrag(rho, lengthScale, local_velocity.magnitude, M, FlightGlobals.getExternalTemperature(part.transform.position) + FARAeroUtil.currentBodyTemp);       //Skin friction drag
            }
            else
            {
                Cd += 0.005;
            }

            for (int i = 0; i < attachNodeDragList.Count; i++)
            {
                attachNodeData node = attachNodeDragList[i];

                double dotProd = Vector3d.Dot(node.location.normalized, local_velocity);
                double tmp     = 0;
                double Cltmp   = 0;
                if (dotProd < 0)
                {
                    dotProd *= dotProd;
                    tmp      = sepFlowCd;

                    //                    Cltmp = tmp * (dotProd - 1);
                    //                    Cltmp *= pair.Value;

                    tmp *= node.areaValue * dotProd;


                    //                    Vector3 CoDshiftOffset = -Vector3.Exclude(pair.Key, part.transform.worldToLocalMatrix.MultiplyVector(velocity.normalized)).normalized;
                    //                    CoDshiftOffset *= Mathf.Sqrt(Mathf.Clamp01(1 - dotProd));
                    //                    CoDshiftOffset *= Mathf.Sqrt(1.5f * pair.Value);

                    CoDshift += node.location * (tmp / (tmp + Cd));
                }
                else
                {
                    Vector3d worldPairVec = part_transform.TransformDirection(node.location.normalized);
                    double   dotProd_2    = dotProd * dotProd;
                    double   liftProd_2   = 1 - dotProd_2;
                    double   liftProd     = Vector3d.Dot(worldPairVec, liftDir);

                    double forceCoefficient = dotProd_2 * bluntBodyCosForceParameter;
                    forceCoefficient += liftProd_2 * bluntBodySinForceParameter;
                    forceCoefficient *= maxPressureCoeff * node.areaValue;      //force applied perependicular to the flat end of the node

                    tmp   = forceCoefficient * dotProd;
                    Cltmp = -forceCoefficient * liftProd;       //negative because lift is in opposite direction of projection of velocity vector onto node direction

                    double Cmtmp = dotProd * liftProd * bluntBodyMomentParameter;
                    Cmtmp *= node.areaValue * node.recipDiameter;

                    if (!node.pitchesAwayFromUpVec)
                    {
                        Cmtmp *= -1;
                    }

                    Cm += Cmtmp;

                    double tmpCdCl = Math.Sqrt(tmp * tmp + Cltmp * Cltmp);
                    CoDshift += node.location * (tmpCdCl / (tmpCdCl + Math.Sqrt(Cd * Cd + Cl * Cl)));

                    /*double liftProd = Vector3d.Dot(worldPairVec, liftDir);
                     *
                     * tmp = maxPressureCoeff * dotProd_2 * dotProd;
                     * tmp *= node.areaValue;
                     *
                     * Cltmp = maxPressureCoeff * dotProd_2 * liftProd;
                     * Cltmp *= -node.areaValue;
                     *
                     * double radius = Math.Sqrt(node.areaValue / Math.PI);
                     * Vector3 CoDshiftOffset = Vector3.Exclude(node.location, local_velocity).normalized;
                     * CoDshiftOffset *= (float)(Math.Abs(liftProd) * radius * 0.4);
                     *
                     * double Cmtmp;
                     * if (node.pitchesAwayFromUpVec)
                     *  Cmtmp = -0.325 * radius * node.areaValue / S * Math.Abs(liftProd);
                     * else
                     *  Cmtmp = 0.325 * radius * node.areaValue / S * Math.Abs(liftProd);
                     *
                     * double tmpCdCl = Math.Sqrt(tmp * tmp + Cltmp * Cltmp);
                     *
                     * CoDshift += node.location * (tmpCdCl / (tmpCdCl + Math.Sqrt(Cd * Cd + Cl * Cl))) + CoDshiftOffset;
                     *
                     * Cm += Cmtmp;*/
                }

                CdAdd         += tmp;
                newtonianLift += Cltmp;
            }


            viscousLift *= MachMultiplier;
            Cd          += CdAdd;
            Cl           = viscousLift + potentialLift;
            Cl          *= crossflowParameter;
            Cm          *= crossflowParameter;

            Cl += newtonianLift;

//            Debug.Log("Cd = " + Cd + " Cl = " + Cl + " Cm = " + Cm + "\nPot Lift = " + potentialLift + " Visc Lift = " + viscousLift + " Newt Lift = " + newtonianLift + "\nCdAdd = " + CdAdd + " sepFlowCd = " + sepFlowCd + " maxPressureCoeff = " + maxPressureCoeff + "\ntaperCrossSectionAreaRatio = " + taperCrossSectionAreaRatio + " crossflowParameter = " + crossflowParameter);
        }
Пример #8
0
        public void SimulateAeroProperties(
            out Vector3 aeroForce,
            out Vector3 aeroTorque,
            Vector3 velocityWorldVector,
            double altitude
            )
        {
            Vector3d position = vessel.CurrentPosition(altitude);

            if (velocityWorldVector.NearlyEqual(lastSimResults.VelocityVector) &&
                (FARAtmosphere.IsCustom
                 // Custom atmospheres are not guaranteed to be independent of latitude and longitude
                     ? position.NearlyEqual(lastSimResults.Position)
                     : altitude.NearlyEqual(lastSimResults.Position.z)))
            {
                aeroForce  = lastSimResults.Force;
                aeroTorque = lastSimResults.Torque;
                return;
            }

            var center = new FARCenterQuery();
            var dummy  = new FARCenterQuery();

            //Calculate main gas properties
            GasProperties properties = FARAtmosphere.GetGasProperties(vessel.mainBody, position, Planetarium.GetUniversalTime());

            if (properties.Pressure <= 0 || properties.Temperature <= 0)
            {
                aeroForce  = Vector3.zero;
                aeroTorque = Vector3.zero;
                return;
            }

            float velocityMag    = velocityWorldVector.magnitude;
            float machNumber     = (float)(velocityMag / properties.SpeedOfSound);
            float reynoldsNumber = (float)FARAeroUtil.CalculateReynoldsNumber(properties.Density,
                                                                              Length,
                                                                              velocityMag,
                                                                              machNumber,
                                                                              properties.Temperature,
                                                                              properties.AdiabaticIndex);

            float reynoldsPerLength = reynoldsNumber / (float)Length;
            float skinFriction      = (float)FARAeroUtil.SkinFrictionDrag(reynoldsNumber, machNumber);

            float pseudoKnudsenNumber = machNumber / (reynoldsNumber + machNumber);

            if (_currentAeroSections != null)
            {
                foreach (FARAeroSection curSection in _currentAeroSections)
                {
                    curSection?.PredictionCalculateAeroForces((float)properties.Density,
                                                              machNumber,
                                                              reynoldsPerLength,
                                                              pseudoKnudsenNumber,
                                                              skinFriction,
                                                              velocityWorldVector,
                                                              center);
                }

                foreach (FARWingAerodynamicModel curWing in _legacyWingModels)
                {
                    if (curWing != null)
                    {
                        center.AddForce(curWing.transform.position,
                                        curWing.PrecomputeCenterOfLift(velocityWorldVector,
                                                                       machNumber,
                                                                       properties.Density,
                                                                       dummy));
                    }
                }
            }

            aeroForce  = center.force;
            aeroTorque = center.TorqueAt(vessel.CoM);

            lastSimResults = new CachedSimResults(velocityWorldVector, position, aeroForce, aeroTorque);
        }
Пример #9
0
        public void SimulateAeroProperties(
            out Vector3 aeroForce,
            out Vector3 aeroTorque,
            Vector3 velocityWorldVector,
            double altitude
            )
        {
            var center = new FARCenterQuery();
            var dummy  = new FARCenterQuery();

            //Calculate main gas properties
            GasProperties properties = FARAtmosphere.GetGasProperties(vessel, altitude, Planetarium.GetUniversalTime());

            if (properties.Pressure <= 0 || properties.Temperature <= 0)
            {
                aeroForce  = Vector3.zero;
                aeroTorque = Vector3.zero;
                return;
            }

            float velocityMag    = velocityWorldVector.magnitude;
            float machNumber     = (float)(velocityMag / properties.SpeedOfSound);
            float reynoldsNumber = (float)FARAeroUtil.CalculateReynoldsNumber(properties.Density,
                                                                              Length,
                                                                              velocityMag,
                                                                              machNumber,
                                                                              properties.Temperature,
                                                                              properties.AdiabaticIndex);

            float reynoldsPerLength = reynoldsNumber / (float)Length;
            float skinFriction      = (float)FARAeroUtil.SkinFrictionDrag(reynoldsNumber, machNumber);

            float pseudoKnudsenNumber = machNumber / (reynoldsNumber + machNumber);

            if (_currentAeroSections != null)
            {
                foreach (FARAeroSection curSection in _currentAeroSections)
                {
                    curSection?.PredictionCalculateAeroForces((float)properties.Density,
                                                              machNumber,
                                                              reynoldsPerLength,
                                                              pseudoKnudsenNumber,
                                                              skinFriction,
                                                              velocityWorldVector,
                                                              center);
                }

                foreach (FARWingAerodynamicModel curWing in _legacyWingModels)
                {
                    if (curWing != null)
                    {
                        center.AddForce(curWing.transform.position,
                                        curWing.PrecomputeCenterOfLift(velocityWorldVector,
                                                                       machNumber,
                                                                       properties.Density,
                                                                       dummy));
                    }
                }
            }

            aeroForce  = center.force;
            aeroTorque = center.TorqueAt(vessel.CoM);
        }