Example #1
0
        void Initialize()
        {
            meshFilter.sharedMesh = sharedMesh;
            if (!debugHelperRenderer)
            {
                meshRenderer.receiveShadows = ((query & LayerUsageFlags.ReceiveShadows) == LayerUsageFlags.ReceiveShadows);
                switch (query & (LayerUsageFlags.Renderable | LayerUsageFlags.CastShadows))
                {
                case LayerUsageFlags.None:                          meshRenderer.enabled = false; break;

                case LayerUsageFlags.Renderable:            meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;                   break;

                case LayerUsageFlags.CastShadows:           meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly;   break;

                case LayerUsageFlags.RenderCastShadows:     meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;                    break;
                }

#if UNITY_EDITOR
                UnityEditor.EditorUtility.SetSelectedRenderState(meshRenderer, UnityEditor.EditorSelectedRenderState.Hidden);
                ChiselGeneratedComponentManager.SetHasLightmapUVs(sharedMesh, false);
#endif
            }
            else
            {
                meshRenderer.allowOcclusionWhenDynamic  = false;
                meshRenderer.lightProbeUsage            = LightProbeUsage.Off;
                meshRenderer.reflectionProbeUsage       = ReflectionProbeUsage.Off;
                meshRenderer.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion;
                meshRenderer.shadowCastingMode          = ShadowCastingMode.Off;
#if UNITY_EDITOR
                meshRenderer.scaleInLightmap = 0.0f;
#endif
            }
        }
Example #2
0
        public override void OnInitialize()
        {
            if (!generatedDataContainer)
            {
                generatedDataContainer = ChiselGeneratedComponentManager.FindContainerGameObject(this);
                if (generatedDataContainer != null)
                {
                    generatedDataTransform = generatedDataContainer.transform;
                }
            }

            colliderSettings = new ChiselGeneratedColliderSettings();
            colliderSettings.Reset();

            renderSettings = new ChiselGeneratedRenderSettings();
            renderSettings.Reset();

#if UNITY_EDITOR
            UnityEditor.UnwrapParam defaults;
            UnityEditor.UnwrapParam.SetDefaults(out defaults);
            uvGenerationSettings.angleError       = defaults.angleError;
            uvGenerationSettings.areaError        = defaults.areaError;
            uvGenerationSettings.hardAngle        = defaults.hardAngle;
            uvGenerationSettings.packMarginPixels = defaults.packMargin * 256;
#endif

            initialized = true;
        }
Example #3
0
        void UpdateSettings(ChiselModel model, GameObjectState state, bool meshIsModified)
        {
#if UNITY_EDITOR
            Profiler.BeginSample("CheckIfFullMeshNeedsToBeHidden");
            // If we need to render partial meshes (where some brushes are hidden) then we should show the full mesh
            ChiselGeneratedComponentManager.CheckIfFullMeshNeedsToBeHidden(model, this);
            Profiler.EndSample();
            if (meshIsModified)
            {
                // Setting the sharedMesh to ensure the meshFilter knows it needs to be updated
                Profiler.BeginSample("OverrideMesh");
                meshFilter.sharedMesh = meshFilter.sharedMesh;
                Profiler.EndSample();
                Profiler.BeginSample("SetDirty");
                UnityEditor.EditorUtility.SetDirty(meshFilter);
                UnityEditor.EditorUtility.SetDirty(model);
                Profiler.EndSample();
                Profiler.BeginSample("SetHasLightmapUVs");
                ChiselGeneratedComponentManager.SetHasLightmapUVs(sharedMesh, false);
                Profiler.EndSample();
                Profiler.BeginSample("ClearLightmapData");
                ChiselGeneratedComponentManager.ClearLightmapData(state, this);
                Profiler.EndSample();
            }
#endif
        }
        static readonly List <GeneratedMeshContents> __foundContents = new List <GeneratedMeshContents>(); // static to avoid allocations
        public void Update(ChiselModel model, GameObjectState state, GeneratedMeshDescription[] meshDescriptions, int startIndex, int endIndex)
        {
            bool meshIsModified = false;

            // Retrieve the generatedMeshes and its materials, combine them into a single Unity Mesh/Material array
            try
            {
                for (int i = startIndex; i < endIndex; i++)
                {
                    ref var meshDescription       = ref meshDescriptions[i];
                    var     generatedMeshContents = model.Node.GetGeneratedMesh(meshDescription);
                    if (generatedMeshContents == null)
                    {
                        continue;
                    }
                    if (generatedMeshContents.indices.Length == 0)
                    {
                        generatedMeshContents.Dispose();
                        continue;
                    }
                    var renderMaterial = ChiselBrushMaterialManager.GetRenderMaterialByInstanceID(meshDescription.surfaceParameter);
                    __foundContents.Add(generatedMeshContents);
                    __foundMaterials.Add(renderMaterial);
                }
                triangleBrushes.Clear();
                if (__foundContents.Count == 0)
                {
                    if (sharedMesh.vertexCount > 0)
                    {
                        sharedMesh.Clear(keepVertexLayout: true);
                    }
                }
                else
                {
                    sharedMesh.CopyFrom(__foundContents, triangleBrushes);
#if UNITY_EDITOR
                    ChiselGeneratedComponentManager.SetHasLightmapUVs(sharedMesh, false);
#endif
                }
                if (renderMaterials != null &&
                    renderMaterials.Length == __foundMaterials.Count)
                {
                    __foundMaterials.CopyTo(renderMaterials);
                }
                else
                {
                    renderMaterials = __foundMaterials.ToArray();
                }
                if (meshFilter.sharedMesh != sharedMesh)
                {
                    meshFilter.sharedMesh = sharedMesh;
                    meshIsModified        = true;
                }
                meshRenderer.sharedMaterials = renderMaterials;
                meshRenderer.enabled         = sharedMesh.vertexCount > 0;
            }
Example #5
0
        public static Bounds CalculateBounds(ChiselGeneratorComponent generator)
        {
            if (!generator.TopTreeNode.Valid)
            {
                return(ChiselHierarchyItem.EmptyBounds);
            }

            var modelMatrix = ChiselNodeHierarchyManager.FindModelTransformMatrixOfTransform(generator.hierarchyItem.Transform);
            var minMax      = new ChiselAABB {
            };
            var boundsCount = 0;

            s_FoundBrushes.Clear();
            ChiselGeneratedComponentManager.GetAllTreeBrushes(generator, s_FoundBrushes);
            foreach (var brush in s_FoundBrushes)
            {
                if (!brush.Valid)
                {
                    continue;
                }

                var transformation = modelMatrix * (Matrix4x4)brush.NodeToTreeSpaceMatrix;
                var childBounds    = brush.Bounds;
                var size           = childBounds.Max - childBounds.Min;
                var magnitude      = math.lengthsq(size);
                if (float.IsInfinity(magnitude) ||
                    float.IsNaN(magnitude))
                {
                    var center   = ((float4)transformation.GetColumn(3)).xyz;
                    var halfSize = size * 0.5f;
                    childBounds = new ChiselAABB {
                        Min = center - halfSize, Max = center + halfSize
                    };
                }
                if (magnitude != 0)
                {
                    if (boundsCount == 0)
                    {
                        minMax = childBounds;
                    }
                    else
                    {
                        minMax.Encapsulate(childBounds);
                    }
                    boundsCount++;
                }
            }
            if (boundsCount == 0)
            {
                return(ChiselHierarchyItem.EmptyBounds);
            }
            var bounds = new Bounds();

            bounds.SetMinMax(minMax.Min, minMax.Max);
            return(bounds);
        }
Example #6
0
        internal void UpdateVisibilityMesh(bool showMesh)
        {
            EnsureMeshesAllocated();
            var srcMesh = sharedMesh;
            var dstMesh = partialMesh;

            dstMesh.Clear(keepVertexLayout: true);
            if (!showMesh)
            {
                return;
            }
            srcMesh.GetVertices(sVertices);
            dstMesh.SetVertices(sVertices);

            srcMesh.GetNormals(sNormals);
            dstMesh.SetNormals(sNormals);

            srcMesh.GetTangents(sTangents);
            dstMesh.SetTangents(sTangents);

            srcMesh.GetUVs(0, sUV0);
            dstMesh.SetUVs(0, sUV0);

            dstMesh.subMeshCount = srcMesh.subMeshCount;
            for (int subMesh = 0, n = 0; subMesh < srcMesh.subMeshCount; subMesh++)
            {
                bool calculateBounds = false;
                int  baseVertex      = (int)srcMesh.GetBaseVertex(subMesh);
                srcMesh.GetTriangles(sSrcTriangles, subMesh, applyBaseVertex: false);
                sDstTriangles.Clear();
                var prevBrushID    = CompactNodeID.Invalid;
                var isBrushVisible = true;
                for (int i = 0; i < sSrcTriangles.Count; i += 3, n++)
                {
                    if (n < triangleBrushes.Length)
                    {
                        var brushID = triangleBrushes[n];
                        if (prevBrushID != brushID)
                        {
                            isBrushVisible = ChiselGeneratedComponentManager.IsBrushVisible(brushID);
                            prevBrushID    = brushID;
                        }
                        if (!isBrushVisible)
                        {
                            continue;
                        }
                    }
                    sDstTriangles.Add(sSrcTriangles[i + 0]);
                    sDstTriangles.Add(sSrcTriangles[i + 1]);
                    sDstTriangles.Add(sSrcTriangles[i + 2]);
                }
                dstMesh.SetTriangles(sDstTriangles, subMesh, calculateBounds, baseVertex);
            }
            dstMesh.RecalculateBounds();
        }
        void UpdateSettings(ChiselModel model, GameObjectState state, bool meshIsModified)
        {
#if UNITY_EDITOR
            // If we need to render partial meshes (where some brushes are hidden) then we should show the full mesh
            ChiselGeneratedComponentManager.CheckIfFullMeshNeedsToBeHidden(model, this);
            if (meshIsModified)
            {
                ChiselGeneratedComponentManager.ClearLightmapData(state, this);
            }
#endif
        }
Example #8
0
 public ChiselModel GetOrCreateDefaultModel()
 {
     if (!DefaultModel)
     {
         DefaultModel = null;
         if (Scene.IsValid() &&
             Scene.isLoaded)
         {
             DefaultModel = ChiselGeneratedComponentManager.CreateDefaultModel(this);
         }
     }
     return(DefaultModel);
 }
        // Will show a warning icon in hierarchy when generator has a problem (do not make this method slow, it is called a lot!)
        public override bool HasValidState()
        {
            if (!ValidNodes)
            {
                return(false);
            }

            if (ChiselGeneratedComponentManager.IsDefaultModel(hierarchyItem.Model))
            {
                return(false);
            }

            return(true);
        }
Example #10
0
 public ChiselModel GetOrCreateDefaultModel(out bool created)
 {
     created = false;
     if (!DefaultModel)
     {
         DefaultModel = null;
         if (Scene.IsValid() &&
             Scene.isLoaded)
         {
             DefaultModel = ChiselGeneratedComponentManager.CreateDefaultModel(this);
             created      = true;
         }
     }
     return(DefaultModel);
 }
Example #11
0
        public static void UpdateModels()
        {
            // Update the tree meshes
            Profiler.BeginSample("Flush");
            try
            {
                if (!CompactHierarchyManager.Flush(s_FinishMeshUpdates))
                {
                    ChiselGeneratedComponentManager.DelayedUVGeneration();
                    return; // Nothing to update ..
                }
            }
            finally
            {
                Profiler.EndSample();
            }

            {
                Profiler.BeginSample("PostUpdateModels");
                PostUpdateModels?.Invoke();
                Profiler.EndSample();
            }
        }
Example #12
0
        /*
         * public static bool FindFirstWorldIntersection(ChiselModel model, Vector3 worldRayStart, Vector3 worldRayEnd, int visibleLayers, out ChiselIntersection foundIntersection)
         * {
         *  return FindFirstWorldIntersection(model, worldRayStart, worldRayEnd, visibleLayers, null, null, out foundIntersection);
         * }
         */
        public static bool FindFirstWorldIntersection(ChiselModel model, Vector3 worldRayStart, Vector3 worldRayEnd, int visibleLayers, GameObject[] ignore, GameObject[] filter, out ChiselIntersection foundIntersection)
        {
            foundIntersection = ChiselIntersection.None;

            if (!ChiselGeneratedComponentManager.IsValidModelToBeSelected(model))
            {
                return(false);
            }

            s_FilterNodes.Clear();
            s_IgnoreNodes.Clear();
            s_IgnoreInstanceIDs.Clear();
            s_FilterInstanceIDs.Clear();
            if (ignore != null)
            {
                foreach (var go in ignore)
                {
                    var node = go.GetComponent <ChiselNode>();
                    if (node)
                    {
                        ChiselNodeHierarchyManager.GetChildrenOfHierarchyItem(s_IgnoreNodes, node.hierarchyItem);
                        s_IgnoreInstanceIDs.Add(node.GetInstanceID());
                    }
                }
            }
            if (filter != null)
            {
                foreach (var go in filter)
                {
                    var node = go.GetComponent <ChiselNode>();
                    if (node)
                    {
                        ChiselNodeHierarchyManager.GetChildrenOfHierarchyItem(s_FilterNodes, node.hierarchyItem);
                        s_FilterInstanceIDs.Add(node.GetInstanceID());
                        if (node.hierarchyItem != null &&
                            node.hierarchyItem.Model)
                        {
                            s_FilterInstanceIDs.Add(node.hierarchyItem.Model.GetInstanceID());
                        }
                    }
                }
            }

            var tree = model.Node;

            if (s_IgnoreInstanceIDs.Contains(model.GetInstanceID()) ||
                (s_FilterInstanceIDs.Count > 0 && !s_FilterInstanceIDs.Contains(model.GetInstanceID())))
            {
                return(false);
            }

            if (((1 << model.gameObject.layer) & visibleLayers) == 0)
            {
                return(false);
            }

            var query          = ChiselMeshQueryManager.GetMeshQuery(model);
            var visibleQueries = ChiselMeshQueryManager.GetVisibleQueries(query);

            // We only accept RayCasts into this model if it's visible
            if (visibleQueries == null ||
                visibleQueries.Length == 0)
            {
                return(false);
            }

            Vector3 treeRayStart;
            Vector3 treeRayEnd;

            var transform = model.transform;

            if (transform)
            {
                var worldToLocalMatrix = transform.worldToLocalMatrix;
                treeRayStart = worldToLocalMatrix.MultiplyPoint(worldRayStart);
                treeRayEnd   = worldToLocalMatrix.MultiplyPoint(worldRayEnd);
            }
            else
            {
                treeRayStart = worldRayStart;
                treeRayEnd   = worldRayEnd;
            }

            var treeIntersections = CSGQueryManager.RayCastMulti(ChiselMeshQueryManager.GetMeshQuery(model), tree, treeRayStart, treeRayEnd, s_IgnoreNodes, s_FilterNodes, ignoreBackfaced: true, ignoreCulled: true);

            if (treeIntersections == null)
            {
                return(false);
            }

            bool found = false;

            for (var i = 0; i < treeIntersections.Length; i++)
            {
                var intersection = treeIntersections[i];
                var brush        = intersection.brush;
                var instanceID   = brush.UserID;

                if ((s_FilterInstanceIDs.Count > 0 && !s_FilterInstanceIDs.Contains(instanceID)) ||
                    s_IgnoreInstanceIDs.Contains(instanceID))
                {
                    continue;
                }

                if (intersection.surfaceIntersection.distance < foundIntersection.brushIntersection.surfaceIntersection.distance)
                {
                    foundIntersection = Convert(intersection);
                    found             = true;
                }
            }
            return(found);
        }
        public static void UpdateModels()
        {
            // Update the tree meshes
            Profiler.BeginSample("Flush");
            try
            {
                if (!CSGManager.Flush())
                {
                    ChiselGeneratedComponentManager.DelayedUVGeneration();
                    return; // Nothing to update ..
                }
            }
            finally
            {
                Profiler.EndSample();
            }

#if UNITY_EDITOR
            ChiselGeneratedComponentManager.OnVisibilityChanged();
#endif


            for (int m = 0; m < registeredModels.Count; m++)
            {
                var model = registeredModels[m];
                if (!model)
                {
                    continue;
                }

                var tree = model.Node;

                // See if the tree has been modified
                if (!tree.Dirty)
                {
                    continue;
                }

                Profiler.BeginSample("UpdateModelMeshDescriptions");
                UpdateModelMeshDescriptions(model);
                Profiler.EndSample();

                updateList.Add(model);
            }

            bool modifications = false;
            try
            {
                for (int m = 0; m < updateList.Count; m++)
                {
                    var model = updateList[m];

                    // Generate (or re-use) components and set them up properly
                    Profiler.BeginSample("componentGenerator.Rebuild");
                    componentGenerator.Rebuild(model);
                    Profiler.EndSample();
                }
            }
            finally
            {
                for (int m = 0; m < updateList.Count; m++)
                {
                    var model = updateList[m];
                    try
                    {
                        modifications = true;
                        Profiler.BeginSample("PostUpdateModel");
                        PostUpdateModel?.Invoke(model);
                        Profiler.EndSample();
                    }
                    catch (Exception ex) // if there's a bug in user-code we don't want to end up in a bad state
                    {
                        Debug.LogException(ex);
                    }
                }
                updateList.Clear();
            }

            if (modifications)
            {
                Profiler.BeginSample("PostUpdateModels");
                PostUpdateModels?.Invoke();
                Profiler.EndSample();
            }
        }
Example #14
0
        public static bool FindFirstWorldIntersection(ChiselModel model, Vector3 worldRayStart, Vector3 worldRayEnd, int filterLayerParameter0, int visibleLayers, GameObject[] ignore, GameObject[] filter, out ChiselIntersection foundIntersection)
        {
            foundIntersection = ChiselIntersection.None;

            if (!ChiselGeneratedComponentManager.IsValidModelToBeSelected(model))
            {
                return(false);
            }

            CSGTreeNode[] ignoreBrushes     = null;
            HashSet <int> ignoreInstanceIDs = null;
            HashSet <int> filterInstanceIDs = null;

            if (ignore != null)
            {
                //var ignoreBrushList = new HashSet<CSGTreeBrush>();
                ignoreInstanceIDs = new HashSet <int>();
                foreach (var go in ignore)
                {
                    var node = go.GetComponent <ChiselNode>();
                    if (node)
                    {
                        //node.GetAllTreeBrushes(ignoreBrushList);
                        ignoreInstanceIDs.Add(node.GetInstanceID());
                    }
                }
            }
            if (filter != null)
            {
                filterInstanceIDs = new HashSet <int>();
                foreach (var go in filter)
                {
                    var node = go.GetComponent <ChiselNode>();
                    if (node)
                    {
                        filterInstanceIDs.Add(node.GetInstanceID());
                    }
                }
            }


            var tree = model.Node;

            if ((ignoreInstanceIDs != null && ignoreInstanceIDs.Contains(model.GetInstanceID())))
            {
                return(false);
            }

            if ((filterInstanceIDs != null && !filterInstanceIDs.Contains(model.GetInstanceID())))
            {
                return(false);
            }

            if (((1 << model.gameObject.layer) & visibleLayers) == 0)
            {
                return(false);
            }

            var query          = ChiselMeshQueryManager.GetMeshQuery(model);
            var visibleQueries = ChiselMeshQueryManager.GetVisibleQueries(query);

            // We only accept RayCasts into this model if it's visible
            if (visibleQueries == null ||
                visibleQueries.Length == 0)
            {
                return(false);
            }

            Vector3 treeRayStart;
            Vector3 treeRayEnd;

            var transform = model.transform;

            if (transform)
            {
                var worldToLocalMatrix = transform.worldToLocalMatrix;
                treeRayStart = worldToLocalMatrix.MultiplyPoint(worldRayStart);
                treeRayEnd   = worldToLocalMatrix.MultiplyPoint(worldRayEnd);
            }
            else
            {
                treeRayStart = worldRayStart;
                treeRayEnd   = worldRayEnd;
            }

            var treeIntersections = CSGManager.RayCastMulti(ChiselMeshQueryManager.GetMeshQuery(model), tree, treeRayStart, treeRayEnd, ignoreBrushes);

            if (treeIntersections == null)
            {
                return(false);
            }

            bool found = false;

            for (var i = 0; i < treeIntersections.Length; i++)
            {
                var intersection = treeIntersections[i];
                var brush        = intersection.brush;
                var instanceID   = brush.UserID;

                if ((filterInstanceIDs != null && !filterInstanceIDs.Contains(instanceID)))
                {
                    continue;
                }

                if ((ignoreInstanceIDs != null && ignoreInstanceIDs.Contains(instanceID)))
                {
                    continue;
                }

                if (intersection.surfaceIntersection.distance < foundIntersection.brushIntersection.surfaceIntersection.distance)
                {
                    foundIntersection = Convert(intersection);
                    found             = true;
                }
            }
            return(found);
        }
Example #15
0
 protected override void OnCleanup()
 {
     ChiselGeneratedComponentManager.RemoveContainerFlags(this);
 }
Example #16
0
        public static void UpdateModels()
        {
            // Update the tree meshes
            if (!CSGManager.Flush())
            {
                ChiselGeneratedComponentManager.DelayedUVGeneration();
                if (sharedUnityMeshes.FindAllUnusedUnityMeshes())
                {
                    sharedUnityMeshes.DestroyNonRecycledUnusedUnityMeshes();
                }
                return; // Nothing to update ..
            }

            for (int m = 0; m < registeredModels.Count; m++)
            {
                var model = registeredModels[m];
                if (!model)
                {
                    continue;
                }

                var tree = model.Node;

                // See if the tree has been modified
                if (!tree.Dirty)
                {
                    continue;
                }

                try
                {
                    if (PreUpdateModel != null)
                    {
                        PreUpdateModel(model);
                    }
                }
                catch (Exception ex) // if there's a bug in user-code we don't want to end up in a bad state
                {
                    Debug.LogException(ex);
                }

                UpdateModelMeshDescriptions(model);

                // Re-use existing UnityEngine.Mesh if they exist
                sharedUnityMeshes.ReuseExistingMeshes(model);

                updateList.Add(model);
            }

            bool modifications = false;

            try
            {
                // Find all meshes whose refCounts are 0
                sharedUnityMeshes.FindAllUnusedUnityMeshes();

                // Separate loop so we can re-use garbage collected UnityEngine.Meshes to avoid allocation costs

                for (int m = 0; m < updateList.Count; m++)
                {
                    var model = updateList[m];

                    // Generate new UnityEngine.Mesh instances and fill them with data from the CSG algorithm (if necessary)
                    //	note: reuses garbage collected meshes when possible
                    sharedUnityMeshes.CreateNewMeshes(model);

                    // Generate (or re-use) components and set them up properly
                    componentGenerator.Rebuild(model);
                }
            }
            finally
            {
                for (int m = 0; m < updateList.Count; m++)
                {
                    var model = updateList[m];
                    try
                    {
                        modifications = true;
                        if (PostUpdateModel != null)
                        {
                            PostUpdateModel(model);
                        }
                    }
                    catch (Exception ex) // if there's a bug in user-code we don't want to end up in a bad state
                    {
                        Debug.LogException(ex);
                    }
                }
                updateList.Clear();
            }

            // Destroy all meshes whose refCounts are 0
            sharedUnityMeshes.DestroyNonRecycledUnusedUnityMeshes();

            if (modifications)
            {
                if (PostUpdateModels != null)
                {
                    PostUpdateModels();
                }
            }
        }
        public void UpdateHelperSurfaceState(DrawModeFlags helperStateFlags, bool ignoreBrushVisibility = false)
        {
            if (!ignoreBrushVisibility)
            {
                ChiselGeneratedComponentManager.UpdateVisibility();
            }

            var shouldHideMesh = !ignoreBrushVisibility &&
                                 visibilityState != VisibilityState.AllVisible &&
                                 visibilityState != VisibilityState.Unknown;

            var showRenderables = (helperStateFlags & DrawModeFlags.HideRenderables) == DrawModeFlags.None;

            for (int i = 0; i < renderables.Length; i++)
            {
                var renderable = renderables[i];
                if (renderable == null ||
                    renderable.invalid)
                {
                    continue;
                }

                if (renderable.meshRenderer != null)
                {
                    renderable.meshRenderer.forceRenderingOff = shouldHideMesh || !showRenderables;
                }
            }

            for (int i = 0; i < debugHelpers.Length; i++)
            {
                var showState = (helperStateFlags & kGeneratedDebugShowFlags[i]) != DrawModeFlags.None;
                debugHelpers[i].visible = !shouldHideMesh && showState;
            }

            if (ignoreBrushVisibility || !needVisibilityMeshUpdate)
            {
                return;
            }

            if (visibilityState == VisibilityState.Mixed)
            {
                for (int i = 0; i < renderables.Length; i++)
                {
                    var renderable = renderables[i];
                    if (renderable == null ||
                        renderable.invalid)
                    {
                        continue;
                    }

                    renderable.UpdateVisibilityMesh(showRenderables);
                }

                for (int i = 0; i < debugHelpers.Length; i++)
                {
                    var show        = (helperStateFlags & kGeneratedDebugShowFlags[i]) != DrawModeFlags.None;
                    var debugHelper = debugHelpers[i];
                    if (debugHelper == null)
                    {
                        continue;
                    }

                    debugHelper.UpdateVisibilityMesh(show);
                }
            }

            needVisibilityMeshUpdate = false;
        }