/** * Constructor for pre-existing PQS * * @param pqsVersion Existing PQS to augment **/ public PQSLoader(PQS pqsVersion) { this.pqsVersion = pqsVersion; // Get the required PQS information transform = pqsVersion.GetComponentsInChildren <PQSMod_CelestialBodyTransform> (true).Where(mod => mod.transform.parent == pqsVersion.transform).FirstOrDefault(); lightDirection = pqsVersion.GetComponentsInChildren <PQSMod_MaterialSetDirection>(true).Where(mod => mod.transform.parent == pqsVersion.transform).FirstOrDefault(); uvs = pqsVersion.GetComponentsInChildren <PQSMod_UVPlanetRelativePosition>(true).Where(mod => mod.transform.parent == pqsVersion.transform).FirstOrDefault(); collider = pqsVersion.GetComponentsInChildren <PQSMod_QuadMeshColliders>(true).Where(mod => mod.transform.parent == pqsVersion.transform).FirstOrDefault(); // Create physics material editor physicsMaterial = new PhysicsMaterialParser(collider.physicsMaterial); }
// Constructor for pre-existing PQS public PQSLoader(PQS pqsVersion) { this.pqsVersion = pqsVersion; // Get the required PQS information transform = pqsVersion.GetComponentsInChildren <PQSMod_CelestialBodyTransform> (true).Where(mod => mod.transform.parent == pqsVersion.transform).FirstOrDefault(); lightDirection = pqsVersion.GetComponentsInChildren <PQSMod_MaterialSetDirection>(true).Where(mod => mod.transform.parent == pqsVersion.transform).FirstOrDefault(); uvs = pqsVersion.GetComponentsInChildren <PQSMod_UVPlanetRelativePosition>(true).Where(mod => mod.transform.parent == pqsVersion.transform).FirstOrDefault(); collider = pqsVersion.GetComponentsInChildren <PQSMod_QuadMeshColliders>(true).Where(mod => mod.transform.parent == pqsVersion.transform).FirstOrDefault(); // Create physics material editor physicsMaterial = new PhysicsMaterialParser(collider.physicsMaterial); // Clone the surface material of the PQS if (PQSMainOptimised.UsesSameShader(pqsVersion.surfaceMaterial)) { pqsVersion.surfaceMaterial = new PQSMainOptimisedLoader(pqsVersion.surfaceMaterial); if (((PQSMainOptimisedLoader)pqsVersion.surfaceMaterial).globalDensity < 2) { ((PQSMainOptimisedLoader)pqsVersion.surfaceMaterial).globalDensity = -8E-06f; } } else if (PQSMainShader.UsesSameShader(pqsVersion.surfaceMaterial)) { pqsVersion.surfaceMaterial = new PQSMainShaderLoader(pqsVersion.surfaceMaterial); if (((PQSMainShaderLoader)pqsVersion.surfaceMaterial).globalDensity < 2) { ((PQSMainShaderLoader)pqsVersion.surfaceMaterial).globalDensity = -8E-06f; } } else if (PQSProjectionAerialQuadRelative.UsesSameShader(pqsVersion.surfaceMaterial)) { pqsVersion.surfaceMaterial = new PQSProjectionAerialQuadRelativeLoader(pqsVersion.surfaceMaterial); if (((PQSProjectionAerialQuadRelativeLoader)pqsVersion.surfaceMaterial).globalDensity < 2) { ((PQSProjectionAerialQuadRelativeLoader)pqsVersion.surfaceMaterial).globalDensity = -8E-06f; } } else if (PQSProjectionSurfaceQuad.UsesSameShader(pqsVersion.surfaceMaterial)) { pqsVersion.surfaceMaterial = new PQSProjectionSurfaceQuadLoader(pqsVersion.surfaceMaterial); } surfaceMaterial = pqsVersion.surfaceMaterial; surfaceMaterial.name = Guid.NewGuid().ToString(); // Clone the fallback material of the PQS fallbackMaterial = new PQSProjectionFallbackLoader(pqsVersion.fallbackMaterial); pqsVersion.fallbackMaterial = fallbackMaterial; fallbackMaterial.name = Guid.NewGuid().ToString(); }
public static T[] GetPQSMods <T>(this PQS pqs) where T : PQSMod { List <T> mods = new List <T> (); foreach (var mod in pqs.GetComponentsInChildren <T>()) { mods.Add(mod); } return(mods.ToArray()); }
internal static void Update() { Debug.Log("EditorBuildings.Update"); // Destroy old clones DestroyAll(); // Find the homeworld CelestialBody homeBody = FlightGlobals.GetHomeBody(); Debug.Log("EditorBuildings.Update", "homeBody = " + homeBody); // Get the pqsController PQS pqs = homeBody?.pqsController; Debug.Log("EditorBuildings.Update", "pqsController = " + pqs); // Filter and Duplicate PQSMods Duplicate(pqs?.GetComponentsInChildren <PQSMod>()); }
public static Mesh ComputeScaledSpaceMesh(CelestialBody body, PQS pqs) { // We need to get the body for Jool (to steal it's mesh) const Double R_SCALED_JOOL = 1000.0f; Double rMetersToScaledUnits = (Single)(R_SCALED_JOOL / body.Radius); // Generate a duplicate of the Jool mesh Mesh mesh = DuplicateMesh(Templates.ReferenceGeosphere); Logger.Active.Log(body); Logger.Active.Log(pqs); Logger.Active.Log(body.pqsController); // If this body has a PQS, we can create a more detailed object, otherwise just return the generic mesh if (pqs == null) { return(mesh); } // first we enable all maps OnDemandStorage.EnableBody(body.bodyName); // In order to generate the scaled space we have to enable the mods. Since this is // a prefab they don't get disabled as kill game performance. To resolve this we // clone the PQS, use it, and then delete it when done. At runtime we can simply use // the PQS that is active GameObject pqsVersionGameObject = Injector.IsInPrefab ? Instantiate(pqs.gameObject) : pqs.gameObject; PQS pqsVersion = pqsVersionGameObject.GetComponent <PQS>(); // Deactivate blacklisted Mods PQSMod[] mods = pqsVersion.GetComponentsInChildren <PQSMod>(true).OrderBy(m => m.order).ToArray(); for (Int32 i = 0; i < mods.Length; i++) { // Disable mods that don't belong to us if (mods[i].transform.parent != pqsVersion.transform) { mods[i].modEnabled = false; continue; } switch (mods[i]) { // Disable the OnDemand notifier case PQSMod_OnDemandHandler _: mods[i].modEnabled = false; continue; case PQSMod_FlattenArea _: typeof(PQSMod_FlattenArea).GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .First(f => f.FieldType == typeof(Boolean)).SetValue(mods[i], true); break; } } pqsVersion.StartUpSphere(); pqsVersion.isBuildingMaps = true; // If we were able to find PQS mods if (mods.Length > 0) { // Generate the PQS modifications Vector3[] vertices = mesh.vertices; for (Int32 i = 0; i < mesh.vertexCount; i++) { // Get the UV coordinate of this vertex Vector2 uv = mesh.uv[i]; // Since this is a geosphere, normalizing the vertex gives the direction from center center Vector3 direction = vertices[i]; direction.Normalize(); // Build the vertex data object for the PQS mods PQS.VertexBuildData vertex = new PQS.VertexBuildData { directionFromCenter = direction, vertHeight = body.Radius, u = uv.x, v = uv.y }; // Build from the PQS for (Int32 m = 0; m < mods.Length; m++) { // Don't build disabled mods if (!mods[m].modEnabled) { continue; } // Don't build mods that don't belong to us if (mods[m].transform.parent != pqsVersion.transform) { continue; } mods[m].OnVertexBuildHeight(vertex); } // Check for sea level if (pqsVersion.mapOcean) { vertex.vertHeight = Math.Max(vertex.vertHeight, body.Radius); } // Adjust the displacement vertices[i] = direction * (Single)(vertex.vertHeight * rMetersToScaledUnits); } mesh.vertices = vertices; mesh.RecalculateNormals(); mesh.RecalculateBounds(); RecalculateTangents(mesh); } // Cleanup pqsVersion.isBuildingMaps = false; pqsVersion.DeactivateSphere(); // If we are working with a copied PQS, clean it up if (Injector.IsInPrefab) { UnityEngine.Object.Destroy(pqsVersionGameObject); } OnDemandStorage.DisableBody(body.bodyName); // Return the generated scaled space mesh return(mesh); }
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) { throw new InvalidOperationException(); } // Tell the PQS that we are going to build maps pqsVersion.SetupExternalRender(); // Get the mod building methods from the PQS Action <PQS.VertexBuildData> modOnVertexBuildHeight = (Action <PQS.VertexBuildData>)Delegate.CreateDelegate( typeof(Action <PQS.VertexBuildData>), pqsVersion, typeof(PQS).GetMethod("Mod_OnVertexBuildHeight", BindingFlags.Instance | BindingFlags.NonPublic)); 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(pqsVersion.mapFilesize, pqsVersion.mapFilesize / 2, TextureFormat.ARGB32, true); Texture2D heightMap = new Texture2D(pqsVersion.mapFilesize, pqsVersion.mapFilesize / 2, TextureFormat.RGB24, true); // Arrays Color[] colorMapValues = new Color[pqsVersion.mapFilesize * (pqsVersion.mapFilesize / 2)]; Color[] heightMapValues = new Color[pqsVersion.mapFilesize * (pqsVersion.mapFilesize / 2)]; // Create a VertexBuildData PQS.VertexBuildData data = new PQS.VertexBuildData(); // Display ScreenMessage message = ScreenMessages.PostScreenMessage("Generating Planet-Maps", Single.MaxValue, ScreenMessageStyle.UPPER_CENTER); yield return(null); // Loop through the pixels for (Int32 y = 0; y < pqsVersion.mapFilesize / 2; y++) { for (Int32 x = 0; x < pqsVersion.mapFilesize; x++) { // Update Message Double percent = (Double)(y * pqsVersion.mapFilesize + x) / (pqsVersion.mapFilesize / 2 * pqsVersion.mapFilesize) * 100; while (CanvasUpdateRegistry.IsRebuildingLayout()) { Thread.Sleep(10); } message.textInstance.text.text = "Generating Planet-Maps: " + percent.ToString("0.00") + "%"; // Update the VertexBuildData data.directionFromCenter = QuaternionD.AngleAxis(360d / pqsVersion.mapFilesize * x, Vector3d.up) * QuaternionD.AngleAxis(90d - 180d / (pqsVersion.mapFilesize / 2f) * y, Vector3d.right) * Vector3d.forward; data.vertHeight = pqsVersion.radius; // Build from the Mods Double height = Double.MinValue; if (options.ExportHeight) { modOnVertexBuildHeight(data); // Adjust the height height = (data.vertHeight - pqsVersion.radius) * (1d / pqsVersion.mapMaxHeight); if (height < 0) { height = 0; } else if (height > 1) { height = 1; } // Set the Pixels heightMapValues[y * pqsVersion.mapFilesize + x] = new Color((Single)height, (Single)height, (Single)height); } if (options.ExportColor) { modOnVertexBuild(data); // Adjust the Color Color color = data.vertColor; 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 * pqsVersion.mapFilesize + x] = color; } } yield return(null); } // Serialize the maps to disk String name = "KittopiaTech/PluginData/" + celestialBody.transform.name + "/"; String path = KSPUtil.ApplicationRootPath + "/GameData/" + name; Directory.CreateDirectory(path); // Colormap if (options.ExportColor) { // 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) { colorMap.Apply(); celestialBody.scaledBody.GetComponent <MeshRenderer>().material.SetTexture("_MainTex", colorMap); } } if (options.ExportHeight) { 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) { // Bump to Normal Map Texture2D normalMap = Utility.BumpToNormalMap(heightMap, pqsVersion.radius, options.NormalStrength); 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) { normalMap.Apply(); celestialBody.scaledBody.GetComponent <MeshRenderer>().material .SetTexture("_BumpMap", normalMap); } } } // 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); }
/// <summary> /// Renders the Window /// </summary> protected override void Render(Int32 id) { // Call base base.Render(id); // Check for PQS if (Current.pqsController == null) { Button(Localization.LOC_KITTOPIATECH_PQSEDITOR_ADD, () => { // Create a new PQS GameObject controllerRoot = new GameObject(Current.name); controllerRoot.transform.parent = Current.transform; PQS pqsVersion = controllerRoot.AddComponent <PQS>(); // I am at this time unable to determine some of the magic parameters which cause the PQS to work... (Or just lazy but who cares :P) PSystemBody Laythe = Utility.FindBody(Injector.StockSystemPrefab.rootBody, "Laythe"); Utility.CopyObjectFields(Laythe.pqsVersion, pqsVersion); pqsVersion.surfaceMaterial = Laythe.pqsVersion.surfaceMaterial; // Create the fallback material (always the same shader) pqsVersion.fallbackMaterial = new PQSProjectionFallbackLoader(); pqsVersion.fallbackMaterial.name = Guid.NewGuid().ToString(); // Create the celestial body transform GameObject mod = new GameObject("_CelestialBody"); mod.transform.parent = controllerRoot.transform; PQSMod_CelestialBodyTransform transform = mod.AddComponent <PQSMod_CelestialBodyTransform>(); transform.sphere = pqsVersion; transform.forceActivate = false; transform.deactivateAltitude = 115000; transform.forceRebuildOnTargetChange = false; transform.planetFade = new PQSMod_CelestialBodyTransform.AltitudeFade(); transform.planetFade.fadeFloatName = "_PlanetOpacity"; transform.planetFade.fadeStart = 100000.0f; transform.planetFade.fadeEnd = 110000.0f; transform.planetFade.valueStart = 0.0f; transform.planetFade.valueEnd = 1.0f; transform.planetFade.secondaryRenderers = new List <GameObject>(); transform.secondaryFades = new PQSMod_CelestialBodyTransform.AltitudeFade[0]; transform.requirements = PQS.ModiferRequirements.Default; transform.modEnabled = true; transform.order = 10; // Create the material direction mod = new GameObject("_Material_SunLight"); mod.transform.parent = controllerRoot.gameObject.transform; PQSMod_MaterialSetDirection lightDirection = mod.AddComponent <PQSMod_MaterialSetDirection>(); lightDirection.sphere = pqsVersion; lightDirection.valueName = "_sunLightDirection"; lightDirection.requirements = PQS.ModiferRequirements.Default; lightDirection.modEnabled = true; lightDirection.order = 100; // Create the UV planet relative position mod = new GameObject("_Material_SurfaceQuads"); mod.transform.parent = controllerRoot.transform; PQSMod_UVPlanetRelativePosition uvs = mod.AddComponent <PQSMod_UVPlanetRelativePosition>(); uvs.sphere = pqsVersion; uvs.requirements = PQS.ModiferRequirements.Default; uvs.modEnabled = true; uvs.order = 999999; // Crete the quad mesh colliders mod = new GameObject("QuadMeshColliders"); mod.transform.parent = controllerRoot.gameObject.transform; PQSMod_QuadMeshColliders collider = mod.AddComponent <PQSMod_QuadMeshColliders>(); collider.sphere = pqsVersion; collider.maxLevelOffset = 0; collider.physicsMaterial = new PhysicMaterial(); collider.physicsMaterial.name = "Ground"; collider.physicsMaterial.dynamicFriction = 0.6f; collider.physicsMaterial.staticFriction = 0.8f; collider.physicsMaterial.bounciness = 0.0f; collider.physicsMaterial.frictionCombine = PhysicMaterialCombine.Maximum; collider.physicsMaterial.bounceCombine = PhysicMaterialCombine.Average; collider.requirements = PQS.ModiferRequirements.Default; collider.modEnabled = true; collider.order = 100; // Assing the new PQS Current.pqsController = pqsVersion; pqsVersion.transform.position = Current.transform.position; pqsVersion.transform.localPosition = Vector3.zero; // Set mode _mode = Modes.List; }, new Rect(20, index * distance + 10, 350, 20)); return; } // Mode List if (_mode == Modes.List) { // Get the PQS-Spheres and their mods IEnumerable <PQS> pqsList = Current.GetComponentsInChildren <PQS>(true); IEnumerable <PQSMod> pqsModList = Current.GetComponentsInChildren <PQSMod>(true); // Scroll BeginScrollView(250, (pqsList.Count() + pqsModList.Count()) * distance + distance * 4, 20); // Index index = 0; // Render foreach (PQS pqs in pqsList) { Button(pqs.ToString(), () => { _mode = Modes.PQS; _sphere = pqs; }, new Rect(20, index * distance + 10, 350, 20)); } foreach (PQSMod mod in pqsModList) { Button(mod.ToString(), () => { _mode = Modes.PQSMod; _sphere = mod.sphere; _mod = mod; }, new Rect(20, index * distance + 10, 350, 20)); } index++; Button(Localization.LOC_KITTOPIATECH_PQSEDITOR_ADD_MOD, () => _mode = Modes.AddMod, new Rect(20, index * distance + 10, 350, 20)); if (Current.pqsController.ChildSpheres.All(s => s.name != Current.pqsController.name + "Ocean")) { Button(Localization.LOC_KITTOPIATECH_PQSEDITOR_ADD_OCEAN, () => { // Generate the PQS object GameObject gameObject = new GameObject("Ocean"); gameObject.layer = Constants.GameLayers.LocalSpace; PQS ocean = gameObject.AddComponent <PQS>(); // Setup materials PSystemBody Body = Utility.FindBody(Injector.StockSystemPrefab.rootBody, "Laythe"); foreach (PQS oc in Body.pqsVersion.GetComponentsInChildren <PQS>(true)) { if (oc.name != "LaytheOcean") { continue; } // Copying Laythes Ocean-properties Utility.CopyObjectFields <PQS>(oc, ocean); } // Load our new Material into the PQS ocean.surfaceMaterial = new PQSOceanSurfaceQuadLoader(ocean.surfaceMaterial); ocean.surfaceMaterial.name = Guid.NewGuid().ToString(); // Load fallback material into the PQS ocean.fallbackMaterial = new PQSOceanSurfaceQuadFallbackLoader(ocean.fallbackMaterial); ocean.fallbackMaterial.name = Guid.NewGuid().ToString(); // Create the UV planet relative position GameObject mod = new GameObject("_Material_SurfaceQuads"); mod.transform.parent = gameObject.transform; PQSMod_UVPlanetRelativePosition uvs = mod.AddComponent <PQSMod_UVPlanetRelativePosition>(); uvs.sphere = ocean; uvs.requirements = PQS.ModiferRequirements.Default; uvs.modEnabled = true; uvs.order = 999999; // Create the AerialPerspective Material AerialPerspectiveMaterial mat = new AerialPerspectiveMaterial(); mat.Create(ocean); // Create the OceanFX OceanFX oceanFX = new OceanFX(); oceanFX.Create(ocean); // Apply the Ocean ocean.transform.parent = Current.pqsController.transform; // Add the ocean PQS to the secondary renders of the CelestialBody Transform PQSMod_CelestialBodyTransform transform = Current.pqsController.GetComponentsInChildren <PQSMod_CelestialBodyTransform>(true).FirstOrDefault(mod_ => mod_.transform.parent == Current.pqsController.transform); transform.planetFade.secondaryRenderers.Add(ocean.gameObject); typeof(PQS).GetField("_childSpheres", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(Current.pqsController, null); // Names! ocean.name = Current.pqsController.name + "Ocean"; ocean.gameObject.name = Current.pqsController.name + "Ocean"; ocean.transform.name = Current.pqsController.name + "Ocean"; // Set up the ocean PQS ocean.parentSphere = Current.pqsController; ocean.transform.position = Current.pqsController.transform.position; ocean.transform.localPosition = Vector3.zero; ocean.radius = Current.Radius; }, new Rect(20, index * distance + 10, 350, 20)); } else { Button(Localization.LOC_KITTOPIATECH_PQSEDITOR_REMOVE_OCEAN, () => { // Find atmosphere the ocean PQS PQS ocean = Current.pqsController.GetComponentsInChildren <PQS>(true).First(pqs => pqs != Current.pqsController); PQSMod_CelestialBodyTransform cbt = Current.pqsController.GetComponentsInChildren <PQSMod_CelestialBodyTransform>(true).First(); // Destroy the ocean PQS (this could be bad - destroying the secondary fades...) cbt.planetFade.secondaryRenderers.Remove(ocean.gameObject); typeof(PQS).GetField("_childSpheres", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(Current.pqsController, null); cbt.secondaryFades = new PQSMod_CelestialBodyTransform.AltitudeFade[0]; ocean.transform.parent = null; UnityEngine.Object.Destroy(ocean); }, new Rect(20, index * distance + 10, 350, 20)); } // End Scroll EndScrollView(); } // Mode PQS if (_mode == Modes.PQS) { // Scroll BeginScrollView(250, Utils.GetScrollSize <PQS>() + Utils.GetScrollSize <HazardousOcean>() + distance * 1, 20); // Index index = 0; // Render the PQS RenderObject(_sphere); // If it is an ocean, create an Hazardous Ocean button if (PQSOceanSurfaceQuad.UsesSameShader(_sphere.surfaceMaterial)) { Label("hazardousOcean"); index--; if (_sphere.GetComponent <HazardousOcean>() != null) { Button(Localization.LOC_KITTOPIATECH_EDIT, () => { UIController.Instance.SetEditedObject(KittopiaWindows.Curve, _sphere.GetComponent <HazardousOcean>().heatCurve ?? new FloatCurve(), c => _sphere.GetComponent <HazardousOcean>().heatCurve = c); UIController.Instance.EnableWindow(KittopiaWindows.Curve); }, new Rect(200, index * distance + 10, 75, 20)); index--; Button(Localization.LOC_KITTOPIATECH_REMOVE, () => UnityEngine.Object.DestroyImmediate(_sphere.GetComponent <HazardousOcean>()), new Rect(285, index * distance + 10, 75, 20)); } else { Button(Localization.LOC_KITTOPIATECH_PQSEDITOR_ADD_HAZOCEAN, () => _sphere.gameObject.AddComponent <HazardousOcean>(), new Rect(200, index * distance + 10, 170, 20)); } } index++; // Rebuild Button(Localization.LOC_KITTOPIATECH_PQSEDITOR_REBUILD, () => _sphere.RebuildSphere()); // End Scroll EndScrollView(); } // Mode PQSMod if (_mode == Modes.PQSMod) { // Scroll BeginScrollView(250, Utils.GetScrollSize(_mod.GetType()) + distance * 5, 20); // Index index = 0; // Render the PQS RenderObject(_mod); index++; // Rebuild Button(Localization.LOC_KITTOPIATECH_PQSEDITOR_REBUILD, () => _sphere.RebuildSphere()); // Remove Button(Localization.LOC_KITTOPIATECH_PQSEDITOR_REMOVE_MOD, () => { _mod.sphere = null; UnityEngine.Object.Destroy(_mod); _mod = null; // Hack _sphere.SetupExternalRender(); _sphere.CloseExternalRender(); _mode = Modes.List; }); // End Scroll EndScrollView(); } // Mode AddPQSMod if (_mode == Modes.AddMod) { // Get all PQSMod types List <Type> types = Parser.ModTypes.Where(t => t.IsSubclassOf(typeof(PQSMod))).ToList(); // Begin Scroll BeginScrollView(250, types.Count * distance + 10, 20); // Index index = 0; // Render the possible types foreach (Type t in types) { Button(t.FullName, () => { // Hack^6 GameObject pqsModObject = new GameObject(t.Name); pqsModObject.transform.parent = Current.pqsController.transform; PQSMod mod = pqsModObject.AddComponent(t) as PQSMod; mod.sphere = Current.pqsController; if (t == typeof(PQSMod_VoronoiCraters)) { PQS mun = Utility.FindBody(Injector.StockSystemPrefab.rootBody, "Mun").pqsVersion; PQSMod_VoronoiCraters craters = mun.GetComponentsInChildren <PQSMod_VoronoiCraters>()[0]; PQSMod_VoronoiCraters nc = pqsModObject.GetComponentsInChildren <PQSMod_VoronoiCraters>()[0]; nc.craterColourRamp = craters.craterColourRamp; nc.craterCurve = craters.craterCurve; nc.jitterCurve = craters.jitterCurve; } else if (t == typeof(PQSMod_VertexPlanet)) { PQSMod_VertexPlanet vp = mod as PQSMod_VertexPlanet; vp.landClasses = new [] { new PQSMod_VertexPlanet.LandClass("Class", 0, 1, Color.black, Color.white, 0) }; vp.continental = new PQSMod_VertexPlanet.SimplexWrapper(0, 0, 0, 0); vp.continentalRuggedness = new PQSMod_VertexPlanet.SimplexWrapper(0, 0, 0, 0); vp.continentalSharpness = new PQSMod_VertexPlanet.NoiseModWrapper(0, 0, 0, 0); vp.continentalSharpnessMap = new PQSMod_VertexPlanet.SimplexWrapper(0, 0, 0, 0); vp.terrainType = new PQSMod_VertexPlanet.SimplexWrapper(0, 0, 0, 0); } else if (t == typeof(PQSMod_HeightColorMap)) { (mod as PQSMod_HeightColorMap).landClasses = new [] { new PQSMod_HeightColorMap.LandClass("Class", 0, 1, Color.black, Color.white, 0) }; } else if (t == typeof(PQSMod_HeightColorMap2)) { (mod as PQSMod_HeightColorMap2).landClasses = new[] { new PQSMod_HeightColorMap2.LandClass("Class", 0, 1, Color.black, Color.white, 0) }; } else if (t == typeof(PQSMod_HeightColorMapNoise)) { (mod as PQSMod_HeightColorMapNoise).landClasses = new[] { new PQSMod_HeightColorMapNoise.LandClass("Class", 0, 1, Color.black, Color.white, 0) }; } else if (t == typeof(PQSLandControl)) { PQSLandControl lc = mod as PQSLandControl; lc.altitudeSimplex = new Simplex(); lc.scatters = new PQSLandControl.LandClassScatter[0]; lc.landClasses = new [] { new PQSLandControl.LandClass() { altitudeRange = new PQSLandControl.LerpRange(), coverageSimplex = new Simplex(), longitudeRange = new PQSLandControl.LerpRange(), latitudeDoubleRange = new PQSLandControl.LerpRange(), latitudeRange = new PQSLandControl.LerpRange(), scatter = new PQSLandControl.LandClassScatterAmount[0] } }; lc.latitudeSimplex = new Simplex(); lc.longitudeSimplex = new Simplex(); } // Edit the mod _mod = mod; _sphere = mod.sphere; _mode = Modes.PQSMod; }, new Rect(20, index * distance + 10, 350, 20)); } // End Scroll EndScrollView(); } }
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); }
/// <summary> /// Generate the scaled space Textures using PQS in a Coroutine /// </summary> public static IEnumerator GeneratePQSMaps(CelestialBody body, Boolean transparentMaps, ExportMode mode) { // Get time DateTime now = DateTime.Now; // Get PQS PQS pqs = body.pqsController; pqs.isBuildingMaps = true; pqs.isFakeBuild = true; // Get the mods Action <PQS.VertexBuildData> modOnVertexBuildHeight = (Action <PQS.VertexBuildData>)Delegate.CreateDelegate( typeof(Action <PQS.VertexBuildData>), pqs, typeof(PQS).GetMethod("Mod_OnVertexBuildHeight", BindingFlags.Instance | BindingFlags.NonPublic)); Action <PQS.VertexBuildData> modOnVertexBuild = (Action <PQS.VertexBuildData>)Delegate.CreateDelegate( typeof(Action <PQS.VertexBuildData>), pqs, typeof(PQS).GetMethod("Mod_OnVertexBuild", BindingFlags.Instance | BindingFlags.NonPublic)); PQSMod[] mods = pqs.GetComponentsInChildren <PQSMod>().Where(m => m.sphere == pqs && m.modEnabled).ToArray(); // Create the Textures Texture2D colorMap = new Texture2D(pqs.mapFilesize, pqs.mapFilesize / 2, TextureFormat.ARGB32, true); Texture2D heightMap = new Texture2D(pqs.mapFilesize, pqs.mapFilesize / 2, TextureFormat.RGB24, true); // Arrays Color[] colorMapValues = new Color[pqs.mapFilesize * (pqs.mapFilesize / 2)]; Color[] heightMapValues = new Color[pqs.mapFilesize * (pqs.mapFilesize / 2)]; // Stuff ScreenMessage message = ScreenMessages.PostScreenMessage("Generating Planet-Maps", Single.MaxValue, ScreenMessageStyle.UPPER_CENTER); // Wait a some time yield return(null); // Loop through the pixels for (int y = 0; y < (pqs.mapFilesize / 2); y++) { for (int x = 0; x < pqs.mapFilesize; x++) { // Update Message Double percent = ((double)((y * pqs.mapFilesize) + x) / ((pqs.mapFilesize / 2) * pqs.mapFilesize)) * 100; while (CanvasUpdateRegistry.IsRebuildingLayout()) { Thread.Sleep(10); } message.textInstance.text.text = "Generating Planet-Maps: " + percent.ToString("0.00") + "%"; // Create a VertexBuildData PQS.VertexBuildData data = new PQS.VertexBuildData { directionFromCenter = (QuaternionD.AngleAxis((360d / pqs.mapFilesize) * x, Vector3d.up) * QuaternionD.AngleAxis(90d - (180d / (pqs.mapFilesize / 2)) * y, Vector3d.right)) * Vector3d.forward, vertHeight = pqs.radius }; // Build from the Mods double height = Double.MinValue; if (mode != ExportMode.COLOR) { modOnVertexBuildHeight(data); // Adjust the height height = (data.vertHeight - pqs.radius) * (1d / pqs.mapMaxHeight); if (height < 0) { height = 0; } else if (height > 1) { height = 1; } // Set the Pixels heightMapValues[(y * pqs.mapFilesize) + x] = new Color((Single)height, (Single)height, (Single)height); } if (mode == ExportMode.COLOR || mode == ExportMode.ALL) { modOnVertexBuild(data); // Adjust the Color Color color = data.vertColor; if (!pqs.mapOcean) { color.a = 1f; } else if (height > pqs.mapOceanHeight) { color.a = transparentMaps ? 0f : 1f; } else if (mode == ExportMode.COLOR) { color.a = 1f; } else { color = pqs.mapOceanColor.A(1f); } // Set the Pixels colorMapValues[(y * pqs.mapFilesize) + x] = color; } } yield return(null); } // Apply the maps if (mode == ExportMode.COLOR || mode == ExportMode.ALL) { colorMap.SetPixels(colorMapValues); colorMap.Apply(); } if (mode != ExportMode.COLOR) { heightMap.SetPixels(heightMapValues); } yield return(null); // Close the Renderer pqs.isBuildingMaps = false; pqs.isFakeBuild = false; // Serialize them to disk string path = KSPUtil.ApplicationRootPath + "/GameData/KittopiaTech/Textures/" + body.name + "/"; Directory.CreateDirectory(path); if (mode == ExportMode.COLOR || mode == ExportMode.ALL) { File.WriteAllBytes(path + body.name + "_Color.png", colorMap.EncodeToPNG()); // Apply them to the ScaledVersion body.scaledBody.GetComponent <MeshRenderer>().material.SetTexture("_MainTex", colorMap); } if (mode != ExportMode.COLOR) { File.WriteAllBytes(path + body.name + "_Height.png", heightMap.EncodeToPNG()); } if (mode == ExportMode.HEIGHTNORMAL || mode == ExportMode.ALL) { // Bump to Normal Map Texture2D normalMap = Utility.BumpToNormalMap(heightMap, UIController.NormalStrength); File.WriteAllBytes(path + body.name + "_Normal.png", normalMap.EncodeToPNG()); // Apply them to the ScaledVersion body.scaledBody.GetComponent <MeshRenderer>().material.SetTexture("_BumpMap", normalMap); } yield return(null); // Declare that we're done ScreenMessages.RemoveMessage(message); ScreenMessages.PostScreenMessage("Operation completed in: " + (DateTime.Now - now).TotalMilliseconds + " ms", 2f, ScreenMessageStyle.UPPER_CENTER); }
/// <summary> /// Find quads that are near a transform /// </summary> public static PQ[] FindNearbyQuads(PQS pqsVersion, Vector3d position, Int32 count) { IEnumerable<PQ> quads = pqsVersion.GetComponentsInChildren<PQ>(true); quads = quads.OrderBy(q => Vector3.Distance(q.quadTransform.position, position)).Take(count); return quads.ToArray(); }
// Generate the scaled space mesh using PQS (all results use scale of 1) public static Mesh ComputeScaledSpaceMesh(CelestialBody body, PQS pqsVersion) { // We need to get the body for Jool (to steal it's mesh) const Double rScaledJool = 1000.0f; Double rMetersToScaledUnits = (Single)(rScaledJool / body.Radius); // Generate a duplicate of the Jool mesh Mesh mesh = DuplicateMesh(Templates.ReferenceGeosphere); // If this body has a PQS, we can create a more detailed object if (pqsVersion != null) { // Find the PQS mods and enable the PQS-sphere IEnumerable <PQSMod> mods = pqsVersion.GetComponentsInChildren <PQSMod>(true).Where(m => m.modEnabled).OrderBy(m => m.order); foreach (PQSMod flatten in mods.Where(m => m is PQSMod_FlattenArea)) { flatten.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).First(f => f.FieldType == typeof(Boolean)).SetValue(flatten, true); } pqsVersion.isBuildingMaps = true; // If we were able to find PQS mods if (mods.Any()) { // Generate the PQS modifications Vector3[] vertices = mesh.vertices; for (Int32 i = 0; i < mesh.vertexCount; i++) { // Get the UV coordinate of this vertex Vector2 uv = mesh.uv[i]; // Since this is a geosphere, normalizing the vertex gives the direction from center center Vector3 direction = vertices[i]; direction.Normalize(); // Build the vertex data object for the PQS mods PQS.VertexBuildData vertex = new PQS.VertexBuildData(); vertex.directionFromCenter = direction; vertex.vertHeight = body.Radius; vertex.u = uv.x; vertex.v = uv.y; // Build from the PQS foreach (PQSMod mod in mods) { mod.OnVertexBuildHeight(vertex); } // Check for sea level if (body.ocean && vertex.vertHeight < body.Radius) { vertex.vertHeight = body.Radius; } // Adjust the displacement vertices[i] = direction * (Single)(vertex.vertHeight * rMetersToScaledUnits); } mesh.vertices = vertices; mesh.RecalculateNormals(); mesh.RecalculateBounds(); } // Cleanup pqsVersion.isBuildingMaps = false; } // Return the generated scaled space mesh return(mesh); }
// Generate the scaled space mesh using PQS (all results use scale of 1) public static Mesh ComputeScaledSpaceMesh(CelestialBody body, PQS pqs) { // We need to get the body for Jool (to steal it's mesh) const Double rScaledJool = 1000.0f; Double rMetersToScaledUnits = (Single)(rScaledJool / body.Radius); // Generate a duplicate of the Jool mesh Mesh mesh = DuplicateMesh(Templates.ReferenceGeosphere); Logger.Active.Log(body); Logger.Active.Log(pqs); Logger.Active.Log(body.pqsController); // If this body has a PQS, we can create a more detailed object if (pqs != null) { // first we enable all maps OnDemandStorage.EnableBody(body.bodyName); // The game object the PQS is attached to GameObject pqsVersionGameObject = null; if (Injector.IsInPrefab) { // In order to generate the scaled space we have to enable the mods. Since this is // a prefab they don't get disabled as kill game performance. To resolve this we // clone the PQS, use it, and then delete it when done pqsVersionGameObject = UnityEngine.Object.Instantiate(pqs.gameObject); } else { // At runtime we simply use the PQS that is active pqsVersionGameObject = pqs.gameObject; } PQS pqsVersion = pqsVersionGameObject.GetComponent <PQS>(); // Load the PQS of the ocean PQS pqsOcean = pqs.ChildSpheres?.FirstOrDefault(); // Deactivate blacklisted Mods Type[] blacklist = { typeof(PQSMod_OnDemandHandler) }; foreach (PQSMod mod in pqsVersion.GetComponentsInChildren <PQSMod>(true) .Where(m => m.enabled && blacklist.Contains(m.GetType()))) { mod.modEnabled = false; } // Find the PQS mods and enable the PQS-sphere PQSMod[] mods = pqsVersion.GetComponentsInChildren <PQSMod>(true) .Where(m => m.modEnabled && m.transform.parent == pqsVersion.transform).OrderBy(m => m.order).ToArray(); foreach (PQSMod flatten in mods.Where(m => m is PQSMod_FlattenArea)) { flatten.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .First(f => f.FieldType == typeof(Boolean)).SetValue(flatten, true); } Logger.Active.Log(mods.Length); // Do the same for the ocean PQSMod[] oceanMods = new PQSMod[0]; if (pqsOcean != null) { oceanMods = pqsOcean.GetComponentsInChildren <PQSMod>(true) .Where(m => m.modEnabled && m.transform.parent == pqsOcean.transform).OrderBy(m => m.order).ToArray(); foreach (PQSMod flatten in oceanMods.Where(m => m is PQSMod_FlattenArea)) { flatten.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .First(f => f.FieldType == typeof(Boolean)).SetValue(flatten, true); } pqsOcean.StartUpSphere(); pqsOcean.isBuildingMaps = true; } pqsVersion.StartUpSphere(); pqsVersion.isBuildingMaps = true; // If we were able to find PQS mods if (mods.Any()) { // Generate the PQS modifications Vector3[] vertices = mesh.vertices; for (Int32 i = 0; i < mesh.vertexCount; i++) { // Get the UV coordinate of this vertex Vector2 uv = mesh.uv[i]; // Since this is a geosphere, normalizing the vertex gives the direction from center center Vector3 direction = vertices[i]; direction.Normalize(); // Build the vertex data object for the PQS mods PQS.VertexBuildData vertex = new PQS.VertexBuildData(); vertex.directionFromCenter = direction; vertex.vertHeight = body.Radius; vertex.u = uv.x; vertex.v = uv.y; // Build from the PQS foreach (PQSMod mod in mods) { mod.OnVertexBuildHeight(vertex); } // Check for sea level if (pqsOcean != null) { // Build the vertex data object for the ocean PQS.VertexBuildData vertexOcean = new PQS.VertexBuildData(); vertexOcean.directionFromCenter = direction; vertexOcean.vertHeight = body.Radius; vertexOcean.u = uv.x; vertexOcean.v = uv.y; // Build from the PQS foreach (PQSMod mod in oceanMods) { mod.OnVertexBuildHeight(vertexOcean); } vertex.vertHeight = Math.Max(vertex.vertHeight, vertexOcean.vertHeight); } // Adjust the displacement vertices[i] = direction * (Single)(vertex.vertHeight * rMetersToScaledUnits); } mesh.vertices = vertices; mesh.RecalculateNormals(); mesh.RecalculateBounds(); } // Cleanup if (pqsOcean != null) { pqsOcean.isBuildingMaps = false; pqsOcean.DeactivateSphere(); } pqsVersion.isBuildingMaps = false; pqsVersion.DeactivateSphere(); // If we are working with a copied PQS, clean it up if (Injector.IsInPrefab) { UnityEngine.Object.Destroy(pqsVersionGameObject); } OnDemandStorage.DisableBody(body.bodyName); } // Return the generated scaled space mesh return(mesh); }
public static T[] GetMods <T>(PQS sphere) where T : PQSMod { return(sphere.GetComponentsInChildren <T>(true).Where(m => m.transform.parent == sphere.transform).ToArray()); }
/// <summary> /// Writes a PQS to a new config node /// </summary> public static void WritePQSToConfigNode(PQS pqsVersion, ref ConfigNode body, bool ocean) { ConfigNode pqs = null; if (!ocean) { CelestialBody cb = pqsVersion.GetComponentInParent <CelestialBody>(); PQSLoader pqsLoader = new PQSLoader(cb); pqs = WriteObjectToConfigNode("PQS", ref body, pqsLoader); WriteObjectToConfigNode("Material", ref pqs, pqsLoader.surfaceMaterial); WriteObjectToConfigNode("FallbackMaterial", ref pqs, pqsLoader.fallbackMaterial); if (pqsLoader.physicsMaterial.Value != null) { WriteObjectToConfigNode("PhysicsMaterial", ref pqs, pqsLoader.physicsMaterial); } } else { CelestialBody cb = pqsVersion.parentSphere.GetComponentInParent <CelestialBody>(); OceanLoader oceanLoader = new OceanLoader(cb); pqs = WriteObjectToConfigNode("Ocean", ref body, oceanLoader); pqs.AddValue("ocean", pqsVersion.parentSphere.mapOcean && cb.ocean); pqs.AddValue("oceanColor", pqsVersion.parentSphere.mapOceanColor); pqs.AddValue("oceanHeight", pqsVersion.parentSphere.mapOceanHeight); pqs.AddValue("density", cb.oceanDensity); WriteObjectToConfigNode("Material", ref pqs, oceanLoader.surfaceMaterial); WriteObjectToConfigNode("FallbackMaterial", ref pqs, oceanLoader.fallbackMaterial); WriteObjectToConfigNode("Fog", ref pqs, new FogLoader(Part.GetComponentUpwards <CelestialBody>(pqsVersion.gameObject))); if (pqsVersion.gameObject.GetComponent <HazardousOcean>() != null) { pqsVersion.gameObject.GetComponent <HazardousOcean>().heatCurve.Save(pqs.AddNode("HazardousOcean")); } } // Mods IEnumerable <PQSMod> mods = pqsVersion.GetComponentsInChildren <PQSMod>(true).Where(m => (ocean || m.sphere == pqsVersion) && !(m is PQSCity) && !(m is PQSCity2)); // Get all loaded types IEnumerable <Type> types = AssemblyLoader.loadedAssemblies.SelectMany(a => a.assembly.GetTypes()); if (mods.Count() != 0) { ConfigNode modsNode = pqs.AddNode("Mods"); foreach (PQSMod Mod in mods) { // Fix PQSMods PQSMod mod = Mod; Type loaderType = types.FirstOrDefault(t => t.Name == Mod.GetType().Name.Replace("PQSMod_", "").Replace("PQS", "")); // No loader if (loaderType == null) { continue; } // Create the loader object loader = Activator.CreateInstance(loaderType); // Reflection, because C# being silly... :/ PropertyInfo info = loaderType.GetProperty("mod"); if (info == null) { continue; } info.SetValue(loader, mod, null); // Load ConfigNode modNode = WriteObjectToConfigNode(loaderType.Name, ref modsNode, loader); IEnumerable <PQSMod> existingMods = pqsVersion.GetComponentsInChildren <PQSMod>(true).Where(m => m.GetType() == mod.GetType() && m.sphere == pqsVersion && m.name == mod.name); modNode.AddValue("index", existingMods.ToList().IndexOf(mod)); // Submods PQSMod_HeightColorMap hcm = mod as PQSMod_HeightColorMap; if (hcm?.landClasses != null) { ConfigNode landClasses = modNode.AddNode("LandClasses"); foreach (PQSMod_HeightColorMap.LandClass landClass in hcm.landClasses) { WriteObjectToConfigNode("Class", ref landClasses, new HeightColorMap.LandClassLoader(landClass)); } } PQSMod_HeightColorMap2 hcm2 = mod as PQSMod_HeightColorMap2; if (hcm2?.landClasses != null) { ConfigNode landClasses = modNode.AddNode("LandClasses"); foreach (PQSMod_HeightColorMap2.LandClass landClass in hcm2.landClasses) { WriteObjectToConfigNode("Class", ref landClasses, new HeightColorMap2.LandClassLoader(landClass)); } } PQSMod_HeightColorMapNoise hcmNoise = mod as PQSMod_HeightColorMapNoise; if (hcmNoise?.landClasses != null) { ConfigNode landClasses = modNode.AddNode("LandClasses"); foreach (PQSMod_HeightColorMapNoise.LandClass landClass in hcmNoise.landClasses) { WriteObjectToConfigNode("Class", ref landClasses, new HeightColorMapNoise.LandClassLoader(landClass)); } } if (mod is PQSLandControl) { PQSLandControl lc = mod as PQSLandControl; if (lc.altitudeSimplex != null) { KopernicusSimplexWrapper lcaltsimpwrap = new KopernicusSimplexWrapper(lc.altitudeBlend, lc.altitudeOctaves, lc.altitudePersistance, lc.altitudeFrequency); lcaltsimpwrap.seed = lc.altitudeSeed; WriteObjectToConfigNode("altitudeSimplex", ref modNode, new VertexPlanet.SimplexLoader(lcaltsimpwrap)); } if (lc.latitudeSimplex != null) { KopernicusSimplexWrapper lclatsimpwrap = new KopernicusSimplexWrapper(lc.latitudeBlend, lc.latitudeOctaves, lc.latitudePersistance, lc.latitudeFrequency); lclatsimpwrap.seed = lc.latitudeSeed; WriteObjectToConfigNode("latitudeSimplex", ref modNode, new VertexPlanet.SimplexLoader(lclatsimpwrap)); } if (lc.longitudeSimplex != null) { KopernicusSimplexWrapper lclongsimpwrap = new KopernicusSimplexWrapper(lc.longitudeBlend, lc.longitudeOctaves, lc.longitudePersistance, lc.longitudeFrequency); lclongsimpwrap.seed = lc.longitudeSeed; WriteObjectToConfigNode("longitudeSimplex", ref modNode, new VertexPlanet.SimplexLoader(lclongsimpwrap)); } if (lc.landClasses != null) { ConfigNode landClasses = modNode.AddNode("landClasses"); foreach (PQSLandControl.LandClass landClass in lc.landClasses) { ConfigNode lcNode = WriteObjectToConfigNode("Class", ref landClasses, new LandControl.LandClassLoader(landClass)); WriteObjectToConfigNode("altitudeRange", ref lcNode, new LandControl.LerpRangeLoader(landClass.altitudeRange)); KopernicusSimplexWrapper lccovsimpwrap = new KopernicusSimplexWrapper(landClass.coverageBlend, landClass.coverageOctaves, landClass.coveragePersistance, landClass.coverageFrequency); lccovsimpwrap.seed = landClass.coverageSeed; WriteObjectToConfigNode("coverageSimplex", ref lcNode, new VertexPlanet.SimplexLoader(lccovsimpwrap)); WriteObjectToConfigNode("latitudeDoubleRange", ref lcNode, new LandControl.LerpRangeLoader(landClass.latitudeDoubleRange)); WriteObjectToConfigNode("latitudeRange", ref lcNode, new LandControl.LerpRangeLoader(landClass.latitudeRange)); WriteObjectToConfigNode("longitudeRange", ref lcNode, new LandControl.LerpRangeLoader(landClass.longitudeRange)); KopernicusSimplexWrapper lcnoisesimpwrap = new KopernicusSimplexWrapper(landClass.noiseBlend, landClass.noiseOctaves, landClass.noisePersistance, landClass.noiseFrequency); lcnoisesimpwrap.seed = landClass.noiseSeed; WriteObjectToConfigNode("noiseSimplex", ref lcNode, new VertexPlanet.SimplexLoader(lcnoisesimpwrap)); if (landClass.scatter != null) { ConfigNode amount = lcNode.AddNode("scatters"); foreach (PQSLandControl.LandClassScatterAmount scatterAmount in landClass.scatter) { WriteObjectToConfigNode("Scatter", ref amount, new LandControl.LandClassScatterAmountLoader(scatterAmount)); } } } } if (lc.scatters != null) { ConfigNode scatters = modNode.AddNode("scatters"); foreach (PQSLandControl.LandClassScatter scatter in lc.scatters) { LandControl.LandClassScatterLoader classLoader = new LandControl.LandClassScatterLoader(scatter); if (scatter.material.shader == new NormalDiffuse().shader) { classLoader.customMaterial = new NormalDiffuseLoader(scatter.material); } else if (scatter.material.shader == new NormalBumped().shader) { classLoader.customMaterial = new NormalBumpedLoader(scatter.material); } else if (scatter.material.shader == new NormalDiffuseDetail().shader) { classLoader.customMaterial = new NormalDiffuseDetailLoader(scatter.material); } else if (scatter.material.shader == new DiffuseWrapLoader().shader) { classLoader.customMaterial = new DiffuseWrapLoader(scatter.material); } else if (scatter.material.shader == new AlphaTestDiffuse().shader) { classLoader.customMaterial = new AlphaTestDiffuseLoader(scatter.material); } else if (scatter.material.shader == new AerialTransCutout().shader) { classLoader.customMaterial = new AerialTransCutoutLoader(scatter.material); } ConfigNode scatterNode = WriteObjectToConfigNode("Scatter", ref scatters, classLoader); WriteObjectToConfigNode("Material", ref scatterNode, classLoader.customMaterial); scatterNode.AddNode("Experiment"); } } } if (mod is PQSMod_VertexPlanet) { PQSMod_VertexPlanet vp = mod as PQSMod_VertexPlanet; WriteObjectToConfigNode("ContinentalSimplex", ref modNode, new PQSMod_VertexPlanet.SimplexWrapper(vp.continental)); WriteObjectToConfigNode("RuggednessSimplex", ref modNode, new PQSMod_VertexPlanet.SimplexWrapper(vp.continentalRuggedness)); WriteObjectToConfigNode("SharpnessNoise", ref modNode, new PQSMod_VertexPlanet.NoiseModWrapper(vp.continentalSharpness)); WriteObjectToConfigNode("SharpnessSimplexMap", ref modNode, new PQSMod_VertexPlanet.SimplexWrapper(vp.continentalSharpnessMap)); WriteObjectToConfigNode("TerrainTypeSimplex", ref modNode, new PQSMod_VertexPlanet.SimplexWrapper(vp.terrainType)); if (vp.landClasses != null) { ConfigNode landClasses = modNode.AddNode("LandClasses"); foreach (PQSMod_VertexPlanet.LandClass landClass in vp.landClasses) { ConfigNode classNode = WriteObjectToConfigNode("Class", ref landClasses, new VertexPlanet.LandClassLoader(landClass)); WriteObjectToConfigNode("SimplexNoiseMap", ref classNode, new PQSMod_VertexPlanet.SimplexWrapper(landClass.colorNoiseMap)); } } } if (!(mod is PQSMod_OceanFX)) { continue; } List <Texture2DParser> wm = (loader as OceanFX).watermain; ConfigNode watermain = modNode.AddNode("Watermain"); foreach (Texture2DParser texture in wm) { watermain.AddValue("waterTex-" + wm.ToList().IndexOf(texture), texture.Value.name); } } } }
/// <summary> /// Will remove all mods of given types (or all, if types null) /// </summary> /// <param name="types">If null, will remove all mods except blacklisted mods</param> /// <param name="p">PQS to remove from</param> /// <param name="blacklist">list of mod types to not remove (optional)</param> public static void RemoveModsOfType(List <Type> types, PQS p, List <Type> blacklist = null) { Logger.Active.Log("Removing mods from pqs " + p.name); List <PQSMod> cpMods = p.GetComponentsInChildren <PQSMod>(true).ToList(); Boolean addTypes = types == null; if (addTypes) { types = new List <Type>(); } if (blacklist == null) { Logger.Active.Log("Creating blacklist"); blacklist = new List <Type>(); if (!types.Contains(typeof(PQSMod_CelestialBodyTransform))) { blacklist.Add(typeof(PQSMod_CelestialBodyTransform)); } if (!types.Contains(typeof(PQSMod_MaterialSetDirection))) { blacklist.Add(typeof(PQSMod_MaterialSetDirection)); } if (!types.Contains(typeof(PQSMod_UVPlanetRelativePosition))) { blacklist.Add(typeof(PQSMod_UVPlanetRelativePosition)); } if (!types.Contains(typeof(PQSMod_QuadMeshColliders))) { blacklist.Add(typeof(PQSMod_QuadMeshColliders)); } Logger.Active.Log("Blacklist count = " + blacklist.Count); } if (addTypes) { Logger.Active.Log("Adding all found PQSMods in pqs " + p.name); foreach (PQSMod m in cpMods) { Type mType = m.GetType(); if (types.Contains(mType) || blacklist.Contains(mType)) { continue; } Logger.Active.Log("Adding to remove list: " + mType); types.Add(mType); } } List <GameObject> toCheck = new List <GameObject>(); foreach (Type mType in types) { List <PQSMod> mods = cpMods.Where(m => m.GetType() == mType).ToList(); foreach (PQSMod delMod in mods) { if (delMod == null) { continue; } Logger.Active.Log("Removed mod " + mType); if (!toCheck.Contains(delMod.gameObject)) { toCheck.Add(delMod.gameObject); } delMod.sphere = null; switch (delMod) { case PQSCity mod: { PQSCity city = mod; if (city.lod != null) { foreach (PQSCity.LODRange range in city.lod) { if (range.objects != null) { foreach (GameObject o in range.objects) { UnityEngine.Object.DestroyImmediate(o); } } if (range.renderers == null) { continue; } foreach (GameObject o in range.renderers) { UnityEngine.Object.DestroyImmediate(o); } } } break; } case PQSCity2 mod: { PQSCity2 city = mod; if (city.objects != null) { foreach (PQSCity2.LodObject range in city.objects) { if (range.objects == null) { continue; } foreach (GameObject o in range.objects) { UnityEngine.Object.DestroyImmediate(o); } } } break; } } cpMods.Remove(delMod); // If no mod is left, delete the game object too GameObject gameObject = delMod.gameObject; UnityEngine.Object.DestroyImmediate(delMod); PQSMod[] allRemainingMods = gameObject.GetComponentsInChildren <PQSMod>(true); if (allRemainingMods.Length == 0) { UnityEngine.Object.DestroyImmediate(gameObject); } } } }
private static void AddMapSOs(List<MapSO> list, PQS pqs) { PQSMod[] mods = pqs.GetComponentsInChildren<PQSMod>(true) as PQSMod[]; foreach (PQSMod m in mods) { foreach (FieldInfo fi in m.GetType().GetFields()) { // this _should_ get everything derived from it. MapSO val = fi.GetValue(m) as MapSO; if(val != null) if(!list.Contains(val)) list.Add(val); } } }
/// <summary> /// A coroutine that updates the scaled space in the background /// </summary> private IEnumerator UpdateScaledSpace() { // Path to the cache String CacheDirectory = "saves/" + HighLogic.SaveFolder + "/diversity/"; for (Int32 a = 0; a < scaledSpaceUpdate.Count; a++) { // Get the body CelestialBody body = scaledSpaceUpdate[a]; current = body.bodyDisplayName; index = a + 1; // Mesh Directory.CreateDirectory(CacheDirectory + "mesh"); Utility.UpdateScaledMesh(body.scaledBody, body.pqsController, body, CacheDirectory + "mesh/"); // Textures Directory.CreateDirectory(CacheDirectory + "textures/" + body.bodyName); String TextureDirectory = CacheDirectory + "textures/" + body.bodyName + "/"; if (File.Exists(TextureDirectory + "color.png") && File.Exists(TextureDirectory + "normal.png")) { Texture2D colorMap = Utility.LoadTexture(TextureDirectory + "color.png", false, true, true); yield return(null); Texture2D normalMap = Utility.LoadTexture(TextureDirectory + "normal.png", false, true, true); yield return(null); // Apply them to the ScaledVersion body.scaledBody.GetComponent <MeshRenderer>().material.SetTexture("_MainTex", colorMap); body.scaledBody.GetComponent <MeshRenderer>().material.SetTexture("_BumpMap", normalMap); yield return(null); } else { // Get PQS PQS pqs = body.pqsController; pqs.SetupExternalRender(); // Get the mods Action <PQS.VertexBuildData> modOnVertexBuildHeight = (Action <PQS.VertexBuildData>)Delegate.CreateDelegate( typeof(Action <PQS.VertexBuildData>), pqs, typeof(PQS).GetMethod("Mod_OnVertexBuildHeight", BindingFlags.Instance | BindingFlags.NonPublic)); Action <PQS.VertexBuildData> modOnVertexBuild = (Action <PQS.VertexBuildData>)Delegate.CreateDelegate( typeof(Action <PQS.VertexBuildData>), pqs, typeof(PQS).GetMethod("Mod_OnVertexBuild", BindingFlags.Instance | BindingFlags.NonPublic)); PQSMod[] mods = pqs.GetComponentsInChildren <PQSMod>().Where(m => m.sphere == pqs && m.modEnabled).ToArray(); // Create the Textures Texture2D colorMap = new Texture2D(pqs.mapFilesize, pqs.mapFilesize / 2, TextureFormat.ARGB32, true); Texture2D heightMap = new Texture2D(pqs.mapFilesize, pqs.mapFilesize / 2, TextureFormat.RGB24, true); // Arrays Color[] colorMapValues = new Color[pqs.mapFilesize * (pqs.mapFilesize / 2)]; Color[] heightMapValues = new Color[pqs.mapFilesize * (pqs.mapFilesize / 2)]; // Wait a some time yield return(null); // Loop through the pixels for (Int32 y = 0; y < (pqs.mapFilesize / 2); y++) { for (Int32 x = 0; x < pqs.mapFilesize; x++) { // Update Message percent = ((Double)((y * pqs.mapFilesize) + x) / ((pqs.mapFilesize / 2) * pqs.mapFilesize)) * 100; // Create a VertexBuildData PQS.VertexBuildData data = new PQS.VertexBuildData { directionFromCenter = (QuaternionD.AngleAxis((360d / pqs.mapFilesize) * x, Vector3d.up) * QuaternionD.AngleAxis(90d - (180d / (pqs.mapFilesize / 2)) * y, Vector3d.right)) * Vector3d.forward, vertHeight = pqs.radius }; // Build from the Mods modOnVertexBuildHeight(data); modOnVertexBuild(data); // Adjust the height Double height = (data.vertHeight - pqs.radius) * (1d / pqs.mapMaxHeight); if (height < 0) { height = 0; } else if (height > 1) { height = 1; } // Adjust the Color Color color = data.vertColor; if (!pqs.mapOcean) { color.a = 1f; } else if (height > pqs.mapOceanHeight) { color.a = 0f; } else { color = pqs.mapOceanColor.A(1f); } // Set the Pixels colorMapValues[(y * pqs.mapFilesize) + x] = color; heightMapValues[(y * pqs.mapFilesize) + x] = new Color((Single)height, (Single)height, (Single)height); } yield return(null); } // Apply the maps colorMap.SetPixels(colorMapValues); colorMap.Apply(); heightMap.SetPixels(heightMapValues); yield return(null); // Close the Renderer pqs.CloseExternalRender(); // Bump to Normal Map Texture2D normalMap = Utility.BumpToNormalMap(heightMap, 7); // Serialize them to disk File.WriteAllBytes(TextureDirectory + "color.png", colorMap.EncodeToPNG()); File.WriteAllBytes(TextureDirectory + "normal.png", normalMap.EncodeToPNG()); yield return(null); // Apply them to the ScaledVersion body.scaledBody.GetComponent <MeshRenderer>().material.SetTexture("_MainTex", colorMap); body.scaledBody.GetComponent <MeshRenderer>().material.SetTexture("_BumpMap", normalMap); yield return(null); } // OnDemand if (Templates.IsKopernicusInstalled) { Type onDemandType = Templates.Types.FirstOrDefault(t => t.Name == "ScaledSpaceOnDemand"); Component onDemand = body.scaledBody.GetComponent(onDemandType); if (onDemand != null) { FieldInfo texture = onDemandType.GetField("texture"); FieldInfo normals = onDemandType.GetField("normals"); String RelativeDirectory = TextureDirectory.Replace(KSPUtil.ApplicationRootPath, "../"); texture.SetValue(onDemand, RelativeDirectory + "color.png"); normals.SetValue(onDemand, RelativeDirectory + "normal.png"); } } percent = 0; yield return(null); } guiEnabled = false; scaledSpaceUpdate.Clear(); FlightDriver.SetPause(false, false); InputLockManager.RemoveControlLock("planetaryDiversityCache"); }
// Generate the scaled space mesh using PQS (all results use scale of 1) public static Mesh ComputeScaledSpaceMesh(PSystemBody body) { // We need to get the body for Jool (to steal it's mesh) PSystemBody Jool = Utility.FindBody(PSystemManager.Instance.systemPrefab.rootBody, "Jool"); const double rScaledJool = 1000.0f; double rMetersToScaledUnits = (float)(rScaledJool / body.celestialBody.Radius); // Generate a duplicate of the Jool mesh Mesh mesh = Utility.DuplicateMesh(Jool.scaledVersion.GetComponent <MeshFilter> ().sharedMesh); // If this body has a PQS, we can create a more detailed object if (body.pqsVersion != null) { // In order to generate the scaled space we have to enable the mods. Since this is // a prefab they don't get disabled as kill game performance. To resolve this we // clone the PQS, use it, and then delete it when done GameObject pqsVersionGameObject = UnityEngine.Object.Instantiate(body.pqsVersion.gameObject) as GameObject; PQS pqsVersion = pqsVersionGameObject.GetComponent <PQS>(); // Find and enable the PQS mods that modify height IEnumerable <PQSMod> mods = pqsVersion.GetComponentsInChildren <PQSMod>(true).Where(mod => (mod.GetType().ToString().Contains("VertexHeight") || mod.GetType().ToString().Contains("VertexSimplexHeight"))); foreach (PQSMod mod in mods) { mod.OnSetup(); } // If we were able to find PQS mods if (mods.Count() > 0) { // Generate the PQS modifications Vector3[] vertices = mesh.vertices; for (int i = 0; i < mesh.vertexCount; i++) { // Get the UV coordinate of this vertex Vector2 uv = mesh.uv[i]; // Since this is a geosphere, normalizing the vertex gives the direction from center center Vector3 direction = vertices[i]; direction.Normalize(); // Build the vertex data object for the PQS mods PQS.VertexBuildData vertex = new PQS.VertexBuildData(); vertex.directionFromCenter = direction; vertex.vertHeight = body.celestialBody.Radius; vertex.u = uv.x; vertex.v = uv.y; // Build from the PQS foreach (PQSMod mod in mods) { mod.OnVertexBuildHeight(vertex); } // Adjust the displacement vertices [i] = direction * (float)(vertex.vertHeight * rMetersToScaledUnits); } mesh.vertices = vertices; mesh.RecalculateNormals(); mesh.RecalculateBounds(); } // Otherwise log an error else { Debug.LogError("PQS BODY HAS NO PQS MODS"); Debug.LogError("-------- PQS ----------"); Utility.GameObjectWalk(body.pqsVersion.gameObject); Debug.LogError("-----------------------"); } // Cleanup UnityEngine.Object.Destroy(pqsVersionGameObject); } // Return the generated scaled space mesh return(mesh); }
// Constructor for pre-existing PQS public PQSLoader(PQS pqsVersion) { this.pqsVersion = pqsVersion; // Get the required PQS information transform = pqsVersion.GetComponentsInChildren<PQSMod_CelestialBodyTransform> (true).FirstOrDefault (mod => mod.transform.parent == pqsVersion.transform); lightDirection = pqsVersion.GetComponentsInChildren<PQSMod_MaterialSetDirection> (true).FirstOrDefault (mod => mod.transform.parent == pqsVersion.transform); uvs = pqsVersion.GetComponentsInChildren<PQSMod_UVPlanetRelativePosition> (true).FirstOrDefault (mod => mod.transform.parent == pqsVersion.transform); collider = pqsVersion.GetComponentsInChildren<PQSMod_QuadMeshColliders> (true).FirstOrDefault (mod => mod.transform.parent == pqsVersion.transform); // Create physics material editor physicsMaterial = new PhysicsMaterialParser (collider.physicsMaterial); // Clone the surface material of the PQS if (PQSMainOptimised.UsesSameShader(pqsVersion.surfaceMaterial)) { pqsVersion.surfaceMaterial = new PQSMainOptimisedLoader(pqsVersion.surfaceMaterial); if (((PQSMainOptimisedLoader)pqsVersion.surfaceMaterial).globalDensity < 2) ((PQSMainOptimisedLoader)pqsVersion.surfaceMaterial).globalDensity = -8E-06f; } else if (PQSMainShader.UsesSameShader(pqsVersion.surfaceMaterial)) { pqsVersion.surfaceMaterial = new PQSMainShaderLoader(pqsVersion.surfaceMaterial); if (((PQSMainShaderLoader)pqsVersion.surfaceMaterial).globalDensity < 2) ((PQSMainShaderLoader)pqsVersion.surfaceMaterial).globalDensity = -8E-06f; } else if (PQSProjectionAerialQuadRelative.UsesSameShader(pqsVersion.surfaceMaterial)) { pqsVersion.surfaceMaterial = new PQSProjectionAerialQuadRelativeLoader(pqsVersion.surfaceMaterial); if (((PQSProjectionAerialQuadRelativeLoader)pqsVersion.surfaceMaterial).globalDensity < 2) ((PQSProjectionAerialQuadRelativeLoader)pqsVersion.surfaceMaterial).globalDensity = -8E-06f; } else if (PQSProjectionSurfaceQuad.UsesSameShader(pqsVersion.surfaceMaterial)) { pqsVersion.surfaceMaterial = new PQSProjectionSurfaceQuadLoader(pqsVersion.surfaceMaterial); } surfaceMaterial = pqsVersion.surfaceMaterial; surfaceMaterial.name = Guid.NewGuid ().ToString (); // Clone the fallback material of the PQS fallbackMaterial = new PQSProjectionFallbackLoader (pqsVersion.fallbackMaterial); pqsVersion.fallbackMaterial = fallbackMaterial; fallbackMaterial.name = Guid.NewGuid ().ToString (); }
//Initialization public void Start () { m_radius = m_manager.GetRadius (); Rt = (Rt / Rg) * m_radius; RL = (RL / Rg) * m_radius; Rg = m_radius; m_mesh = MeshFactory.MakePlane (2, 2, MeshFactory.PLANE.XY, false, false); m_mesh.bounds = new Bounds (parentCelestialBody.transform.position, new Vector3 (1e8f, 1e8f, 1e8f)); //Inscatter is responsible for the change in the sky color as the sun moves //The raw file is a 4D array of 32 bit floats with a range of 0 to 1.589844 //As there is not such thing as a 4D texture the data is packed into a 3D texture //and the shader manually performs the sample for the 4th dimension m_inscatter = new RenderTexture (RES_MU_S * RES_NU, RES_MU * RES_R, 0, RenderTextureFormat.ARGBHalf); m_inscatter.wrapMode = TextureWrapMode.Clamp; m_inscatter.filterMode = FilterMode.Bilinear; //Transmittance is responsible for the change in the sun color as it moves //The raw file is a 2D array of 32 bit floats with a range of 0 to 1 m_transmit = new RenderTexture (TRANSMITTANCE_W, TRANSMITTANCE_H, 0, RenderTextureFormat.ARGBHalf); m_transmit.wrapMode = TextureWrapMode.Clamp; m_transmit.filterMode = FilterMode.Bilinear; //Irradiance is responsible for the change in the sky color as the sun moves //The raw file is a 2D array of 32 bit floats with a range of 0 to 1 m_irradiance = new RenderTexture (SKY_W, SKY_H, 0, RenderTextureFormat.ARGBHalf); m_irradiance.wrapMode = TextureWrapMode.Clamp; m_irradiance.filterMode = FilterMode.Bilinear; initiateOrRestart (); m_skyMaterialScaled = new Material (ShaderTool.GetMatFromShader2 ("CompiledSkyScaled.shader")); //m_skyMaterialScaled.renderQueue = 2004; m_skyExtinction = new Material (ShaderTool.GetMatFromShader2 ("CompiledSkyExtinction.shader")); //m_skyExtinction.renderQueue = 2002; sunGlare = new Texture2D (512, 512); black = new Texture2D (512, 512); sunGlare.LoadImage (System.IO.File.ReadAllBytes (String.Format ("{0}/{1}", assetDir + m_filePath, "sunglare.png"))); black.LoadImage (System.IO.File.ReadAllBytes (String.Format ("{0}/{1}", assetDir + m_filePath, "black.png"))); sunGlare.wrapMode = TextureWrapMode.Clamp; m_skyMaterialScaled.SetTexture ("_Sun_Glare", sunGlare); InitUniforms (m_skyMaterialScaled); InitUniforms (m_skyExtinction); if (m_manager.GetCore ().render24bitDepthBuffer && !m_manager.GetCore ().d3d9) { m_atmosphereMaterial = ShaderTool.GetMatFromShader2 ("CompiledAtmosphericScatter24bitdepth.shader"); } else { m_atmosphereMaterial = ShaderTool.GetMatFromShader2 ("CompiledAtmosphericScatter.shader"); } CurrentPQS = parentCelestialBody.pqsController; currentPQSMod_CelestialBodyTransform = CurrentPQS.GetComponentsInChildren<PQSMod_CelestialBodyTransform> ()[0]; if (!currentPQSMod_CelestialBodyTransform) { Debug.Log ("[Scatterer] PQSMod_CelestialBodyTransform not found for " + parentCelestialBody.name); } //testPQS = parentCelestialBody.pqsController; // for (int j = 0; j < 10; j++) { // debugSettings[j] = true; // } for (int j = 0; j < 10; j++) { additionalScales [j] = 1f; } skyObject = new GameObject (); skyMF = skyObject.AddComponent < MeshFilter > (); Mesh idmesh = skyMF.mesh; idmesh.Clear (); idmesh = m_mesh; // skyObject.layer = layer; // celestialTransform = ScaledSpace.Instance.scaledSpaceTransforms.Single(t => t.name == parentCelestialBody.name); celestialTransform = ParentPlanetTransform; // skyObject.transform.parent = parentCelestialBody.transform; skyObject.transform.parent = celestialTransform; skyMR = skyObject.AddComponent < MeshRenderer > (); skyMR.sharedMaterial = m_skyMaterialScaled; skyMR.material = m_skyMaterialScaled; skyMR.castShadows = false; skyMR.receiveShadows = false; ///same for skyextinct skyExtinctObject = new GameObject (); skyExtinctMF = skyExtinctObject.AddComponent < MeshFilter > (); idmesh = skyExtinctMF.mesh; idmesh.Clear (); idmesh = m_mesh; // skyExtinctObject.layer = layer; skyExtinctObject.transform.parent = celestialTransform; skyExtinctMR = skyExtinctObject.AddComponent < MeshRenderer > (); skyExtinctMR.sharedMaterial = m_skyExtinction; skyExtinctMR.material = m_skyExtinction; skyExtinctMR.castShadows = false; skyExtinctMR.receiveShadows = false; hp = new SimplePostProcessCube (10000, m_atmosphereMaterial); atmosphereMesh = hp.GameObject; atmosphereMesh.layer = 15; atmosphereMeshrenderer = hp.GameObject.GetComponent < MeshRenderer > (); atmosphereMeshrenderer.material = m_atmosphereMaterial; //celestialBodies = (CelestialBody[]) CelestialBody.FindObjectsOfType(typeof(CelestialBody)); }