void UpdateThermodynamicsPre(ModularFI.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>();

                //FARAeroPartModule aeroModule = (FARAeroPartModule)module;

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

                if (part.exposedArea > part.radiativeArea)
                {
                    part.exposedArea = part.radiativeArea;      //sanity check just in case
                }
                //fi.SetSkinProperties(ptd);
            }
            //fi.timeSinceLastUpdate = 0;
            //Debug.Log("MFI: " + fi.CoM + " " + Planetarium.GetUniversalTime());
        }
        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
                }
            }
        }
        double CalculateBodyArea(ModularFI.ModularFlightIntegrator fi, PartThermalData ptd)
        {
            FARAeroPartModule module = null;

            if (ptd.part.Modules.Contains <FARAeroPartModule>())
            {
                module = ptd.part.Modules.GetModule <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));
            }
        }
Esempio n. 4
0
        public static void UpdateThermodynamicsPre(ModularFI.ModularFlightIntegrator fi)
        {
            if (lastVessel != fi.Vessel || parts.Count != fi.partThermalDataList.Count)
            {
                parts.Clear();
                lastVessel = fi.Vessel;

                for (int i = fi.partThermalDataList.Count; i-- > 0;)
                {
                    var ptd  = fi.partThermalDataList[i];
                    var part = ptd.part;
                    if (part.GetComponent <ModuleNonReentryRated>())
                    {
                        parts.Add(part);
                    }
                }
            }

            for (int i = fi.partThermalDataList.Count; i-- > 0;)
            {
                PartThermalData ptd  = fi.partThermalDataList[i];
                var             part = ptd.part;
                if (parts.Contains(part))
                {
                    ptd.convectionTempMultiplier  = Math.Max(ptd.convectionTempMultiplier, 0.75d);
                    ptd.convectionCoeffMultiplier = Math.Max(ptd.convectionCoeffMultiplier, 0.75d);
                    ptd.convectionAreaMultiplier  = Math.Max(ptd.convectionAreaMultiplier, 0.75d);

                    ptd.postShockExtTemp = UtilMath.LerpUnclamped(part.vessel.atmosphericTemperature, part.vessel.externalTemperature, ptd.convectionTempMultiplier);
                    ptd.finalCoeff       = part.vessel.convectiveCoefficient * ptd.convectionArea * 0.001d * part.heatConvectiveConstant * ptd.convectionCoeffMultiplier;
                }
            }
        }
        double CalculateSunArea(ModularFI.ModularFlightIntegrator fi, PartThermalData ptd)
        {
            FARAeroPartModule module = null;

            if (ptd.part.Modules.Contains <FARAeroPartModule>())
            {
                module = ptd.part.Modules.GetModule <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. 6
0
 public override void UpdateRadiation(PartThermalData ptd)
 {
     if (updateRadiationOverride == null)
     {
         base.UpdateRadiation(ptd);
     }
     else
     {
         updateRadiationOverride(this, ptd);
     }
 }
Esempio n. 7
0
 public override double GetSunArea(PartThermalData ptd)
 {
     if (updateGetSunAreaOverride == null)
     {
         return(base.GetSunArea(ptd));
     }
     else
     {
         return(updateGetSunAreaOverride(this, ptd));
     }
 }
Esempio n. 8
0
 public override double GetBodyArea(PartThermalData ptd)
 {
     if (getBodyAreaOverride == null)
     {
         return(base.GetBodyArea(ptd));
     }
     else
     {
         return(getBodyAreaOverride(this, ptd));
     }
 }
Esempio n. 9
0
 public override void SetSkinProperties(PartThermalData ptd)
 {
     if (setSkinPropertiesOverride == null)
     {
         base.SetSkinProperties(ptd);
     }
     else
     {
         setSkinPropertiesOverride(this, 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));
        }
Esempio n. 11
0
 public static void UpdateThermodynamicsPre(ModularFI.ModularFlightIntegrator fi)
 {
     for (int i = fi.partThermalDataList.Count; i-- > 0;)
     {
         PartThermalData ptd = fi.partThermalDataList[i];
         if (ptd.part.maximum_drag == float.MinValue)
         {
             ptd.convectionTempMultiplier = Math.Max(ptd.convectionTempMultiplier, 0.5d);
             ptd.convectionTempMultiplier = Math.Max(ptd.convectionCoeffMultiplier, 0.5d);
         }
     }
 }
        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 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
                }
            }
        }
Esempio n. 14
0
        public static void UpdateThermodynamicsPre(ModularFI.ModularFlightIntegrator fi)
        {
            foreach (Part part in _registeredNonReentryParts)
            {
                if (part.vessel != fi.Vessel)
                {
                    continue;
                }

                PartThermalData ptd = part.ptd;
                ptd.convectionTempMultiplier  = Math.Max(ptd.convectionTempMultiplier, 0.75d);
                ptd.convectionCoeffMultiplier = Math.Max(ptd.convectionCoeffMultiplier, 0.75d);
                ptd.convectionAreaMultiplier  = Math.Max(ptd.convectionAreaMultiplier, 0.75d);

                ptd.postShockExtTemp = UtilMath.LerpUnclamped(part.vessel.atmosphericTemperature, part.vessel.externalTemperature, ptd.convectionTempMultiplier);
                ptd.finalCoeff       = part.vessel.convectiveCoefficient * ptd.convectionArea * 0.001d * part.heatConvectiveConstant * ptd.convectionCoeffMultiplier;
            }
        }
Esempio n. 15
0
        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;
                }

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

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

                if (part.exposedArea > part.radiativeArea)
                {
                    part.exposedArea = part.radiativeArea; //sanity check just in case
                }
            }
        }
Esempio n. 16
0
 public void BaseFIetSkinPropertie(PartThermalData ptd)
 {
     base.SetSkinProperties(ptd);
 }
Esempio n. 17
0
 public double BaseFIBodyArea(PartThermalData ptd)
 {
     return(base.GetBodyArea(ptd));
 }
        //Update aerodynamics
        //Adapted from KSP Trajectories, Kerbal Wind Tunnel, FAR, and AeroGUI
        void UpdateAerodynamics(ModularFI.ModularFlightIntegrator fi, Part part)
        {
            Vessel v = FlightGlobals.ActiveVessel;

            wx_enabled = Util.getWindBool(); //Is weather enabled?
            use_climo  = Util.useCLIM();     //Are we using the climatology
            use_point  = Util.useWX();       //Are we using MPAS point time-series

            //Get main vessel and get reference to Kerbin (i.e. celestial body)
            kerbin = Util.getbody();

            //Get wind vector (initialize to zero)
            Vector3d windVec = Vector3d.zero;

            if (use_climo)
            {
                //Retrieve wind vector from climatology
                windVec = KerbalWxClimo.getWSWind(); // .GetWind(FlightGlobals.currentMainBody, part, rb.position);
            }
            else if (use_point)
            {
                //Retrieve wind vector from point forecast
                windVec = KerbalWxPoint.getWSWind(); // .GetWind(FlightGlobals.currentMainBody, part, rb.position);
            }
            //Check to see if root part is in list. If not do not perform aero update.
            //This avoids updating aerodynamics of parts that have been decoupled and are no longer part of the active vessel.
            bool hasPart = false;

            for (int i = 0; i < fi.PartThermalDataCount; i++)
            {
                PartThermalData pttd  = fi.partThermalDataList[i];
                Part            ppart = pttd.part;
                if (ppart == v.rootPart)
                {
                    hasPart = true;
                }
            }

            if (!hasPart)
            {
                return;
            }

            //Get position of current vessel
            double vheight = v.altitude;
            double vlat    = v.latitude;
            double vlng    = v.longitude;

            double air_pressure; double air_density; double soundSpeed;
            //Define gamma (i.e. ratio between specific heat of dry air at constant pressure and specific heat of dry air at constant volume: cp/cv).
            double gamma = 1.4;
            //Util.Log("MFI wx_enabled: " + wx_enabled+", use_point: "+use_point+", use_climo: "+use_climo);
            bool inatmos = false;

            if ((FlightGlobals.ActiveVessel.mainBody == kerbin) && (v.altitude <= 70000) && (wx_enabled))
            {
                if (use_climo)
                {
                    //Retrieve air pressure/density at vessel location
                    climate_api.wx_aero ptd = _clim_api.getPTD(vlat, vlng, vheight);
                    air_density  = ptd.density;
                    air_pressure = ptd.pressure;
                }
                else
                {
                    //Retrieve air pressure/density at vessel location
                    weather_api.wx_aero ptd = _wx_api.getPTD(vheight);
                    air_density  = ptd.density;
                    air_pressure = ptd.pressure;
                }
                //Compute speed of sound based on air pressure and air density.
                soundSpeed = Math.Sqrt(gamma * (air_pressure / air_density));
                inatmos    = true;
            }
            else
            {
                soundSpeed = v.speedOfSound;
            }
            //Get height from surface
            double hsfc = v.heightFromTerrain;
            //Determine if vessel is grounded (i.e. on the ground)
            bool isgrounded = true;

            if (hsfc >= 10)
            {
                isgrounded = false;
            }

            //If FAR is present FAR will handle aerodynamic updates or if we're not on Kerbin (i.e. in a different atmosphere)
            if (part.Modules.Contains <ModuleAeroSurface>() || (part.Modules.Contains("MissileLauncher") && part.vessel.rootPart == part) || (haveFAR) || (v.mainBody != kerbin) || (!inatmos))
            {
                fi.BaseFIUpdateAerodynamics(part);

                if (((!part.DragCubes.None) && (!part.hasLiftModule)) || (part.name.Contains("kerbalEVA")))
                {
                    double drag  = part.DragCubes.AreaDrag * PhysicsGlobals.DragCubeMultiplier * fi.pseudoReDragMult;
                    float  pscal = (float)(part.dynamicPressurekPa * drag * PhysicsGlobals.DragMultiplier);

                    //Estimate lift force from body lift
                    Vector3 lforce = part.transform.rotation * (part.bodyLiftScalar * part.DragCubes.LiftForce);
                    lforce = Vector3.ProjectOnPlane(lforce, -part.dragVectorDir);
                }
                return;
            }
            else
            {
                fi.BaseFIUpdateAerodynamics(part); //Run base aerodynamic update first (fix bug where parachutes experience multiplicative acceleration)

                // Get rigid body
                Rigidbody rb = part.rb;
                if (rb)
                {
                    if (part == v.rootPart)
                    {
                        v.mach = 0;
                    }
                    //Retrieve wind vector at vessel location
                    //Vector3d windVec = KWPWind.GetWind(FlightGlobals.currentMainBody, part, rb.position);
                    //Util.Log("MFI windVec: " + windVec + ", use_point: " + use_point + ", use_climo: " + use_climo);
                    //Retrieve world velocity without wind vector
                    Vector3 velocity_nowind = rb.velocity + Krakensbane.GetFrameVelocity();
                    //Compute mach number
                    double mach_nowind = velocity_nowind.magnitude / soundSpeed;

                    Vector3 drag_sum = Vector3.zero;
                    Vector3 lift_sum = Vector3.zero;

                    if (((!part.DragCubes.None) && (!part.hasLiftModule)) || (part.name.Contains("kerbalEVA")))
                    {
                        //Estimate Drag force
                        double pseudoreynolds   = part.atmDensity * Math.Abs(velocity_nowind.magnitude);
                        double pseudoReDragMult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate((float)pseudoreynolds);
                        double drag             = part.DragCubes.AreaDrag * PhysicsGlobals.DragCubeMultiplier * pseudoReDragMult;
                        float  pscal            = (float)(part.dynamicPressurekPa * drag * PhysicsGlobals.DragMultiplier);
                        drag_sum += -part.dragVectorDir * pscal;

                        //Estimate lift force from body lift
                        float   pbodyLiftScalar = (float)(part.dynamicPressurekPa * part.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier) * PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift").liftMachCurve.Evaluate((float)part.machNumber);
                        Vector3 lforce2         = part.transform.rotation * (pbodyLiftScalar * part.DragCubes.LiftForce);
                        lforce2   = Vector3.ProjectOnPlane(lforce2, -part.dragVectorDir);
                        lift_sum += lforce2;
                    }

                    //Util.Log("BodyLift Default: " + part.bodyLiftScalar + ", Lift Force: " + lift_force);
                    //Loop through each part module to look for lifting surfaces
                    for (int j = 0; j < part.Modules.Count; ++j)
                    {
                        var m = part.Modules[j];
                        if (m is ModuleLiftingSurface)
                        {
                            //Initialize force vectors
                            Vector3 lforce = Vector3.zero;
                            Vector3 dforce = Vector3.zero;
                            //Convert kPa to Pa
                            double liftQ = part.dynamicPressurekPa * 1000;
                            ModuleLiftingSurface wing = (ModuleLiftingSurface)m;

                            //Get wing coefficients
                            Vector3 nVel       = Vector3.zero;
                            Vector3 liftVector = Vector3.zero;
                            float   liftdot;
                            float   absdot;
                            wing.SetupCoefficients(velocity_nowind, out nVel, out liftVector, out liftdot, out absdot);

                            //Get Lift/drag force
                            lforce = wing.GetLiftVector(liftVector, liftdot, absdot, liftQ, (float)part.machNumber);
                            dforce = wing.GetDragVector(nVel, absdot, liftQ);

                            if (part.name.Contains("kerbalEVA"))
                            {
                                continue;
                            }
                            drag_sum += dforce;
                            //lift_sum += lforce;
                            if (isgrounded)
                            {
                                lift_sum += lforce;
                            }
                        }
                    }

                    //Retrieve world velocity and subtract off wind vector
                    Vector3 velocity_wind = rb.velocity + Krakensbane.GetFrameVelocity() - windVec;
                    //Compute mach number
                    double mach_wind = velocity_wind.magnitude / soundSpeed;
                    //Set mach number
                    part.machNumber = mach_wind; // *mdiv;
                    if (part == v.rootPart)
                    {
                        fi.mach = mach_wind;
                    }
                    //Get drag and lift forces with wind
                    List <Vector3> total_forces = GetDragLiftForce(fi, part, velocity_wind, windVec, part.machNumber, isgrounded);

                    //Compute difference in drag/lift with and without wind.
                    Vector3 total_drag = total_forces[0] - drag_sum;
                    Vector3 total_lift = total_forces[1] - lift_sum;

                    //Calculate force due to wind
                    Vector3 force = total_lift + total_drag;

                    if (double.IsNaN(force.sqrMagnitude) || (((float)force.magnitude).NearlyEqual(0.0f)))
                    {
                        force = Vector3d.zero;
                    }
                    else
                    {
                        //Adapted from FAR - apply numerical control factor
                        float numericalControlFactor = (float)(part.rb.mass * velocity_wind.magnitude * 0.67 / (force.magnitude * TimeWarp.fixedDeltaTime));
                        force *= Math.Min(numericalControlFactor, 1);
                        part.AddForce(force);
                    }
                    v.mach = fi.mach;
                }
            }
        }
Esempio n. 19
0
 public double BaseFIGetSunArea(PartThermalData ptd)
 {
     return(base.GetSunArea(ptd));
 }
        public void UpdateThermodynamicsPre(ModularFI.ModularFlightIntegrator fi)
        {
            wx_enabled = Util.getWindBool();
            use_climo  = Util.useCLIM();
            use_point  = Util.useWX();

            //Get reference to Kerbin (i.e. celestial body)
            kerbin = Util.getbody();

            //Get vessel position
            Vessel v       = FlightGlobals.ActiveVessel;
            double vheight = v.altitude;
            double vlat    = v.latitude;
            double vlng    = v.longitude;

            //Check to see if root part is in list. If not do not perform thermo update.
            //This avoids updating thermodynamics of parts that have been decoupled and are no longer part of the active vessel.

            bool hasPart = false;

            for (int i = 0; i < fi.PartThermalDataCount; i++)
            {
                PartThermalData pttd = fi.partThermalDataList[i];
                Part            part = pttd.part;
                if (part == v.rootPart)
                {
                    hasPart = true;
                }
            }

            if (!hasPart)
            {
                return;
            }

            //Start out with Stock Thermodynamics before performing adjustments due to wind/weather.
            fi.BaseFIUpdateThermodynamics();

            // Initialize External Temp and part drag/lift sum for GUI. //
            // This ensures GUI updates are smooth and don't bounce back and forth between stock aero and KWP aero updates //
            v.externalTemperature = fi.externalTemperature;

            if ((fi.CurrentMainBody != kerbin) || (v.altitude >= 70000))
            {
                return;
            }
            //Check if in atmosphere
            if (wx_enabled)
            {
                //Define gamma (ratio of cp/cv)
                double gamma = 1.4;

                if (use_climo)
                {
                    climate_api.wx_aero ptd = _clim_api.getPTD(vlat, vlng, vheight); //Retrieve pressure,temperature,and density from climate API
                    //Adjust atmospheric constants
                    CalculateConstantsAtmosphere_CLIMO(fi, ptd, v);
                }
                else
                {
                    weather_api.wx_aero ptd = _wx_api.getPTD(vheight); //Retrieve pressure,temperature,and density from climate API
                    //Adjust atmospheric constants
                    CalculateConstantsAtmosphere_WX(fi, ptd, v);
                }
                // change density lerp
                double shockDensity = GetShockDensity(fi.density, fi.mach, gamma);
                fi.DensityThermalLerp = CalculateDensityThermalLerp(shockDensity);
                double lerpVal = fi.dynamicPressurekPa;
                if (lerpVal < 1d)
                {
                    fi.convectiveCoefficient *= UtilMath.LerpUnclamped(0.1d, 1d, lerpVal);
                }

                // reset background temps
                fi.backgroundRadiationTemp        = CalculateBackgroundRadiationTemperature(fi.atmosphericTemperature, fi.DensityThermalLerp);
                fi.backgroundRadiationTempExposed = CalculateBackgroundRadiationTemperature(fi.externalTemperature, fi.DensityThermalLerp);
            }
            else if (!wx_enabled)
            {
                fi.BaseFIUpdateThermodynamics();
            }
        }
Esempio n. 21
0
 public void BaseFIUpdateRadiation(PartThermalData ptd)
 {
     base.UpdateRadiation(ptd);
 }