///<summary> /// Tries to remove a relationship about ownerB from rulesA's Specific list. ///</summary> ///<param name="rulesA">Collision rules that will lose an entry in its Specific relationships.</param> ///<param name="ownerB">Owner of the collision rules that will be removed from ownerA's Specific relationships.</param> public static void RemoveRule(CollisionRules rulesA, ICollisionRulesOwner ownerB) { if (!rulesA.specific.Remove(ownerB.CollisionRules)) { ownerB.CollisionRules.specific.Remove(rulesA); } }
///<summary> /// Tries to remove a relationship about rulesB from ownerA's Specific list. ///</summary> ///<param name="ownerA">Owner of the collision rules that will lose an entry in its Specific relationships.</param> ///<param name="rulesB">Collision rules that will be removed from ownerA's Specific relationships.</param> public static void RemoveRule(ICollisionRulesOwner ownerA, CollisionRules rulesB) { if (!ownerA.CollisionRules.specific.Remove(rulesB)) { rulesB.specific.Remove(ownerA.CollisionRules); } }
protected BroadPhaseEntry() { CollisionRules = new CollisionRules(); collisionRulesUpdatedDelegate = CollisionRulesUpdated; hashCode = (int)(base.GetHashCode() * 0xd8163841); }
protected override void CollisionRulesUpdated() { for (int i = 0; i < pairs.Count; i++) { pairs[i].CollisionRule = CollisionRules.CollisionRuleCalculator(pairs[i].BroadPhaseOverlap.entryA, pairs[i].BroadPhaseOverlap.entryB); } }
protected override void CollisionRulesUpdated() { foreach (var pair in pairs.Values) { pair.CollisionRule = CollisionRules.CollisionRuleCalculator(pair.BroadPhaseOverlap.entryA, pair.BroadPhaseOverlap.entryB); } }
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); } }
protected internal CollisionRule GetCollisionRule(BroadPhaseEntry entryA, BroadPhaseEntry entryB) { if (entryA.IsActive || entryB.IsActive) { return(CollisionRules.collisionRuleCalculator(entryA, entryB)); } return(CollisionRule.NoBroadPhase); }
///<summary> /// Default implementation used to calculate collision rules due to the rulesets' specific relationships. ///</summary> ///<param name="a">First ruleset in the pair.</param> ///<param name="b">Second ruleset in the pair.</param> ///<returns>Collision rule governing the interaction between the pair.</returns> public static CollisionRule GetSpecificCollisionRuleDefault(CollisionRules a, CollisionRules b) { CollisionRule aToB; a.specific.WrappedDictionary.TryGetValue(b, out aToB); CollisionRule bToA; b.specific.WrappedDictionary.TryGetValue(a, out bToA); return(aToB > bToA ? aToB : bToA); }
///<summary> /// Default implementation used to calculate collision rules due to the rulesets' collision groups. ///</summary> ///<param name="a">First ruleset in the pair.</param> ///<param name="b">Second ruleset in the pair.</param> ///<returns>Collision rule governing the interaction between the pair.</returns> public static CollisionRule GetGroupCollisionRuleDefault(CollisionRules a, CollisionRules b) { if (a.group == null || b.group == null) { return(CollisionRule.Defer); //This can happen occasionally when objects aren't in a space or are being handled uniquely (like in compound bodies). } CollisionRule pairRule; CollisionGroupRules.TryGetValue(new CollisionGroupPair(a.group, b.group), out pairRule); return(pairRule); }
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); } }
///<summary> /// Default implementation used to calculate collision rules due to the rulesets' personal rules. ///</summary> ///<param name="a">First ruleset in the pair.</param> ///<param name="b">Second ruleset in the pair.</param> ///<returns>Collision rule governing the interaction between the pair.</returns> public static CollisionRule GetPersonalCollisionRuleDefault(CollisionRules a, CollisionRules b) { return(a.personal > b.personal ? a.personal : b.personal); }
///<summary> /// Adds an entry in rulesA's Specific relationships list about ownerB. ///</summary> ///<param name="ownerA">Owner of the collision rules that will gain an entry in its Specific relationships.</param> ///<param name="rulesB">Collision rules that will be added to ownerA's Specific relationships.</param> ///<param name="rule">Rule assigned to the pair.</param> public static void AddRule(ICollisionRulesOwner ownerA, CollisionRules rulesB, CollisionRule rule) { ownerA.CollisionRules.specific.Add(rulesB, rule); }
///<summary> /// Adds an entry in rulesA's Specific relationships list about ownerB. ///</summary> ///<param name="rulesA">Collision rules that will gain an entry in its Specific relationships.</param> ///<param name="ownerB">Owner of the collision rules that will be added to ownerA's Specific relationships.</param> ///<param name="rule">Rule assigned to the pair.</param> public static void AddRule(CollisionRules rulesA, ICollisionRulesOwner ownerB, CollisionRule rule) { rulesA.specific.Add(ownerB.CollisionRules, rule); }
bool SupportRayFilterFunction(BroadPhaseEntry entry) { //Only permit an object to be used as a support if it fully collides with the character. return(CollisionRules.CollisionRuleCalculator(entry, characterBody.CollisionInformation) == CollisionRule.Normal); }
void AnalyzeEntry(int i) { var entityCollidable = broadPhaseEntries[i] as EntityCollidable; if (entityCollidable != null && entityCollidable.IsActive && entityCollidable.entity.isDynamic && CollisionRules.collisionRuleCalculator(this, entityCollidable) <= CollisionRule.Normal) { bool keepGoing = false; foreach (var tri in surfaceTriangles) { //Don't need to do anything if the entity is outside of the water. if (Toolbox.IsPointInsideTriangle(ref tri[0], ref tri[1], ref tri[2], ref entityCollidable.worldTransform.Position)) { keepGoing = true; break; } } if (!keepGoing) { return; } //The entity is submerged, apply buoyancy forces. float submergedVolume; Vector3 submergedCenter; GetBuoyancyInformation(entityCollidable, out submergedVolume, out submergedCenter); if (submergedVolume > 0) { //The approximation can sometimes output a volume greater than the shape itself. Don't let that error seep into usage. float fractionSubmerged = Math.Min(1, submergedVolume / entityCollidable.entity.CollisionInformation.Shape.Volume); //Divide the volume by the density multiplier if present. float densityMultiplier; if (DensityMultipliers.TryGetValue(entityCollidable.entity, out densityMultiplier)) { submergedVolume /= densityMultiplier; } Vector3 force; Vector3.Multiply(ref upVector, -gravity * Density * dt * submergedVolume, out force); entityCollidable.entity.ApplyImpulseWithoutActivating(ref submergedCenter, ref force); //Flow if (FlowForce != 0) { float dot = Math.Max(Vector3.Dot(entityCollidable.entity.linearVelocity, flowDirection), 0); if (dot < MaxFlowSpeed) { force = Math.Min(FlowForce, (MaxFlowSpeed - dot) * entityCollidable.entity.mass) * dt * fractionSubmerged * FlowDirection; entityCollidable.entity.ApplyLinearImpulse(ref force); } } //Damping entityCollidable.entity.ModifyLinearDamping(fractionSubmerged * LinearDamping); entityCollidable.entity.ModifyAngularDamping(fractionSubmerged * AngularDamping); } } }
/// <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="supportingCollidable">Collidable supporting the wheel, if any.</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 Collidable supportingCollidable, out Entity entity, out Material material) { suspensionLength = float.MaxValue; location = Toolbox.NoVector; supportingCollidable = null; entity = null; normal = Toolbox.NoVector; material = null; Collidable testCollidable; RayHit rayHit; bool hit = false; for (int i = 0; i < detector.CollisionInformation.pairs.Count; i++) { var pair = detector.CollisionInformation.pairs[i]; testCollidable = (pair.BroadPhaseOverlap.entryA == detector.CollisionInformation ? pair.BroadPhaseOverlap.entryB : pair.BroadPhaseOverlap.entryA) as Collidable; if (testCollidable != null) { if (CollisionRules.CollisionRuleCalculator(this, testCollidable) == CollisionRule.Normal && testCollidable.RayCast(new Ray(wheel.suspension.worldAttachmentPoint, wheel.suspension.worldDirection), wheel.suspension.restLength, out rayHit) && rayHit.T < suspensionLength) { suspensionLength = rayHit.T; EntityCollidable entityCollidable; if ((entityCollidable = testCollidable as EntityCollidable) != null) { entity = entityCollidable.Entity; material = entityCollidable.Entity.Material; } else { entity = null; supportingCollidable = testCollidable; var materialOwner = testCollidable 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); }