aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
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
parentThank you, otakup0pe, for a patch that enables basic auth with LSL (diff)
downloadopensim-SC_OLD-08819bcbea9012d67cc4cb44e4d7ec7e5837bac6.zip
opensim-SC_OLD-08819bcbea9012d67cc4cb44e4d7ec7e5837bac6.tar.gz
opensim-SC_OLD-08819bcbea9012d67cc4cb44e4d7ec7e5837bac6.tar.bz2
opensim-SC_OLD-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 'OpenSim')
-rw-r--r--OpenSim/Client/MXP/ClientStack/MXPClientView.cs5
-rw-r--r--OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs5
-rw-r--r--OpenSim/Framework/IClientAPI.cs1
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs11
-rw-r--r--OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs73
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs5
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs3
-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
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs4
17 files changed, 475 insertions, 2 deletions
diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
index d8980c1..a7bcc07 100644
--- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
+++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
@@ -1240,6 +1240,11 @@ namespace OpenSim.Client.MXP.ClientStack
1240 // Need to translate to MXP somehow 1240 // Need to translate to MXP somehow
1241 } 1241 }
1242 1242
1243 public void SendCameraConstraint(Vector4 ConstraintPlane)
1244 {
1245
1246 }
1247
1243 public void SendLandParcelOverlay(byte[] data, int sequence_id) 1248 public void SendLandParcelOverlay(byte[] data, int sequence_id)
1244 { 1249 {
1245 // Need to translate to MXP somehow 1250 // Need to translate to MXP somehow
diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
index 4570395..324b5af 100644
--- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
+++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
@@ -780,6 +780,11 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
780 throw new System.NotImplementedException(); 780 throw new System.NotImplementedException();
781 } 781 }
782 782
783 public void SendCameraConstraint(Vector4 ConstraintPlane)
784 {
785
786 }
787
783 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount) 788 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount)
784 { 789 {
785 throw new System.NotImplementedException(); 790 throw new System.NotImplementedException();
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index fea0cea..52d9716 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -1007,6 +1007,7 @@ namespace OpenSim.Framework
1007 1007
1008 void SendLandAccessListData(List<UUID> avatars, uint accessFlag, int localLandID); 1008 void SendLandAccessListData(List<UUID> avatars, uint accessFlag, int localLandID);
1009 void SendForceClientSelectObjects(List<uint> objectIDs); 1009 void SendForceClientSelectObjects(List<uint> objectIDs);
1010 void SendCameraConstraint(Vector4 ConstraintPlane);
1010 void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount); 1011 void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount);
1011 void SendLandParcelOverlay(byte[] data, int sequence_id); 1012 void SendLandParcelOverlay(byte[] data, int sequence_id);
1012 1013
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index a13f6d4..3a93007 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -3779,8 +3779,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3779 } 3779 }
3780 } 3780 }
3781 3781
3782 public void SendCameraConstraint(Vector4 ConstraintPlane)
3783 {
3784 CameraConstraintPacket cpack = (CameraConstraintPacket)PacketPool.Instance.GetPacket(PacketType.CameraConstraint);
3785 cpack.CameraCollidePlane = new CameraConstraintPacket.CameraCollidePlaneBlock();
3786 cpack.CameraCollidePlane.Plane = ConstraintPlane;
3787 m_log.DebugFormat("[CLIENTVIEW]: Constraint {0}", ConstraintPlane);
3788 OutPacket(cpack, ThrottleOutPacketType.Task);
3789 }
3790
3782 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount) 3791 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount)
3783 { 3792 {
3793
3794
3784 int notifyCount = ownersAndCount.Count; 3795 int notifyCount = ownersAndCount.Count;
3785 ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); 3796 ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply);
3786 3797
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index ed38046..62779e7 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -900,6 +900,11 @@ namespace OpenSim.Region.Examples.SimpleModule
900 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount) 900 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount)
901 { 901 {
902 } 902 }
903
904 public void SendCameraConstraint(Vector4 ConstraintPlane)
905 {
906
907 }
903 908
904 public void SendLandParcelOverlay(byte[] data, int sequence_id) 909 public void SendLandParcelOverlay(byte[] data, int sequence_id)
905 { 910 {
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 87207a0..2a8436b 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -186,6 +186,14 @@ namespace OpenSim.Region.Framework.Scenes
186 //PauPaw:Proper PID Controler for autopilot************ 186 //PauPaw:Proper PID Controler for autopilot************
187 private bool m_moveToPositionInProgress; 187 private bool m_moveToPositionInProgress;
188 private Vector3 m_moveToPositionTarget = Vector3.Zero; 188 private Vector3 m_moveToPositionTarget = Vector3.Zero;
189
190 private bool m_followCamAuto = false;
191
192 private int m_movementUpdateCount = 0;
193
194 private const int NumMovementsBetweenRayCast = 5;
195
196 private bool CameraConstraintActive = false;
189 //private int m_moveToPositionStateStatus = 0; 197 //private int m_moveToPositionStateStatus = 0;
190 //***************************************************** 198 //*****************************************************
191 199
@@ -1073,6 +1081,44 @@ namespace OpenSim.Region.Framework.Scenes
1073 } 1081 }
1074 } 1082 }
1075 1083
1084
1085 /// <summary>
1086 /// Callback for the Camera view block check. Gets called with the results of the camera view block test
1087 /// hitYN is true when there's something in the way.
1088 /// </summary>
1089 /// <param name="hitYN"></param>
1090 /// <param name="collisionPoint"></param>
1091 /// <param name="localid"></param>
1092 /// <param name="distance"></param>
1093 public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance)
1094 {
1095 if (m_followCamAuto)
1096 {
1097
1098 if (hitYN)
1099 {
1100 CameraConstraintActive = true;
1101 //m_log.DebugFormat("[RAYCASTRESULT]: {0}, {1}, {2}, {3}", hitYN, collisionPoint, localid, distance);
1102
1103 Vector3 normal = Vector3.Normalize(new Vector3(0,0,collisionPoint.Z) - collisionPoint);
1104 ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint)));
1105 }
1106 else
1107 {
1108 if (((Util.GetDistanceTo(lastPhysPos, AbsolutePosition) > 0.02)
1109 || (Util.GetDistanceTo(m_lastVelocity, m_velocity) > 0.02)
1110 || lastPhysRot != m_bodyRot))
1111 {
1112 if (CameraConstraintActive)
1113 {
1114 ControllingClient.SendCameraConstraint(new Vector4(0, 0.5f, 0.9f, -3000f));
1115 CameraConstraintActive = false;
1116 }
1117 }
1118 }
1119 }
1120 }
1121
1076 /// <summary> 1122 /// <summary>
1077 /// This is the event handler for client movement. If a client is moving, this event is triggering. 1123 /// This is the event handler for client movement. If a client is moving, this event is triggering.
1078 /// </summary> 1124 /// </summary>
@@ -1098,11 +1144,18 @@ namespace OpenSim.Region.Framework.Scenes
1098 // return; 1144 // return;
1099 //} 1145 //}
1100 1146
1147
1148 m_movementUpdateCount++;
1149 if (m_movementUpdateCount >= int.MaxValue)
1150 m_movementUpdateCount = 1;
1151
1152
1101 // Must check for standing up even when PhysicsActor is null, 1153 // Must check for standing up even when PhysicsActor is null,
1102 // since sitting currently removes avatar from physical scene 1154 // since sitting currently removes avatar from physical scene
1103 //m_log.Debug("agentPos:" + AbsolutePosition.ToString()); 1155 //m_log.Debug("agentPos:" + AbsolutePosition.ToString());
1104 1156
1105 // This is irritating. Really. 1157 // This is irritating. Really.
1158
1106 if (!AbsolutePosition.IsFinite()) 1159 if (!AbsolutePosition.IsFinite())
1107 { 1160 {
1108 RemoveFromPhysicalScene(); 1161 RemoveFromPhysicalScene();
@@ -1157,8 +1210,26 @@ namespace OpenSim.Region.Framework.Scenes
1157 { 1210 {
1158 StandUp(); 1211 StandUp();
1159 } 1212 }
1160
1161 1213
1214
1215
1216 // Check if Client has camera in 'follow cam' or 'build' mode.
1217 Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation);
1218
1219 m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f)
1220 && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
1221
1222
1223 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
1224 if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
1225 {
1226
1227 if (m_followCamAuto)
1228 {
1229 Vector3 headadjustment = new Vector3(0, 0, 0.3f);
1230 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - (m_pos + headadjustment)), Vector3.Distance(m_CameraCenter, (m_pos + headadjustment)) + 0.3f, RayCastCameraCallback);
1231 }
1232 }
1162 1233
1163 m_mouseLook = (flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; 1234 m_mouseLook = (flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
1164 1235
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 776e972..44bd716 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -1233,6 +1233,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1233 1233
1234 } 1234 }
1235 1235
1236 public void SendCameraConstraint(Vector4 ConstraintPlane)
1237 {
1238
1239 }
1240
1236 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount) 1241 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount)
1237 { 1242 {
1238 1243
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index a1ed6ee..2102db9 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -904,6 +904,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC
904 public void SendForceClientSelectObjects(List<uint> objectIDs) 904 public void SendForceClientSelectObjects(List<uint> objectIDs)
905 { 905 {
906 } 906 }
907 public void SendCameraConstraint(Vector4 ConstraintPlane)
908 {
909 }
907 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount) 910 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount)
908 { 911 {
909 } 912 }
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
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 21541e1..4b59b50 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -942,6 +942,10 @@ namespace OpenSim.Tests.Common.Mock
942 { 942 {
943 } 943 }
944 944
945 public void SendCameraConstraint(Vector4 ConstraintPlane)
946 {
947 }
948
945 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount) 949 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount)
946 { 950 {
947 } 951 }