diff options
author | Melanie | 2013-01-06 10:52:22 +0000 |
---|---|---|
committer | Melanie | 2013-01-06 10:52:22 +0000 |
commit | 083ac92b344262ae72516ba05cc93cdcd2f2a454 (patch) | |
tree | 1992de8e08171aac3e811fb1d43abc6ad8b894af /OpenSim/Region/Physics/UbitOdePlugin | |
parent | Merge branch 'master' into careminster (diff) | |
parent | bug fix, cleanup... (diff) | |
download | opensim-SC-083ac92b344262ae72516ba05cc93cdcd2f2a454.zip opensim-SC-083ac92b344262ae72516ba05cc93cdcd2f2a454.tar.gz opensim-SC-083ac92b344262ae72516ba05cc93cdcd2f2a454.tar.bz2 opensim-SC-083ac92b344262ae72516ba05cc93cdcd2f2a454.tar.xz |
Merge branch 'avination' into careminster
Diffstat (limited to 'OpenSim/Region/Physics/UbitOdePlugin')
-rw-r--r-- | OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs | 62 | ||||
-rw-r--r-- | OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs | 571 | ||||
-rw-r--r-- | OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs | 288 | ||||
-rw-r--r-- | OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs | 15 | ||||
-rw-r--r-- | OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs | 253 |
5 files changed, 833 insertions, 356 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs index bb04ea7..f7e4c1c 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs | |||
@@ -715,7 +715,17 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
715 | Vector3 off = _velocity; | 715 | Vector3 off = _velocity; |
716 | float t = 0.5f * timeStep; | 716 | float t = 0.5f * timeStep; |
717 | off = off * t; | 717 | off = off * t; |
718 | d.Quaternion qtmp; | ||
719 | d.GeomCopyQuaternion(bbox, out qtmp); | ||
720 | Quaternion q; | ||
721 | q.X = qtmp.X; | ||
722 | q.Y = qtmp.Y; | ||
723 | q.Z = qtmp.Z; | ||
724 | q.W = qtmp.W; | ||
725 | off *= Quaternion.Conjugate(q); | ||
726 | |||
718 | d.GeomSetOffsetPosition(bbox, off.X, off.Y, off.Z); | 727 | d.GeomSetOffsetPosition(bbox, off.X, off.Y, off.Z); |
728 | |||
719 | off.X = 2.0f * (m_size.X + Math.Abs(off.X)); | 729 | off.X = 2.0f * (m_size.X + Math.Abs(off.X)); |
720 | off.Y = 2.0f * (m_size.Y + Math.Abs(off.Y)); | 730 | off.Y = 2.0f * (m_size.Y + Math.Abs(off.Y)); |
721 | off.Z = m_size.Z + 2.0f * Math.Abs(off.Z); | 731 | off.Z = m_size.Z + 2.0f * Math.Abs(off.Z); |
@@ -741,6 +751,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
741 | d.GeomSetCategoryBits(feetbox, (uint)m_collisionCategories); | 751 | d.GeomSetCategoryBits(feetbox, (uint)m_collisionCategories); |
742 | d.GeomSetCollideBits(feetbox, (uint)m_collisionFlags); | 752 | d.GeomSetCollideBits(feetbox, (uint)m_collisionFlags); |
743 | } | 753 | } |
754 | uint cat1 = d.GeomGetCategoryBits(bbox); | ||
755 | uint col1 = d.GeomGetCollideBits(bbox); | ||
756 | |||
744 | } | 757 | } |
745 | } | 758 | } |
746 | 759 | ||
@@ -1527,8 +1540,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1527 | { | 1540 | { |
1528 | if (CollisionEventsThisFrame != null) | 1541 | if (CollisionEventsThisFrame != null) |
1529 | { | 1542 | { |
1530 | CollisionEventsThisFrame.Clear(); | 1543 | lock (CollisionEventsThisFrame) |
1531 | CollisionEventsThisFrame = null; | 1544 | { |
1545 | CollisionEventsThisFrame.Clear(); | ||
1546 | CollisionEventsThisFrame = null; | ||
1547 | } | ||
1532 | } | 1548 | } |
1533 | m_eventsubscription = 0; | 1549 | m_eventsubscription = 0; |
1534 | } | 1550 | } |
@@ -1537,8 +1553,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1537 | { | 1553 | { |
1538 | if (CollisionEventsThisFrame == null) | 1554 | if (CollisionEventsThisFrame == null) |
1539 | CollisionEventsThisFrame = new CollisionEventUpdate(); | 1555 | CollisionEventsThisFrame = new CollisionEventUpdate(); |
1540 | CollisionEventsThisFrame.AddCollider(CollidedWith, contact); | 1556 | lock (CollisionEventsThisFrame) |
1541 | _parent_scene.AddCollisionEventReporting(this); | 1557 | { |
1558 | CollisionEventsThisFrame.AddCollider(CollidedWith, contact); | ||
1559 | _parent_scene.AddCollisionEventReporting(this); | ||
1560 | } | ||
1542 | } | 1561 | } |
1543 | 1562 | ||
1544 | public void SendCollisions() | 1563 | public void SendCollisions() |
@@ -1546,26 +1565,29 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1546 | if (CollisionEventsThisFrame == null) | 1565 | if (CollisionEventsThisFrame == null) |
1547 | return; | 1566 | return; |
1548 | 1567 | ||
1549 | if (m_cureventsubscription < m_eventsubscription) | 1568 | lock (CollisionEventsThisFrame) |
1550 | return; | 1569 | { |
1551 | 1570 | if (m_cureventsubscription < m_eventsubscription) | |
1552 | m_cureventsubscription = 0; | 1571 | return; |
1553 | 1572 | ||
1554 | int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count; | 1573 | m_cureventsubscription = 0; |
1555 | 1574 | ||
1556 | if (!SentEmptyCollisionsEvent || ncolisions > 0) | 1575 | int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count; |
1557 | { | ||
1558 | base.SendCollisionUpdate(CollisionEventsThisFrame); | ||
1559 | 1576 | ||
1560 | if (ncolisions == 0) | 1577 | if (!SentEmptyCollisionsEvent || ncolisions > 0) |
1561 | { | ||
1562 | SentEmptyCollisionsEvent = true; | ||
1563 | _parent_scene.RemoveCollisionEventReporting(this); | ||
1564 | } | ||
1565 | else | ||
1566 | { | 1578 | { |
1567 | SentEmptyCollisionsEvent = false; | 1579 | base.SendCollisionUpdate(CollisionEventsThisFrame); |
1568 | CollisionEventsThisFrame.Clear(); | 1580 | |
1581 | if (ncolisions == 0) | ||
1582 | { | ||
1583 | SentEmptyCollisionsEvent = true; | ||
1584 | _parent_scene.RemoveCollisionEventReporting(this); | ||
1585 | } | ||
1586 | else | ||
1587 | { | ||
1588 | SentEmptyCollisionsEvent = false; | ||
1589 | CollisionEventsThisFrame.Clear(); | ||
1590 | } | ||
1569 | } | 1591 | } |
1570 | } | 1592 | } |
1571 | } | 1593 | } |
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs index 561ab1c..6e9281b 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs | |||
@@ -56,8 +56,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
56 | private OdeScene m_scene; | 56 | private OdeScene m_scene; |
57 | 57 | ||
58 | IntPtr ray; // the ray. we only need one for our lifetime | 58 | IntPtr ray; // the ray. we only need one for our lifetime |
59 | IntPtr Sphere; | ||
60 | IntPtr Box; | ||
61 | IntPtr Plane; | ||
59 | 62 | ||
60 | private const int ColisionContactGeomsPerTest = 5; | 63 | private int CollisionContactGeomsPerTest = 25; |
61 | private const int DefaultMaxCount = 25; | 64 | private const int DefaultMaxCount = 25; |
62 | private const int MaxTimePerCallMS = 30; | 65 | private const int MaxTimePerCallMS = 30; |
63 | 66 | ||
@@ -65,6 +68,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
65 | /// ODE near callback delegate | 68 | /// ODE near callback delegate |
66 | /// </summary> | 69 | /// </summary> |
67 | private d.NearCallback nearCallback; | 70 | private d.NearCallback nearCallback; |
71 | private d.NearCallback nearProbeCallback; | ||
68 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 72 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
69 | private List<ContactResult> m_contactResults = new List<ContactResult>(); | 73 | private List<ContactResult> m_contactResults = new List<ContactResult>(); |
70 | private RayFilterFlags CurrentRayFilter; | 74 | private RayFilterFlags CurrentRayFilter; |
@@ -74,155 +78,21 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
74 | { | 78 | { |
75 | m_scene = pScene; | 79 | m_scene = pScene; |
76 | nearCallback = near; | 80 | nearCallback = near; |
81 | nearProbeCallback = nearProbe; | ||
77 | ray = d.CreateRay(IntPtr.Zero, 1.0f); | 82 | ray = d.CreateRay(IntPtr.Zero, 1.0f); |
78 | d.GeomSetCategoryBits(ray,0); | 83 | d.GeomSetCategoryBits(ray, 0); |
84 | Box = d.CreateBox(IntPtr.Zero, 1.0f, 1.0f, 1.0f); | ||
85 | d.GeomSetCategoryBits(Box, 0); | ||
86 | Sphere = d.CreateSphere(IntPtr.Zero,1.0f); | ||
87 | d.GeomSetCategoryBits(Sphere, 0); | ||
88 | Plane = d.CreatePlane(IntPtr.Zero, 0f,0f,1f,1f); | ||
89 | d.GeomSetCategoryBits(Sphere, 0); | ||
79 | } | 90 | } |
80 | 91 | ||
81 | /// <summary> | 92 | public void QueueRequest(ODERayRequest req) |
82 | /// Queues request for a raycast to all world | ||
83 | /// </summary> | ||
84 | /// <param name="position">Origin of Ray</param> | ||
85 | /// <param name="direction">Ray direction</param> | ||
86 | /// <param name="length">Ray length</param> | ||
87 | /// <param name="retMethod">Return method to send the results</param> | ||
88 | public void QueueRequest(Vector3 position, Vector3 direction, float length, RayCallback retMethod) | ||
89 | { | ||
90 | ODERayRequest req = new ODERayRequest(); | ||
91 | req.geom = IntPtr.Zero; | ||
92 | req.callbackMethod = retMethod; | ||
93 | req.Count = DefaultMaxCount; | ||
94 | req.length = length; | ||
95 | req.Normal = direction; | ||
96 | req.Origin = position; | ||
97 | req.filter = RayFilterFlags.AllPrims; | ||
98 | |||
99 | m_PendingRequests.Enqueue(req); | ||
100 | } | ||
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> | ||
109 | public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RayCallback retMethod) | ||
110 | { | ||
111 | ODERayRequest req = new ODERayRequest(); | ||
112 | req.geom = geom; | ||
113 | req.callbackMethod = retMethod; | ||
114 | req.length = length; | ||
115 | req.Normal = direction; | ||
116 | req.Origin = position; | ||
117 | req.Count = DefaultMaxCount; | ||
118 | req.filter = RayFilterFlags.AllPrims; | ||
119 | |||
120 | m_PendingRequests.Enqueue(req); | ||
121 | } | ||
122 | |||
123 | public void QueueRequest(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) | ||
124 | { | ||
125 | ODERayRequest req = new ODERayRequest(); | ||
126 | req.geom = IntPtr.Zero; | ||
127 | req.callbackMethod = retMethod; | ||
128 | req.Count = DefaultMaxCount; | ||
129 | req.length = length; | ||
130 | req.Normal = direction; | ||
131 | req.Origin = position; | ||
132 | req.filter = RayFilterFlags.AllPrims | RayFilterFlags.land; | ||
133 | |||
134 | m_PendingRequests.Enqueue(req); | ||
135 | } | ||
136 | |||
137 | public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) | ||
138 | { | 93 | { |
139 | ODERayRequest req = new ODERayRequest(); | 94 | if (req.Count == 0) |
140 | req.geom = geom; | 95 | req.Count = DefaultMaxCount; |
141 | req.callbackMethod = retMethod; | ||
142 | req.length = length; | ||
143 | req.Normal = direction; | ||
144 | req.Origin = position; | ||
145 | req.Count = DefaultMaxCount; | ||
146 | req.filter = RayFilterFlags.AllPrims; | ||
147 | |||
148 | m_PendingRequests.Enqueue(req); | ||
149 | } | ||
150 | |||
151 | /// <summary> | ||
152 | /// Queues a raycast | ||
153 | /// </summary> | ||
154 | /// <param name="position">Origin of Ray</param> | ||
155 | /// <param name="direction">Ray normal</param> | ||
156 | /// <param name="length">Ray length</param> | ||
157 | /// <param name="count"></param> | ||
158 | /// <param name="retMethod">Return method to send the results</param> | ||
159 | public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod) | ||
160 | { | ||
161 | ODERayRequest req = new ODERayRequest(); | ||
162 | req.geom = IntPtr.Zero; | ||
163 | req.callbackMethod = retMethod; | ||
164 | req.length = length; | ||
165 | req.Normal = direction; | ||
166 | req.Origin = position; | ||
167 | req.Count = count; | ||
168 | req.filter = RayFilterFlags.AllPrims; | ||
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; | ||
184 | |||
185 | m_PendingRequests.Enqueue(req); | ||
186 | } | ||
187 | |||
188 | public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod) | ||
189 | { | ||
190 | ODERayRequest req = new ODERayRequest(); | ||
191 | req.geom = geom; | ||
192 | req.callbackMethod = retMethod; | ||
193 | req.length = length; | ||
194 | req.Normal = direction; | ||
195 | req.Origin = position; | ||
196 | req.Count = count; | ||
197 | req.filter = RayFilterFlags.AllPrims; | ||
198 | |||
199 | m_PendingRequests.Enqueue(req); | ||
200 | } | ||
201 | |||
202 | public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RaycastCallback retMethod) | ||
203 | { | ||
204 | ODERayRequest req = new ODERayRequest(); | ||
205 | req.geom = IntPtr.Zero; | ||
206 | req.callbackMethod = retMethod; | ||
207 | req.length = length; | ||
208 | req.Normal = direction; | ||
209 | req.Origin = position; | ||
210 | req.Count = count; | ||
211 | req.filter = RayFilterFlags.AllPrims; | ||
212 | |||
213 | m_PendingRequests.Enqueue(req); | ||
214 | } | ||
215 | |||
216 | public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, int count, RaycastCallback retMethod) | ||
217 | { | ||
218 | ODERayRequest req = new ODERayRequest(); | ||
219 | req.geom = geom; | ||
220 | req.callbackMethod = retMethod; | ||
221 | req.length = length; | ||
222 | req.Normal = direction; | ||
223 | req.Origin = position; | ||
224 | req.Count = count; | ||
225 | req.filter = RayFilterFlags.AllPrims; | ||
226 | 96 | ||
227 | m_PendingRequests.Enqueue(req); | 97 | m_PendingRequests.Enqueue(req); |
228 | } | 98 | } |
@@ -258,21 +128,64 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
258 | CurrentRayFilter = req.filter; | 128 | CurrentRayFilter = req.filter; |
259 | CurrentMaxCount = req.Count; | 129 | CurrentMaxCount = req.Count; |
260 | 130 | ||
131 | CollisionContactGeomsPerTest = req.Count & 0xffff; | ||
132 | |||
261 | closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1); | 133 | closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1); |
262 | backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1); | 134 | backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1); |
263 | 135 | ||
264 | d.GeomRaySetLength(ray, req.length); | 136 | if (req.callbackMethod is ProbeBoxCallback) |
265 | d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); | 137 | { |
266 | d.GeomRaySetParams(ray, 0, backfacecull); | 138 | if (CollisionContactGeomsPerTest > 80) |
267 | d.GeomRaySetClosestHit(ray, closestHit); | 139 | CollisionContactGeomsPerTest = 80; |
140 | d.GeomBoxSetLengths(Box, req.Normal.X, req.Normal.Y, req.Normal.Z); | ||
141 | d.GeomSetPosition(Box, req.Origin.X, req.Origin.Y, req.Origin.Z); | ||
142 | d.Quaternion qtmp; | ||
143 | qtmp.X = req.orientation.X; | ||
144 | qtmp.Y = req.orientation.Y; | ||
145 | qtmp.Z = req.orientation.Z; | ||
146 | qtmp.W = req.orientation.W; | ||
147 | d.GeomSetQuaternion(Box, ref qtmp); | ||
148 | } | ||
149 | else if (req.callbackMethod is ProbeSphereCallback) | ||
150 | { | ||
151 | if (CollisionContactGeomsPerTest > 80) | ||
152 | CollisionContactGeomsPerTest = 80; | ||
153 | |||
154 | d.GeomSphereSetRadius(Sphere, req.length); | ||
155 | d.GeomSetPosition(Sphere, req.Origin.X, req.Origin.Y, req.Origin.Z); | ||
156 | } | ||
157 | else if (req.callbackMethod is ProbePlaneCallback) | ||
158 | { | ||
159 | if (CollisionContactGeomsPerTest > 80) | ||
160 | CollisionContactGeomsPerTest = 80; | ||
161 | |||
162 | d.GeomPlaneSetParams(Plane, req.Normal.X, req.Normal.Y, req.Normal.Z, req.length); | ||
163 | } | ||
164 | |||
165 | else | ||
166 | { | ||
167 | if (CollisionContactGeomsPerTest > 25) | ||
168 | CollisionContactGeomsPerTest = 25; | ||
268 | 169 | ||
269 | if (req.callbackMethod is RaycastCallback) | 170 | d.GeomRaySetLength(ray, req.length); |
270 | // if we only want one get only one per colision pair saving memory | 171 | d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); |
271 | CurrentRayFilter |= RayFilterFlags.ClosestHit; | 172 | d.GeomRaySetParams(ray, 0, backfacecull); |
173 | d.GeomRaySetClosestHit(ray, closestHit); | ||
174 | |||
175 | if (req.callbackMethod is RaycastCallback) | ||
176 | // if we only want one get only one per Collision pair saving memory | ||
177 | CurrentRayFilter |= RayFilterFlags.ClosestHit; | ||
178 | } | ||
179 | |||
180 | if ((CurrentRayFilter & RayFilterFlags.ContactsUnImportant) != 0) | ||
181 | unchecked | ||
182 | { | ||
183 | CollisionContactGeomsPerTest |= (int)d.CONTACTS_UNIMPORTANT; | ||
184 | } | ||
272 | 185 | ||
273 | if (req.geom == IntPtr.Zero) | 186 | if (req.geom == IntPtr.Zero) |
274 | { | 187 | { |
275 | // translate ray filter to colision flags | 188 | // translate ray filter to Collision flags |
276 | catflags = 0; | 189 | catflags = 0; |
277 | if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0) | 190 | if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0) |
278 | catflags |= CollisionCategories.VolumeDtc; | 191 | catflags |= CollisionCategories.VolumeDtc; |
@@ -289,15 +202,48 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
289 | 202 | ||
290 | if (catflags != 0) | 203 | if (catflags != 0) |
291 | { | 204 | { |
292 | d.GeomSetCollideBits(ray, (uint)catflags); | 205 | if (req.callbackMethod is ProbeBoxCallback) |
293 | doSpaceRay(req); | 206 | { |
207 | catflags |= CollisionCategories.Space; | ||
208 | d.GeomSetCollideBits(Box, (uint)catflags); | ||
209 | d.GeomSetCategoryBits(Box, (uint)catflags); | ||
210 | doProbe(req, Box); | ||
211 | } | ||
212 | else if (req.callbackMethod is ProbeSphereCallback) | ||
213 | { | ||
214 | catflags |= CollisionCategories.Space; | ||
215 | d.GeomSetCollideBits(Sphere, (uint)catflags); | ||
216 | d.GeomSetCategoryBits(Sphere, (uint)catflags); | ||
217 | doProbe(req, Sphere); | ||
218 | } | ||
219 | else if (req.callbackMethod is ProbePlaneCallback) | ||
220 | { | ||
221 | catflags |= CollisionCategories.Space; | ||
222 | d.GeomSetCollideBits(Plane, (uint)catflags); | ||
223 | d.GeomSetCategoryBits(Plane, (uint)catflags); | ||
224 | doPlane(req); | ||
225 | } | ||
226 | else | ||
227 | { | ||
228 | d.GeomSetCollideBits(ray, (uint)catflags); | ||
229 | doSpaceRay(req); | ||
230 | } | ||
294 | } | 231 | } |
295 | } | 232 | } |
296 | else | 233 | else |
297 | { | 234 | { |
298 | // if we select a geom don't use filters | 235 | // if we select a geom don't use filters |
299 | d.GeomSetCollideBits(ray, (uint)CollisionCategories.All); | 236 | |
300 | doGeomRay(req); | 237 | if (req.callbackMethod is ProbePlaneCallback) |
238 | { | ||
239 | d.GeomSetCollideBits(Plane, (uint)CollisionCategories.All); | ||
240 | doPlane(req); | ||
241 | } | ||
242 | else | ||
243 | { | ||
244 | d.GeomSetCollideBits(ray, (uint)CollisionCategories.All); | ||
245 | doGeomRay(req); | ||
246 | } | ||
301 | } | 247 | } |
302 | } | 248 | } |
303 | 249 | ||
@@ -382,6 +328,61 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
382 | } | 328 | } |
383 | } | 329 | } |
384 | 330 | ||
331 | private void doProbe(ODERayRequest req, IntPtr probe) | ||
332 | { | ||
333 | // Collide tests | ||
334 | if ((CurrentRayFilter & FilterActiveSpace) != 0) | ||
335 | { | ||
336 | d.SpaceCollide2(probe, m_scene.ActiveSpace, IntPtr.Zero, nearCallback); | ||
337 | d.SpaceCollide2(probe, m_scene.CharsSpace, IntPtr.Zero, nearCallback); | ||
338 | } | ||
339 | if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount)) | ||
340 | d.SpaceCollide2(probe, m_scene.StaticSpace, IntPtr.Zero, nearCallback); | ||
341 | if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount)) | ||
342 | d.SpaceCollide2(probe, m_scene.GroundSpace, IntPtr.Zero, nearCallback); | ||
343 | |||
344 | List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count); | ||
345 | lock (m_PendingRequests) | ||
346 | { | ||
347 | cresult.AddRange(m_contactResults); | ||
348 | m_contactResults.Clear(); | ||
349 | } | ||
350 | if (req.callbackMethod is ProbeBoxCallback) | ||
351 | ((ProbeBoxCallback)req.callbackMethod)(cresult); | ||
352 | else if (req.callbackMethod is ProbeSphereCallback) | ||
353 | ((ProbeSphereCallback)req.callbackMethod)(cresult); | ||
354 | } | ||
355 | |||
356 | private void doPlane(ODERayRequest req) | ||
357 | { | ||
358 | // Collide tests | ||
359 | if (req.geom == IntPtr.Zero) | ||
360 | { | ||
361 | if ((CurrentRayFilter & FilterActiveSpace) != 0) | ||
362 | { | ||
363 | d.SpaceCollide2(Plane, m_scene.ActiveSpace, IntPtr.Zero, nearCallback); | ||
364 | d.SpaceCollide2(Plane, m_scene.CharsSpace, IntPtr.Zero, nearCallback); | ||
365 | } | ||
366 | if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount)) | ||
367 | d.SpaceCollide2(Plane, m_scene.StaticSpace, IntPtr.Zero, nearCallback); | ||
368 | if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount)) | ||
369 | d.SpaceCollide2(Plane, m_scene.GroundSpace, IntPtr.Zero, nearCallback); | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | d.SpaceCollide2(Plane, req.geom, IntPtr.Zero, nearCallback); | ||
374 | } | ||
375 | |||
376 | List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count); | ||
377 | lock (m_PendingRequests) | ||
378 | { | ||
379 | cresult.AddRange(m_contactResults); | ||
380 | m_contactResults.Clear(); | ||
381 | } | ||
382 | |||
383 | ((ProbePlaneCallback)req.callbackMethod)(cresult); | ||
384 | } | ||
385 | |||
385 | /// <summary> | 386 | /// <summary> |
386 | /// Method that actually initiates the raycast with a geom | 387 | /// Method that actually initiates the raycast with a geom |
387 | /// </summary> | 388 | /// </summary> |
@@ -436,7 +437,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
436 | private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom) | 437 | private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom) |
437 | { | 438 | { |
438 | IntPtr ContactgeomsArray = m_scene.ContactgeomsArray; | 439 | IntPtr ContactgeomsArray = m_scene.ContactgeomsArray; |
439 | if (ContactgeomsArray == IntPtr.Zero || index >= ColisionContactGeomsPerTest) | 440 | if (ContactgeomsArray == IntPtr.Zero || index >= CollisionContactGeomsPerTest) |
440 | return false; | 441 | return false; |
441 | 442 | ||
442 | IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf)); | 443 | IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf)); |
@@ -469,7 +470,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
469 | int count = 0; | 470 | int count = 0; |
470 | try | 471 | try |
471 | { | 472 | { |
472 | count = d.CollidePtr(g1, g2, ColisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); | 473 | count = d.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); |
473 | } | 474 | } |
474 | catch (Exception e) | 475 | catch (Exception e) |
475 | { | 476 | { |
@@ -479,85 +480,211 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
479 | 480 | ||
480 | if (count == 0) | 481 | if (count == 0) |
481 | return; | 482 | return; |
482 | 483 | /* | |
484 | uint cat1 = d.GeomGetCategoryBits(g1); | ||
485 | uint cat2 = d.GeomGetCategoryBits(g2); | ||
486 | uint col1 = d.GeomGetCollideBits(g1); | ||
487 | uint col2 = d.GeomGetCollideBits(g2); | ||
488 | */ | ||
489 | |||
483 | uint ID = 0; | 490 | uint ID = 0; |
484 | PhysicsActor p2 = null; | 491 | PhysicsActor p2 = null; |
485 | 492 | ||
486 | m_scene.actor_name_map.TryGetValue(g2, out p2); | 493 | m_scene.actor_name_map.TryGetValue(g2, out p2); |
487 | 494 | ||
488 | if (p2 == null) | 495 | if (p2 == null) |
489 | { | ||
490 | /* | ||
491 | string name; | ||
492 | |||
493 | if (!m_scene.geom_name_map.TryGetValue(g2, out name)) | ||
494 | return; | ||
495 | |||
496 | if (name == "Terrain") | ||
497 | { | ||
498 | // land colision | ||
499 | if ((CurrentRayFilter & RayFilterFlags.land) == 0) | ||
500 | return; | ||
501 | } | ||
502 | else if (name == "Water") | ||
503 | { | ||
504 | if ((CurrentRayFilter & RayFilterFlags.water) == 0) | ||
505 | return; | ||
506 | } | ||
507 | else | ||
508 | return; | ||
509 | */ | ||
510 | return; | 496 | return; |
511 | } | 497 | |
512 | else | 498 | switch (p2.PhysicsActorType) |
513 | { | 499 | { |
514 | switch (p2.PhysicsActorType) | 500 | case (int)ActorTypes.Prim: |
515 | { | ||
516 | case (int)ActorTypes.Prim: | ||
517 | 501 | ||
518 | RayFilterFlags thisFlags; | 502 | RayFilterFlags thisFlags; |
519 | 503 | ||
520 | if (p2.IsPhysical) | 504 | if (p2.IsPhysical) |
521 | thisFlags = RayFilterFlags.physical; | 505 | thisFlags = RayFilterFlags.physical; |
522 | else | 506 | else |
523 | thisFlags = RayFilterFlags.nonphysical; | 507 | thisFlags = RayFilterFlags.nonphysical; |
524 | 508 | ||
525 | if (p2.Phantom) | 509 | if (p2.Phantom) |
526 | thisFlags |= RayFilterFlags.phantom; | 510 | thisFlags |= RayFilterFlags.phantom; |
527 | 511 | ||
528 | if (p2.IsVolumeDtc) | 512 | if (p2.IsVolumeDtc) |
529 | thisFlags |= RayFilterFlags.volumedtc; | 513 | thisFlags |= RayFilterFlags.volumedtc; |
530 | 514 | ||
531 | if ((thisFlags & CurrentRayFilter) == 0) | 515 | if ((thisFlags & CurrentRayFilter) == 0) |
532 | return; | 516 | return; |
533 | 517 | ||
534 | ID = ((OdePrim)p2).LocalID; | 518 | ID = ((OdePrim)p2).LocalID; |
535 | break; | 519 | break; |
536 | 520 | ||
537 | case (int)ActorTypes.Agent: | 521 | case (int)ActorTypes.Agent: |
538 | 522 | ||
539 | if ((CurrentRayFilter & RayFilterFlags.agent) == 0) | 523 | if ((CurrentRayFilter & RayFilterFlags.agent) == 0) |
540 | return; | 524 | return; |
541 | else | 525 | else |
542 | ID = ((OdeCharacter)p2).LocalID; | 526 | ID = ((OdeCharacter)p2).LocalID; |
543 | break; | 527 | break; |
544 | 528 | ||
545 | case (int)ActorTypes.Ground: | 529 | case (int)ActorTypes.Ground: |
546 | 530 | ||
547 | if ((CurrentRayFilter & RayFilterFlags.land) == 0) | 531 | if ((CurrentRayFilter & RayFilterFlags.land) == 0) |
548 | return; | 532 | return; |
549 | break; | 533 | break; |
550 | 534 | ||
551 | case (int)ActorTypes.Water: | 535 | case (int)ActorTypes.Water: |
552 | 536 | ||
553 | if ((CurrentRayFilter & RayFilterFlags.water) == 0) | 537 | if ((CurrentRayFilter & RayFilterFlags.water) == 0) |
554 | return; | 538 | return; |
539 | break; | ||
540 | |||
541 | default: | ||
542 | break; | ||
543 | } | ||
544 | |||
545 | d.ContactGeom curcontact = new d.ContactGeom(); | ||
546 | |||
547 | // closestHit for now only works for meshs, so must do it for others | ||
548 | if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0) | ||
549 | { | ||
550 | // Loop all contacts, build results. | ||
551 | for (int i = 0; i < count; i++) | ||
552 | { | ||
553 | if (!GetCurContactGeom(i, ref curcontact)) | ||
555 | break; | 554 | break; |
556 | 555 | ||
557 | default: | 556 | ContactResult collisionresult = new ContactResult(); |
557 | collisionresult.ConsumerID = ID; | ||
558 | collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z); | ||
559 | collisionresult.Depth = curcontact.depth; | ||
560 | collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y, | ||
561 | curcontact.normal.Z); | ||
562 | lock (m_contactResults) | ||
563 | { | ||
564 | m_contactResults.Add(collisionresult); | ||
565 | if (m_contactResults.Count >= CurrentMaxCount) | ||
566 | return; | ||
567 | } | ||
568 | } | ||
569 | } | ||
570 | else | ||
571 | { | ||
572 | // keep only closest contact | ||
573 | ContactResult collisionresult = new ContactResult(); | ||
574 | collisionresult.ConsumerID = ID; | ||
575 | collisionresult.Depth = float.MaxValue; | ||
576 | |||
577 | for (int i = 0; i < count; i++) | ||
578 | { | ||
579 | if (!GetCurContactGeom(i, ref curcontact)) | ||
558 | break; | 580 | break; |
581 | |||
582 | if (curcontact.depth < collisionresult.Depth) | ||
583 | { | ||
584 | collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z); | ||
585 | collisionresult.Depth = curcontact.depth; | ||
586 | collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y, | ||
587 | curcontact.normal.Z); | ||
588 | } | ||
589 | } | ||
590 | |||
591 | if (collisionresult.Depth != float.MaxValue) | ||
592 | { | ||
593 | lock (m_contactResults) | ||
594 | m_contactResults.Add(collisionresult); | ||
559 | } | 595 | } |
560 | } | 596 | } |
597 | } | ||
598 | |||
599 | private void nearProbe(IntPtr space, IntPtr g1, IntPtr g2) | ||
600 | { | ||
601 | if (g1 == IntPtr.Zero || g1 == g2) | ||
602 | return; | ||
603 | |||
604 | if (m_contactResults.Count >= CurrentMaxCount) | ||
605 | return; | ||
606 | |||
607 | if (d.GeomIsSpace(g1)) | ||
608 | { | ||
609 | try | ||
610 | { | ||
611 | d.SpaceCollide2(g1, g2, IntPtr.Zero, nearProbeCallback); | ||
612 | } | ||
613 | catch (Exception e) | ||
614 | { | ||
615 | m_log.WarnFormat("[PHYSICS Ray]: Unable to Space collide test an object: {0}", e.Message); | ||
616 | } | ||
617 | return; | ||
618 | } | ||
619 | |||
620 | int count = 0; | ||
621 | try | ||
622 | { | ||
623 | count = d.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); | ||
624 | } | ||
625 | catch (Exception e) | ||
626 | { | ||
627 | m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message); | ||
628 | return; | ||
629 | } | ||
630 | |||
631 | if (count == 0) | ||
632 | return; | ||
633 | |||
634 | uint ID = 0; | ||
635 | PhysicsActor p1 = null; | ||
636 | |||
637 | m_scene.actor_name_map.TryGetValue(g1, out p1); | ||
638 | |||
639 | if (p1 == null) | ||
640 | return; | ||
641 | |||
642 | switch (p1.PhysicsActorType) | ||
643 | { | ||
644 | case (int)ActorTypes.Prim: | ||
645 | |||
646 | RayFilterFlags thisFlags; | ||
647 | |||
648 | if (p1.IsPhysical) | ||
649 | thisFlags = RayFilterFlags.physical; | ||
650 | else | ||
651 | thisFlags = RayFilterFlags.nonphysical; | ||
652 | |||
653 | if (p1.Phantom) | ||
654 | thisFlags |= RayFilterFlags.phantom; | ||
655 | |||
656 | if (p1.IsVolumeDtc) | ||
657 | thisFlags |= RayFilterFlags.volumedtc; | ||
658 | |||
659 | if ((thisFlags & CurrentRayFilter) == 0) | ||
660 | return; | ||
661 | |||
662 | ID = ((OdePrim)p1).LocalID; | ||
663 | break; | ||
664 | |||
665 | case (int)ActorTypes.Agent: | ||
666 | |||
667 | if ((CurrentRayFilter & RayFilterFlags.agent) == 0) | ||
668 | return; | ||
669 | else | ||
670 | ID = ((OdeCharacter)p1).LocalID; | ||
671 | break; | ||
672 | |||
673 | case (int)ActorTypes.Ground: | ||
674 | |||
675 | if ((CurrentRayFilter & RayFilterFlags.land) == 0) | ||
676 | return; | ||
677 | break; | ||
678 | |||
679 | case (int)ActorTypes.Water: | ||
680 | |||
681 | if ((CurrentRayFilter & RayFilterFlags.water) == 0) | ||
682 | return; | ||
683 | break; | ||
684 | |||
685 | default: | ||
686 | break; | ||
687 | } | ||
561 | 688 | ||
562 | d.ContactGeom curcontact = new d.ContactGeom(); | 689 | d.ContactGeom curcontact = new d.ContactGeom(); |
563 | 690 | ||
@@ -624,6 +751,21 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
624 | d.GeomDestroy(ray); | 751 | d.GeomDestroy(ray); |
625 | ray = IntPtr.Zero; | 752 | ray = IntPtr.Zero; |
626 | } | 753 | } |
754 | if (Box != IntPtr.Zero) | ||
755 | { | ||
756 | d.GeomDestroy(Box); | ||
757 | Box = IntPtr.Zero; | ||
758 | } | ||
759 | if (Sphere != IntPtr.Zero) | ||
760 | { | ||
761 | d.GeomDestroy(Sphere); | ||
762 | Sphere = IntPtr.Zero; | ||
763 | } | ||
764 | if (Plane != IntPtr.Zero) | ||
765 | { | ||
766 | d.GeomDestroy(Plane); | ||
767 | Plane = IntPtr.Zero; | ||
768 | } | ||
627 | } | 769 | } |
628 | } | 770 | } |
629 | 771 | ||
@@ -636,5 +778,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
636 | public float length; | 778 | public float length; |
637 | public object callbackMethod; | 779 | public object callbackMethod; |
638 | public RayFilterFlags filter; | 780 | public RayFilterFlags filter; |
781 | public Quaternion orientation; | ||
639 | } | 782 | } |
640 | } \ No newline at end of file | 783 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs index 225bff8..ecc732a 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs | |||
@@ -52,6 +52,21 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
52 | } | 52 | } |
53 | 53 | ||
54 | private static Vector3 SitAjust = new Vector3(0, 0, 0.4f); | 54 | private static Vector3 SitAjust = new Vector3(0, 0, 0.4f); |
55 | private const RayFilterFlags RaySitFlags = RayFilterFlags.AllPrims | RayFilterFlags.ClosestHit; | ||
56 | |||
57 | private void RotAroundZ(float x, float y, ref Quaternion ori) | ||
58 | { | ||
59 | double ang = Math.Atan2(y, x); | ||
60 | ang *= 0.5d; | ||
61 | float s = (float)Math.Sin(ang); | ||
62 | float c = (float)Math.Cos(ang); | ||
63 | |||
64 | ori.X = 0; | ||
65 | ori.Y = 0; | ||
66 | ori.Z = s; | ||
67 | ori.W = c; | ||
68 | } | ||
69 | |||
55 | 70 | ||
56 | public void Sit(PhysicsActor actor, Vector3 avPos, Vector3 avCameraPosition, Vector3 offset, Vector3 avOffset, SitAvatarCallback PhysicsSitResponse) | 71 | public void Sit(PhysicsActor actor, Vector3 avPos, Vector3 avCameraPosition, Vector3 offset, Vector3 avOffset, SitAvatarCallback PhysicsSitResponse) |
57 | { | 72 | { |
@@ -63,88 +78,82 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
63 | 78 | ||
64 | IntPtr geom = ((OdePrim)actor).prim_geom; | 79 | IntPtr geom = ((OdePrim)actor).prim_geom; |
65 | 80 | ||
66 | d.Vector3 dtmp = d.GeomGetPosition(geom); | 81 | Vector3 geopos = d.GeomGetPositionOMV(geom); |
67 | Vector3 geopos; | 82 | Quaternion geomOri = d.GeomGetQuaternionOMV(geom); |
68 | geopos.X = dtmp.X; | 83 | Quaternion geomInvOri = Quaternion.Conjugate(geomOri); |
69 | geopos.Y = dtmp.Y; | 84 | |
70 | geopos.Z = dtmp.Z; | 85 | Quaternion ori = Quaternion.Identity; |
71 | 86 | ||
72 | 87 | Vector3 rayDir = geopos + offset - avCameraPosition; | |
73 | d.AABB aabb; | 88 | |
74 | Quaternion ori; | ||
75 | d.Quaternion qtmp; | ||
76 | d.GeomCopyQuaternion(geom, out qtmp); | ||
77 | Quaternion geomOri; | ||
78 | geomOri.X = qtmp.X; | ||
79 | geomOri.Y = qtmp.Y; | ||
80 | geomOri.Z = qtmp.Z; | ||
81 | geomOri.W = qtmp.W; | ||
82 | Quaternion geomInvOri; | ||
83 | geomInvOri.X = -qtmp.X; | ||
84 | geomInvOri.Y = -qtmp.Y; | ||
85 | geomInvOri.Z = -qtmp.Z; | ||
86 | geomInvOri.W = qtmp.W; | ||
87 | |||
88 | Vector3 target = geopos + offset; | ||
89 | Vector3 rayDir = target - avCameraPosition; | ||
90 | float raylen = rayDir.Length(); | 89 | float raylen = rayDir.Length(); |
90 | if (raylen < 0.001f) | ||
91 | { | ||
92 | PhysicsSitResponse(-1, actor.LocalID, offset, Quaternion.Identity); | ||
93 | return; | ||
94 | } | ||
91 | float t = 1 / raylen; | 95 | float t = 1 / raylen; |
92 | rayDir.X *= t; | 96 | rayDir.X *= t; |
93 | rayDir.Y *= t; | 97 | rayDir.Y *= t; |
94 | rayDir.Z *= t; | 98 | rayDir.Z *= t; |
95 | 99 | ||
96 | raylen += 0.5f; | 100 | raylen += 30f; // focal point may be far |
97 | List<ContactResult> rayResults; | 101 | List<ContactResult> rayResults; |
98 | 102 | ||
99 | rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir , raylen, 1); | 103 | rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir, raylen, 1, RaySitFlags); |
100 | if (rayResults.Count == 0 || rayResults[0].ConsumerID != actor.LocalID) | 104 | if (rayResults.Count == 0) |
101 | { | 105 | { |
102 | d.GeomGetAABB(geom,out aabb); | 106 | /* if this fundamental ray failed, then just fail so user can try another spot and not be sitted far on a big prim |
107 | d.AABB aabb; | ||
108 | d.GeomGetAABB(geom, out aabb); | ||
103 | offset = new Vector3(avOffset.X, 0, aabb.MaxZ + avOffset.Z - geopos.Z); | 109 | offset = new Vector3(avOffset.X, 0, aabb.MaxZ + avOffset.Z - geopos.Z); |
104 | ori = geomInvOri; | 110 | ori = geomInvOri; |
105 | offset *= geomInvOri; | 111 | offset *= geomInvOri; |
106 | |||
107 | PhysicsSitResponse(1, actor.LocalID, offset, ori); | 112 | PhysicsSitResponse(1, actor.LocalID, offset, ori); |
113 | */ | ||
114 | PhysicsSitResponse(0, actor.LocalID, offset, ori); | ||
108 | return; | 115 | return; |
109 | } | 116 | } |
110 | 117 | ||
118 | int status = 1; | ||
111 | offset = rayResults[0].Pos - geopos; | 119 | offset = rayResults[0].Pos - geopos; |
112 | double ang; | ||
113 | float s; | ||
114 | float c; | ||
115 | 120 | ||
116 | d.GeomClassID geoclass = d.GeomGetClass(geom); | 121 | d.GeomClassID geoclass = d.GeomGetClass(geom); |
117 | 122 | ||
118 | if (geoclass == d.GeomClassID.SphereClass) | 123 | if (geoclass == d.GeomClassID.SphereClass) |
119 | { | 124 | { |
120 | float r = d.GeomSphereGetRadius(geom); | 125 | float r = d.GeomSphereGetRadius(geom); |
121 | 126 | ||
122 | offset.Normalize(); | 127 | offset.Normalize(); |
123 | offset *= r; | 128 | offset *= r; |
124 | 129 | ||
125 | ang = Math.Atan2(offset.Y, offset.X); | 130 | RotAroundZ(offset.X, offset.Y, ref ori); |
126 | ang *= 0.5d; | ||
127 | s = (float)Math.Sin(ang); | ||
128 | c = (float)Math.Cos(ang); | ||
129 | |||
130 | ori = new Quaternion(0, 0, s, c); | ||
131 | 131 | ||
132 | if (r < 0.4f) | 132 | if (r < 0.4f) |
133 | { | 133 | { |
134 | offset = new Vector3(0, 0, r); | 134 | offset = new Vector3(0, 0, r); |
135 | } | 135 | } |
136 | else if (offset.Z < 0.4f) | 136 | else |
137 | { | 137 | { |
138 | t = offset.Z; | 138 | if (offset.Z < 0.4f) |
139 | float rsq = r * r; | 139 | { |
140 | 140 | t = offset.Z; | |
141 | t = 1.0f / (rsq - t * t); | 141 | float rsq = r * r; |
142 | offset.X *= t; | 142 | |
143 | offset.Y *= t; | 143 | t = 1.0f / (rsq - t * t); |
144 | offset.Z = 0.4f; | 144 | offset.X *= t; |
145 | t = rsq - 0.16f; | 145 | offset.Y *= t; |
146 | offset.X *= t; | 146 | offset.Z = 0.4f; |
147 | offset.Y *= t; | 147 | t = rsq - 0.16f; |
148 | offset.X *= t; | ||
149 | offset.Y *= t; | ||
150 | } | ||
151 | else if (r > 0.8f && offset.Z > 0.8f * r) | ||
152 | { | ||
153 | status = 3; | ||
154 | avOffset.X = -avOffset.X; | ||
155 | avOffset.Z *= 1.6f; | ||
156 | } | ||
148 | } | 157 | } |
149 | 158 | ||
150 | offset += avOffset * ori; | 159 | offset += avOffset * ori; |
@@ -152,26 +161,189 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
152 | ori = geomInvOri * ori; | 161 | ori = geomInvOri * ori; |
153 | offset *= geomInvOri; | 162 | offset *= geomInvOri; |
154 | 163 | ||
155 | PhysicsSitResponse(1, actor.LocalID, offset, ori); | 164 | PhysicsSitResponse(status, actor.LocalID, offset, ori); |
156 | return; | 165 | return; |
157 | } | 166 | } |
158 | 167 | ||
159 | Vector3 norm = rayResults[0].Normal; | 168 | Vector3 norm = rayResults[0].Normal; |
160 | 169 | ||
161 | if (norm.Z < 0) | 170 | if (norm.Z < -0.4f) |
162 | { | 171 | { |
163 | PhysicsSitResponse(0, actor.LocalID, offset, Quaternion.Identity); | 172 | PhysicsSitResponse(0, actor.LocalID, offset, Quaternion.Identity); |
164 | return; | 173 | return; |
165 | } | 174 | } |
166 | 175 | ||
167 | ang = Math.Atan2(-rayDir.Y, -rayDir.X); | ||
168 | ang *= 0.5d; | ||
169 | s = (float)Math.Sin(ang); | ||
170 | c = (float)Math.Cos(ang); | ||
171 | 176 | ||
172 | ori = new Quaternion(0, 0, s, c); | 177 | float SitNormX = -rayDir.X; |
178 | float SitNormY = -rayDir.Y; | ||
179 | |||
180 | Vector3 pivot = geopos + offset; | ||
181 | |||
182 | float edgeNormalX = norm.X; | ||
183 | float edgeNormalY = norm.Y; | ||
184 | float edgeDirX = -rayDir.X; | ||
185 | float edgeDirY = -rayDir.Y; | ||
186 | Vector3 edgePos = rayResults[0].Pos; | ||
187 | float edgeDist = float.MaxValue; | ||
188 | |||
189 | bool foundEdge = false; | ||
190 | |||
191 | if (norm.Z < 0.5f) | ||
192 | { | ||
193 | float rayDist = 4.0f; | ||
194 | float curEdgeDist = 0.0f; | ||
195 | |||
196 | for (int i = 0; i < 6; i++) | ||
197 | { | ||
198 | pivot.X -= 0.005f * norm.X; | ||
199 | pivot.Y -= 0.005f * norm.Y; | ||
200 | pivot.Z -= 0.005f * norm.Z; | ||
201 | |||
202 | rayDir.X = -norm.X * norm.Z; | ||
203 | rayDir.Y = -norm.Y * norm.Z; | ||
204 | rayDir.Z = 1.0f - norm.Z * norm.Z; | ||
205 | rayDir.Normalize(); | ||
206 | |||
207 | rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims); | ||
208 | if (rayResults.Count == 0) | ||
209 | break; | ||
210 | |||
211 | curEdgeDist += rayResults[0].Depth; | ||
212 | |||
213 | if (Math.Abs(rayResults[0].Normal.Z) < 0.7f) | ||
214 | { | ||
215 | rayDist -= rayResults[0].Depth; | ||
216 | if (rayDist < 0f) | ||
217 | break; | ||
218 | |||
219 | pivot = rayResults[0].Pos; | ||
220 | norm = rayResults[0].Normal; | ||
221 | edgeNormalX = norm.X; | ||
222 | edgeNormalY = norm.Y; | ||
223 | edgeDirX = -rayDir.X; | ||
224 | edgeDirY = -rayDir.Y; | ||
225 | } | ||
226 | else | ||
227 | { | ||
228 | foundEdge = true; | ||
229 | edgeDist = curEdgeDist; | ||
230 | edgePos = rayResults[0].Pos; | ||
231 | break; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | if (!foundEdge) | ||
236 | { | ||
237 | PhysicsSitResponse(0, actor.LocalID, offset, ori); | ||
238 | return; | ||
239 | } | ||
240 | avOffset.X *= 0.5f; | ||
241 | } | ||
242 | |||
243 | else if (norm.Z > 0.866f) | ||
244 | { | ||
245 | float toCamBaseX = avCameraPosition.X - pivot.X; | ||
246 | float toCamBaseY = avCameraPosition.Y - pivot.Y; | ||
247 | float toCamX = toCamBaseX; | ||
248 | float toCamY = toCamBaseY; | ||
249 | |||
250 | for (int j = 0; j < 4; j++) | ||
251 | { | ||
252 | float rayDist = 1.0f; | ||
253 | float curEdgeDist = 0.0f; | ||
254 | |||
255 | for (int i = 0; i < 3; i++) | ||
256 | { | ||
257 | pivot.Z -= 0.005f; | ||
258 | rayDir.X = toCamX; | ||
259 | rayDir.Y = toCamY; | ||
260 | rayDir.Z = (-toCamX * norm.X - toCamY * norm.Y) / norm.Z; | ||
261 | rayDir.Normalize(); | ||
262 | |||
263 | rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims); | ||
264 | if (rayResults.Count == 0) | ||
265 | break; | ||
266 | |||
267 | curEdgeDist += rayResults[0].Depth; | ||
268 | |||
269 | if (rayResults[0].Normal.Z > 0.5f) | ||
270 | { | ||
271 | rayDist -= rayResults[0].Depth; | ||
272 | if (rayDist < 0f) | ||
273 | break; | ||
274 | |||
275 | pivot = rayResults[0].Pos; | ||
276 | norm = rayResults[0].Normal; | ||
277 | } | ||
278 | else | ||
279 | { | ||
280 | foundEdge = true; | ||
281 | if (curEdgeDist < edgeDist) | ||
282 | { | ||
283 | edgeDist = curEdgeDist; | ||
284 | edgeNormalX = rayResults[0].Normal.X; | ||
285 | edgeNormalY = rayResults[0].Normal.Y; | ||
286 | edgeDirX = rayDir.X; | ||
287 | edgeDirY = rayDir.Y; | ||
288 | edgePos = rayResults[0].Pos; | ||
289 | } | ||
290 | break; | ||
291 | } | ||
292 | } | ||
293 | if (foundEdge && edgeDist < 0.2f) | ||
294 | break; | ||
295 | |||
296 | pivot = geopos + offset; | ||
297 | |||
298 | switch (j) | ||
299 | { | ||
300 | case 0: | ||
301 | toCamX = -toCamBaseY; | ||
302 | toCamY = toCamBaseX; | ||
303 | break; | ||
304 | case 1: | ||
305 | toCamX = toCamBaseY; | ||
306 | toCamY = -toCamBaseX; | ||
307 | break; | ||
308 | case 2: | ||
309 | toCamX = -toCamBaseX; | ||
310 | toCamY = -toCamBaseY; | ||
311 | break; | ||
312 | default: | ||
313 | break; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | if (!foundEdge) | ||
318 | { | ||
319 | avOffset.X = -avOffset.X; | ||
320 | avOffset.Z *= 1.6f; | ||
321 | |||
322 | RotAroundZ(SitNormX, SitNormY, ref ori); | ||
323 | |||
324 | offset += avOffset * ori; | ||
325 | |||
326 | ori = geomInvOri * ori; | ||
327 | offset *= geomInvOri; | ||
328 | |||
329 | PhysicsSitResponse(3, actor.LocalID, offset, ori); | ||
330 | return; | ||
331 | } | ||
332 | avOffset.X *= 0.5f; | ||
333 | } | ||
334 | |||
335 | SitNormX = edgeNormalX; | ||
336 | SitNormY = edgeNormalY; | ||
337 | if (edgeDirX * SitNormX + edgeDirY * SitNormY < 0) | ||
338 | { | ||
339 | SitNormX = -SitNormX; | ||
340 | SitNormY = -SitNormY; | ||
341 | } | ||
342 | |||
343 | RotAroundZ(SitNormX, SitNormY, ref ori); | ||
173 | 344 | ||
174 | offset += avOffset * ori; | 345 | offset = edgePos + avOffset * ori; |
346 | offset -= geopos; | ||
175 | 347 | ||
176 | ori = geomInvOri * ori; | 348 | ori = geomInvOri * ori; |
177 | offset *= geomInvOri; | 349 | offset *= geomInvOri; |
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs index 403a4ce..10d7d50 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs | |||
@@ -44,7 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
44 | using System; | 44 | using System; |
45 | using System.Runtime.InteropServices; | 45 | using System.Runtime.InteropServices; |
46 | using System.Security; | 46 | using System.Security; |
47 | 47 | using OMV = OpenMetaverse; | |
48 | namespace OdeAPI | 48 | namespace OdeAPI |
49 | { | 49 | { |
50 | //#if dDOUBLE | 50 | //#if dDOUBLE |
@@ -925,9 +925,20 @@ namespace OdeAPI | |||
925 | { | 925 | { |
926 | unsafe { return *(GeomGetPositionUnsafe(geom)); } | 926 | unsafe { return *(GeomGetPositionUnsafe(geom)); } |
927 | } | 927 | } |
928 | public static OMV.Vector3 GeomGetPositionOMV(IntPtr geom) | ||
929 | { | ||
930 | Vector3 vtmp = GeomGetPosition(geom); | ||
931 | return new OMV.Vector3(vtmp.X, vtmp.Y, vtmp.Z); | ||
932 | } | ||
928 | 933 | ||
929 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity] | 934 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity] |
930 | public static extern void GeomCopyQuaternion(IntPtr geom, out Quaternion q); | 935 | public static extern void GeomCopyQuaternion(IntPtr geom, out Quaternion q); |
936 | public static OMV.Quaternion GeomGetQuaternionOMV(IntPtr geom) | ||
937 | { | ||
938 | Quaternion qtmp; | ||
939 | GeomCopyQuaternion(geom, out qtmp); | ||
940 | return new OMV.Quaternion(qtmp.X, qtmp.Y, qtmp.Z, qtmp.W); | ||
941 | } | ||
931 | 942 | ||
932 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity] | 943 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity] |
933 | public static extern void GeomCopyQuaternion(IntPtr geom, out dReal X); | 944 | public static extern void GeomCopyQuaternion(IntPtr geom, out dReal X); |
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs index fbf2f0d..d045b59 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs | |||
@@ -2579,7 +2579,16 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2579 | { | 2579 | { |
2580 | if (retMethod != null) | 2580 | if (retMethod != null) |
2581 | { | 2581 | { |
2582 | m_rayCastManager.QueueRequest(position, direction, length, retMethod); | 2582 | ODERayRequest req = new ODERayRequest(); |
2583 | req.geom = IntPtr.Zero; | ||
2584 | req.callbackMethod = retMethod; | ||
2585 | req.length = length; | ||
2586 | req.Normal = direction; | ||
2587 | req.Origin = position; | ||
2588 | req.Count = 0; | ||
2589 | req.filter = RayFilterFlags.All; | ||
2590 | |||
2591 | m_rayCastManager.QueueRequest(req); | ||
2583 | } | 2592 | } |
2584 | } | 2593 | } |
2585 | 2594 | ||
@@ -2587,29 +2596,51 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2587 | { | 2596 | { |
2588 | if (retMethod != null) | 2597 | if (retMethod != null) |
2589 | { | 2598 | { |
2590 | m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod); | 2599 | ODERayRequest req = new ODERayRequest(); |
2600 | req.geom = IntPtr.Zero; | ||
2601 | req.callbackMethod = retMethod; | ||
2602 | req.length = length; | ||
2603 | req.Normal = direction; | ||
2604 | req.Origin = position; | ||
2605 | req.Count = Count; | ||
2606 | req.filter = RayFilterFlags.All; | ||
2607 | |||
2608 | m_rayCastManager.QueueRequest(req); | ||
2591 | } | 2609 | } |
2592 | } | 2610 | } |
2593 | 2611 | ||
2594 | // don't like this | 2612 | |
2595 | public override List<ContactResult> RaycastWorld(Vector3 position, Vector3 direction, float length, int Count) | 2613 | public override List<ContactResult> RaycastWorld(Vector3 position, Vector3 direction, float length, int Count) |
2596 | { | 2614 | { |
2597 | ContactResult[] ourResults = null; | 2615 | List<ContactResult> ourresults = new List<ContactResult>(); |
2616 | object SyncObject = new object(); | ||
2617 | |||
2598 | RayCallback retMethod = delegate(List<ContactResult> results) | 2618 | RayCallback retMethod = delegate(List<ContactResult> results) |
2599 | { | 2619 | { |
2600 | ourResults = new ContactResult[results.Count]; | 2620 | lock (SyncObject) |
2601 | results.CopyTo(ourResults, 0); | 2621 | { |
2622 | ourresults = results; | ||
2623 | Monitor.PulseAll(SyncObject); | ||
2624 | } | ||
2602 | }; | 2625 | }; |
2603 | int waitTime = 0; | 2626 | |
2604 | m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod); | 2627 | ODERayRequest req = new ODERayRequest(); |
2605 | while (ourResults == null && waitTime < 1000) | 2628 | req.geom = IntPtr.Zero; |
2629 | req.callbackMethod = retMethod; | ||
2630 | req.length = length; | ||
2631 | req.Normal = direction; | ||
2632 | req.Origin = position; | ||
2633 | req.Count = Count; | ||
2634 | req.filter = RayFilterFlags.All; | ||
2635 | |||
2636 | lock (SyncObject) | ||
2606 | { | 2637 | { |
2607 | Thread.Sleep(1); | 2638 | m_rayCastManager.QueueRequest(req); |
2608 | waitTime++; | 2639 | if (!Monitor.Wait(SyncObject, 500)) |
2640 | return null; | ||
2641 | else | ||
2642 | return ourresults; | ||
2609 | } | 2643 | } |
2610 | if (ourResults == null) | ||
2611 | return new List<ContactResult>(); | ||
2612 | return new List<ContactResult>(ourResults); | ||
2613 | } | 2644 | } |
2614 | 2645 | ||
2615 | public override bool SuportsRaycastWorldFiltered() | 2646 | public override bool SuportsRaycastWorldFiltered() |
@@ -2631,9 +2662,18 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2631 | } | 2662 | } |
2632 | }; | 2663 | }; |
2633 | 2664 | ||
2665 | ODERayRequest req = new ODERayRequest(); | ||
2666 | req.geom = IntPtr.Zero; | ||
2667 | req.callbackMethod = retMethod; | ||
2668 | req.length = length; | ||
2669 | req.Normal = direction; | ||
2670 | req.Origin = position; | ||
2671 | req.Count = Count; | ||
2672 | req.filter = filter; | ||
2673 | |||
2634 | lock (SyncObject) | 2674 | lock (SyncObject) |
2635 | { | 2675 | { |
2636 | m_rayCastManager.QueueRequest(position, direction, length, Count,filter, retMethod); | 2676 | m_rayCastManager.QueueRequest(req); |
2637 | if (!Monitor.Wait(SyncObject, 500)) | 2677 | if (!Monitor.Wait(SyncObject, 500)) |
2638 | return null; | 2678 | return null; |
2639 | else | 2679 | else |
@@ -2641,74 +2681,163 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2641 | } | 2681 | } |
2642 | } | 2682 | } |
2643 | 2683 | ||
2644 | public override void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) | 2684 | public override List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags) |
2645 | { | 2685 | { |
2646 | if (retMethod != null && actor !=null) | 2686 | if (actor == null) |
2687 | return new List<ContactResult>(); | ||
2688 | |||
2689 | IntPtr geom; | ||
2690 | if (actor is OdePrim) | ||
2691 | geom = ((OdePrim)actor).prim_geom; | ||
2692 | else if (actor is OdeCharacter) | ||
2693 | geom = ((OdePrim)actor).prim_geom; | ||
2694 | else | ||
2695 | return new List<ContactResult>(); | ||
2696 | |||
2697 | if (geom == IntPtr.Zero) | ||
2698 | return new List<ContactResult>(); | ||
2699 | |||
2700 | List<ContactResult> ourResults = null; | ||
2701 | object SyncObject = new object(); | ||
2702 | |||
2703 | RayCallback retMethod = delegate(List<ContactResult> results) | ||
2647 | { | 2704 | { |
2648 | IntPtr geom; | 2705 | lock (SyncObject) |
2649 | if (actor is OdePrim) | 2706 | { |
2650 | geom = ((OdePrim)actor).prim_geom; | 2707 | ourResults = results; |
2651 | else if (actor is OdeCharacter) | 2708 | Monitor.PulseAll(SyncObject); |
2652 | geom = ((OdePrim)actor).prim_geom; | 2709 | } |
2653 | else | 2710 | }; |
2654 | return; | 2711 | |
2655 | if (geom == IntPtr.Zero) | 2712 | ODERayRequest req = new ODERayRequest(); |
2656 | return; | 2713 | req.geom = geom; |
2657 | m_rayCastManager.QueueRequest(geom, position, direction, length, retMethod); | 2714 | req.callbackMethod = retMethod; |
2715 | req.length = length; | ||
2716 | req.Normal = direction; | ||
2717 | req.Origin = position; | ||
2718 | req.Count = Count; | ||
2719 | req.filter = flags; | ||
2720 | |||
2721 | lock (SyncObject) | ||
2722 | { | ||
2723 | m_rayCastManager.QueueRequest(req); | ||
2724 | if (!Monitor.Wait(SyncObject, 500)) | ||
2725 | return new List<ContactResult>(); | ||
2658 | } | 2726 | } |
2727 | |||
2728 | if (ourResults == null) | ||
2729 | return new List<ContactResult>(); | ||
2730 | return ourResults; | ||
2659 | } | 2731 | } |
2660 | 2732 | ||
2661 | public override void RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod) | 2733 | public override List<ContactResult> BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags) |
2662 | { | 2734 | { |
2663 | if (retMethod != null && actor != null) | 2735 | List<ContactResult> ourResults = null; |
2736 | object SyncObject = new object(); | ||
2737 | |||
2738 | ProbeBoxCallback retMethod = delegate(List<ContactResult> results) | ||
2664 | { | 2739 | { |
2665 | IntPtr geom; | 2740 | lock (SyncObject) |
2666 | if (actor is OdePrim) | 2741 | { |
2667 | geom = ((OdePrim)actor).prim_geom; | 2742 | ourResults = results; |
2668 | else if (actor is OdeCharacter) | 2743 | Monitor.PulseAll(SyncObject); |
2669 | geom = ((OdePrim)actor).prim_geom; | 2744 | } |
2670 | else | 2745 | }; |
2671 | return; | 2746 | |
2672 | if (geom == IntPtr.Zero) | 2747 | ODERayRequest req = new ODERayRequest(); |
2673 | return; | 2748 | req.geom = IntPtr.Zero; |
2749 | req.callbackMethod = retMethod; | ||
2750 | req.Normal = size; | ||
2751 | req.Origin = position; | ||
2752 | req.orientation = orientation; | ||
2753 | req.Count = Count; | ||
2754 | req.filter = flags; | ||
2755 | |||
2756 | lock (SyncObject) | ||
2757 | { | ||
2758 | m_rayCastManager.QueueRequest(req); | ||
2759 | if (!Monitor.Wait(SyncObject, 500)) | ||
2760 | return new List<ContactResult>(); | ||
2761 | } | ||
2762 | |||
2763 | if (ourResults == null) | ||
2764 | return new List<ContactResult>(); | ||
2765 | return ourResults; | ||
2766 | } | ||
2767 | |||
2768 | public override List<ContactResult> SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags) | ||
2769 | { | ||
2770 | List<ContactResult> ourResults = null; | ||
2771 | object SyncObject = new object(); | ||
2772 | |||
2773 | ProbeSphereCallback retMethod = delegate(List<ContactResult> results) | ||
2774 | { | ||
2775 | ourResults = results; | ||
2776 | Monitor.PulseAll(SyncObject); | ||
2777 | }; | ||
2778 | |||
2779 | ODERayRequest req = new ODERayRequest(); | ||
2780 | req.geom = IntPtr.Zero; | ||
2781 | req.callbackMethod = retMethod; | ||
2782 | req.length = radius; | ||
2783 | req.Origin = position; | ||
2784 | req.Count = Count; | ||
2785 | req.filter = flags; | ||
2674 | 2786 | ||
2675 | m_rayCastManager.QueueRequest(geom,position, direction, length, Count, retMethod); | 2787 | |
2788 | lock (SyncObject) | ||
2789 | { | ||
2790 | m_rayCastManager.QueueRequest(req); | ||
2791 | if (!Monitor.Wait(SyncObject, 500)) | ||
2792 | return new List<ContactResult>(); | ||
2676 | } | 2793 | } |
2794 | |||
2795 | if (ourResults == null) | ||
2796 | return new List<ContactResult>(); | ||
2797 | return ourResults; | ||
2677 | } | 2798 | } |
2678 | 2799 | ||
2679 | // don't like this | 2800 | public override List<ContactResult> PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags) |
2680 | public override List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count) | ||
2681 | { | 2801 | { |
2802 | IntPtr geom = IntPtr.Zero;; | ||
2803 | |||
2682 | if (actor != null) | 2804 | if (actor != null) |
2683 | { | 2805 | { |
2684 | IntPtr geom; | ||
2685 | if (actor is OdePrim) | 2806 | if (actor is OdePrim) |
2686 | geom = ((OdePrim)actor).prim_geom; | 2807 | geom = ((OdePrim)actor).prim_geom; |
2687 | else if (actor is OdeCharacter) | 2808 | else if (actor is OdeCharacter) |
2688 | geom = ((OdePrim)actor).prim_geom; | 2809 | geom = ((OdePrim)actor).prim_geom; |
2689 | else | 2810 | } |
2690 | return new List<ContactResult>(); | ||
2691 | if (geom == IntPtr.Zero) | ||
2692 | return new List<ContactResult>(); | ||
2693 | 2811 | ||
2694 | ContactResult[] ourResults = null; | 2812 | List<ContactResult> ourResults = null; |
2695 | RayCallback retMethod = delegate(List<ContactResult> results) | 2813 | object SyncObject = new object(); |
2696 | { | 2814 | |
2697 | ourResults = new ContactResult[results.Count]; | 2815 | ProbePlaneCallback retMethod = delegate(List<ContactResult> results) |
2698 | results.CopyTo(ourResults, 0); | 2816 | { |
2699 | }; | 2817 | ourResults = results; |
2700 | int waitTime = 0; | 2818 | Monitor.PulseAll(SyncObject); |
2701 | m_rayCastManager.QueueRequest(geom,position, direction, length, Count, retMethod); | 2819 | }; |
2702 | while (ourResults == null && waitTime < 1000) | 2820 | |
2703 | { | 2821 | ODERayRequest req = new ODERayRequest(); |
2704 | Thread.Sleep(1); | 2822 | req.geom = geom; |
2705 | waitTime++; | 2823 | req.callbackMethod = retMethod; |
2706 | } | 2824 | req.length = plane.W; |
2707 | if (ourResults == null) | 2825 | req.Normal.X = plane.X; |
2826 | req.Normal.Y = plane.Y; | ||
2827 | req.Normal.Z = plane.Z; | ||
2828 | req.Count = Count; | ||
2829 | req.filter = flags; | ||
2830 | |||
2831 | lock (SyncObject) | ||
2832 | { | ||
2833 | m_rayCastManager.QueueRequest(req); | ||
2834 | if (!Monitor.Wait(SyncObject, 500)) | ||
2708 | return new List<ContactResult>(); | 2835 | return new List<ContactResult>(); |
2709 | return new List<ContactResult>(ourResults); | ||
2710 | } | 2836 | } |
2711 | return new List<ContactResult>(); | 2837 | |
2838 | if (ourResults == null) | ||
2839 | return new List<ContactResult>(); | ||
2840 | return ourResults; | ||
2712 | } | 2841 | } |
2713 | 2842 | ||
2714 | public override int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse) | 2843 | public override int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse) |