aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs680
1 files changed, 680 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs b/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs
new file mode 100644
index 0000000..b82d593
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs
@@ -0,0 +1,680 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Runtime.InteropServices;
32using System.Text;
33using OpenSim.Framework;
34using OpenSim.Region.PhysicsModules.SharedBase;
35using OdeAPI;
36using log4net;
37using OpenMetaverse;
38
39namespace OpenSim.Region.PhysicsModule.ubOde
40{
41 /// <summary>
42 /// Processes raycast requests as ODE is in a state to be able to do them.
43 /// This ensures that it's thread safe and there will be no conflicts.
44 /// Requests get returned by a different thread then they were requested by.
45 /// </summary>
46 public class ODERayCastRequestManager
47 {
48 /// <summary>
49 /// Pending ray requests
50 /// </summary>
51 protected OpenSim.Framework.LocklessQueue<ODERayRequest> m_PendingRequests = new OpenSim.Framework.LocklessQueue<ODERayRequest>();
52
53 /// <summary>
54 /// Scene that created this object.
55 /// </summary>
56 private ODEScene m_scene;
57
58 IntPtr ray; // the ray. we only need one for our lifetime
59 IntPtr Sphere;
60 IntPtr Box;
61 IntPtr Plane;
62
63 private int CollisionContactGeomsPerTest = 25;
64 private const int DefaultMaxCount = 25;
65 private const int MaxTimePerCallMS = 30;
66
67 /// <summary>
68 /// ODE near callback delegate
69 /// </summary>
70 private d.NearCallback nearCallback;
71 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
72 private List<ContactResult> m_contactResults = new List<ContactResult>();
73 private RayFilterFlags CurrentRayFilter;
74 private int CurrentMaxCount;
75
76 public ODERayCastRequestManager(ODEScene pScene)
77 {
78 m_scene = pScene;
79 nearCallback = near;
80 ray = d.CreateRay(IntPtr.Zero, 1.0f);
81 d.GeomSetCategoryBits(ray, 0);
82 Box = d.CreateBox(IntPtr.Zero, 1.0f, 1.0f, 1.0f);
83 d.GeomSetCategoryBits(Box, 0);
84 Sphere = d.CreateSphere(IntPtr.Zero,1.0f);
85 d.GeomSetCategoryBits(Sphere, 0);
86 Plane = d.CreatePlane(IntPtr.Zero, 0f,0f,1f,1f);
87 d.GeomSetCategoryBits(Sphere, 0);
88 }
89
90 public void QueueRequest(ODERayRequest req)
91 {
92 if (req.Count == 0)
93 req.Count = DefaultMaxCount;
94
95 m_PendingRequests.Enqueue(req);
96 }
97
98 /// <summary>
99 /// Process all queued raycast requests
100 /// </summary>
101 /// <returns>Time in MS the raycasts took to process.</returns>
102 public int ProcessQueuedRequests()
103 {
104
105 if (m_PendingRequests.Count <= 0)
106 return 0;
107
108 if (m_scene.ContactgeomsArray == IntPtr.Zero || ray == IntPtr.Zero)
109 // oops something got wrong or scene isn't ready still
110 {
111 m_PendingRequests.Clear();
112 return 0;
113 }
114
115 int time = Util.EnvironmentTickCount();
116
117 ODERayRequest req;
118 int closestHit;
119 int backfacecull;
120 CollisionCategories catflags;
121
122 while (m_PendingRequests.Dequeue(out req))
123 {
124 if (req.callbackMethod != null)
125 {
126 IntPtr geom = IntPtr.Zero;
127 if (req.actor != null)
128 {
129 if (m_scene.haveActor(req.actor))
130 {
131 if (req.actor is OdePrim)
132 geom = ((OdePrim)req.actor).prim_geom;
133 else if (req.actor is OdeCharacter)
134 geom = ((OdePrim)req.actor).prim_geom;
135 }
136 if (geom == IntPtr.Zero)
137 {
138 NoContacts(req);
139 continue;
140 }
141 }
142
143 CurrentRayFilter = req.filter;
144 CurrentMaxCount = req.Count;
145
146 CollisionContactGeomsPerTest = req.Count & 0xffff;
147
148 closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1);
149 backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1);
150
151 if (req.callbackMethod is ProbeBoxCallback)
152 {
153 if (CollisionContactGeomsPerTest > 80)
154 CollisionContactGeomsPerTest = 80;
155 d.GeomBoxSetLengths(Box, req.Normal.X, req.Normal.Y, req.Normal.Z);
156 d.GeomSetPosition(Box, req.Origin.X, req.Origin.Y, req.Origin.Z);
157 d.Quaternion qtmp;
158 qtmp.X = req.orientation.X;
159 qtmp.Y = req.orientation.Y;
160 qtmp.Z = req.orientation.Z;
161 qtmp.W = req.orientation.W;
162 d.GeomSetQuaternion(Box, ref qtmp);
163 }
164 else if (req.callbackMethod is ProbeSphereCallback)
165 {
166 if (CollisionContactGeomsPerTest > 80)
167 CollisionContactGeomsPerTest = 80;
168
169 d.GeomSphereSetRadius(Sphere, req.length);
170 d.GeomSetPosition(Sphere, req.Origin.X, req.Origin.Y, req.Origin.Z);
171 }
172 else if (req.callbackMethod is ProbePlaneCallback)
173 {
174 if (CollisionContactGeomsPerTest > 80)
175 CollisionContactGeomsPerTest = 80;
176
177 d.GeomPlaneSetParams(Plane, req.Normal.X, req.Normal.Y, req.Normal.Z, req.length);
178 }
179
180 else
181 {
182 if (CollisionContactGeomsPerTest > 25)
183 CollisionContactGeomsPerTest = 25;
184
185 d.GeomRaySetLength(ray, req.length);
186 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
187 d.GeomRaySetParams(ray, 0, backfacecull);
188
189 if (req.callbackMethod is RaycastCallback)
190 {
191 // if we only want one get only one per Collision pair saving memory
192 CurrentRayFilter |= RayFilterFlags.ClosestHit;
193 d.GeomRaySetClosestHit(ray, 1);
194 }
195 else
196 d.GeomRaySetClosestHit(ray, closestHit);
197 }
198
199 if ((CurrentRayFilter & RayFilterFlags.ContactsUnImportant) != 0)
200 unchecked
201 {
202 CollisionContactGeomsPerTest |= (int)d.CONTACTS_UNIMPORTANT;
203 }
204
205 if (geom == IntPtr.Zero)
206 {
207 // translate ray filter to Collision flags
208 catflags = 0;
209 if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0)
210 catflags |= CollisionCategories.VolumeDtc;
211 if ((CurrentRayFilter & RayFilterFlags.phantom) != 0)
212 catflags |= CollisionCategories.Phantom;
213 if ((CurrentRayFilter & RayFilterFlags.agent) != 0)
214 catflags |= CollisionCategories.Character;
215 if ((CurrentRayFilter & RayFilterFlags.PrimsNonPhantom) != 0)
216 catflags |= CollisionCategories.Geom;
217 if ((CurrentRayFilter & RayFilterFlags.land) != 0)
218 catflags |= CollisionCategories.Land;
219 if ((CurrentRayFilter & RayFilterFlags.water) != 0)
220 catflags |= CollisionCategories.Water;
221
222 if (catflags != 0)
223 {
224 if (req.callbackMethod is ProbeBoxCallback)
225 {
226 catflags |= CollisionCategories.Space;
227 d.GeomSetCollideBits(Box, (uint)catflags);
228 d.GeomSetCategoryBits(Box, (uint)catflags);
229 doProbe(req, Box);
230 }
231 else if (req.callbackMethod is ProbeSphereCallback)
232 {
233 catflags |= CollisionCategories.Space;
234 d.GeomSetCollideBits(Sphere, (uint)catflags);
235 d.GeomSetCategoryBits(Sphere, (uint)catflags);
236 doProbe(req, Sphere);
237 }
238 else if (req.callbackMethod is ProbePlaneCallback)
239 {
240 catflags |= CollisionCategories.Space;
241 d.GeomSetCollideBits(Plane, (uint)catflags);
242 d.GeomSetCategoryBits(Plane, (uint)catflags);
243 doPlane(req,IntPtr.Zero);
244 }
245 else
246 {
247 d.GeomSetCollideBits(ray, (uint)catflags);
248 doSpaceRay(req);
249 }
250 }
251 }
252 else
253 {
254 // if we select a geom don't use filters
255
256 if (req.callbackMethod is ProbePlaneCallback)
257 {
258 d.GeomSetCollideBits(Plane, (uint)CollisionCategories.All);
259 doPlane(req,geom);
260 }
261 else
262 {
263 d.GeomSetCollideBits(ray, (uint)CollisionCategories.All);
264 doGeomRay(req,geom);
265 }
266 }
267 }
268
269 if (Util.EnvironmentTickCountSubtract(time) > MaxTimePerCallMS)
270 break;
271 }
272
273 lock (m_contactResults)
274 m_contactResults.Clear();
275
276 return Util.EnvironmentTickCountSubtract(time);
277 }
278 /// <summary>
279 /// Method that actually initiates the raycast with spaces
280 /// </summary>
281 /// <param name="req"></param>
282 ///
283
284 private void NoContacts(ODERayRequest req)
285 {
286 if (req.callbackMethod is RaycastCallback)
287 {
288 ((RaycastCallback)req.callbackMethod)(false, Vector3.Zero, 0, 0, Vector3.Zero);
289 return;
290 }
291 List<ContactResult> cresult = new List<ContactResult>();
292
293 if (req.callbackMethod is RayCallback)
294 ((RayCallback)req.callbackMethod)(cresult);
295 else if (req.callbackMethod is ProbeBoxCallback)
296 ((ProbeBoxCallback)req.callbackMethod)(cresult);
297 else if (req.callbackMethod is ProbeSphereCallback)
298 ((ProbeSphereCallback)req.callbackMethod)(cresult);
299 }
300
301 private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhantom;
302// private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
303 private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhantom;
304
305 private void doSpaceRay(ODERayRequest req)
306 {
307 // Collide tests
308 if ((CurrentRayFilter & FilterActiveSpace) != 0)
309 {
310 d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
311 d.SpaceCollide2(ray, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
312 }
313 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
314 d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
315 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
316 {
317 // current ode land to ray collisions is very bad
318 // so for now limit its range badly
319 if (req.length > 60.0f)
320 d.GeomRaySetLength(ray, 60.0f);
321
322 d.SpaceCollide2(ray, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
323 }
324
325 if (req.callbackMethod is RaycastCallback)
326 {
327 // Define default results
328 bool hitYN = false;
329 uint hitConsumerID = 0;
330 float distance = float.MaxValue;
331 Vector3 closestcontact = Vector3.Zero;
332 Vector3 snormal = Vector3.Zero;
333
334 // Find closest contact and object.
335 lock (m_contactResults)
336 {
337 foreach (ContactResult cResult in m_contactResults)
338 {
339 if(cResult.Depth < distance)
340 {
341 closestcontact = cResult.Pos;
342 hitConsumerID = cResult.ConsumerID;
343 distance = cResult.Depth;
344 snormal = cResult.Normal;
345 }
346 }
347 m_contactResults.Clear();
348 }
349
350 if (distance > 0 && distance < float.MaxValue)
351 hitYN = true;
352 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
353 }
354 else
355 {
356 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
357 lock (m_PendingRequests)
358 {
359 cresult.AddRange(m_contactResults);
360 m_contactResults.Clear();
361 }
362 ((RayCallback)req.callbackMethod)(cresult);
363 }
364 }
365
366 private void doProbe(ODERayRequest req, IntPtr probe)
367 {
368 // Collide tests
369 if ((CurrentRayFilter & FilterActiveSpace) != 0)
370 {
371 d.SpaceCollide2(probe, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
372 d.SpaceCollide2(probe, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
373 }
374 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
375 d.SpaceCollide2(probe, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
376 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
377 d.SpaceCollide2(probe, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
378
379 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
380 lock (m_PendingRequests)
381 {
382 cresult.AddRange(m_contactResults);
383 m_contactResults.Clear();
384 }
385 if (req.callbackMethod is ProbeBoxCallback)
386 ((ProbeBoxCallback)req.callbackMethod)(cresult);
387 else if (req.callbackMethod is ProbeSphereCallback)
388 ((ProbeSphereCallback)req.callbackMethod)(cresult);
389 }
390
391 private void doPlane(ODERayRequest req,IntPtr geom)
392 {
393 // Collide tests
394 if (geom == IntPtr.Zero)
395 {
396 if ((CurrentRayFilter & FilterActiveSpace) != 0)
397 {
398 d.SpaceCollide2(Plane, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
399 d.SpaceCollide2(Plane, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
400 }
401 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
402 d.SpaceCollide2(Plane, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
403 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
404 d.SpaceCollide2(Plane, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
405 }
406 else
407 {
408 d.SpaceCollide2(Plane, geom, IntPtr.Zero, nearCallback);
409 }
410
411 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
412 lock (m_PendingRequests)
413 {
414 cresult.AddRange(m_contactResults);
415 m_contactResults.Clear();
416 }
417
418 ((ProbePlaneCallback)req.callbackMethod)(cresult);
419 }
420
421 /// <summary>
422 /// Method that actually initiates the raycast with a geom
423 /// </summary>
424 /// <param name="req"></param>
425 private void doGeomRay(ODERayRequest req, IntPtr geom)
426 {
427 // Collide test
428 d.SpaceCollide2(ray, geom, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test
429
430 if (req.callbackMethod is RaycastCallback)
431 {
432 // Define default results
433 bool hitYN = false;
434 uint hitConsumerID = 0;
435 float distance = float.MaxValue;
436 Vector3 closestcontact = Vector3.Zero;
437 Vector3 snormal = Vector3.Zero;
438
439 // Find closest contact and object.
440 lock (m_contactResults)
441 {
442 foreach (ContactResult cResult in m_contactResults)
443 {
444 if(cResult.Depth < distance )
445 {
446 closestcontact = cResult.Pos;
447 hitConsumerID = cResult.ConsumerID;
448 distance = cResult.Depth;
449 snormal = cResult.Normal;
450 }
451 }
452 m_contactResults.Clear();
453 }
454
455 if (distance > 0 && distance < float.MaxValue)
456 hitYN = true;
457
458 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
459 }
460 else
461 {
462 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
463 lock (m_PendingRequests)
464 {
465 cresult.AddRange(m_contactResults);
466 m_contactResults.Clear();
467 }
468 ((RayCallback)req.callbackMethod)(cresult);
469 }
470 }
471
472 private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
473 {
474 IntPtr ContactgeomsArray = m_scene.ContactgeomsArray;
475 if (ContactgeomsArray == IntPtr.Zero || index >= CollisionContactGeomsPerTest)
476 return false;
477
478 IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
479 newcontactgeom = (d.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(d.ContactGeom));
480 return true;
481 }
482
483 // This is the standard Near. g1 is the ray
484 private void near(IntPtr space, IntPtr g1, IntPtr g2)
485 {
486 if (g2 == IntPtr.Zero || g1 == g2)
487 return;
488
489 if (m_contactResults.Count >= CurrentMaxCount)
490 return;
491
492 if (d.GeomIsSpace(g2))
493 {
494 try
495 {
496 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
497 }
498 catch (Exception e)
499 {
500 m_log.WarnFormat("[PHYSICS Ray]: Unable to Space collide test an object: {0}", e.Message);
501 }
502 return;
503 }
504
505 int count = 0;
506 try
507 {
508 count = d.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
509 }
510 catch (Exception e)
511 {
512 m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message);
513 return;
514 }
515
516 if (count == 0)
517 return;
518/*
519 uint cat1 = d.GeomGetCategoryBits(g1);
520 uint cat2 = d.GeomGetCategoryBits(g2);
521 uint col1 = d.GeomGetCollideBits(g1);
522 uint col2 = d.GeomGetCollideBits(g2);
523*/
524
525 uint ID = 0;
526 PhysicsActor p2 = null;
527
528 m_scene.actor_name_map.TryGetValue(g2, out p2);
529
530 if (p2 == null)
531 return;
532
533 switch (p2.PhysicsActorType)
534 {
535 case (int)ActorTypes.Prim:
536
537 RayFilterFlags thisFlags;
538
539 if (p2.IsPhysical)
540 thisFlags = RayFilterFlags.physical;
541 else
542 thisFlags = RayFilterFlags.nonphysical;
543
544 if (p2.Phantom)
545 thisFlags |= RayFilterFlags.phantom;
546
547 if (p2.IsVolumeDtc)
548 thisFlags |= RayFilterFlags.volumedtc;
549
550 if ((thisFlags & CurrentRayFilter) == 0)
551 return;
552
553 ID = ((OdePrim)p2).LocalID;
554 break;
555
556 case (int)ActorTypes.Agent:
557
558 if ((CurrentRayFilter & RayFilterFlags.agent) == 0)
559 return;
560 else
561 ID = ((OdeCharacter)p2).LocalID;
562 break;
563
564 case (int)ActorTypes.Ground:
565
566 if ((CurrentRayFilter & RayFilterFlags.land) == 0)
567 return;
568 break;
569
570 case (int)ActorTypes.Water:
571
572 if ((CurrentRayFilter & RayFilterFlags.water) == 0)
573 return;
574 break;
575
576 default:
577 break;
578 }
579
580 d.ContactGeom curcontact = new d.ContactGeom();
581
582 // closestHit for now only works for meshs, so must do it for others
583 if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0)
584 {
585 // Loop all contacts, build results.
586 for (int i = 0; i < count; i++)
587 {
588 if (!GetCurContactGeom(i, ref curcontact))
589 break;
590
591 ContactResult collisionresult = new ContactResult();
592 collisionresult.ConsumerID = ID;
593 collisionresult.Pos.X = curcontact.pos.X;
594 collisionresult.Pos.Y = curcontact.pos.Y;
595 collisionresult.Pos.Z = curcontact.pos.Z;
596 collisionresult.Depth = curcontact.depth;
597 collisionresult.Normal.X = curcontact.normal.X;
598 collisionresult.Normal.Y = curcontact.normal.Y;
599 collisionresult.Normal.Z = curcontact.normal.Z;
600 lock (m_contactResults)
601 {
602 m_contactResults.Add(collisionresult);
603 if (m_contactResults.Count >= CurrentMaxCount)
604 return;
605 }
606 }
607 }
608 else
609 {
610 // keep only closest contact
611 ContactResult collisionresult = new ContactResult();
612 collisionresult.ConsumerID = ID;
613 collisionresult.Depth = float.MaxValue;
614
615 for (int i = 0; i < count; i++)
616 {
617 if (!GetCurContactGeom(i, ref curcontact))
618 break;
619
620 if (curcontact.depth < collisionresult.Depth)
621 {
622 collisionresult.Pos.X = curcontact.pos.X;
623 collisionresult.Pos.Y = curcontact.pos.Y;
624 collisionresult.Pos.Z = curcontact.pos.Z;
625 collisionresult.Depth = curcontact.depth;
626 collisionresult.Normal.X = curcontact.normal.X;
627 collisionresult.Normal.Y = curcontact.normal.Y;
628 collisionresult.Normal.Z = curcontact.normal.Z;
629 }
630 }
631
632 if (collisionresult.Depth != float.MaxValue)
633 {
634 lock (m_contactResults)
635 m_contactResults.Add(collisionresult);
636 }
637 }
638 }
639
640 /// <summary>
641 /// Dereference the creator scene so that it can be garbage collected if needed.
642 /// </summary>
643 internal void Dispose()
644 {
645 m_scene = null;
646 if (ray != IntPtr.Zero)
647 {
648 d.GeomDestroy(ray);
649 ray = IntPtr.Zero;
650 }
651 if (Box != IntPtr.Zero)
652 {
653 d.GeomDestroy(Box);
654 Box = IntPtr.Zero;
655 }
656 if (Sphere != IntPtr.Zero)
657 {
658 d.GeomDestroy(Sphere);
659 Sphere = IntPtr.Zero;
660 }
661 if (Plane != IntPtr.Zero)
662 {
663 d.GeomDestroy(Plane);
664 Plane = IntPtr.Zero;
665 }
666 }
667 }
668
669 public struct ODERayRequest
670 {
671 public PhysicsActor actor;
672 public Vector3 Origin;
673 public Vector3 Normal;
674 public int Count;
675 public float length;
676 public object callbackMethod;
677 public RayFilterFlags filter;
678 public Quaternion orientation;
679 }
680}