From 081b2ac34ec57fe0f67f0e63c9179e3a141f0ea5 Mon Sep 17 00:00:00 2001 From: Teravus Ovares Date: Sun, 9 Mar 2008 15:43:01 +0000 Subject: * Cleaned up some locking on the ODEPlugin to make it more developer friendly * Expect the occasional deadlock? --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 137 ++-- OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 864 +++++++++++++------------- 2 files changed, 496 insertions(+), 505 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 36b3828..8a8a5fb 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -293,6 +293,8 @@ namespace OpenSim.Region.Physics.OdePlugin _parent_scene.addActivePrim(this); } + #region Mass Calculation + private float CalculateMass() { float volume = 0; @@ -598,6 +600,9 @@ namespace OpenSim.Region.Physics.OdePlugin return returnMass; } + #endregion + + public void setMass() { if (Body != (IntPtr) 0) @@ -734,11 +739,7 @@ namespace OpenSim.Region.Physics.OdePlugin private void changelink(float timestep) { - while (ode.lockquery()) - { - } - ode.dlock(_parent_scene.world); - + if (_parent == null && m_taintparent != null) { if (m_taintparent.PhysicsActorType == (int)ActorTypes.Prim) @@ -763,18 +764,14 @@ namespace OpenSim.Region.Physics.OdePlugin m_linkJoint = (IntPtr)0; } - ode.dunlock(_parent_scene.world); + _parent = m_taintparent; } private void changeSelectedStatus(float timestep) { - while (ode.lockquery()) - { - } - ode.dlock(_parent_scene.world); - + if (m_taintselected) { @@ -831,7 +828,7 @@ namespace OpenSim.Region.Physics.OdePlugin } - ode.dunlock(_parent_scene.world); + resetCollisionAccounting(); m_isSelected = m_taintselected; } @@ -860,10 +857,8 @@ namespace OpenSim.Region.Physics.OdePlugin } public void changeadd(float timestep) { - while (ode.lockquery()) - { - } - ode.dlock(_parent_scene.world); + + int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position); IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position); @@ -992,7 +987,7 @@ namespace OpenSim.Region.Physics.OdePlugin } - ode.dunlock(_parent_scene.world); + _parent_scene.geom_name_map[prim_geom] = this.m_primName; _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this; @@ -1004,10 +999,7 @@ namespace OpenSim.Region.Physics.OdePlugin } public void Move(float timestep) { - while (ode.lockquery()) - { - } - ode.dlock(_parent_scene.world); + if (m_isphysical) @@ -1057,7 +1049,7 @@ namespace OpenSim.Region.Physics.OdePlugin d.SpaceAdd(m_targetSpace, prim_geom); } } - ode.dunlock(_parent_scene.world); + changeSelectedStatus(timestep); @@ -1067,10 +1059,7 @@ namespace OpenSim.Region.Physics.OdePlugin public void rotate(float timestep) { - while (ode.lockquery()) - { - } - ode.dlock(_parent_scene.world); + d.Quaternion myrot = new d.Quaternion(); myrot.W = _orientation.w; @@ -1082,8 +1071,6 @@ namespace OpenSim.Region.Physics.OdePlugin { d.BodySetQuaternion(Body, ref myrot); } - - ode.dunlock(_parent_scene.world); resetCollisionAccounting(); m_taintrot = _orientation; @@ -1098,46 +1085,35 @@ namespace OpenSim.Region.Physics.OdePlugin public void changedisable(float timestep) { - while (ode.lockquery()) - { - } - ode.dlock(_parent_scene.world); + m_disabled = true; if (Body != (IntPtr)0) { d.BodyDisable(Body); Body = (IntPtr)0; } - ode.dunlock(_parent_scene.world); + m_taintdisable = false; } public void changePhysicsStatus(float timestep) { - lock (ode) - { - while (ode.lockquery()) - { - } - ode.dlock(_parent_scene.world); + - if (m_isphysical == true) + if (m_isphysical == true) + { + if (Body == (IntPtr)0) { - if (Body == (IntPtr)0) - { - enableBody(); - } + enableBody(); } - else + } + else + { + if (Body != (IntPtr)0) { - if (Body != (IntPtr)0) - { - disableBody(); - } + disableBody(); } - - ode.dunlock(_parent_scene.world); } changeSelectedStatus(timestep); @@ -1148,10 +1124,7 @@ namespace OpenSim.Region.Physics.OdePlugin public void changesize(float timestamp) { - while (ode.lockquery()) - { - } - ode.dlock(_parent_scene.world); + //if (!_parent_scene.geom_name_map.ContainsKey(prim_geom)) //{ // m_taintsize = _size; @@ -1311,8 +1284,6 @@ namespace OpenSim.Region.Physics.OdePlugin _parent_scene.geom_name_map[prim_geom] = oldname; - ode.dunlock(_parent_scene.world); - changeSelectedStatus(timestamp); resetCollisionAccounting(); @@ -1321,12 +1292,7 @@ namespace OpenSim.Region.Physics.OdePlugin public void changeshape(float timestamp) { - while (ode.lockquery()) - { - } - ode.dlock(_parent_scene.world); - - + string oldname = _parent_scene.geom_name_map[prim_geom]; // Cleanup of old prim geometry and Bodies @@ -1471,8 +1437,6 @@ namespace OpenSim.Region.Physics.OdePlugin _parent_scene.geom_name_map[prim_geom] = oldname; - ode.dunlock(_parent_scene.world); - changeSelectedStatus(timestamp); resetCollisionAccounting(); @@ -1483,10 +1447,7 @@ namespace OpenSim.Region.Physics.OdePlugin { if (!m_isSelected) { - while (ode.lockquery()) - { - } - ode.dlock(_parent_scene.world); + lock (m_forcelist) @@ -1505,7 +1466,6 @@ namespace OpenSim.Region.Physics.OdePlugin m_forcelist.Clear(); } - ode.dunlock(_parent_scene.world); m_collisionscore = 0; m_interpenetrationcount = 0; @@ -1517,24 +1477,17 @@ namespace OpenSim.Region.Physics.OdePlugin { if (!m_isSelected) { - lock (ode) - { - while (ode.lockquery()) - { - } - ode.dlock(_parent_scene.world); + - System.Threading.Thread.Sleep(20); - if (IsPhysical) + System.Threading.Thread.Sleep(20); + if (IsPhysical) + { + if (Body != (IntPtr)0) { - if (Body != (IntPtr)0) - { - d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z); - } + d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z); } - - ode.dunlock(_parent_scene.world); - } + } + //resetCollisionAccounting(); } m_taintVelocity = PhysicsVector.Zero; @@ -1763,12 +1716,16 @@ namespace OpenSim.Region.Physics.OdePlugin if (l_position.X > 255.95f || l_position.X < 0f || l_position.Y > 255.95f || l_position.Y < 0f) { base.RaiseOutOfBounds(_position); + + //if (m_crossingfailures < 5) + //{ + //base.RequestPhysicsterseUpdate(); + //} + //else + //{ + //base.RaiseOutOfBounds(_position); + //} } - //if (m_crossingfailures < 5) - //{ - //base.RequestPhysicsterseUpdate(); - //} - //} if (l_position.Z < 0) { diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs index 266cb3d..5b1fd78 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs @@ -229,14 +229,7 @@ namespace OpenSim.Region.Physics.OdePlugin } } - public void starttiming() - { - ms = Environment.TickCount; - } - public int stoptiming() - { - return Environment.TickCount - ms; - } + // Initialize the mesh plugin public override void Initialise(IMesher meshmerizer) { @@ -245,15 +238,9 @@ namespace OpenSim.Region.Physics.OdePlugin internal void waitForSpaceUnlock(IntPtr space) { - - while (d.SpaceLockQuery(space)) - { - - } - - - + while (d.SpaceLockQuery(space)){ } // Wait and do nothing } + /// /// Debug space message for printing the space that a prim/avatar is in. /// @@ -264,6 +251,8 @@ namespace OpenSim.Region.Physics.OdePlugin return calculateSpaceForGeom(pos).ToString(); } + #region Collision Detection + /// /// This is our near callback. A geometry is near a body /// @@ -299,314 +288,359 @@ namespace OpenSim.Region.Physics.OdePlugin //Collide all geoms in each space.. //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback); + return; } - else - { - // Colliding Geom To Geom - // This portion of the function 'was' blatantly ripped off from BoxStack.cs - if (g1 == (IntPtr)0 || g2 == (IntPtr)0) - return; + + + // Colliding Geom To Geom + // This portion of the function 'was' blatantly ripped off from BoxStack.cs + if (g1 == (IntPtr)0 || g2 == (IntPtr)0) + return; - IntPtr b1 = d.GeomGetBody(g1); - IntPtr b2 = d.GeomGetBody(g2); + IntPtr b1 = d.GeomGetBody(g1); + IntPtr b2 = d.GeomGetBody(g2); - if (g1 == g2) - return; // Can't collide with yourself + if (g1 == g2) + return; // Can't collide with yourself - if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) - return; + if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) + return; + + + + d.GeomClassID id = d.GeomGetClass(g1); + + String name1 = null; + String name2 = null; + if (!geom_name_map.TryGetValue(g1, out name1)) + { + name1 = "null"; + } + if (!geom_name_map.TryGetValue(g2, out name2)) + { + name2 = "null"; + } + + //if (id == d.GeomClassId.TriMeshClass) + //{ + // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2); + //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); + //} + + // Figure out how many contact points we have + int count = 0; + try + { + //m_log.Warn(g1.ToString() + "|" + g2.ToString()); + count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf); + } + catch (SEHException) + { + m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); + ode.drelease(world); + base.TriggerPhysicsBasedRestart(); + } + catch (System.AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to collide test an object"); + return; + } - d.GeomClassID id = d.GeomGetClass(g1); + PhysicsActor p1; + PhysicsActor p2; - String name1 = null; - String name2 = null; + for (int i = 0; i < count; i++) + { + //m_log.Warn("[CCOUNT]: " + count); + IntPtr joint; + // If we're colliding with terrain, use 'TerrainContact' instead of contact. + // allows us to have different settings - if (!geom_name_map.TryGetValue(g1, out name1)) + if (!actor_name_map.TryGetValue(g1, out p1)) { - name1 = "null"; + p1 = PANull; } - if (!geom_name_map.TryGetValue(g2, out name2)) + if (!actor_name_map.TryGetValue(g2, out p2)) { - name2 = "null"; + p2 = PANull; } - //if (id == d.GeomClassId.TriMeshClass) - //{ - // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2); - //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); - //} + // We only need to test p2 for 'jump crouch purposes' + p2.IsColliding = true; - // Figure out how many contact points we have - int count = 0; - try + switch (p1.PhysicsActorType) { - //m_log.Warn(g1.ToString() + "|" + g2.ToString()); - count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf); - } - catch (SEHException) - { - m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); - ode.drelease(world); - base.TriggerPhysicsBasedRestart(); - } - catch (System.AccessViolationException) - { - - m_log.Warn("[PHYSICS]: Unable to collide test an object"); - return; + case (int)ActorTypes.Agent: + p2.CollidingObj = true; + break; + case (int)ActorTypes.Prim: + if (p2.Velocity.X > 0 || p2.Velocity.Y > 0 || p2.Velocity.Z > 0) + p2.CollidingObj = true; + break; + case (int)ActorTypes.Unknown: + p2.CollidingGround = true; + break; + default: + p2.CollidingGround = true; + break; } - PhysicsActor p1; - PhysicsActor p2; + // we don't want prim or avatar to explode - for (int i = 0; i < count; i++) - { - //m_log.Warn("[CCOUNT]: " + count); - IntPtr joint; - // If we're colliding with terrain, use 'TerrainContact' instead of contact. - // allows us to have different settings + #region InterPenetration Handling - Unintended physics explosions - if (!actor_name_map.TryGetValue(g1, out p1)) + if (contacts[i].depth >= 0.08f) + { + //This is disabled at the moment only because it needs more tweaking + //It will eventually be uncommented + + if (contacts[i].depth >= 1.00f) { - p1 = PANull; + //m_log.Debug("[PHYSICS]: " + contacts[i].depth.ToString()); } - if (!actor_name_map.TryGetValue(g2, out p2)) + + //If you interpenetrate a prim with an agent + if ((p2.PhysicsActorType == (int) ActorTypes.Agent && + p1.PhysicsActorType == (int) ActorTypes.Prim) || + (p1.PhysicsActorType == (int) ActorTypes.Agent && + p2.PhysicsActorType == (int) ActorTypes.Prim)) { - p2 = PANull; + # region disabled code1 + //contacts[i].depth = contacts[i].depth * 4.15f; + /* + if (p2.PhysicsActorType == (int) ActorTypes.Agent) + { + p2.CollidingObj = true; + contacts[i].depth = 0.003f; + p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); + OdeCharacter character = (OdeCharacter) p2; + character.SetPidStatus(true); + contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p1.Size.X / 2), contacts[i].pos.Y + (p1.Size.Y / 2), contacts[i].pos.Z + (p1.Size.Z / 2)); + + } + else + { + + //contacts[i].depth = 0.0000000f; + } + if (p1.PhysicsActorType == (int) ActorTypes.Agent) + { + + p1.CollidingObj = true; + contacts[i].depth = 0.003f; + p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); + contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p2.Size.X / 2), contacts[i].pos.Y + (p2.Size.Y / 2), contacts[i].pos.Z + (p2.Size.Z / 2)); + OdeCharacter character = (OdeCharacter)p1; + character.SetPidStatus(true); + } + else + { + + //contacts[i].depth = 0.0000000f; + } + */ + #endregion } + - // We only need to test p2 for 'jump crouch purposes' - p2.IsColliding = true; - - switch (p1.PhysicsActorType) + // If you interpenetrate a prim with another prim + if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim) { - case (int)ActorTypes.Agent: - p2.CollidingObj = true; - break; - case (int)ActorTypes.Prim: - if (p2.Velocity.X > 0 || p2.Velocity.Y > 0 || p2.Velocity.Z > 0) - p2.CollidingObj = true; - break; - case (int)ActorTypes.Unknown: - p2.CollidingGround = true; - break; - default: - p2.CollidingGround = true; - break; - } + #region disabledcode2 + //OdePrim op1 = (OdePrim)p1; + //OdePrim op2 = (OdePrim)p2; + //op1.m_collisionscore++; + //op2.m_collisionscore++; + - // we don't want prim or avatar to explode + //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000) + //{ + //op1.m_taintdisable = true; + //AddPhysicsActorTaint(p1); + //op2.m_taintdisable = true; + //AddPhysicsActorTaint(p2); + //} + + //if (contacts[i].depth >= 0.25f) + //{ + // Don't collide, one or both prim will expld. + - #region InterPenetration Handling - Unintended physics explosions + //op1.m_interpenetrationcount++; + //op2.m_interpenetrationcount++; + //interpenetrations_before_disable = 200; + //if (op1.m_interpenetrationcount >= interpenetrations_before_disable) + //{ + //op1.m_taintdisable = true; + //AddPhysicsActorTaint(p1); + //} + //if (op2.m_interpenetrationcount >= interpenetrations_before_disable) + //{ + // op2.m_taintdisable = true; + //AddPhysicsActorTaint(p2); + //} - if (contacts[i].depth >= 0.08f) + + //contacts[i].depth = contacts[i].depth / 8f; + //contacts[i].normal = new d.Vector3(0, 0, 1); + //} + //if (op1.m_disabled || op2.m_disabled) + //{ + //Manually disabled objects stay disabled + //contacts[i].depth = 0f; + //} + #endregion + } + if (contacts[i].depth >= 1.00f) { - //This is disabled at the moment only because it needs more tweaking - //It will eventually be uncommented - - if (contacts[i].depth >= 1.00f) - { - //m_log.Debug("[PHYSICS]: " + contacts[i].depth.ToString()); - } - - //If you interpenetrate a prim with an agent + //m_log.Info("[P]: " + contacts[i].depth.ToString()); if ((p2.PhysicsActorType == (int) ActorTypes.Agent && - p1.PhysicsActorType == (int) ActorTypes.Prim) || + p1.PhysicsActorType == (int) ActorTypes.Unknown) || (p1.PhysicsActorType == (int) ActorTypes.Agent && - p2.PhysicsActorType == (int) ActorTypes.Prim)) + p2.PhysicsActorType == (int) ActorTypes.Unknown)) { - //contacts[i].depth = contacts[i].depth * 4.15f; - /* if (p2.PhysicsActorType == (int) ActorTypes.Agent) - { - p2.CollidingObj = true; - contacts[i].depth = 0.003f; - p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); + { OdeCharacter character = (OdeCharacter) p2; + + //p2.CollidingObj = true; + contacts[i].depth = 0.00000003f; + p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 0.5f); + contacts[i].pos = + new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), + contacts[i].pos.Y + (p1.Size.Y/2), + contacts[i].pos.Z + (p1.Size.Z/2)); character.SetPidStatus(true); - contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p1.Size.X / 2), contacts[i].pos.Y + (p1.Size.Y / 2), contacts[i].pos.Z + (p1.Size.Z / 2)); - } else { - - //contacts[i].depth = 0.0000000f; } if (p1.PhysicsActorType == (int) ActorTypes.Agent) { - - p1.CollidingObj = true; - contacts[i].depth = 0.003f; - p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); - contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p2.Size.X / 2), contacts[i].pos.Y + (p2.Size.Y / 2), contacts[i].pos.Z + (p2.Size.Z / 2)); OdeCharacter character = (OdeCharacter)p1; + + //p2.CollidingObj = true; + contacts[i].depth = 0.00000003f; + p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 0.5f); + contacts[i].pos = + new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), + contacts[i].pos.Y + (p1.Size.Y/2), + contacts[i].pos.Z + (p1.Size.Z/2)); character.SetPidStatus(true); } else { - //contacts[i].depth = 0.0000000f; } - */ } - + } + } - // If you interpenetrate a prim with another prim - if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim) - { - //OdePrim op1 = (OdePrim)p1; - //OdePrim op2 = (OdePrim)p2; - //op1.m_collisionscore++; - //op2.m_collisionscore++; - + #endregion - //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000) - //{ - //op1.m_taintdisable = true; - //AddPhysicsActorTaint(p1); - //op2.m_taintdisable = true; - //AddPhysicsActorTaint(p2); - //} - - //if (contacts[i].depth >= 0.25f) - //{ - // Don't collide, one or both prim will expld. - - - //op1.m_interpenetrationcount++; - //op2.m_interpenetrationcount++; - //interpenetrations_before_disable = 200; - //if (op1.m_interpenetrationcount >= interpenetrations_before_disable) - //{ - //op1.m_taintdisable = true; - //AddPhysicsActorTaint(p1); - //} - //if (op2.m_interpenetrationcount >= interpenetrations_before_disable) - //{ - // op2.m_taintdisable = true; - //AddPhysicsActorTaint(p2); - //} - - - //contacts[i].depth = contacts[i].depth / 8f; - //contacts[i].normal = new d.Vector3(0, 0, 1); - //} - //if (op1.m_disabled || op2.m_disabled) - //{ - //Manually disabled objects stay disabled - //contacts[i].depth = 0f; - //} + if (contacts[i].depth >= 0f) + { + // If we're collidng against terrain + if (name1 == "Terrain" || name2 == "Terrain") + { + // If we're moving + if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && + (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) + { + // Use the movement terrain contact + AvatarMovementTerrainContact.geom = contacts[i]; + joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); } - if (contacts[i].depth >= 1.00f) + else { - //m_log.Info("[P]: " + contacts[i].depth.ToString()); - if ((p2.PhysicsActorType == (int) ActorTypes.Agent && - p1.PhysicsActorType == (int) ActorTypes.Unknown) || - (p1.PhysicsActorType == (int) ActorTypes.Agent && - p2.PhysicsActorType == (int) ActorTypes.Unknown)) - { - if (p2.PhysicsActorType == (int) ActorTypes.Agent) - { - OdeCharacter character = (OdeCharacter) p2; - - //p2.CollidingObj = true; - contacts[i].depth = 0.00000003f; - p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 0.5f); - contacts[i].pos = - new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), - contacts[i].pos.Y + (p1.Size.Y/2), - contacts[i].pos.Z + (p1.Size.Z/2)); - character.SetPidStatus(true); - } - else - { - } - if (p1.PhysicsActorType == (int) ActorTypes.Agent) - { - OdeCharacter character = (OdeCharacter)p1; - - //p2.CollidingObj = true; - contacts[i].depth = 0.00000003f; - p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 0.5f); - contacts[i].pos = - new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), - contacts[i].pos.Y + (p1.Size.Y/2), - contacts[i].pos.Z + (p1.Size.Z/2)); - character.SetPidStatus(true); - } - else - { - //contacts[i].depth = 0.0000000f; - } - } + // Use the non moving terrain contact + TerrainContact.geom = contacts[i]; + joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); } } - - #endregion - - if (contacts[i].depth >= 0f) + else { - // If we're collidng against terrain - if (name1 == "Terrain" || name2 == "Terrain") + // we're colliding with prim or avatar + + // check if we're moving + if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && + (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) { - // If we're moving - if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && - (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) - { - // Use the movement terrain contact - AvatarMovementTerrainContact.geom = contacts[i]; - joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); - } - else - { - // Use the non moving terrain contact - TerrainContact.geom = contacts[i]; - joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); - } + // Use the Movement prim contact + AvatarMovementprimContact.geom = contacts[i]; + joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); } else { - // we're colliding with prim or avatar - - // check if we're moving - if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && - (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) - { - // Use the Movement prim contact - AvatarMovementprimContact.geom = contacts[i]; - joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); - } - else - { - // Use the non movement contact - contact.geom = contacts[i]; - joint = d.JointCreateContact(world, contactgroup, ref contact); - } + // Use the non movement contact + contact.geom = contacts[i]; + joint = d.JointCreateContact(world, contactgroup, ref contact); } - d.JointAttach(joint, b1, b2); } + d.JointAttach(joint, b1, b2); + } - if (count > 3) - { - // If there are more then 3 contact points, it's likely - // that we've got a pile of objects - // - // 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; - } - //System.Console.WriteLine(count.ToString()); - //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); + if (count > 3) + { + // If there are more then 3 contact points, it's likely + // that we've got a pile of objects + // + // 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; } + //System.Console.WriteLine(count.ToString()); + //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); } + } - private float GetTerrainHeightAtXY(float x, float y) + + public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount) { - return (float)_origheightmap[(int)y * Constants.RegionSize + (int)x]; - + /* String name1 = null; + String name2 = null; + if (!geom_name_map.TryGetValue(trimesh, out name1)) + { + name1 = "null"; + } + if (!geom_name_map.TryGetValue(refObject, out name2)) + { + name2 = "null"; + } + + m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2); + */ + return 1; + } + + public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex) + { + String name1 = null; + String name2 = null; + + if (!geom_name_map.TryGetValue(trimesh, out name1)) + { + name1 = "null"; + } + + if (!geom_name_map.TryGetValue(refObject, out name2)) + { + name2 = "null"; + } + + // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex); + + d.Vector3 v0 = new d.Vector3(); + d.Vector3 v1 = new d.Vector3(); + d.Vector3 v2 = new d.Vector3(); + + d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2); + // m_log.DebugFormat("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z); + + return 1; } /// @@ -715,6 +749,17 @@ namespace OpenSim.Region.Physics.OdePlugin } } + #endregion + + private float GetTerrainHeightAtXY(float x, float y) + { + return (float)_origheightmap[(int)y * Constants.RegionSize + (int)x]; + + + } + + #region Add/Remove Entities + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) { PhysicsVector pos = new PhysicsVector(); @@ -735,6 +780,80 @@ namespace OpenSim.Region.Physics.OdePlugin } } + private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation, + IMesh mesh, PrimitiveBaseShape pbs, bool isphysical) + { + PhysicsVector pos = new PhysicsVector(); + pos.X = position.X; + pos.Y = position.Y; + pos.Z = position.Z; + PhysicsVector siz = new PhysicsVector(); + siz.X = size.X; + siz.Y = size.Y; + siz.Z = size.Z; + Quaternion rot = new Quaternion(); + rot.w = rotation.w; + rot.x = rotation.x; + rot.y = rotation.y; + rot.z = rotation.z; + + + + OdePrim newPrim; + lock (OdeLock) + { + newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode); + + _prims.Add(newPrim); + } + + + return newPrim; + } + + public void addActivePrim(OdePrim activatePrim) + { + // adds active prim.. (ones that should be iterated over in collisions_optimized + + _activeprims.Add(activatePrim); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation) //To be removed + { + return AddPrimShape(primName, pbs, position, size, rotation, false); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, bool isPhysical) + { + PhysicsActor result; + IMesh mesh = null; + + switch (pbs.ProfileShape) + { + case ProfileShape.Square: + /// support simple box & hollow box now; later, more shapes + if (needsMeshing(pbs)) + { + mesh = mesher.CreateMesh(primName, pbs, size); + } + + break; + } + + result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical); + + + return result; + } + + + public void remActivePrim(OdePrim deactivatePrim) + { + _activeprims.Remove(deactivatePrim); + } + public override void RemovePrim(PhysicsActor prim) { if (prim is OdePrim) @@ -767,10 +886,8 @@ namespace OpenSim.Region.Physics.OdePlugin { if (prim.prim_geom != (IntPtr)0) { - while (ode.lockquery()) - { - } - ode.dlock(world); + + //System.Threading.Thread.Sleep(20); prim.ResetTaints(); @@ -846,11 +963,15 @@ namespace OpenSim.Region.Physics.OdePlugin //} } - ode.dunlock(world); + } } } + #endregion + + #region Space Separation Calculation + /// /// Takes a space pointer and zeros out the array we're using to hold the spaces /// @@ -1065,95 +1186,10 @@ namespace OpenSim.Region.Physics.OdePlugin return returnint; } + #endregion - private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation, - IMesh mesh, PrimitiveBaseShape pbs, bool isphysical) - { - PhysicsVector pos = new PhysicsVector(); - pos.X = position.X; - pos.Y = position.Y; - pos.Z = position.Z; - PhysicsVector siz = new PhysicsVector(); - siz.X = size.X; - siz.Y = size.Y; - siz.Z = size.Z; - Quaternion rot = new Quaternion(); - rot.w = rotation.w; - rot.x = rotation.x; - rot.y = rotation.y; - rot.z = rotation.z; - - - - OdePrim newPrim; - lock (OdeLock) - { - newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode); - - _prims.Add(newPrim); - } - - - return newPrim; - } - - public void addActivePrim(OdePrim activatePrim) - { - // adds active prim.. (ones that should be iterated over in collisions_optimized - - _activeprims.Add(activatePrim); - } - - public void remActivePrim(OdePrim deactivatePrim) - { - _activeprims.Remove(deactivatePrim); - } - - public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount) - { -/* String name1 = null; - String name2 = null; - - if (!geom_name_map.TryGetValue(trimesh, out name1)) - { - name1 = "null"; - } - if (!geom_name_map.TryGetValue(refObject, out name2)) - { - name2 = "null"; - } - - m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2); -*/ - return 1; - } - - public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex) - { - String name1 = null; - String name2 = null; - - if (!geom_name_map.TryGetValue(trimesh, out name1)) - { - name1 = "null"; - } - - if (!geom_name_map.TryGetValue(refObject, out name2)) - { - name2 = "null"; - } - -// m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex); - - d.Vector3 v0 = new d.Vector3(); - d.Vector3 v1 = new d.Vector3(); - d.Vector3 v2 = new d.Vector3(); - d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2); -// m_log.DebugFormat("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z); - return 1; - } /// /// Routine to figure out if we need to mesh this prim with our mesher @@ -1183,36 +1219,7 @@ namespace OpenSim.Region.Physics.OdePlugin return false; } - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation) //To be removed - { - return AddPrimShape(primName, pbs, position, size, rotation, false); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation, bool isPhysical) - { - PhysicsActor result; - IMesh mesh = null; - - switch (pbs.ProfileShape) - { - case ProfileShape.Square: - /// support simple box & hollow box now; later, more shapes - if (needsMeshing(pbs)) - { - mesh = mesher.CreateMesh(primName, pbs, size); - } - - break; - } - - result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical); - - - return result; - } - + /// /// Called after our prim properties are set Scale, position etc. /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex @@ -1224,8 +1231,11 @@ namespace OpenSim.Region.Physics.OdePlugin if (prim is OdePrim) { OdePrim taintedprim = ((OdePrim) prim); - if (!(_taintedPrim.Contains(taintedprim))) - _taintedPrim.Add(taintedprim); + lock (_taintedPrim) + { + if (!(_taintedPrim.Contains(taintedprim))) + _taintedPrim.Add(taintedprim); + } } } @@ -1292,12 +1302,50 @@ namespace OpenSim.Region.Physics.OdePlugin ode.dlock(world); try { - foreach (OdeCharacter actor in _characters) + lock (_characters) { - if (actor != null) - actor.Move(timeStep); + foreach (OdeCharacter actor in _characters) + { + if (actor != null) + actor.Move(timeStep); + } } + + bool processedtaints = false; + + lock (_taintedPrim) + { + foreach (OdePrim prim in _taintedPrim) + { + if (prim.m_taintremove) + { + RemovePrimThreadLocked(prim); + } + + prim.ProcessTaints(timeStep); + + processedtaints = true; + prim.m_collisionscore = 0; + } + + if (processedtaints) + _taintedPrim = new List(); + + } + + lock (_activeprims) + { + foreach (OdePrim prim in _activeprims) + { + prim.m_collisionscore = 0; + } + } + + + + + collision_optimized(timeStep); d.WorldQuickStep(world, ODE_STEPSIZE); @@ -1321,47 +1369,29 @@ namespace OpenSim.Region.Physics.OdePlugin } } - foreach (OdeCharacter actor in _characters) - { - if (actor != null) - actor.UpdatePositionAndVelocity(); - } - - if (!ode.lockquery()) - { - bool processedtaints = false; - foreach (OdePrim prim in _taintedPrim) - { - if (prim.m_taintremove) - { - RemovePrimThreadLocked(prim); - } - - prim.ProcessTaints(timeStep); - - processedtaints = true; - prim.m_collisionscore = 0; - } - if (processedtaints) - _taintedPrim = new List(); - } - foreach (OdePrim prim in _activeprims) + lock (_characters) { - prim.m_collisionscore = 0; + foreach (OdeCharacter actor in _characters) + { + if (actor != null) + actor.UpdatePositionAndVelocity(); + } } - - - if (timeStep < 0.2f) + lock (_activeprims) { - foreach (OdePrim actor in _activeprims) + if (timeStep < 0.2f) { - if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag)) + foreach (OdePrim actor in _activeprims) { - actor.UpdatePositionAndVelocity(); + if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag)) + { + actor.UpdatePositionAndVelocity(); + } } } } + } return fps; } @@ -1375,6 +1405,8 @@ namespace OpenSim.Region.Physics.OdePlugin // for now we won't be multithreaded get { return (false); } } + + #region ODE Specific Terrain Fixes public float[] ResizeTerrain512NearestNeighbour(float[] heightMap) { float[] returnarr = new float[262144]; @@ -1637,11 +1669,12 @@ namespace OpenSim.Region.Physics.OdePlugin return returnarr; } + #endregion + public override void SetTerrain(float[] heightMap) { // this._heightmap[i] = (double)heightMap[i]; - // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) - // also, creating a buffer zone of one extra sample all around + // dbm (danx0r) -- creating a buffer zone of one extra sample all around _origheightmap = heightMap; const uint heightmapWidth = m_regionWidth + 2; const uint heightmapHeight = m_regionHeight + 2; @@ -1654,6 +1687,7 @@ namespace OpenSim.Region.Physics.OdePlugin //Double resolution heightMap = ResizeTerrain512Interpolation(heightMap); + for (int x = 0; x < heightmapWidthSamples; x++) { for (int y = 0; y < heightmapHeightSamples; y++) -- cgit v1.1