29 using System.Collections.Generic;
30 using System.Reflection;
31 using System.Runtime.InteropServices;
33 using OpenSim.Framework;
34 using OpenSim.Region.PhysicsModules.SharedBase;
39 namespace OpenSim.
Region.PhysicsModule.ubOde
51 m_raymanager = raymanager;
54 private static Vector3 SitAjust =
new Vector3(0, 0, 0.4f);
55 private const RayFilterFlags RaySitFlags = RayFilterFlags.AllPrims | RayFilterFlags.ClosestHit;
57 private void RotAroundZ(
float x,
float y, ref Quaternion ori)
59 double ang = Math.Atan2(y, x);
61 float s = (float)Math.Sin(ang);
62 float c = (float)Math.Cos(ang);
73 if (!m_scene.haveActor(actor) || !(actor is
OdePrim) || ((
OdePrim)actor).prim_geom == IntPtr.Zero)
75 PhysicsSitResponse(-1, actor.
LocalID, offset, Quaternion.Identity);
79 IntPtr geom = ((
OdePrim)actor).prim_geom;
81 Vector3 geopos = d.GeomGetPositionOMV(geom);
82 Quaternion geomOri = d.GeomGetQuaternionOMV(geom);
87 Quaternion geomInvOri = Quaternion.Conjugate(geomOri);
89 Quaternion ori = Quaternion.Identity;
91 Vector3 rayDir = geopos + offset - avCameraPosition;
93 float raylen = rayDir.Length();
96 PhysicsSitResponse(-1, actor.
LocalID, offset, Quaternion.Identity);
105 List<ContactResult> rayResults;
107 rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir, raylen, 1, RaySitFlags);
108 if (rayResults.Count == 0)
118 PhysicsSitResponse(0, actor.LocalID, offset, ori);
124 offset = rayResults[0].Pos - geopos;
126 d.GeomClassID geoclass = d.GeomGetClass(geom);
128 if (geoclass == d.GeomClassID.SphereClass)
130 float r = d.GeomSphereGetRadius(geom);
135 RotAroundZ(offset.X, offset.Y, ref ori);
139 offset =
new Vector3(0, 0, r);
148 t = 1.0f / (rsq - t * t);
156 else if (r > 0.8f && offset.Z > 0.8f * r)
159 avOffset.X = -avOffset.X;
164 offset += avOffset * ori;
166 ori = geomInvOri * ori;
167 offset *= geomInvOri;
169 PhysicsSitResponse(status, actor.LocalID, offset, ori);
173 Vector3 norm = rayResults[0].Normal;
177 PhysicsSitResponse(0, actor.LocalID, offset, Quaternion.Identity);
182 float SitNormX = -rayDir.X;
183 float SitNormY = -rayDir.Y;
185 Vector3 pivot = geopos + offset;
187 float edgeNormalX = norm.X;
188 float edgeNormalY = norm.Y;
189 float edgeDirX = -rayDir.X;
190 float edgeDirY = -rayDir.Y;
191 Vector3 edgePos = rayResults[0].Pos;
192 float edgeDist = float.MaxValue;
194 bool foundEdge =
false;
198 float rayDist = 4.0f;
200 for (
int i = 0; i < 6; i++)
202 pivot.X -= 0.01f * norm.X;
203 pivot.Y -= 0.01f * norm.Y;
204 pivot.Z -= 0.01f * norm.Z;
206 rayDir.X = -norm.X * norm.Z;
207 rayDir.Y = -norm.Y * norm.Z;
208 rayDir.Z = 1.0f - norm.Z * norm.Z;
211 rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims);
212 if (rayResults.Count == 0)
215 if (Math.Abs(rayResults[0].Normal.Z) < 0.7f)
217 rayDist -= rayResults[0].Depth;
221 pivot = rayResults[0].Pos;
222 norm = rayResults[0].Normal;
223 edgeNormalX = norm.X;
224 edgeNormalY = norm.Y;
225 edgeDirX = -rayDir.X;
226 edgeDirY = -rayDir.Y;
231 edgePos = rayResults[0].Pos;
238 PhysicsSitResponse(0, actor.LocalID, offset, ori);
244 else if (norm.Z > 0.866f)
246 float toCamBaseX = avCameraPosition.X - pivot.X;
247 float toCamBaseY = avCameraPosition.Y - pivot.Y;
248 float toCamX = toCamBaseX;
249 float toCamY = toCamBaseY;
251 for (
int j = 0; j < 4; j++)
253 float rayDist = 1.0f;
254 float curEdgeDist = 0.0f;
256 for (
int i = 0; i < 3; i++)
261 rayDir.Z = (-toCamX * norm.X - toCamY * norm.Y) / norm.Z;
264 rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims);
265 if (rayResults.Count == 0)
268 curEdgeDist += rayResults[0].Depth;
270 if (rayResults[0].
Normal.Z > 0.5f)
272 rayDist -= rayResults[0].Depth;
276 pivot = rayResults[0].Pos;
277 norm = rayResults[0].Normal;
282 if (curEdgeDist < edgeDist)
284 edgeDist = curEdgeDist;
285 edgeNormalX = rayResults[0].Normal.X;
286 edgeNormalY = rayResults[0].Normal.Y;
289 edgePos = rayResults[0].Pos;
294 if (foundEdge && edgeDist < 0.2f)
297 pivot = geopos + offset;
302 toCamX = -toCamBaseY;
307 toCamY = -toCamBaseX;
310 toCamX = -toCamBaseX;
311 toCamY = -toCamBaseY;
320 avOffset.X = -avOffset.X;
323 RotAroundZ(SitNormX, SitNormY, ref ori);
325 offset += avOffset * ori;
327 ori = geomInvOri * ori;
328 offset *= geomInvOri;
330 PhysicsSitResponse(3, actor.LocalID, offset, ori);
336 SitNormX = edgeNormalX;
337 SitNormY = edgeNormalY;
338 if (edgeDirX * SitNormX + edgeDirY * SitNormY < 0)
340 SitNormX = -SitNormX;
341 SitNormY = -SitNormY;
344 RotAroundZ(SitNormX, SitNormY, ref ori);
346 offset = edgePos + avOffset * ori;
349 ori = geomInvOri * ori;
350 offset *= geomInvOri;
352 PhysicsSitResponse(1, actor.LocalID, offset, ori);
Processes raycast requests as ODE is in a state to be able to do them. This ensures that it's thread ...
ODESitAvatar(ODEScene pScene, ODERayCastRequestManager raymanager)
void Sit(PhysicsActor actor, Vector3 avPos, Vector3 avCameraPosition, Vector3 offset, Vector3 avOffset, SitAvatarCallback PhysicsSitResponse)
delegate void SitAvatarCallback(int status, uint partID, Vector3 offset, Quaternion Orientation)