NativeList(int initialCapacity, Allocator allocator, int disposeSentinelStackDepth) { var totalSize = UnsafeUtility.SizeOf <T>() * (long)initialCapacity; #if ENABLE_UNITY_COLLECTIONS_CHECKS CheckAllocator(allocator); CheckInitialCapacity(initialCapacity); CollectionHelper.CheckIsUnmanaged <T>(); CheckTotalSize(initialCapacity, totalSize); DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, disposeSentinelStackDepth, allocator); if (s_staticSafetyId.Data == 0) { CreateStaticSafetyId(); } AtomicSafetyHandle.SetStaticSafetyId(ref m_Safety, s_staticSafetyId.Data); #endif m_ListData = UnsafeList.Create(UnsafeUtility.SizeOf <T>(), UnsafeUtility.AlignOf <T>(), initialCapacity, allocator); m_DeprecatedAllocator = allocator; #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.SetBumpSecondaryVersionOnScheduleWrite(m_Safety, true); #endif }
public static unsafe void RunWithoutJobsInternal <T>(ref T jobData, ref EntityQuery query, Entity *limitToEntityArray, int limitToEntityArrayLength) where T : struct, IJobEntityBatch { var prebuiltBatchList = new UnsafeList(Allocator.TempJob); try { ChunkIterationUtility.FindFilteredBatchesForEntityArrayWithQuery( query._GetImpl(), limitToEntityArray, limitToEntityArrayLength, ref prebuiltBatchList); ArchetypeChunk *chunks = (ArchetypeChunk *)prebuiltBatchList.Ptr; int chunkCounts = prebuiltBatchList.Length; for (int i = 0; i != chunkCounts; i++) { jobData.Execute(chunks[i], i); } } finally { prebuiltBatchList.Dispose(); } }
//The thread index is passed in because otherwise job reflection can't inject it through a pointer. public void Write <T>(T value, int threadIndex) where T : unmanaged { var blockList = m_perThreadBlockLists + threadIndex; if (blockList->nextWriteAddress > blockList->lastByteAddressInBlock) { if (blockList->elementCount == 0) { blockList->blocks = new UnsafeList(m_allocator); blockList->blocks.SetCapacity <BlockPtr>(10); } BlockPtr newBlockPtr = new BlockPtr { ptr = (byte *)UnsafeUtility.Malloc(m_blockSize, UnsafeUtility.AlignOf <T>(), m_allocator) }; blockList->nextWriteAddress = newBlockPtr.ptr; blockList->lastByteAddressInBlock = newBlockPtr.ptr + m_blockSize - 1; blockList->blocks.Add(newBlockPtr); } UnsafeUtility.CopyStructureToPtr(ref value, blockList->nextWriteAddress); blockList->nextWriteAddress += m_elementSize; blockList->elementCount++; }
public static Connection Create(Peer peer) { Connection connection; connection.m_PeerPtr = peer.NativeData; connection.Id = peer.ID; connection.m_DataStream = UnsafeList.Create ( UnsafeUtility.SizeOf <byte>(), UnsafeUtility.AlignOf <byte>(), 4096, Allocator.Persistent, NativeArrayOptions.ClearMemory ); connection.m_IncomingEvents = UnsafeList.Create ( UnsafeUtility.SizeOf <DriverEvent>(), UnsafeUtility.AlignOf <DriverEvent>(), 8, Allocator.Persistent, NativeArrayOptions.ClearMemory ); return(connection); }
public unsafe static void Sort <T>(this UnsafeList list) where T : struct, IComparable <T> { list.Sort <T, DefaultComparer <T> >(new DefaultComparer <T>()); }
static bool GetExtrudedVertices(UnsafeList <SegmentVertex> shapeVertices, Range range, Matrix4x4 matrix0, Matrix4x4 matrix1, in ChiselBlobBuilder builder, ref BrushMeshBlob root, out ChiselBlobBuilderArray <float3> localVertices, out NativeArray <int> segmentIndices, Allocator allocator)
void Deallocate() { UnsafeList.Destroy(m_ListData); m_ListData = null; }
public void UnsafeListIndexOf() { int num = UnsafeList.IndexOf <long>(uList, COUNT / 3 * 2); }
/// <summary> /// Sorts a list in ascending order. /// </summary> /// <typeparam name="T">Source type of elements</typeparam> /// <param name="list">List to perform sort.</param> public unsafe static void Sort <T>(this UnsafeList <T> list) where T : unmanaged, IComparable <T> { list.Sort(new DefaultComparer <T>()); }
/// <summary> /// Adds elements from a list to this list. /// </summary> /// <typeparam name="T">Source type of elements</typeparam> /// <remarks> /// If the list has reached its current capacity, internal array won't be resized, and exception will be thrown. /// </remarks> public void AddRangeNoResize(UnsafeList list) { AddRangeNoResize(UnsafeUtility.SizeOf <T>(), UnsafeUtility.AlignOf <T>(), list.Ptr, list.Length); }
public void Execute() { var addedEntityCount = 0; var removedEntityCount = RemovedChunkEntities.Length; for (var i = 0; i < GatheredChanges.Length; i++) { var changesForChunk = GatheredChanges[i]; addedEntityCount += changesForChunk.AddedComponentEntities.Length; removedEntityCount += changesForChunk.RemovedComponentEntities.Length; } if (addedEntityCount == 0 && removedEntityCount == 0) { return; } var buffer = new UnsafeList(UnsafeUtility.SizeOf <byte>(), UnsafeUtility.AlignOf <byte>(), (addedEntityCount + removedEntityCount) * ComponentSize, Allocator); var addedComponents = new UnsafeList(UnsafeUtility.SizeOf <Entity>(), UnsafeUtility.AlignOf <Entity>(), addedEntityCount, Allocator); var removedComponents = new UnsafeList(UnsafeUtility.SizeOf <Entity>(), UnsafeUtility.AlignOf <Entity>(), removedEntityCount, Allocator); var chunksWithRemovedData = new NativeList <int>(GatheredChanges.Length, Allocator.Temp); for (var i = 0; i < GatheredChanges.Length; i++) { var changesForChunk = GatheredChanges[i]; if (changesForChunk.AddedComponentDataBuffer.IsCreated) { buffer.AddRangeNoResize <byte>(changesForChunk.AddedComponentDataBuffer.Ptr, changesForChunk.AddedComponentDataBuffer.Length); addedComponents.AddRangeNoResize <Entity>(changesForChunk.AddedComponentEntities.Ptr, changesForChunk.AddedComponentEntities.Length); changesForChunk.AddedComponentDataBuffer.Dispose(); changesForChunk.AddedComponentEntities.Dispose(); } if (changesForChunk.RemovedComponentDataBuffer.IsCreated) { chunksWithRemovedData.AddNoResize(i); } } for (var i = 0; i < chunksWithRemovedData.Length; i++) { var changesForChunk = GatheredChanges[chunksWithRemovedData[i]]; buffer.AddRangeNoResize <byte>(changesForChunk.RemovedComponentDataBuffer.Ptr, changesForChunk.RemovedComponentDataBuffer.Length); removedComponents.AddRangeNoResize <Entity>(changesForChunk.RemovedComponentEntities.Ptr, changesForChunk.RemovedComponentEntities.Length); changesForChunk.RemovedComponentDataBuffer.Dispose(); changesForChunk.RemovedComponentEntities.Dispose(); } chunksWithRemovedData.Dispose(); buffer.AddRangeNoResize <byte>(RemovedChunkComponentDataBuffer.GetUnsafeReadOnlyPtr(), RemovedChunkComponentDataBuffer.Length); removedComponents.AddRangeNoResize <Entity>(RemovedChunkEntities.GetUnsafeReadOnlyPtr(), RemovedChunkEntities.Length); Result.Value = new Result { Buffer = buffer, AddedComponents = addedComponents, RemovedComponents = removedComponents }; }
public void Execute(int index) { var chunk = Chunks[index].m_Chunk; var archetype = chunk->Archetype; var indexInTypeArray = ChunkDataUtility.GetIndexInTypeArray(archetype, TypeIndex); if (indexInTypeArray == -1) // Archetype doesn't match required component { return; } var changesForChunk = GatheredChanges + index; if (ShadowChunksBySequenceNumber.TryGetValue(chunk->SequenceNumber, out var shadow)) { if (!ChangeVersionUtility.DidChange(chunk->GetChangeVersion(indexInTypeArray), shadow.ComponentVersion) && !ChangeVersionUtility.DidChange(chunk->GetChangeVersion(0), shadow.EntityVersion)) { return; } if (!changesForChunk->AddedComponentEntities.IsCreated) { changesForChunk->AddedComponentEntities = new UnsafeList(Allocator.TempJob); changesForChunk->AddedComponentDataBuffer = new UnsafeList(Allocator.TempJob); changesForChunk->RemovedComponentEntities = new UnsafeList(Allocator.TempJob); changesForChunk->RemovedComponentDataBuffer = new UnsafeList(Allocator.TempJob); } var entityDataPtr = chunk->Buffer + archetype->Offsets[0]; var componentDataPtr = chunk->Buffer + archetype->Offsets[indexInTypeArray]; var currentCount = chunk->Count; var previousCount = shadow.Count; var i = 0; for (; i < currentCount && i < previousCount; i++) { var currentComponentData = componentDataPtr + ComponentSize * i; var previousComponentData = shadow.ComponentDataBuffer + ComponentSize * i; var entity = *(Entity *)(entityDataPtr + sizeof(Entity) * i); var previousEntity = *(Entity *)(shadow.EntityDataBuffer + sizeof(Entity) * i); if (entity != previousEntity || UnsafeUtility.MemCmp(currentComponentData, previousComponentData, ComponentSize) != 0) { // CHANGED COMPONENT DATA! OnRemovedComponent(changesForChunk, previousEntity, previousComponentData, ComponentSize); OnNewComponent(changesForChunk, entity, currentComponentData, ComponentSize); } } for (; i < currentCount; i++) { // NEW COMPONENT DATA! var entity = *(Entity *)(entityDataPtr + sizeof(Entity) * i); var currentComponentData = componentDataPtr + ComponentSize * i; OnNewComponent(changesForChunk, entity, currentComponentData, ComponentSize); } for (; i < previousCount; i++) { // REMOVED COMPONENT DATA! var entity = *(Entity *)(entityDataPtr + sizeof(Entity) * i); var previousComponentData = shadow.ComponentDataBuffer + ComponentSize * i; OnRemovedComponent(changesForChunk, entity, previousComponentData, ComponentSize); } } else { // This is a new chunk var addedComponentDataBuffer = new UnsafeList(ComponentSize, 4, chunk->Count, Allocator.TempJob); var addedComponentEntities = new UnsafeList(sizeof(Entity), 4, chunk->Count, Allocator.TempJob); var entityDataPtr = chunk->Buffer + archetype->Offsets[0]; var componentDataPtr = chunk->Buffer + archetype->Offsets[indexInTypeArray]; addedComponentDataBuffer.AddRange <byte>(componentDataPtr, chunk->Count * ComponentSize); addedComponentEntities.AddRange <Entity>(entityDataPtr, chunk->Count); changesForChunk->AddedComponentDataBuffer = addedComponentDataBuffer; changesForChunk->AddedComponentEntities = addedComponentEntities; } }
static unsafe uint GetListHash <T>(ref UnsafeList <T> list) where T : unmanaged { return(math.hash(list.Ptr, list.Length * sizeof(T))); }
public unsafe static void ReplaceIfExists(ushort *hashTable, UnsafeList <ushort> *chainedIndices, UnsafeList <float3> *vertices, float3 vertex) { var centerIndex = new int3((int)(vertex.x / HashedVertices.kCellSize), (int)(vertex.y / HashedVertices.kCellSize), (int)(vertex.z / HashedVertices.kCellSize)); var offsets = stackalloc int3[] { new int3(-1, -1, -1), new int3(-1, -1, 0), new int3(-1, -1, +1), new int3(-1, 0, -1), new int3(-1, 0, 0), new int3(-1, 0, +1), new int3(-1, +1, -1), new int3(-1, +1, 0), new int3(-1, +1, +1), new int3(0, -1, -1), new int3(0, -1, 0), new int3(0, -1, +1), new int3(0, 0, -1), new int3(0, 0, 0), new int3(0, 0, +1), new int3(0, +1, -1), new int3(0, +1, 0), new int3(0, +1, +1), new int3(+1, -1, -1), new int3(+1, -1, 0), new int3(+1, -1, +1), new int3(+1, 0, -1), new int3(+1, 0, 0), new int3(+1, 0, +1), new int3(+1, +1, -1), new int3(+1, +1, 0), new int3(+1, +1, +1) }; float3 *verticesPtr = (float3 *)vertices->Ptr; ushort closestVertexIndex = ushort.MaxValue; for (int i = 0; i < 3 * 3 * 3; i++) { var index = centerIndex + offsets[i]; var chainIndex = ((int)hashTable[GetHash(index)]) - 1; { float closestDistance = CSGConstants.kSqrVertexEqualEpsilon; while (chainIndex != -1) { var nextChainIndex = ((int)((ushort *)chainedIndices->Ptr)[chainIndex]) - 1; var sqrDistance = math.lengthsq(verticesPtr[chainIndex] - vertex); if (sqrDistance < closestDistance) { closestVertexIndex = (ushort)chainIndex; closestDistance = sqrDistance; } chainIndex = nextChainIndex; } } } if (closestVertexIndex == ushort.MaxValue) { return; } verticesPtr[closestVertexIndex] = vertex; }
// Add but make the assumption we're not growing any list public unsafe static ushort Add(ushort *hashTable, UnsafeList <ushort> *chainedIndices, UnsafeList <float3> *vertices, float3 vertex) { var centerIndex = new int3((int)(vertex.x / HashedVertices.kCellSize), (int)(vertex.y / HashedVertices.kCellSize), (int)(vertex.z / HashedVertices.kCellSize)); var offsets = stackalloc int3[] { new int3(-1, -1, -1), new int3(-1, -1, 0), new int3(-1, -1, +1), new int3(-1, 0, -1), new int3(-1, 0, 0), new int3(-1, 0, +1), new int3(-1, +1, -1), new int3(-1, +1, 0), new int3(-1, +1, +1), new int3(0, -1, -1), new int3(0, -1, 0), new int3(0, -1, +1), new int3(0, 0, -1), new int3(0, 0, 0), new int3(0, 0, +1), new int3(0, +1, -1), new int3(0, +1, 0), new int3(0, +1, +1), new int3(+1, -1, -1), new int3(+1, -1, 0), new int3(+1, -1, +1), new int3(+1, 0, -1), new int3(+1, 0, 0), new int3(+1, 0, +1), new int3(+1, +1, -1), new int3(+1, +1, 0), new int3(+1, +1, +1) }; float3 *verticesPtr = (float3 *)vertices->Ptr; ushort closestVertexIndex = ushort.MaxValue; for (int i = 0; i < 3 * 3 * 3; i++) { var index = centerIndex + offsets[i]; var chainIndex = ((int)hashTable[GetHash(index)]) - 1; { float closestDistance = CSGConstants.kSqrVertexEqualEpsilon; while (chainIndex != -1) { var nextChainIndex = ((int)((ushort *)chainedIndices->Ptr)[chainIndex]) - 1; var sqrDistance = math.lengthsq(verticesPtr[chainIndex] - vertex); if (sqrDistance < closestDistance) { closestVertexIndex = (ushort)chainIndex; closestDistance = sqrDistance; } chainIndex = nextChainIndex; } } } if (closestVertexIndex != ushort.MaxValue) { return(closestVertexIndex); } // Add Unique vertex { var hashCode = GetHash(centerIndex); var prevChainIndex = hashTable[hashCode]; var newChainIndex = chainedIndices->Length; vertices->Add(vertex); chainedIndices->Add((ushort)prevChainIndex); hashTable[(int)hashCode] = (ushort)(newChainIndex + 1); return((ushort)newChainIndex); } }
public bool ConvexPartition(int curveSegments, out UnsafeList <SegmentVertex> polygonVerticesArray, out UnsafeList <int> polygonVerticesSegments, Allocator allocator) { using (var shapeVertices = new NativeList <SegmentVertex>(Allocator.Temp)) { GetPathVertices(curveSegments, shapeVertices); //Profiler.BeginSample("ConvexPartition"); if (shapeVertices.Length == 3) { polygonVerticesArray = new UnsafeList <SegmentVertex>(3, allocator); polygonVerticesSegments = new UnsafeList <int>(1, allocator); polygonVerticesArray.Resize(3, NativeArrayOptions.UninitializedMemory); polygonVerticesArray[0] = shapeVertices[0]; polygonVerticesArray[1] = shapeVertices[1]; polygonVerticesArray[2] = shapeVertices[2]; polygonVerticesSegments.Resize(1, NativeArrayOptions.UninitializedMemory); polygonVerticesSegments[0] = polygonVerticesArray.Length; } else { polygonVerticesArray = new UnsafeList <SegmentVertex>(shapeVertices.Length * math.max(1, shapeVertices.Length / 2), allocator); polygonVerticesSegments = new UnsafeList <int>(shapeVertices.Length, allocator); if (!External.BayazitDecomposerBursted.ConvexPartition(shapeVertices, ref polygonVerticesArray, ref polygonVerticesSegments)) { polygonVerticesArray.Dispose(); polygonVerticesSegments.Dispose(); polygonVerticesArray = default; polygonVerticesSegments = default; return(false); } } for (int i = 0; i < polygonVerticesSegments.Length; i++) { var range = new Range { start = i == 0 ? 0 : polygonVerticesSegments[i - 1], end = polygonVerticesSegments[i] }; if (CalculateOrientation(polygonVerticesArray, range) < 0) { External.BayazitDecomposerBursted.Reverse(polygonVerticesArray, range); } } //Profiler.EndSample(); //Debug.Assert(polygonVerticesArray.Length == 0 || polygonVerticesArray.Length == polygonVerticesSegments[polygonVerticesSegments.Length - 1]); return(true); } }
public void Execute(int index1) { if (allTreeBrushIndexOrders.Length == rebuildTreeBrushIndexOrders.Length) { //for (int index1 = 0; index1 < updateBrushIndicesArray.Length; index1++) { var brush1IndexOrder = rebuildTreeBrushIndexOrders[index1]; int brush1NodeOrder = brush1IndexOrder.nodeOrder; var brush1Intersections = brushBrushIntersections[brush1NodeOrder]; if (!brush1Intersections.IsCreated) { brush1Intersections = new UnsafeList <BrushIntersectWith>(16, allocator); } for (int index0 = 0; index0 < rebuildTreeBrushIndexOrders.Length; index0++) { var brush0IndexOrder = rebuildTreeBrushIndexOrders[index0]; int brush0NodeOrder = brush0IndexOrder.nodeOrder; if (brush0NodeOrder <= brush1NodeOrder) { continue; } var result = IntersectionUtility.FindIntersection(brush0NodeOrder, brush1NodeOrder, ref brushMeshLookup, ref brushTreeSpaceBounds, ref transformationCache, ref transformedPlanes0, ref transformedPlanes1); if (result == IntersectionType.NoIntersection) { continue; } result = IntersectionUtility.Flip(result); IntersectionUtility.StoreIntersection(ref brush1Intersections, brush0IndexOrder, result); } brushBrushIntersections[brush1NodeOrder] = brush1Intersections; } return; } NativeCollectionHelpers.EnsureMinimumSizeAndClear(ref foundBrushes, allTreeBrushIndexOrders.Length); NativeCollectionHelpers.EnsureMinimumSizeAndClear(ref usedBrushes, allTreeBrushIndexOrders.Length); // TODO: figure out a way to avoid needing this for (int a = 0; a < rebuildTreeBrushIndexOrders.Length; a++) { foundBrushes.Set(rebuildTreeBrushIndexOrders[a].nodeOrder, true); } //for (int index1 = 0; index1 < updateBrushIndicesArray.Length; index1++) { var brush1IndexOrder = rebuildTreeBrushIndexOrders[index1]; int brush1NodeOrder = brush1IndexOrder.nodeOrder; var brush1Intersections = brushBrushIntersections[brush1NodeOrder]; if (!brush1Intersections.IsCreated) { brush1Intersections = new UnsafeList <BrushIntersectWith>(16, allocator); } for (int index0 = 0; index0 < allTreeBrushIndexOrders.Length; index0++) { var brush0IndexOrder = allTreeBrushIndexOrders[index0]; int brush0NodeOrder = brush0IndexOrder.nodeOrder; if (brush0NodeOrder == brush1NodeOrder) { continue; } var found = foundBrushes.IsSet(brush0NodeOrder); if (brush0NodeOrder < brush1NodeOrder && found) { continue; } var result = IntersectionUtility.FindIntersection(brush0NodeOrder, brush1NodeOrder, ref brushMeshLookup, ref brushTreeSpaceBounds, ref transformationCache, ref transformedPlanes0, ref transformedPlanes1); if (result == IntersectionType.NoIntersection) { continue; } if (!found) { if (!usedBrushes.IsSet(brush0IndexOrder.nodeOrder)) { usedBrushes.Set(brush0IndexOrder.nodeOrder, true); brushesThatNeedIndirectUpdateHashMap.Add(brush0IndexOrder); result = IntersectionUtility.Flip(result); IntersectionUtility.StoreIntersection(ref brush1Intersections, brush0IndexOrder, result); } } else { if (brush0NodeOrder > brush1NodeOrder) { result = IntersectionUtility.Flip(result); IntersectionUtility.StoreIntersection(ref brush1Intersections, brush0IndexOrder, result); } } } brushBrushIntersections[brush1NodeOrder] = brush1Intersections; } }
/// <summary> /// Sorts the container in ascending order. /// </summary> /// <typeparam name="T">Source type of elements</typeparam> /// <param name="container">The container to perform sort.</param> /// <param name="inputDeps">The job handle or handles for any scheduled jobs that use this container.</param> /// <returns>A new job handle containing the prior handles as well as the handle for the job that sorts /// the container.</returns> public unsafe static JobHandle Sort <T>(this UnsafeList <T> container, JobHandle inputDeps) where T : unmanaged, IComparable <T> { return(container.Sort(new DefaultComparer <T>(), inputDeps)); }
public void Dispose() { UnsafeList.Destroy(m_ListData); }
/// <summary> /// Sorts the container using a custom comparison function. /// </summary> /// <typeparam name="T">Source type of elements</typeparam> /// <typeparam name="U">The comparer type.</typeparam> /// <param name="container">The container to perform sort.</param> /// <param name="comp">A comparison function that indicates whether one element in the array is less than, equal to, or greater than another element.</param> /// <param name="inputDeps">The job handle or handles for any scheduled jobs that use this container.</param> /// <returns>A new job handle containing the prior handles as well as the handle for the job that sorts /// the container.</returns> public unsafe static JobHandle Sort <T, U>(this UnsafeList <T> container, U comp, JobHandle inputDeps) where T : unmanaged where U : IComparer <T> { return(Sort(container.Ptr, container.Length, comp, inputDeps)); }
public void Execute(int index) { var count = input.BeginForEachIndex(index); if (count == 0) { return; } var brushIndexOrder = input.Read <IndexOrder>(); var brushNodeOrder = brushIndexOrder.nodeOrder; var vertexCount = input.Read <int>(); NativeCollectionHelpers.EnsureCapacityAndClear(ref brushVertices, vertexCount); for (int v = 0; v < vertexCount; v++) { var vertex = input.Read <float3>(); brushVertices.AddNoResize(vertex); } var surfaceOuterCount = input.Read <int>(); NativeCollectionHelpers.EnsureSizeAndClear(ref surfaceLoopIndices, surfaceOuterCount); for (int o = 0; o < surfaceOuterCount; o++) { UnsafeList <int> inner = default; var surfaceInnerCount = input.Read <int>(); if (surfaceInnerCount > 0) { inner = new UnsafeList <int>(surfaceInnerCount, Allocator.Temp); //inner.ResizeUninitialized(surfaceInnerCount); for (int i = 0; i < surfaceInnerCount; i++) { inner.AddNoResize(input.Read <int>()); } } surfaceLoopIndices[o] = inner; } var surfaceLoopCount = input.Read <int>(); NativeCollectionHelpers.EnsureMinimumSizeAndClear(ref surfaceLoopAllInfos, surfaceLoopCount); NativeCollectionHelpers.EnsureSizeAndClear(ref surfaceLoopAllEdges, surfaceLoopCount); for (int l = 0; l < surfaceLoopCount; l++) { surfaceLoopAllInfos[l] = input.Read <SurfaceInfo>(); var edgeCount = input.Read <int>(); if (edgeCount > 0) { var edgesInner = new UnsafeList <Edge>(edgeCount, Allocator.Temp); //edgesInner.ResizeUninitialized(edgeCount); for (int e = 0; e < edgeCount; e++) { edgesInner.AddNoResize(input.Read <Edge>()); } surfaceLoopAllEdges[l] = edgesInner; } } input.EndForEachIndex(); if (!basePolygonCache[brushNodeOrder].IsCreated) { return; } var maxLoops = 0; var maxIndices = 0; for (int s = 0; s < surfaceLoopIndices.Length; s++) { if (!surfaceLoopIndices[s].IsCreated) { continue; } var length = surfaceLoopIndices[s].Length; maxIndices += length; maxLoops = math.max(maxLoops, length); } ref var baseSurfaces = ref basePolygonCache[brushNodeOrder].Value.surfaces;
/// <summary> /// Binary search for the value in the sorted container. /// </summary> /// <typeparam name="T">Source type of elements</typeparam> /// <param name="container">The container to perform search.</param> /// <param name="value">The value to search for.</param> /// <returns>Positive index of the specified value if value is found. Otherwise bitwise complement of index of first greater value.</returns> /// <remarks>Array must be sorted, otherwise value searched might not be found even when it is in array. IComparer corresponds to IComparer used by sort.</remarks> public static int BinarySearch <T>(this UnsafeList <T> container, T value) where T : unmanaged, IComparable <T> { return(container.BinarySearch(value, new DefaultComparer <T>())); }
public void Execute(int index) { var chunk = Chunks[index].m_Chunk; var archetype = chunk->Archetype; if (!archetype->CompareMask(QueryMask)) // Archetype doesn't match required query { return; } var changesForChunk = GatheredChanges + index; if (ShadowChunksBySequenceNumber.TryGetValue(chunk->SequenceNumber, out var shadow)) { if (!ChangeVersionUtility.DidChange(chunk->GetChangeVersion(0), shadow.Version)) { return; } if (!changesForChunk->AddedEntities.IsCreated) { changesForChunk->AddedEntities = new UnsafeList(Allocator.TempJob); changesForChunk->RemovedEntities = new UnsafeList(Allocator.TempJob); } var currentEntity = (Entity *)(chunk->Buffer + archetype->Offsets[0]); var entityFromShadow = (Entity *)shadow.EntityBuffer; var currentCount = chunk->Count; var shadowCount = shadow.Count; var i = 0; for (; i < currentCount && i < shadowCount; i++) { if (currentEntity[i] == entityFromShadow[i]) { continue; } // Was a valid entity but version was incremented, thus destroyed if (entityFromShadow[i].Version != 0) { changesForChunk->RemovedEntities.Add(entityFromShadow[i]); changesForChunk->AddedEntities.Add(currentEntity[i]); } } for (; i < currentCount; i++) { // NEW ENTITY! changesForChunk->AddedEntities.Add(currentEntity[i]); } for (; i < shadowCount; i++) { // REMOVED ENTITY! changesForChunk->RemovedEntities.Add(entityFromShadow[i]); } } else { // This is a new chunk var addedComponentEntities = new UnsafeList(sizeof(Entity), 4, chunk->Count, Allocator.TempJob); var entityDataPtr = chunk->Buffer + archetype->Offsets[0]; addedComponentEntities.AddRange <Entity>(entityDataPtr, chunk->Count); changesForChunk->AddedEntities = addedComponentEntities; } }
/// <summary> /// Binary search for the value in the sorted container. /// </summary> /// <typeparam name="T">Source type of elements</typeparam> /// <typeparam name="U">The comparer type.</typeparam> /// <param name="container">The container to perform search.</param> /// <param name="value">The value to search for.</param> /// <returns>Positive index of the specified value if value is found. Otherwise bitwise complement of index of first greater value.</returns> /// <remarks>Array must be sorted, otherwise value searched might not be found even when it is in array. IComparer corresponds to IComparer used by sort.</remarks> public unsafe static int BinarySearch <T, U>(this UnsafeList <T> container, T value, U comp) where T : unmanaged where U : IComparer <T> { return(BinarySearch(container.Ptr, container.Length, value, comp)); }
public void DestroyEntities(Entity *entities, int count) { var entityIndex = 0; var additionalDestroyList = new UnsafeList(Allocator.Persistent); int minDestroyStride = int.MaxValue; int maxDestroyStride = 0; while (entityIndex != count) { var entityBatchInChunk = GetFirstEntityBatchInChunk(entities + entityIndex, count - entityIndex); var chunk = entityBatchInChunk.Chunk; var batchCount = entityBatchInChunk.Count; var indexInChunk = entityBatchInChunk.StartIndex; if (chunk == null) { entityIndex += batchCount; continue; } AddToDestroyList(chunk, indexInChunk, batchCount, count, ref additionalDestroyList, ref minDestroyStride, ref maxDestroyStride); DestroyBatch(new EntityBatchInChunk { Chunk = chunk, StartIndex = indexInChunk, Count = batchCount }); entityIndex += batchCount; } // Apply additional destroys from any LinkedEntityGroup if (additionalDestroyList.Ptr != null) { var additionalDestroyPtr = (Entity *)additionalDestroyList.Ptr; // Optimal for destruction speed is if entities with same archetype/chunk are followed one after another. // So we lay out the to be destroyed objects assuming that the destroyed entities are "similar": // Reorder destruction by index in entityGroupArray... //@TODO: This is a very specialized fastpath that is likely only going to give benefits in the stress test. /// Figure out how to make this more general purpose. if (minDestroyStride == maxDestroyStride) { var reordered = (Entity *)UnsafeUtility.Malloc(additionalDestroyList.Length * sizeof(Entity), 16, Allocator.TempJob); int batchCount = additionalDestroyList.Length / minDestroyStride; for (int i = 0; i != batchCount; i++) { for (int j = 0; j != minDestroyStride; j++) { reordered[j * batchCount + i] = additionalDestroyPtr[i * minDestroyStride + j]; } } DestroyEntities(reordered, additionalDestroyList.Length); UnsafeUtility.Free(reordered, Allocator.TempJob); } else { DestroyEntities(additionalDestroyPtr, additionalDestroyList.Length); } UnsafeUtility.Free(additionalDestroyPtr, Allocator.Persistent); } }
/// <summary> /// Decompose the polygon into several smaller non-concave polygon. /// If the polygon is already convex, it will return the original polygon, unless it is over MaxPolygonVertices. /// </summary> public static bool ConvexPartition(NativeList <SegmentVertex> srcVertices, ref UnsafeList <SegmentVertex> outputVertices, ref UnsafeList <int> outputRanges, int defaultSegment = 0) { Debug.Assert(srcVertices.Length > 3); var allVertices = new NativeList <SegmentVertex>(Allocator.Temp); var ranges = new NativeList <Range>(Allocator.Temp); try { allVertices.AddRange(srcVertices); ranges.Add(new Range { start = 0, end = srcVertices.Length }); var originalVertexCount = srcVertices.Length * 2; int counter = 0; while (counter < ranges.Length) { var vertices = allVertices; var range = ranges[counter]; counter++; if (counter > originalVertexCount) { Debug.LogWarning($"counter > {originalVertexCount}"); return(false); } var count = range.Length; if (count == 0) { continue; } ForceCounterClockWise(vertices, range); int reflexIndex; for (reflexIndex = 0; reflexIndex < count; ++reflexIndex) { if (Reflex(reflexIndex, vertices, range)) { break; } } // Check if polygon is already convex if (reflexIndex == count) { // Check if polygon is degenerate, in which case we skip it if (math.abs(GetSignedDoubleArea(vertices, range)) <= 0.0f) { continue; } var desiredCapacity = outputVertices.Length + range.Length; if (outputVertices.Capacity < desiredCapacity) { outputVertices.Capacity = desiredCapacity; } for (int n = range.start; n < range.end; n++) { outputVertices.Add(vertices[n]); } outputRanges.Add(outputVertices.Length); continue; } int i = reflexIndex; var lowerDist = float.PositiveInfinity; var lowerInt = float2.zero; var lowerIndex = 0; var upperDist = float.PositiveInfinity; var upperInt = float2.zero; var upperIndex = 0; for (int j = 0; j < count; ++j) { // if line intersects with an edge if (Left(At(i - 1, vertices, range).position, At(i, vertices, range).position, At(j, vertices, range).position) && RightOn(At(i - 1, vertices, range).position, At(i, vertices, range).position, At(j - 1, vertices, range).position)) { // find the point of intersection var p = LineIntersect(At(i - 1, vertices, range).position, At(i, vertices, range).position, At(j, vertices, range).position, At(j - 1, vertices, range).position); if (RightOn(At(i + 1, vertices, range).position, At(i, vertices, range).position, p)) { // make sure it's inside the poly var d = SquareDist(At(i, vertices, range).position, p); if (d < lowerDist) { // keep only the closest intersection lowerDist = d; lowerInt = p; lowerIndex = j; } } } if (Left(At(i + 1, vertices, range).position, At(i, vertices, range).position, At(j + 1, vertices, range).position) && RightOn(At(i + 1, vertices, range).position, At(i, vertices, range).position, At(j, vertices, range).position)) { var p = LineIntersect(At(i + 1, vertices, range).position, At(i, vertices, range).position, At(j, vertices, range).position, At(j + 1, vertices, range).position); if (LeftOn(At(i - 1, vertices, range).position, At(i, vertices, range).position, p)) { var d = SquareDist(At(i, vertices, range).position, p); if (d < upperDist) { upperDist = d; upperIndex = j; upperInt = p; } } } } // if there are no vertices to connect to, choose a float2 in the middle if (lowerIndex == (upperIndex + 1) % count) { var sp = ((lowerInt + upperInt) / 2.0f); var newRange = Copy(i, upperIndex, vertices, range, allVertices); allVertices.Add(new SegmentVertex { position = sp, segmentIndex = defaultSegment }); newRange.end++; ranges.Add(newRange); newRange = Copy(lowerIndex, i, vertices, range, allVertices); allVertices.Add(new SegmentVertex { position = sp, segmentIndex = defaultSegment }); newRange.end++; ranges.Add(newRange); } else { double highestScore = 0; double bestIndex = lowerIndex; while (upperIndex < lowerIndex) { upperIndex += count; } for (int j = lowerIndex; j <= upperIndex; ++j) { if (!CanSee(i, j, vertices, range)) { continue; } double score = 1 / (SquareDist(At(i, vertices, range).position, At(j, vertices, range).position) + 1); if (Reflex(j, vertices, range)) { if (RightOn(At(j - 1, vertices, range).position, At(j, vertices, range).position, At(i, vertices, range).position) && LeftOn(At(j + 1, vertices, range).position, At(j, vertices, range).position, At(i, vertices, range).position)) { score += 3; } else { score += 2; } } else { score += 1; } if (score > highestScore) { bestIndex = j; highestScore = score; } } ranges.Add(Copy(i, (int)(bestIndex), vertices, range, allVertices)); ranges.Add(Copy((int)(bestIndex), i, vertices, range, allVertices)); } } return(outputRanges.Length > 0); } finally { allVertices.Dispose(); allVertices = default; ranges.Dispose(); ranges = default; } }
public List(int initialCapacity, Allocator allocator) { _list = UnsafeList.Create(UnsafeUtility.SizeOf <T>(), UnsafeUtility.AlignOf <T>(), initialCapacity, allocator); _allocator = allocator; }
public void Execute(int index) { var chunk = Chunks[index].m_Chunk; var archetype = chunk->Archetype; var indexInTypeArray = ChunkDataUtility.GetIndexInTypeArray(archetype, TypeIndex); if (indexInTypeArray == -1) // Archetype doesn't match required component { return; } var changesForChunk = GatheredChanges + index; if (ShadowChunksBySequenceNumber.TryGetValue(chunk->SequenceNumber, out var shadow)) { if (!ChangeVersionUtility.DidChange(chunk->GetChangeVersion(0), shadow.Version)) { return; } if (!changesForChunk->AddedEntities.IsCreated) { changesForChunk->Chunk = chunk; changesForChunk->AddedEntities = new UnsafeList(Allocator.TempJob); changesForChunk->RemovedEntities = new UnsafeList(Allocator.TempJob); } var entityDataPtr = (Entity *)(chunk->Buffer + archetype->Offsets[0]); var currentCount = chunk->Count; var previousCount = shadow.EntityCount; var i = 0; for (; i < currentCount && i < previousCount; i++) { var currentEntity = entityDataPtr[i]; var previousEntity = shadow.EntityDataBuffer[i]; if (currentEntity != previousEntity) { // CHANGED ENTITY! changesForChunk->RemovedEntities.Add(previousEntity); changesForChunk->AddedEntities.Add(currentEntity); } } for (; i < currentCount; i++) { // NEW ENTITY! changesForChunk->AddedEntities.Add(entityDataPtr[i]); } for (; i < previousCount; i++) { // REMOVED ENTITY! changesForChunk->RemovedEntities.Add(shadow.EntityDataBuffer[i]); } } else { // This is a new chunk var addedEntities = new UnsafeList(sizeof(Entity), 4, chunk->Count, Allocator.TempJob); var entityDataPtr = chunk->Buffer + archetype->Offsets[0]; addedEntities.AddRange <Entity>(entityDataPtr, chunk->Count); changesForChunk->Chunk = chunk; changesForChunk->AddedEntities = addedEntities; } }
public unsafe static void Sort <T, U>(this UnsafeList list, U comp) where T : struct where U : IComparer <T> { IntroSort <T, U>(list.Ptr, list.Length, comp); }
internal void Construct() { m_TypeHashToIndex = new UnsafeHashMap <long, int>(64, Allocator.Persistent); m_Delegates = new UnsafeList <UnmanagedComponentSystemDelegates>(64, Allocator.Persistent); m_DebugNames = new UnsafeList <FixedString64>(64, Allocator.Persistent); }