예제 #1
0
 public void DoubleDispose()
 {
     using (var ms = new MemoryStream())
     {
         var blockStream = new BlockStream(Zstd, ms, CompressionMode.Compress);
         blockStream.Dispose();
         blockStream.Dispose();
     }
 }
예제 #2
0
        public void ToArray([Values(1, 100, 200)] int count, [Values(1, 3, 10)] int batchSize)
        {
            var stream   = new BlockStream(count, 0x11843789);
            var fillInts = new WriteInts {
                Writer = stream
            };

            fillInts.Schedule(count, batchSize).Complete();

            var array     = stream.ToNativeArray <int>();
            int itemIndex = 0;

            for (int i = 0; i != count; ++i)
            {
                for (int j = 0; j < i; ++j)
                {
                    Assert.AreEqual(j, array[itemIndex]);
                    itemIndex++;
                }
            }

            array.Dispose();

            stream.Dispose();
        }
예제 #3
0
 public void Dispose()
 {
     if (!_leaveOpen)
     {
         _blockStream.Dispose();
     }
     _writer.Dispose();
 }
예제 #4
0
        public void WriteWithoutBegin()
        {
            var stream = new BlockStream(1, 0x9b98651c);

            BlockStream.Writer writer = stream;
            Assert.Throws <ArgumentException>(() => writer.Write(5));

            stream.Dispose();
        }
예제 #5
0
        public void OutOfBoundsWrite()
        {
            var stream = new BlockStream(1);

            BlockStream.Writer writer = stream;
            Assert.Throws <UnityEngine.Assertions.AssertionException>(() => writer.BeginForEachIndex(-1));
            Assert.Throws <UnityEngine.Assertions.AssertionException>(() => writer.BeginForEachIndex(2));

            stream.Dispose();
        }
예제 #6
0
        public void OutOfBoundsWrite()
        {
            var stream = new BlockStream(1, 0x9b98651c);

            BlockStream.Writer writer = stream;
            Assert.Throws <ArgumentException>(() => writer.BeginForEachIndex(-1));
            Assert.Throws <ArgumentException>(() => writer.BeginForEachIndex(2));

            stream.Dispose();
        }
예제 #7
0
        public void CreateAndDestroy([Values(1, 100, 200)] int count)
        {
            var stream = new BlockStream(count, 0x9b98651b);

            Assert.IsTrue(stream.IsCreated);
            Assert.IsTrue(stream.ForEachCount == count);
            Assert.IsTrue(stream.ComputeItemCount() == 0);

            stream.Dispose();
            Assert.IsFalse(stream.IsCreated);
        }
예제 #8
0
        public void JacobianIteratorHasJacobiansLeftTest()
        {
            var jacobianStream = new BlockStream(1, 0x01234567);

            BlockStream.Reader jacobianStreamReader = jacobianStream;
            int workItemIndex = 0;
            var jacIterator   = new JacobianIterator(jacobianStreamReader, workItemIndex);

            Assert.IsFalse(jacIterator.HasJacobiansLeft());

            jacobianStream.Dispose();
        }
예제 #9
0
        public void Dispose()
        {
            _dataFile?.Flush();
            _dataFile?.Close();
            _dataFile?.Dispose();
            _dataFile = null;

            _indexFile?.Flush();
            _indexFile?.Close();
            _indexFile?.Dispose();
            _indexFile = null;
        }
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        if (m_CharacterControllersGroup.CalculateEntityCount() == 0)
        {
            return(inputDeps);
        }

        var chunks = m_CharacterControllersGroup.CreateArchetypeChunkArray(Allocator.TempJob);

        var ccComponentType     = GetArchetypeChunkComponentType <CharacterControllerComponentData>();
        var ccInternalType      = GetArchetypeChunkComponentType <CharacterControllerInternalData>();
        var physicsColliderType = GetArchetypeChunkComponentType <PhysicsCollider>();
        var translationType     = GetArchetypeChunkComponentType <Translation>();
        var rotationType        = GetArchetypeChunkComponentType <Rotation>();

        BlockStream deferredImpulses = new BlockStream(chunks.Length, 0xCA37B9F2);

        var ccJob = new CharacterControllerJob()
        {
            // Archetypes
            CharacterControllerComponentType = ccComponentType,
            CharacterControllerInternalType  = ccInternalType,
            PhysicsColliderType = physicsColliderType,
            TranslationType     = translationType,
            RotationType        = rotationType,
            // Input
            DeltaTime             = Time.fixedDeltaTime,
            PhysicsWorld          = m_BuildPhysicsWorldSystem.PhysicsWorld,
            DeferredImpulseWriter = deferredImpulses
        };

        inputDeps = JobHandle.CombineDependencies(inputDeps, m_ExportPhysicsWorldSystem.FinalJobHandle);
        inputDeps = ccJob.Schedule(m_CharacterControllersGroup, inputDeps);

        var applyJob = new ApplyDefferedPhysicsUpdatesJob()
        {
            Chunks = chunks,
            DeferredImpulseReader = deferredImpulses,
            PhysicsVelocityData   = GetComponentDataFromEntity <PhysicsVelocity>(),
            PhysicsMassData       = GetComponentDataFromEntity <PhysicsMass>(),
            TranslationData       = GetComponentDataFromEntity <Translation>(),
            RotationData          = GetComponentDataFromEntity <Rotation>()
        };

        inputDeps = applyJob.Schedule(inputDeps);
        var disposeHandle = deferredImpulses.Dispose(inputDeps);

        // Must finish all jobs before physics step end
        m_EndFramePhysicsSystem.HandlesToWaitFor.Add(disposeHandle);

        return(inputDeps);
    }
예제 #11
0
        public void ItemCount([Values(1, 100, 200)] int count, [Values(1, 3, 10)] int batchSize)
        {
            var stream   = new BlockStream(count, 0xd3e8afdd);
            var fillInts = new WriteInts {
                Writer = stream
            };

            fillInts.Schedule(count, batchSize).Complete();

            Assert.AreEqual(count * (count - 1) / 2, stream.ComputeItemCount());

            stream.Dispose();
        }
예제 #12
0
        public void ParallelWriteThrows()
        {
            var stream   = new BlockStream(100, 0xd3e8afdd);
            var fillInts = new WriteInts {
                Writer = stream
            };

            var writerJob = fillInts.Schedule(100, 16);

            Assert.Throws <InvalidOperationException>(() => fillInts.Schedule(100, 16));

            writerJob.Complete();
            stream.Dispose();
        }
예제 #13
0
        public void DisposeAfterSchedule()
        {
            var stream   = new BlockStream(100, 0xd3e8afdd);
            var fillInts = new WriteInts {
                Writer = stream
            };
            var writerJob = fillInts.Schedule(100, 16);

            var disposeJob = stream.Dispose(writerJob);

            Assert.IsFalse(stream.IsCreated);

            disposeJob.Complete();
        }
예제 #14
0
        public void IncorrectTypedReads()
        {
            var stream = new BlockStream(1);

            BlockStream.Writer writer = stream;
            writer.BeginForEachIndex(0);
            writer.Write <int>(5);
            writer.EndForEachIndex();

            BlockStream.Reader reader = stream;

            reader.BeginForEachIndex(0);
            Assert.Throws <UnityEngine.Assertions.AssertionException>(() => reader.Read <float>());

            stream.Dispose();
        }
예제 #15
0
        public void PopulateInts([Values(1, 100, 200)] int count, [Values(1, 3, 10)] int batchSize)
        {
            var stream   = new BlockStream(count, 0x9b98651c);
            var fillInts = new WriteInts {
                Writer = stream
            };
            var jobHandle = fillInts.Schedule(count, batchSize);

            var compareInts = new ReadInts {
                Reader = stream
            };
            var res0 = compareInts.Schedule(count, batchSize, jobHandle);
            var res1 = compareInts.Schedule(count, batchSize, jobHandle);

            res0.Complete();
            res1.Complete();

            stream.Dispose();
        }
예제 #16
0
        public void TreeOverlapPerfTest(int elementCount, bool newOverlap)
        {
            // Execute dummy job just to get Burst compilation out of the way.
            {
                var dummyBlockStream = new BlockStream(1, 0, Allocator.TempJob);
                var dummyNodes       = new NativeArray <Node>(0, Allocator.TempJob);
                var dummyFilters     = new NativeArray <CollisionFilter>(0, Allocator.TempJob);
                new TestTreeOverlapJob
                {
                    CollisionPairWriter = dummyBlockStream,
                    Nodes      = dummyNodes,
                    Filter     = dummyFilters,
                    NumObjects = 0,
                    DummyRun   = true
                }.Run();
                dummyBlockStream.Dispose();
                dummyNodes.Dispose();
                dummyFilters.Dispose();
            }

            elementCount *= 2;
            int numNodes = elementCount / 3 * 2 + 4;
            var points   = new NativeArray <PointAndIndex>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var aabbs    = new NativeArray <Aabb>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var filters  = new NativeArray <CollisionFilter>(elementCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

            // Override filter data with default filters.
            for (int i = 0; i < filters.Length; i++)
            {
                filters[i] = CollisionFilter.Default;
            }

            InitInputWithCopyArrays(points, aabbs, filters);

            var nodes = new NativeArray <Node>(numNodes, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

            var bvh = new BoundingVolumeHierarchy(nodes);

            bvh.Build(points, aabbs, out int numNodesOut);
            bvh.CheckIntegrity();

            var collisionPairs = new BlockStream(1, 0xd586fc6e);

            var job = new TestTreeOverlapJob
            {
                Nodes               = nodes,
                Filter              = filters,
                NumObjects          = elementCount,
                CollisionPairWriter = collisionPairs,
                DummyRun            = false
            };

            Measure.Method(() =>
            {
                job.Run();
            }).Definition(sampleUnit: SampleUnit.Millisecond)
            .MeasurementCount(1)
            .Run();

            points.Dispose();
            aabbs.Dispose();
            nodes.Dispose();
            collisionPairs.Dispose();
            filters.Dispose();
        }
예제 #17
0
        public unsafe void OverlapTaskFilteringTest([Values(2, 10, 33, 100)] int elementCount)
        {
            elementCount *= 2;
            int numNodes = elementCount + Constants.MaxNumTreeBranches;

            var points      = new NativeArray <PointAndIndex>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var aabbs       = new NativeArray <Aabb>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var bodyFilters = new NativeArray <CollisionFilter>(elementCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

            InitInputWithCopyArrays(points, aabbs, bodyFilters);

            var   nodes    = new NativeArray <Node>(numNodes, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            Node *nodesPtr = (Node *)nodes.GetUnsafePtr();

            var seenUnfiltered = new HashSet <BodyIndexPair>();
            {
                var bvhUnfiltered = new BoundingVolumeHierarchy(nodes);
                bvhUnfiltered.Build(points, aabbs, out int numNodesOut);
                bvhUnfiltered.CheckIntegrity();

                EverythingWriter pairWriter = new EverythingWriter {
                    SeenPairs = seenUnfiltered
                };
                BoundingVolumeHierarchy.TreeOverlap(ref pairWriter, nodesPtr, nodesPtr);
            }

            var nodeFilters = new NativeArray <CollisionFilter>(numNodes, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var bvhFiltered = new BoundingVolumeHierarchy(nodes, nodeFilters);
            int numNodesFilteredTree;

            bvhFiltered.Build(points, aabbs, out numNodesFilteredTree);
            bvhFiltered.BuildCombinedCollisionFilter(bodyFilters, 0, numNodesFilteredTree - 1);

            var filteredCollisionPairs = new BlockStream(1, 0xec87b613);

            BlockStream.Writer filteredPairWriter = filteredCollisionPairs;
            filteredPairWriter.BeginForEachIndex(0);
            CollisionFilter *bodyFiltersPtr = (CollisionFilter *)bodyFilters.GetUnsafePtr();
            var bufferedPairs = new Broadphase.BodyPairWriter(&filteredPairWriter, bodyFiltersPtr);

            CollisionFilter *nodeFiltersPtr = (CollisionFilter *)nodeFilters.GetUnsafePtr();

            BoundingVolumeHierarchy.TreeOverlap(ref bufferedPairs, nodesPtr, nodesPtr, nodeFiltersPtr, nodeFiltersPtr);
            bufferedPairs.Close();
            filteredPairWriter.EndForEachIndex();

            BlockStream.Reader filteredPairReader = filteredCollisionPairs;
            filteredPairReader.BeginForEachIndex(0);

            // Check that every pair in our filtered set also appears in the unfiltered set
            while (filteredPairReader.RemainingItemCount > 0)
            {
                var pair = filteredPairReader.Read <BodyIndexPair>();

                Assert.IsTrue(seenUnfiltered.Contains(pair));
                seenUnfiltered.Remove(pair); // Remove the pair
            }

            // Pairs were removed, so the only remaining ones should be filtered
            foreach (BodyIndexPair pair in seenUnfiltered)
            {
                bool shouldCollide = CollisionFilter.IsCollisionEnabled(bodyFilters[pair.BodyAIndex], bodyFilters[pair.BodyBIndex]);
                Assert.IsFalse(shouldCollide);
            }

            nodeFilters.Dispose();
            nodes.Dispose();
            bodyFilters.Dispose();
            aabbs.Dispose();
            points.Dispose();
            filteredCollisionPairs.Dispose();
        }
예제 #18
0
        public unsafe void BuildTreeAndOverlapTasks([Values(2, 10, 33, 100)] int elementCount)
        {
            const int threadCount = 8;

            elementCount *= 2;
            int numNodes = elementCount + Constants.MaxNumTreeBranches;

            var points      = new NativeArray <PointAndIndex>(elementCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var aabbs       = new NativeArray <Aabb>(elementCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var filters     = new NativeArray <CollisionFilter>(elementCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var nodefilters = new NativeArray <CollisionFilter>(numNodes, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var branchCount = new NativeArray <int>(1, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

            InitInputWithCopyArrays(points, aabbs, filters);

            // Override filter data with default filters.
            for (int i = 0; i < filters.Length; i++)
            {
                filters[i] = CollisionFilter.Default;
            }

            for (int i = 0; i < nodefilters.Length; i++)
            {
                nodefilters[i] = CollisionFilter.Default;
            }

            var nodes = new NativeArray <Node>(numNodes, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

            var ranges           = new NativeArray <Range>(Constants.MaxNumTreeBranches, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var branchNodeOffset = new NativeArray <int>(Constants.MaxNumTreeBranches, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var shouldDoWork     = new NativeArray <int>(1, Allocator.TempJob);

            shouldDoWork[0] = 1;
            int oldBranchCount = branchCount[0];

            JobHandle handle = new BuildFirstNLevelsJob
            {
                Points            = points,
                Nodes             = (Node *)nodes.GetUnsafePtr(),
                Ranges            = ranges,
                BranchNodeOffsets = branchNodeOffset,
                BranchCount       = branchCount,
                ThreadCount       = threadCount,
                ShouldDoWork      = shouldDoWork
            }.Schedule();

            handle = new BuildBranchesJob
            {
                Points            = points,
                Aabbs             = aabbs,
                BodyFilters       = filters,
                Nodes             = (Node *)nodes.GetUnsafePtr(),
                Ranges            = ranges,
                BranchNodeOffsets = branchNodeOffset,
                BranchCount       = branchCount
            }.ScheduleUnsafeIndex0(branchCount, 1, handle);

            new FinalizeTreeJob
            {
                Aabbs             = aabbs,
                LeafFilters       = filters,
                Nodes             = (Node *)nodes.GetUnsafePtr(),
                BranchNodeOffsets = branchNodeOffset,
                NumNodes          = numNodes,
                BranchCount       = branchCount,
                ShouldDoWork      = shouldDoWork,
                OldBranchCount    = oldBranchCount
            }.Schedule(handle).Complete();

            int numBranchOverlapPairs = branchCount[0] * (branchCount[0] + 1) / 2;
            var nodePairIndices       = new NativeList <int2>(Allocator.TempJob);

            nodePairIndices.ResizeUninitialized(numBranchOverlapPairs);
            var collisionPairs = new BlockStream(numBranchOverlapPairs, 0xb08c3d78);

            handle = new Broadphase.DynamicVsDynamicBuildBranchNodePairsJob
            {
                Ranges          = ranges,
                NumBranches     = branchCount,
                NodePairIndices = nodePairIndices
            }.Schedule();

            handle = new Broadphase.DynamicVsDynamicFindOverlappingPairsJob
            {
                DynamicNodes       = nodes,
                PairWriter         = collisionPairs,
                BodyFilters        = filters,
                NodePairIndices    = nodePairIndices,
                DynamicNodeFilters = nodefilters,
            }.Schedule(nodePairIndices, numBranchOverlapPairs, handle);

            handle.Complete();


            int numPairs = collisionPairs.ComputeItemCount();

            Assert.AreEqual(elementCount / 2, numPairs);
            //Debug.Log($"Num colliding pairs: {numPairs}");

            var bvh = new BoundingVolumeHierarchy(nodes);

            bvh.CheckIntegrity();


            nodePairIndices.Dispose();
            filters.Dispose();
            nodefilters.Dispose();
            nodes.Dispose();
            ranges.Dispose();
            collisionPairs.Dispose();
            branchCount.Dispose();
            shouldDoWork.Dispose();
        }
예제 #19
0
 public void Dispose()
 {
     _reader.Dispose();
     _blockStream.Dispose();
 }
예제 #20
0
        public unsafe void ManifoldQueryTest()
        {
            const uint seed      = 0x98765432;
            Random     rnd       = new Random(seed);
            int        numWorlds = 1000;

            uint dbgWorld = 0;

            if (dbgWorld > 0)
            {
                numWorlds = 1;
            }

            for (int iWorld = 0; iWorld < numWorlds; iWorld++)
            {
                // Save state to repro this query without doing everything that came before it
                if (dbgWorld > 0)
                {
                    rnd.state = dbgWorld;
                }
                uint worldState            = rnd.state;
                Physics.PhysicsWorld world = TestUtils.GenerateRandomWorld(ref rnd, rnd.NextInt(1, 20), 3.0f);

                // Manifold test
                // TODO would be nice if we could change the world collision tolerance
                for (int iBodyA = 0; iBodyA < world.NumBodies; iBodyA++)
                {
                    for (int iBodyB = iBodyA + 1; iBodyB < world.NumBodies; iBodyB++)
                    {
                        Physics.RigidBody bodyA = world.Bodies[iBodyA];
                        Physics.RigidBody bodyB = world.Bodies[iBodyB];
                        if (bodyA.Collider->Type == ColliderType.Mesh && bodyB.Collider->Type == ColliderType.Mesh)
                        {
                            continue; // TODO - no mesh-mesh manifold support yet
                        }

                        // Build manifolds
                        BlockStream        contacts      = new BlockStream(1, 0, Allocator.Temp);
                        BlockStream.Writer contactWriter = contacts;
                        contactWriter.BeginForEachIndex(0);
                        ManifoldQueries.BodyBody(ref world, new BodyIndexPair {
                            BodyAIndex = iBodyA, BodyBIndex = iBodyB
                        }, 1.0f, ref contactWriter);
                        contactWriter.EndForEachIndex();

                        // Read each manifold
                        BlockStream.Reader contactReader = contacts;
                        contactReader.BeginForEachIndex(0);
                        int manifoldIndex = 0;
                        while (contactReader.RemainingItemCount > 0)
                        {
                            string failureMessage = iWorld + " (" + worldState + ") " + iBodyA + " vs " + iBodyB + " #" + manifoldIndex;
                            manifoldIndex++;

                            // Read the manifold header
                            ContactHeader header = contactReader.Read <ContactHeader>();
                            ConvexConvexManifoldQueries.Manifold manifold = new ConvexConvexManifoldQueries.Manifold();
                            manifold.NumContacts = header.NumContacts;
                            manifold.Normal      = header.Normal;

                            // Get the leaf shapes
                            ChildCollider leafA, leafB;
                            {
                                Collider.GetLeafCollider(bodyA.Collider, bodyA.WorldFromBody, header.ColliderKeys.ColliderKeyA, out leafA);
                                Collider.GetLeafCollider(bodyB.Collider, bodyB.WorldFromBody, header.ColliderKeys.ColliderKeyB, out leafB);
                            }

                            // Read each contact point
                            int minIndex = 0;
                            for (int iContact = 0; iContact < header.NumContacts; iContact++)
                            {
                                // Read the contact and find the closest
                                ContactPoint contact = contactReader.Read <ContactPoint>();
                                manifold[iContact] = contact;
                                if (contact.Distance < manifold[minIndex].Distance)
                                {
                                    minIndex = iContact;
                                }

                                // Check that the contact point is on or inside the shape
                                CheckPointOnSurface(ref leafA, contact.Position + manifold.Normal * contact.Distance, failureMessage + " contact " + iContact + " leaf A");
                                CheckPointOnSurface(ref leafB, contact.Position, failureMessage + " contact " + iContact + " leaf B");
                            }

                            // Check the closest point
                            {
                                ContactPoint           closestPoint = manifold[minIndex];
                                RigidTransform         aFromWorld   = math.inverse(leafA.TransformFromChild);
                                DistanceQueries.Result result       = new DistanceQueries.Result
                                {
                                    PositionOnAinA = math.transform(aFromWorld, closestPoint.Position + manifold.Normal * closestPoint.Distance),
                                    NormalInA      = math.mul(aFromWorld.rot, manifold.Normal),
                                    Distance       = closestPoint.Distance
                                };

                                MTransform aFromB            = new MTransform(math.mul(aFromWorld, leafB.TransformFromChild));
                                float      referenceDistance = DistanceQueries.ConvexConvex(leafA.Collider, leafB.Collider, aFromB).Distance;
                                ValidateDistanceResult(result, ref ((ConvexCollider *)leafA.Collider)->ConvexHull, ref ((ConvexCollider *)leafB.Collider)->ConvexHull, aFromB, referenceDistance, failureMessage + " closest point");
                            }

                            // Check that the manifold is flat
                            CheckManifoldFlat(ref manifold, manifold.Normal, failureMessage + ": non-flat A");
                            CheckManifoldFlat(ref manifold, float3.zero, failureMessage + ": non-flat B");
                        }

                        contacts.Dispose();
                    }
                }

                world.Dispose(); // TODO leaking memory if the test fails
            }
        }