예제 #1
0
 public void addCollider(uint localID, ContactPoint contact)
 {
     Cleared = false;
     /*ContactPoint oldCol;
     if(!m_objCollisionList.TryGetValue(localID, out oldCol))
     {
         */
     lock (m_objCollisionList)
         m_objCollisionList[localID] = contact;
     /*}
     else
     {
         if(oldCol.PenetrationDepth < contact.PenetrationDepth)
             lock(m_objCollisionList)
                 m_objCollisionList[localID] = contact;
     }*/
 }
예제 #2
0
        public void PhysicsCollision(EventArgs e)
        {
            // single threaded here
            if (e == null)
                return;

            CollisionEventUpdate a = (CollisionEventUpdate) e;
            Dictionary<uint, ContactPoint> collissionswith = a.m_objCollisionList;
            List<uint> thisHitColliders = new List<uint>();
            List<uint> startedColliders = new List<uint>();
            ContactPoint startedCollider = new ContactPoint();

            // calculate things that started colliding this time
            // and build up list of colliders this time
            foreach (uint localID in collissionswith.Keys)
            {
                thisHitColliders.Add(localID);
                if (!m_lastColliders.Contains(localID))
                {
                    startedCollider = collissionswith[localID];
                    startedColliders.Add(localID);
                }
                //MainConsole.Instance.Debug("[OBJECT]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
            }

            // calculate things that ended colliding
#if (!ISWIN)
            List<uint> endedColliders = new List<uint>();
            foreach (uint localId in m_lastColliders)
            {
                if (!thisHitColliders.Contains(localId)) endedColliders.Add(localId);
            }
#else
            List<uint> endedColliders = m_lastColliders.Where(localID => !thisHitColliders.Contains(localID)).ToList();
#endif

            //add the items that started colliding this time to the last colliders list.
            m_lastColliders.AddRange(startedColliders);
            // remove things that ended colliding from the last colliders list
            foreach (uint localID in endedColliders)
                m_lastColliders.Remove(localID);

            if (m_parentGroup == null)
                return;
            if (m_parentGroup.IsDeleted)
                return;

            const string SoundGlassCollision = "6a45ba0b-5775-4ea8-8513-26008a17f873";
            const string SoundMetalCollision = "9e5c1297-6eed-40c0-825a-d9bcd86e3193";
            const string SoundStoneCollision = "9538f37c-456e-4047-81be-6435045608d4";
            const string SoundFleshCollision = "dce5fdd4-afe4-4ea1-822f-dd52cac46b08";
            const string SoundPlasticCollision = "0e24a717-b97e-4b77-9c94-b59a5a88b2da";
            const string SoundRubberCollision = "153c8bf7-fb89-4d89-b263-47e58b1b4774";
            const string SoundWoodCollision = "063c97d3-033a-4e9b-98d8-05c8074922cb";

            // play the sound.
            if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f)
            {
                SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, 0, 0, false, false);
            }
            else if (startedColliders.Count > 0)
            {
                switch (startedCollider.Type)
                {
                    case ActorTypes.Agent:
                        break; // Agents will play the sound so we don't

                    case ActorTypes.Ground:
                        SendSound(SoundWoodCollision, 1, true, 0, 0, false, false);
                        break; //Always play the click or thump sound when hitting ground

                    case ActorTypes.Prim:
                        if (m_material == OpenMetaverse.Material.Flesh)
                            SendSound(SoundFleshCollision, 1, true, 0, 0, false, false);
                        else if (m_material == OpenMetaverse.Material.Glass)
                            SendSound(SoundGlassCollision, 1, true, 0, 0, false, false);
                        else if (m_material == OpenMetaverse.Material.Metal)
                            SendSound(SoundMetalCollision, 1, true, 0, 0, false, false);
                        else if (m_material == OpenMetaverse.Material.Plastic)
                            SendSound(SoundPlasticCollision, 1, true, 0, 0, false, false);
                        else if (m_material == OpenMetaverse.Material.Rubber)
                            SendSound(SoundRubberCollision, 1, true, 0, 0, false, false);
                        else if (m_material == OpenMetaverse.Material.Stone)
                            SendSound(SoundStoneCollision, 1, true, 0, 0, false, false);
                        else if (m_material == OpenMetaverse.Material.Wood)
                            SendSound(SoundWoodCollision, 1, true, 0, 0, false, false);
                        break; //Play based on material type in prim2prim collisions

                    default:
                        break; //Unclear of what this object is, no sounds
                }
            }
            if (CollisionSprite != UUID.Zero && CollisionSoundVolume > 0.0f)
                // The collision volume isn't a mistake, its an SL feature/bug
            {
                // TODO: make a sprite!
            }
            if (((AggregateScriptEvents & scriptEvents.collision) != 0) ||
                ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
                ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
                ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
                ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
                ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
                (CollisionSound != UUID.Zero) ||
                PassCollisions != 2)
            {
                if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_start) != 0 ||
                    (m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision) != 0)
                {
                    // do event notification
                    if (startedColliders.Count > 0)
                    {
                        ColliderArgs StartCollidingMessage = new ColliderArgs();
                        List<DetectedObject> colliding = new List<DetectedObject>();
                        foreach (uint localId in startedColliders)
                        {
                            if (localId != 0)
                            {
                                // always running this check because if the user deletes the object it would return a null reference.
                                if (m_parentGroup == null)
                                    return;

                                if (m_parentGroup.Scene == null)
                                    return;

                                ISceneChildEntity obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
                                string data = "";
                                if (obj != null)
                                {
                                    if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.Name))
                                    {
                                        bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                        //If it is 1, it is to accept ONLY collisions from this object
                                        if (found)
                                        {
                                            DetectedObject detobj = new DetectedObject
                                                                        {
                                                                            keyUUID = obj.UUID, nameStr = obj.Name, ownerUUID = obj.OwnerID, posVector = obj.AbsolutePosition, rotQuat = obj.GetWorldRotation(), velVector = obj.Velocity, colliderType = 0, groupUUID = obj.GroupID
                                                                        };
                                            colliding.Add(detobj);
                                        }
                                            //If it is 0, it is to not accept collisions from this object
                                        else
                                        {
                                        }
                                    }
                                    else
                                    {
                                        bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                        //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work
                                        if (!found)
                                        {
                                            DetectedObject detobj = new DetectedObject
                                                                        {
                                                                            keyUUID = obj.UUID, nameStr = obj.Name, ownerUUID = obj.OwnerID, posVector = obj.AbsolutePosition, rotQuat = obj.GetWorldRotation(), velVector = obj.Velocity, colliderType = 0, groupUUID = obj.GroupID
                                                                        };
                                            colliding.Add(detobj);
                                        }
                                    }
                                }
                                else
                                {
                                    IScenePresence av = ParentGroup.Scene.GetScenePresence(localId);
                                    if (av != null)
                                    {
                                        if (av.LocalId == localId)
                                        {
                                            if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name))
                                            {
                                                bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                                //If it is 1, it is to accept ONLY collisions from this avatar
                                                if (found)
                                                {
                                                    DetectedObject detobj = new DetectedObject
                                                                                {
                                                                                    keyUUID = av.UUID, nameStr = av.ControllingClient.Name, ownerUUID = av.UUID, posVector = av.AbsolutePosition, rotQuat = av.Rotation, velVector = av.Velocity, colliderType = 0, groupUUID = av.ControllingClient.ActiveGroupId
                                                                                };
                                                    colliding.Add(detobj);
                                                }
                                                    //If it is 0, it is to not accept collisions from this avatar
                                                else
                                                {
                                                }
                                            }
                                            else
                                            {
                                                bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                                //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
                                                if (!found)
                                                {
                                                    DetectedObject detobj = new DetectedObject
                                                                                {
                                                                                    keyUUID = av.UUID, nameStr = av.ControllingClient.Name, ownerUUID = av.UUID, posVector = av.AbsolutePosition, rotQuat = av.Rotation, velVector = av.Velocity, colliderType = 0, groupUUID = av.ControllingClient.ActiveGroupId
                                                                                };
                                                    colliding.Add(detobj);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        if (colliding.Count > 0)
                        {
                            StartCollidingMessage.Colliders = colliding;
                            // always running this check because if the user deletes the object it would return a null reference.
                            if (m_parentGroup == null)
                                return;

                            if (m_parentGroup.Scene == null)
                                return;
                            //Always send to the prim it is occuring to
                            m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(this, StartCollidingMessage);
                            if ((this.UUID != this.ParentGroup.RootPart.UUID))
                            {
                                const int PASS_IF_NOT_HANDLED = 0;
                                const int PASS_ALWAYS = 1;
                                const int PASS_NEVER = 2;
                                if (this.PassCollisions == PASS_NEVER)
                                {
                                }
                                if (this.PassCollisions == PASS_ALWAYS)
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(
                                        this.ParentGroup.RootPart, StartCollidingMessage);
                                }
                                else if (((this.ScriptEvents & scriptEvents.collision_start) == 0) &&
                                         this.PassCollisions == PASS_IF_NOT_HANDLED)
                                    //If no event in this prim, pass to parent
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(
                                        this.ParentGroup.RootPart, StartCollidingMessage);
                                }
                            }
                        }
                    }
                }

                if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision) != 0)
                {
                    if (m_lastColliders.Count > 0)
                    {
                        ColliderArgs CollidingMessage = new ColliderArgs();
                        List<DetectedObject> colliding = new List<DetectedObject>();
                        foreach (uint localId in m_lastColliders)
                        {
                            if (localId != 0)
                            {
                                if (m_parentGroup == null)
                                    return;

                                if (m_parentGroup.Scene == null)
                                    return;

                                ISceneChildEntity obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
                                string data = "";
                                if (obj != null)
                                {
                                    if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.Name))
                                    {
                                        bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                        //If it is 1, it is to accept ONLY collisions from this object
                                        if (found)
                                        {
                                            DetectedObject detobj = new DetectedObject
                                                                        {
                                                                            keyUUID = obj.UUID, nameStr = obj.Name, ownerUUID = obj.OwnerID, posVector = obj.AbsolutePosition, rotQuat = obj.GetWorldRotation(), velVector = obj.Velocity, colliderType = 0, groupUUID = obj.GroupID
                                                                        };
                                            colliding.Add(detobj);
                                        }
                                            //If it is 0, it is to not accept collisions from this object
                                        else
                                        {
                                        }
                                    }
                                    else
                                    {
                                        bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                        //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work
                                        if (!found)
                                        {
                                            DetectedObject detobj = new DetectedObject
                                                                        {
                                                                            keyUUID = obj.UUID, nameStr = obj.Name, ownerUUID = obj.OwnerID, posVector = obj.AbsolutePosition, rotQuat = obj.GetWorldRotation(), velVector = obj.Velocity, colliderType = 0, groupUUID = obj.GroupID
                                                                        };
                                            colliding.Add(detobj);
                                        }
                                    }
                                }
                                else
                                {
                                    IScenePresence av = ParentGroup.Scene.GetScenePresence(localId);
                                    if (av != null)
                                    {
                                        if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name))
                                        {
                                            bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                            //If it is 1, it is to accept ONLY collisions from this avatar
                                            if (found)
                                            {
                                                DetectedObject detobj = new DetectedObject
                                                                            {
                                                                                keyUUID = av.UUID, nameStr = av.ControllingClient.Name, ownerUUID = av.UUID, posVector = av.AbsolutePosition, rotQuat = av.Rotation, velVector = av.Velocity, colliderType = 0, groupUUID = av.ControllingClient.ActiveGroupId
                                                                            };
                                                colliding.Add(detobj);
                                            }
                                                //If it is 0, it is to not accept collisions from this avatar
                                            else
                                            {
                                            }
                                        }
                                        else
                                        {
                                            bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                            //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
                                            if (!found)
                                            {
                                                DetectedObject detobj = new DetectedObject
                                                                            {
                                                                                keyUUID = av.UUID, nameStr = av.ControllingClient.Name, ownerUUID = av.UUID, posVector = av.AbsolutePosition, rotQuat = av.Rotation, velVector = av.Velocity, colliderType = 0, groupUUID = av.ControllingClient.ActiveGroupId
                                                                            };
                                                colliding.Add(detobj);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        if (colliding.Count > 0)
                        {
                            CollidingMessage.Colliders = colliding;
                            // always running this check because if the user deletes the object it would return a null reference.
                            if (m_parentGroup == null)
                                return;

                            if (m_parentGroup.Scene == null)
                                return;

                            m_parentGroup.Scene.EventManager.TriggerScriptColliding(this, CollidingMessage);

                            if ((this.UUID != this.ParentGroup.RootPart.UUID))
                            {
                                const int PASS_IF_NOT_HANDLED = 0;
                                const int PASS_ALWAYS = 1;
                                const int PASS_NEVER = 2;
                                if (this.PassCollisions == PASS_NEVER)
                                {
                                }
                                if (this.PassCollisions == PASS_ALWAYS)
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptColliding(this.ParentGroup.RootPart,
                                                                                            CollidingMessage);
                                }
                                else if (((this.ScriptEvents & scriptEvents.collision) == 0) &&
                                         this.PassCollisions == PASS_IF_NOT_HANDLED)
                                    //If no event in this prim, pass to parent
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptColliding(
                                        this.ParentGroup.RootPart, CollidingMessage);
                                }
                            }
                        }
                    }
                }

                if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_end) != 0)
                {
                    if (endedColliders.Count > 0)
                    {
                        ColliderArgs EndCollidingMessage = new ColliderArgs();
                        List<DetectedObject> colliding = new List<DetectedObject>();
                        foreach (uint localId in endedColliders)
                        {
                            if (localId != 0)
                            {
                                // always running this check because if the user deletes the object it would return a null reference.
                                if (m_parentGroup == null)
                                    return;
                                if (m_parentGroup.Scene == null)
                                    return;
                                ISceneChildEntity obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
                                string data = "";
                                if (obj != null)
                                {
                                    if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.Name))
                                    {
                                        bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                        //If it is 1, it is to accept ONLY collisions from this object
                                        if (found)
                                        {
                                            DetectedObject detobj = new DetectedObject
                                                                        {
                                                                            keyUUID = obj.UUID, nameStr = obj.Name, ownerUUID = obj.OwnerID, posVector = obj.AbsolutePosition, rotQuat = obj.GetWorldRotation(), velVector = obj.Velocity, colliderType = 0, groupUUID = obj.GroupID
                                                                        };
                                            colliding.Add(detobj);
                                        }
                                            //If it is 0, it is to not accept collisions from this object
                                        else
                                        {
                                        }
                                    }
                                    else
                                    {
                                        bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                        //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work
                                        if (!found)
                                        {
                                            DetectedObject detobj = new DetectedObject
                                                                        {
                                                                            keyUUID = obj.UUID, nameStr = obj.Name, ownerUUID = obj.OwnerID, posVector = obj.AbsolutePosition, rotQuat = obj.GetWorldRotation(), velVector = obj.Velocity, colliderType = 0, groupUUID = obj.GroupID
                                                                        };
                                            colliding.Add(detobj);
                                        }
                                    }
                                }
                                else
                                {
                                    IScenePresence av = ParentGroup.Scene.GetScenePresence(localId);
                                    if (av != null)
                                    {
                                        if (av.LocalId == localId)
                                        {
                                            if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) || m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name))
                                            {
                                                bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                                //If it is 1, it is to accept ONLY collisions from this avatar
                                                if (found)
                                                {
                                                    DetectedObject detobj = new DetectedObject
                                                                                {
                                                                                    keyUUID = av.UUID, nameStr = av.ControllingClient.Name, ownerUUID = av.UUID, posVector = av.AbsolutePosition, rotQuat = av.Rotation, velVector = av.Velocity, colliderType = 0, groupUUID = av.ControllingClient.ActiveGroupId
                                                                                };
                                                    colliding.Add(detobj);
                                                }
                                                    //If it is 0, it is to not accept collisions from this avatar
                                                else
                                                {
                                                }
                                            }
                                            else
                                            {
                                                bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
                                                //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
                                                if (!found)
                                                {
                                                    DetectedObject detobj = new DetectedObject
                                                                                {
                                                                                    keyUUID = av.UUID, nameStr = av.ControllingClient.Name, ownerUUID = av.UUID, posVector = av.AbsolutePosition, rotQuat = av.Rotation, velVector = av.Velocity, colliderType = 0, groupUUID = av.ControllingClient.ActiveGroupId
                                                                                };
                                                    colliding.Add(detobj);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        if (colliding.Count > 0)
                        {
                            EndCollidingMessage.Colliders = colliding;
                            // always running this check because if the user deletes the object it would return a null reference.
                            if (m_parentGroup == null)
                                return;

                            if (m_parentGroup.Scene == null)
                                return;

                            m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(this, EndCollidingMessage);

                            if ((this.UUID != this.ParentGroup.RootPart.UUID))
                            {
                                const int PASS_IF_NOT_HANDLED = 0;
                                const int PASS_ALWAYS = 1;
                                const int PASS_NEVER = 2;
                                if (this.PassCollisions == PASS_NEVER)
                                {
                                }
                                if (this.PassCollisions == PASS_ALWAYS)
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(
                                        this.ParentGroup.RootPart, EndCollidingMessage);
                                }
                                else if (((this.ScriptEvents & scriptEvents.collision_end) == 0) &&
                                         this.PassCollisions == PASS_IF_NOT_HANDLED)
                                    //If no event in this prim, pass to parent
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(
                                        this.ParentGroup.RootPart, EndCollidingMessage);
                                }
                            }
                        }
                    }
                }
                if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.land_collision_start) != 0 ||
                    (m_parentGroup.RootPart.ScriptEvents & scriptEvents.land_collision) != 0)
                {
                    if (startedColliders.Count > 0)
                    {
                        ColliderArgs LandStartCollidingMessage = new ColliderArgs();
                        List<DetectedObject> colliding = (from localId in startedColliders
                                                          where localId == 0
                                                          select new DetectedObject
                                                                     {
                                                                         keyUUID = UUID.Zero, nameStr = "", ownerUUID = UUID.Zero, posVector = m_parentGroup.RootPart.AbsolutePosition, rotQuat = Quaternion.Identity, velVector = Vector3.Zero, colliderType = 0, groupUUID = UUID.Zero
                                                                     }).ToList();

                        if (colliding.Count > 0)
                        {
                            LandStartCollidingMessage.Colliders = colliding;
                            // always running this check because if the user deletes the object it would return a null reference.
                            if (m_parentGroup == null)
                                return;

                            if (m_parentGroup.Scene == null)
                                return;

                            m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingStart(this,
                                                                                             LandStartCollidingMessage);

                            if ((this.UUID != this.ParentGroup.RootPart.UUID))
                            {
                                const int PASS_IF_NOT_HANDLED = 0;
                                const int PASS_ALWAYS = 1;
                                const int PASS_NEVER = 2;
                                if (this.PassCollisions == PASS_NEVER)
                                {
                                }
                                if (this.PassCollisions == PASS_ALWAYS)
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingStart(
                                        this.ParentGroup.RootPart, LandStartCollidingMessage);
                                }
                                else if (((this.ScriptEvents & scriptEvents.land_collision_start) == 0) &&
                                         this.PassCollisions == PASS_IF_NOT_HANDLED)
                                    //If no event in this prim, pass to parent
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingStart(
                                        this.ParentGroup.RootPart, LandStartCollidingMessage);
                                }
                            }
                        }
                    }
                }
                if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.land_collision) != 0)
                {
                    if (m_lastColliders.Count > 0)
                    {
                        ColliderArgs LandCollidingMessage = new ColliderArgs();
                        List<DetectedObject> colliding = new List<DetectedObject>();
                        foreach (uint localId in m_lastColliders)
                        {
                            if (localId == 0)
                            {
                                //Hope that all is left is ground!
                                DetectedObject detobj = new DetectedObject
                                                            {
                                                                keyUUID = UUID.Zero,
                                                                nameStr = "",
                                                                ownerUUID = UUID.Zero,
                                                                posVector = m_parentGroup.RootPart.AbsolutePosition,
                                                                rotQuat = Quaternion.Identity,
                                                                velVector = Vector3.Zero,
                                                                colliderType = 0,
                                                                groupUUID = UUID.Zero
                                                            };
                                colliding.Add(detobj);
                            }
                        }

                        if (colliding.Count > 0)
                        {
                            LandCollidingMessage.Colliders = colliding;
                            // always running this check because if the user deletes the object it would return a null reference.
                            if (m_parentGroup == null)
                                return;

                            if (m_parentGroup.Scene == null)
                                return;

                            m_parentGroup.Scene.EventManager.TriggerScriptLandColliding(this, LandCollidingMessage);

                            if ((this.UUID != this.ParentGroup.RootPart.UUID))
                            {
                                const int PASS_IF_NOT_HANDLED = 0;
                                const int PASS_ALWAYS = 1;
                                const int PASS_NEVER = 2;
                                if (this.PassCollisions == PASS_NEVER)
                                {
                                }
                                if (this.PassCollisions == PASS_ALWAYS)
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptLandColliding(this.ParentGroup.RootPart,
                                                                                            LandCollidingMessage);
                                }
                                else if (((this.ScriptEvents & scriptEvents.land_collision) == 0) &&
                                         this.PassCollisions == PASS_IF_NOT_HANDLED)
                                    //If no event in this prim, pass to parent
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptLandColliding(
                                        this.ParentGroup.RootPart, LandCollidingMessage);
                                }
                            }
                        }
                    }
                }
                if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.land_collision_end) != 0)
                {
                    if (endedColliders.Count > 0)
                    {
                        ColliderArgs LandEndCollidingMessage = new ColliderArgs();
                        List<DetectedObject> colliding = (from localId in startedColliders
                                                          where localId == 0
                                                          select new DetectedObject
                                                                     {
                                                                         keyUUID = UUID.Zero, nameStr = "", ownerUUID = UUID.Zero, posVector = m_parentGroup.RootPart.AbsolutePosition, rotQuat = Quaternion.Identity, velVector = Vector3.Zero, colliderType = 0, groupUUID = UUID.Zero
                                                                     }).ToList();

                        if (colliding.Count > 0)
                        {
                            LandEndCollidingMessage.Colliders = colliding;
                            // always running this check because if the user deletes the object it would return a null reference.
                            if (m_parentGroup == null)
                                return;

                            if (m_parentGroup.Scene == null)
                                return;

                            m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd(this, LandEndCollidingMessage);

                            if ((this.UUID != this.ParentGroup.RootPart.UUID))
                            {
                                const int PASS_IF_NOT_HANDLED = 0;
                                const int PASS_ALWAYS = 1;
                                const int PASS_NEVER = 2;
                                if (this.PassCollisions == PASS_NEVER)
                                {
                                }
                                if (this.PassCollisions == PASS_ALWAYS)
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd(
                                        this.ParentGroup.RootPart, LandEndCollidingMessage);
                                }
                                else if (((this.ScriptEvents & scriptEvents.land_collision_end) == 0) &&
                                         this.PassCollisions == PASS_IF_NOT_HANDLED)
                                    //If no event in this prim, pass to parent
                                {
                                    m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd(
                                        this.ParentGroup.RootPart, LandEndCollidingMessage);
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #3
0
        /// <summary>
        ///   This is our near callback.  A geometry is near a body
        /// </summary>
        /// <param name = "space">The space that contains the geoms.  Remember, spaces are also geoms</param>
        /// <param name = "g1">a geometry or space</param>
        /// <param name = "g2">another geometry or space</param>
        private void near(IntPtr space, IntPtr g1, IntPtr g2)
        {
            //  no lock here!  It's invoked from within Simulate(), which is thread-locked

            if (g1 == IntPtr.Zero || g2 == IntPtr.Zero || g1 == g2)
                return;

            // Test if we're colliding a geom with a space.
            // If so we have to drill down into the space recursively

            if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
            {
                // Separating static prim geometry spaces.
                // We'll be calling near recursivly if one
                // of them is a space to find all of the
                // contact points in the space
                try
                {
                    d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
                }
                catch (Exception e)
                {
                    MainConsole.Instance.WarnFormat("[PHYSICS]: SpaceCollide2 failed: {0} ", e);
                    return;
                }
                return;
            }
            IntPtr b1 = d.GeomGetBody(g1);
            IntPtr b2 = d.GeomGetBody(g2);

            int FindContactsTime = Util.EnvironmentTickCount();

            // Figure out how many contact points we have
            int count = 0;
            try
            {
                // Colliding Geom To Geom
                // This portion of the function 'was' blatantly ripped off from BoxStack.cs

                if (g1 == g2)
                    return; // Can't collide with yourself

                if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
                    return;

                count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray,
                                     d.ContactGeom.unmanagedSizeOf);
            }
            catch (Exception e)
            {
                MainConsole.Instance.WarnFormat("[PHYSICS]:  ode Collide failed: {0} ", e);

                PhysicsActor badObj;
                if (actor_name_map.TryGetValue(g1, out badObj))
                    if (badObj is AuroraODEPrim)
                        RemovePrim((AuroraODEPrim)badObj);
                    else if (badObj is AuroraODECharacter)
                        RemoveAvatar((AuroraODECharacter)badObj);
                if (actor_name_map.TryGetValue(g2, out badObj))
                    if (badObj is AuroraODEPrim)
                        RemovePrim((AuroraODEPrim)badObj);
                    else if (badObj is AuroraODECharacter)
                        RemoveAvatar((AuroraODECharacter)badObj);
                return;
            }

            if (count == 0)
                return;

            PhysicsActor p1;
            PhysicsActor p2;

            if (!actor_name_map.TryGetValue(g1, out p1))
                p1 = PANull;

            if (!actor_name_map.TryGetValue(g2, out p2))
                p2 = PANull;
            /*
                        if (p1 is AuroraODEPrim && (p1 as AuroraODEPrim)._zeroFlag)
                            (p1 as AuroraODEPrim)._zeroFlag = false;
                        if (p2 is AuroraODEPrim && (p2 as AuroraODEPrim)._zeroFlag)
                            (p2 as AuroraODEPrim)._zeroFlag = false;
            */
            m_StatFindContactsTime = Util.EnvironmentTickCountSubtract(FindContactsTime);

            if (p1.CollisionScore >= float.MaxValue - count)
                p1.CollisionScore = 0;
            p1.CollisionScore += count;

            if (p2.CollisionScore >= float.MaxValue - count)
                p2.CollisionScore = 0;
            p2.CollisionScore += count;

            int ContactLoopTime = Util.EnvironmentTickCount();

            ContactPoint maxDepthContact = new ContactPoint();
            d.ContactGeom curContact = new d.ContactGeom();

            int NotSkipedCount = 0;

            #region Contact Loop

            IntPtr joint = IntPtr.Zero;

            for (int i = 0; i < count; i++)
            {

                if (!GetCurContactGeom(i, ref curContact))
                    break;

                if (curContact.depth > maxDepthContact.PenetrationDepth)
                {
                    maxDepthContact.PenetrationDepth = curContact.depth;
                    maxDepthContact.Position.X = curContact.pos.X;
                    maxDepthContact.Position.Y = curContact.pos.Y;
                    maxDepthContact.Position.Z = curContact.pos.Z;
                    maxDepthContact.Type = (ActorTypes) p1.PhysicsActorType;
                    maxDepthContact.SurfaceNormal.X = curContact.normal.X;
                    maxDepthContact.SurfaceNormal.Y = curContact.normal.Y;
                    maxDepthContact.SurfaceNormal.Z = curContact.normal.Z;
                }

                bool p2col = true;

                // We only need to test p2 for 'jump crouch purposes'
                if (p2 is AuroraODECharacter && p1.PhysicsActorType == (int) ActorTypes.Prim)
                {
                    // Testing if the collision is at the feet of the avatar
                    if ((p2.Position.Z - maxDepthContact.Position.Z) < (p2.Size.Z*0.6f))
                        p2col = false;
                }

                p2.IsColliding = p2col;

                // Logic for collision handling
                // Note, that if *all* contacts are skipped (VolumeDetect)
                // The prim still detects (and forwards) collision events but 
                // appears to be phantom for the world
                Boolean skipThisContact = false;

                if (p1 is PhysicsObject && ((PhysicsObject) p1).VolumeDetect)
                    skipThisContact = true; // No collision on volume detect prims

                if (p2 is PhysicsObject && ((PhysicsObject) p2).VolumeDetect)
                    skipThisContact = true; // No collision on volume detect prims

                if (curContact.depth < 0f)
                    skipThisContact = true;


                if (!skipThisContact &&
                    m_filterCollisions &&
                    checkDupe(curContact, p2.PhysicsActorType))
                    skipThisContact = true;


                if (!skipThisContact)
                {
                    NotSkipedCount++;

                    // If we're colliding against terrain
                    if (p1.PhysicsActorType == (int) ActorTypes.Ground)
                    {
                        if (p2.PhysicsActorType == (int) ActorTypes.Prim)
                        {
                            if (m_filterCollisions)
                                _perloopContact.Add(curContact);

                            ((AuroraODEPrim)p2).GetContactParam(p2, ref newGlobalcontact);

                            joint = CreateContacJoint(ref curContact);
                        }
                        //Can't collide against anything else, agents do their own ground checks
                    }
                    else if ((p1.PhysicsActorType == (int) ActorTypes.Agent) &&
                             (p2.PhysicsActorType == (int) ActorTypes.Agent))
                    {
                        GetContactParam(0.0f, AvatarContactBounce, ref newGlobalcontact);

                        if (m_filterCollisions)
                            _perloopContact.Add(curContact);

                        joint = CreateContacJoint(ref curContact);
                    }

                    else if (p1.PhysicsActorType == (int) ActorTypes.Prim)
                    {
                        if (p2.PhysicsActorType == (int) ActorTypes.Agent)
                        {
                            ((AuroraODEPrim)p1).GetContactParam(p2, ref newGlobalcontact);
                            if (m_filterCollisions)
                                _perloopContact.Add(curContact);

                            joint = CreateContacJoint(ref curContact);
                        }
                        else if (p2.PhysicsActorType == (int) ActorTypes.Prim)
                        {
                            if (m_filterCollisions)
                                _perloopContact.Add(curContact);

                            //Add restitution and friction changes
                            ((AuroraODEPrim)p1).GetContactParam(p2, ref newGlobalcontact);

                            joint = CreateContacJoint(ref curContact);
                        }
                    }

                    if (m_global_contactcount < m_currentmaxContactsbeforedeath && joint != IntPtr.Zero)
                        // stack collide!
                    {
                        d.JointAttach(joint, b1, b2);
                        m_global_contactcount++;
                        joint = IntPtr.Zero;
                    }
                }
            }

            #endregion

            m_StatContactLoopTime = Util.EnvironmentTickCountSubtract(ContactLoopTime);

            int CollisionAccountingTime = Util.EnvironmentTickCount();

            if (NotSkipedCount > 0)
            {
                if (count > geomContactPointsStartthrottle)
                {
                    // If there are more then 3 contact points, it's likely
                    // that we've got a pile of objects, so ...
                    // We don't want to send out hundreds of terse updates over and over again
                    // so lets throttle them and send them again after it's somewhat sorted out.
                    p2.ThrottleUpdates = true;
                }
            }
            collision_accounting_events(p1, p2, maxDepthContact);
            m_StatCollisionAccountingTime = Util.EnvironmentTickCountSubtract(CollisionAccountingTime);
        }
예제 #4
0
 private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact)
 {
     if (!p2.SubscribedEvents() && !p1.SubscribedEvents())
         return;
     FireCollisionEvent(p1, p2, contact);
     if (p1.SubscribedEvents())
         p1.AddCollisionEvent(p2.LocalID, contact);
     if (p2.SubscribedEvents())
         p2.AddCollisionEvent(p1.LocalID, contact);
 }
예제 #5
0
 public void FireCollisionEvent(PhysicsActor actor, PhysicsActor collidedActor, ContactPoint contact)
 {
     if (OnCollisionEvent != null)
     {
         OnCollisionEvent(actor, collidedActor, contact);
     }
 }
예제 #6
0
 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
 {
 }
예제 #7
0
 public abstract void AddCollisionEvent(uint localID, ContactPoint contact);
예제 #8
0
 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
 {
     CollisionEventsThisFrame.addCollider(CollidedWith, contact);
 }
예제 #9
0
        private void AddODECollision(d.ContactGeom curContact, PhysicsActor p1, PhysicsActor p2, IntPtr b1, IntPtr b2, ContactPoint maxDepthContact, ref int NotSkipedCount)
        {
            IntPtr joint = IntPtr.Zero;

            bool p2col = true;

            // We only need to test p2 for 'jump crouch purposes'
            if (p2 is AuroraODECharacter && p1.PhysicsActorType == (int)ActorTypes.Prim)
            {
                // Testing if the collision is at the feet of the avatar
                if ((p2.Position.Z - maxDepthContact.Position.Z) < (p2.Size.Z * 0.6f))
                    p2col = false;
            }

            p2.IsTruelyColliding = true;
            p2.IsColliding = p2col;

            // Logic for collision handling
            // Note, that if *all* contacts are skipped (VolumeDetect)
            // The prim still detects (and forwards) collision events but 
            // appears to be phantom for the world

            // No collision on volume detect prims
            if ((p1 is PhysicsObject && ((PhysicsObject)p1).VolumeDetect) ||
                (p2 is PhysicsObject && ((PhysicsObject)p2).VolumeDetect))
                return;

            if (curContact.depth < 0f)
                return;//Has to be penetrating

            if (m_filterCollisions &&
                checkDupe(curContact, p2.PhysicsActorType))
                return;
            if (m_filterCollisions)
                _perloopContact.Add(curContact);

            NotSkipedCount++;

            // If we're colliding against terrain
            if (p1.PhysicsActorType == (int)ActorTypes.Ground)
            {
                if (p2.PhysicsActorType == (int)ActorTypes.Prim)
                {
                    ((AuroraODEPrim)p2).GetContactParam(p2, ref newGlobalcontact);

                    joint = CreateContacJoint(curContact);
                }
                else
                {
                    newGlobalcontact = new d.Contact();
                    newGlobalcontact.surface.mode |= d.ContactFlags.SoftERP;
                    newGlobalcontact.surface.mu = 75;
                    newGlobalcontact.surface.bounce = 0.1f;
                    newGlobalcontact.surface.soft_erp = 0.05025f;
                    //GetContactParam(0.0f, AvatarContactBounce, ref newGlobalcontact);
                    joint = CreateContacJoint(curContact);
                }
                //Can't collide against anything else, agents do their own ground checks
            }
            else if ((p1.PhysicsActorType == (int)ActorTypes.Agent) &&
                        (p2.PhysicsActorType == (int)ActorTypes.Agent))
            {
                GetContactParam(0.0f, AvatarContactBounce, ref newGlobalcontact);

                joint = CreateContacJoint(curContact);
            }
            else if (p1.PhysicsActorType == (int)ActorTypes.Prim)
            {
                //Add restitution and friction changes
                ((AuroraODEPrim)p1).GetContactParam(p2, ref newGlobalcontact);

                joint = CreateContacJoint(curContact);
            }

            if (m_global_contactcount < m_currentmaxContactsbeforedeath && joint != IntPtr.Zero)
            {
                d.JointAttach(joint, b1, b2);
                m_global_contactcount++;
                joint = IntPtr.Zero;
            }
        }
예제 #10
0
        /// <summary>
        ///   This is our near callback.  A geometry is near a body
        /// </summary>
        /// <param name = "space">The space that contains the geoms.  Remember, spaces are also geoms</param>
        /// <param name = "g1">a geometry or space</param>
        /// <param name = "g2">another geometry or space</param>
        private void near(IntPtr space, IntPtr g1, IntPtr g2)
        {
            if (g1 == IntPtr.Zero || g2 == IntPtr.Zero || g1 == g2)
                return;

            // Test if we're colliding a geom with a space.
            // If so we have to drill down into the space recursively
            if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
            {
                // Separating static prim geometry spaces.
                // We'll be calling near recursivly if one
                // of them is a space to find all of the
                // contact points in the space
                try
                {
                    d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
                }
                catch (Exception e)
                {
                    MainConsole.Instance.WarnFormat("[PHYSICS]: SpaceCollide2 failed: {0} ", e);
                    return;
                }
                return;
            }
            IntPtr b1 = d.GeomGetBody(g1);
            IntPtr b2 = d.GeomGetBody(g2);

            // Figure out how many contact points we have
            int count = 0;
            try
            {
                // Colliding Geom To Geom
                // This portion of the function 'was' blatantly ripped off from BoxStack.cs

                if (g1 == g2)
                    return; // Can't collide with yourself

                if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
                    return;

                count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray,
                                     d.ContactGeom.unmanagedSizeOf);
            }
            catch (Exception e)
            {
                MainConsole.Instance.WarnFormat("[PHYSICS]:  ode Collide failed: {0} ", e.ToString());

                PhysicsActor badObj;
                if (actor_name_map.TryGetValue(g1, out badObj))
                    if (badObj is AuroraODEPrim)
                        RemovePrim((AuroraODEPrim)badObj);
                    else if (badObj is AuroraODECharacter)
                        RemoveAvatar((AuroraODECharacter)badObj);
                if (actor_name_map.TryGetValue(g2, out badObj))
                    if (badObj is AuroraODEPrim)
                        RemovePrim((AuroraODEPrim)badObj);
                    else if (badObj is AuroraODECharacter)
                        RemoveAvatar((AuroraODECharacter)badObj);
                return;
            }

            if (count == 0)
                return;

            PhysicsActor p1;
            PhysicsActor p2;

            if (!actor_name_map.TryGetValue(g1, out p1))
                p1 = PANull;

            if (!actor_name_map.TryGetValue(g2, out p2))
                p2 = PANull;

            if (p1.CollisionScore >= float.MaxValue - count)
                p1.CollisionScore = 0;
            p1.CollisionScore += count;

            if (p2.CollisionScore >= float.MaxValue - count)
                p2.CollisionScore = 0;
            p2.CollisionScore += count;

            ContactPoint maxDepthContact = new ContactPoint();
            d.ContactGeom curContact = new d.ContactGeom();

            int NotSkipedCount = 0;

            //StatContactLoopTime = CollectTime(() =>
            #region Contact Loop
            {
                for (int i = 0; i < count; i++)
                {
                    if (!GetCurContactGeom(i, ref curContact))
                        break;

                    if (curContact.depth > maxDepthContact.PenetrationDepth)
                    {
                        maxDepthContact.PenetrationDepth = curContact.depth;
                        maxDepthContact.Position.X = curContact.pos.X;
                        maxDepthContact.Position.Y = curContact.pos.Y;
                        maxDepthContact.Position.Z = curContact.pos.Z;
                        maxDepthContact.Type = (ActorTypes)p1.PhysicsActorType;
                        maxDepthContact.SurfaceNormal.X = curContact.normal.X;
                        maxDepthContact.SurfaceNormal.Y = curContact.normal.Y;
                        maxDepthContact.SurfaceNormal.Z = curContact.normal.Z;
                    }
                }
            }
            if (p1 is AuroraODECharacter || p2 is AuroraODECharacter)
                AddODECollision(curContact, p1, p2, b1, b2, maxDepthContact, ref NotSkipedCount);
            else
            {
                for (int i = 0; i < count; i++)
                {
                    if (!GetCurContactGeom(i, ref curContact))
                        break;
                    AddODECollision(curContact, p1, p2, b1, b2, maxDepthContact, ref NotSkipedCount);

                }
            }
            #endregion//);

            //StatCollisionAccountingTime = CollectTime(() =>
            {
                if (NotSkipedCount > 0)
                {
                    if (NotSkipedCount > geomContactPointsStartthrottle)
                    {
                        // If there are more then 3 contact points, it's likely
                        // that we've got a pile of objects, so ...
                        // We don't want to send out hundreds of terse updates over and over again
                        // so lets throttle them and send them again after it's somewhat sorted out.
                        p2.ThrottleUpdates = true;
                    }
                }
                collision_accounting_events(p1, p2, maxDepthContact);
            }//);
        }
예제 #11
0
 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
 {
 }
예제 #12
0
 public abstract void AddCollisionEvent(uint localID, ContactPoint contact);
예제 #13
0
 public override void AddCollisionEvent(uint localID, ContactPoint contact)
 {
     args.addCollider(localID, contact);
 }
예제 #14
0
 public void FireCollisionEvent(PhysicsActor actor, PhysicsActor collidedActor, ContactPoint contact)
 {
     if (OnCollisionEvent != null)
         OnCollisionEvent(actor, collidedActor, contact);
 }
예제 #15
0
        /// <summary>
        ///   Called from Simulate
        ///   This is the avatar's movement control + PID Controller
        /// </summary>
        /// <param name = "timeStep"></param>
        public void Move(float timeStep, ref List<AuroraODECharacter> defects)
        {
            //  no lock; for now it's only called from within Simulate()

            // If the PID Controller isn't active then we set our force
            // calculating base velocity to the current position

            if (Body == IntPtr.Zero)
                return;

            if (!m_shouldBePhysical)
                return;

            Vector3 vec = Vector3.Zero;
            d.Vector3 vel = d.BodyGetLinearVel(Body);
            d.Vector3 tempPos;
            d.BodyCopyPosition(Body, out tempPos);

            #region Flight Ceiling

            // rex, added height check

            if (m_pidControllerActive == false)
            {
                _zeroPosition = tempPos;
            }

            if (_parent_scene.m_useFlightCeilingHeight && tempPos.Z > _parent_scene.m_flightCeilingHeight)
            {
                tempPos.Z = _parent_scene.m_flightCeilingHeight;
                d.BodySetPosition(Body, tempPos.X, tempPos.Y, tempPos.Z);
                if (vel.Z > 0.0f)
                {
                    vel.Z = 0.0f;
                    d.BodySetLinearVel(Body, vel.X, vel.Y, vel.Z);
                }
                if (_target_velocity.Z > 0.0f)
                    _target_velocity.Z = 0.0f;
            }

            // endrex

            #endregion

            #region NonFinite Pos

            Vector3 localPos = new Vector3(tempPos.X, tempPos.Y, tempPos.Z);

            if (!IsFinite(localPos))
            {
                MainConsole.Instance.Warn("[PHYSICS]: Avatar Position is non-finite!");
                defects.Add(this);
                // _parent_scene.RemoveCharacter(this);

                // destroy avatar capsule and related ODE data

                if (Amotor != IntPtr.Zero)
                {
                    // Kill the Amotor
                    d.JointDestroy(Amotor);
                    Amotor = IntPtr.Zero;
                }

                //kill the Geometry
                _parent_scene.waitForSpaceUnlock(_parent_scene.space);

                if (Body != IntPtr.Zero)
                {
                    //kill the body
                    d.BodyDestroy(Body);

                    Body = IntPtr.Zero;
                }

                if (Shell != IntPtr.Zero)
                {
                    d.GeomDestroy(Shell);
                    Shell = IntPtr.Zero;
                }
                return;
            }

            #endregion

            #region Check for out of region

            if (Position.X < 0.25f || Position.Y < 0.25f ||
                Position.X > _parent_scene.Region.RegionSizeX - .25f ||
                Position.Y > _parent_scene.Region.RegionSizeY - .25f)
            {
                if (!CheckForRegionCrossing())
                {
                    Vector3 newPos = Position;
                    newPos.X = Util.Clip(Position.X, 0.75f, _parent_scene.Region.RegionSizeX - 0.75f);
                    newPos.Y = Util.Clip(Position.Y, 0.75f, _parent_scene.Region.RegionSizeY - 0.75f);
                    Position = newPos;
                    d.BodySetPosition(Body, newPos.X, newPos.Y, newPos.Z);
                }
            }

            #endregion

            #region Movement Multiplier

            float movementmult = 1f;
            if (!m_alwaysRun)
                movementmult /= _parent_scene.avMovementDivisorWalk;
            else
                movementmult /= _parent_scene.avMovementDivisorRun;

            movementmult *= 10;
            movementmult *= SpeedModifier;
//            movementmult *= 1 / _parent_scene.TimeDilation;
            if (flying)
                movementmult *= _parent_scene.m_AvFlySpeed;

            #endregion

            #region Check for underground

            d.AABB aabb;
            d.GeomGetAABB(Shell, out aabb);
            float chrminZ = aabb.MinZ;

            Vector3 posch = localPos;

            float ftmp;

            if (flying)
            {
                ftmp = 0.75f*timeStep;
                posch.X += vel.X*ftmp;
                posch.Y += vel.Y*ftmp;
            }

            float groundHeight = _parent_scene.GetTerrainHeightAtXY(posch.X, posch.Y);

            if (chrminZ < groundHeight)
            {
                float depth = groundHeight - chrminZ;

                if (_target_velocity.Z < 0)
                    _target_velocity.Z = 0;

                if (!flying)
                {
                    if (vel.Z < -10f)
                        vel.Z = -10f;
                    vec.Z = -vel.Z*PID_D*1.5f + depth*PID_P*50.0f;
                }
                else
                {
                    vec.Z = depth*PID_P*50.0f;
                }

                if (depth < 0.12f)
                {
                    m_iscolliding = true;
                    m_colliderfilter = 2;
                    m_iscollidingGround = true;

                    ContactPoint point = new ContactPoint
                                             {
                                                 Type = ActorTypes.Ground,
                                                 PenetrationDepth = depth,
                                                 Position = {X = localPos.X, Y = localPos.Y, Z = chrminZ},
                                                 SurfaceNormal = new Vector3(0, 0, -1f)
                                             };

                    //0 is the ground localID
                    AddCollisionEvent(0, point);
                    vec.Z *= 0.5f;
                }
                else
                    m_iscollidingGround = false;
            }
            else
                m_iscollidingGround = false;
/*
            if(Flying && _target_velocity == Vector3.Zero &&
                Math.Abs(vel.Z) < 0.1)
                notMoving = true;
*/

            #endregion

            #region Movement

            #region Jump code

            if (IsJumping)
            {
//                if ((IsColliding) && m_preJumpCounter > _parent_scene.m_preJumpTime || m_preJumpCounter > 150)
                if ((IsColliding) && m_preJumpCounter > _parent_scene.m_preJumpTime || m_preJumpCounter > 150)
                {
                    m_isJumping = false;
                    m_preJumpCounter = 0;
                    _target_velocity.Z = 0;
                }
                else
                    m_preJumpCounter++;
            }

            else if (m_ispreJumping)
            {
                if (m_preJumpCounter == _parent_scene.m_preJumpTime)
                {
                    m_ispreJumping = false;
                    _target_velocity.X = m_preJumpForce.X*_parent_scene.m_preJumpForceMultiplierX;
                    _target_velocity.Y = m_preJumpForce.Y*_parent_scene.m_preJumpForceMultiplierY;
                    _target_velocity.Z = m_preJumpForce.Z*_parent_scene.m_preJumpForceMultiplierZ;

                    m_preJumpCounter = 0;
                    m_isJumping = true;
                }
                else
                {
                    m_preJumpCounter++;
                    TriggerMovementUpdate();
                    return;
                }
            }


            //This is for jumping on prims, since otherwise, you don't get off the ground sometimes
//            if (m_iscolliding && m_isJumping && _target_velocity.Z < 1 && !Flying)
//                _target_velocity.Z += m_preJumpForce.Z * _parent_scene.m_preJumpForceMultiplier;

            #endregion

            Vector3 gravForce = new Vector3();

            //  if velocity is zero, use position control; otherwise, velocity control
            if (_target_velocity == Vector3.Zero &&
                Math.Abs(vel.X) < 0.1 && Math.Abs(vel.Y) < 0.1 && Math.Abs(vel.Z) < 0.1 &&
                (this.m_iscolliding || this.flying || (this._zeroFlag && _wasZeroFlagFlying == flying)))
                //This is so that if we get moved by something else, it will update us in the client
            {
                m_isJumping = false;
                //  keep track of where we stopped.  No more slippin' & slidin'
                if (!_zeroFlag)
                {
                    _zeroFlag = true;
                    _wasZeroFlagFlying = flying;
                    _zeroPosition = tempPos;
                }

                if (m_pidControllerActive)
                {
                    // We only want to deactivate the PID Controller if we think we want to have our surrogate
                    // react to the physics scene by moving it's position.
                    // Avatar to Avatar collisions
                    // Prim to avatar collisions
                    // if target vel is zero why was it here ?
                    vec.X = -vel.X*PID_D + (_zeroPosition.X - tempPos.X)*PID_P;
                    vec.Y = -vel.Y*PID_D + (_zeroPosition.Y - tempPos.Y)*PID_P;
//                    if (!realFlying)
//                        vec.Z +=  - vel.Z * PID_D * 5;
//                    else
                    if (flying)
                        vec.Z += -vel.Z*PID_D*0.5f + (_zeroPosition.Z - tempPos.Z)*PID_P;

//                    _parent_scene.CalculateGravity(m_mass, tempPos, true, 0.15f, ref gravForce);
//                    vec += gravForce;
                }
            }
            else
            {
                m_pidControllerActive = true;
                _zeroFlag = false;

                if (m_iscolliding)
                {
                    if (!flying) //If there is a ground collision, it sets flying to false, so check against real flying
                    {
                        // We're standing or walking on something
                        if (_target_velocity.X != 0.0f)
                            vec.X += (_target_velocity.X * movementmult - vel.X) * PID_D * 2;
                        if (_target_velocity.Y != 0.0f)
                            vec.Y += (_target_velocity.Y * movementmult - vel.Y) * PID_D * 2;
                        if (_target_velocity.Z != 0.0f)
                            vec.Z += (_target_velocity.Z * movementmult - vel.Z) * PID_D;
                        /*// We're standing or walking on something
                        vec.X += (_target_velocity.X*movementmult - vel.X)*PID_D*2;
                        vec.Y += (_target_velocity.Y*movementmult - vel.Y)*PID_D*2;
                        if (_target_velocity.Z > 0.0f)
                            vec.Z += (_target_velocity.Z*movementmult - vel.Z)*PID_D;
                                // + (_zeroPosition.Z - tempPos.Z) * PID_P)) _zeropos maybe bad here*/
                    }
                    else
                    {
                        // We're flying and colliding with something
                        vec.X += (_target_velocity.X*movementmult - vel.X)*PID_D*0.5f;
                        vec.Y += (_target_velocity.Y*movementmult - vel.Y)*PID_D*0.5f;
                        //if(_target_velocity.Z > 0)
                        vec.Z += (_target_velocity.Z*movementmult - vel.Z)*PID_D*0.5f;
                    }
                }
                else
                {
                    if (flying)
                    {
                        // we're flying
                        vec.X += (_target_velocity.X * movementmult - vel.X) * PID_D * 0.75f;
                        vec.Y += (_target_velocity.Y * movementmult - vel.Y) * PID_D * 0.75f;
                    }
                    else
                    {
                        // we're not colliding and we're not flying so that means we're falling!
                        // m_iscolliding includes collisions with the ground.
                        vec.X += (_target_velocity.X - vel.X) * PID_D * 0.85f;
                        vec.Y += (_target_velocity.Y - vel.Y) * PID_D * 0.85f;
                    }
                }


                if (flying)
                {
                    #region Av gravity

                    if (_parent_scene.AllowAvGravity &&
                        tempPos.Z > _parent_scene.AvGravityHeight) //Should be stop avies from flying upwards
                    {
                        //Decay going up 
                        if (_target_velocity.Z > 0)
                        {
                            //How much should we force them down?
                            float Multiplier = (_parent_scene.AllowAvsToEscapeGravity ? .03f : .1f);
                            //How much should we force them down?
                            float fudgeHeight = (_parent_scene.AllowAvsToEscapeGravity ? 80 : 30);
                            //We add the 30 so that gravity is resonably strong once they pass the min height
                            Multiplier *= tempPos.Z + fudgeHeight - _parent_scene.AvGravityHeight;

                            //Limit these so that things don't go wrong
                            if (Multiplier < 1)
                                Multiplier = 1;

                            float maxpower = (_parent_scene.AllowAvsToEscapeGravity ? 1.5f : 3f);

                            if (Multiplier > maxpower)
                                Multiplier = maxpower;

                            _target_velocity.Z /= Multiplier;
                            vel.Z /= Multiplier;
                        }
                    }

                    #endregion

                    vec.Z = (_target_velocity.Z*movementmult - vel.Z)*PID_D*0.5f;
                    if (_parent_scene.AllowAvGravity && tempPos.Z > _parent_scene.AvGravityHeight)
                        //Add extra gravity
                        vec.Z += ((10*_parent_scene.gravityz)*Mass);
                }
            }

            if (realFlying)
            {
                #region Auto Fly Height

                //Added for auto fly height. Kitto Flora
                //Changed to only check if the avatar is flying around,

                // Revolution: If the avatar is going down, they are trying to land (probably), so don't push them up to make it harder
                //   Only if they are moving around sideways do we need to push them up
                if (_target_velocity.X != 0 || _target_velocity.Y != 0)
                {
                    Vector3 forwardVel = new Vector3(_target_velocity.X > 0 ? 2 : (_target_velocity.X < 0 ? -2 : 0),
                                                     _target_velocity.Y > 0 ? 2 : (_target_velocity.Y < 0 ? -2 : 0),
                                                     0);
                    float target_altitude = _parent_scene.GetTerrainHeightAtXY(tempPos.X, tempPos.Y) +
                                            MinimumGroundFlightOffset;

                    //We cheat a bit and do a bit lower than normal
                    if ((tempPos.Z - CAPSULE_LENGTH) < target_altitude ||
                        (tempPos.Z - CAPSULE_LENGTH) <
                        _parent_scene.GetTerrainHeightAtXY(tempPos.X + forwardVel.X, tempPos.Y + forwardVel.Y)
                        + MinimumGroundFlightOffset)
                        if (_target_velocity.Z < 0)
                            vec.Z += (target_altitude - tempPos.Z)*PID_P*0.5f; //Don't apply so much
                        else
                            vec.Z += (target_altitude - tempPos.Z)*PID_P*1.05f;
                }
                else
                {
                    //Straight up and down, only apply when they are very close to the ground
                    float target_altitude = _parent_scene.GetTerrainHeightAtXY(tempPos.X, tempPos.Y);

                    if ((tempPos.Z - CAPSULE_LENGTH + (MinimumGroundFlightOffset/1.5)) <
                        target_altitude + MinimumGroundFlightOffset)
                    {
                        if ((tempPos.Z - CAPSULE_LENGTH) < target_altitude + 1)
                        {
                            vec.Z += ((target_altitude + 4) - (tempPos.Z - CAPSULE_LENGTH))*PID_P;
                        }
                        else
                            vec.Z += ((target_altitude + MinimumGroundFlightOffset) - (tempPos.Z - CAPSULE_LENGTH))*
                                     PID_P*0.5f;
                    }
                }

                #endregion
            }

            #region Gravity

            if (!flying)
                _parent_scene.CalculateGravity(m_mass, tempPos, true, 1.0f, ref gravForce);
            else
                _parent_scene.CalculateGravity(m_mass, tempPos, false, 0.65f, ref gravForce);
                    //Allow point gravity and repulsors affect us a bit

            vec += gravForce;

            #endregion

            #region Under water physics

            if (_parent_scene.AllowUnderwaterPhysics && tempPos.X < _parent_scene.Region.RegionSizeX &&
                tempPos.Y < _parent_scene.Region.RegionSizeY)
            {
                //Position plus height to av's shoulder (aprox) is just above water
                if ((tempPos.Z + (CAPSULE_LENGTH/3) - .25f) < _parent_scene.GetWaterLevel(tempPos.X, tempPos.Y))
                {
                    if (StartingUnderWater)
                        ShouldBeWalking = Flying = false;
                    StartingUnderWater = false;
                    WasUnderWater = true;
                    Flying = true;
                    lastUnderwaterPush = 0;
                    if (ShouldBeWalking)
                    {
                        lastUnderwaterPush += (float) (_parent_scene.GetWaterLevel(tempPos.X, tempPos.Y) - tempPos.Z)*33 +
                                              3;
                        vec.Z += lastUnderwaterPush;
                    }
                    else
                    {
                        lastUnderwaterPush += 3500;
                        lastUnderwaterPush += (float) (_parent_scene.GetWaterLevel(tempPos.X, tempPos.Y) - tempPos.Z)*8;
                        vec.Z += lastUnderwaterPush;
                    }
                }
                else
                {
                    StartingUnderWater = true;
                    if (WasUnderWater)
                    {
                        WasUnderWater = false;
                        Flying = true;
                    }
                }
            }

            #endregion

            #endregion

            #region Apply the force

            if (IsFinite(vec))
            {
                if (vec.X < 100000000 && vec.Y < 10000000 && vec.Z < 10000000)
                    //Checks for crazy, going to NaN us values
                {
                    // round small values to zero. those possible are just errors
                    if (Math.Abs(vec.X) < 0.001)
                        vec.X = 0;
                    if (Math.Abs(vec.Y) < 0.001)
                        vec.Y = 0;
                    if (Math.Abs(vec.Z) < 0.001)
                        vec.Z = 0;

                    //ODE autodisables not moving prims, accept it and reenable when we need to
                    if (!d.BodyIsEnabled(Body))
                        d.BodyEnable(Body);

                    if (vec == Vector3.Zero) //if we arn't moving, STOP
                    {
                        if (m_lastForceApplied != -1)
                        {
                            m_lastForceApplied = -1;
                            d.BodySetLinearVel(Body, vec.X, vec.Y, vec.Z);
                        }
                    }
                    else
                    {
                        if (m_lastForceApplied < 5)
                            vec *= m_lastForceApplied / 5;
                        doForce(vec);
                        m_lastForceApplied++;
                    }

//                    if (!_zeroFlag && (!flying || m_iscolliding))
//                        AlignAvatarTiltWithCurrentDirectionOfMovement (vec, gravForce);

                    // the Amotor still lets avatar rotation to drift during colisions
                    // so force it back to identity

                    d.Quaternion qtmp;
                    qtmp.W = 1;
                    qtmp.X = 0;
                    qtmp.Y = 0;
                    qtmp.Z = 0;
                    d.BodySetQuaternion(Body, ref qtmp);
                    d.BodySetAngularVel(Body, 0, 0, 0);

                    //When falling, we keep going faster and faster, and eventually, the client blue screens (blue is all you see).
                    // The speed that does this is slightly higher than -30, so we cap it here so we never do that during falling.
                    if (vel.Z < -30)
                    {
                        vel.Z = -30;
                        d.BodySetLinearVel(Body, vel.X, vel.Y, vel.Z);
                    }

                    //Decay out the target velocity DON'T it forces tons of updates

                    _target_velocity *= _parent_scene.m_avDecayTime;
                    if (!_zeroFlag && _target_velocity.ApproxEquals (Vector3.Zero, _parent_scene.m_avStopDecaying))
                        _target_velocity = Vector3.Zero;

                }
                else
                {
                    //This is a safe guard from going NaN, but it isn't very smooth... which is ok
                    d.BodySetForce(Body, 0, 0, 0);
                    d.BodySetLinearVel(Body, 0, 0, 0);
                }
            }
            else
            {
                MainConsole.Instance.Warn("[PHYSICS]: Got a NaN force vector in Move()");
                MainConsole.Instance.Warn("[PHYSICS]: Avatar Position is non-finite!");
                defects.Add(this);
                //kill the Geometry
                _parent_scene.waitForSpaceUnlock(_parent_scene.space);

                if (Body != IntPtr.Zero)
                {
                    //kill the body
                    d.BodyDestroy(Body);

                    Body = IntPtr.Zero;
                }

                if (Shell != IntPtr.Zero)
                {
                    d.GeomDestroy(Shell);
                    Shell = IntPtr.Zero;
                }
            }

            #endregion
        }