/// <summary>
        /// Returns the Color for the Instance Position
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        public Color GetCameraColor(StaticInstance instance)
        {
            SetupCameraForVessel(instance);
            // Move the current object out of the cams view
            InstanceUtil.SetLayerRecursively(instance, 0);
            grasCamera.targetTexture = cameraRenderTexture;
            grasCamera.enabled       = true;
            //Light light = grasCamera.gameObject.AddOrGetComponent<Light>();
            //light.type = LightType.Point;
            //light.intensity = 1;
            //light.color = Color.white;
            //light.enabled = true;
            grasCamera.Render();
            //light.enabled = false;

            Ray        myRay   = new Ray(cameraObject.transform.position, instance.CelestialBody.transform.position);
            RaycastHit castHit = new RaycastHit();

            if (!Physics.Raycast(myRay, out castHit, float.PositiveInfinity, 1 << 15))
            {
                Log.Normal("NO raycast hit");
            }
            else
            {
                Renderer rend = castHit.transform.GetComponent <Renderer>();

                if (rend != null)
                {
                    if (rend.materials.Length != 0)
                    {
                        foreach (string name in rend.material.GetTexturePropertyNames())
                        {
                            Texture2D lowTex = (Texture2D)rend.material.GetTexture("_lowTex");
                        }
                    }
                    else
                    {
                        Log.Normal("No Raycast material found");
                    }
                }
                else
                {
                    Log.Normal("No renderer found");
                }
            }


            // bring it back to the normal scenery
            InstanceUtil.SetLayerRecursively(instance, 15);

            Color newColor = GrassColorUtils.AverageColor(cameraRenderTexture.ToTexture2D().GetPixels());

            newColor.a = 1;

            return(newColor);
        }
        public Texture2D GetCameraTexture(StaticInstance instance)
        {
            Texture2D MidTex2 = null;

            SetupCameraForVessel(instance);

            Ray        myRay   = new Ray(cameraObject.transform.position, instance.CelestialBody.transform.position);
            RaycastHit castHit = new RaycastHit();

            if (!Physics.Raycast(myRay, out castHit, float.PositiveInfinity, 1 << 15))
            {
                Log.Normal("NO raycast hit");
            }
            else
            {
                Renderer rend = castHit.transform.GetComponent <Renderer>();

                if (rend != null)
                {
                    if (rend.materials.Length != 0)
                    {
                        Texture midTex = rend.material.GetTexture("_lowTex");
                        if (midTex != null)
                        {
                            MidTex2 = midTex.ToTexture2D(64);
                            //rend.material.GetTexture("_midTex").ToTexture2D().WritePNG("Test/MidTex");
                            //rend.material.GetTexture("_highTex").ToTexture2D().WritePNG("Test/HighTex");
                        }
                        else
                        {
                            Log.Normal("No LowTex found");
                        }
                    }
                    else
                    {
                        Log.Normal("No Raycast material found");
                    }
                }
                else
                {
                    Log.Normal("No renderer found");
                }
            }

            InstanceUtil.SetLayerRecursively(instance, 15);

            return(MidTex2);
        }
        private void Spawn()
        {
            CelestialBody.CBUpdate();
            isSpawned = true;

            mesh = ModelVariant.SpawnVariant(this);
            {
                if (_mesh == null)
                {
                    Log.UserError("Cannot spawn 3dModel of Instance: " + model.name);
                    Destroy();
                    return;
                }
            }

            if (model.isSquad)
            {
                InstanceUtil.MangleSquadStatic(this);
            }
            InstanceUtil.SetLayerRecursively(this, 15);

            mesh.SetActive(true);

            //Scaling
            origScale = gameObject.transform.localScale;             // save the original scale for later use
            gameObject.transform.localScale *= ModelScale;

            foreach (StaticModule module in model.modules)
            {
                moduleKey = (module.moduleNamespace + "_" + module.moduleClassname);
                Type moduleType;
                if (staticModules.ContainsKey(moduleKey))
                {
                    moduleType = staticModules[moduleKey];
                }
                else
                {
                    moduleType = AssemblyLoader.loadedAssemblies.SelectMany(asm => asm.assembly.GetTypes()).FirstOrDefault(t => t.Namespace == module.moduleNamespace && t.Name == module.moduleClassname);
                    staticModules.Add(moduleKey, moduleType);
                }

                StaticModule mod = mesh.AddComponent(moduleType) as StaticModule;

                if (mod != null)
                {
                    mod.enabled        = false;
                    mod.staticInstance = this;
                    foreach (string fieldName in module.moduleFields.Keys)
                    {
                        FieldInfo field = mod.GetType().GetField(fieldName);
                        if (field != null)
                        {
                            field.SetValue(mod, Convert.ChangeType(module.moduleFields[fieldName], field.FieldType));
                        }
                        else
                        {
                            Log.UserWarning("Field " + fieldName + " does not exist in " + module.moduleClassname);
                        }
                    }
                    //myStaticModules.Add(mod);
                }
                else
                {
                    Log.UserError("Module " + module.moduleClassname + " could not be loaded in " + gameObject.name);
                }
            }


            foreach (Renderer renderer in gameObject.GetComponentsInChildren <Renderer>(true))
            {
                renderer.enabled = true;
                AdvancedTextures.CheckForExistingMaterial(renderer);
            }

            ModelVariant.ApplyVariant(this);

            //Make LaunchSites more sturdy
            if (!model.isSquad)
            {
                Destructable.MakeDestructable(this);
                if (hasLauchSites)
                {
                    destructible.impactMomentumThreshold = Math.Max(destructible.impactMomentumThreshold, 3000f);
                    launchSite.AttachSelector();
                }
            }

            foreach (var facility in myFacilities)
            {
                facility.AttachSelector();
            }
        }
        /// <summary>
        /// Spawns a new Instance in the Gameworld and registers itself to the Static Database
        /// </summary>
        /// <param name="editing"></param>
        /// <param name="bPreview"></param>
        internal void SpawnObject(Boolean editing = false, Boolean bPreview = false)
        {
            // mangle Squads statics
            if (model.isSquad)
            {
                InstanceUtil.MangleSquadStatic(this);
            }

            // Objects spawned at runtime should be active, ones spawned at loading not
            InstanceUtil.SetActiveRecursively(this, editing);

            Transform[]       gameObjectList = gameObject.GetComponentsInChildren <Transform>();
            List <GameObject> rendererList   = (from t in gameObjectList where t.gameObject.GetComponent <Renderer>() != null select t.gameObject).ToList();

            InstanceUtil.SetLayerRecursively(this, 15);

            if (bPreview && editing)
            {
                this.ToggleAllColliders(false);
            }


            this.preview = bPreview;

            if (editing)
            {
                KerbalKonstructs.instance.selectObject(this, true, true, bPreview);
            }

            float objvisibleRange = VisibilityRange;

            if (objvisibleRange < 1)
            {
                objvisibleRange = 25000f;
            }

            PQSCity.LODRange range = new PQSCity.LODRange
            {
                renderers    = new GameObject[0],
                objects      = new GameObject[0],
                visibleRange = objvisibleRange
            };

            pqsCity                        = gameObject.AddComponent <PQSCity>();
            pqsCity.lod                    = new[] { range };
            pqsCity.frameDelta             = 10000;                        //update interval for its own visiblility range checking. unused by KK, so set this to a high value
            pqsCity.repositionRadial       = RadialPosition;               //position
            pqsCity.repositionRadiusOffset = RadiusOffset;                 //height
            pqsCity.reorientInitialUp      = Orientation;                  //orientation
            pqsCity.reorientFinalAngle     = RotationAngle;                //rotation x axis
            pqsCity.reorientToSphere       = true;                         //adjust rotations to match the direction of gravity
            pqsCity.sphere                 = CelestialBody.pqsController;
            origScale                      = pqsCity.transform.localScale; // save the original scale for later use
            pqsCity.transform.localScale  *= ModelScale;
            pqsCity.order                  = 100;
            pqsCity.modEnabled             = true;
            pqsCity.repositionToSphere     = true; //enable repositioning
            gameObject.transform.parent    = CelestialBody.pqsController.transform;
            pqsCity.transform.parent       = CelestialBody.pqsController.transform;

            switch (heighReference)
            {
            case HeightReference.Sphere:
                pqsCity.repositionToSphereSurface = false;     //Snap to surface?

                break;

            case HeightReference.Terrain:

                pqsCity.repositionToSphereSurface          = true; //Snap to surface?
                pqsCity.repositionToSphereSurfaceAddHeight = true;
                pqsCity.repositionToSphere = false;
                break;

            default:
                // we try to descide which one is the best to take
                string biome = ScienceUtil.GetExperimentBiome(CelestialBody, RefLatitude, RefLongitude);
                float  heightAboveTerrain = SDRescale.GetSurfaceRefereceHeight(this);

                if ((biome == "Water" || biome == "Shores") && ((Math.Abs(RadiusOffset) < 5) && heightAboveTerrain > 5))     // most likely at ocean surface
                {
                    Log.Normal("Found a swimming object: " + this.gameObject.name);
                    pqsCity.repositionToSphereSurface = false;     //Snap to surface?
                    heighReference = HeightReference.Sphere;
                }
                else
                {
                    {
                        //    Log.Normal("found new Radiusffset: " + heightAboveTerrain);
                        RadiusOffset = heightAboveTerrain;
                        pqsCity.repositionToSphereSurface          = true; //Snap to surface?#
                        pqsCity.repositionToSphereSurfaceAddHeight = true;
                        pqsCity.repositionRadiusOffset             = heightAboveTerrain;
                        pqsCity.repositionToSphere = false;

                        heighReference = HeightReference.Terrain;
                    }
                }
                break;
            }


            //pqsCity.lat = RefLatitude ;
            //pqsCity.lon = RefLongitude;
            pqsCity.alt = RadiusOffset;
            pqsCity.ResetCelestialBody();
            pqsCity.OnSetup();
            pqsCity.Orientate();


            //PQSCity2.LodObject lodObject = new PQSCity2.LodObject();
            //lodObject.visibleRange = VisibilityRange;
            //lodObject.objects = new GameObject[] { };
            //pqsCity2 = gameObject.AddComponent<PQSCity2>();
            //pqsCity2.objects = new[] { lodObject };
            //pqsCity2.objectName = "";
            //pqsCity2.lat = RefLatitude;
            //pqsCity2.lon = RefLongitude;
            //pqsCity2.alt = RadiusOffset;
            //pqsCity2.up = Orientation;
            //pqsCity2.rotation = RotationAngle;
            //pqsCity2.sphere = CelestialBody.pqsController;


            //pqsCity2.OnSetup();
            //pqsCity2.Orientate();


            foreach (StaticModule module in model.modules)
            {
                Type         moduleType = AssemblyLoader.loadedAssemblies.SelectMany(asm => asm.assembly.GetTypes()).FirstOrDefault(t => t.Namespace == module.moduleNamespace && t.Name == module.moduleClassname);
                StaticModule mod        = gameObject.AddComponent(moduleType) as StaticModule;

                if (mod != null)
                {
                    mod.staticInstance = this;
                    foreach (string fieldName in module.moduleFields.Keys)
                    {
                        FieldInfo field = mod.GetType().GetField(fieldName);
                        if (field != null)
                        {
                            field.SetValue(mod, Convert.ChangeType(module.moduleFields[fieldName], field.FieldType));
                        }
                        else
                        {
                            Log.UserWarning("Field " + fieldName + " does not exist in " + module.moduleClassname);
                        }
                    }
                }
                else
                {
                    Log.UserError("Module " + module.moduleClassname + " could not be loaded in " + gameObject.name);
                }
            }

            foreach (GameObject gorenderer in rendererList)
            {
                gorenderer.GetComponent <Renderer>().enabled = true;
            }

            StaticDatabase.AddStatic(this);

            // Add them to the bodys objectlist, so they show up as anomalies
            // After we got a new Name from StaticDatabase.AddStatic()
            if (isScanable)
            {
                Log.Normal("Added " + gameObject.name + " to scanable Objects");
                var pqsObjectList = CelestialBody.pqsSurfaceObjects.ToList();
                pqsObjectList.Add(pqsCity as PQSSurfaceObject);
                CelestialBody.pqsSurfaceObjects = pqsObjectList.ToArray();
            }
        }
        /// <summary>
        /// Spawns a new Instance in the Gameworld and registers itself to the Static Database
        /// </summary>
        /// <param name="editing"></param>
        /// <param name="bPreview"></param>
        internal void SpawnObject(Boolean editing = false, Boolean bPreview = false)
        {
            // mangle Squads statics
            if (model.isSquad)
            {
                InstanceUtil.MangleSquadStatic(this);
            }

            // Objects spawned at runtime should be active, ones spawned at loading not
            InstanceUtil.SetActiveRecursively(this, editing);

            Transform[]       gameObjectList = gameObject.GetComponentsInChildren <Transform>();
            List <GameObject> rendererList   = (from t in gameObjectList where t.gameObject.GetComponent <Renderer>() != null select t.gameObject).ToList();

            InstanceUtil.SetLayerRecursively(this, 15);

            if (bPreview && editing)
            {
                this.ToggleAllColliders(false);
            }


            this.preview = bPreview;

            if (editing)
            {
                KerbalKonstructs.instance.selectObject(this, true, true, bPreview);
            }

            InstanceUtil.CreateGroupCenterIfMissing(this);

            groupCenter = StaticDatabase.allCenters[groupCenterName];

            if (RelativePosition.Equals(Vector3.zero))
            {
                Log.Normal("LegacySpawnInstance called for " + configPath);
                LegacySpawnInstance();
                gameObject.transform.parent = groupCenter.gameObject.transform;
                pqsCity.enabled             = false;
                pqsCity.sphere = null;
                pqsCity        = null;

                RelativePosition = gameObject.transform.localPosition;
                Orientation      = gameObject.transform.localEulerAngles;
            }
            else
            {
                gameObject.transform.position         = groupCenter.gameObject.transform.position;
                gameObject.transform.parent           = groupCenter.gameObject.transform;
                gameObject.transform.localPosition    = RelativePosition;
                gameObject.transform.localEulerAngles = Orientation;
            }

            //Scaling
            origScale = gameObject.transform.localScale;             // save the original scale for later use
            gameObject.transform.localScale *= ModelScale;

            RefLatitude    = (float)CelestialBody.GetLatitudeAndLongitude(gameObject.transform.position).x;
            RefLongitude   = (float)(CelestialBody.GetLatitudeAndLongitude(gameObject.transform.position).y);
            RadialPosition = radialPosition;

            foreach (StaticModule module in model.modules)
            {
                Type         moduleType = AssemblyLoader.loadedAssemblies.SelectMany(asm => asm.assembly.GetTypes()).FirstOrDefault(t => t.Namespace == module.moduleNamespace && t.Name == module.moduleClassname);
                StaticModule mod        = gameObject.AddComponent(moduleType) as StaticModule;

                if (mod != null)
                {
                    mod.staticInstance = this;
                    foreach (string fieldName in module.moduleFields.Keys)
                    {
                        FieldInfo field = mod.GetType().GetField(fieldName);
                        if (field != null)
                        {
                            field.SetValue(mod, Convert.ChangeType(module.moduleFields[fieldName], field.FieldType));
                        }
                        else
                        {
                            Log.UserWarning("Field " + fieldName + " does not exist in " + module.moduleClassname);
                        }
                    }
                }
                else
                {
                    Log.UserError("Module " + module.moduleClassname + " could not be loaded in " + gameObject.name);
                }
            }

            foreach (GameObject gorenderer in rendererList)
            {
                gorenderer.GetComponent <Renderer>().enabled = true;
            }

            StaticDatabase.AddStatic(this);

            // Add them to the bodys objectlist, so they show up as anomalies
            // After we got a new Name from StaticDatabase.AddStatic()
            if (isScanable)
            {
                Log.Normal("Added " + gameObject.name + " to scanable Objects");
                var pqsObjectList = CelestialBody.pqsSurfaceObjects.ToList();
                if (!pqsObjectList.Contains((PQSSurfaceObject)groupCenter.pqsCity))
                {
                    pqsObjectList.Add(groupCenter.pqsCity as PQSSurfaceObject);
                }
                CelestialBody.pqsSurfaceObjects = pqsObjectList.ToArray();
            }
        }
        /// <summary>
        /// Returns the Color for the Instance Position
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        public Color GetCameraColor(StaticInstance instance)
        {
            SetupCameraForVessel(instance);
            // Move the current object out of the cams view
            InstanceUtil.SetLayerRecursively(instance, 0);
            grasCamera.targetTexture = cameraRenderTexture;
            grasCamera.enabled       = true;
            grasCamera.Render();

            //Ray myRay = new Ray(cameraObject.transform.position, instance.CelestialBody.transform.position);
            //RaycastHit castHit = new RaycastHit();
            //if (!Physics.Raycast(myRay, out castHit, float.PositiveInfinity, 1 << 15))
            //{
            //    Log.Normal("NO raycast hit");
            //}
            //else
            //{

            //    Renderer rend = castHit.transform.GetComponentsInChildren<Renderer>(true).FirstOrDefault();

            //    if (rend == null)
            //    {
            //        Log.Normal("No renderer found");
            //    }
            //    if (rend.materials.Length == 0)
            //    {
            //        Log.Normal("No Raycast material found");
            //    }
            //    if (rend.material.shader == null)
            //    {
            //        Log.Normal("No shader found");
            //    }
            //    else
            //    {
            //        RenderTexture myTexture = new RenderTexture(20, 20, 24);
            //        Graphics.Blit(null, myTexture, rend.material);
            //        myTexture.
            //    }
            //}

            // bring it back to the normal scenery
            InstanceUtil.SetLayerRecursively(instance, 15);

            RenderTexture.active = cameraRenderTexture;
            cameraTexture.ReadPixels(new Rect(0, 0, frameWidth, frameHeight), 0, 0);

            grasCamera.targetTexture = null;
            grasCamera.enabled       = false;
            RenderTexture.active     = null;

            Color[] cols = cameraTexture.GetPixels();
            float   r = 0, g = 0, b = 0;
            int     len = cols.Length;

            for (int i = 0; i < len; i++)
            {
                r += cols[i].r;
                g += cols[i].g;
                b += cols[i].b;
            }
            Color outColor = new Color();

            outColor.r = r / len;
            outColor.g = g / len;
            outColor.b = b / len;
            //outColor.a = 0.014f;
            return(outColor);
        }