Exemple #1
0
        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);
        }
Exemple #2
0
        // 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);
        }