aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
diff options
context:
space:
mode:
authorUbitUmarov2012-04-16 16:16:55 +0100
committerUbitUmarov2012-04-16 16:16:55 +0100
commit86a2169d7343825c74ae271f637002377b92b438 (patch)
tree5bfc66b130edcacc738d3f4e8b4efa854a37fe7e /OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
parentUse chode character actor.SetMomentum() to force full restore Velocity in sce... (diff)
downloadopensim-SC_OLD-86a2169d7343825c74ae271f637002377b92b438.zip
opensim-SC_OLD-86a2169d7343825c74ae271f637002377b92b438.tar.gz
opensim-SC_OLD-86a2169d7343825c74ae271f637002377b92b438.tar.bz2
opensim-SC_OLD-86a2169d7343825c74ae271f637002377b92b438.tar.xz
ubitODE + physmanager: - Revised use of ODE collisions categories and bits(flags) for better use as filters together with top spaces (for example physical prims are on topactivespace and not physical are on topstaticspace) - Added new world raycast with filters. This blocks calling thread with a timeout of 500ms waiting for heartbeat ode thread signal job done. - Don't let ode bodies being disabled for 2 long except for vehicles. This is necessary to detect when the object is at rest at top of other and that is removed. Assume that vehicles can be enabled by used action.
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