Esempio n. 1
0
        double CalculateSunArea(ModularFI.ModularFlightIntegrator fi, FlightIntegrator.PartThermalData ptd)
        {
            FARAeroPartModule module = null;

            if (ptd.part.Modules.Contains("FARAeroPartModule"))
            {
                module = (FARAeroPartModule)ptd.part.Modules["FARAeroPartModule"];
            }

            if ((object)module != null)
            {
                double sunArea = module.ProjectedAreaWorld(fi.sunVector) * ptd.sunAreaMultiplier;

                if (sunArea > 0)
                {
                    return(sunArea);
                }
                else
                {
                    return(fi.BaseFIGetSunArea(ptd));
                }
            }
            else
            {
                return(fi.BaseFIGetSunArea(ptd));
            }
        }
Esempio n. 2
0
        double CalculateAreaExposed(ModularFI.ModularFlightIntegrator fi, Part part, FARAeroPartModule aeroModule)
        {
            if ((object)aeroModule != null)
            {
                double exposedArea = aeroModule.ProjectedAreaLocal(-part.dragVectorDirLocal);

                if (exposedArea > 0)
                {
                    return(exposedArea);
                }
                else
                {
                    return(fi.BaseFICalculateAreaExposed(part));
                }
            }
            else
            {
                return(fi.BaseFICalculateAreaExposed(part));
            }

            /*else
             * {
             *  if (stockRadArea > 0)
             *      return aeroModule.ProjectedAreas.totalArea * dragCubeExposed / stockRadArea;
             *  else
             *      return aeroModule.ProjectedAreas.totalArea;
             * }*/
        }
Esempio n. 3
0
        double CalculateBodyArea(ModularFI.ModularFlightIntegrator fi, FlightIntegrator.PartThermalData ptd)
        {
            FARAeroPartModule module = null;

            if (ptd.part.Modules.Contains("FARAeroPartModule"))
            {
                module = (FARAeroPartModule)ptd.part.Modules["FARAeroPartModule"];
            }

            if ((object)module != null)
            {
                double bodyArea = module.ProjectedAreaWorld(-fi.Vessel.upAxis) * ptd.bodyAreaMultiplier;

                if (bodyArea > 0)
                {
                    return(bodyArea);
                }
                else
                {
                    return(fi.BaseFIBodyArea(ptd));
                }
            }
            else
            {
                return(fi.BaseFIBodyArea(ptd));
            }
        }
        private static void UpdateThermodynamicsPre(ModularFlightIntegrator fi)
        {
            for (int i = 0; i < fi.PartThermalDataCount; i++)
            {
                PartThermalData ptd  = fi.partThermalDataList[i];
                Part            part = ptd.part;
                if (!part.Modules.Contains <FARAeroPartModule>())
                {
                    continue;
                }

                FARAeroPartModule aeroModule = part.Modules.GetModule <FARAeroPartModule>();

                // make sure drag cube areas are correct based on voxelization
                if (!part.DragCubes.None && aeroModule)
                {
                    for (int j = 0; j < 6; j++)
                    {
                        part.DragCubes.AreaOccluded[FARAeroPartModule.ProjectedArea.FaceMap[j]] =
                            (float)aeroModule.ProjectedAreas[j];
                    }
                }

                part.radiativeArea = CalculateAreaRadiative(fi, part, aeroModule);
                part.exposedArea   =
                    part.machNumber > 0 ? CalculateAreaExposed(fi, part, aeroModule) : part.radiativeArea;

                if (FARSettings.ExposedAreaLimited && part.exposedArea > part.radiativeArea)
                {
                    part.exposedArea = part.radiativeArea; //sanity check just in case
                }
            }
        }
Esempio n. 5
0
        private void FixedUpdate()
        {
            if (_vehicleAero == null)
            {
                return;
            }
            if (_vehicleAero.CalculationCompleted)
            {
                _vehicleAero.GetNewAeroData(out _currentAeroModules, out _unusedAeroModules, out _currentAeroSections, out _legacyWingModels);

                if ((object)_flightGUI == null)
                {
                    _flightGUI = _vessel.GetComponent <FerramAerospaceResearch.FARGUI.FARFlightGUI.FlightGUI>();
                }

                _flightGUI.UpdateAeroModules(_currentAeroModules, _legacyWingModels);
                //Debug.Log("Updating " + _vessel.vesselName + " aero properties\n\rCross-Sectional Area: " + _vehicleAero.MaxCrossSectionArea + " Crit Mach: " + _vehicleAero.CriticalMach + "\n\rUnusedAeroCount: " + _unusedAeroModules.Count + " UsedAeroCount: " + _currentAeroModules.Count + " sectCount: " + _currentAeroSections.Count);

                for (int i = 0; i < _unusedAeroModules.Count; i++)
                {
                    FARAeroPartModule a = _unusedAeroModules[i];
                    a.SetShielded(true);
                    a.ForceLegacyAeroUpdates();
                    //Debug.Log(a.part.partInfo.title + " shielded, area: " + a.ProjectedAreas.totalArea);
                }

                for (int i = 0; i < _currentAeroModules.Count; i++)
                {
                    FARAeroPartModule a = _currentAeroModules[i];
                    a.SetShielded(false);
                    a.ForceLegacyAeroUpdates();
                    //Debug.Log(a.part.partInfo.title + " unshielded, area: " + a.ProjectedAreas.totalArea);
                }

                _vesselIntakeRamDrag.UpdateAeroData(_currentAeroModules, _unusedAeroModules);
            }

            if (FlightGlobals.ready && _currentAeroSections != null && _vessel)
            {
                CalculateAndApplyVesselAeroProperties();
            }


            if (_currentGeoModules.Count > geoModulesReady)
            {
                CheckGeoModulesReady();
            }
            if (_updateRateLimiter < FARSettingsScenarioModule.VoxelSettings.minPhysTicksPerUpdate)
            {
                _updateRateLimiter++;
            }
            else if (_updateQueued)
            {
                VesselUpdate(_recalcGeoModules);
            }
        }
 double CalculateAreaRadiative(ModularFI.ModularFlightIntegrator fi, Part part, FARAeroPartModule aeroModule)
 {
     //double dragCubeExposed = fi.BaseFICalculateAreaExposed(part);
     if ((object)aeroModule == null)
         return fi.BaseFICalculateAreaRadiative(part);
     else
     {
         return aeroModule.ProjectedAreas.totalArea;
     }
 }
        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();
            }
        }
Esempio n. 8
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();
            }
        }
        double CalculateAreaExposed(ModularFI.ModularFlightIntegrator fi, Part part)
        {
            FARAeroPartModule module = null;

            if (part.Modules.Contains <FARAeroPartModule>())
            {
                module = part.Modules.GetModule <FARAeroPartModule>();
            }

            return(CalculateAreaExposed(fi, part, module));
        }
Esempio n. 10
0
        private static double CalculateAreaRadiative(ModularFlightIntegrator fi, Part part)
        {
            FARAeroPartModule module = null;

            if (part.Modules.Contains <FARAeroPartModule>())
            {
                module = part.Modules.GetModule <FARAeroPartModule>();
            }

            return(CalculateAreaRadiative(fi, part, module));
        }
        double CalculateAreaExposed(ModularFI.ModularFlightIntegrator fi, Part part)
        {
            FARAeroPartModule module = null;

            if (part.Modules.Contains("FARAeroPartModule"))
            {
                module = (FARAeroPartModule)part.Modules["FARAeroPartModule"];
            }

            return(CalculateAreaExposed(fi, part, module));
        }
        private static double CalculateBodyArea(ModularFlightIntegrator fi, PartThermalData ptd)
        {
            FARAeroPartModule module = ptd.part.Modules.GetModule <FARAeroPartModule>();

            if (module is null)
            {
                return(fi.BaseFIBodyArea(ptd));
            }
            double bodyArea = module.ProjectedAreaWorld(-fi.Vessel.upAxis) * ptd.bodyAreaMultiplier;

            return(bodyArea > 0 ? bodyArea : fi.BaseFIBodyArea(ptd));
        }
        private static double CalculateSunArea(ModularFlightIntegrator fi, PartThermalData ptd)
        {
            FARAeroPartModule module = ptd.part.Modules.GetModule <FARAeroPartModule>();

            if (module is null)
            {
                return(fi.BaseFIGetSunArea(ptd));
            }
            double sunArea = module.ProjectedAreaWorld(fi.sunVector) * ptd.sunAreaMultiplier;

            return(sunArea > 0 ? sunArea : fi.BaseFIGetSunArea(ptd));
        }
 double CalculateAreaExposed(ModularFI.ModularFlightIntegrator fi, Part part, FARAeroPartModule aeroModule)
 {
     double dragCubeExposed = fi.BaseFICalculateAreaExposed(part);
     if (aeroModule == null)
         return dragCubeExposed;
     else
     {
         double cubeRadiative = fi.BaseFICalculateAreaRadiative(part);
         if (cubeRadiative > 0)
             return aeroModule.ProjectedAreas.totalArea * dragCubeExposed / cubeRadiative;
         else
             return aeroModule.ProjectedAreas.totalArea;
     }
 }
 double CalculateAreaExposed(ModularFI.ModularFlightIntegrator fi, Part part, FARAeroPartModule aeroModule)
 {
     if ((object)aeroModule == null)
         return fi.BaseFICalculateAreaExposed(part);
     else
         return aeroModule.ProjectedAreaLocal(-part.dragVectorDirLocal);
     /*else
     {
         if (stockRadArea > 0)
             return aeroModule.ProjectedAreas.totalArea * dragCubeExposed / stockRadArea;
         else
             return aeroModule.ProjectedAreas.totalArea;
     }*/
 }
Esempio n. 16
0
        private static double CalculateAreaRadiative(
            ModularFlightIntegrator fi,
            Part part,
            FARAeroPartModule aeroModule
            )
        {
            if (aeroModule is null)
            {
                return(fi.BaseFICalculateAreaRadiative(part));
            }
            double radArea = aeroModule.ProjectedAreas.totalArea;

            return(radArea > 0 ? radArea : fi.BaseFICalculateAreaRadiative(part));
        }
Esempio n. 17
0
        private void FixedUpdate()
        {
            if (_vehicleAero == null)
            {
                return;
            }
            if (_vehicleAero.CalculationCompleted)
            {
                _vehicleAero.GetNewAeroData(out _currentAeroModules, out _unusedAeroModules, out _currentAeroSections, out _legacyWingModels);

                _vessel.SendMessage("UpdateAeroModules", _currentAeroModules);

                for (int i = 0; i < _unusedAeroModules.Count; i++)
                {
                    FARAeroPartModule a = _unusedAeroModules[i];
                    a.SetShielded(true);
                    //Debug.Log(a.part.partInfo.title + " shielded");
                }

                for (int i = 0; i < _currentAeroModules.Count; i++)
                {
                    FARAeroPartModule a = _currentAeroModules[i];
                    a.SetShielded(false);
                    //Debug.Log(a.part.partInfo.title + " unshielded");
                }

                _vesselIntakeRamDrag.UpdateAeroData(_currentAeroModules, _unusedAeroModules);
            }

            if (FlightGlobals.ready && _currentAeroSections != null)
            {
                CalculateAndApplyVesselAeroProperties();
            }

            if (_currentGeoModules.Count > geoModulesReady)
            {
                CheckGeoModulesReady();
            }
            if (_updateRateLimiter < FARSettingsScenarioModule.VoxelSettings.minPhysTicksPerUpdate)
            {
                _updateRateLimiter++;
            }
            else if (_updateQueued)
            {
                VesselUpdate(_recalcGeoModules);
            }
        }
Esempio n. 18
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();
                }
            }
        }
        private static void UpdateThermodynamicsPre(ModularFlightIntegrator fi)
        {
            bool voxelizationCompleted =
                (fi.Vessel.vesselModules.Find(module => module is FARVesselAero) as FARVesselAero)?
                .HasEverValidVoxelization() ?? false;

            for (int i = 0; i < fi.PartThermalDataCount; i++)
            {
                PartThermalData   ptd        = fi.partThermalDataList[i];
                Part              part       = ptd.part;
                FARAeroPartModule aeroModule = part.Modules.GetModule <FARAeroPartModule>();
                if (aeroModule is null)
                {
                    continue;
                }

                // make sure drag cube areas are correct based on voxelization
                if (voxelizationCompleted)
                {
                    if (!part.DragCubes.None && aeroModule)
                    {
                        for (int j = 0; j < 6; j++)
                        {
                            part.DragCubes.AreaOccluded[FARAeroPartModule.ProjectedArea.FaceMap[j]] =
                                (float)aeroModule.ProjectedAreas[j];
                        }
                    }

                    part.radiativeArea = CalculateAreaRadiative(fi, part, aeroModule);
                    part.exposedArea   = part.machNumber > 0
                                           ? CalculateAreaExposed(fi, part, aeroModule)
                                           : part.radiativeArea;
                }
                else
                {
                    part.radiativeArea = fi.BaseFICalculateAreaRadiative(part);
                    part.exposedArea   = fi.BaseFICalculateAreaExposed(part);
                }

                if (FARSettings.ExposedAreaLimited && part.exposedArea > part.radiativeArea)
                {
                    part.exposedArea = part.radiativeArea; //sanity check just in case
                }
            }
        }
        void UpdateThermodynamicsPre(ModularFI.ModularFlightIntegrator fi)
        {
            for (int i = 0; i < fi.PartThermalDataCount; i++)
            {
                Part part = fi.partThermalDataList[i].part;
                if (!part.Modules.Contains("FARAeroPartModule"))
                {
                    continue;
                }

                PartModule module = part.Modules["FARAeroPartModule"];

                FARAeroPartModule aeroModule = (FARAeroPartModule)module;

                part.radiativeArea = CalculateAreaRadiative(fi, part, aeroModule);
                part.exposedArea   = part.machNumber > 0 ? CalculateAreaExposed(fi, part, aeroModule) : 0;
            }
            //Debug.Log("MFI: " + fi.CoM + " " + Planetarium.GetUniversalTime());
        }
        double CalculateAreaExposed(ModularFI.ModularFlightIntegrator fi, Part part, FARAeroPartModule aeroModule)
        {
            double dragCubeExposed = fi.BaseFICalculateAreaExposed(part);

            if (aeroModule == null)
            {
                return(dragCubeExposed);
            }
            else
            {
                double cubeRadiative = fi.BaseFICalculateAreaRadiative(part);
                if (cubeRadiative > 0)
                {
                    return(aeroModule.ProjectedAreas.totalArea * dragCubeExposed / cubeRadiative);
                }
                else
                {
                    return(aeroModule.ProjectedAreas.totalArea);
                }
            }
        }
        private void ApplyIntakeDrag(float currentRamDrag, Vector3 vesselVelNorm, float dynPres)
        {
            for (int i = _intakeTransforms.Count - 1; i >= 0; i--)
            {
                ModuleResourceIntake intake = _intakeModules[i];
                if (!intake.intakeEnabled)
                {
                    continue;
                }

                Transform transform = _intakeTransforms[i];
                if (transform == null)
                {
                    _intakeModules.RemoveAt(i);
                    _intakeTransforms.RemoveAt(i);
                    _aeroModulesWithIntakes.RemoveAt(i);
                    //++i;
                    continue;
                }

                float cosAoA = Vector3.Dot(_intakeTransforms[i].forward, vesselVelNorm);
                if (cosAoA < 0)
                {
                    cosAoA = 0;
                }

                if (cosAoA <= 0)
                {
                    continue;
                }

                FARAeroPartModule aeroModule = _aeroModulesWithIntakes[i];


                Vector3 force = -aeroModule.partLocalVelNorm * cosAoA * currentRamDrag * (float)intake.area * 100f;
                //if(float.IsNaN(force.sqrMagnitude))
                //    force = Vector3.zero;
                aeroModule.AddLocalForce(force, Vector3.zero);
            }
        }
Esempio n. 23
0
        private void ApplyIntakeDrag(float currentRamDrag, Vector3 vesselVelNorm, float dynPres)
        {
            for (int i = 0; i < _intakeTransforms.Count; i++)
            {
                ModuleResourceIntake intake = _intakeModules[i];
                if (!intake.intakeEnabled)
                {
                    continue;
                }

                Transform transform = _intakeTransforms[i];
                if (transform == null)
                {
                    _intakeModules.RemoveAt(i);
                    _intakeTransforms.RemoveAt(i);
                    _aeroModulesWithIntakes.RemoveAt(i);
                    --i;
                    continue;
                }

                float cosAoA = Vector3.Dot(_intakeTransforms[i].forward, vesselVelNorm);
                if (cosAoA < 0)
                {
                    cosAoA = 0;
                }

                if (cosAoA <= intake.aoaThreshold)
                {
                    continue;
                }

                FARAeroPartModule aeroModule = _aeroModulesWithIntakes[i];

                aeroModule.AddLocalForce(-aeroModule.partLocalVelNorm * dynPres * cosAoA * currentRamDrag * intake.area * 100, Vector3.zero);
            }
        }
        private static double CalculateAreaExposed(ModularFlightIntegrator fi, Part part)
        {
            FARAeroPartModule module = part.Modules.GetModule <FARAeroPartModule>();

            return(CalculateAreaExposed(fi, part, module));
        }
 double CalculateAreaRadiative(ModularFI.ModularFlightIntegrator fi, Part part, FARAeroPartModule aeroModule)
 {
     //double dragCubeExposed = fi.BaseFICalculateAreaExposed(part);
     if ((object)aeroModule == null)
     {
         return(fi.BaseFICalculateAreaRadiative(part));
     }
     else
     {
         return(aeroModule.ProjectedAreas.totalArea);
     }
 }
        public void PredictionCalculateAeroForces(float atmDensity, float machNumber, float reynoldsPerUnitLength, float pseudoKnudsenNumber, float skinFrictionDrag, Vector3 vel, ferram4.FARCenterQuery center)
        {
            if (partData.Count == 0)
            {
                return;
            }

            PartData          data       = partData[0];
            FARAeroPartModule aeroModule = null;

            for (int i = 0; i < partData.Count; i++)
            {
                data       = partData[i];
                aeroModule = data.aeroModule;
                if (aeroModule.part == null || aeroModule.part.partTransform == null)
                {
                    continue;
                }
                break;
            }
            if (aeroModule.part == null || aeroModule.part.transform == null)
            {
                return;
            }
            double skinFrictionForce = skinFrictionDrag * xForceSkinFriction.Evaluate(machNumber);      //this will be the same for each part, so why recalc it multiple times?
            double xForceAoA0        = xForcePressureAoA0.Evaluate(machNumber);
            double xForceAoA180      = xForcePressureAoA180.Evaluate(machNumber);

            Vector3 xRefVector = data.xRefVectorPartSpace;
            Vector3 nRefVector = data.nRefVectorPartSpace;

            Vector3 velLocal = aeroModule.part.partTransform.worldToLocalMatrix.MultiplyVector(vel);

            //Vector3 angVelLocal = aeroModule.partLocalAngVel;

            //velLocal += Vector3.Cross(angVelLocal, data.centroidPartSpace);       //some transform issue here, needs investigation
            Vector3 velLocalNorm = velLocal.normalized;

            Vector3 localNormalForceVec = Vector3.ProjectOnPlane(-velLocalNorm, xRefVector).normalized;

            double cosAoA     = Vector3.Dot(xRefVector, velLocalNorm);
            double cosSqrAoA  = cosAoA * cosAoA;
            double sinSqrAoA  = Math.Max(1 - cosSqrAoA, 0);
            double sinAoA     = Math.Sqrt(sinSqrAoA);
            double sin2AoA    = 2 * sinAoA * Math.Abs(cosAoA);
            double cosHalfAoA = Math.Sqrt(0.5 + 0.5 * Math.Abs(cosAoA));


            double nForce = 0;

            nForce = cosHalfAoA * sin2AoA * potentialFlowNormalForce * Math.Sign(cosAoA); //potential flow normal force
            if (nForce < 0)                                                               //potential flow is not significant over the rear face of things
            {
                nForce = 0;
            }
            //if (machNumber > 3)
            //    nForce *= 2d - machNumber * 0.3333333333333333d;

            float normalForceFactor = Math.Abs(Vector3.Dot(localNormalForceVec, nRefVector));

            normalForceFactor *= normalForceFactor;

            normalForceFactor = invFlatnessRatio * (1 - normalForceFactor) + flatnessRatio * normalForceFactor;     //accounts for changes in relative flatness of shape


            float crossFlowMach, crossFlowReynolds;

            crossFlowMach     = machNumber * (float)sinAoA;
            crossFlowReynolds = reynoldsPerUnitLength * diameter * normalForceFactor * (float)sinAoA;

            nForce += viscCrossflowDrag * sinSqrAoA * CalculateCrossFlowDrag(crossFlowMach, crossFlowReynolds);            //viscous crossflow normal force

            nForce *= normalForceFactor;

            double xForce = -skinFrictionForce *Math.Sign(cosAoA) * cosSqrAoA;

            double localVelForce = xForce * pseudoKnudsenNumber;

            xForce -= localVelForce;

            localVelForce = Math.Abs(localVelForce);

            float moment = (float)(cosAoA * sinAoA);


            if (cosAoA > 0)
            {
                xForce += cosSqrAoA * xForceAoA0;
                float momentFactor;
                if (machNumber > 6)
                {
                    momentFactor = hypersonicMomentForward;
                }
                else if (machNumber < 0.6)
                {
                    momentFactor = 0.6f * hypersonicMomentBackward;
                }
                else
                {
                    float tmp = (-0.185185185f * machNumber + 1.11111111111f);
                    momentFactor = tmp * hypersonicMomentBackward * 0.6f + (1 - tmp) * hypersonicMomentForward;
                }
                //if (machNumber < 1.5)
                //    momentFactor += hypersonicMomentBackward * (0.5f - machNumber * 0.33333333333333333333333333333333f) * 0.2f;

                moment *= momentFactor;
            }
            else
            {
                xForce += cosSqrAoA * xForceAoA180;
                float momentFactor;     //negative to deal with the ref vector facing the opposite direction, causing the moment vector to point in the opposite direction
                if (machNumber > 6)
                {
                    momentFactor = hypersonicMomentBackward;
                }
                else if (machNumber < 0.6)
                {
                    momentFactor = 0.6f * hypersonicMomentForward;
                }
                else
                {
                    float tmp = (-0.185185185f * machNumber + 1.11111111111f);
                    momentFactor = tmp * hypersonicMomentForward * 0.6f + (1 - tmp) * hypersonicMomentBackward;
                }
                //if (machNumber < 1.5)
                //    momentFactor += hypersonicMomentForward * (0.5f - machNumber * 0.33333333333333333333333333333333f) * 0.2f;

                moment *= momentFactor;
            }
            moment /= normalForceFactor;

            Vector3 forceVector = (float)xForce * xRefVector + (float)nForce * localNormalForceVec;

            forceVector -= (float)localVelForce * velLocalNorm;
            Vector3 torqueVector = Vector3.Cross(xRefVector, localNormalForceVec) * moment;

            Matrix4x4 localToWorld = aeroModule.part.partTransform.localToWorldMatrix;

            float dynPresAndScaling = 0.0005f * atmDensity * velLocal.sqrMagnitude;        //dyn pres and N -> kN conversion

            forceVector  *= dynPresAndScaling;
            torqueVector *= dynPresAndScaling;

            forceVector  = localToWorld.MultiplyVector(forceVector);
            torqueVector = localToWorld.MultiplyVector(torqueVector);
            Vector3 centroid = Vector3.zero;

            for (int i = 0; i < partData.Count; i++)
            {
                PartData          data2  = partData[i];
                FARAeroPartModule module = data2.aeroModule;
                if ((object)module == null)
                {
                    continue;
                }

                if (module.part == null || module.part.partTransform == null)
                {
                    continue;
                }

                centroid = module.part.partTransform.localToWorldMatrix.MultiplyPoint3x4(data2.centroidPartSpace);
                center.AddForce(centroid, forceVector * data2.dragFactor);
            }
            center.AddTorque(torqueVector);
        }
        public void FlightCalculateAeroForces(float atmDensity, float machNumber, float reynoldsPerUnitLength, float pseudoKnudsenNumber, float skinFrictionDrag)
        {
            double skinFrictionForce = skinFrictionDrag * xForceSkinFriction.Evaluate(machNumber);      //this will be the same for each part, so why recalc it multiple times?
            double xForceAoA0        = xForcePressureAoA0.Evaluate(machNumber);
            double xForceAoA180      = xForcePressureAoA180.Evaluate(machNumber);

            for (int i = 0; i < partData.Count; i++)
            {
                PartData          data       = partData[i];
                FARAeroPartModule aeroModule = data.aeroModule;
                if ((object)aeroModule == null)
                {
                    continue;
                }

                Vector3 xRefVector = data.xRefVectorPartSpace;
                Vector3 nRefVector = data.nRefVectorPartSpace;

                Vector3 velLocal = aeroModule.partLocalVel;

                Vector3 angVelLocal = aeroModule.partLocalAngVel;

                velLocal += Vector3.Cross(data.centroidPartSpace, angVelLocal);       //some transform issue here, needs investigation
                Vector3 velLocalNorm = velLocal.normalized;

                Vector3 localNormalForceVec = Vector3.ProjectOnPlane(-velLocalNorm, xRefVector).normalized;

                double cosAoA     = Vector3.Dot(xRefVector, velLocalNorm);
                double cosSqrAoA  = cosAoA * cosAoA;
                double sinSqrAoA  = Math.Max(1 - cosSqrAoA, 0);
                double sinAoA     = Math.Sqrt(sinSqrAoA);
                double sin2AoA    = 2 * sinAoA * Math.Abs(cosAoA);
                double cosHalfAoA = Math.Sqrt(0.5 + 0.5 * Math.Abs(cosAoA));


                double nForce = 0;
                nForce = potentialFlowNormalForce * Math.Sign(cosAoA) * cosHalfAoA * sin2AoA; //potential flow normal force
                if (nForce < 0)                                                               //potential flow is not significant over the rear face of things
                {
                    nForce = 0;
                }

                //if (machNumber > 3)
                //    nForce *= 2d - machNumber * 0.3333333333333333d;

                float normalForceFactor = Math.Abs(Vector3.Dot(localNormalForceVec, nRefVector));
                normalForceFactor *= normalForceFactor;

                normalForceFactor = invFlatnessRatio * (1 - normalForceFactor) + flatnessRatio * normalForceFactor;     //accounts for changes in relative flatness of shape


                float crossFlowMach, crossFlowReynolds;
                crossFlowMach     = machNumber * (float)sinAoA;
                crossFlowReynolds = reynoldsPerUnitLength * diameter * (float)sinAoA / normalForceFactor;

                nForce += viscCrossflowDrag * sinSqrAoA * CalculateCrossFlowDrag(crossFlowMach, crossFlowReynolds);            //viscous crossflow normal force

                nForce *= normalForceFactor;

                double xForce = -skinFrictionForce *Math.Sign(cosAoA) * cosSqrAoA;

                double localVelForce = xForce * pseudoKnudsenNumber;
                xForce -= localVelForce;

                localVelForce = Math.Abs(localVelForce);

                float moment        = (float)(cosAoA * sinAoA);
                float dampingMoment = 4f * moment;

                if (cosAoA > 0)
                {
                    xForce += cosSqrAoA * xForceAoA0;
                    float momentFactor;
                    if (machNumber > 6)
                    {
                        momentFactor = hypersonicMomentForward;
                    }
                    else if (machNumber < 0.6)
                    {
                        momentFactor = 0.6f * hypersonicMomentBackward;
                    }
                    else
                    {
                        float tmp = (-0.185185185f * machNumber + 1.11111111111f);
                        momentFactor = tmp * hypersonicMomentBackward * 0.6f + (1 - tmp) * hypersonicMomentForward;
                    }
                    //if (machNumber < 1.5)
                    //    momentFactor += hypersonicMomentBackward * (0.5f - machNumber * 0.33333333333333333333333333333333f) * 0.2f;

                    moment        *= momentFactor;
                    dampingMoment *= momentFactor;
                }
                else
                {
                    xForce += cosSqrAoA * xForceAoA180;
                    float momentFactor;     //negative to deal with the ref vector facing the opposite direction, causing the moment vector to point in the opposite direction
                    if (machNumber > 6)
                    {
                        momentFactor = hypersonicMomentBackward;
                    }
                    else if (machNumber < 0.6)
                    {
                        momentFactor = 0.6f * hypersonicMomentForward;
                    }
                    else
                    {
                        float tmp = (-0.185185185f * machNumber + 1.11111111111f);
                        momentFactor = tmp * hypersonicMomentForward * 0.6f + (1 - tmp) * hypersonicMomentBackward;
                    }
                    //if (machNumber < 1.5)
                    //    momentFactor += hypersonicMomentForward * (0.5f - machNumber * 0.33333333333333333333333333333333f) * 0.2f;

                    moment        *= momentFactor;
                    dampingMoment *= momentFactor;
                }
                moment       /= normalForceFactor;
                dampingMoment = Math.Abs(dampingMoment) * 0.1f;
                //dampingMoment += (float)Math.Abs(skinFrictionForce) * 0.1f;
                float rollDampingMoment = (float)(skinFrictionForce * 0.5 * diameter); //skin friction force times avg moment arm for vehicle
                rollDampingMoment *= (0.75f + flatnessRatio * 0.25f);                  //this is just an approximation for now

                Vector3 forceVector = (float)xForce * xRefVector + (float)nForce * localNormalForceVec;
                forceVector -= (float)localVelForce * velLocalNorm;

                Vector3 torqueVector = Vector3.Cross(xRefVector, localNormalForceVec) * moment;

                Vector3 axialAngLocalVel    = Vector3.Dot(xRefVector, angVelLocal) * xRefVector;
                Vector3 nonAxialAngLocalVel = angVelLocal - axialAngLocalVel;

                if (velLocal.sqrMagnitude > 0.001f)
                {
                    torqueVector -= (dampingMoment * nonAxialAngLocalVel) + (rollDampingMoment * axialAngLocalVel * axialAngLocalVel.magnitude) / velLocal.sqrMagnitude;
                }
                else
                {
                    torqueVector -= (dampingMoment * nonAxialAngLocalVel) + (rollDampingMoment * axialAngLocalVel * axialAngLocalVel.magnitude) / 0.001f;
                }

                //float dynPresAndScaling = 0.0005f * atmDensity * velLocal.sqrMagnitude * data.dragFactor;        //dyn pres and N -> kN conversion

                //forceVector *= dynPresAndScaling;
                //torqueVector *= dynPresAndScaling;

                forceVector  *= data.dragFactor;
                torqueVector *= data.dragFactor;

                aeroModule.AddLocalForceAndTorque(forceVector, torqueVector, data.centroidPartSpace);
            }
        }
        public void UpdateAeroData(List <FARAeroPartModule> allUsedAeroModules, List <FARAeroPartModule> allUnusedAeroModules)
        {
            _aeroModulesWithIntakes.Clear();
            _intakeModules.Clear();
            _intakeTransforms.Clear();
            _airBreathingEngines.Clear();

            HashSet <string> intakeResourceNames = new HashSet <string>();


            for (int i = 0; i < allUsedAeroModules.Count; i++)       //get all exposed intakes
            {
                FARAeroPartModule aeroModule = allUsedAeroModules[i];
                if (aeroModule == null)
                {
                    continue;
                }
                Part p = aeroModule.part;

                for (int j = 0; j < p.Modules.Count; j++)
                {
                    PartModule m = p.Modules[j];
                    if (m is ModuleResourceIntake)
                    {
                        ModuleResourceIntake intake = (ModuleResourceIntake)m;

                        if (intake.node != null && intake.node.attachedPart != null)
                        {
                            continue;
                        }

                        _aeroModulesWithIntakes.Add(aeroModule);
                        _intakeModules.Add(intake);
                        _intakeTransforms.Add(p.FindModelTransform(intake.intakeTransformName));
                        if (!intakeResourceNames.Contains(intake.resourceName))
                        {
                            intakeResourceNames.Add(intake.resourceName);
                        }
                    }
                }
            }


            for (int i = 0; i < allUsedAeroModules.Count; i++)       //get all exposed engines
            {
                FARAeroPartModule aeroModule = allUsedAeroModules[i];
                if (aeroModule == null)
                {
                    continue;
                }
                Part p = aeroModule.part;

                for (int j = 0; j < p.Modules.Count; j++)
                {
                    PartModule m = p.Modules[j];

                    if (m is ModuleEngines)
                    {
                        ModuleEngines e = (ModuleEngines)m;
                        if (FARAeroUtil.AJELoaded)
                        {
                            if (m.ClassID == AJE_JET_CLASS_ID || m.ClassID == AJE_PROP_CLASS_ID)
                            {
                                _airBreathingEngines.Add(e);
                                continue;
                            }
                        }

                        for (int k = 0; k < e.propellants.Count; k++)
                        {
                            Propellant prop = e.propellants[k];
                            if (intakeResourceNames.Contains(prop.name))
                            {
                                _airBreathingEngines.Add(e);
                                break;
                            }
                        }
                    }
                }
            }
        }
        private static double CalculateAreaExposed(ModularFlightIntegrator fi, Part part, FARAeroPartModule aeroModule)
        {
            if (aeroModule is null)
            {
                return(fi.BaseFICalculateAreaExposed(part));
            }

            // Apparently stock exposed area is actually weighted by some function of mach number...
            // otherwise heating is much lower
            double exposedArea = FARSettings.ExposedAreaUsesKSPHack
                                     ? part.DragCubes.ExposedArea
                                     : aeroModule.ProjectedAreaLocal(-part.dragVectorDirLocal);

            return(exposedArea > 0 ? exposedArea : fi.BaseFICalculateAreaExposed(part));
        }
Esempio n. 30
0
        private void CalculateAeroForces(
            float machNumber,
            float reynoldsPerUnitLength,
            float pseudoKnudsenNumber,
            float skinFrictionDrag,
            IForceContext forceContext
            )
        {
            //this will be the same for each part, so why recalc it multiple times?
            double skinFrictionForce = skinFrictionDrag * xForceSkinFriction.Evaluate(machNumber);
            double xForceAoA0        = xForcePressureAoA0.Evaluate(machNumber);
            double xForceAoA180      = xForcePressureAoA180.Evaluate(machNumber);

            foreach (PartData data in partData)
            {
                FARAeroPartModule aeroModule = data.aeroModule;
                if (aeroModule is null)
                {
                    continue;
                }

                Vector3 xRefVector = data.xRefVectorPartSpace;
                Vector3 nRefVector = data.nRefVectorPartSpace;

                Vector3 velLocal = forceContext.LocalVelocity(data);
                // Rejects both negligible speed and invalid simulation cases
                if (velLocal.sqrMagnitude.NearlyEqual(0.0f))
                {
                    continue;
                }

                Vector3 angVelLocal = aeroModule.partLocalAngVel;

                //some transform issue here, needs investigation
                velLocal += Vector3.Cross(data.centroidPartSpace, angVelLocal);
                Vector3 velLocalNorm = velLocal.normalized;

                Vector3 localNormalForceVec = Vector3.ProjectOnPlane(-velLocalNorm, xRefVector).normalized;

                double cosAoA     = Vector3.Dot(xRefVector, velLocalNorm);
                double cosSqrAoA  = cosAoA * cosAoA;
                double sinSqrAoA  = Math.Max(1 - cosSqrAoA, 0);
                double sinAoA     = Math.Sqrt(sinSqrAoA);
                double sin2AoA    = 2 * sinAoA * Math.Abs(cosAoA);
                double cosHalfAoA = Math.Sqrt(0.5 + 0.5 * Math.Abs(cosAoA));


                //potential flow normal force
                double nForce = potentialFlowNormalForce * Math.Sign(cosAoA) * cosHalfAoA * sin2AoA;
                //potential flow is not significant over the rear face of things
                if (nForce < 0)
                {
                    nForce = 0;
                }

                float normalForceFactor = Math.Abs(Vector3.Dot(localNormalForceVec, nRefVector));
                normalForceFactor *= normalForceFactor;

                //accounts for changes in relative flatness of shape
                normalForceFactor = invFlatnessRatio * (1 - normalForceFactor) + flatnessRatio * normalForceFactor;


                float crossFlowMach     = machNumber * (float)sinAoA;
                float crossFlowReynolds = reynoldsPerUnitLength * diameter * (float)sinAoA / normalForceFactor;

                //viscous crossflow normal force
                nForce += viscCrossflowDrag * sinSqrAoA * CalculateCrossFlowDrag(crossFlowMach, crossFlowReynolds);

                nForce *= normalForceFactor;

                double xForce = -skinFrictionForce *Math.Sign(cosAoA) * cosSqrAoA;

                double localVelForce = xForce * pseudoKnudsenNumber;
                xForce -= localVelForce;

                localVelForce = Math.Abs(localVelForce);

                float moment        = (float)(cosAoA * sinAoA);
                float dampingMoment = 4f * moment;

                if (cosAoA > 0)
                {
                    xForce += cosSqrAoA * xForceAoA0;
                    float momentFactor;
                    if (machNumber > 6)
                    {
                        momentFactor = hypersonicMomentForward;
                    }
                    else if (machNumber < 0.6)
                    {
                        momentFactor = 0.6f * hypersonicMomentBackward;
                    }
                    else
                    {
                        float tmp = -0.185185185f * machNumber + 1.11111111111f;
                        momentFactor = tmp * hypersonicMomentBackward * 0.6f + (1 - tmp) * hypersonicMomentForward;
                    }

                    moment        *= momentFactor;
                    dampingMoment *= momentFactor;
                }
                else
                {
                    xForce += cosSqrAoA * xForceAoA180;
                    //negative to deal with the ref vector facing the opposite direction, causing the moment vector to point in the opposite direction
                    float momentFactor;
                    if (machNumber > 6)
                    {
                        momentFactor = hypersonicMomentBackward;
                    }
                    else if (machNumber < 0.6)
                    {
                        momentFactor = 0.6f * hypersonicMomentForward;
                    }
                    else
                    {
                        float tmp = -0.185185185f * machNumber + 1.11111111111f;
                        momentFactor = tmp * hypersonicMomentForward * 0.6f + (1 - tmp) * hypersonicMomentBackward;
                    }

                    moment        *= momentFactor;
                    dampingMoment *= momentFactor;
                }

                moment       /= normalForceFactor;
                dampingMoment = Math.Abs(dampingMoment) * 0.1f;
                //skin friction force times avg moment arm for vehicle
                float rollDampingMoment = (float)(skinFrictionForce * 0.5 * diameter);
                //this is just an approximation for now
                rollDampingMoment *= 0.75f + flatnessRatio * 0.25f;

                Vector3 forceVector = (float)xForce * xRefVector + (float)nForce * localNormalForceVec;
                forceVector -= (float)localVelForce * velLocalNorm;

                Vector3 torqueVector = Vector3.Cross(xRefVector, localNormalForceVec) * moment;

                Vector3 axialAngLocalVel    = Vector3.Dot(xRefVector, angVelLocal) * xRefVector;
                Vector3 nonAxialAngLocalVel = angVelLocal - axialAngLocalVel;

                if (velLocal.sqrMagnitude > 0.001f)
                {
                    torqueVector -= dampingMoment * nonAxialAngLocalVel +
                                    rollDampingMoment *
                                    axialAngLocalVel *
                                    axialAngLocalVel.magnitude /
                                    velLocal.sqrMagnitude;
                }
                else
                {
                    torqueVector -= dampingMoment * nonAxialAngLocalVel +
                                    rollDampingMoment * axialAngLocalVel * axialAngLocalVel.magnitude / 0.001f;
                }

                forceVector  *= data.dragFactor;
                torqueVector *= data.dragFactor;

                forceContext.ApplyForce(data, velLocal, forceVector, torqueVector);
            }
        }
Esempio n. 31
0
        private static double CalculateAreaExposed(ModularFlightIntegrator fi, Part part, FARAeroPartModule aeroModule)
        {
            if (aeroModule is null)
            {
                return(fi.BaseFICalculateAreaExposed(part));
            }
            double exposedArea = aeroModule.ProjectedAreaLocal(-part.dragVectorDirLocal);

            return(exposedArea > 0 ? exposedArea : fi.BaseFICalculateAreaExposed(part));
        }
Esempio n. 32
0
        public void UpdateAeroData(List <FARAeroPartModule> allUsedAeroModules, List <FARAeroPartModule> allUnusedAeroModules)
        {
            _aeroModulesWithIntakes.Clear();
            _intakeModules.Clear();
            _intakeTransforms.Clear();
            _airBreathingEngines.Clear();

            for (int i = 0; i < allUsedAeroModules.Count; i++)       //get all exposed intakes and engines
            {
                FARAeroPartModule aeroModule = allUsedAeroModules[i];
                if (aeroModule == null)
                {
                    continue;
                }
                Part p = aeroModule.part;

                if (p.Modules.Contains("ModuleResourceIntake"))
                {
                    ModuleResourceIntake intake = (ModuleResourceIntake)p.Modules["ModuleResourceIntake"];
                    _aeroModulesWithIntakes.Add(aeroModule);
                    _intakeModules.Add(intake);
                    _intakeTransforms.Add(p.FindModelTransform(intake.intakeTransformName));
                }
                if (p.Modules.Contains("ModuleEngines"))
                {
                    ModuleEngines engines = (ModuleEngines)p.Modules["ModuleEngines"];
                    for (int j = 0; j < engines.propellants.Count; j++)
                    {
                        Propellant prop = engines.propellants[j];
                        if (prop.name == "IntakeAir")
                        {
                            _airBreathingEngines.Add(engines);
                            break;
                        }
                    }
                }
                if (p.Modules.Contains("ModuleEnginesFX"))
                {
                    ModuleEnginesFX engines = (ModuleEnginesFX)p.Modules["ModuleEnginesFX"];
                    for (int j = 0; j < engines.propellants.Count; j++)
                    {
                        Propellant prop = engines.propellants[j];
                        if (prop.name == "IntakeAir")
                        {
                            _airBreathingEngines.Add(engines);
                            break;
                        }
                    }
                }
            }

            for (int i = 0; i < allUnusedAeroModules.Count; i++)     //get all covered airbreathing Engines
            {
                FARAeroPartModule aeroModule = allUnusedAeroModules[i];
                if (aeroModule == null)
                {
                    continue;
                }
                Part p = aeroModule.part;
                if (p.Modules.Contains("ModuleEngines"))
                {
                    ModuleEngines engines = (ModuleEngines)p.Modules["ModuleEngines"];
                    for (int j = 0; j < engines.propellants.Count; j++)
                    {
                        Propellant prop = engines.propellants[j];
                        if (prop.name == "IntakeAir")
                        {
                            _airBreathingEngines.Add(engines);
                            break;
                        }
                    }
                }
                if (p.Modules.Contains("ModuleEnginesFX"))
                {
                    ModuleEnginesFX engines = (ModuleEnginesFX)p.Modules["ModuleEnginesFX"];
                    for (int j = 0; j < engines.propellants.Count; j++)
                    {
                        Propellant prop = engines.propellants[j];
                        if (prop.name == "IntakeAir")
                        {
                            _airBreathingEngines.Add(engines);
                            break;
                        }
                    }
                }
            }
        }