aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authorTeravus Ovares2009-07-19 02:32:02 +0000
committerTeravus Ovares2009-07-19 02:32:02 +0000
commit08819bcbea9012d67cc4cb44e4d7ec7e5837bac6 (patch)
tree9158d1b42f1563db2294cfce5e85f41f1345d613 /OpenSim/Region/Physics
parentThank you, otakup0pe, for a patch that enables basic auth with LSL (diff)
downloadopensim-SC-08819bcbea9012d67cc4cb44e4d7ec7e5837bac6.zip
opensim-SC-08819bcbea9012d67cc4cb44e4d7ec7e5837bac6.tar.gz
opensim-SC-08819bcbea9012d67cc4cb44e4d7ec7e5837bac6.tar.bz2
opensim-SC-08819bcbea9012d67cc4cb44e4d7ec7e5837bac6.tar.xz
* Created a way that the OpenSimulator scene can ask the physics scene to do a raycast test safely.
* Test for prim obstructions between the avatar and camera. If there are obstructions, inform the client to move the camera closer. This makes it so that walls and objects don't obstruct your view while you're moving around. Try walking inside a hollowed tori. You'll see how much easier it is now because your camera automatically moves closer so you can still see. * Created a way to know if the user's camera is alt + cammed or just following the avatar. * Changes IClientAPI interface by adding SendCameraConstraint(Vector4 CameraConstraint)
Diffstat (limited to '')
-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