internal static CSGTreeNode Find(CompactNodeID compactNodeID) { if (compactNodeID == CompactNodeID.Invalid) { return(CSGTreeNode.Invalid); } ref var hierarchy = ref CompactHierarchyManager.GetHierarchy(compactNodeID);
public NodeID GetNodeID(CompactNodeID compactNodeID) { int nodeIndex; Debug.Assert(IsCreated); if (compactNodeID == CompactNodeID.Invalid) { Debug.LogError($"{nameof(compactNodeID)} is an invalid node"); return(NodeID.Invalid); } nodeIndex = HierarchyIndexOfInternal(compactNodeID); if (nodeIndex == -1) { return(NodeID.Invalid); } if (nodeIndex < 0 || nodeIndex >= compactNodes.Length) { Debug.LogError($"{nameof(compactNodeID)} nodeIndex is out of range"); return(NodeID.Invalid); } return(compactNodes[nodeIndex].nodeID); }
public bool DeleteRecursive(CompactNodeID compactNodeID) { if (compactNodeID == RootID) // Cannot remove root { return(false); } var nodeIndex = HierarchyIndexOfInternal(compactNodeID); if (nodeIndex == -1) { throw new ArgumentException(nameof(compactNodeID), $"{nameof(compactNodeID)} is invalid"); } var parentID = compactNodes[nodeIndex].parentID; var parentIndex = HierarchyIndexOfInternal(parentID); if (parentIndex == -1) { // node doesn't have a parent, so it cannot be removed from its parent var childCount = ChildCount(compactNodeID); if (childCount > 0) { DeleteRangeInternal(nodeIndex, 0, childCount, deleteChildren: true); } FreeIndexRange(nodeIndex, 1); return(true); } var index = SiblingIndexOfInternal(parentIndex, nodeIndex); var result = DeleteRangeInternal(parentIndex, index, range: 1, deleteChildren: true); return(result); }
public bool Detach(CompactNodeID compactNodeID) { Debug.Assert(IsCreated); if (compactNodeID == RootID) // Cannot remove root { return(false); } var nodeIndex = HierarchyIndexOfInternal(compactNodeID); if (nodeIndex == -1) { throw new ArgumentException(nameof(compactNodeID), $"{nameof(compactNodeID)} is invalid"); } var parentID = compactNodes[nodeIndex].parentID; var parentIndex = HierarchyIndexOfInternal(parentID); if (parentIndex == -1) { return(false); // node doesn't have a parent, so it cannot be removed from its parent } var index = SiblingIndexOfInternal(parentIndex, nodeIndex); return(DetachRangeInternal(parentIndex, index, range: 1)); }
public int SiblingIndexOf(CompactNodeID parent, CompactNodeID child) { Debug.Assert(IsCreated); if (parent == CompactNodeID.Invalid) { return(-1); } var nodeIndex = HierarchyIndexOfInternal(child); if (nodeIndex == -1) { return(-1); } var childParent = compactNodes[nodeIndex].parentID; if (childParent == CompactNodeID.Invalid || childParent != parent) { return(-1); } var parentIndex = HierarchyIndexOfInternal(childParent); Debug.Assert(parentIndex != -1); return(SiblingIndexOfInternal(parentIndex, nodeIndex)); }
public bool DeleteChildFromParentRecursiveAt(CompactNodeID parentID, int index) { Debug.Assert(IsCreated); var parentIndex = HierarchyIndexOfInternal(parentID); if (parentIndex < 0) { throw new ArgumentException(nameof(parentID), $"{nameof(parentID)} is invalid"); } return(DeleteRangeInternal(parentIndex, index, range: 1, deleteChildren: true)); }
public int ChildCount(CompactNodeID compactNodeID) { Debug.Assert(IsCreated); var nodeIndex = HierarchyIndexOfInternal(compactNodeID); if (nodeIndex == -1) { throw new ArgumentException(nameof(compactNodeID), $"{nameof(compactNodeID)} is invalid"); } return(compactNodes[nodeIndex].childCount); }
public bool DetachChildrenFromParentAt(CompactNodeID parentID, int index, int range) { Debug.Assert(IsCreated); var parentIndex = HierarchyIndexOfInternal(parentID); if (parentIndex < 0) { throw new ArgumentException(nameof(parentID), $"{nameof(parentID)} is invalid"); } return(DetachRangeInternal(parentIndex, index, range)); }
public bool DestroyAllChildrenFromParent(CompactNodeID parentID) { Debug.Assert(IsCreated); var parentIndex = HierarchyIndexOfInternal(parentID); if (parentIndex < 0) { throw new ArgumentException(nameof(parentID), $"{nameof(parentID)} is invalid"); } return(DeleteAllChildrenInternal(parentIndex)); }
public bool IsValidCompactNodeID(CompactNodeID compactNodeID) { Debug.Assert(IsCreated); if (!idManager.IsValidID(compactNodeID.value, compactNodeID.generation, out var index)) { return(false); } if (compactNodes[index].compactNodeID != compactNodeID) { return(false); } return(true); }
public CompactNodeID ParentOf(CompactNodeID compactNodeID) { Debug.Assert(IsCreated); if (compactNodeID == CompactNodeID.Invalid) { throw new ArgumentException(nameof(compactNodeID), $"{nameof(compactNodeID)} is an invalid node"); } var nodeIndex = HierarchyIndexOfInternal(compactNodeID); if (nodeIndex == -1) { return(CompactNodeID.Invalid); } return(compactNodes[nodeIndex].parentID); }
public int SiblingIndexOf(CompactNodeID compactNodeID) { Debug.Assert(IsCreated); var nodeIndex = HierarchyIndexOfInternal(compactNodeID); if (nodeIndex == -1) { throw new ArgumentException(nameof(compactNodeID), $"{nameof(compactNodeID)} is an invalid node"); } var parentID = compactNodes[nodeIndex].parentID; if (parentID == CompactNodeID.Invalid) { return(-1); } var parentIndex = HierarchyIndexOfInternal(parentID); Debug.Assert(parentIndex != -1); return(SiblingIndexOfInternal(parentIndex, nodeIndex)); }
public IntersectionType Get(CompactNodeID nodeID) { var idValue = nodeID.value; idValue -= BitOffset; if (idValue < 0 || idValue >= BitCount) { //Debug.Assert(false); return(IntersectionType.InvalidValue); } idValue <<= 1; var int32Index = idValue >> 5; // divide by 32 var bitIndex = idValue & 31; // remainder var twoBit = ((uint)3) << bitIndex; var bitShifted = (uint)intersectionBits[int32Index] & (uint)twoBit; var value = (IntersectionType)((uint)bitShifted >> (int)bitIndex); Debug.Assert(value != IntersectionType.InvalidValue); return(value); }
public NodeID GetNodeIDNoErrors(CompactNodeID compactNodeID) { int nodeIndex; Debug.Assert(IsCreated); if (compactNodeID == CompactNodeID.Invalid) { return(NodeID.Invalid); } nodeIndex = HierarchyIndexOfInternalNoErrors(compactNodeID); if (nodeIndex == -1) { return(NodeID.Invalid); } if (nodeIndex < 0 || nodeIndex >= compactNodes.Length) { return(NodeID.Invalid); } return(compactNodes[nodeIndex].nodeID); }
public ref CompactNode GetChildRef(CompactNodeID compactNodeID) { return(ref UnsafeGetChildRefAtInternal(compactNodeID)); }
public void AttachToParent(CompactNodeID parentID, CompactNodeID compactNodeID) { AttachToParent(ref CompactHierarchyManager.HierarchyIDLookup, CompactHierarchyManager.HierarchyList, ref CompactHierarchyManager.NodeIDLookup, CompactHierarchyManager.Nodes, parentID, compactNodeID, ignoreBrushMeshHashes: true); }
internal ref CompactChildNode GetNodeRef(CompactNodeID compactNodeID) { return(ref UnsafeGetNodeRefAtInternal(compactNodeID)); }
public bool AttachToParentAt(CompactNodeID parentID, int index, CompactNodeID compactNodeID) { return(AttachToParentAt(ref CompactHierarchyManager.HierarchyIDLookup, CompactHierarchyManager.HierarchyList, ref CompactHierarchyManager.NodeIDLookup, CompactHierarchyManager.Nodes, parentID, index, compactNodeID)); }
internal void AttachToParent(ref IDManager hierarchyIDLookup, NativeList <CompactHierarchy> hierarchies, ref IDManager nodeIDLookup, NativeList <CompactNodeID> nodes, CompactNodeID parentID, CompactNodeID compactNodeID, bool ignoreBrushMeshHashes = false) { Debug.Assert(IsCreated); var parentIndex = HierarchyIndexOfInternal(parentID); if (parentIndex == -1) { throw new ArgumentException(nameof(parentID), $"{nameof(parentID)} is invalid"); } if (!IsValidCompactNodeID(compactNodeID)) { return; } var parentHierarchy = compactNodes[parentIndex]; var parentChildCount = parentHierarchy.childCount; AttachInternal(ref hierarchyIDLookup, hierarchies, ref nodeIDLookup, nodes, parentID, parentIndex, parentChildCount, compactNodeID, ignoreBrushMeshHashes); }
public CompactNode GetChild(CompactNodeID compactNodeID) { return(UnsafeGetChildRefAtInternal(compactNodeID)); }
internal bool AttachToParentAt(ref IDManager hierarchyIDLookup, NativeList <CompactHierarchy> hierarchies, ref IDManager nodeIDLookup, NativeList <CompactNodeID> nodes, CompactNodeID parentID, int index, CompactNodeID compactNodeID) { Debug.Assert(IsCreated); if (index < 0) { Debug.LogError("The index must be positive"); return(false); } var parentIndex = HierarchyIndexOfInternal(parentID); if (parentIndex == -1) { throw new ArgumentException(nameof(parentID), $"{nameof(parentID)} is invalid"); } if (!IsValidCompactNodeID(compactNodeID)) { return(false); } return(AttachInternal(ref hierarchyIDLookup, hierarchies, ref nodeIDLookup, nodes, parentID, parentIndex, index, compactNodeID)); }
public CompactNode GetChildAt(CompactNodeID compactNodeID, int index) { return(SafeGetChildRefAtInternal(compactNodeID, index)); }
public static ChiselBlobAssetReference <CompactTree> Create(ref CompactHierarchy compactHierarchy, NativeArray <CompactNodeID> nodes, NativeArray <CompactNodeID> brushes, CompactNodeID treeCompactNodeID) { if (brushes.Length == 0) { return(ChiselBlobAssetReference <CompactTree> .Null); } var minNodeIDValue = int.MaxValue; var maxNodeIDValue = 0; for (int b = 0; b < nodes.Length; b++) { var nodeID = nodes[b]; if (nodeID == CompactNodeID.Invalid) { continue; } var nodeIDValue = nodeID.value; minNodeIDValue = math.min(nodeIDValue, minNodeIDValue); maxNodeIDValue = math.max(nodeIDValue, maxNodeIDValue); } if (minNodeIDValue == int.MaxValue) { minNodeIDValue = 0; } var minBrushIDValue = int.MaxValue; var maxBrushIDValue = 0; for (int b = 0; b < brushes.Length; b++) { var brushCompactNodeID = brushes[b]; if (brushCompactNodeID == CompactNodeID.Invalid) { continue; } var brushCompactNodeIDValue = brushCompactNodeID.value; minBrushIDValue = math.min(brushCompactNodeIDValue, minBrushIDValue); maxBrushIDValue = math.max(brushCompactNodeIDValue, maxBrushIDValue); } if (minBrushIDValue == int.MaxValue) { minBrushIDValue = 0; } var desiredBrushIDValueToBottomUpLength = (maxBrushIDValue + 1) - minBrushIDValue; var brushIDValueToAncestorLegend = new NativeArray <int>(desiredBrushIDValueToBottomUpLength, Allocator.Temp); var brushIDValueToOrder = new NativeArray <int>(desiredBrushIDValueToBottomUpLength, Allocator.Temp); using (var brushAncestorLegend = new NativeList <BrushAncestorLegend>(brushes.Length, Allocator.Temp)) using (var brushAncestorsIDValues = new NativeList <int>(brushes.Length, Allocator.Temp)) { // Bottom-up -> per brush list of all ancestors to root for (int b = 0; b < brushes.Length; b++) { var brushCompactNodeID = brushes[b]; if (!compactHierarchy.IsValidCompactNodeID(brushCompactNodeID)) { continue; } var parentStart = brushAncestorsIDValues.Length; var parentCompactNodeID = compactHierarchy.ParentOf(brushCompactNodeID); while (compactHierarchy.IsValidCompactNodeID(parentCompactNodeID) && parentCompactNodeID != treeCompactNodeID) { var parentCompactNodeIDValue = parentCompactNodeID.value; brushAncestorsIDValues.Add(parentCompactNodeIDValue); parentCompactNodeID = compactHierarchy.ParentOf(parentCompactNodeID); } var brushCompactNodeIDValue = brushCompactNodeID.value; brushIDValueToAncestorLegend[brushCompactNodeIDValue - minBrushIDValue] = brushAncestorLegend.Length; brushIDValueToOrder[brushCompactNodeIDValue - minBrushIDValue] = b; brushAncestorLegend.Add(new BrushAncestorLegend() { ancestorEndIDValue = brushAncestorsIDValues.Length, ancestorStartIDValue = parentStart }); } var nodeQueue = new NativeList <CompactTopDownBuilderNode>(brushes.Length, Allocator.Temp); var hierarchyNodes = new NativeList <CompactHierarchyNode>(brushes.Length, Allocator.Temp); using (brushIDValueToAncestorLegend) using (brushIDValueToOrder) { if (brushAncestorLegend.Length == 0) { return(ChiselBlobAssetReference <CompactTree> .Null); } // Top-down nodeQueue.Add(new CompactTopDownBuilderNode { compactNodeID = treeCompactNodeID, compactHierarchyindex = 0 }); hierarchyNodes.Add(new CompactHierarchyNode { Type = CSGNodeType.Tree, Operation = CSGOperationType.Additive, CompactNodeID = treeCompactNodeID }); while (nodeQueue.Length > 0) { var parentItem = nodeQueue[0]; var parentCompactNodeID = parentItem.compactNodeID; nodeQueue.RemoveAt(0); var nodeCount = compactHierarchy.ChildCount(parentCompactNodeID); if (nodeCount == 0) { var item = hierarchyNodes[parentItem.compactHierarchyindex]; item.childOffset = -1; item.childCount = 0; hierarchyNodes[parentItem.compactHierarchyindex] = item; continue; } int firstCompactTreeIndex = 0; // Skip all nodes that are not additive at the start of the branch since they will never produce any geometry while (firstCompactTreeIndex < nodeCount) { var childCompactNodeID = compactHierarchy.GetChildCompactNodeIDAt(parentItem.compactNodeID, firstCompactTreeIndex); if (!compactHierarchy.IsValidCompactNodeID(childCompactNodeID)) { break; } var operation = compactHierarchy.GetOperation(childCompactNodeID); if (operation == CSGOperationType.Additive || operation == CSGOperationType.Copy) { break; } firstCompactTreeIndex++; } var firstChildIndex = hierarchyNodes.Length; for (int i = firstCompactTreeIndex; i < nodeCount; i++) { var childCompactNodeID = compactHierarchy.GetChildCompactNodeIDAt(parentItem.compactNodeID, i); // skip invalid nodes (they don't contribute to the mesh) if (!compactHierarchy.IsValidCompactNodeID(childCompactNodeID)) { continue; } var childType = compactHierarchy.GetTypeOfNode(childCompactNodeID); if (childType != CSGNodeType.Brush) { nodeQueue.Add(new CompactTopDownBuilderNode { compactNodeID = childCompactNodeID, compactHierarchyindex = hierarchyNodes.Length }); } hierarchyNodes.Add(new CompactHierarchyNode { Type = childType, Operation = compactHierarchy.GetOperation(childCompactNodeID), CompactNodeID = childCompactNodeID }); } { var item = hierarchyNodes[parentItem.compactHierarchyindex]; item.childOffset = firstChildIndex; item.childCount = hierarchyNodes.Length - firstChildIndex; hierarchyNodes[parentItem.compactHierarchyindex] = item; } } using (hierarchyNodes) using (nodeQueue) { var builder = new ChiselBlobBuilder(Allocator.Temp); ref var root = ref builder.ConstructRoot <CompactTree>(); builder.Construct(ref root.compactHierarchy, hierarchyNodes); builder.Construct(ref root.brushAncestorLegend, brushAncestorLegend); builder.Construct(ref root.brushAncestors, brushAncestorsIDValues); root.minBrushIDValue = minBrushIDValue; root.minNodeIDValue = minNodeIDValue; root.maxNodeIDValue = maxNodeIDValue; builder.Construct(ref root.brushIDValueToAncestorLegend, brushIDValueToAncestorLegend, desiredBrushIDValueToBottomUpLength); var compactTree = builder.CreateBlobAssetReference <CompactTree>(Allocator.Persistent); builder.Dispose(); return(compactTree); } } }
public CompactNodeID GetChildCompactNodeIDAt(CompactNodeID compactNodeID, int index) { return(GetChildCompactNodeIDAtInternal(compactNodeID, index)); }