aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs')
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs260
1 files changed, 221 insertions, 39 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs
index fd3a3ba..9e23763 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODESitAvatar.cs
@@ -54,6 +54,20 @@ namespace OpenSim.Region.Physics.OdePlugin
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; 55 private const RayFilterFlags RaySitFlags = RayFilterFlags.AllPrims | RayFilterFlags.ClosestHit;
56 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
70
57 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)
58 { 72 {
59 if (!m_scene.haveActor(actor) || !(actor is OdePrim) || ((OdePrim)actor).prim_geom == IntPtr.Zero) 73 if (!m_scene.haveActor(actor) || !(actor is OdePrim) || ((OdePrim)actor).prim_geom == IntPtr.Zero)
@@ -72,7 +86,7 @@ namespace OpenSim.Region.Physics.OdePlugin
72 86
73 87
74 d.AABB aabb; 88 d.AABB aabb;
75 Quaternion ori; 89 Quaternion ori = Quaternion.Identity;
76 d.Quaternion qtmp; 90 d.Quaternion qtmp;
77 d.GeomCopyQuaternion(geom, out qtmp); 91 d.GeomCopyQuaternion(geom, out qtmp);
78 Quaternion geomOri; 92 Quaternion geomOri;
@@ -86,9 +100,14 @@ namespace OpenSim.Region.Physics.OdePlugin
86 geomInvOri.Z = -qtmp.Z; 100 geomInvOri.Z = -qtmp.Z;
87 geomInvOri.W = qtmp.W; 101 geomInvOri.W = qtmp.W;
88 102
89 Vector3 target = geopos + offset; 103 Vector3 rayDir = geopos + offset - avCameraPosition;
90 Vector3 rayDir = target - avCameraPosition;
91 float raylen = rayDir.Length(); 104 float raylen = rayDir.Length();
105 if (raylen < 0.001f)
106 {
107 PhysicsSitResponse(-1, actor.LocalID, offset, Quaternion.Identity);
108 return;
109 }
110
92 float t = 1 / raylen; 111 float t = 1 / raylen;
93 rayDir.X *= t; 112 rayDir.X *= t;
94 rayDir.Y *= t; 113 rayDir.Y *= t;
@@ -98,9 +117,9 @@ namespace OpenSim.Region.Physics.OdePlugin
98 List<ContactResult> rayResults; 117 List<ContactResult> rayResults;
99 118
100 rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir, raylen, 1, RaySitFlags); 119 rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir, raylen, 1, RaySitFlags);
101 if (rayResults.Count == 0 || rayResults[0].ConsumerID != actor.LocalID) 120 if (rayResults.Count == 0)
102 { 121 {
103 d.GeomGetAABB(geom,out aabb); 122 d.GeomGetAABB(geom, out aabb);
104 offset = new Vector3(avOffset.X, 0, aabb.MaxZ + avOffset.Z - geopos.Z); 123 offset = new Vector3(avOffset.X, 0, aabb.MaxZ + avOffset.Z - geopos.Z);
105 ori = geomInvOri; 124 ori = geomInvOri;
106 offset *= geomInvOri; 125 offset *= geomInvOri;
@@ -109,44 +128,45 @@ namespace OpenSim.Region.Physics.OdePlugin
109 return; 128 return;
110 } 129 }
111 130
112
113 offset = rayResults[0].Pos - geopos; 131 offset = rayResults[0].Pos - geopos;
114 double ang;
115 float s;
116 float c;
117 132
118 d.GeomClassID geoclass = d.GeomGetClass(geom); 133 d.GeomClassID geoclass = d.GeomGetClass(geom);
119 134
120 if (geoclass == d.GeomClassID.SphereClass) 135 if (geoclass == d.GeomClassID.SphereClass)
121 { 136 {
122 float r = d.GeomSphereGetRadius(geom); 137 int status = 1;
138 float r = d.GeomSphereGetRadius(geom);
123 139
124 offset.Normalize(); 140 offset.Normalize();
125 offset *= r; 141 offset *= r;
126 142
127 ang = Math.Atan2(offset.Y, offset.X); 143 RotAroundZ(offset.X, offset.Y, ref ori);
128 ang *= 0.5d;
129 s = (float)Math.Sin(ang);
130 c = (float)Math.Cos(ang);
131
132 ori = new Quaternion(0, 0, s, c);
133 144
134 if (r < 0.4f) 145 if (r < 0.4f)
135 { 146 {
136 offset = new Vector3(0, 0, r); 147 offset = new Vector3(0, 0, r);
137 } 148 }
138 else if (offset.Z < 0.4f) 149 else
139 { 150 {
140 t = offset.Z; 151 if (offset.Z < 0.4f)
141 float rsq = r * r; 152 {
142 153 t = offset.Z;
143 t = 1.0f / (rsq - t * t); 154 float rsq = r * r;
144 offset.X *= t; 155
145 offset.Y *= t; 156 t = 1.0f / (rsq - t * t);
146 offset.Z = 0.4f; 157 offset.X *= t;
147 t = rsq - 0.16f; 158 offset.Y *= t;
148 offset.X *= t; 159 offset.Z = 0.4f;
149 offset.Y *= t; 160 t = rsq - 0.16f;
161 offset.X *= t;
162 offset.Y *= t;
163 }
164 else if (r > 0.8f && offset.Z > 0.8f * r)
165 {
166 status = 3;
167 avOffset.X = -avOffset.X;
168 avOffset.Z += 0.4f;
169 }
150 } 170 }
151 171
152 offset += avOffset * ori; 172 offset += avOffset * ori;
@@ -154,27 +174,189 @@ namespace OpenSim.Region.Physics.OdePlugin
154 ori = geomInvOri * ori; 174 ori = geomInvOri * ori;
155 offset *= geomInvOri; 175 offset *= geomInvOri;
156 176
157 PhysicsSitResponse(1, actor.LocalID, offset, ori); 177 PhysicsSitResponse(status, actor.LocalID, offset, ori);
158 return; 178 return;
159 } 179 }
160 180
161/* 181 Vector3 norm = rayResults[0].Normal;
162 // contact normals aren't reliable on meshs or sculpts it seems
163 Vector3 norm = rayResults[0].Normal;
164 182
165 if (norm.Z < 0) 183 if (norm.Z < -0.4f)
184 {
185 PhysicsSitResponse(0, actor.LocalID, offset, Quaternion.Identity);
186 return;
187 }
188
189 float SitNormX = -rayDir.X;
190 float SitNormY = -rayDir.Y;
191
192 Vector3 pivot = geopos + offset;
193
194 float edgeNormalX = norm.X;
195 float edgeNormalY = norm.Y;
196 float edgeDirX = -rayDir.X;
197 float edgeDirY = -rayDir.Y;
198 Vector3 edgePos = rayResults[0].Pos;
199 float edgeDist = float.MaxValue;
200
201 bool foundEdge = false;
202
203 if (norm.Z < 0.5f)
204 {
205 float rayDist = 4.0f;
206 float curEdgeDist = 0.0f;
207 pivot = geopos + offset;
208
209 for (int i = 0; i < 6; i++)
166 { 210 {
167 PhysicsSitResponse(0, actor.LocalID, offset, Quaternion.Identity); 211 pivot.X -= 0.005f * norm.X;
212 pivot.Y -= 0.005f * norm.Y;
213 pivot.Z -= 0.005f * norm.Z;
214
215 rayDir.X = -norm.X * norm.Z;
216 rayDir.Y = -norm.Y * norm.Z;
217 rayDir.Z = 1.0f - norm.Z * norm.Z;
218 rayDir.Normalize();
219
220 rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims);
221 if (rayResults.Count == 0)
222 break;
223
224 curEdgeDist += rayResults[0].Depth;
225
226 if (Math.Abs(rayResults[0].Normal.Z) < 0.7f)
227 {
228 rayDist -= rayResults[0].Depth;
229 if (rayDist < 0f)
230 break;
231
232 pivot = rayResults[0].Pos;
233 norm = rayResults[0].Normal;
234 edgeNormalX = norm.X;
235 edgeNormalY = norm.Y;
236 edgeDirX = rayDir.X;
237 edgeDirY = rayDir.Y;
238 }
239 else
240 {
241 foundEdge = true;
242 if (curEdgeDist < edgeDist)
243 {
244 edgeDist = curEdgeDist;
245 edgePos = rayResults[0].Pos;
246 }
247 break;
248 }
249 }
250
251 if (!foundEdge)
252 {
253 PhysicsSitResponse(0, actor.LocalID, offset, ori);
168 return; 254 return;
169 } 255 }
170*/ 256 avOffset.X *= 0.5f;
257 }
171 258
172 ang = Math.Atan2(-rayDir.Y, -rayDir.X); 259 else if (norm.Z > 0.866f)
173 ang *= 0.5d; 260 {
174 s = (float)Math.Sin(ang); 261 float toCamBaseX = avCameraPosition.X - pivot.X;
175 c = (float)Math.Cos(ang); 262 float toCamBaseY = avCameraPosition.Y - pivot.Y;
263 float toCamX = toCamBaseX;
264 float toCamY = toCamBaseY;
265
266 for (int j = 0; j < 4; j++)
267 {
268 float rayDist = 1.0f;
269 float curEdgeDist = 0.0f;
270 pivot = geopos + offset;
271
272 for (int i = 0; i < 3; i++)
273 {
274 pivot.Z -= 0.005f;
275 rayDir.X = toCamX;
276 rayDir.Y = toCamY;
277 rayDir.Z = (-toCamX * norm.X - toCamY * norm.Y) / norm.Z;
278 rayDir.Normalize();
279
280 rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims);
281 if (rayResults.Count == 0)
282 break;
283
284 curEdgeDist += rayResults[0].Depth;
285
286 if (rayResults[0].Normal.Z > 0.5f)
287 {
288 rayDist -= rayResults[0].Depth;
289 if (rayDist < 0f)
290 break;
291
292 pivot = rayResults[0].Pos;
293 norm = rayResults[0].Normal;
294 }
295 else
296 {
297 foundEdge = true;
298 if (curEdgeDist < edgeDist)
299 {
300 edgeDist = curEdgeDist;
301 edgeNormalX = rayResults[0].Normal.X;
302 edgeNormalY = rayResults[0].Normal.Y;
303 edgeDirX = rayDir.X;
304 edgeDirY = rayDir.Y;
305 edgePos = rayResults[0].Pos;
306 }
307 break;
308 }
309 }
310 if (foundEdge && edgeDist < 0.2f)
311 break;
312
313 switch (j)
314 {
315 case 0:
316 toCamX = -toCamBaseY;
317 toCamY = toCamBaseX;
318 break;
319 case 1:
320 toCamX = toCamBaseY;
321 toCamY = -toCamBaseX;
322 break;
323 case 2:
324 toCamX = -toCamBaseX;
325 toCamY = -toCamBaseY;
326 break;
327 default:
328 break;
329 }
330 }
331
332 if (!foundEdge)
333 {
334 avOffset.X = -avOffset.X;
335 avOffset.Z += 0.4f;
336
337 RotAroundZ(SitNormX, SitNormY, ref ori);
338
339 offset += avOffset * ori;
340
341 ori = geomInvOri * ori;
342 offset *= geomInvOri;
343
344 PhysicsSitResponse(3, actor.LocalID, offset, ori);
345 return;
346 }
347 avOffset.X *= 0.5f;
348 }
349
350 SitNormX = edgeNormalX;
351 SitNormY = edgeNormalY;
352 offset = edgePos - geopos;
353 if (edgeDirX * SitNormX + edgeDirY * SitNormY < 0)
354 {
355 SitNormX = -SitNormX;
356 SitNormY = -SitNormY;
357 }
176 358
177 ori = new Quaternion(0, 0, s, c); 359 RotAroundZ(SitNormX, SitNormY, ref ori);
178 360
179 offset += avOffset * ori; 361 offset += avOffset * ori;
180 362