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)); }
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)); }
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); } }
/// <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); } }
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(); } }
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); }
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); }
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; } }
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)); }
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)); }
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)); }
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)); }
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)); }
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)); }
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(); }