// render the fields of the interesting body
        public static void Render()
        {
            // get interesting body
            CelestialBody body = Interesting_body();

            // maintain visualization modes
            if (body == null)
            {
                show_inner = false;
                show_outer = false;
                show_pause = false;
            }
            else
            {
                if (Input.GetKeyDown(KeyCode.Keypad0))
                {
                    if (show_inner || show_outer || show_pause)
                    {
                        show_inner = false;
                        show_outer = false;
                        show_pause = false;
                    }
                    else
                    {
                        show_inner = true;
                        show_outer = true;
                        show_pause = true;
                    }
                }
                if (Input.GetKeyDown(KeyCode.Keypad1))
                {
                    show_inner = true;
                    show_outer = false;
                    show_pause = false;
                }
                if (Input.GetKeyDown(KeyCode.Keypad2))
                {
                    show_inner = false;
                    show_outer = true;
                    show_pause = false;
                }
                if (Input.GetKeyDown(KeyCode.Keypad3))
                {
                    show_inner = false;
                    show_outer = false;
                    show_pause = true;
                }
            }


            // if there is an active body, and at least one of the modes is active
            if (body != null && (show_inner || show_outer || show_pause))
            {
                // if we don't know if preprocessing is completed
                if (preprocess_thread != null)
                {
                    // if the preprocess thread has not done yet
                    if (preprocess_thread.IsAlive)
                    {
                        // disable all modes
                        show_inner = false;
                        show_outer = false;
                        show_pause = false;

                        // tell the user and do nothing
                        Message.Post("<color=#00ffff><b>Fitting particles to signed distance fields</b></color>", "Come back in a minute");
                        return;
                    }

                    // wait for particle-fitting thread to cleanup
                    preprocess_thread.Join();

                    // preprocessing is complete
                    preprocess_thread = null;
                }


                // load and configure shader
                if (mat == null)
                {
                    if (!Settings.LowQualityRendering)
                    {
                        // load shader
                        mat = Lib.GetShader("MiniParticle");

                        // configure shader
                        mat.SetColor("POINT_COLOR", new Color(0.33f, 0.33f, 0.33f, 0.1f));
                    }
                    else
                    {
                        // load shader
                        mat = Lib.GetShader("PointParticle");

                        // configure shader
                        mat.SetColor("POINT_COLOR", new Color(0.33f, 0.33f, 0.33f, 0.1f));
                        mat.SetFloat("POINT_SIZE", 4.0f);
                    }
                }

                // generate radii-normalized GMS space
                RadiationBody rb  = Info(body);
                Space         gsm = Gsm_space(rb.body, FlightGlobals.Bodies[rb.reference]);

#if DEBUG               // show axis
                LineRenderer.Commit(gsm.origin, gsm.origin + gsm.x_axis * gsm.scale * 5.0f, Color.red);
                LineRenderer.Commit(gsm.origin, gsm.origin + gsm.y_axis * gsm.scale * 5.0f, Color.green);
                LineRenderer.Commit(gsm.origin, gsm.origin + gsm.z_axis * gsm.scale * 5.0f, Color.blue);
#endif
                // get magnetic field data
                RadiationModel mf = Info(body).model;

                // enable material
                mat.SetPass(0);

                // render active body fields
                Matrix4x4 m = gsm.Look_at();
                if (show_inner && mf.has_inner)
                {
                    mf.inner_pmesh.Render(m);
                }
                if (show_outer && mf.has_outer)
                {
                    mf.outer_pmesh.Render(m);
                }
                if (show_pause && mf.has_pause)
                {
                    mf.pause_pmesh.Render(m);
                }
            }
        }
        public static void Render()
        {
            // do nothing if signal mechanic is disabled
            if (!Features.Signal)
            {
                return;
            }

            // get home body position
            Vector3 home = ScaledSpace.LocalToScaledSpace(FlightGlobals.GetHomeBody().position);

            // for each vessel
            foreach (Vessel v in FlightGlobals.Vessels)
            {
                // get info from the cache
                Vessel_Info vi = Cache.VesselInfo(v);

                // skip invalid vessels
                if (!vi.is_valid)
                {
                    continue;
                }

                // get data from db
                VesselData vd = DB.Vessel(v);

                // skip vessels with showlink disabled
                if (!vd.cfg_showlink)
                {
                    continue;
                }

                // get connection info
                ConnectionInfo conn = vi.connection;

                // skip unlinked vessels
                // - we don't show the red line anymore
                if (!conn.linked)
                {
                    continue;
                }

                // start of the line
                Vector3 a = ScaledSpace.LocalToScaledSpace(v.GetWorldPos3D());

                // determine end of line and color
                Vector3 b;
                Color   color;
                if (conn.status == LinkStatus.direct_link)
                {
                    b     = home;
                    color = Color.green;
                }
                else //< indirect link
                {
                    // get link path
                    var path = conn.path;

                    // use relay position
                    b     = ScaledSpace.LocalToScaledSpace(path[path.Count - 1].GetWorldPos3D());
                    color = Color.yellow;
                }

                // commit the line
                LineRenderer.Commit(a, b, color);

                // if transmitting or relaying science data
                if (vi.transmitting.Length > 0 || vi.relaying.Length > 0)
                {
                    // deduce number of particles and distance between them
                    Vector3 dir            = b - a;
                    float   len            = dir.magnitude;
                    int     particle_count = Lib.Clamp((int)(len / 80.0f), 1, 256);
                    dir /= (float)particle_count;

                    // used for 'moving' effect
                    float k = Time.realtimeSinceStartup / 3.0f;
                    k -= Mathf.Floor(k);

                    // particle color
                    // - fade to avoid overlapping
                    Color clr = Color.cyan;
                    clr.a = Mathf.Min(Lib.Clamp(1.0f - 0.01f * PlanetariumCamera.fetch.Distance / dir.magnitude, 0.0f, 1.0f) * 2.0f, 1.0f);

                    // for each particle
                    for (int i = 0; i < particle_count; ++i)
                    {
                        // commit particle
                        ParticleRenderer.Commit(a + dir * ((float)i + k), 8.0f, clr);
                    }
                }
            }
        }