Merge branch 'master' of ssh://melanie@3dhosting.de/var/git/careminster into careminster
commit
ab1a3688e2
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -140,6 +140,10 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
public int m_eventsubscription = 0;
|
||||
private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
|
||||
|
||||
private Vector3 m_taintMomentum = Vector3.Zero;
|
||||
private bool m_haveTaintMomentum = false;
|
||||
|
||||
|
||||
// unique UUID of this character object
|
||||
public UUID m_uuid;
|
||||
public bool bad = false;
|
||||
|
@ -800,8 +804,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
{
|
||||
if (value.IsFinite())
|
||||
{
|
||||
m_pidControllerActive = true;
|
||||
_target_velocity = value;
|
||||
m_pidControllerActive = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -911,6 +915,14 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
|
||||
public override void SetMomentum(Vector3 momentum)
|
||||
{
|
||||
if (momentum.IsFinite())
|
||||
{
|
||||
m_taintMomentum = momentum;
|
||||
m_haveTaintMomentum = true;
|
||||
_parent_scene.AddPhysicsActorTaint(this);
|
||||
}
|
||||
else
|
||||
m_log.Warn("[PHYSICS] !isFinite momentum");
|
||||
}
|
||||
|
||||
|
||||
|
@ -1110,9 +1122,18 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
}
|
||||
// end add Kitto Flora
|
||||
}
|
||||
|
||||
if (vel.X * vel.X + vel.Y * vel.Y + vel.Z * vel.Z > 2500.0f) // 50ms apply breaks
|
||||
{
|
||||
float breakfactor = 0.16f * m_mass; // will give aprox 60m/s terminal velocity at free fall
|
||||
vec.X -= breakfactor * vel.X;
|
||||
vec.Y -= breakfactor * vel.Y;
|
||||
vec.Z -= breakfactor * vel.Z;
|
||||
}
|
||||
|
||||
if (vec.IsFinite())
|
||||
{
|
||||
if (!vec.ApproxEquals(Vector3.Zero, 0.02f)) // 0.01 allows 0.002 !!
|
||||
if (vec.LengthSquared() > 0.0004f) // 0.01 allows 0.002 !!
|
||||
{
|
||||
//Console.WriteLine("DF 2"); // ##
|
||||
|
||||
|
@ -1327,7 +1348,6 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
{
|
||||
lock (m_syncRoot)
|
||||
{
|
||||
|
||||
if (m_tainted_isPhysical != m_isPhysical)
|
||||
{
|
||||
if (m_tainted_isPhysical)
|
||||
|
@ -1369,9 +1389,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
{
|
||||
d.GeomDestroy(Shell);
|
||||
}
|
||||
catch (System.AccessViolationException)
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[PHYSICS]: PrimGeom dead");
|
||||
m_log.ErrorFormat("[PHYSICS]: Failed to destroy character shell {0}",e.Message);
|
||||
}
|
||||
// Remove any old entries
|
||||
//string tShell;
|
||||
|
@ -1418,12 +1438,21 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
{
|
||||
d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z);
|
||||
|
||||
_position.X = m_taintPosition.X;
|
||||
_position.Y = m_taintPosition.Y;
|
||||
_position.Z = m_taintPosition.Z;
|
||||
}
|
||||
_position.X = m_taintPosition.X;
|
||||
_position.Y = m_taintPosition.Y;
|
||||
_position.Z = m_taintPosition.Z;
|
||||
}
|
||||
|
||||
if (m_haveTaintMomentum)
|
||||
{
|
||||
m_haveTaintMomentum = false;
|
||||
_velocity = m_taintMomentum;
|
||||
_target_velocity = m_taintMomentum;
|
||||
m_pidControllerActive = true;
|
||||
if (Body != IntPtr.Zero)
|
||||
d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -115,12 +115,11 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
private CollisionCategories m_collisionCategories = (CollisionCategories.Character);
|
||||
|
||||
// Default, Collide with Other Geometries, spaces, bodies and characters.
|
||||
private CollisionCategories m_collisionFlags = (CollisionCategories.Geom
|
||||
| CollisionCategories.Space
|
||||
| CollisionCategories.Body
|
||||
| CollisionCategories.Character
|
||||
private CollisionCategories m_collisionFlags = (CollisionCategories.Character
|
||||
| CollisionCategories.Geom
|
||||
| CollisionCategories.VolumeDtc
|
||||
);
|
||||
// we do land collisions not ode | CollisionCategories.Land);
|
||||
// we do land collisions not ode | CollisionCategories.Land);
|
||||
public IntPtr Body = IntPtr.Zero;
|
||||
private OdeScene _parent_scene;
|
||||
public IntPtr Shell = IntPtr.Zero;
|
||||
|
@ -639,6 +638,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
|
||||
public override void SetMomentum(Vector3 momentum)
|
||||
{
|
||||
if (momentum.IsFinite())
|
||||
AddChange(changes.Momentum, momentum);
|
||||
}
|
||||
|
||||
|
||||
|
@ -663,8 +664,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
}
|
||||
Shell = d.CreateCapsule(_parent_scene.ActiveSpace, CAPSULE_RADIUS, CAPSULE_LENGTH);
|
||||
|
||||
d.GeomSetCategoryBits(Shell, (int)m_collisionCategories);
|
||||
d.GeomSetCollideBits(Shell, (int)m_collisionFlags);
|
||||
d.GeomSetCategoryBits(Shell, (uint)m_collisionCategories);
|
||||
d.GeomSetCollideBits(Shell, (uint)m_collisionFlags);
|
||||
|
||||
d.MassSetCapsule(out ShellMass, m_density, 3, CAPSULE_RADIUS, CAPSULE_LENGTH);
|
||||
|
||||
|
@ -759,7 +760,6 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
_parent_scene.geom_name_map.Remove(Shell);
|
||||
_parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
|
||||
d.GeomDestroy(Shell);
|
||||
_parent_scene.geom_name_map.Remove(Shell);
|
||||
Shell = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
@ -991,6 +991,14 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
// end add Kitto Flora
|
||||
}
|
||||
|
||||
if (vel.X * vel.X + vel.Y * vel.Y + vel.Z * vel.Z > 2500.0f) // 50m/s apply breaks
|
||||
{
|
||||
float breakfactor = 0.16f * m_mass; // will give aprox 60m/s terminal velocity at free fall
|
||||
vec.X -= breakfactor * vel.X;
|
||||
vec.Y -= breakfactor * vel.Y;
|
||||
vec.Z -= breakfactor * vel.Z;
|
||||
}
|
||||
|
||||
if (vec.IsFinite())
|
||||
{
|
||||
if (vec.X != 0 || vec.Y !=0 || vec.Z !=0)
|
||||
|
@ -1324,6 +1332,16 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
}
|
||||
}
|
||||
|
||||
// for now momentum is actually velocity
|
||||
private void changeMomentum(Vector3 newmomentum)
|
||||
{
|
||||
_velocity = newmomentum;
|
||||
_target_velocity = newmomentum;
|
||||
m_pidControllerActive = true;
|
||||
if (Body != IntPtr.Zero)
|
||||
d.BodySetLinearVel(Body, newmomentum.X, newmomentum.Y, newmomentum.Z);
|
||||
}
|
||||
|
||||
private void donullchange()
|
||||
{
|
||||
}
|
||||
|
@ -1395,6 +1413,10 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
case changes.Size:
|
||||
changeSize((Vector3)arg);
|
||||
break;
|
||||
|
||||
case changes.Momentum:
|
||||
changeMomentum((Vector3)arg);
|
||||
break;
|
||||
/* not in use for now
|
||||
case changes.Shape:
|
||||
changeShape((PrimitiveBaseShape)arg);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
||||
|
||||
int time = Util.EnvironmentTickCount();
|
||||
|
||||
ODERayRequest req;
|
||||
int closestHit;
|
||||
int backfacecull;
|
||||
CollisionCategories catflags;
|
||||
|
||||
int i = 50; // arbitary limit of processed tests per frame
|
||||
|
||||
while(m_PendingRequests.Dequeue(out req))
|
||||
while (m_PendingRequests.Dequeue(out req))
|
||||
{
|
||||
if (req.geom == IntPtr.Zero)
|
||||
doSpaceRay(req);
|
||||
else
|
||||
doGeomRay(req);
|
||||
if(--i < 0)
|
||||
break;
|
||||
if (req.callbackMethod != null)
|
||||
{
|
||||
CurrentRayFilter = req.filter;
|
||||
CurrentMaxCount = req.Count;
|
||||
|
||||
closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1);
|
||||
backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1);
|
||||
|
||||
d.GeomRaySetLength(ray, req.length);
|
||||
d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
|
||||
d.GeomRaySetParams(ray, 0, backfacecull);
|
||||
d.GeomRaySetClosestHit(ray, closestHit);
|
||||
|
||||
if (req.callbackMethod is RaycastCallback)
|
||||
// if we only want one get only one per colision pair saving memory
|
||||
CurrentRayFilter |= RayFilterFlags.ClosestHit;
|
||||
|
||||
if (req.geom == IntPtr.Zero)
|
||||
{
|
||||
// translate ray filter to colision flags
|
||||
catflags = 0;
|
||||
if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0)
|
||||
catflags |= CollisionCategories.VolumeDtc;
|
||||
if ((CurrentRayFilter & RayFilterFlags.phantom) != 0)
|
||||
catflags |= CollisionCategories.Phantom;
|
||||
if ((CurrentRayFilter & RayFilterFlags.agent) != 0)
|
||||
catflags |= CollisionCategories.Character;
|
||||
if ((CurrentRayFilter & RayFilterFlags.PrimsNonPhantom) != 0)
|
||||
catflags |= CollisionCategories.Geom;
|
||||
if ((CurrentRayFilter & RayFilterFlags.land) != 0)
|
||||
catflags |= CollisionCategories.Land;
|
||||
if ((CurrentRayFilter & RayFilterFlags.water) != 0)
|
||||
catflags |= CollisionCategories.Water;
|
||||
|
||||
if (catflags != 0)
|
||||
doSpaceRay(req);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we select a geom don't use filters
|
||||
d.GeomSetCollideBits(ray, (uint)CollisionCategories.All);
|
||||
doGeomRay(req);
|
||||
}
|
||||
}
|
||||
|
||||
if (Util.EnvironmentTickCountSubtract(time) > MaxTimePerCallMS)
|
||||
break;
|
||||
}
|
||||
|
||||
lock (m_contactResults)
|
||||
m_contactResults.Clear();
|
||||
|
||||
return System.Environment.TickCount - time;
|
||||
return Util.EnvironmentTickCountSubtract(time);
|
||||
}
|
||||
/// <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,25 +338,30 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
{
|
||||
foreach (ContactResult cResult in m_contactResults)
|
||||
{
|
||||
if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact))
|
||||
if(cResult.Depth < distance)
|
||||
{
|
||||
closestcontact = cResult.Pos;
|
||||
hitConsumerID = cResult.ConsumerID;
|
||||
distance = cResult.Depth;
|
||||
hitYN = true;
|
||||
snormal = cResult.Normal;
|
||||
}
|
||||
}
|
||||
m_contactResults.Clear();
|
||||
}
|
||||
|
||||
|
||||
if (distance > 0 && distance < float.MaxValue)
|
||||
hitYN = true;
|
||||
((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
|
||||
}
|
||||
else
|
||||
{
|
||||
((RayCallback)req.callbackMethod)(m_contactResults);
|
||||
List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
|
||||
lock (m_PendingRequests)
|
||||
{
|
||||
cresult.AddRange(m_contactResults);
|
||||
m_contactResults.Clear();
|
||||
}
|
||||
((RayCallback)req.callbackMethod)(cresult);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,27 +371,16 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
/// <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,25 +388,31 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
{
|
||||
foreach (ContactResult cResult in m_contactResults)
|
||||
{
|
||||
if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact))
|
||||
if(cResult.Depth < distance )
|
||||
{
|
||||
closestcontact = cResult.Pos;
|
||||
hitConsumerID = cResult.ConsumerID;
|
||||
distance = cResult.Depth;
|
||||
hitYN = true;
|
||||
snormal = cResult.Normal;
|
||||
}
|
||||
}
|
||||
m_contactResults.Clear();
|
||||
}
|
||||
|
||||
if (distance > 0 && distance < float.MaxValue)
|
||||
hitYN = true;
|
||||
|
||||
((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
|
||||
}
|
||||
else
|
||||
{
|
||||
((RayCallback)req.callbackMethod)(m_contactResults);
|
||||
List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
|
||||
lock (m_PendingRequests)
|
||||
{
|
||||
cresult.AddRange(m_contactResults);
|
||||
m_contactResults.Clear();
|
||||
}
|
||||
((RayCallback)req.callbackMethod)(cresult);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,20 +427,16 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
return true;
|
||||
}
|
||||
|
||||
// This is the standard Near. g2 is the ray
|
||||
// This is the standard Near. g1 is the ray
|
||||
private void near(IntPtr space, IntPtr g1, IntPtr g2)
|
||||
{
|
||||
//Don't test against heightfield Geom, or you'll be sorry!
|
||||
// Exclude heightfield geom
|
||||
|
||||
if (g1 == IntPtr.Zero || g1 == g2)
|
||||
if (g2 == IntPtr.Zero || g1 == g2)
|
||||
return;
|
||||
|
||||
if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
|
||||
if (m_contactResults.Count >= CurrentMaxCount)
|
||||
return;
|
||||
|
||||
// Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms.
|
||||
if (d.GeomIsSpace(g1))
|
||||
if (d.GeomIsSpace(g2))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -381,10 +454,6 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
{
|
||||
count = d.CollidePtr(g1, g2, ColisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
|
||||
}
|
||||
catch (SEHException)
|
||||
{
|
||||
m_log.Error("[PHYSICS Ray]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message);
|
||||
|
@ -394,31 +463,116 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
if (count == 0)
|
||||
return;
|
||||
|
||||
PhysicsActor p1 = null;
|
||||
uint ID = 0;
|
||||
PhysicsActor p2 = null;
|
||||
|
||||
if (g1 != IntPtr.Zero)
|
||||
m_scene.actor_name_map.TryGetValue(g1, out p1);
|
||||
m_scene.actor_name_map.TryGetValue(g2, out p2);
|
||||
|
||||
if (p2 == null)
|
||||
{
|
||||
string name;
|
||||
|
||||
if (!m_scene.geom_name_map.TryGetValue(g2, out name))
|
||||
return;
|
||||
|
||||
if (name == "Terrain")
|
||||
{
|
||||
// land colision
|
||||
if ((CurrentRayFilter & RayFilterFlags.land) == 0)
|
||||
return;
|
||||
}
|
||||
else if (name == "Water")
|
||||
{
|
||||
if ((CurrentRayFilter & RayFilterFlags.water) == 0)
|
||||
return;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p2 is OdePrim)
|
||||
{
|
||||
RayFilterFlags thisFlags;
|
||||
|
||||
if (p2.IsPhysical)
|
||||
thisFlags = RayFilterFlags.physical;
|
||||
else
|
||||
thisFlags = RayFilterFlags.nonphysical;
|
||||
|
||||
if (p2.Phantom)
|
||||
thisFlags |= RayFilterFlags.phantom;
|
||||
|
||||
if (p2.IsVolumeDtc)
|
||||
thisFlags |= RayFilterFlags.volumedtc;
|
||||
|
||||
if ((thisFlags & CurrentRayFilter) == 0)
|
||||
return;
|
||||
|
||||
ID = ((OdePrim)p2).m_localID;
|
||||
}
|
||||
else if (p2 is OdeCharacter)
|
||||
{
|
||||
if ((CurrentRayFilter & RayFilterFlags.agent) == 0)
|
||||
return;
|
||||
else
|
||||
ID = ((OdeCharacter)p2).m_localID;
|
||||
}
|
||||
else //??
|
||||
return;
|
||||
}
|
||||
|
||||
d.ContactGeom curcontact = new d.ContactGeom();
|
||||
// Loop over contacts, build results.
|
||||
for (int i = 0; i < count; i++)
|
||||
|
||||
// closestHit for now only works for meshs, so must do it for others
|
||||
if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0)
|
||||
{
|
||||
if (!GetCurContactGeom(i, ref curcontact))
|
||||
break;
|
||||
if (p1 != null) {
|
||||
if (p1 is OdePrim)
|
||||
// Loop all contacts, build results.
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (!GetCurContactGeom(i, ref curcontact))
|
||||
break;
|
||||
|
||||
ContactResult collisionresult = new ContactResult();
|
||||
collisionresult.ConsumerID = ID;
|
||||
collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z);
|
||||
collisionresult.Depth = curcontact.depth;
|
||||
collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y,
|
||||
curcontact.normal.Z);
|
||||
lock (m_contactResults)
|
||||
{
|
||||
m_contactResults.Add(collisionresult);
|
||||
if (m_contactResults.Count >= CurrentMaxCount)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep only closest contact
|
||||
ContactResult collisionresult = new ContactResult();
|
||||
collisionresult.ConsumerID = ID;
|
||||
collisionresult.Depth = float.MaxValue;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (!GetCurContactGeom(i, ref curcontact))
|
||||
break;
|
||||
|
||||
if (curcontact.depth < collisionresult.Depth)
|
||||
{
|
||||
ContactResult collisionresult = new ContactResult();
|
||||
|
||||
collisionresult.ConsumerID = ((OdePrim)p1).m_localID;
|
||||
collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z);
|
||||
collisionresult.Depth = curcontact.depth;
|
||||
collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y,
|
||||
curcontact.normal.Z);
|
||||
lock (m_contactResults)
|
||||
m_contactResults.Add(collisionresult);
|
||||
}
|
||||
}
|
||||
|
||||
if (collisionresult.Depth != float.MaxValue)
|
||||
{
|
||||
lock (m_contactResults)
|
||||
m_contactResults.Add(collisionresult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -428,6 +582,11 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
internal void Dispose()
|
||||
{
|
||||
m_scene = null;
|
||||
if (ray != IntPtr.Zero)
|
||||
{
|
||||
d.GeomDestroy(ray);
|
||||
ray = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -439,5 +598,6 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
public int Count;
|
||||
public float length;
|
||||
public object callbackMethod;
|
||||
public RayFilterFlags filter;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
m_log.WarnFormat("ODE configuration: {0}", ode_config);
|
||||
|
||||
if (ode_config.Contains("ODE_Ubit"))
|
||||
if (ode_config != null && ode_config != "")
|
||||
{
|
||||
OdeUbitLib = true;
|
||||
}
|
||||
m_log.WarnFormat("ODE configuration: {0}", ode_config);
|
||||
|
||||
if (ode_config.Contains("ODE_Ubit"))
|
||||
{
|
||||
OdeUbitLib = true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
if (region != null)
|
||||
{
|
||||
|
@ -518,6 +549,15 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
waitForSpaceUnlock(newspace);
|
||||
d.SpaceSetSublevel(newspace, 2);
|
||||
d.HashSpaceSetLevels(newspace, -2, 8);
|
||||
d.GeomSetCategoryBits(newspace, (uint)(CollisionCategories.Space |
|
||||
CollisionCategories.Geom |
|
||||
CollisionCategories.Land |
|
||||
CollisionCategories.Water |
|
||||
CollisionCategories.Phantom |
|
||||
CollisionCategories.VolumeDtc
|
||||
));
|
||||
d.GeomSetCollideBits(newspace, 0);
|
||||
|
||||
staticPrimspace[i, j] = newspace;
|
||||
}
|
||||
// let this now be real maximum values
|
||||
|
@ -1745,8 +1785,6 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
|
||||
m_rayCastManager.ProcessQueuedRequests();
|
||||
|
||||
|
||||
|
||||
statray += Util.EnvironmentTickCountSubtract(statstart);
|
||||
collision_optimized();
|
||||
statcol += Util.EnvironmentTickCountSubtract(statstart);
|
||||
|
@ -2125,14 +2163,14 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
RegionTerrain.Remove(pOffset);
|
||||
if (GroundGeom != IntPtr.Zero)
|
||||
{
|
||||
d.GeomDestroy(GroundGeom);
|
||||
|
||||
if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
|
||||
{
|
||||
TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
|
||||
TerrainHeightFieldHeightsHandlers.Remove(GroundGeom);
|
||||
TerrainHeightFieldHeights.Remove(GroundGeom);
|
||||
}
|
||||
d.SpaceRemove(StaticSpace, GroundGeom);
|
||||
d.GeomDestroy(GroundGeom);
|
||||
}
|
||||
}
|
||||
IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
|
||||
|
@ -2147,8 +2185,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
GroundGeom = d.CreateHeightfield(StaticSpace, HeightmapData, 1);
|
||||
if (GroundGeom != IntPtr.Zero)
|
||||
{
|
||||
d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land));
|
||||
d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space));
|
||||
d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
|
||||
d.GeomSetCollideBits(GroundGeom, 0);
|
||||
|
||||
}
|
||||
geom_name_map[GroundGeom] = "Terrain";
|
||||
|
@ -2236,14 +2274,15 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
RegionTerrain.Remove(pOffset);
|
||||
if (GroundGeom != IntPtr.Zero)
|
||||
{
|
||||
d.GeomDestroy(GroundGeom);
|
||||
|
||||
if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
|
||||
{
|
||||
TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
|
||||
if (TerrainHeightFieldHeightsHandlers[GroundGeom].IsAllocated)
|
||||
TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
|
||||
TerrainHeightFieldHeightsHandlers.Remove(GroundGeom);
|
||||
TerrainHeightFieldHeights.Remove(GroundGeom);
|
||||
}
|
||||
d.SpaceRemove(StaticSpace, GroundGeom);
|
||||
d.GeomDestroy(GroundGeom);
|
||||
}
|
||||
}
|
||||
IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
|
||||
|
@ -2263,8 +2302,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
GroundGeom = d.CreateUbitTerrain(StaticSpace, HeightmapData, 1);
|
||||
if (GroundGeom != IntPtr.Zero)
|
||||
{
|
||||
d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land));
|
||||
d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space));
|
||||
d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
|
||||
d.GeomSetCollideBits(GroundGeom, 0);
|
||||
|
||||
}
|
||||
geom_name_map[GroundGeom] = "Terrain";
|
||||
|
@ -2359,57 +2398,76 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
|
||||
public void randomizeWater(float baseheight)
|
||||
{
|
||||
const uint heightmapWidth = m_regionWidth + 2;
|
||||
const uint heightmapHeight = m_regionHeight + 2;
|
||||
const uint heightmapWidthSamples = m_regionWidth + 2;
|
||||
const uint heightmapHeightSamples = m_regionHeight + 2;
|
||||
const uint heightmapWidth = Constants.RegionSize + 2;
|
||||
const uint heightmapHeight = Constants.RegionSize + 2;
|
||||
const uint heightmapWidthSamples = heightmapWidth + 1;
|
||||
const uint heightmapHeightSamples = heightmapHeight + 1;
|
||||
|
||||
const float scale = 1.0f;
|
||||
const float offset = 0.0f;
|
||||
const float thickness = 2.9f;
|
||||
const int wrap = 0;
|
||||
|
||||
for (int i = 0; i < (258 * 258); i++)
|
||||
float[] _watermap = new float[heightmapWidthSamples * heightmapWidthSamples];
|
||||
|
||||
float maxheigh = float.MinValue;
|
||||
float minheigh = float.MaxValue;
|
||||
float val;
|
||||
for (int i = 0; i < (heightmapWidthSamples * heightmapHeightSamples); i++)
|
||||
{
|
||||
_watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f);
|
||||
// m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f));
|
||||
|
||||
val = (baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f);
|
||||
_watermap[i] = val;
|
||||
if (maxheigh < val)
|
||||
maxheigh = val;
|
||||
if (minheigh > val)
|
||||
minheigh = val;
|
||||
}
|
||||
|
||||
float thickness = minheigh;
|
||||
|
||||
lock (OdeLock)
|
||||
{
|
||||
if (WaterGeom != IntPtr.Zero)
|
||||
{
|
||||
d.SpaceRemove(StaticSpace, WaterGeom);
|
||||
d.GeomDestroy(WaterGeom);
|
||||
d.GeomHeightfieldDataDestroy(WaterHeightmapData);
|
||||
WaterGeom = IntPtr.Zero;
|
||||
WaterHeightmapData = IntPtr.Zero;
|
||||
if(WaterMapHandler.IsAllocated)
|
||||
WaterMapHandler.Free();
|
||||
}
|
||||
IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
|
||||
d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight,
|
||||
|
||||
WaterHeightmapData = d.GeomHeightfieldDataCreate();
|
||||
|
||||
WaterMapHandler = GCHandle.Alloc(_watermap, GCHandleType.Pinned);
|
||||
|
||||
d.GeomHeightfieldDataBuildSingle(WaterHeightmapData, WaterMapHandler.AddrOfPinnedObject(), 0, heightmapWidth, heightmapHeight,
|
||||
(int)heightmapWidthSamples, (int)heightmapHeightSamples, scale,
|
||||
offset, thickness, wrap);
|
||||
d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight);
|
||||
WaterGeom = d.CreateHeightfield(StaticSpace, HeightmapData, 1);
|
||||
d.GeomHeightfieldDataSetBounds(WaterHeightmapData, minheigh, maxheigh);
|
||||
WaterGeom = d.CreateHeightfield(StaticSpace, WaterHeightmapData, 1);
|
||||
if (WaterGeom != IntPtr.Zero)
|
||||
{
|
||||
d.GeomSetCategoryBits(WaterGeom, (int)(CollisionCategories.Water));
|
||||
d.GeomSetCollideBits(WaterGeom, (int)(CollisionCategories.Space));
|
||||
d.GeomSetCategoryBits(WaterGeom, (uint)(CollisionCategories.Water));
|
||||
d.GeomSetCollideBits(WaterGeom, 0);
|
||||
|
||||
geom_name_map[WaterGeom] = "Water";
|
||||
|
||||
d.Matrix3 R = new d.Matrix3();
|
||||
|
||||
Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
|
||||
Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);
|
||||
|
||||
q1 = q1 * q2;
|
||||
Vector3 v3;
|
||||
float angle;
|
||||
q1.GetAxisAngle(out v3, out angle);
|
||||
|
||||
d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
|
||||
d.GeomSetRotation(WaterGeom, ref R);
|
||||
d.GeomSetPosition(WaterGeom, (float)Constants.RegionSize * 0.5f, (float)Constants.RegionSize * 0.5f, 0);
|
||||
}
|
||||
geom_name_map[WaterGeom] = "Water";
|
||||
|
||||
d.Matrix3 R = new d.Matrix3();
|
||||
|
||||
Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
|
||||
Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);
|
||||
|
||||
q1 = q1 * q2;
|
||||
Vector3 v3;
|
||||
float angle;
|
||||
q1.GetAxisAngle(out v3, out angle);
|
||||
|
||||
d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
|
||||
d.GeomSetRotation(WaterGeom, ref R);
|
||||
d.GeomSetPosition(WaterGeom, 128, 128, 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
|
@ -2427,11 +2485,34 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
}
|
||||
}
|
||||
|
||||
if (TerrainHeightFieldHeightsHandlers.Count > 0)
|
||||
{
|
||||
foreach (GCHandle gch in TerrainHeightFieldHeightsHandlers.Values)
|
||||
{
|
||||
if (gch.IsAllocated)
|
||||
gch.Free();
|
||||
}
|
||||
}
|
||||
|
||||
if (WaterGeom != IntPtr.Zero)
|
||||
{
|
||||
d.GeomDestroy(WaterGeom);
|
||||
WaterGeom = IntPtr.Zero;
|
||||
if (WaterHeightmapData != IntPtr.Zero)
|
||||
d.GeomHeightfieldDataDestroy(WaterHeightmapData);
|
||||
WaterHeightmapData = IntPtr.Zero;
|
||||
|
||||
if (WaterMapHandler.IsAllocated)
|
||||
WaterMapHandler.Free();
|
||||
}
|
||||
|
||||
|
||||
if (ContactgeomsArray != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(ContactgeomsArray);
|
||||
if (GlobalContactsArray != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(GlobalContactsArray);
|
||||
|
||||
|
||||
d.WorldDestroy(world);
|
||||
//d.CloseODE();
|
||||
}
|
||||
|
@ -2502,6 +2583,35 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
return new List<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)
|
||||
|
|
|
@ -9980,7 +9980,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
// return total object mass
|
||||
SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
|
||||
if (obj != null)
|
||||
return (double)obj.GetMass();
|
||||
return obj.GetMass();
|
||||
|
||||
// the object is null so the key is for an avatar
|
||||
ScenePresence avatar = World.GetScenePresence(key);
|
||||
|
@ -9990,7 +9990,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
// child agents have a mass of 1.0
|
||||
return 1;
|
||||
else
|
||||
return (double)avatar.PhysicsActor.Mass;
|
||||
return avatar.GetMass();
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
|
@ -11834,6 +11834,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
|
||||
return contacts[0];
|
||||
}
|
||||
/*
|
||||
// not done:
|
||||
private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
|
||||
{
|
||||
ContactResult[] contacts = null;
|
||||
World.ForEachSOG(delegate(SceneObjectGroup group)
|
||||
{
|
||||
if (m_host.ParentGroup == group)
|
||||
return;
|
||||
|
||||
if (group.IsAttachment)
|
||||
return;
|
||||
|
||||
if(group.RootPart.PhysActor != null)
|
||||
return;
|
||||
|
||||
contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
|
||||
});
|
||||
return contacts;
|
||||
}
|
||||
*/
|
||||
|
||||
public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
|
||||
{
|
||||
|
@ -11874,38 +11895,101 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
|
||||
bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
|
||||
|
||||
if (checkTerrain)
|
||||
{
|
||||
ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
|
||||
if (groundContact != null)
|
||||
results.Add((ContactResult)groundContact);
|
||||
}
|
||||
|
||||
if (checkAgents)
|
||||
if (World.SuportsRayCastFiltered())
|
||||
{
|
||||
ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
|
||||
foreach (ContactResult r in agentHits)
|
||||
results.Add(r);
|
||||
}
|
||||
if (dist == 0)
|
||||
return list;
|
||||
|
||||
if (checkPhysical || checkNonPhysical)
|
||||
RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
|
||||
if (checkTerrain)
|
||||
rayfilter |= RayFilterFlags.land;
|
||||
// if (checkAgents)
|
||||
// rayfilter |= RayFilterFlags.agent;
|
||||
if (checkPhysical)
|
||||
rayfilter |= RayFilterFlags.physical;
|
||||
if (checkNonPhysical)
|
||||
rayfilter |= RayFilterFlags.nonphysical;
|
||||
if (detectPhantom)
|
||||
rayfilter |= RayFilterFlags.LSLPhanton;
|
||||
|
||||
Vector3 direction = dir * ( 1/dist);
|
||||
|
||||
if(rayfilter == 0)
|
||||
{
|
||||
list.Add(new LSL_Integer(0));
|
||||
return list;
|
||||
}
|
||||
|
||||
// get some more contacts to sort ???
|
||||
int physcount = 4 * count;
|
||||
if (physcount > 20)
|
||||
physcount = 20;
|
||||
|
||||
object physresults;
|
||||
physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
|
||||
|
||||
if (physresults == null)
|
||||
{
|
||||
list.Add(new LSL_Integer(-3)); // timeout error
|
||||
return list;
|
||||
}
|
||||
|
||||
results = (List<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
|
||||
{
|
||||
ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
|
||||
foreach (ContactResult r in objectHits)
|
||||
results.Add(r);
|
||||
if (checkTerrain)
|
||||
{
|
||||
ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
|
||||
if (groundContact != null)
|
||||
results.Add((ContactResult)groundContact);
|
||||
}
|
||||
|
||||
if (checkAgents)
|
||||
{
|
||||
ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
|
||||
foreach (ContactResult r in agentHits)
|
||||
results.Add(r);
|
||||
}
|
||||
|
||||
if (checkPhysical || checkNonPhysical || detectPhantom)
|
||||
{
|
||||
ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
|
||||
foreach (ContactResult r in objectHits)
|
||||
results.Add(r);
|
||||
}
|
||||
}
|
||||
|
||||
results.Sort(delegate(ContactResult a, ContactResult b)
|
||||
{
|
||||
return (int)(a.Depth - b.Depth);
|
||||
return a.Depth.CompareTo(b.Depth);
|
||||
});
|
||||
|
||||
int values = 0;
|
||||
SceneObjectGroup thisgrp = m_host.ParentGroup;
|
||||
|
||||
foreach (ContactResult result in results)
|
||||
{
|
||||
if (result.Depth > dist)
|
||||
continue;
|
||||
|
||||
// physics ray can return colisions with host prim
|
||||
if (m_host.LocalId == result.ConsumerID)
|
||||
continue;
|
||||
|
||||
UUID itemID = UUID.Zero;
|
||||
int linkNum = 0;
|
||||
|
||||
|
@ -11913,6 +11997,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
// It's a prim!
|
||||
if (part != null)
|
||||
{
|
||||
// dont detect members of same object ???
|
||||
if (part.ParentGroup == thisgrp)
|
||||
continue;
|
||||
|
||||
if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
|
||||
itemID = part.ParentGroup.UUID;
|
||||
else
|
||||
|
@ -11923,7 +12011,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
else
|
||||
{
|
||||
ScenePresence sp = World.GetScenePresence(result.ConsumerID);
|
||||
/// It it a boy? a girl?
|
||||
/// It it a boy? a girl?
|
||||
if (sp != null)
|
||||
itemID = sp.UUID;
|
||||
}
|
||||
|
@ -11934,14 +12022,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
|
||||
list.Add(new LSL_Integer(linkNum));
|
||||
|
||||
|
||||
if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
|
||||
list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
|
||||
|
||||
values++;
|
||||
count--;
|
||||
|
||||
if (count == 0)
|
||||
values++;
|
||||
if (values >= count)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue