Пример #1
0
        /// <summary>
        /// Compares two build settings and returns if they are practially different.
        /// </summary>
        public static bool AreDifferent(CSGBuildSettings settings1, CSGBuildSettings settings2)
        {
            if (settings1.GenerateCollisionMeshes != settings2.GenerateCollisionMeshes)
            {
                return(true);
            }
            if (settings1.GenerateTangents != settings2.GenerateTangents)
            {
                return(true);
            }
            if (settings1.OptimizeGeometry != settings2.OptimizeGeometry)
            {
                return(true);
            }
            if (settings1.GenerateLightmapUVs != settings2.GenerateLightmapUVs)
            {
                return(true);
            }

            // Only compare UV unwrap settings if unwrapping is in use
            if (settings1.GenerateLightmapUVs && settings1.GenerateLightmapUVs)
            {
                if (settings1.UnwrapAngleError != settings2.UnwrapAngleError)
                {
                    return(true);
                }

                if (settings1.UnwrapAreaError != settings2.UnwrapAreaError)
                {
                    return(true);
                }

                if (settings1.UnwrapHardAngle != settings2.UnwrapHardAngle)
                {
                    return(true);
                }

                if (settings1.UnwrapPackMargin != settings2.UnwrapPackMargin)
                {
                    return(true);
                }
            }

            if (settings1.DefaultPhysicsMaterial != settings2.DefaultPhysicsMaterial)
            {
                return(true);
            }
            if (settings1.DefaultVisualMaterial != settings2.DefaultVisualMaterial)
            {
                return(true);
            }

            // Don't compare IsBuilt

            // No practical differences found
            return(false);
        }
Пример #2
0
        internal static void BuildCollision(Transform meshGroupHolder,
                                            PolygonEntry[] polygonIndex,
                                            CSGBuildSettings buildSettings,
                                            List <Mesh> collisionMeshDictionary)
        {
            collisionMeshDictionary.Clear();

            if (polygonIndex.Length > 0)
            {
                Mesh           mesh          = new Mesh();
                List <Vector3> positionsList = new List <Vector3>();
                List <Vector3> normalsList   = new List <Vector3>();
                List <Vector2> uvList        = new List <Vector2>();
                List <int>     trianglesList = new List <int>();

                for (int i = 0; i < polygonIndex.Length; i++)
                {
                    if (polygonIndex[i] != null)
                    {
                        int positionOffset = positionsList.Count;
                        int triangleOffset = trianglesList.Count;

                        PolygonEntry polygonEntry = polygonIndex[i];

                        if (PolygonEntry.IsValid(polygonEntry) &&
                            polygonEntry.Positions.Length > 0 &&
                            !polygonEntry.ExcludeFromBuild)    // Skip polygons that weren't built
                        {
                            if (polygonEntry.Positions.Length + positionOffset > MESH_VERTEX_LIMIT)
                            {
                                FinalizeCollisionMesh(meshGroupHolder, mesh, buildSettings, positionsList, normalsList, uvList, trianglesList, collisionMeshDictionary);
                                mesh = new Mesh();
                                positionsList.Clear();
                                normalsList.Clear();
                                uvList.Clear();
                                trianglesList.Clear();
                                positionOffset = 0;
                            }
                            positionsList.AddRange(polygonEntry.Positions);
                            normalsList.AddRange(polygonEntry.Normals);
                            uvList.AddRange(polygonEntry.UV);

                            for (int j = 0; j < polygonEntry.Triangles.Length; j++)
                            {
                                trianglesList.Add(polygonEntry.Triangles[j] + positionOffset);
                            }

                            polygonEntry.BuiltMesh           = mesh;
                            polygonEntry.BuiltVertexOffset   = positionOffset;
                            polygonEntry.BuiltTriangleOffset = triangleOffset;
                        }
                    }
                }
                FinalizeCollisionMesh(meshGroupHolder, mesh, buildSettings, positionsList, normalsList, uvList, trianglesList, collisionMeshDictionary);
            }
        }
Пример #3
0
        internal static BuildStatus Build(List <Brush> brushes,
                                          CSGBuildSettings buildSettings,
                                          CSGBuildContext.BuildContext buildContext,
                                          Transform rootTransform,
                                          MaterialMeshDictionary materialMeshDictionary,
                                          List <Mesh> collisionMeshDictionary,
                                          bool polygonsRemoved,
                                          bool forceRebuild,
                                          Action <float> onProgressChange,
                                          Action <GameObject, Mesh> onFinalizeVisualMesh,
                                          Action <GameObject, Mesh> onFinalizeCollisionMesh,
                                          bool multithreaded)
        {
            CSGFactory.brushes                 = brushes;
            CSGFactory.buildSettings           = buildSettings;
            CSGFactory.buildContext            = buildContext;
            CSGFactory.rootTransform           = rootTransform;
            CSGFactory.materialMeshDictionary  = materialMeshDictionary;
            CSGFactory.collisionMeshDictionary = collisionMeshDictionary;
            CSGFactory.polygonsRemoved         = polygonsRemoved;
            CSGFactory.forceRebuild            = forceRebuild;
            CSGFactory.onProgressChange        = onProgressChange;
            CSGFactory.onFinalizeVisualMesh    = onFinalizeVisualMesh;
            CSGFactory.onFinalizeCollisionMesh = onFinalizeCollisionMesh;

//			DebugExclude.hackyHolder = DebugExclude.GetMetaDataHolder();
//			BrushChunk.ResetNextID();

            if (buildInProgress)
            {
                Debug.LogWarning("Existing build has not completed");
            }

            if (multithreaded)
            {
                readyForFinalize = false;
                buildInProgress  = true;
                ThreadPool.QueueUserWorkItem(CoreBuild, true);
                // FinalizeBuild is called by Tick when CoreBuild is complete
                return(BuildStatus.Started);
            }
            else
            {
                readyForFinalize = false;
                CoreBuild(null);
                bool buildOccurred = FinalizeBuild();
                buildInProgress = false;

                return(buildOccurred ? BuildStatus.Complete : BuildStatus.Unnecessary);
            }
        }
        internal static void FinalizeCollisionMesh(Transform meshGroupHolder,
                                                   Mesh mesh,
                                                   CSGBuildSettings buildSettings,
                                                   List <Vector3> positionsList,
                                                   List <Vector3> normalsList,
                                                   List <Vector2> uvList,
                                                   List <int> trianglesList,
                                                   List <Mesh> collisionMeshDictionary)
        {
            Vector3[] positionsArray = new Vector3[positionsList.Count];
            Vector3[] normalsArray   = new Vector3[normalsList.Count];
            Vector2[] uvArray        = new Vector2[uvList.Count];
            int[]     trianglesArray = new int[trianglesList.Count];

            positionsList.CopyTo(positionsArray);
            normalsList.CopyTo(normalsArray);
            uvList.CopyTo(uvArray);
            trianglesList.CopyTo(trianglesArray);

            mesh.vertices = positionsArray;
            mesh.normals  = normalsArray;
            mesh.uv       = uvArray;


            if (meshGroupHolder.position != Vector3.zero ||
                meshGroupHolder.rotation != Quaternion.identity ||
                meshGroupHolder.lossyScale != Vector3.one)
            {
                mesh.LocalizeToTransform(meshGroupHolder);
            }

            mesh.triangles = trianglesArray;

            GameObject newGameObject = new GameObject("CollisionMesh");

            // Allow any editor dependent code to fire, e.g. assigning physics materials
            if (OnFinalizeCollisionMesh != null)
            {
                OnFinalizeCollisionMesh(newGameObject, mesh);
            }

            MeshCollider meshCollider = newGameObject.AddComponent <MeshCollider>();

            meshCollider.sharedMesh = mesh;
            // Assign the physics material from build settings
            meshCollider.sharedMaterial = buildSettings.DefaultPhysicsMaterial;
            // Reparent
            newGameObject.transform.SetParent(meshGroupHolder, false);            //.parent = meshGroupHolder;
            collisionMeshDictionary.Add(mesh);
        }
Пример #5
0
        /// <summary>
        /// Builds the brushes into final meshes
        /// </summary>
        /// <param name="forceRebuild">If set to <c>true</c> all brushes will be built and cached data ignored, otherwise SabreCSG will only rebuild brushes it knows have changed</param>
        /// <param name="buildInBackground">If set to <c>true</c> the majority of the build will occur in a background thread</param>
        public virtual void Build(bool forceRebuild, bool buildInBackground)
        {
            // If any of the build settings have changed, force all brushes to rebuild
            if (!lastBuildSettings.IsBuilt || CSGBuildSettings.AreDifferent(buildSettings, lastBuildSettings))
            {
                forceRebuild = true;
            }

            // Make sure we have the most accurate list of brushes, ignoring inactive objects
            brushes = new List <Brush>(transform.GetComponentsInChildren <Brush>(false));

            // Let each brush know it's about to be built
            for (int i = 0; i < brushes.Count; i++)
            {
                brushes[i].PrepareToBuild(brushes, forceRebuild);
            }

            // Perform a check to make sure the default material is OK
            Material defaultMaterial = GetDefaultMaterial();

            if (defaultMaterial == null)
            {
                Debug.LogError("Default fallback material file is missing, try reimporting SabreCSG");
            }

            // Make sure the build context has been initialized.
            if (buildContext == null)
            {
                buildContext = BuildContext;
            }

            BuildStatus buildStatus = CSGFactory.Build(brushes,
                                                       buildSettings,
                                                       buildContext,
                                                       this.transform,
                                                       materialMeshDictionary,
                                                       collisionMeshDictionary,
                                                       polygonsRemoved,
                                                       forceRebuild,
                                                       OnBuildProgressChanged,
                                                       OnFinalizeVisualMesh,
                                                       OnFinalizeCollisionMesh,
                                                       buildInBackground);

            if (buildStatus == BuildStatus.Complete)
            {
                OnBuildComplete();
            }
        }
Пример #6
0
        public virtual void OnBuildComplete()
        {
            polygonsRemoved = false;

            // Mark the brushes that have been built (so we can differentiate later if new brushes are built or not)
            builtBrushes.Clear();
            builtBrushes.AddRange(brushes);

            // Copy the last build settings, so that we can make minor changes to built meshes that are consistent
            // with how they were built. E.g. maintaining tangents as appropriate
            lastBuildSettings         = buildSettings.ShallowCopy();
            lastBuildSettings.IsBuilt = true;             // Make it clear that the lastBuildSettings refers to a completed build

            // Fire any post process build events
            FirePostBuildEvents();
        }
Пример #7
0
        internal static void BuildVisual(Transform meshGroupHolder,
                                         PolygonEntry[] polygonIndex,
                                         CSGBuildSettings buildSettings,
                                         CSGBuildContext.BuildContext buildContext,
                                         MaterialMeshDictionary materialMeshDictionary)
        {
            materialMeshDictionary.Clear();

            // Reset statistics
            buildContext.buildMetrics.TotalMeshes    = 0;
            buildContext.buildMetrics.TotalVertices  = 0;
            buildContext.buildMetrics.TotalTriangles = 0;

            Dictionary <Material, List <PolygonEntry> > polygonMaterialTable = new Dictionary <Material, List <PolygonEntry> >();

            for (int i = 0; i < polygonIndex.Length; i++)
            {
                PolygonEntry entry = polygonIndex[i];

                if (PolygonEntry.IsValid(entry) &&
                    entry.Positions.Length > 0 &&
                    !entry.ExcludeFromBuild)    // Skip polygons that weren't built
                {
                    Material material = entry.Material;

                    if (material == null)
                    {
                        material = buildSettings.DefaultVisualMaterial;
                    }

                    if (polygonMaterialTable.ContainsKey(material))
                    {
                        polygonMaterialTable[material].Add(entry);
                    }
                    else
                    {
                        polygonMaterialTable.Add(material, new List <PolygonEntry>()
                        {
                            entry
                        });
                    }
                }
            }

            foreach (KeyValuePair <Material, List <PolygonEntry> > row in polygonMaterialTable)
            {
                Mesh mesh = new Mesh();

                List <Vector3> positionsList = new List <Vector3>();
                List <Vector3> normalsList   = new List <Vector3>();
                List <Vector2> uvList        = new List <Vector2>();
                List <Color>   colorsList    = new List <Color>();
                List <int>     trianglesList = new List <int>();

                for (int i = 0; i < row.Value.Count; i++)
                {
                    int positionOffset = positionsList.Count;
                    int triangleOffset = trianglesList.Count;

                    PolygonEntry polygonEntry = row.Value[i];
                    if (polygonEntry.Positions.Length + positionOffset > MESH_VERTEX_LIMIT)
                    {
                        FinalizeVisualMesh(meshGroupHolder, mesh, row.Key, buildSettings, buildContext, positionsList, normalsList, uvList, colorsList, trianglesList, materialMeshDictionary);
                        mesh = new Mesh();
                        positionsList.Clear();
                        normalsList.Clear();
                        uvList.Clear();
                        colorsList.Clear();
                        trianglesList.Clear();
                        positionOffset = 0;
                    }
                    positionsList.AddRange(polygonEntry.Positions);
                    normalsList.AddRange(polygonEntry.Normals);
                    uvList.AddRange(polygonEntry.UV);
                    colorsList.AddRange(polygonEntry.Colors);

                    for (int j = 0; j < polygonEntry.Triangles.Length; j++)
                    {
                        trianglesList.Add(polygonEntry.Triangles[j] + positionOffset);
                    }

                    row.Value[i].BuiltMesh           = mesh;
                    row.Value[i].BuiltVertexOffset   = positionOffset;
                    row.Value[i].BuiltTriangleOffset = triangleOffset;
                }

                FinalizeVisualMesh(meshGroupHolder, mesh, row.Key, buildSettings, buildContext, positionsList, normalsList, uvList, colorsList, trianglesList, materialMeshDictionary);
            }
        }
Пример #8
0
        internal static void FinalizeCollisionMesh(Transform meshGroupHolder,
                                                   Mesh mesh,
                                                   CSGBuildSettings buildSettings,
                                                   List <Vector3> positionsList,
                                                   List <Vector3> normalsList,
                                                   List <Vector2> uvList,
                                                   List <int> trianglesList,
                                                   List <Mesh> collisionMeshDictionary)
        {
            Vector3[] positionsArray = new Vector3[positionsList.Count];
            Vector3[] normalsArray   = new Vector3[normalsList.Count];
            Vector2[] uvArray        = new Vector2[uvList.Count];
            int[]     trianglesArray = new int[trianglesList.Count];

            positionsList.CopyTo(positionsArray);
            normalsList.CopyTo(normalsArray);
            uvList.CopyTo(uvArray);
            trianglesList.CopyTo(trianglesArray);

            mesh.vertices = positionsArray;
            mesh.normals  = normalsArray;
            mesh.uv       = uvArray;

            if (meshGroupHolder.position != Vector3.zero ||
                meshGroupHolder.rotation != Quaternion.identity ||
                meshGroupHolder.lossyScale != Vector3.one)
            {
                mesh.LocalizeToTransform(meshGroupHolder);
            }

            mesh.triangles = trianglesArray;

            GameObject newGameObject = new GameObject("CollisionMesh");

            // Allow any editor dependent code to fire, e.g. assigning physics materials
            if (OnFinalizeCollisionMesh != null)
            {
                OnFinalizeCollisionMesh(newGameObject, mesh);
            }

            MeshCollider meshCollider = newGameObject.AddComponent <MeshCollider>();

            meshCollider.sharedMesh = mesh;
            // Assign the physics material from build settings
            meshCollider.sharedMaterial = buildSettings.DefaultPhysicsMaterial;
            // Reparent
            newGameObject.transform.SetParent(meshGroupHolder, false);//.parent = meshGroupHolder;

#if UNITY_EDITOR
            if (buildSettings.SaveMeshesAsAssets)
            {
                // Make sure the folder exists to save into
                string path = SceneManager.GetActiveScene().path;
                path = Path.Combine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path));
                if (!Directory.Exists(path))
                {
                    UnityEditor.AssetDatabase.CreateFolder(Path.GetDirectoryName(path), Path.GetFileName(path));
                }
                // Save to a file rather than leaving it as a scene asset
                UnityEditor.AssetDatabase.CreateAsset(mesh, Path.Combine(path, "CollisionMesh" + collisionMeshDictionary.Count + ".asset"));
            }
#endif

            collisionMeshDictionary.Add(mesh);
        }
Пример #9
0
        internal static void FinalizeVisualMesh(Transform meshGroupHolder,
                                                Mesh mesh,
                                                Material material,
                                                CSGBuildSettings buildSettings,
                                                CSGBuildContext.BuildContext buildContext,
                                                List <Vector3> positionsList,
                                                List <Vector3> normalsList,
                                                List <Vector2> uvList,
                                                List <Color> colorsList,
                                                List <int> trianglesList,
                                                MaterialMeshDictionary materialMeshDictionary)
        {
            Vector3[] positionsArray = new Vector3[positionsList.Count];
            Vector3[] normalsArray   = new Vector3[normalsList.Count];
            Vector2[] uvArray        = new Vector2[uvList.Count];
            Color[]   colorsArray    = new Color[colorsList.Count];
            int[]     trianglesArray = new int[trianglesList.Count];

            positionsList.CopyTo(positionsArray);
            normalsList.CopyTo(normalsArray);
            uvList.CopyTo(uvArray);
            trianglesList.CopyTo(trianglesArray);
            colorsList.CopyTo(colorsArray);

            mesh.vertices = positionsArray;
            mesh.normals  = normalsArray;
            mesh.uv       = uvArray;
            mesh.colors   = colorsArray;

            if (meshGroupHolder.position != Vector3.zero ||
                meshGroupHolder.rotation != Quaternion.identity ||
                meshGroupHolder.lossyScale != Vector3.one)
            {
                mesh.LocalizeToTransform(meshGroupHolder);
            }

            mesh.triangles = trianglesArray;

            if (buildSettings.GenerateTangents)
            {
                // Generate tangents, necessary for some shaders
                mesh.GenerateTangents();
            }

            buildContext.buildMetrics.TotalMeshes++;
            buildContext.buildMetrics.TotalVertices  += positionsArray.Length;
            buildContext.buildMetrics.TotalTriangles += trianglesArray.Length / 3;

            GameObject newGameObject = new GameObject("MaterialMesh");

            // Allow any editor dependent code to fire, e.g. lightmap unwrapping, static flags
            if (OnFinalizeVisualMesh != null)
            {
                OnFinalizeVisualMesh(newGameObject, mesh);
            }

            newGameObject.AddComponent <MeshFilter>().sharedMesh = mesh;
            MeshRenderer meshRenderer = newGameObject.AddComponent <MeshRenderer>();

            meshRenderer.sharedMaterial       = material;
            meshRenderer.shadowCastingMode    = buildSettings.ShadowCastingMode;
            meshRenderer.reflectionProbeUsage = buildSettings.ReflectionProbeUsage;
            //newGameObject.transform.parent = meshGroupHolder;

            newGameObject.transform.SetParent(meshGroupHolder, false);

#if UNITY_EDITOR
            if (buildSettings.SaveMeshesAsAssets)
            {
                // Make sure the folder exists to save into
                string path = SceneManager.GetActiveScene().path;
                path = Path.Combine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path));
                if (!Directory.Exists(path))
                {
                    UnityEditor.AssetDatabase.CreateFolder(Path.GetDirectoryName(path), Path.GetFileName(path));
                }
                // Save to a file rather than leaving it as a scene asset
                UnityEditor.AssetDatabase.CreateAsset(mesh, Path.Combine(path, "VisualMesh" + materialMeshDictionary.MeshCount + ".asset"));
            }
#endif

            materialMeshDictionary.Add(material, mesh, newGameObject);
        }
Пример #10
0
        internal static void FinalizeVisualMesh(Transform meshGroupHolder,
                                                Mesh mesh,
                                                Material material,
                                                CSGBuildSettings buildSettings,
                                                CSGBuildContext.BuildContext buildContext,
                                                List <Vector3> positionsList,
                                                List <Vector3> normalsList,
                                                List <Vector2> uvList,
                                                List <Color> colorsList,
                                                List <int> trianglesList,
                                                MaterialMeshDictionary materialMeshDictionary)
        {
            Vector3[] positionsArray = new Vector3[positionsList.Count];
            Vector3[] normalsArray   = new Vector3[normalsList.Count];
            Vector2[] uvArray        = new Vector2[uvList.Count];
            Color[]   colorsArray    = new Color[colorsList.Count];
            int[]     trianglesArray = new int[trianglesList.Count];

            positionsList.CopyTo(positionsArray);
            normalsList.CopyTo(normalsArray);
            uvList.CopyTo(uvArray);
            trianglesList.CopyTo(trianglesArray);
            colorsList.CopyTo(colorsArray);

            mesh.vertices = positionsArray;
            mesh.normals  = normalsArray;
            mesh.uv       = uvArray;
            mesh.colors   = colorsArray;


            if (meshGroupHolder.position != Vector3.zero ||
                meshGroupHolder.rotation != Quaternion.identity ||
                meshGroupHolder.lossyScale != Vector3.one)
            {
                mesh.LocalizeToTransform(meshGroupHolder);
            }

            mesh.triangles = trianglesArray;

            if (buildSettings.GenerateTangents)
            {
                // Generate tangents, necessary for some shaders
                mesh.GenerateTangents();
            }

            buildContext.buildMetrics.TotalMeshes++;
            buildContext.buildMetrics.TotalVertices  += positionsArray.Length;
            buildContext.buildMetrics.TotalTriangles += trianglesArray.Length / 3;

            GameObject newGameObject = new GameObject("MaterialMesh");

            // Allow any editor dependent code to fire, e.g. lightmap unwrapping, static flags
            if (OnFinalizeVisualMesh != null)
            {
                OnFinalizeVisualMesh(newGameObject, mesh);
            }


            newGameObject.AddComponent <MeshFilter>().sharedMesh       = mesh;
            newGameObject.AddComponent <MeshRenderer>().sharedMaterial = material;
//			newGameObject.transform.parent = meshGroupHolder;
            newGameObject.transform.SetParent(meshGroupHolder, false);

            materialMeshDictionary.Add(material, mesh, newGameObject);
        }