예제 #1
0
        /// <summary>
        /// Generates a thumbnail for the planet
        /// </summary>
        public static Texture2D GetPlanetThumbnail(CelestialBody body)
        {
            // Config
            RuntimePreviewGenerator.TransparentBackground = true;
            RuntimePreviewGenerator.BackgroundColor       = Color.clear;
            RuntimePreviewGenerator.PreviewDirection      = Vector3.forward;
            RuntimePreviewGenerator.Padding = -0.15f;

            ScaledSpaceOnDemand od       = body.scaledBody.GetComponent <ScaledSpaceOnDemand>();
            Boolean             isLoaded = true;

            if (od != null)
            {
                isLoaded = od.isLoaded;
                if (!isLoaded)
                {
                    od.LoadTextures();
                }
            }

            GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);

            sphere.GetComponentInChildren <MeshFilter>().sharedMesh =
                body.scaledBody.GetComponent <MeshFilter>().sharedMesh;
            sphere.GetComponentInChildren <MeshRenderer>().sharedMaterial =
                body.scaledBody.GetComponent <MeshRenderer>().sharedMaterial;

            Texture2D finalTexture = RuntimePreviewGenerator.GenerateModelPreview(sphere.transform, 256, 256);

            Object.DestroyImmediate(sphere);

            if (!isLoaded)
            {
                od.UnloadTextures();
            }

            return(finalTexture);
        }
            public static IEnumerator UpdateTextures(CelestialBody celestialBody, TextureOptions options)
            {
                // Get time
                DateTime now = DateTime.Now;

                // If the user wants to export normals, we need height too
                if (options.ExportNormal)
                {
                    options.ExportHeight = true;
                }

                // Prepare the PQS
                PQS pqsVersion = celestialBody.pqsController;

                // If the PQS is null, abort
                if (pqsVersion == null)
                {
                    yield break;
                }

                // Tell the PQS that we are going to build maps
                pqsVersion.SetupExternalRender();

                // Get the mod building methods from the PQS
                #if !KSP131
                Action <PQS.VertexBuildData, Boolean> modOnVertexBuildHeight =
                    (Action <PQS.VertexBuildData, Boolean>)Delegate.CreateDelegate(
                        typeof(Action <PQS.VertexBuildData, Boolean>),
                        pqsVersion,
                        typeof(PQS).GetMethod("Mod_OnVertexBuildHeight",
                                              BindingFlags.Instance | BindingFlags.NonPublic));
                #else
                Action <PQS.VertexBuildData> modOnVertexBuildHeight =
                    (Action <PQS.VertexBuildData>)Delegate.CreateDelegate(
                        typeof(Action <PQS.VertexBuildData>),
                        pqsVersion,
                        typeof(PQS).GetMethod("Mod_OnVertexBuildHeight",
                                              BindingFlags.Instance | BindingFlags.NonPublic));
                #endif
                Action <PQS.VertexBuildData> modOnVertexBuild = (Action <PQS.VertexBuildData>)Delegate.CreateDelegate(
                    typeof(Action <PQS.VertexBuildData>),
                    pqsVersion,
                    typeof(PQS).GetMethod("Mod_OnVertexBuild", BindingFlags.Instance | BindingFlags.NonPublic));

                // Get all mods the PQS is connected to
                PQSMod[] mods = pqsVersion.GetComponentsInChildren <PQSMod>()
                                .Where(m => m.sphere == pqsVersion && m.modEnabled).OrderBy(m => m.order).ToArray();

                // Prevent the PQS from updating
                pqsVersion.enabled = false;

                // Create the Textures
                Texture2D colorMap = new Texture2D(options.Resolution, options.Resolution / 2,
                                                   TextureFormat.ARGB32,
                                                   true);
                Texture2D heightMap = new Texture2D(options.Resolution, options.Resolution / 2,
                                                    TextureFormat.RGB24,
                                                    true);

                // Arrays
                Color[] colorMapValues  = new Color[options.Resolution * (options.Resolution / 2)];
                Color[] heightMapValues = new Color[options.Resolution * (options.Resolution / 2)];

                // Create a VertexBuildData
                PQS.VertexBuildData data = new PQS.VertexBuildData();

                // Display
                ScreenMessage message = ScreenMessages.PostScreenMessage("Generating terrain data", Single.MaxValue, ScreenMessageStyle.UPPER_CENTER);
                yield return(null);

                Double[] heightValues = new Double[options.Resolution * (options.Resolution / 2)];

                // Loop through the pixels
                for (Int32 y = 0; y < options.Resolution / 2; y++)
                {
                    // Update Message
                    Double percent = y / (options.Resolution / 2d) * 100;
                    while (CanvasUpdateRegistry.IsRebuildingLayout())
                    {
                        Thread.Sleep(10);
                    }
                    message.textInstance.text.text = "Generating terrain data: " + percent.ToString("0.00") + "%";

                    for (Int32 x = 0; x < options.Resolution; x++)
                    {
                        // Update the VertexBuildData
                        data.directionFromCenter =
                            QuaternionD.AngleAxis(360d / options.Resolution * x, Vector3d.up) *
                            QuaternionD.AngleAxis(90d - 180d / (options.Resolution / 2f) * y, Vector3d.right)
                            * Vector3d.forward;
                        data.vertHeight = pqsVersion.radius;

                        #if !KSP131
                        modOnVertexBuildHeight(data, true);
                        #else
                        modOnVertexBuildHeight(data);
                        #endif
                        modOnVertexBuild(data);

                        // Cache the results
                        heightValues[y * options.Resolution + x]   = data.vertHeight;
                        colorMapValues[y * options.Resolution + x] = data.vertColor;
                    }
                    yield return(null);
                }

                // Update Message
                while (CanvasUpdateRegistry.IsRebuildingLayout())
                {
                    Thread.Sleep(10);
                }
                message.textInstance.text.text = "Calculating height difference";

                // Figure out the delta radius ourselves
                Double minHeight = Double.MaxValue;
                Double maxHeight = Double.MinValue;
                for (Int32 i = 0; i < heightValues.Length; i++)
                {
                    if (heightValues[i] > maxHeight)
                    {
                        maxHeight = heightValues[i];
                    }
                    else if (heightValues[i] < minHeight)
                    {
                        minHeight = heightValues[i];
                    }
                }
                Double deltaRadius = maxHeight - minHeight;
                yield return(null);

                // Update Message
                while (CanvasUpdateRegistry.IsRebuildingLayout())
                {
                    Thread.Sleep(10);
                }
                message.textInstance.text.text = "Calculating color data";

                // Apply the values
                for (Int32 y = 0; y < options.Resolution / 2; y++)
                {
                    // Update Message
                    Double percent = y / (options.Resolution / 2d) * 100;
                    while (CanvasUpdateRegistry.IsRebuildingLayout())
                    {
                        Thread.Sleep(10);
                    }
                    message.textInstance.text.text = "Calculating color data: " + percent.ToString("0.00") + "%";

                    for (Int32 x = 0; x < options.Resolution; x++)
                    {
                        // Build from the Mods
                        Double height = heightValues[y * options.Resolution + x] - pqsVersion.radius;
                        if (options.ExportColor)
                        {
                            // Adjust the Color
                            Color color = colorMapValues[y * options.Resolution + x];
                            if (!pqsVersion.mapOcean)
                            {
                                color.a = 1f;
                            }
                            else if (height > pqsVersion.mapOceanHeight)
                            {
                                color.a = options.TransparentMaps ? 0f : 1f;
                            }
                            else
                            {
                                color = pqsVersion.mapOceanColor.A(1f);
                            }

                            // Set the Pixels
                            colorMapValues[y * options.Resolution + x] = color;
                        }
                        if (options.ExportHeight)
                        {
                            // Adjust the height
                            height = height / deltaRadius;
                            if (height < 0)
                            {
                                height = 0;
                            }
                            else if (height > 1)
                            {
                                height = 1;
                            }

                            // Set the Pixels
                            heightMapValues[y * options.Resolution + x] =
                                new Color((Single)height, (Single)height, (Single)height);
                        }
                    }

                    yield return(null);
                }

                // Serialize the maps to disk
                String name = "KittopiaTech/PluginData/" + celestialBody.transform.name + "/" + DateTime.Now.ToString("yyyy-MM-dd_hh-mm-ss") + "/";
                String path = KSPUtil.ApplicationRootPath + "/GameData/" + name;
                Directory.CreateDirectory(path);

                // Colormap
                if (options.ExportColor)
                {
                    // Update Message
                    while (CanvasUpdateRegistry.IsRebuildingLayout())
                    {
                        Thread.Sleep(10);
                    }
                    message.textInstance.text.text = "Exporting planet maps: Color";

                    // Save it
                    colorMap.SetPixels(colorMapValues);
                    yield return(null);

                    if (options.SaveToDisk)
                    {
                        File.WriteAllBytes(path + celestialBody.transform.name + "_Color.png", colorMap.EncodeToPNG());
                        colorMap.name = name + celestialBody.transform.name + "_Color.png";
                        yield return(null);
                    }

                    // Apply it
                    if (options.ApplyToScaled)
                    {
                        ScaledSpaceOnDemand od = celestialBody.scaledBody.GetComponent <ScaledSpaceOnDemand>();
                        if (od != null)
                        {
                            od.texture = colorMap.name;
                            UnityEngine.Object.DestroyImmediate(colorMap);

                            if (od.isLoaded)
                            {
                                od.UnloadTextures();
                                od.LoadTextures();
                            }
                        }
                        else
                        {
                            colorMap.Apply();
                            celestialBody.scaledBody.GetComponent <MeshRenderer>().sharedMaterial.SetTexture("_MainTex", colorMap);
                        }
                    }
                    else
                    {
                        UnityEngine.Object.DestroyImmediate(colorMap);
                    }
                }

                if (options.ExportHeight)
                {
                    // Update Message
                    while (CanvasUpdateRegistry.IsRebuildingLayout())
                    {
                        Thread.Sleep(10);
                    }
                    message.textInstance.text.text = "Exporting planet maps: Height";

                    heightMap.SetPixels(heightMapValues);
                    yield return(null);

                    if (options.SaveToDisk)
                    {
                        File.WriteAllBytes(path + celestialBody.transform.name + "_Height.png",
                                           heightMap.EncodeToPNG());
                        yield return(null);
                    }

                    if (options.ExportNormal)
                    {
                        // Update Message
                        while (CanvasUpdateRegistry.IsRebuildingLayout())
                        {
                            Thread.Sleep(10);
                        }
                        message.textInstance.text.text = "Exporting planet maps: Normal";

                        // Bump to Normal Map
                        Texture2D normalMap = Utility.BumpToNormalMap(heightMap, pqsVersion, options.NormalStrength / 10);
                        yield return(null);

                        if (options.SaveToDisk)
                        {
                            File.WriteAllBytes(path + celestialBody.transform.name + "_Normal.png",
                                               normalMap.EncodeToPNG());
                            normalMap.name = name + celestialBody.transform.name + "_Normal.png";
                            yield return(null);
                        }

                        // Apply it
                        if (options.ApplyToScaled)
                        {
                            ScaledSpaceOnDemand od = celestialBody.scaledBody.GetComponent <ScaledSpaceOnDemand>();
                            if (od != null)
                            {
                                od.normals = normalMap.name;
                                UnityEngine.Object.DestroyImmediate(normalMap);

                                if (od.isLoaded)
                                {
                                    od.UnloadTextures();
                                    od.LoadTextures();
                                }
                            }
                            else
                            {
                                normalMap.Apply();
                                celestialBody.scaledBody.GetComponent <MeshRenderer>().sharedMaterial
                                .SetTexture("_BumpMap", normalMap);
                            }
                        }
                        else
                        {
                            UnityEngine.Object.DestroyImmediate(normalMap);
                        }
                    }

                    UnityEngine.Object.DestroyImmediate(heightMap);
                }

                // Close the Renderer
                pqsVersion.enabled = true;
                pqsVersion.CloseExternalRender();

                // Declare that we're done
                ScreenMessages.RemoveMessage(message);
                ScreenMessages.PostScreenMessage("Operation completed in: " + (DateTime.Now - now).TotalMilliseconds + " ms", 2f, ScreenMessageStyle.UPPER_CENTER);
            }