Exemple #1
0
        protected void TryToAdd(Collidable a, Collidable b, Material materialA, Material materialB)
        {
            CollisionRule rule;

            if ((rule = CollisionRules.collisionRuleCalculator(a, b)) < CollisionRule.NoNarrowPhasePair)
            {
                //Clamp the rule to the parent's rule.  Always use the more restrictive option.
                //Don't have to test for NoNarrowPhasePair rule on the parent's rule because then the parent wouldn't exist!
                if (rule < CollisionRule)
                {
                    rule = CollisionRule;
                }
                var pair = new CollidablePair(a, b);
                if (!subPairs.ContainsKey(pair))
                {
                    var newPair = NarrowPhaseHelper.GetPairHandler(ref pair, rule);
                    if (newPair != null)
                    {
                        newPair.UpdateMaterialProperties(materialA, materialB);  //Override the materials, if necessary.
                        newPair.Parent = this;
                        subPairs.Add(pair, newPair);
                    }
                }
                containedPairs.Add(pair);
            }
        }
Exemple #2
0
        void UpdateBroadPhaseOverlap(int i)
        {
            BroadPhaseOverlap overlap = broadPhaseOverlaps.Elements[i];

            if (overlap.collisionRule < CollisionRule.NoNarrowPhasePair)
            {
                NarrowPhasePair pair;
                //see if the overlap is already present in the narrow phase.
                if (!overlapMapping.TryGetValue(overlap, out pair))
                {
                    //Create/enqueue based on collision table
                    pair = NarrowPhaseHelper.GetPairHandler(ref overlap);
                    if (pair != null)
                    {
                        pair.NarrowPhase = this;
                        //Add the new object to the 'todo' list.
                        //Technically, this doesn't need to be thread-safe when this is called from the sequential context.
                        //It's just bunched together for maintainability despite the slight performance hit.
                        newNarrowPhasePairs.Enqueue(pair);
                    }
                }
                if (pair != null)
                {
                    //Update the collision rule.
                    pair.CollisionRule = overlap.collisionRule;
                    if (pair.BroadPhaseOverlap.collisionRule < CollisionRule.NoNarrowPhaseUpdate)
                    {
                        pair.UpdateCollision(TimeStepSettings.TimeStepDuration);
                    }
                    pair.NeedsUpdate = false;
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Finds contacts between the query object and any intersected objects within the character's bounding box.
        /// </summary>
        /// <param name="queryObject">Collidable to query for contacts with.</param>
        /// <param name="tractionContacts">Output contacts that would provide traction.</param>
        /// <param name="supportContacts">Output contacts that would provide support.</param>
        /// <param name="sideContacts">Output contacts on the sides of the query object.</param>
        /// <param name="headContacts">Output contacts on the head of the query object.</param>
        /// <param name="forceStandardPairsToBeQueries">An extremely hacky control parameter that makes any mesh-cylinder pair treat the mesh as double sided. Useful for not going through the ceiling when changing stances.</param>
        public void QueryContacts(EntityCollidable queryObject,
                                  ref QuickList <CharacterContact> tractionContacts, ref QuickList <CharacterContact> supportContacts, ref QuickList <CharacterContact> sideContacts, ref QuickList <CharacterContact> headContacts,
                                  bool forceStandardPairsToBeQueries = false)
        {
            var downDirection = characterBody.orientationMatrix.Down;

            tractionContacts.Clear();
            supportContacts.Clear();
            sideContacts.Clear();
            headContacts.Clear();

            foreach (var collidable in characterBody.CollisionInformation.OverlappedCollidables)
            {
                //The query object is assumed to have a valid bounding box.
                if (collidable.BoundingBox.Intersects(queryObject.BoundingBox))
                {
                    var pair        = new CollidablePair(collidable, queryObject);
                    var pairHandler = NarrowPhaseHelper.GetPairHandler(ref pair);
                    if (pairHandler.CollisionRule == CollisionRule.Normal)
                    {
                        if (forceStandardPairsToBeQueries)
                        {
                            //TODO: This is a massive hack that assumes a fixed set of collidable types. This won't work in the long run.
                            //The only reason it's here is that it was the easiest solution, combined with the fact that the character has to be rewritten for v2 anyway.
                            //Hopefully no one gets bit by this before the replacement is available.
                            //The core reason it exists is that one sided meshes don't generate contacts on their backside. That means a query shape can end up above a ceiling
                            //and it won't detect the ceiling. A better solution would be to let the caller choose whether or not to filter the contacts, and then use a
                            //direct test rather than stateful pair to perform the query here. Still some type-related annoyance to deal with, but a bit better.
                            var standardPair = pairHandler as StandardPairHandler;
                            if (standardPair != null)
                            {
                                standardPair.ContactManifold.IsQuery = true;
                            }
                        }
                        pairHandler.SuppressEvents = true;
                        pairHandler.UpdateCollision(0);
                        pairHandler.SuppressEvents = false;
                        if (forceStandardPairsToBeQueries)
                        {
                            //TODO: Again, superhack! Avoid this in v2.
                            var standardPair = pairHandler as StandardPairHandler;
                            if (standardPair != null)
                            {
                                standardPair.ContactManifold.IsQuery = false;
                            }
                        }

                        contactCategorizer.CategorizeContacts(pairHandler, characterBody.CollisionInformation, ref downDirection,
                                                              ref tractionContacts, ref supportContacts, ref sideContacts, ref headContacts);
                    }
                    //TODO: It would be nice if this was a bit easier.
                    //Having to remember to clean up AND give it back is a bit weird, especially with the property-diving.
                    //No one would ever just guess this correctly.
                    //At least hide it behind a NarrowPhaseHelper function.
                    pairHandler.CleanUp();
                    pairHandler.Factory.GiveBack(pairHandler);
                }
            }
        }
        protected void TryToAdd(int index)
        {
            var entry = new TriangleEntry {
                Index = index
            };

            if (!subPairs.ContainsKey(entry))
            {
                var collidablePair = new CollidablePair(CollidableA, entry.Collidable = GetOpposingCollidable(index));
                var newPair        = (MobileMeshPairHandler)NarrowPhaseHelper.GetPairHandler(ref collidablePair);
                if (newPair != null)
                {
                    newPair.CollisionRule = CollisionRule;
                    newPair.UpdateMaterialProperties(MaterialA, MaterialB);  //Override the materials, if necessary.  Meshes don't currently support custom materials but..
                    newPair.Parent = this;
                    subPairs.Add(entry, newPair);
                }
            }
            containedPairs.Add(entry);
        }
        protected void TryToAdd(EntityCollidable collidable)
        {
            CollisionRule rule;

            if ((rule = CollisionRules.collisionRuleCalculator(DetectorVolume, collidable)) < CollisionRule.NoNarrowPhasePair)
            {
                //Clamp the rule to the parent's rule.  Always use the more restrictive option.
                //Don't have to test for NoNarrowPhasePair rule on the parent's rule because then the parent wouldn't exist!
                if (rule < CollisionRule)
                {
                    rule = CollisionRule;
                }
                if (!subPairs.ContainsKey(collidable))
                {
                    var newPair = NarrowPhaseHelper.GetPairHandler(DetectorVolume, collidable, rule) as DetectorVolumePairHandler;
                    if (newPair != null)
                    {
                        newPair.Parent = this;
                        subPairs.Add(collidable, newPair);
                    }
                }
                containedPairs.Add(collidable);
            }
        }