Пример #1
0
 ///<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);
     }
 }
Пример #2
0
 ///<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);
     }
 }
Пример #3
0
        protected BroadPhaseEntry()
        {
            CollisionRules = new CollisionRules();
            collisionRulesUpdatedDelegate = CollisionRulesUpdated;

            hashCode = (int)(base.GetHashCode() * 0xd8163841);
        }
Пример #4
0
 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);
     }
 }
Пример #5
0
 protected override void CollisionRulesUpdated()
 {
     foreach (var pair in pairs.Values)
     {
         pair.CollisionRule = CollisionRules.CollisionRuleCalculator(pair.BroadPhaseOverlap.entryA, pair.BroadPhaseOverlap.entryB);
     }
 }
Пример #6
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);
            }
        }
Пример #7
0
 protected internal CollisionRule GetCollisionRule(BroadPhaseEntry entryA, BroadPhaseEntry entryB)
 {
     if (entryA.IsActive || entryB.IsActive)
     {
         return(CollisionRules.collisionRuleCalculator(entryA, entryB));
     }
     return(CollisionRule.NoBroadPhase);
 }
Пример #8
0
        ///<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);
        }
Пример #9
0
        ///<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);
            }
        }
Пример #11
0
 ///<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);
 }
Пример #12
0
 ///<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);
 }
Пример #13
0
 ///<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);
 }
Пример #14
0
 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);
 }
Пример #15
0
        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);
                }
            }
        }
Пример #16
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="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);
        }