Пример #1
0
        public void CollisionFilterTest_LayerSelfCollision()
        {
            var filter0 = new CollisionFilter();

            var filter1 = new CollisionFilter
            {
                BelongsTo    = 1,
                CollidesWith = 1
            };

            var filter2 = new CollisionFilter
            {
                BelongsTo    = 0xffffffff,
                CollidesWith = 0xffffffff
            };

            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter0, filter0));
            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(CollisionFilter.Zero, CollisionFilter.Zero));
            Assert.IsTrue(filter0.Equals(CollisionFilter.Zero));

            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter1, filter1));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter2, filter2));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(CollisionFilter.Default, CollisionFilter.Default));
            Assert.IsTrue(filter2.Equals(CollisionFilter.Default));
        }
Пример #2
0
        public void CollisionFilterTestLayerSelfCollision()
        {
            var filter0 = new CollisionFilter();

            var filter1 = new CollisionFilter
            {
                MaskBits     = 1,
                CategoryBits = 1
            };

            var filter2 = new CollisionFilter
            {
                MaskBits     = 0xffffffff,
                CategoryBits = 0xffffffff
            };

            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter0, filter0));
            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(CollisionFilter.Zero, CollisionFilter.Zero));
            Assert.IsTrue(filter0.Equals(CollisionFilter.Zero));

            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter1, filter1));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter2, filter2));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(CollisionFilter.Default, CollisionFilter.Default));
            Assert.IsTrue(filter2.Equals(CollisionFilter.Default));
        }
Пример #3
0
        public static unsafe bool ColliderCollider <T>(ColliderCastInput input, Collider *target, ref T collector) where T : struct, ICollector <ColliderCastHit>
        {
            if (!CollisionFilter.IsCollisionEnabled(input.Collider->Filter, target->Filter))
            {
                return(false);
            }

            if (!input.QueryContext.IsInitialized)
            {
                input.QueryContext = QueryContext.DefaultContext;
            }

            switch (input.Collider->CollisionType)
            {
            case CollisionType.Convex:
                switch (target->Type)
                {
                case ColliderType.Sphere:
                case ColliderType.Capsule:
                case ColliderType.Triangle:
                case ColliderType.Quad:
                case ColliderType.Box:
                case ColliderType.Cylinder:
                case ColliderType.Convex:
                    if (ConvexConvex(input, target, collector.MaxFraction, out ColliderCastHit hit))
                    {
                        return(collector.AddHit(hit));
                    }
                    return(false);

                case ColliderType.Mesh:
                    return(ConvexMesh(input, (MeshCollider *)target, ref collector));

                case ColliderType.Compound:
                    return(ConvexCompound(input, (CompoundCollider *)target, ref collector));

                case ColliderType.Terrain:
                    return(ConvexTerrain(input, (TerrainCollider *)target, ref collector));

                default:
                    SafetyChecks.ThrowNotImplementedException();
                    return(default);
                }

            case CollisionType.Composite:
            case CollisionType.Terrain:
                // no support for casting composite shapes
                SafetyChecks.ThrowNotImplementedException();
                return(default);

            default:
                SafetyChecks.ThrowNotImplementedException();
                return(default);
            }
        }
Пример #4
0
    /// <summary>
    /// Variant of <see cref="TrimByFilter{T}(ref NativeList{T}, EntityManager, CollisionFilter)"/> to be used within a Job which does not have access to an <see cref="EntityManager"/>.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="castResults"></param>
    /// <param name="colliderData"></param>
    /// <param name="filter"></param>
    public unsafe static void TrimByFilter <T>(ref NativeList <T> castResults, ComponentDataFromEntity <PhysicsCollider> colliderData, CollisionFilter filter) where T : struct, IQueryResult
    {
        for (int i = (castResults.Length - 1); i >= 0; --i)
        {
            if (colliderData.HasComponent(castResults[i].Entity))
            {
                PhysicsCollider collider = colliderData[castResults[i].Entity];

                if (CollisionFilter.IsCollisionEnabled(filter, collider.ColliderPtr->Filter))
                {
                    continue;
                }
            }

            castResults.RemoveAt(i);
        }
    }
Пример #5
0
        public static unsafe bool ColliderCollider <T>(ColliderCastInput input, Collider *target, ref T collector) where T : struct, ICollector <ColliderCastHit>
        {
            if (!CollisionFilter.IsCollisionEnabled(input.Collider->Filter, target->Filter))
            {
                return(false);
            }

            switch (input.Collider->CollisionType)
            {
            case CollisionType.Convex:
                switch (target->Type)
                {
                case ColliderType.Sphere:
                case ColliderType.Capsule:
                case ColliderType.Triangle:
                case ColliderType.Quad:
                case ColliderType.Box:
                case ColliderType.Cylinder:
                case ColliderType.Convex:
                    return(ConvexConvex(input, target, ref collector));

                case ColliderType.Mesh:
                    return(ConvexMesh(input, (MeshCollider *)target, ref collector));

                case ColliderType.Compound:
                    return(ConvexCompound(input, (CompoundCollider *)target, ref collector));

                case ColliderType.Terrain:
                    return(ConvexTerrain(input, (TerrainCollider *)target, ref collector));

                default:
                    throw new NotImplementedException();
                }

            case CollisionType.Composite:
            case CollisionType.Terrain:
                // no support for casting composite shapes
                throw new NotImplementedException();

            default:
                throw new NotImplementedException();
            }
        }
Пример #6
0
            public bool ColliderCastLeaf <T>(ColliderCastInput input, int primitiveKey, ref T collector)
                where T : struct, ICollector <ColliderCastHit>
            {
                m_Mesh->GetPrimitive(primitiveKey, out float3x4 vertices, out Mesh.PrimitiveFlags flags, out CollisionFilter filter);

                if (!CollisionFilter.IsCollisionEnabled(input.Collider->Filter, filter)) // TODO: could do this check within GetPrimitive()
                {
                    return(false);
                }

                int  numPolygons = Mesh.GetNumPolygonsInPrimitive(flags);
                bool isQuad      = Mesh.IsPrimitveFlagSet(flags, Mesh.PrimitiveFlags.IsQuad);

                bool acceptHit = false;
                int  numHits   = collector.NumHits;

                var polygon = new PolygonCollider();

                polygon.InitEmpty();
                for (int polygonIndex = 0; polygonIndex < numPolygons; polygonIndex++)
                {
                    float fraction = collector.MaxFraction;

                    if (isQuad)
                    {
                        polygon.SetAsQuad(vertices[0], vertices[1], vertices[2], vertices[3]);
                    }
                    else
                    {
                        polygon.SetAsTriangle(vertices[0], vertices[1 + polygonIndex], vertices[2 + polygonIndex]);
                    }

                    if (ConvexConvex(input, (Collider *)&polygon, ref collector))
                    {
                        acceptHit = true;
                        // TODO.ma make a version that doesn't transform, just updates collider key
                        collector.TransformNewHits(numHits++, fraction, MTransform.Identity, m_NumColliderKeyBits, (uint)(primitiveKey << 1 | polygonIndex));
                    }
                }

                return(acceptHit);
            }
Пример #7
0
            public bool ColliderCastLeaf <T>(ColliderCastInput input, int primitiveKey, ref T collector)
                where T : struct, ICollector <ColliderCastHit>
            {
                m_Mesh->GetPrimitive(primitiveKey, out float3x4 vertices, out Mesh.PrimitiveFlags flags, out CollisionFilter filter);

                if (!CollisionFilter.IsCollisionEnabled(input.Collider->Filter, filter)) // TODO: could do this check within GetPrimitive()
                {
                    return(false);
                }

                int  numPolygons = Mesh.GetNumPolygonsInPrimitive(flags);
                bool isQuad      = Mesh.IsPrimitveFlagSet(flags, Mesh.PrimitiveFlags.IsQuad);

                bool acceptHit = false;

                var polygon = new PolygonCollider();

                polygon.InitEmpty();
                for (int polygonIndex = 0; polygonIndex < numPolygons; polygonIndex++)
                {
                    float fraction = collector.MaxFraction;

                    if (isQuad)
                    {
                        polygon.SetAsQuad(vertices[0], vertices[1], vertices[2], vertices[3]);
                    }
                    else
                    {
                        polygon.SetAsTriangle(vertices[0], vertices[1 + polygonIndex], vertices[2 + polygonIndex]);
                    }

                    if (ConvexConvex(input, (Collider *)&polygon, collector.MaxFraction, out ColliderCastHit hit))
                    {
                        hit.ColliderKey = input.QueryContext.SetSubKey(m_NumColliderKeyBits, (uint)(primitiveKey << 1 | polygonIndex));
                        acceptHit      |= collector.AddHit(hit);
                    }
                }

                return(acceptHit);
            }
Пример #8
0
            public void Execute([ReadOnly] ref PhysicsCollider collider, [ReadOnly] ref Translation translation, [ReadOnly] ref Rotation rotation)
            {
                if (!CollisionFilter.IsCollisionEnabled(IncludeMask, collider.ColliderPtr->Filter))
                {
                    return;
                }

                switch (collider.ColliderPtr->Type)
                {
                case ColliderType.Box:
                case ColliderType.Triangle:
                case ColliderType.Quad:
                case ColliderType.Cylinder:
                case ColliderType.Convex:
                    HandleConvex((ConvexCollider *)collider.ColliderPtr, ref translation, ref rotation);
                    break;

                case ColliderType.Sphere:
                    break;

                case ColliderType.Capsule:
                    break;

                case ColliderType.Mesh:
                    HandleMesh((MeshCollider *)collider.ColliderPtr, ref translation, ref rotation);
                    break;

                case ColliderType.Compound:
                    break;

                case ColliderType.Terrain:
                    HandleTerrain((TerrainCollider *)collider.ColliderPtr, ref translation, ref rotation);
                    break;

                default:
                    break;
                }
            }
Пример #9
0
        public void CollisionFilterTest_GroupIndexSimple()
        {
            var filter0 = new CollisionFilter
            {
                GroupIndex = 1
            };

            var filter1 = new CollisionFilter
            {
                BelongsTo    = 1,
                CollidesWith = 1,
                GroupIndex   = -1
            };

            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter0, CollisionFilter.Zero));
            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter0, CollisionFilter.Default));

            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter1, CollisionFilter.Zero));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter1, CollisionFilter.Default));

            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter0, filter0));
            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter1, filter1));
        }
Пример #10
0
        public void CollisionFilterTest_BelongsToAndCollidesWithBits()
        {
            var filterA = new CollisionFilter
            {
                BelongsTo    = 1,
                CollidesWith = 2
            };

            var filterB = new CollisionFilter
            {
                BelongsTo    = 2,
                CollidesWith = 1
            };

            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filterA, filterA));
            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filterB, filterB));

            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filterA, filterB));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filterB, filterA));

            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filterA, CollisionFilter.Default));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filterB, CollisionFilter.Default));
        }
Пример #11
0
        public void CollisionFilterTestGroupIndexSimple()
        {
            var filter0 = new CollisionFilter
            {
                GroupIndex = 1
            };

            var filter1 = new CollisionFilter
            {
                MaskBits     = 1,
                CategoryBits = 1,
                GroupIndex   = -1
            };

            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter0, CollisionFilter.Zero));
            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter0, CollisionFilter.Default));

            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter1, CollisionFilter.Zero));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter1, CollisionFilter.Default));

            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter0, filter0));
            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter1, filter1));
        }
Пример #12
0
        public void CollisionFilterTestLayerAndCategoryBits()
        {
            var filterA = new CollisionFilter
            {
                MaskBits     = 1,
                CategoryBits = 2
            };

            var filterB = new CollisionFilter
            {
                MaskBits     = 2,
                CategoryBits = 1
            };

            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filterA, filterA));
            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filterB, filterB));

            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filterA, filterB));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filterB, filterA));

            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filterA, CollisionFilter.Default));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filterB, CollisionFilter.Default));
        }
Пример #13
0
        public void CollisionFilterTest_GroupIndex()
        {
            var filter0 = new CollisionFilter
            {
                GroupIndex = 1
            };

            var filter1 = new CollisionFilter
            {
                BelongsTo    = 1,
                CollidesWith = 1,
                GroupIndex   = -1
            };

            var filter2 = new CollisionFilter
            {
                BelongsTo    = 1,
                CollidesWith = 1,
                GroupIndex   = 1
            };

            var filter3 = new CollisionFilter
            {
                BelongsTo    = 0,
                CollidesWith = 0,
                GroupIndex   = -1
            };

            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter0, filter2));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter2, filter0));

            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter1, filter2));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter2, filter1));

            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter3, filter1));
            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter1, filter3));
        }
Пример #14
0
        public void CollisionFilterTestGroupIndex()
        {
            var filter0 = new CollisionFilter
            {
                GroupIndex = 1
            };

            var filter1 = new CollisionFilter
            {
                MaskBits     = 1,
                CategoryBits = 1,
                GroupIndex   = -1
            };

            var filter2 = new CollisionFilter
            {
                MaskBits     = 1,
                CategoryBits = 1,
                GroupIndex   = 1
            };

            var filter3 = new CollisionFilter
            {
                MaskBits     = 0,
                CategoryBits = 0,
                GroupIndex   = -1
            };

            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter0, filter2));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter2, filter0));

            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter1, filter2));
            Assert.IsTrue(CollisionFilter.IsCollisionEnabled(filter2, filter1));

            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter3, filter1));
            Assert.IsFalse(CollisionFilter.IsCollisionEnabled(filter1, filter3));
        }
Пример #15
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();
        }