aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs')
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs326
1 files changed, 243 insertions, 83 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
index 4b3f83b..e66580d 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
@@ -30,10 +30,11 @@ using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Runtime.InteropServices; 31using System.Runtime.InteropServices;
32using System.Text; 32using System.Text;
33using OpenMetaverse; 33using OpenSim.Framework;
34using OpenSim.Region.Physics.Manager; 34using OpenSim.Region.Physics.Manager;
35using OdeAPI; 35using OdeAPI;
36using log4net; 36using log4net;
37using OpenMetaverse;
37 38
38namespace OpenSim.Region.Physics.OdePlugin 39namespace OpenSim.Region.Physics.OdePlugin
39{ 40{
@@ -54,9 +55,11 @@ namespace OpenSim.Region.Physics.OdePlugin
54 /// </summary> 55 /// </summary>
55 private OdeScene m_scene; 56 private OdeScene m_scene;
56 57
57 IntPtr ray; 58 IntPtr ray; // the ray. we only need one for our lifetime
58 59
59 private const int ColisionContactGeomsPerTest = 5; 60 private const int ColisionContactGeomsPerTest = 5;
61 private const int DefaultMaxCount = 25;
62 private const int MaxTimePerCallMS = 30;
60 63
61 /// <summary> 64 /// <summary>
62 /// ODE near callback delegate 65 /// ODE near callback delegate
@@ -64,19 +67,22 @@ namespace OpenSim.Region.Physics.OdePlugin
64 private d.NearCallback nearCallback; 67 private d.NearCallback nearCallback;
65 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 68 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
66 private List<ContactResult> m_contactResults = new List<ContactResult>(); 69 private List<ContactResult> m_contactResults = new List<ContactResult>();
70 private RayFilterFlags CurrentRayFilter;
71 private int CurrentMaxCount;
67 72
68 public ODERayCastRequestManager(OdeScene pScene) 73 public ODERayCastRequestManager(OdeScene pScene)
69 { 74 {
70 m_scene = pScene; 75 m_scene = pScene;
71 nearCallback = near; 76 nearCallback = near;
72 ray = d.CreateRay(IntPtr.Zero, 1.0f); 77 ray = d.CreateRay(IntPtr.Zero, 1.0f);
78 d.GeomSetCategoryBits(ray,0);
73 } 79 }
74 80
75 /// <summary> 81 /// <summary>
76 /// Queues a raycast 82 /// Queues request for a raycast to all world
77 /// </summary> 83 /// </summary>
78 /// <param name="position">Origin of Ray</param> 84 /// <param name="position">Origin of Ray</param>
79 /// <param name="direction">Ray normal</param> 85 /// <param name="direction">Ray direction</param>
80 /// <param name="length">Ray length</param> 86 /// <param name="length">Ray length</param>
81 /// <param name="retMethod">Return method to send the results</param> 87 /// <param name="retMethod">Return method to send the results</param>
82 public void QueueRequest(Vector3 position, Vector3 direction, float length, RayCallback retMethod) 88 public void QueueRequest(Vector3 position, Vector3 direction, float length, RayCallback retMethod)
@@ -84,14 +90,22 @@ namespace OpenSim.Region.Physics.OdePlugin
84 ODERayRequest req = new ODERayRequest(); 90 ODERayRequest req = new ODERayRequest();
85 req.geom = IntPtr.Zero; 91 req.geom = IntPtr.Zero;
86 req.callbackMethod = retMethod; 92 req.callbackMethod = retMethod;
87 req.Count = 0; 93 req.Count = DefaultMaxCount;
88 req.length = length; 94 req.length = length;
89 req.Normal = direction; 95 req.Normal = direction;
90 req.Origin = position; 96 req.Origin = position;
97 req.filter = RayFilterFlags.AllButLand;
91 98
92 m_PendingRequests.Enqueue(req); 99 m_PendingRequests.Enqueue(req);
93 } 100 }
94 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>
95 public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RayCallback retMethod) 109 public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RayCallback retMethod)
96 { 110 {
97 ODERayRequest req = new ODERayRequest(); 111 ODERayRequest req = new ODERayRequest();
@@ -100,7 +114,8 @@ namespace OpenSim.Region.Physics.OdePlugin
100 req.length = length; 114 req.length = length;
101 req.Normal = direction; 115 req.Normal = direction;
102 req.Origin = position; 116 req.Origin = position;
103 req.Count = 0; 117 req.Count = DefaultMaxCount;
118 req.filter = RayFilterFlags.AllButLand;
104 119
105 m_PendingRequests.Enqueue(req); 120 m_PendingRequests.Enqueue(req);
106 } 121 }
@@ -110,10 +125,11 @@ namespace OpenSim.Region.Physics.OdePlugin
110 ODERayRequest req = new ODERayRequest(); 125 ODERayRequest req = new ODERayRequest();
111 req.geom = IntPtr.Zero; 126 req.geom = IntPtr.Zero;
112 req.callbackMethod = retMethod; 127 req.callbackMethod = retMethod;
113 req.Count = 0; 128 req.Count = DefaultMaxCount;
114 req.length = length; 129 req.length = length;
115 req.Normal = direction; 130 req.Normal = direction;
116 req.Origin = position; 131 req.Origin = position;
132 req.filter = RayFilterFlags.AllButLand;
117 133
118 m_PendingRequests.Enqueue(req); 134 m_PendingRequests.Enqueue(req);
119 } 135 }
@@ -126,7 +142,8 @@ namespace OpenSim.Region.Physics.OdePlugin
126 req.length = length; 142 req.length = length;
127 req.Normal = direction; 143 req.Normal = direction;
128 req.Origin = position; 144 req.Origin = position;
129 req.Count = 0; 145 req.Count = DefaultMaxCount;
146 req.filter = RayFilterFlags.AllButLand;
130 147
131 m_PendingRequests.Enqueue(req); 148 m_PendingRequests.Enqueue(req);
132 } 149 }
@@ -148,6 +165,22 @@ namespace OpenSim.Region.Physics.OdePlugin
148 req.Normal = direction; 165 req.Normal = direction;
149 req.Origin = position; 166 req.Origin = position;
150 req.Count = count; 167 req.Count = count;
168 req.filter = RayFilterFlags.AllButLand;
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;
151 184
152 m_PendingRequests.Enqueue(req); 185 m_PendingRequests.Enqueue(req);
153 } 186 }
@@ -161,6 +194,7 @@ namespace OpenSim.Region.Physics.OdePlugin
161 req.Normal = direction; 194 req.Normal = direction;
162 req.Origin = position; 195 req.Origin = position;
163 req.Count = count; 196 req.Count = count;
197 req.filter = RayFilterFlags.AllButLand;
164 198
165 m_PendingRequests.Enqueue(req); 199 m_PendingRequests.Enqueue(req);
166 } 200 }
@@ -174,6 +208,7 @@ namespace OpenSim.Region.Physics.OdePlugin
174 req.Normal = direction; 208 req.Normal = direction;
175 req.Origin = position; 209 req.Origin = position;
176 req.Count = count; 210 req.Count = count;
211 req.filter = RayFilterFlags.AllButLand;
177 212
178 m_PendingRequests.Enqueue(req); 213 m_PendingRequests.Enqueue(req);
179 } 214 }
@@ -187,6 +222,7 @@ namespace OpenSim.Region.Physics.OdePlugin
187 req.Normal = direction; 222 req.Normal = direction;
188 req.Origin = position; 223 req.Origin = position;
189 req.Count = count; 224 req.Count = count;
225 req.filter = RayFilterFlags.AllButLand;
190 226
191 m_PendingRequests.Enqueue(req); 227 m_PendingRequests.Enqueue(req);
192 } 228 }
@@ -197,63 +233,104 @@ namespace OpenSim.Region.Physics.OdePlugin
197 /// <returns>Time in MS the raycasts took to process.</returns> 233 /// <returns>Time in MS the raycasts took to process.</returns>
198 public int ProcessQueuedRequests() 234 public int ProcessQueuedRequests()
199 { 235 {
200 int time = System.Environment.TickCount;
201 236
202 if (m_PendingRequests.Count <= 0) 237 if (m_PendingRequests.Count <= 0)
203 return 0; 238 return 0;
204 239
205 if (m_scene.ContactgeomsArray == IntPtr.Zero) // oops something got wrong or scene isn't ready still 240 if (m_scene.ContactgeomsArray == IntPtr.Zero || ray == IntPtr.Zero)
241 // oops something got wrong or scene isn't ready still
206 { 242 {
207 m_PendingRequests.Clear(); 243 m_PendingRequests.Clear();
208 return 0; 244 return 0;
209 } 245 }
210 246
211 ODERayRequest req; 247 int time = Util.EnvironmentTickCount();
212 248
213 int i = 50; // arbitary limit of processed tests per frame 249 ODERayRequest req;
250 int closestHit;
251 int backfacecull;
252 CollisionCategories catflags;
214 253
215 while(m_PendingRequests.Dequeue(out req)) 254 while (m_PendingRequests.Dequeue(out req))
216 { 255 {
217 if (req.geom == IntPtr.Zero) 256 if (req.callbackMethod != null)
218 doSpaceRay(req); 257 {
219 else 258 CurrentRayFilter = req.filter;
220 doGeomRay(req); 259 CurrentMaxCount = req.Count;
221 if(--i < 0) 260
222 break; 261 closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1);
262 backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1);
263
264 d.GeomRaySetLength(ray, req.length);
265 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
266 d.GeomRaySetParams(ray, 0, backfacecull);
267 d.GeomRaySetClosestHit(ray, closestHit);
268
269 if (req.callbackMethod is RaycastCallback)
270 // if we only want one get only one per colision pair saving memory
271 CurrentRayFilter |= RayFilterFlags.ClosestHit;
272
273 if (req.geom == IntPtr.Zero)
274 {
275 // translate ray filter to colision flags
276 catflags = 0;
277 if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0)
278 catflags |= CollisionCategories.VolumeDtc;
279 if ((CurrentRayFilter & RayFilterFlags.phantom) != 0)
280 catflags |= CollisionCategories.Phantom;
281 if ((CurrentRayFilter & RayFilterFlags.agent) != 0)
282 catflags |= CollisionCategories.Character;
283 if ((CurrentRayFilter & RayFilterFlags.PrimsNonPhantom) != 0)
284 catflags |= CollisionCategories.Geom;
285 if ((CurrentRayFilter & RayFilterFlags.land) != 0)
286 catflags |= CollisionCategories.Land;
287 if ((CurrentRayFilter & RayFilterFlags.water) != 0)
288 catflags |= CollisionCategories.Water;
289
290 if (catflags != 0)
291 doSpaceRay(req);
292 }
293 else
294 {
295 // if we select a geom don't use filters
296 d.GeomSetCollideBits(ray, (uint)CollisionCategories.All);
297 doGeomRay(req);
298 }
299 }
300
301 if (Util.EnvironmentTickCountSubtract(time) > MaxTimePerCallMS)
302 break;
223 } 303 }
224 304
225 lock (m_contactResults) 305 lock (m_contactResults)
226 m_contactResults.Clear(); 306 m_contactResults.Clear();
227 307
228 return System.Environment.TickCount - time; 308 return Util.EnvironmentTickCountSubtract(time);
229 } 309 }
230 /// <summary> 310 /// <summary>
231 /// Method that actually initiates the raycast with full top space 311 /// Method that actually initiates the raycast with spaces
232 /// </summary> 312 /// </summary>
233 /// <param name="req"></param> 313 /// <param name="req"></param>
234 private void doSpaceRay(ODERayRequest req) 314 ///
235 {
236 // Create the ray
237// IntPtr ray = d.CreateRay(m_scene.TopSpace, req.length);
238 d.GeomRaySetLength(ray, req.length);
239 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
240 315
241 // Collide test 316 private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhanton;
242 d.SpaceCollide2(m_scene.TopSpace, ray, IntPtr.Zero, nearCallback); 317 private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
243
244 // Remove Ray
245// d.GeomDestroy(ray);
246 318
247 if (req.callbackMethod == null) 319 private void doSpaceRay(ODERayRequest req)
248 return; 320 {
321 // Collide tests
322 if ((CurrentRayFilter & FilterActiveSpace) != 0)
323 d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
324 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
325 d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
249 326
250 if (req.callbackMethod is RaycastCallback) 327 if (req.callbackMethod is RaycastCallback)
251 { 328 {
252 // Define default results 329 // Define default results
253 bool hitYN = false; 330 bool hitYN = false;
254 uint hitConsumerID = 0; 331 uint hitConsumerID = 0;
255 float distance = 999999999999f; 332 float distance = float.MaxValue;
256 Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f); 333 Vector3 closestcontact = Vector3.Zero;
257 Vector3 snormal = Vector3.Zero; 334 Vector3 snormal = Vector3.Zero;
258 335
259 // Find closest contact and object. 336 // Find closest contact and object.
@@ -261,25 +338,30 @@ namespace OpenSim.Region.Physics.OdePlugin
261 { 338 {
262 foreach (ContactResult cResult in m_contactResults) 339 foreach (ContactResult cResult in m_contactResults)
263 { 340 {
264 if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact)) 341 if(cResult.Depth < distance)
265 { 342 {
266 closestcontact = cResult.Pos; 343 closestcontact = cResult.Pos;
267 hitConsumerID = cResult.ConsumerID; 344 hitConsumerID = cResult.ConsumerID;
268 distance = cResult.Depth; 345 distance = cResult.Depth;
269 hitYN = true;
270 snormal = cResult.Normal; 346 snormal = cResult.Normal;
271 } 347 }
272 } 348 }
273 m_contactResults.Clear(); 349 m_contactResults.Clear();
274 } 350 }
275 351
352 if (distance > 0 && distance < float.MaxValue)
353 hitYN = true;
276 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal); 354 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
277 } 355 }
278 else 356 else
279 { 357 {
280 ((RayCallback)req.callbackMethod)(m_contactResults); 358 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
281 lock (m_PendingRequests) 359 lock (m_PendingRequests)
360 {
361 cresult.AddRange(m_contactResults);
282 m_contactResults.Clear(); 362 m_contactResults.Clear();
363 }
364 ((RayCallback)req.callbackMethod)(cresult);
283 } 365 }
284 } 366 }
285 367
@@ -289,27 +371,16 @@ namespace OpenSim.Region.Physics.OdePlugin
289 /// <param name="req"></param> 371 /// <param name="req"></param>
290 private void doGeomRay(ODERayRequest req) 372 private void doGeomRay(ODERayRequest req)
291 { 373 {
292 // Create the ray
293// IntPtr ray = d.CreateRay(m_scene.TopSpace, req.length);
294 d.GeomRaySetLength(ray, req.length);
295 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
296
297 // Collide test 374 // Collide test
298 d.SpaceCollide2(req.geom, ray, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test 375 d.SpaceCollide2(ray, req.geom, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test
299
300 // Remove Ray
301// d.GeomDestroy(ray);
302
303 if (req.callbackMethod == null)
304 return;
305 376
306 if (req.callbackMethod is RaycastCallback) 377 if (req.callbackMethod is RaycastCallback)
307 { 378 {
308 // Define default results 379 // Define default results
309 bool hitYN = false; 380 bool hitYN = false;
310 uint hitConsumerID = 0; 381 uint hitConsumerID = 0;
311 float distance = 999999999999f; 382 float distance = float.MaxValue;
312 Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f); 383 Vector3 closestcontact = Vector3.Zero;
313 Vector3 snormal = Vector3.Zero; 384 Vector3 snormal = Vector3.Zero;
314 385
315 // Find closest contact and object. 386 // Find closest contact and object.
@@ -317,25 +388,31 @@ namespace OpenSim.Region.Physics.OdePlugin
317 { 388 {
318 foreach (ContactResult cResult in m_contactResults) 389 foreach (ContactResult cResult in m_contactResults)
319 { 390 {
320 if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact)) 391 if(cResult.Depth < distance )
321 { 392 {
322 closestcontact = cResult.Pos; 393 closestcontact = cResult.Pos;
323 hitConsumerID = cResult.ConsumerID; 394 hitConsumerID = cResult.ConsumerID;
324 distance = cResult.Depth; 395 distance = cResult.Depth;
325 hitYN = true;
326 snormal = cResult.Normal; 396 snormal = cResult.Normal;
327 } 397 }
328 } 398 }
329 m_contactResults.Clear(); 399 m_contactResults.Clear();
330 } 400 }
331 401
402 if (distance > 0 && distance < float.MaxValue)
403 hitYN = true;
404
332 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal); 405 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
333 } 406 }
334 else 407 else
335 { 408 {
336 ((RayCallback)req.callbackMethod)(m_contactResults); 409 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
337 lock (m_PendingRequests) 410 lock (m_PendingRequests)
411 {
412 cresult.AddRange(m_contactResults);
338 m_contactResults.Clear(); 413 m_contactResults.Clear();
414 }
415 ((RayCallback)req.callbackMethod)(cresult);
339 } 416 }
340 } 417 }
341 418
@@ -350,20 +427,16 @@ namespace OpenSim.Region.Physics.OdePlugin
350 return true; 427 return true;
351 } 428 }
352 429
353 // This is the standard Near. g2 is the ray 430 // This is the standard Near. g1 is the ray
354 private void near(IntPtr space, IntPtr g1, IntPtr g2) 431 private void near(IntPtr space, IntPtr g1, IntPtr g2)
355 { 432 {
356 //Don't test against heightfield Geom, or you'll be sorry! 433 if (g2 == IntPtr.Zero || g1 == g2)
357 // Exclude heightfield geom
358
359 if (g1 == IntPtr.Zero || g1 == g2)
360 return; 434 return;
361 435
362 if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass) 436 if (m_contactResults.Count >= CurrentMaxCount)
363 return; 437 return;
364 438
365 // Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms. 439 if (d.GeomIsSpace(g2))
366 if (d.GeomIsSpace(g1))
367 { 440 {
368 try 441 try
369 { 442 {
@@ -381,10 +454,6 @@ namespace OpenSim.Region.Physics.OdePlugin
381 { 454 {
382 count = d.CollidePtr(g1, g2, ColisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); 455 count = d.CollidePtr(g1, g2, ColisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
383 } 456 }
384 catch (SEHException)
385 {
386 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.");
387 }
388 catch (Exception e) 457 catch (Exception e)
389 { 458 {
390 m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message); 459 m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message);
@@ -394,31 +463,116 @@ namespace OpenSim.Region.Physics.OdePlugin
394 if (count == 0) 463 if (count == 0)
395 return; 464 return;
396 465
397 PhysicsActor p1 = null; 466 uint ID = 0;
467 PhysicsActor p2 = null;
468
469 m_scene.actor_name_map.TryGetValue(g2, out p2);
470
471 if (p2 == null)
472 {
473 string name;
474
475 if (!m_scene.geom_name_map.TryGetValue(g2, out name))
476 return;
477
478 if (name == "Terrain")
479 {
480 // land colision
481 if ((CurrentRayFilter & RayFilterFlags.land) == 0)
482 return;
483 }
484 else if (name == "Water")
485 {
486 if ((CurrentRayFilter & RayFilterFlags.water) == 0)
487 return;
488 }
489 else
490 return;
491 }
492 else
493 {
494 if (p2 is OdePrim)
495 {
496 RayFilterFlags thisFlags;
497
498 if (p2.IsPhysical)
499 thisFlags = RayFilterFlags.physical;
500 else
501 thisFlags = RayFilterFlags.nonphysical;
398 502
399 if (g1 != IntPtr.Zero) 503 if (p2.Phantom)
400 m_scene.actor_name_map.TryGetValue(g1, out p1); 504 thisFlags |= RayFilterFlags.phantom;
505
506 if (p2.IsVolumeDtc)
507 thisFlags |= RayFilterFlags.volumedtc;
508
509 if ((thisFlags & CurrentRayFilter) == 0)
510 return;
511
512 ID = ((OdePrim)p2).m_localID;
513 }
514 else if (p2 is OdeCharacter)
515 {
516 if ((CurrentRayFilter & RayFilterFlags.agent) == 0)
517 return;
518 else
519 ID = ((OdeCharacter)p2).m_localID;
520 }
521 else //??
522 return;
523 }
401 524
402 d.ContactGeom curcontact = new d.ContactGeom(); 525 d.ContactGeom curcontact = new d.ContactGeom();
403 // Loop over contacts, build results. 526
404 for (int i = 0; i < count; i++) 527 // closestHit for now only works for meshs, so must do it for others
528 if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0)
405 { 529 {
406 if (!GetCurContactGeom(i, ref curcontact)) 530 // Loop all contacts, build results.
407 break; 531 for (int i = 0; i < count; i++)
408 if (p1 != null) { 532 {
409 if (p1 is OdePrim) 533 if (!GetCurContactGeom(i, ref curcontact))
534 break;
535
536 ContactResult collisionresult = new ContactResult();
537 collisionresult.ConsumerID = ID;
538 collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z);
539 collisionresult.Depth = curcontact.depth;
540 collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y,
541 curcontact.normal.Z);
542 lock (m_contactResults)
543 {
544 m_contactResults.Add(collisionresult);
545 if (m_contactResults.Count >= CurrentMaxCount)
546 return;
547 }
548 }
549 }
550 else
551 {
552 // keep only closest contact
553 ContactResult collisionresult = new ContactResult();
554 collisionresult.ConsumerID = ID;
555 collisionresult.Depth = float.MaxValue;
556
557 for (int i = 0; i < count; i++)
558 {
559 if (!GetCurContactGeom(i, ref curcontact))
560 break;
561
562 if (curcontact.depth < collisionresult.Depth)
410 { 563 {
411 ContactResult collisionresult = new ContactResult();
412
413 collisionresult.ConsumerID = ((OdePrim)p1).m_localID;
414 collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z); 564 collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z);
415 collisionresult.Depth = curcontact.depth; 565 collisionresult.Depth = curcontact.depth;
416 collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y, 566 collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y,
417 curcontact.normal.Z); 567 curcontact.normal.Z);
418 lock (m_contactResults)
419 m_contactResults.Add(collisionresult);
420 } 568 }
421 } 569 }
570
571 if (collisionresult.Depth != float.MaxValue)
572 {
573 lock (m_contactResults)
574 m_contactResults.Add(collisionresult);
575 }
422 } 576 }
423 } 577 }
424 578
@@ -428,6 +582,11 @@ namespace OpenSim.Region.Physics.OdePlugin
428 internal void Dispose() 582 internal void Dispose()
429 { 583 {
430 m_scene = null; 584 m_scene = null;
585 if (ray != IntPtr.Zero)
586 {
587 d.GeomDestroy(ray);
588 ray = IntPtr.Zero;
589 }
431 } 590 }
432 } 591 }
433 592
@@ -439,5 +598,6 @@ namespace OpenSim.Region.Physics.OdePlugin
439 public int Count; 598 public int Count;
440 public float length; 599 public float length;
441 public object callbackMethod; 600 public object callbackMethod;
601 public RayFilterFlags filter;
442 } 602 }
443} \ No newline at end of file 603} \ No newline at end of file