Beispiel #1
0
  static double CurvedPanelOutput(Vessel vessel, ProtoPartSnapshot part, Part prefab, PartModule m, Vector3d sun_dir, double sun_dist, double atmo_factor)
  {
    // if, for whatever reason, sun_dist is zero (or negative), we do not return any output
    if (sun_dist <= double.Epsilon) return 0.0;

    // shortcuts
    Quaternion rot = part.rotation;

    // get values from part
    string transform_name = Lib.ReflectionValue<string>(m, "PanelTransformName");
    float tot_rate = Lib.ReflectionValue<float>(m, "TotalEnergyRate");

    // get components
    Transform[] components = prefab.FindModelTransforms(transform_name);
    if (components.Length == 0) return 0.0;

    // calculate solar flux
    double solar_flux = Sim.SolarFlux(sun_dist);

    // reduce solar flux inside atmosphere
    solar_flux *= atmo_factor;

    // for each one of the components the curved panel is composed of
    double output = 0.0;
    foreach(Transform t in components)
    {
      double cosine_factor = Math.Max(Vector3d.Dot(sun_dir, (vessel.transform.rotation * rot * t.forward.normalized).normalized), 0.0);
      output += (double)tot_rate / (double)components.Length * cosine_factor * solar_flux / Sim.SolarFluxAtHome();
    }
    return output;
  }
Beispiel #2
0
  static double CurvedPanelOutput(Vessel vessel, ProtoPartSnapshot part, Part prefab, Vector3d sun_dir, double sun_dist, double atmo_factor)
  {
    // if, for whatever reason, sun_dist is zero (or negative), we do not return any output
    if (sun_dist <= double.Epsilon) return 0.0;

    // shortcuts
    Quaternion rot = part.rotation;

    // get values from part
    string transform_name = part.partData.GetValue("PanelTransformName");
    float k = Convert.ToSingle(part.partData.GetValue("chargePerTransform"));

    // get components
    Transform[] components = prefab.FindModelTransforms(transform_name);
    if (components.Length == 0) return 0.0;

    // calculate solar flux
    double solar_flux = Sim.SolarFlux(sun_dist);

    // reduce solar flux inside atmosphere
    solar_flux *= atmo_factor;

    // normalize against solar flux at home
    solar_flux /= Sim.SolarFluxAtHome();
    solar_flux *= k;

    // for each one of the components the curved panel is composed of
    double output = 0.0;
    foreach(Transform t in prefab.FindModelTransforms(transform_name))
    {
      double cosine_factor = Math.Max(Vector3d.Dot(sun_dir, (vessel.transform.rotation * rot * t.forward).normalized), 0.0);
      output += cosine_factor * solar_flux;
    }
    return output;
  }
Beispiel #3
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 #4
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 #5
0
  // return solar panel EC output
  // note: we ignore temperature curve, and make sure it is not relavant in the MM patch
  static double PanelOutput(Vessel vessel, ProtoPartSnapshot part, ModuleDeployableSolarPanel panel, Vector3d sun_dir, double sun_dist, double atmo_factor)
  {
    // if, for whatever reason, sun_dist is zero (or negative), we do not return any output
    if (sun_dist <= double.Epsilon) return 0.0;

    // shortcuts
    Quaternion rot = part.rotation;
    Vector3d normal = panel.part.FindModelComponent<Transform>(panel.raycastTransformName).forward;

    // calculate cosine factor
    // note: for gameplay reasons, we ignore tracking panel pivots
    double cosine_factor = panel.sunTracking ? 1.0 : Math.Max(Vector3d.Dot(sun_dir, (vessel.transform.rotation * rot * normal).normalized), 0.0);

    // calculate solar flux
    double solar_flux = Sim.SolarFlux(sun_dist);

    // reduce solar flux inside atmosphere
    solar_flux *= atmo_factor;

    // finally, calculate output
    return panel.chargeRate * cosine_factor * (panel.useCurve ? panel.powerCurve.Evaluate((float)sun_dist) : solar_flux / Sim.SolarFluxAtHome());
  }
Beispiel #6
0
 // return normalized natural lighting at specified distance from the sun (1 in the home world)
 public static double NaturalLighting(double sun_dist)
 {
   // return natural lighting
   // note: should be 1 at kerbin
   return Sim.SolarFlux(sun_dist) / Sim.SolarFluxAtHome();
 }
Beispiel #7
0
  // draw the window
  void render(int _)
  {
    // shortcut
    CelestialBody sun = FlightGlobals.Bodies[0];

    // get selected body
    CelestialBody body = Lib.SelectedBody();

    // calculate simulation values
    double atmo_factor = Sim.AtmosphereFactor(body, 0.7071);
    double gamma_factor = Sim.GammaTransparency(body, 0.0);
    double sun_dist = Sim.Apoapsis(Lib.PlanetarySystem(body)) - sun.Radius - body.Radius;
    Vector3d sun_dir = (sun.position - body.position).normalized;
    double solar_flux = Sim.SolarFlux(sun_dist) * atmo_factor;
    double albedo_flux = Sim.AlbedoFlux(body, body.position + sun_dir * body.Radius);
    double body_flux = Sim.BodyFlux(body, 0.0);
    double total_flux = solar_flux + albedo_flux + body_flux + Sim.BackgroundFlux();
    double temperature = body.atmosphere ? body.GetTemperature(0.0) : Sim.BlackBodyTemperature(total_flux);

    // calculate night-side temperature
    double total_flux_min = Sim.AlbedoFlux(body, body.position - sun_dir * body.Radius) + body_flux + Sim.BackgroundFlux();
    double temperature_min = Sim.BlackBodyTemperature(total_flux_min);

    // calculate radiation at body surface
    double radiation = Radiation.ComputeSurface(body, gamma_factor);

    // draw pseudo-title
    GUILayout.BeginHorizontal();
    GUILayout.Label(body.bodyName.ToUpper(), top_style);
    GUILayout.EndHorizontal();

    // surface panel
    string temperature_str = body.atmosphere
      ? Lib.HumanReadableTemp(temperature)
      : Lib.BuildString(Lib.HumanReadableTemp(temperature_min), " / ", Lib.HumanReadableTemp(temperature));
    render_title("SURFACE");
    render_content("temperature", temperature_str);
    render_content("radiation", Lib.HumanReadableRadiationRate(radiation));
    render_content("solar flux", Lib.HumanReadableFlux(solar_flux));
    render_space();

    // atmosphere panel
    if (body.atmosphere)
    {
      render_title("ATMOSPHERE");
      render_content("breathable", body.atmosphereContainsOxygen ? "yes" : "no");
      render_content("light absorption", Lib.HumanReadablePerc(1.0 - Sim.AtmosphereFactor(body, 0.7071)));
      render_content("gamma absorption", Lib.HumanReadablePerc(1.0 - Sim.GammaTransparency(body, 0.0)));
      render_space();
    }

    // rendering panel
    render_title("RENDERING");
    render_content("inner belt", ref Radiation.show_inner);
    render_content("outer belt", ref Radiation.show_outer);
    render_content("magnetopause", ref Radiation.show_pause);
    render_space();


    // draw footer
    GUILayout.BeginHorizontal();
    GUILayout.Label("(ALT+N to open and close)", bot_style);
    if (Lib.IsClicked()) Close();
    GUILayout.EndHorizontal();

    // enable dragging
    GUI.DragWindow(drag_rect);
  }
Beispiel #8
0
  public static void body_info(this Panel p)
  {
    // only show in mapview
    if (!MapView.MapIsEnabled) return;

    // only show if there is a selected body and that body is not the sun
    CelestialBody body = Lib.SelectedBody();
    if (body == null || (body.flightGlobalsIndex == 0 && !Features.Radiation)) return;

    // shortcut
    CelestialBody sun = FlightGlobals.Bodies[0];

    // for all bodies except the sun
    if (body != sun)
    {
      // calculate simulation values
      double atmo_factor = Sim.AtmosphereFactor(body, 0.7071);
      double gamma_factor = Sim.GammaTransparency(body, 0.0);
      double sun_dist = Sim.Apoapsis(Lib.PlanetarySystem(body)) - sun.Radius - body.Radius;
      Vector3d sun_dir = (sun.position - body.position).normalized;
      double solar_flux = Sim.SolarFlux(sun_dist) * atmo_factor;
      double albedo_flux = Sim.AlbedoFlux(body, body.position + sun_dir * body.Radius);
      double body_flux = Sim.BodyFlux(body, 0.0);
      double total_flux = solar_flux + albedo_flux + body_flux + Sim.BackgroundFlux();
      double temperature = body.atmosphere ? body.GetTemperature(0.0) : Sim.BlackBodyTemperature(total_flux);

      // calculate night-side temperature
      double total_flux_min = Sim.AlbedoFlux(body, body.position - sun_dir * body.Radius) + body_flux + Sim.BackgroundFlux();
      double temperature_min = Sim.BlackBodyTemperature(total_flux_min);

      // calculate radiation at body surface
      double radiation = Radiation.ComputeSurface(body, gamma_factor);

      // surface panel
      string temperature_str = body.atmosphere
        ? Lib.HumanReadableTemp(temperature)
        : Lib.BuildString(Lib.HumanReadableTemp(temperature_min), " / ", Lib.HumanReadableTemp(temperature));
      p.section("SURFACE");
      p.content("temperature", temperature_str);
      p.content("solar flux", Lib.HumanReadableFlux(solar_flux));
      if (Features.Radiation) p.content("radiation", Lib.HumanReadableRadiation(radiation));

      // atmosphere panel
      if (body.atmosphere)
      {
        p.section("ATMOSPHERE");
        p.content("breathable", Sim.Breathable(body) ? "yes" : "no");
        p.content("light absorption", Lib.HumanReadablePerc(1.0 - Sim.AtmosphereFactor(body, 0.7071)));
        if (Features.Radiation) p.content("gamma absorption", Lib.HumanReadablePerc(1.0 - Sim.GammaTransparency(body, 0.0)));
      }
    }

    // rendering panel
    if (Features.Radiation)
    {
      p.section("RENDERING");
      p.content("inner belt",   Radiation.show_inner ? "<color=green>show</color>" : "<color=red>hide</color>", string.Empty, () => p.toggle(ref Radiation.show_inner));
      p.content("outer belt",   Radiation.show_outer ? "<color=green>show</color>" : "<color=red>hide</color>", string.Empty, () => p.toggle(ref Radiation.show_outer));
      p.content("magnetopause", Radiation.show_pause ? "<color=green>show</color>" : "<color=red>hide</color>", string.Empty, () => p.toggle(ref Radiation.show_pause));
    }

    // explain the user how to toggle the BodyInfo window
    p.content(string.Empty);
    p.content("<i>Press <b>B</b> to open this window again</i>");

    // set metadata
    p.title(Lib.BuildString(Lib.Ellipsis(body.bodyName, 24), " <color=#cccccc>BODY INFO</color>"));
  }