Пример #1
0
        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))
                {
                    DetectorVolumePairHandler newPair =
                        NarrowPhaseHelper.GetPairHandler(DetectorVolume, collidable, rule) as DetectorVolumePairHandler;
                    if (newPair != null)
                    {
                        newPair.Parent = this;
                        subPairs.Add(collidable, newPair);
                    }
                }

                containedPairs.Add(collidable);
            }
        }
Пример #2
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);
            }
        }
Пример #3
0
 protected internal CollisionRule GetCollisionRule(BroadPhaseEntry entryA, BroadPhaseEntry entryB)
 {
     if (entryA.IsActive || entryB.IsActive)
     {
         return(CollisionRules.collisionRuleCalculator(entryA, entryB));
     }
     return(CollisionRule.NoBroadPhase);
 }
Пример #4
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;
                Vector3f 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;
                    }
                    Vector3f force;
                    Vector3f.Multiply(ref upVector, -gravity * Density * dt * submergedVolume, out force);
                    entityCollidable.entity.ApplyImpulseWithoutActivating(ref submergedCenter, ref force);

                    //Flow
                    if (FlowForce != 0)
                    {
                        float dot = Math.Max(Vector3f.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);
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Updates the listing of contained entities and their states after the end of a space update.
        /// </summary>
        /// <param name="dt">Time since last frame in simulation seconds.</param>
        void IEndOfTimeStepUpdateable.Update(float dt)
        {
            //Get rid of any entities that are no longer nearby.
            foreach (Entity e in nearbyEntities.Keys)
            {
                if (!(e.CollisionInformation.BoundingBox.Intersects(TriangleMesh.Tree.BoundingBox)))
                {
                    entities.Add(e);
                }
            }

            for (int i = 0; i < entities.count; i++)
            {
                var e = entities.Elements[i];
                if (nearbyEntities[e].IsContained)
                {
                    //STOPS CONTAINED event
                    if (VolumeStopsContainingEntity != null)
                    {
                        VolumeStopsContainingEntity(this, e);
                    }
                }
                if (nearbyEntities[e].IsTouching)
                {
                    //STOPS TOUCHING event
                    if (EntityStopsTouching != null)
                    {
                        EntityStopsTouching(e, this);
                    }
                }

                nearbyEntities.Remove(e);
            }
            entities.Clear();

            //Get an updated look at all included entities.
            QueryAccelerator.GetEntries(TriangleMesh.Tree.BoundingBox, entries);
            for (int i = 0; i < entries.count; i++)
            {
                var e = entries.Elements[i] as EntityCollidable;
                if (e != null && CollisionRules.collisionRuleCalculator(e.collisionRules, collisionRules) <= CollisionRule.NoSolver)
                {
                    entities.Add(e.Entity);
                }
            }
            entries.Clear();
            ContainmentState containmentState;

            for (int i = 0; i < entities.count; i++)
            {
                var  e = entities.Elements[i];
                bool isContained;
                bool isTouching = IsEntityIntersectingVolume(e, out isContained);
                if (nearbyEntities.TryGetValue(e, out containmentState))
                {
                    if (!containmentState.IsTouching && isTouching)
                    {
                        //BEGIN TOUCHING event
                        if (EntityBeginsTouching != null)
                        {
                            EntityBeginsTouching(e, this);
                        }
                    }
                    else if (containmentState.IsTouching && !isTouching)
                    {
                        //END TOUCHING event
                        if (EntityStopsTouching != null)
                        {
                            EntityStopsTouching(e, this);
                        }
                    }
                    if (!containmentState.IsContained && isContained)
                    {
                        //BEGIN CONTAINED event
                        if (VolumeBeginsContainingEntity != null)
                        {
                            VolumeBeginsContainingEntity(this, e);
                        }
                    }
                    else if (containmentState.IsContained && !isContained)
                    {
                        //END CONTAINED event
                        if (VolumeStopsContainingEntity != null)
                        {
                            VolumeStopsContainingEntity(this, e);
                        }
                    }
                    nearbyEntities[e] = new ContainmentState(isTouching, isContained);
                }
                else
                {
                    //Add new entry for the new entity.
                    nearbyEntities.Add(e, new ContainmentState(isTouching, isContained));
                    if (isTouching)
                    {
                        //BEGIN TOUCHING event
                        if (EntityBeginsTouching != null)
                        {
                            EntityBeginsTouching(e, this);
                        }
                    }
                    if (isContained)
                    {
                        //BEGIN CONTAINED event
                        if (VolumeBeginsContainingEntity != null)
                        {
                            VolumeBeginsContainingEntity(this, e);
                        }
                    }
                }
            }

            entities.Clear();
        }