Merge branch 'master' of ssh://melanie@3dhosting.de/var/git/careminster into careminster

avinationmerge
Melanie 2012-04-17 01:50:49 +01:00
commit ab1a3688e2
13 changed files with 1214 additions and 813 deletions

View File

@ -1891,6 +1891,19 @@ namespace OpenSim.Region.Framework.Scenes
EventManager.TriggerPrimsLoaded(this); 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);
}
/// <summary> /// <summary>
/// Gets a new rez location based on the raycast and the size of the object that is being rezzed. /// Gets a new rez location based on the raycast and the size of the object that is being rezzed.

View File

@ -753,7 +753,7 @@ namespace OpenSim.Region.Framework.Scenes
if (m_movementAnimationUpdateCounter >= 2) if (m_movementAnimationUpdateCounter >= 2)
{ {
m_movementAnimationUpdateCounter = 0; m_movementAnimationUpdateCounter = 0;
if (Animator != null) if (Animator != null && ParentID == 0) // skip it if sitting
{ {
Animator.UpdateMovementAnimations(); Animator.UpdateMovementAnimations();
} }
@ -1077,10 +1077,13 @@ namespace OpenSim.Region.Framework.Scenes
public void TeleportWithMomentum(Vector3 pos) public void TeleportWithMomentum(Vector3 pos)
{ {
bool isFlying = Flying; bool isFlying = Flying;
Vector3 vel = Velocity;
RemoveFromPhysicalScene(); RemoveFromPhysicalScene();
CheckLandingPoint(ref pos); CheckLandingPoint(ref pos);
AbsolutePosition = pos; AbsolutePosition = pos;
AddToPhysicalScene(isFlying); AddToPhysicalScene(isFlying);
if (PhysicsActor != null)
PhysicsActor.SetMomentum(vel);
SendTerseUpdateToAllClients(); SendTerseUpdateToAllClients();
} }
@ -1385,8 +1388,16 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (m_followCamAuto) if (m_followCamAuto)
{ {
Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; // Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); // 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);
}
} }
} }

View File

@ -140,6 +140,10 @@ namespace OpenSim.Region.Physics.OdePlugin
public int m_eventsubscription = 0; public int m_eventsubscription = 0;
private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate(); private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
private Vector3 m_taintMomentum = Vector3.Zero;
private bool m_haveTaintMomentum = false;
// unique UUID of this character object // unique UUID of this character object
public UUID m_uuid; public UUID m_uuid;
public bool bad = false; public bool bad = false;
@ -800,8 +804,8 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
if (value.IsFinite()) if (value.IsFinite())
{ {
m_pidControllerActive = true;
_target_velocity = value; _target_velocity = value;
m_pidControllerActive = true;
} }
else else
{ {
@ -911,6 +915,14 @@ namespace OpenSim.Region.Physics.OdePlugin
public override void SetMomentum(Vector3 momentum) 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 // 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.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"); // ## //Console.WriteLine("DF 2"); // ##
@ -1327,7 +1348,6 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
lock (m_syncRoot) lock (m_syncRoot)
{ {
if (m_tainted_isPhysical != m_isPhysical) if (m_tainted_isPhysical != m_isPhysical)
{ {
if (m_tainted_isPhysical) if (m_tainted_isPhysical)
@ -1369,9 +1389,9 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
d.GeomDestroy(Shell); 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 // Remove any old entries
//string tShell; //string tShell;
@ -1418,12 +1438,21 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z); d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z);
}
_position.X = m_taintPosition.X; _position.X = m_taintPosition.X;
_position.Y = m_taintPosition.Y; _position.Y = m_taintPosition.Y;
_position.Z = m_taintPosition.Z; _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);
}
} }
} }

View File

@ -172,6 +172,12 @@ namespace OpenSim.Region.Physics.Manager
public virtual bool Phantom { get; set; } public virtual bool Phantom { get; set; }
public virtual bool IsVolumeDtc
{
get { return false; }
set { return; }
}
public virtual byte PhysicsShapeType { get; set; } public virtual byte PhysicsShapeType { get; set; }
public abstract PrimitiveBaseShape Shape { set; } public abstract PrimitiveBaseShape Shape { set; }

View File

@ -43,6 +43,34 @@ namespace OpenSim.Region.Physics.Manager
public delegate void JointDeactivated(PhysicsJoint joint); 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 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
}
/// <summary> /// <summary>
/// Contact result from a raycast. /// Contact result from a raycast.
/// </summary> /// </summary>
@ -54,6 +82,8 @@ namespace OpenSim.Region.Physics.Manager
public Vector3 Normal; public Vector3 Normal;
} }
public abstract class PhysicsScene public abstract class PhysicsScene
{ {
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -280,6 +310,16 @@ namespace OpenSim.Region.Physics.Manager
return new List<ContactResult>(); return new List<ContactResult>();
} }
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, RaycastCallback retMethod){}
public virtual void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) { } public virtual void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) { }
public virtual List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count) public virtual List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count)

View File

@ -335,7 +335,7 @@ namespace OpenSim.Region.Physics.Meshing
if (primShape.SculptData.Length <= 0) 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; return false;
} }

View File

@ -339,7 +339,7 @@ namespace OpenSim.Region.Physics.Meshing
if (primShape.SculptData.Length <= 0) 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; return false;
} }

View File

@ -115,10 +115,9 @@ namespace OpenSim.Region.Physics.OdePlugin
private CollisionCategories m_collisionCategories = (CollisionCategories.Character); private CollisionCategories m_collisionCategories = (CollisionCategories.Character);
// Default, Collide with Other Geometries, spaces, bodies and characters. // Default, Collide with Other Geometries, spaces, bodies and characters.
private CollisionCategories m_collisionFlags = (CollisionCategories.Geom private CollisionCategories m_collisionFlags = (CollisionCategories.Character
| CollisionCategories.Space | CollisionCategories.Geom
| CollisionCategories.Body | CollisionCategories.VolumeDtc
| CollisionCategories.Character
); );
// we do land collisions not ode | CollisionCategories.Land); // we do land collisions not ode | CollisionCategories.Land);
public IntPtr Body = IntPtr.Zero; public IntPtr Body = IntPtr.Zero;
@ -639,6 +638,8 @@ namespace OpenSim.Region.Physics.OdePlugin
public override void SetMomentum(Vector3 momentum) 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); Shell = d.CreateCapsule(_parent_scene.ActiveSpace, CAPSULE_RADIUS, CAPSULE_LENGTH);
d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); d.GeomSetCategoryBits(Shell, (uint)m_collisionCategories);
d.GeomSetCollideBits(Shell, (int)m_collisionFlags); d.GeomSetCollideBits(Shell, (uint)m_collisionFlags);
d.MassSetCapsule(out ShellMass, m_density, 3, CAPSULE_RADIUS, CAPSULE_LENGTH); 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.geom_name_map.Remove(Shell);
_parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
d.GeomDestroy(Shell); d.GeomDestroy(Shell);
_parent_scene.geom_name_map.Remove(Shell);
Shell = IntPtr.Zero; Shell = IntPtr.Zero;
} }
} }
@ -991,6 +991,14 @@ namespace OpenSim.Region.Physics.OdePlugin
// end add Kitto Flora // 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.IsFinite())
{ {
if (vec.X != 0 || vec.Y !=0 || vec.Z !=0) 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() private void donullchange()
{ {
} }
@ -1395,6 +1413,10 @@ namespace OpenSim.Region.Physics.OdePlugin
case changes.Size: case changes.Size:
changeSize((Vector3)arg); changeSize((Vector3)arg);
break; break;
case changes.Momentum:
changeMomentum((Vector3)arg);
break;
/* not in use for now /* not in use for now
case changes.Shape: case changes.Shape:
changeShape((PrimitiveBaseShape)arg); changeShape((PrimitiveBaseShape)arg);

View File

@ -108,25 +108,29 @@ namespace OpenSim.Region.Physics.OdePlugin
private float m_waterHeight; private float m_waterHeight;
private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. 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 // Default we're a Geometry
private CollisionCategories m_collisionCategories = (CollisionCategories.Geom); 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 // 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; public bool m_disabled;
@ -179,6 +183,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public float primOOBradiusSQ; public float primOOBradiusSQ;
public d.Mass primdMass; // prim inertia information on it's own referencial public d.Mass primdMass; // prim inertia information on it's own referencial
float primMass; // prim own mass float primMass; // prim own mass
float primVolume; // prim own volume;
float _mass; // object mass acording to case float _mass; // object mass acording to case
private bool hasOOBoffsetFromMesh = false; // if true we did compute it form mesh centroid, else from aabb 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 public override bool Phantom // this is not reliable for internal use
{ {
get { return m_fakeisphantom; } get { return m_fakeisphantom; }
@ -327,10 +340,7 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
if (m_colliderfilter == 0) if (m_colliderfilter == 0)
{
m_softcolide = false;
m_iscolliding = false; m_iscolliding = false;
}
else else
m_iscolliding = true; m_iscolliding = true;
} }
@ -422,6 +432,10 @@ namespace OpenSim.Region.Physics.OdePlugin
public override Vector3 GeometricCenter 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 get
{ {
return Vector3.Zero; return Vector3.Zero;
@ -949,7 +963,6 @@ namespace OpenSim.Region.Physics.OdePlugin
m_iscolliding = false; m_iscolliding = false;
m_colliderfilter = 0; m_colliderfilter = 0;
m_softcolide = true;
m_NoColide = false; m_NoColide = false;
hasOOBoffsetFromMesh = false; hasOOBoffsetFromMesh = false;
@ -992,6 +1005,132 @@ namespace OpenSim.Region.Physics.OdePlugin
m_collisionscore = 0; 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) private void createAMotor(Vector3 axis)
{ {
if (Body == IntPtr.Zero) if (Body == IntPtr.Zero)
@ -1188,7 +1327,7 @@ namespace OpenSim.Region.Physics.OdePlugin
d.GeomSetCategoryBits(prim_geom, 0); d.GeomSetCategoryBits(prim_geom, 0);
if (m_isphysical) if (m_isphysical)
{ {
d.GeomSetCollideBits(prim_geom, (int)CollisionCategories.Land); d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
} }
else else
{ {
@ -1198,8 +1337,8 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
else else
{ {
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
} }
CalcPrimBodyData(); CalcPrimBodyData();
@ -1296,6 +1435,7 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
prim_geom = IntPtr.Zero; prim_geom = IntPtr.Zero;
collide_geom = IntPtr.Zero;
} }
else else
{ {
@ -1319,66 +1459,23 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace); IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace);
prim.m_targetSpace = targetSpace; prim.m_targetSpace = targetSpace;
d.GeomEnable(prim_geom); collide_geom = IntPtr.Zero;
} }
public void enableBodySoft() public void enableBodySoft()
{ {
m_disabled = false;
if (!childPrim && !m_isSelected) if (!childPrim && !m_isSelected)
{ {
if (m_isphysical && Body != IntPtr.Zero) if (m_isphysical && Body != IntPtr.Zero)
{ {
if (m_isphantom && !m_isVolumeDetect) UpdateCollisionCatFlags();
{ ApplyCollisionCatFlags();
m_collisionCategories = 0;
m_collisionFlags = CollisionCategories.Land;
}
else
{
m_collisionCategories |= CollisionCategories.Body;
m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
}
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); d.BodyEnable(Body);
} }
} }
m_disabled = false; resetCollisionAccounting();
resetCollisionAccounting(); // this sets m_disable to false
} }
private void disableBodySoft() private void disableBodySoft()
@ -1388,45 +1485,12 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
if (m_isphysical && Body != IntPtr.Zero) if (m_isphysical && Body != IntPtr.Zero)
{ {
m_collisionCategories &= ~CollisionCategories.Body; if (m_isSelected)
m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); m_collisionFlags = CollisionCategories.Selected;
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 else
{ m_collisionCategories = 0;
d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); m_collisionFlags = 0;
d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); ApplyCollisionCatFlags();
}
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);
}
d.BodyDisable(Body); d.BodyDisable(Body);
} }
} }
@ -1566,7 +1630,6 @@ namespace OpenSim.Region.Physics.OdePlugin
// d.BodySetAngularDampingThreshold(Body, 0.001f); // d.BodySetAngularDampingThreshold(Body, 0.001f);
d.BodySetDamping(Body, .002f, .002f); d.BodySetDamping(Body, .002f, .002f);
if (m_targetSpace != IntPtr.Zero) if (m_targetSpace != IntPtr.Zero)
{ {
_parent_scene.waitForSpaceUnlock(m_targetSpace); _parent_scene.waitForSpaceUnlock(m_targetSpace);
@ -1588,6 +1651,13 @@ namespace OpenSim.Region.Physics.OdePlugin
d.SpaceSetSublevel(m_targetSpace, 3); d.SpaceSetSublevel(m_targetSpace, 3);
d.SpaceSetCleanup(m_targetSpace, false); d.SpaceSetCleanup(m_targetSpace, false);
d.SpaceAdd(m_targetSpace, prim_geom); 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; collide_geom = m_targetSpace;
} }
@ -1619,38 +1689,6 @@ namespace OpenSim.Region.Physics.OdePlugin
d.SpaceAdd(m_targetSpace, prm.prim_geom); 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; prm.m_collisionscore = 0;
if(!m_disabled) if(!m_disabled)
@ -1666,45 +1704,21 @@ namespace OpenSim.Region.Physics.OdePlugin
createAMotor(m_angularlock); createAMotor(m_angularlock);
} }
m_collisionscore = 0;
UpdateCollisionCatFlags();
ApplyCollisionCatFlags();
if (m_isSelected || m_disabled) if (m_isSelected || m_disabled)
{ {
m_collisionCategories &= ~CollisionCategories.Body;
m_collisionFlags &= ~(CollisionCategories.Land | CollisionCategories.Wind);
d.GeomDisable(prim_geom);
d.BodyDisable(Body); d.BodyDisable(Body);
} }
else 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.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z);
d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.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.addActivePrim(this);
_parent_scene.addActiveGroups(this); _parent_scene.addActiveGroups(this);
} }
@ -1714,8 +1728,22 @@ namespace OpenSim.Region.Physics.OdePlugin
if (Body != IntPtr.Zero) if (Body != IntPtr.Zero)
{ {
_parent_scene.remActivePrim(this); _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 (prim_geom != IntPtr.Zero)
{ {
if (m_NoColide) if (m_NoColide)
@ -1725,8 +1753,8 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
else else
{ {
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
} }
UpdateDataFromGeom(); UpdateDataFromGeom();
d.GeomSetBody(prim_geom, IntPtr.Zero); d.GeomSetBody(prim_geom, IntPtr.Zero);
@ -1740,8 +1768,18 @@ namespace OpenSim.Region.Physics.OdePlugin
foreach (OdePrim prm in childrenPrim) foreach (OdePrim prm in childrenPrim)
{ {
_parent_scene.remActivePrim(prm); _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.prim_geom != IntPtr.Zero)
{ {
if (prm.m_NoColide) if (prm.m_NoColide)
@ -1751,8 +1789,8 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
else else
{ {
d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
} }
prm.UpdateDataFromGeom(); prm.UpdateDataFromGeom();
SetInStaticSpace(prm); SetInStaticSpace(prm);
@ -2292,6 +2330,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// keep using basic shape mass for now // keep using basic shape mass for now
volume = CalculatePrimVolume(); volume = CalculatePrimVolume();
primVolume = volume;
primMass = m_density * volume; primMass = m_density * volume;
if (primMass <= 0) if (primMass <= 0)
@ -2515,11 +2554,12 @@ namespace OpenSim.Region.Physics.OdePlugin
d.GeomSetQuaternion(prim_geom, ref myrot); d.GeomSetQuaternion(prim_geom, ref myrot);
if (!m_isphysical) if (!m_isphysical)
SetInStaticSpace(this);
}
if (m_isphysical && Body == IntPtr.Zero)
{ {
SetInStaticSpace(this);
UpdateCollisionCatFlags();
ApplyCollisionCatFlags();
}
else
MakeBody(); MakeBody();
} }
} }
@ -2602,86 +2642,12 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
} }
private void changePhantomStatus(bool newval) private void changePhantomStatus(bool newval)
{ {
m_isphantom = newval; m_isphantom = newval;
if (m_isSelected) UpdateCollisionCatFlags();
{ ApplyCollisionCatFlags();
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);
}
} }
private void changeSelectedStatus(bool newval) private void changeSelectedStatus(bool newval)
@ -2714,7 +2680,7 @@ namespace OpenSim.Region.Physics.OdePlugin
if (m_delaySelect || m_isphysical) if (m_delaySelect || m_isphysical)
{ {
m_collisionCategories = CollisionCategories.Selected; m_collisionCategories = CollisionCategories.Selected;
m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space); m_collisionFlags = 0;
if (!childPrim) if (!childPrim)
{ {
@ -2733,10 +2699,9 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
else else
{ {
d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); d.GeomSetCategoryBits(prm.prim_geom, (uint)m_collisionCategories);
d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); d.GeomSetCollideBits(prm.prim_geom, (uint)m_collisionFlags);
} }
d.GeomDisable(prm.prim_geom);
} }
prm.m_delaySelect = false; prm.m_delaySelect = false;
} }
@ -2748,13 +2713,23 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
d.GeomSetCategoryBits(prim_geom, 0); d.GeomSetCategoryBits(prim_geom, 0);
d.GeomSetCollideBits(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 else
{ {
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 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; m_delaySelect = false;
@ -2769,75 +2744,10 @@ namespace OpenSim.Region.Physics.OdePlugin
if (!childPrim && Body != IntPtr.Zero && !m_disabled) if (!childPrim && Body != IntPtr.Zero && !m_disabled)
d.BodyEnable(Body); d.BodyEnable(Body);
if (m_isphantom && !m_isVolumeDetect) UpdateCollisionCatFlags();
{ ApplyCollisionCatFlags();
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);
}
m_delaySelect = false; m_delaySelect = false;
m_softcolide = true;
} }
resetCollisionAccounting(); resetCollisionAccounting();
@ -2890,7 +2800,6 @@ namespace OpenSim.Region.Physics.OdePlugin
if (givefakepos < 0) if (givefakepos < 0)
givefakepos = 0; givefakepos = 0;
// changeSelectedStatus(); // changeSelectedStatus();
m_softcolide = true;
resetCollisionAccounting(); resetCollisionAccounting();
} }
@ -2951,7 +2860,6 @@ namespace OpenSim.Region.Physics.OdePlugin
givefakeori--; givefakeori--;
if (givefakeori < 0) if (givefakeori < 0)
givefakeori = 0; givefakeori = 0;
m_softcolide = true;
resetCollisionAccounting(); resetCollisionAccounting();
} }
@ -3022,7 +2930,6 @@ namespace OpenSim.Region.Physics.OdePlugin
if (givefakeori < 0) if (givefakeori < 0)
givefakeori = 0; givefakeori = 0;
m_softcolide = true;
resetCollisionAccounting(); resetCollisionAccounting();
} }
@ -3111,6 +3018,8 @@ namespace OpenSim.Region.Physics.OdePlugin
d.GeomSetQuaternion(prim_geom, ref myrot); d.GeomSetQuaternion(prim_geom, ref myrot);
} }
if (m_isphysical)
{
if (chp) if (chp)
{ {
if (parent != null) if (parent != null)
@ -3120,8 +3029,14 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
else else
MakeBody(); MakeBody();
}
else
{
UpdateCollisionCatFlags();
ApplyCollisionCatFlags();
}
m_softcolide = true;
resetCollisionAccounting(); resetCollisionAccounting();
} }
@ -3142,18 +3057,8 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
m_collidesWater = newval; m_collidesWater = newval;
if (prim_geom != IntPtr.Zero && !m_isphantom) UpdateCollisionCatFlags();
{ ApplyCollisionCatFlags();
if (m_collidesWater)
{
m_collisionFlags |= CollisionCategories.Water;
}
else
{
m_collisionFlags &= ~CollisionCategories.Water;
}
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
}
} }
private void changeSetTorque(Vector3 newtorque) private void changeSetTorque(Vector3 newtorque)
@ -3240,6 +3145,8 @@ namespace OpenSim.Region.Physics.OdePlugin
private void changeVolumedetetion(bool newVolDtc) private void changeVolumedetetion(bool newVolDtc)
{ {
m_isVolumeDetect = newVolDtc; m_isVolumeDetect = newVolDtc;
UpdateCollisionCatFlags();
ApplyCollisionCatFlags();
} }
protected void changeBuilding(bool newbuilding) protected void changeBuilding(bool newbuilding)
@ -3320,11 +3227,13 @@ namespace OpenSim.Region.Physics.OdePlugin
public void Move() public void Move()
{ {
if (!childPrim && m_isphysical && Body != IntPtr.Zero && 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) // !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
if (d.BodyIsEnabled(Body))
{
float timestep = _parent_scene.ODE_STEPSIZE; float timestep = _parent_scene.ODE_STEPSIZE;
// check outside region // check outside region
@ -3369,7 +3278,7 @@ namespace OpenSim.Region.Physics.OdePlugin
_position.X = Util.Clip(lpos.X, -2f, -0.1f); _position.X = Util.Clip(lpos.X, -2f, -0.1f);
m_outbounds = true; m_outbounds = true;
} }
else if(lpos.X > _parent_scene.WorldExtents.X) 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); _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
m_outbounds = true; m_outbounds = true;
@ -3379,13 +3288,13 @@ namespace OpenSim.Region.Physics.OdePlugin
_position.Y = Util.Clip(lpos.Y, -2f, -0.1f); _position.Y = Util.Clip(lpos.Y, -2f, -0.1f);
m_outbounds = true; m_outbounds = true;
} }
else if(lpos.Y > _parent_scene.WorldExtents.Y) 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); _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
m_outbounds = true; m_outbounds = true;
} }
if(m_outbounds) if (m_outbounds)
{ {
m_lastposition = _position; m_lastposition = _position;
m_lastorientation = _orientation; m_lastorientation = _orientation;
@ -3408,18 +3317,20 @@ namespace OpenSim.Region.Physics.OdePlugin
return; return;
} }
if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
{
// 'VEHICLES' are dealt with in ODEDynamics.cs
m_vehicle.Step();
return;
}
else
{
float fx = 0; float fx = 0;
float fy = 0; float fy = 0;
float fz = 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; float m_mass = _mass;
// fz = 0f; // fz = 0f;
@ -3604,6 +3515,20 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
} }
else // body disabled
{
// let vehicles sleep
if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
return;
if (++bodydisablecontrol < 20)
return;
bodydisablecontrol = 0;
d.BodyEnable(Body);
return;
}
}
else else
{ // is not physical, or is not a body or is selected { // is not physical, or is not a body or is selected
// _zeroPosition = d.BodyGetPosition(Body); // _zeroPosition = d.BodyGetPosition(Body);

View File

@ -30,10 +30,11 @@ using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using OpenMetaverse; using OpenSim.Framework;
using OpenSim.Region.Physics.Manager; using OpenSim.Region.Physics.Manager;
using OdeAPI; using OdeAPI;
using log4net; using log4net;
using OpenMetaverse;
namespace OpenSim.Region.Physics.OdePlugin namespace OpenSim.Region.Physics.OdePlugin
{ {
@ -54,9 +55,11 @@ namespace OpenSim.Region.Physics.OdePlugin
/// </summary> /// </summary>
private OdeScene m_scene; 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 ColisionContactGeomsPerTest = 5;
private const int DefaultMaxCount = 25;
private const int MaxTimePerCallMS = 30;
/// <summary> /// <summary>
/// ODE near callback delegate /// ODE near callback delegate
@ -64,19 +67,22 @@ namespace OpenSim.Region.Physics.OdePlugin
private d.NearCallback nearCallback; private d.NearCallback nearCallback;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private List<ContactResult> m_contactResults = new List<ContactResult>(); private List<ContactResult> m_contactResults = new List<ContactResult>();
private RayFilterFlags CurrentRayFilter;
private int CurrentMaxCount;
public ODERayCastRequestManager(OdeScene pScene) public ODERayCastRequestManager(OdeScene pScene)
{ {
m_scene = pScene; m_scene = pScene;
nearCallback = near; nearCallback = near;
ray = d.CreateRay(IntPtr.Zero, 1.0f); ray = d.CreateRay(IntPtr.Zero, 1.0f);
d.GeomSetCategoryBits(ray,0);
} }
/// <summary> /// <summary>
/// Queues a raycast /// Queues request for a raycast to all world
/// </summary> /// </summary>
/// <param name="position">Origin of Ray</param> /// <param name="position">Origin of Ray</param>
/// <param name="direction">Ray normal</param> /// <param name="direction">Ray direction</param>
/// <param name="length">Ray length</param> /// <param name="length">Ray length</param>
/// <param name="retMethod">Return method to send the results</param> /// <param name="retMethod">Return method to send the results</param>
public void QueueRequest(Vector3 position, Vector3 direction, float length, RayCallback retMethod) public void QueueRequest(Vector3 position, Vector3 direction, float length, RayCallback retMethod)
@ -84,14 +90,22 @@ namespace OpenSim.Region.Physics.OdePlugin
ODERayRequest req = new ODERayRequest(); ODERayRequest req = new ODERayRequest();
req.geom = IntPtr.Zero; req.geom = IntPtr.Zero;
req.callbackMethod = retMethod; req.callbackMethod = retMethod;
req.Count = 0; req.Count = DefaultMaxCount;
req.length = length; req.length = length;
req.Normal = direction; req.Normal = direction;
req.Origin = position; req.Origin = position;
req.filter = RayFilterFlags.AllPrims;
m_PendingRequests.Enqueue(req); m_PendingRequests.Enqueue(req);
} }
/// <summary>
/// Queues request for a raycast to particular part
/// </summary>
/// <param name="position">Origin of Ray</param>
/// <param name="direction">Ray direction</param>
/// <param name="length">Ray length</param>
/// <param name="retMethod">Return method to send the results</param>
public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RayCallback retMethod) public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RayCallback retMethod)
{ {
ODERayRequest req = new ODERayRequest(); ODERayRequest req = new ODERayRequest();
@ -100,7 +114,8 @@ namespace OpenSim.Region.Physics.OdePlugin
req.length = length; req.length = length;
req.Normal = direction; req.Normal = direction;
req.Origin = position; req.Origin = position;
req.Count = 0; req.Count = DefaultMaxCount;
req.filter = RayFilterFlags.AllPrims;
m_PendingRequests.Enqueue(req); m_PendingRequests.Enqueue(req);
} }
@ -110,10 +125,11 @@ namespace OpenSim.Region.Physics.OdePlugin
ODERayRequest req = new ODERayRequest(); ODERayRequest req = new ODERayRequest();
req.geom = IntPtr.Zero; req.geom = IntPtr.Zero;
req.callbackMethod = retMethod; req.callbackMethod = retMethod;
req.Count = 0; req.Count = DefaultMaxCount;
req.length = length; req.length = length;
req.Normal = direction; req.Normal = direction;
req.Origin = position; req.Origin = position;
req.filter = RayFilterFlags.AllPrims;
m_PendingRequests.Enqueue(req); m_PendingRequests.Enqueue(req);
} }
@ -126,7 +142,8 @@ namespace OpenSim.Region.Physics.OdePlugin
req.length = length; req.length = length;
req.Normal = direction; req.Normal = direction;
req.Origin = position; req.Origin = position;
req.Count = 0; req.Count = DefaultMaxCount;
req.filter = RayFilterFlags.AllPrims;
m_PendingRequests.Enqueue(req); m_PendingRequests.Enqueue(req);
} }
@ -148,6 +165,22 @@ namespace OpenSim.Region.Physics.OdePlugin
req.Normal = direction; req.Normal = direction;
req.Origin = position; req.Origin = position;
req.Count = count; 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); m_PendingRequests.Enqueue(req);
} }
@ -161,6 +194,7 @@ namespace OpenSim.Region.Physics.OdePlugin
req.Normal = direction; req.Normal = direction;
req.Origin = position; req.Origin = position;
req.Count = count; req.Count = count;
req.filter = RayFilterFlags.AllPrims;
m_PendingRequests.Enqueue(req); m_PendingRequests.Enqueue(req);
} }
@ -174,6 +208,7 @@ namespace OpenSim.Region.Physics.OdePlugin
req.Normal = direction; req.Normal = direction;
req.Origin = position; req.Origin = position;
req.Count = count; req.Count = count;
req.filter = RayFilterFlags.AllPrims;
m_PendingRequests.Enqueue(req); m_PendingRequests.Enqueue(req);
} }
@ -187,6 +222,7 @@ namespace OpenSim.Region.Physics.OdePlugin
req.Normal = direction; req.Normal = direction;
req.Origin = position; req.Origin = position;
req.Count = count; req.Count = count;
req.filter = RayFilterFlags.AllPrims;
m_PendingRequests.Enqueue(req); m_PendingRequests.Enqueue(req);
} }
@ -197,63 +233,104 @@ namespace OpenSim.Region.Physics.OdePlugin
/// <returns>Time in MS the raycasts took to process.</returns> /// <returns>Time in MS the raycasts took to process.</returns>
public int ProcessQueuedRequests() public int ProcessQueuedRequests()
{ {
int time = System.Environment.TickCount;
if (m_PendingRequests.Count <= 0) if (m_PendingRequests.Count <= 0)
return 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(); m_PendingRequests.Clear();
return 0; return 0;
} }
int time = Util.EnvironmentTickCount();
ODERayRequest req; 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.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) 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); doSpaceRay(req);
}
else else
{
// if we select a geom don't use filters
d.GeomSetCollideBits(ray, (uint)CollisionCategories.All);
doGeomRay(req); doGeomRay(req);
if(--i < 0) }
}
if (Util.EnvironmentTickCountSubtract(time) > MaxTimePerCallMS)
break; break;
} }
lock (m_contactResults) lock (m_contactResults)
m_contactResults.Clear(); m_contactResults.Clear();
return System.Environment.TickCount - time; return Util.EnvironmentTickCountSubtract(time);
} }
/// <summary> /// <summary>
/// Method that actually initiates the raycast with full top space /// Method that actually initiates the raycast with spaces
/// </summary> /// </summary>
/// <param name="req"></param> /// <param name="req"></param>
///
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) private void doSpaceRay(ODERayRequest req)
{ {
// Create the ray // Collide tests
// IntPtr ray = d.CreateRay(m_scene.TopSpace, req.length); if ((CurrentRayFilter & FilterActiveSpace) != 0)
d.GeomRaySetLength(ray, req.length); d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
// Collide test
d.SpaceCollide2(m_scene.TopSpace, ray, IntPtr.Zero, nearCallback);
// Remove Ray
// d.GeomDestroy(ray);
if (req.callbackMethod == null)
return;
if (req.callbackMethod is RaycastCallback) if (req.callbackMethod is RaycastCallback)
{ {
// Define default results // Define default results
bool hitYN = false; bool hitYN = false;
uint hitConsumerID = 0; uint hitConsumerID = 0;
float distance = 999999999999f; float distance = float.MaxValue;
Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f); Vector3 closestcontact = Vector3.Zero;
Vector3 snormal = Vector3.Zero; Vector3 snormal = Vector3.Zero;
// Find closest contact and object. // Find closest contact and object.
@ -261,26 +338,31 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
foreach (ContactResult cResult in m_contactResults) 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; closestcontact = cResult.Pos;
hitConsumerID = cResult.ConsumerID; hitConsumerID = cResult.ConsumerID;
distance = cResult.Depth; distance = cResult.Depth;
hitYN = true;
snormal = cResult.Normal; snormal = cResult.Normal;
} }
} }
m_contactResults.Clear(); m_contactResults.Clear();
} }
if (distance > 0 && distance < float.MaxValue)
hitYN = true;
((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal); ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
} }
else else
{ {
((RayCallback)req.callbackMethod)(m_contactResults); List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
lock (m_PendingRequests) lock (m_PendingRequests)
{
cresult.AddRange(m_contactResults);
m_contactResults.Clear(); m_contactResults.Clear();
} }
((RayCallback)req.callbackMethod)(cresult);
}
} }
/// <summary> /// <summary>
@ -289,27 +371,16 @@ namespace OpenSim.Region.Physics.OdePlugin
/// <param name="req"></param> /// <param name="req"></param>
private void doGeomRay(ODERayRequest req) 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 // Collide test
d.SpaceCollide2(req.geom, ray, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test d.SpaceCollide2(ray, req.geom, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test
// Remove Ray
// d.GeomDestroy(ray);
if (req.callbackMethod == null)
return;
if (req.callbackMethod is RaycastCallback) if (req.callbackMethod is RaycastCallback)
{ {
// Define default results // Define default results
bool hitYN = false; bool hitYN = false;
uint hitConsumerID = 0; uint hitConsumerID = 0;
float distance = 999999999999f; float distance = float.MaxValue;
Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f); Vector3 closestcontact = Vector3.Zero;
Vector3 snormal = Vector3.Zero; Vector3 snormal = Vector3.Zero;
// Find closest contact and object. // Find closest contact and object.
@ -317,26 +388,32 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
foreach (ContactResult cResult in m_contactResults) 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; closestcontact = cResult.Pos;
hitConsumerID = cResult.ConsumerID; hitConsumerID = cResult.ConsumerID;
distance = cResult.Depth; distance = cResult.Depth;
hitYN = true;
snormal = cResult.Normal; snormal = cResult.Normal;
} }
} }
m_contactResults.Clear(); m_contactResults.Clear();
} }
if (distance > 0 && distance < float.MaxValue)
hitYN = true;
((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal); ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
} }
else else
{ {
((RayCallback)req.callbackMethod)(m_contactResults); List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
lock (m_PendingRequests) lock (m_PendingRequests)
{
cresult.AddRange(m_contactResults);
m_contactResults.Clear(); m_contactResults.Clear();
} }
((RayCallback)req.callbackMethod)(cresult);
}
} }
private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom) private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
@ -350,20 +427,16 @@ namespace OpenSim.Region.Physics.OdePlugin
return true; 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) private void near(IntPtr space, IntPtr g1, IntPtr g2)
{ {
//Don't test against heightfield Geom, or you'll be sorry! if (g2 == IntPtr.Zero || g1 == g2)
// Exclude heightfield geom
if (g1 == IntPtr.Zero || g1 == g2)
return; return;
if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass) if (m_contactResults.Count >= CurrentMaxCount)
return; return;
// Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms. if (d.GeomIsSpace(g2))
if (d.GeomIsSpace(g1))
{ {
try try
{ {
@ -381,10 +454,6 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
count = d.CollidePtr(g1, g2, ColisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); 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) catch (Exception e)
{ {
m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message); m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message);
@ -394,32 +463,117 @@ namespace OpenSim.Region.Physics.OdePlugin
if (count == 0) if (count == 0)
return; return;
PhysicsActor p1 = null; uint ID = 0;
PhysicsActor p2 = null;
if (g1 != IntPtr.Zero) m_scene.actor_name_map.TryGetValue(g2, out p2);
m_scene.actor_name_map.TryGetValue(g1, out p1);
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(); d.ContactGeom curcontact = new d.ContactGeom();
// Loop over contacts, build results.
// closestHit for now only works for meshs, so must do it for others
if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0)
{
// Loop all contacts, build results.
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
if (!GetCurContactGeom(i, ref curcontact)) if (!GetCurContactGeom(i, ref curcontact))
break; break;
if (p1 != null) {
if (p1 is OdePrim)
{
ContactResult collisionresult = new ContactResult();
collisionresult.ConsumerID = ((OdePrim)p1).m_localID; ContactResult collisionresult = new ContactResult();
collisionresult.ConsumerID = ID;
collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z); collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z);
collisionresult.Depth = curcontact.depth; collisionresult.Depth = curcontact.depth;
collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y, collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y,
curcontact.normal.Z); curcontact.normal.Z);
lock (m_contactResults) lock (m_contactResults)
{
m_contactResults.Add(collisionresult); 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)
{
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);
}
}
if (collisionresult.Depth != float.MaxValue)
{
lock (m_contactResults)
m_contactResults.Add(collisionresult);
}
}
} }
/// <summary> /// <summary>
@ -428,6 +582,11 @@ namespace OpenSim.Region.Physics.OdePlugin
internal void Dispose() internal void Dispose()
{ {
m_scene = null; 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 int Count;
public float length; public float length;
public object callbackMethod; public object callbackMethod;
public RayFilterFlags filter;
} }
} }

View File

@ -889,13 +889,13 @@ namespace OdeAPI
public static extern IntPtr GeomGetBody(IntPtr geom); public static extern IntPtr GeomGetBody(IntPtr geom);
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetCategoryBits"), SuppressUnmanagedCodeSecurity] [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] [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetClassData"), SuppressUnmanagedCodeSecurity]
public static extern IntPtr GeomGetClassData(IntPtr geom); public static extern IntPtr GeomGetClassData(IntPtr geom);
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetCollideBits"), SuppressUnmanagedCodeSecurity] [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] [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetClass"), SuppressUnmanagedCodeSecurity]
public static extern GeomClassID GeomGetClass(IntPtr geom); public static extern GeomClassID GeomGetClass(IntPtr geom);
@ -1086,10 +1086,10 @@ namespace OdeAPI
public static extern void GeomSetBody(IntPtr geom, IntPtr body); public static extern void GeomSetBody(IntPtr geom, IntPtr body);
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetCategoryBits"), SuppressUnmanagedCodeSecurity] [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] [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] [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); public static extern IntPtr GeomSetConvex(IntPtr geom, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);

View File

@ -60,19 +60,31 @@ namespace OpenSim.Region.Physics.OdePlugin
public int lastframe; 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] [Flags]
public enum CollisionCategories : int public enum CollisionCategories : uint
{ {
Disabled = 0, Disabled = 0,
Geom = 0x00000001, //by 'things' types
Body = 0x00000002, Space = 0x01,
Space = 0x00000004, Geom = 0x02, // aka prim/part
Character = 0x00000008, Character = 0x04,
Land = 0x00000010, Land = 0x08,
Water = 0x00000020, Water = 0x010,
Wind = 0x00000040,
Sensor = 0x00000080, // by state
Selected = 0x00000100 Phantom = 0x01000,
VolumeDtc = 0x02000,
Selected = 0x04000,
NoShape = 0x08000,
All = 0xffffffff
} }
/// <summary> /// <summary>
@ -116,6 +128,7 @@ namespace OpenSim.Region.Physics.OdePlugin
Acceleration, Acceleration,
Force, Force,
Torque, Torque,
Momentum,
AddForce, AddForce,
AddAngForce, AddAngForce,
@ -186,7 +199,9 @@ namespace OpenSim.Region.Physics.OdePlugin
private float waterlevel = 0f; private float waterlevel = 0f;
private int framecount = 0; 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 avPIDD = 2200f; // make it visible
public float avPIDP = 900f; // 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 geomCrossingFailuresBeforeOutofbounds = 6;
public int bodyFramesAutoDisable = 20; public int bodyFramesAutoDisable = 5;
private float[] _watermap;
private d.NearCallback nearCallback; private d.NearCallback nearCallback;
@ -350,7 +364,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// i must RtC#FM // 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(ActiveSpace, -2, 8);
d.HashSpaceSetLevels(StaticSpace, -2, 8); d.HashSpaceSetLevels(StaticSpace, -2, 8);
@ -358,13 +372,27 @@ namespace OpenSim.Region.Physics.OdePlugin
d.SpaceSetSublevel(ActiveSpace, 1); d.SpaceSetSublevel(ActiveSpace, 1);
d.SpaceSetSublevel(StaticSpace, 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.JointGroupCreate(0);
//contactgroup //contactgroup
d.WorldSetAutoDisableFlag(world, false); d.WorldSetAutoDisableFlag(world, false);
} }
_watermap = new float[258 * 258];
} }
// Initialize the mesh plugin // Initialize the mesh plugin
@ -374,15 +402,18 @@ namespace OpenSim.Region.Physics.OdePlugin
// checkThread(); // checkThread();
mesher = meshmerizer; mesher = meshmerizer;
m_config = config; m_config = config;
/*
string ode_config = d.GetConfiguration("ODE"); string ode_config = d.GetConfiguration("ODE");
if (ode_config != null && ode_config != "")
{
m_log.WarnFormat("ODE configuration: {0}", ode_config); m_log.WarnFormat("ODE configuration: {0}", ode_config);
if (ode_config.Contains("ODE_Ubit")) if (ode_config.Contains("ODE_Ubit"))
{ {
OdeUbitLib = true; OdeUbitLib = true;
} }
}
*/
/* /*
if (region != null) if (region != null)
{ {
@ -518,6 +549,15 @@ namespace OpenSim.Region.Physics.OdePlugin
waitForSpaceUnlock(newspace); waitForSpaceUnlock(newspace);
d.SpaceSetSublevel(newspace, 2); d.SpaceSetSublevel(newspace, 2);
d.HashSpaceSetLevels(newspace, -2, 8); 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; staticPrimspace[i, j] = newspace;
} }
// let this now be real maximum values // let this now be real maximum values
@ -1745,8 +1785,6 @@ namespace OpenSim.Region.Physics.OdePlugin
m_rayCastManager.ProcessQueuedRequests(); m_rayCastManager.ProcessQueuedRequests();
statray += Util.EnvironmentTickCountSubtract(statstart); statray += Util.EnvironmentTickCountSubtract(statstart);
collision_optimized(); collision_optimized();
statcol += Util.EnvironmentTickCountSubtract(statstart); statcol += Util.EnvironmentTickCountSubtract(statstart);
@ -2125,14 +2163,14 @@ namespace OpenSim.Region.Physics.OdePlugin
RegionTerrain.Remove(pOffset); RegionTerrain.Remove(pOffset);
if (GroundGeom != IntPtr.Zero) if (GroundGeom != IntPtr.Zero)
{ {
d.GeomDestroy(GroundGeom);
if (TerrainHeightFieldHeights.ContainsKey(GroundGeom)) if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
{ {
TerrainHeightFieldHeightsHandlers[GroundGeom].Free(); TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
TerrainHeightFieldHeightsHandlers.Remove(GroundGeom); TerrainHeightFieldHeightsHandlers.Remove(GroundGeom);
TerrainHeightFieldHeights.Remove(GroundGeom); TerrainHeightFieldHeights.Remove(GroundGeom);
} }
d.SpaceRemove(StaticSpace, GroundGeom);
d.GeomDestroy(GroundGeom);
} }
} }
IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
@ -2147,8 +2185,8 @@ namespace OpenSim.Region.Physics.OdePlugin
GroundGeom = d.CreateHeightfield(StaticSpace, HeightmapData, 1); GroundGeom = d.CreateHeightfield(StaticSpace, HeightmapData, 1);
if (GroundGeom != IntPtr.Zero) if (GroundGeom != IntPtr.Zero)
{ {
d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land)); d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space)); d.GeomSetCollideBits(GroundGeom, 0);
} }
geom_name_map[GroundGeom] = "Terrain"; geom_name_map[GroundGeom] = "Terrain";
@ -2236,14 +2274,15 @@ namespace OpenSim.Region.Physics.OdePlugin
RegionTerrain.Remove(pOffset); RegionTerrain.Remove(pOffset);
if (GroundGeom != IntPtr.Zero) if (GroundGeom != IntPtr.Zero)
{ {
d.GeomDestroy(GroundGeom);
if (TerrainHeightFieldHeights.ContainsKey(GroundGeom)) if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
{ {
if (TerrainHeightFieldHeightsHandlers[GroundGeom].IsAllocated)
TerrainHeightFieldHeightsHandlers[GroundGeom].Free(); TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
TerrainHeightFieldHeightsHandlers.Remove(GroundGeom); TerrainHeightFieldHeightsHandlers.Remove(GroundGeom);
TerrainHeightFieldHeights.Remove(GroundGeom); TerrainHeightFieldHeights.Remove(GroundGeom);
} }
d.SpaceRemove(StaticSpace, GroundGeom);
d.GeomDestroy(GroundGeom);
} }
} }
IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
@ -2263,8 +2302,8 @@ namespace OpenSim.Region.Physics.OdePlugin
GroundGeom = d.CreateUbitTerrain(StaticSpace, HeightmapData, 1); GroundGeom = d.CreateUbitTerrain(StaticSpace, HeightmapData, 1);
if (GroundGeom != IntPtr.Zero) if (GroundGeom != IntPtr.Zero)
{ {
d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land)); d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space)); d.GeomSetCollideBits(GroundGeom, 0);
} }
geom_name_map[GroundGeom] = "Terrain"; geom_name_map[GroundGeom] = "Terrain";
@ -2359,39 +2398,59 @@ namespace OpenSim.Region.Physics.OdePlugin
public void randomizeWater(float baseheight) public void randomizeWater(float baseheight)
{ {
const uint heightmapWidth = m_regionWidth + 2; const uint heightmapWidth = Constants.RegionSize + 2;
const uint heightmapHeight = m_regionHeight + 2; const uint heightmapHeight = Constants.RegionSize + 2;
const uint heightmapWidthSamples = m_regionWidth + 2; const uint heightmapWidthSamples = heightmapWidth + 1;
const uint heightmapHeightSamples = m_regionHeight + 2; const uint heightmapHeightSamples = heightmapHeight + 1;
const float scale = 1.0f; const float scale = 1.0f;
const float offset = 0.0f; const float offset = 0.0f;
const float thickness = 2.9f;
const int wrap = 0; 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) lock (OdeLock)
{ {
if (WaterGeom != IntPtr.Zero) 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, (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale,
offset, thickness, wrap); offset, thickness, wrap);
d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight); d.GeomHeightfieldDataSetBounds(WaterHeightmapData, minheigh, maxheigh);
WaterGeom = d.CreateHeightfield(StaticSpace, HeightmapData, 1); WaterGeom = d.CreateHeightfield(StaticSpace, WaterHeightmapData, 1);
if (WaterGeom != IntPtr.Zero) if (WaterGeom != IntPtr.Zero)
{ {
d.GeomSetCategoryBits(WaterGeom, (int)(CollisionCategories.Water)); d.GeomSetCategoryBits(WaterGeom, (uint)(CollisionCategories.Water));
d.GeomSetCollideBits(WaterGeom, (int)(CollisionCategories.Space)); d.GeomSetCollideBits(WaterGeom, 0);
}
geom_name_map[WaterGeom] = "Water"; geom_name_map[WaterGeom] = "Water";
d.Matrix3 R = new d.Matrix3(); d.Matrix3 R = new d.Matrix3();
@ -2406,10 +2465,9 @@ namespace OpenSim.Region.Physics.OdePlugin
d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
d.GeomSetRotation(WaterGeom, ref R); d.GeomSetRotation(WaterGeom, ref R);
d.GeomSetPosition(WaterGeom, 128, 128, 0); d.GeomSetPosition(WaterGeom, (float)Constants.RegionSize * 0.5f, (float)Constants.RegionSize * 0.5f, 0);
}
} }
} }
public override void Dispose() 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) if (ContactgeomsArray != IntPtr.Zero)
Marshal.FreeHGlobal(ContactgeomsArray); Marshal.FreeHGlobal(ContactgeomsArray);
if (GlobalContactsArray != IntPtr.Zero) if (GlobalContactsArray != IntPtr.Zero)
Marshal.FreeHGlobal(GlobalContactsArray); Marshal.FreeHGlobal(GlobalContactsArray);
d.WorldDestroy(world); d.WorldDestroy(world);
//d.CloseODE(); //d.CloseODE();
} }
@ -2502,6 +2583,35 @@ namespace OpenSim.Region.Physics.OdePlugin
return new List<ContactResult>(ourResults); return new List<ContactResult>(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<ContactResult> ourresults = new List<ContactResult>();
RayCallback retMethod = delegate(List<ContactResult> 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) public override void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
{ {
if (retMethod != null && actor !=null) if (retMethod != null && actor !=null)

View File

@ -9980,7 +9980,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// return total object mass // return total object mass
SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId); SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
if (obj != null) if (obj != null)
return (double)obj.GetMass(); return obj.GetMass();
// the object is null so the key is for an avatar // the object is null so the key is for an avatar
ScenePresence avatar = World.GetScenePresence(key); ScenePresence avatar = World.GetScenePresence(key);
@ -9990,7 +9990,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// child agents have a mass of 1.0 // child agents have a mass of 1.0
return 1; return 1;
else else
return (double)avatar.PhysicsActor.Mass; return avatar.GetMass();
} }
catch (KeyNotFoundException) catch (KeyNotFoundException)
{ {
@ -11834,6 +11834,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return contacts[0]; 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) public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
{ {
@ -11874,6 +11895,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
if (World.SuportsRayCastFiltered())
{
if (dist == 0)
return list;
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<ContactResult>)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
{
if (checkTerrain) if (checkTerrain)
{ {
ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
@ -11888,24 +11965,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
results.Add(r); results.Add(r);
} }
if (checkPhysical || checkNonPhysical) if (checkPhysical || checkNonPhysical || detectPhantom)
{ {
ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
foreach (ContactResult r in objectHits) foreach (ContactResult r in objectHits)
results.Add(r); results.Add(r);
} }
}
results.Sort(delegate(ContactResult a, ContactResult b) results.Sort(delegate(ContactResult a, ContactResult b)
{ {
return (int)(a.Depth - b.Depth); return a.Depth.CompareTo(b.Depth);
}); });
int values = 0; int values = 0;
SceneObjectGroup thisgrp = m_host.ParentGroup;
foreach (ContactResult result in results) foreach (ContactResult result in results)
{ {
if (result.Depth > dist) if (result.Depth > dist)
continue; continue;
// physics ray can return colisions with host prim
if (m_host.LocalId == result.ConsumerID)
continue;
UUID itemID = UUID.Zero; UUID itemID = UUID.Zero;
int linkNum = 0; int linkNum = 0;
@ -11913,6 +11997,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// It's a prim! // It's a prim!
if (part != null) 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) if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
itemID = part.ParentGroup.UUID; itemID = part.ParentGroup.UUID;
else else
@ -11934,14 +12022,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
list.Add(new LSL_Integer(linkNum)); list.Add(new LSL_Integer(linkNum));
if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z)); list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
values++; values++;
count--; if (values >= count)
if (count == 0)
break; break;
} }