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);
}
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>
/// 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)
{
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);
}
}
}

View File

@ -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;
}
}
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 IsVolumeDtc
{
get { return false; }
set { return; }
}
public virtual byte PhysicsShapeType { get; 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 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>
/// Contact result from a raycast.
/// </summary>
@ -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<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, int Count, RayCallback retMethod) { }
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)
{
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;
}

View File

@ -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;
}

View File

@ -115,10 +115,9 @@ 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);
public IntPtr Body = 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);

View File

@ -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);
}
if (m_isSelected)
m_collisionFlags = CollisionCategories.Selected;
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);
}
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,11 +2554,12 @@ namespace OpenSim.Region.Physics.OdePlugin
d.GeomSetQuaternion(prim_geom, ref myrot);
if (!m_isphysical)
SetInStaticSpace(this);
}
if (m_isphysical && Body == IntPtr.Zero)
{
SetInStaticSpace(this);
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,6 +3018,8 @@ namespace OpenSim.Region.Physics.OdePlugin
d.GeomSetQuaternion(prim_geom, ref myrot);
}
if (m_isphysical)
{
if (chp)
{
if (parent != null)
@ -3120,8 +3029,14 @@ namespace OpenSim.Region.Physics.OdePlugin
}
else
MakeBody();
}
else
{
UpdateCollisionCatFlags();
ApplyCollisionCatFlags();
}
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,11 +3227,13 @@ 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))
{
float timestep = _parent_scene.ODE_STEPSIZE;
// check outside region
@ -3408,18 +3317,20 @@ namespace OpenSim.Region.Physics.OdePlugin
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 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;
@ -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
{ // is not physical, or is not a body or is selected
// _zeroPosition = d.BodyGetPosition(Body);

View File

@ -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
/// </summary>
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;
/// <summary>
/// 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<ContactResult> m_contactResults = new List<ContactResult>();
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);
}
/// <summary>
/// Queues a raycast
/// Queues request for a raycast to all world
/// </summary>
/// <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="retMethod">Return method to send the results</param>
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);
}
/// <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)
{
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
/// <returns>Time in MS the raycasts took to process.</returns>
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;
}
ODERayRequest req;
int time = Util.EnvironmentTickCount();
int i = 50; // arbitary limit of processed tests per frame
ODERayRequest req;
int closestHit;
int backfacecull;
CollisionCategories catflags;
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)
{
// 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(--i < 0)
}
}
if (Util.EnvironmentTickCountSubtract(time) > MaxTimePerCallMS)
break;
}
lock (m_contactResults)
m_contactResults.Clear();
return System.Environment.TickCount - time;
return Util.EnvironmentTickCountSubtract(time);
}
/// <summary>
/// Method that actually initiates the raycast with full top space
/// Method that actually initiates the raycast with spaces
/// </summary>
/// <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)
{
// 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,26 +338,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<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
lock (m_PendingRequests)
{
cresult.AddRange(m_contactResults);
m_contactResults.Clear();
}
((RayCallback)req.callbackMethod)(cresult);
}
}
/// <summary>
@ -289,27 +371,16 @@ namespace OpenSim.Region.Physics.OdePlugin
/// <param name="req"></param>
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,26 +388,32 @@ 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<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
lock (m_PendingRequests)
{
cresult.AddRange(m_contactResults);
m_contactResults.Clear();
}
((RayCallback)req.callbackMethod)(cresult);
}
}
private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
@ -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,32 +463,117 @@ 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.
// 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++)
{
if (!GetCurContactGeom(i, ref curcontact))
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.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)
{
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>
@ -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;
}
}

View File

@ -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);

View File

@ -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
}
/// <summary>
@ -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");
if (ode_config != null && ode_config != "")
{
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))
{
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,39 +2398,59 @@ 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();
@ -2406,10 +2465,9 @@ namespace OpenSim.Region.Physics.OdePlugin
d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
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()
@ -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<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)
{
if (retMethod != null && actor !=null)

View File

@ -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,6 +11895,62 @@ 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 (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)
{
ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
@ -11888,24 +11965,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
results.Add(r);
}
if (checkPhysical || checkNonPhysical)
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
@ -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)
if (values >= count)
break;
}