aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
diff options
context:
space:
mode:
authorRobert Adams2015-09-08 04:54:16 -0700
committerRobert Adams2015-09-08 04:54:16 -0700
commite5367d822be9b05e74c859afe2d2956a3e95aa33 (patch)
treee904050a30715df587aa527d7f313755177726a7 /OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
parentadd lost admin_reset_land method (diff)
parentDeleted access control spec from [LoginService] section of standalone config.... (diff)
downloadopensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.zip
opensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.gz
opensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.bz2
opensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.xz
Merge of ubitworkvarnew with opensim/master as of 20150905.
This integrates the OpenSim refactoring to make physics, etc into modules. AVN physics hasn't been moved to new location. Does not compile yet. Merge branch 'osmaster' into mbworknew1
Diffstat (limited to 'OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs')
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs446
1 files changed, 446 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs b/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
new file mode 100644
index 0000000..80f0fcf
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
@@ -0,0 +1,446 @@
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 OpenMetaverse;
34using OpenSim.Region.PhysicsModules.SharedBase;
35using Ode.NET;
36using log4net;
37
38namespace OpenSim.Region.PhysicsModule.ODE
39{
40 /// <summary>
41 /// Processes raycast requests as ODE is in a state to be able to do them.
42 /// This ensures that it's thread safe and there will be no conflicts.
43 /// Requests get returned by a different thread then they were requested by.
44 /// </summary>
45 public class ODERayCastRequestManager
46 {
47 /// <summary>
48 /// Pending raycast requests
49 /// </summary>
50 protected List<ODERayCastRequest> m_PendingRequests = new List<ODERayCastRequest>();
51
52 /// <summary>
53 /// Pending ray requests
54 /// </summary>
55 protected List<ODERayRequest> m_PendingRayRequests = new List<ODERayRequest>();
56
57 /// <summary>
58 /// Scene that created this object.
59 /// </summary>
60 private OdeScene m_scene;
61
62 /// <summary>
63 /// ODE contact array to be filled by the collision testing
64 /// </summary>
65 d.ContactGeom[] contacts = new d.ContactGeom[5];
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
74
75 public ODERayCastRequestManager(OdeScene pScene)
76 {
77 m_scene = pScene;
78 nearCallback = near;
79
80 }
81
82 /// <summary>
83 /// Queues a raycast
84 /// </summary>
85 /// <param name="position">Origin of Ray</param>
86 /// <param name="direction">Ray normal</param>
87 /// <param name="length">Ray length</param>
88 /// <param name="retMethod">Return method to send the results</param>
89 public void QueueRequest(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
90 {
91 lock (m_PendingRequests)
92 {
93 ODERayCastRequest req = new ODERayCastRequest();
94 req.callbackMethod = retMethod;
95 req.length = length;
96 req.Normal = direction;
97 req.Origin = position;
98
99 m_PendingRequests.Add(req);
100 }
101 }
102
103 /// <summary>
104 /// Queues a raycast
105 /// </summary>
106 /// <param name="position">Origin of Ray</param>
107 /// <param name="direction">Ray normal</param>
108 /// <param name="length">Ray length</param>
109 /// <param name="count"></param>
110 /// <param name="retMethod">Return method to send the results</param>
111 public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod)
112 {
113 lock (m_PendingRequests)
114 {
115 ODERayRequest req = new ODERayRequest();
116 req.callbackMethod = retMethod;
117 req.length = length;
118 req.Normal = direction;
119 req.Origin = position;
120 req.Count = count;
121
122 m_PendingRayRequests.Add(req);
123 }
124 }
125
126 /// <summary>
127 /// Process all queued raycast requests
128 /// </summary>
129 /// <returns>Time in MS the raycasts took to process.</returns>
130 public int ProcessQueuedRequests()
131 {
132 int time = System.Environment.TickCount;
133 lock (m_PendingRequests)
134 {
135 if (m_PendingRequests.Count > 0)
136 {
137 ODERayCastRequest[] reqs = m_PendingRequests.ToArray();
138 for (int i = 0; i < reqs.Length; i++)
139 {
140 if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
141 RayCast(reqs[i]); // if there isn't anyone to send results
142 }
143
144 m_PendingRequests.Clear();
145 }
146 }
147
148 lock (m_PendingRayRequests)
149 {
150 if (m_PendingRayRequests.Count > 0)
151 {
152 ODERayRequest[] reqs = m_PendingRayRequests.ToArray();
153 for (int i = 0; i < reqs.Length; i++)
154 {
155 if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
156 RayCast(reqs[i]); // if there isn't anyone to send results
157 }
158
159 m_PendingRayRequests.Clear();
160 }
161 }
162
163 lock (m_contactResults)
164 m_contactResults.Clear();
165
166 return System.Environment.TickCount - time;
167 }
168
169 /// <summary>
170 /// Method that actually initiates the raycast
171 /// </summary>
172 /// <param name="req"></param>
173 private void RayCast(ODERayCastRequest req)
174 {
175 // NOTE: limit ray lenght or collisions will take all avaiable stack space
176 // this value may still be too large, depending on machine configuration
177 // of maximum stack
178 float len = req.length;
179 if (len > 250f)
180 len = 250f;
181
182 // Create the ray
183 IntPtr ray = d.CreateRay(m_scene.space, len);
184 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
185
186 // Collide test
187 d.SpaceCollide2(m_scene.space, ray, IntPtr.Zero, nearCallback);
188
189 // Remove Ray
190 d.GeomDestroy(ray);
191
192 // Define default results
193 bool hitYN = false;
194 uint hitConsumerID = 0;
195 float distance = 999999999999f;
196 Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f);
197 Vector3 snormal = Vector3.Zero;
198
199 // Find closest contact and object.
200 lock (m_contactResults)
201 {
202 foreach (ContactResult cResult in m_contactResults)
203 {
204 if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact))
205 {
206 closestcontact = cResult.Pos;
207 hitConsumerID = cResult.ConsumerID;
208 distance = cResult.Depth;
209 hitYN = true;
210 snormal = cResult.Normal;
211 }
212 }
213
214 m_contactResults.Clear();
215 }
216
217 // Return results
218 if (req.callbackMethod != null)
219 req.callbackMethod(hitYN, closestcontact, hitConsumerID, distance, snormal);
220 }
221
222 /// <summary>
223 /// Method that actually initiates the raycast
224 /// </summary>
225 /// <param name="req"></param>
226 private void RayCast(ODERayRequest req)
227 {
228 // limit ray lenght or collisions will take all avaiable stack space
229 float len = req.length;
230 if (len > 250f)
231 len = 250f;
232
233 // Create the ray
234 IntPtr ray = d.CreateRay(m_scene.space, len);
235 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
236
237 // Collide test
238 d.SpaceCollide2(m_scene.space, ray, IntPtr.Zero, nearCallback);
239
240 // Remove Ray
241 d.GeomDestroy(ray);
242
243 // Find closest contact and object.
244 lock (m_contactResults)
245 {
246 // Return results
247 if (req.callbackMethod != null)
248 req.callbackMethod(m_contactResults);
249 }
250 }
251
252 // This is the standard Near. Uses space AABBs to speed up detection.
253 private void near(IntPtr space, IntPtr g1, IntPtr g2)
254 {
255
256 //Don't test against heightfield Geom, or you'll be sorry!
257
258 /*
259 terminate called after throwing an instance of 'std::bad_alloc'
260 what(): std::bad_alloc
261 Stacktrace:
262
263 at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0x00004>
264 at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0xffffffff>
265 at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0x00280>
266 at (wrapper native-to-managed) OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0xfff
267 fffff>
268 at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0x00004>
269 at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0xffffffff>
270 at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.RayCast (OpenSim.Region.Physics.OdePlugin.ODERayCastRequest) <
271 0x00114>
272 at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.ProcessQueuedRequests () <0x000eb>
273 at OpenSim.Region.Physics.OdePlugin.OdeScene.Simulate (single) <0x017e6>
274 at OpenSim.Region.Framework.Scenes.SceneGraph.UpdatePhysics (double) <0x00042>
275 at OpenSim.Region.Framework.Scenes.Scene.Update () <0x0039e>
276 at OpenSim.Region.Framework.Scenes.Scene.Heartbeat (object) <0x00019>
277 at (wrapper runtime-invoke) object.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <0xffffffff>
278
279 Native stacktrace:
280
281 mono [0x80d2a42]
282 [0xb7f5840c]
283 /lib/i686/cmov/libc.so.6(abort+0x188) [0xb7d1a018]
284 /usr/lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x158) [0xb45fc988]
285 /usr/lib/libstdc++.so.6 [0xb45fa865]
286 /usr/lib/libstdc++.so.6 [0xb45fa8a2]
287 /usr/lib/libstdc++.so.6 [0xb45fa9da]
288 /usr/lib/libstdc++.so.6(_Znwj+0x83) [0xb45fb033]
289 /usr/lib/libstdc++.so.6(_Znaj+0x1d) [0xb45fb11d]
290 libode.so(_ZN13dxHeightfield23dCollideHeightfieldZoneEiiiiP6dxGeomiiP12dContactGeomi+0xd04) [0xb46678e4]
291 libode.so(_Z19dCollideHeightfieldP6dxGeomS0_iP12dContactGeomi+0x54b) [0xb466832b]
292 libode.so(dCollide+0x102) [0xb46571b2]
293 [0x95cfdec9]
294 [0x8ea07fe1]
295 [0xab260146]
296 libode.so [0xb465a5c4]
297 libode.so(_ZN11dxHashSpace8collide2EPvP6dxGeomPFvS0_S2_S2_E+0x75) [0xb465bcf5]
298 libode.so(dSpaceCollide2+0x177) [0xb465ac67]
299 [0x95cf978e]
300 [0x8ea07945]
301 [0x95cf2bbc]
302 [0xab2787e7]
303 [0xab419fb3]
304 [0xab416657]
305 [0xab415bda]
306 [0xb609b08e]
307 mono(mono_runtime_delegate_invoke+0x34) [0x8192534]
308 mono [0x81a2f0f]
309 mono [0x81d28b6]
310 mono [0x81ea2c6]
311 /lib/i686/cmov/libpthread.so.0 [0xb7e744c0]
312 /lib/i686/cmov/libc.so.6(clone+0x5e) [0xb7dcd6de]
313 */
314
315 // Exclude heightfield geom
316
317 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
318 return;
319 if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass || d.GeomGetClass(g2) == d.GeomClassID.HeightfieldClass)
320 return;
321
322 // Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms.
323 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
324 {
325 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
326 return;
327
328 // Separating static prim geometry spaces.
329 // We'll be calling near recursivly if one
330 // of them is a space to find all of the
331 // contact points in the space
332 try
333 {
334 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
335 }
336 catch (AccessViolationException)
337 {
338 m_log.Warn("[PHYSICS]: Unable to collide test a space");
339 return;
340 }
341 //Colliding a space or a geom with a space or a geom. so drill down
342
343 //Collide all geoms in each space..
344 //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
345 //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
346 return;
347 }
348
349 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
350 return;
351
352 int count = 0;
353 try
354 {
355
356 if (g1 == g2)
357 return; // Can't collide with yourself
358
359 lock (contacts)
360 {
361 count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf);
362 }
363 }
364 catch (SEHException)
365 {
366 m_log.Error("[PHYSICS]: 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.");
367 }
368 catch (Exception e)
369 {
370 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
371 return;
372 }
373
374 PhysicsActor p1 = null;
375 PhysicsActor p2 = null;
376
377 if (g1 != IntPtr.Zero)
378 m_scene.actor_name_map.TryGetValue(g1, out p1);
379
380 if (g2 != IntPtr.Zero)
381 m_scene.actor_name_map.TryGetValue(g1, out p2);
382
383 // Loop over contacts, build results.
384 for (int i = 0; i < count; i++)
385 {
386 if (p1 != null)
387 {
388 if (p1 is OdePrim)
389 {
390 ContactResult collisionresult = new ContactResult();
391
392 collisionresult.ConsumerID = p1.LocalID;
393 collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z);
394 collisionresult.Depth = contacts[i].depth;
395 collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y,
396 contacts[i].normal.Z);
397 lock (m_contactResults)
398 m_contactResults.Add(collisionresult);
399 }
400 }
401
402 if (p2 != null)
403 {
404 if (p2 is OdePrim)
405 {
406 ContactResult collisionresult = new ContactResult();
407
408 collisionresult.ConsumerID = p2.LocalID;
409 collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z);
410 collisionresult.Depth = contacts[i].depth;
411 collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y,
412 contacts[i].normal.Z);
413
414 lock (m_contactResults)
415 m_contactResults.Add(collisionresult);
416 }
417 }
418 }
419 }
420
421 /// <summary>
422 /// Dereference the creator scene so that it can be garbage collected if needed.
423 /// </summary>
424 internal void Dispose()
425 {
426 m_scene = null;
427 }
428 }
429
430 public struct ODERayCastRequest
431 {
432 public Vector3 Origin;
433 public Vector3 Normal;
434 public float length;
435 public RaycastCallback callbackMethod;
436 }
437
438 public struct ODERayRequest
439 {
440 public Vector3 Origin;
441 public Vector3 Normal;
442 public int Count;
443 public float length;
444 public RayCallback callbackMethod;
445 }
446}