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. diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index fd7f7d8e1a..7a634c4d6b 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) // skip it if sitting { Animator.UpdateMovementAnimations(); } @@ -1077,10 +1077,13 @@ namespace OpenSim.Region.Framework.Scenes public void TeleportWithMomentum(Vector3 pos) { bool isFlying = Flying; + Vector3 vel = Velocity; RemoveFromPhysicalScene(); CheckLandingPoint(ref pos); AbsolutePosition = pos; AddToPhysicalScene(isFlying); + if (PhysicsActor != null) + PhysicsActor.SetMomentum(vel); SendTerseUpdateToAllClients(); } @@ -1385,8 +1388,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); + } } } diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs index 2945199faf..ec717d73b0 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,14 @@ namespace OpenSim.Region.Physics.OdePlugin public override void SetMomentum(Vector3 momentum) { + if (momentum.IsFinite()) + { + m_taintMomentum = momentum; + m_haveTaintMomentum = true; + _parent_scene.AddPhysicsActorTaint(this); + } + else + m_log.Warn("[PHYSICS] !isFinite momentum"); } @@ -1110,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"); // ## @@ -1327,7 +1348,6 @@ namespace OpenSim.Region.Physics.OdePlugin { lock (m_syncRoot) { - if (m_tainted_isPhysical != m_isPhysical) { if (m_tainted_isPhysical) @@ -1369,9 +1389,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; @@ -1418,12 +1438,21 @@ 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) + { + m_haveTaintMomentum = false; + _velocity = m_taintMomentum; + _target_velocity = m_taintMomentum; + m_pidControllerActive = true; + if (Body != IntPtr.Zero) + d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z); + } } } 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/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; } diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs index 4266fdab95..9c1b87bea8 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs @@ -115,12 +115,11 @@ 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 + | CollisionCategories.VolumeDtc ); - // 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 +638,8 @@ namespace OpenSim.Region.Physics.OdePlugin public override void SetMomentum(Vector3 momentum) { + if (momentum.IsFinite()) + AddChange(changes.Momentum, momentum); } @@ -663,8 +664,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 +760,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; } } @@ -991,6 +991,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) @@ -1324,6 +1332,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 +1413,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..5122ebfa11 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.AllPrims; 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.AllPrims; 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.AllPrims; 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.AllPrims; 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.AllPrims; + + 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.AllPrims; 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.AllPrims; 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.AllPrims; 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) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 9564d4616d..3a7eb3212d 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) { @@ -11834,6 +11834,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) { @@ -11874,38 +11895,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; @@ -11913,6 +11997,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 @@ -11923,7 +12011,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; } @@ -11934,14 +12022,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; }