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); } }
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; } } }
/// <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); } }