Beispiel #1
0
  public static environment_data analyze_environment(CelestialBody body, double altitude_mult)
  {
    // shortcuts
    CelestialBody sun = Sim.Sun();

    // calculate data
    environment_data env = new environment_data();
    env.body = body;
    env.altitude = body.Radius * altitude_mult;
    env.landed = env.altitude <= double.Epsilon;
    env.breathable = env.landed && body.atmosphereContainsOxygen;
    env.sun_dist = Sim.Apoapsis(Lib.PlanetarySystem(body)) - sun.Radius - body.Radius;
    Vector3d sun_dir = (sun.position - body.position).normalized;
    env.sun_flux = Sim.SolarFlux(env.sun_dist);
    env.body_flux = Sim.BodyFlux(body, body.position + sun_dir * (body.Radius + env.altitude));
    env.body_back_flux = Sim.BodyFlux(body, body.position - sun_dir * (body.Radius + env.altitude));
    env.background_temp = Sim.BackgroundTemperature();
    env.sun_temp = Sim.BlackBody(env.sun_flux);
    env.body_temp = Sim.BlackBody(env.body_flux);
    env.body_back_temp = Sim.BlackBody(env.body_back_flux);
    env.light_temp = env.background_temp + env.sun_temp + env.body_temp;
    env.shadow_temp = env.background_temp + env.body_back_temp;
    env.atmo_temp = body.GetTemperature(0.0);
    env.orbital_period = Sim.OrbitalPeriod(body, env.altitude);
    env.shadow_period = Sim.ShadowPeriod(body, env.altitude);
    env.shadow_time = env.shadow_period / env.orbital_period;
    env.temp_diff = env.landed && body.atmosphere
      ? Math.Abs(Settings.SurvivalTemperature - env.atmo_temp)
      : Lib.Mix(Math.Abs(Settings.SurvivalTemperature - env.light_temp), Math.Abs(Settings.SurvivalTemperature - env.shadow_temp), env.shadow_time);
    env.atmo_factor = env.landed ? Sim.AtmosphereFactor(body, 0.7071) : 1.0;

    // return data
    return env;
  }
Beispiel #2
0
        // at the two highest timewarp speed, the number of sun visibility samples drop to the point that
        // the quantization error first became noticeable, and then exceed 100%
        // to solve this, we switch to an analytical estimation of the portion of orbit that was in sunlight
        // - we check against timewarp rate, instead of index, to avoid issues during timewarp blending
        public void highspeedWarp(Vessel v)
        {
            // don't re-calculate this on every tick. So, if sunlight is not 1.0 or 0.0, do nothing here
            if (sunlight > 0.0001 && sunlight < 0.9999)
            {
                return;
            }

            sunlight   = 1.0 - Sim.ShadowPeriod(v) / Sim.OrbitalPeriod(v);
            solar_flux = Sim.SolarFlux(Sim.SunDistance(Lib.VesselPosition(v))) * atmo_factor;
        }
Beispiel #3
0
            /// <summary>
            /// Update the 'sunsInfo' list and the 'mainSun', 'solarFluxTotal' variables.
            /// Uses discrete or analytic (for high timewarp speeds) evaluation methods based on the isAnalytic bool.
            /// Require the 'visibleBodies' variable to be set.
            /// </summary>
            // at the two highest timewarp speed, the number of sun visibility samples drop to the point that
            // the quantization error first became noticeable, and then exceed 100%, to solve this :
            // - we switch to an analytical estimation of the sunlight/shadow period
            // - atmo_factor become an average atmospheric absorption factor over the daylight period (not the whole day)
            public static void UpdateSunsInfo(VesselData vd, Vector3d vesselPosition)
            {
                Vessel v             = vd.Vessel;
                double lastSolarFlux = 0.0;

                vd.sunsInfo          = new List <SunInfo>(Sim.suns.Count);
                vd.solarFluxTotal    = 0.0;
                vd.rawSolarFluxTotal = 0.0;

                foreach (Sim.SunData sunData in Sim.suns)
                {
                    SunInfo sunInfo = new SunInfo(sunData);

                    if (vd.isAnalytic)
                    {
                        // get sun direction and distance
                        Lib.DirectionAndDistance(vesselPosition, sunInfo.sunData.body, out sunInfo.direction, out sunInfo.distance);
                        // analytical estimation of the portion of orbit that was in sunlight, current limitations :
                        // - the result is dependant on the vessel altitude at the time of evaluation,
                        //   consequently it gives inconsistent behavior with highly eccentric orbits
                        // - this totally ignore the orbit inclinaison, polar orbits will be treated as equatorial orbits
                        sunInfo.sunlightFactor = 1.0 - Sim.ShadowPeriod(v) / Sim.OrbitalPeriod(v);
                        // get atmospheric absorbtion
                        // for atmospheric bodies whose rotation period is less than 120 hours,
                        // determine analytic atmospheric absorption over a single body revolution instead
                        // of using a discrete value that would be unreliable at large timesteps :
                        if (vd.inAtmosphere)
                        {
                            sunInfo.atmoFactor = Sim.AtmosphereFactorAnalytic(v.mainBody, vesselPosition, sunInfo.direction);
                        }
                        else
                        {
                            sunInfo.atmoFactor = 1.0;
                        }
                    }
                    else
                    {
                        // determine if in sunlight, calculate sun direction and distance
                        sunInfo.sunlightFactor = Sim.IsBodyVisible(v, vesselPosition, sunData.body, vd.visibleBodies, out sunInfo.direction, out sunInfo.distance) ? 1.0 : 0.0;
                        // get atmospheric absorbtion
                        sunInfo.atmoFactor = Sim.AtmosphereFactor(v.mainBody, vesselPosition, sunInfo.direction);
                    }

                    // get resulting solar flux in W/m²
                    sunInfo.rawSolarFlux = sunInfo.sunData.SolarFlux(sunInfo.distance);
                    sunInfo.solarFlux    = sunInfo.rawSolarFlux * sunInfo.sunlightFactor * sunInfo.atmoFactor;
                    // increment total flux from all stars
                    vd.rawSolarFluxTotal += sunInfo.rawSolarFlux;
                    vd.solarFluxTotal    += sunInfo.solarFlux;
                    // add the star to the list
                    vd.sunsInfo.Add(sunInfo);
                    // the most powerful star will be our "default" sun. Uses raw flux before atmo / sunlight factor
                    if (sunInfo.rawSolarFlux > lastSolarFlux)
                    {
                        lastSolarFlux = sunInfo.rawSolarFlux;
                        vd.mainSun    = sunInfo;
                    }
                }

                vd.sunlightFactor = 0.0;
                foreach (SunInfo sunInfo in vd.sunsInfo)
                {
                    sunInfo.fluxProportion = sunInfo.rawSolarFlux / vd.rawSolarFluxTotal;
                    vd.sunlightFactor     += sunInfo.SunlightFactor * sunInfo.fluxProportion;
                }
                // avoid rounding errors
                if (vd.sunlightFactor > 0.99)
                {
                    vd.sunlightFactor = 1.0;
                }
            }
Beispiel #4
0
  public vessel_info(Vessel v, uint vessel_id, UInt64 inc)
  {
    // NOTE: anything used here can't in turn use cache, unless you know what you are doing

    // NOTE: you can't cache vessel position
    // at any point in time all vessel/body positions are relative to a different frame of reference
    // so comparing the current position of a vessel, with the cached one of another make no sense

    // associate with an unique incremental id
    this.inc = inc;

    // determine if this is a valid vessel
    is_vessel = Lib.IsVessel(v);
    if (!is_vessel) return;

    // determine if this is a rescue mission vessel
    is_rescue = Misc.IsRescueMission(v);
    if (is_rescue) return;

    // dead EVA are not valid vessels
    if (EVA.IsDead(v)) return;

    // shortcut for common tests
    is_valid = true;

    // generate id once
    id = vessel_id;

    // calculate crew info for the vessel
    crew_count = Lib.CrewCount(v);
    crew_capacity = Lib.CrewCapacity(v);

    // get vessel position
    Vector3d position = Lib.VesselPosition(v);

    // this should never happen again
    if (Vector3d.Distance(position, v.mainBody.position) < 1.0)
    {
      throw new Exception("Shit hit the fan for vessel " + v.vesselName);
    }

    // determine if in sunlight, calculate sun direction and distance
    sunlight = Sim.RaytraceBody(v, position, FlightGlobals.Bodies[0], out sun_dir, out sun_dist) ? 1.0 : 0.0;

    // at the two highest timewarp speed, the number of sun visibility samples drop to the point that
    // the quantization error first became noticeable, and then exceed 100%
    // to solve this, we switch to an analytical estimation of the portion of orbit that was in sunlight
    // - we check against timewarp rate, instead of index, to avoid issues during timewarp blending
    if (v.mainBody.flightGlobalsIndex != 0 && TimeWarp.CurrentRate > 1000.0f)
    {
      sunlight = 1.0 - Sim.ShadowPeriod(v) / Sim.OrbitalPeriod(v);
    }

    // environment stuff
    atmo_factor = Sim.AtmosphereFactor(v.mainBody, position, sun_dir);
    gamma_transparency = Sim.GammaTransparency(v.mainBody, v.altitude);
    underwater = Sim.Underwater(v);
    breathable = Sim.Breathable(v, underwater);
    landed = Lib.Landed(v);

    // temperature at vessel position
    temperature = Sim.Temperature(v, position, sunlight, atmo_factor, out solar_flux, out albedo_flux, out body_flux, out total_flux);
    temp_diff = Sim.TempDiff(temperature, v.mainBody, landed);

    // radiation
    radiation = Radiation.Compute(v, position, gamma_transparency, sunlight, out blackout, out magnetosphere, out inner_belt, out outer_belt, out interstellar);

    // extended atmosphere
    thermosphere = Sim.InsideThermosphere(v);
    exosphere = Sim.InsideExosphere(v);

    // malfunction stuff
    malfunction = Reliability.HasMalfunction(v);
    critical = Reliability.HasCriticalFailure(v);

    // signal info
    antenna = new AntennaInfo(v);
    avoid_inf_recursion.Add(v.id);
    connection = Signal.connection(v, position, antenna, blackout, avoid_inf_recursion);
    transmitting = Science.transmitting(v, connection.linked);
    relaying = Signal.relaying(v, avoid_inf_recursion);
    avoid_inf_recursion.Remove(v.id);

    // habitat data
    volume = Habitat.tot_volume(v);
    surface = Habitat.tot_surface(v);
    pressure = Habitat.pressure(v);
    poisoning = Habitat.poisoning(v);
    shielding = Habitat.shielding(v);
    living_space = Habitat.living_space(v);
    comforts = new Comforts(v, landed, crew_count > 1, connection.linked);

    // data about greenhouses
    greenhouses = Greenhouse.Greenhouses(v);

    // other stuff
    gravioli = Sim.Graviolis(v);
  }
Beispiel #5
0
  public vessel_info(Vessel v, uint vessel_id, UInt64 inc)
  {
    // NOTE: anything used here can't in turn use cache, unless you know what you are doing

    // associate with an unique incremental id
    this.inc = inc;

    // determine if this is a valid vessel
    is_vessel = Lib.IsVessel(v);
    if (!is_vessel) return;

    // determine if this is a resque mission vessel
    is_resque = Lib.IsResqueMission(v);
    if (is_resque) return;

    // dead EVA are not valid vessels
    if (v.isEVA && EVA.KerbalData(v).eva_dead) return;

    // shortcut for common tests
    is_valid = true;

    // generate id once
    id = vessel_id;

    // calculate crew info for the vessel
    crew_count = Lib.CrewCount(v);
    crew_capacity = Lib.CrewCapacity(v);

    // get vessel position once
    position = Lib.VesselPosition(v);

    // determine if in sunlight, calculate sun direction and distance
    sunlight = Sim.RaytraceBody(v, position, FlightGlobals.Bodies[0], out sun_dir, out sun_dist) ? 1.0 : 0.0;

    // if the orbit length vs simulation step is lower than an acceptable threshold, use discrete sun visibility
    if (v.mainBody.flightGlobalsIndex != 0)
    {
      double orbit_period = Sim.OrbitalPeriod(v);
      if (orbit_period / Kerbalism.elapsed_s < 16.0) sunlight = 1.0 - Sim.ShadowPeriod(v) / orbit_period;
    }

    // calculate environment stuff
    atmo_factor = Sim.AtmosphereFactor(v.mainBody, position, sun_dir);
    gamma_transparency = Sim.GammaTransparency(v.mainBody, v.altitude);
    breathable = Sim.Breathable(v);
    landed = Lib.Landed(v);

    // calculate temperature at vessel position
    temperature = Sim.Temperature(v, position, sunlight, atmo_factor, out solar_flux, out albedo_flux, out body_flux, out total_flux);

    // calculate radiation
    radiation = Radiation.Compute(v, position, gamma_transparency, sunlight, out blackout, out inside_pause, out inside_belt);

    // calculate malfunction stuff
    max_malfunction = Reliability.MaxMalfunction(v);
    avg_quality = Reliability.AverageQuality(v);

    // calculate signal info
    antenna = new antenna_data(v);
    avoid_inf_recursion.Add(v.id);
    link = Signal.Link(v, position, antenna, blackout, avoid_inf_recursion);
    avoid_inf_recursion.Remove(v.id);

    // partial data about modules, used by vessel info/monitor
    scrubbers = Scrubber.PartialData(v);
    recyclers = Recycler.PartialData(v);
    greenhouses = Greenhouse.PartialData(v);

    // woot relativity
    time_dilation = Sim.TimeDilation(v);
  }
Beispiel #6
0
            /// <summary>
            /// Update the 'sunsInfo' list and the 'mainSun', 'solarFluxTotal' variables.
            /// Uses discrete or analytic (for high timewarp speeds) evaluation methods based on the isAnalytic bool.
            /// Require the 'visibleBodies' variable to be set.
            /// </summary>
            // at the two highest timewarp speed, the number of sun visibility samples drop to the point that
            // the quantization error first became noticeable, and then exceed 100%, to solve this:
            // - we switch to an analytical estimation of the sunlight/shadow period
            // - atmo_factor become an average atmospheric absorption factor over the daylight period (not the whole day)
            public static void UpdateSunsInfo(VesselData vd, Vector3d vesselPosition, double elapsedSeconds)
            {
                Vessel v             = vd.Vessel;
                double lastSolarFlux = 0.0;

                vd.sunsInfo          = new List <SunInfo>(Sim.suns.Count);
                vd.solarFluxTotal    = 0.0;
                vd.rawSolarFluxTotal = 0.0;

                foreach (Sim.SunData sunData in Sim.suns)
                {
                    SunInfo sunInfo = new SunInfo(sunData);

                    if (vd.isAnalytic)
                    {
                        // get sun direction and distance
                        Lib.DirectionAndDistance(vesselPosition, sunInfo.sunData.body, out sunInfo.direction, out sunInfo.distance);
                        // analytical estimation of the portion of orbit that was in sunlight.
                        // it has some limitations, see the comments on Sim.ShadowPeriod

                        if (Settings.UseSamplingSunFactor)
                        {
                            // sampling estimation of the portion of orbit that is in sunlight
                            // until we will calculate again
                            sunInfo.sunlightFactor = Sim.SampleSunFactor(v, elapsedSeconds);
                        }

                        else
                        {
                            // analytical estimation of the portion of orbit that was in sunlight.
                            // it has some limitations, see the comments on Sim.ShadowPeriod
                            sunInfo.sunlightFactor = 1.0 - Sim.ShadowPeriod(v) / Sim.OrbitalPeriod(v);
                        }


                        // get atmospheric absorbtion
                        // for atmospheric bodies whose rotation period is less than 120 hours,
                        // determine analytic atmospheric absorption over a single body revolution instead
                        // of using a discrete value that would be unreliable at large timesteps :
                        if (vd.inAtmosphere)
                        {
                            sunInfo.atmoFactor = Sim.AtmosphereFactorAnalytic(v.mainBody, vesselPosition, sunInfo.direction);
                        }
                        else
                        {
                            sunInfo.atmoFactor = 1.0;
                        }
                    }
                    else
                    {
                        // determine if in sunlight, calculate sun direction and distance
                        sunInfo.sunlightFactor = Sim.IsBodyVisible(v, vesselPosition, sunData.body, vd.visibleBodies, out sunInfo.direction, out sunInfo.distance) ? 1.0 : 0.0;
                        // get atmospheric absorbtion
                        sunInfo.atmoFactor = Sim.AtmosphereFactor(v.mainBody, vesselPosition, sunInfo.direction);
                    }

                    // get resulting solar flux in W/m²
                    sunInfo.rawSolarFlux = sunInfo.sunData.SolarFlux(sunInfo.distance);
                    sunInfo.solarFlux    = sunInfo.rawSolarFlux * sunInfo.sunlightFactor * sunInfo.atmoFactor;
                    // increment total flux from all stars
                    vd.rawSolarFluxTotal += sunInfo.rawSolarFlux;
                    vd.solarFluxTotal    += sunInfo.solarFlux;
                    // add the star to the list
                    vd.sunsInfo.Add(sunInfo);
                    // the most powerful star will be our "default" sun. Uses raw flux before atmo / sunlight factor
                    if (sunInfo.rawSolarFlux > lastSolarFlux)
                    {
                        lastSolarFlux = sunInfo.rawSolarFlux;
                        vd.mainSun    = sunInfo;
                    }
                }

                vd.sunlightFactor = 0.0;
                foreach (SunInfo sunInfo in vd.sunsInfo)
                {
                    sunInfo.fluxProportion = sunInfo.rawSolarFlux / vd.rawSolarFluxTotal;
                    vd.sunlightFactor     += sunInfo.SunlightFactor * sunInfo.fluxProportion;
                }
                // avoid rounding errors
                if (vd.sunlightFactor > 0.99)
                {
                    vd.sunlightFactor = 1.0;
                }
            }