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 } }
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; }
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; }
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); }
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 }
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); }
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); }
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(); } }
/* * 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(); } }
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); }
protected override void OnCleanup() { ChiselGeneratedComponentManager.RemoveContainerFlags(this); }
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; }