///<summary> /// Updates the pair handler's contacts. ///</summary> ///<param name="dt">Timestep duration.</param> protected virtual void UpdateContacts(float dt) { UpdateContainedPairs(); //Eliminate old pairs. foreach (CollidablePair pair in subPairs.Keys) { if (!containedPairs.Contains(pair)) { pairsToRemove.Add(pair); } } for (int i = 0; i < pairsToRemove.Count; i++) { CollidablePairHandler toReturn = subPairs[pairsToRemove.Elements[i]]; subPairs.Remove(pairsToRemove.Elements[i]); toReturn.CleanUp(); toReturn.Factory.GiveBack(toReturn); } containedPairs.Clear(); pairsToRemove.Clear(); foreach (CollidablePairHandler pair in subPairs.Values) { if (pair.BroadPhaseOverlap.collisionRule < CollisionRule.NoNarrowPhaseUpdate) //Don't test if the collision rules say don't. { pair.UpdateCollision(dt); } } }
///<summary> /// Constructs a new nonconvex manifold constraint. ///</summary> public NonConvexContactManifoldConstraint(CollidablePairHandler pairHandler) : base(pairHandler) { //All of the constraints are always in the solver group. Some of them are just deactivated sometimes. //This reduces some bookkeeping complications. penetrationConstraints = new RawList <ContactPenetrationConstraint>(4); frictionConstraints = new RawList <ContactFrictionConstraint>(4); for (int i = 0; i < 4; i++) { var penetrationConstraint = new ContactPenetrationConstraint(); penetrationConstraintPool.Push(penetrationConstraint); Add(penetrationConstraint); var frictionConstraint = new ContactFrictionConstraint(); frictionConstraintPool.Push(frictionConstraint); Add(frictionConstraint); } }
internal void RemovePair(CollidablePairHandler pair, ref int index) { if (pairs.Count > index) { pairs.FastRemoveAt(index); if (pairs.Count > index) { var endPair = pairs.Elements[index]; if (endPair.CollidableA == this) { endPair.listIndexA = index; } else { endPair.listIndexB = index; } } } index = -1; }
///<summary> /// Constructs a new convex contact manifold constraint. ///</summary> public ConvexContactManifoldConstraint(CollidablePairHandler pairHandler) : base(pairHandler) { //All of the constraints are always in the solver group. Some of them are just deactivated sometimes. //This reduces some bookkeeping complications. penetrationConstraints = new RawList <ContactPenetrationConstraint>(4); //Order matters in this adding process. Sliding friction computes some information used by the twist friction, and both use penetration impulses. for (int i = 0; i < 4; i++) { var penetrationConstraint = new ContactPenetrationConstraint(); Add(penetrationConstraint); penetrationConstraintPool.Push(penetrationConstraint); } slidingFriction = new SlidingFrictionTwoAxis(); Add(slidingFriction); twistFriction = new TwistFrictionConstraint(); Add(twistFriction); }
static bool DefaultCCDFilter(CollidablePairHandler pair) { return(pair.broadPhaseOverlap.collisionRule < CollisionRule.NoSolver); }
internal void AddPair(CollidablePairHandler pair, ref int index) { index = pairs.Count; pairs.Add(pair); }
protected ContactManifoldConstraint(CollidablePairHandler pairHandler) { this.pair = pairHandler; }
internal ContactCollection(CollidablePairHandler pair) { this.pair = pair; }
/// <summary> /// Takes a collision pair and distributes its contacts into categories according to the categorizer's thresholds. /// </summary> /// <param name="pair">Source of the contacts to categorize.</param> /// <param name="characterCollidable">Collidable associated with the character.</param> /// <param name="downDirection">Down direction of the character.</param> /// <param name="tractionContacts">List to contain the traction contacts found in the input contacts list.</param> /// <param name="supportContacts">List to contain the support contacts found in the input contacts list.</param> /// <param name="sideContacts">List to contain the side contacts found in the input contacts list.</param> /// <param name="headContacts">List to contain the head contacts found in the input contacts list.</param> /// <typeparam name="TOutputContacts">List type used to store the output character contact structs.</typeparam> public void CategorizeContacts <TOutputContacts>(CollidablePairHandler pair, EntityCollidable characterCollidable, ref Vector3 downDirection, ref TOutputContacts tractionContacts, ref TOutputContacts supportContacts, ref TOutputContacts sideContacts, ref TOutputContacts headContacts) where TOutputContacts : IList <CharacterContact> { var contactCollection = pair.Contacts; for (int i = pair.ContactCount - 1; i >= 0; --i) { var contactInfo = contactCollection[i]; CharacterContact characterContact; characterContact.Contact = new ContactData(contactInfo.Contact); characterContact.Collidable = pair.CollidableA == characterCollidable ? pair.CollidableB : pair.CollidableA; //It's possible that a subpair has a non-normal collision rule, even if the parent pair is normal. //Note that only contacts with nonnegative penetration depths are used. //Negative depth contacts are 'speculative' in nature. //If we were to use such a speculative contact for support, the character would find supports //in situations where it should not. //This can actually be useful in some situations, but keep it disabled by default. if (contactInfo.Pair.CollisionRule != CollisionRule.Normal || characterContact.Contact.PenetrationDepth < 0) { continue; } float dot; Vector3 offset; Vector3.Subtract(ref characterContact.Contact.Position, ref characterCollidable.worldTransform.Position, out offset); Vector3.Dot(ref characterContact.Contact.Normal, ref offset, out dot); if (dot < 0) { //The normal should face outward. Vector3.Negate(ref characterContact.Contact.Normal, out characterContact.Contact.Normal); } Vector3.Dot(ref characterContact.Contact.Normal, ref downDirection, out dot); if (dot > SupportThreshold) { //It's a support. supportContacts.Add(characterContact); if (dot > TractionThreshold) { //It's a traction contact. tractionContacts.Add(characterContact); } else { //Considering the side contacts to be supports can help with upstepping. sideContacts.Add(characterContact); } } else if (dot < HeadThreshold) { //It's a head contact. headContacts.Add(characterContact); } else { //It's a side contact. These could obstruct the stepping. sideContacts.Add(characterContact); } } }