From 5da77e047a59601cdb6f78f30af4a32a094d861d Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 13 Apr 2012 17:50:03 +0100 Subject: [PATCH 01/12] don't do Animator.UpdateMovementAnimations() in scenepresence RegionHeartbeatEnd if agent is sitting. Also restore Velocity in teleportWithMomentum() --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index b51d41be4c..c4b75bdd34 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -753,7 +753,7 @@ namespace OpenSim.Region.Framework.Scenes if (m_movementAnimationUpdateCounter >= 2) { m_movementAnimationUpdateCounter = 0; - if (Animator != null) + if (Animator != null && ParentID == 0) // don't do it sitting { Animator.UpdateMovementAnimations(); } @@ -1077,11 +1077,12 @@ namespace OpenSim.Region.Framework.Scenes public void TeleportWithMomentum(Vector3 pos) { bool isFlying = Flying; + Vector3 vel = Velocity; RemoveFromPhysicalScene(); CheckLandingPoint(ref pos); AbsolutePosition = pos; AddToPhysicalScene(isFlying); - + Velocity = vel; SendTerseUpdateToAllClients(); } From b574d43c5d5706cf6325c909ddf0ff573e44e49b Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 13 Apr 2012 20:34:56 +0100 Subject: [PATCH 02/12] Use presence absolute position to request raycast to camera. Used m_pos maybe a sitting offset. For reasons i don't understand that also seems to crash ode more when i let this rays colide with heighmaps (ubitODE with normal ode lib). --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index c4b75bdd34..855a34138d 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -753,7 +753,7 @@ namespace OpenSim.Region.Framework.Scenes if (m_movementAnimationUpdateCounter >= 2) { m_movementAnimationUpdateCounter = 0; - if (Animator != null && ParentID == 0) // don't do it sitting + if (Animator != null && ParentID == 0) // skip it if sitting { Animator.UpdateMovementAnimations(); } @@ -1386,8 +1386,16 @@ namespace OpenSim.Region.Framework.Scenes { if (m_followCamAuto) { - Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; - m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); + // Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; + // m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); + Vector3 posAdjusted = AbsolutePosition + HEAD_ADJUSTMENT; + Vector3 distTocam = CameraPosition - posAdjusted; + float distTocamlen = distTocam.Length(); + if (distTocamlen > 0) + { + distTocam *= 1.0f / distTocamlen; + m_scene.PhysicsScene.RaycastWorld(posAdjusted, distTocam, distTocamlen + 0.3f, RayCastCameraCallback); + } } } From 3999822e13d7ae2f6ab1c19a19a01e0cc7c7acd7 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 14 Apr 2012 05:07:52 +0100 Subject: [PATCH 03/12] Use chode character actor.SetMomentum() to force full restore Velocity in scenepresence TeleportWithMomentum(), since actor.Velocity was selected by original coders as the input of a desired velocity (even 'forces') that is modified by character conditions, like not changing velocity.Z if it is in free fall. --- .../Region/Framework/Scenes/ScenePresence.cs | 4 +++- .../Physics/ChOdePlugin/ODECharacter.cs | 20 ++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 855a34138d..8ac09e9aec 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1082,7 +1082,9 @@ namespace OpenSim.Region.Framework.Scenes CheckLandingPoint(ref pos); AbsolutePosition = pos; AddToPhysicalScene(isFlying); - Velocity = vel; + if (PhysicsActor != null) + PhysicsActor.SetMomentum(vel); + SendTerseUpdateToAllClients(); } diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs index 2945199faf..1f1ba951a7 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs @@ -140,6 +140,10 @@ namespace OpenSim.Region.Physics.OdePlugin public int m_eventsubscription = 0; private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate(); + private Vector3 m_taintMomentum = Vector3.Zero; + private bool m_haveTaintMomentum = false; + + // unique UUID of this character object public UUID m_uuid; public bool bad = false; @@ -800,8 +804,8 @@ namespace OpenSim.Region.Physics.OdePlugin { if (value.IsFinite()) { - m_pidControllerActive = true; _target_velocity = value; + m_pidControllerActive = true; } else { @@ -911,6 +915,12 @@ namespace OpenSim.Region.Physics.OdePlugin public override void SetMomentum(Vector3 momentum) { + if (momentum.IsFinite()) + { + m_taintMomentum = momentum; + m_haveTaintMomentum = true; + _parent_scene.AddPhysicsActorTaint(this); + } } @@ -1424,6 +1434,14 @@ namespace OpenSim.Region.Physics.OdePlugin } } + if (m_haveTaintMomentum) + { + m_haveTaintMomentum = false; + _velocity = m_taintMomentum; + _target_velocity = m_taintMomentum; + m_pidControllerActive = true; + d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z); + } } } From 86a2169d7343825c74ae271f637002377b92b438 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 16 Apr 2012 16:16:55 +0100 Subject: [PATCH 04/12] ubitODE + physmanager: - Revised use of ODE collisions categories and bits(flags) for better use as filters together with top spaces (for example physical prims are on topactivespace and not physical are on topstaticspace) - Added new world raycast with filters. This blocks calling thread with a timeout of 500ms waiting for heartbeat ode thread signal job done. - Don't let ode bodies being disabled for 2 long except for vehicles. This is necessary to detect when the object is at rest at top of other and that is removed. Assume that vehicles can be enabled by used action. --- .../Region/Physics/Manager/PhysicsActor.cs | 6 + .../Region/Physics/Manager/PhysicsScene.cs | 40 + .../Physics/UbitOdePlugin/ODECharacter.cs | 29 +- .../Region/Physics/UbitOdePlugin/ODEPrim.cs | 1157 ++++++++--------- .../UbitOdePlugin/ODERayCastRequestManager.cs | 326 +++-- .../Region/Physics/UbitOdePlugin/OdeApi.cs | 8 +- .../Region/Physics/UbitOdePlugin/OdeScene.cs | 240 +++- 7 files changed, 1030 insertions(+), 776 deletions(-) diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index be67204454..b66d7f1152 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -172,6 +172,12 @@ namespace OpenSim.Region.Physics.Manager public virtual bool Phantom { get; set; } + public virtual bool IsVolumeDtc + { + get { return false; } + set { return; } + } + public virtual byte PhysicsShapeType { get; set; } public abstract PrimitiveBaseShape Shape { set; } diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index f2c0c28dc4..d10a2aa29d 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -43,6 +43,34 @@ namespace OpenSim.Region.Physics.Manager public delegate void JointDeactivated(PhysicsJoint joint); public delegate void JointErrorMessage(PhysicsJoint joint, string message); // this refers to an "error message due to a problem", not "amount of joint constraint violation" + public enum RayFilterFlags:ushort + { + // the flags + water = 0x01, + land = 0x02, + agent = 0x04, + nonphysical = 0x08, + physical = 0x10, + phantom = 0x20, + volumedtc = 0x40, + + // ray cast colision control (may only work for meshs) + BackFaceCull = 0x4000, + ClosestHit = 0x8000, + + // some combinations + LSLPhanton = phantom | volumedtc, + PrimsNonPhantom = nonphysical | physical, + PrimsNonPhantomAgents = nonphysical | physical | agent, + + AllPrims = nonphysical | phantom | volumedtc | physical, + AllButLand = agent | nonphysical | physical | phantom | volumedtc, + + ClosestAndBackCull = ClosestHit | BackFaceCull, + + All = 0x3f + } + /// /// Contact result from a raycast. /// @@ -54,6 +82,8 @@ namespace OpenSim.Region.Physics.Manager public Vector3 Normal; } + + public abstract class PhysicsScene { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -280,6 +310,16 @@ namespace OpenSim.Region.Physics.Manager return new List(); } + public virtual object RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter) + { + return null; + } + + public virtual bool SuportsRaycastWorldFiltered() + { + return false; + } + public virtual void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod){} public virtual void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) { } public virtual List RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count) diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs index 4266fdab95..b9bb06ec58 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs @@ -115,12 +115,10 @@ namespace OpenSim.Region.Physics.OdePlugin private CollisionCategories m_collisionCategories = (CollisionCategories.Character); // Default, Collide with Other Geometries, spaces, bodies and characters. - private CollisionCategories m_collisionFlags = (CollisionCategories.Geom - | CollisionCategories.Space - | CollisionCategories.Body - | CollisionCategories.Character + private CollisionCategories m_collisionFlags = (CollisionCategories.Character + | CollisionCategories.Geom ); - // we do land collisions not ode | CollisionCategories.Land); + // we do land collisions not ode | CollisionCategories.Land); public IntPtr Body = IntPtr.Zero; private OdeScene _parent_scene; public IntPtr Shell = IntPtr.Zero; @@ -639,6 +637,8 @@ namespace OpenSim.Region.Physics.OdePlugin public override void SetMomentum(Vector3 momentum) { + if (momentum.IsFinite()) + AddChange(changes.Momentum, momentum); } @@ -663,8 +663,8 @@ namespace OpenSim.Region.Physics.OdePlugin } Shell = d.CreateCapsule(_parent_scene.ActiveSpace, CAPSULE_RADIUS, CAPSULE_LENGTH); - d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); - d.GeomSetCollideBits(Shell, (int)m_collisionFlags); + d.GeomSetCategoryBits(Shell, (uint)m_collisionCategories); + d.GeomSetCollideBits(Shell, (uint)m_collisionFlags); d.MassSetCapsule(out ShellMass, m_density, 3, CAPSULE_RADIUS, CAPSULE_LENGTH); @@ -759,7 +759,6 @@ namespace OpenSim.Region.Physics.OdePlugin _parent_scene.geom_name_map.Remove(Shell); _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); d.GeomDestroy(Shell); - _parent_scene.geom_name_map.Remove(Shell); Shell = IntPtr.Zero; } } @@ -1324,6 +1323,16 @@ namespace OpenSim.Region.Physics.OdePlugin } } + // for now momentum is actually velocity + private void changeMomentum(Vector3 newmomentum) + { + _velocity = newmomentum; + _target_velocity = newmomentum; + m_pidControllerActive = true; + if (Body != IntPtr.Zero) + d.BodySetLinearVel(Body, newmomentum.X, newmomentum.Y, newmomentum.Z); + } + private void donullchange() { } @@ -1395,6 +1404,10 @@ namespace OpenSim.Region.Physics.OdePlugin case changes.Size: changeSize((Vector3)arg); break; + + case changes.Momentum: + changeMomentum((Vector3)arg); + break; /* not in use for now case changes.Shape: changeShape((PrimitiveBaseShape)arg); diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs index f739183fcd..32c4722bab 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs @@ -108,25 +108,29 @@ namespace OpenSim.Region.Physics.OdePlugin private float m_waterHeight; private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. - private int body_autodisable_frames = 20; + private int body_autodisable_frames = 5; + private int bodydisablecontrol = 0; - private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom - | CollisionCategories.Space - | CollisionCategories.Body - | CollisionCategories.Character - ); -// private bool m_collidesLand = true; - private bool m_collidesWater; - public bool m_returnCollisions; - private bool m_softcolide; - - private bool m_NoColide; // for now only for internal use for bad meshs // Default we're a Geometry private CollisionCategories m_collisionCategories = (CollisionCategories.Geom); + // Default colide nonphysical don't try to colide with anything + private const CollisionCategories m_default_collisionFlagsNotPhysical = 0; + + private const CollisionCategories m_default_collisionFlagsPhysical = (CollisionCategories.Geom | + CollisionCategories.Character | + CollisionCategories.Land | + CollisionCategories.VolumeDtc); + +// private bool m_collidesLand = true; + private bool m_collidesWater; + public bool m_returnCollisions; + + private bool m_NoColide; // for now only for internal use for bad meshs + // Default, Collide with Other Geometries, spaces and Bodies - private CollisionCategories m_collisionFlags = m_default_collisionFlags; + private CollisionCategories m_collisionFlags = m_default_collisionFlagsNotPhysical; public bool m_disabled; @@ -179,6 +183,7 @@ namespace OpenSim.Region.Physics.OdePlugin public float primOOBradiusSQ; public d.Mass primdMass; // prim inertia information on it's own referencial float primMass; // prim own mass + float primVolume; // prim own volume; float _mass; // object mass acording to case private bool hasOOBoffsetFromMesh = false; // if true we did compute it form mesh centroid, else from aabb @@ -216,6 +221,14 @@ namespace OpenSim.Region.Physics.OdePlugin } } + public override bool IsVolumeDtc + { + set { return; } + get { return m_isVolumeDetect; } + + } + + public override bool Phantom // this is not reliable for internal use { get { return m_fakeisphantom; } @@ -327,10 +340,7 @@ namespace OpenSim.Region.Physics.OdePlugin } if (m_colliderfilter == 0) - { - m_softcolide = false; m_iscolliding = false; - } else m_iscolliding = true; } @@ -422,6 +432,10 @@ namespace OpenSim.Region.Physics.OdePlugin public override Vector3 GeometricCenter { + // this is not real geometric center but a average of positions relative to root prim acording to + // http://wiki.secondlife.com/wiki/llGetGeometricCenter + // ignoring tortured prims details since sl also seems to ignore + // so no real use in doing it on physics get { return Vector3.Zero; @@ -949,7 +963,6 @@ namespace OpenSim.Region.Physics.OdePlugin m_iscolliding = false; m_colliderfilter = 0; - m_softcolide = true; m_NoColide = false; hasOOBoffsetFromMesh = false; @@ -992,6 +1005,132 @@ namespace OpenSim.Region.Physics.OdePlugin m_collisionscore = 0; } + private void UpdateCollisionCatFlags() + { + if(m_isphysical && m_disabled) + { + m_collisionCategories = 0; + m_collisionFlags = 0; + } + + else if (m_isSelected) + { + m_collisionCategories = CollisionCategories.Selected; + m_collisionFlags = 0; + } + + else if (m_isVolumeDetect) + { + m_collisionCategories = CollisionCategories.VolumeDtc; + if (m_isphysical) + m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character; + else + m_collisionFlags = 0; + } + else if (m_isphantom) + { + m_collisionCategories = CollisionCategories.Phantom; + if (m_isphysical) + m_collisionFlags = CollisionCategories.Land; + else + m_collisionFlags = 0; + } + else + { + m_collisionCategories = CollisionCategories.Geom; + if (m_isphysical) + m_collisionFlags = m_default_collisionFlagsPhysical; + else + m_collisionFlags = m_default_collisionFlagsNotPhysical; + } + } + + private void ApplyCollisionCatFlags() + { + if (prim_geom != IntPtr.Zero) + { + if (!childPrim && childrenPrim.Count > 0) + { + foreach (OdePrim prm in childrenPrim) + { + if (m_isphysical && m_disabled) + { + prm.m_collisionCategories = 0; + prm.m_collisionFlags = 0; + } + else + { + // preserve some + if (prm.m_isSelected) + { + prm.m_collisionCategories = CollisionCategories.Selected; + prm.m_collisionFlags = 0; + } + else if (prm.IsVolumeDtc) + { + prm.m_collisionCategories = CollisionCategories.VolumeDtc; + if (m_isphysical) + prm.m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character; + else + prm.m_collisionFlags = 0; + } + else if (prm.m_isphantom) + { + prm.m_collisionCategories = CollisionCategories.Phantom; + if (m_isphysical) + prm.m_collisionFlags = CollisionCategories.Land; + else + prm.m_collisionFlags = 0; + } + else + { + prm.m_collisionCategories = m_collisionCategories; + prm.m_collisionFlags = m_collisionFlags; + } + } + + if (prm.prim_geom != IntPtr.Zero) + { + if (prm.m_NoColide) + { + d.GeomSetCategoryBits(prm.prim_geom, 0); + if (m_isphysical) + d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); + else + d.GeomSetCollideBits(prm.prim_geom, 0); + } + else + { + d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories); + d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags); + } + } + } + } + + if (m_NoColide) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land); + if (collide_geom != prim_geom && collide_geom != IntPtr.Zero) + { + d.GeomSetCategoryBits(collide_geom, 0); + d.GeomSetCollideBits(collide_geom, (uint)CollisionCategories.Land); + } + } + else + { + d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags); + if (collide_geom != prim_geom && collide_geom != IntPtr.Zero) + { + d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories); + d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags); + } + } + } + } + private void createAMotor(Vector3 axis) { if (Body == IntPtr.Zero) @@ -1188,7 +1327,7 @@ namespace OpenSim.Region.Physics.OdePlugin d.GeomSetCategoryBits(prim_geom, 0); if (m_isphysical) { - d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); + d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land); } else { @@ -1198,8 +1337,8 @@ namespace OpenSim.Region.Physics.OdePlugin } else { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags); } CalcPrimBodyData(); @@ -1296,6 +1435,7 @@ namespace OpenSim.Region.Physics.OdePlugin } prim_geom = IntPtr.Zero; + collide_geom = IntPtr.Zero; } else { @@ -1319,66 +1459,23 @@ namespace OpenSim.Region.Physics.OdePlugin { IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace); prim.m_targetSpace = targetSpace; - d.GeomEnable(prim_geom); + collide_geom = IntPtr.Zero; } public void enableBodySoft() { + m_disabled = false; if (!childPrim && !m_isSelected) { if (m_isphysical && Body != IntPtr.Zero) { - if (m_isphantom && !m_isVolumeDetect) - { - m_collisionCategories = 0; - m_collisionFlags = CollisionCategories.Land; - } - else - { - m_collisionCategories |= CollisionCategories.Body; - m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); - } + UpdateCollisionCatFlags(); + ApplyCollisionCatFlags(); - foreach (OdePrim prm in childrenPrim) - { - prm.m_collisionCategories = m_collisionCategories; - prm.m_collisionFlags = m_collisionFlags; - - if (prm.prim_geom != IntPtr.Zero) - { - if (prm.m_NoColide) - { - d.GeomSetCategoryBits(prm.prim_geom, 0); - d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); - } - else - { - d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); - } - d.GeomEnable(prm.prim_geom); - } - } - - if (prim_geom != IntPtr.Zero) - { - if (m_NoColide) - { - d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); - } - else - { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } - d.GeomEnable(prim_geom); - } d.BodyEnable(Body); } } - m_disabled = false; - resetCollisionAccounting(); // this sets m_disable to false + resetCollisionAccounting(); } private void disableBodySoft() @@ -1388,45 +1485,12 @@ namespace OpenSim.Region.Physics.OdePlugin { if (m_isphysical && Body != IntPtr.Zero) { - m_collisionCategories &= ~CollisionCategories.Body; - m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); - - foreach (OdePrim prm in childrenPrim) - { - prm.m_collisionCategories = m_collisionCategories; - prm.m_collisionFlags = m_collisionFlags; - - if (prm.prim_geom != IntPtr.Zero) - { - if (prm.m_NoColide) - { - d.GeomSetCategoryBits(prm.prim_geom, 0); - d.GeomSetCollideBits(prm.prim_geom, 0); - } - else - { - d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); - } - d.GeomDisable(prm.prim_geom); - } - } - - if (prim_geom != IntPtr.Zero) - { - if (m_NoColide) - { - d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, 0); - } - else - { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } - d.GeomDisable(prim_geom); - } - + if (m_isSelected) + m_collisionFlags = CollisionCategories.Selected; + else + m_collisionCategories = 0; + m_collisionFlags = 0; + ApplyCollisionCatFlags(); d.BodyDisable(Body); } } @@ -1566,7 +1630,6 @@ namespace OpenSim.Region.Physics.OdePlugin // d.BodySetAngularDampingThreshold(Body, 0.001f); d.BodySetDamping(Body, .002f, .002f); - if (m_targetSpace != IntPtr.Zero) { _parent_scene.waitForSpaceUnlock(m_targetSpace); @@ -1588,6 +1651,13 @@ namespace OpenSim.Region.Physics.OdePlugin d.SpaceSetSublevel(m_targetSpace, 3); d.SpaceSetCleanup(m_targetSpace, false); d.SpaceAdd(m_targetSpace, prim_geom); + + d.GeomSetCategoryBits(m_targetSpace, (uint)(CollisionCategories.Space | + CollisionCategories.Geom | + CollisionCategories.Phantom | + CollisionCategories.VolumeDtc + )); + d.GeomSetCollideBits(m_targetSpace, 0); collide_geom = m_targetSpace; } @@ -1619,38 +1689,6 @@ namespace OpenSim.Region.Physics.OdePlugin d.SpaceAdd(m_targetSpace, prm.prim_geom); } - if (m_isSelected || m_disabled) - { - prm.m_collisionCategories &= ~CollisionCategories.Body; - prm.m_collisionFlags &= ~(CollisionCategories.Land | CollisionCategories.Wind); - d.GeomDisable(prm.prim_geom); - } - else - { - if (m_isphantom && !m_isVolumeDetect) - { - prm.m_collisionCategories = 0; - prm.m_collisionFlags = CollisionCategories.Land; - } - else - { - prm.m_collisionCategories |= CollisionCategories.Body; - prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); - } - d.GeomEnable(prm.prim_geom); - } - - if (prm.m_NoColide) - { - d.GeomSetCategoryBits(prm.prim_geom, 0); - d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); - d.GeomEnable(prm.prim_geom); - } - else - { - d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); - d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); - } prm.m_collisionscore = 0; if(!m_disabled) @@ -1666,45 +1704,21 @@ namespace OpenSim.Region.Physics.OdePlugin createAMotor(m_angularlock); } + m_collisionscore = 0; + + UpdateCollisionCatFlags(); + ApplyCollisionCatFlags(); + if (m_isSelected || m_disabled) { - m_collisionCategories &= ~CollisionCategories.Body; - m_collisionFlags &= ~(CollisionCategories.Land | CollisionCategories.Wind); - - d.GeomDisable(prim_geom); d.BodyDisable(Body); } else { - if (m_isphantom && !m_isVolumeDetect) - { - m_collisionCategories = 0; - m_collisionFlags = CollisionCategories.Land; - } - else - { - m_collisionCategories |= CollisionCategories.Body; - m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); - } - d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z); d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z); } - if (m_NoColide) - { - d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); - } - else - { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } - - m_collisionscore = 0; - - m_softcolide = true; _parent_scene.addActivePrim(this); _parent_scene.addActiveGroups(this); } @@ -1714,8 +1728,22 @@ namespace OpenSim.Region.Physics.OdePlugin if (Body != IntPtr.Zero) { _parent_scene.remActivePrim(this); - m_collisionCategories &= ~CollisionCategories.Body; - m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); + + collide_geom = IntPtr.Zero; + + if (m_disabled) + m_collisionCategories = 0; + else if (m_isSelected) + m_collisionCategories = CollisionCategories.Selected; + else if (m_isVolumeDetect) + m_collisionCategories = CollisionCategories.VolumeDtc; + else if (m_isphantom) + m_collisionCategories = CollisionCategories.Phantom; + else + m_collisionCategories = CollisionCategories.Geom; + + m_collisionFlags = 0; + if (prim_geom != IntPtr.Zero) { if (m_NoColide) @@ -1725,8 +1753,8 @@ namespace OpenSim.Region.Physics.OdePlugin } else { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags); } UpdateDataFromGeom(); d.GeomSetBody(prim_geom, IntPtr.Zero); @@ -1740,8 +1768,18 @@ namespace OpenSim.Region.Physics.OdePlugin foreach (OdePrim prm in childrenPrim) { _parent_scene.remActivePrim(prm); - prm.m_collisionCategories = m_collisionCategories; - prm.m_collisionFlags = m_collisionFlags; + + if (prm.m_isSelected) + prm.m_collisionCategories = CollisionCategories.Selected; + else if (prm.m_isVolumeDetect) + prm.m_collisionCategories = CollisionCategories.VolumeDtc; + else if (prm.m_isphantom) + prm.m_collisionCategories = CollisionCategories.Phantom; + else + prm.m_collisionCategories = CollisionCategories.Geom; + + prm.m_collisionFlags = 0; + if (prm.prim_geom != IntPtr.Zero) { if (prm.m_NoColide) @@ -1751,8 +1789,8 @@ namespace OpenSim.Region.Physics.OdePlugin } else { - d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); + d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories); + d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags); } prm.UpdateDataFromGeom(); SetInStaticSpace(prm); @@ -2292,6 +2330,7 @@ namespace OpenSim.Region.Physics.OdePlugin // keep using basic shape mass for now volume = CalculatePrimVolume(); + primVolume = volume; primMass = m_density * volume; if (primMass <= 0) @@ -2515,12 +2554,13 @@ namespace OpenSim.Region.Physics.OdePlugin d.GeomSetQuaternion(prim_geom, ref myrot); if (!m_isphysical) + { SetInStaticSpace(this); - } - - if (m_isphysical && Body == IntPtr.Zero) - { - MakeBody(); + UpdateCollisionCatFlags(); + ApplyCollisionCatFlags(); + } + else + MakeBody(); } } @@ -2602,86 +2642,12 @@ namespace OpenSim.Region.Physics.OdePlugin } } - private void changePhantomStatus(bool newval) { m_isphantom = newval; - if (m_isSelected) - { - m_collisionCategories = CollisionCategories.Selected; - m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space); - } - else - { - if (m_isphantom && !m_isVolumeDetect) - { - m_collisionCategories = 0; - if (m_isphysical) - m_collisionFlags = CollisionCategories.Land; - else - m_collisionFlags = 0; // should never happen - } - - else - { - m_collisionCategories = CollisionCategories.Geom; - if (m_isphysical) - m_collisionCategories |= CollisionCategories.Body; - - m_collisionFlags = m_default_collisionFlags | CollisionCategories.Land; - - if (m_collidesWater) - m_collisionFlags |= CollisionCategories.Water; - } - } - - if (!childPrim) - { - foreach (OdePrim prm in childrenPrim) - { - prm.m_collisionCategories = m_collisionCategories; - prm.m_collisionFlags = m_collisionFlags; - - if (!prm.m_disabled && prm.prim_geom != IntPtr.Zero) - { - if (prm.m_NoColide) - { - d.GeomSetCategoryBits(prm.prim_geom, 0); - if (m_isphysical) - d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); - else - d.GeomSetCollideBits(prm.prim_geom, 0); - } - else - { - d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); - } - if(!m_isSelected) - d.GeomEnable(prm.prim_geom); - } - } - } - - if (!m_disabled && prim_geom != IntPtr.Zero) - { - if (m_NoColide) - { - d.GeomSetCategoryBits(prim_geom, 0); - if (m_isphysical) - d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); - else - d.GeomSetCollideBits(prim_geom, 0); - } - else - { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } - if(!m_isSelected) - d.GeomEnable(prim_geom); - } + UpdateCollisionCatFlags(); + ApplyCollisionCatFlags(); } private void changeSelectedStatus(bool newval) @@ -2714,7 +2680,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_delaySelect || m_isphysical) { m_collisionCategories = CollisionCategories.Selected; - m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space); + m_collisionFlags = 0; if (!childPrim) { @@ -2733,10 +2699,9 @@ namespace OpenSim.Region.Physics.OdePlugin } else { - d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); + d.GeomSetCategoryBits(prm.prim_geom, (uint)m_collisionCategories); + d.GeomSetCollideBits(prm.prim_geom, (uint)m_collisionFlags); } - d.GeomDisable(prm.prim_geom); } prm.m_delaySelect = false; } @@ -2748,13 +2713,23 @@ namespace OpenSim.Region.Physics.OdePlugin { d.GeomSetCategoryBits(prim_geom, 0); d.GeomSetCollideBits(prim_geom, 0); + if (collide_geom != prim_geom && collide_geom != IntPtr.Zero) + { + d.GeomSetCategoryBits(collide_geom, 0); + d.GeomSetCollideBits(collide_geom, 0); + } + } else { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags); + if (collide_geom != prim_geom && collide_geom != IntPtr.Zero) + { + d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories); + d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags); + } } - d.GeomDisable(prim_geom); } m_delaySelect = false; @@ -2769,75 +2744,10 @@ namespace OpenSim.Region.Physics.OdePlugin if (!childPrim && Body != IntPtr.Zero && !m_disabled) d.BodyEnable(Body); - if (m_isphantom && !m_isVolumeDetect) - { - m_collisionCategories = 0; - if(m_isphysical) - m_collisionFlags = CollisionCategories.Land; - else - m_collisionFlags = 0; - } - else - { - m_collisionCategories = CollisionCategories.Geom; - if (m_isphysical) - m_collisionCategories |= CollisionCategories.Body; - - m_collisionFlags = m_default_collisionFlags | CollisionCategories.Land; - - if (m_collidesWater) - m_collisionFlags |= CollisionCategories.Water; - } - - if (!childPrim) - { - foreach (OdePrim prm in childrenPrim) - { - prm.m_collisionCategories = m_collisionCategories; - prm.m_collisionFlags = m_collisionFlags; - - if (!prm.m_disabled && prm.prim_geom != IntPtr.Zero) - { - if (prm.m_NoColide) - { - d.GeomSetCategoryBits(prm.prim_geom, 0); - if (m_isphysical) - d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); - else - d.GeomSetCollideBits(prm.prim_geom, 0); - } - else - { - d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); - } - d.GeomEnable(prm.prim_geom); - } - prm.m_delaySelect = false; - prm.m_softcolide = true; - } - } - - if (!m_disabled && prim_geom != IntPtr.Zero) - { - if (m_NoColide) - { - d.GeomSetCategoryBits(prim_geom, 0); - if (m_isphysical) - d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); - else - d.GeomSetCollideBits(prim_geom, 0); - } - else - { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } - d.GeomEnable(prim_geom); - } + UpdateCollisionCatFlags(); + ApplyCollisionCatFlags(); m_delaySelect = false; - m_softcolide = true; } resetCollisionAccounting(); @@ -2890,7 +2800,6 @@ namespace OpenSim.Region.Physics.OdePlugin if (givefakepos < 0) givefakepos = 0; // changeSelectedStatus(); - m_softcolide = true; resetCollisionAccounting(); } @@ -2951,7 +2860,6 @@ namespace OpenSim.Region.Physics.OdePlugin givefakeori--; if (givefakeori < 0) givefakeori = 0; - m_softcolide = true; resetCollisionAccounting(); } @@ -3022,7 +2930,6 @@ namespace OpenSim.Region.Physics.OdePlugin if (givefakeori < 0) givefakeori = 0; - m_softcolide = true; resetCollisionAccounting(); } @@ -3111,17 +3018,25 @@ namespace OpenSim.Region.Physics.OdePlugin d.GeomSetQuaternion(prim_geom, ref myrot); } - if (chp) + if (m_isphysical) { - if (parent != null) + if (chp) { - parent.MakeBody(); + if (parent != null) + { + parent.MakeBody(); + } } + else + MakeBody(); + } + + else + { + UpdateCollisionCatFlags(); + ApplyCollisionCatFlags(); } - else - MakeBody(); - m_softcolide = true; resetCollisionAccounting(); } @@ -3142,18 +3057,8 @@ namespace OpenSim.Region.Physics.OdePlugin { m_collidesWater = newval; - if (prim_geom != IntPtr.Zero && !m_isphantom) - { - if (m_collidesWater) - { - m_collisionFlags |= CollisionCategories.Water; - } - else - { - m_collisionFlags &= ~CollisionCategories.Water; - } - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } + UpdateCollisionCatFlags(); + ApplyCollisionCatFlags(); } private void changeSetTorque(Vector3 newtorque) @@ -3240,6 +3145,8 @@ namespace OpenSim.Region.Physics.OdePlugin private void changeVolumedetetion(bool newVolDtc) { m_isVolumeDetect = newVolDtc; + UpdateCollisionCatFlags(); + ApplyCollisionCatFlags(); } protected void changeBuilding(bool newbuilding) @@ -3320,288 +3227,306 @@ namespace OpenSim.Region.Physics.OdePlugin public void Move() { if (!childPrim && m_isphysical && Body != IntPtr.Zero && - !m_disabled && !m_isSelected && d.BodyIsEnabled(Body) && !m_building && !m_outbounds) + !m_disabled && !m_isSelected && !m_building && !m_outbounds) // !m_disabled && !m_isSelected && !m_building && !m_outbounds) { -// if (!d.BodyIsEnabled(Body)) d.BodyEnable(Body); // KF add 161009 + // if (!d.BodyIsEnabled(Body)) d.BodyEnable(Body); // KF add 161009 - float timestep = _parent_scene.ODE_STEPSIZE; - - // check outside region - d.Vector3 lpos; - d.GeomCopyPosition(prim_geom, out lpos); // root position that is seem by rest of simulator - - if (lpos.Z < -100 || lpos.Z > 100000f) + if (d.BodyIsEnabled(Body)) { - m_outbounds = true; + float timestep = _parent_scene.ODE_STEPSIZE; - lpos.Z = Util.Clip(lpos.Z, -100f, 100000f); - _acceleration.X = 0; - _acceleration.Y = 0; - _acceleration.Z = 0; + // check outside region + d.Vector3 lpos; + d.GeomCopyPosition(prim_geom, out lpos); // root position that is seem by rest of simulator - _velocity.X = 0; - _velocity.Y = 0; - _velocity.Z = 0; - m_rotationalVelocity.X = 0; - m_rotationalVelocity.Y = 0; - m_rotationalVelocity.Z = 0; - - d.BodySetLinearVel(Body, 0, 0, 0); // stop it - d.BodySetAngularVel(Body, 0, 0, 0); // stop it - d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere - m_lastposition = _position; - m_lastorientation = _orientation; - - base.RequestPhysicsterseUpdate(); - - m_throttleUpdates = false; - throttleCounter = 0; - _zeroFlag = true; - - disableBodySoft(); // disable it and colisions - base.RaiseOutOfBounds(_position); - return; - } - - if (lpos.X < 0f) - { - _position.X = Util.Clip(lpos.X, -2f, -0.1f); - m_outbounds = true; - } - else if(lpos.X > _parent_scene.WorldExtents.X) - { - _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f); - m_outbounds = true; - } - if (lpos.Y < 0f) - { - _position.Y = Util.Clip(lpos.Y, -2f, -0.1f); - m_outbounds = true; - } - else if(lpos.Y > _parent_scene.WorldExtents.Y) - { - _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f); - m_outbounds = true; - } - - if(m_outbounds) - { - m_lastposition = _position; - m_lastorientation = _orientation; - - d.Vector3 dtmp = d.BodyGetAngularVel(Body); - m_rotationalVelocity.X = dtmp.X; - m_rotationalVelocity.Y = dtmp.Y; - m_rotationalVelocity.Z = dtmp.Z; - - dtmp = d.BodyGetLinearVel(Body); - _velocity.X = dtmp.X; - _velocity.Y = dtmp.Y; - _velocity.Z = dtmp.Z; - - d.BodySetLinearVel(Body, 0, 0, 0); // stop it - d.BodySetAngularVel(Body, 0, 0, 0); - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - disableBodySoft(); // stop collisions - base.RequestPhysicsterseUpdate(); - return; - } - - - float fx = 0; - float fy = 0; - float fz = 0; - - if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) - { - // 'VEHICLES' are dealt with in ODEDynamics.cs - m_vehicle.Step(); - } - else - { - float m_mass = _mass; - - // fz = 0f; - //m_log.Info(m_collisionFlags.ToString()); - if (m_usePID) + if (lpos.Z < -100 || lpos.Z > 100000f) { + m_outbounds = true; - // If the PID Controller isn't active then we set our force - // calculating base velocity to the current position + lpos.Z = Util.Clip(lpos.Z, -100f, 100000f); + _acceleration.X = 0; + _acceleration.Y = 0; + _acceleration.Z = 0; - if ((m_PIDTau < 1) && (m_PIDTau != 0)) - { - //PID_G = PID_G / m_PIDTau; - m_PIDTau = 1; - } + _velocity.X = 0; + _velocity.Y = 0; + _velocity.Z = 0; + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; - if ((PID_G - m_PIDTau) <= 0) - { - PID_G = m_PIDTau + 1; - } + d.BodySetLinearVel(Body, 0, 0, 0); // stop it + d.BodySetAngularVel(Body, 0, 0, 0); // stop it + d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere + m_lastposition = _position; + m_lastorientation = _orientation; - d.Vector3 vel = d.BodyGetLinearVel(Body); - d.Vector3 pos = d.BodyGetPosition(Body); - _target_velocity = - new Vector3( - (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep), - (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep), - (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep) - ); + base.RequestPhysicsterseUpdate(); - // if velocity is zero, use position control; otherwise, velocity control + m_throttleUpdates = false; + throttleCounter = 0; + _zeroFlag = true; - if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) - { - // keep track of where we stopped. No more slippin' & slidin' - - // 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 - - //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); - //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2); - //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; - d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); - d.BodySetLinearVel(Body, 0, 0, 0); - d.BodyAddForce(Body, 0, 0, fz); - return; - } - else - { - _zeroFlag = false; - - // We're flying and colliding with something - fx = ((_target_velocity.X) - vel.X) * (PID_D); - fy = ((_target_velocity.Y) - vel.Y) * (PID_D); - - // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P; - - fz = ((_target_velocity.Z - vel.Z) * (PID_D)); - } - } // end if (m_usePID) - - // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller - else if (m_useHoverPID) - { - //Console.WriteLine("Hover " + Name); - - // If we're using the PID controller, then we have no gravity - - // 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 ((m_PIDTau < 1)) - { - PID_G = PID_G / m_PIDTau; - } - - if ((PID_G - m_PIDTau) <= 0) - { - PID_G = m_PIDTau + 1; - } - - // Where are we, and where are we headed? - d.Vector3 pos = d.BodyGetPosition(Body); - d.Vector3 vel = d.BodyGetLinearVel(Body); - - // Non-Vehicles have a limited set of Hover options. - // determine what our target height really is based on HoverType - switch (m_PIDHoverType) - { - case PIDHoverType.Ground: - m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); - m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; - break; - case PIDHoverType.GroundAndWater: - m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); - m_waterHeight = _parent_scene.GetWaterLevel(); - if (m_groundHeight > m_waterHeight) - { - m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; - } - else - { - m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight; - } - break; - - } // end switch (m_PIDHoverType) - - - _target_velocity = - new Vector3(0.0f, 0.0f, - (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep) - ); - - // if velocity is zero, use position control; otherwise, velocity control - - if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) - { - // keep track of where we stopped. No more slippin' & slidin' - - // 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 - - d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); - d.BodySetLinearVel(Body, vel.X, vel.Y, 0); - // ? d.BodyAddForce(Body, 0, 0, fz); - return; - } - else - { - _zeroFlag = false; - - // We're flying and colliding with something - fz = ((_target_velocity.Z - vel.Z) * (PID_D)); - } + disableBodySoft(); // disable it and colisions + base.RaiseOutOfBounds(_position); + return; } + + if (lpos.X < 0f) + { + _position.X = Util.Clip(lpos.X, -2f, -0.1f); + m_outbounds = true; + } + else if (lpos.X > _parent_scene.WorldExtents.X) + { + _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f); + m_outbounds = true; + } + if (lpos.Y < 0f) + { + _position.Y = Util.Clip(lpos.Y, -2f, -0.1f); + m_outbounds = true; + } + else if (lpos.Y > _parent_scene.WorldExtents.Y) + { + _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f); + m_outbounds = true; + } + + if (m_outbounds) + { + m_lastposition = _position; + m_lastorientation = _orientation; + + d.Vector3 dtmp = d.BodyGetAngularVel(Body); + m_rotationalVelocity.X = dtmp.X; + m_rotationalVelocity.Y = dtmp.Y; + m_rotationalVelocity.Z = dtmp.Z; + + dtmp = d.BodyGetLinearVel(Body); + _velocity.X = dtmp.X; + _velocity.Y = dtmp.Y; + _velocity.Z = dtmp.Z; + + d.BodySetLinearVel(Body, 0, 0, 0); // stop it + d.BodySetAngularVel(Body, 0, 0, 0); + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + disableBodySoft(); // stop collisions + base.RequestPhysicsterseUpdate(); + return; + } + + if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) + { + // 'VEHICLES' are dealt with in ODEDynamics.cs + m_vehicle.Step(); + return; + } + else { - float b = (1.0f - m_buoyancy); - fx = _parent_scene.gravityx * b; - fy = _parent_scene.gravityy * b; - fz = _parent_scene.gravityz * b; + + float fx = 0; + float fy = 0; + float fz = 0; + + float m_mass = _mass; + + // fz = 0f; + //m_log.Info(m_collisionFlags.ToString()); + if (m_usePID) + { + + // If the PID Controller isn't active then we set our force + // calculating base velocity to the current position + + if ((m_PIDTau < 1) && (m_PIDTau != 0)) + { + //PID_G = PID_G / m_PIDTau; + m_PIDTau = 1; + } + + if ((PID_G - m_PIDTau) <= 0) + { + PID_G = m_PIDTau + 1; + } + + d.Vector3 vel = d.BodyGetLinearVel(Body); + d.Vector3 pos = d.BodyGetPosition(Body); + _target_velocity = + new Vector3( + (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep), + (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep), + (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep) + ); + + // if velocity is zero, use position control; otherwise, velocity control + + if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) + { + // keep track of where we stopped. No more slippin' & slidin' + + // 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 + + //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); + //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2); + //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; + d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); + d.BodySetLinearVel(Body, 0, 0, 0); + d.BodyAddForce(Body, 0, 0, fz); + return; + } + else + { + _zeroFlag = false; + + // We're flying and colliding with something + fx = ((_target_velocity.X) - vel.X) * (PID_D); + fy = ((_target_velocity.Y) - vel.Y) * (PID_D); + + // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P; + + fz = ((_target_velocity.Z - vel.Z) * (PID_D)); + } + } // end if (m_usePID) + + // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller + else if (m_useHoverPID) + { + //Console.WriteLine("Hover " + Name); + + // If we're using the PID controller, then we have no gravity + + // 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 ((m_PIDTau < 1)) + { + PID_G = PID_G / m_PIDTau; + } + + if ((PID_G - m_PIDTau) <= 0) + { + PID_G = m_PIDTau + 1; + } + + // Where are we, and where are we headed? + d.Vector3 pos = d.BodyGetPosition(Body); + d.Vector3 vel = d.BodyGetLinearVel(Body); + + // Non-Vehicles have a limited set of Hover options. + // determine what our target height really is based on HoverType + switch (m_PIDHoverType) + { + case PIDHoverType.Ground: + m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); + m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; + break; + case PIDHoverType.GroundAndWater: + m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); + m_waterHeight = _parent_scene.GetWaterLevel(); + if (m_groundHeight > m_waterHeight) + { + m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; + } + else + { + m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight; + } + break; + + } // end switch (m_PIDHoverType) + + + _target_velocity = + new Vector3(0.0f, 0.0f, + (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep) + ); + + // if velocity is zero, use position control; otherwise, velocity control + + if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) + { + // keep track of where we stopped. No more slippin' & slidin' + + // 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 + + d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); + d.BodySetLinearVel(Body, vel.X, vel.Y, 0); + // ? d.BodyAddForce(Body, 0, 0, fz); + return; + } + else + { + _zeroFlag = false; + + // We're flying and colliding with something + fz = ((_target_velocity.Z - vel.Z) * (PID_D)); + } + } + else + { + float b = (1.0f - m_buoyancy); + fx = _parent_scene.gravityx * b; + fy = _parent_scene.gravityy * b; + fz = _parent_scene.gravityz * b; + } + + fx *= m_mass; + fy *= m_mass; + fz *= m_mass; + + // constant force + fx += m_force.X; + fy += m_force.Y; + fz += m_force.Z; + + fx += m_forceacc.X; + fy += m_forceacc.Y; + fz += m_forceacc.Z; + + m_forceacc = Vector3.Zero; + + //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString()); + if (fx != 0 || fy != 0 || fz != 0) + { + d.BodyAddForce(Body, fx, fy, fz); + //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz); + } + + Vector3 trq; + + trq = _torque; + trq += m_angularForceacc; + m_angularForceacc = Vector3.Zero; + if (trq.X != 0 || trq.Y != 0 || trq.Z != 0) + { + d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z); + } + } + } + else // body disabled + { + // let vehicles sleep + if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) + return; - fx *= m_mass; - fy *= m_mass; - fz *= m_mass; - - // constant force - fx += m_force.X; - fy += m_force.Y; - fz += m_force.Z; - - fx += m_forceacc.X; - fy += m_forceacc.Y; - fz += m_forceacc.Z; - - m_forceacc = Vector3.Zero; - - //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString()); - if (fx != 0 || fy != 0 || fz != 0) - { - d.BodyAddForce(Body, fx, fy, fz); - //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz); - } - - Vector3 trq; - - trq = _torque; - trq += m_angularForceacc; - m_angularForceacc = Vector3.Zero; - if (trq.X != 0 || trq.Y != 0 || trq.Z != 0) - { - d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z); - } + if (++bodydisablecontrol < 20) + return; + bodydisablecontrol = 0; + d.BodyEnable(Body); + return; } } else diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs index 4b3f83b24d..e66580de5d 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs @@ -30,10 +30,11 @@ using System.Collections.Generic; using System.Reflection; using System.Runtime.InteropServices; using System.Text; -using OpenMetaverse; +using OpenSim.Framework; using OpenSim.Region.Physics.Manager; using OdeAPI; using log4net; +using OpenMetaverse; namespace OpenSim.Region.Physics.OdePlugin { @@ -54,9 +55,11 @@ namespace OpenSim.Region.Physics.OdePlugin /// private OdeScene m_scene; - IntPtr ray; + IntPtr ray; // the ray. we only need one for our lifetime private const int ColisionContactGeomsPerTest = 5; + private const int DefaultMaxCount = 25; + private const int MaxTimePerCallMS = 30; /// /// ODE near callback delegate @@ -64,19 +67,22 @@ namespace OpenSim.Region.Physics.OdePlugin private d.NearCallback nearCallback; private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private List m_contactResults = new List(); + private RayFilterFlags CurrentRayFilter; + private int CurrentMaxCount; public ODERayCastRequestManager(OdeScene pScene) { m_scene = pScene; nearCallback = near; ray = d.CreateRay(IntPtr.Zero, 1.0f); + d.GeomSetCategoryBits(ray,0); } /// - /// Queues a raycast + /// Queues request for a raycast to all world /// /// Origin of Ray - /// Ray normal + /// Ray direction /// Ray length /// Return method to send the results public void QueueRequest(Vector3 position, Vector3 direction, float length, RayCallback retMethod) @@ -84,14 +90,22 @@ namespace OpenSim.Region.Physics.OdePlugin ODERayRequest req = new ODERayRequest(); req.geom = IntPtr.Zero; req.callbackMethod = retMethod; - req.Count = 0; + req.Count = DefaultMaxCount; req.length = length; req.Normal = direction; req.Origin = position; + req.filter = RayFilterFlags.AllButLand; m_PendingRequests.Enqueue(req); } + /// + /// Queues request for a raycast to particular part + /// + /// Origin of Ray + /// Ray direction + /// Ray length + /// Return method to send the results public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RayCallback retMethod) { ODERayRequest req = new ODERayRequest(); @@ -100,7 +114,8 @@ namespace OpenSim.Region.Physics.OdePlugin req.length = length; req.Normal = direction; req.Origin = position; - req.Count = 0; + req.Count = DefaultMaxCount; + req.filter = RayFilterFlags.AllButLand; m_PendingRequests.Enqueue(req); } @@ -110,10 +125,11 @@ namespace OpenSim.Region.Physics.OdePlugin ODERayRequest req = new ODERayRequest(); req.geom = IntPtr.Zero; req.callbackMethod = retMethod; - req.Count = 0; + req.Count = DefaultMaxCount; req.length = length; req.Normal = direction; req.Origin = position; + req.filter = RayFilterFlags.AllButLand; m_PendingRequests.Enqueue(req); } @@ -126,7 +142,8 @@ namespace OpenSim.Region.Physics.OdePlugin req.length = length; req.Normal = direction; req.Origin = position; - req.Count = 0; + req.Count = DefaultMaxCount; + req.filter = RayFilterFlags.AllButLand; m_PendingRequests.Enqueue(req); } @@ -148,6 +165,22 @@ namespace OpenSim.Region.Physics.OdePlugin req.Normal = direction; req.Origin = position; req.Count = count; + req.filter = RayFilterFlags.AllButLand; + + m_PendingRequests.Enqueue(req); + } + + + public void QueueRequest(Vector3 position, Vector3 direction, float length, int count,RayFilterFlags filter , RayCallback retMethod) + { + ODERayRequest req = new ODERayRequest(); + req.geom = IntPtr.Zero; + req.callbackMethod = retMethod; + req.length = length; + req.Normal = direction; + req.Origin = position; + req.Count = count; + req.filter = filter; m_PendingRequests.Enqueue(req); } @@ -161,6 +194,7 @@ namespace OpenSim.Region.Physics.OdePlugin req.Normal = direction; req.Origin = position; req.Count = count; + req.filter = RayFilterFlags.AllButLand; m_PendingRequests.Enqueue(req); } @@ -174,6 +208,7 @@ namespace OpenSim.Region.Physics.OdePlugin req.Normal = direction; req.Origin = position; req.Count = count; + req.filter = RayFilterFlags.AllButLand; m_PendingRequests.Enqueue(req); } @@ -187,6 +222,7 @@ namespace OpenSim.Region.Physics.OdePlugin req.Normal = direction; req.Origin = position; req.Count = count; + req.filter = RayFilterFlags.AllButLand; m_PendingRequests.Enqueue(req); } @@ -197,63 +233,104 @@ namespace OpenSim.Region.Physics.OdePlugin /// Time in MS the raycasts took to process. public int ProcessQueuedRequests() { - int time = System.Environment.TickCount; if (m_PendingRequests.Count <= 0) return 0; - if (m_scene.ContactgeomsArray == IntPtr.Zero) // oops something got wrong or scene isn't ready still + if (m_scene.ContactgeomsArray == IntPtr.Zero || ray == IntPtr.Zero) + // oops something got wrong or scene isn't ready still { m_PendingRequests.Clear(); return 0; } + int time = Util.EnvironmentTickCount(); + ODERayRequest req; + int closestHit; + int backfacecull; + CollisionCategories catflags; - int i = 50; // arbitary limit of processed tests per frame - - while(m_PendingRequests.Dequeue(out req)) + while (m_PendingRequests.Dequeue(out req)) { - if (req.geom == IntPtr.Zero) - doSpaceRay(req); - else - doGeomRay(req); - if(--i < 0) - break; + if (req.callbackMethod != null) + { + CurrentRayFilter = req.filter; + CurrentMaxCount = req.Count; + + closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1); + backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1); + + d.GeomRaySetLength(ray, req.length); + d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); + d.GeomRaySetParams(ray, 0, backfacecull); + d.GeomRaySetClosestHit(ray, closestHit); + + if (req.callbackMethod is RaycastCallback) + // if we only want one get only one per colision pair saving memory + CurrentRayFilter |= RayFilterFlags.ClosestHit; + + if (req.geom == IntPtr.Zero) + { + // translate ray filter to colision flags + catflags = 0; + if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0) + catflags |= CollisionCategories.VolumeDtc; + if ((CurrentRayFilter & RayFilterFlags.phantom) != 0) + catflags |= CollisionCategories.Phantom; + if ((CurrentRayFilter & RayFilterFlags.agent) != 0) + catflags |= CollisionCategories.Character; + if ((CurrentRayFilter & RayFilterFlags.PrimsNonPhantom) != 0) + catflags |= CollisionCategories.Geom; + if ((CurrentRayFilter & RayFilterFlags.land) != 0) + catflags |= CollisionCategories.Land; + if ((CurrentRayFilter & RayFilterFlags.water) != 0) + catflags |= CollisionCategories.Water; + + if (catflags != 0) + doSpaceRay(req); + } + else + { + // if we select a geom don't use filters + d.GeomSetCollideBits(ray, (uint)CollisionCategories.All); + doGeomRay(req); + } + } + + if (Util.EnvironmentTickCountSubtract(time) > MaxTimePerCallMS) + break; } lock (m_contactResults) m_contactResults.Clear(); - return System.Environment.TickCount - time; + return Util.EnvironmentTickCountSubtract(time); } /// - /// Method that actually initiates the raycast with full top space + /// Method that actually initiates the raycast with spaces /// /// + /// + + private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhanton; + private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton; + private void doSpaceRay(ODERayRequest req) { - // Create the ray -// IntPtr ray = d.CreateRay(m_scene.TopSpace, req.length); - d.GeomRaySetLength(ray, req.length); - d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); - - // Collide test - d.SpaceCollide2(m_scene.TopSpace, ray, IntPtr.Zero, nearCallback); - - // Remove Ray -// d.GeomDestroy(ray); - - if (req.callbackMethod == null) - return; + // Collide tests + if ((CurrentRayFilter & FilterActiveSpace) != 0) + d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback); + if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount)) + d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback); if (req.callbackMethod is RaycastCallback) { // Define default results bool hitYN = false; uint hitConsumerID = 0; - float distance = 999999999999f; - Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f); + float distance = float.MaxValue; + Vector3 closestcontact = Vector3.Zero; Vector3 snormal = Vector3.Zero; // Find closest contact and object. @@ -261,25 +338,30 @@ namespace OpenSim.Region.Physics.OdePlugin { foreach (ContactResult cResult in m_contactResults) { - if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact)) + if(cResult.Depth < distance) { closestcontact = cResult.Pos; hitConsumerID = cResult.ConsumerID; distance = cResult.Depth; - hitYN = true; snormal = cResult.Normal; } } m_contactResults.Clear(); } - + + if (distance > 0 && distance < float.MaxValue) + hitYN = true; ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal); } else { - ((RayCallback)req.callbackMethod)(m_contactResults); + List cresult = new List(m_contactResults.Count); lock (m_PendingRequests) + { + cresult.AddRange(m_contactResults); m_contactResults.Clear(); + } + ((RayCallback)req.callbackMethod)(cresult); } } @@ -289,27 +371,16 @@ namespace OpenSim.Region.Physics.OdePlugin /// private void doGeomRay(ODERayRequest req) { - // Create the ray -// IntPtr ray = d.CreateRay(m_scene.TopSpace, req.length); - d.GeomRaySetLength(ray, req.length); - d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); - // Collide test - d.SpaceCollide2(req.geom, ray, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test - - // Remove Ray -// d.GeomDestroy(ray); - - if (req.callbackMethod == null) - return; + d.SpaceCollide2(ray, req.geom, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test if (req.callbackMethod is RaycastCallback) { // Define default results bool hitYN = false; uint hitConsumerID = 0; - float distance = 999999999999f; - Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f); + float distance = float.MaxValue; + Vector3 closestcontact = Vector3.Zero; Vector3 snormal = Vector3.Zero; // Find closest contact and object. @@ -317,25 +388,31 @@ namespace OpenSim.Region.Physics.OdePlugin { foreach (ContactResult cResult in m_contactResults) { - if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact)) + if(cResult.Depth < distance ) { closestcontact = cResult.Pos; hitConsumerID = cResult.ConsumerID; distance = cResult.Depth; - hitYN = true; snormal = cResult.Normal; } } m_contactResults.Clear(); } + if (distance > 0 && distance < float.MaxValue) + hitYN = true; + ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal); } else { - ((RayCallback)req.callbackMethod)(m_contactResults); + List cresult = new List(m_contactResults.Count); lock (m_PendingRequests) + { + cresult.AddRange(m_contactResults); m_contactResults.Clear(); + } + ((RayCallback)req.callbackMethod)(cresult); } } @@ -350,20 +427,16 @@ namespace OpenSim.Region.Physics.OdePlugin return true; } - // This is the standard Near. g2 is the ray + // This is the standard Near. g1 is the ray private void near(IntPtr space, IntPtr g1, IntPtr g2) { - //Don't test against heightfield Geom, or you'll be sorry! - // Exclude heightfield geom - - if (g1 == IntPtr.Zero || g1 == g2) + if (g2 == IntPtr.Zero || g1 == g2) return; - if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass) + if (m_contactResults.Count >= CurrentMaxCount) return; - // Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms. - if (d.GeomIsSpace(g1)) + if (d.GeomIsSpace(g2)) { try { @@ -381,10 +454,6 @@ namespace OpenSim.Region.Physics.OdePlugin { count = d.CollidePtr(g1, g2, ColisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); } - catch (SEHException) - { - m_log.Error("[PHYSICS Ray]: 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."); - } catch (Exception e) { m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message); @@ -394,31 +463,116 @@ namespace OpenSim.Region.Physics.OdePlugin if (count == 0) return; - PhysicsActor p1 = null; + uint ID = 0; + PhysicsActor p2 = null; - if (g1 != IntPtr.Zero) - m_scene.actor_name_map.TryGetValue(g1, out p1); + m_scene.actor_name_map.TryGetValue(g2, out p2); + + if (p2 == null) + { + string name; + + if (!m_scene.geom_name_map.TryGetValue(g2, out name)) + return; + + if (name == "Terrain") + { + // land colision + if ((CurrentRayFilter & RayFilterFlags.land) == 0) + return; + } + else if (name == "Water") + { + if ((CurrentRayFilter & RayFilterFlags.water) == 0) + return; + } + else + return; + } + else + { + if (p2 is OdePrim) + { + RayFilterFlags thisFlags; + + if (p2.IsPhysical) + thisFlags = RayFilterFlags.physical; + else + thisFlags = RayFilterFlags.nonphysical; + + if (p2.Phantom) + thisFlags |= RayFilterFlags.phantom; + + if (p2.IsVolumeDtc) + thisFlags |= RayFilterFlags.volumedtc; + + if ((thisFlags & CurrentRayFilter) == 0) + return; + + ID = ((OdePrim)p2).m_localID; + } + else if (p2 is OdeCharacter) + { + if ((CurrentRayFilter & RayFilterFlags.agent) == 0) + return; + else + ID = ((OdeCharacter)p2).m_localID; + } + else //?? + return; + } d.ContactGeom curcontact = new d.ContactGeom(); - // Loop over contacts, build results. - for (int i = 0; i < count; i++) + + // closestHit for now only works for meshs, so must do it for others + if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0) { - if (!GetCurContactGeom(i, ref curcontact)) - break; - if (p1 != null) { - if (p1 is OdePrim) + // Loop all contacts, build results. + for (int i = 0; i < count; i++) + { + if (!GetCurContactGeom(i, ref curcontact)) + break; + + ContactResult collisionresult = new ContactResult(); + collisionresult.ConsumerID = ID; + collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z); + collisionresult.Depth = curcontact.depth; + collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y, + curcontact.normal.Z); + lock (m_contactResults) + { + m_contactResults.Add(collisionresult); + if (m_contactResults.Count >= CurrentMaxCount) + return; + } + } + } + else + { + // keep only closest contact + ContactResult collisionresult = new ContactResult(); + collisionresult.ConsumerID = ID; + collisionresult.Depth = float.MaxValue; + + for (int i = 0; i < count; i++) + { + if (!GetCurContactGeom(i, ref curcontact)) + break; + + if (curcontact.depth < collisionresult.Depth) { - ContactResult collisionresult = new ContactResult(); - - collisionresult.ConsumerID = ((OdePrim)p1).m_localID; collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z); collisionresult.Depth = curcontact.depth; collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y, curcontact.normal.Z); - lock (m_contactResults) - m_contactResults.Add(collisionresult); } } + + if (collisionresult.Depth != float.MaxValue) + { + lock (m_contactResults) + m_contactResults.Add(collisionresult); + } } } @@ -428,6 +582,11 @@ namespace OpenSim.Region.Physics.OdePlugin internal void Dispose() { m_scene = null; + if (ray != IntPtr.Zero) + { + d.GeomDestroy(ray); + ray = IntPtr.Zero; + } } } @@ -439,5 +598,6 @@ namespace OpenSim.Region.Physics.OdePlugin public int Count; public float length; public object callbackMethod; + public RayFilterFlags filter; } } \ No newline at end of file diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs index f5129cb540..0e4961b85a 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs @@ -889,13 +889,13 @@ namespace OdeAPI public static extern IntPtr GeomGetBody(IntPtr geom); [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetCategoryBits"), SuppressUnmanagedCodeSecurity] - public static extern int GeomGetCategoryBits(IntPtr geom); + public static extern uint GeomGetCategoryBits(IntPtr geom); [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetClassData"), SuppressUnmanagedCodeSecurity] public static extern IntPtr GeomGetClassData(IntPtr geom); [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetCollideBits"), SuppressUnmanagedCodeSecurity] - public static extern int GeomGetCollideBits(IntPtr geom); + public static extern uint GeomGetCollideBits(IntPtr geom); [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetClass"), SuppressUnmanagedCodeSecurity] public static extern GeomClassID GeomGetClass(IntPtr geom); @@ -1086,10 +1086,10 @@ namespace OdeAPI public static extern void GeomSetBody(IntPtr geom, IntPtr body); [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetCategoryBits"), SuppressUnmanagedCodeSecurity] - public static extern void GeomSetCategoryBits(IntPtr geom, int bits); + public static extern void GeomSetCategoryBits(IntPtr geom, uint bits); [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetCollideBits"), SuppressUnmanagedCodeSecurity] - public static extern void GeomSetCollideBits(IntPtr geom, int bits); + public static extern void GeomSetCollideBits(IntPtr geom, uint bits); [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetConvex"), SuppressUnmanagedCodeSecurity] public static extern IntPtr GeomSetConvex(IntPtr geom, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons); diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs index 3e0ccefe65..7632e25530 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs @@ -60,19 +60,31 @@ namespace OpenSim.Region.Physics.OdePlugin public int lastframe; } + // colision flags of things others can colide with + // rays, sensors, probes removed since can't be colided with + // The top space where things are placed provided further selection + // ie physical are in active space nonphysical in static + // this should be exclusive as possible + [Flags] - public enum CollisionCategories : int + public enum CollisionCategories : uint { Disabled = 0, - Geom = 0x00000001, - Body = 0x00000002, - Space = 0x00000004, - Character = 0x00000008, - Land = 0x00000010, - Water = 0x00000020, - Wind = 0x00000040, - Sensor = 0x00000080, - Selected = 0x00000100 + //by 'things' types + Space = 0x01, + Geom = 0x02, // aka prim/part + Character = 0x04, + Land = 0x08, + Water = 0x010, + + // by state + Phantom = 0x01000, + VolumeDtc = 0x02000, + Selected = 0x04000, + NoShape = 0x08000, + + + All = 0xffffffff } /// @@ -116,6 +128,7 @@ namespace OpenSim.Region.Physics.OdePlugin Acceleration, Force, Torque, + Momentum, AddForce, AddAngForce, @@ -186,7 +199,9 @@ namespace OpenSim.Region.Physics.OdePlugin private float waterlevel = 0f; private int framecount = 0; - internal IntPtr WaterGeom; + private IntPtr WaterGeom = IntPtr.Zero; + private IntPtr WaterHeightmapData = IntPtr.Zero; + private GCHandle WaterMapHandler = new GCHandle(); public float avPIDD = 2200f; // make it visible public float avPIDP = 900f; // make it visible @@ -213,9 +228,8 @@ namespace OpenSim.Region.Physics.OdePlugin // public int geomCrossingFailuresBeforeOutofbounds = 6; - public int bodyFramesAutoDisable = 20; + public int bodyFramesAutoDisable = 5; - private float[] _watermap; private d.NearCallback nearCallback; @@ -350,7 +364,7 @@ namespace OpenSim.Region.Physics.OdePlugin // i must RtC#FM } - d.HashSpaceSetLevels(TopSpace, -2, 8); // cell sizes from .25 to 256 ?? need check what this really does + d.HashSpaceSetLevels(TopSpace, -2, 8); d.HashSpaceSetLevels(ActiveSpace, -2, 8); d.HashSpaceSetLevels(StaticSpace, -2, 8); @@ -358,13 +372,27 @@ namespace OpenSim.Region.Physics.OdePlugin d.SpaceSetSublevel(ActiveSpace, 1); d.SpaceSetSublevel(StaticSpace, 1); + d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space | + CollisionCategories.Geom | + CollisionCategories.Character | + CollisionCategories.Phantom | + CollisionCategories.VolumeDtc + )); + d.GeomSetCollideBits(ActiveSpace, 0); + d.GeomSetCategoryBits(StaticSpace, (uint)(CollisionCategories.Space | + CollisionCategories.Geom | + CollisionCategories.Land | + CollisionCategories.Water | + CollisionCategories.Phantom | + CollisionCategories.VolumeDtc + )); + d.GeomSetCollideBits(StaticSpace, 0); + contactgroup = d.JointGroupCreate(0); //contactgroup d.WorldSetAutoDisableFlag(world, false); } - - _watermap = new float[258 * 258]; } // Initialize the mesh plugin @@ -374,15 +402,18 @@ namespace OpenSim.Region.Physics.OdePlugin // checkThread(); mesher = meshmerizer; m_config = config; - +/* string ode_config = d.GetConfiguration("ODE"); - m_log.WarnFormat("ODE configuration: {0}", ode_config); - - if (ode_config.Contains("ODE_Ubit")) + if (ode_config != null && ode_config != "") { - OdeUbitLib = true; - } + m_log.WarnFormat("ODE configuration: {0}", ode_config); + if (ode_config.Contains("ODE_Ubit")) + { + OdeUbitLib = true; + } + } +*/ /* if (region != null) { @@ -518,6 +549,15 @@ namespace OpenSim.Region.Physics.OdePlugin waitForSpaceUnlock(newspace); d.SpaceSetSublevel(newspace, 2); d.HashSpaceSetLevels(newspace, -2, 8); + d.GeomSetCategoryBits(newspace, (uint)(CollisionCategories.Space | + CollisionCategories.Geom | + CollisionCategories.Land | + CollisionCategories.Water | + CollisionCategories.Phantom | + CollisionCategories.VolumeDtc + )); + d.GeomSetCollideBits(newspace, 0); + staticPrimspace[i, j] = newspace; } // let this now be real maximum values @@ -1745,8 +1785,6 @@ namespace OpenSim.Region.Physics.OdePlugin m_rayCastManager.ProcessQueuedRequests(); - - statray += Util.EnvironmentTickCountSubtract(statstart); collision_optimized(); statcol += Util.EnvironmentTickCountSubtract(statstart); @@ -2125,14 +2163,14 @@ namespace OpenSim.Region.Physics.OdePlugin RegionTerrain.Remove(pOffset); if (GroundGeom != IntPtr.Zero) { + d.GeomDestroy(GroundGeom); + if (TerrainHeightFieldHeights.ContainsKey(GroundGeom)) { TerrainHeightFieldHeightsHandlers[GroundGeom].Free(); TerrainHeightFieldHeightsHandlers.Remove(GroundGeom); TerrainHeightFieldHeights.Remove(GroundGeom); } - d.SpaceRemove(StaticSpace, GroundGeom); - d.GeomDestroy(GroundGeom); } } IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); @@ -2147,8 +2185,8 @@ namespace OpenSim.Region.Physics.OdePlugin GroundGeom = d.CreateHeightfield(StaticSpace, HeightmapData, 1); if (GroundGeom != IntPtr.Zero) { - d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land)); - d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space)); + d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land)); + d.GeomSetCollideBits(GroundGeom, 0); } geom_name_map[GroundGeom] = "Terrain"; @@ -2236,14 +2274,15 @@ namespace OpenSim.Region.Physics.OdePlugin RegionTerrain.Remove(pOffset); if (GroundGeom != IntPtr.Zero) { + d.GeomDestroy(GroundGeom); + if (TerrainHeightFieldHeights.ContainsKey(GroundGeom)) { - TerrainHeightFieldHeightsHandlers[GroundGeom].Free(); + if (TerrainHeightFieldHeightsHandlers[GroundGeom].IsAllocated) + TerrainHeightFieldHeightsHandlers[GroundGeom].Free(); TerrainHeightFieldHeightsHandlers.Remove(GroundGeom); TerrainHeightFieldHeights.Remove(GroundGeom); } - d.SpaceRemove(StaticSpace, GroundGeom); - d.GeomDestroy(GroundGeom); } } IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); @@ -2263,8 +2302,8 @@ namespace OpenSim.Region.Physics.OdePlugin GroundGeom = d.CreateUbitTerrain(StaticSpace, HeightmapData, 1); if (GroundGeom != IntPtr.Zero) { - d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land)); - d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space)); + d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land)); + d.GeomSetCollideBits(GroundGeom, 0); } geom_name_map[GroundGeom] = "Terrain"; @@ -2359,57 +2398,76 @@ namespace OpenSim.Region.Physics.OdePlugin public void randomizeWater(float baseheight) { - const uint heightmapWidth = m_regionWidth + 2; - const uint heightmapHeight = m_regionHeight + 2; - const uint heightmapWidthSamples = m_regionWidth + 2; - const uint heightmapHeightSamples = m_regionHeight + 2; + const uint heightmapWidth = Constants.RegionSize + 2; + const uint heightmapHeight = Constants.RegionSize + 2; + const uint heightmapWidthSamples = heightmapWidth + 1; + const uint heightmapHeightSamples = heightmapHeight + 1; + const float scale = 1.0f; const float offset = 0.0f; - const float thickness = 2.9f; const int wrap = 0; - for (int i = 0; i < (258 * 258); i++) + float[] _watermap = new float[heightmapWidthSamples * heightmapWidthSamples]; + + float maxheigh = float.MinValue; + float minheigh = float.MaxValue; + float val; + for (int i = 0; i < (heightmapWidthSamples * heightmapHeightSamples); i++) { - _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f); - // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f)); + + val = (baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f); + _watermap[i] = val; + if (maxheigh < val) + maxheigh = val; + if (minheigh > val) + minheigh = val; } + float thickness = minheigh; + lock (OdeLock) { if (WaterGeom != IntPtr.Zero) { - d.SpaceRemove(StaticSpace, WaterGeom); + d.GeomDestroy(WaterGeom); + d.GeomHeightfieldDataDestroy(WaterHeightmapData); + WaterGeom = IntPtr.Zero; + WaterHeightmapData = IntPtr.Zero; + if(WaterMapHandler.IsAllocated) + WaterMapHandler.Free(); } - IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); - d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight, + + WaterHeightmapData = d.GeomHeightfieldDataCreate(); + + WaterMapHandler = GCHandle.Alloc(_watermap, GCHandleType.Pinned); + + d.GeomHeightfieldDataBuildSingle(WaterHeightmapData, WaterMapHandler.AddrOfPinnedObject(), 0, heightmapWidth, heightmapHeight, (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale, offset, thickness, wrap); - d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight); - WaterGeom = d.CreateHeightfield(StaticSpace, HeightmapData, 1); + d.GeomHeightfieldDataSetBounds(WaterHeightmapData, minheigh, maxheigh); + WaterGeom = d.CreateHeightfield(StaticSpace, WaterHeightmapData, 1); if (WaterGeom != IntPtr.Zero) { - d.GeomSetCategoryBits(WaterGeom, (int)(CollisionCategories.Water)); - d.GeomSetCollideBits(WaterGeom, (int)(CollisionCategories.Space)); + d.GeomSetCategoryBits(WaterGeom, (uint)(CollisionCategories.Water)); + d.GeomSetCollideBits(WaterGeom, 0); + geom_name_map[WaterGeom] = "Water"; + + d.Matrix3 R = new d.Matrix3(); + + Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f); + Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f); + + q1 = q1 * q2; + Vector3 v3; + float angle; + q1.GetAxisAngle(out v3, out angle); + + d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); + d.GeomSetRotation(WaterGeom, ref R); + d.GeomSetPosition(WaterGeom, (float)Constants.RegionSize * 0.5f, (float)Constants.RegionSize * 0.5f, 0); } - geom_name_map[WaterGeom] = "Water"; - - d.Matrix3 R = new d.Matrix3(); - - Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f); - Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f); - - q1 = q1 * q2; - Vector3 v3; - float angle; - q1.GetAxisAngle(out v3, out angle); - - d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); - d.GeomSetRotation(WaterGeom, ref R); - d.GeomSetPosition(WaterGeom, 128, 128, 0); - } - } public override void Dispose() @@ -2427,11 +2485,34 @@ namespace OpenSim.Region.Physics.OdePlugin } } + if (TerrainHeightFieldHeightsHandlers.Count > 0) + { + foreach (GCHandle gch in TerrainHeightFieldHeightsHandlers.Values) + { + if (gch.IsAllocated) + gch.Free(); + } + } + + if (WaterGeom != IntPtr.Zero) + { + d.GeomDestroy(WaterGeom); + WaterGeom = IntPtr.Zero; + if (WaterHeightmapData != IntPtr.Zero) + d.GeomHeightfieldDataDestroy(WaterHeightmapData); + WaterHeightmapData = IntPtr.Zero; + + if (WaterMapHandler.IsAllocated) + WaterMapHandler.Free(); + } + + if (ContactgeomsArray != IntPtr.Zero) Marshal.FreeHGlobal(ContactgeomsArray); if (GlobalContactsArray != IntPtr.Zero) Marshal.FreeHGlobal(GlobalContactsArray); + d.WorldDestroy(world); //d.CloseODE(); } @@ -2502,6 +2583,35 @@ namespace OpenSim.Region.Physics.OdePlugin return new List(ourResults); } + public override bool SuportsRaycastWorldFiltered() + { + return true; + } + + public override object RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter) + { + object SyncObject = new object(); + List ourresults = new List(); + + RayCallback retMethod = delegate(List results) + { + lock (SyncObject) + { + ourresults = results; + Monitor.PulseAll(SyncObject); + } + }; + + lock (SyncObject) + { + m_rayCastManager.QueueRequest(position, direction, length, Count,filter, retMethod); + if (!Monitor.Wait(SyncObject, 500)) + return null; + else + return ourresults; + } + } + public override void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) { if (retMethod != null && actor !=null) From 03139f07d7e5780dbe274e32911b4bf85d801ad8 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 16 Apr 2012 17:32:30 +0200 Subject: [PATCH 05/12] Downgrade an error log message to info because there is nothing we can do if an asset is damaged so it should not spew red ink. --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 2 +- OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 75fa1efd45..825b858a92 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -335,7 +335,7 @@ namespace OpenSim.Region.Physics.Meshing if (primShape.SculptData.Length <= 0) { - m_log.ErrorFormat("[MESH]: asset data for {0} is zero length", primName); + m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName); return false; } diff --git a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs index 8e903e83ba..f002bbab45 100644 --- a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs @@ -339,7 +339,7 @@ namespace OpenSim.Region.Physics.Meshing if (primShape.SculptData.Length <= 0) { - m_log.ErrorFormat("[MESH]: asset data for {0} is zero length", primName); + m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName); return false; } From 25a2f97bc2bb26fdb0d5856340f3ec8ce3ca9b98 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 16 Apr 2012 16:33:57 +0100 Subject: [PATCH 06/12] added suport funtions for ubitODE raycastFiltered --- OpenSim/Region/Framework/Scenes/Scene.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a34079ccc8..3e08128462 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1891,6 +1891,19 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerPrimsLoaded(this); } + public bool SuportsRayCastFiltered() + { + if (PhysicsScene == null) + return false; + return PhysicsScene.SuportsRaycastWorldFiltered(); + } + + public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter) + { + if (PhysicsScene == null) + return null; + return PhysicsScene.RaycastWorld(position, direction, length, Count,filter); + } /// /// Gets a new rez location based on the raycast and the size of the object that is being rezzed. From f05a977afaacca2df4406f2d4aefed960a4b7f1c Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 16 Apr 2012 16:35:35 +0100 Subject: [PATCH 07/12] Let llCastRay use ubitODE raycast if avaiable plus a few changes/fixes that should be checked. PROBLEM: it will not detect nonphysical phantons :( --- .../Shared/Api/Implementation/LSL_Api.cs | 108 ++++++++++++++---- 1 file changed, 86 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 2f61b70348..5b5e23e038 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -11869,38 +11869,101 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); - if (checkTerrain) - { - ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); - if (groundContact != null) - results.Add((ContactResult)groundContact); - } - if (checkAgents) + if (World.SuportsRayCastFiltered()) { - ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); - foreach (ContactResult r in agentHits) - results.Add(r); - } + if (dist == 0) + return list; - if (checkPhysical || checkNonPhysical) + RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull; + if (checkTerrain) + rayfilter |= RayFilterFlags.land; +// if (checkAgents) +// rayfilter |= RayFilterFlags.agent; + if (checkPhysical) + rayfilter |= RayFilterFlags.physical; + if (checkNonPhysical) + rayfilter |= RayFilterFlags.nonphysical; + if (detectPhantom) + rayfilter |= RayFilterFlags.LSLPhanton; + + Vector3 direction = dir * ( 1/dist); + + if(rayfilter == 0) + { + list.Add(new LSL_Integer(0)); + return list; + } + + // get some more contacts to sort ??? + int physcount = 4 * count; + if (physcount > 20) + physcount = 20; + + object physresults; + physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter); + + if (physresults == null) + { + list.Add(new LSL_Integer(-3)); // timeout error + return list; + } + + results = (List)physresults; + + // for now physics doesn't detect sitted avatars so do it outside physics + if (checkAgents) + { + ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); + foreach (ContactResult r in agentHits) + results.Add(r); + } + + // bug: will not detect phantom unless they are physical + // don't use ObjectIntersection because its also bad + + } + else { - ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); - foreach (ContactResult r in objectHits) - results.Add(r); + if (checkTerrain) + { + ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); + if (groundContact != null) + results.Add((ContactResult)groundContact); + } + + if (checkAgents) + { + ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); + foreach (ContactResult r in agentHits) + results.Add(r); + } + + if (checkPhysical || checkNonPhysical || detectPhantom) + { + ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); + foreach (ContactResult r in objectHits) + results.Add(r); + } } results.Sort(delegate(ContactResult a, ContactResult b) { - return (int)(a.Depth - b.Depth); + return a.Depth.CompareTo(b.Depth); }); int values = 0; + SceneObjectGroup thisgrp = m_host.ParentGroup; + foreach (ContactResult result in results) { if (result.Depth > dist) continue; + // physics ray can return colisions with host prim + if (m_host.LocalId == result.ConsumerID) + continue; + UUID itemID = UUID.Zero; int linkNum = 0; @@ -11908,6 +11971,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // It's a prim! if (part != null) { + // dont detect members of same object ??? + if (part.ParentGroup == thisgrp) + continue; + if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY) itemID = part.ParentGroup.UUID; else @@ -11918,7 +11985,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api else { ScenePresence sp = World.GetScenePresence(result.ConsumerID); - /// It it a boy? a girl? + /// It it a boy? a girl? if (sp != null) itemID = sp.UUID; } @@ -11929,14 +11996,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) list.Add(new LSL_Integer(linkNum)); - if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z)); - - values++; - count--; - if (count == 0) + values++; + if (values >= count) break; } From 04ed5519a5ad265794a0768a6a3c9e4e0fdf1a6c Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 16 Apr 2012 17:14:31 +0100 Subject: [PATCH 08/12] chODE bug fix --- .../Region/Physics/ChOdePlugin/ODECharacter.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs index 1f1ba951a7..c53ccecf75 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs @@ -921,6 +921,8 @@ namespace OpenSim.Region.Physics.OdePlugin m_haveTaintMomentum = true; _parent_scene.AddPhysicsActorTaint(this); } + else + m_log.Warn("[PHYSICS] !isFinite momentum"); } @@ -1337,7 +1339,6 @@ namespace OpenSim.Region.Physics.OdePlugin { lock (m_syncRoot) { - if (m_tainted_isPhysical != m_isPhysical) { if (m_tainted_isPhysical) @@ -1379,9 +1380,9 @@ namespace OpenSim.Region.Physics.OdePlugin { d.GeomDestroy(Shell); } - catch (System.AccessViolationException) + catch (Exception e) { - m_log.Error("[PHYSICS]: PrimGeom dead"); + m_log.ErrorFormat("[PHYSICS]: Failed to destroy character shell {0}",e.Message); } // Remove any old entries //string tShell; @@ -1428,10 +1429,10 @@ namespace OpenSim.Region.Physics.OdePlugin { d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z); - _position.X = m_taintPosition.X; - _position.Y = m_taintPosition.Y; - _position.Z = m_taintPosition.Z; } + _position.X = m_taintPosition.X; + _position.Y = m_taintPosition.Y; + _position.Z = m_taintPosition.Z; } if (m_haveTaintMomentum) @@ -1440,7 +1441,8 @@ namespace OpenSim.Region.Physics.OdePlugin _velocity = m_taintMomentum; _target_velocity = m_taintMomentum; m_pidControllerActive = true; - d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z); + if (Body != IntPtr.Zero) + d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z); } } } From fff5c61ae83ad54eaff640d2868186d275f3dd62 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 16 Apr 2012 17:47:17 +0100 Subject: [PATCH 09/12] chODE: if character velocity > 50m/s apply breaks. In free fall this will give a terminal velocity +- 60m/s --- OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs index c53ccecf75..ec717d73b0 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs @@ -1122,9 +1122,18 @@ namespace OpenSim.Region.Physics.OdePlugin } // end add Kitto Flora } + + if (vel.X * vel.X + vel.Y * vel.Y + vel.Z * vel.Z > 2500.0f) // 50ms apply breaks + { + float breakfactor = 0.16f * m_mass; // will give aprox 60m/s terminal velocity at free fall + vec.X -= breakfactor * vel.X; + vec.Y -= breakfactor * vel.Y; + vec.Z -= breakfactor * vel.Z; + } + if (vec.IsFinite()) { - if (!vec.ApproxEquals(Vector3.Zero, 0.02f)) // 0.01 allows 0.002 !! + if (vec.LengthSquared() > 0.0004f) // 0.01 allows 0.002 !! { //Console.WriteLine("DF 2"); // ## From 6480b72eda967d6166cb8a64c5bca20c7841358c Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 16 Apr 2012 19:44:02 +0100 Subject: [PATCH 10/12] ubitODE: - fix remove characters from default raycasts filters as older code (or camera is very odd) - Slow down avatar if velocity is higher than 50m/s as in chODE --- .../Region/Physics/UbitOdePlugin/ODECharacter.cs | 8 ++++++++ .../UbitOdePlugin/ODERayCastRequestManager.cs | 16 ++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs index b9bb06ec58..3185aad7e4 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs @@ -990,6 +990,14 @@ namespace OpenSim.Region.Physics.OdePlugin // end add Kitto Flora } + if (vel.X * vel.X + vel.Y * vel.Y + vel.Z * vel.Z > 2500.0f) // 50m/s apply breaks + { + float breakfactor = 0.16f * m_mass; // will give aprox 60m/s terminal velocity at free fall + vec.X -= breakfactor * vel.X; + vec.Y -= breakfactor * vel.Y; + vec.Z -= breakfactor * vel.Z; + } + if (vec.IsFinite()) { if (vec.X != 0 || vec.Y !=0 || vec.Z !=0) diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs index e66580de5d..5122ebfa11 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.Physics.OdePlugin req.length = length; req.Normal = direction; req.Origin = position; - req.filter = RayFilterFlags.AllButLand; + req.filter = RayFilterFlags.AllPrims; m_PendingRequests.Enqueue(req); } @@ -115,7 +115,7 @@ namespace OpenSim.Region.Physics.OdePlugin req.Normal = direction; req.Origin = position; req.Count = DefaultMaxCount; - req.filter = RayFilterFlags.AllButLand; + req.filter = RayFilterFlags.AllPrims; m_PendingRequests.Enqueue(req); } @@ -129,7 +129,7 @@ namespace OpenSim.Region.Physics.OdePlugin req.length = length; req.Normal = direction; req.Origin = position; - req.filter = RayFilterFlags.AllButLand; + req.filter = RayFilterFlags.AllPrims; m_PendingRequests.Enqueue(req); } @@ -143,7 +143,7 @@ namespace OpenSim.Region.Physics.OdePlugin req.Normal = direction; req.Origin = position; req.Count = DefaultMaxCount; - req.filter = RayFilterFlags.AllButLand; + req.filter = RayFilterFlags.AllPrims; m_PendingRequests.Enqueue(req); } @@ -165,7 +165,7 @@ namespace OpenSim.Region.Physics.OdePlugin req.Normal = direction; req.Origin = position; req.Count = count; - req.filter = RayFilterFlags.AllButLand; + req.filter = RayFilterFlags.AllPrims; m_PendingRequests.Enqueue(req); } @@ -194,7 +194,7 @@ namespace OpenSim.Region.Physics.OdePlugin req.Normal = direction; req.Origin = position; req.Count = count; - req.filter = RayFilterFlags.AllButLand; + req.filter = RayFilterFlags.AllPrims; m_PendingRequests.Enqueue(req); } @@ -208,7 +208,7 @@ namespace OpenSim.Region.Physics.OdePlugin req.Normal = direction; req.Origin = position; req.Count = count; - req.filter = RayFilterFlags.AllButLand; + req.filter = RayFilterFlags.AllPrims; m_PendingRequests.Enqueue(req); } @@ -222,7 +222,7 @@ namespace OpenSim.Region.Physics.OdePlugin req.Normal = direction; req.Origin = position; req.Count = count; - req.filter = RayFilterFlags.AllButLand; + req.filter = RayFilterFlags.AllPrims; m_PendingRequests.Enqueue(req); } From 723015e4f0b30b520a6b8e4aa88bacb74cca64c6 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 16 Apr 2012 21:58:25 +0100 Subject: [PATCH 11/12] fix (http://opensimulator.org/mantis/view.php?id=5965) llGetObjectMass was bad for sitted avatars not checking for the null physicsactor --- .../Shared/Api/Implementation/LSL_Api.cs | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 5b5e23e038..8e73eb1cef 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9980,7 +9980,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // return total object mass SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId); if (obj != null) - return (double)obj.GetMass(); + return obj.GetMass(); // the object is null so the key is for an avatar ScenePresence avatar = World.GetScenePresence(key); @@ -9990,7 +9990,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // child agents have a mass of 1.0 return 1; else - return (double)avatar.PhysicsActor.Mass; + return avatar.GetMass(); } catch (KeyNotFoundException) { @@ -11829,6 +11829,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return contacts[0]; } +/* + // not done: + private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght) + { + ContactResult[] contacts = null; + World.ForEachSOG(delegate(SceneObjectGroup group) + { + if (m_host.ParentGroup == group) + return; + + if (group.IsAttachment) + return; + + if(group.RootPart.PhysActor != null) + return; + + contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght); + }); + return contacts; + } +*/ public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) { From 36207b88ffc7801fb15e544e727cb3efaa25d6ea Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 17 Apr 2012 01:00:50 +0100 Subject: [PATCH 12/12] ubitODE: bug fix let avatars colide with volume detectors --- OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs index 3185aad7e4..9c1b87bea8 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs @@ -117,6 +117,7 @@ namespace OpenSim.Region.Physics.OdePlugin // Default, Collide with Other Geometries, spaces, bodies and characters. private CollisionCategories m_collisionFlags = (CollisionCategories.Character | CollisionCategories.Geom + | CollisionCategories.VolumeDtc ); // we do land collisions not ode | CollisionCategories.Land); public IntPtr Body = IntPtr.Zero;