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.cs583
1 files changed, 356 insertions, 227 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
index 54a83c2..31757a9 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,169 +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 {
139 ODERayRequest req = new ODERayRequest();
140 req.geom = geom;
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(IntPtr geom, Vector3 position, Vector3 direction, float length, int count,RayFilterFlags flags, RayCallback retMethod)
203 {
204 ODERayRequest req = new ODERayRequest();
205 req.geom = geom;
206 req.callbackMethod = retMethod;
207 req.length = length;
208 req.Normal = direction;
209 req.Origin = position;
210 req.Count = count;
211 req.filter = flags;
212
213 m_PendingRequests.Enqueue(req);
214 }
215
216 public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RaycastCallback retMethod)
217 {
218 ODERayRequest req = new ODERayRequest();
219 req.geom = IntPtr.Zero;
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
227 m_PendingRequests.Enqueue(req);
228 }
229
230 public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, int count, RaycastCallback retMethod)
231 { 93 {
232 ODERayRequest req = new ODERayRequest(); 94 if (req.Count == 0)
233 req.geom = geom; 95 req.Count = DefaultMaxCount;
234 req.callbackMethod = retMethod;
235 req.length = length;
236 req.Normal = direction;
237 req.Origin = position;
238 req.Count = count;
239 req.filter = RayFilterFlags.AllPrims;
240 96
241 m_PendingRequests.Enqueue(req); 97 m_PendingRequests.Enqueue(req);
242 } 98 }
@@ -272,21 +128,64 @@ namespace OpenSim.Region.Physics.OdePlugin
272 CurrentRayFilter = req.filter; 128 CurrentRayFilter = req.filter;
273 CurrentMaxCount = req.Count; 129 CurrentMaxCount = req.Count;
274 130
131 CollisionContactGeomsPerTest = req.Count & 0xffff;
132
275 closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1); 133 closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1);
276 backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1); 134 backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1);
277 135
278 d.GeomRaySetLength(ray, req.length); 136 if (req.callbackMethod is ProbeBoxCallback)
279 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); 137 {
280 d.GeomRaySetParams(ray, 0, backfacecull); 138 if (CollisionContactGeomsPerTest > 80)
281 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.GeomSetOffsetWorldQuaternion(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;
282 169
283 if (req.callbackMethod is RaycastCallback) 170 d.GeomRaySetLength(ray, req.length);
284 // 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);
285 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 }
286 185
287 if (req.geom == IntPtr.Zero) 186 if (req.geom == IntPtr.Zero)
288 { 187 {
289 // translate ray filter to colision flags 188 // translate ray filter to Collision flags
290 catflags = 0; 189 catflags = 0;
291 if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0) 190 if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0)
292 catflags |= CollisionCategories.VolumeDtc; 191 catflags |= CollisionCategories.VolumeDtc;
@@ -303,15 +202,48 @@ namespace OpenSim.Region.Physics.OdePlugin
303 202
304 if (catflags != 0) 203 if (catflags != 0)
305 { 204 {
306 d.GeomSetCollideBits(ray, (uint)catflags); 205 if (req.callbackMethod is ProbeBoxCallback)
307 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 }
308 } 231 }
309 } 232 }
310 else 233 else
311 { 234 {
312 // if we select a geom don't use filters 235 // if we select a geom don't use filters
313 d.GeomSetCollideBits(ray, (uint)CollisionCategories.All); 236
314 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 }
315 } 247 }
316 } 248 }
317 249
@@ -396,6 +328,61 @@ namespace OpenSim.Region.Physics.OdePlugin
396 } 328 }
397 } 329 }
398 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
399 /// <summary> 386 /// <summary>
400 /// Method that actually initiates the raycast with a geom 387 /// Method that actually initiates the raycast with a geom
401 /// </summary> 388 /// </summary>
@@ -450,7 +437,7 @@ namespace OpenSim.Region.Physics.OdePlugin
450 private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom) 437 private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
451 { 438 {
452 IntPtr ContactgeomsArray = m_scene.ContactgeomsArray; 439 IntPtr ContactgeomsArray = m_scene.ContactgeomsArray;
453 if (ContactgeomsArray == IntPtr.Zero || index >= ColisionContactGeomsPerTest) 440 if (ContactgeomsArray == IntPtr.Zero || index >= CollisionContactGeomsPerTest)
454 return false; 441 return false;
455 442
456 IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf)); 443 IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
@@ -483,7 +470,7 @@ namespace OpenSim.Region.Physics.OdePlugin
483 int count = 0; 470 int count = 0;
484 try 471 try
485 { 472 {
486 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);
487 } 474 }
488 catch (Exception e) 475 catch (Exception e)
489 { 476 {
@@ -494,84 +481,210 @@ namespace OpenSim.Region.Physics.OdePlugin
494 if (count == 0) 481 if (count == 0)
495 return; 482 return;
496 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
497 uint ID = 0; 490 uint ID = 0;
498 PhysicsActor p2 = null; 491 PhysicsActor p2 = null;
499 492
500 m_scene.actor_name_map.TryGetValue(g2, out p2); 493 m_scene.actor_name_map.TryGetValue(g2, out p2);
501 494
502 if (p2 == null) 495 if (p2 == null)
503 {
504 /*
505 string name;
506
507 if (!m_scene.geom_name_map.TryGetValue(g2, out name))
508 return;
509
510 if (name == "Terrain")
511 {
512 // land colision
513 if ((CurrentRayFilter & RayFilterFlags.land) == 0)
514 return;
515 }
516 else if (name == "Water")
517 {
518 if ((CurrentRayFilter & RayFilterFlags.water) == 0)
519 return;
520 }
521 else
522 return;
523 */
524 return; 496 return;
525 } 497
526 else 498 switch (p2.PhysicsActorType)
527 { 499 {
528 switch (p2.PhysicsActorType) 500 case (int)ActorTypes.Prim:
529 {
530 case (int)ActorTypes.Prim:
531 501
532 RayFilterFlags thisFlags; 502 RayFilterFlags thisFlags;
533 503
534 if (p2.IsPhysical) 504 if (p2.IsPhysical)
535 thisFlags = RayFilterFlags.physical; 505 thisFlags = RayFilterFlags.physical;
536 else 506 else
537 thisFlags = RayFilterFlags.nonphysical; 507 thisFlags = RayFilterFlags.nonphysical;
538 508
539 if (p2.Phantom) 509 if (p2.Phantom)
540 thisFlags |= RayFilterFlags.phantom; 510 thisFlags |= RayFilterFlags.phantom;
541 511
542 if (p2.IsVolumeDtc) 512 if (p2.IsVolumeDtc)
543 thisFlags |= RayFilterFlags.volumedtc; 513 thisFlags |= RayFilterFlags.volumedtc;
544 514
545 if ((thisFlags & CurrentRayFilter) == 0) 515 if ((thisFlags & CurrentRayFilter) == 0)
546 return; 516 return;
547 517
548 ID = ((OdePrim)p2).LocalID; 518 ID = ((OdePrim)p2).LocalID;
549 break; 519 break;
550 520
551 case (int)ActorTypes.Agent: 521 case (int)ActorTypes.Agent:
552 522
553 if ((CurrentRayFilter & RayFilterFlags.agent) == 0) 523 if ((CurrentRayFilter & RayFilterFlags.agent) == 0)
554 return; 524 return;
555 else 525 else
556 ID = ((OdeCharacter)p2).LocalID; 526 ID = ((OdeCharacter)p2).LocalID;
557 break; 527 break;
558 528
559 case (int)ActorTypes.Ground: 529 case (int)ActorTypes.Ground:
560 530
561 if ((CurrentRayFilter & RayFilterFlags.land) == 0) 531 if ((CurrentRayFilter & RayFilterFlags.land) == 0)
562 return; 532 return;
563 break; 533 break;
564 534
565 case (int)ActorTypes.Water: 535 case (int)ActorTypes.Water:
566 536
567 if ((CurrentRayFilter & RayFilterFlags.water) == 0) 537 if ((CurrentRayFilter & RayFilterFlags.water) == 0)
568 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))
569 break; 554 break;
570 555
571 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))
572 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);
573 } 595 }
574 } 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 }
575 688
576 d.ContactGeom curcontact = new d.ContactGeom(); 689 d.ContactGeom curcontact = new d.ContactGeom();
577 690
@@ -638,6 +751,21 @@ namespace OpenSim.Region.Physics.OdePlugin
638 d.GeomDestroy(ray); 751 d.GeomDestroy(ray);
639 ray = IntPtr.Zero; 752 ray = IntPtr.Zero;
640 } 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 }
641 } 769 }
642 } 770 }
643 771
@@ -650,5 +778,6 @@ namespace OpenSim.Region.Physics.OdePlugin
650 public float length; 778 public float length;
651 public object callbackMethod; 779 public object callbackMethod;
652 public RayFilterFlags filter; 780 public RayFilterFlags filter;
781 public Quaternion orientation;
653 } 782 }
654} \ No newline at end of file 783} \ No newline at end of file