public static void RemoveRange <T>(this NativeListArray <T> .NativeList list, int index, int count) where T : unmanaged { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(list.m_Safety); #endif if (count == 0) { return; } if (index < 0 || index + count > list.Length) { LogRangeError(); return; } if (index == 0 && count == list.Length) { list.Clear(); return; } if (index + count < list.Length) { var listPtr = (T *)list.GetUnsafePtr(); int size = sizeof(T); UnsafeUtility.MemMove(listPtr + index, listPtr + (index + count), (list.Length - (index + count)) * size); } list.Resize(list.Length - count, NativeArrayOptions.ClearMemory); }
public int AllocateItemAndAddValues(NativeListArray <T> .NativeList other) { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndBumpSecondaryVersion(m_Safety); #endif var index = m_Array->AllocateItem(); var ptr = m_Array->Ptr[index]; if (ptr == null || !ptr->IsCreated) { m_Array->InitializeIndex(index, UnsafeUtility.SizeOf <T>(), UnsafeUtility.AlignOf <T>(), other.Length); } else { ptr->Clear(); if (ptr->Capacity < other.Length) { ptr->SetCapacity <T>(other.Length); } } #if ENABLE_UNITY_COLLECTIONS_CHECKS CheckAllocated(m_Array->Ptr[index]); var dstList = new NativeList(m_Array->Ptr[index], ref m_Safety); #else var dstList = new NativeList(m_Array->Ptr[index]); #endif dstList.AddRangeNoResize(other); return(index); }
public static void CopyFrom <T>(this NativeListArray <T> .NativeList list, NativeList <T> elements, int start, int count) where T : unmanaged { CheckLengthInRange(count, elements.Length); CheckIndexInRangeInc(start, elements.Length - count); list.Clear(); list.AddRangeNoResize((T *)elements.GetUnsafeReadOnlyPtr() + start, count); }
public static void *GetUnsafePtr <T>(this NativeListArray <T> .NativeList list) where T : unmanaged { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(list.m_Safety); #endif return(list.m_ListData->Ptr); }
/* * public static void RemoveAt<T>(this NativeListArray<T>.NativeList list, int index) * where T : unmanaged, IEquatable<T> * { * RemoveRange(list, index, 1); * } * * public static void Remove<T>(this NativeListArray<T>.NativeList list, T item) * where T : unmanaged, IEquatable<T> * { * for (int index = 0; index < list.Length; index++) * { * if (list[index].Equals(item)) * { * RemoveRange(list, index, 1); * return; * } * } * } */ public static void Remove(this NativeListArray <int> .NativeList list, int item) { for (int index = 0; index < list.Length; index++) { if (list[index] == item) { RemoveRange(list, index, 1); return; } } }
public static void Remove(this NativeListArray <Edge> .NativeList list, Edge item) { for (int index = 0; index < list.Length; index++) { if (list[index].index1 == item.index1 && list[index].index2 == item.index2) { RemoveRange(list, index, 1); return; } } }
public unsafe void ReplaceIfExists(NativeListArray <float3> .NativeList uniqueVertices) { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif // Add Unique vertex for (int i = 0; i < uniqueVertices.Length; i++) { var vertex = uniqueVertices[i]; HashedVerticesUtility.ReplaceIfExists((ushort *)m_HashTable, m_ChainedIndices, m_Vertices, vertex); } }
public static void EnsureConstantSizeAndClear <T>(ref NativeListArray <T> array, int constantSize, Allocator allocator = Allocator.Temp) where T : unmanaged { if (!array.IsCreated) { array = new NativeListArray <T>(constantSize, allocator); } else { array.ClearChildren(); } }
public static bool Contains <T>(this NativeListArray <T> .NativeList array, T item) where T : unmanaged, IEquatable <T> { for (int index = 0; index < array.Length; index++) { if (array[index].Equals(item)) { return(true); } } return(false); }
public static bool Contains(this NativeListArray <Edge> .NativeList array, Edge item) { for (int index = 0; index < array.Length; index++) { if (array[index].index1 == item.index1 && array[index].index2 == item.index2) { return(true); } } return(false); }
public static int IndexOf(NativeListArray <Edge> .NativeList edges, Edge edge, out bool inverted) { for (int e = 0; e < edges.Length; e++) { if (edges[e].index1 == edge.index1 && edges[e].index2 == edge.index2) { inverted = false; return(e); } if (edges[e].index1 == edge.index2 && edges[e].index2 == edge.index1) { inverted = true; return(e); } } inverted = false; return(-1); }
public static void EnsureSizeAndClear <T>(ref NativeListArray <T> array, int exactSize, Allocator allocator = Allocator.Temp) where T : unmanaged { if (!array.IsCreated || array.Capacity < exactSize) { if (array.IsCreated) { array.Dispose(); } array = new NativeListArray <T>(exactSize, allocator); } else { array.ClearChildren(); } array.ResizeExact(exactSize); }
public static void RemoveDuplicates(ref NativeListArray <Edge> .NativeList edges) { if (edges.Length < 3) { edges.Clear(); return; } for (int e = edges.Length - 1; e >= 0; e--) { if (edges[e].index1 != edges[e].index2) { continue; } edges.RemoveAtSwapBack(e); } }
public unsafe void AddUniqueVertices(NativeListArray <float3> .NativeList uniqueVertices) { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif // Add Unique vertex for (int i = 0; i < uniqueVertices.Length; i++) { var vertex = uniqueVertices[i]; var centerIndex = new int3((int)(vertex.x / kCellSize), (int)(vertex.y / kCellSize), (int)(vertex.z / kCellSize)); var hashCode = HashedVerticesUtility.GetHash(centerIndex); var prevChainIndex = ((ushort *)m_HashTable)[hashCode]; var newChainIndex = m_ChainedIndices->Length; m_Vertices->AddNoResize(vertex); m_ChainedIndices->AddNoResize((ushort)prevChainIndex); ((ushort *)m_HashTable)[(int)hashCode] = (ushort)(newChainIndex + 1); } }
static int IndexOf(NativeListArray <Edge> .NativeList edges, Edge edge, out bool inverted) { //var builder = new System.Text.StringBuilder(); for (int e = 0; e < edges.Length; e++) { //builder.AppendLine($"{e}/{edges.Count}: {edges[e]} {edge}"); if (edges[e].index1 == edge.index1 && edges[e].index2 == edge.index2) { inverted = false; return(e); } if (edges[e].index1 == edge.index2 && edges[e].index2 == edge.index1) { inverted = true; return(e); } } //Debug.Log(builder.ToString()); inverted = false; return(-1); }
static bool AddEdgesNoResize(NativeListArray <Edge> .NativeList dstEdges, NativeListArray <Edge> .NativeList srcEdges) { if (srcEdges.Length == 0) { return(false); } for (int ae = srcEdges.Length - 1; ae >= 0; ae--) { var addEdge = srcEdges[ae]; for (int e = dstEdges.Length - 1; e >= 0;) { if (addEdge.Equals(dstEdges[e])) { NotUniqueEdgeException(); dstEdges.RemoveAtSwapBack(e); } else { e--; } } } bool duplicates = false; for (int v = 0; v < srcEdges.Length; v++) { var addEdge = srcEdges[v]; var index = IndexOf(dstEdges, addEdge, out bool _); if (index != -1) { //Debug.Log($"Duplicate edge {inverted} {values[v].index1}/{values[v].index2} {edges[index].index1}/{edges[index].index2}"); duplicates = true; continue; } dstEdges.AddNoResize(addEdge); } return(duplicates); }
public JobHandle Dispose(JobHandle dependency) { JobHandle lastJobHandle = default; if (meshDescriptions.IsCreated) { lastJobHandle = JobHandle.CombineDependencies(lastJobHandle, meshDescriptions.Dispose(dependency)); } if (subMeshSections.IsCreated) { lastJobHandle = JobHandle.CombineDependencies(lastJobHandle, subMeshSections.Dispose(dependency)); } if (meshes.IsCreated) { lastJobHandle = JobHandle.CombineDependencies(lastJobHandle, meshes.Dispose(dependency)); } if (triangleBrushIndices.IsCreated) { lastJobHandle = JobHandle.CombineDependencies(lastJobHandle, triangleBrushIndices.Dispose(dependency)); } if (renderDescriptors.IsCreated) { lastJobHandle = JobHandle.CombineDependencies(lastJobHandle, renderDescriptors.Dispose(dependency)); } if (colliderDescriptors.IsCreated) { lastJobHandle = JobHandle.CombineDependencies(lastJobHandle, colliderDescriptors.Dispose(dependency)); } meshDescriptions = default; subMeshSections = default; meshes = default; triangleBrushIndices = default; renderDescriptors = default; colliderDescriptors = default; return(lastJobHandle); }
public void EnsureInitialized() { if (!meshDescriptions.IsCreated) { meshDescriptions = new NativeList <GeneratedMeshDescription>(Allocator.Persistent); } else { meshDescriptions.Clear(); } if (!subMeshSections.IsCreated) { subMeshSections = new NativeList <SubMeshSection>(Allocator.Persistent); } else { subMeshSections.Clear(); } if (!meshes.IsCreated) { meshes = new NativeList <Mesh.MeshData>(Allocator.Persistent); } if (!triangleBrushIndices.IsCreated) { triangleBrushIndices = new NativeListArray <int>(Allocator.Persistent); } if (!renderDescriptors.IsCreated) { renderDescriptors = new NativeArray <VertexAttributeDescriptor>(s_RenderDescriptors, Allocator.Persistent); } if (!colliderDescriptors.IsCreated) { colliderDescriptors = new NativeArray <VertexAttributeDescriptor>(s_ColliderDescriptors, Allocator.Persistent); } }
public void Execute(int index) { //var brushNodeIndex = treeBrushNodeIndices[index]; var count = input.BeginForEachIndex(index); if (count == 0) { return; } HashedVertices brushVertices; NativeListArray <int> surfaceLoopIndices; NativeList <SurfaceInfo> surfaceLoopAllInfos; NativeListArray <Edge> surfaceLoopAllEdges; var brushNodeIndex = input.Read <int>(); var vertexCount = input.Read <int>(); brushVertices = new HashedVertices(vertexCount, allocator); for (int v = 0; v < vertexCount; v++) { var vertex = input.Read <float3>(); brushVertices.AddNoResize(vertex); } var surfaceOuterCount = input.Read <int>(); surfaceLoopIndices = new NativeListArray <int>(surfaceOuterCount, allocator); surfaceLoopIndices.ResizeExact(surfaceOuterCount); for (int o = 0; o < surfaceOuterCount; o++) { var surfaceInnerCount = input.Read <int>(); if (surfaceInnerCount > 0) { var inner = surfaceLoopIndices.AllocateWithCapacityForIndex(o, surfaceInnerCount); //inner.ResizeUninitialized(surfaceInnerCount); for (int i = 0; i < surfaceInnerCount; i++) { inner.AddNoResize(input.Read <int>()); } } } var surfaceLoopCount = input.Read <int>(); surfaceLoopAllInfos = new NativeList <SurfaceInfo>(surfaceLoopCount, allocator); surfaceLoopAllEdges = new NativeListArray <Edge>(surfaceLoopCount, allocator); surfaceLoopAllInfos.ResizeUninitialized(surfaceLoopCount); surfaceLoopAllEdges.ResizeExact(surfaceLoopCount); for (int l = 0; l < surfaceLoopCount; l++) { surfaceLoopAllInfos[l] = input.Read <SurfaceInfo>(); var edgeCount = input.Read <int>(); if (edgeCount > 0) { var edgesInner = surfaceLoopAllEdges.AllocateWithCapacityForIndex(l, edgeCount); //edgesInner.ResizeUninitialized(edgeCount); for (int e = 0; e < edgeCount; e++) { edgesInner.AddNoResize(input.Read <Edge>()); } } } input.EndForEachIndex(); var maxLoops = 0; var maxIndices = 0; for (int s = 0; s < surfaceLoopIndices.Length; s++) { if (!surfaceLoopIndices.IsIndexCreated(s)) { continue; } var length = surfaceLoopIndices[s].Length; maxIndices += length; maxLoops = math.max(maxLoops, length); } ref var baseSurfaces = ref basePolygons[brushNodeIndex].Value.surfaces;
public void AddRangeNoResize(NativeListArray <T> .NativeList list) { AddRangeNoResize(list.GetUnsafeReadOnlyPtr(), list.Length); }
void CopyFrom(NativeListArray <Edge> dst, int index, ref BrushIntersectionLoop brushIntersectionLoop, HashedVertices hashedTreeSpaceVertices, int extraCapacity) { ref var vertexIndex = ref brushIntersectionLoop.loopVertexIndex;
void IntersectLoopsJob(HashedVertices brushVertices, NativeListArray <int> .NativeList loopIndices, int surfaceLoopIndex, NativeListArray <int> holeIndices, NativeList <SurfaceInfo> allInfos, NativeListArray <Edge> allEdges, NativeListArray <Edge> .NativeList intersectionLoop, CategoryGroupIndex intersectionCategory, SurfaceInfo intersectionInfo) { if (intersectionLoop.Length == 0) { return; } //Debug.Assert(allEdges.Length == allInfos.Length); //Debug.Assert(allInfos.Length == holeIndices.Length); var currentLoopEdges = allEdges[surfaceLoopIndex]; var currentInfo = allInfos[surfaceLoopIndex]; var currentHoleIndices = holeIndices[surfaceLoopIndex]; // It might look like we could just set the interiorCategory of brush_intersection here, and let all other cut loops copy from it below, // but the same brush_intersection might be used by another categorized_loop and then we'd try to reroute it again, which wouldn't work //brush_intersection.interiorCategory = newHoleCategory; if (currentLoopEdges.Length == 0) { return; } var maxLength = math.max(intersectionLoop.Length, currentLoopEdges.Length); if (maxLength < 3) { return; } int inside2 = 0, outside2 = 0; var categories2 = stackalloc EdgeCategory[currentLoopEdges.Length]; var treeSpacePlanes1 = brushTreeSpacePlanes[intersectionInfo.brushNodeIndex]; for (int e = 0; e < currentLoopEdges.Length; e++) { var category = BooleanEdgesUtility.CategorizeEdge(currentLoopEdges[e], ref treeSpacePlanes1.Value.treeSpacePlanes, intersectionLoop, brushVertices); categories2[e] = category; if (category == EdgeCategory.Inside) { inside2++; } else if (category == EdgeCategory.Outside) { outside2++; } } var aligned2 = currentLoopEdges.Length - (inside2 + outside2); int inside1 = 0, outside1 = 0; var categories1 = stackalloc EdgeCategory[intersectionLoop.Length]; var treeSpacePlanes2 = brushTreeSpacePlanes[currentInfo.brushNodeIndex]; for (int e = 0; e < intersectionLoop.Length; e++) { var category = BooleanEdgesUtility.CategorizeEdge(intersectionLoop[e], ref treeSpacePlanes2.Value.treeSpacePlanes, currentLoopEdges, brushVertices); categories1[e] = category; if (category == EdgeCategory.Inside) { inside1++; } else if (category == EdgeCategory.Outside) { outside1++; } } var aligned1 = intersectionLoop.Length - (inside1 + outside1); // Completely outside if ((inside1 + aligned1) == 0 && (aligned2 + inside2) == 0) { return; } if ((inside1 + (inside2 + aligned2)) < 3) { return; } // Completely aligned if (((outside1 + inside1) == 0 && (outside2 + inside2) == 0) || // polygon1 edges Completely inside polygon2 (inside1 == 0 && outside2 == 0)) { // New polygon overrides the existing polygon currentInfo.interiorCategory = intersectionCategory; allInfos[surfaceLoopIndex] = currentInfo; //Debug.Assert(holeIndices.IsAllocated(surfaceLoopIndex)); return; } var outEdges = stackalloc Edge[maxLength]; var outEdgesLength = 0; // polygon2 edges Completely inside polygon1 if (outside1 == 0 && inside2 == 0) { // polygon1 Completely inside polygon2 for (int n = 0; n < intersectionLoop.Length; n++) { outEdges[outEdgesLength] = intersectionLoop[n]; outEdgesLength++; } //OperationResult.Polygon1InsidePolygon2; } else { //int outEdgesLength = 0; // Can't read from outEdges.Length since it's marked as WriteOnly for (int e = 0; e < intersectionLoop.Length; e++) { var category = categories1[e]; if (category == EdgeCategory.Inside) { outEdges[outEdgesLength] = intersectionLoop[e]; outEdgesLength++; } } for (int e = 0; e < currentLoopEdges.Length; e++) { var category = categories2[e]; if (category != EdgeCategory.Outside) { outEdges[outEdgesLength] = currentLoopEdges[e]; outEdgesLength++; } } //OperationResult.Cut; } if (outEdgesLength < 3) { return; } // FIXME: when brush_intersection and categorized_loop are grazing each other, // technically we cut it but we shouldn't be creating it as a separate polygon + hole (bug7) // the output of cutting operations are both holes for the original polygon (categorized_loop) // and new polygons on the surface of the brush that need to be categorized intersectionInfo.interiorCategory = intersectionCategory; if (currentHoleIndices.Length > 0 && // TODO: fix touching not being updated properly brushesTouchedByBrushes.ContainsKey(currentInfo.brushNodeIndex)) { // Figure out why this is seemingly not necessary? var intersectedHoleIndices = stackalloc int[currentHoleIndices.Length]; var intersectedHoleIndicesLength = 0; // the output of cutting operations are both holes for the original polygon (categorized_loop) // and new polygons on the surface of the brush that need to be categorized ref var brushesTouchedByBrush = ref brushesTouchedByBrushes[currentInfo.brushNodeIndex].Value; ref var brushIntersections = ref brushesTouchedByBrushes[currentInfo.brushNodeIndex].Value.brushIntersections;
public static void AddRangeNoResize <T>(this NativeList <T> list, NativeListArray <T> .NativeList elements) where T : unmanaged { list.AddRangeNoResize(elements.GetUnsafeReadOnlyPtr(), elements.Length); }