// return the surface radiation for the body specified (used by body info panel) public static double ComputeSurface(CelestialBody b, double gamma_transparency) { // store stuff Space gsm; Vector3 p; float D; // transform to local space once Vector3d position = ScaledSpace.LocalToScaledSpace(b.position); // accumulate radiation double radiation = 0.0; CelestialBody body = b; while (body != null) { RadiationBody rb = Info(body); RadiationModel mf = rb.model; if (mf.Has_Field()) { // generate radii-normalized GSM space gsm = GSM_Space(rb.body, FlightGlobals.Bodies[rb.reference]); // move the poing in GSM space p = gsm.Transform_IN(position); // accumulate radiation and determine pause/belt flags if (mf.has_inner) { D = mf.Inner_Func(p); radiation += Lib.Clamp(D / -0.0666f, 0.0f, 1.0f) * rb.radiation_inner; } if (mf.has_outer) { D = mf.Outer_Func(p); radiation += Lib.Clamp(D / -0.0333f, 0.0f, 1.0f) * rb.radiation_outer; } if (mf.has_pause) { D = mf.Pause_Func(p); radiation += Lib.Clamp(D / -0.1332f, 0.0f, 1.0f) * rb.radiation_pause; } } // avoid loops in the chain body = (body.referenceBody != null && body.referenceBody.referenceBody == body) ? null : body.referenceBody; } // add extern radiation radiation += Settings.ExternRadiation; // clamp radiation to positive range // note: we avoid radiation going to zero by using a small positive value radiation = Math.Max(radiation, Nominal); // return radiation, scaled by gamma transparency if inside atmosphere return(radiation * gamma_transparency); }
// return the total environent radiation at position specified public static double Compute(Vessel v, Vector3d position, double gamma_transparency, double sunlight, out bool blackout, out bool magnetosphere, out bool inner_belt, out bool outer_belt, out bool interstellar) { // prepare out parameters blackout = false; magnetosphere = false; inner_belt = false; outer_belt = false; interstellar = false; // no-op when Radiation is disabled if (!Features.Radiation) { return(0.0); } // store stuff Space gsm; Vector3 p; float D; // transform to local space once position = ScaledSpace.LocalToScaledSpace(position); // accumulate radiation double radiation = 0.0; CelestialBody body = v.mainBody; while (body != null) { RadiationBody rb = Info(body); RadiationModel mf = rb.model; if (mf.Has_Field()) { // generate radii-normalized GSM space gsm = GSM_Space(rb.body, FlightGlobals.Bodies[rb.reference]); // move the poing in GSM space p = gsm.Transform_IN(position); // accumulate radiation and determine pause/belt flags if (mf.has_inner) { D = mf.Inner_Func(p); radiation += Lib.Clamp(D / -0.0666f, 0.0f, 1.0f) * rb.radiation_inner; inner_belt |= D < 0.0f; } if (mf.has_outer) { D = mf.Outer_Func(p); radiation += Lib.Clamp(D / -0.0333f, 0.0f, 1.0f) * rb.radiation_outer; outer_belt |= D < 0.0f; } if (mf.has_pause) { D = mf.Pause_Func(p); radiation += Lib.Clamp(D / -0.1332f, 0.0f, 1.0f) * rb.radiation_pause; magnetosphere |= D < 0.0f && rb.body.flightGlobalsIndex != 0; //< ignore heliopause interstellar |= D > 0.0f && rb.body.flightGlobalsIndex == 0; //< outside heliopause } } // avoid loops in the chain body = (body.referenceBody != null && body.referenceBody.referenceBody == body) ? null : body.referenceBody; } // add extern radiation radiation += Settings.ExternRadiation; // add emitter radiation radiation += Emitter.Total(v); // if there is a storm in progress if (Storm.InProgress(v)) { // inside a magnetopause (except heliosphere), blackout the signal // outside, add storm radiations modulated by sun visibility if (magnetosphere) { blackout = true; } else { radiation += Settings.StormRadiation * sunlight; } } // clamp radiation to positive range // note: we avoid radiation going to zero by using a small positive value radiation = Math.Max(radiation, Nominal); // return radiation, scaled by gamma transparency if inside atmosphere return(radiation * gamma_transparency); }
// do the particle-fitting in another thread public static void Preprocess() { // deduce number of particles int inner_count = 150000; int outer_count = 600000; int pause_count = 250000; if (Settings.LowQualityRendering) { inner_count /= 5; outer_count /= 5; pause_count /= 5; } // start time UInt64 time = Lib.Clocks(); // create all magnetic fields and do particle-fitting List <string> done = new List <string>(); foreach (var pair in models) { // get radiation data RadiationModel mf = pair.Value; // skip if model is already done if (done.Contains(mf.name)) { continue; } // add to the skip list done.Add(mf.name); // if it has a field if (mf.Has_Field()) { // some feedback in the log // note: can't use BuildString here, as it is not thread-safe Lib.Verbose("particle-fitting '" + mf.name + "'..."); } // particle-fitting for the inner radiation belt if (mf.has_inner) { mf.inner_pmesh = new ParticleMesh(mf.Inner_Func, mf.Inner_Domain(), mf.Inner_Offset(), inner_count, mf.inner_quality); } // particle-fitting for the outer radiation belt if (mf.has_outer) { mf.outer_pmesh = new ParticleMesh(mf.Outer_Func, mf.Outer_Domain(), mf.Outer_Offset(), outer_count, mf.outer_quality); } // particle-fitting for the magnetopause if (mf.has_pause) { mf.pause_pmesh = new ParticleMesh(mf.Pause_Func, mf.Pause_Domain(), mf.Pause_Offset(), pause_count, mf.pause_quality); } } // measure time required // note: can't use BuildString here, as it is not thread-safe Lib.Verbose("particle-fitting completed in " + Lib.Seconds(Lib.Clocks() - time).ToString("F3") + " seconds"); }