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); }
// 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); }