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 void Init() { CSGManager.Clear(); }
public static bool GetNodesInFrustum(Frustum frustum, int visibleLayers, ref HashSet <CSGTreeNode> rectFoundNodes) { rectFoundNodes.Clear(); var planes = new Plane[6]; Vector4 srcVector; var allTrees = CSGManager.AllTrees; for (var t = 0; t < allTrees.Length; t++) { var tree = allTrees[t]; var model = ChiselNodeHierarchyManager.FindChiselNodeByTreeNode(tree) as ChiselModel; if (!ChiselModelManager.IsVisible(model)) { continue; } if (((1 << model.gameObject.layer) & visibleLayers) == 0) { continue; } 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) { continue; } // Transform the frustum into the space of the tree var transform = model.transform; var worldToLocalMatrixInversed = transform.localToWorldMatrix; // localToWorldMatrix == worldToLocalMatrix.inverse var worldToLocalMatrixInversedTransposed = worldToLocalMatrixInversed.transpose; for (int p = 0; p < 6; p++) { var srcPlane = frustum.Planes[p]; srcVector.x = srcPlane.normal.x; srcVector.y = srcPlane.normal.y; srcVector.z = srcPlane.normal.z; srcVector.w = srcPlane.distance; srcVector = worldToLocalMatrixInversedTransposed * srcVector; planes[p].normal = srcVector; planes[p].distance = srcVector.w; } var treeNodesInFrustum = CSGManager.GetNodesInFrustum(tree, query, planes); if (treeNodesInFrustum == null) { continue; } for (int n = 0; n < treeNodesInFrustum.Length; n++) { var treeNode = treeNodesInFrustum[n]; rectFoundNodes.Add(treeNode); } } return(rectFoundNodes.Count > 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); }
public static bool FindMultiWorldIntersection(Vector3 worldRayStart, Vector3 worldRayEnd, int filterLayerParameter0, int visibleLayers, GameObject[] ignore, GameObject[] filter, out ChiselIntersection[] intersections) { intersections = null; __foundIntersections.Clear(); HashSet <int> ignoreInstanceIDs = null; HashSet <int> filterInstanceIDs = null; if (ignore != null) { ignoreInstanceIDs = new HashSet <int>(); foreach (var go in ignore) { var node = go.GetComponent <ChiselNode>(); if (node) { 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 allTrees = CSGManager.AllTrees; for (var t = 0; t < allTrees.Length; t++) { var tree = allTrees[t]; var model = ChiselNodeHierarchyManager.FindChiselNodeByTreeNode(tree) as ChiselModel; if (!ChiselModelManager.IsVisible(model)) { continue; } 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) { continue; } 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); if (treeIntersections == null) { continue; } 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; } __foundIntersections[brush] = Convert(intersection); } } if (__foundIntersections.Count == 0) { return(false); } var sortedIntersections = __foundIntersections.Values.ToArray(); Array.Sort(sortedIntersections, (x, y) => (x.brushIntersection.surfaceIntersection.distance < y.brushIntersection.surfaceIntersection.distance) ? -1 : 0); __foundIntersections.Clear(); intersections = sortedIntersections; return(true); }
public static void UpdateModels() { // Update the tree meshes if (!CSGManager.Flush()) { CSGGeneratedComponentManager.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 static bool FindFirstWorldIntersection(List <ChiselIntersection> foundIntersections, Vector3 worldRayStart, Vector3 worldRayEnd, int visibleLayers = ~0, bool ignoreBackfaced = false, bool ignoreCulled = false, GameObject[] ignore = null, GameObject[] filter = null) { bool found = false; s_IgnoreInstanceIDs.Clear(); s_FilterInstanceIDs.Clear(); s_IgnoreNodes.Clear(); s_FilterNodes.Clear(); if (ignore != null) { foreach (var go in ignore) { var node = go.GetComponent <ChiselNode>(); if (node) { node.CollectCSGTreeNodes(s_IgnoreNodes); s_IgnoreInstanceIDs.Add(node.GetInstanceID()); } } } if (filter != null) { foreach (var go in filter) { var node = go.GetComponent <ChiselNode>(); if (node) { node.CollectCSGTreeNodes(s_FilterNodes); s_FilterInstanceIDs.Add(node.GetInstanceID()); if (node.hierarchyItem != null && node.hierarchyItem.Model) { s_FilterInstanceIDs.Add(node.hierarchyItem.Model.GetInstanceID()); } } } } var allTrees = CSGManager.AllTrees; for (var t = 0; t < allTrees.Length; t++) { var tree = allTrees[t]; var model = ChiselNodeHierarchyManager.FindChiselNodeByTreeNode(tree) as ChiselModel; if (!ChiselModelManager.IsVisible(model)) { continue; } if (((1 << model.gameObject.layer) & visibleLayers) == 0) { continue; } var modelInstanceID = model.GetInstanceID(); if (s_IgnoreInstanceIDs.Contains(modelInstanceID) || (s_FilterInstanceIDs.Count > 0 && !s_FilterInstanceIDs.Contains(modelInstanceID))) { continue; } 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, s_IgnoreNodes, s_FilterNodes, ignoreBackfaced, ignoreCulled); if (treeIntersections == null) { continue; } 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; } foundIntersections.Add(Convert(intersection)); found = true; } } return(found); }