aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs23
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs62
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs571
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs288
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs15
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs253
6 files changed, 853 insertions, 359 deletions
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index a442cf0..d24ab2a 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -38,6 +38,9 @@ namespace OpenSim.Region.Physics.Manager
38 38
39 public delegate void RaycastCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal); 39 public delegate void RaycastCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal);
40 public delegate void RayCallback(List<ContactResult> list); 40 public delegate void RayCallback(List<ContactResult> list);
41 public delegate void ProbeBoxCallback(List<ContactResult> list);
42 public delegate void ProbeSphereCallback(List<ContactResult> list);
43 public delegate void ProbePlaneCallback(List<ContactResult> list);
41 public delegate void SitAvatarCallback(int status, uint partID, Vector3 offset, Quaternion Orientation); 44 public delegate void SitAvatarCallback(int status, uint partID, Vector3 offset, Quaternion Orientation);
42 45
43 public delegate void JointMoved(PhysicsJoint joint); 46 public delegate void JointMoved(PhysicsJoint joint);
@@ -56,6 +59,7 @@ namespace OpenSim.Region.Physics.Manager
56 volumedtc = 0x40, 59 volumedtc = 0x40,
57 60
58 // ray cast colision control (may only work for meshs) 61 // ray cast colision control (may only work for meshs)
62 ContactsUnImportant = 0x2000,
59 BackFaceCull = 0x4000, 63 BackFaceCull = 0x4000,
60 ClosestHit = 0x8000, 64 ClosestHit = 0x8000,
61 65
@@ -351,9 +355,22 @@ namespace OpenSim.Region.Physics.Manager
351 return false; 355 return false;
352 } 356 }
353 357
354 public virtual void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod){} 358 public virtual List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags)
355 public virtual void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) { } 359 {
356 public virtual List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count) 360 return new List<ContactResult>();
361 }
362
363 public virtual List<ContactResult> BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags)
364 {
365 return new List<ContactResult>();
366 }
367
368 public virtual List<ContactResult> SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags)
369 {
370 return new List<ContactResult>();
371 }
372
373 public virtual List<ContactResult> PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags)
357 { 374 {
358 return new List<ContactResult>(); 375 return new List<ContactResult>();
359 } 376 }
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
index bb04ea7..f7e4c1c 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
@@ -715,7 +715,17 @@ namespace OpenSim.Region.Physics.OdePlugin
715 Vector3 off = _velocity; 715 Vector3 off = _velocity;
716 float t = 0.5f * timeStep; 716 float t = 0.5f * timeStep;
717 off = off * t; 717 off = off * t;
718 d.Quaternion qtmp;
719 d.GeomCopyQuaternion(bbox, out qtmp);
720 Quaternion q;
721 q.X = qtmp.X;
722 q.Y = qtmp.Y;
723 q.Z = qtmp.Z;
724 q.W = qtmp.W;
725 off *= Quaternion.Conjugate(q);
726
718 d.GeomSetOffsetPosition(bbox, off.X, off.Y, off.Z); 727 d.GeomSetOffsetPosition(bbox, off.X, off.Y, off.Z);
728
719 off.X = 2.0f * (m_size.X + Math.Abs(off.X)); 729 off.X = 2.0f * (m_size.X + Math.Abs(off.X));
720 off.Y = 2.0f * (m_size.Y + Math.Abs(off.Y)); 730 off.Y = 2.0f * (m_size.Y + Math.Abs(off.Y));
721 off.Z = m_size.Z + 2.0f * Math.Abs(off.Z); 731 off.Z = m_size.Z + 2.0f * Math.Abs(off.Z);
@@ -741,6 +751,9 @@ namespace OpenSim.Region.Physics.OdePlugin
741 d.GeomSetCategoryBits(feetbox, (uint)m_collisionCategories); 751 d.GeomSetCategoryBits(feetbox, (uint)m_collisionCategories);
742 d.GeomSetCollideBits(feetbox, (uint)m_collisionFlags); 752 d.GeomSetCollideBits(feetbox, (uint)m_collisionFlags);
743 } 753 }
754 uint cat1 = d.GeomGetCategoryBits(bbox);
755 uint col1 = d.GeomGetCollideBits(bbox);
756
744 } 757 }
745 } 758 }
746 759
@@ -1527,8 +1540,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1527 { 1540 {
1528 if (CollisionEventsThisFrame != null) 1541 if (CollisionEventsThisFrame != null)
1529 { 1542 {
1530 CollisionEventsThisFrame.Clear(); 1543 lock (CollisionEventsThisFrame)
1531 CollisionEventsThisFrame = null; 1544 {
1545 CollisionEventsThisFrame.Clear();
1546 CollisionEventsThisFrame = null;
1547 }
1532 } 1548 }
1533 m_eventsubscription = 0; 1549 m_eventsubscription = 0;
1534 } 1550 }
@@ -1537,8 +1553,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1537 { 1553 {
1538 if (CollisionEventsThisFrame == null) 1554 if (CollisionEventsThisFrame == null)
1539 CollisionEventsThisFrame = new CollisionEventUpdate(); 1555 CollisionEventsThisFrame = new CollisionEventUpdate();
1540 CollisionEventsThisFrame.AddCollider(CollidedWith, contact); 1556 lock (CollisionEventsThisFrame)
1541 _parent_scene.AddCollisionEventReporting(this); 1557 {
1558 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
1559 _parent_scene.AddCollisionEventReporting(this);
1560 }
1542 } 1561 }
1543 1562
1544 public void SendCollisions() 1563 public void SendCollisions()
@@ -1546,26 +1565,29 @@ namespace OpenSim.Region.Physics.OdePlugin
1546 if (CollisionEventsThisFrame == null) 1565 if (CollisionEventsThisFrame == null)
1547 return; 1566 return;
1548 1567
1549 if (m_cureventsubscription < m_eventsubscription) 1568 lock (CollisionEventsThisFrame)
1550 return; 1569 {
1551 1570 if (m_cureventsubscription < m_eventsubscription)
1552 m_cureventsubscription = 0; 1571 return;
1553 1572
1554 int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count; 1573 m_cureventsubscription = 0;
1555 1574
1556 if (!SentEmptyCollisionsEvent || ncolisions > 0) 1575 int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count;
1557 {
1558 base.SendCollisionUpdate(CollisionEventsThisFrame);
1559 1576
1560 if (ncolisions == 0) 1577 if (!SentEmptyCollisionsEvent || ncolisions > 0)
1561 {
1562 SentEmptyCollisionsEvent = true;
1563 _parent_scene.RemoveCollisionEventReporting(this);
1564 }
1565 else
1566 { 1578 {
1567 SentEmptyCollisionsEvent = false; 1579 base.SendCollisionUpdate(CollisionEventsThisFrame);
1568 CollisionEventsThisFrame.Clear(); 1580
1581 if (ncolisions == 0)
1582 {
1583 SentEmptyCollisionsEvent = true;
1584 _parent_scene.RemoveCollisionEventReporting(this);
1585 }
1586 else
1587 {
1588 SentEmptyCollisionsEvent = false;
1589 CollisionEventsThisFrame.Clear();
1590 }
1569 } 1591 }
1570 } 1592 }
1571 } 1593 }
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
index 561ab1c..6e9281b 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
@@ -56,8 +56,11 @@ namespace OpenSim.Region.Physics.OdePlugin
56 private OdeScene m_scene; 56 private OdeScene m_scene;
57 57
58 IntPtr ray; // the ray. we only need one for our lifetime 58 IntPtr ray; // the ray. we only need one for our lifetime
59 IntPtr Sphere;
60 IntPtr Box;
61 IntPtr Plane;
59 62
60 private const int ColisionContactGeomsPerTest = 5; 63 private int CollisionContactGeomsPerTest = 25;
61 private const int DefaultMaxCount = 25; 64 private const int DefaultMaxCount = 25;
62 private const int MaxTimePerCallMS = 30; 65 private const int MaxTimePerCallMS = 30;
63 66
@@ -65,6 +68,7 @@ namespace OpenSim.Region.Physics.OdePlugin
65 /// ODE near callback delegate 68 /// ODE near callback delegate
66 /// </summary> 69 /// </summary>
67 private d.NearCallback nearCallback; 70 private d.NearCallback nearCallback;
71 private d.NearCallback nearProbeCallback;
68 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 72 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
69 private List<ContactResult> m_contactResults = new List<ContactResult>(); 73 private List<ContactResult> m_contactResults = new List<ContactResult>();
70 private RayFilterFlags CurrentRayFilter; 74 private RayFilterFlags CurrentRayFilter;
@@ -74,155 +78,21 @@ namespace OpenSim.Region.Physics.OdePlugin
74 { 78 {
75 m_scene = pScene; 79 m_scene = pScene;
76 nearCallback = near; 80 nearCallback = near;
81 nearProbeCallback = nearProbe;
77 ray = d.CreateRay(IntPtr.Zero, 1.0f); 82 ray = d.CreateRay(IntPtr.Zero, 1.0f);
78 d.GeomSetCategoryBits(ray,0); 83 d.GeomSetCategoryBits(ray, 0);
84 Box = d.CreateBox(IntPtr.Zero, 1.0f, 1.0f, 1.0f);
85 d.GeomSetCategoryBits(Box, 0);
86 Sphere = d.CreateSphere(IntPtr.Zero,1.0f);
87 d.GeomSetCategoryBits(Sphere, 0);
88 Plane = d.CreatePlane(IntPtr.Zero, 0f,0f,1f,1f);
89 d.GeomSetCategoryBits(Sphere, 0);
79 } 90 }
80 91
81 /// <summary> 92 public void QueueRequest(ODERayRequest req)
82 /// Queues request for a raycast to all world
83 /// </summary>
84 /// <param name="position">Origin of Ray</param>
85 /// <param name="direction">Ray direction</param>
86 /// <param name="length">Ray length</param>
87 /// <param name="retMethod">Return method to send the results</param>
88 public void QueueRequest(Vector3 position, Vector3 direction, float length, RayCallback retMethod)
89 {
90 ODERayRequest req = new ODERayRequest();
91 req.geom = IntPtr.Zero;
92 req.callbackMethod = retMethod;
93 req.Count = DefaultMaxCount;
94 req.length = length;
95 req.Normal = direction;
96 req.Origin = position;
97 req.filter = RayFilterFlags.AllPrims;
98
99 m_PendingRequests.Enqueue(req);
100 }
101
102 /// <summary>
103 /// Queues request for a raycast to particular part
104 /// </summary>
105 /// <param name="position">Origin of Ray</param>
106 /// <param name="direction">Ray direction</param>
107 /// <param name="length">Ray length</param>
108 /// <param name="retMethod">Return method to send the results</param>
109 public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RayCallback retMethod)
110 {
111 ODERayRequest req = new ODERayRequest();
112 req.geom = geom;
113 req.callbackMethod = retMethod;
114 req.length = length;
115 req.Normal = direction;
116 req.Origin = position;
117 req.Count = DefaultMaxCount;
118 req.filter = RayFilterFlags.AllPrims;
119
120 m_PendingRequests.Enqueue(req);
121 }
122
123 public void QueueRequest(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
124 {
125 ODERayRequest req = new ODERayRequest();
126 req.geom = IntPtr.Zero;
127 req.callbackMethod = retMethod;
128 req.Count = DefaultMaxCount;
129 req.length = length;
130 req.Normal = direction;
131 req.Origin = position;
132 req.filter = RayFilterFlags.AllPrims | RayFilterFlags.land;
133
134 m_PendingRequests.Enqueue(req);
135 }
136
137 public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
138 { 93 {
139 ODERayRequest req = new ODERayRequest(); 94 if (req.Count == 0)
140 req.geom = geom; 95 req.Count = DefaultMaxCount;
141 req.callbackMethod = retMethod;
142 req.length = length;
143 req.Normal = direction;
144 req.Origin = position;
145 req.Count = DefaultMaxCount;
146 req.filter = RayFilterFlags.AllPrims;
147
148 m_PendingRequests.Enqueue(req);
149 }
150
151 /// <summary>
152 /// Queues a raycast
153 /// </summary>
154 /// <param name="position">Origin of Ray</param>
155 /// <param name="direction">Ray normal</param>
156 /// <param name="length">Ray length</param>
157 /// <param name="count"></param>
158 /// <param name="retMethod">Return method to send the results</param>
159 public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod)
160 {
161 ODERayRequest req = new ODERayRequest();
162 req.geom = IntPtr.Zero;
163 req.callbackMethod = retMethod;
164 req.length = length;
165 req.Normal = direction;
166 req.Origin = position;
167 req.Count = count;
168 req.filter = RayFilterFlags.AllPrims;
169
170 m_PendingRequests.Enqueue(req);
171 }
172
173
174 public void QueueRequest(Vector3 position, Vector3 direction, float length, int count,RayFilterFlags filter , RayCallback retMethod)
175 {
176 ODERayRequest req = new ODERayRequest();
177 req.geom = IntPtr.Zero;
178 req.callbackMethod = retMethod;
179 req.length = length;
180 req.Normal = direction;
181 req.Origin = position;
182 req.Count = count;
183 req.filter = filter;
184
185 m_PendingRequests.Enqueue(req);
186 }
187
188 public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod)
189 {
190 ODERayRequest req = new ODERayRequest();
191 req.geom = geom;
192 req.callbackMethod = retMethod;
193 req.length = length;
194 req.Normal = direction;
195 req.Origin = position;
196 req.Count = count;
197 req.filter = RayFilterFlags.AllPrims;
198
199 m_PendingRequests.Enqueue(req);
200 }
201
202 public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RaycastCallback retMethod)
203 {
204 ODERayRequest req = new ODERayRequest();
205 req.geom = IntPtr.Zero;
206 req.callbackMethod = retMethod;
207 req.length = length;
208 req.Normal = direction;
209 req.Origin = position;
210 req.Count = count;
211 req.filter = RayFilterFlags.AllPrims;
212
213 m_PendingRequests.Enqueue(req);
214 }
215
216 public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, int count, RaycastCallback retMethod)
217 {
218 ODERayRequest req = new ODERayRequest();
219 req.geom = geom;
220 req.callbackMethod = retMethod;
221 req.length = length;
222 req.Normal = direction;
223 req.Origin = position;
224 req.Count = count;
225 req.filter = RayFilterFlags.AllPrims;
226 96
227 m_PendingRequests.Enqueue(req); 97 m_PendingRequests.Enqueue(req);
228 } 98 }
@@ -258,21 +128,64 @@ namespace OpenSim.Region.Physics.OdePlugin
258 CurrentRayFilter = req.filter; 128 CurrentRayFilter = req.filter;
259 CurrentMaxCount = req.Count; 129 CurrentMaxCount = req.Count;
260 130
131 CollisionContactGeomsPerTest = req.Count & 0xffff;
132
261 closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1); 133 closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1);
262 backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1); 134 backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1);
263 135
264 d.GeomRaySetLength(ray, req.length); 136 if (req.callbackMethod is ProbeBoxCallback)
265 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); 137 {
266 d.GeomRaySetParams(ray, 0, backfacecull); 138 if (CollisionContactGeomsPerTest > 80)
267 d.GeomRaySetClosestHit(ray, closestHit); 139 CollisionContactGeomsPerTest = 80;
140 d.GeomBoxSetLengths(Box, req.Normal.X, req.Normal.Y, req.Normal.Z);
141 d.GeomSetPosition(Box, req.Origin.X, req.Origin.Y, req.Origin.Z);
142 d.Quaternion qtmp;
143 qtmp.X = req.orientation.X;
144 qtmp.Y = req.orientation.Y;
145 qtmp.Z = req.orientation.Z;
146 qtmp.W = req.orientation.W;
147 d.GeomSetQuaternion(Box, ref qtmp);
148 }
149 else if (req.callbackMethod is ProbeSphereCallback)
150 {
151 if (CollisionContactGeomsPerTest > 80)
152 CollisionContactGeomsPerTest = 80;
153
154 d.GeomSphereSetRadius(Sphere, req.length);
155 d.GeomSetPosition(Sphere, req.Origin.X, req.Origin.Y, req.Origin.Z);
156 }
157 else if (req.callbackMethod is ProbePlaneCallback)
158 {
159 if (CollisionContactGeomsPerTest > 80)
160 CollisionContactGeomsPerTest = 80;
161
162 d.GeomPlaneSetParams(Plane, req.Normal.X, req.Normal.Y, req.Normal.Z, req.length);
163 }
164
165 else
166 {
167 if (CollisionContactGeomsPerTest > 25)
168 CollisionContactGeomsPerTest = 25;
268 169
269 if (req.callbackMethod is RaycastCallback) 170 d.GeomRaySetLength(ray, req.length);
270 // if we only want one get only one per colision pair saving memory 171 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
271 CurrentRayFilter |= RayFilterFlags.ClosestHit; 172 d.GeomRaySetParams(ray, 0, backfacecull);
173 d.GeomRaySetClosestHit(ray, closestHit);
174
175 if (req.callbackMethod is RaycastCallback)
176 // if we only want one get only one per Collision pair saving memory
177 CurrentRayFilter |= RayFilterFlags.ClosestHit;
178 }
179
180 if ((CurrentRayFilter & RayFilterFlags.ContactsUnImportant) != 0)
181 unchecked
182 {
183 CollisionContactGeomsPerTest |= (int)d.CONTACTS_UNIMPORTANT;
184 }
272 185
273 if (req.geom == IntPtr.Zero) 186 if (req.geom == IntPtr.Zero)
274 { 187 {
275 // translate ray filter to colision flags 188 // translate ray filter to Collision flags
276 catflags = 0; 189 catflags = 0;
277 if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0) 190 if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0)
278 catflags |= CollisionCategories.VolumeDtc; 191 catflags |= CollisionCategories.VolumeDtc;
@@ -289,15 +202,48 @@ namespace OpenSim.Region.Physics.OdePlugin
289 202
290 if (catflags != 0) 203 if (catflags != 0)
291 { 204 {
292 d.GeomSetCollideBits(ray, (uint)catflags); 205 if (req.callbackMethod is ProbeBoxCallback)
293 doSpaceRay(req); 206 {
207 catflags |= CollisionCategories.Space;
208 d.GeomSetCollideBits(Box, (uint)catflags);
209 d.GeomSetCategoryBits(Box, (uint)catflags);
210 doProbe(req, Box);
211 }
212 else if (req.callbackMethod is ProbeSphereCallback)
213 {
214 catflags |= CollisionCategories.Space;
215 d.GeomSetCollideBits(Sphere, (uint)catflags);
216 d.GeomSetCategoryBits(Sphere, (uint)catflags);
217 doProbe(req, Sphere);
218 }
219 else if (req.callbackMethod is ProbePlaneCallback)
220 {
221 catflags |= CollisionCategories.Space;
222 d.GeomSetCollideBits(Plane, (uint)catflags);
223 d.GeomSetCategoryBits(Plane, (uint)catflags);
224 doPlane(req);
225 }
226 else
227 {
228 d.GeomSetCollideBits(ray, (uint)catflags);
229 doSpaceRay(req);
230 }
294 } 231 }
295 } 232 }
296 else 233 else
297 { 234 {
298 // if we select a geom don't use filters 235 // if we select a geom don't use filters
299 d.GeomSetCollideBits(ray, (uint)CollisionCategories.All); 236
300 doGeomRay(req); 237 if (req.callbackMethod is ProbePlaneCallback)
238 {
239 d.GeomSetCollideBits(Plane, (uint)CollisionCategories.All);
240 doPlane(req);
241 }
242 else
243 {
244 d.GeomSetCollideBits(ray, (uint)CollisionCategories.All);
245 doGeomRay(req);
246 }
301 } 247 }
302 } 248 }
303 249
@@ -382,6 +328,61 @@ namespace OpenSim.Region.Physics.OdePlugin
382 } 328 }
383 } 329 }
384 330
331 private void doProbe(ODERayRequest req, IntPtr probe)
332 {
333 // Collide tests
334 if ((CurrentRayFilter & FilterActiveSpace) != 0)
335 {
336 d.SpaceCollide2(probe, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
337 d.SpaceCollide2(probe, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
338 }
339 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
340 d.SpaceCollide2(probe, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
341 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
342 d.SpaceCollide2(probe, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
343
344 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
345 lock (m_PendingRequests)
346 {
347 cresult.AddRange(m_contactResults);
348 m_contactResults.Clear();
349 }
350 if (req.callbackMethod is ProbeBoxCallback)
351 ((ProbeBoxCallback)req.callbackMethod)(cresult);
352 else if (req.callbackMethod is ProbeSphereCallback)
353 ((ProbeSphereCallback)req.callbackMethod)(cresult);
354 }
355
356 private void doPlane(ODERayRequest req)
357 {
358 // Collide tests
359 if (req.geom == IntPtr.Zero)
360 {
361 if ((CurrentRayFilter & FilterActiveSpace) != 0)
362 {
363 d.SpaceCollide2(Plane, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
364 d.SpaceCollide2(Plane, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
365 }
366 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
367 d.SpaceCollide2(Plane, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
368 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
369 d.SpaceCollide2(Plane, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
370 }
371 else
372 {
373 d.SpaceCollide2(Plane, req.geom, IntPtr.Zero, nearCallback);
374 }
375
376 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
377 lock (m_PendingRequests)
378 {
379 cresult.AddRange(m_contactResults);
380 m_contactResults.Clear();
381 }
382
383 ((ProbePlaneCallback)req.callbackMethod)(cresult);
384 }
385
385 /// <summary> 386 /// <summary>
386 /// Method that actually initiates the raycast with a geom 387 /// Method that actually initiates the raycast with a geom
387 /// </summary> 388 /// </summary>
@@ -436,7 +437,7 @@ namespace OpenSim.Region.Physics.OdePlugin
436 private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom) 437 private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
437 { 438 {
438 IntPtr ContactgeomsArray = m_scene.ContactgeomsArray; 439 IntPtr ContactgeomsArray = m_scene.ContactgeomsArray;
439 if (ContactgeomsArray == IntPtr.Zero || index >= ColisionContactGeomsPerTest) 440 if (ContactgeomsArray == IntPtr.Zero || index >= CollisionContactGeomsPerTest)
440 return false; 441 return false;
441 442
442 IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf)); 443 IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
@@ -469,7 +470,7 @@ namespace OpenSim.Region.Physics.OdePlugin
469 int count = 0; 470 int count = 0;
470 try 471 try
471 { 472 {
472 count = d.CollidePtr(g1, g2, ColisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); 473 count = d.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
473 } 474 }
474 catch (Exception e) 475 catch (Exception e)
475 { 476 {
@@ -479,85 +480,211 @@ namespace OpenSim.Region.Physics.OdePlugin
479 480
480 if (count == 0) 481 if (count == 0)
481 return; 482 return;
482 483/*
484 uint cat1 = d.GeomGetCategoryBits(g1);
485 uint cat2 = d.GeomGetCategoryBits(g2);
486 uint col1 = d.GeomGetCollideBits(g1);
487 uint col2 = d.GeomGetCollideBits(g2);
488*/
489
483 uint ID = 0; 490 uint ID = 0;
484 PhysicsActor p2 = null; 491 PhysicsActor p2 = null;
485 492
486 m_scene.actor_name_map.TryGetValue(g2, out p2); 493 m_scene.actor_name_map.TryGetValue(g2, out p2);
487 494
488 if (p2 == null) 495 if (p2 == null)
489 {
490 /*
491 string name;
492
493 if (!m_scene.geom_name_map.TryGetValue(g2, out name))
494 return;
495
496 if (name == "Terrain")
497 {
498 // land colision
499 if ((CurrentRayFilter & RayFilterFlags.land) == 0)
500 return;
501 }
502 else if (name == "Water")
503 {
504 if ((CurrentRayFilter & RayFilterFlags.water) == 0)
505 return;
506 }
507 else
508 return;
509 */
510 return; 496 return;
511 } 497
512 else 498 switch (p2.PhysicsActorType)
513 { 499 {
514 switch (p2.PhysicsActorType) 500 case (int)ActorTypes.Prim:
515 {
516 case (int)ActorTypes.Prim:
517 501
518 RayFilterFlags thisFlags; 502 RayFilterFlags thisFlags;
519 503
520 if (p2.IsPhysical) 504 if (p2.IsPhysical)
521 thisFlags = RayFilterFlags.physical; 505 thisFlags = RayFilterFlags.physical;
522 else 506 else
523 thisFlags = RayFilterFlags.nonphysical; 507 thisFlags = RayFilterFlags.nonphysical;
524 508
525 if (p2.Phantom) 509 if (p2.Phantom)
526 thisFlags |= RayFilterFlags.phantom; 510 thisFlags |= RayFilterFlags.phantom;
527 511
528 if (p2.IsVolumeDtc) 512 if (p2.IsVolumeDtc)
529 thisFlags |= RayFilterFlags.volumedtc; 513 thisFlags |= RayFilterFlags.volumedtc;
530 514
531 if ((thisFlags & CurrentRayFilter) == 0) 515 if ((thisFlags & CurrentRayFilter) == 0)
532 return; 516 return;
533 517
534 ID = ((OdePrim)p2).LocalID; 518 ID = ((OdePrim)p2).LocalID;
535 break; 519 break;
536 520
537 case (int)ActorTypes.Agent: 521 case (int)ActorTypes.Agent:
538 522
539 if ((CurrentRayFilter & RayFilterFlags.agent) == 0) 523 if ((CurrentRayFilter & RayFilterFlags.agent) == 0)
540 return; 524 return;
541 else 525 else
542 ID = ((OdeCharacter)p2).LocalID; 526 ID = ((OdeCharacter)p2).LocalID;
543 break; 527 break;
544 528
545 case (int)ActorTypes.Ground: 529 case (int)ActorTypes.Ground:
546 530
547 if ((CurrentRayFilter & RayFilterFlags.land) == 0) 531 if ((CurrentRayFilter & RayFilterFlags.land) == 0)
548 return; 532 return;
549 break; 533 break;
550 534
551 case (int)ActorTypes.Water: 535 case (int)ActorTypes.Water:
552 536
553 if ((CurrentRayFilter & RayFilterFlags.water) == 0) 537 if ((CurrentRayFilter & RayFilterFlags.water) == 0)
554 return; 538 return;
539 break;
540
541 default:
542 break;
543 }
544
545 d.ContactGeom curcontact = new d.ContactGeom();
546
547 // closestHit for now only works for meshs, so must do it for others
548 if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0)
549 {
550 // Loop all contacts, build results.
551 for (int i = 0; i < count; i++)
552 {
553 if (!GetCurContactGeom(i, ref curcontact))
555 break; 554 break;
556 555
557 default: 556 ContactResult collisionresult = new ContactResult();
557 collisionresult.ConsumerID = ID;
558 collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z);
559 collisionresult.Depth = curcontact.depth;
560 collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y,
561 curcontact.normal.Z);
562 lock (m_contactResults)
563 {
564 m_contactResults.Add(collisionresult);
565 if (m_contactResults.Count >= CurrentMaxCount)
566 return;
567 }
568 }
569 }
570 else
571 {
572 // keep only closest contact
573 ContactResult collisionresult = new ContactResult();
574 collisionresult.ConsumerID = ID;
575 collisionresult.Depth = float.MaxValue;
576
577 for (int i = 0; i < count; i++)
578 {
579 if (!GetCurContactGeom(i, ref curcontact))
558 break; 580 break;
581
582 if (curcontact.depth < collisionresult.Depth)
583 {
584 collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z);
585 collisionresult.Depth = curcontact.depth;
586 collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y,
587 curcontact.normal.Z);
588 }
589 }
590
591 if (collisionresult.Depth != float.MaxValue)
592 {
593 lock (m_contactResults)
594 m_contactResults.Add(collisionresult);
559 } 595 }
560 } 596 }
597 }
598
599 private void nearProbe(IntPtr space, IntPtr g1, IntPtr g2)
600 {
601 if (g1 == IntPtr.Zero || g1 == g2)
602 return;
603
604 if (m_contactResults.Count >= CurrentMaxCount)
605 return;
606
607 if (d.GeomIsSpace(g1))
608 {
609 try
610 {
611 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearProbeCallback);
612 }
613 catch (Exception e)
614 {
615 m_log.WarnFormat("[PHYSICS Ray]: Unable to Space collide test an object: {0}", e.Message);
616 }
617 return;
618 }
619
620 int count = 0;
621 try
622 {
623 count = d.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
624 }
625 catch (Exception e)
626 {
627 m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message);
628 return;
629 }
630
631 if (count == 0)
632 return;
633
634 uint ID = 0;
635 PhysicsActor p1 = null;
636
637 m_scene.actor_name_map.TryGetValue(g1, out p1);
638
639 if (p1 == null)
640 return;
641
642 switch (p1.PhysicsActorType)
643 {
644 case (int)ActorTypes.Prim:
645
646 RayFilterFlags thisFlags;
647
648 if (p1.IsPhysical)
649 thisFlags = RayFilterFlags.physical;
650 else
651 thisFlags = RayFilterFlags.nonphysical;
652
653 if (p1.Phantom)
654 thisFlags |= RayFilterFlags.phantom;
655
656 if (p1.IsVolumeDtc)
657 thisFlags |= RayFilterFlags.volumedtc;
658
659 if ((thisFlags & CurrentRayFilter) == 0)
660 return;
661
662 ID = ((OdePrim)p1).LocalID;
663 break;
664
665 case (int)ActorTypes.Agent:
666
667 if ((CurrentRayFilter & RayFilterFlags.agent) == 0)
668 return;
669 else
670 ID = ((OdeCharacter)p1).LocalID;
671 break;
672
673 case (int)ActorTypes.Ground:
674
675 if ((CurrentRayFilter & RayFilterFlags.land) == 0)
676 return;
677 break;
678
679 case (int)ActorTypes.Water:
680
681 if ((CurrentRayFilter & RayFilterFlags.water) == 0)
682 return;
683 break;
684
685 default:
686 break;
687 }
561 688
562 d.ContactGeom curcontact = new d.ContactGeom(); 689 d.ContactGeom curcontact = new d.ContactGeom();
563 690
@@ -624,6 +751,21 @@ namespace OpenSim.Region.Physics.OdePlugin
624 d.GeomDestroy(ray); 751 d.GeomDestroy(ray);
625 ray = IntPtr.Zero; 752 ray = IntPtr.Zero;
626 } 753 }
754 if (Box != IntPtr.Zero)
755 {
756 d.GeomDestroy(Box);
757 Box = IntPtr.Zero;
758 }
759 if (Sphere != IntPtr.Zero)
760 {
761 d.GeomDestroy(Sphere);
762 Sphere = IntPtr.Zero;
763 }
764 if (Plane != IntPtr.Zero)
765 {
766 d.GeomDestroy(Plane);
767 Plane = IntPtr.Zero;
768 }
627 } 769 }
628 } 770 }
629 771
@@ -636,5 +778,6 @@ namespace OpenSim.Region.Physics.OdePlugin
636 public float length; 778 public float length;
637 public object callbackMethod; 779 public object callbackMethod;
638 public RayFilterFlags filter; 780 public RayFilterFlags filter;
781 public Quaternion orientation;
639 } 782 }
640} \ No newline at end of file 783} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs
index 225bff8..ecc732a 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs
@@ -52,6 +52,21 @@ namespace OpenSim.Region.Physics.OdePlugin
52 } 52 }
53 53
54 private static Vector3 SitAjust = new Vector3(0, 0, 0.4f); 54 private static Vector3 SitAjust = new Vector3(0, 0, 0.4f);
55 private const RayFilterFlags RaySitFlags = RayFilterFlags.AllPrims | RayFilterFlags.ClosestHit;
56
57 private void RotAroundZ(float x, float y, ref Quaternion ori)
58 {
59 double ang = Math.Atan2(y, x);
60 ang *= 0.5d;
61 float s = (float)Math.Sin(ang);
62 float c = (float)Math.Cos(ang);
63
64 ori.X = 0;
65 ori.Y = 0;
66 ori.Z = s;
67 ori.W = c;
68 }
69
55 70
56 public void Sit(PhysicsActor actor, Vector3 avPos, Vector3 avCameraPosition, Vector3 offset, Vector3 avOffset, SitAvatarCallback PhysicsSitResponse) 71 public void Sit(PhysicsActor actor, Vector3 avPos, Vector3 avCameraPosition, Vector3 offset, Vector3 avOffset, SitAvatarCallback PhysicsSitResponse)
57 { 72 {
@@ -63,88 +78,82 @@ namespace OpenSim.Region.Physics.OdePlugin
63 78
64 IntPtr geom = ((OdePrim)actor).prim_geom; 79 IntPtr geom = ((OdePrim)actor).prim_geom;
65 80
66 d.Vector3 dtmp = d.GeomGetPosition(geom); 81 Vector3 geopos = d.GeomGetPositionOMV(geom);
67 Vector3 geopos; 82 Quaternion geomOri = d.GeomGetQuaternionOMV(geom);
68 geopos.X = dtmp.X; 83 Quaternion geomInvOri = Quaternion.Conjugate(geomOri);
69 geopos.Y = dtmp.Y; 84
70 geopos.Z = dtmp.Z; 85 Quaternion ori = Quaternion.Identity;
71 86
72 87 Vector3 rayDir = geopos + offset - avCameraPosition;
73 d.AABB aabb; 88
74 Quaternion ori;
75 d.Quaternion qtmp;
76 d.GeomCopyQuaternion(geom, out qtmp);
77 Quaternion geomOri;
78 geomOri.X = qtmp.X;
79 geomOri.Y = qtmp.Y;
80 geomOri.Z = qtmp.Z;
81 geomOri.W = qtmp.W;
82 Quaternion geomInvOri;
83 geomInvOri.X = -qtmp.X;
84 geomInvOri.Y = -qtmp.Y;
85 geomInvOri.Z = -qtmp.Z;
86 geomInvOri.W = qtmp.W;
87
88 Vector3 target = geopos + offset;
89 Vector3 rayDir = target - avCameraPosition;
90 float raylen = rayDir.Length(); 89 float raylen = rayDir.Length();
90 if (raylen < 0.001f)
91 {
92 PhysicsSitResponse(-1, actor.LocalID, offset, Quaternion.Identity);
93 return;
94 }
91 float t = 1 / raylen; 95 float t = 1 / raylen;
92 rayDir.X *= t; 96 rayDir.X *= t;
93 rayDir.Y *= t; 97 rayDir.Y *= t;
94 rayDir.Z *= t; 98 rayDir.Z *= t;
95 99
96 raylen += 0.5f; 100 raylen += 30f; // focal point may be far
97 List<ContactResult> rayResults; 101 List<ContactResult> rayResults;
98 102
99 rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir , raylen, 1); 103 rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir, raylen, 1, RaySitFlags);
100 if (rayResults.Count == 0 || rayResults[0].ConsumerID != actor.LocalID) 104 if (rayResults.Count == 0)
101 { 105 {
102 d.GeomGetAABB(geom,out aabb); 106/* if this fundamental ray failed, then just fail so user can try another spot and not be sitted far on a big prim
107 d.AABB aabb;
108 d.GeomGetAABB(geom, out aabb);
103 offset = new Vector3(avOffset.X, 0, aabb.MaxZ + avOffset.Z - geopos.Z); 109 offset = new Vector3(avOffset.X, 0, aabb.MaxZ + avOffset.Z - geopos.Z);
104 ori = geomInvOri; 110 ori = geomInvOri;
105 offset *= geomInvOri; 111 offset *= geomInvOri;
106
107 PhysicsSitResponse(1, actor.LocalID, offset, ori); 112 PhysicsSitResponse(1, actor.LocalID, offset, ori);
113*/
114 PhysicsSitResponse(0, actor.LocalID, offset, ori);
108 return; 115 return;
109 } 116 }
110 117
118 int status = 1;
111 offset = rayResults[0].Pos - geopos; 119 offset = rayResults[0].Pos - geopos;
112 double ang;
113 float s;
114 float c;
115 120
116 d.GeomClassID geoclass = d.GeomGetClass(geom); 121 d.GeomClassID geoclass = d.GeomGetClass(geom);
117 122
118 if (geoclass == d.GeomClassID.SphereClass) 123 if (geoclass == d.GeomClassID.SphereClass)
119 { 124 {
120 float r = d.GeomSphereGetRadius(geom); 125 float r = d.GeomSphereGetRadius(geom);
121 126
122 offset.Normalize(); 127 offset.Normalize();
123 offset *= r; 128 offset *= r;
124 129
125 ang = Math.Atan2(offset.Y, offset.X); 130 RotAroundZ(offset.X, offset.Y, ref ori);
126 ang *= 0.5d;
127 s = (float)Math.Sin(ang);
128 c = (float)Math.Cos(ang);
129
130 ori = new Quaternion(0, 0, s, c);
131 131
132 if (r < 0.4f) 132 if (r < 0.4f)
133 { 133 {
134 offset = new Vector3(0, 0, r); 134 offset = new Vector3(0, 0, r);
135 } 135 }
136 else if (offset.Z < 0.4f) 136 else
137 { 137 {
138 t = offset.Z; 138 if (offset.Z < 0.4f)
139 float rsq = r * r; 139 {
140 140 t = offset.Z;
141 t = 1.0f / (rsq - t * t); 141 float rsq = r * r;
142 offset.X *= t; 142
143 offset.Y *= t; 143 t = 1.0f / (rsq - t * t);
144 offset.Z = 0.4f; 144 offset.X *= t;
145 t = rsq - 0.16f; 145 offset.Y *= t;
146 offset.X *= t; 146 offset.Z = 0.4f;
147 offset.Y *= t; 147 t = rsq - 0.16f;
148 offset.X *= t;
149 offset.Y *= t;
150 }
151 else if (r > 0.8f && offset.Z > 0.8f * r)
152 {
153 status = 3;
154 avOffset.X = -avOffset.X;
155 avOffset.Z *= 1.6f;
156 }
148 } 157 }
149 158
150 offset += avOffset * ori; 159 offset += avOffset * ori;
@@ -152,26 +161,189 @@ namespace OpenSim.Region.Physics.OdePlugin
152 ori = geomInvOri * ori; 161 ori = geomInvOri * ori;
153 offset *= geomInvOri; 162 offset *= geomInvOri;
154 163
155 PhysicsSitResponse(1, actor.LocalID, offset, ori); 164 PhysicsSitResponse(status, actor.LocalID, offset, ori);
156 return; 165 return;
157 } 166 }
158 167
159 Vector3 norm = rayResults[0].Normal; 168 Vector3 norm = rayResults[0].Normal;
160 169
161 if (norm.Z < 0) 170 if (norm.Z < -0.4f)
162 { 171 {
163 PhysicsSitResponse(0, actor.LocalID, offset, Quaternion.Identity); 172 PhysicsSitResponse(0, actor.LocalID, offset, Quaternion.Identity);
164 return; 173 return;
165 } 174 }
166 175
167 ang = Math.Atan2(-rayDir.Y, -rayDir.X);
168 ang *= 0.5d;
169 s = (float)Math.Sin(ang);
170 c = (float)Math.Cos(ang);
171 176
172 ori = new Quaternion(0, 0, s, c); 177 float SitNormX = -rayDir.X;
178 float SitNormY = -rayDir.Y;
179
180 Vector3 pivot = geopos + offset;
181
182 float edgeNormalX = norm.X;
183 float edgeNormalY = norm.Y;
184 float edgeDirX = -rayDir.X;
185 float edgeDirY = -rayDir.Y;
186 Vector3 edgePos = rayResults[0].Pos;
187 float edgeDist = float.MaxValue;
188
189 bool foundEdge = false;
190
191 if (norm.Z < 0.5f)
192 {
193 float rayDist = 4.0f;
194 float curEdgeDist = 0.0f;
195
196 for (int i = 0; i < 6; i++)
197 {
198 pivot.X -= 0.005f * norm.X;
199 pivot.Y -= 0.005f * norm.Y;
200 pivot.Z -= 0.005f * norm.Z;
201
202 rayDir.X = -norm.X * norm.Z;
203 rayDir.Y = -norm.Y * norm.Z;
204 rayDir.Z = 1.0f - norm.Z * norm.Z;
205 rayDir.Normalize();
206
207 rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims);
208 if (rayResults.Count == 0)
209 break;
210
211 curEdgeDist += rayResults[0].Depth;
212
213 if (Math.Abs(rayResults[0].Normal.Z) < 0.7f)
214 {
215 rayDist -= rayResults[0].Depth;
216 if (rayDist < 0f)
217 break;
218
219 pivot = rayResults[0].Pos;
220 norm = rayResults[0].Normal;
221 edgeNormalX = norm.X;
222 edgeNormalY = norm.Y;
223 edgeDirX = -rayDir.X;
224 edgeDirY = -rayDir.Y;
225 }
226 else
227 {
228 foundEdge = true;
229 edgeDist = curEdgeDist;
230 edgePos = rayResults[0].Pos;
231 break;
232 }
233 }
234
235 if (!foundEdge)
236 {
237 PhysicsSitResponse(0, actor.LocalID, offset, ori);
238 return;
239 }
240 avOffset.X *= 0.5f;
241 }
242
243 else if (norm.Z > 0.866f)
244 {
245 float toCamBaseX = avCameraPosition.X - pivot.X;
246 float toCamBaseY = avCameraPosition.Y - pivot.Y;
247 float toCamX = toCamBaseX;
248 float toCamY = toCamBaseY;
249
250 for (int j = 0; j < 4; j++)
251 {
252 float rayDist = 1.0f;
253 float curEdgeDist = 0.0f;
254
255 for (int i = 0; i < 3; i++)
256 {
257 pivot.Z -= 0.005f;
258 rayDir.X = toCamX;
259 rayDir.Y = toCamY;
260 rayDir.Z = (-toCamX * norm.X - toCamY * norm.Y) / norm.Z;
261 rayDir.Normalize();
262
263 rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims);
264 if (rayResults.Count == 0)
265 break;
266
267 curEdgeDist += rayResults[0].Depth;
268
269 if (rayResults[0].Normal.Z > 0.5f)
270 {
271 rayDist -= rayResults[0].Depth;
272 if (rayDist < 0f)
273 break;
274
275 pivot = rayResults[0].Pos;
276 norm = rayResults[0].Normal;
277 }
278 else
279 {
280 foundEdge = true;
281 if (curEdgeDist < edgeDist)
282 {
283 edgeDist = curEdgeDist;
284 edgeNormalX = rayResults[0].Normal.X;
285 edgeNormalY = rayResults[0].Normal.Y;
286 edgeDirX = rayDir.X;
287 edgeDirY = rayDir.Y;
288 edgePos = rayResults[0].Pos;
289 }
290 break;
291 }
292 }
293 if (foundEdge && edgeDist < 0.2f)
294 break;
295
296 pivot = geopos + offset;
297
298 switch (j)
299 {
300 case 0:
301 toCamX = -toCamBaseY;
302 toCamY = toCamBaseX;
303 break;
304 case 1:
305 toCamX = toCamBaseY;
306 toCamY = -toCamBaseX;
307 break;
308 case 2:
309 toCamX = -toCamBaseX;
310 toCamY = -toCamBaseY;
311 break;
312 default:
313 break;
314 }
315 }
316
317 if (!foundEdge)
318 {
319 avOffset.X = -avOffset.X;
320 avOffset.Z *= 1.6f;
321
322 RotAroundZ(SitNormX, SitNormY, ref ori);
323
324 offset += avOffset * ori;
325
326 ori = geomInvOri * ori;
327 offset *= geomInvOri;
328
329 PhysicsSitResponse(3, actor.LocalID, offset, ori);
330 return;
331 }
332 avOffset.X *= 0.5f;
333 }
334
335 SitNormX = edgeNormalX;
336 SitNormY = edgeNormalY;
337 if (edgeDirX * SitNormX + edgeDirY * SitNormY < 0)
338 {
339 SitNormX = -SitNormX;
340 SitNormY = -SitNormY;
341 }
342
343 RotAroundZ(SitNormX, SitNormY, ref ori);
173 344
174 offset += avOffset * ori; 345 offset = edgePos + avOffset * ori;
346 offset -= geopos;
175 347
176 ori = geomInvOri * ori; 348 ori = geomInvOri * ori;
177 offset *= geomInvOri; 349 offset *= geomInvOri;
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs
index 403a4ce..10d7d50 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs
@@ -44,7 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44using System; 44using System;
45using System.Runtime.InteropServices; 45using System.Runtime.InteropServices;
46using System.Security; 46using System.Security;
47 47using OMV = OpenMetaverse;
48namespace OdeAPI 48namespace OdeAPI
49{ 49{
50//#if dDOUBLE 50//#if dDOUBLE
@@ -925,9 +925,20 @@ namespace OdeAPI
925 { 925 {
926 unsafe { return *(GeomGetPositionUnsafe(geom)); } 926 unsafe { return *(GeomGetPositionUnsafe(geom)); }
927 } 927 }
928 public static OMV.Vector3 GeomGetPositionOMV(IntPtr geom)
929 {
930 Vector3 vtmp = GeomGetPosition(geom);
931 return new OMV.Vector3(vtmp.X, vtmp.Y, vtmp.Z);
932 }
928 933
929 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity] 934 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity]
930 public static extern void GeomCopyQuaternion(IntPtr geom, out Quaternion q); 935 public static extern void GeomCopyQuaternion(IntPtr geom, out Quaternion q);
936 public static OMV.Quaternion GeomGetQuaternionOMV(IntPtr geom)
937 {
938 Quaternion qtmp;
939 GeomCopyQuaternion(geom, out qtmp);
940 return new OMV.Quaternion(qtmp.X, qtmp.Y, qtmp.Z, qtmp.W);
941 }
931 942
932 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity] 943 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity]
933 public static extern void GeomCopyQuaternion(IntPtr geom, out dReal X); 944 public static extern void GeomCopyQuaternion(IntPtr geom, out dReal X);
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
index fbf2f0d..d045b59 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
@@ -2579,7 +2579,16 @@ namespace OpenSim.Region.Physics.OdePlugin
2579 { 2579 {
2580 if (retMethod != null) 2580 if (retMethod != null)
2581 { 2581 {
2582 m_rayCastManager.QueueRequest(position, direction, length, retMethod); 2582 ODERayRequest req = new ODERayRequest();
2583 req.geom = IntPtr.Zero;
2584 req.callbackMethod = retMethod;
2585 req.length = length;
2586 req.Normal = direction;
2587 req.Origin = position;
2588 req.Count = 0;
2589 req.filter = RayFilterFlags.All;
2590
2591 m_rayCastManager.QueueRequest(req);
2583 } 2592 }
2584 } 2593 }
2585 2594
@@ -2587,29 +2596,51 @@ namespace OpenSim.Region.Physics.OdePlugin
2587 { 2596 {
2588 if (retMethod != null) 2597 if (retMethod != null)
2589 { 2598 {
2590 m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod); 2599 ODERayRequest req = new ODERayRequest();
2600 req.geom = IntPtr.Zero;
2601 req.callbackMethod = retMethod;
2602 req.length = length;
2603 req.Normal = direction;
2604 req.Origin = position;
2605 req.Count = Count;
2606 req.filter = RayFilterFlags.All;
2607
2608 m_rayCastManager.QueueRequest(req);
2591 } 2609 }
2592 } 2610 }
2593 2611
2594 // don't like this 2612
2595 public override List<ContactResult> RaycastWorld(Vector3 position, Vector3 direction, float length, int Count) 2613 public override List<ContactResult> RaycastWorld(Vector3 position, Vector3 direction, float length, int Count)
2596 { 2614 {
2597 ContactResult[] ourResults = null; 2615 List<ContactResult> ourresults = new List<ContactResult>();
2616 object SyncObject = new object();
2617
2598 RayCallback retMethod = delegate(List<ContactResult> results) 2618 RayCallback retMethod = delegate(List<ContactResult> results)
2599 { 2619 {
2600 ourResults = new ContactResult[results.Count]; 2620 lock (SyncObject)
2601 results.CopyTo(ourResults, 0); 2621 {
2622 ourresults = results;
2623 Monitor.PulseAll(SyncObject);
2624 }
2602 }; 2625 };
2603 int waitTime = 0; 2626
2604 m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod); 2627 ODERayRequest req = new ODERayRequest();
2605 while (ourResults == null && waitTime < 1000) 2628 req.geom = IntPtr.Zero;
2629 req.callbackMethod = retMethod;
2630 req.length = length;
2631 req.Normal = direction;
2632 req.Origin = position;
2633 req.Count = Count;
2634 req.filter = RayFilterFlags.All;
2635
2636 lock (SyncObject)
2606 { 2637 {
2607 Thread.Sleep(1); 2638 m_rayCastManager.QueueRequest(req);
2608 waitTime++; 2639 if (!Monitor.Wait(SyncObject, 500))
2640 return null;
2641 else
2642 return ourresults;
2609 } 2643 }
2610 if (ourResults == null)
2611 return new List<ContactResult>();
2612 return new List<ContactResult>(ourResults);
2613 } 2644 }
2614 2645
2615 public override bool SuportsRaycastWorldFiltered() 2646 public override bool SuportsRaycastWorldFiltered()
@@ -2631,9 +2662,18 @@ namespace OpenSim.Region.Physics.OdePlugin
2631 } 2662 }
2632 }; 2663 };
2633 2664
2665 ODERayRequest req = new ODERayRequest();
2666 req.geom = IntPtr.Zero;
2667 req.callbackMethod = retMethod;
2668 req.length = length;
2669 req.Normal = direction;
2670 req.Origin = position;
2671 req.Count = Count;
2672 req.filter = filter;
2673
2634 lock (SyncObject) 2674 lock (SyncObject)
2635 { 2675 {
2636 m_rayCastManager.QueueRequest(position, direction, length, Count,filter, retMethod); 2676 m_rayCastManager.QueueRequest(req);
2637 if (!Monitor.Wait(SyncObject, 500)) 2677 if (!Monitor.Wait(SyncObject, 500))
2638 return null; 2678 return null;
2639 else 2679 else
@@ -2641,74 +2681,163 @@ namespace OpenSim.Region.Physics.OdePlugin
2641 } 2681 }
2642 } 2682 }
2643 2683
2644 public override void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) 2684 public override List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags)
2645 { 2685 {
2646 if (retMethod != null && actor !=null) 2686 if (actor == null)
2687 return new List<ContactResult>();
2688
2689 IntPtr geom;
2690 if (actor is OdePrim)
2691 geom = ((OdePrim)actor).prim_geom;
2692 else if (actor is OdeCharacter)
2693 geom = ((OdePrim)actor).prim_geom;
2694 else
2695 return new List<ContactResult>();
2696
2697 if (geom == IntPtr.Zero)
2698 return new List<ContactResult>();
2699
2700 List<ContactResult> ourResults = null;
2701 object SyncObject = new object();
2702
2703 RayCallback retMethod = delegate(List<ContactResult> results)
2647 { 2704 {
2648 IntPtr geom; 2705 lock (SyncObject)
2649 if (actor is OdePrim) 2706 {
2650 geom = ((OdePrim)actor).prim_geom; 2707 ourResults = results;
2651 else if (actor is OdeCharacter) 2708 Monitor.PulseAll(SyncObject);
2652 geom = ((OdePrim)actor).prim_geom; 2709 }
2653 else 2710 };
2654 return; 2711
2655 if (geom == IntPtr.Zero) 2712 ODERayRequest req = new ODERayRequest();
2656 return; 2713 req.geom = geom;
2657 m_rayCastManager.QueueRequest(geom, position, direction, length, retMethod); 2714 req.callbackMethod = retMethod;
2715 req.length = length;
2716 req.Normal = direction;
2717 req.Origin = position;
2718 req.Count = Count;
2719 req.filter = flags;
2720
2721 lock (SyncObject)
2722 {
2723 m_rayCastManager.QueueRequest(req);
2724 if (!Monitor.Wait(SyncObject, 500))
2725 return new List<ContactResult>();
2658 } 2726 }
2727
2728 if (ourResults == null)
2729 return new List<ContactResult>();
2730 return ourResults;
2659 } 2731 }
2660 2732
2661 public override void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) 2733 public override List<ContactResult> BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags)
2662 { 2734 {
2663 if (retMethod != null && actor != null) 2735 List<ContactResult> ourResults = null;
2736 object SyncObject = new object();
2737
2738 ProbeBoxCallback retMethod = delegate(List<ContactResult> results)
2664 { 2739 {
2665 IntPtr geom; 2740 lock (SyncObject)
2666 if (actor is OdePrim) 2741 {
2667 geom = ((OdePrim)actor).prim_geom; 2742 ourResults = results;
2668 else if (actor is OdeCharacter) 2743 Monitor.PulseAll(SyncObject);
2669 geom = ((OdePrim)actor).prim_geom; 2744 }
2670 else 2745 };
2671 return; 2746
2672 if (geom == IntPtr.Zero) 2747 ODERayRequest req = new ODERayRequest();
2673 return; 2748 req.geom = IntPtr.Zero;
2749 req.callbackMethod = retMethod;
2750 req.Normal = size;
2751 req.Origin = position;
2752 req.orientation = orientation;
2753 req.Count = Count;
2754 req.filter = flags;
2755
2756 lock (SyncObject)
2757 {
2758 m_rayCastManager.QueueRequest(req);
2759 if (!Monitor.Wait(SyncObject, 500))
2760 return new List<ContactResult>();
2761 }
2762
2763 if (ourResults == null)
2764 return new List<ContactResult>();
2765 return ourResults;
2766 }
2767
2768 public override List<ContactResult> SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags)
2769 {
2770 List<ContactResult> ourResults = null;
2771 object SyncObject = new object();
2772
2773 ProbeSphereCallback retMethod = delegate(List<ContactResult> results)
2774 {
2775 ourResults = results;
2776 Monitor.PulseAll(SyncObject);
2777 };
2778
2779 ODERayRequest req = new ODERayRequest();
2780 req.geom = IntPtr.Zero;
2781 req.callbackMethod = retMethod;
2782 req.length = radius;
2783 req.Origin = position;
2784 req.Count = Count;
2785 req.filter = flags;
2674 2786
2675 m_rayCastManager.QueueRequest(geom,position, direction, length, Count, retMethod); 2787
2788 lock (SyncObject)
2789 {
2790 m_rayCastManager.QueueRequest(req);
2791 if (!Monitor.Wait(SyncObject, 500))
2792 return new List<ContactResult>();
2676 } 2793 }
2794
2795 if (ourResults == null)
2796 return new List<ContactResult>();
2797 return ourResults;
2677 } 2798 }
2678 2799
2679 // don't like this 2800 public override List<ContactResult> PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags)
2680 public override List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count)
2681 { 2801 {
2802 IntPtr geom = IntPtr.Zero;;
2803
2682 if (actor != null) 2804 if (actor != null)
2683 { 2805 {
2684 IntPtr geom;
2685 if (actor is OdePrim) 2806 if (actor is OdePrim)
2686 geom = ((OdePrim)actor).prim_geom; 2807 geom = ((OdePrim)actor).prim_geom;
2687 else if (actor is OdeCharacter) 2808 else if (actor is OdeCharacter)
2688 geom = ((OdePrim)actor).prim_geom; 2809 geom = ((OdePrim)actor).prim_geom;
2689 else 2810 }
2690 return new List<ContactResult>();
2691 if (geom == IntPtr.Zero)
2692 return new List<ContactResult>();
2693 2811
2694 ContactResult[] ourResults = null; 2812 List<ContactResult> ourResults = null;
2695 RayCallback retMethod = delegate(List<ContactResult> results) 2813 object SyncObject = new object();
2696 { 2814
2697 ourResults = new ContactResult[results.Count]; 2815 ProbePlaneCallback retMethod = delegate(List<ContactResult> results)
2698 results.CopyTo(ourResults, 0); 2816 {
2699 }; 2817 ourResults = results;
2700 int waitTime = 0; 2818 Monitor.PulseAll(SyncObject);
2701 m_rayCastManager.QueueRequest(geom,position, direction, length, Count, retMethod); 2819 };
2702 while (ourResults == null && waitTime < 1000) 2820
2703 { 2821 ODERayRequest req = new ODERayRequest();
2704 Thread.Sleep(1); 2822 req.geom = geom;
2705 waitTime++; 2823 req.callbackMethod = retMethod;
2706 } 2824 req.length = plane.W;
2707 if (ourResults == null) 2825 req.Normal.X = plane.X;
2826 req.Normal.Y = plane.Y;
2827 req.Normal.Z = plane.Z;
2828 req.Count = Count;
2829 req.filter = flags;
2830
2831 lock (SyncObject)
2832 {
2833 m_rayCastManager.QueueRequest(req);
2834 if (!Monitor.Wait(SyncObject, 500))
2708 return new List<ContactResult>(); 2835 return new List<ContactResult>();
2709 return new List<ContactResult>(ourResults);
2710 } 2836 }
2711 return new List<ContactResult>(); 2837
2838 if (ourResults == null)
2839 return new List<ContactResult>();
2840 return ourResults;
2712 } 2841 }
2713 2842
2714 public override int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse) 2843 public override int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse)