/// <summary>
        /// Tests a ray against the collidable.
        /// </summary>
        /// <param name="ray">Ray to test.</param>
        /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param>
        /// <param name="rayHit">Hit data, if any.</param>
        /// <param name="hitChild">Child collidable hit by the ray, if any.</param>
        /// <returns>Whether or not the ray hit the entry.</returns>
        public bool RayCast(Ray ray, float maximumLength, out RayHit rayHit, out CompoundChild hitChild)
        {
            rayHit   = new RayHit();
            hitChild = null;
            var hitElements = PhysicsResources.GetCompoundChildList();

            if (hierarchy.Tree.GetOverlaps(ray, maximumLength, hitElements))
            {
                rayHit.T = float.MaxValue;
                for (int i = 0; i < hitElements.Count; i++)
                {
                    EntityCollidable candidate = hitElements.Elements[i].CollisionInformation;
                    RayHit           tempHit;
                    if (candidate.RayCast(ray, maximumLength, out tempHit) && tempHit.T < rayHit.T)
                    {
                        rayHit   = tempHit;
                        hitChild = hitElements.Elements[i];
                    }
                }
                PhysicsResources.GiveBack(hitElements);
                return(rayHit.T != float.MaxValue);
            }
            PhysicsResources.GiveBack(hitElements);
            return(false);
        }
        ///<summary>
        /// Constructs a new CompoundCollidable.
        ///</summary>
        ///<param name="compoundShape">Compound shape to use for the collidable.</param>
        public CompoundCollidable(CompoundShape compoundShape)
            : base(compoundShape)
        {
            Events = new CompoundEventManager();

            for (int i = 0; i < compoundShape.shapes.Count; i++)
            {
                CompoundChild child = GetChild(compoundShape.shapes.Elements[i], i);
                this.children.Add(child);
            }
            hierarchy = new CompoundHierarchy(this);
        }
Example #3
0
        ///<summary>
        /// Constructs a new compound hierarchy.
        ///</summary>
        ///<param name="owner">Owner of the hierarchy.</param>
        public CompoundHierarchy(CompoundCollidable owner)
        {
            this.owner = owner;
            var children = new CompoundChild[owner.children.Count];

            Array.Copy(owner.children.Elements, children, owner.children.Count);
            //In order to initialize a good tree, the local space bounding boxes should first be computed.
            //Otherwise, the tree would try to create a hierarchy based on a bunch of zeroed out bounding boxes!
            for (int i = 0; i < children.Length; i++)
            {
                children[i].CollisionInformation.worldTransform = owner.Shape.shapes.Elements[i].LocalTransform;
                children[i].CollisionInformation.UpdateBoundingBoxInternal(0);
            }
            tree = new BoundingBoxTree <CompoundChild>(children);
        }
        /// <summary>
        /// Casts a convex shape against the collidable.
        /// </summary>
        /// <param name="castShape">Shape to cast.</param>
        /// <param name="startingTransform">Initial transform of the shape.</param>
        /// <param name="sweep">Sweep to apply to the shape.</param>
        /// <param name="filter">Test to apply to the entry. If it returns true, the entry is processed, otherwise the entry is ignored. If a collidable hierarchy is present
        /// in the entry, this filter will be passed into inner ray casts.</param>
        /// <param name="hit">Hit data, if any.</param>
        /// <param name="hitChild">Child hit by the cast.</param>
        /// <returns>Whether or not the cast hit anything.</returns>
        public bool ConvexCast(CollisionShapes.ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, Func <BroadPhaseEntry, bool> filter, out RayHit hit, out CompoundChild hitChild)
        {
            hit      = new RayHit();
            hitChild = null;
            if (!filter(this))
            {
                return(false);
            }
            BoundingBox boundingBox;

            castShape.GetSweptBoundingBox(ref startingTransform, ref sweep, out boundingBox);
            var hitElements = PhysicsResources.GetCompoundChildList();

            if (hierarchy.Tree.GetOverlaps(boundingBox, hitElements))
            {
                hit.T = float.MaxValue;
                for (int i = 0; i < hitElements.Count; i++)
                {
                    var    candidate = hitElements.Elements[i].CollisionInformation;
                    RayHit tempHit;
                    if (candidate.ConvexCast(castShape, ref startingTransform, ref sweep, filter, out tempHit) && tempHit.T < hit.T)
                    {
                        hit      = tempHit;
                        hitChild = hitElements.Elements[i];
                    }
                }
                PhysicsResources.GiveBack(hitElements);
                return(hit.T != float.MaxValue);
            }
            PhysicsResources.GiveBack(hitElements);
            return(false);
        }
 /// <summary>
 /// Tests a ray against the collidable.
 /// </summary>
 /// <param name="ray">Ray to test.</param>
 /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param>
 /// <param name="filter">Test to apply to the entry. If it returns true, the entry is processed, otherwise the entry is ignored. If a collidable hierarchy is present
 /// in the entry, this filter will be passed into inner ray casts.</param>
 /// <param name="rayHit">Hit location of the ray on the collidable, if any.</param>
 /// <param name="hitChild">Child hit by the ray.</param>
 /// <returns>Whether or not the ray hit the collidable.</returns>
 public bool RayCast(Ray ray, float maximumLength, Func <BroadPhaseEntry, bool> filter, out RayHit rayHit, out CompoundChild hitChild)
 {
     rayHit   = new RayHit();
     hitChild = null;
     if (filter(this))
     {
         var hitElements = PhysicsResources.GetCompoundChildList();
         if (hierarchy.Tree.GetOverlaps(ray, maximumLength, hitElements))
         {
             rayHit.T = float.MaxValue;
             for (int i = 0; i < hitElements.Count; i++)
             {
                 RayHit tempHit;
                 if (hitElements.Elements[i].CollisionInformation.RayCast(ray, maximumLength, filter, out tempHit) && tempHit.T < rayHit.T)
                 {
                     rayHit   = tempHit;
                     hitChild = hitElements.Elements[i];
                 }
             }
             PhysicsResources.GiveBack(hitElements);
             return(rayHit.T != float.MaxValue);
         }
         PhysicsResources.GiveBack(hitElements);
     }
     return(false);
 }