Ejemplo n.º 1
0
            public static unsafe void Execute(ref NativeMultiHashMapVisitKeyMutableValueJobStruct <TJob, TKey, TValue> fullData, IntPtr additionalPtr, IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex)
            {
                while (true)
                {
                    int begin;
                    int end;

                    if (!JobsUtility.GetWorkStealingRange(ref ranges, jobIndex, out begin, out end))
                    {
                        return;
                    }

                    var buckets  = (int *)fullData.HashMap.m_MultiHashMapData.m_Buffer->buckets;
                    var nextPtrs = (int *)fullData.HashMap.m_MultiHashMapData.m_Buffer->next;
                    var keys     = fullData.HashMap.m_MultiHashMapData.m_Buffer->keys;
                    var values   = fullData.HashMap.m_MultiHashMapData.m_Buffer->values;

                    for (int i = begin; i < end; i++)
                    {
                        int entryIndex = buckets[i];

                        while (entryIndex != -1)
                        {
                            var key = UnsafeUtility.ReadArrayElement <TKey>(keys, entryIndex);

                            fullData.JobData.ExecuteNext(key, ref UnsafeUtilityEx.ArrayElementAsRef <TValue>(values, entryIndex));

                            entryIndex = nextPtrs[entryIndex];
                        }
                    }
                }
            }
Ejemplo n.º 2
0
            static unsafe void ExecuteInnerLoop(ref JobStruct_Process1 <T, U0> jobData, int begin, int end)
            {
                ComponentChunkCache cache0;

                while (begin != end)
                {
                    jobData.Iterator.Iterator0.UpdateCache(begin, out cache0);
                    var ptr0 = UnsafeUtilityEx.RestrictNoAlias(cache0.CachedPtr);

                    var curEnd = Math.Min(end, cache0.CachedEndIndex);

                    for (var i = begin; i != curEnd; i++)
                    {
#if CSHARP_7_OR_LATER
                        ref var value0 = ref UnsafeUtilityEx.ArrayElementAsRef <U0>(ptr0, i);
                        jobData.Data.Execute(ref value0);
#else
                        var value0 = UnsafeUtility.ReadArrayElement <U0>(ptr0, i);

                        jobData.Data.Execute(ref value0);

                        if (jobData.Iterator.IsReadOnly0 == 0)
                        {
                            UnsafeUtility.WriteArrayElement(ptr0, i, value0);
                        }
#endif
                    }

                    begin = curEnd;
                }
Ejemplo n.º 3
0
        public void RangeQuery(AABB bounds, NativeList <OctElement <T> > results)
        {
            var targetBounds = new Aabb {
                Min = bounds.Min, Max = bounds.Max
            };
            var outputResults = (UnsafeList *)NativeListUnsafeUtility.GetInternalListDataPtrUnchecked(ref results);

            if (Data->TotalElements > outputResults->Capacity)
            {
                // todo: find out why its possible to return more elements than exists
                // should be able to use 'TotalElements' for capacity here. 10/100 work,
                // but 1000 yields 1012-1018 elements...
                outputResults->Resize <OctElement <T> >(Data->TotalElements * 2);
            }

            var resultsPtr = (byte *)outputResults->Ptr;
            var nodesPtr   = (byte *)Data->Nodes->Ptr;
            var elementPtr = (byte *)Data->Elements->Ptr;
            var quadPtr    = (byte *)Data->Quads->Ptr;

            var quadCount = Data->Quads->Length;
            var maxLeaves = quadCount * 16 * Data->TotalDepth;

            int resultCount  = 0;
            int containCount = 0;
            int overlapCount = 0;

            // Work around c# enforcing use of Span<T>.
            var useStack = maxLeaves <= 256;
            var size     = useStack ? sizeof(int) * maxLeaves : 1;
            var ptr1     = stackalloc int[size];
            var ptr2     = stackalloc int[size];

            size = sizeof(int) * maxLeaves;
            var containOffsets = useStack ? ptr1 : (int *)UnsafeUtility.Malloc(size, sizeof(int), Allocator.Temp);
            var overlapOffsets = useStack ? ptr2 : (int *)UnsafeUtility.Malloc(size, sizeof(int), Allocator.Temp);

            for (int i = 0; i < quadCount; i++)
            {
                QuadGroup quad = *(QuadGroup *)(quadPtr + i * sizeof(QuadGroup));

                bool4 isContainedA       = quad.Bounds.ContainedBy(targetBounds);
                bool4 isOverlapA         = quad.Bounds.OverlappedBy(targetBounds);
                bool4 skipMaskA          = !isContainedA & !isOverlapA;
                bool4 containedLeafMaskA = !skipMaskA & isContainedA;
                bool4 intersectedMaskA   = !containedLeafMaskA & isOverlapA;

                containCount = compress(containOffsets, containCount, quad.Offsets, containedLeafMaskA);
                overlapCount = compress(overlapOffsets, overlapCount, quad.Offsets, intersectedMaskA);
            }

            for (int i = 0; i < containCount; i++)
            {
                ref var node = ref UnsafeUtilityEx.ArrayElementAsRef <OctNode>(nodesPtr, containOffsets[i]);
                var     src  = elementPtr + node.firstChildIndex * UnsafeUtility.SizeOf <OctElement <T> >();
                var     dst  = resultsPtr + resultCount * UnsafeUtility.SizeOf <OctElement <T> >();
                UnsafeUtility.MemCpy(dst, src, node.count * UnsafeUtility.SizeOf <OctElement <T> >());
                resultCount += node.count;
            }
Ejemplo n.º 4
0
 public void FromArrayUnsafe(T[] array)
 {
     Length = array.Length;
     for (var i = 0; i < Length; i++)
     {
         UnsafeUtilityEx.ArrayElementAsRef <T>(ArrayDataPtr, i) = array[i];
     }
 }
        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            var random          = new Unity.Mathematics.Random(RandomSeed);
            var index           = chunk.GetSharedComponentIndex(SpriteAnimationChunkType);
            var spriteAnimation = UniqueSpriteAnimations[index];
            var entities        = chunk.GetNativeArray(EntityChunkType);
            var states          = chunk.GetNativeArray(SpriteAnimationStateChunkType).GetUnsafePtr();
            var randomizers     = chunk.GetNativeArray(SpriteAnimationRandomizerChunkType);

            for (var i = 0; i < chunk.Count; ++i)
            {
                spriteAnimation.ClipIndex = random.NextInt(0, spriteAnimation.ClipCount);
                SpriteAnimationMap.TryAdd(entities[i], spriteAnimation);
                UnsafeUtilityEx.ArrayElementAsRef <SpriteAnimationState>(states, i).Speed =
                    random.NextFloat(randomizers[i].RandomSpeedStart, randomizers[i].RandomSpeedEnd);
            }
        }
Ejemplo n.º 6
0
        protected override unsafe void OnUpdate()
        {
            var typeMoveCommand     = GetArchetypeChunkComponentType <MoveCommand>(true);
            var typeDestroyable     = GetArchetypeChunkComponentType <DestroyableComponentData>();
            var typeTicks           = GetArchetypeChunkComponentType <DateTimeTicksToProcess>(true);
            var typeTeamTag         = GetArchetypeChunkComponentType <TeamTag>(true);
            var typePhysicsVelocity = GetArchetypeChunkComponentType <PhysicsVelocity>();
            var currentTicks        = DateTime.Now.Ticks;

            using (var moveCommandChunks = _queryMoveCommand.CreateArchetypeChunkArray(Allocator.TempJob))
                using (var velocitiesChunks = _query.CreateArchetypeChunkArray(Allocator.TempJob))
                {
                    foreach (var moveCommandChunk in moveCommandChunks)
                    {
                        var moveCommands = moveCommandChunk.GetNativeArray(typeMoveCommand);
                        var destroys     = moveCommandChunk.GetNativeArray(typeDestroyable);
                        var ticks        = moveCommandChunk.GetNativeArray(typeTicks);
                        for (var i = 0; i < ticks.Length; i++)
                        {
                            if (ticks[i].Value < currentTicks || destroys[i].ShouldDestroy)
                            {
                                continue;
                            }
                            destroys[i] = new DestroyableComponentData()
                            {
                                ShouldDestroy = true
                            };
                            foreach (var velocitiesChunk in velocitiesChunks)
                            {
                                var teamTags          = velocitiesChunk.GetNativeArray(typeTeamTag);
                                var physicsVelocities = velocitiesChunk.GetNativeArray(typePhysicsVelocity);
                                for (var j = 0; j < teamTags.Length; j++)
                                {
                                    if (teamTags[j].Id != moveCommands[i].Id)
                                    {
                                        continue;
                                    }
                                    UnsafeUtilityEx
                                    .ArrayElementAsRef <PhysicsVelocity>(NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(physicsVelocities), j)
                                    .Linear += moveCommands[i].DeltaVelocity;
                                }
                            }
                        }
                    }
                }
        }
Ejemplo n.º 7
0
            private static unsafe void ExecuteInnerLoopByChunk(ref JobStruct_Process1 <T, U0> jobData, int begin,
                                                               int end)
            {
                ComponentChunkCache cache0;

                for (var blockIndex = begin; blockIndex != end; ++blockIndex)
                {
                    jobData.Iterator.Iterator0.MoveToChunkByIndex(blockIndex);

                    var processBlock = false;

                    processBlock |= jobData.Iterator.IsChangedFilter0 != 0 &&
                                    jobData.Iterator.Iterator0.IsCurrentChunkChanged();

                    if (!processBlock)
                    {
                        continue;
                    }

                    jobData.Iterator.Iterator0.UpdateCacheToCurrentChunk(out cache0, jobData.Iterator.IsReadOnly0 == 0);
                    var ptr0 = UnsafeUtilityEx.RestrictNoAlias(cache0.CachedPtr);

                    for (var i = cache0.CachedBeginIndex; i != cache0.CachedEndIndex; i++)
                    {
#if CSHARP_7_OR_LATER
                        ref var value0 = ref UnsafeUtilityEx.ArrayElementAsRef <U0>(ptr0, i);
                        jobData.Data.Execute(ref value0);
#else
                        var value0 = UnsafeUtility.ReadArrayElement <U0>(ptr0, i);

                        jobData.Data.Execute(ref value0);

                        if (jobData.Iterator.IsReadOnly0 == 0)
                        {
                            UnsafeUtility.WriteArrayElement(ptr0, i, value0);
                        }
#endif
                    }
                }
 public static unsafe ref T ArrayElementAsRef <T>(byte *offsetPtr, int index) where T : struct => ref UnsafeUtilityEx.ArrayElementAsRef <T>(offsetPtr, index);
Ejemplo n.º 9
0
        public static void MoveChunks(EntityManager srcEntities, ArchetypeManager dstArchetypeManager,
                                      EntityGroupManager dstGroupManager, EntityDataManager *dstEntityDataManager, SharedComponentDataManager dstSharedComponents)
        {
            var srcArchetypeManager  = srcEntities.ArchetypeManager;
            var srcEntityDataManager = srcEntities.Entities;
            var srcSharedComponents  = srcEntities.m_SharedComponentManager;

            var entityRemapping = new NativeArray <EntityRemapUtility.EntityRemapInfo>(srcEntityDataManager->Capacity, Allocator.Temp);

            dstEntityDataManager->AllocateEntitiesForRemapping(srcEntityDataManager, ref entityRemapping);
            srcEntityDataManager->FreeAllEntities();

            var samplerShared = CustomSampler.Create("MoveAllSharedComponents");

            samplerShared.Begin();
            var remapShared = dstSharedComponents.MoveAllSharedComponents(srcSharedComponents, Allocator.Temp);

            samplerShared.End();

            Archetype *srcArchetype;

            int chunkCount     = 0;
            int archetypeCount = 0;

            srcArchetype = srcArchetypeManager.m_LastArchetype;
            while (srcArchetype != null)
            {
                archetypeCount++;
                chunkCount  += srcArchetype->ChunkCount;
                srcArchetype = srcArchetype->PrevArchetype;
            }

            var remapChunks     = new NativeArray <RemapChunk>(chunkCount, Allocator.Temp);
            var remapArchetypes = new NativeArray <RemapArchetype>(archetypeCount, Allocator.Temp);

            int chunkIndex     = 0;
            int archetypeIndex = 0;

            srcArchetype = srcArchetypeManager.m_LastArchetype;
            while (srcArchetype != null)
            {
                if (srcArchetype->ChunkCount != 0)
                {
                    if (srcArchetype->NumManagedArrays != 0)
                    {
                        throw new ArgumentException("MoveEntitiesFrom is not supported with managed arrays");
                    }

                    var dstArchetype = dstArchetypeManager.GetOrCreateArchetype(srcArchetype->Types, srcArchetype->TypesCount, dstGroupManager);

                    remapArchetypes[archetypeIndex] = new RemapArchetype {
                        srcArchetype = srcArchetype, dstArchetype = dstArchetype
                    };

                    for (var c = srcArchetype->ChunkList.Begin; c != srcArchetype->ChunkList.End; c = c->Next)
                    {
                        remapChunks[chunkIndex] = new RemapChunk {
                            chunk = (Chunk *)c, dstArchetype = dstArchetype
                        };
                        chunkIndex++;
                    }

                    archetypeIndex++;

                    dstEntityDataManager->IncrementComponentTypeOrderVersion(dstArchetype);
                }

                srcArchetype = srcArchetype->PrevArchetype;
            }

            for (int j = 0; j < remapChunks.Length; j++)
            {
                ref RemapChunk remapChunk   = ref UnsafeUtilityEx.ArrayElementAsRef <RemapChunk>(remapChunks.GetUnsafePtr(), j);
                ref Chunk *    chunk        = ref remapChunk.chunk;
Ejemplo n.º 10
0
 public ref   Aabb4 this[int i]
 => ref UnsafeUtilityEx.ArrayElementAsRef <Aabb4>(UnsafeUtility.AddressOf(ref this), i);
Ejemplo n.º 11
0
 public ref            T this[int index] => ref UnsafeUtilityEx.ArrayElementAsRef <T>((byte *)m_OffsetPtr + *m_OffsetPtr, index);
Ejemplo n.º 12
0
 public ref             T this[int x, int y]
 => ref UnsafeUtilityEx.ArrayElementAsRef <T>(_ptr, CalculateIndex(x, y));
Ejemplo n.º 13
0
 public ref             T this[int i]
 => ref UnsafeUtilityEx.ArrayElementAsRef <T>(_ptr, i);
Ejemplo n.º 14
0
 public ref       Keyframe this[int index] => ref UnsafeUtilityEx.ArrayElementAsRef <Keyframe>(array, index);
Ejemplo n.º 15
0
        protected override void OnUpdate()
        {
            //EntityManager.CompleteAllJobs();

            var batchCount = Data.Batches.Length;
            var batchesPtr = (byte *)Data.Batches.Ptr;
            var dataPtr    = (byte *)_dataPtr;

            Job.WithCode(() =>
            {
                ref var data = ref UnsafeUtilityEx.AsRef <EventSystemData>(dataPtr);

                data.StructuralChanges.Clear();
                data.EntityCount = 0;
                data.HasChanged  = false;

                // Process Queues

                for (var i = 0; i < data.Batches.Length; i++)
                {
                    ref var batch = ref UnsafeUtilityEx.ArrayElementAsRef <EventBatch>(batchesPtr, i);

                    var requiredEntities = batch.ComponentQueue.Count();
                    data.EntityCount    += requiredEntities;
                    batch.HasChanged     = batch.EntityCount != requiredEntities;

                    if (!batch.HasChanged)
                    {
                        continue;
                    }

                    data.HasChanged   = true;
                    batch.EntityCount = requiredEntities;

                    if (requiredEntities == 0)
                    {
                        // Deactivate all
                        if (batch.ActiveChunks.ChunkCount != 0)
                        {
                            data.StructuralChanges.AddComponentToChunks.Add(new AddComponentChunkOp
                            {
                                Chunks    = batch.ActiveArchetypeChunks.Ptr,
                                Count     = batch.ActiveArchetypeChunks.Length,
                                TypeIndex = data.DisabledTypeIndex,
                            });
                        }
                        continue;
                    }

                    var capacity                   = batch.Archetype.ChunkCapacity;
                    var requiredFullChunks         = requiredEntities / capacity;
                    var fitsExactlyInChunkCapacity = requiredEntities % capacity == 0;
                    var requiredPartialChunks      = fitsExactlyInChunkCapacity ? 0 : 1;
                    var requiredChunks             = requiredFullChunks + requiredPartialChunks;
                    var remainingEntities          = requiredEntities;
                    var remainingInactiveFulls     = batch.InactiveFullArchetypeChunks.Length;

                    if (requiredFullChunks > 0)
                    {
                        var remainingFullChunks = requiredFullChunks;

                        // Keep full active chunks
                        if (batch.ActiveFullArchetypeChunks.Length != 0)
                        {
                            var kept             = math.min(remainingFullChunks, batch.ActiveFullArchetypeChunks.Length);
                            remainingFullChunks -= kept;

                            var excessActiveChunks = batch.ActiveFullArchetypeChunks.Length - kept;
                            if (excessActiveChunks != 0)
                            {
                                // Deactivate excess
                                data.StructuralChanges.AddComponentToChunks.Add(new AddComponentChunkOp
                                {
                                    Chunks    = batch.ActiveFullArchetypeChunks.Ptr,
                                    Count     = excessActiveChunks,
                                    TypeIndex = data.DisabledTypeIndex,
                                });
                            }
                        }

                        if (batch.ActivePartialArchetypeChunk.Length != 0)
                        {
                            // Deactivate partial chunks
                            data.StructuralChanges.AddComponentToChunks.Add(new AddComponentChunkOp
                            {
                                Chunks    = batch.ActivePartialArchetypeChunk.Ptr,
                                Count     = batch.ActivePartialArchetypeChunk.Length,
                                TypeIndex = data.DisabledTypeIndex,
                            });
                        }

                        // Activate inactive full chunks
                        if (remainingFullChunks > 0 && remainingInactiveFulls != 0)
                        {
                            var conversionCount = math.min(remainingFullChunks, batch.InactiveFullArchetypeChunks.Length);
                            data.StructuralChanges.RemoveComponentFromChunks.Add(new RemoveComponentChunkOp
                            {
                                Chunks    = batch.InactiveFullArchetypeChunks.Ptr,
                                TypeIndex = data.DisabledTypeIndex,
                                Count     = conversionCount,
                            });
                            remainingInactiveFulls -= conversionCount;
                            remainingFullChunks    -= conversionCount;
                        }

                        remainingEntities -= (requiredFullChunks - remainingFullChunks) * capacity;
                    }
                    else if (batch.ActiveArchetypeChunks.Length != 0)
                    {
                        // Deactivate all active chunks
                        data.StructuralChanges.AddComponentToChunks.Add(new AddComponentChunkOp
                        {
                            Chunks    = batch.ActiveArchetypeChunks.Ptr,
                            Count     = batch.ActiveArchetypeChunks.Length,
                            TypeIndex = data.DisabledTypeIndex,
                        });
                    }

                    if (remainingEntities > 0 && batch.InactiveChunks.ChunkCount != 0)
                    {
                        // Create from inactive partials
                        if (batch.InactivePartialArchetypeChunk.Length != 0)
                        {
                            var batchInChunks = new NativeList <EntityBatchInChunkProxy>(Allocator.Temp);
                            for (var j = 0; j < batch.InactivePartialArchetypeChunk.Length; j++)
                            {
                                var archetypeChunk = ((ArchetypeChunk *)batch.InactivePartialArchetypeChunk.Ptr)[j];
                                var amountToMove   = math.min(archetypeChunk.Count, remainingEntities);
                                var entityBatch    = new EntityBatchInChunkProxy
                                {
                                    ChunkPtr   = archetypeChunk.GetChunkPtr(),
                                    Count      = amountToMove,
                                    StartIndex = 0,
                                };
                                batchInChunks.Add(entityBatch);
                                remainingEntities -= amountToMove;
                                if (remainingEntities == 0)
                                {
                                    break;
                                }
                            }

                            data.StructuralChanges.RemoveComponentBatches.Add(new RemoveComponentBatchOp
                            {
                                EntityBatches = batchInChunks.AsParallelWriter().ListData,
                                TypeIndex     = data.DisabledTypeIndex,
                            });
                        }

                        // Create from inactive fulls
                        if (remainingEntities > 0 && remainingInactiveFulls != 0)
                        {
                            var batchInChunks = new NativeList <EntityBatchInChunkProxy>(Allocator.Temp);
                            for (var j = remainingInactiveFulls - 1; j == -1; j--)
                            {
                                var archetypeChunk = ((ArchetypeChunk *)batch.InactiveFullArchetypeChunks.Ptr)[j];
                                var amountToMove   = math.min(archetypeChunk.Count, remainingEntities);
                                var entityBatch    = new EntityBatchInChunkProxy
                                {
                                    ChunkPtr   = archetypeChunk.GetChunkPtr(),
                                    Count      = amountToMove,
                                    StartIndex = 0,
                                };
                                batchInChunks.Add(entityBatch);
                                remainingEntities -= amountToMove;
                                if (remainingEntities == 0)
                                {
                                    break;
                                }
                            }

                            data.StructuralChanges.RemoveComponentBatches.Add(new RemoveComponentBatchOp
                            {
                                EntityBatches = batchInChunks.AsParallelWriter().ListData,
                                TypeIndex     = data.DisabledTypeIndex,
                            });
                        }
                    }

                    if (remainingEntities != 0)
                    {
                        data.StructuralChanges.CreateChunks.Add(new CreateChunksOp
                        {
                            Archetype   = batch.Archetype,
                            EntityCount = remainingEntities,
                        });
                    }
                }
Ejemplo n.º 16
0
        public void ClearAndBulkInsert(NativeArray <OctElement <T> > incomingElements)
        {
            // Always have to clear before bulk insert as otherwise the lookup and node
            // allocations need to account for existing data.
            Clear();

            if (Data->Elements->Capacity < Data->TotalElements + incomingElements.Length)
            {
                Data->Elements->Resize <OctElement <T> >(math.max(incomingElements.Length, Data->Elements->Capacity * 2));
            }

            // Aabb extents are double that of AABB
            var extents = Data->RootBounds.Extents / 2;

            // Prepare morton codes
            var mortonCodes         = new NativeArray <int>(incomingElements.Length, Allocator.Temp);
            var depthExtentsScaling = LookupTables.DepthLookup[Data->MaxDepth] / extents;

            for (var i = 0; i < incomingElements.Length; i++)
            {
                var incPos = incomingElements[i].pos;
                incPos  -= Data->RootBounds.Center;   // Offset by center
                incPos.y = -incPos.y;                 // World -> array
                var pos = (incPos + extents) * .5f;   // Make positive
                // Now scale into available space that belongs to the depth
                pos *= depthExtentsScaling;
                // And interleave the bits for the morton code
                mortonCodes[i] = (int)(LookupTables.MortonLookup[(int)pos.x] | (LookupTables.MortonLookup[(int)pos.y] << 1) | (LookupTables.MortonLookup[(int)pos.z] << 2));
            }

            // Index total child element count per node (total, so parent's counts include those of child nodes)

            for (var i = 0; i < mortonCodes.Length; i++)
            {
                int atIndex = 0;
                for (int depth = 0; depth <= Data->MaxDepth; depth++)
                {
                    // Increment the node on this depth that this element is contained in
                    UnsafeUtilityEx.ArrayElementAsRef <int>(Data->NodeInfo->Ptr, atIndex)++;
                    atIndex = IncrementIndex(depth, mortonCodes, i, atIndex);
                }
            }

            // Prepare the tree leaf nodes
            var q1Ptr = (QuadGroup *)((byte *)Data->Quads->Ptr + Data->Quads->Length++ *sizeof(QuadGroup));
            var q2Ptr = (QuadGroup *)((byte *)Data->Quads->Ptr + Data->Quads->Length++ *sizeof(QuadGroup));

            RecursivePrepareLeaves(Data->RootBounds, 1, 1, q1Ptr, q2Ptr);

            // Add elements to leaf nodes
            for (var i = 0; i < incomingElements.Length; i++)
            {
                int atIndex = 0;
                for (int depth = 0; depth <= Data->MaxDepth; depth++)
                {
                    ref var node = ref UnsafeUtilityEx.ArrayElementAsRef <OctNode>(Data->Nodes->Ptr, atIndex);
                    if (node.isLeaf)
                    {
                        // We found a leaf, add this element to it and move to the next element
                        UnsafeUtility.WriteArrayElement(Data->Elements->Ptr, node.firstChildIndex + node.count, incomingElements[i]);
                        node.count++;
                        break;
                    }
                    // No leaf found, we keep going deeper until we find one
                    atIndex = IncrementIndex(depth, mortonCodes, i, atIndex);
                }
            }
Ejemplo n.º 17
0
        internal unsafe void KNearest(float3 queryPosition, NativeSlice <int> result, ref KnnQueryTemp temp)
        {
            int k = result.Length;

            temp.Heap.Clear();

            var points      = Points;
            var permutation = m_permutation;
            var rootNode    = RootNode;
            var nodePtr     = m_nodes.GetUnsafePtr();

            // Biggest Smallest Squared Radius
            float  bssr             = float.PositiveInfinity;
            float3 rootClosestPoint = rootNode.Bounds.ClosestPoint(queryPosition);

            PushToHeap(m_rootNodeIndex[0], rootClosestPoint, queryPosition, ref temp);

            // searching
            while (temp.MinHeap.Count > 0)
            {
                KdQueryNode queryNode = temp.MinHeap.PopObj();

                if (queryNode.Distance > bssr)
                {
                    continue;
                }

                ref KdNode node = ref UnsafeUtilityEx.ArrayElementAsRef <KdNode>(nodePtr, queryNode.NodeIndex);

                if (!node.Leaf)
                {
                    int    partitionAxis    = node.PartitionAxis;
                    float  partitionCoord   = node.PartitionCoordinate;
                    float3 tempClosestPoint = queryNode.TempClosestPoint;

                    if (tempClosestPoint[partitionAxis] - partitionCoord < 0)
                    {
                        // we already know we are on the side of negative bound/node,
                        // so we don't need to test for distance
                        // push to stack for later querying
                        PushToHeap(node.NegativeChildIndex, tempClosestPoint, queryPosition, ref temp);

                        // project the tempClosestPoint to other bound
                        tempClosestPoint[partitionAxis] = partitionCoord;

                        if (node.Count != 0)
                        {
                            PushToHeap(node.PositiveChildIndex, tempClosestPoint, queryPosition, ref temp);
                        }
                    }
                    else
                    {
                        // we already know we are on the side of positive bound/node,
                        // so we don't need to test for distance
                        // push to stack for later querying
                        PushToHeap(node.PositiveChildIndex, tempClosestPoint, queryPosition, ref temp);

                        // project the tempClosestPoint to other bound
                        tempClosestPoint[partitionAxis] = partitionCoord;

                        if (node.Count != 0)
                        {
                            PushToHeap(node.NegativeChildIndex, tempClosestPoint, queryPosition, ref temp);
                        }
                    }
                }
                else
                {
                    for (int i = node.Start; i < node.End; i++)
                    {
                        int   index   = permutation[i];
                        float sqrDist = math.lengthsq(points[index] - queryPosition);

                        if (sqrDist <= bssr)
                        {
                            temp.Heap.PushObj(index, sqrDist);

                            if (temp.Heap.Count == k)
                            {
                                bssr = temp.Heap.HeadValue;
                            }
                        }
                    }
                }
            }