/// <summary> /// Removes a child shape. /// </summary> /// <param name="shape">The shape.</param> public void RemoveChildShape(ColliderShape shape) { colliderShapes.Remove(shape); InternalCompoundShape.RemoveChildShape(shape.InternalShape); shape.Parent = null; }
/// <summary> /// Counts how many objects are overlapping with a given ColliderShape. If trackObjects are true, you can /// use OverlappedWith to check if another PhysicsComponent was part of the overlapping objects /// </summary> /// <param name="shape">ColliderShape to check for overlaps with</param> /// <param name="position">Position to move the ColliderShape, in addition to its LocalOffset</param> /// <param name="myGroup">What collision group is the ColliderShape in?</param> /// <param name="overlapsWith">What collision groups does the ColliderShape overlap with?</param> /// <param name="contactTest">If true, contact test overlapping objects. See ContactResults for output. Defaults to false</param> /// <param name="stopAfterFirstContact">If contact testing, should we stop contact testing after our first contact was found?</param> /// <returns>Number of overlapping objects</returns> public static int PerformOverlapTest(ColliderShape shape, Xenko.Core.Mathematics.Vector3?position = null, CollisionFilterGroups myGroup = CollisionFilterGroups.DefaultFilter, CollisionFilterGroupFlags overlapsWith = CollisionFilterGroupFlags.AllFilter, bool contactTest = false, bool stopAfterFirstContact = false) { // doesn't support multithreading if (mySimulation.simulationLocker != null) { throw new InvalidOperationException("Overlap testing not supported with multithreaded physics"); } if (ghostObject == null) { ghostObject = new BulletSharp.PairCachingGhostObject { ContactProcessingThreshold = 1e18f, UserObject = shape }; ghostObject.CollisionFlags |= BulletSharp.CollisionFlags.NoContactResponse; internalResults = new OverlapCallback(); NativeOverlappingObjects = new HashSet <object>(); } ghostObject.CollisionShape = shape.InternalShape; ghostObject.WorldTransform = Matrix.Transformation(shape.Scaling, shape.LocalRotation, position.HasValue ? position.Value + shape.LocalOffset : shape.LocalOffset); mySimulation.collisionWorld.AddCollisionObject(ghostObject, (BulletSharp.CollisionFilterGroups)myGroup, (BulletSharp.CollisionFilterGroups)overlapsWith); int overlapCount = ghostObject.NumOverlappingObjects; NativeOverlappingObjects.Clear(); for (int i = 0; i < overlapCount; i++) { NativeOverlappingObjects.Add(ghostObject.OverlappingPairs[i]); } if (contactTest) { internalResults.Clear(); internalResults.CollisionFilterGroup = (int)myGroup; internalResults.CollisionFilterMask = (int)overlapsWith; foreach (object nativeobj in NativeOverlappingObjects) { mySimulation.collisionWorld.ContactPairTest(ghostObject, (BulletSharp.CollisionObject)nativeobj, internalResults); if (stopAfterFirstContact && internalResults.Contacts.Count > 0) { break; } } } mySimulation.collisionWorld.RemoveCollisionObject(ghostObject); return(overlapCount); }
/// <summary> /// Adds a child shape. /// </summary> /// <param name="shape">The shape.</param> public void AddChildShape(ColliderShape shape) { colliderShapes.Add(shape); var compoundMatrix = Matrix.RotationQuaternion(shape.LocalRotation) * Matrix.Translation(shape.LocalOffset); InternalCompoundShape.AddChildShape(compoundMatrix, shape.InternalShape); shape.Parent = this; }
public void Dispose() { if (Shape == null) { return; } var compound = Shape.Parent; compound?.RemoveChildShape(Shape); Shape.Dispose(); Shape = null; }
internal static ColliderShape CreateShape(IColliderShapeDesc desc) { if (desc == null) { return(null); } ColliderShape shape = desc.CreateShape(); if (shape == null) { return(null); } //shape.UpdateLocalTransformations(); shape.Description = desc; return(shape); }
internal static ColliderShape Compose(IReadOnlyList <IAssetColliderShapeDesc> descs) { if (descs == null) { return(null); } ColliderShape res = null; if (descs.Count == 1) //single shape case { res = CreateShape(descs[0]); if (res == null) { return(null); } res.DoNotDispose = true; } else if (descs.Count > 1) //need a compound shape in this case { var compound = new CompoundColliderShape(); foreach (var desc in descs) { var subShape = CreateShape(desc); if (subShape == null) { continue; } compound.AddChildShape(subShape); } res = compound; res.DoNotDispose = true; } return(res); }
internal static ColliderShape CreateShape(IColliderShapeDesc desc) { if (desc == null) { return(null); } ColliderShape shape = null; var type = desc.GetType(); if (type == typeof(BoxColliderShapeDesc)) { var boxDesc = (BoxColliderShapeDesc)desc; shape = new BoxColliderShape(boxDesc.Is2D, boxDesc.Size) { LocalOffset = boxDesc.LocalOffset, LocalRotation = boxDesc.LocalRotation }; } else if (type == typeof(CapsuleColliderShapeDesc)) { var capsuleDesc = (CapsuleColliderShapeDesc)desc; shape = new CapsuleColliderShape(capsuleDesc.Is2D, capsuleDesc.Radius, capsuleDesc.Length, capsuleDesc.Orientation) { LocalOffset = capsuleDesc.LocalOffset, LocalRotation = capsuleDesc.LocalRotation }; } else if (type == typeof(CylinderColliderShapeDesc)) { var cylinderDesc = (CylinderColliderShapeDesc)desc; shape = new CylinderColliderShape(cylinderDesc.Height, cylinderDesc.Radius, cylinderDesc.Orientation) { LocalOffset = cylinderDesc.LocalOffset, LocalRotation = cylinderDesc.LocalRotation }; } else if (type == typeof(ConeColliderShapeDesc)) { var coneDesc = (ConeColliderShapeDesc)desc; shape = new ConeColliderShape(coneDesc.Height, coneDesc.Radius, coneDesc.Orientation) { LocalOffset = coneDesc.LocalOffset, LocalRotation = coneDesc.LocalRotation }; } else if (type == typeof(SphereColliderShapeDesc)) { var sphereDesc = (SphereColliderShapeDesc)desc; shape = new SphereColliderShape(sphereDesc.Is2D, sphereDesc.Radius) { LocalOffset = sphereDesc.LocalOffset }; } else if (type == typeof(StaticPlaneColliderShapeDesc)) { var planeDesc = (StaticPlaneColliderShapeDesc)desc; shape = new StaticPlaneColliderShape(planeDesc.Normal, planeDesc.Offset); } else if (type == typeof(ConvexHullColliderShapeDesc)) { var convexDesc = (ConvexHullColliderShapeDesc)desc; if (convexDesc.ConvexHulls == null) { return(null); } //Optimize performance and focus on less shapes creation since this shape could be nested if (convexDesc.ConvexHulls.Count == 1) { if (convexDesc.ConvexHulls[0].Count == 1 && convexDesc.ConvexHullsIndices[0][0].Count > 0) { shape = new ConvexHullColliderShape(convexDesc.ConvexHulls[0][0], convexDesc.ConvexHullsIndices[0][0], convexDesc.Scaling) { NeedsCustomCollisionCallback = true, }; //shape.UpdateLocalTransformations(); shape.Description = desc; return(shape); } if (convexDesc.ConvexHulls[0].Count <= 1) { return(null); } var subCompound = new CompoundColliderShape { NeedsCustomCollisionCallback = true, }; for (var i = 0; i < convexDesc.ConvexHulls[0].Count; i++) { var verts = convexDesc.ConvexHulls[0][i]; var indices = convexDesc.ConvexHullsIndices[0][i]; if (indices.Count == 0) { continue; } var subHull = new ConvexHullColliderShape(verts, indices, convexDesc.Scaling); //subHull.UpdateLocalTransformations(); subCompound.AddChildShape(subHull); } //subCompound.UpdateLocalTransformations(); subCompound.Description = desc; return(subCompound); } if (convexDesc.ConvexHulls.Count <= 1) { return(null); } var compound = new CompoundColliderShape { NeedsCustomCollisionCallback = true, }; for (var i = 0; i < convexDesc.ConvexHulls.Count; i++) { var verts = convexDesc.ConvexHulls[i]; var indices = convexDesc.ConvexHullsIndices[i]; if (verts.Count == 1) { if (indices[0].Count == 0) { continue; } var subHull = new ConvexHullColliderShape(verts[0], indices[0], convexDesc.Scaling); //subHull.UpdateLocalTransformations(); compound.AddChildShape(subHull); } else if (verts.Count > 1) { var subCompound = new CompoundColliderShape(); for (var b = 0; b < verts.Count; b++) { var subVerts = verts[b]; var subIndex = indices[b]; if (subIndex.Count == 0) { continue; } var subHull = new ConvexHullColliderShape(subVerts, subIndex, convexDesc.Scaling); //subHull.UpdateLocalTransformations(); subCompound.AddChildShape(subHull); } //subCompound.UpdateLocalTransformations(); compound.AddChildShape(subCompound); } } //compound.UpdateLocalTransformations(); compound.Description = desc; return(compound); } else if (type == typeof(ColliderShapeAssetDesc)) { var assetDesc = (ColliderShapeAssetDesc)desc; if (assetDesc.Shape == null) { return(null); } if (assetDesc.Shape.Shape == null) { assetDesc.Shape.Shape = Compose(assetDesc.Shape.Descriptions); } shape = assetDesc.Shape.Shape; } if (shape == null) { return(shape); } //shape.UpdateLocalTransformations(); shape.Description = desc; return(shape); }