aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs1
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs2
-rw-r--r--OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs5
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs36
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs295
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs23
-rw-r--r--OpenSim/Region/Physics/POSPlugin/POSScene.cs2
-rw-r--r--OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs1
8 files changed, 364 insertions, 1 deletions
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs
index 83d7a1d..92d5771 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs
@@ -210,6 +210,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
210 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>(); 210 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
211 return returncolliders; 211 return returncolliders;
212 } 212 }
213
213 } 214 }
214 215
215 public class BasicActor : PhysicsActor 216 public class BasicActor : PhysicsActor
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
index 58c2a15..e0f856a 100644
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
+++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
@@ -700,6 +700,8 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin
700 m_world.SetCollisionAddedCallback(m_CollisionInterface); 700 m_world.SetCollisionAddedCallback(m_CollisionInterface);
701 } 701 }
702 } 702 }
703
704
703 705
704 } 706 }
705} 707}
diff --git a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
index 7e5e812..abed8df 100644
--- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
+++ b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
@@ -817,9 +817,14 @@ namespace OpenSim.Region.Physics.BulletXPlugin
817 GC.Collect(); 817 GC.Collect();
818 BulletXMessage("Terrain erased!", false); 818 BulletXMessage("Terrain erased!", false);
819 } 819 }
820
821
822
820 //this._heightmap = null; 823 //this._heightmap = null;
821 } 824 }
822 825
826
827
823 internal void AddForgottenRigidBody(RigidBody forgottenRigidBody) 828 internal void AddForgottenRigidBody(RigidBody forgottenRigidBody)
824 { 829 {
825 _forgottenRigidBodies.Add(forgottenRigidBody); 830 _forgottenRigidBodies.Add(forgottenRigidBody);
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index 410707b..95699fb 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -36,6 +36,8 @@ namespace OpenSim.Region.Physics.Manager
36{ 36{
37 public delegate void physicsCrash(); 37 public delegate void physicsCrash();
38 38
39 public delegate void RaycastCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance);
40
39 public abstract class PhysicsScene 41 public abstract class PhysicsScene
40 { 42 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -152,6 +154,39 @@ namespace OpenSim.Region.Physics.Manager
152 154
153 public abstract bool IsThreaded { get; } 155 public abstract bool IsThreaded { get; }
154 156
157 /// <summary>
158 /// True if the physics plugin supports raycasting against the physics scene
159 /// </summary>
160 public virtual bool SupportsRayCast()
161 {
162 return false;
163 }
164
165 /// <summary>
166 /// Queue a raycast against the physics scene.
167 /// The provided callback method will be called when the raycast is complete
168 ///
169 /// Many physics engines don't support collision testing at the same time as
170 /// manipulating the physics scene, so we queue the request up and callback
171 /// a custom method when the raycast is complete.
172 /// This allows physics engines that give an immediate result to callback immediately
173 /// and ones that don't, to callback when it gets a result back.
174 ///
175 /// ODE for example will not allow you to change the scene while collision testing or
176 /// it asserts, 'opteration not valid for locked space'. This includes adding a ray to the scene.
177 ///
178 /// This is named RayCastWorld to not conflict with modrex's Raycast method.
179 /// </summary>
180 /// <param name="position">Origin of the ray</param>
181 /// <param name="direction">Direction of the ray</param>
182 /// <param name="length">Length of ray in meters</param>
183 /// <param name="retMethod">Method to call when the raycast is complete</param>
184 public virtual void RaycastWorld( Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
185 {
186 if (retMethod != null)
187 retMethod(false, Vector3.Zero, 0, 999999999999f);
188 }
189
155 private class NullPhysicsScene : PhysicsScene 190 private class NullPhysicsScene : PhysicsScene
156 { 191 {
157 private static int m_workIndicator; 192 private static int m_workIndicator;
@@ -240,6 +275,7 @@ namespace OpenSim.Region.Physics.Manager
240 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>(); 275 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
241 return returncolliders; 276 return returncolliders;
242 } 277 }
278
243 } 279 }
244 } 280 }
245 public delegate void JointMoved(PhysicsJoint joint); 281 public delegate void JointMoved(PhysicsJoint joint);
diff --git a/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs
new file mode 100644
index 0000000..3a4bb02
--- /dev/null
+++ b/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs
@@ -0,0 +1,295 @@
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.Physics.Manager;
35using Ode.NET;
36using log4net;
37
38namespace OpenSim.Region.Physics.OdePlugin
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 /// Scene that created this object.
54 /// </summary>
55 private OdeScene m_scene;
56
57 /// <summary>
58 /// ODE contact array to be filled by the collision testing
59 /// </summary>
60 d.ContactGeom[] contacts = new d.ContactGeom[5];
61
62 /// <summary>
63 /// ODE near callback delegate
64 /// </summary>
65 private d.NearCallback nearCallback;
66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
67 private List<ContactResult> m_contactResults = new List<ContactResult>();
68
69
70 public ODERayCastRequestManager( OdeScene pScene)
71 {
72 m_scene = pScene;
73 nearCallback = near;
74
75 }
76
77 /// <summary>
78 /// Queues a raycast
79 /// </summary>
80 /// <param name="position">Origin of Ray</param>
81 /// <param name="direction">Ray normal</param>
82 /// <param name="length">Ray length</param>
83 /// <param name="retMethod">Return method to send the results</param>
84 public void QueueRequest(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
85 {
86 lock (m_PendingRequests)
87 {
88 ODERayCastRequest req = new ODERayCastRequest();
89 req.callbackMethod = retMethod;
90 req.length = length;
91 req.Normal = direction;
92 req.Origin = position;
93
94 m_PendingRequests.Add(req);
95 }
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 int time = System.Environment.TickCount;
105 lock (m_PendingRequests)
106 {
107 if (m_PendingRequests.Count > 0)
108 {
109 foreach (ODERayCastRequest req in m_PendingRequests)
110 {
111 if (req.callbackMethod != null) // quick optimization here, don't raycast
112 RayCast(req); // if there isn't anyone to send results to
113
114 }
115
116 m_PendingRequests.Clear();
117 }
118 }
119
120 lock (m_contactResults)
121 m_contactResults.Clear();
122
123 return System.Environment.TickCount - time;
124 }
125
126 /// <summary>
127 /// Method that actually initiates the raycast
128 /// </summary>
129 /// <param name="req"></param>
130 private void RayCast(ODERayCastRequest req)
131 {
132 // Create the ray
133 IntPtr ray = d.CreateRay(m_scene.space, req.length);
134 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
135
136 // Collide test
137 d.SpaceCollide2(m_scene.space, ray, IntPtr.Zero, nearCallback);
138
139 // Remove Ray
140 d.GeomDestroy(ray);
141
142
143 // Define default results
144 bool hitYN = false;
145 uint hitConsumerID = 0;
146 float distance = 999999999999f;
147 Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f);
148
149 // Find closest contact and object.
150 lock (m_contactResults)
151 {
152 foreach(ContactResult cResult in m_contactResults)
153 {
154 if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact))
155 {
156 closestcontact = cResult.Pos;
157 hitConsumerID = cResult.ConsumerID;
158 distance = cResult.Depth;
159 hitYN = true;
160 }
161 }
162
163 m_contactResults.Clear();
164 }
165
166 // Return results
167 if (req.callbackMethod != null)
168 req.callbackMethod(hitYN, closestcontact, hitConsumerID, distance);
169 }
170
171 // This is the standard Near. Uses space AABBs to speed up detection.
172 private void near(IntPtr space, IntPtr g1, IntPtr g2)
173 {
174 // Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms.
175 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
176 {
177 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
178 return;
179
180 // Separating static prim geometry spaces.
181 // We'll be calling near recursivly if one
182 // of them is a space to find all of the
183 // contact points in the space
184 try
185 {
186 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
187 }
188 catch (AccessViolationException)
189 {
190 m_log.Warn("[PHYSICS]: Unable to collide test a space");
191 return;
192 }
193 //Colliding a space or a geom with a space or a geom. so drill down
194
195 //Collide all geoms in each space..
196 //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
197 //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
198 return;
199 }
200
201 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
202 return;
203
204 int count = 0;
205 try
206 {
207
208 if (g1 == g2)
209 return; // Can't collide with yourself
210
211 lock (contacts)
212 {
213 count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf);
214 }
215 }
216 catch (SEHException)
217 {
218 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.");
219 }
220 catch (Exception e)
221 {
222 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
223 return;
224 }
225
226 PhysicsActor p1 = null;
227 PhysicsActor p2 = null;
228
229 if (g1 != IntPtr.Zero)
230 m_scene.actor_name_map.TryGetValue(g1, out p1);
231
232 if (g2 != IntPtr.Zero)
233 m_scene.actor_name_map.TryGetValue(g1, out p2);
234
235 // Loop over contacts, build results.
236 for (int i = 0; i < count; i++)
237 {
238 if (p1 != null) {
239 if (p1 is OdePrim)
240 {
241 ContactResult collisionresult = new ContactResult();
242
243 collisionresult.ConsumerID = ((OdePrim)p1).m_localID;
244 collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z);
245 collisionresult.Depth = contacts[i].depth;
246
247 lock (m_contactResults)
248 m_contactResults.Add(collisionresult);
249 }
250 }
251
252 if (p2 != null)
253 {
254 if (p2 is OdePrim)
255 {
256 ContactResult collisionresult = new ContactResult();
257
258 collisionresult.ConsumerID = ((OdePrim)p2).m_localID;
259 collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z);
260 collisionresult.Depth = contacts[i].depth;
261
262 lock (m_contactResults)
263 m_contactResults.Add(collisionresult);
264 }
265 }
266
267
268 }
269
270 }
271
272 /// <summary>
273 /// Dereference the creator scene so that it can be garbage collected if needed.
274 /// </summary>
275 internal void Dispose()
276 {
277 m_scene = null;
278 }
279 }
280
281 public struct ODERayCastRequest
282 {
283 public Vector3 Origin;
284 public Vector3 Normal;
285 public float length;
286 public RaycastCallback callbackMethod;
287 }
288
289 public struct ContactResult
290 {
291 public Vector3 Pos;
292 public float Depth;
293 public uint ConsumerID;
294 }
295}
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 889afb6..87357a3 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -306,6 +306,8 @@ namespace OpenSim.Region.Physics.OdePlugin
306 306
307 private volatile int m_global_contactcount = 0; 307 private volatile int m_global_contactcount = 0;
308 308
309 private ODERayCastRequestManager m_rayCastManager;
310
309 /// <summary> 311 /// <summary>
310 /// Initiailizes the scene 312 /// Initiailizes the scene
311 /// Sets many properties that ODE requires to be stable 313 /// Sets many properties that ODE requires to be stable
@@ -321,7 +323,7 @@ namespace OpenSim.Region.Physics.OdePlugin
321 nearCallback = near; 323 nearCallback = near;
322 triCallback = TriCallback; 324 triCallback = TriCallback;
323 triArrayCallback = TriArrayCallback; 325 triArrayCallback = TriArrayCallback;
324 326 m_rayCastManager = new ODERayCastRequestManager(this);
325 lock (OdeLock) 327 lock (OdeLock)
326 { 328 {
327 // Create the world and the first space 329 // Create the world and the first space
@@ -2833,6 +2835,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2833 //if ((framecount % m_randomizeWater) == 0) 2835 //if ((framecount % m_randomizeWater) == 0)
2834 // randomizeWater(waterlevel); 2836 // randomizeWater(waterlevel);
2835 2837
2838 int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests();
2839
2836 collision_optimized(timeStep); 2840 collision_optimized(timeStep);
2837 2841
2838 lock (_collisionEventPrim) 2842 lock (_collisionEventPrim)
@@ -3377,6 +3381,9 @@ namespace OpenSim.Region.Physics.OdePlugin
3377 3381
3378 public override void Dispose() 3382 public override void Dispose()
3379 { 3383 {
3384 m_rayCastManager.Dispose();
3385 m_rayCastManager = null;
3386
3380 lock (OdeLock) 3387 lock (OdeLock)
3381 { 3388 {
3382 lock (_prims) 3389 lock (_prims)
@@ -3417,6 +3424,20 @@ namespace OpenSim.Region.Physics.OdePlugin
3417 } 3424 }
3418 return returncolliders; 3425 return returncolliders;
3419 } 3426 }
3427
3428 public override bool SupportsRayCast()
3429 {
3430 return true;
3431 }
3432
3433 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
3434 {
3435 if (retMethod != null)
3436 {
3437 m_rayCastManager.QueueRequest(position, direction, length, retMethod);
3438 }
3439 }
3440
3420#if USE_DRAWSTUFF 3441#if USE_DRAWSTUFF
3421 // Keyboard callback 3442 // Keyboard callback
3422 public void command(int cmd) 3443 public void command(int cmd)
diff --git a/OpenSim/Region/Physics/POSPlugin/POSScene.cs b/OpenSim/Region/Physics/POSPlugin/POSScene.cs
index 3128477..029dcce 100644
--- a/OpenSim/Region/Physics/POSPlugin/POSScene.cs
+++ b/OpenSim/Region/Physics/POSPlugin/POSScene.cs
@@ -272,5 +272,7 @@ namespace OpenSim.Region.Physics.POSPlugin
272 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>(); 272 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
273 return returncolliders; 273 return returncolliders;
274 } 274 }
275
276
275 } 277 }
276} 278}
diff --git a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs
index 3082455..e7d989c 100644
--- a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs
+++ b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs
@@ -214,6 +214,7 @@ namespace OpenSim.Region.Physics.PhysXPlugin
214 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>(); 214 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
215 return returncolliders; 215 return returncolliders;
216 } 216 }
217
217 } 218 }
218 219
219 public class PhysXCharacter : PhysicsActor 220 public class PhysXCharacter : PhysicsActor