Ejemplo n.º 1
0
        /// <summary>
        /// Finds a supporting entity, the contact location, and the contact normal.
        /// </summary>
        /// <param name="location">Contact point between the wheel and the support.</param>
        /// <param name="normal">Contact normal between the wheel and the support.</param>
        /// <param name="suspensionLength">Length of the suspension at the contact.</param>
        /// <param name="entity">Supporting object.</param>
        /// <param name="material">Material of the wheel.</param>
        /// <returns>Whether or not any support was found.</returns>
        protected internal override bool FindSupport(out Vector3 location, out Vector3 normal, out float suspensionLength, out Entity entity, out Material material)
        {
            suspensionLength = float.MaxValue;
            location         = Toolbox.NoVector;
            entity           = null;
            normal           = Toolbox.NoVector;
            material         = null;

            Collidable testCollider;
            RayHit     rayHit;

            bool hit = false;

            for (int i = 0; i < detector.CollisionInformation.pairs.Count; i++)
            {
                NarrowPhasePair pair = detector.CollisionInformation.pairs[i];
                testCollider = (pair.BroadPhaseOverlap.entryA == detector.CollisionInformation ? pair.BroadPhaseOverlap.entryB : pair.BroadPhaseOverlap.entryA) as Collidable;
                if (testCollider != null)
                {
                    if (CollisionRules.CollisionRuleCalculator(CollisionRules, testCollider.collisionRules) == CollisionRule.Normal &&
                        testCollider.RayCast(new Ray(wheel.suspension.worldAttachmentPoint, wheel.suspension.worldDirection), wheel.suspension.restLength,
                                             out rayHit) &&
                        rayHit.T < suspensionLength)
                    {
                        suspensionLength = rayHit.T;
                        EntityCollidable entityCollisionInfo;
                        if ((entityCollisionInfo = testCollider as EntityCollidable) != null)
                        {
                            entity   = entityCollisionInfo.Entity;
                            material = entityCollisionInfo.Entity.Material;
                        }
                        else
                        {
                            entity = null;
                            var materialOwner = testCollider as IMaterialOwner;
                            if (materialOwner != null)
                            {
                                material = materialOwner.Material;
                            }
                        }
                        location = rayHit.Location;
                        normal   = rayHit.Normal;
                        hit      = true;
                    }
                }
            }
            if (hit)
            {
                if (suspensionLength > 0)
                {
                    normal.Normalize();
                }
                else
                {
                    Vector3.Negate(ref wheel.suspension.worldDirection, out normal);
                }
                return(true);
            }
            return(false);
        }
Ejemplo n.º 2
0
 protected void OnCreatePair(NarrowPhasePair pair)
 {
     overlapMapping.Add(pair.BroadPhaseOverlap, pair);
     pair.OnAddedToNarrowPhase();
     if (CreatingPair != null)
         CreatingPair(pair);
 }
Ejemplo n.º 3
0
 protected void OnRemovePair(NarrowPhasePair pair)
 {
     overlapMapping.Remove(pair.BroadPhaseOverlap);
     pair.CleanUp();
     pair.Factory.GiveBack(pair);
     if (RemovingPair != null)
     {
         RemovingPair(pair);
     }
 }
Ejemplo n.º 4
0
        void RemoveFriction(EntityCollidable sender, BroadPhaseEntry other, NarrowPhasePair pair)
        {
            var collidablePair = pair as CollidablePairHandler;

            if (collidablePair != null)
            {
                //The default values for InteractionProperties is all zeroes- zero friction, zero bounciness.
                //That's exactly how we want the character to behave when hitting objects.
                collidablePair.UpdateMaterialProperties(new InteractionProperties());
            }
        }
Ejemplo n.º 5
0
 public void OnPairUpdated(BroadPhaseEntry other, NarrowPhasePair collisionPair)
 {
     if (InternalPairUpdated != null)
     {
         eventStoragePairUpdated.Enqueue(new EventStoragePairUpdated(other, collisionPair));
     }
     if (PairUpdating != null)
     {
         PairUpdating(owner, other, collisionPair);
     }
 }
Ejemplo n.º 6
0
        private void RemoveStaleOverlaps()
        {
            //Remove stale objects.
            for (int i = narrowPhasePairs.Count - 1; i >= 0; i--)
            {
                NarrowPhasePair pair = narrowPhasePairs.Elements[i];

                //A stale overlap is a pair which has not been updated, but not because of inactivity.

                //Pairs between two inactive shapes are not updated because the broad phase does not output overlaps
                //between inactive entries.  We need to keep such pairs around, otherwise when they wake up, lots of extra work
                //will be needed and quality will suffer.

                //The classic stale overlap is two objects which have moved apart.  Because the bounding boxes no longer overlap,
                //the broad phase does not generate an overlap for them.  Obviously, we should get rid of such a pair.
                //Any such pair will have at least one active member.  Having velocity requires activity and teleportation will activate the object.

                //There's another sneaky kind of stale overlap.  Consider a sleeping dynamic object on a Terrain.  The Terrain, being a static object,
                //is considered inactive.  The sleeping dynamic object is also inactive.  Now, remove the sleeping dynamic object.
                //Both objects are still considered inactive.  But the pair is clearly stale- one of its members doesn't even exist anymore!
                //This has nasty side effects, like retaining memory.  To solve this, also check to see if either member does not belong to the simulation.


                if (pair.NeedsUpdate &&                                 //If we didn't receive an update in the previous narrow phase run and...
                    (pair.broadPhaseOverlap.entryA.IsActive ||
                     pair.broadPhaseOverlap.entryB.IsActive ||          //one of us is active or..
                     pair.broadPhaseOverlap.entryA.BroadPhase == null ||
                     pair.broadPhaseOverlap.entryB.BroadPhase == null)) //one of us doesn't exist anymore...
                {
                    //Get rid of the pair!
                    if (RemovingPair != null)
                    {
                        RemovingPair(pair);
                    }

                    narrowPhasePairs.FastRemoveAt(i);
                    overlapMapping.Remove(pair.BroadPhaseOverlap);
                    //The clean up will issue an order to get rid of the solver updateable if it is active.
                    pair.CleanUp();
                    pair.Factory.GiveBack(pair);
                }
                else
                {
                    pair.NeedsUpdate = true;
                }
            }
        }
Ejemplo n.º 7
0
        ///<summary>
        /// Gets a narrow phase pair for a given broad phase overlap.
        ///</summary>
        ///<param name="pair">Overlap to use to create the pair.</param>
        ///<returns>A INarrowPhasePair for the overlap.</returns>
        public static NarrowPhasePair GetPairHandler(ref BroadPhaseOverlap pair)
        {
            NarrowPhasePairFactory factory;

            if (collisionManagers.TryGetValue(new TypePair(pair.entryA.GetType(), pair.entryB.GetType()), out factory))
            {
                var toReturn = factory.GetNarrowPhasePair();
                toReturn.BroadPhaseOverlap = pair;
                toReturn.Factory           = factory;
                return(toReturn);
            }
            //Convex-convex collisions are a pretty significant chunk of all tests, so rather than defining them all, just have a fallback.
            var a = pair.entryA as ConvexCollidable;
            var b = pair.entryB as ConvexCollidable;

            if (a != null && b != null)
            {
                NarrowPhasePair toReturn = Factories.ConvexConvex.GetNarrowPhasePair();
                toReturn.BroadPhaseOverlap = pair;
                toReturn.Factory           = Factories.ConvexConvex;
                return(toReturn);
            }
            return(null);
        }
 internal EventStoragePairUpdated(BroadPhaseEntry other, NarrowPhasePair pair)
 {
     this.other = other;
     this.pair  = pair;
 }
 /// <summary>
 /// Returns a pair to the factory for re-use.
 /// </summary>
 /// <param name="pair">Pair to return.</param>
 public abstract void GiveBack(NarrowPhasePair pair);
Ejemplo n.º 10
0
 private void OnCollisionPairCreated(EntityCollidable sender, BroadPhaseEntry other, NarrowPhasePair pair)
 {
     if (!(other.Tag is Collider))
     {
         Console.WriteLine("ERROR: TAG WAS NOT COLLIDER.");
     }
     else
     {
         Collider otherCollider = (Collider)other.Tag;
         TriggerEntered?.Invoke(otherCollider);
     }
 }