/// <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;
        }
Example #4
0
        public void Dispose()
        {
            if (Shape == null)
            {
                return;
            }

            var compound = Shape.Parent;

            compound?.RemoveChildShape(Shape);

            Shape.Dispose();
            Shape = null;
        }
Example #5
0
        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);
        }
Example #6
0
        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);
        }
Example #7
0
        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);
        }