aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/ubOde
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/PhysicsModules/ubOde')
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEApi.cs2024
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs1978
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs1096
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs933
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs97
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs3958
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs680
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs2819
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODESitAvatar.cs356
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/Properties/AssemblyInfo.cs61
10 files changed, 14002 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEApi.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEApi.cs
new file mode 100644
index 0000000..daf3af1
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEApi.cs
@@ -0,0 +1,2024 @@
1/*
2 * based on:
3 * Ode.NET - .NET bindings for ODE
4 * Jason Perkins (starkos@industriousone.com)
5 * Licensed under the New BSD
6 * Part of the OpenDynamicsEngine
7Open Dynamics Engine
8Copyright (c) 2001-2007, Russell L. Smith.
9All rights reserved.
10
11Redistribution and use in source and binary forms, with or without
12modification, are permitted provided that the following conditions
13are met:
14
15Redistributions of source code must retain the above copyright notice,
16this list of conditions and the following disclaimer.
17
18Redistributions in binary form must reproduce the above copyright notice,
19this list of conditions and the following disclaimer in the documentation
20and/or other materials provided with the distribution.
21
22Neither the names of ODE's copyright owner nor the names of its
23contributors may be used to endorse or promote products derived from
24this software without specific prior written permission.
25
26THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
32TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 * changes by opensim team;
39 * changes by Aurora team http://www.aurora-sim.org/
40 * changes by Ubit Umarov
41 */
42
43using System;
44using System.Runtime.InteropServices;
45using System.Security;
46using OMV = OpenMetaverse;
47namespace OdeAPI
48{
49//#if dDOUBLE
50// don't see much use in double precision with time steps of 20ms and 10 iterations used on opensim
51// at least we save same memory and memory access time, FPU performance on intel usually is similar
52// using dReal = System.Double;
53//#else
54 using dReal = System.Single;
55//#endif
56
57 public static class d
58 {
59 public static dReal Infinity = dReal.MaxValue;
60 public static int NTotalBodies = 0;
61 public static int NTotalGeoms = 0;
62
63 public const uint CONTACTS_UNIMPORTANT = 0x80000000;
64
65 #region Flags and Enumerations
66
67 [Flags]
68 public enum AllocateODEDataFlags : uint
69 {
70 BasicData = 0,
71 CollisionData = 0x00000001,
72 All = ~0u
73 }
74
75 [Flags]
76 public enum IniteODEFlags : uint
77 {
78 dInitFlagManualThreadCleanup = 0x00000001
79 }
80
81 [Flags]
82 public enum ContactFlags : int
83 {
84 Mu2 = 0x001,
85 FDir1 = 0x002,
86 Bounce = 0x004,
87 SoftERP = 0x008,
88 SoftCFM = 0x010,
89 Motion1 = 0x020,
90 Motion2 = 0x040,
91 MotionN = 0x080,
92 Slip1 = 0x100,
93 Slip2 = 0x200,
94 Approx0 = 0x0000,
95 Approx1_1 = 0x1000,
96 Approx1_2 = 0x2000,
97 Approx1 = 0x3000
98 }
99
100 public enum GeomClassID : int
101 {
102 SphereClass,
103 BoxClass,
104 CapsuleClass,
105 CylinderClass,
106 PlaneClass,
107 RayClass,
108 ConvexClass,
109 GeomTransformClass,
110 TriMeshClass,
111 HeightfieldClass,
112 FirstSpaceClass,
113 SimpleSpaceClass = FirstSpaceClass,
114 HashSpaceClass,
115 QuadTreeSpaceClass,
116 LastSpaceClass = QuadTreeSpaceClass,
117 ubtTerrainClass,
118 FirstUserClass,
119 LastUserClass = FirstUserClass + MaxUserClasses - 1,
120 NumClasses,
121 MaxUserClasses = 5
122 }
123
124 public enum JointType : int
125 {
126 None,
127 Ball,
128 Hinge,
129 Slider,
130 Contact,
131 Universal,
132 Hinge2,
133 Fixed,
134 Null,
135 AMotor,
136 LMotor,
137 Plane2D
138 }
139
140 public enum JointParam : int
141 {
142 LoStop,
143 HiStop,
144 Vel,
145 FMax,
146 FudgeFactor,
147 Bounce,
148 CFM,
149 StopERP,
150 StopCFM,
151 SuspensionERP,
152 SuspensionCFM,
153 LoStop2 = 256,
154 HiStop2,
155 Vel2,
156 FMax2,
157 FudgeFactor2,
158 Bounce2,
159 CFM2,
160 StopERP2,
161 StopCFM2,
162 SuspensionERP2,
163 SuspensionCFM2,
164 LoStop3 = 512,
165 HiStop3,
166 Vel3,
167 FMax3,
168 FudgeFactor3,
169 Bounce3,
170 CFM3,
171 StopERP3,
172 StopCFM3,
173 SuspensionERP3,
174 SuspensionCFM3
175 }
176
177 public enum dSweepAndPruneAxis : int
178 {
179 XYZ = ((0)|(1<<2)|(2<<4)),
180 XZY = ((0)|(2<<2)|(1<<4)),
181 YXZ = ((1)|(0<<2)|(2<<4)),
182 YZX = ((1)|(2<<2)|(0<<4)),
183 ZXY = ((2)|(0<<2)|(1<<4)),
184 ZYX = ((2)|(1<<2)|(0<<4))
185 }
186
187 #endregion
188
189 #region Callbacks
190
191 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
192 public delegate int AABBTestFn(IntPtr o1, IntPtr o2, ref AABB aabb);
193
194 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
195 public delegate int ColliderFn(IntPtr o1, IntPtr o2, int flags, out ContactGeom contact, int skip);
196
197 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
198 public delegate void GetAABBFn(IntPtr geom, out AABB aabb);
199
200 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
201 public delegate ColliderFn GetColliderFnFn(int num);
202
203 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
204 public delegate void GeomDtorFn(IntPtr o);
205
206 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
207 public delegate dReal HeightfieldGetHeight(IntPtr p_user_data, int x, int z);
208
209 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
210 public delegate dReal OSTerrainGetHeight(IntPtr p_user_data, int x, int z);
211
212 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
213 public delegate void NearCallback(IntPtr data, IntPtr geom1, IntPtr geom2);
214
215 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
216 public delegate int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex);
217
218 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
219 public delegate int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount);
220
221 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
222 public delegate int TriRayCallback(IntPtr trimesh, IntPtr ray, int triangleIndex, dReal u, dReal v);
223
224 #endregion
225
226 #region Structs
227
228 [StructLayout(LayoutKind.Sequential)]
229 public struct AABB
230 {
231 public dReal MinX, MaxX;
232 public dReal MinY, MaxY;
233 public dReal MinZ, MaxZ;
234 }
235
236
237 [StructLayout(LayoutKind.Sequential)]
238 public struct Contact
239 {
240 public SurfaceParameters surface;
241 public ContactGeom geom;
242 public Vector3 fdir1;
243 public static readonly int unmanagedSizeOf = Marshal.SizeOf(typeof(Contact));
244 }
245
246
247 [StructLayout(LayoutKind.Sequential)]
248 public struct ContactGeom
249 {
250
251 public Vector3 pos;
252 public Vector3 normal;
253 public dReal depth;
254 public IntPtr g1;
255 public IntPtr g2;
256 public int side1;
257 public int side2;
258 public static readonly int unmanagedSizeOf = Marshal.SizeOf(typeof(ContactGeom));
259 }
260
261 [StructLayout(LayoutKind.Sequential)]
262 public struct GeomClass
263 {
264 public int bytes;
265 public GetColliderFnFn collider;
266 public GetAABBFn aabb;
267 public AABBTestFn aabb_test;
268 public GeomDtorFn dtor;
269 }
270
271
272 [StructLayout(LayoutKind.Sequential)]
273 public struct JointFeedback
274 {
275 public Vector3 f1;
276 public Vector3 t1;
277 public Vector3 f2;
278 public Vector3 t2;
279 }
280
281
282 [StructLayout(LayoutKind.Sequential)]
283 public struct Mass
284 {
285 public dReal mass;
286 public Vector4 c;
287 public Matrix3 I;
288 }
289
290
291 [StructLayout(LayoutKind.Sequential)]
292 public struct Matrix3
293 {
294 public Matrix3(dReal m00, dReal m10, dReal m20, dReal m01, dReal m11, dReal m21, dReal m02, dReal m12, dReal m22)
295 {
296 M00 = m00; M10 = m10; M20 = m20; _m30 = 0.0f;
297 M01 = m01; M11 = m11; M21 = m21; _m31 = 0.0f;
298 M02 = m02; M12 = m12; M22 = m22; _m32 = 0.0f;
299 }
300 public dReal M00, M10, M20;
301 private dReal _m30;
302 public dReal M01, M11, M21;
303 private dReal _m31;
304 public dReal M02, M12, M22;
305 private dReal _m32;
306 }
307
308 [StructLayout(LayoutKind.Sequential)]
309 public struct Matrix4
310 {
311 public Matrix4(dReal m00, dReal m10, dReal m20, dReal m30,
312 dReal m01, dReal m11, dReal m21, dReal m31,
313 dReal m02, dReal m12, dReal m22, dReal m32,
314 dReal m03, dReal m13, dReal m23, dReal m33)
315 {
316 M00 = m00; M10 = m10; M20 = m20; M30 = m30;
317 M01 = m01; M11 = m11; M21 = m21; M31 = m31;
318 M02 = m02; M12 = m12; M22 = m22; M32 = m32;
319 M03 = m03; M13 = m13; M23 = m23; M33 = m33;
320 }
321 public dReal M00, M10, M20, M30;
322 public dReal M01, M11, M21, M31;
323 public dReal M02, M12, M22, M32;
324 public dReal M03, M13, M23, M33;
325 }
326
327 [StructLayout(LayoutKind.Sequential)]
328 public struct Quaternion
329 {
330 public dReal W, X, Y, Z;
331 }
332
333
334 [StructLayout(LayoutKind.Sequential)]
335 public struct SurfaceParameters
336 {
337 public ContactFlags mode;
338 public dReal mu;
339 public dReal mu2;
340 public dReal bounce;
341 public dReal bounce_vel;
342 public dReal soft_erp;
343 public dReal soft_cfm;
344 public dReal motion1;
345 public dReal motion2;
346 public dReal motionN;
347 public dReal slip1;
348 public dReal slip2;
349 }
350
351
352 [StructLayout(LayoutKind.Sequential)]
353 public struct Vector3
354 {
355 public Vector3(dReal x, dReal y, dReal z)
356 {
357 X = x; Y = y; Z = z; _w = 0.0f;
358 }
359 public dReal X, Y, Z;
360 private dReal _w;
361 }
362
363
364 [StructLayout(LayoutKind.Sequential)]
365 public struct Vector4
366 {
367 public Vector4(dReal x, dReal y, dReal z, dReal w)
368 {
369 X = x; Y = y; Z = z; W = w;
370 }
371 public dReal X, Y, Z, W;
372 }
373
374 #endregion
375
376 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dAllocateODEDataForThread"), SuppressUnmanagedCodeSecurity]
377 public static extern int AllocateODEDataForThread(uint ODEInitFlags);
378
379 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dAreConnected"), SuppressUnmanagedCodeSecurity]
380 public static extern bool AreConnected(IntPtr b1, IntPtr b2);
381
382 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dAreConnectedExcluding"), SuppressUnmanagedCodeSecurity]
383 public static extern bool AreConnectedExcluding(IntPtr b1, IntPtr b2, JointType joint_type);
384
385 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddForce"), SuppressUnmanagedCodeSecurity]
386 public static extern void BodyAddForce(IntPtr body, dReal fx, dReal fy, dReal fz);
387
388 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddForceAtPos"), SuppressUnmanagedCodeSecurity]
389 public static extern void BodyAddForceAtPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
390
391 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddForceAtRelPos"), SuppressUnmanagedCodeSecurity]
392 public static extern void BodyAddForceAtRelPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
393
394 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelForce"), SuppressUnmanagedCodeSecurity]
395 public static extern void BodyAddRelForce(IntPtr body, dReal fx, dReal fy, dReal fz);
396
397 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelForceAtPos"), SuppressUnmanagedCodeSecurity]
398 public static extern void BodyAddRelForceAtPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
399
400 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelForceAtRelPos"), SuppressUnmanagedCodeSecurity]
401 public static extern void BodyAddRelForceAtRelPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
402
403 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelTorque"), SuppressUnmanagedCodeSecurity]
404 public static extern void BodyAddRelTorque(IntPtr body, dReal fx, dReal fy, dReal fz);
405
406 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddTorque"), SuppressUnmanagedCodeSecurity]
407 public static extern void BodyAddTorque(IntPtr body, dReal fx, dReal fy, dReal fz);
408
409 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyPosition"), SuppressUnmanagedCodeSecurity]
410 public static extern void BodyCopyPosition(IntPtr body, out Vector3 pos);
411
412 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyPosition"), SuppressUnmanagedCodeSecurity]
413 public static extern void BodyCopyPosition(IntPtr body, out dReal X);
414
415 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyQuaternion"), SuppressUnmanagedCodeSecurity]
416 public static extern void BodyCopyQuaternion(IntPtr body, out Quaternion quat);
417
418 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyQuaternion"), SuppressUnmanagedCodeSecurity]
419 public static extern void BodyCopyQuaternion(IntPtr body, out dReal X);
420
421 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyRotation"), SuppressUnmanagedCodeSecurity]
422 public static extern void BodyCopyRotation(IntPtr body, out Matrix3 R);
423
424 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyRotation"), SuppressUnmanagedCodeSecurity]
425 public static extern void BodyCopyRotation(IntPtr body, out dReal M00);
426
427 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCreate"), SuppressUnmanagedCodeSecurity]
428 public static extern IntPtr BodyiCreate(IntPtr world);
429 public static IntPtr BodyCreate(IntPtr world)
430 {
431 NTotalBodies++;
432 return BodyiCreate(world);
433 }
434
435 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyDestroy"), SuppressUnmanagedCodeSecurity]
436 public static extern void BodyiDestroy(IntPtr body);
437 public static void BodyDestroy(IntPtr body)
438 {
439 NTotalBodies--;
440 BodyiDestroy(body);
441 }
442
443 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyDisable"), SuppressUnmanagedCodeSecurity]
444 public static extern void BodyDisable(IntPtr body);
445
446 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyEnable"), SuppressUnmanagedCodeSecurity]
447 public static extern void BodyEnable(IntPtr body);
448
449 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
450 public static extern dReal BodyGetAutoDisableAngularThreshold(IntPtr body);
451
452 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
453 public static extern bool BodyGetAutoDisableFlag(IntPtr body);
454
455 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableDefaults"), SuppressUnmanagedCodeSecurity]
456 public static extern void BodyGetAutoDisableDefaults(IntPtr body);
457
458 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
459 public static extern dReal BodyGetAutoDisableLinearThreshold(IntPtr body);
460
461 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
462 public static extern int BodyGetAutoDisableSteps(IntPtr body);
463
464 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
465 public static extern dReal BodyGetAutoDisableTime(IntPtr body);
466
467 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAngularVel"), SuppressUnmanagedCodeSecurity]
468 public extern unsafe static Vector3* BodyGetAngularVelUnsafe(IntPtr body);
469 public static Vector3 BodyGetAngularVel(IntPtr body)
470 {
471 unsafe { return *(BodyGetAngularVelUnsafe(body)); }
472 }
473
474 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetData"), SuppressUnmanagedCodeSecurity]
475 public static extern IntPtr BodyGetData(IntPtr body);
476
477 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetFiniteRotationMode"), SuppressUnmanagedCodeSecurity]
478 public static extern int BodyGetFiniteRotationMode(IntPtr body);
479
480 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetFiniteRotationAxis"), SuppressUnmanagedCodeSecurity]
481 public static extern void BodyGetFiniteRotationAxis(IntPtr body, out Vector3 result);
482
483 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetForce"), SuppressUnmanagedCodeSecurity]
484 public extern unsafe static Vector3* BodyGetForceUnsafe(IntPtr body);
485 public static Vector3 BodyGetForce(IntPtr body)
486 {
487 unsafe { return *(BodyGetForceUnsafe(body)); }
488 }
489
490 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetGravityMode"), SuppressUnmanagedCodeSecurity]
491 public static extern bool BodyGetGravityMode(IntPtr body);
492
493 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetGyroscopicMode"), SuppressUnmanagedCodeSecurity]
494 public static extern int BodyGetGyroscopicMode(IntPtr body);
495
496 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetJoint"), SuppressUnmanagedCodeSecurity]
497 public static extern IntPtr BodyGetJoint(IntPtr body, int index);
498
499 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetLinearVel"), SuppressUnmanagedCodeSecurity]
500 public extern unsafe static Vector3* BodyGetLinearVelUnsafe(IntPtr body);
501 public static Vector3 BodyGetLinearVel(IntPtr body)
502 {
503 unsafe { return *(BodyGetLinearVelUnsafe(body)); }
504 }
505
506 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetMass"), SuppressUnmanagedCodeSecurity]
507 public static extern void BodyGetMass(IntPtr body, out Mass mass);
508
509 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetNumJoints"), SuppressUnmanagedCodeSecurity]
510 public static extern int BodyGetNumJoints(IntPtr body);
511
512 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetPointVel"), SuppressUnmanagedCodeSecurity]
513 public static extern void BodyGetPointVel(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
514
515 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetPosition"), SuppressUnmanagedCodeSecurity]
516 public extern unsafe static Vector3* BodyGetPositionUnsafe(IntPtr body);
517 public static Vector3 BodyGetPosition(IntPtr body)
518 {
519 unsafe { return *(BodyGetPositionUnsafe(body)); }
520 }
521
522 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetPosRelPoint"), SuppressUnmanagedCodeSecurity]
523 public static extern void BodyGetPosRelPoint(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
524
525 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetQuaternion"), SuppressUnmanagedCodeSecurity]
526 public extern unsafe static Quaternion* BodyGetQuaternionUnsafe(IntPtr body);
527 public static Quaternion BodyGetQuaternion(IntPtr body)
528 {
529 unsafe { return *(BodyGetQuaternionUnsafe(body)); }
530 }
531
532 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetRelPointPos"), SuppressUnmanagedCodeSecurity]
533 public static extern void BodyGetRelPointPos(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
534
535 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetRelPointVel"), SuppressUnmanagedCodeSecurity]
536 public static extern void BodyGetRelPointVel(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
537
538 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetRotation"), SuppressUnmanagedCodeSecurity]
539 public extern unsafe static Matrix3* BodyGetRotationUnsafe(IntPtr body);
540 public static Matrix3 BodyGetRotation(IntPtr body)
541 {
542 unsafe { return *(BodyGetRotationUnsafe(body)); }
543 }
544
545 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetTorque"), SuppressUnmanagedCodeSecurity]
546 public extern unsafe static Vector3* BodyGetTorqueUnsafe(IntPtr body);
547 public static Vector3 BodyGetTorque(IntPtr body)
548 {
549 unsafe { return *(BodyGetTorqueUnsafe(body)); }
550 }
551
552 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetWorld"), SuppressUnmanagedCodeSecurity]
553 public static extern IntPtr BodyGetWorld(IntPtr body);
554
555 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetFirstGeom"), SuppressUnmanagedCodeSecurity]
556 public static extern IntPtr BodyGetFirstGeom(IntPtr body);
557
558 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetNextGeom"), SuppressUnmanagedCodeSecurity]
559 public static extern IntPtr dBodyGetNextGeom(IntPtr Geom);
560
561
562 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyIsEnabled"), SuppressUnmanagedCodeSecurity]
563 public static extern bool BodyIsEnabled(IntPtr body);
564
565 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularVel"), SuppressUnmanagedCodeSecurity]
566 public static extern void BodySetAngularVel(IntPtr body, dReal x, dReal y, dReal z);
567
568 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
569 public static extern void BodySetAutoDisableAngularThreshold(IntPtr body, dReal angular_threshold);
570
571 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableDefaults"), SuppressUnmanagedCodeSecurity]
572 public static extern void BodySetAutoDisableDefaults(IntPtr body);
573
574 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
575 public static extern void BodySetAutoDisableFlag(IntPtr body, bool do_auto_disable);
576
577 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
578 public static extern void BodySetAutoDisableLinearThreshold(IntPtr body, dReal linear_threshold);
579
580 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
581 public static extern void BodySetAutoDisableSteps(IntPtr body, int steps);
582
583 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
584 public static extern void BodySetAutoDisableTime(IntPtr body, dReal time);
585
586 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetData"), SuppressUnmanagedCodeSecurity]
587 public static extern void BodySetData(IntPtr body, IntPtr data);
588
589 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetFiniteRotationMode"), SuppressUnmanagedCodeSecurity]
590 public static extern void BodySetFiniteRotationMode(IntPtr body, int mode);
591
592 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetFiniteRotationAxis"), SuppressUnmanagedCodeSecurity]
593 public static extern void BodySetFiniteRotationAxis(IntPtr body, dReal x, dReal y, dReal z);
594
595 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetLinearDamping"), SuppressUnmanagedCodeSecurity]
596 public static extern void BodySetLinearDamping(IntPtr body, dReal scale);
597
598 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularDamping"), SuppressUnmanagedCodeSecurity]
599 public static extern void BodySetAngularDamping(IntPtr body, dReal scale);
600
601 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetLinearDamping"), SuppressUnmanagedCodeSecurity]
602 public static extern dReal BodyGetLinearDamping(IntPtr body);
603
604 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAngularDamping"), SuppressUnmanagedCodeSecurity]
605 public static extern dReal BodyGetAngularDamping(IntPtr body);
606
607 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularDamping"), SuppressUnmanagedCodeSecurity]
608 public static extern void BodySetDamping(IntPtr body, dReal linear_scale, dReal angular_scale);
609
610 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
611 public static extern void BodySetAngularDampingThreshold(IntPtr body, dReal threshold);
612
613 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
614 public static extern void BodySetLinearDampingThreshold(IntPtr body, dReal threshold);
615
616 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
617 public static extern dReal BodyGetLinearDampingThreshold(IntPtr body);
618
619 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
620 public static extern dReal BodyGetAngularDampingThreshold(IntPtr body);
621
622 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetForce"), SuppressUnmanagedCodeSecurity]
623 public static extern void BodySetForce(IntPtr body, dReal x, dReal y, dReal z);
624
625 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetGravityMode"), SuppressUnmanagedCodeSecurity]
626 public static extern void BodySetGravityMode(IntPtr body, bool mode);
627
628 /// <summary>
629 /// Sets the Gyroscopic term status on the body specified.
630 /// </summary>
631 /// <param name="body">Pointer to body</param>
632 /// <param name="enabled">NonZero enabled, Zero disabled</param>
633 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetGyroscopicMode"), SuppressUnmanagedCodeSecurity]
634 public static extern void dBodySetGyroscopicMode(IntPtr body, int enabled);
635
636 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetLinearVel"), SuppressUnmanagedCodeSecurity]
637 public static extern void BodySetLinearVel(IntPtr body, dReal x, dReal y, dReal z);
638
639 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetMass"), SuppressUnmanagedCodeSecurity]
640 public static extern void BodySetMass(IntPtr body, ref Mass mass);
641
642 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetPosition"), SuppressUnmanagedCodeSecurity]
643 public static extern void BodySetPosition(IntPtr body, dReal x, dReal y, dReal z);
644
645 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetQuaternion"), SuppressUnmanagedCodeSecurity]
646 public static extern void BodySetQuaternion(IntPtr body, ref Quaternion q);
647
648 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetQuaternion"), SuppressUnmanagedCodeSecurity]
649 public static extern void BodySetQuaternion(IntPtr body, ref dReal w);
650
651 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetRotation"), SuppressUnmanagedCodeSecurity]
652 public static extern void BodySetRotation(IntPtr body, ref Matrix3 R);
653
654 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetRotation"), SuppressUnmanagedCodeSecurity]
655 public static extern void BodySetRotation(IntPtr body, ref dReal M00);
656
657 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetTorque"), SuppressUnmanagedCodeSecurity]
658 public static extern void BodySetTorque(IntPtr body, dReal x, dReal y, dReal z);
659
660 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyVectorFromWorld"), SuppressUnmanagedCodeSecurity]
661 public static extern void BodyVectorFromWorld(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
662
663 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyVectorToWorld"), SuppressUnmanagedCodeSecurity]
664 public static extern void BodyVectorToWorld(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
665
666 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBoxBox"), SuppressUnmanagedCodeSecurity]
667 public static extern void BoxBox(ref Vector3 p1, ref Matrix3 R1,
668 ref Vector3 side1, ref Vector3 p2,
669 ref Matrix3 R2, ref Vector3 side2,
670 ref Vector3 normal, out dReal depth, out int return_code,
671 int maxc, out ContactGeom contact, int skip);
672
673 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBoxTouchesBox"), SuppressUnmanagedCodeSecurity]
674 public static extern void BoxTouchesBox(ref Vector3 _p1, ref Matrix3 R1,
675 ref Vector3 side1, ref Vector3 _p2,
676 ref Matrix3 R2, ref Vector3 side2);
677
678 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCleanupODEAllDataForThread"), SuppressUnmanagedCodeSecurity]
679 public static extern void CleanupODEAllDataForThread();
680
681 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dClosestLineSegmentPoints"), SuppressUnmanagedCodeSecurity]
682 public static extern void ClosestLineSegmentPoints(ref Vector3 a1, ref Vector3 a2,
683 ref Vector3 b1, ref Vector3 b2,
684 ref Vector3 cp1, ref Vector3 cp2);
685
686 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCloseODE"), SuppressUnmanagedCodeSecurity]
687 public static extern void CloseODE();
688
689 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCollide"), SuppressUnmanagedCodeSecurity]
690 public static extern int Collide(IntPtr o1, IntPtr o2, int flags, [In, Out] ContactGeom[] contact, int skip);
691 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCollide"), SuppressUnmanagedCodeSecurity]
692 public static extern int CollidePtr(IntPtr o1, IntPtr o2, int flags, IntPtr contactgeomarray, int skip);
693
694 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dConnectingJoint"), SuppressUnmanagedCodeSecurity]
695 public static extern IntPtr ConnectingJoint(IntPtr j1, IntPtr j2);
696
697 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateBox"), SuppressUnmanagedCodeSecurity]
698 public static extern IntPtr CreateiBox(IntPtr space, dReal lx, dReal ly, dReal lz);
699 public static IntPtr CreateBox(IntPtr space, dReal lx, dReal ly, dReal lz)
700 {
701 NTotalGeoms++;
702 return CreateiBox(space, lx, ly, lz);
703 }
704
705 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateCapsule"), SuppressUnmanagedCodeSecurity]
706 public static extern IntPtr CreateiCapsule(IntPtr space, dReal radius, dReal length);
707 public static IntPtr CreateCapsule(IntPtr space, dReal radius, dReal length)
708 {
709 NTotalGeoms++;
710 return CreateiCapsule(space, radius, length);
711 }
712
713 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateConvex"), SuppressUnmanagedCodeSecurity]
714 public static extern IntPtr CreateiConvex(IntPtr space, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
715 public static IntPtr CreateConvex(IntPtr space, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons)
716 {
717 NTotalGeoms++;
718 return CreateiConvex(space, planes, planeCount, points, pointCount, polygons);
719 }
720
721 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateCylinder"), SuppressUnmanagedCodeSecurity]
722 public static extern IntPtr CreateiCylinder(IntPtr space, dReal radius, dReal length);
723 public static IntPtr CreateCylinder(IntPtr space, dReal radius, dReal length)
724 {
725 NTotalGeoms++;
726 return CreateiCylinder(space, radius, length);
727 }
728
729 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateHeightfield"), SuppressUnmanagedCodeSecurity]
730 public static extern IntPtr CreateiHeightfield(IntPtr space, IntPtr data, int bPlaceable);
731 public static IntPtr CreateHeightfield(IntPtr space, IntPtr data, int bPlaceable)
732 {
733 NTotalGeoms++;
734 return CreateiHeightfield(space, data, bPlaceable);
735 }
736
737 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateOSTerrain"), SuppressUnmanagedCodeSecurity]
738 public static extern IntPtr CreateiOSTerrain(IntPtr space, IntPtr data, int bPlaceable);
739 public static IntPtr CreateOSTerrain(IntPtr space, IntPtr data, int bPlaceable)
740 {
741 NTotalGeoms++;
742 return CreateiOSTerrain(space, data, bPlaceable);
743 }
744
745
746
747
748
749 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeom"), SuppressUnmanagedCodeSecurity]
750 public static extern IntPtr CreateiGeom(int classnum);
751 public static IntPtr CreateGeom(int classnum)
752 {
753 NTotalGeoms++;
754 return CreateiGeom(classnum);
755 }
756
757 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeomClass"), SuppressUnmanagedCodeSecurity]
758 public static extern int CreateGeomClass(ref GeomClass classptr);
759
760 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeomTransform"), SuppressUnmanagedCodeSecurity]
761 public static extern IntPtr CreateGeomTransform(IntPtr space);
762
763 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreatePlane"), SuppressUnmanagedCodeSecurity]
764 public static extern IntPtr CreateiPlane(IntPtr space, dReal a, dReal b, dReal c, dReal d);
765 public static IntPtr CreatePlane(IntPtr space, dReal a, dReal b, dReal c, dReal d)
766 {
767 NTotalGeoms++;
768 return CreateiPlane(space, a, b, c, d);
769 }
770
771 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateRay"), SuppressUnmanagedCodeSecurity]
772 public static extern IntPtr CreateiRay(IntPtr space, dReal length);
773 public static IntPtr CreateRay(IntPtr space, dReal length)
774 {
775 NTotalGeoms++;
776 return CreateiRay(space, length);
777 }
778
779 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateSphere"), SuppressUnmanagedCodeSecurity]
780 public static extern IntPtr CreateiSphere(IntPtr space, dReal radius);
781 public static IntPtr CreateSphere(IntPtr space, dReal radius)
782 {
783 NTotalGeoms++;
784 return CreateiSphere(space, radius);
785 }
786
787 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateTriMesh"), SuppressUnmanagedCodeSecurity]
788 public static extern IntPtr CreateiTriMesh(IntPtr space, IntPtr data,
789 TriCallback callback, TriArrayCallback arrayCallback, TriRayCallback rayCallback);
790 public static IntPtr CreateTriMesh(IntPtr space, IntPtr data,
791 TriCallback callback, TriArrayCallback arrayCallback, TriRayCallback rayCallback)
792 {
793 NTotalGeoms++;
794 return CreateiTriMesh(space, data, callback, arrayCallback, rayCallback);
795 }
796 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dDot"), SuppressUnmanagedCodeSecurity]
797 public static extern dReal Dot(ref dReal X0, ref dReal X1, int n);
798
799 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dDQfromW"), SuppressUnmanagedCodeSecurity]
800 public static extern void DQfromW(dReal[] dq, ref Vector3 w, ref Quaternion q);
801
802 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dFactorCholesky"), SuppressUnmanagedCodeSecurity]
803 public static extern int FactorCholesky(ref dReal A00, int n);
804
805 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dFactorLDLT"), SuppressUnmanagedCodeSecurity]
806 public static extern void FactorLDLT(ref dReal A, out dReal d, int n, int nskip);
807
808 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxGetLengths"), SuppressUnmanagedCodeSecurity]
809 public static extern void GeomBoxGetLengths(IntPtr geom, out Vector3 len);
810
811 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxGetLengths"), SuppressUnmanagedCodeSecurity]
812 public static extern void GeomBoxGetLengths(IntPtr geom, out dReal x);
813
814 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxPointDepth"), SuppressUnmanagedCodeSecurity]
815 public static extern dReal GeomBoxPointDepth(IntPtr geom, dReal x, dReal y, dReal z);
816
817 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxSetLengths"), SuppressUnmanagedCodeSecurity]
818 public static extern void GeomBoxSetLengths(IntPtr geom, dReal x, dReal y, dReal z);
819
820 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCapsuleGetParams"), SuppressUnmanagedCodeSecurity]
821 public static extern void GeomCapsuleGetParams(IntPtr geom, out dReal radius, out dReal length);
822
823 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCapsulePointDepth"), SuppressUnmanagedCodeSecurity]
824 public static extern dReal GeomCapsulePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
825
826 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCapsuleSetParams"), SuppressUnmanagedCodeSecurity]
827 public static extern void GeomCapsuleSetParams(IntPtr geom, dReal radius, dReal length);
828
829 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomClearOffset"), SuppressUnmanagedCodeSecurity]
830 public static extern void GeomClearOffset(IntPtr geom);
831
832 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetPosition"), SuppressUnmanagedCodeSecurity]
833 public static extern IntPtr GeomCopyOffsetPosition(IntPtr geom, ref Vector3 pos);
834
835 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetPosition"), SuppressUnmanagedCodeSecurity]
836 public static extern IntPtr GeomCopyOffsetPosition(IntPtr geom, ref dReal X);
837
838 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
839 public static extern void GeomCopyOffsetQuaternion(IntPtr geom, ref Quaternion Q);
840
841 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
842 public static extern void GeomCopyOffsetQuaternion(IntPtr geom, ref dReal X);
843
844 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetRotation"), SuppressUnmanagedCodeSecurity]
845 public static extern IntPtr GeomCopyOffsetRotation(IntPtr geom, ref Matrix3 R);
846
847 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetRotation"), SuppressUnmanagedCodeSecurity]
848 public static extern IntPtr GeomCopyOffsetRotation(IntPtr geom, ref dReal M00);
849
850 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyPosition"), SuppressUnmanagedCodeSecurity]
851 public static extern void GeomCopyPosition(IntPtr geom, out Vector3 pos);
852
853 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyPosition"), SuppressUnmanagedCodeSecurity]
854 public static extern void GeomCopyPosition(IntPtr geom, out dReal X);
855
856 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyRotation"), SuppressUnmanagedCodeSecurity]
857 public static extern void GeomCopyRotation(IntPtr geom, out Matrix3 R);
858
859 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyRotation"), SuppressUnmanagedCodeSecurity]
860 public static extern void GeomCopyRotation(IntPtr geom, out dReal M00);
861
862 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCylinderGetParams"), SuppressUnmanagedCodeSecurity]
863 public static extern void GeomCylinderGetParams(IntPtr geom, out dReal radius, out dReal length);
864
865 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCylinderSetParams"), SuppressUnmanagedCodeSecurity]
866 public static extern void GeomCylinderSetParams(IntPtr geom, dReal radius, dReal length);
867
868 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomDestroy"), SuppressUnmanagedCodeSecurity]
869 public static extern void GeomiDestroy(IntPtr geom);
870 public static void GeomDestroy(IntPtr geom)
871 {
872 NTotalGeoms--;
873 GeomiDestroy(geom);
874 }
875
876
877 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomDisable"), SuppressUnmanagedCodeSecurity]
878 public static extern void GeomDisable(IntPtr geom);
879
880 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomEnable"), SuppressUnmanagedCodeSecurity]
881 public static extern void GeomEnable(IntPtr geom);
882
883 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetAABB"), SuppressUnmanagedCodeSecurity]
884 public static extern void GeomGetAABB(IntPtr geom, out AABB aabb);
885
886 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetAABB"), SuppressUnmanagedCodeSecurity]
887 public static extern void GeomGetAABB(IntPtr geom, out dReal minX);
888
889 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetBody"), SuppressUnmanagedCodeSecurity]
890 public static extern IntPtr GeomGetBody(IntPtr geom);
891
892 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetCategoryBits"), SuppressUnmanagedCodeSecurity]
893 public static extern uint GeomGetCategoryBits(IntPtr geom);
894
895 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetClassData"), SuppressUnmanagedCodeSecurity]
896 public static extern IntPtr GeomGetClassData(IntPtr geom);
897
898 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetCollideBits"), SuppressUnmanagedCodeSecurity]
899 public static extern uint GeomGetCollideBits(IntPtr geom);
900
901 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetClass"), SuppressUnmanagedCodeSecurity]
902 public static extern GeomClassID GeomGetClass(IntPtr geom);
903
904 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetData"), SuppressUnmanagedCodeSecurity]
905 public static extern IntPtr GeomGetData(IntPtr geom);
906
907 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetPosition"), SuppressUnmanagedCodeSecurity]
908 public extern unsafe static Vector3* GeomGetOffsetPositionUnsafe(IntPtr geom);
909 public static Vector3 GeomGetOffsetPosition(IntPtr geom)
910 {
911 unsafe { return *(GeomGetOffsetPositionUnsafe(geom)); }
912 }
913
914 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetRotation"), SuppressUnmanagedCodeSecurity]
915 public extern unsafe static Matrix3* GeomGetOffsetRotationUnsafe(IntPtr geom);
916 public static Matrix3 GeomGetOffsetRotation(IntPtr geom)
917 {
918 unsafe { return *(GeomGetOffsetRotationUnsafe(geom)); }
919 }
920
921 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetPosition"), SuppressUnmanagedCodeSecurity]
922 public extern unsafe static Vector3* GeomGetPositionUnsafe(IntPtr geom);
923 public static Vector3 GeomGetPosition(IntPtr geom)
924 {
925 unsafe { return *(GeomGetPositionUnsafe(geom)); }
926 }
927 public static OMV.Vector3 GeomGetPositionOMV(IntPtr geom)
928 {
929 Vector3 vtmp = GeomGetPosition(geom);
930 return new OMV.Vector3(vtmp.X, vtmp.Y, vtmp.Z);
931 }
932
933 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity]
934 public static extern void GeomCopyQuaternion(IntPtr geom, out Quaternion q);
935 public static OMV.Quaternion GeomGetQuaternionOMV(IntPtr geom)
936 {
937 Quaternion qtmp;
938 GeomCopyQuaternion(geom, out qtmp);
939 return new OMV.Quaternion(qtmp.X, qtmp.Y, qtmp.Z, qtmp.W);
940 }
941
942 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity]
943 public static extern void GeomCopyQuaternion(IntPtr geom, out dReal X);
944
945 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetRotation"), SuppressUnmanagedCodeSecurity]
946 public extern unsafe static Matrix3* GeomGetRotationUnsafe(IntPtr geom);
947 public static Matrix3 GeomGetRotation(IntPtr geom)
948 {
949 unsafe { return *(GeomGetRotationUnsafe(geom)); }
950 }
951
952 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetSpace"), SuppressUnmanagedCodeSecurity]
953 public static extern IntPtr GeomGetSpace(IntPtr geom);
954
955 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildByte"), SuppressUnmanagedCodeSecurity]
956 public static extern void GeomHeightfieldDataBuildByte(IntPtr d, byte[] pHeightData, int bCopyHeightData,
957 dReal width, dReal depth, int widthSamples, int depthSamples,
958 dReal scale, dReal offset, dReal thickness, int bWrap);
959
960 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildByte"), SuppressUnmanagedCodeSecurity]
961 public static extern void GeomHeightfieldDataBuildByte(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
962 dReal width, dReal depth, int widthSamples, int depthSamples,
963 dReal scale, dReal offset, dReal thickness, int bWrap);
964
965 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildCallback"), SuppressUnmanagedCodeSecurity]
966 public static extern void GeomHeightfieldDataBuildCallback(IntPtr d, IntPtr pUserData, HeightfieldGetHeight pCallback,
967 dReal width, dReal depth, int widthSamples, int depthSamples,
968 dReal scale, dReal offset, dReal thickness, int bWrap);
969
970 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
971 public static extern void GeomHeightfieldDataBuildShort(IntPtr d, ushort[] pHeightData, int bCopyHeightData,
972 dReal width, dReal depth, int widthSamples, int depthSamples,
973 dReal scale, dReal offset, dReal thickness, int bWrap);
974
975 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
976 public static extern void GeomHeightfieldDataBuildShort(IntPtr d, short[] pHeightData, int bCopyHeightData,
977 dReal width, dReal depth, int widthSamples, int depthSamples,
978 dReal scale, dReal offset, dReal thickness, int bWrap);
979
980 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
981 public static extern void GeomHeightfieldDataBuildShort(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
982 dReal width, dReal depth, int widthSamples, int depthSamples,
983 dReal scale, dReal offset, dReal thickness, int bWrap);
984
985 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildSingle"), SuppressUnmanagedCodeSecurity]
986 public static extern void GeomHeightfieldDataBuildSingle(IntPtr d, float[] pHeightData, int bCopyHeightData,
987 dReal width, dReal depth, int widthSamples, int depthSamples,
988 dReal scale, dReal offset, dReal thickness, int bWrap);
989
990 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildSingle"), SuppressUnmanagedCodeSecurity]
991 public static extern void GeomHeightfieldDataBuildSingle(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
992 dReal width, dReal depth, int widthSamples, int depthSamples,
993 dReal scale, dReal offset, dReal thickness, int bWrap);
994
995
996
997 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity]
998 public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, double[] pHeightData, int bCopyHeightData,
999 dReal width, dReal depth, int widthSamples, int depthSamples,
1000 dReal scale, dReal offset, dReal thickness, int bWrap);
1001
1002 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity]
1003 public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
1004 dReal width, dReal depth, int widthSamples, int depthSamples,
1005 dReal scale, dReal offset, dReal thickness, int bWrap);
1006
1007 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataCreate"), SuppressUnmanagedCodeSecurity]
1008 public static extern IntPtr GeomHeightfieldDataCreate();
1009
1010 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataDestroy"), SuppressUnmanagedCodeSecurity]
1011 public static extern void GeomHeightfieldDataDestroy(IntPtr d);
1012
1013 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataSetBounds"), SuppressUnmanagedCodeSecurity]
1014 public static extern void GeomHeightfieldDataSetBounds(IntPtr d, dReal minHeight, dReal maxHeight);
1015
1016 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldGetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1017 public static extern IntPtr GeomHeightfieldGetHeightfieldData(IntPtr g);
1018
1019 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldSetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1020 public static extern void GeomHeightfieldSetHeightfieldData(IntPtr g, IntPtr d);
1021
1022
1023 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataBuild"), SuppressUnmanagedCodeSecurity]
1024 public static extern void GeomOSTerrainDataBuild(IntPtr d, float[] pHeightData, int bCopyHeightData,
1025 dReal sampleSize, int widthSamples, int depthSamples,
1026 dReal offset, dReal thickness, int bWrap);
1027
1028 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataBuild"), SuppressUnmanagedCodeSecurity]
1029 public static extern void GeomOSTerrainDataBuild(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
1030 dReal sampleSize, int widthSamples, int depthSamples,
1031 dReal thickness, int bWrap);
1032
1033 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataCreate"), SuppressUnmanagedCodeSecurity]
1034 public static extern IntPtr GeomOSTerrainDataCreate();
1035
1036 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataDestroy"), SuppressUnmanagedCodeSecurity]
1037 public static extern void GeomOSTerrainDataDestroy(IntPtr d);
1038
1039 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataSetBounds"), SuppressUnmanagedCodeSecurity]
1040 public static extern void GeomOSTerrainDataSetBounds(IntPtr d, dReal minHeight, dReal maxHeight);
1041
1042 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainGetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1043 public static extern IntPtr GeomOSTerrainGetHeightfieldData(IntPtr g);
1044
1045 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainSetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1046 public static extern void GeomOSTerrainSetHeightfieldData(IntPtr g, IntPtr d);
1047
1048
1049 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsEnabled"), SuppressUnmanagedCodeSecurity]
1050 public static extern bool GeomIsEnabled(IntPtr geom);
1051
1052 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsOffset"), SuppressUnmanagedCodeSecurity]
1053 public static extern bool GeomIsOffset(IntPtr geom);
1054
1055 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsSpace"), SuppressUnmanagedCodeSecurity]
1056 public static extern bool GeomIsSpace(IntPtr geom);
1057
1058 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlaneGetParams"), SuppressUnmanagedCodeSecurity]
1059 public static extern void GeomPlaneGetParams(IntPtr geom, ref Vector4 result);
1060
1061 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlaneGetParams"), SuppressUnmanagedCodeSecurity]
1062 public static extern void GeomPlaneGetParams(IntPtr geom, ref dReal A);
1063
1064 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlanePointDepth"), SuppressUnmanagedCodeSecurity]
1065 public static extern dReal GeomPlanePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
1066
1067 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlaneSetParams"), SuppressUnmanagedCodeSecurity]
1068 public static extern void GeomPlaneSetParams(IntPtr plane, dReal a, dReal b, dReal c, dReal d);
1069
1070 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGet"), SuppressUnmanagedCodeSecurity]
1071 public static extern void GeomRayGet(IntPtr ray, ref Vector3 start, ref Vector3 dir);
1072
1073 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGet"), SuppressUnmanagedCodeSecurity]
1074 public static extern void GeomRayGet(IntPtr ray, ref dReal startX, ref dReal dirX);
1075
1076 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGetClosestHit"), SuppressUnmanagedCodeSecurity]
1077 public static extern int GeomRayGetClosestHit(IntPtr ray);
1078
1079 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGetLength"), SuppressUnmanagedCodeSecurity]
1080 public static extern dReal GeomRayGetLength(IntPtr ray);
1081
1082 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGetParams"), SuppressUnmanagedCodeSecurity]
1083 public static extern dReal GeomRayGetParams(IntPtr g, out int firstContact, out int backfaceCull);
1084
1085 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySet"), SuppressUnmanagedCodeSecurity]
1086 public static extern void GeomRaySet(IntPtr ray, dReal px, dReal py, dReal pz, dReal dx, dReal dy, dReal dz);
1087
1088 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySetClosestHit"), SuppressUnmanagedCodeSecurity]
1089 public static extern void GeomRaySetClosestHit(IntPtr ray, int closestHit);
1090
1091 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySetLength"), SuppressUnmanagedCodeSecurity]
1092 public static extern void GeomRaySetLength(IntPtr ray, dReal length);
1093
1094 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySetParams"), SuppressUnmanagedCodeSecurity]
1095 public static extern void GeomRaySetParams(IntPtr ray, int firstContact, int backfaceCull);
1096
1097 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetBody"), SuppressUnmanagedCodeSecurity]
1098 public static extern void GeomSetBody(IntPtr geom, IntPtr body);
1099
1100 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetCategoryBits"), SuppressUnmanagedCodeSecurity]
1101 public static extern void GeomSetCategoryBits(IntPtr geom, uint bits);
1102
1103 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetCollideBits"), SuppressUnmanagedCodeSecurity]
1104 public static extern void GeomSetCollideBits(IntPtr geom, uint bits);
1105
1106 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetConvex"), SuppressUnmanagedCodeSecurity]
1107 public static extern IntPtr GeomSetConvex(IntPtr geom, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
1108
1109 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetData"), SuppressUnmanagedCodeSecurity]
1110 public static extern void GeomSetData(IntPtr geom, IntPtr data);
1111
1112 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetPosition"), SuppressUnmanagedCodeSecurity]
1113 public static extern void GeomSetOffsetPosition(IntPtr geom, dReal x, dReal y, dReal z);
1114
1115 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
1116 public static extern void GeomSetOffsetQuaternion(IntPtr geom, ref Quaternion Q);
1117
1118 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
1119 public static extern void GeomSetOffsetQuaternion(IntPtr geom, ref dReal X);
1120
1121 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetRotation"), SuppressUnmanagedCodeSecurity]
1122 public static extern void GeomSetOffsetRotation(IntPtr geom, ref Matrix3 R);
1123
1124 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetRotation"), SuppressUnmanagedCodeSecurity]
1125 public static extern void GeomSetOffsetRotation(IntPtr geom, ref dReal M00);
1126
1127 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldPosition"), SuppressUnmanagedCodeSecurity]
1128 public static extern void GeomSetOffsetWorldPosition(IntPtr geom, dReal x, dReal y, dReal z);
1129
1130 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldQuaternion"), SuppressUnmanagedCodeSecurity]
1131 public static extern void GeomSetOffsetWorldQuaternion(IntPtr geom, ref Quaternion Q);
1132
1133 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldQuaternion"), SuppressUnmanagedCodeSecurity]
1134 public static extern void GeomSetOffsetWorldQuaternion(IntPtr geom, ref dReal X);
1135
1136 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldRotation"), SuppressUnmanagedCodeSecurity]
1137 public static extern void GeomSetOffsetWorldRotation(IntPtr geom, ref Matrix3 R);
1138
1139 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldRotation"), SuppressUnmanagedCodeSecurity]
1140 public static extern void GeomSetOffsetWorldRotation(IntPtr geom, ref dReal M00);
1141
1142 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetPosition"), SuppressUnmanagedCodeSecurity]
1143 public static extern void GeomSetPosition(IntPtr geom, dReal x, dReal y, dReal z);
1144
1145 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetQuaternion"), SuppressUnmanagedCodeSecurity]
1146 public static extern void GeomSetQuaternion(IntPtr geom, ref Quaternion quat);
1147
1148 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetQuaternion"), SuppressUnmanagedCodeSecurity]
1149 public static extern void GeomSetQuaternion(IntPtr geom, ref dReal w);
1150
1151 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetRotation"), SuppressUnmanagedCodeSecurity]
1152 public static extern void GeomSetRotation(IntPtr geom, ref Matrix3 R);
1153
1154 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetRotation"), SuppressUnmanagedCodeSecurity]
1155 public static extern void GeomSetRotation(IntPtr geom, ref dReal M00);
1156
1157 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSphereGetRadius"), SuppressUnmanagedCodeSecurity]
1158 public static extern dReal GeomSphereGetRadius(IntPtr geom);
1159
1160 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSpherePointDepth"), SuppressUnmanagedCodeSecurity]
1161 public static extern dReal GeomSpherePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
1162
1163 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSphereSetRadius"), SuppressUnmanagedCodeSecurity]
1164 public static extern void GeomSphereSetRadius(IntPtr geom, dReal radius);
1165
1166 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformGetCleanup"), SuppressUnmanagedCodeSecurity]
1167 public static extern int GeomTransformGetCleanup(IntPtr geom);
1168
1169 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformGetGeom"), SuppressUnmanagedCodeSecurity]
1170 public static extern IntPtr GeomTransformGetGeom(IntPtr geom);
1171
1172 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformGetInfo"), SuppressUnmanagedCodeSecurity]
1173 public static extern int GeomTransformGetInfo(IntPtr geom);
1174
1175 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformSetCleanup"), SuppressUnmanagedCodeSecurity]
1176 public static extern void GeomTransformSetCleanup(IntPtr geom, int mode);
1177
1178 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformSetGeom"), SuppressUnmanagedCodeSecurity]
1179 public static extern void GeomTransformSetGeom(IntPtr geom, IntPtr obj);
1180
1181 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformSetInfo"), SuppressUnmanagedCodeSecurity]
1182 public static extern void GeomTransformSetInfo(IntPtr geom, int info);
1183
1184 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble"), SuppressUnmanagedCodeSecurity]
1185 public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
1186 double[] vertices, int vertexStride, int vertexCount,
1187 int[] indices, int indexCount, int triStride);
1188
1189 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble"), SuppressUnmanagedCodeSecurity]
1190 public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
1191 IntPtr vertices, int vertexStride, int vertexCount,
1192 IntPtr indices, int indexCount, int triStride);
1193
1194 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble1"), SuppressUnmanagedCodeSecurity]
1195 public static extern void GeomTriMeshDataBuildDouble1(IntPtr d,
1196 double[] vertices, int vertexStride, int vertexCount,
1197 int[] indices, int indexCount, int triStride,
1198 double[] normals);
1199
1200 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble1"), SuppressUnmanagedCodeSecurity]
1201 public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
1202 IntPtr vertices, int vertexStride, int vertexCount,
1203 IntPtr indices, int indexCount, int triStride,
1204 IntPtr normals);
1205
1206 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple"), SuppressUnmanagedCodeSecurity]
1207 public static extern void GeomTriMeshDataBuildSingle(IntPtr d,
1208 dReal[] vertices, int vertexStride, int vertexCount,
1209 int[] indices, int indexCount, int triStride);
1210
1211 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple"), SuppressUnmanagedCodeSecurity]
1212 public static extern void GeomTriMeshDataBuildSingle(IntPtr d,
1213 IntPtr vertices, int vertexStride, int vertexCount,
1214 IntPtr indices, int indexCount, int triStride);
1215
1216 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple1"), SuppressUnmanagedCodeSecurity]
1217 public static extern void GeomTriMeshDataBuildSingle1(IntPtr d,
1218 dReal[] vertices, int vertexStride, int vertexCount,
1219 int[] indices, int indexCount, int triStride,
1220 dReal[] normals);
1221
1222 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple1"), SuppressUnmanagedCodeSecurity]
1223 public static extern void GeomTriMeshDataBuildSingle1(IntPtr d,
1224 IntPtr vertices, int vertexStride, int vertexCount,
1225 IntPtr indices, int indexCount, int triStride,
1226 IntPtr normals);
1227
1228 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle"), SuppressUnmanagedCodeSecurity]
1229 public static extern void GeomTriMeshDataBuildSimple(IntPtr d,
1230 float[] vertices, int vertexStride, int vertexCount,
1231 int[] indices, int indexCount, int triStride);
1232
1233 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle"), SuppressUnmanagedCodeSecurity]
1234 public static extern void GeomTriMeshDataBuildSimple(IntPtr d,
1235 IntPtr vertices, int vertexStride, int vertexCount,
1236 IntPtr indices, int indexCount, int triStride);
1237
1238 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle1"), SuppressUnmanagedCodeSecurity]
1239 public static extern void GeomTriMeshDataBuildSimple1(IntPtr d,
1240 float[] vertices, int vertexStride, int vertexCount,
1241 int[] indices, int indexCount, int triStride,
1242 float[] normals);
1243
1244 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle1"), SuppressUnmanagedCodeSecurity]
1245 public static extern void GeomTriMeshDataBuildSimple1(IntPtr d,
1246 IntPtr vertices, int vertexStride, int vertexCount,
1247 IntPtr indices, int indexCount, int triStride,
1248 IntPtr normals);
1249
1250 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshClearTCCache"), SuppressUnmanagedCodeSecurity]
1251 public static extern void GeomTriMeshClearTCCache(IntPtr g);
1252
1253 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataCreate"), SuppressUnmanagedCodeSecurity]
1254 public static extern IntPtr GeomTriMeshDataCreate();
1255
1256 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataDestroy"), SuppressUnmanagedCodeSecurity]
1257 public static extern void GeomTriMeshDataDestroy(IntPtr d);
1258
1259 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataGet"), SuppressUnmanagedCodeSecurity]
1260 public static extern IntPtr GeomTriMeshDataGet(IntPtr d, int data_id);
1261
1262 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataPreprocess"), SuppressUnmanagedCodeSecurity]
1263 public static extern void GeomTriMeshDataPreprocess(IntPtr d);
1264
1265 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataSet"), SuppressUnmanagedCodeSecurity]
1266 public static extern void GeomTriMeshDataSet(IntPtr d, int data_id, IntPtr in_data);
1267
1268 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataUpdate"), SuppressUnmanagedCodeSecurity]
1269 public static extern void GeomTriMeshDataUpdate(IntPtr d);
1270
1271 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshEnableTC"), SuppressUnmanagedCodeSecurity]
1272 public static extern void GeomTriMeshEnableTC(IntPtr g, int geomClass, bool enable);
1273
1274 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetArrayCallback"), SuppressUnmanagedCodeSecurity]
1275 public static extern TriArrayCallback GeomTriMeshGetArrayCallback(IntPtr g);
1276
1277 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetCallback"), SuppressUnmanagedCodeSecurity]
1278 public static extern TriCallback GeomTriMeshGetCallback(IntPtr g);
1279
1280 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetData"), SuppressUnmanagedCodeSecurity]
1281 public static extern IntPtr GeomTriMeshGetData(IntPtr g);
1282
1283 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetLastTransform"), SuppressUnmanagedCodeSecurity]
1284 public extern unsafe static Matrix4* GeomTriMeshGetLastTransformUnsafe(IntPtr geom);
1285 public static Matrix4 GeomTriMeshGetLastTransform(IntPtr geom)
1286 {
1287 unsafe { return *(GeomTriMeshGetLastTransformUnsafe(geom)); }
1288 }
1289
1290 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetPoint"), SuppressUnmanagedCodeSecurity]
1291 public extern static void GeomTriMeshGetPoint(IntPtr g, int index, dReal u, dReal v, ref Vector3 outVec);
1292
1293 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetRayCallback"), SuppressUnmanagedCodeSecurity]
1294 public static extern TriRayCallback GeomTriMeshGetRayCallback(IntPtr g);
1295
1296 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetTriangle"), SuppressUnmanagedCodeSecurity]
1297 public extern static void GeomTriMeshGetTriangle(IntPtr g, int index, ref Vector3 v0, ref Vector3 v1, ref Vector3 v2);
1298
1299 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetTriangleCount"), SuppressUnmanagedCodeSecurity]
1300 public extern static int GeomTriMeshGetTriangleCount(IntPtr g);
1301
1302 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetTriMeshDataID"), SuppressUnmanagedCodeSecurity]
1303 public static extern IntPtr GeomTriMeshGetTriMeshDataID(IntPtr g);
1304
1305 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshIsTCEnabled"), SuppressUnmanagedCodeSecurity]
1306 public static extern bool GeomTriMeshIsTCEnabled(IntPtr g, int geomClass);
1307
1308 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetArrayCallback"), SuppressUnmanagedCodeSecurity]
1309 public static extern void GeomTriMeshSetArrayCallback(IntPtr g, TriArrayCallback arrayCallback);
1310
1311 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetCallback"), SuppressUnmanagedCodeSecurity]
1312 public static extern void GeomTriMeshSetCallback(IntPtr g, TriCallback callback);
1313
1314 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetData"), SuppressUnmanagedCodeSecurity]
1315 public static extern void GeomTriMeshSetData(IntPtr g, IntPtr data);
1316
1317 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetLastTransform"), SuppressUnmanagedCodeSecurity]
1318 public static extern void GeomTriMeshSetLastTransform(IntPtr g, ref Matrix4 last_trans);
1319
1320 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetLastTransform"), SuppressUnmanagedCodeSecurity]
1321 public static extern void GeomTriMeshSetLastTransform(IntPtr g, ref dReal M00);
1322
1323 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetRayCallback"), SuppressUnmanagedCodeSecurity]
1324 public static extern void GeomTriMeshSetRayCallback(IntPtr g, TriRayCallback callback);
1325
1326 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGetConfiguration"), SuppressUnmanagedCodeSecurity]
1327 public static extern IntPtr iGetConfiguration();
1328
1329 public static string GetConfiguration()
1330 {
1331 IntPtr ptr = iGetConfiguration();
1332 string s = Marshal.PtrToStringAnsi(ptr);
1333 return s;
1334 }
1335
1336 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dHashSpaceCreate"), SuppressUnmanagedCodeSecurity]
1337 public static extern IntPtr HashSpaceCreate(IntPtr space);
1338
1339 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dHashSpaceGetLevels"), SuppressUnmanagedCodeSecurity]
1340 public static extern void HashSpaceGetLevels(IntPtr space, out int minlevel, out int maxlevel);
1341
1342 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dHashSpaceSetLevels"), SuppressUnmanagedCodeSecurity]
1343 public static extern void HashSpaceSetLevels(IntPtr space, int minlevel, int maxlevel);
1344
1345 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInfiniteAABB"), SuppressUnmanagedCodeSecurity]
1346 public static extern void InfiniteAABB(IntPtr geom, out AABB aabb);
1347
1348 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInitODE"), SuppressUnmanagedCodeSecurity]
1349 public static extern void InitODE();
1350
1351 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInitODE2"), SuppressUnmanagedCodeSecurity]
1352 public static extern int InitODE2(uint ODEInitFlags);
1353
1354 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dIsPositiveDefinite"), SuppressUnmanagedCodeSecurity]
1355 public static extern int IsPositiveDefinite(ref dReal A, int n);
1356
1357 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInvertPDMatrix"), SuppressUnmanagedCodeSecurity]
1358 public static extern int InvertPDMatrix(ref dReal A, out dReal Ainv, int n);
1359
1360 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddAMotorTorques"), SuppressUnmanagedCodeSecurity]
1361 public static extern void JointAddAMotorTorques(IntPtr joint, dReal torque1, dReal torque2, dReal torque3);
1362
1363 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddHingeTorque"), SuppressUnmanagedCodeSecurity]
1364 public static extern void JointAddHingeTorque(IntPtr joint, dReal torque);
1365
1366 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddHinge2Torque"), SuppressUnmanagedCodeSecurity]
1367 public static extern void JointAddHinge2Torques(IntPtr joint, dReal torque1, dReal torque2);
1368
1369 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddPRTorque"), SuppressUnmanagedCodeSecurity]
1370 public static extern void JointAddPRTorque(IntPtr joint, dReal torque);
1371
1372 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddUniversalTorque"), SuppressUnmanagedCodeSecurity]
1373 public static extern void JointAddUniversalTorques(IntPtr joint, dReal torque1, dReal torque2);
1374
1375 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddSliderForce"), SuppressUnmanagedCodeSecurity]
1376 public static extern void JointAddSliderForce(IntPtr joint, dReal force);
1377
1378 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAttach"), SuppressUnmanagedCodeSecurity]
1379 public static extern void JointAttach(IntPtr joint, IntPtr body1, IntPtr body2);
1380
1381 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateAMotor"), SuppressUnmanagedCodeSecurity]
1382 public static extern IntPtr JointCreateAMotor(IntPtr world, IntPtr group);
1383
1384 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateBall"), SuppressUnmanagedCodeSecurity]
1385 public static extern IntPtr JointCreateBall(IntPtr world, IntPtr group);
1386
1387 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateContact"), SuppressUnmanagedCodeSecurity]
1388 public static extern IntPtr JointCreateContact(IntPtr world, IntPtr group, ref Contact contact);
1389 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateContact"), SuppressUnmanagedCodeSecurity]
1390 public static extern IntPtr JointCreateContactPtr(IntPtr world, IntPtr group, IntPtr contact);
1391
1392 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateFixed"), SuppressUnmanagedCodeSecurity]
1393 public static extern IntPtr JointCreateFixed(IntPtr world, IntPtr group);
1394
1395 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateHinge"), SuppressUnmanagedCodeSecurity]
1396 public static extern IntPtr JointCreateHinge(IntPtr world, IntPtr group);
1397
1398 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateHinge2"), SuppressUnmanagedCodeSecurity]
1399 public static extern IntPtr JointCreateHinge2(IntPtr world, IntPtr group);
1400
1401 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateLMotor"), SuppressUnmanagedCodeSecurity]
1402 public static extern IntPtr JointCreateLMotor(IntPtr world, IntPtr group);
1403
1404 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateNull"), SuppressUnmanagedCodeSecurity]
1405 public static extern IntPtr JointCreateNull(IntPtr world, IntPtr group);
1406
1407 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreatePR"), SuppressUnmanagedCodeSecurity]
1408 public static extern IntPtr JointCreatePR(IntPtr world, IntPtr group);
1409
1410 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreatePlane2D"), SuppressUnmanagedCodeSecurity]
1411 public static extern IntPtr JointCreatePlane2D(IntPtr world, IntPtr group);
1412
1413 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateSlider"), SuppressUnmanagedCodeSecurity]
1414 public static extern IntPtr JointCreateSlider(IntPtr world, IntPtr group);
1415
1416 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateUniversal"), SuppressUnmanagedCodeSecurity]
1417 public static extern IntPtr JointCreateUniversal(IntPtr world, IntPtr group);
1418
1419 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointDestroy"), SuppressUnmanagedCodeSecurity]
1420 public static extern void JointDestroy(IntPtr j);
1421
1422 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAngle"), SuppressUnmanagedCodeSecurity]
1423 public static extern dReal JointGetAMotorAngle(IntPtr j, int anum);
1424
1425 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAngleRate"), SuppressUnmanagedCodeSecurity]
1426 public static extern dReal JointGetAMotorAngleRate(IntPtr j, int anum);
1427
1428 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAxis"), SuppressUnmanagedCodeSecurity]
1429 public static extern void JointGetAMotorAxis(IntPtr j, int anum, out Vector3 result);
1430
1431 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAxisRel"), SuppressUnmanagedCodeSecurity]
1432 public static extern int JointGetAMotorAxisRel(IntPtr j, int anum);
1433
1434 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorMode"), SuppressUnmanagedCodeSecurity]
1435 public static extern int JointGetAMotorMode(IntPtr j);
1436
1437 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1438 public static extern int JointGetAMotorNumAxes(IntPtr j);
1439
1440 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorParam"), SuppressUnmanagedCodeSecurity]
1441 public static extern dReal JointGetAMotorParam(IntPtr j, int parameter);
1442
1443 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetBallAnchor"), SuppressUnmanagedCodeSecurity]
1444 public static extern void JointGetBallAnchor(IntPtr j, out Vector3 result);
1445
1446 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetBallAnchor2"), SuppressUnmanagedCodeSecurity]
1447 public static extern void JointGetBallAnchor2(IntPtr j, out Vector3 result);
1448
1449 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetBody"), SuppressUnmanagedCodeSecurity]
1450 public static extern IntPtr JointGetBody(IntPtr j);
1451
1452 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetData"), SuppressUnmanagedCodeSecurity]
1453 public static extern IntPtr JointGetData(IntPtr j);
1454
1455 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetFeedback"), SuppressUnmanagedCodeSecurity]
1456 public extern unsafe static JointFeedback* JointGetFeedbackUnsafe(IntPtr j);
1457 public static JointFeedback JointGetFeedback(IntPtr j)
1458 {
1459 unsafe { return *(JointGetFeedbackUnsafe(j)); }
1460 }
1461
1462 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAnchor"), SuppressUnmanagedCodeSecurity]
1463 public static extern void JointGetHingeAnchor(IntPtr j, out Vector3 result);
1464
1465 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAngle"), SuppressUnmanagedCodeSecurity]
1466 public static extern dReal JointGetHingeAngle(IntPtr j);
1467
1468 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAngleRate"), SuppressUnmanagedCodeSecurity]
1469 public static extern dReal JointGetHingeAngleRate(IntPtr j);
1470
1471 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAxis"), SuppressUnmanagedCodeSecurity]
1472 public static extern void JointGetHingeAxis(IntPtr j, out Vector3 result);
1473
1474 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeParam"), SuppressUnmanagedCodeSecurity]
1475 public static extern dReal JointGetHingeParam(IntPtr j, int parameter);
1476
1477 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Angle1"), SuppressUnmanagedCodeSecurity]
1478 public static extern dReal JointGetHinge2Angle1(IntPtr j);
1479
1480 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Angle1Rate"), SuppressUnmanagedCodeSecurity]
1481 public static extern dReal JointGetHinge2Angle1Rate(IntPtr j);
1482
1483 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Angle2Rate"), SuppressUnmanagedCodeSecurity]
1484 public static extern dReal JointGetHinge2Angle2Rate(IntPtr j);
1485
1486 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAnchor2"), SuppressUnmanagedCodeSecurity]
1487 public static extern void JointGetHingeAnchor2(IntPtr j, out Vector3 result);
1488
1489 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Anchor"), SuppressUnmanagedCodeSecurity]
1490 public static extern void JointGetHinge2Anchor(IntPtr j, out Vector3 result);
1491
1492 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Anchor2"), SuppressUnmanagedCodeSecurity]
1493 public static extern void JointGetHinge2Anchor2(IntPtr j, out Vector3 result);
1494
1495 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Axis1"), SuppressUnmanagedCodeSecurity]
1496 public static extern void JointGetHinge2Axis1(IntPtr j, out Vector3 result);
1497
1498 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Axis2"), SuppressUnmanagedCodeSecurity]
1499 public static extern void JointGetHinge2Axis2(IntPtr j, out Vector3 result);
1500
1501 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Param"), SuppressUnmanagedCodeSecurity]
1502 public static extern dReal JointGetHinge2Param(IntPtr j, int parameter);
1503
1504 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetLMotorAxis"), SuppressUnmanagedCodeSecurity]
1505 public static extern void JointGetLMotorAxis(IntPtr j, int anum, out Vector3 result);
1506
1507 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetLMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1508 public static extern int JointGetLMotorNumAxes(IntPtr j);
1509
1510 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetLMotorParam"), SuppressUnmanagedCodeSecurity]
1511 public static extern dReal JointGetLMotorParam(IntPtr j, int parameter);
1512
1513 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRAnchor"), SuppressUnmanagedCodeSecurity]
1514 public static extern void JointGetPRAnchor(IntPtr j, out Vector3 result);
1515
1516 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRAxis1"), SuppressUnmanagedCodeSecurity]
1517 public static extern void JointGetPRAxis1(IntPtr j, out Vector3 result);
1518
1519 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRAxis2"), SuppressUnmanagedCodeSecurity]
1520 public static extern void JointGetPRAxis2(IntPtr j, out Vector3 result);
1521
1522 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRParam"), SuppressUnmanagedCodeSecurity]
1523 public static extern dReal JointGetPRParam(IntPtr j, int parameter);
1524
1525 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRPosition"), SuppressUnmanagedCodeSecurity]
1526 public static extern dReal JointGetPRPosition(IntPtr j);
1527
1528 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRPositionRate"), SuppressUnmanagedCodeSecurity]
1529 public static extern dReal JointGetPRPositionRate(IntPtr j);
1530
1531 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderAxis"), SuppressUnmanagedCodeSecurity]
1532 public static extern void JointGetSliderAxis(IntPtr j, out Vector3 result);
1533
1534 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderParam"), SuppressUnmanagedCodeSecurity]
1535 public static extern dReal JointGetSliderParam(IntPtr j, int parameter);
1536
1537 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderPosition"), SuppressUnmanagedCodeSecurity]
1538 public static extern dReal JointGetSliderPosition(IntPtr j);
1539
1540 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderPositionRate"), SuppressUnmanagedCodeSecurity]
1541 public static extern dReal JointGetSliderPositionRate(IntPtr j);
1542
1543 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetType"), SuppressUnmanagedCodeSecurity]
1544 public static extern JointType JointGetType(IntPtr j);
1545
1546 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAnchor"), SuppressUnmanagedCodeSecurity]
1547 public static extern void JointGetUniversalAnchor(IntPtr j, out Vector3 result);
1548
1549 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAnchor2"), SuppressUnmanagedCodeSecurity]
1550 public static extern void JointGetUniversalAnchor2(IntPtr j, out Vector3 result);
1551
1552 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle1"), SuppressUnmanagedCodeSecurity]
1553 public static extern dReal JointGetUniversalAngle1(IntPtr j);
1554
1555 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle1Rate"), SuppressUnmanagedCodeSecurity]
1556 public static extern dReal JointGetUniversalAngle1Rate(IntPtr j);
1557
1558 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle2"), SuppressUnmanagedCodeSecurity]
1559 public static extern dReal JointGetUniversalAngle2(IntPtr j);
1560
1561 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle2Rate"), SuppressUnmanagedCodeSecurity]
1562 public static extern dReal JointGetUniversalAngle2Rate(IntPtr j);
1563
1564 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngles"), SuppressUnmanagedCodeSecurity]
1565 public static extern void JointGetUniversalAngles(IntPtr j, out dReal angle1, out dReal angle2);
1566
1567 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAxis1"), SuppressUnmanagedCodeSecurity]
1568 public static extern void JointGetUniversalAxis1(IntPtr j, out Vector3 result);
1569
1570 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAxis2"), SuppressUnmanagedCodeSecurity]
1571 public static extern void JointGetUniversalAxis2(IntPtr j, out Vector3 result);
1572
1573 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalParam"), SuppressUnmanagedCodeSecurity]
1574 public static extern dReal JointGetUniversalParam(IntPtr j, int parameter);
1575
1576 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGroupCreate"), SuppressUnmanagedCodeSecurity]
1577 public static extern IntPtr JointGroupCreate(int max_size);
1578
1579 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGroupDestroy"), SuppressUnmanagedCodeSecurity]
1580 public static extern void JointGroupDestroy(IntPtr group);
1581
1582 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGroupEmpty"), SuppressUnmanagedCodeSecurity]
1583 public static extern void JointGroupEmpty(IntPtr group);
1584
1585 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorAngle"), SuppressUnmanagedCodeSecurity]
1586 public static extern void JointSetAMotorAngle(IntPtr j, int anum, dReal angle);
1587
1588 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorAxis"), SuppressUnmanagedCodeSecurity]
1589 public static extern void JointSetAMotorAxis(IntPtr j, int anum, int rel, dReal x, dReal y, dReal z);
1590
1591 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorMode"), SuppressUnmanagedCodeSecurity]
1592 public static extern void JointSetAMotorMode(IntPtr j, int mode);
1593
1594 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1595 public static extern void JointSetAMotorNumAxes(IntPtr group, int num);
1596
1597 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorParam"), SuppressUnmanagedCodeSecurity]
1598 public static extern void JointSetAMotorParam(IntPtr group, int parameter, dReal value);
1599
1600 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetBallAnchor"), SuppressUnmanagedCodeSecurity]
1601 public static extern void JointSetBallAnchor(IntPtr j, dReal x, dReal y, dReal z);
1602
1603 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetBallAnchor2"), SuppressUnmanagedCodeSecurity]
1604 public static extern void JointSetBallAnchor2(IntPtr j, dReal x, dReal y, dReal z);
1605
1606 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetData"), SuppressUnmanagedCodeSecurity]
1607 public static extern void JointSetData(IntPtr j, IntPtr data);
1608
1609 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetFeedback"), SuppressUnmanagedCodeSecurity]
1610 public static extern void JointSetFeedback(IntPtr j, out JointFeedback feedback);
1611
1612 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetFixed"), SuppressUnmanagedCodeSecurity]
1613 public static extern void JointSetFixed(IntPtr j);
1614
1615 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeAnchor"), SuppressUnmanagedCodeSecurity]
1616 public static extern void JointSetHingeAnchor(IntPtr j, dReal x, dReal y, dReal z);
1617
1618 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeAnchorDelta"), SuppressUnmanagedCodeSecurity]
1619 public static extern void JointSetHingeAnchorDelta(IntPtr j, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
1620
1621 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeAxis"), SuppressUnmanagedCodeSecurity]
1622 public static extern void JointSetHingeAxis(IntPtr j, dReal x, dReal y, dReal z);
1623
1624 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeParam"), SuppressUnmanagedCodeSecurity]
1625 public static extern void JointSetHingeParam(IntPtr j, int parameter, dReal value);
1626
1627 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Anchor"), SuppressUnmanagedCodeSecurity]
1628 public static extern void JointSetHinge2Anchor(IntPtr j, dReal x, dReal y, dReal z);
1629
1630 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Axis1"), SuppressUnmanagedCodeSecurity]
1631 public static extern void JointSetHinge2Axis1(IntPtr j, dReal x, dReal y, dReal z);
1632
1633 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Axis2"), SuppressUnmanagedCodeSecurity]
1634 public static extern void JointSetHinge2Axis2(IntPtr j, dReal x, dReal y, dReal z);
1635
1636 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Param"), SuppressUnmanagedCodeSecurity]
1637 public static extern void JointSetHinge2Param(IntPtr j, int parameter, dReal value);
1638
1639 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetLMotorAxis"), SuppressUnmanagedCodeSecurity]
1640 public static extern void JointSetLMotorAxis(IntPtr j, int anum, int rel, dReal x, dReal y, dReal z);
1641
1642 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetLMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1643 public static extern void JointSetLMotorNumAxes(IntPtr j, int num);
1644
1645 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetLMotorParam"), SuppressUnmanagedCodeSecurity]
1646 public static extern void JointSetLMotorParam(IntPtr j, int parameter, dReal value);
1647
1648 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPlane2DAngleParam"), SuppressUnmanagedCodeSecurity]
1649 public static extern void JointSetPlane2DAngleParam(IntPtr j, int parameter, dReal value);
1650
1651 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPlane2DXParam"), SuppressUnmanagedCodeSecurity]
1652 public static extern void JointSetPlane2DXParam(IntPtr j, int parameter, dReal value);
1653
1654 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPlane2DYParam"), SuppressUnmanagedCodeSecurity]
1655 public static extern void JointSetPlane2DYParam(IntPtr j, int parameter, dReal value);
1656
1657 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRAnchor"), SuppressUnmanagedCodeSecurity]
1658 public static extern void JointSetPRAnchor(IntPtr j, dReal x, dReal y, dReal z);
1659
1660 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRAxis1"), SuppressUnmanagedCodeSecurity]
1661 public static extern void JointSetPRAxis1(IntPtr j, dReal x, dReal y, dReal z);
1662
1663 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRAxis2"), SuppressUnmanagedCodeSecurity]
1664 public static extern void JointSetPRAxis2(IntPtr j, dReal x, dReal y, dReal z);
1665
1666 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRParam"), SuppressUnmanagedCodeSecurity]
1667 public static extern void JointSetPRParam(IntPtr j, int parameter, dReal value);
1668
1669 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetSliderAxis"), SuppressUnmanagedCodeSecurity]
1670 public static extern void JointSetSliderAxis(IntPtr j, dReal x, dReal y, dReal z);
1671
1672 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetSliderAxisDelta"), SuppressUnmanagedCodeSecurity]
1673 public static extern void JointSetSliderAxisDelta(IntPtr j, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
1674
1675 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetSliderParam"), SuppressUnmanagedCodeSecurity]
1676 public static extern void JointSetSliderParam(IntPtr j, int parameter, dReal value);
1677
1678 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalAnchor"), SuppressUnmanagedCodeSecurity]
1679 public static extern void JointSetUniversalAnchor(IntPtr j, dReal x, dReal y, dReal z);
1680
1681 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalAxis1"), SuppressUnmanagedCodeSecurity]
1682 public static extern void JointSetUniversalAxis1(IntPtr j, dReal x, dReal y, dReal z);
1683
1684 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalAxis2"), SuppressUnmanagedCodeSecurity]
1685 public static extern void JointSetUniversalAxis2(IntPtr j, dReal x, dReal y, dReal z);
1686
1687 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalParam"), SuppressUnmanagedCodeSecurity]
1688 public static extern void JointSetUniversalParam(IntPtr j, int parameter, dReal value);
1689
1690 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dLDLTAddTL"), SuppressUnmanagedCodeSecurity]
1691 public static extern void LDLTAddTL(ref dReal L, ref dReal d, ref dReal a, int n, int nskip);
1692
1693 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassAdd"), SuppressUnmanagedCodeSecurity]
1694 public static extern void MassAdd(ref Mass a, ref Mass b);
1695
1696 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassAdjust"), SuppressUnmanagedCodeSecurity]
1697 public static extern void MassAdjust(ref Mass m, dReal newmass);
1698
1699 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassCheck"), SuppressUnmanagedCodeSecurity]
1700 public static extern bool MassCheck(ref Mass m);
1701
1702 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassRotate"), SuppressUnmanagedCodeSecurity]
1703 public static extern void MassRotate(ref Mass mass, ref Matrix3 R);
1704
1705 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassRotate"), SuppressUnmanagedCodeSecurity]
1706 public static extern void MassRotate(ref Mass mass, ref dReal M00);
1707
1708 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetBox"), SuppressUnmanagedCodeSecurity]
1709 public static extern void MassSetBox(out Mass mass, dReal density, dReal lx, dReal ly, dReal lz);
1710
1711 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetBoxTotal"), SuppressUnmanagedCodeSecurity]
1712 public static extern void MassSetBoxTotal(out Mass mass, dReal total_mass, dReal lx, dReal ly, dReal lz);
1713
1714 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCapsule"), SuppressUnmanagedCodeSecurity]
1715 public static extern void MassSetCapsule(out Mass mass, dReal density, int direction, dReal radius, dReal length);
1716
1717 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCapsuleTotal"), SuppressUnmanagedCodeSecurity]
1718 public static extern void MassSetCapsuleTotal(out Mass mass, dReal total_mass, int direction, dReal radius, dReal length);
1719
1720 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCylinder"), SuppressUnmanagedCodeSecurity]
1721 public static extern void MassSetCylinder(out Mass mass, dReal density, int direction, dReal radius, dReal length);
1722
1723 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCylinderTotal"), SuppressUnmanagedCodeSecurity]
1724 public static extern void MassSetCylinderTotal(out Mass mass, dReal total_mass, int direction, dReal radius, dReal length);
1725
1726 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetParameters"), SuppressUnmanagedCodeSecurity]
1727 public static extern void MassSetParameters(out Mass mass, dReal themass,
1728 dReal cgx, dReal cgy, dReal cgz,
1729 dReal i11, dReal i22, dReal i33,
1730 dReal i12, dReal i13, dReal i23);
1731
1732 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetSphere"), SuppressUnmanagedCodeSecurity]
1733 public static extern void MassSetSphere(out Mass mass, dReal density, dReal radius);
1734
1735 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetSphereTotal"), SuppressUnmanagedCodeSecurity]
1736 public static extern void dMassSetSphereTotal(out Mass mass, dReal total_mass, dReal radius);
1737
1738 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetTrimesh"), SuppressUnmanagedCodeSecurity]
1739 public static extern void MassSetTrimesh(out Mass mass, dReal density, IntPtr g);
1740
1741 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetZero"), SuppressUnmanagedCodeSecurity]
1742 public static extern void MassSetZero(out Mass mass);
1743
1744 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassTranslate"), SuppressUnmanagedCodeSecurity]
1745 public static extern void MassTranslate(ref Mass mass, dReal x, dReal y, dReal z);
1746
1747 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply0"), SuppressUnmanagedCodeSecurity]
1748 public static extern void Multiply0(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
1749
1750 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply0"), SuppressUnmanagedCodeSecurity]
1751 private static extern void MultiplyiM3V3(out Vector3 vout, ref Matrix3 matrix, ref Vector3 vect,int p, int q, int r);
1752 public static void MultiplyM3V3(out Vector3 outvector, ref Matrix3 matrix, ref Vector3 invector)
1753 {
1754 MultiplyiM3V3(out outvector, ref matrix, ref invector, 3, 3, 1);
1755 }
1756
1757 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply1"), SuppressUnmanagedCodeSecurity]
1758 public static extern void Multiply1(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
1759
1760 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply2"), SuppressUnmanagedCodeSecurity]
1761 public static extern void Multiply2(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
1762
1763 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQFromAxisAndAngle"), SuppressUnmanagedCodeSecurity]
1764 public static extern void QFromAxisAndAngle(out Quaternion q, dReal ax, dReal ay, dReal az, dReal angle);
1765
1766 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQfromR"), SuppressUnmanagedCodeSecurity]
1767 public static extern void QfromR(out Quaternion q, ref Matrix3 R);
1768
1769 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply0"), SuppressUnmanagedCodeSecurity]
1770 public static extern void QMultiply0(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1771
1772 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply1"), SuppressUnmanagedCodeSecurity]
1773 public static extern void QMultiply1(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1774
1775 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply2"), SuppressUnmanagedCodeSecurity]
1776 public static extern void QMultiply2(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1777
1778 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply3"), SuppressUnmanagedCodeSecurity]
1779 public static extern void QMultiply3(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1780
1781 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQSetIdentity"), SuppressUnmanagedCodeSecurity]
1782 public static extern void QSetIdentity(out Quaternion q);
1783
1784 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQuadTreeSpaceCreate"), SuppressUnmanagedCodeSecurity]
1785 public static extern IntPtr QuadTreeSpaceCreate(IntPtr space, ref Vector3 center, ref Vector3 extents, int depth);
1786
1787 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQuadTreeSpaceCreate"), SuppressUnmanagedCodeSecurity]
1788 public static extern IntPtr QuadTreeSpaceCreate(IntPtr space, ref dReal centerX, ref dReal extentsX, int depth);
1789
1790 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRandReal"), SuppressUnmanagedCodeSecurity]
1791 public static extern dReal RandReal();
1792
1793 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFrom2Axes"), SuppressUnmanagedCodeSecurity]
1794 public static extern void RFrom2Axes(out Matrix3 R, dReal ax, dReal ay, dReal az, dReal bx, dReal by, dReal bz);
1795
1796 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFromAxisAndAngle"), SuppressUnmanagedCodeSecurity]
1797 public static extern void RFromAxisAndAngle(out Matrix3 R, dReal x, dReal y, dReal z, dReal angle);
1798
1799 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFromEulerAngles"), SuppressUnmanagedCodeSecurity]
1800 public static extern void RFromEulerAngles(out Matrix3 R, dReal phi, dReal theta, dReal psi);
1801
1802 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRfromQ"), SuppressUnmanagedCodeSecurity]
1803 public static extern void RfromQ(out Matrix3 R, ref Quaternion q);
1804
1805 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFromZAxis"), SuppressUnmanagedCodeSecurity]
1806 public static extern void RFromZAxis(out Matrix3 R, dReal ax, dReal ay, dReal az);
1807
1808 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRSetIdentity"), SuppressUnmanagedCodeSecurity]
1809 public static extern void RSetIdentity(out Matrix3 R);
1810
1811 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSetValue"), SuppressUnmanagedCodeSecurity]
1812 public static extern void SetValue(out dReal a, int n);
1813
1814 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSetZero"), SuppressUnmanagedCodeSecurity]
1815 public static extern void SetZero(out dReal a, int n);
1816
1817 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSimpleSpaceCreate"), SuppressUnmanagedCodeSecurity]
1818 public static extern IntPtr SimpleSpaceCreate(IntPtr space);
1819
1820 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveCholesky"), SuppressUnmanagedCodeSecurity]
1821 public static extern void SolveCholesky(ref dReal L, out dReal b, int n);
1822
1823 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveL1"), SuppressUnmanagedCodeSecurity]
1824 public static extern void SolveL1(ref dReal L, out dReal b, int n, int nskip);
1825
1826 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveL1T"), SuppressUnmanagedCodeSecurity]
1827 public static extern void SolveL1T(ref dReal L, out dReal b, int n, int nskip);
1828
1829 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveLDLT"), SuppressUnmanagedCodeSecurity]
1830 public static extern void SolveLDLT(ref dReal L, ref dReal d, out dReal b, int n, int nskip);
1831
1832 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceAdd"), SuppressUnmanagedCodeSecurity]
1833 public static extern void SpaceAdd(IntPtr space, IntPtr geom);
1834
1835 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceLockQuery"), SuppressUnmanagedCodeSecurity]
1836 public static extern bool SpaceLockQuery(IntPtr space);
1837
1838 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceClean"), SuppressUnmanagedCodeSecurity]
1839 public static extern void SpaceClean(IntPtr space);
1840
1841 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceCollide"), SuppressUnmanagedCodeSecurity]
1842 public static extern void SpaceCollide(IntPtr space, IntPtr data, NearCallback callback);
1843
1844 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceCollide2"), SuppressUnmanagedCodeSecurity]
1845 public static extern void SpaceCollide2(IntPtr space1, IntPtr space2, IntPtr data, NearCallback callback);
1846
1847 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceDestroy"), SuppressUnmanagedCodeSecurity]
1848 public static extern void SpaceDestroy(IntPtr space);
1849
1850 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetCleanup"), SuppressUnmanagedCodeSecurity]
1851 public static extern bool SpaceGetCleanup(IntPtr space);
1852
1853 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetNumGeoms"), SuppressUnmanagedCodeSecurity]
1854 public static extern int SpaceGetNumGeoms(IntPtr space);
1855
1856 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetGeom"), SuppressUnmanagedCodeSecurity]
1857 public static extern IntPtr SpaceGetGeom(IntPtr space, int i);
1858
1859 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetSublevel"), SuppressUnmanagedCodeSecurity]
1860 public static extern int SpaceGetSublevel(IntPtr space);
1861
1862 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceQuery"), SuppressUnmanagedCodeSecurity]
1863 public static extern bool SpaceQuery(IntPtr space, IntPtr geom);
1864
1865 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceRemove"), SuppressUnmanagedCodeSecurity]
1866 public static extern void SpaceRemove(IntPtr space, IntPtr geom);
1867
1868 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceSetCleanup"), SuppressUnmanagedCodeSecurity]
1869 public static extern void SpaceSetCleanup(IntPtr space, bool mode);
1870
1871 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceSetSublevel"), SuppressUnmanagedCodeSecurity]
1872 public static extern void SpaceSetSublevel(IntPtr space, int sublevel);
1873
1874 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSweepAndPruneSpaceCreate"), SuppressUnmanagedCodeSecurity]
1875 public static extern IntPtr SweepAndPruneSpaceCreate(IntPtr space, int AxisOrder);
1876
1877 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dVectorScale"), SuppressUnmanagedCodeSecurity]
1878 public static extern void VectorScale(out dReal a, ref dReal d, int n);
1879
1880 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldCreate"), SuppressUnmanagedCodeSecurity]
1881 public static extern IntPtr WorldCreate();
1882
1883 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldDestroy"), SuppressUnmanagedCodeSecurity]
1884 public static extern void WorldDestroy(IntPtr world);
1885
1886 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableAverageSamplesCount"), SuppressUnmanagedCodeSecurity]
1887 public static extern int WorldGetAutoDisableAverageSamplesCount(IntPtr world);
1888
1889 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
1890 public static extern dReal WorldGetAutoDisableAngularThreshold(IntPtr world);
1891
1892 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
1893 public static extern bool WorldGetAutoDisableFlag(IntPtr world);
1894
1895 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
1896 public static extern dReal WorldGetAutoDisableLinearThreshold(IntPtr world);
1897
1898 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
1899 public static extern int WorldGetAutoDisableSteps(IntPtr world);
1900
1901 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
1902 public static extern dReal WorldGetAutoDisableTime(IntPtr world);
1903
1904 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoEnableDepthSF1"), SuppressUnmanagedCodeSecurity]
1905 public static extern int WorldGetAutoEnableDepthSF1(IntPtr world);
1906
1907 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetCFM"), SuppressUnmanagedCodeSecurity]
1908 public static extern dReal WorldGetCFM(IntPtr world);
1909
1910 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetERP"), SuppressUnmanagedCodeSecurity]
1911 public static extern dReal WorldGetERP(IntPtr world);
1912
1913 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetGravity"), SuppressUnmanagedCodeSecurity]
1914 public static extern void WorldGetGravity(IntPtr world, out Vector3 gravity);
1915
1916 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetGravity"), SuppressUnmanagedCodeSecurity]
1917 public static extern void WorldGetGravity(IntPtr world, out dReal X);
1918
1919 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetContactMaxCorrectingVel"), SuppressUnmanagedCodeSecurity]
1920 public static extern dReal WorldGetContactMaxCorrectingVel(IntPtr world);
1921
1922 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetContactSurfaceLayer"), SuppressUnmanagedCodeSecurity]
1923 public static extern dReal WorldGetContactSurfaceLayer(IntPtr world);
1924
1925 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAngularDamping"), SuppressUnmanagedCodeSecurity]
1926 public static extern dReal WorldGetAngularDamping(IntPtr world);
1927
1928 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
1929 public static extern dReal WorldGetAngularDampingThreshold(IntPtr world);
1930
1931 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetLinearDamping"), SuppressUnmanagedCodeSecurity]
1932 public static extern dReal WorldGetLinearDamping(IntPtr world);
1933
1934 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
1935 public static extern dReal WorldGetLinearDampingThreshold(IntPtr world);
1936
1937 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetQuickStepNumIterations"), SuppressUnmanagedCodeSecurity]
1938 public static extern int WorldGetQuickStepNumIterations(IntPtr world);
1939
1940 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetQuickStepW"), SuppressUnmanagedCodeSecurity]
1941 public static extern dReal WorldGetQuickStepW(IntPtr world);
1942
1943 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetMaxAngularSpeed"), SuppressUnmanagedCodeSecurity]
1944 public static extern dReal WorldGetMaxAngularSpeed(IntPtr world);
1945
1946 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldImpulseToForce"), SuppressUnmanagedCodeSecurity]
1947 public static extern void WorldImpulseToForce(IntPtr world, dReal stepsize, dReal ix, dReal iy, dReal iz, out Vector3 force);
1948
1949 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldImpulseToForce"), SuppressUnmanagedCodeSecurity]
1950 public static extern void WorldImpulseToForce(IntPtr world, dReal stepsize, dReal ix, dReal iy, dReal iz, out dReal forceX);
1951
1952 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldQuickStep"), SuppressUnmanagedCodeSecurity]
1953 public static extern void WorldQuickStep(IntPtr world, dReal stepsize);
1954
1955 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAngularDamping"), SuppressUnmanagedCodeSecurity]
1956 public static extern void WorldSetAngularDamping(IntPtr world, dReal scale);
1957
1958 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
1959 public static extern void WorldSetAngularDampingThreshold(IntPtr world, dReal threshold);
1960
1961 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
1962 public static extern void WorldSetAutoDisableAngularThreshold(IntPtr world, dReal angular_threshold);
1963
1964 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableAverageSamplesCount"), SuppressUnmanagedCodeSecurity]
1965 public static extern void WorldSetAutoDisableAverageSamplesCount(IntPtr world, int average_samples_count);
1966
1967 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
1968 public static extern void WorldSetAutoDisableFlag(IntPtr world, bool do_auto_disable);
1969
1970 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
1971 public static extern void WorldSetAutoDisableLinearThreshold(IntPtr world, dReal linear_threshold);
1972
1973 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
1974 public static extern void WorldSetAutoDisableSteps(IntPtr world, int steps);
1975
1976 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
1977 public static extern void WorldSetAutoDisableTime(IntPtr world, dReal time);
1978
1979 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoEnableDepthSF1"), SuppressUnmanagedCodeSecurity]
1980 public static extern void WorldSetAutoEnableDepthSF1(IntPtr world, int autoEnableDepth);
1981
1982 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetCFM"), SuppressUnmanagedCodeSecurity]
1983 public static extern void WorldSetCFM(IntPtr world, dReal cfm);
1984
1985 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetContactMaxCorrectingVel"), SuppressUnmanagedCodeSecurity]
1986 public static extern void WorldSetContactMaxCorrectingVel(IntPtr world, dReal vel);
1987
1988 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetContactSurfaceLayer"), SuppressUnmanagedCodeSecurity]
1989 public static extern void WorldSetContactSurfaceLayer(IntPtr world, dReal depth);
1990
1991 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetDamping"), SuppressUnmanagedCodeSecurity]
1992 public static extern void WorldSetDamping(IntPtr world, dReal linear_scale, dReal angular_scale);
1993
1994 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetERP"), SuppressUnmanagedCodeSecurity]
1995 public static extern void WorldSetERP(IntPtr world, dReal erp);
1996
1997 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetGravity"), SuppressUnmanagedCodeSecurity]
1998 public static extern void WorldSetGravity(IntPtr world, dReal x, dReal y, dReal z);
1999
2000 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetLinearDamping"), SuppressUnmanagedCodeSecurity]
2001 public static extern void WorldSetLinearDamping(IntPtr world, dReal scale);
2002
2003 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
2004 public static extern void WorldSetLinearDampingThreshold(IntPtr world, dReal threshold);
2005
2006 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetQuickStepNumIterations"), SuppressUnmanagedCodeSecurity]
2007 public static extern void WorldSetQuickStepNumIterations(IntPtr world, int num);
2008
2009 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetQuickStepW"), SuppressUnmanagedCodeSecurity]
2010 public static extern void WorldSetQuickStepW(IntPtr world, dReal over_relaxation);
2011
2012 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetMaxAngularSpeed"), SuppressUnmanagedCodeSecurity]
2013 public static extern void WorldSetMaxAngularSpeed(IntPtr world, dReal max_speed);
2014
2015 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldStep"), SuppressUnmanagedCodeSecurity]
2016 public static extern void WorldStep(IntPtr world, dReal stepsize);
2017
2018 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldStepFast1"), SuppressUnmanagedCodeSecurity]
2019 public static extern void WorldStepFast1(IntPtr world, dReal stepsize, int maxiterations);
2020
2021 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldExportDIF"), SuppressUnmanagedCodeSecurity]
2022 public static extern void WorldExportDIF(IntPtr world, string filename, bool append, string prefix);
2023 }
2024}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs
new file mode 100644
index 0000000..55619c0
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs
@@ -0,0 +1,1978 @@
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
28
29// Revision by Ubit 2011/12
30
31using System;
32using System.Collections.Generic;
33using System.Reflection;
34using OpenMetaverse;
35using OdeAPI;
36using OpenSim.Framework;
37using OpenSim.Region.PhysicsModules.SharedBase;
38using log4net;
39
40namespace OpenSim.Region.PhysicsModule.ubOde
41{
42 /// <summary>
43 /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
44 /// </summary>
45
46 public enum dParam : int
47 {
48 LowStop = 0,
49 HiStop = 1,
50 Vel = 2,
51 FMax = 3,
52 FudgeFactor = 4,
53 Bounce = 5,
54 CFM = 6,
55 StopERP = 7,
56 StopCFM = 8,
57 LoStop2 = 256,
58 HiStop2 = 257,
59 Vel2 = 258,
60 FMax2 = 259,
61 StopERP2 = 7 + 256,
62 StopCFM2 = 8 + 256,
63 LoStop3 = 512,
64 HiStop3 = 513,
65 Vel3 = 514,
66 FMax3 = 515,
67 StopERP3 = 7 + 512,
68 StopCFM3 = 8 + 512
69 }
70
71 public class OdeCharacter : PhysicsActor
72 {
73 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
74
75 private Vector3 _position;
76 private Vector3 _zeroPosition;
77 private Vector3 _velocity;
78 private Vector3 _target_velocity;
79 private Vector3 _acceleration;
80 private Vector3 m_rotationalVelocity;
81 private Vector3 m_size;
82 private Vector3 m_collideNormal;
83 private Quaternion m_orientation;
84 private Quaternion m_orientation2D;
85 private float m_mass = 80f;
86 public float m_density = 60f;
87 private bool m_pidControllerActive = true;
88
89 const float basePID_D = 0.55f; // scaled for unit mass unit time (2200 /(50*80))
90 const float basePID_P = 0.225f; // scaled for unit mass unit time (900 /(50*80))
91 public float PID_D;
92 public float PID_P;
93
94 private float timeStep;
95 private float invtimeStep;
96
97 private float m_feetOffset = 0;
98 private float feetOff = 0;
99 private float boneOff = 0;
100 private float AvaAvaSizeXsq = 0.3f;
101 private float AvaAvaSizeYsq = 0.2f;
102
103 public float walkDivisor = 1.3f;
104 public float runDivisor = 0.8f;
105 private bool flying = false;
106 private bool m_iscolliding = false;
107 private bool m_iscollidingGround = false;
108 private bool m_iscollidingObj = false;
109 private bool m_alwaysRun = false;
110
111 private bool _zeroFlag = false;
112
113
114 private uint m_localID = 0;
115 public bool m_returnCollisions = false;
116 // taints and their non-tainted counterparts
117 public bool m_isPhysical = false; // the current physical status
118 public float MinimumGroundFlightOffset = 3f;
119
120 private float m_buoyancy = 0f;
121
122 private bool m_freemove = false;
123 // private CollisionLocker ode;
124
125// private string m_name = String.Empty;
126 // other filter control
127 int m_colliderfilter = 0;
128 int m_colliderGroundfilter = 0;
129 int m_colliderObjectfilter = 0;
130
131 // Default we're a Character
132 private CollisionCategories m_collisionCategories = (CollisionCategories.Character);
133
134 // Default, Collide with Other Geometries, spaces, bodies and characters.
135 private CollisionCategories m_collisionFlags = (CollisionCategories.Character
136 | CollisionCategories.Geom
137 | CollisionCategories.VolumeDtc
138 );
139 // we do land collisions not ode | CollisionCategories.Land);
140 public IntPtr Body = IntPtr.Zero;
141 private ODEScene _parent_scene;
142 private IntPtr capsule = IntPtr.Zero;
143 public IntPtr collider = IntPtr.Zero;
144
145 public IntPtr Amotor = IntPtr.Zero;
146
147 public d.Mass ShellMass;
148
149 public int m_eventsubscription = 0;
150 private int m_cureventsubscription = 0;
151 private CollisionEventUpdate CollisionEventsThisFrame = null;
152 private bool SentEmptyCollisionsEvent;
153
154 // unique UUID of this character object
155 public UUID m_uuid;
156 public bool bad = false;
157
158 float mu;
159
160 // HoverHeight control
161 private float m_PIDHoverHeight;
162 private float m_PIDHoverTau;
163 private bool m_useHoverPID;
164 private PIDHoverType m_PIDHoverType;
165 private float m_targetHoverHeight;
166
167
168 public OdeCharacter(uint localID, String avName, ODEScene parent_scene, Vector3 pos, Vector3 pSize, float pfeetOffset, float density, float walk_divisor, float rundivisor)
169 {
170 m_uuid = UUID.Random();
171 m_localID = localID;
172
173 timeStep = parent_scene.ODE_STEPSIZE;
174 invtimeStep = 1 / timeStep;
175
176 if (pos.IsFinite())
177 {
178 if (pos.Z > 99999f)
179 {
180 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
181 }
182 if (pos.Z < -100f) // shouldn't this be 0 ?
183 {
184 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
185 }
186 _position = pos;
187 }
188 else
189 {
190 _position = new Vector3(((float)_parent_scene.WorldExtents.X * 0.5f), ((float)_parent_scene.WorldExtents.Y * 0.5f), parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f);
191 m_log.Warn("[PHYSICS]: Got NaN Position on Character Create");
192 }
193
194 _parent_scene = parent_scene;
195
196
197 m_size.X = pSize.X;
198 m_size.Y = pSize.Y;
199 m_size.Z = pSize.Z;
200
201 if(m_size.X <0.01f)
202 m_size.X = 0.01f;
203 if(m_size.Y <0.01f)
204 m_size.Y = 0.01f;
205 if(m_size.Z <0.01f)
206 m_size.Z = 0.01f;
207
208 m_feetOffset = pfeetOffset;
209 m_orientation = Quaternion.Identity;
210 m_orientation2D = Quaternion.Identity;
211 m_density = density;
212
213 // force lower density for testing
214 m_density = 3.0f;
215
216 mu = parent_scene.AvatarFriction;
217
218 walkDivisor = walk_divisor;
219 runDivisor = rundivisor;
220
221 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; ; // sure we have a default
222
223 PID_D = basePID_D * m_mass * invtimeStep;
224 PID_P = basePID_P * m_mass * invtimeStep;
225
226 m_isPhysical = false; // current status: no ODE information exists
227
228 Name = avName;
229
230 AddChange(changes.Add, null);
231 }
232
233 public override int PhysicsActorType
234 {
235 get { return (int)ActorTypes.Agent; }
236 set { return; }
237 }
238
239 public override void getContactData(ref ContactData cdata)
240 {
241 cdata.mu = mu;
242 cdata.bounce = 0;
243 cdata.softcolide = false;
244 }
245
246 public override bool Building { get; set; }
247
248 /// <summary>
249 /// If this is set, the avatar will move faster
250 /// </summary>
251 public override bool SetAlwaysRun
252 {
253 get { return m_alwaysRun; }
254 set { m_alwaysRun = value; }
255 }
256
257 public override uint LocalID
258 {
259 get { return m_localID; }
260 set { m_localID = value; }
261 }
262
263 public override PhysicsActor ParentActor
264 {
265 get { return (PhysicsActor)this; }
266 }
267
268 public override bool Grabbed
269 {
270 set { return; }
271 }
272
273 public override bool Selected
274 {
275 set { return; }
276 }
277
278 public override float Buoyancy
279 {
280 get { return m_buoyancy; }
281 set { m_buoyancy = value; }
282 }
283
284 public override bool FloatOnWater
285 {
286 set { return; }
287 }
288
289 public override bool IsPhysical
290 {
291 get { return m_isPhysical; }
292 set { return; }
293 }
294
295 public override bool ThrottleUpdates
296 {
297 get { return false; }
298 set { return; }
299 }
300
301 public override bool Flying
302 {
303 get { return flying; }
304 set
305 {
306 flying = value;
307// m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying);
308 }
309 }
310
311 /// <summary>
312 /// Returns if the avatar is colliding in general.
313 /// This includes the ground and objects and avatar.
314 /// </summary>
315 public override bool IsColliding
316 {
317 get { return (m_iscolliding || m_iscollidingGround); }
318 set
319 {
320 if (value)
321 {
322 m_colliderfilter += 3;
323 if (m_colliderfilter > 3)
324 m_colliderfilter = 3;
325 }
326 else
327 {
328 m_colliderfilter--;
329 if (m_colliderfilter < 0)
330 m_colliderfilter = 0;
331 }
332
333 if (m_colliderfilter == 0)
334 m_iscolliding = false;
335 else
336 {
337 m_pidControllerActive = true;
338 m_iscolliding = true;
339 m_freemove = false;
340 }
341 }
342 }
343
344 /// <summary>
345 /// Returns if an avatar is colliding with the ground
346 /// </summary>
347 public override bool CollidingGround
348 {
349 get { return m_iscollidingGround; }
350 set
351 {
352/* we now control this
353 if (value)
354 {
355 m_colliderGroundfilter += 2;
356 if (m_colliderGroundfilter > 2)
357 m_colliderGroundfilter = 2;
358 }
359 else
360 {
361 m_colliderGroundfilter--;
362 if (m_colliderGroundfilter < 0)
363 m_colliderGroundfilter = 0;
364 }
365
366 if (m_colliderGroundfilter == 0)
367 m_iscollidingGround = false;
368 else
369 m_iscollidingGround = true;
370 */
371 }
372
373 }
374
375 /// <summary>
376 /// Returns if the avatar is colliding with an object
377 /// </summary>
378 public override bool CollidingObj
379 {
380 get { return m_iscollidingObj; }
381 set
382 {
383 // Ubit filter this also
384 if (value)
385 {
386 m_colliderObjectfilter += 2;
387 if (m_colliderObjectfilter > 2)
388 m_colliderObjectfilter = 2;
389 }
390 else
391 {
392 m_colliderObjectfilter--;
393 if (m_colliderObjectfilter < 0)
394 m_colliderObjectfilter = 0;
395 }
396
397 if (m_colliderObjectfilter == 0)
398 m_iscollidingObj = false;
399 else
400 m_iscollidingObj = true;
401
402// m_iscollidingObj = value;
403
404 if (m_iscollidingObj)
405 m_pidControllerActive = false;
406 else
407 m_pidControllerActive = true;
408 }
409 }
410
411 /// <summary>
412 /// turn the PID controller on or off.
413 /// The PID Controller will turn on all by itself in many situations
414 /// </summary>
415 /// <param name="status"></param>
416 public void SetPidStatus(bool status)
417 {
418 m_pidControllerActive = status;
419 }
420
421 public override bool Stopped
422 {
423 get { return _zeroFlag; }
424 }
425
426 /// <summary>
427 /// This 'puts' an avatar somewhere in the physics space.
428 /// Not really a good choice unless you 'know' it's a good
429 /// spot otherwise you're likely to orbit the avatar.
430 /// </summary>
431 public override Vector3 Position
432 {
433 get { return _position; }
434 set
435 {
436 if (value.IsFinite())
437 {
438 if (value.Z > 9999999f)
439 {
440 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
441 }
442 if (value.Z < -100f)
443 {
444 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
445 }
446 AddChange(changes.Position, value);
447 }
448 else
449 {
450 m_log.Warn("[PHYSICS]: Got a NaN Position from Scene on a Character");
451 }
452 }
453 }
454
455 public override Vector3 RotationalVelocity
456 {
457 get { return m_rotationalVelocity; }
458 set { m_rotationalVelocity = value; }
459 }
460
461 /// <summary>
462 /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight
463 /// and use it to offset landings properly
464 /// </summary>
465 public override Vector3 Size
466 {
467 get
468 {
469 return m_size;
470 }
471 set
472 {
473 if (value.IsFinite())
474 {
475 if(value.X <0.01f)
476 value.X = 0.01f;
477 if(value.Y <0.01f)
478 value.Y = 0.01f;
479 if(value.Z <0.01f)
480 value.Z = 0.01f;
481
482 AddChange(changes.Size, value);
483 }
484 else
485 {
486 m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character");
487 }
488 }
489 }
490
491 public override void setAvatarSize(Vector3 size, float feetOffset)
492 {
493 if (size.IsFinite())
494 {
495 if (size.X < 0.01f)
496 size.X = 0.01f;
497 if (size.Y < 0.01f)
498 size.Y = 0.01f;
499 if (size.Z < 0.01f)
500 size.Z = 0.01f;
501
502 strAvatarSize st = new strAvatarSize();
503 st.size = size;
504 st.offset = feetOffset;
505 AddChange(changes.AvatarSize, st);
506 }
507 else
508 {
509 m_log.Warn("[PHYSICS]: Got a NaN AvatarSize from Scene on a Character");
510 }
511
512 }
513 /// <summary>
514 /// This creates the Avatar's physical Surrogate at the position supplied
515 /// </summary>
516 /// <param name="npositionX"></param>
517 /// <param name="npositionY"></param>
518 /// <param name="npositionZ"></param>
519
520 //
521 /// <summary>
522 /// Uses the capped cyllinder volume formula to calculate the avatar's mass.
523 /// This may be used in calculations in the scene/scenepresence
524 /// </summary>
525 public override float Mass
526 {
527 get
528 {
529 return m_mass;
530 }
531 }
532 public override void link(PhysicsActor obj)
533 {
534
535 }
536
537 public override void delink()
538 {
539
540 }
541
542 public override void LockAngularMotion(byte axislocks)
543 {
544
545 }
546
547
548 public override Vector3 Force
549 {
550 get { return _target_velocity; }
551 set { return; }
552 }
553
554 public override int VehicleType
555 {
556 get { return 0; }
557 set { return; }
558 }
559
560 public override void VehicleFloatParam(int param, float value)
561 {
562
563 }
564
565 public override void VehicleVectorParam(int param, Vector3 value)
566 {
567
568 }
569
570 public override void VehicleRotationParam(int param, Quaternion rotation)
571 {
572
573 }
574
575 public override void VehicleFlags(int param, bool remove)
576 {
577
578 }
579
580 public override void SetVolumeDetect(int param)
581 {
582
583 }
584
585 public override Vector3 CenterOfMass
586 {
587 get
588 {
589 Vector3 pos = _position;
590 return pos;
591 }
592 }
593
594 public override Vector3 GeometricCenter
595 {
596 get
597 {
598 Vector3 pos = _position;
599 return pos;
600 }
601 }
602
603 public override PrimitiveBaseShape Shape
604 {
605 set { return; }
606 }
607
608 public override Vector3 Velocity
609 {
610 get
611 {
612 return _velocity;
613 }
614 set
615 {
616 if (value.IsFinite())
617 {
618 AddChange(changes.Velocity, value);
619 }
620 else
621 {
622 m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character");
623 }
624 }
625 }
626
627 public override Vector3 Torque
628 {
629 get { return Vector3.Zero; }
630 set { return; }
631 }
632
633 public override float CollisionScore
634 {
635 get { return 0f; }
636 set { }
637 }
638
639 public override bool Kinematic
640 {
641 get { return false; }
642 set { }
643 }
644
645 public override Quaternion Orientation
646 {
647 get { return m_orientation; }
648 set
649 {
650// fakeori = value;
651// givefakeori++;
652 value.Normalize();
653 AddChange(changes.Orientation, value);
654 }
655 }
656
657 public override Vector3 Acceleration
658 {
659 get { return _acceleration; }
660 set { }
661 }
662
663 public void SetAcceleration(Vector3 accel)
664 {
665 m_pidControllerActive = true;
666 _acceleration = accel;
667 }
668
669 /// <summary>
670 /// Adds the force supplied to the Target Velocity
671 /// The PID controller takes this target velocity and tries to make it a reality
672 /// </summary>
673 /// <param name="force"></param>
674 public override void AddForce(Vector3 force, bool pushforce)
675 {
676 if (force.IsFinite())
677 {
678 if (pushforce)
679 {
680 AddChange(changes.Force, force * m_density / (_parent_scene.ODE_STEPSIZE * 28f));
681 }
682 else
683 {
684 AddChange(changes.Velocity, force);
685 }
686 }
687 else
688 {
689 m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character");
690 }
691 //m_lastUpdateSent = false;
692 }
693
694 public override void AddAngularForce(Vector3 force, bool pushforce)
695 {
696
697 }
698
699 public override void SetMomentum(Vector3 momentum)
700 {
701 if (momentum.IsFinite())
702 AddChange(changes.Momentum, momentum);
703 }
704
705
706 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
707 {
708 // sizes one day should came from visual parameters
709 float sx = m_size.X;
710 float sy = m_size.Y;
711 float sz = m_size.Z;
712
713 float bot = -sz * 0.5f + m_feetOffset;
714 boneOff = bot + 0.3f;
715
716 float feetsz = sz * 0.45f;
717 if (feetsz > 0.6f)
718 feetsz = 0.6f;
719
720 feetOff = bot + feetsz;
721
722 AvaAvaSizeXsq = 0.4f * sx;
723 AvaAvaSizeXsq *= AvaAvaSizeXsq;
724 AvaAvaSizeYsq = 0.5f * sy;
725 AvaAvaSizeYsq *= AvaAvaSizeYsq;
726
727 _parent_scene.waitForSpaceUnlock(_parent_scene.CharsSpace);
728
729 collider = d.HashSpaceCreate(_parent_scene.CharsSpace);
730 d.HashSpaceSetLevels(collider, -4, 3);
731 d.SpaceSetSublevel(collider, 3);
732 d.SpaceSetCleanup(collider, false);
733 d.GeomSetCategoryBits(collider, (uint)m_collisionCategories);
734 d.GeomSetCollideBits(collider, (uint)m_collisionFlags);
735
736 float r = m_size.X;
737 if (m_size.Y > r)
738 r = m_size.Y;
739 float l = m_size.Z - r;
740 r *= 0.5f;
741
742 capsule = d.CreateCapsule(collider, r, l);
743
744 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; // update mass
745
746 d.MassSetBoxTotal(out ShellMass, m_mass, m_size.X, m_size.Y, m_size.Z);
747
748 PID_D = basePID_D * m_mass / _parent_scene.ODE_STEPSIZE;
749 PID_P = basePID_P * m_mass / _parent_scene.ODE_STEPSIZE;
750
751 Body = d.BodyCreate(_parent_scene.world);
752
753 _zeroFlag = false;
754 m_pidControllerActive = true;
755 m_freemove = false;
756
757 _velocity = Vector3.Zero;
758
759 d.BodySetAutoDisableFlag(Body, false);
760 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
761
762 _position.X = npositionX;
763 _position.Y = npositionY;
764 _position.Z = npositionZ;
765
766 d.BodySetMass(Body, ref ShellMass);
767 d.GeomSetBody(capsule, Body);
768
769 // The purpose of the AMotor here is to keep the avatar's physical
770 // surrogate from rotating while moving
771 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
772 d.JointAttach(Amotor, Body, IntPtr.Zero);
773
774 d.JointSetAMotorMode(Amotor, 0);
775 d.JointSetAMotorNumAxes(Amotor, 3);
776 d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
777 d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
778 d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
779
780 d.JointSetAMotorAngle(Amotor, 0, 0);
781 d.JointSetAMotorAngle(Amotor, 1, 0);
782 d.JointSetAMotorAngle(Amotor, 2, 0);
783
784 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM, 0f); // make it HARD
785 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM2, 0f);
786 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM3, 0f);
787 d.JointSetAMotorParam(Amotor, (int)dParam.StopERP, 0.8f);
788 d.JointSetAMotorParam(Amotor, (int)dParam.StopERP2, 0.8f);
789 d.JointSetAMotorParam(Amotor, (int)dParam.StopERP3, 0.8f);
790
791 // These lowstops and high stops are effectively (no wiggle room)
792 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -1e-5f);
793 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 1e-5f);
794 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -1e-5f);
795 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 1e-5f);
796 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -1e-5f);
797 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 1e-5f);
798
799 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
800 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel2, 0);
801 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel3, 0);
802
803 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, 5e8f);
804 d.JointSetAMotorParam(Amotor, (int)dParam.FMax2, 5e8f);
805 d.JointSetAMotorParam(Amotor, (int)dParam.FMax3, 5e8f);
806 }
807
808 /// <summary>
809 /// Destroys the avatar body and geom
810
811 private void AvatarGeomAndBodyDestroy()
812 {
813 // Kill the Amotor
814 if (Amotor != IntPtr.Zero)
815 {
816 d.JointDestroy(Amotor);
817 Amotor = IntPtr.Zero;
818 }
819
820 if (Body != IntPtr.Zero)
821 {
822 //kill the body
823 d.BodyDestroy(Body);
824 Body = IntPtr.Zero;
825 }
826
827 //kill the Geoms
828 if (capsule != IntPtr.Zero)
829 {
830 _parent_scene.actor_name_map.Remove(capsule);
831 _parent_scene.waitForSpaceUnlock(collider);
832 d.GeomDestroy(capsule);
833 capsule = IntPtr.Zero;
834 }
835
836 if (collider != IntPtr.Zero)
837 {
838 d.SpaceDestroy(collider);
839 collider = IntPtr.Zero;
840 }
841
842 }
843
844 //in place 2D rotation around Z assuming rot is normalised and is a rotation around Z
845 public void RotateXYonZ(ref float x, ref float y, ref Quaternion rot)
846 {
847 float sin = 2.0f * rot.Z * rot.W;
848 float cos = rot.W * rot.W - rot.Z * rot.Z;
849 float tx = x;
850
851 x = tx * cos - y * sin;
852 y = tx * sin + y * cos;
853 }
854 public void RotateXYonZ(ref float x, ref float y, ref float sin, ref float cos)
855 {
856 float tx = x;
857 x = tx * cos - y * sin;
858 y = tx * sin + y * cos;
859 }
860 public void invRotateXYonZ(ref float x, ref float y, ref float sin, ref float cos)
861 {
862 float tx = x;
863 x = tx * cos + y * sin;
864 y = -tx * sin + y * cos;
865 }
866
867 public void invRotateXYonZ(ref float x, ref float y, ref Quaternion rot)
868 {
869 float sin = - 2.0f * rot.Z * rot.W;
870 float cos = rot.W * rot.W - rot.Z * rot.Z;
871 float tx = x;
872
873 x = tx * cos - y * sin;
874 y = tx * sin + y * cos;
875 }
876
877 public bool Collide(IntPtr me, IntPtr other, bool reverse, ref d.ContactGeom contact,
878 ref d.ContactGeom altContact , ref bool useAltcontact, ref bool feetcollision)
879 {
880 feetcollision = false;
881 useAltcontact = false;
882
883 if (me == capsule)
884 {
885 Vector3 offset;
886
887 float h = contact.pos.Z - _position.Z;
888 offset.Z = h - feetOff;
889
890 offset.X = contact.pos.X - _position.X;
891 offset.Y = contact.pos.Y - _position.Y;
892
893 d.GeomClassID gtype = d.GeomGetClass(other);
894 if (gtype == d.GeomClassID.CapsuleClass)
895 {
896 Vector3 roff = offset * Quaternion.Inverse(m_orientation2D);
897 float r = roff.X *roff.X / AvaAvaSizeXsq;
898 r += (roff.Y * roff.Y) / AvaAvaSizeYsq;
899 if (r > 1.0f)
900 return false;
901
902 float dp = 1.0f -(float)Math.Sqrt((double)r);
903 if (dp > 0.05f)
904 dp = 0.05f;
905
906 contact.depth = dp;
907
908 if (offset.Z < 0)
909 {
910 feetcollision = true;
911 if (h < boneOff)
912 {
913 m_collideNormal.X = contact.normal.X;
914 m_collideNormal.Y = contact.normal.Y;
915 m_collideNormal.Z = contact.normal.Z;
916 IsColliding = true;
917 }
918 }
919 return true;
920 }
921/*
922 d.AABB aabb;
923 d.GeomGetAABB(other,out aabb);
924 float othertop = aabb.MaxZ - _position.Z;
925*/
926// if (offset.Z > 0 || othertop > -feetOff || contact.normal.Z > 0.35f)
927 if (offset.Z > 0 || contact.normal.Z > 0.35f)
928 {
929 if (offset.Z <= 0)
930 {
931 feetcollision = true;
932 if (h < boneOff)
933 {
934 m_collideNormal.X = contact.normal.X;
935 m_collideNormal.Y = contact.normal.Y;
936 m_collideNormal.Z = contact.normal.Z;
937 IsColliding = true;
938 }
939 }
940 return true;
941 }
942
943 altContact = contact;
944 useAltcontact = true;
945
946 offset.Z -= 0.2f;
947
948 offset.Normalize();
949
950 if (contact.depth > 0.1f)
951 contact.depth = 0.1f;
952
953 if (reverse)
954 {
955 altContact.normal.X = offset.X;
956 altContact.normal.Y = offset.Y;
957 altContact.normal.Z = offset.Z;
958 }
959 else
960 {
961 altContact.normal.X = -offset.X;
962 altContact.normal.Y = -offset.Y;
963 altContact.normal.Z = -offset.Z;
964 }
965
966 feetcollision = true;
967 if (h < boneOff)
968 {
969 m_collideNormal.X = contact.normal.X;
970 m_collideNormal.Y = contact.normal.Y;
971 m_collideNormal.Z = contact.normal.Z;
972 IsColliding = true;
973 }
974 return true;
975 }
976 return false;
977 }
978
979 /// <summary>
980 /// Called from Simulate
981 /// This is the avatar's movement control + PID Controller
982 /// </summary>
983 /// <param name="timeStep"></param>
984 public void Move(List<OdeCharacter> defects)
985 {
986 if (Body == IntPtr.Zero)
987 return;
988
989 d.Vector3 dtmp = d.BodyGetPosition(Body);
990 Vector3 localpos = new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
991
992 // the Amotor still lets avatar rotation to drift during colisions
993 // so force it back to identity
994
995 d.Quaternion qtmp;
996 qtmp.W = m_orientation2D.W;
997 qtmp.X = m_orientation2D.X;
998 qtmp.Y = m_orientation2D.Y;
999 qtmp.Z = m_orientation2D.Z;
1000 d.BodySetQuaternion(Body, ref qtmp);
1001
1002 if (m_pidControllerActive == false)
1003 {
1004 _zeroPosition = localpos;
1005 }
1006
1007 if (!localpos.IsFinite())
1008 {
1009 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
1010 defects.Add(this);
1011 // _parent_scene.RemoveCharacter(this);
1012
1013 // destroy avatar capsule and related ODE data
1014 AvatarGeomAndBodyDestroy();
1015 return;
1016 }
1017
1018 // check outbounds forcing to be in world
1019 bool fixbody = false;
1020 if (localpos.X < 0.0f)
1021 {
1022 fixbody = true;
1023 localpos.X = 0.1f;
1024 }
1025 else if (localpos.X > _parent_scene.WorldExtents.X - 0.1f)
1026 {
1027 fixbody = true;
1028 localpos.X = _parent_scene.WorldExtents.X - 0.1f;
1029 }
1030 if (localpos.Y < 0.0f)
1031 {
1032 fixbody = true;
1033 localpos.Y = 0.1f;
1034 }
1035 else if (localpos.Y > _parent_scene.WorldExtents.Y - 0.1)
1036 {
1037 fixbody = true;
1038 localpos.Y = _parent_scene.WorldExtents.Y - 0.1f;
1039 }
1040 if (fixbody)
1041 {
1042 m_freemove = false;
1043 d.BodySetPosition(Body, localpos.X, localpos.Y, localpos.Z);
1044 }
1045
1046 float breakfactor;
1047
1048 Vector3 vec = Vector3.Zero;
1049 dtmp = d.BodyGetLinearVel(Body);
1050 Vector3 vel = new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
1051 float velLengthSquared = vel.LengthSquared();
1052
1053 Vector3 ctz = _target_velocity;
1054
1055 float movementdivisor = 1f;
1056 //Ubit change divisions into multiplications below
1057 if (!m_alwaysRun)
1058 movementdivisor = 1 / walkDivisor;
1059 else
1060 movementdivisor = 1 / runDivisor;
1061
1062 ctz.X *= movementdivisor;
1063 ctz.Y *= movementdivisor;
1064
1065 //******************************************
1066 // colide with land
1067
1068 d.AABB aabb;
1069// d.GeomGetAABB(feetbox, out aabb);
1070 d.GeomGetAABB(capsule, out aabb);
1071 float chrminZ = aabb.MinZ; // move up a bit
1072 Vector3 posch = localpos;
1073
1074 float ftmp;
1075
1076 if (flying)
1077 {
1078 ftmp = timeStep;
1079 posch.X += vel.X * ftmp;
1080 posch.Y += vel.Y * ftmp;
1081 }
1082
1083 float terrainheight = _parent_scene.GetTerrainHeightAtXY(posch.X, posch.Y);
1084 if (chrminZ < terrainheight)
1085 {
1086 if (ctz.Z < 0)
1087 ctz.Z = 0;
1088
1089 Vector3 n = _parent_scene.GetTerrainNormalAtXY(posch.X, posch.Y);
1090 float depth = terrainheight - chrminZ;
1091
1092 vec.Z = depth * PID_P * 50;
1093
1094 if (!flying)
1095 vec.Z += -vel.Z * PID_D;
1096
1097 if (depth < 0.2f)
1098 {
1099 m_colliderGroundfilter++;
1100 if (m_colliderGroundfilter > 2)
1101 {
1102 m_iscolliding = true;
1103 m_colliderfilter = 2;
1104
1105 if (m_colliderGroundfilter > 10)
1106 {
1107 m_colliderGroundfilter = 10;
1108 m_freemove = false;
1109 }
1110
1111 m_collideNormal.X = n.X;
1112 m_collideNormal.Y = n.Y;
1113 m_collideNormal.Z = n.Z;
1114
1115 m_iscollidingGround = true;
1116
1117
1118 ContactPoint contact = new ContactPoint();
1119 contact.PenetrationDepth = depth;
1120 contact.Position.X = localpos.X;
1121 contact.Position.Y = localpos.Y;
1122 contact.Position.Z = terrainheight;
1123 contact.SurfaceNormal.X = -n.X;
1124 contact.SurfaceNormal.Y = -n.Y;
1125 contact.SurfaceNormal.Z = -n.Z;
1126 contact.RelativeSpeed = -vel.Z;
1127 contact.CharacterFeet = true;
1128 AddCollisionEvent(0, contact);
1129
1130// vec.Z *= 0.5f;
1131 }
1132 }
1133
1134 else
1135 {
1136 m_colliderGroundfilter -= 5;
1137 if (m_colliderGroundfilter <= 0)
1138 {
1139 m_colliderGroundfilter = 0;
1140 m_iscollidingGround = false;
1141 }
1142 }
1143 }
1144 else
1145 {
1146 m_colliderGroundfilter -= 5;
1147 if (m_colliderGroundfilter <= 0)
1148 {
1149 m_colliderGroundfilter = 0;
1150 m_iscollidingGround = false;
1151 }
1152 }
1153
1154 bool hoverPIDActive = false;
1155
1156 if (m_useHoverPID && m_PIDHoverTau != 0 && m_PIDHoverHeight != 0)
1157 {
1158 hoverPIDActive = true;
1159
1160 switch (m_PIDHoverType)
1161 {
1162 case PIDHoverType.Ground:
1163 m_targetHoverHeight = terrainheight + m_PIDHoverHeight;
1164 break;
1165
1166 case PIDHoverType.GroundAndWater:
1167 float waterHeight = _parent_scene.GetWaterLevel();
1168 if (terrainheight > waterHeight)
1169 m_targetHoverHeight = terrainheight + m_PIDHoverHeight;
1170 else
1171 m_targetHoverHeight = waterHeight + m_PIDHoverHeight;
1172 break;
1173 } // end switch (m_PIDHoverType)
1174
1175 // don't go underground
1176 if (m_targetHoverHeight > terrainheight + 0.5f * (aabb.MaxZ - aabb.MinZ))
1177 {
1178 float fz = (m_targetHoverHeight - localpos.Z);
1179
1180 // if error is zero, use position control; otherwise, velocity control
1181 if (Math.Abs(fz) < 0.01f)
1182 {
1183 ctz.Z = 0;
1184 }
1185 else
1186 {
1187 _zeroFlag = false;
1188 fz /= m_PIDHoverTau;
1189
1190 float tmp = Math.Abs(fz);
1191 if (tmp > 50)
1192 fz = 50 * Math.Sign(fz);
1193 else if (tmp < 0.1)
1194 fz = 0.1f * Math.Sign(fz);
1195
1196 ctz.Z = fz;
1197 }
1198 }
1199 }
1200
1201 //******************************************
1202 if (!m_iscolliding)
1203 m_collideNormal.Z = 0;
1204
1205 bool tviszero = (ctz.X == 0.0f && ctz.Y == 0.0f && ctz.Z == 0.0f);
1206
1207 if (!tviszero)
1208 {
1209 m_freemove = false;
1210
1211 // movement relative to surface if moving on it
1212 // dont disturbe vertical movement, ie jumps
1213 if (m_iscolliding && !flying && ctz.Z == 0 && m_collideNormal.Z > 0.2f && m_collideNormal.Z < 0.94f)
1214 {
1215 float p = ctz.X * m_collideNormal.X + ctz.Y * m_collideNormal.Y;
1216 ctz.X *= (float)Math.Sqrt(1 - m_collideNormal.X * m_collideNormal.X);
1217 ctz.Y *= (float)Math.Sqrt(1 - m_collideNormal.Y * m_collideNormal.Y);
1218 ctz.Z -= p;
1219 if (ctz.Z < 0)
1220 ctz.Z *= 2;
1221
1222 }
1223
1224 }
1225
1226 if (!m_freemove)
1227 {
1228
1229 // if velocity is zero, use position control; otherwise, velocity control
1230 if (tviszero && m_iscolliding && !flying)
1231 {
1232 // keep track of where we stopped. No more slippin' & slidin'
1233 if (!_zeroFlag)
1234 {
1235 _zeroFlag = true;
1236 _zeroPosition = localpos;
1237 }
1238 if (m_pidControllerActive)
1239 {
1240 // We only want to deactivate the PID Controller if we think we want to have our surrogate
1241 // react to the physics scene by moving it's position.
1242 // Avatar to Avatar collisions
1243 // Prim to avatar collisions
1244
1245 vec.X = -vel.X * PID_D * 2f + (_zeroPosition.X - localpos.X) * (PID_P * 5);
1246 vec.Y = -vel.Y * PID_D * 2f + (_zeroPosition.Y - localpos.Y) * (PID_P * 5);
1247 if(vel.Z > 0)
1248 vec.Z += -vel.Z * PID_D + (_zeroPosition.Z - localpos.Z) * PID_P;
1249 else
1250 vec.Z += (-vel.Z * PID_D + (_zeroPosition.Z - localpos.Z) * PID_P) * 0.2f;
1251/*
1252 if (flying)
1253 {
1254 vec.Z += -vel.Z * PID_D + (_zeroPosition.Z - localpos.Z) * PID_P;
1255 }
1256*/
1257 }
1258 //PidStatus = true;
1259 }
1260 else
1261 {
1262 m_pidControllerActive = true;
1263 _zeroFlag = false;
1264
1265 if (m_iscolliding)
1266 {
1267 if (!flying)
1268 {
1269 // we are on a surface
1270 if (ctz.Z > 0f)
1271 {
1272 // moving up or JUMPING
1273 vec.Z += (ctz.Z - vel.Z) * PID_D * 2f;
1274 vec.X += (ctz.X - vel.X) * (PID_D);
1275 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1276 }
1277 else
1278 {
1279 // we are moving down on a surface
1280 if (ctz.Z == 0)
1281 {
1282 if (vel.Z > 0)
1283 vec.Z -= vel.Z * PID_D * 2f;
1284 vec.X += (ctz.X - vel.X) * (PID_D);
1285 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1286 }
1287 // intencionally going down
1288 else
1289 {
1290 if (ctz.Z < vel.Z)
1291 vec.Z += (ctz.Z - vel.Z) * PID_D;
1292 else
1293 {
1294 }
1295
1296 if (Math.Abs(ctz.X) > Math.Abs(vel.X))
1297 vec.X += (ctz.X - vel.X) * (PID_D);
1298 if (Math.Abs(ctz.Y) > Math.Abs(vel.Y))
1299 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1300 }
1301 }
1302
1303 // We're standing on something
1304 }
1305 else
1306 {
1307 // We're flying and colliding with something
1308 vec.X += (ctz.X - vel.X) * (PID_D * 0.0625f);
1309 vec.Y += (ctz.Y - vel.Y) * (PID_D * 0.0625f);
1310 vec.Z += (ctz.Z - vel.Z) * (PID_D * 0.0625f);
1311 }
1312 }
1313 else // ie not colliding
1314 {
1315 if (flying || hoverPIDActive) //(!m_iscolliding && flying)
1316 {
1317 // we're in mid air suspended
1318 vec.X += (ctz.X - vel.X) * (PID_D);
1319 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1320 vec.Z += (ctz.Z - vel.Z) * (PID_D);
1321 }
1322
1323 else
1324 {
1325 // we're not colliding and we're not flying so that means we're falling!
1326 // m_iscolliding includes collisions with the ground.
1327
1328 // d.Vector3 pos = d.BodyGetPosition(Body);
1329 vec.X += (ctz.X - vel.X) * PID_D * 0.833f;
1330 vec.Y += (ctz.Y - vel.Y) * PID_D * 0.833f;
1331 // hack for breaking on fall
1332 if (ctz.Z == -9999f)
1333 vec.Z += -vel.Z * PID_D - _parent_scene.gravityz * m_mass;
1334 }
1335 }
1336 }
1337
1338 if (velLengthSquared > 2500.0f) // 50m/s apply breaks
1339 {
1340 breakfactor = 0.16f * m_mass;
1341 vec.X -= breakfactor * vel.X;
1342 vec.Y -= breakfactor * vel.Y;
1343 vec.Z -= breakfactor * vel.Z;
1344 }
1345 }
1346 else
1347 {
1348 breakfactor = m_mass;
1349 vec.X -= breakfactor * vel.X;
1350 vec.Y -= breakfactor * vel.Y;
1351 if (flying)
1352 vec.Z -= 0.5f * breakfactor * vel.Z;
1353 else
1354 vec.Z -= .16f* m_mass * vel.Z;
1355 }
1356
1357 if (flying || hoverPIDActive)
1358 {
1359 vec.Z -= _parent_scene.gravityz * m_mass;
1360
1361 if(!hoverPIDActive)
1362 {
1363 //Added for auto fly height. Kitto Flora
1364 float target_altitude = terrainheight + MinimumGroundFlightOffset;
1365
1366 if (localpos.Z < target_altitude)
1367 {
1368 vec.Z += (target_altitude - localpos.Z) * PID_P * 5.0f;
1369 }
1370 // end add Kitto Flora
1371 }
1372 }
1373
1374 if (vec.IsFinite())
1375 {
1376 if (vec.X != 0 || vec.Y !=0 || vec.Z !=0)
1377 d.BodyAddForce(Body, vec.X, vec.Y, vec.Z);
1378 }
1379 else
1380 {
1381 m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()");
1382 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
1383 defects.Add(this);
1384 // _parent_scene.RemoveCharacter(this);
1385 // destroy avatar capsule and related ODE data
1386 AvatarGeomAndBodyDestroy();
1387 return;
1388 }
1389
1390 // update our local ideia of position velocity and aceleration
1391 // _position = localpos;
1392 _position = localpos;
1393
1394 if (_zeroFlag)
1395 {
1396 _velocity = Vector3.Zero;
1397 _acceleration = Vector3.Zero;
1398 m_rotationalVelocity = Vector3.Zero;
1399 }
1400 else
1401 {
1402 Vector3 a =_velocity; // previus velocity
1403 SetSmooth(ref _velocity, ref vel, 2);
1404 a = (_velocity - a) * invtimeStep;
1405 SetSmooth(ref _acceleration, ref a, 2);
1406
1407 dtmp = d.BodyGetAngularVel(Body);
1408 m_rotationalVelocity.X = 0f;
1409 m_rotationalVelocity.Y = 0f;
1410 m_rotationalVelocity.Z = dtmp.Z;
1411 Math.Round(m_rotationalVelocity.Z,3);
1412 }
1413 }
1414
1415 public void round(ref Vector3 v, int digits)
1416 {
1417 v.X = (float)Math.Round(v.X, digits);
1418 v.Y = (float)Math.Round(v.Y, digits);
1419 v.Z = (float)Math.Round(v.Z, digits);
1420 }
1421
1422 public void SetSmooth(ref Vector3 dst, ref Vector3 value)
1423 {
1424 dst.X = 0.1f * dst.X + 0.9f * value.X;
1425 dst.Y = 0.1f * dst.Y + 0.9f * value.Y;
1426 dst.Z = 0.1f * dst.Z + 0.9f * value.Z;
1427 }
1428
1429 public void SetSmooth(ref Vector3 dst, ref Vector3 value, int rounddigits)
1430 {
1431 dst.X = 0.4f * dst.X + 0.6f * value.X;
1432 dst.X = (float)Math.Round(dst.X, rounddigits);
1433
1434 dst.Y = 0.4f * dst.Y + 0.6f * value.Y;
1435 dst.Y = (float)Math.Round(dst.Y, rounddigits);
1436
1437 dst.Z = 0.4f * dst.Z + 0.6f * value.Z;
1438 dst.Z = (float)Math.Round(dst.Z, rounddigits);
1439 }
1440
1441
1442 /// <summary>
1443 /// Updates the reported position and velocity.
1444 /// Used to copy variables from unmanaged space at heartbeat rate and also trigger scene updates acording
1445 /// also outbounds checking
1446 /// copy and outbounds now done in move(..) at ode rate
1447 ///
1448 /// </summary>
1449 public void UpdatePositionAndVelocity()
1450 {
1451 return;
1452
1453// if (Body == IntPtr.Zero)
1454// return;
1455
1456 }
1457
1458 /// <summary>
1459 /// Cleanup the things we use in the scene.
1460 /// </summary>
1461 public void Destroy()
1462 {
1463 AddChange(changes.Remove, null);
1464 }
1465
1466 public override void CrossingFailure()
1467 {
1468 }
1469
1470 public override Vector3 PIDTarget { set { return; } }
1471 public override bool PIDActive {get {return m_pidControllerActive;} set { return; } }
1472 public override float PIDTau { set { return; } }
1473
1474 public override float PIDHoverHeight
1475 {
1476 set
1477 {
1478 AddChange(changes.PIDHoverHeight,value);
1479 }
1480 }
1481 public override bool PIDHoverActive
1482 {
1483 get
1484 {
1485 return m_useHoverPID;
1486 }
1487 set
1488 {
1489 AddChange(changes.PIDHoverActive, value);
1490 }
1491 }
1492
1493 public override PIDHoverType PIDHoverType
1494 {
1495 set
1496 {
1497 AddChange(changes.PIDHoverType,value);
1498 }
1499 }
1500
1501 public override float PIDHoverTau
1502 {
1503 set
1504 {
1505 float tmp =0;
1506 if (value > 0)
1507 {
1508 float mint = (0.05f > timeStep ? 0.05f : timeStep);
1509 if (value < mint)
1510 tmp = mint;
1511 else
1512 tmp = value;
1513 }
1514 AddChange(changes.PIDHoverTau, tmp);
1515 }
1516 }
1517
1518 public override Quaternion APIDTarget { set { return; } }
1519
1520 public override bool APIDActive { set { return; } }
1521
1522 public override float APIDStrength { set { return; } }
1523
1524 public override float APIDDamping { set { return; } }
1525
1526
1527 public override void SubscribeEvents(int ms)
1528 {
1529 m_eventsubscription = ms;
1530 m_cureventsubscription = 0;
1531 if (CollisionEventsThisFrame == null)
1532 CollisionEventsThisFrame = new CollisionEventUpdate();
1533 SentEmptyCollisionsEvent = false;
1534 }
1535
1536 public override void UnSubscribeEvents()
1537 {
1538 if (CollisionEventsThisFrame != null)
1539 {
1540 lock (CollisionEventsThisFrame)
1541 {
1542 CollisionEventsThisFrame.Clear();
1543 CollisionEventsThisFrame = null;
1544 }
1545 }
1546 m_eventsubscription = 0;
1547 }
1548
1549 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1550 {
1551 if (CollisionEventsThisFrame == null)
1552 CollisionEventsThisFrame = new CollisionEventUpdate();
1553 lock (CollisionEventsThisFrame)
1554 {
1555 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
1556 _parent_scene.AddCollisionEventReporting(this);
1557 }
1558 }
1559
1560 public void SendCollisions()
1561 {
1562 if (CollisionEventsThisFrame == null)
1563 return;
1564
1565 lock (CollisionEventsThisFrame)
1566 {
1567 if (m_cureventsubscription < m_eventsubscription)
1568 return;
1569
1570 m_cureventsubscription = 0;
1571
1572 int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count;
1573
1574 if (!SentEmptyCollisionsEvent || ncolisions > 0)
1575 {
1576 base.SendCollisionUpdate(CollisionEventsThisFrame);
1577
1578 if (ncolisions == 0)
1579 {
1580 SentEmptyCollisionsEvent = true;
1581 _parent_scene.RemoveCollisionEventReporting(this);
1582 }
1583 else
1584 {
1585 SentEmptyCollisionsEvent = false;
1586 CollisionEventsThisFrame.Clear();
1587 }
1588 }
1589 }
1590 }
1591
1592 internal void AddCollisionFrameTime(int t)
1593 {
1594 // protect it from overflow crashing
1595 if (m_cureventsubscription < 50000)
1596 m_cureventsubscription += t;
1597 }
1598
1599 public override bool SubscribedEvents()
1600 {
1601 if (m_eventsubscription > 0)
1602 return true;
1603 return false;
1604 }
1605
1606 private void changePhysicsStatus(bool NewStatus)
1607 {
1608 if (NewStatus != m_isPhysical)
1609 {
1610 if (NewStatus)
1611 {
1612 AvatarGeomAndBodyDestroy();
1613
1614 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z);
1615
1616 _parent_scene.actor_name_map[collider] = (PhysicsActor)this;
1617 _parent_scene.actor_name_map[capsule] = (PhysicsActor)this;
1618 _parent_scene.AddCharacter(this);
1619 }
1620 else
1621 {
1622 _parent_scene.RemoveCollisionEventReporting(this);
1623 _parent_scene.RemoveCharacter(this);
1624 // destroy avatar capsule and related ODE data
1625 AvatarGeomAndBodyDestroy();
1626 }
1627 m_freemove = false;
1628 m_isPhysical = NewStatus;
1629 }
1630 }
1631
1632 private void changeAdd()
1633 {
1634 changePhysicsStatus(true);
1635 }
1636
1637 private void changeRemove()
1638 {
1639 changePhysicsStatus(false);
1640 }
1641
1642 private void changeShape(PrimitiveBaseShape arg)
1643 {
1644 }
1645
1646 private void changeAvatarSize(strAvatarSize st)
1647 {
1648 m_feetOffset = st.offset;
1649 changeSize(st.size);
1650 }
1651
1652 private void changeSize(Vector3 pSize)
1653 {
1654 if (pSize.IsFinite())
1655 {
1656 // for now only look to Z changes since viewers also don't change X and Y
1657 if (pSize.Z != m_size.Z)
1658 {
1659 AvatarGeomAndBodyDestroy();
1660
1661
1662 float oldsz = m_size.Z;
1663 m_size = pSize;
1664
1665
1666 AvatarGeomAndBodyCreation(_position.X, _position.Y,
1667 _position.Z + (m_size.Z - oldsz) * 0.5f);
1668
1669 Velocity = Vector3.Zero;
1670
1671
1672 _parent_scene.actor_name_map[collider] = (PhysicsActor)this;
1673 _parent_scene.actor_name_map[capsule] = (PhysicsActor)this;
1674 }
1675 m_freemove = false;
1676 m_pidControllerActive = true;
1677 }
1678 else
1679 {
1680 m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character");
1681 }
1682 }
1683
1684 private void changePosition( Vector3 newPos)
1685 {
1686 if (Body != IntPtr.Zero)
1687 d.BodySetPosition(Body, newPos.X, newPos.Y, newPos.Z);
1688 _position = newPos;
1689 m_freemove = false;
1690 m_pidControllerActive = true;
1691 }
1692
1693 private void changeOrientation(Quaternion newOri)
1694 {
1695 if (m_orientation != newOri)
1696 {
1697 m_orientation = newOri; // keep a copy for core use
1698 // but only use rotations around Z
1699
1700 m_orientation2D.W = newOri.W;
1701 m_orientation2D.Z = newOri.Z;
1702
1703 float t = m_orientation2D.W * m_orientation2D.W + m_orientation2D.Z * m_orientation2D.Z;
1704 if (t > 0)
1705 {
1706 t = 1.0f / (float)Math.Sqrt(t);
1707 m_orientation2D.W *= t;
1708 m_orientation2D.Z *= t;
1709 }
1710 else
1711 {
1712 m_orientation2D.W = 1.0f;
1713 m_orientation2D.Z = 0f;
1714 }
1715 m_orientation2D.Y = 0f;
1716 m_orientation2D.X = 0f;
1717
1718 d.Quaternion myrot = new d.Quaternion();
1719 myrot.X = m_orientation2D.X;
1720 myrot.Y = m_orientation2D.Y;
1721 myrot.Z = m_orientation2D.Z;
1722 myrot.W = m_orientation2D.W;
1723 d.BodySetQuaternion(Body, ref myrot);
1724 }
1725 }
1726
1727 private void changeVelocity(Vector3 newVel)
1728 {
1729 m_pidControllerActive = true;
1730 m_freemove = false;
1731 _target_velocity = newVel;
1732 }
1733
1734 private void changeSetTorque(Vector3 newTorque)
1735 {
1736 }
1737
1738 private void changeAddForce(Vector3 newForce)
1739 {
1740 }
1741
1742 private void changeAddAngularForce(Vector3 arg)
1743 {
1744 }
1745
1746 private void changeAngularLock(byte arg)
1747 {
1748 }
1749
1750 private void changeFloatOnWater(bool arg)
1751 {
1752 }
1753
1754 private void changeVolumedetetion(bool arg)
1755 {
1756 }
1757
1758 private void changeSelectedStatus(bool arg)
1759 {
1760 }
1761
1762 private void changeDisable(bool arg)
1763 {
1764 }
1765
1766 private void changeBuilding(bool arg)
1767 {
1768 }
1769
1770 private void setFreeMove()
1771 {
1772 m_pidControllerActive = true;
1773 _zeroFlag = false;
1774 _target_velocity = Vector3.Zero;
1775 m_freemove = true;
1776 m_colliderfilter = -1;
1777 m_colliderObjectfilter = -1;
1778 m_colliderGroundfilter = -1;
1779
1780 m_iscolliding = false;
1781 m_iscollidingGround = false;
1782 m_iscollidingObj = false;
1783
1784 CollisionEventsThisFrame.Clear();
1785 }
1786
1787 private void changeForce(Vector3 newForce)
1788 {
1789 setFreeMove();
1790
1791 if (Body != IntPtr.Zero)
1792 {
1793 if (newForce.X != 0f || newForce.Y != 0f || newForce.Z != 0)
1794 d.BodyAddForce(Body, newForce.X, newForce.Y, newForce.Z);
1795 }
1796 }
1797
1798 // for now momentum is actually velocity
1799 private void changeMomentum(Vector3 newmomentum)
1800 {
1801 _velocity = newmomentum;
1802 setFreeMove();
1803
1804 if (Body != IntPtr.Zero)
1805 d.BodySetLinearVel(Body, newmomentum.X, newmomentum.Y, newmomentum.Z);
1806 }
1807
1808 private void changePIDHoverHeight(float val)
1809 {
1810 m_PIDHoverHeight = val;
1811 if (val == 0)
1812 m_useHoverPID = false;
1813 }
1814
1815 private void changePIDHoverType(PIDHoverType type)
1816 {
1817 m_PIDHoverType = type;
1818 }
1819
1820 private void changePIDHoverTau(float tau)
1821 {
1822 m_PIDHoverTau = tau;
1823 }
1824
1825 private void changePIDHoverActive(bool active)
1826 {
1827 m_useHoverPID = active;
1828 }
1829
1830 private void donullchange()
1831 {
1832 }
1833
1834 public bool DoAChange(changes what, object arg)
1835 {
1836 if (collider == IntPtr.Zero && what != changes.Add && what != changes.Remove)
1837 {
1838 return false;
1839 }
1840
1841 // nasty switch
1842 switch (what)
1843 {
1844 case changes.Add:
1845 changeAdd();
1846 break;
1847 case changes.Remove:
1848 changeRemove();
1849 break;
1850
1851 case changes.Position:
1852 changePosition((Vector3)arg);
1853 break;
1854
1855 case changes.Orientation:
1856 changeOrientation((Quaternion)arg);
1857 break;
1858
1859 case changes.PosOffset:
1860 donullchange();
1861 break;
1862
1863 case changes.OriOffset:
1864 donullchange();
1865 break;
1866
1867 case changes.Velocity:
1868 changeVelocity((Vector3)arg);
1869 break;
1870
1871 // case changes.Acceleration:
1872 // changeacceleration((Vector3)arg);
1873 // break;
1874 // case changes.AngVelocity:
1875 // changeangvelocity((Vector3)arg);
1876 // break;
1877
1878 case changes.Force:
1879 changeForce((Vector3)arg);
1880 break;
1881
1882 case changes.Torque:
1883 changeSetTorque((Vector3)arg);
1884 break;
1885
1886 case changes.AddForce:
1887 changeAddForce((Vector3)arg);
1888 break;
1889
1890 case changes.AddAngForce:
1891 changeAddAngularForce((Vector3)arg);
1892 break;
1893
1894 case changes.AngLock:
1895 changeAngularLock((byte)arg);
1896 break;
1897
1898 case changes.Size:
1899 changeSize((Vector3)arg);
1900 break;
1901
1902 case changes.AvatarSize:
1903 changeAvatarSize((strAvatarSize)arg);
1904 break;
1905
1906 case changes.Momentum:
1907 changeMomentum((Vector3)arg);
1908 break;
1909
1910 case changes.PIDHoverHeight:
1911 changePIDHoverHeight((float)arg);
1912 break;
1913
1914 case changes.PIDHoverType:
1915 changePIDHoverType((PIDHoverType)arg);
1916 break;
1917
1918 case changes.PIDHoverTau:
1919 changePIDHoverTau((float)arg);
1920 break;
1921
1922 case changes.PIDHoverActive:
1923 changePIDHoverActive((bool)arg);
1924 break;
1925
1926/* not in use for now
1927 case changes.Shape:
1928 changeShape((PrimitiveBaseShape)arg);
1929 break;
1930
1931 case changes.CollidesWater:
1932 changeFloatOnWater((bool)arg);
1933 break;
1934
1935 case changes.VolumeDtc:
1936 changeVolumedetetion((bool)arg);
1937 break;
1938
1939 case changes.Physical:
1940 changePhysicsStatus((bool)arg);
1941 break;
1942
1943 case changes.Selected:
1944 changeSelectedStatus((bool)arg);
1945 break;
1946
1947 case changes.disabled:
1948 changeDisable((bool)arg);
1949 break;
1950
1951 case changes.building:
1952 changeBuilding((bool)arg);
1953 break;
1954*/
1955 case changes.Null:
1956 donullchange();
1957 break;
1958
1959 default:
1960 donullchange();
1961 break;
1962 }
1963 return false;
1964 }
1965
1966 public void AddChange(changes what, object arg)
1967 {
1968 _parent_scene.AddChange((PhysicsActor)this, what, arg);
1969 }
1970
1971 private struct strAvatarSize
1972 {
1973 public Vector3 size;
1974 public float offset;
1975 }
1976
1977 }
1978}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs
new file mode 100644
index 0000000..c3b4dd8
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs
@@ -0,0 +1,1096 @@
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
28/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
29 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
30 * ODEPrim.cs contains methods dealing with Prim editing, Prim
31 * characteristics and Kinetic motion.
32 * ODEDynamics.cs contains methods dealing with Prim Physical motion
33 * (dynamics) and the associated settings. Old Linear and angular
34 * motors for dynamic motion have been replace with MoveLinear()
35 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
36 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
37 * switch between 'VEHICLE' parameter use and general dynamics
38 * settings use.
39 */
40
41// Extensive change Ubit 2012
42
43using System;
44using System.Collections.Generic;
45using System.Reflection;
46using System.Runtime.InteropServices;
47using log4net;
48using OpenMetaverse;
49using OdeAPI;
50using OpenSim.Framework;
51using OpenSim.Region.PhysicsModules.SharedBase;
52
53namespace OpenSim.Region.PhysicsModule.ubOde
54{
55 public class ODEDynamics
56 {
57 public Vehicle Type
58 {
59 get { return m_type; }
60 }
61
62 private OdePrim rootPrim;
63 private ODEScene _pParentScene;
64
65 // Vehicle properties
66 // WARNING this are working copies for internel use
67 // their values may not be the corresponding parameter
68
69 private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
70 private Quaternion m_RollreferenceFrame = Quaternion.Identity; // what hell is this ?
71
72 private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
73
74 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
75 // HOVER_TERRAIN_ONLY
76 // HOVER_GLOBAL_HEIGHT
77 // NO_DEFLECTION_UP
78 // HOVER_WATER_ONLY
79 // HOVER_UP_ONLY
80 // LIMIT_MOTOR_UP
81 // LIMIT_ROLL_ONLY
82 private Vector3 m_BlockingEndPoint = Vector3.Zero; // not sl
83
84 // Linear properties
85 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
86 private Vector3 m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
87 private float m_linearMotorDecayTimescale = 120;
88 private float m_linearMotorTimescale = 1000;
89 private Vector3 m_linearMotorOffset = Vector3.Zero;
90
91 //Angular properties
92 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
93 private float m_angularMotorTimescale = 1000; // motor angular velocity ramp up rate
94 private float m_angularMotorDecayTimescale = 120; // motor angular velocity decay rate
95 private Vector3 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); // body angular velocity decay rate
96
97 //Deflection properties
98 private float m_angularDeflectionEfficiency = 0;
99 private float m_angularDeflectionTimescale = 1000;
100 private float m_linearDeflectionEfficiency = 0;
101 private float m_linearDeflectionTimescale = 1000;
102
103 //Banking properties
104 private float m_bankingEfficiency = 0;
105 private float m_bankingMix = 0;
106 private float m_bankingTimescale = 1000;
107
108 //Hover and Buoyancy properties
109 private float m_VhoverHeight = 0f;
110 private float m_VhoverEfficiency = 0f;
111 private float m_VhoverTimescale = 1000f;
112 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
113 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
114 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
115 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
116
117 //Attractor properties
118 private float m_verticalAttractionEfficiency = 1.0f; // damped
119 private float m_verticalAttractionTimescale = 1000f; // Timescale > 300 means no vert attractor.
120
121
122 // auxiliar
123 private float m_lmEfect = 0f; // current linear motor eficiency
124 private float m_lmDecay = 0f; // current linear decay
125
126 private float m_amEfect = 0; // current angular motor eficiency
127 private float m_amDecay = 0f; // current linear decay
128
129 private float m_ffactor = 1.0f;
130
131 private float m_timestep = 0.02f;
132 private float m_invtimestep = 50;
133
134
135 float m_ampwr;
136 float m_amdampX;
137 float m_amdampY;
138 float m_amdampZ;
139
140 float m_gravmod;
141
142 public float FrictionFactor
143 {
144 get
145 {
146 return m_ffactor;
147 }
148 }
149
150 public float GravMod
151 {
152 set
153 {
154 m_gravmod = value;
155 }
156 }
157
158
159 public ODEDynamics(OdePrim rootp)
160 {
161 rootPrim = rootp;
162 _pParentScene = rootPrim._parent_scene;
163 m_timestep = _pParentScene.ODE_STEPSIZE;
164 m_invtimestep = 1.0f / m_timestep;
165 m_gravmod = rootPrim.GravModifier;
166 }
167
168 public void DoSetVehicle(VehicleData vd)
169 {
170 m_type = vd.m_type;
171 m_flags = vd.m_flags;
172
173
174 // Linear properties
175 m_linearMotorDirection = vd.m_linearMotorDirection;
176
177 m_linearFrictionTimescale = vd.m_linearFrictionTimescale;
178 if (m_linearFrictionTimescale.X < m_timestep) m_linearFrictionTimescale.X = m_timestep;
179 if (m_linearFrictionTimescale.Y < m_timestep) m_linearFrictionTimescale.Y = m_timestep;
180 if (m_linearFrictionTimescale.Z < m_timestep) m_linearFrictionTimescale.Z = m_timestep;
181
182 m_linearMotorDecayTimescale = vd.m_linearMotorDecayTimescale;
183 if (m_linearMotorDecayTimescale < m_timestep) m_linearMotorDecayTimescale = m_timestep;
184 m_linearMotorDecayTimescale += 0.2f;
185 m_linearMotorDecayTimescale *= m_invtimestep;
186
187 m_linearMotorTimescale = vd.m_linearMotorTimescale;
188 if (m_linearMotorTimescale < m_timestep) m_linearMotorTimescale = m_timestep;
189
190 m_linearMotorOffset = vd.m_linearMotorOffset;
191
192 //Angular properties
193 m_angularMotorDirection = vd.m_angularMotorDirection;
194 m_angularMotorTimescale = vd.m_angularMotorTimescale;
195 if (m_angularMotorTimescale < m_timestep) m_angularMotorTimescale = m_timestep;
196
197 m_angularMotorDecayTimescale = vd.m_angularMotorDecayTimescale;
198 if (m_angularMotorDecayTimescale < m_timestep) m_angularMotorDecayTimescale = m_timestep;
199 m_angularMotorDecayTimescale *= m_invtimestep;
200
201 m_angularFrictionTimescale = vd.m_angularFrictionTimescale;
202 if (m_angularFrictionTimescale.X < m_timestep) m_angularFrictionTimescale.X = m_timestep;
203 if (m_angularFrictionTimescale.Y < m_timestep) m_angularFrictionTimescale.Y = m_timestep;
204 if (m_angularFrictionTimescale.Z < m_timestep) m_angularFrictionTimescale.Z = m_timestep;
205
206 //Deflection properties
207 m_angularDeflectionEfficiency = vd.m_angularDeflectionEfficiency;
208 m_angularDeflectionTimescale = vd.m_angularDeflectionTimescale;
209 if (m_angularDeflectionTimescale < m_timestep) m_angularDeflectionTimescale = m_timestep;
210
211 m_linearDeflectionEfficiency = vd.m_linearDeflectionEfficiency;
212 m_linearDeflectionTimescale = vd.m_linearDeflectionTimescale;
213 if (m_linearDeflectionTimescale < m_timestep) m_linearDeflectionTimescale = m_timestep;
214
215 //Banking properties
216 m_bankingEfficiency = vd.m_bankingEfficiency;
217 m_bankingMix = vd.m_bankingMix;
218 m_bankingTimescale = vd.m_bankingTimescale;
219 if (m_bankingTimescale < m_timestep) m_bankingTimescale = m_timestep;
220
221 //Hover and Buoyancy properties
222 m_VhoverHeight = vd.m_VhoverHeight;
223 m_VhoverEfficiency = vd.m_VhoverEfficiency;
224 m_VhoverTimescale = vd.m_VhoverTimescale;
225 if (m_VhoverTimescale < m_timestep) m_VhoverTimescale = m_timestep;
226
227 m_VehicleBuoyancy = vd.m_VehicleBuoyancy;
228
229 //Attractor properties
230 m_verticalAttractionEfficiency = vd.m_verticalAttractionEfficiency;
231 m_verticalAttractionTimescale = vd.m_verticalAttractionTimescale;
232 if (m_verticalAttractionTimescale < m_timestep) m_verticalAttractionTimescale = m_timestep;
233
234 // Axis
235 m_referenceFrame = vd.m_referenceFrame;
236
237 m_lmEfect = 0;
238 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
239 m_amEfect = 0;
240 m_ffactor = 1.0f;
241 }
242
243 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
244 {
245 float len;
246
247 switch (pParam)
248 {
249 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
250 if (pValue < 0f) pValue = 0f;
251 if (pValue > 1f) pValue = 1f;
252 m_angularDeflectionEfficiency = pValue;
253 break;
254 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
255 if (pValue < m_timestep) pValue = m_timestep;
256 m_angularDeflectionTimescale = pValue;
257 break;
258 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
259 if (pValue < m_timestep) pValue = m_timestep;
260 else if (pValue > 120) pValue = 120;
261 m_angularMotorDecayTimescale = pValue * m_invtimestep;
262 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
263 break;
264 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
265 if (pValue < m_timestep) pValue = m_timestep;
266 m_angularMotorTimescale = pValue;
267 break;
268 case Vehicle.BANKING_EFFICIENCY:
269 if (pValue < -1f) pValue = -1f;
270 if (pValue > 1f) pValue = 1f;
271 m_bankingEfficiency = pValue;
272 break;
273 case Vehicle.BANKING_MIX:
274 if (pValue < 0f) pValue = 0f;
275 if (pValue > 1f) pValue = 1f;
276 m_bankingMix = pValue;
277 break;
278 case Vehicle.BANKING_TIMESCALE:
279 if (pValue < m_timestep) pValue = m_timestep;
280 m_bankingTimescale = pValue;
281 break;
282 case Vehicle.BUOYANCY:
283 if (pValue < -1f) pValue = -1f;
284 if (pValue > 1f) pValue = 1f;
285 m_VehicleBuoyancy = pValue;
286 break;
287 case Vehicle.HOVER_EFFICIENCY:
288 if (pValue < 0f) pValue = 0f;
289 if (pValue > 1f) pValue = 1f;
290 m_VhoverEfficiency = pValue;
291 break;
292 case Vehicle.HOVER_HEIGHT:
293 m_VhoverHeight = pValue;
294 break;
295 case Vehicle.HOVER_TIMESCALE:
296 if (pValue < m_timestep) pValue = m_timestep;
297 m_VhoverTimescale = pValue;
298 break;
299 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
300 if (pValue < 0f) pValue = 0f;
301 if (pValue > 1f) pValue = 1f;
302 m_linearDeflectionEfficiency = pValue;
303 break;
304 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
305 if (pValue < m_timestep) pValue = m_timestep;
306 m_linearDeflectionTimescale = pValue;
307 break;
308 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
309 if (pValue < m_timestep) pValue = m_timestep;
310 else if (pValue > 120) pValue = 120;
311 m_linearMotorDecayTimescale = (0.2f +pValue) * m_invtimestep;
312 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
313 break;
314 case Vehicle.LINEAR_MOTOR_TIMESCALE:
315 if (pValue < m_timestep) pValue = m_timestep;
316 m_linearMotorTimescale = pValue;
317 break;
318 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
319 if (pValue < 0f) pValue = 0f;
320 if (pValue > 1f) pValue = 1f;
321 m_verticalAttractionEfficiency = pValue;
322 break;
323 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
324 if (pValue < m_timestep) pValue = m_timestep;
325 m_verticalAttractionTimescale = pValue;
326 break;
327
328 // These are vector properties but the engine lets you use a single float value to
329 // set all of the components to the same value
330 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
331 if (pValue < m_timestep) pValue = m_timestep;
332 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
333 break;
334 case Vehicle.ANGULAR_MOTOR_DIRECTION:
335 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
336 len = m_angularMotorDirection.Length();
337 if (len > 12.566f)
338 m_angularMotorDirection *= (12.566f / len);
339
340 m_amEfect = 1.0f ; // turn it on
341 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
342
343 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
344 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
345 d.BodyEnable(rootPrim.Body);
346 break;
347 case Vehicle.LINEAR_FRICTION_TIMESCALE:
348 if (pValue < m_timestep) pValue = m_timestep;
349 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
350 break;
351 case Vehicle.LINEAR_MOTOR_DIRECTION:
352 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
353 len = m_linearMotorDirection.Length();
354 if (len > 100.0f)
355 m_linearMotorDirection *= (100.0f / len);
356
357 m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale;
358 m_lmEfect = 1.0f; // turn it on
359
360 m_ffactor = 0.0f;
361 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
362 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
363 d.BodyEnable(rootPrim.Body);
364 break;
365 case Vehicle.LINEAR_MOTOR_OFFSET:
366 m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
367 len = m_linearMotorOffset.Length();
368 if (len > 100.0f)
369 m_linearMotorOffset *= (100.0f / len);
370 break;
371 }
372 }//end ProcessFloatVehicleParam
373
374 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
375 {
376 float len;
377
378 switch (pParam)
379 {
380 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
381 if (pValue.X < m_timestep) pValue.X = m_timestep;
382 if (pValue.Y < m_timestep) pValue.Y = m_timestep;
383 if (pValue.Z < m_timestep) pValue.Z = m_timestep;
384
385 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
386 break;
387 case Vehicle.ANGULAR_MOTOR_DIRECTION:
388 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
389 // Limit requested angular speed to 2 rps= 4 pi rads/sec
390 len = m_angularMotorDirection.Length();
391 if (len > 12.566f)
392 m_angularMotorDirection *= (12.566f / len);
393
394 m_amEfect = 1.0f; // turn it on
395 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
396
397 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
398 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
399 d.BodyEnable(rootPrim.Body);
400 break;
401 case Vehicle.LINEAR_FRICTION_TIMESCALE:
402 if (pValue.X < m_timestep) pValue.X = m_timestep;
403 if (pValue.Y < m_timestep) pValue.Y = m_timestep;
404 if (pValue.Z < m_timestep) pValue.Z = m_timestep;
405 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
406 break;
407 case Vehicle.LINEAR_MOTOR_DIRECTION:
408 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
409 len = m_linearMotorDirection.Length();
410 if (len > 100.0f)
411 m_linearMotorDirection *= (100.0f / len);
412
413 m_lmEfect = 1.0f; // turn it on
414 m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale;
415
416 m_ffactor = 0.0f;
417 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
418 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
419 d.BodyEnable(rootPrim.Body);
420 break;
421 case Vehicle.LINEAR_MOTOR_OFFSET:
422 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
423 len = m_linearMotorOffset.Length();
424 if (len > 100.0f)
425 m_linearMotorOffset *= (100.0f / len);
426 break;
427 case Vehicle.BLOCK_EXIT:
428 m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z);
429 break;
430 }
431 }//end ProcessVectorVehicleParam
432
433 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
434 {
435 switch (pParam)
436 {
437 case Vehicle.REFERENCE_FRAME:
438 // m_referenceFrame = Quaternion.Inverse(pValue);
439 m_referenceFrame = pValue;
440 break;
441 case Vehicle.ROLL_FRAME:
442 m_RollreferenceFrame = pValue;
443 break;
444 }
445 }//end ProcessRotationVehicleParam
446
447 internal void ProcessVehicleFlags(int pParam, bool remove)
448 {
449 if (remove)
450 {
451 m_flags &= ~((VehicleFlag)pParam);
452 }
453 else
454 {
455 m_flags |= (VehicleFlag)pParam;
456 }
457 }//end ProcessVehicleFlags
458
459 internal void ProcessTypeChange(Vehicle pType)
460 {
461 m_lmEfect = 0;
462
463 m_amEfect = 0;
464 m_ffactor = 1f;
465
466 m_linearMotorDirection = Vector3.Zero;
467 m_angularMotorDirection = Vector3.Zero;
468
469 m_BlockingEndPoint = Vector3.Zero;
470 m_RollreferenceFrame = Quaternion.Identity;
471 m_linearMotorOffset = Vector3.Zero;
472
473 m_referenceFrame = Quaternion.Identity;
474
475 // Set Defaults For Type
476 m_type = pType;
477 switch (pType)
478 {
479 case Vehicle.TYPE_NONE:
480 m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
481 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
482 m_linearMotorTimescale = 1000;
483 m_linearMotorDecayTimescale = 120 * m_invtimestep;
484 m_angularMotorTimescale = 1000;
485 m_angularMotorDecayTimescale = 1000 * m_invtimestep;
486 m_VhoverHeight = 0;
487 m_VhoverEfficiency = 1;
488 m_VhoverTimescale = 1000;
489 m_VehicleBuoyancy = 0;
490 m_linearDeflectionEfficiency = 0;
491 m_linearDeflectionTimescale = 1000;
492 m_angularDeflectionEfficiency = 0;
493 m_angularDeflectionTimescale = 1000;
494 m_bankingEfficiency = 0;
495 m_bankingMix = 1;
496 m_bankingTimescale = 1000;
497 m_verticalAttractionEfficiency = 0;
498 m_verticalAttractionTimescale = 1000;
499
500 m_flags = (VehicleFlag)0;
501 break;
502
503 case Vehicle.TYPE_SLED:
504 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
505 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
506 m_linearMotorTimescale = 1000;
507 m_linearMotorDecayTimescale = 120 * m_invtimestep;
508 m_angularMotorTimescale = 1000;
509 m_angularMotorDecayTimescale = 120 * m_invtimestep;
510 m_VhoverHeight = 0;
511 m_VhoverEfficiency = 1;
512 m_VhoverTimescale = 10;
513 m_VehicleBuoyancy = 0;
514 m_linearDeflectionEfficiency = 1;
515 m_linearDeflectionTimescale = 1;
516 m_angularDeflectionEfficiency = 0;
517 m_angularDeflectionTimescale = 10;
518 m_verticalAttractionEfficiency = 1;
519 m_verticalAttractionTimescale = 1000;
520 m_bankingEfficiency = 0;
521 m_bankingMix = 1;
522 m_bankingTimescale = 10;
523 m_flags &=
524 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
525 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
526 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
527 VehicleFlag.LIMIT_ROLL_ONLY |
528 VehicleFlag.LIMIT_MOTOR_UP);
529 break;
530
531 case Vehicle.TYPE_CAR:
532 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
533 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
534 m_linearMotorTimescale = 1;
535 m_linearMotorDecayTimescale = 60 * m_invtimestep;
536 m_angularMotorTimescale = 1;
537 m_angularMotorDecayTimescale = 0.8f * m_invtimestep;
538 m_VhoverHeight = 0;
539 m_VhoverEfficiency = 0;
540 m_VhoverTimescale = 1000;
541 m_VehicleBuoyancy = 0;
542 m_linearDeflectionEfficiency = 1;
543 m_linearDeflectionTimescale = 2;
544 m_angularDeflectionEfficiency = 0;
545 m_angularDeflectionTimescale = 10;
546 m_verticalAttractionEfficiency = 1f;
547 m_verticalAttractionTimescale = 10f;
548 m_bankingEfficiency = -0.2f;
549 m_bankingMix = 1;
550 m_bankingTimescale = 1;
551 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
552 VehicleFlag.HOVER_TERRAIN_ONLY |
553 VehicleFlag.HOVER_GLOBAL_HEIGHT);
554 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
555 VehicleFlag.LIMIT_ROLL_ONLY |
556 VehicleFlag.LIMIT_MOTOR_UP |
557 VehicleFlag.HOVER_UP_ONLY);
558 break;
559 case Vehicle.TYPE_BOAT:
560 m_linearFrictionTimescale = new Vector3(10, 3, 2);
561 m_angularFrictionTimescale = new Vector3(10, 10, 10);
562 m_linearMotorTimescale = 5;
563 m_linearMotorDecayTimescale = 60 * m_invtimestep;
564 m_angularMotorTimescale = 4;
565 m_angularMotorDecayTimescale = 4 * m_invtimestep;
566 m_VhoverHeight = 0;
567 m_VhoverEfficiency = 0.5f;
568 m_VhoverTimescale = 2;
569 m_VehicleBuoyancy = 1;
570 m_linearDeflectionEfficiency = 0.5f;
571 m_linearDeflectionTimescale = 3;
572 m_angularDeflectionEfficiency = 0.5f;
573 m_angularDeflectionTimescale = 5;
574 m_verticalAttractionEfficiency = 0.5f;
575 m_verticalAttractionTimescale = 5f;
576 m_bankingEfficiency = -0.3f;
577 m_bankingMix = 0.8f;
578 m_bankingTimescale = 1;
579 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
580 VehicleFlag.HOVER_GLOBAL_HEIGHT |
581 VehicleFlag.HOVER_UP_ONLY); // |
582// VehicleFlag.LIMIT_ROLL_ONLY);
583 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
584 VehicleFlag.LIMIT_MOTOR_UP |
585 VehicleFlag.HOVER_UP_ONLY | // new sl
586 VehicleFlag.HOVER_WATER_ONLY);
587 break;
588
589 case Vehicle.TYPE_AIRPLANE:
590 m_linearFrictionTimescale = new Vector3(200, 10, 5);
591 m_angularFrictionTimescale = new Vector3(20, 20, 20);
592 m_linearMotorTimescale = 2;
593 m_linearMotorDecayTimescale = 60 * m_invtimestep;
594 m_angularMotorTimescale = 4;
595 m_angularMotorDecayTimescale = 8 * m_invtimestep;
596 m_VhoverHeight = 0;
597 m_VhoverEfficiency = 0.5f;
598 m_VhoverTimescale = 1000;
599 m_VehicleBuoyancy = 0;
600 m_linearDeflectionEfficiency = 0.5f;
601 m_linearDeflectionTimescale = 0.5f;
602 m_angularDeflectionEfficiency = 1;
603 m_angularDeflectionTimescale = 2;
604 m_verticalAttractionEfficiency = 0.9f;
605 m_verticalAttractionTimescale = 2f;
606 m_bankingEfficiency = 1;
607 m_bankingMix = 0.7f;
608 m_bankingTimescale = 2;
609 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
610 VehicleFlag.HOVER_TERRAIN_ONLY |
611 VehicleFlag.HOVER_GLOBAL_HEIGHT |
612 VehicleFlag.HOVER_UP_ONLY |
613 VehicleFlag.NO_DEFLECTION_UP |
614 VehicleFlag.LIMIT_MOTOR_UP);
615 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
616 break;
617
618 case Vehicle.TYPE_BALLOON:
619 m_linearFrictionTimescale = new Vector3(5, 5, 5);
620 m_angularFrictionTimescale = new Vector3(10, 10, 10);
621 m_linearMotorTimescale = 5;
622 m_linearMotorDecayTimescale = 60 * m_invtimestep;
623 m_angularMotorTimescale = 6;
624 m_angularMotorDecayTimescale = 10 * m_invtimestep;
625 m_VhoverHeight = 5;
626 m_VhoverEfficiency = 0.8f;
627 m_VhoverTimescale = 10;
628 m_VehicleBuoyancy = 1;
629 m_linearDeflectionEfficiency = 0;
630 m_linearDeflectionTimescale = 5 * m_invtimestep;
631 m_angularDeflectionEfficiency = 0;
632 m_angularDeflectionTimescale = 5;
633 m_verticalAttractionEfficiency = 1f;
634 m_verticalAttractionTimescale = 1000f;
635 m_bankingEfficiency = 0;
636 m_bankingMix = 0.7f;
637 m_bankingTimescale = 5;
638 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
639 VehicleFlag.HOVER_TERRAIN_ONLY |
640 VehicleFlag.HOVER_UP_ONLY |
641 VehicleFlag.NO_DEFLECTION_UP |
642 VehicleFlag.LIMIT_MOTOR_UP | //);
643 VehicleFlag.LIMIT_ROLL_ONLY | // new sl
644 VehicleFlag.HOVER_GLOBAL_HEIGHT); // new sl
645
646// m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
647// VehicleFlag.HOVER_GLOBAL_HEIGHT);
648 break;
649
650 }
651
652 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
653 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
654
655 }//end SetDefaultsForType
656
657 internal void Stop()
658 {
659 m_lmEfect = 0;
660 m_lmDecay = 0f;
661 m_amEfect = 0;
662 m_amDecay = 0;
663 m_ffactor = 1f;
664 }
665
666 public static Vector3 Xrot(Quaternion rot)
667 {
668 Vector3 vec;
669 rot.Normalize(); // just in case
670 vec.X = 2 * (rot.X * rot.X + rot.W * rot.W) - 1;
671 vec.Y = 2 * (rot.X * rot.Y + rot.Z * rot.W);
672 vec.Z = 2 * (rot.X * rot.Z - rot.Y * rot.W);
673 return vec;
674 }
675
676 public static Vector3 Zrot(Quaternion rot)
677 {
678 Vector3 vec;
679 rot.Normalize(); // just in case
680 vec.X = 2 * (rot.X * rot.Z + rot.Y * rot.W);
681 vec.Y = 2 * (rot.Y * rot.Z - rot.X * rot.W);
682 vec.Z = 2 * (rot.Z * rot.Z + rot.W * rot.W) - 1;
683
684 return vec;
685 }
686
687 private const float pi = (float)Math.PI;
688 private const float halfpi = 0.5f * (float)Math.PI;
689 private const float twopi = 2.0f * pi;
690
691 public static Vector3 ubRot2Euler(Quaternion rot)
692 {
693 // returns roll in X
694 // pitch in Y
695 // yaw in Z
696 Vector3 vec;
697
698 // assuming rot is normalised
699 // rot.Normalize();
700
701 float zX = rot.X * rot.Z + rot.Y * rot.W;
702
703 if (zX < -0.49999f)
704 {
705 vec.X = 0;
706 vec.Y = -halfpi;
707 vec.Z = (float)(-2d * Math.Atan(rot.X / rot.W));
708 }
709 else if (zX > 0.49999f)
710 {
711 vec.X = 0;
712 vec.Y = halfpi;
713 vec.Z = (float)(2d * Math.Atan(rot.X / rot.W));
714 }
715 else
716 {
717 vec.Y = (float)Math.Asin(2 * zX);
718
719 float sqw = rot.W * rot.W;
720
721 float minuszY = rot.X * rot.W - rot.Y * rot.Z;
722 float zZ = rot.Z * rot.Z + sqw - 0.5f;
723
724 vec.X = (float)Math.Atan2(minuszY, zZ);
725
726 float yX = rot.Z * rot.W - rot.X * rot.Y; //( have negative ?)
727 float yY = rot.X * rot.X + sqw - 0.5f;
728 vec.Z = (float)Math.Atan2(yX, yY);
729 }
730 return vec;
731 }
732
733 public static void GetRollPitch(Quaternion rot, out float roll, out float pitch)
734 {
735 // assuming rot is normalised
736 // rot.Normalize();
737
738 float zX = rot.X * rot.Z + rot.Y * rot.W;
739
740 if (zX < -0.49999f)
741 {
742 roll = 0;
743 pitch = -halfpi;
744 }
745 else if (zX > 0.49999f)
746 {
747 roll = 0;
748 pitch = halfpi;
749 }
750 else
751 {
752 pitch = (float)Math.Asin(2 * zX);
753
754 float minuszY = rot.X * rot.W - rot.Y * rot.Z;
755 float zZ = rot.Z * rot.Z + rot.W * rot.W - 0.5f;
756
757 roll = (float)Math.Atan2(minuszY, zZ);
758 }
759 return ;
760 }
761
762 internal void Step()
763 {
764 IntPtr Body = rootPrim.Body;
765
766 d.Mass dmass;
767 d.BodyGetMass(Body, out dmass);
768
769 d.Quaternion rot = d.BodyGetQuaternion(Body);
770 Quaternion objrotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
771 Quaternion rotq = objrotq; // rotq = rotation of object
772 rotq *= m_referenceFrame; // rotq is now rotation in vehicle reference frame
773 Quaternion irotq = Quaternion.Inverse(rotq);
774
775 d.Vector3 dvtmp;
776 Vector3 tmpV;
777 Vector3 curVel; // velocity in world
778 Vector3 curAngVel; // angular velocity in world
779 Vector3 force = Vector3.Zero; // actually linear aceleration until mult by mass in world frame
780 Vector3 torque = Vector3.Zero;// actually angular aceleration until mult by Inertia in vehicle frame
781 d.Vector3 dtorque = new d.Vector3();
782
783 dvtmp = d.BodyGetLinearVel(Body);
784 curVel.X = dvtmp.X;
785 curVel.Y = dvtmp.Y;
786 curVel.Z = dvtmp.Z;
787 Vector3 curLocalVel = curVel * irotq; // current velocity in local
788
789 dvtmp = d.BodyGetAngularVel(Body);
790 curAngVel.X = dvtmp.X;
791 curAngVel.Y = dvtmp.Y;
792 curAngVel.Z = dvtmp.Z;
793 Vector3 curLocalAngVel = curAngVel * irotq; // current angular velocity in local
794
795 float ldampZ = 0;
796
797 // linear motor
798 if (m_lmEfect > 0.01 && m_linearMotorTimescale < 1000)
799 {
800 tmpV = m_linearMotorDirection - curLocalVel; // velocity error
801 tmpV *= m_lmEfect / m_linearMotorTimescale; // error to correct in this timestep
802 tmpV *= rotq; // to world
803
804 if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0)
805 tmpV.Z = 0;
806
807 if (m_linearMotorOffset.X != 0 || m_linearMotorOffset.Y != 0 || m_linearMotorOffset.Z != 0)
808 {
809 // have offset, do it now
810 tmpV *= dmass.mass;
811 d.BodyAddForceAtRelPos(Body, tmpV.X, tmpV.Y, tmpV.Z, m_linearMotorOffset.X, m_linearMotorOffset.Y, m_linearMotorOffset.Z);
812 }
813 else
814 {
815 force.X += tmpV.X;
816 force.Y += tmpV.Y;
817 force.Z += tmpV.Z;
818 }
819
820 m_lmEfect *= m_lmDecay;
821// m_ffactor = 0.01f + 1e-4f * curVel.LengthSquared();
822 m_ffactor = 0.0f;
823 }
824 else
825 {
826 m_lmEfect = 0;
827 m_ffactor = 1f;
828 }
829
830 // hover
831 if (m_VhoverTimescale < 300 && rootPrim.prim_geom != IntPtr.Zero)
832 {
833 // d.Vector3 pos = d.BodyGetPosition(Body);
834 d.Vector3 pos = d.GeomGetPosition(rootPrim.prim_geom);
835 pos.Z -= 0.21f; // minor offset that seems to be always there in sl
836
837 float t = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
838 float perr;
839
840 // default to global but don't go underground
841 perr = m_VhoverHeight - pos.Z;
842
843 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == 0)
844 {
845 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
846 {
847 perr += _pParentScene.GetWaterLevel();
848 }
849 else if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
850 {
851 perr += t;
852 }
853 else
854 {
855 float w = _pParentScene.GetWaterLevel();
856 if (t > w)
857 perr += t;
858 else
859 perr += w;
860 }
861 }
862 else if (t > m_VhoverHeight)
863 perr = t - pos.Z; ;
864
865 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) == 0 || perr > -0.1)
866 {
867 ldampZ = m_VhoverEfficiency * m_invtimestep;
868
869 perr *= (1.0f + ldampZ) / m_VhoverTimescale;
870
871 // force.Z += perr - curVel.Z * tmp;
872 force.Z += perr;
873 ldampZ *= -curVel.Z;
874
875 force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
876 }
877 else // no buoyancy
878 force.Z += _pParentScene.gravityz;
879 }
880 else
881 {
882 // default gravity and Buoyancy
883 force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
884 }
885
886 // linear deflection
887 if (m_linearDeflectionEfficiency > 0)
888 {
889 float len = curVel.Length();
890 if (len > 0.01) // if moving
891 {
892 Vector3 atAxis;
893 atAxis = Xrot(rotq); // where are we pointing to
894 atAxis *= len; // make it same size as world velocity vector
895
896 tmpV = -atAxis; // oposite direction
897 atAxis -= curVel; // error to one direction
898 len = atAxis.LengthSquared();
899
900 tmpV -= curVel; // error to oposite
901 float lens = tmpV.LengthSquared();
902
903 if (len > 0.01 || lens > 0.01) // do nothing if close enougth
904 {
905 if (len < lens)
906 tmpV = atAxis;
907
908 tmpV *= (m_linearDeflectionEfficiency / m_linearDeflectionTimescale); // error to correct in this timestep
909 force.X += tmpV.X;
910 force.Y += tmpV.Y;
911 if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) == 0)
912 force.Z += tmpV.Z;
913 }
914 }
915 }
916
917 // linear friction/damping
918 if (curLocalVel.X != 0 || curLocalVel.Y != 0 || curLocalVel.Z != 0)
919 {
920 tmpV.X = -curLocalVel.X / m_linearFrictionTimescale.X;
921 tmpV.Y = -curLocalVel.Y / m_linearFrictionTimescale.Y;
922 tmpV.Z = -curLocalVel.Z / m_linearFrictionTimescale.Z;
923 tmpV *= rotq; // to world
924
925 if(ldampZ != 0 && Math.Abs(ldampZ) > Math.Abs(tmpV.Z))
926 tmpV.Z = ldampZ;
927 force.X += tmpV.X;
928 force.Y += tmpV.Y;
929 force.Z += tmpV.Z;
930 }
931
932 // vertical atractor
933 if (m_verticalAttractionTimescale < 300)
934 {
935 float roll;
936 float pitch;
937
938
939
940 float ftmp = m_invtimestep / m_verticalAttractionTimescale / m_verticalAttractionTimescale;
941
942 float ftmp2;
943 ftmp2 = 0.5f * m_verticalAttractionEfficiency * m_invtimestep;
944 m_amdampX = ftmp2;
945
946 m_ampwr = 1.0f - 0.8f * m_verticalAttractionEfficiency;
947
948 GetRollPitch(irotq, out roll, out pitch);
949
950 if (roll > halfpi)
951 roll = pi - roll;
952 else if (roll < -halfpi)
953 roll = -pi - roll;
954
955 float effroll = pitch / halfpi;
956 effroll *= effroll;
957 effroll = 1 - effroll;
958 effroll *= roll;
959
960
961 torque.X += effroll * ftmp;
962
963 if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) == 0)
964 {
965 float effpitch = roll / halfpi;
966 effpitch *= effpitch;
967 effpitch = 1 - effpitch;
968 effpitch *= pitch;
969
970 torque.Y += effpitch * ftmp;
971 }
972
973 if (m_bankingEfficiency != 0 && Math.Abs(effroll) > 0.01)
974 {
975
976 float broll = effroll;
977 /*
978 if (broll > halfpi)
979 broll = pi - broll;
980 else if (broll < -halfpi)
981 broll = -pi - broll;
982 */
983 broll *= m_bankingEfficiency;
984 if (m_bankingMix != 0)
985 {
986 float vfact = Math.Abs(curLocalVel.X) / 10.0f;
987 if (vfact > 1.0f) vfact = 1.0f;
988
989 if (curLocalVel.X >= 0)
990 broll *= (1 + (vfact - 1) * m_bankingMix);
991 else
992 broll *= -(1 + (vfact - 1) * m_bankingMix);
993 }
994 // make z rot be in world Z not local as seems to be in sl
995
996 broll = broll / m_bankingTimescale;
997
998
999 tmpV = Zrot(irotq);
1000 tmpV *= broll;
1001
1002 torque.X += tmpV.X;
1003 torque.Y += tmpV.Y;
1004 torque.Z += tmpV.Z;
1005
1006 m_amdampZ = Math.Abs(m_bankingEfficiency) / m_bankingTimescale;
1007 m_amdampY = m_amdampZ;
1008
1009 }
1010 else
1011 {
1012 m_amdampZ = 1 / m_angularFrictionTimescale.Z;
1013 m_amdampY = m_amdampX;
1014 }
1015 }
1016 else
1017 {
1018 m_ampwr = 1.0f;
1019 m_amdampX = 1 / m_angularFrictionTimescale.X;
1020 m_amdampY = 1 / m_angularFrictionTimescale.Y;
1021 m_amdampZ = 1 / m_angularFrictionTimescale.Z;
1022 }
1023
1024 // angular motor
1025 if (m_amEfect > 0.01 && m_angularMotorTimescale < 1000)
1026 {
1027 tmpV = m_angularMotorDirection - curLocalAngVel; // velocity error
1028 tmpV *= m_amEfect / m_angularMotorTimescale; // error to correct in this timestep
1029 torque.X += tmpV.X * m_ampwr;
1030 torque.Y += tmpV.Y * m_ampwr;
1031 torque.Z += tmpV.Z;
1032
1033 m_amEfect *= m_amDecay;
1034 }
1035 else
1036 m_amEfect = 0;
1037
1038 // angular deflection
1039 if (m_angularDeflectionEfficiency > 0)
1040 {
1041 Vector3 dirv;
1042
1043 if (curLocalVel.X > 0.01f)
1044 dirv = curLocalVel;
1045 else if (curLocalVel.X < -0.01f)
1046 // use oposite
1047 dirv = -curLocalVel;
1048 else
1049 {
1050 // make it fall into small positive x case
1051 dirv.X = 0.01f;
1052 dirv.Y = curLocalVel.Y;
1053 dirv.Z = curLocalVel.Z;
1054 }
1055
1056 float ftmp = m_angularDeflectionEfficiency / m_angularDeflectionTimescale;
1057
1058 if (Math.Abs(dirv.Z) > 0.01)
1059 {
1060 torque.Y += - (float)Math.Atan2(dirv.Z, dirv.X) * ftmp;
1061 }
1062
1063 if (Math.Abs(dirv.Y) > 0.01)
1064 {
1065 torque.Z += (float)Math.Atan2(dirv.Y, dirv.X) * ftmp;
1066 }
1067 }
1068
1069 // angular friction
1070 if (curLocalAngVel.X != 0 || curLocalAngVel.Y != 0 || curLocalAngVel.Z != 0)
1071 {
1072 torque.X -= curLocalAngVel.X * m_amdampX;
1073 torque.Y -= curLocalAngVel.Y * m_amdampY;
1074 torque.Z -= curLocalAngVel.Z * m_amdampZ;
1075 }
1076
1077
1078 if (force.X != 0 || force.Y != 0 || force.Z != 0)
1079 {
1080 force *= dmass.mass;
1081 d.BodyAddForce(Body, force.X, force.Y, force.Z);
1082 }
1083
1084 if (torque.X != 0 || torque.Y != 0 || torque.Z != 0)
1085 {
1086 torque *= m_referenceFrame; // to object frame
1087 dtorque.X = torque.X ;
1088 dtorque.Y = torque.Y;
1089 dtorque.Z = torque.Z;
1090
1091 d.MultiplyM3V3(out dvtmp, ref dmass.I, ref dtorque);
1092 d.BodyAddRelTorque(Body, dvtmp.X, dvtmp.Y, dvtmp.Z); // add torque in object frame
1093 }
1094 }
1095 }
1096}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs
new file mode 100644
index 0000000..40b5ef7
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs
@@ -0,0 +1,933 @@
1/*
2 * AJLDuarte 2012
3 */
4
5using System;
6using System.Threading;
7using System.Collections.Generic;
8using System.IO;
9using System.Reflection;
10using System.Runtime.InteropServices;
11using System.Text;
12using OpenSim.Framework;
13using OpenSim.Region.PhysicsModules.SharedBase;
14using OdeAPI;
15using log4net;
16using Nini.Config;
17using OpenMetaverse;
18
19namespace OpenSim.Region.PhysicsModule.ubOde
20{
21 public enum MeshState : byte
22 {
23 noNeed = 0,
24
25 loadingAsset = 1,
26
27 AssetOK = 0x0f, // 00001111
28
29 NeedMask = 0x30, // 00110000
30 needMesh = 0x10, // 00010000
31 needAsset = 0x20, // 00100000
32
33 FailMask = 0xC0, // 11000000
34 AssetFailed = 0x40, // 01000000
35 MeshFailed = 0x80, // 10000000
36
37 MeshNoColide = FailMask | needAsset
38 }
39
40 public enum meshWorkerCmnds : byte
41 {
42 nop = 0,
43 addnew,
44 changefull,
45 changesize,
46 changeshapetype,
47 getmesh,
48 }
49
50 public class ODEPhysRepData
51 {
52 public PhysicsActor actor;
53 public PrimitiveBaseShape pbs;
54 public IMesh mesh;
55
56 public Vector3 size;
57 public Vector3 OBB;
58 public Vector3 OBBOffset;
59
60 public float volume;
61
62 public byte shapetype;
63 public bool hasOBB;
64 public bool hasMeshVolume;
65 public MeshState meshState;
66 public UUID? assetID;
67 public meshWorkerCmnds comand;
68 }
69
70 public class ODEMeshWorker
71 {
72
73 private ILog m_log;
74 private ODEScene m_scene;
75 private IMesher m_mesher;
76
77 public bool meshSculptedPrim = true;
78 public bool forceSimplePrimMeshing = false;
79 public float meshSculptLOD = 32;
80 public float MeshSculptphysicalLOD = 32;
81
82
83 private OpenSim.Framework.BlockingQueue<ODEPhysRepData> createqueue = new OpenSim.Framework.BlockingQueue<ODEPhysRepData>();
84 private bool m_running;
85
86 private Thread m_thread;
87
88 public ODEMeshWorker(ODEScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig)
89 {
90 m_scene = pScene;
91 m_log = pLog;
92 m_mesher = pMesher;
93
94 if (pConfig != null)
95 {
96 forceSimplePrimMeshing = pConfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
97 meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
98 meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
99 MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
100 }
101 m_running = true;
102 m_thread = new Thread(DoWork);
103 m_thread.Name = "OdeMeshWorker";
104 m_thread.Start();
105 }
106
107 private void DoWork()
108 {
109 m_mesher.ExpireFileCache();
110
111 while(m_running)
112 {
113 ODEPhysRepData nextRep = createqueue.Dequeue();
114 if(!m_running)
115 return;
116 if (nextRep == null)
117 continue;
118 if (m_scene.haveActor(nextRep.actor))
119 {
120 switch (nextRep.comand)
121 {
122 case meshWorkerCmnds.changefull:
123 case meshWorkerCmnds.changeshapetype:
124 case meshWorkerCmnds.changesize:
125 GetMesh(nextRep);
126 if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
127 m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
128 break;
129 case meshWorkerCmnds.getmesh:
130 DoRepDataGetMesh(nextRep);
131 break;
132 }
133 }
134 }
135 }
136
137 public void Stop()
138 {
139 try
140 {
141 m_thread.Abort();
142 createqueue.Clear();
143 }
144 catch
145 {
146 }
147 }
148
149 public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
150 Vector3 size, byte shapetype)
151 {
152 ODEPhysRepData repData = new ODEPhysRepData();
153 repData.actor = actor;
154 repData.pbs = pbs;
155 repData.size = size;
156 repData.shapetype = shapetype;
157
158 CheckMesh(repData);
159 CalcVolumeData(repData);
160 m_scene.AddChange(actor, changes.PhysRepData, repData);
161 return;
162 }
163
164 public ODEPhysRepData NewActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
165 Vector3 size, byte shapetype)
166 {
167 ODEPhysRepData repData = new ODEPhysRepData();
168 repData.actor = actor;
169 repData.pbs = pbs;
170 repData.size = size;
171 repData.shapetype = shapetype;
172
173 CheckMesh(repData);
174 CalcVolumeData(repData);
175 m_scene.AddChange(actor, changes.AddPhysRep, repData);
176 return repData;
177 }
178
179 public void RequestMesh(ODEPhysRepData repData)
180 {
181 repData.mesh = null;
182
183 if (repData.meshState == MeshState.needAsset)
184 {
185 PrimitiveBaseShape pbs = repData.pbs;
186
187 // check if we got outdated
188
189 if (!pbs.SculptEntry || pbs.SculptTexture == UUID.Zero)
190 {
191 repData.meshState = MeshState.noNeed;
192 return;
193 }
194
195 repData.assetID = pbs.SculptTexture;
196 repData.meshState = MeshState.loadingAsset;
197
198 repData.comand = meshWorkerCmnds.getmesh;
199 createqueue.Enqueue(repData);
200 }
201 }
202
203 // creates and prepares a mesh to use and calls parameters estimation
204 public bool CreateActorPhysRep(ODEPhysRepData repData)
205 {
206 IMesh mesh = repData.mesh;
207
208 if (mesh != null)
209 {
210 IntPtr vertices, indices;
211 int vertexCount, indexCount;
212 int vertexStride, triStride;
213
214 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
215 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
216
217 if (vertexCount == 0 || indexCount == 0)
218 {
219 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}",
220 repData.actor.Name, repData.pbs.SculptTexture.ToString());
221 repData.meshState = MeshState.MeshFailed;
222 repData.hasOBB = false;
223 repData.mesh = null;
224 m_scene.mesher.ReleaseMesh(mesh);
225 }
226 else
227 {
228 repData.OBBOffset = mesh.GetCentroid();
229 repData.OBB = mesh.GetOBB();
230 repData.hasOBB = true;
231 mesh.releaseSourceMeshData();
232 }
233 }
234 CalcVolumeData(repData);
235 return true;
236 }
237
238 public void AssetLoaded(ODEPhysRepData repData)
239 {
240 if (m_scene.haveActor(repData.actor))
241 {
242 if (needsMeshing(repData.pbs)) // no need for pbs now?
243 {
244 repData.comand = meshWorkerCmnds.changefull;
245 createqueue.Enqueue(repData);
246 }
247 }
248 else
249 repData.pbs.SculptData = Utils.EmptyBytes;
250 }
251
252 public void DoRepDataGetMesh(ODEPhysRepData repData)
253 {
254 if (!repData.pbs.SculptEntry)
255 return;
256
257 if (repData.meshState != MeshState.loadingAsset)
258 return;
259
260 if (repData.assetID == null || repData.assetID == UUID.Zero)
261 return;
262
263 if (repData.assetID != repData.pbs.SculptTexture)
264 return;
265
266 // check if it is in cache
267 GetMesh(repData);
268 if (repData.meshState != MeshState.needAsset)
269 {
270 CreateActorPhysRep(repData);
271 m_scene.AddChange(repData.actor, changes.PhysRepData, repData);
272 return;
273 }
274
275 RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
276 if (assetProvider == null)
277 return;
278 ODEAssetRequest asr = new ODEAssetRequest(this, assetProvider, repData, m_log);
279 }
280
281
282 /// <summary>
283 /// Routine to figure out if we need to mesh this prim with our mesher
284 /// </summary>
285 /// <param name="pbs"></param>
286 /// <returns></returns>
287 public bool needsMeshing(PrimitiveBaseShape pbs)
288 {
289 // check sculpts or meshs
290 if (pbs.SculptEntry)
291 {
292 if (meshSculptedPrim)
293 return true;
294
295 if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
296 return true;
297
298 return false;
299 }
300
301 if (forceSimplePrimMeshing)
302 return true;
303
304 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
305
306 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
307 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
308 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
309 {
310
311 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
312 && pbs.ProfileHollow == 0
313 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
314 && pbs.PathBegin == 0 && pbs.PathEnd == 0
315 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
316 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
317 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
318 {
319 return false;
320 }
321 }
322
323 // following code doesn't give meshs to boxes and spheres ever
324 // and it's odd.. so for now just return true if asked to force meshs
325 // hopefully mesher will fail if doesn't suport so things still get basic boxes
326
327 int iPropertiesNotSupportedDefault = 0;
328
329 if (pbs.ProfileHollow != 0)
330 iPropertiesNotSupportedDefault++;
331
332 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
333 iPropertiesNotSupportedDefault++;
334
335 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
336 iPropertiesNotSupportedDefault++;
337
338 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
339 iPropertiesNotSupportedDefault++;
340
341 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
342 iPropertiesNotSupportedDefault++;
343
344 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
345 iPropertiesNotSupportedDefault++;
346
347 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
348 iPropertiesNotSupportedDefault++;
349
350 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
351 iPropertiesNotSupportedDefault++;
352
353 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
354 iPropertiesNotSupportedDefault++;
355
356 // test for torus
357 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
358 {
359 if (pbs.PathCurve == (byte)Extrusion.Curve1)
360 {
361 iPropertiesNotSupportedDefault++;
362 }
363 }
364 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
365 {
366 if (pbs.PathCurve == (byte)Extrusion.Straight)
367 {
368 iPropertiesNotSupportedDefault++;
369 }
370
371 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
372 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
373 {
374 iPropertiesNotSupportedDefault++;
375 }
376 }
377 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
378 {
379 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
380 {
381 iPropertiesNotSupportedDefault++;
382 }
383 }
384 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
385 {
386 if (pbs.PathCurve == (byte)Extrusion.Straight)
387 {
388 iPropertiesNotSupportedDefault++;
389 }
390 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
391 {
392 iPropertiesNotSupportedDefault++;
393 }
394 }
395
396 if (iPropertiesNotSupportedDefault == 0)
397 {
398 return false;
399 }
400 return true;
401 }
402
403 // see if we need a mesh and if so if we have a cached one
404 // called with a new repData
405 public void CheckMesh(ODEPhysRepData repData)
406 {
407 PhysicsActor actor = repData.actor;
408 PrimitiveBaseShape pbs = repData.pbs;
409
410 if (!needsMeshing(pbs))
411 {
412 repData.meshState = MeshState.noNeed;
413 return;
414 }
415
416 IMesh mesh = null;
417
418 Vector3 size = repData.size;
419 byte shapetype = repData.shapetype;
420
421 bool convex;
422
423 int clod = (int)LevelOfDetail.High;
424 if (shapetype == 0)
425 convex = false;
426 else
427 {
428 convex = true;
429 if (pbs.SculptType != (byte)SculptType.Mesh)
430 clod = (int)LevelOfDetail.Low;
431 }
432
433 mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
434
435 if (mesh == null)
436 {
437 if (pbs.SculptEntry)
438 {
439 if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero)
440 {
441 repData.assetID = pbs.SculptTexture;
442 repData.meshState = MeshState.needAsset;
443 }
444 else
445 repData.meshState = MeshState.MeshFailed;
446
447 return;
448 }
449 else
450 {
451 repData.meshState = MeshState.needMesh;
452 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
453 if (mesh == null)
454 {
455 repData.meshState = MeshState.MeshFailed;
456 return;
457 }
458 }
459 }
460
461 repData.meshState = MeshState.AssetOK;
462 repData.mesh = mesh;
463
464 if (pbs.SculptEntry)
465 {
466 repData.assetID = pbs.SculptTexture;
467 }
468
469 pbs.SculptData = Utils.EmptyBytes;
470 return ;
471 }
472
473 public void GetMesh(ODEPhysRepData repData)
474 {
475 PhysicsActor actor = repData.actor;
476
477 PrimitiveBaseShape pbs = repData.pbs;
478
479 repData.mesh = null;
480 repData.hasOBB = false;
481
482 if (!needsMeshing(pbs))
483 {
484 repData.meshState = MeshState.noNeed;
485 return;
486 }
487
488 if (repData.meshState == MeshState.MeshFailed)
489 return;
490
491 if (pbs.SculptEntry)
492 {
493 if (repData.meshState == MeshState.AssetFailed)
494 {
495 if (pbs.SculptTexture == repData.assetID)
496 return;
497 }
498 }
499
500 repData.meshState = MeshState.noNeed;
501
502 IMesh mesh = null;
503 Vector3 size = repData.size;
504 byte shapetype = repData.shapetype;
505
506 bool convex;
507 int clod = (int)LevelOfDetail.High;
508 if (shapetype == 0)
509 convex = false;
510 else
511 {
512 convex = true;
513 if (pbs.SculptType != (byte)SculptType.Mesh)
514 clod = (int)LevelOfDetail.Low;
515 }
516
517 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
518
519 if (mesh == null)
520 {
521 if (pbs.SculptEntry)
522 {
523 if (pbs.SculptTexture == UUID.Zero)
524 return;
525
526 repData.assetID = pbs.SculptTexture;
527
528 if (pbs.SculptData == null || pbs.SculptData.Length == 0)
529 {
530 repData.meshState = MeshState.needAsset;
531 return;
532 }
533 }
534 }
535
536 repData.mesh = mesh;
537 repData.pbs.SculptData = Utils.EmptyBytes;
538
539 if (mesh == null)
540 {
541 if (pbs.SculptEntry)
542 repData.meshState = MeshState.AssetFailed;
543 else
544 repData.meshState = MeshState.MeshFailed;
545
546 return;
547 }
548
549 repData.meshState = MeshState.AssetOK;
550
551 return;
552 }
553
554 private void CalculateBasicPrimVolume(ODEPhysRepData repData)
555 {
556 PrimitiveBaseShape _pbs = repData.pbs;
557 Vector3 _size = repData.size;
558
559 float volume = _size.X * _size.Y * _size.Z; // default
560 float tmp;
561
562 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
563 float hollowVolume = hollowAmount * hollowAmount;
564
565 switch (_pbs.ProfileShape)
566 {
567 case ProfileShape.Square:
568 // default box
569
570 if (_pbs.PathCurve == (byte)Extrusion.Straight)
571 {
572 if (hollowAmount > 0.0)
573 {
574 switch (_pbs.HollowShape)
575 {
576 case HollowShape.Square:
577 case HollowShape.Same:
578 break;
579
580 case HollowShape.Circle:
581
582 hollowVolume *= 0.78539816339f;
583 break;
584
585 case HollowShape.Triangle:
586
587 hollowVolume *= (0.5f * .5f);
588 break;
589
590 default:
591 hollowVolume = 0;
592 break;
593 }
594 volume *= (1.0f - hollowVolume);
595 }
596 }
597
598 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
599 {
600 //a tube
601
602 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
603 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
604 volume -= volume * tmp * tmp;
605
606 if (hollowAmount > 0.0)
607 {
608 hollowVolume *= hollowAmount;
609
610 switch (_pbs.HollowShape)
611 {
612 case HollowShape.Square:
613 case HollowShape.Same:
614 break;
615
616 case HollowShape.Circle:
617 hollowVolume *= 0.78539816339f;
618 break;
619
620 case HollowShape.Triangle:
621 hollowVolume *= 0.5f * 0.5f;
622 break;
623 default:
624 hollowVolume = 0;
625 break;
626 }
627 volume *= (1.0f - hollowVolume);
628 }
629 }
630
631 break;
632
633 case ProfileShape.Circle:
634
635 if (_pbs.PathCurve == (byte)Extrusion.Straight)
636 {
637 volume *= 0.78539816339f; // elipse base
638
639 if (hollowAmount > 0.0)
640 {
641 switch (_pbs.HollowShape)
642 {
643 case HollowShape.Same:
644 case HollowShape.Circle:
645 break;
646
647 case HollowShape.Square:
648 hollowVolume *= 0.5f * 2.5984480504799f;
649 break;
650
651 case HollowShape.Triangle:
652 hollowVolume *= .5f * 1.27323954473516f;
653 break;
654
655 default:
656 hollowVolume = 0;
657 break;
658 }
659 volume *= (1.0f - hollowVolume);
660 }
661 }
662
663 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
664 {
665 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
666 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
667 volume *= (1.0f - tmp * tmp);
668
669 if (hollowAmount > 0.0)
670 {
671
672 // calculate the hollow volume by it's shape compared to the prim shape
673 hollowVolume *= hollowAmount;
674
675 switch (_pbs.HollowShape)
676 {
677 case HollowShape.Same:
678 case HollowShape.Circle:
679 break;
680
681 case HollowShape.Square:
682 hollowVolume *= 0.5f * 2.5984480504799f;
683 break;
684
685 case HollowShape.Triangle:
686 hollowVolume *= .5f * 1.27323954473516f;
687 break;
688
689 default:
690 hollowVolume = 0;
691 break;
692 }
693 volume *= (1.0f - hollowVolume);
694 }
695 }
696 break;
697
698 case ProfileShape.HalfCircle:
699 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
700 {
701 volume *= 0.5236f;
702
703 if (hollowAmount > 0.0)
704 {
705 hollowVolume *= hollowAmount;
706
707 switch (_pbs.HollowShape)
708 {
709 case HollowShape.Circle:
710 case HollowShape.Triangle: // diference in sl is minor and odd
711 case HollowShape.Same:
712 break;
713
714 case HollowShape.Square:
715 hollowVolume *= 0.909f;
716 break;
717
718 // case HollowShape.Triangle:
719 // hollowVolume *= .827f;
720 // break;
721 default:
722 hollowVolume = 0;
723 break;
724 }
725 volume *= (1.0f - hollowVolume);
726 }
727
728 }
729 break;
730
731 case ProfileShape.EquilateralTriangle:
732
733 if (_pbs.PathCurve == (byte)Extrusion.Straight)
734 {
735 volume *= 0.32475953f;
736
737 if (hollowAmount > 0.0)
738 {
739
740 // calculate the hollow volume by it's shape compared to the prim shape
741 switch (_pbs.HollowShape)
742 {
743 case HollowShape.Same:
744 case HollowShape.Triangle:
745 hollowVolume *= .25f;
746 break;
747
748 case HollowShape.Square:
749 hollowVolume *= 0.499849f * 3.07920140172638f;
750 break;
751
752 case HollowShape.Circle:
753 // Hollow shape is a perfect cyllinder in respect to the cube's scale
754 // Cyllinder hollow volume calculation
755
756 hollowVolume *= 0.1963495f * 3.07920140172638f;
757 break;
758
759 default:
760 hollowVolume = 0;
761 break;
762 }
763 volume *= (1.0f - hollowVolume);
764 }
765 }
766 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
767 {
768 volume *= 0.32475953f;
769 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
770 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
771 volume *= (1.0f - tmp * tmp);
772
773 if (hollowAmount > 0.0)
774 {
775
776 hollowVolume *= hollowAmount;
777
778 switch (_pbs.HollowShape)
779 {
780 case HollowShape.Same:
781 case HollowShape.Triangle:
782 hollowVolume *= .25f;
783 break;
784
785 case HollowShape.Square:
786 hollowVolume *= 0.499849f * 3.07920140172638f;
787 break;
788
789 case HollowShape.Circle:
790
791 hollowVolume *= 0.1963495f * 3.07920140172638f;
792 break;
793
794 default:
795 hollowVolume = 0;
796 break;
797 }
798 volume *= (1.0f - hollowVolume);
799 }
800 }
801 break;
802
803 default:
804 break;
805 }
806
807 float taperX1;
808 float taperY1;
809 float taperX;
810 float taperY;
811 float pathBegin;
812 float pathEnd;
813 float profileBegin;
814 float profileEnd;
815
816 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
817 {
818 taperX1 = _pbs.PathScaleX * 0.01f;
819 if (taperX1 > 1.0f)
820 taperX1 = 2.0f - taperX1;
821 taperX = 1.0f - taperX1;
822
823 taperY1 = _pbs.PathScaleY * 0.01f;
824 if (taperY1 > 1.0f)
825 taperY1 = 2.0f - taperY1;
826 taperY = 1.0f - taperY1;
827 }
828 else
829 {
830 taperX = _pbs.PathTaperX * 0.01f;
831 if (taperX < 0.0f)
832 taperX = -taperX;
833 taperX1 = 1.0f - taperX;
834
835 taperY = _pbs.PathTaperY * 0.01f;
836 if (taperY < 0.0f)
837 taperY = -taperY;
838 taperY1 = 1.0f - taperY;
839 }
840
841 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
842
843 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
844 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
845 volume *= (pathEnd - pathBegin);
846
847 // this is crude aproximation
848 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
849 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
850 volume *= (profileEnd - profileBegin);
851
852 repData.volume = volume;
853 }
854
855 private void CalcVolumeData(ODEPhysRepData repData)
856 {
857 if (repData.hasOBB)
858 {
859 Vector3 OBB = repData.OBB;
860 }
861 else
862 {
863 Vector3 OBB = repData.size;
864 OBB.X *= 0.5f;
865 OBB.Y *= 0.5f;
866 OBB.Z *= 0.5f;
867
868 repData.OBB = OBB;
869 repData.OBBOffset = Vector3.Zero;
870 }
871
872 CalculateBasicPrimVolume(repData);
873 }
874 }
875
876 public class ODEAssetRequest
877 {
878 ODEMeshWorker m_worker;
879 private ILog m_log;
880 ODEPhysRepData repData;
881
882 public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
883 ODEPhysRepData pRepData, ILog plog)
884 {
885 m_worker = pWorker;
886 m_log = plog;
887 repData = pRepData;
888
889 repData.meshState = MeshState.AssetFailed;
890 if (provider == null)
891 return;
892
893 if (repData.assetID == null)
894 return;
895
896 UUID assetID = (UUID) repData.assetID;
897 if (assetID == UUID.Zero)
898 return;
899
900 repData.meshState = MeshState.loadingAsset;
901 provider(assetID, ODEassetReceived);
902 }
903
904 void ODEassetReceived(AssetBase asset)
905 {
906 repData.meshState = MeshState.AssetFailed;
907 if (asset != null)
908 {
909 if (asset.Data != null && asset.Data.Length > 0)
910 {
911 repData.meshState = MeshState.noNeed;
912
913 if (!repData.pbs.SculptEntry)
914 return;
915 if (repData.pbs.SculptTexture != repData.assetID)
916 return;
917
918// repData.pbs.SculptData = new byte[asset.Data.Length];
919// asset.Data.CopyTo(repData.pbs.SculptData,0);
920 repData.pbs.SculptData = asset.Data;
921 repData.meshState = MeshState.AssetOK;
922 m_worker.AssetLoaded(repData);
923 }
924 else
925 m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
926 repData.actor.Name, asset.ID.ToString());
927 }
928 else
929 m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.",
930 repData.actor.Name);
931 }
932 }
933}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs
new file mode 100644
index 0000000..bd66b4d
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs
@@ -0,0 +1,97 @@
1using System;
2using System.Reflection;
3using log4net;
4using Nini.Config;
5using Mono.Addins;
6using OdeAPI;
7using OpenSim.Framework;
8using OpenSim.Region.Framework.Scenes;
9using OpenSim.Region.Framework.Interfaces;
10
11namespace OpenSim.Region.PhysicsModule.ubOde
12{
13 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ubODEPhysicsScene")]
14 class ubOdeModule : INonSharedRegionModule
15 {
16 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
17
18 private bool m_Enabled = false;
19 private IConfigSource m_config;
20 private ODEScene m_scene;
21 private bool OSOdeLib;
22
23 #region INonSharedRegionModule
24
25 public string Name
26 {
27 get { return "ubODE"; }
28 }
29
30 public Type ReplaceableInterface
31 {
32 get { return null; }
33 }
34
35 public void Initialise(IConfigSource source)
36 {
37 IConfig config = source.Configs["Startup"];
38 if (config != null)
39 {
40 string physics = config.GetString("physics", string.Empty);
41 if (physics == Name)
42 {
43 m_config = source;
44 m_Enabled = true;
45 }
46 }
47 }
48
49 public void Close()
50 {
51 }
52
53 public void AddRegion(Scene scene)
54 {
55 if (!m_Enabled)
56 return;
57
58 if (Util.IsWindows())
59 Util.LoadArchSpecificWindowsDll("ode.dll");
60
61 // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to
62 // http://opensimulator.org/mantis/view.php?id=2750).
63 d.InitODE();
64
65 string ode_config = d.GetConfiguration();
66 if (ode_config != null && ode_config != "")
67 {
68 m_log.InfoFormat("[ubODE] ode library configuration: {0}", ode_config);
69 // ubODE still not avaiable
70 if (ode_config.Contains("ODE_OPENSIM"))
71 {
72 OSOdeLib = true;
73 }
74 }
75
76 m_scene = new ODEScene(scene, m_config, Name, OSOdeLib);
77 }
78
79 public void RemoveRegion(Scene scene)
80 {
81 if (!m_Enabled || m_scene == null)
82 return;
83
84 m_scene.Dispose();
85 m_scene = null;
86 }
87
88 public void RegionLoaded(Scene scene)
89 {
90 if (!m_Enabled || m_scene == null)
91 return;
92
93 m_scene.RegionLoaded();
94 }
95 #endregion
96 }
97}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
new file mode 100644
index 0000000..7d57cb4
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
@@ -0,0 +1,3958 @@
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
28/*
29 * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces
30 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
31 * ODEPrim.cs contains methods dealing with Prim editing, Prim
32 * characteristics and Kinetic motion.
33 * ODEDynamics.cs contains methods dealing with Prim Physical motion
34 * (dynamics) and the associated settings. Old Linear and angular
35 * motors for dynamic motion have been replace with MoveLinear()
36 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
37 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
38 * switch between 'VEHICLE' parameter use and general dynamics
39 * settings use.
40 */
41
42//#define SPAM
43
44using System;
45using System.Collections.Generic;
46using System.Reflection;
47using System.Runtime.InteropServices;
48using System.Threading;
49using log4net;
50using OpenMetaverse;
51using OdeAPI;
52using OpenSim.Framework;
53using OpenSim.Region.PhysicsModules.SharedBase;
54
55namespace OpenSim.Region.PhysicsModule.ubOde
56{
57 public class OdePrim : PhysicsActor
58 {
59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60
61 private bool m_isphysical;
62 private bool m_fakeisphysical;
63 private bool m_isphantom;
64 private bool m_fakeisphantom;
65 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
66 private bool m_fakeisVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
67
68 protected bool m_building;
69 protected bool m_forcePosOrRotation;
70 private bool m_iscolliding;
71
72 internal bool m_isSelected;
73 private bool m_delaySelect;
74 private bool m_lastdoneSelected;
75 internal bool m_outbounds;
76
77 private byte m_angularlocks = 0;
78
79 private Quaternion m_lastorientation;
80 private Quaternion _orientation;
81
82 private Vector3 _position;
83 private Vector3 _velocity;
84 private Vector3 m_torque;
85 private Vector3 m_lastVelocity;
86 private Vector3 m_lastposition;
87 private Vector3 m_rotationalVelocity;
88 private Vector3 _size;
89 private Vector3 _acceleration;
90 private IntPtr Amotor;
91
92 private Vector3 m_force;
93 private Vector3 m_forceacc;
94 private Vector3 m_angularForceacc;
95
96 private float m_invTimeStep;
97 private float m_timeStep;
98
99 private Vector3 m_PIDTarget;
100 private float m_PIDTau;
101 private bool m_usePID;
102
103 private float m_PIDHoverHeight;
104 private float m_PIDHoverTau;
105 private bool m_useHoverPID;
106 private PIDHoverType m_PIDHoverType;
107 private float m_targetHoverHeight;
108 private float m_groundHeight;
109 private float m_waterHeight;
110 private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
111
112 private int body_autodisable_frames;
113 public int bodydisablecontrol = 0;
114 private float m_gravmod = 1.0f;
115
116 // Default we're a Geometry
117 private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
118 // Default colide nonphysical don't try to colide with anything
119 private const CollisionCategories m_default_collisionFlagsNotPhysical = 0;
120
121 private const CollisionCategories m_default_collisionFlagsPhysical = (CollisionCategories.Geom |
122 CollisionCategories.Character |
123 CollisionCategories.Land |
124 CollisionCategories.VolumeDtc);
125
126// private bool m_collidesLand = true;
127 private bool m_collidesWater;
128// public bool m_returnCollisions;
129
130 private bool m_NoColide; // for now only for internal use for bad meshs
131
132
133 // Default, Collide with Other Geometries, spaces and Bodies
134 private CollisionCategories m_collisionFlags = m_default_collisionFlagsNotPhysical;
135
136 public bool m_disabled;
137
138 private uint m_localID;
139
140 private IMesh m_mesh;
141 private object m_meshlock = new object();
142 private PrimitiveBaseShape _pbs;
143
144 private UUID? m_assetID;
145 private MeshState m_meshState;
146
147 public ODEScene _parent_scene;
148
149 /// <summary>
150 /// The physics space which contains prim geometry
151 /// </summary>
152 public IntPtr m_targetSpace;
153
154 public IntPtr prim_geom;
155 public IntPtr _triMeshData;
156
157 private PhysicsActor _parent;
158
159 private List<OdePrim> childrenPrim = new List<OdePrim>();
160
161 public float m_collisionscore;
162 private int m_colliderfilter = 0;
163
164 public IntPtr collide_geom; // for objects: geom if single prim space it linkset
165
166 private float m_density;
167 private byte m_shapetype;
168 public bool _zeroFlag;
169 private bool m_lastUpdateSent;
170
171 public IntPtr Body;
172
173 private Vector3 _target_velocity;
174
175 public Vector3 m_OBBOffset;
176 public Vector3 m_OBB;
177 public float primOOBradiusSQ;
178
179 private bool m_hasOBB = true;
180
181 private float m_physCost;
182 private float m_streamCost;
183
184 public d.Mass primdMass; // prim inertia information on it's own referencial
185 float primMass; // prim own mass
186 float primVolume; // prim own volume;
187 float _mass; // object mass acording to case
188
189 public int givefakepos;
190 private Vector3 fakepos;
191 public int givefakeori;
192 private Quaternion fakeori;
193
194 private int m_eventsubscription;
195 private int m_cureventsubscription;
196 private CollisionEventUpdate CollisionEventsThisFrame = null;
197 private bool SentEmptyCollisionsEvent;
198
199 public volatile bool childPrim;
200
201 public ODEDynamics m_vehicle;
202
203 internal int m_material = (int)Material.Wood;
204 private float mu;
205 private float bounce;
206
207 /// <summary>
208 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
209 /// </summary>
210 public override bool IsPhysical // this is not reliable for internal use
211 {
212 get { return m_fakeisphysical; }
213 set
214 {
215 m_fakeisphysical = value; // we show imediatly to outside that we changed physical
216 // and also to stop imediatly some updates
217 // but real change will only happen in taintprocessing
218
219 if (!value) // Zero the remembered last velocity
220 m_lastVelocity = Vector3.Zero;
221 AddChange(changes.Physical, value);
222 }
223 }
224
225 public override bool IsVolumeDtc
226 {
227 get { return m_fakeisVolumeDetect; }
228 set
229 {
230 m_fakeisVolumeDetect = value;
231 AddChange(changes.VolumeDtc, value);
232 }
233 }
234
235 public override bool Phantom // this is not reliable for internal use
236 {
237 get { return m_fakeisphantom; }
238 set
239 {
240 m_fakeisphantom = value;
241 AddChange(changes.Phantom, value);
242 }
243 }
244
245 public override bool Building // this is not reliable for internal use
246 {
247 get { return m_building; }
248 set
249 {
250// if (value)
251// m_building = true;
252 AddChange(changes.building, value);
253 }
254 }
255
256 public override void getContactData(ref ContactData cdata)
257 {
258 cdata.mu = mu;
259 cdata.bounce = bounce;
260
261 // cdata.softcolide = m_softcolide;
262 cdata.softcolide = false;
263
264 if (m_isphysical)
265 {
266 ODEDynamics veh;
267 if (_parent != null)
268 veh = ((OdePrim)_parent).m_vehicle;
269 else
270 veh = m_vehicle;
271
272 if (veh != null && veh.Type != Vehicle.TYPE_NONE)
273 cdata.mu *= veh.FrictionFactor;
274// cdata.mu *= 0;
275 }
276 }
277
278 public override float PhysicsCost
279 {
280 get
281 {
282 return m_physCost;
283 }
284 }
285
286 public override float StreamCost
287 {
288 get
289 {
290 return m_streamCost;
291 }
292 }
293
294 public override int PhysicsActorType
295 {
296 get { return (int)ActorTypes.Prim; }
297 set { return; }
298 }
299
300 public override bool SetAlwaysRun
301 {
302 get { return false; }
303 set { return; }
304 }
305
306 public override uint LocalID
307 {
308 get { return m_localID; }
309 set { m_localID = value; }
310 }
311
312 public override PhysicsActor ParentActor
313 {
314 get
315 {
316 if (childPrim)
317 return _parent;
318 else
319 return (PhysicsActor)this;
320 }
321 }
322
323 public override bool Grabbed
324 {
325 set { return; }
326 }
327
328 public override bool Selected
329 {
330 set
331 {
332 if (value)
333 m_isSelected = value; // if true set imediatly to stop moves etc
334 AddChange(changes.Selected, value);
335 }
336 }
337
338 public override bool Flying
339 {
340 // no flying prims for you
341 get { return false; }
342 set { }
343 }
344
345 public override bool IsColliding
346 {
347 get { return m_iscolliding; }
348 set
349 {
350 if (value)
351 {
352 m_colliderfilter += 2;
353 if (m_colliderfilter > 2)
354 m_colliderfilter = 2;
355 }
356 else
357 {
358 m_colliderfilter--;
359 if (m_colliderfilter < 0)
360 m_colliderfilter = 0;
361 }
362
363 if (m_colliderfilter == 0)
364 m_iscolliding = false;
365 else
366 m_iscolliding = true;
367 }
368 }
369
370 public override bool CollidingGround
371 {
372 get { return false; }
373 set { return; }
374 }
375
376 public override bool CollidingObj
377 {
378 get { return false; }
379 set { return; }
380 }
381
382
383 public override bool ThrottleUpdates {get;set;}
384
385 public override bool Stopped
386 {
387 get { return _zeroFlag; }
388 }
389
390 public override Vector3 Position
391 {
392 get
393 {
394 if (givefakepos > 0)
395 return fakepos;
396 else
397 return _position;
398 }
399
400 set
401 {
402 fakepos = value;
403 givefakepos++;
404 AddChange(changes.Position, value);
405 }
406 }
407
408 public override Vector3 Size
409 {
410 get { return _size; }
411 set
412 {
413 if (value.IsFinite())
414 {
415 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, value, m_shapetype);
416 }
417 else
418 {
419 m_log.WarnFormat("[PHYSICS]: Got NaN Size on object {0}", Name);
420 }
421 }
422 }
423
424 public override float Mass
425 {
426 get { return primMass; }
427 }
428
429 public override Vector3 Force
430 {
431 get { return m_force; }
432 set
433 {
434 if (value.IsFinite())
435 {
436 AddChange(changes.Force, value);
437 }
438 else
439 {
440 m_log.WarnFormat("[PHYSICS]: NaN in Force Applied to an Object {0}", Name);
441 }
442 }
443 }
444
445 public override void SetVolumeDetect(int param)
446 {
447 m_fakeisVolumeDetect = (param != 0);
448 AddChange(changes.VolumeDtc, m_fakeisVolumeDetect);
449 }
450
451 public override Vector3 GeometricCenter
452 {
453 // this is not real geometric center but a average of positions relative to root prim acording to
454 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
455 // ignoring tortured prims details since sl also seems to ignore
456 // so no real use in doing it on physics
457 get
458 {
459 return Vector3.Zero;
460 }
461 }
462
463 public override Vector3 CenterOfMass
464 {
465 get
466 {
467 lock (_parent_scene.OdeLock)
468 {
469 d.Vector3 dtmp;
470 if (!childPrim && Body != IntPtr.Zero)
471 {
472 dtmp = d.BodyGetPosition(Body);
473 return new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
474 }
475 else if (prim_geom != IntPtr.Zero)
476 {
477 d.Quaternion dq;
478 d.GeomCopyQuaternion(prim_geom, out dq);
479 Quaternion q;
480 q.X = dq.X;
481 q.Y = dq.Y;
482 q.Z = dq.Z;
483 q.W = dq.W;
484
485 Vector3 Ptot = m_OBBOffset * q;
486 dtmp = d.GeomGetPosition(prim_geom);
487 Ptot.X += dtmp.X;
488 Ptot.Y += dtmp.Y;
489 Ptot.Z += dtmp.Z;
490
491 // if(childPrim) we only know about physical linksets
492 return Ptot;
493/*
494 float tmass = _mass;
495 Ptot *= tmass;
496
497 float m;
498
499 foreach (OdePrim prm in childrenPrim)
500 {
501 m = prm._mass;
502 Ptot += prm.CenterOfMass * m;
503 tmass += m;
504 }
505
506 if (tmass == 0)
507 tmass = 0;
508 else
509 tmass = 1.0f / tmass;
510
511 Ptot *= tmass;
512 return Ptot;
513*/
514 }
515 else
516 return _position;
517 }
518 }
519 }
520
521 public override Vector3 OOBsize
522 {
523 get
524 {
525 return m_OBB;
526 }
527 }
528
529 public override Vector3 OOBoffset
530 {
531 get
532 {
533 return m_OBBOffset;
534 }
535 }
536
537 public override float OOBRadiusSQ
538 {
539 get
540 {
541 return primOOBradiusSQ;
542 }
543 }
544
545 public override PrimitiveBaseShape Shape
546 {
547 set
548 {
549// AddChange(changes.Shape, value);
550 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, value, _size, m_shapetype);
551 }
552 }
553
554 public override byte PhysicsShapeType
555 {
556 get
557 {
558 return m_shapetype;
559 }
560 set
561 {
562 m_shapetype = value;
563 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, _size, value);
564 }
565 }
566
567 public override Vector3 Velocity
568 {
569 get
570 {
571 if (_zeroFlag)
572 return Vector3.Zero;
573 return _velocity;
574 }
575 set
576 {
577 if (value.IsFinite())
578 {
579 AddChange(changes.Velocity, value);
580 }
581 else
582 {
583 m_log.WarnFormat("[PHYSICS]: Got NaN Velocity in Object {0}", Name);
584 }
585
586 }
587 }
588
589 public override Vector3 Torque
590 {
591 get
592 {
593 if (!IsPhysical || Body == IntPtr.Zero)
594 return Vector3.Zero;
595
596 return m_torque;
597 }
598
599 set
600 {
601 if (value.IsFinite())
602 {
603 AddChange(changes.Torque, value);
604 }
605 else
606 {
607 m_log.WarnFormat("[PHYSICS]: Got NaN Torque in Object {0}", Name);
608 }
609 }
610 }
611
612 public override float CollisionScore
613 {
614 get { return m_collisionscore; }
615 set { m_collisionscore = value; }
616 }
617
618 public override bool Kinematic
619 {
620 get { return false; }
621 set { }
622 }
623
624 public override Quaternion Orientation
625 {
626 get
627 {
628 if (givefakeori > 0)
629 return fakeori;
630 else
631
632 return _orientation;
633 }
634 set
635 {
636 if (QuaternionIsFinite(value))
637 {
638 fakeori = value;
639 givefakeori++;
640
641 value.Normalize();
642
643 AddChange(changes.Orientation, value);
644 }
645 else
646 m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name);
647
648 }
649 }
650
651 public override Vector3 Acceleration
652 {
653 get { return _acceleration; }
654 set { }
655 }
656
657 public override Vector3 RotationalVelocity
658 {
659 get
660 {
661 Vector3 pv = Vector3.Zero;
662 if (_zeroFlag)
663 return pv;
664
665 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f))
666 return pv;
667
668 return m_rotationalVelocity;
669 }
670 set
671 {
672 if (value.IsFinite())
673 {
674 AddChange(changes.AngVelocity, value);
675 }
676 else
677 {
678 m_log.WarnFormat("[PHYSICS]: Got NaN RotationalVelocity in Object {0}", Name);
679 }
680 }
681 }
682
683 public override float Buoyancy
684 {
685 get { return m_buoyancy; }
686 set
687 {
688 AddChange(changes.Buoyancy,value);
689 }
690 }
691
692 public override bool FloatOnWater
693 {
694 set
695 {
696 AddChange(changes.CollidesWater, value);
697 }
698 }
699
700 public override Vector3 PIDTarget
701 {
702 set
703 {
704 if (value.IsFinite())
705 {
706 AddChange(changes.PIDTarget,value);
707 }
708 else
709 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name);
710 }
711 }
712
713 public override bool PIDActive
714 {
715 get
716 {
717 return m_usePID;
718 }
719 set
720 {
721 AddChange(changes.PIDActive,value);
722 }
723 }
724
725 public override float PIDTau
726 {
727 set
728 {
729 float tmp = 0;
730 if (value > 0)
731 {
732 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
733 if (value < mint)
734 tmp = mint;
735 else
736 tmp = value;
737 }
738 AddChange(changes.PIDTau,tmp);
739 }
740 }
741
742 public override float PIDHoverHeight
743 {
744 set
745 {
746 AddChange(changes.PIDHoverHeight,value);
747 }
748 }
749 public override bool PIDHoverActive
750 {
751 get
752 {
753 return m_useHoverPID;
754 }
755 set
756 {
757 AddChange(changes.PIDHoverActive, value);
758 }
759 }
760
761 public override PIDHoverType PIDHoverType
762 {
763 set
764 {
765 AddChange(changes.PIDHoverType,value);
766 }
767 }
768
769 public override float PIDHoverTau
770 {
771 set
772 {
773 float tmp =0;
774 if (value > 0)
775 {
776 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
777 if (value < mint)
778 tmp = mint;
779 else
780 tmp = value;
781 }
782 AddChange(changes.PIDHoverTau, tmp);
783 }
784 }
785
786 public override Quaternion APIDTarget { set { return; } }
787
788 public override bool APIDActive { set { return; } }
789
790 public override float APIDStrength { set { return; } }
791
792 public override float APIDDamping { set { return; } }
793
794 public override int VehicleType
795 {
796 // we may need to put a fake on this
797 get
798 {
799 if (m_vehicle == null)
800 return (int)Vehicle.TYPE_NONE;
801 else
802 return (int)m_vehicle.Type;
803 }
804 set
805 {
806 AddChange(changes.VehicleType, value);
807 }
808 }
809
810 public override void VehicleFloatParam(int param, float value)
811 {
812 strVehicleFloatParam fp = new strVehicleFloatParam();
813 fp.param = param;
814 fp.value = value;
815 AddChange(changes.VehicleFloatParam, fp);
816 }
817
818 public override void VehicleVectorParam(int param, Vector3 value)
819 {
820 strVehicleVectorParam fp = new strVehicleVectorParam();
821 fp.param = param;
822 fp.value = value;
823 AddChange(changes.VehicleVectorParam, fp);
824 }
825
826 public override void VehicleRotationParam(int param, Quaternion value)
827 {
828 strVehicleQuatParam fp = new strVehicleQuatParam();
829 fp.param = param;
830 fp.value = value;
831 AddChange(changes.VehicleRotationParam, fp);
832 }
833
834 public override void VehicleFlags(int param, bool value)
835 {
836 strVehicleBoolParam bp = new strVehicleBoolParam();
837 bp.param = param;
838 bp.value = value;
839 AddChange(changes.VehicleFlags, bp);
840 }
841
842 public override void SetVehicle(object vdata)
843 {
844 AddChange(changes.SetVehicle, vdata);
845 }
846 public void SetAcceleration(Vector3 accel)
847 {
848 _acceleration = accel;
849 }
850
851 public override void AddForce(Vector3 force, bool pushforce)
852 {
853 if (force.IsFinite())
854 {
855 if(pushforce)
856 AddChange(changes.AddForce, force);
857 else // a impulse
858 AddChange(changes.AddForce, force * m_invTimeStep);
859 }
860 else
861 {
862 m_log.WarnFormat("[PHYSICS]: Got Invalid linear force vector from Scene in Object {0}", Name);
863 }
864 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
865 }
866
867 public override void AddAngularForce(Vector3 force, bool pushforce)
868 {
869 if (force.IsFinite())
870 {
871// if(pushforce) for now applyrotationimpulse seems more happy applied as a force
872 AddChange(changes.AddAngForce, force);
873// else // a impulse
874// AddChange(changes.AddAngForce, force * m_invTimeStep);
875 }
876 else
877 {
878 m_log.WarnFormat("[PHYSICS]: Got Invalid Angular force vector from Scene in Object {0}", Name);
879 }
880 }
881
882 public override void CrossingFailure()
883 {
884 if (m_outbounds)
885 {
886 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f);
887 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f);
888 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
889
890 m_lastposition = _position;
891 _velocity.X = 0;
892 _velocity.Y = 0;
893 _velocity.Z = 0;
894
895 m_lastVelocity = _velocity;
896 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
897 m_vehicle.Stop();
898
899 if(Body != IntPtr.Zero)
900 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
901 if (prim_geom != IntPtr.Zero)
902 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
903
904 m_outbounds = false;
905 changeDisable(false);
906 base.RequestPhysicsterseUpdate();
907 }
908 }
909
910 public override void SetMomentum(Vector3 momentum)
911 {
912 }
913
914 public override void SetMaterial(int pMaterial)
915 {
916 m_material = pMaterial;
917 mu = _parent_scene.m_materialContactsData[pMaterial].mu;
918 bounce = _parent_scene.m_materialContactsData[pMaterial].bounce;
919 }
920
921 public override float Density
922 {
923 get
924 {
925 return m_density * 100f;
926 }
927 set
928 {
929 m_density = value / 100f;
930 // for not prim mass is not updated since this implies full rebuild of body inertia TODO
931 }
932 }
933 public override float GravModifier
934 {
935 get
936 {
937 return m_gravmod;
938 }
939 set
940 {
941 m_gravmod = value;
942 if (m_vehicle != null)
943 m_vehicle.GravMod = m_gravmod;
944 }
945 }
946 public override float Friction
947 {
948 get
949 {
950 return mu;
951 }
952 set
953 {
954 mu = value;
955 }
956 }
957
958 public override float Restitution
959 {
960 get
961 {
962 return bounce;
963 }
964 set
965 {
966 bounce = value;
967 }
968 }
969
970 public void setPrimForRemoval()
971 {
972 AddChange(changes.Remove, null);
973 }
974
975 public override void link(PhysicsActor obj)
976 {
977 AddChange(changes.Link, obj);
978 }
979
980 public override void delink()
981 {
982 AddChange(changes.DeLink, null);
983 }
984
985 public override void LockAngularMotion(byte axislock)
986 {
987// m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
988 AddChange(changes.AngLock, axislock);
989
990 }
991
992 public override void SubscribeEvents(int ms)
993 {
994 m_eventsubscription = ms;
995 m_cureventsubscription = 0;
996 if (CollisionEventsThisFrame == null)
997 CollisionEventsThisFrame = new CollisionEventUpdate();
998 SentEmptyCollisionsEvent = false;
999 }
1000
1001 public override void UnSubscribeEvents()
1002 {
1003 if (CollisionEventsThisFrame != null)
1004 {
1005 CollisionEventsThisFrame.Clear();
1006 CollisionEventsThisFrame = null;
1007 }
1008 m_eventsubscription = 0;
1009 _parent_scene.RemoveCollisionEventReporting(this);
1010 }
1011
1012 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1013 {
1014 if (CollisionEventsThisFrame == null)
1015 CollisionEventsThisFrame = new CollisionEventUpdate();
1016// if(CollisionEventsThisFrame.Count < 32)
1017 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
1018 }
1019
1020 public void SendCollisions()
1021 {
1022 if (CollisionEventsThisFrame == null)
1023 return;
1024
1025 if (m_cureventsubscription < m_eventsubscription)
1026 return;
1027
1028 m_cureventsubscription = 0;
1029
1030 int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count;
1031
1032 if (!SentEmptyCollisionsEvent || ncolisions > 0)
1033 {
1034 base.SendCollisionUpdate(CollisionEventsThisFrame);
1035
1036 if (ncolisions == 0)
1037 {
1038 SentEmptyCollisionsEvent = true;
1039 _parent_scene.RemoveCollisionEventReporting(this);
1040 }
1041 else
1042 {
1043 SentEmptyCollisionsEvent = false;
1044 CollisionEventsThisFrame.Clear();
1045 }
1046 }
1047 }
1048
1049 internal void AddCollisionFrameTime(int t)
1050 {
1051 if (m_cureventsubscription < 50000)
1052 m_cureventsubscription += t;
1053 }
1054
1055 public override bool SubscribedEvents()
1056 {
1057 if (m_eventsubscription > 0)
1058 return true;
1059 return false;
1060 }
1061
1062 public OdePrim(String primName, ODEScene parent_scene, Vector3 pos, Vector3 size,
1063 Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical,bool pisPhantom,byte _shapeType,uint plocalID)
1064 {
1065 Name = primName;
1066 LocalID = plocalID;
1067
1068 m_vehicle = null;
1069
1070 if (!pos.IsFinite())
1071 {
1072 pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
1073 parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
1074 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Position for {0}", Name);
1075 }
1076 _position = pos;
1077 givefakepos = 0;
1078
1079 m_timeStep = parent_scene.ODE_STEPSIZE;
1080 m_invTimeStep = 1f / m_timeStep;
1081
1082 m_density = parent_scene.geomDefaultDensity;
1083 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
1084
1085 prim_geom = IntPtr.Zero;
1086 collide_geom = IntPtr.Zero;
1087 Body = IntPtr.Zero;
1088
1089 if (!size.IsFinite())
1090 {
1091 size = new Vector3(0.5f, 0.5f, 0.5f);
1092 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Size for {0}", Name);
1093 }
1094
1095 if (size.X <= 0) size.X = 0.01f;
1096 if (size.Y <= 0) size.Y = 0.01f;
1097 if (size.Z <= 0) size.Z = 0.01f;
1098
1099 _size = size;
1100
1101 if (!QuaternionIsFinite(rotation))
1102 {
1103 rotation = Quaternion.Identity;
1104 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Rotation for {0}", Name);
1105 }
1106
1107 _orientation = rotation;
1108 givefakeori = 0;
1109
1110 _pbs = pbs;
1111
1112 _parent_scene = parent_scene;
1113 m_targetSpace = IntPtr.Zero;
1114
1115 if (pos.Z < 0)
1116 {
1117 m_isphysical = false;
1118 }
1119 else
1120 {
1121 m_isphysical = pisPhysical;
1122 }
1123 m_fakeisphysical = m_isphysical;
1124
1125 m_isVolumeDetect = false;
1126 m_fakeisVolumeDetect = false;
1127
1128 m_force = Vector3.Zero;
1129
1130 m_iscolliding = false;
1131 m_colliderfilter = 0;
1132 m_NoColide = false;
1133
1134 _triMeshData = IntPtr.Zero;
1135
1136 m_shapetype = _shapeType;
1137
1138 m_lastdoneSelected = false;
1139 m_isSelected = false;
1140 m_delaySelect = false;
1141
1142 m_isphantom = pisPhantom;
1143 m_fakeisphantom = pisPhantom;
1144
1145 mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
1146 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
1147
1148 m_building = true; // control must set this to false when done
1149
1150 // get basic mass parameters
1151 ODEPhysRepData repData = _parent_scene.m_meshWorker.NewActorPhysRep(this, _pbs, _size, m_shapetype);
1152
1153 primVolume = repData.volume;
1154 m_OBB = repData.OBB;
1155 m_OBBOffset = repData.OBBOffset;
1156
1157 UpdatePrimBodyData();
1158 }
1159
1160 private void resetCollisionAccounting()
1161 {
1162 m_collisionscore = 0;
1163 }
1164
1165 private void UpdateCollisionCatFlags()
1166 {
1167 if(m_isphysical && m_disabled)
1168 {
1169 m_collisionCategories = 0;
1170 m_collisionFlags = 0;
1171 }
1172
1173 else if (m_isSelected)
1174 {
1175 m_collisionCategories = CollisionCategories.Selected;
1176 m_collisionFlags = 0;
1177 }
1178
1179 else if (m_isVolumeDetect)
1180 {
1181 m_collisionCategories = CollisionCategories.VolumeDtc;
1182 if (m_isphysical)
1183 m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character;
1184 else
1185 m_collisionFlags = 0;
1186 }
1187 else if (m_isphantom)
1188 {
1189 m_collisionCategories = CollisionCategories.Phantom;
1190 if (m_isphysical)
1191 m_collisionFlags = CollisionCategories.Land;
1192 else
1193 m_collisionFlags = 0;
1194 }
1195 else
1196 {
1197 m_collisionCategories = CollisionCategories.Geom;
1198 if (m_isphysical)
1199 m_collisionFlags = m_default_collisionFlagsPhysical;
1200 else
1201 m_collisionFlags = m_default_collisionFlagsNotPhysical;
1202 }
1203 }
1204
1205 private void ApplyCollisionCatFlags()
1206 {
1207 if (prim_geom != IntPtr.Zero)
1208 {
1209 if (!childPrim && childrenPrim.Count > 0)
1210 {
1211 foreach (OdePrim prm in childrenPrim)
1212 {
1213 if (m_isphysical && m_disabled)
1214 {
1215 prm.m_collisionCategories = 0;
1216 prm.m_collisionFlags = 0;
1217 }
1218 else
1219 {
1220 // preserve some
1221 if (prm.m_isSelected)
1222 {
1223 prm.m_collisionCategories = CollisionCategories.Selected;
1224 prm.m_collisionFlags = 0;
1225 }
1226 else if (prm.m_isVolumeDetect)
1227 {
1228 prm.m_collisionCategories = CollisionCategories.VolumeDtc;
1229 if (m_isphysical)
1230 prm.m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character;
1231 else
1232 prm.m_collisionFlags = 0;
1233 }
1234 else if (prm.m_isphantom)
1235 {
1236 prm.m_collisionCategories = CollisionCategories.Phantom;
1237 if (m_isphysical)
1238 prm.m_collisionFlags = CollisionCategories.Land;
1239 else
1240 prm.m_collisionFlags = 0;
1241 }
1242 else
1243 {
1244 prm.m_collisionCategories = m_collisionCategories;
1245 prm.m_collisionFlags = m_collisionFlags;
1246 }
1247 }
1248
1249 if (prm.prim_geom != IntPtr.Zero)
1250 {
1251 if (prm.m_NoColide)
1252 {
1253 d.GeomSetCategoryBits(prm.prim_geom, 0);
1254 if (m_isphysical)
1255 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
1256 else
1257 d.GeomSetCollideBits(prm.prim_geom, 0);
1258 }
1259 else
1260 {
1261 d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
1262 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
1263 }
1264 }
1265 }
1266 }
1267
1268 if (m_NoColide)
1269 {
1270 d.GeomSetCategoryBits(prim_geom, 0);
1271 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
1272 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
1273 {
1274 d.GeomSetCategoryBits(collide_geom, 0);
1275 d.GeomSetCollideBits(collide_geom, (uint)CollisionCategories.Land);
1276 }
1277 }
1278 else
1279 {
1280 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1281 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1282 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
1283 {
1284 d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories);
1285 d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags);
1286 }
1287 }
1288 }
1289 }
1290
1291 private void createAMotor(byte axislock)
1292 {
1293 if (Body == IntPtr.Zero)
1294 return;
1295
1296 if (Amotor != IntPtr.Zero)
1297 {
1298 d.JointDestroy(Amotor);
1299 Amotor = IntPtr.Zero;
1300 }
1301
1302 int axisnum = 0;
1303 bool axisX = false;
1304 bool axisY = false;
1305 bool axisZ = false;
1306 if((axislock & 0x02) != 0)
1307 {
1308 axisnum++;
1309 axisX = true;
1310 }
1311 if((axislock & 0x04) != 0)
1312 {
1313 axisnum++;
1314 axisY = true;
1315 }
1316 if((axislock & 0x08) != 0)
1317 {
1318 axisnum++;
1319 axisZ = true;
1320 }
1321
1322 if(axisnum == 0)
1323 return;
1324 // stop it
1325 d.BodySetTorque(Body, 0, 0, 0);
1326 d.BodySetAngularVel(Body, 0, 0, 0);
1327
1328 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
1329 d.JointAttach(Amotor, Body, IntPtr.Zero);
1330
1331 d.JointSetAMotorMode(Amotor, 0);
1332
1333 d.JointSetAMotorNumAxes(Amotor, axisnum);
1334
1335 // get current orientation to lock
1336
1337 d.Quaternion dcur = d.BodyGetQuaternion(Body);
1338 Quaternion curr; // crap convertion between identical things
1339 curr.X = dcur.X;
1340 curr.Y = dcur.Y;
1341 curr.Z = dcur.Z;
1342 curr.W = dcur.W;
1343 Vector3 ax;
1344
1345 int i = 0;
1346 int j = 0;
1347 if (axisX)
1348 {
1349 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X
1350 d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z);
1351 d.JointSetAMotorAngle(Amotor, 0, 0);
1352 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, 0f);
1353 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0f);
1354 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
1355 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
1356 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
1357 d.JointSetAMotorParam(Amotor, (int)d.JointParam.CFM, 0f);
1358 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
1359 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f);
1360 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f);
1361 i++;
1362 j = 256; // move to next axis set
1363 }
1364
1365 if (axisY)
1366 {
1367 ax = (new Vector3(0, 1, 0)) * curr;
1368 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1369 d.JointSetAMotorAngle(Amotor, i, 0);
1370 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
1371 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
1372 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1373 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1374 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1375 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
1376 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1377 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1378 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1379 i++;
1380 j += 256;
1381 }
1382
1383 if (axisZ)
1384 {
1385 ax = (new Vector3(0, 0, 1)) * curr;
1386 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1387 d.JointSetAMotorAngle(Amotor, i, 0);
1388 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
1389 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
1390 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1391 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1392 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1393 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
1394 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1395 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1396 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1397 }
1398 }
1399
1400
1401 private void SetGeom(IntPtr geom)
1402 {
1403 prim_geom = geom;
1404 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
1405 if (prim_geom != IntPtr.Zero)
1406 {
1407
1408 if (m_NoColide)
1409 {
1410 d.GeomSetCategoryBits(prim_geom, 0);
1411 if (m_isphysical)
1412 {
1413 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
1414 }
1415 else
1416 {
1417 d.GeomSetCollideBits(prim_geom, 0);
1418 d.GeomDisable(prim_geom);
1419 }
1420 }
1421 else
1422 {
1423 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1424 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1425 }
1426
1427 UpdatePrimBodyData();
1428 _parent_scene.actor_name_map[prim_geom] = this;
1429
1430/*
1431// debug
1432 d.AABB aabb;
1433 d.GeomGetAABB(prim_geom, out aabb);
1434 float x = aabb.MaxX - aabb.MinX;
1435 float y = aabb.MaxY - aabb.MinY;
1436 float z = aabb.MaxZ - aabb.MinZ;
1437 if( x > 60.0f || y > 60.0f || z > 60.0f)
1438 m_log.WarnFormat("[PHYSICS]: large prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}",
1439 Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString());
1440 else if (x < 0.001f || y < 0.001f || z < 0.001f)
1441 m_log.WarnFormat("[PHYSICS]: small prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}",
1442 Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString());
1443*/
1444
1445 }
1446 else
1447 m_log.Warn("Setting bad Geom");
1448 }
1449
1450 private bool GetMeshGeom()
1451 {
1452 IntPtr vertices, indices;
1453 int vertexCount, indexCount;
1454 int vertexStride, triStride;
1455
1456 IMesh mesh = m_mesh;
1457
1458 if (mesh == null)
1459 return false;
1460
1461 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
1462 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
1463
1464 if (vertexCount == 0 || indexCount == 0)
1465 {
1466 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on OdePrim {0}, mesh {1} at {2}",
1467 Name, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh",_position.ToString());
1468
1469 m_hasOBB = false;
1470 m_OBBOffset = Vector3.Zero;
1471 m_OBB = _size * 0.5f;
1472
1473 m_physCost = 0.1f;
1474 m_streamCost = 1.0f;
1475
1476 _parent_scene.mesher.ReleaseMesh(mesh);
1477 m_meshState = MeshState.MeshFailed;
1478 m_mesh = null;
1479 return false;
1480 }
1481
1482 IntPtr geo = IntPtr.Zero;
1483
1484 try
1485 {
1486 _triMeshData = d.GeomTriMeshDataCreate();
1487
1488 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1489 d.GeomTriMeshDataPreprocess(_triMeshData);
1490
1491 geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null);
1492 }
1493
1494 catch (Exception e)
1495 {
1496 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e);
1497 if (_triMeshData != IntPtr.Zero)
1498 {
1499 try
1500 {
1501 d.GeomTriMeshDataDestroy(_triMeshData);
1502 }
1503 catch
1504 {
1505 }
1506 }
1507 _triMeshData = IntPtr.Zero;
1508
1509 m_hasOBB = false;
1510 m_OBBOffset = Vector3.Zero;
1511 m_OBB = _size * 0.5f;
1512 m_physCost = 0.1f;
1513 m_streamCost = 1.0f;
1514
1515 _parent_scene.mesher.ReleaseMesh(mesh);
1516 m_meshState = MeshState.MeshFailed;
1517 m_mesh = null;
1518 return false;
1519 }
1520
1521 m_physCost = 0.0013f * (float)indexCount;
1522 // todo
1523 m_streamCost = 1.0f;
1524
1525 SetGeom(geo);
1526
1527 return true;
1528 }
1529
1530 private void CreateGeom()
1531 {
1532 bool hasMesh = false;
1533
1534 m_NoColide = false;
1535
1536 if ((m_meshState & MeshState.MeshNoColide) != 0)
1537 m_NoColide = true;
1538
1539 else if(m_mesh != null)
1540 {
1541 if (GetMeshGeom())
1542 hasMesh = true;
1543 else
1544 m_NoColide = true;
1545 }
1546
1547
1548 if (!hasMesh)
1549 {
1550 IntPtr geo = IntPtr.Zero;
1551
1552 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1
1553 && _size.X == _size.Y && _size.Y == _size.Z)
1554 { // it's a sphere
1555 try
1556 {
1557 geo = d.CreateSphere(m_targetSpace, _size.X * 0.5f);
1558 }
1559 catch (Exception e)
1560 {
1561 m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e);
1562 return;
1563 }
1564 }
1565 else
1566 {// do it as a box
1567 try
1568 {
1569 geo = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1570 }
1571 catch (Exception e)
1572 {
1573 m_log.Warn("[PHYSICS]: Create box failed: {0}", e);
1574 return;
1575 }
1576 }
1577 m_physCost = 0.1f;
1578 m_streamCost = 1.0f;
1579 SetGeom(geo);
1580 }
1581 }
1582
1583 private void RemoveGeom()
1584 {
1585 if (prim_geom != IntPtr.Zero)
1586 {
1587 _parent_scene.actor_name_map.Remove(prim_geom);
1588
1589 try
1590 {
1591 d.GeomDestroy(prim_geom);
1592 if (_triMeshData != IntPtr.Zero)
1593 {
1594 d.GeomTriMeshDataDestroy(_triMeshData);
1595 _triMeshData = IntPtr.Zero;
1596 }
1597 }
1598 catch (Exception e)
1599 {
1600 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e);
1601 }
1602
1603 prim_geom = IntPtr.Zero;
1604 collide_geom = IntPtr.Zero;
1605 m_targetSpace = IntPtr.Zero;
1606 }
1607 else
1608 {
1609 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name);
1610 }
1611
1612 lock (m_meshlock)
1613 {
1614 if (m_mesh != null)
1615 {
1616 _parent_scene.mesher.ReleaseMesh(m_mesh);
1617 m_mesh = null;
1618 }
1619 }
1620
1621 Body = IntPtr.Zero;
1622 m_hasOBB = false;
1623 }
1624
1625 //sets non physical prim m_targetSpace to right space in spaces grid for static prims
1626 // should only be called for non physical prims unless they are becoming non physical
1627 private void SetInStaticSpace(OdePrim prim)
1628 {
1629 IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace);
1630 prim.m_targetSpace = targetSpace;
1631 collide_geom = IntPtr.Zero;
1632 }
1633
1634 public void enableBodySoft()
1635 {
1636 m_disabled = false;
1637 if (!childPrim && !m_isSelected)
1638 {
1639 if (m_isphysical && Body != IntPtr.Zero)
1640 {
1641 UpdateCollisionCatFlags();
1642 ApplyCollisionCatFlags();
1643
1644 _zeroFlag = true;
1645 d.BodyEnable(Body);
1646
1647 }
1648 }
1649 resetCollisionAccounting();
1650 }
1651
1652 private void disableBodySoft()
1653 {
1654 m_disabled = true;
1655 if (!childPrim)
1656 {
1657 if (m_isphysical && Body != IntPtr.Zero)
1658 {
1659 if (m_isSelected)
1660 m_collisionFlags = CollisionCategories.Selected;
1661 else
1662 m_collisionCategories = 0;
1663 m_collisionFlags = 0;
1664 ApplyCollisionCatFlags();
1665 d.BodyDisable(Body);
1666 }
1667 }
1668 }
1669
1670 private void MakeBody()
1671 {
1672 if (!m_isphysical) // only physical get bodies
1673 return;
1674
1675 if (childPrim) // child prims don't get bodies;
1676 return;
1677
1678 if (m_building)
1679 return;
1680
1681 if (prim_geom == IntPtr.Zero)
1682 {
1683 m_log.Warn("[PHYSICS]: Unable to link the linkset. Root has no geom yet");
1684 return;
1685 }
1686
1687 if (Body != IntPtr.Zero)
1688 {
1689 DestroyBody();
1690 m_log.Warn("[PHYSICS]: MakeBody called having a body");
1691 }
1692
1693 if (d.GeomGetBody(prim_geom) != IntPtr.Zero)
1694 {
1695 d.GeomSetBody(prim_geom, IntPtr.Zero);
1696 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body");
1697 }
1698
1699 d.Matrix3 mymat = new d.Matrix3();
1700 d.Quaternion myrot = new d.Quaternion();
1701 d.Mass objdmass = new d.Mass { };
1702
1703 Body = d.BodyCreate(_parent_scene.world);
1704
1705 objdmass = primdMass;
1706
1707 // rotate inertia
1708 myrot.X = _orientation.X;
1709 myrot.Y = _orientation.Y;
1710 myrot.Z = _orientation.Z;
1711 myrot.W = _orientation.W;
1712
1713 d.RfromQ(out mymat, ref myrot);
1714 d.MassRotate(ref objdmass, ref mymat);
1715
1716 // set the body rotation
1717 d.BodySetRotation(Body, ref mymat);
1718
1719 // recompute full object inertia if needed
1720 if (childrenPrim.Count > 0)
1721 {
1722 d.Matrix3 mat = new d.Matrix3();
1723 d.Quaternion quat = new d.Quaternion();
1724 d.Mass tmpdmass = new d.Mass { };
1725 Vector3 rcm;
1726
1727 rcm.X = _position.X;
1728 rcm.Y = _position.Y;
1729 rcm.Z = _position.Z;
1730
1731 lock (childrenPrim)
1732 {
1733 foreach (OdePrim prm in childrenPrim)
1734 {
1735 if (prm.prim_geom == IntPtr.Zero)
1736 {
1737 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements, skipping it. No geom yet");
1738 continue;
1739 }
1740
1741 tmpdmass = prm.primdMass;
1742
1743 // apply prim current rotation to inertia
1744 quat.X = prm._orientation.X;
1745 quat.Y = prm._orientation.Y;
1746 quat.Z = prm._orientation.Z;
1747 quat.W = prm._orientation.W;
1748 d.RfromQ(out mat, ref quat);
1749 d.MassRotate(ref tmpdmass, ref mat);
1750
1751 Vector3 ppos = prm._position;
1752 ppos.X -= rcm.X;
1753 ppos.Y -= rcm.Y;
1754 ppos.Z -= rcm.Z;
1755 // refer inertia to root prim center of mass position
1756 d.MassTranslate(ref tmpdmass,
1757 ppos.X,
1758 ppos.Y,
1759 ppos.Z);
1760
1761 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
1762 // fix prim colision cats
1763
1764 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero)
1765 {
1766 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
1767 m_log.Warn("[PHYSICS]: MakeBody child geom already had a body");
1768 }
1769
1770 d.GeomClearOffset(prm.prim_geom);
1771 d.GeomSetBody(prm.prim_geom, Body);
1772 prm.Body = Body;
1773 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation
1774 }
1775 }
1776 }
1777
1778 d.GeomClearOffset(prim_geom); // make sure we don't have a hidden offset
1779 // associate root geom with body
1780 d.GeomSetBody(prim_geom, Body);
1781
1782 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
1783 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z);
1784
1785 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
1786 myrot.X = -myrot.X;
1787 myrot.Y = -myrot.Y;
1788 myrot.Z = -myrot.Z;
1789
1790 d.RfromQ(out mymat, ref myrot);
1791 d.MassRotate(ref objdmass, ref mymat);
1792
1793 d.BodySetMass(Body, ref objdmass);
1794 _mass = objdmass.mass;
1795
1796 // disconnect from world gravity so we can apply buoyancy
1797 d.BodySetGravityMode(Body, false);
1798
1799 d.BodySetAutoDisableFlag(Body, true);
1800 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1801 d.BodySetAutoDisableAngularThreshold(Body, 0.05f);
1802 d.BodySetAutoDisableLinearThreshold(Body, 0.05f);
1803 d.BodySetDamping(Body, .008f, .005f);
1804
1805 if (m_targetSpace != IntPtr.Zero)
1806 {
1807 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1808 if (d.SpaceQuery(m_targetSpace, prim_geom))
1809 d.SpaceRemove(m_targetSpace, prim_geom);
1810 }
1811
1812 if (childrenPrim.Count == 0)
1813 {
1814 collide_geom = prim_geom;
1815 m_targetSpace = _parent_scene.ActiveSpace;
1816 }
1817 else
1818 {
1819 m_targetSpace = d.HashSpaceCreate(_parent_scene.ActiveSpace);
1820 d.HashSpaceSetLevels(m_targetSpace, -2, 8);
1821 d.SpaceSetSublevel(m_targetSpace, 3);
1822 d.SpaceSetCleanup(m_targetSpace, false);
1823
1824 d.GeomSetCategoryBits(m_targetSpace, (uint)(CollisionCategories.Space |
1825 CollisionCategories.Geom |
1826 CollisionCategories.Phantom |
1827 CollisionCategories.VolumeDtc
1828 ));
1829 d.GeomSetCollideBits(m_targetSpace, 0);
1830 collide_geom = m_targetSpace;
1831 }
1832
1833 d.SpaceAdd(m_targetSpace, prim_geom);
1834
1835 if (m_delaySelect)
1836 {
1837 m_isSelected = true;
1838 m_delaySelect = false;
1839 }
1840
1841 m_collisionscore = 0;
1842
1843 UpdateCollisionCatFlags();
1844 ApplyCollisionCatFlags();
1845
1846 _parent_scene.addActivePrim(this);
1847
1848 lock (childrenPrim)
1849 {
1850 foreach (OdePrim prm in childrenPrim)
1851 {
1852 if (prm.prim_geom == IntPtr.Zero)
1853 continue;
1854
1855 Vector3 ppos = prm._position;
1856 d.GeomSetOffsetWorldPosition(prm.prim_geom, ppos.X, ppos.Y, ppos.Z); // set relative position
1857
1858 if (prm.m_targetSpace != m_targetSpace)
1859 {
1860 if (prm.m_targetSpace != IntPtr.Zero)
1861 {
1862 _parent_scene.waitForSpaceUnlock(prm.m_targetSpace);
1863 if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom))
1864 d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
1865 }
1866 prm.m_targetSpace = m_targetSpace;
1867 d.SpaceAdd(m_targetSpace, prm.prim_geom);
1868 }
1869
1870 prm.m_collisionscore = 0;
1871
1872 if(!m_disabled)
1873 prm.m_disabled = false;
1874
1875 _parent_scene.addActivePrim(prm);
1876 }
1877 }
1878
1879 // The body doesn't already have a finite rotation mode set here
1880 if (m_angularlocks != 0 && _parent == null)
1881 {
1882 createAMotor(m_angularlocks);
1883 }
1884
1885 if (m_isSelected || m_disabled)
1886 {
1887 d.BodyDisable(Body);
1888 _zeroFlag = true;
1889 }
1890 else
1891 {
1892 d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z);
1893 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
1894 _zeroFlag = false;
1895 bodydisablecontrol = 0;
1896 }
1897 _parent_scene.addActiveGroups(this);
1898 }
1899
1900 private void DestroyBody()
1901 {
1902 if (Body != IntPtr.Zero)
1903 {
1904 _parent_scene.remActivePrim(this);
1905
1906 collide_geom = IntPtr.Zero;
1907
1908 if (m_disabled)
1909 m_collisionCategories = 0;
1910 else if (m_isSelected)
1911 m_collisionCategories = CollisionCategories.Selected;
1912 else if (m_isVolumeDetect)
1913 m_collisionCategories = CollisionCategories.VolumeDtc;
1914 else if (m_isphantom)
1915 m_collisionCategories = CollisionCategories.Phantom;
1916 else
1917 m_collisionCategories = CollisionCategories.Geom;
1918
1919 m_collisionFlags = 0;
1920
1921 if (prim_geom != IntPtr.Zero)
1922 {
1923 if (m_NoColide)
1924 {
1925 d.GeomSetCategoryBits(prim_geom, 0);
1926 d.GeomSetCollideBits(prim_geom, 0);
1927 }
1928 else
1929 {
1930 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1931 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1932 }
1933 UpdateDataFromGeom();
1934 d.GeomSetBody(prim_geom, IntPtr.Zero);
1935 SetInStaticSpace(this);
1936 }
1937
1938 if (!childPrim)
1939 {
1940 lock (childrenPrim)
1941 {
1942 foreach (OdePrim prm in childrenPrim)
1943 {
1944 _parent_scene.remActivePrim(prm);
1945
1946 if (prm.m_isSelected)
1947 prm.m_collisionCategories = CollisionCategories.Selected;
1948 else if (prm.m_isVolumeDetect)
1949 prm.m_collisionCategories = CollisionCategories.VolumeDtc;
1950 else if (prm.m_isphantom)
1951 prm.m_collisionCategories = CollisionCategories.Phantom;
1952 else
1953 prm.m_collisionCategories = CollisionCategories.Geom;
1954
1955 prm.m_collisionFlags = 0;
1956
1957 if (prm.prim_geom != IntPtr.Zero)
1958 {
1959 if (prm.m_NoColide)
1960 {
1961 d.GeomSetCategoryBits(prm.prim_geom, 0);
1962 d.GeomSetCollideBits(prm.prim_geom, 0);
1963 }
1964 else
1965 {
1966 d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
1967 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
1968 }
1969 prm.UpdateDataFromGeom();
1970 SetInStaticSpace(prm);
1971 }
1972 prm.Body = IntPtr.Zero;
1973 prm._mass = prm.primMass;
1974 prm.m_collisionscore = 0;
1975 }
1976 }
1977 if (Amotor != IntPtr.Zero)
1978 {
1979 d.JointDestroy(Amotor);
1980 Amotor = IntPtr.Zero;
1981 }
1982 _parent_scene.remActiveGroup(this);
1983 d.BodyDestroy(Body);
1984 }
1985 Body = IntPtr.Zero;
1986 }
1987 _mass = primMass;
1988 m_collisionscore = 0;
1989 }
1990
1991 private void FixInertia(Vector3 NewPos,Quaternion newrot)
1992 {
1993 d.Matrix3 mat = new d.Matrix3();
1994 d.Quaternion quat = new d.Quaternion();
1995
1996 d.Mass tmpdmass = new d.Mass { };
1997 d.Mass objdmass = new d.Mass { };
1998
1999 d.BodyGetMass(Body, out tmpdmass);
2000 objdmass = tmpdmass;
2001
2002 d.Vector3 dobjpos;
2003 d.Vector3 thispos;
2004
2005 // get current object position and rotation
2006 dobjpos = d.BodyGetPosition(Body);
2007
2008 // get prim own inertia in its local frame
2009 tmpdmass = primdMass;
2010
2011 // transform to object frame
2012 mat = d.GeomGetOffsetRotation(prim_geom);
2013 d.MassRotate(ref tmpdmass, ref mat);
2014
2015 thispos = d.GeomGetOffsetPosition(prim_geom);
2016 d.MassTranslate(ref tmpdmass,
2017 thispos.X,
2018 thispos.Y,
2019 thispos.Z);
2020
2021 // subtract current prim inertia from object
2022 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2023
2024 // back prim own inertia
2025 tmpdmass = primdMass;
2026
2027 // update to new position and orientation
2028 _position = NewPos;
2029 d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z);
2030 _orientation = newrot;
2031 quat.X = newrot.X;
2032 quat.Y = newrot.Y;
2033 quat.Z = newrot.Z;
2034 quat.W = newrot.W;
2035 d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat);
2036
2037 mat = d.GeomGetOffsetRotation(prim_geom);
2038 d.MassRotate(ref tmpdmass, ref mat);
2039
2040 thispos = d.GeomGetOffsetPosition(prim_geom);
2041 d.MassTranslate(ref tmpdmass,
2042 thispos.X,
2043 thispos.Y,
2044 thispos.Z);
2045
2046 d.MassAdd(ref objdmass, ref tmpdmass);
2047
2048 // fix all positions
2049 IntPtr g = d.BodyGetFirstGeom(Body);
2050 while (g != IntPtr.Zero)
2051 {
2052 thispos = d.GeomGetOffsetPosition(g);
2053 thispos.X -= objdmass.c.X;
2054 thispos.Y -= objdmass.c.Y;
2055 thispos.Z -= objdmass.c.Z;
2056 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2057 g = d.dBodyGetNextGeom(g);
2058 }
2059 d.BodyVectorToWorld(Body,objdmass.c.X, objdmass.c.Y, objdmass.c.Z,out thispos);
2060
2061 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2062 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2063 d.BodySetMass(Body, ref objdmass);
2064 _mass = objdmass.mass;
2065 }
2066
2067
2068
2069 private void FixInertia(Vector3 NewPos)
2070 {
2071 d.Matrix3 primmat = new d.Matrix3();
2072 d.Mass tmpdmass = new d.Mass { };
2073 d.Mass objdmass = new d.Mass { };
2074 d.Mass primmass = new d.Mass { };
2075
2076 d.Vector3 dobjpos;
2077 d.Vector3 thispos;
2078
2079 d.BodyGetMass(Body, out objdmass);
2080
2081 // get prim own inertia in its local frame
2082 primmass = primdMass;
2083 // transform to object frame
2084 primmat = d.GeomGetOffsetRotation(prim_geom);
2085 d.MassRotate(ref primmass, ref primmat);
2086
2087 tmpdmass = primmass;
2088
2089 thispos = d.GeomGetOffsetPosition(prim_geom);
2090 d.MassTranslate(ref tmpdmass,
2091 thispos.X,
2092 thispos.Y,
2093 thispos.Z);
2094
2095 // subtract current prim inertia from object
2096 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2097
2098 // update to new position
2099 _position = NewPos;
2100 d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z);
2101
2102 thispos = d.GeomGetOffsetPosition(prim_geom);
2103 d.MassTranslate(ref primmass,
2104 thispos.X,
2105 thispos.Y,
2106 thispos.Z);
2107
2108 d.MassAdd(ref objdmass, ref primmass);
2109
2110 // fix all positions
2111 IntPtr g = d.BodyGetFirstGeom(Body);
2112 while (g != IntPtr.Zero)
2113 {
2114 thispos = d.GeomGetOffsetPosition(g);
2115 thispos.X -= objdmass.c.X;
2116 thispos.Y -= objdmass.c.Y;
2117 thispos.Z -= objdmass.c.Z;
2118 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2119 g = d.dBodyGetNextGeom(g);
2120 }
2121
2122 d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos);
2123
2124 // get current object position and rotation
2125 dobjpos = d.BodyGetPosition(Body);
2126
2127 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2128 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2129 d.BodySetMass(Body, ref objdmass);
2130 _mass = objdmass.mass;
2131 }
2132
2133 private void FixInertia(Quaternion newrot)
2134 {
2135 d.Matrix3 mat = new d.Matrix3();
2136 d.Quaternion quat = new d.Quaternion();
2137
2138 d.Mass tmpdmass = new d.Mass { };
2139 d.Mass objdmass = new d.Mass { };
2140 d.Vector3 dobjpos;
2141 d.Vector3 thispos;
2142
2143 d.BodyGetMass(Body, out objdmass);
2144
2145 // get prim own inertia in its local frame
2146 tmpdmass = primdMass;
2147 mat = d.GeomGetOffsetRotation(prim_geom);
2148 d.MassRotate(ref tmpdmass, ref mat);
2149 // transform to object frame
2150 thispos = d.GeomGetOffsetPosition(prim_geom);
2151 d.MassTranslate(ref tmpdmass,
2152 thispos.X,
2153 thispos.Y,
2154 thispos.Z);
2155
2156 // subtract current prim inertia from object
2157 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2158
2159 // update to new orientation
2160 _orientation = newrot;
2161 quat.X = newrot.X;
2162 quat.Y = newrot.Y;
2163 quat.Z = newrot.Z;
2164 quat.W = newrot.W;
2165 d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat);
2166
2167 tmpdmass = primdMass;
2168 mat = d.GeomGetOffsetRotation(prim_geom);
2169 d.MassRotate(ref tmpdmass, ref mat);
2170 d.MassTranslate(ref tmpdmass,
2171 thispos.X,
2172 thispos.Y,
2173 thispos.Z);
2174
2175 d.MassAdd(ref objdmass, ref tmpdmass);
2176
2177 // fix all positions
2178 IntPtr g = d.BodyGetFirstGeom(Body);
2179 while (g != IntPtr.Zero)
2180 {
2181 thispos = d.GeomGetOffsetPosition(g);
2182 thispos.X -= objdmass.c.X;
2183 thispos.Y -= objdmass.c.Y;
2184 thispos.Z -= objdmass.c.Z;
2185 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2186 g = d.dBodyGetNextGeom(g);
2187 }
2188
2189 d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos);
2190 // get current object position and rotation
2191 dobjpos = d.BodyGetPosition(Body);
2192
2193 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2194 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2195 d.BodySetMass(Body, ref objdmass);
2196 _mass = objdmass.mass;
2197 }
2198
2199
2200 #region Mass Calculation
2201
2202 private void UpdatePrimBodyData()
2203 {
2204 primMass = m_density * primVolume;
2205
2206 if (primMass <= 0)
2207 primMass = 0.0001f;//ckrinke: Mass must be greater then zero.
2208 if (primMass > _parent_scene.maximumMassObject)
2209 primMass = _parent_scene.maximumMassObject;
2210
2211 _mass = primMass; // just in case
2212
2213 d.MassSetBoxTotal(out primdMass, primMass, 2.0f * m_OBB.X, 2.0f * m_OBB.Y, 2.0f * m_OBB.Z);
2214
2215 d.MassTranslate(ref primdMass,
2216 m_OBBOffset.X,
2217 m_OBBOffset.Y,
2218 m_OBBOffset.Z);
2219
2220 primOOBradiusSQ = m_OBB.LengthSquared();
2221
2222 if (_triMeshData != IntPtr.Zero)
2223 {
2224 float pc = m_physCost;
2225 float psf = primOOBradiusSQ;
2226 psf *= 1.33f * .2f;
2227 pc *= psf;
2228 if (pc < 0.1f)
2229 pc = 0.1f;
2230
2231 m_physCost = pc;
2232 }
2233 else
2234 m_physCost = 0.1f;
2235
2236 m_streamCost = 1.0f;
2237 }
2238
2239 #endregion
2240
2241
2242 /// <summary>
2243 /// Add a child prim to this parent prim.
2244 /// </summary>
2245 /// <param name="prim">Child prim</param>
2246 // I'm the parent
2247 // prim is the child
2248 public void ParentPrim(OdePrim prim)
2249 {
2250 //Console.WriteLine("ParentPrim " + m_primName);
2251 if (this.m_localID != prim.m_localID)
2252 {
2253 DestroyBody(); // for now we need to rebuil entire object on link change
2254
2255 lock (childrenPrim)
2256 {
2257 // adopt the prim
2258 if (!childrenPrim.Contains(prim))
2259 childrenPrim.Add(prim);
2260
2261 // see if this prim has kids and adopt them also
2262 // should not happen for now
2263 foreach (OdePrim prm in prim.childrenPrim)
2264 {
2265 if (!childrenPrim.Contains(prm))
2266 {
2267 if (prm.Body != IntPtr.Zero)
2268 {
2269 if (prm.prim_geom != IntPtr.Zero)
2270 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
2271 if (prm.Body != prim.Body)
2272 prm.DestroyBody(); // don't loose bodies around
2273 prm.Body = IntPtr.Zero;
2274 }
2275
2276 childrenPrim.Add(prm);
2277 prm._parent = this;
2278 }
2279 }
2280 }
2281 //Remove old children from the prim
2282 prim.childrenPrim.Clear();
2283
2284 if (prim.Body != IntPtr.Zero)
2285 {
2286 if (prim.prim_geom != IntPtr.Zero)
2287 d.GeomSetBody(prim.prim_geom, IntPtr.Zero);
2288 prim.DestroyBody(); // don't loose bodies around
2289 prim.Body = IntPtr.Zero;
2290 }
2291
2292 prim.childPrim = true;
2293 prim._parent = this;
2294
2295 MakeBody(); // full nasty reconstruction
2296 }
2297 }
2298
2299 private void UpdateChildsfromgeom()
2300 {
2301 if (childrenPrim.Count > 0)
2302 {
2303 foreach (OdePrim prm in childrenPrim)
2304 prm.UpdateDataFromGeom();
2305 }
2306 }
2307
2308 private void UpdateDataFromGeom()
2309 {
2310 if (prim_geom != IntPtr.Zero)
2311 {
2312 d.Quaternion qtmp;
2313 d.GeomCopyQuaternion(prim_geom, out qtmp);
2314 _orientation.X = qtmp.X;
2315 _orientation.Y = qtmp.Y;
2316 _orientation.Z = qtmp.Z;
2317 _orientation.W = qtmp.W;
2318/*
2319// Debug
2320 float qlen = _orientation.Length();
2321 if (qlen > 1.01f || qlen < 0.99)
2322 m_log.WarnFormat("[PHYSICS]: Got nonnorm quaternion from geom in Object {0} norm {1}", Name, qlen);
2323//
2324*/
2325 _orientation.Normalize();
2326
2327 d.Vector3 lpos = d.GeomGetPosition(prim_geom);
2328 _position.X = lpos.X;
2329 _position.Y = lpos.Y;
2330 _position.Z = lpos.Z;
2331 }
2332 }
2333
2334 private void ChildDelink(OdePrim odePrim, bool remakebodies)
2335 {
2336 // Okay, we have a delinked child.. destroy all body and remake
2337 if (odePrim != this && !childrenPrim.Contains(odePrim))
2338 return;
2339
2340 DestroyBody();
2341
2342 if (odePrim == this) // delinking the root prim
2343 {
2344 OdePrim newroot = null;
2345 lock (childrenPrim)
2346 {
2347 if (childrenPrim.Count > 0)
2348 {
2349 newroot = childrenPrim[0];
2350 childrenPrim.RemoveAt(0);
2351 foreach (OdePrim prm in childrenPrim)
2352 {
2353 newroot.childrenPrim.Add(prm);
2354 }
2355 childrenPrim.Clear();
2356 }
2357 if (newroot != null)
2358 {
2359 newroot.childPrim = false;
2360 newroot._parent = null;
2361 if (remakebodies)
2362 newroot.MakeBody();
2363 }
2364 }
2365 }
2366
2367 else
2368 {
2369 lock (childrenPrim)
2370 {
2371 childrenPrim.Remove(odePrim);
2372 odePrim.childPrim = false;
2373 odePrim._parent = null;
2374 // odePrim.UpdateDataFromGeom();
2375 if (remakebodies)
2376 odePrim.MakeBody();
2377 }
2378 }
2379 if (remakebodies)
2380 MakeBody();
2381 }
2382
2383 protected void ChildRemove(OdePrim odePrim, bool reMakeBody)
2384 {
2385 // Okay, we have a delinked child.. destroy all body and remake
2386 if (odePrim != this && !childrenPrim.Contains(odePrim))
2387 return;
2388
2389 DestroyBody();
2390
2391 if (odePrim == this)
2392 {
2393 OdePrim newroot = null;
2394 lock (childrenPrim)
2395 {
2396 if (childrenPrim.Count > 0)
2397 {
2398 newroot = childrenPrim[0];
2399 childrenPrim.RemoveAt(0);
2400 foreach (OdePrim prm in childrenPrim)
2401 {
2402 newroot.childrenPrim.Add(prm);
2403 }
2404 childrenPrim.Clear();
2405 }
2406 if (newroot != null)
2407 {
2408 newroot.childPrim = false;
2409 newroot._parent = null;
2410 newroot.MakeBody();
2411 }
2412 }
2413 if (reMakeBody)
2414 MakeBody();
2415 return;
2416 }
2417 else
2418 {
2419 lock (childrenPrim)
2420 {
2421 childrenPrim.Remove(odePrim);
2422 odePrim.childPrim = false;
2423 odePrim._parent = null;
2424 if (reMakeBody)
2425 odePrim.MakeBody();
2426 }
2427 }
2428 MakeBody();
2429 }
2430
2431
2432 #region changes
2433
2434 private void changeadd()
2435 {
2436 }
2437
2438 private void changeAngularLock(byte newLocks)
2439 {
2440 // do we have a Physical object?
2441 if (Body != IntPtr.Zero)
2442 {
2443 //Check that we have a Parent
2444 //If we have a parent then we're not authorative here
2445 if (_parent == null)
2446 {
2447 if (newLocks != 0)
2448 {
2449 createAMotor(newLocks);
2450 }
2451 else
2452 {
2453 if (Amotor != IntPtr.Zero)
2454 {
2455 d.JointDestroy(Amotor);
2456 Amotor = IntPtr.Zero;
2457 }
2458 }
2459 }
2460 }
2461 // Store this for later in case we get turned into a separate body
2462 m_angularlocks = newLocks;
2463 }
2464
2465 private void changeLink(OdePrim NewParent)
2466 {
2467 if (_parent == null && NewParent != null)
2468 {
2469 NewParent.ParentPrim(this);
2470 }
2471 else if (_parent != null)
2472 {
2473 if (_parent is OdePrim)
2474 {
2475 if (NewParent != _parent)
2476 {
2477 (_parent as OdePrim).ChildDelink(this, false); // for now...
2478 childPrim = false;
2479
2480 if (NewParent != null)
2481 {
2482 NewParent.ParentPrim(this);
2483 }
2484 }
2485 }
2486 }
2487 _parent = NewParent;
2488 }
2489
2490
2491 private void Stop()
2492 {
2493 if (!childPrim)
2494 {
2495// m_force = Vector3.Zero;
2496 m_forceacc = Vector3.Zero;
2497 m_angularForceacc = Vector3.Zero;
2498// m_torque = Vector3.Zero;
2499 _velocity = Vector3.Zero;
2500 _acceleration = Vector3.Zero;
2501 m_rotationalVelocity = Vector3.Zero;
2502 _target_velocity = Vector3.Zero;
2503 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2504 m_vehicle.Stop();
2505
2506 _zeroFlag = false;
2507 base.RequestPhysicsterseUpdate();
2508 }
2509
2510 if (Body != IntPtr.Zero)
2511 {
2512 d.BodySetForce(Body, 0f, 0f, 0f);
2513 d.BodySetTorque(Body, 0f, 0f, 0f);
2514 d.BodySetLinearVel(Body, 0f, 0f, 0f);
2515 d.BodySetAngularVel(Body, 0f, 0f, 0f);
2516 }
2517 }
2518
2519 private void changePhantomStatus(bool newval)
2520 {
2521 m_isphantom = newval;
2522
2523 UpdateCollisionCatFlags();
2524 ApplyCollisionCatFlags();
2525 }
2526
2527/* not in use
2528 internal void ChildSelectedChange(bool childSelect)
2529 {
2530 if(childPrim)
2531 return;
2532
2533 if (childSelect == m_isSelected)
2534 return;
2535
2536 if (childSelect)
2537 {
2538 DoSelectedStatus(true);
2539 }
2540
2541 else
2542 {
2543 foreach (OdePrim prm in childrenPrim)
2544 {
2545 if (prm.m_isSelected)
2546 return;
2547 }
2548 DoSelectedStatus(false);
2549 }
2550 }
2551*/
2552 private void changeSelectedStatus(bool newval)
2553 {
2554 if (m_lastdoneSelected == newval)
2555 return;
2556
2557 m_lastdoneSelected = newval;
2558 DoSelectedStatus(newval);
2559 }
2560
2561 private void CheckDelaySelect()
2562 {
2563 if (m_delaySelect)
2564 {
2565 DoSelectedStatus(m_isSelected);
2566 }
2567 }
2568
2569 private void DoSelectedStatus(bool newval)
2570 {
2571 m_isSelected = newval;
2572 Stop();
2573
2574 if (newval)
2575 {
2576 if (!childPrim && Body != IntPtr.Zero)
2577 d.BodyDisable(Body);
2578
2579 if (m_delaySelect || m_isphysical)
2580 {
2581 m_collisionCategories = CollisionCategories.Selected;
2582 m_collisionFlags = 0;
2583
2584 if (!childPrim)
2585 {
2586 foreach (OdePrim prm in childrenPrim)
2587 {
2588 prm.m_collisionCategories = m_collisionCategories;
2589 prm.m_collisionFlags = m_collisionFlags;
2590
2591 if (prm.prim_geom != IntPtr.Zero)
2592 {
2593
2594 if (prm.m_NoColide)
2595 {
2596 d.GeomSetCategoryBits(prm.prim_geom, 0);
2597 d.GeomSetCollideBits(prm.prim_geom, 0);
2598 }
2599 else
2600 {
2601 d.GeomSetCategoryBits(prm.prim_geom, (uint)m_collisionCategories);
2602 d.GeomSetCollideBits(prm.prim_geom, (uint)m_collisionFlags);
2603 }
2604 }
2605 prm.m_delaySelect = false;
2606 }
2607 }
2608// else if (_parent != null)
2609// ((OdePrim)_parent).ChildSelectedChange(true);
2610
2611
2612 if (prim_geom != IntPtr.Zero)
2613 {
2614 if (m_NoColide)
2615 {
2616 d.GeomSetCategoryBits(prim_geom, 0);
2617 d.GeomSetCollideBits(prim_geom, 0);
2618 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
2619 {
2620 d.GeomSetCategoryBits(collide_geom, 0);
2621 d.GeomSetCollideBits(collide_geom, 0);
2622 }
2623
2624 }
2625 else
2626 {
2627 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
2628 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
2629 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
2630 {
2631 d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories);
2632 d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags);
2633 }
2634 }
2635 }
2636
2637 m_delaySelect = false;
2638 }
2639 else if(!m_isphysical)
2640 {
2641 m_delaySelect = true;
2642 }
2643 }
2644 else
2645 {
2646 if (!childPrim)
2647 {
2648 if (Body != IntPtr.Zero && !m_disabled)
2649 {
2650 _zeroFlag = true;
2651 d.BodyEnable(Body);
2652 }
2653 }
2654// else if (_parent != null)
2655// ((OdePrim)_parent).ChildSelectedChange(false);
2656
2657 UpdateCollisionCatFlags();
2658 ApplyCollisionCatFlags();
2659
2660 m_delaySelect = false;
2661 }
2662
2663 resetCollisionAccounting();
2664 }
2665
2666 private void changePosition(Vector3 newPos)
2667 {
2668 CheckDelaySelect();
2669 if (m_isphysical)
2670 {
2671 if (childPrim) // inertia is messed, must rebuild
2672 {
2673 if (m_building)
2674 {
2675 _position = newPos;
2676 }
2677
2678 else if (m_forcePosOrRotation && _position != newPos && Body != IntPtr.Zero)
2679 {
2680 FixInertia(newPos);
2681 if (!d.BodyIsEnabled(Body))
2682 {
2683 _zeroFlag = true;
2684 d.BodyEnable(Body);
2685 }
2686 }
2687 }
2688 else
2689 {
2690 if (_position != newPos)
2691 {
2692 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2693 _position = newPos;
2694 }
2695 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2696 {
2697 _zeroFlag = true;
2698 d.BodyEnable(Body);
2699 }
2700 }
2701 }
2702 else
2703 {
2704 if (prim_geom != IntPtr.Zero)
2705 {
2706 if (newPos != _position)
2707 {
2708 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2709 _position = newPos;
2710
2711 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2712 }
2713 }
2714 }
2715 givefakepos--;
2716 if (givefakepos < 0)
2717 givefakepos = 0;
2718// changeSelectedStatus();
2719 resetCollisionAccounting();
2720 }
2721
2722 private void changeOrientation(Quaternion newOri)
2723 {
2724 CheckDelaySelect();
2725 if (m_isphysical)
2726 {
2727 if (childPrim) // inertia is messed, must rebuild
2728 {
2729 if (m_building)
2730 {
2731 _orientation = newOri;
2732 }
2733/*
2734 else if (m_forcePosOrRotation && _orientation != newOri && Body != IntPtr.Zero)
2735 {
2736 FixInertia(_position, newOri);
2737 if (!d.BodyIsEnabled(Body))
2738 d.BodyEnable(Body);
2739 }
2740*/
2741 }
2742 else
2743 {
2744 if (newOri != _orientation)
2745 {
2746 d.Quaternion myrot = new d.Quaternion();
2747 myrot.X = newOri.X;
2748 myrot.Y = newOri.Y;
2749 myrot.Z = newOri.Z;
2750 myrot.W = newOri.W;
2751 d.GeomSetQuaternion(prim_geom, ref myrot);
2752 _orientation = newOri;
2753 if (Body != IntPtr.Zero && m_angularlocks != 0)
2754 createAMotor(m_angularlocks);
2755 }
2756 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2757 {
2758 _zeroFlag = true;
2759 d.BodyEnable(Body);
2760 }
2761 }
2762 }
2763 else
2764 {
2765 if (prim_geom != IntPtr.Zero)
2766 {
2767 if (newOri != _orientation)
2768 {
2769 d.Quaternion myrot = new d.Quaternion();
2770 myrot.X = newOri.X;
2771 myrot.Y = newOri.Y;
2772 myrot.Z = newOri.Z;
2773 myrot.W = newOri.W;
2774 d.GeomSetQuaternion(prim_geom, ref myrot);
2775 _orientation = newOri;
2776 }
2777 }
2778 }
2779 givefakeori--;
2780 if (givefakeori < 0)
2781 givefakeori = 0;
2782 resetCollisionAccounting();
2783 }
2784
2785 private void changePositionAndOrientation(Vector3 newPos, Quaternion newOri)
2786 {
2787 CheckDelaySelect();
2788 if (m_isphysical)
2789 {
2790 if (childPrim && m_building) // inertia is messed, must rebuild
2791 {
2792 _position = newPos;
2793 _orientation = newOri;
2794 }
2795 else
2796 {
2797 if (newOri != _orientation)
2798 {
2799 d.Quaternion myrot = new d.Quaternion();
2800 myrot.X = newOri.X;
2801 myrot.Y = newOri.Y;
2802 myrot.Z = newOri.Z;
2803 myrot.W = newOri.W;
2804 d.GeomSetQuaternion(prim_geom, ref myrot);
2805 _orientation = newOri;
2806 if (Body != IntPtr.Zero && m_angularlocks != 0)
2807 createAMotor(m_angularlocks);
2808 }
2809 if (_position != newPos)
2810 {
2811 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2812 _position = newPos;
2813 }
2814 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2815 {
2816 _zeroFlag = true;
2817 d.BodyEnable(Body);
2818 }
2819 }
2820 }
2821 else
2822 {
2823 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
2824 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
2825
2826 if (prim_geom != IntPtr.Zero)
2827 {
2828 if (newOri != _orientation)
2829 {
2830 d.Quaternion myrot = new d.Quaternion();
2831 myrot.X = newOri.X;
2832 myrot.Y = newOri.Y;
2833 myrot.Z = newOri.Z;
2834 myrot.W = newOri.W;
2835 d.GeomSetQuaternion(prim_geom, ref myrot);
2836 _orientation = newOri;
2837 }
2838
2839 if (newPos != _position)
2840 {
2841 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2842 _position = newPos;
2843
2844 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2845 }
2846 }
2847 }
2848 givefakepos--;
2849 if (givefakepos < 0)
2850 givefakepos = 0;
2851 givefakeori--;
2852 if (givefakeori < 0)
2853 givefakeori = 0;
2854 resetCollisionAccounting();
2855 }
2856
2857 private void changeDisable(bool disable)
2858 {
2859 if (disable)
2860 {
2861 if (!m_disabled)
2862 disableBodySoft();
2863 }
2864 else
2865 {
2866 if (m_disabled)
2867 enableBodySoft();
2868 }
2869 }
2870
2871 private void changePhysicsStatus(bool NewStatus)
2872 {
2873 CheckDelaySelect();
2874
2875 m_isphysical = NewStatus;
2876
2877 if (!childPrim)
2878 {
2879 if (NewStatus)
2880 {
2881 if (Body == IntPtr.Zero)
2882 MakeBody();
2883 }
2884 else
2885 {
2886 if (Body != IntPtr.Zero)
2887 {
2888 DestroyBody();
2889 }
2890 Stop();
2891 }
2892 }
2893
2894 resetCollisionAccounting();
2895 }
2896
2897 private void changeSize(Vector3 newSize)
2898 {
2899 }
2900
2901 private void changeShape(PrimitiveBaseShape newShape)
2902 {
2903 }
2904
2905 private void changeAddPhysRep(ODEPhysRepData repData)
2906 {
2907 _size = repData.size; //??
2908 _pbs = repData.pbs;
2909 m_shapetype = repData.shapetype;
2910
2911 m_mesh = repData.mesh;
2912
2913 m_assetID = repData.assetID;
2914 m_meshState = repData.meshState;
2915
2916 m_hasOBB = repData.hasOBB;
2917 m_OBBOffset = repData.OBBOffset;
2918 m_OBB = repData.OBB;
2919
2920 primVolume = repData.volume;
2921
2922 CreateGeom();
2923
2924 if (prim_geom != IntPtr.Zero)
2925 {
2926 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2927 d.Quaternion myrot = new d.Quaternion();
2928 myrot.X = _orientation.X;
2929 myrot.Y = _orientation.Y;
2930 myrot.Z = _orientation.Z;
2931 myrot.W = _orientation.W;
2932 d.GeomSetQuaternion(prim_geom, ref myrot);
2933 }
2934
2935 if (!m_isphysical)
2936 {
2937 SetInStaticSpace(this);
2938 UpdateCollisionCatFlags();
2939 ApplyCollisionCatFlags();
2940 }
2941 else
2942 MakeBody();
2943
2944 if ((m_meshState & MeshState.NeedMask) != 0)
2945 {
2946 repData.size = _size;
2947 repData.pbs = _pbs;
2948 repData.shapetype = m_shapetype;
2949 _parent_scene.m_meshWorker.RequestMesh(repData);
2950 }
2951 }
2952
2953 private void changePhysRepData(ODEPhysRepData repData)
2954 {
2955 CheckDelaySelect();
2956
2957 OdePrim parent = (OdePrim)_parent;
2958
2959 bool chp = childPrim;
2960
2961 if (chp)
2962 {
2963 if (parent != null)
2964 {
2965 parent.DestroyBody();
2966 }
2967 }
2968 else
2969 {
2970 DestroyBody();
2971 }
2972
2973 RemoveGeom();
2974
2975 _size = repData.size;
2976 _pbs = repData.pbs;
2977 m_shapetype = repData.shapetype;
2978
2979 m_mesh = repData.mesh;
2980
2981 m_assetID = repData.assetID;
2982 m_meshState = repData.meshState;
2983
2984 m_hasOBB = repData.hasOBB;
2985 m_OBBOffset = repData.OBBOffset;
2986 m_OBB = repData.OBB;
2987
2988 primVolume = repData.volume;
2989
2990 CreateGeom();
2991
2992 if (prim_geom != IntPtr.Zero)
2993 {
2994 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2995 d.Quaternion myrot = new d.Quaternion();
2996 myrot.X = _orientation.X;
2997 myrot.Y = _orientation.Y;
2998 myrot.Z = _orientation.Z;
2999 myrot.W = _orientation.W;
3000 d.GeomSetQuaternion(prim_geom, ref myrot);
3001 }
3002
3003 if (m_isphysical)
3004 {
3005 if (chp)
3006 {
3007 if (parent != null)
3008 {
3009 parent.MakeBody();
3010 }
3011 }
3012 else
3013 MakeBody();
3014 }
3015 else
3016 {
3017 SetInStaticSpace(this);
3018 UpdateCollisionCatFlags();
3019 ApplyCollisionCatFlags();
3020 }
3021
3022 resetCollisionAccounting();
3023
3024 if ((m_meshState & MeshState.NeedMask) != 0)
3025 {
3026 repData.size = _size;
3027 repData.pbs = _pbs;
3028 repData.shapetype = m_shapetype;
3029 _parent_scene.m_meshWorker.RequestMesh(repData);
3030 }
3031 }
3032
3033 private void changeFloatOnWater(bool newval)
3034 {
3035 m_collidesWater = newval;
3036
3037 UpdateCollisionCatFlags();
3038 ApplyCollisionCatFlags();
3039 }
3040
3041 private void changeSetTorque(Vector3 newtorque)
3042 {
3043 if (!m_isSelected)
3044 {
3045 if (m_isphysical && Body != IntPtr.Zero)
3046 {
3047 if (m_disabled)
3048 enableBodySoft();
3049 else if (!d.BodyIsEnabled(Body))
3050 d.BodyEnable(Body);
3051
3052 }
3053 m_torque = newtorque;
3054 }
3055 }
3056
3057 private void changeForce(Vector3 force)
3058 {
3059 m_force = force;
3060 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
3061 d.BodyEnable(Body);
3062 }
3063
3064 private void changeAddForce(Vector3 theforce)
3065 {
3066 m_forceacc += theforce;
3067 if (!m_isSelected)
3068 {
3069 lock (this)
3070 {
3071 //m_log.Info("[PHYSICS]: dequeing forcelist");
3072 if (m_isphysical && Body != IntPtr.Zero)
3073 {
3074 if (m_disabled)
3075 enableBodySoft();
3076 else if (!d.BodyIsEnabled(Body))
3077 d.BodyEnable(Body);
3078 }
3079 }
3080 m_collisionscore = 0;
3081 }
3082 }
3083
3084 // actually angular impulse
3085 private void changeAddAngularImpulse(Vector3 aimpulse)
3086 {
3087 m_angularForceacc += aimpulse * m_invTimeStep;
3088 if (!m_isSelected)
3089 {
3090 lock (this)
3091 {
3092 if (m_isphysical && Body != IntPtr.Zero)
3093 {
3094 if (m_disabled)
3095 enableBodySoft();
3096 else if (!d.BodyIsEnabled(Body))
3097 d.BodyEnable(Body);
3098 }
3099 }
3100 m_collisionscore = 0;
3101 }
3102 }
3103
3104 private void changevelocity(Vector3 newVel)
3105 {
3106 float len = newVel.LengthSquared();
3107 if (len > 100000.0f) // limit to 100m/s
3108 {
3109 len = 100.0f / (float)Math.Sqrt(len);
3110 newVel *= len;
3111 }
3112
3113 if (!m_isSelected)
3114 {
3115 if (Body != IntPtr.Zero)
3116 {
3117 if (m_disabled)
3118 enableBodySoft();
3119 else if (!d.BodyIsEnabled(Body))
3120 d.BodyEnable(Body);
3121
3122 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
3123 }
3124 //resetCollisionAccounting();
3125 }
3126 _velocity = newVel;
3127 }
3128
3129 private void changeangvelocity(Vector3 newAngVel)
3130 {
3131 float len = newAngVel.LengthSquared();
3132 if (len > 144.0f) // limit to 12rad/s
3133 {
3134 len = 12.0f / (float)Math.Sqrt(len);
3135 newAngVel *= len;
3136 }
3137
3138 if (!m_isSelected)
3139 {
3140 if (Body != IntPtr.Zero)
3141 {
3142 if (m_disabled)
3143 enableBodySoft();
3144 else if (!d.BodyIsEnabled(Body))
3145 d.BodyEnable(Body);
3146
3147
3148 d.BodySetAngularVel(Body, newAngVel.X, newAngVel.Y, newAngVel.Z);
3149 }
3150 //resetCollisionAccounting();
3151 }
3152 m_rotationalVelocity = newAngVel;
3153 }
3154
3155 private void changeVolumedetetion(bool newVolDtc)
3156 {
3157 m_isVolumeDetect = newVolDtc;
3158 m_fakeisVolumeDetect = newVolDtc;
3159 UpdateCollisionCatFlags();
3160 ApplyCollisionCatFlags();
3161 }
3162
3163 protected void changeBuilding(bool newbuilding)
3164 {
3165 // Check if we need to do anything
3166 if (newbuilding == m_building)
3167 return;
3168
3169 if ((bool)newbuilding)
3170 {
3171 m_building = true;
3172 if (!childPrim)
3173 DestroyBody();
3174 }
3175 else
3176 {
3177 m_building = false;
3178 CheckDelaySelect();
3179 if (!childPrim)
3180 MakeBody();
3181 }
3182 if (!childPrim && childrenPrim.Count > 0)
3183 {
3184 foreach (OdePrim prm in childrenPrim)
3185 prm.changeBuilding(m_building); // call directly
3186 }
3187 }
3188
3189 public void changeSetVehicle(VehicleData vdata)
3190 {
3191 if (m_vehicle == null)
3192 m_vehicle = new ODEDynamics(this);
3193 m_vehicle.DoSetVehicle(vdata);
3194 }
3195
3196 private void changeVehicleType(int value)
3197 {
3198 if (value == (int)Vehicle.TYPE_NONE)
3199 {
3200 if (m_vehicle != null)
3201 m_vehicle = null;
3202 }
3203 else
3204 {
3205 if (m_vehicle == null)
3206 m_vehicle = new ODEDynamics(this);
3207
3208 m_vehicle.ProcessTypeChange((Vehicle)value);
3209 }
3210 }
3211
3212 private void changeVehicleFloatParam(strVehicleFloatParam fp)
3213 {
3214 if (m_vehicle == null)
3215 return;
3216
3217 m_vehicle.ProcessFloatVehicleParam((Vehicle)fp.param, fp.value);
3218 }
3219
3220 private void changeVehicleVectorParam(strVehicleVectorParam vp)
3221 {
3222 if (m_vehicle == null)
3223 return;
3224 m_vehicle.ProcessVectorVehicleParam((Vehicle)vp.param, vp.value);
3225 }
3226
3227 private void changeVehicleRotationParam(strVehicleQuatParam qp)
3228 {
3229 if (m_vehicle == null)
3230 return;
3231 m_vehicle.ProcessRotationVehicleParam((Vehicle)qp.param, qp.value);
3232 }
3233
3234 private void changeVehicleFlags(strVehicleBoolParam bp)
3235 {
3236 if (m_vehicle == null)
3237 return;
3238 m_vehicle.ProcessVehicleFlags(bp.param, bp.value);
3239 }
3240
3241 private void changeBuoyancy(float b)
3242 {
3243 m_buoyancy = b;
3244 }
3245
3246 private void changePIDTarget(Vector3 trg)
3247 {
3248 m_PIDTarget = trg;
3249 }
3250
3251 private void changePIDTau(float tau)
3252 {
3253 m_PIDTau = tau;
3254 }
3255
3256 private void changePIDActive(bool val)
3257 {
3258 m_usePID = val;
3259 }
3260
3261 private void changePIDHoverHeight(float val)
3262 {
3263 m_PIDHoverHeight = val;
3264 if (val == 0)
3265 m_useHoverPID = false;
3266 }
3267
3268 private void changePIDHoverType(PIDHoverType type)
3269 {
3270 m_PIDHoverType = type;
3271 }
3272
3273 private void changePIDHoverTau(float tau)
3274 {
3275 m_PIDHoverTau = tau;
3276 }
3277
3278 private void changePIDHoverActive(bool active)
3279 {
3280 m_useHoverPID = active;
3281 }
3282
3283 #endregion
3284
3285 public void Move()
3286 {
3287 if (!childPrim && m_isphysical && Body != IntPtr.Zero &&
3288 !m_disabled && !m_isSelected && !m_building && !m_outbounds)
3289 {
3290 if (!d.BodyIsEnabled(Body))
3291 {
3292 // let vehicles sleep
3293 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3294 return;
3295
3296 if (++bodydisablecontrol < 50)
3297 return;
3298
3299 // clear residuals
3300 d.BodySetAngularVel(Body,0f,0f,0f);
3301 d.BodySetLinearVel(Body,0f,0f,0f);
3302 _zeroFlag = true;
3303 d.BodyEnable(Body);
3304 bodydisablecontrol = -4;
3305 }
3306
3307 if(bodydisablecontrol < 0)
3308 bodydisablecontrol ++;
3309
3310 d.Vector3 lpos = d.GeomGetPosition(prim_geom); // root position that is seem by rest of simulator
3311
3312 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3313 {
3314 // 'VEHICLES' are dealt with in ODEDynamics.cs
3315 m_vehicle.Step();
3316 return;
3317 }
3318
3319 float fx = 0;
3320 float fy = 0;
3321 float fz = 0;
3322
3323 float m_mass = _mass;
3324
3325 if (m_usePID && m_PIDTau > 0)
3326 {
3327 // for now position error
3328 _target_velocity =
3329 new Vector3(
3330 (m_PIDTarget.X - lpos.X),
3331 (m_PIDTarget.Y - lpos.Y),
3332 (m_PIDTarget.Z - lpos.Z)
3333 );
3334
3335 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.02f))
3336 {
3337 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
3338 d.BodySetLinearVel(Body, 0, 0, 0);
3339 return;
3340 }
3341 else
3342 {
3343 _zeroFlag = false;
3344
3345 float tmp = 1 / m_PIDTau;
3346 _target_velocity *= tmp;
3347
3348 // apply limits
3349 tmp = _target_velocity.Length();
3350 if (tmp > 50.0f)
3351 {
3352 tmp = 50 / tmp;
3353 _target_velocity *= tmp;
3354 }
3355 else if (tmp < 0.05f)
3356 {
3357 tmp = 0.05f / tmp;
3358 _target_velocity *= tmp;
3359 }
3360
3361 d.Vector3 vel = d.BodyGetLinearVel(Body);
3362 fx = (_target_velocity.X - vel.X) * m_invTimeStep;
3363 fy = (_target_velocity.Y - vel.Y) * m_invTimeStep;
3364 fz = (_target_velocity.Z - vel.Z) * m_invTimeStep;
3365// d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z);
3366 }
3367 } // end if (m_usePID)
3368
3369 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
3370 else if (m_useHoverPID && m_PIDHoverTau != 0 && m_PIDHoverHeight != 0)
3371 {
3372
3373 // Non-Vehicles have a limited set of Hover options.
3374 // determine what our target height really is based on HoverType
3375
3376 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(lpos.X, lpos.Y);
3377
3378 switch (m_PIDHoverType)
3379 {
3380 case PIDHoverType.Ground:
3381 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3382 break;
3383
3384 case PIDHoverType.GroundAndWater:
3385 m_waterHeight = _parent_scene.GetWaterLevel();
3386 if (m_groundHeight > m_waterHeight)
3387 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3388 else
3389 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
3390 break;
3391 } // end switch (m_PIDHoverType)
3392
3393 // don't go underground unless volumedetector
3394
3395 if (m_targetHoverHeight > m_groundHeight || m_isVolumeDetect)
3396 {
3397 d.Vector3 vel = d.BodyGetLinearVel(Body);
3398
3399 fz = (m_targetHoverHeight - lpos.Z);
3400
3401 // if error is zero, use position control; otherwise, velocity control
3402 if (Math.Abs(fz) < 0.01f)
3403 {
3404 d.BodySetPosition(Body, lpos.X, lpos.Y, m_targetHoverHeight);
3405 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
3406 }
3407 else
3408 {
3409 _zeroFlag = false;
3410 fz /= m_PIDHoverTau;
3411
3412 float tmp = Math.Abs(fz);
3413 if (tmp > 50)
3414 fz = 50 * Math.Sign(fz);
3415 else if (tmp < 0.1)
3416 fz = 0.1f * Math.Sign(fz);
3417
3418 fz = ((fz - vel.Z) * m_invTimeStep);
3419 }
3420 }
3421 }
3422 else
3423 {
3424 float b = (1.0f - m_buoyancy) * m_gravmod;
3425 fx = _parent_scene.gravityx * b;
3426 fy = _parent_scene.gravityy * b;
3427 fz = _parent_scene.gravityz * b;
3428 }
3429
3430 fx *= m_mass;
3431 fy *= m_mass;
3432 fz *= m_mass;
3433
3434 // constant force
3435 fx += m_force.X;
3436 fy += m_force.Y;
3437 fz += m_force.Z;
3438
3439 fx += m_forceacc.X;
3440 fy += m_forceacc.Y;
3441 fz += m_forceacc.Z;
3442
3443 m_forceacc = Vector3.Zero;
3444
3445 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
3446 if (fx != 0 || fy != 0 || fz != 0)
3447 {
3448 d.BodyAddForce(Body, fx, fy, fz);
3449 //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz);
3450 }
3451
3452 Vector3 trq;
3453
3454 trq = m_torque;
3455 trq += m_angularForceacc;
3456 m_angularForceacc = Vector3.Zero;
3457 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0)
3458 {
3459 d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z);
3460 }
3461 }
3462 else
3463 { // is not physical, or is not a body or is selected
3464 // _zeroPosition = d.BodyGetPosition(Body);
3465 return;
3466 //Console.WriteLine("Nothing " + Name);
3467
3468 }
3469 }
3470
3471 public void UpdatePositionAndVelocity(int frame)
3472 {
3473 if (_parent == null && !m_disabled && !m_building && !m_outbounds && Body != IntPtr.Zero)
3474 {
3475 bool bodyenabled = d.BodyIsEnabled(Body);
3476
3477 if(bodydisablecontrol < 0)
3478 return;
3479
3480 if (bodyenabled || !_zeroFlag)
3481 {
3482 bool lastZeroFlag = _zeroFlag;
3483
3484 d.Vector3 lpos = d.GeomGetPosition(prim_geom);
3485
3486 // check outside region
3487 if (lpos.Z < -100 || lpos.Z > 100000f)
3488 {
3489 m_outbounds = true;
3490
3491 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f);
3492 _acceleration.X = 0;
3493 _acceleration.Y = 0;
3494 _acceleration.Z = 0;
3495
3496 _velocity.X = 0;
3497 _velocity.Y = 0;
3498 _velocity.Z = 0;
3499 m_rotationalVelocity.X = 0;
3500 m_rotationalVelocity.Y = 0;
3501 m_rotationalVelocity.Z = 0;
3502
3503 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3504 d.BodySetAngularVel(Body, 0, 0, 0); // stop it
3505 d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere
3506 m_lastposition = _position;
3507 m_lastorientation = _orientation;
3508
3509 base.RequestPhysicsterseUpdate();
3510
3511// throttleCounter = 0;
3512 _zeroFlag = true;
3513
3514 disableBodySoft(); // disable it and colisions
3515 base.RaiseOutOfBounds(_position);
3516 return;
3517 }
3518
3519 if (lpos.X < 0f)
3520 {
3521 _position.X = Util.Clip(lpos.X, -2f, -0.1f);
3522 m_outbounds = true;
3523 }
3524 else if (lpos.X > _parent_scene.WorldExtents.X)
3525 {
3526 _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
3527 m_outbounds = true;
3528 }
3529 if (lpos.Y < 0f)
3530 {
3531 _position.Y = Util.Clip(lpos.Y, -2f, -0.1f);
3532 m_outbounds = true;
3533 }
3534 else if (lpos.Y > _parent_scene.WorldExtents.Y)
3535 {
3536 _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
3537 m_outbounds = true;
3538 }
3539
3540 if (m_outbounds)
3541 {
3542 m_lastposition = _position;
3543 m_lastorientation = _orientation;
3544
3545 d.Vector3 dtmp = d.BodyGetAngularVel(Body);
3546 m_rotationalVelocity.X = dtmp.X;
3547 m_rotationalVelocity.Y = dtmp.Y;
3548 m_rotationalVelocity.Z = dtmp.Z;
3549
3550 dtmp = d.BodyGetLinearVel(Body);
3551 _velocity.X = dtmp.X;
3552 _velocity.Y = dtmp.Y;
3553 _velocity.Z = dtmp.Z;
3554
3555 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3556 d.BodySetAngularVel(Body, 0, 0, 0);
3557 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3558 disableBodySoft(); // stop collisions
3559 UnSubscribeEvents();
3560
3561 base.RequestPhysicsterseUpdate();
3562 return;
3563 }
3564
3565 d.Quaternion ori;
3566 d.GeomCopyQuaternion(prim_geom, out ori);
3567
3568 // decide if moving
3569 // use positions since this are integrated quantities
3570 // tolerance values depende a lot on simulation noise...
3571 // use simple math.abs since we dont need to be exact
3572 if(!bodyenabled)
3573 {
3574 _zeroFlag = true;
3575 }
3576 else
3577 {
3578 float poserror;
3579 float angerror;
3580 if(_zeroFlag)
3581 {
3582 poserror = 0.01f;
3583 angerror = 0.001f;
3584 }
3585 else
3586 {
3587 poserror = 0.005f;
3588 angerror = 0.0005f;
3589 }
3590
3591 if (
3592 (Math.Abs(_position.X - lpos.X) < poserror)
3593 && (Math.Abs(_position.Y - lpos.Y) < poserror)
3594 && (Math.Abs(_position.Z - lpos.Z) < poserror)
3595 && (Math.Abs(_orientation.X - ori.X) < angerror)
3596 && (Math.Abs(_orientation.Y - ori.Y) < angerror)
3597 && (Math.Abs(_orientation.Z - ori.Z) < angerror) // ignore W
3598 )
3599 _zeroFlag = true;
3600 else
3601 _zeroFlag = false;
3602 }
3603
3604 // update position
3605 if (!(_zeroFlag && lastZeroFlag))
3606 {
3607 _position.X = lpos.X;
3608 _position.Y = lpos.Y;
3609 _position.Z = lpos.Z;
3610
3611 _orientation.X = ori.X;
3612 _orientation.Y = ori.Y;
3613 _orientation.Z = ori.Z;
3614 _orientation.W = ori.W;
3615 }
3616
3617 // update velocities and aceleration
3618 if (_zeroFlag || lastZeroFlag)
3619 {
3620 // disable interpolators
3621 _velocity = Vector3.Zero;
3622 _acceleration = Vector3.Zero;
3623 m_rotationalVelocity = Vector3.Zero;
3624 }
3625 else
3626 {
3627 d.Vector3 vel = d.BodyGetLinearVel(Body);
3628
3629 _acceleration = _velocity;
3630
3631 if ((Math.Abs(vel.X) < 0.005f) &&
3632 (Math.Abs(vel.Y) < 0.005f) &&
3633 (Math.Abs(vel.Z) < 0.005f))
3634 {
3635 _velocity = Vector3.Zero;
3636 float t = -m_invTimeStep;
3637 _acceleration = _acceleration * t;
3638 }
3639 else
3640 {
3641 _velocity.X = vel.X;
3642 _velocity.Y = vel.Y;
3643 _velocity.Z = vel.Z;
3644 _acceleration = (_velocity - _acceleration) * m_invTimeStep;
3645 }
3646
3647 if ((Math.Abs(_acceleration.X) < 0.01f) &&
3648 (Math.Abs(_acceleration.Y) < 0.01f) &&
3649 (Math.Abs(_acceleration.Z) < 0.01f))
3650 {
3651 _acceleration = Vector3.Zero;
3652 }
3653
3654 if ((Math.Abs(_orientation.X - ori.X) < 0.0001) &&
3655 (Math.Abs(_orientation.Y - ori.Y) < 0.0001) &&
3656 (Math.Abs(_orientation.Z - ori.Z) < 0.0001)
3657 )
3658 {
3659 m_rotationalVelocity = Vector3.Zero;
3660 }
3661 else
3662 {
3663 vel = d.BodyGetAngularVel(Body);
3664 m_rotationalVelocity.X = vel.X;
3665 m_rotationalVelocity.Y = vel.Y;
3666 m_rotationalVelocity.Z = vel.Z;
3667 }
3668 }
3669
3670 if (_zeroFlag)
3671 {
3672 if (!m_lastUpdateSent)
3673 {
3674 base.RequestPhysicsterseUpdate();
3675 if (lastZeroFlag)
3676 m_lastUpdateSent = true;
3677 }
3678 return;
3679 }
3680
3681 base.RequestPhysicsterseUpdate();
3682 m_lastUpdateSent = false;
3683 }
3684 }
3685 }
3686
3687 internal static bool QuaternionIsFinite(Quaternion q)
3688 {
3689 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
3690 return false;
3691 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
3692 return false;
3693 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
3694 return false;
3695 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
3696 return false;
3697 return true;
3698 }
3699
3700 internal static void DMassSubPartFromObj(ref d.Mass part, ref d.Mass theobj)
3701 {
3702 // assumes object center of mass is zero
3703 float smass = part.mass;
3704 theobj.mass -= smass;
3705
3706 smass *= 1.0f / (theobj.mass); ;
3707
3708 theobj.c.X -= part.c.X * smass;
3709 theobj.c.Y -= part.c.Y * smass;
3710 theobj.c.Z -= part.c.Z * smass;
3711
3712 theobj.I.M00 -= part.I.M00;
3713 theobj.I.M01 -= part.I.M01;
3714 theobj.I.M02 -= part.I.M02;
3715 theobj.I.M10 -= part.I.M10;
3716 theobj.I.M11 -= part.I.M11;
3717 theobj.I.M12 -= part.I.M12;
3718 theobj.I.M20 -= part.I.M20;
3719 theobj.I.M21 -= part.I.M21;
3720 theobj.I.M22 -= part.I.M22;
3721 }
3722
3723 private void donullchange()
3724 {
3725 }
3726
3727 public bool DoAChange(changes what, object arg)
3728 {
3729 if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.AddPhysRep && what != changes.Remove)
3730 {
3731 return false;
3732 }
3733
3734 // nasty switch
3735 switch (what)
3736 {
3737 case changes.Add:
3738 changeadd();
3739 break;
3740
3741 case changes.AddPhysRep:
3742 changeAddPhysRep((ODEPhysRepData)arg);
3743 break;
3744
3745 case changes.Remove:
3746 //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff...
3747 //When we return true, it destroys all of the prims in the linkset anyway
3748 if (_parent != null)
3749 {
3750 OdePrim parent = (OdePrim)_parent;
3751 parent.ChildRemove(this, false);
3752 }
3753 else
3754 ChildRemove(this, false);
3755
3756 m_vehicle = null;
3757 RemoveGeom();
3758 m_targetSpace = IntPtr.Zero;
3759 UnSubscribeEvents();
3760 return true;
3761
3762 case changes.Link:
3763 OdePrim tmp = (OdePrim)arg;
3764 changeLink(tmp);
3765 break;
3766
3767 case changes.DeLink:
3768 changeLink(null);
3769 break;
3770
3771 case changes.Position:
3772 changePosition((Vector3)arg);
3773 break;
3774
3775 case changes.Orientation:
3776 changeOrientation((Quaternion)arg);
3777 break;
3778
3779 case changes.PosOffset:
3780 donullchange();
3781 break;
3782
3783 case changes.OriOffset:
3784 donullchange();
3785 break;
3786
3787 case changes.Velocity:
3788 changevelocity((Vector3)arg);
3789 break;
3790
3791// case changes.Acceleration:
3792// changeacceleration((Vector3)arg);
3793// break;
3794
3795 case changes.AngVelocity:
3796 changeangvelocity((Vector3)arg);
3797 break;
3798
3799 case changes.Force:
3800 changeForce((Vector3)arg);
3801 break;
3802
3803 case changes.Torque:
3804 changeSetTorque((Vector3)arg);
3805 break;
3806
3807 case changes.AddForce:
3808 changeAddForce((Vector3)arg);
3809 break;
3810
3811 case changes.AddAngForce:
3812 changeAddAngularImpulse((Vector3)arg);
3813 break;
3814
3815 case changes.AngLock:
3816 changeAngularLock((byte)arg);
3817 break;
3818
3819 case changes.Size:
3820 changeSize((Vector3)arg);
3821 break;
3822
3823 case changes.Shape:
3824 changeShape((PrimitiveBaseShape)arg);
3825 break;
3826
3827 case changes.PhysRepData:
3828 changePhysRepData((ODEPhysRepData) arg);
3829 break;
3830
3831 case changes.CollidesWater:
3832 changeFloatOnWater((bool)arg);
3833 break;
3834
3835 case changes.VolumeDtc:
3836 changeVolumedetetion((bool)arg);
3837 break;
3838
3839 case changes.Phantom:
3840 changePhantomStatus((bool)arg);
3841 break;
3842
3843 case changes.Physical:
3844 changePhysicsStatus((bool)arg);
3845 break;
3846
3847 case changes.Selected:
3848 changeSelectedStatus((bool)arg);
3849 break;
3850
3851 case changes.disabled:
3852 changeDisable((bool)arg);
3853 break;
3854
3855 case changes.building:
3856 changeBuilding((bool)arg);
3857 break;
3858
3859 case changes.VehicleType:
3860 changeVehicleType((int)arg);
3861 break;
3862
3863 case changes.VehicleFlags:
3864 changeVehicleFlags((strVehicleBoolParam) arg);
3865 break;
3866
3867 case changes.VehicleFloatParam:
3868 changeVehicleFloatParam((strVehicleFloatParam) arg);
3869 break;
3870
3871 case changes.VehicleVectorParam:
3872 changeVehicleVectorParam((strVehicleVectorParam) arg);
3873 break;
3874
3875 case changes.VehicleRotationParam:
3876 changeVehicleRotationParam((strVehicleQuatParam) arg);
3877 break;
3878
3879 case changes.SetVehicle:
3880 changeSetVehicle((VehicleData) arg);
3881 break;
3882
3883 case changes.Buoyancy:
3884 changeBuoyancy((float)arg);
3885 break;
3886
3887 case changes.PIDTarget:
3888 changePIDTarget((Vector3)arg);
3889 break;
3890
3891 case changes.PIDTau:
3892 changePIDTau((float)arg);
3893 break;
3894
3895 case changes.PIDActive:
3896 changePIDActive((bool)arg);
3897 break;
3898
3899 case changes.PIDHoverHeight:
3900 changePIDHoverHeight((float)arg);
3901 break;
3902
3903 case changes.PIDHoverType:
3904 changePIDHoverType((PIDHoverType)arg);
3905 break;
3906
3907 case changes.PIDHoverTau:
3908 changePIDHoverTau((float)arg);
3909 break;
3910
3911 case changes.PIDHoverActive:
3912 changePIDHoverActive((bool)arg);
3913 break;
3914
3915 case changes.Null:
3916 donullchange();
3917 break;
3918
3919
3920
3921 default:
3922 donullchange();
3923 break;
3924 }
3925 return false;
3926 }
3927
3928 public void AddChange(changes what, object arg)
3929 {
3930 _parent_scene.AddChange((PhysicsActor) this, what, arg);
3931 }
3932
3933
3934 private struct strVehicleBoolParam
3935 {
3936 public int param;
3937 public bool value;
3938 }
3939
3940 private struct strVehicleFloatParam
3941 {
3942 public int param;
3943 public float value;
3944 }
3945
3946 private struct strVehicleQuatParam
3947 {
3948 public int param;
3949 public Quaternion value;
3950 }
3951
3952 private struct strVehicleVectorParam
3953 {
3954 public int param;
3955 public Vector3 value;
3956 }
3957 }
3958}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs b/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs
new file mode 100644
index 0000000..b82d593
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs
@@ -0,0 +1,680 @@
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 OpenSim.Framework;
34using OpenSim.Region.PhysicsModules.SharedBase;
35using OdeAPI;
36using log4net;
37using OpenMetaverse;
38
39namespace OpenSim.Region.PhysicsModule.ubOde
40{
41 /// <summary>
42 /// Processes raycast requests as ODE is in a state to be able to do them.
43 /// This ensures that it's thread safe and there will be no conflicts.
44 /// Requests get returned by a different thread then they were requested by.
45 /// </summary>
46 public class ODERayCastRequestManager
47 {
48 /// <summary>
49 /// Pending ray requests
50 /// </summary>
51 protected OpenSim.Framework.LocklessQueue<ODERayRequest> m_PendingRequests = new OpenSim.Framework.LocklessQueue<ODERayRequest>();
52
53 /// <summary>
54 /// Scene that created this object.
55 /// </summary>
56 private ODEScene m_scene;
57
58 IntPtr ray; // the ray. we only need one for our lifetime
59 IntPtr Sphere;
60 IntPtr Box;
61 IntPtr Plane;
62
63 private int CollisionContactGeomsPerTest = 25;
64 private const int DefaultMaxCount = 25;
65 private const int MaxTimePerCallMS = 30;
66
67 /// <summary>
68 /// ODE near callback delegate
69 /// </summary>
70 private d.NearCallback nearCallback;
71 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
72 private List<ContactResult> m_contactResults = new List<ContactResult>();
73 private RayFilterFlags CurrentRayFilter;
74 private int CurrentMaxCount;
75
76 public ODERayCastRequestManager(ODEScene pScene)
77 {
78 m_scene = pScene;
79 nearCallback = near;
80 ray = d.CreateRay(IntPtr.Zero, 1.0f);
81 d.GeomSetCategoryBits(ray, 0);
82 Box = d.CreateBox(IntPtr.Zero, 1.0f, 1.0f, 1.0f);
83 d.GeomSetCategoryBits(Box, 0);
84 Sphere = d.CreateSphere(IntPtr.Zero,1.0f);
85 d.GeomSetCategoryBits(Sphere, 0);
86 Plane = d.CreatePlane(IntPtr.Zero, 0f,0f,1f,1f);
87 d.GeomSetCategoryBits(Sphere, 0);
88 }
89
90 public void QueueRequest(ODERayRequest req)
91 {
92 if (req.Count == 0)
93 req.Count = DefaultMaxCount;
94
95 m_PendingRequests.Enqueue(req);
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
105 if (m_PendingRequests.Count <= 0)
106 return 0;
107
108 if (m_scene.ContactgeomsArray == IntPtr.Zero || ray == IntPtr.Zero)
109 // oops something got wrong or scene isn't ready still
110 {
111 m_PendingRequests.Clear();
112 return 0;
113 }
114
115 int time = Util.EnvironmentTickCount();
116
117 ODERayRequest req;
118 int closestHit;
119 int backfacecull;
120 CollisionCategories catflags;
121
122 while (m_PendingRequests.Dequeue(out req))
123 {
124 if (req.callbackMethod != null)
125 {
126 IntPtr geom = IntPtr.Zero;
127 if (req.actor != null)
128 {
129 if (m_scene.haveActor(req.actor))
130 {
131 if (req.actor is OdePrim)
132 geom = ((OdePrim)req.actor).prim_geom;
133 else if (req.actor is OdeCharacter)
134 geom = ((OdePrim)req.actor).prim_geom;
135 }
136 if (geom == IntPtr.Zero)
137 {
138 NoContacts(req);
139 continue;
140 }
141 }
142
143 CurrentRayFilter = req.filter;
144 CurrentMaxCount = req.Count;
145
146 CollisionContactGeomsPerTest = req.Count & 0xffff;
147
148 closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1);
149 backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1);
150
151 if (req.callbackMethod is ProbeBoxCallback)
152 {
153 if (CollisionContactGeomsPerTest > 80)
154 CollisionContactGeomsPerTest = 80;
155 d.GeomBoxSetLengths(Box, req.Normal.X, req.Normal.Y, req.Normal.Z);
156 d.GeomSetPosition(Box, req.Origin.X, req.Origin.Y, req.Origin.Z);
157 d.Quaternion qtmp;
158 qtmp.X = req.orientation.X;
159 qtmp.Y = req.orientation.Y;
160 qtmp.Z = req.orientation.Z;
161 qtmp.W = req.orientation.W;
162 d.GeomSetQuaternion(Box, ref qtmp);
163 }
164 else if (req.callbackMethod is ProbeSphereCallback)
165 {
166 if (CollisionContactGeomsPerTest > 80)
167 CollisionContactGeomsPerTest = 80;
168
169 d.GeomSphereSetRadius(Sphere, req.length);
170 d.GeomSetPosition(Sphere, req.Origin.X, req.Origin.Y, req.Origin.Z);
171 }
172 else if (req.callbackMethod is ProbePlaneCallback)
173 {
174 if (CollisionContactGeomsPerTest > 80)
175 CollisionContactGeomsPerTest = 80;
176
177 d.GeomPlaneSetParams(Plane, req.Normal.X, req.Normal.Y, req.Normal.Z, req.length);
178 }
179
180 else
181 {
182 if (CollisionContactGeomsPerTest > 25)
183 CollisionContactGeomsPerTest = 25;
184
185 d.GeomRaySetLength(ray, req.length);
186 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
187 d.GeomRaySetParams(ray, 0, backfacecull);
188
189 if (req.callbackMethod is RaycastCallback)
190 {
191 // if we only want one get only one per Collision pair saving memory
192 CurrentRayFilter |= RayFilterFlags.ClosestHit;
193 d.GeomRaySetClosestHit(ray, 1);
194 }
195 else
196 d.GeomRaySetClosestHit(ray, closestHit);
197 }
198
199 if ((CurrentRayFilter & RayFilterFlags.ContactsUnImportant) != 0)
200 unchecked
201 {
202 CollisionContactGeomsPerTest |= (int)d.CONTACTS_UNIMPORTANT;
203 }
204
205 if (geom == IntPtr.Zero)
206 {
207 // translate ray filter to Collision flags
208 catflags = 0;
209 if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0)
210 catflags |= CollisionCategories.VolumeDtc;
211 if ((CurrentRayFilter & RayFilterFlags.phantom) != 0)
212 catflags |= CollisionCategories.Phantom;
213 if ((CurrentRayFilter & RayFilterFlags.agent) != 0)
214 catflags |= CollisionCategories.Character;
215 if ((CurrentRayFilter & RayFilterFlags.PrimsNonPhantom) != 0)
216 catflags |= CollisionCategories.Geom;
217 if ((CurrentRayFilter & RayFilterFlags.land) != 0)
218 catflags |= CollisionCategories.Land;
219 if ((CurrentRayFilter & RayFilterFlags.water) != 0)
220 catflags |= CollisionCategories.Water;
221
222 if (catflags != 0)
223 {
224 if (req.callbackMethod is ProbeBoxCallback)
225 {
226 catflags |= CollisionCategories.Space;
227 d.GeomSetCollideBits(Box, (uint)catflags);
228 d.GeomSetCategoryBits(Box, (uint)catflags);
229 doProbe(req, Box);
230 }
231 else if (req.callbackMethod is ProbeSphereCallback)
232 {
233 catflags |= CollisionCategories.Space;
234 d.GeomSetCollideBits(Sphere, (uint)catflags);
235 d.GeomSetCategoryBits(Sphere, (uint)catflags);
236 doProbe(req, Sphere);
237 }
238 else if (req.callbackMethod is ProbePlaneCallback)
239 {
240 catflags |= CollisionCategories.Space;
241 d.GeomSetCollideBits(Plane, (uint)catflags);
242 d.GeomSetCategoryBits(Plane, (uint)catflags);
243 doPlane(req,IntPtr.Zero);
244 }
245 else
246 {
247 d.GeomSetCollideBits(ray, (uint)catflags);
248 doSpaceRay(req);
249 }
250 }
251 }
252 else
253 {
254 // if we select a geom don't use filters
255
256 if (req.callbackMethod is ProbePlaneCallback)
257 {
258 d.GeomSetCollideBits(Plane, (uint)CollisionCategories.All);
259 doPlane(req,geom);
260 }
261 else
262 {
263 d.GeomSetCollideBits(ray, (uint)CollisionCategories.All);
264 doGeomRay(req,geom);
265 }
266 }
267 }
268
269 if (Util.EnvironmentTickCountSubtract(time) > MaxTimePerCallMS)
270 break;
271 }
272
273 lock (m_contactResults)
274 m_contactResults.Clear();
275
276 return Util.EnvironmentTickCountSubtract(time);
277 }
278 /// <summary>
279 /// Method that actually initiates the raycast with spaces
280 /// </summary>
281 /// <param name="req"></param>
282 ///
283
284 private void NoContacts(ODERayRequest req)
285 {
286 if (req.callbackMethod is RaycastCallback)
287 {
288 ((RaycastCallback)req.callbackMethod)(false, Vector3.Zero, 0, 0, Vector3.Zero);
289 return;
290 }
291 List<ContactResult> cresult = new List<ContactResult>();
292
293 if (req.callbackMethod is RayCallback)
294 ((RayCallback)req.callbackMethod)(cresult);
295 else if (req.callbackMethod is ProbeBoxCallback)
296 ((ProbeBoxCallback)req.callbackMethod)(cresult);
297 else if (req.callbackMethod is ProbeSphereCallback)
298 ((ProbeSphereCallback)req.callbackMethod)(cresult);
299 }
300
301 private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhantom;
302// private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
303 private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhantom;
304
305 private void doSpaceRay(ODERayRequest req)
306 {
307 // Collide tests
308 if ((CurrentRayFilter & FilterActiveSpace) != 0)
309 {
310 d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
311 d.SpaceCollide2(ray, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
312 }
313 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
314 d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
315 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
316 {
317 // current ode land to ray collisions is very bad
318 // so for now limit its range badly
319 if (req.length > 60.0f)
320 d.GeomRaySetLength(ray, 60.0f);
321
322 d.SpaceCollide2(ray, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
323 }
324
325 if (req.callbackMethod is RaycastCallback)
326 {
327 // Define default results
328 bool hitYN = false;
329 uint hitConsumerID = 0;
330 float distance = float.MaxValue;
331 Vector3 closestcontact = Vector3.Zero;
332 Vector3 snormal = Vector3.Zero;
333
334 // Find closest contact and object.
335 lock (m_contactResults)
336 {
337 foreach (ContactResult cResult in m_contactResults)
338 {
339 if(cResult.Depth < distance)
340 {
341 closestcontact = cResult.Pos;
342 hitConsumerID = cResult.ConsumerID;
343 distance = cResult.Depth;
344 snormal = cResult.Normal;
345 }
346 }
347 m_contactResults.Clear();
348 }
349
350 if (distance > 0 && distance < float.MaxValue)
351 hitYN = true;
352 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
353 }
354 else
355 {
356 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
357 lock (m_PendingRequests)
358 {
359 cresult.AddRange(m_contactResults);
360 m_contactResults.Clear();
361 }
362 ((RayCallback)req.callbackMethod)(cresult);
363 }
364 }
365
366 private void doProbe(ODERayRequest req, IntPtr probe)
367 {
368 // Collide tests
369 if ((CurrentRayFilter & FilterActiveSpace) != 0)
370 {
371 d.SpaceCollide2(probe, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
372 d.SpaceCollide2(probe, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
373 }
374 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
375 d.SpaceCollide2(probe, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
376 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
377 d.SpaceCollide2(probe, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
378
379 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
380 lock (m_PendingRequests)
381 {
382 cresult.AddRange(m_contactResults);
383 m_contactResults.Clear();
384 }
385 if (req.callbackMethod is ProbeBoxCallback)
386 ((ProbeBoxCallback)req.callbackMethod)(cresult);
387 else if (req.callbackMethod is ProbeSphereCallback)
388 ((ProbeSphereCallback)req.callbackMethod)(cresult);
389 }
390
391 private void doPlane(ODERayRequest req,IntPtr geom)
392 {
393 // Collide tests
394 if (geom == IntPtr.Zero)
395 {
396 if ((CurrentRayFilter & FilterActiveSpace) != 0)
397 {
398 d.SpaceCollide2(Plane, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
399 d.SpaceCollide2(Plane, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
400 }
401 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
402 d.SpaceCollide2(Plane, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
403 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
404 d.SpaceCollide2(Plane, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
405 }
406 else
407 {
408 d.SpaceCollide2(Plane, geom, IntPtr.Zero, nearCallback);
409 }
410
411 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
412 lock (m_PendingRequests)
413 {
414 cresult.AddRange(m_contactResults);
415 m_contactResults.Clear();
416 }
417
418 ((ProbePlaneCallback)req.callbackMethod)(cresult);
419 }
420
421 /// <summary>
422 /// Method that actually initiates the raycast with a geom
423 /// </summary>
424 /// <param name="req"></param>
425 private void doGeomRay(ODERayRequest req, IntPtr geom)
426 {
427 // Collide test
428 d.SpaceCollide2(ray, geom, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test
429
430 if (req.callbackMethod is RaycastCallback)
431 {
432 // Define default results
433 bool hitYN = false;
434 uint hitConsumerID = 0;
435 float distance = float.MaxValue;
436 Vector3 closestcontact = Vector3.Zero;
437 Vector3 snormal = Vector3.Zero;
438
439 // Find closest contact and object.
440 lock (m_contactResults)
441 {
442 foreach (ContactResult cResult in m_contactResults)
443 {
444 if(cResult.Depth < distance )
445 {
446 closestcontact = cResult.Pos;
447 hitConsumerID = cResult.ConsumerID;
448 distance = cResult.Depth;
449 snormal = cResult.Normal;
450 }
451 }
452 m_contactResults.Clear();
453 }
454
455 if (distance > 0 && distance < float.MaxValue)
456 hitYN = true;
457
458 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
459 }
460 else
461 {
462 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
463 lock (m_PendingRequests)
464 {
465 cresult.AddRange(m_contactResults);
466 m_contactResults.Clear();
467 }
468 ((RayCallback)req.callbackMethod)(cresult);
469 }
470 }
471
472 private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
473 {
474 IntPtr ContactgeomsArray = m_scene.ContactgeomsArray;
475 if (ContactgeomsArray == IntPtr.Zero || index >= CollisionContactGeomsPerTest)
476 return false;
477
478 IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
479 newcontactgeom = (d.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(d.ContactGeom));
480 return true;
481 }
482
483 // This is the standard Near. g1 is the ray
484 private void near(IntPtr space, IntPtr g1, IntPtr g2)
485 {
486 if (g2 == IntPtr.Zero || g1 == g2)
487 return;
488
489 if (m_contactResults.Count >= CurrentMaxCount)
490 return;
491
492 if (d.GeomIsSpace(g2))
493 {
494 try
495 {
496 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
497 }
498 catch (Exception e)
499 {
500 m_log.WarnFormat("[PHYSICS Ray]: Unable to Space collide test an object: {0}", e.Message);
501 }
502 return;
503 }
504
505 int count = 0;
506 try
507 {
508 count = d.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
509 }
510 catch (Exception e)
511 {
512 m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message);
513 return;
514 }
515
516 if (count == 0)
517 return;
518/*
519 uint cat1 = d.GeomGetCategoryBits(g1);
520 uint cat2 = d.GeomGetCategoryBits(g2);
521 uint col1 = d.GeomGetCollideBits(g1);
522 uint col2 = d.GeomGetCollideBits(g2);
523*/
524
525 uint ID = 0;
526 PhysicsActor p2 = null;
527
528 m_scene.actor_name_map.TryGetValue(g2, out p2);
529
530 if (p2 == null)
531 return;
532
533 switch (p2.PhysicsActorType)
534 {
535 case (int)ActorTypes.Prim:
536
537 RayFilterFlags thisFlags;
538
539 if (p2.IsPhysical)
540 thisFlags = RayFilterFlags.physical;
541 else
542 thisFlags = RayFilterFlags.nonphysical;
543
544 if (p2.Phantom)
545 thisFlags |= RayFilterFlags.phantom;
546
547 if (p2.IsVolumeDtc)
548 thisFlags |= RayFilterFlags.volumedtc;
549
550 if ((thisFlags & CurrentRayFilter) == 0)
551 return;
552
553 ID = ((OdePrim)p2).LocalID;
554 break;
555
556 case (int)ActorTypes.Agent:
557
558 if ((CurrentRayFilter & RayFilterFlags.agent) == 0)
559 return;
560 else
561 ID = ((OdeCharacter)p2).LocalID;
562 break;
563
564 case (int)ActorTypes.Ground:
565
566 if ((CurrentRayFilter & RayFilterFlags.land) == 0)
567 return;
568 break;
569
570 case (int)ActorTypes.Water:
571
572 if ((CurrentRayFilter & RayFilterFlags.water) == 0)
573 return;
574 break;
575
576 default:
577 break;
578 }
579
580 d.ContactGeom curcontact = new d.ContactGeom();
581
582 // closestHit for now only works for meshs, so must do it for others
583 if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0)
584 {
585 // Loop all contacts, build results.
586 for (int i = 0; i < count; i++)
587 {
588 if (!GetCurContactGeom(i, ref curcontact))
589 break;
590
591 ContactResult collisionresult = new ContactResult();
592 collisionresult.ConsumerID = ID;
593 collisionresult.Pos.X = curcontact.pos.X;
594 collisionresult.Pos.Y = curcontact.pos.Y;
595 collisionresult.Pos.Z = curcontact.pos.Z;
596 collisionresult.Depth = curcontact.depth;
597 collisionresult.Normal.X = curcontact.normal.X;
598 collisionresult.Normal.Y = curcontact.normal.Y;
599 collisionresult.Normal.Z = curcontact.normal.Z;
600 lock (m_contactResults)
601 {
602 m_contactResults.Add(collisionresult);
603 if (m_contactResults.Count >= CurrentMaxCount)
604 return;
605 }
606 }
607 }
608 else
609 {
610 // keep only closest contact
611 ContactResult collisionresult = new ContactResult();
612 collisionresult.ConsumerID = ID;
613 collisionresult.Depth = float.MaxValue;
614
615 for (int i = 0; i < count; i++)
616 {
617 if (!GetCurContactGeom(i, ref curcontact))
618 break;
619
620 if (curcontact.depth < collisionresult.Depth)
621 {
622 collisionresult.Pos.X = curcontact.pos.X;
623 collisionresult.Pos.Y = curcontact.pos.Y;
624 collisionresult.Pos.Z = curcontact.pos.Z;
625 collisionresult.Depth = curcontact.depth;
626 collisionresult.Normal.X = curcontact.normal.X;
627 collisionresult.Normal.Y = curcontact.normal.Y;
628 collisionresult.Normal.Z = curcontact.normal.Z;
629 }
630 }
631
632 if (collisionresult.Depth != float.MaxValue)
633 {
634 lock (m_contactResults)
635 m_contactResults.Add(collisionresult);
636 }
637 }
638 }
639
640 /// <summary>
641 /// Dereference the creator scene so that it can be garbage collected if needed.
642 /// </summary>
643 internal void Dispose()
644 {
645 m_scene = null;
646 if (ray != IntPtr.Zero)
647 {
648 d.GeomDestroy(ray);
649 ray = IntPtr.Zero;
650 }
651 if (Box != IntPtr.Zero)
652 {
653 d.GeomDestroy(Box);
654 Box = IntPtr.Zero;
655 }
656 if (Sphere != IntPtr.Zero)
657 {
658 d.GeomDestroy(Sphere);
659 Sphere = IntPtr.Zero;
660 }
661 if (Plane != IntPtr.Zero)
662 {
663 d.GeomDestroy(Plane);
664 Plane = IntPtr.Zero;
665 }
666 }
667 }
668
669 public struct ODERayRequest
670 {
671 public PhysicsActor actor;
672 public Vector3 Origin;
673 public Vector3 Normal;
674 public int Count;
675 public float length;
676 public object callbackMethod;
677 public RayFilterFlags filter;
678 public Quaternion orientation;
679 }
680}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs
new file mode 100644
index 0000000..2da2603
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs
@@ -0,0 +1,2819 @@
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
28// Revision 2011/12/13 by Ubit Umarov
29//#define SPAM
30
31using System;
32using System.Collections.Generic;
33using System.Reflection;
34using System.Runtime.InteropServices;
35using System.Threading;
36using System.IO;
37using System.Diagnostics;
38using log4net;
39using Nini.Config;
40using Mono.Addins;
41using OdeAPI;
42using OpenSim.Framework;
43using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.PhysicsModules.SharedBase;
46using OpenMetaverse;
47
48namespace OpenSim.Region.PhysicsModule.ubOde
49{
50 // colision flags of things others can colide with
51 // rays, sensors, probes removed since can't be colided with
52 // The top space where things are placed provided further selection
53 // ie physical are in active space nonphysical in static
54 // this should be exclusive as possible
55
56 [Flags]
57 public enum CollisionCategories : uint
58 {
59 Disabled = 0,
60 //by 'things' types
61 Space = 0x01,
62 Geom = 0x02, // aka prim/part
63 Character = 0x04,
64 Land = 0x08,
65 Water = 0x010,
66
67 // by state
68 Phantom = 0x01000,
69 VolumeDtc = 0x02000,
70 Selected = 0x04000,
71 NoShape = 0x08000,
72
73
74 All = 0xffffffff
75 }
76
77 /// <summary>
78 /// Material type for a primitive
79 /// </summary>
80 public enum Material : int
81 {
82 /// <summary></summary>
83 Stone = 0,
84 /// <summary></summary>
85 Metal = 1,
86 /// <summary></summary>
87 Glass = 2,
88 /// <summary></summary>
89 Wood = 3,
90 /// <summary></summary>
91 Flesh = 4,
92 /// <summary></summary>
93 Plastic = 5,
94 /// <summary></summary>
95 Rubber = 6,
96
97 light = 7 // compatibility with old viewers
98 }
99
100 public enum changes : int
101 {
102 Add = 0, // arg null. finishs the prim creation. should be used internally only ( to remove later ?)
103 Remove,
104 Link, // arg AuroraODEPrim new parent prim or null to delink. Makes the prim part of a object with prim parent as root
105 // or removes from a object if arg is null
106 DeLink,
107 Position, // arg Vector3 new position in world coords. Changes prim position. Prim must know if it is root or child
108 Orientation, // arg Quaternion new orientation in world coords. Changes prim position. Prim must know it it is root or child
109 PosOffset, // not in use
110 // arg Vector3 new position in local coords. Changes prim position in object
111 OriOffset, // not in use
112 // arg Vector3 new position in local coords. Changes prim position in object
113 Velocity,
114 AngVelocity,
115 Acceleration,
116 Force,
117 Torque,
118 Momentum,
119
120 AddForce,
121 AddAngForce,
122 AngLock,
123
124 Buoyancy,
125
126 PIDTarget,
127 PIDTau,
128 PIDActive,
129
130 PIDHoverHeight,
131 PIDHoverType,
132 PIDHoverTau,
133 PIDHoverActive,
134
135 Size,
136 AvatarSize,
137 Shape,
138 PhysRepData,
139 AddPhysRep,
140
141 CollidesWater,
142 VolumeDtc,
143
144 Physical,
145 Phantom,
146 Selected,
147 disabled,
148 building,
149
150 VehicleType,
151 VehicleFloatParam,
152 VehicleVectorParam,
153 VehicleRotationParam,
154 VehicleFlags,
155 SetVehicle,
156
157 Null //keep this last used do dim the methods array. does nothing but pulsing the prim
158 }
159
160 public struct ODEchangeitem
161 {
162 public PhysicsActor actor;
163 public OdeCharacter character;
164 public changes what;
165 public Object arg;
166 }
167
168 public class ODEScene : PhysicsScene
169 {
170 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
171
172 public bool m_OSOdeLib = false;
173 public bool m_suportCombine = false; // mega suport not tested
174 public Scene m_frameWorkScene = null;
175
176// private int threadid = 0;
177
178// const d.ContactFlags comumContactFlags = d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM |d.ContactFlags.Approx1 | d.ContactFlags.Bounce;
179
180 const d.ContactFlags comumContactFlags = d.ContactFlags.Bounce | d.ContactFlags.Approx1 | d.ContactFlags.Slip1 | d.ContactFlags.Slip2;
181 const float comumContactERP = 0.75f;
182 const float comumContactCFM = 0.0001f;
183 const float comumContactSLIP = 0f;
184
185 float frictionMovementMult = 0.8f;
186
187 float TerrainBounce = 0.1f;
188 float TerrainFriction = 0.3f;
189
190 public float AvatarFriction = 0;// 0.9f * 0.5f;
191
192 // this netx dimensions are only relevant for terrain partition (mega regions)
193 // WorldExtents below has the simulation dimensions
194 // they should be identical except on mega regions
195 private uint m_regionWidth = Constants.RegionSize;
196 private uint m_regionHeight = Constants.RegionSize;
197
198 public float ODE_STEPSIZE = 0.020f;
199 public float HalfOdeStep = 0.01f;
200 public int odetimestepMS = 20; // rounded
201 private float metersInSpace = 25.6f;
202 private float m_timeDilation = 1.0f;
203
204 private DateTime m_lastframe;
205 private DateTime m_lastMeshExpire;
206
207 public float gravityx = 0f;
208 public float gravityy = 0f;
209 public float gravityz = -9.8f;
210
211 private float waterlevel = 0f;
212 private int framecount = 0;
213
214 private float avDensity = 80f;
215 private float avMovementDivisorWalk = 1.3f;
216 private float avMovementDivisorRun = 0.8f;
217 private float minimumGroundFlightOffset = 3f;
218 public float maximumMassObject = 10000.01f;
219
220 public float geomDefaultDensity = 10.0f;
221
222 public float bodyPIDD = 35f;
223 public float bodyPIDG = 25;
224
225 public int bodyFramesAutoDisable = 5;
226
227 private d.NearCallback nearCallback;
228
229 private HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>();
230 private HashSet<OdePrim> _prims = new HashSet<OdePrim>();
231 private HashSet<OdePrim> _activeprims = new HashSet<OdePrim>();
232 private HashSet<OdePrim> _activegroups = new HashSet<OdePrim>();
233
234 public OpenSim.Framework.LocklessQueue<ODEchangeitem> ChangesQueue = new OpenSim.Framework.LocklessQueue<ODEchangeitem>();
235
236 /// <summary>
237 /// A list of actors that should receive collision events.
238 /// </summary>
239 private List<PhysicsActor> _collisionEventPrim = new List<PhysicsActor>();
240 private List<PhysicsActor> _collisionEventPrimRemove = new List<PhysicsActor>();
241
242 private HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>();
243 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
244
245 private float contactsurfacelayer = 0.002f;
246
247 private int contactsPerCollision = 80;
248 internal IntPtr ContactgeomsArray = IntPtr.Zero;
249 private IntPtr GlobalContactsArray = IntPtr.Zero;
250 private d.Contact SharedTmpcontact = new d.Contact();
251
252 const int maxContactsbeforedeath = 6000;
253 private volatile int m_global_contactcount = 0;
254
255 private IntPtr contactgroup;
256
257 public ContactData[] m_materialContactsData = new ContactData[8];
258
259 private Dictionary<Vector3, IntPtr> RegionTerrain = new Dictionary<Vector3, IntPtr>();
260 private Dictionary<IntPtr, float[]> TerrainHeightFieldHeights = new Dictionary<IntPtr, float[]>();
261 private Dictionary<IntPtr, GCHandle> TerrainHeightFieldHeightsHandlers = new Dictionary<IntPtr, GCHandle>();
262
263 private int m_physicsiterations = 15;
264 private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag
265// private PhysicsActor PANull = new NullPhysicsActor();
266 private float step_time = 0.0f;
267
268 public IntPtr world;
269
270 // split the spaces acording to contents type
271 // ActiveSpace contains characters and active prims
272 // StaticSpace contains land and other that is mostly static in enviroment
273 // this can contain subspaces, like the grid in staticspace
274 // as now space only contains this 2 top spaces
275
276 public IntPtr TopSpace; // the global space
277 public IntPtr ActiveSpace; // space for active prims
278 public IntPtr CharsSpace; // space for active prims
279 public IntPtr StaticSpace; // space for the static things around
280 public IntPtr GroundSpace; // space for ground
281
282 // some speedup variables
283 private int spaceGridMaxX;
284 private int spaceGridMaxY;
285 private float spacesPerMeterX;
286 private float spacesPerMeterY;
287
288 // split static geometry collision into a grid as before
289 private IntPtr[,] staticPrimspace;
290 private IntPtr[] staticPrimspaceOffRegion;
291
292 public Object OdeLock;
293 public static Object SimulationLock;
294
295 public IMesher mesher;
296
297 public IConfigSource m_config;
298
299 public bool physics_logging = false;
300 public int physics_logging_interval = 0;
301 public bool physics_logging_append_existing_logfile = false;
302
303 private Vector3 m_worldOffset = Vector3.Zero;
304 public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
305 private PhysicsScene m_parentScene = null;
306
307 private ODERayCastRequestManager m_rayCastManager;
308 public ODEMeshWorker m_meshWorker;
309
310 /* maybe needed if ode uses tls
311 private void checkThread()
312 {
313
314 int th = Thread.CurrentThread.ManagedThreadId;
315 if(th != threadid)
316 {
317 threadid = th;
318 d.AllocateODEDataForThread(~0U);
319 }
320 }
321 */
322
323 IConfig physicsconfig = null;
324
325 public ODEScene(Scene pscene, IConfigSource psourceconfig, string pname, bool pOSOdeLib)
326 {
327 OdeLock = new Object();
328
329 EngineType = pname;
330 PhysicsSceneName = EngineType + "/" + pscene.RegionInfo.RegionName;
331
332 m_config = psourceconfig;
333 m_OSOdeLib = pOSOdeLib;
334
335// m_OSOdeLib = false; //debug
336
337 m_frameWorkScene = pscene;
338
339 m_frameWorkScene.RegisterModuleInterface<PhysicsScene>(this);
340
341 Initialization();
342
343 base.Initialise(m_frameWorkScene.PhysicsRequestAsset,
344 (m_frameWorkScene.Heightmap != null ? m_frameWorkScene.Heightmap.GetFloatsSerialised() : new float[m_frameWorkScene.RegionInfo.RegionSizeX * m_frameWorkScene.RegionInfo.RegionSizeY]),
345 (float)m_frameWorkScene.RegionInfo.RegionSettings.WaterHeight);
346 }
347
348 public void RegionLoaded()
349 {
350 mesher = m_frameWorkScene.RequestModuleInterface<IMesher>();
351 if (mesher == null)
352 {
353 m_log.ErrorFormat("[ubOde] No mesher. module disabled");
354 return;
355 }
356
357 m_meshWorker = new ODEMeshWorker(this, m_log, mesher, physicsconfig);
358 m_frameWorkScene.PhysicsEnabled = true;
359 }
360 /// <summary>
361 /// Initiailizes the scene
362 /// Sets many properties that ODE requires to be stable
363 /// These settings need to be tweaked 'exactly' right or weird stuff happens.
364 /// </summary>
365 private void Initialization()
366 {
367 // checkThread();
368 SimulationLock = new Object();
369
370 nearCallback = near;
371
372 m_rayCastManager = new ODERayCastRequestManager(this);
373
374 WorldExtents.X = m_frameWorkScene.RegionInfo.RegionSizeX;
375 m_regionWidth = (uint)WorldExtents.X;
376 WorldExtents.Y = m_frameWorkScene.RegionInfo.RegionSizeY;
377 m_regionHeight = (uint)WorldExtents.Y;
378
379 m_suportCombine = false;
380
381 lock (OdeLock)
382 {
383 // Create the world and the first space
384 try
385 {
386 world = d.WorldCreate();
387 TopSpace = d.HashSpaceCreate(IntPtr.Zero);
388
389 // now the major subspaces
390 ActiveSpace = d.HashSpaceCreate(TopSpace);
391 CharsSpace = d.HashSpaceCreate(TopSpace);
392 StaticSpace = d.HashSpaceCreate(TopSpace);
393 GroundSpace = d.HashSpaceCreate(TopSpace);
394 }
395 catch
396 {
397 // i must RtC#FM
398 // i did!
399 }
400
401 d.HashSpaceSetLevels(TopSpace, -5, 12);
402 d.HashSpaceSetLevels(ActiveSpace, -5, 10);
403 d.HashSpaceSetLevels(CharsSpace, -4, 3);
404 d.HashSpaceSetLevels(StaticSpace, -5, 12);
405 d.HashSpaceSetLevels(GroundSpace, 0, 8);
406
407 // demote to second level
408 d.SpaceSetSublevel(ActiveSpace, 1);
409 d.SpaceSetSublevel(CharsSpace, 1);
410 d.SpaceSetSublevel(StaticSpace, 1);
411 d.SpaceSetSublevel(GroundSpace, 1);
412
413 d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space |
414 CollisionCategories.Geom |
415 CollisionCategories.Character |
416 CollisionCategories.Phantom |
417 CollisionCategories.VolumeDtc
418 ));
419 d.GeomSetCollideBits(ActiveSpace, (uint)(CollisionCategories.Space |
420 CollisionCategories.Geom |
421 CollisionCategories.Character |
422 CollisionCategories.Phantom |
423 CollisionCategories.VolumeDtc
424 ));
425 d.GeomSetCategoryBits(CharsSpace, (uint)(CollisionCategories.Space |
426 CollisionCategories.Geom |
427 CollisionCategories.Character |
428 CollisionCategories.Phantom |
429 CollisionCategories.VolumeDtc
430 ));
431 d.GeomSetCollideBits(CharsSpace, 0);
432
433 d.GeomSetCategoryBits(StaticSpace, (uint)(CollisionCategories.Space |
434 CollisionCategories.Geom |
435 // CollisionCategories.Land |
436 // CollisionCategories.Water |
437 CollisionCategories.Phantom |
438 CollisionCategories.VolumeDtc
439 ));
440 d.GeomSetCollideBits(StaticSpace, 0);
441
442 d.GeomSetCategoryBits(GroundSpace, (uint)(CollisionCategories.Land));
443 d.GeomSetCollideBits(GroundSpace, 0);
444
445 contactgroup = d.JointGroupCreate(maxContactsbeforedeath + 1);
446 //contactgroup
447
448 d.WorldSetAutoDisableFlag(world, false);
449 }
450
451
452 // checkThread();
453
454
455 // Defaults
456
457 int contactsPerCollision = 80;
458
459 physicsconfig = null;
460
461 if (m_config != null)
462 {
463 physicsconfig = m_config.Configs["ODEPhysicsSettings"];
464 if (physicsconfig != null)
465 {
466 gravityx = physicsconfig.GetFloat("world_gravityx", gravityx);
467 gravityy = physicsconfig.GetFloat("world_gravityy", gravityy);
468 gravityz = physicsconfig.GetFloat("world_gravityz", gravityz);
469
470 metersInSpace = physicsconfig.GetFloat("meters_in_small_space", metersInSpace);
471
472 // contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", contactsurfacelayer);
473
474 ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", ODE_STEPSIZE);
475
476 avDensity = physicsconfig.GetFloat("av_density", avDensity);
477 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", avMovementDivisorWalk);
478 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", avMovementDivisorRun);
479
480 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", contactsPerCollision);
481
482 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity);
483 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable);
484
485 physics_logging = physicsconfig.GetBoolean("physics_logging", false);
486 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
487 physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
488
489 minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", minimumGroundFlightOffset);
490 maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", maximumMassObject);
491
492 avDensity *= 3f / 80f; // scale other engines density option to this
493 }
494 }
495
496 d.WorldSetCFM(world, comumContactCFM);
497 d.WorldSetERP(world, comumContactERP);
498
499 d.WorldSetGravity(world, gravityx, gravityy, gravityz);
500
501 d.WorldSetLinearDamping(world, 0.002f);
502 d.WorldSetAngularDamping(world, 0.002f);
503 d.WorldSetAngularDampingThreshold(world, 0f);
504 d.WorldSetLinearDampingThreshold(world, 0f);
505 d.WorldSetMaxAngularSpeed(world, 100f);
506
507 d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
508
509 d.WorldSetContactSurfaceLayer(world, contactsurfacelayer);
510 d.WorldSetContactMaxCorrectingVel(world, 60.0f);
511
512 HalfOdeStep = ODE_STEPSIZE * 0.5f;
513 odetimestepMS = (int)(1000.0f * ODE_STEPSIZE + 0.5f);
514
515 ContactgeomsArray = Marshal.AllocHGlobal(contactsPerCollision * d.ContactGeom.unmanagedSizeOf);
516 GlobalContactsArray = Marshal.AllocHGlobal((maxContactsbeforedeath + 100) * d.Contact.unmanagedSizeOf);
517
518 SharedTmpcontact.geom.g1 = IntPtr.Zero;
519 SharedTmpcontact.geom.g2 = IntPtr.Zero;
520
521 SharedTmpcontact.geom.side1 = -1;
522 SharedTmpcontact.geom.side2 = -1;
523
524 SharedTmpcontact.surface.mode = comumContactFlags;
525 SharedTmpcontact.surface.mu = 0;
526 SharedTmpcontact.surface.bounce = 0;
527 SharedTmpcontact.surface.soft_cfm = comumContactCFM;
528 SharedTmpcontact.surface.soft_erp = comumContactERP;
529 SharedTmpcontact.surface.slip1 = comumContactSLIP;
530 SharedTmpcontact.surface.slip2 = comumContactSLIP;
531
532 m_materialContactsData[(int)Material.Stone].mu = 0.8f;
533 m_materialContactsData[(int)Material.Stone].bounce = 0.4f;
534
535 m_materialContactsData[(int)Material.Metal].mu = 0.3f;
536 m_materialContactsData[(int)Material.Metal].bounce = 0.4f;
537
538 m_materialContactsData[(int)Material.Glass].mu = 0.2f;
539 m_materialContactsData[(int)Material.Glass].bounce = 0.7f;
540
541 m_materialContactsData[(int)Material.Wood].mu = 0.6f;
542 m_materialContactsData[(int)Material.Wood].bounce = 0.5f;
543
544 m_materialContactsData[(int)Material.Flesh].mu = 0.9f;
545 m_materialContactsData[(int)Material.Flesh].bounce = 0.3f;
546
547 m_materialContactsData[(int)Material.Plastic].mu = 0.4f;
548 m_materialContactsData[(int)Material.Plastic].bounce = 0.7f;
549
550 m_materialContactsData[(int)Material.Rubber].mu = 0.9f;
551 m_materialContactsData[(int)Material.Rubber].bounce = 0.95f;
552
553 m_materialContactsData[(int)Material.light].mu = 0.0f;
554 m_materialContactsData[(int)Material.light].bounce = 0.0f;
555
556
557 spacesPerMeterX = 1.0f / metersInSpace;
558 spacesPerMeterY = spacesPerMeterX;
559 spaceGridMaxX = (int)(WorldExtents.X * spacesPerMeterX);
560 spaceGridMaxY = (int)(WorldExtents.Y * spacesPerMeterY);
561
562 if (spaceGridMaxX > 24)
563 {
564 spaceGridMaxX = 24;
565 spacesPerMeterX = spaceGridMaxX / WorldExtents.X;
566 }
567
568 if (spaceGridMaxY > 24)
569 {
570 spaceGridMaxY = 24;
571 spacesPerMeterY = spaceGridMaxY / WorldExtents.Y;
572 }
573
574 staticPrimspace = new IntPtr[spaceGridMaxX, spaceGridMaxY];
575
576 // create all spaces now
577 int i, j;
578 IntPtr newspace;
579
580 for (i = 0; i < spaceGridMaxX; i++)
581 for (j = 0; j < spaceGridMaxY; j++)
582 {
583 newspace = d.HashSpaceCreate(StaticSpace);
584 d.GeomSetCategoryBits(newspace, (int)CollisionCategories.Space);
585 waitForSpaceUnlock(newspace);
586 d.SpaceSetSublevel(newspace, 2);
587 d.HashSpaceSetLevels(newspace, -2, 8);
588 d.GeomSetCategoryBits(newspace, (uint)(CollisionCategories.Space |
589 CollisionCategories.Geom |
590 CollisionCategories.Land |
591 CollisionCategories.Water |
592 CollisionCategories.Phantom |
593 CollisionCategories.VolumeDtc
594 ));
595 d.GeomSetCollideBits(newspace, 0);
596
597 staticPrimspace[i, j] = newspace;
598 }
599
600 // let this now be index limit
601 spaceGridMaxX--;
602 spaceGridMaxY--;
603
604 // create 4 off world spaces (x<0,x>max,y<0,y>max)
605 staticPrimspaceOffRegion = new IntPtr[4];
606
607 for (i = 0; i < 4; i++)
608 {
609 newspace = d.HashSpaceCreate(StaticSpace);
610 d.GeomSetCategoryBits(newspace, (int)CollisionCategories.Space);
611 waitForSpaceUnlock(newspace);
612 d.SpaceSetSublevel(newspace, 2);
613 d.HashSpaceSetLevels(newspace, -2, 8);
614 d.GeomSetCategoryBits(newspace, (uint)(CollisionCategories.Space |
615 CollisionCategories.Geom |
616 CollisionCategories.Land |
617 CollisionCategories.Water |
618 CollisionCategories.Phantom |
619 CollisionCategories.VolumeDtc
620 ));
621 d.GeomSetCollideBits(newspace, 0);
622
623 staticPrimspaceOffRegion[i] = newspace;
624 }
625
626 m_lastframe = DateTime.UtcNow;
627 m_lastMeshExpire = m_lastframe;
628 }
629
630 internal void waitForSpaceUnlock(IntPtr space)
631 {
632 //if (space != IntPtr.Zero)
633 //while (d.SpaceLockQuery(space)) { } // Wait and do nothing
634 }
635
636 #region Collision Detection
637
638 // sets a global contact for a joint for contactgeom , and base contact description)
639 private IntPtr CreateContacJoint(ref d.ContactGeom contactGeom,bool smooth)
640 {
641 if (m_global_contactcount >= maxContactsbeforedeath)
642 return IntPtr.Zero;
643
644 m_global_contactcount++;
645 if(smooth)
646 SharedTmpcontact.geom.depth = contactGeom.depth * 0.05f;
647 else
648 SharedTmpcontact.geom.depth = contactGeom.depth;
649 SharedTmpcontact.geom.pos = contactGeom.pos;
650 SharedTmpcontact.geom.normal = contactGeom.normal;
651
652 IntPtr contact = new IntPtr(GlobalContactsArray.ToInt64() + (Int64)(m_global_contactcount * d.Contact.unmanagedSizeOf));
653 Marshal.StructureToPtr(SharedTmpcontact, contact, true);
654 return d.JointCreateContactPtr(world, contactgroup, contact);
655 }
656
657 private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
658 {
659 if (ContactgeomsArray == IntPtr.Zero || index >= contactsPerCollision)
660 return false;
661
662 IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
663 newcontactgeom = (d.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(d.ContactGeom));
664 return true;
665 }
666
667 /// <summary>
668 /// This is our near callback. A geometry is near a body
669 /// </summary>
670 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
671 /// <param name="g1">a geometry or space</param>
672 /// <param name="g2">another geometry or space</param>
673 ///
674
675 private void near(IntPtr space, IntPtr g1, IntPtr g2)
676 {
677 // no lock here! It's invoked from within Simulate(), which is thread-locked
678
679 if (m_global_contactcount >= maxContactsbeforedeath)
680 return;
681
682 // Test if we're colliding a geom with a space.
683 // If so we have to drill down into the space recursively
684
685 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
686 return;
687
688 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
689 {
690 // We'll be calling near recursivly if one
691 // of them is a space to find all of the
692 // contact points in the space
693 try
694 {
695 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
696 }
697 catch (AccessViolationException)
698 {
699 m_log.Warn("[PHYSICS]: Unable to collide test a space");
700 return;
701 }
702 //here one should check collisions of geoms inside a space
703 // but on each space we only should have geoms that not colide amoung each other
704 // so we don't dig inside spaces
705 return;
706 }
707
708 // get geom bodies to check if we already a joint contact
709 // guess this shouldn't happen now
710 IntPtr b1 = d.GeomGetBody(g1);
711 IntPtr b2 = d.GeomGetBody(g2);
712
713 // d.GeomClassID id = d.GeomGetClass(g1);
714
715 // Figure out how many contact points we have
716 int count = 0;
717 try
718 {
719 // Colliding Geom To Geom
720 // This portion of the function 'was' blatantly ripped off from BoxStack.cs
721
722 if (g1 == g2)
723 return; // Can't collide with yourself
724
725 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
726 return;
727 /*
728 // debug
729 PhysicsActor dp2;
730 if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
731 {
732 d.AABB aabb;
733 d.GeomGetAABB(g2, out aabb);
734 float x = aabb.MaxX - aabb.MinX;
735 float y = aabb.MaxY - aabb.MinY;
736 float z = aabb.MaxZ - aabb.MinZ;
737 if (x > 60.0f || y > 60.0f || z > 60.0f)
738 {
739 if (!actor_name_map.TryGetValue(g2, out dp2))
740 m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2");
741 else
742 m_log.WarnFormat("[PHYSICS]: land versus large prim geo {0},size {1}, AABBsize <{2},{3},{4}>, at {5} ori {6},({7})",
743 dp2.Name, dp2.Size, x, y, z,
744 dp2.Position.ToString(),
745 dp2.Orientation.ToString(),
746 dp2.Orientation.Length());
747 return;
748 }
749 }
750 //
751 */
752
753
754 if (d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc ||
755 d.GeomGetCategoryBits(g2) == (uint)CollisionCategories.VolumeDtc)
756 {
757 int cflags;
758 unchecked
759 {
760 cflags = (int)(1 | d.CONTACTS_UNIMPORTANT);
761 }
762 count = d.CollidePtr(g1, g2, cflags, ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
763 }
764 else
765 count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
766 }
767 catch (SEHException)
768 {
769 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.");
770 // ode.drelease(world);
771 base.TriggerPhysicsBasedRestart();
772 }
773 catch (Exception e)
774 {
775 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
776 return;
777 }
778
779 // contacts done
780 if (count == 0)
781 return;
782
783 // try get physical actors
784 PhysicsActor p1;
785 PhysicsActor p2;
786
787 if (!actor_name_map.TryGetValue(g1, out p1))
788 {
789 m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 1");
790 return;
791 }
792
793 if (!actor_name_map.TryGetValue(g2, out p2))
794 {
795 m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2");
796 return;
797 }
798
799 // update actors collision score
800 if (p1.CollisionScore >= float.MaxValue - count)
801 p1.CollisionScore = 0;
802 p1.CollisionScore += count;
803
804 if (p2.CollisionScore >= float.MaxValue - count)
805 p2.CollisionScore = 0;
806 p2.CollisionScore += count;
807
808 // get first contact
809 d.ContactGeom curContact = new d.ContactGeom();
810
811 if (!GetCurContactGeom(0, ref curContact))
812 return;
813
814 ContactPoint maxDepthContact = new ContactPoint();
815
816 // do volume detection case
817 if ((p1.IsVolumeDtc || p2.IsVolumeDtc))
818 {
819 maxDepthContact = new ContactPoint(
820 new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z),
821 new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z),
822 curContact.depth, false
823 );
824
825 collision_accounting_events(p1, p2, maxDepthContact);
826 return;
827 }
828
829 // big messy collision analises
830
831 float mu = 0;
832 float bounce = 0;
833// bool IgnoreNegSides = false;
834
835 ContactData contactdata1 = new ContactData(0, 0, false);
836 ContactData contactdata2 = new ContactData(0, 0, false);
837
838 bool dop1ava = false;
839 bool dop2ava = false;
840 bool ignore = false;
841 bool smoothMesh = false;
842
843 switch (p1.PhysicsActorType)
844 {
845 case (int)ActorTypes.Agent:
846 {
847 dop1ava = true;
848 switch (p2.PhysicsActorType)
849 {
850 case (int)ActorTypes.Agent:
851 case (int)ActorTypes.Prim:
852 break;
853
854 default:
855 ignore = true; // avatar to terrain and water ignored
856 break;
857 }
858 break;
859 }
860
861 case (int)ActorTypes.Prim:
862 {
863 switch (p2.PhysicsActorType)
864 {
865 case (int)ActorTypes.Agent:
866 dop2ava = true;
867 break;
868
869 case (int)ActorTypes.Prim:
870 Vector3 relV = p1.Velocity - p2.Velocity;
871 float relVlenSQ = relV.LengthSquared();
872 if (relVlenSQ > 0.0001f)
873 {
874 p1.CollidingObj = true;
875 p2.CollidingObj = true;
876 }
877 p1.getContactData(ref contactdata1);
878 p2.getContactData(ref contactdata2);
879 bounce = contactdata1.bounce * contactdata2.bounce;
880 mu = (float)Math.Sqrt(contactdata1.mu * contactdata2.mu);
881
882 if (relVlenSQ > 0.01f)
883 mu *= frictionMovementMult;
884
885 if(d.GeomGetClass(g2) == d.GeomClassID.TriMeshClass &&
886 d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass)
887 smoothMesh = true;
888 break;
889
890 case (int)ActorTypes.Ground:
891 p1.getContactData(ref contactdata1);
892 bounce = contactdata1.bounce * TerrainBounce;
893 mu = (float)Math.Sqrt(contactdata1.mu * TerrainFriction);
894
895 if (Math.Abs(p1.Velocity.X) > 0.1f || Math.Abs(p1.Velocity.Y) > 0.1f)
896 mu *= frictionMovementMult;
897 p1.CollidingGround = true;
898
899 if(d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass)
900 smoothMesh = true;
901 break;
902
903 case (int)ActorTypes.Water:
904 default:
905 ignore = true;
906 break;
907 }
908 }
909 break;
910
911 case (int)ActorTypes.Ground:
912 if (p2.PhysicsActorType == (int)ActorTypes.Prim)
913 {
914 p2.CollidingGround = true;
915 p2.getContactData(ref contactdata2);
916 bounce = contactdata2.bounce * TerrainBounce;
917 mu = (float)Math.Sqrt(contactdata2.mu * TerrainFriction);
918
919// if (curContact.side1 > 0) // should be 2 ?
920// IgnoreNegSides = true;
921
922 if (Math.Abs(p2.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y) > 0.1f)
923 mu *= frictionMovementMult;
924
925 if(d.GeomGetClass(g2) == d.GeomClassID.TriMeshClass)
926 smoothMesh = true;
927 }
928 else
929 ignore = true;
930 break;
931
932 case (int)ActorTypes.Water:
933 default:
934 break;
935 }
936
937 if (ignore)
938 return;
939
940 IntPtr Joint;
941 bool FeetCollision = false;
942 int ncontacts = 0;
943
944 int i = 0;
945
946 maxDepthContact = new ContactPoint();
947 maxDepthContact.PenetrationDepth = float.MinValue;
948 ContactPoint minDepthContact = new ContactPoint();
949 minDepthContact.PenetrationDepth = float.MaxValue;
950
951 SharedTmpcontact.geom.depth = 0;
952 SharedTmpcontact.surface.mu = mu;
953 SharedTmpcontact.surface.bounce = bounce;
954
955 d.ContactGeom altContact = new d.ContactGeom();
956 bool useAltcontact = false;
957 bool noskip = true;
958
959 if(dop1ava || dop2ava)
960 smoothMesh = false;
961
962 while (true)
963 {
964 noskip = true;
965 useAltcontact = false;
966
967 if (dop1ava)
968 {
969 if ((((OdeCharacter)p1).Collide(g1, g2, false, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
970 {
971 if (p2.PhysicsActorType == (int)ActorTypes.Agent)
972 {
973 p1.CollidingObj = true;
974 p2.CollidingObj = true;
975 }
976 else if (p2.Velocity.LengthSquared() > 0.0f)
977 p2.CollidingObj = true;
978 }
979 else
980 noskip = false;
981 }
982 else if (dop2ava)
983 {
984 if ((((OdeCharacter)p2).Collide(g2, g1, true, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
985 {
986 if (p1.PhysicsActorType == (int)ActorTypes.Agent)
987 {
988 p1.CollidingObj = true;
989 p2.CollidingObj = true;
990 }
991 else if (p2.Velocity.LengthSquared() > 0.0f)
992 p1.CollidingObj = true;
993 }
994 else
995 noskip = false;
996 }
997
998 if (noskip)
999 {
1000 if(useAltcontact)
1001 Joint = CreateContacJoint(ref altContact,smoothMesh);
1002 else
1003 Joint = CreateContacJoint(ref curContact,smoothMesh);
1004
1005 if (Joint == IntPtr.Zero)
1006 break;
1007
1008 d.JointAttach(Joint, b1, b2);
1009
1010 ncontacts++;
1011
1012 if (curContact.depth > maxDepthContact.PenetrationDepth)
1013 {
1014 maxDepthContact.Position.X = curContact.pos.X;
1015 maxDepthContact.Position.Y = curContact.pos.Y;
1016 maxDepthContact.Position.Z = curContact.pos.Z;
1017 maxDepthContact.PenetrationDepth = curContact.depth;
1018 maxDepthContact.CharacterFeet = FeetCollision;
1019 }
1020
1021 if (curContact.depth < minDepthContact.PenetrationDepth)
1022 {
1023 minDepthContact.PenetrationDepth = curContact.depth;
1024 minDepthContact.SurfaceNormal.X = curContact.normal.X;
1025 minDepthContact.SurfaceNormal.Y = curContact.normal.Y;
1026 minDepthContact.SurfaceNormal.Z = curContact.normal.Z;
1027 }
1028 }
1029
1030 if (++i >= count)
1031 break;
1032
1033 if (!GetCurContactGeom(i, ref curContact))
1034 break;
1035 }
1036
1037 if (ncontacts > 0)
1038 {
1039 maxDepthContact.SurfaceNormal.X = minDepthContact.SurfaceNormal.X;
1040 maxDepthContact.SurfaceNormal.Y = minDepthContact.SurfaceNormal.Y;
1041 maxDepthContact.SurfaceNormal.Z = minDepthContact.SurfaceNormal.Z;
1042
1043 collision_accounting_events(p1, p2, maxDepthContact);
1044 }
1045 }
1046
1047 private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact)
1048 {
1049 uint obj2LocalID = 0;
1050
1051 bool p1events = p1.SubscribedEvents();
1052 bool p2events = p2.SubscribedEvents();
1053
1054 if (p1.IsVolumeDtc)
1055 p2events = false;
1056 if (p2.IsVolumeDtc)
1057 p1events = false;
1058
1059 if (!p2events && !p1events)
1060 return;
1061
1062 Vector3 vel = Vector3.Zero;
1063 if (p2 != null && p2.IsPhysical)
1064 vel = p2.Velocity;
1065
1066 if (p1 != null && p1.IsPhysical)
1067 vel -= p1.Velocity;
1068
1069 contact.RelativeSpeed = Vector3.Dot(vel, contact.SurfaceNormal);
1070
1071 switch ((ActorTypes)p1.PhysicsActorType)
1072 {
1073 case ActorTypes.Agent:
1074 case ActorTypes.Prim:
1075 {
1076 switch ((ActorTypes)p2.PhysicsActorType)
1077 {
1078 case ActorTypes.Agent:
1079 case ActorTypes.Prim:
1080 if (p2events)
1081 {
1082 AddCollisionEventReporting(p2);
1083 p2.AddCollisionEvent(p1.ParentActor.LocalID, contact);
1084 }
1085 obj2LocalID = p2.ParentActor.LocalID;
1086 break;
1087
1088 case ActorTypes.Ground:
1089 case ActorTypes.Unknown:
1090 default:
1091 obj2LocalID = 0;
1092 break;
1093 }
1094 if (p1events)
1095 {
1096 contact.SurfaceNormal = -contact.SurfaceNormal;
1097 AddCollisionEventReporting(p1);
1098 p1.AddCollisionEvent(obj2LocalID, contact);
1099 }
1100 break;
1101 }
1102 case ActorTypes.Ground:
1103 case ActorTypes.Unknown:
1104 default:
1105 {
1106 if (p2events && !p2.IsVolumeDtc)
1107 {
1108 AddCollisionEventReporting(p2);
1109 p2.AddCollisionEvent(0, contact);
1110 }
1111 break;
1112 }
1113 }
1114 }
1115
1116 /// <summary>
1117 /// This is our collision testing routine in ODE
1118 /// </summary>
1119 /// <param name="timeStep"></param>
1120 private void collision_optimized()
1121 {
1122 lock (_characters)
1123 {
1124 try
1125 {
1126 foreach (OdeCharacter chr in _characters)
1127 {
1128 if (chr == null || chr.Body == IntPtr.Zero)
1129 continue;
1130
1131 chr.IsColliding = false;
1132 // chr.CollidingGround = false; not done here
1133 chr.CollidingObj = false;
1134 // do colisions with static space
1135 d.SpaceCollide2(chr.collider, StaticSpace, IntPtr.Zero, nearCallback);
1136
1137 // no coll with gnd
1138 }
1139 // chars with chars
1140 d.SpaceCollide(CharsSpace, IntPtr.Zero, nearCallback);
1141
1142 }
1143 catch (AccessViolationException)
1144 {
1145 m_log.Warn("[PHYSICS]: Unable to collide Character to static space");
1146 }
1147
1148 }
1149
1150 lock (_activeprims)
1151 {
1152 foreach (OdePrim aprim in _activeprims)
1153 {
1154 aprim.CollisionScore = 0;
1155 aprim.IsColliding = false;
1156 }
1157 }
1158 lock (_activeprims)
1159 {
1160 try
1161 {
1162 foreach (OdePrim aprim in _activegroups)
1163 {
1164 if(!aprim.m_outbounds && d.BodyIsEnabled(aprim.Body))
1165 {
1166 d.SpaceCollide2(StaticSpace, aprim.collide_geom, IntPtr.Zero, nearCallback);
1167 d.SpaceCollide2(GroundSpace, aprim.collide_geom, IntPtr.Zero, nearCallback);
1168 }
1169 }
1170 }
1171 catch (Exception e)
1172 {
1173 m_log.Warn("[PHYSICS]: Unable to collide Active to Static: " + e.Message);
1174 }
1175 }
1176
1177 // colide active amoung them
1178 try
1179 {
1180 d.SpaceCollide(ActiveSpace, IntPtr.Zero, nearCallback);
1181 }
1182 catch (Exception e)
1183 {
1184 m_log.Warn("[PHYSICS]: Unable to collide in Active: " + e.Message);
1185 }
1186
1187 // and with chars
1188 try
1189 {
1190 d.SpaceCollide2(CharsSpace,ActiveSpace, IntPtr.Zero, nearCallback);
1191 }
1192 catch (Exception e)
1193 {
1194 m_log.Warn("[PHYSICS]: Unable to collide Active to Character: " + e.Message);
1195 }
1196 }
1197
1198 #endregion
1199 /// <summary>
1200 /// Add actor to the list that should receive collision events in the simulate loop.
1201 /// </summary>
1202 /// <param name="obj"></param>
1203 public void AddCollisionEventReporting(PhysicsActor obj)
1204 {
1205 if (!_collisionEventPrim.Contains(obj))
1206 _collisionEventPrim.Add(obj);
1207 }
1208
1209 /// <summary>
1210 /// Remove actor from the list that should receive collision events in the simulate loop.
1211 /// </summary>
1212 /// <param name="obj"></param>
1213 public void RemoveCollisionEventReporting(PhysicsActor obj)
1214 {
1215 if (_collisionEventPrim.Contains(obj) && !_collisionEventPrimRemove.Contains(obj))
1216 _collisionEventPrimRemove.Add(obj);
1217 }
1218
1219 public override float TimeDilation
1220 {
1221 get { return m_timeDilation; }
1222 }
1223
1224 public override bool SupportsNINJAJoints
1225 {
1226 get { return false; }
1227 }
1228
1229 #region Add/Remove Entities
1230
1231 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying)
1232 {
1233 return null;
1234 }
1235
1236 public override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, float feetOffset, bool isFlying)
1237 {
1238 OdeCharacter newAv = new OdeCharacter(localID, avName, this, position,
1239 size, feetOffset, avDensity, avMovementDivisorWalk, avMovementDivisorRun);
1240 newAv.Flying = isFlying;
1241 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1242
1243 return newAv;
1244 }
1245
1246 public void AddCharacter(OdeCharacter chr)
1247 {
1248 lock (_characters)
1249 {
1250 if (!_characters.Contains(chr))
1251 {
1252 _characters.Add(chr);
1253 if (chr.bad)
1254 m_log.DebugFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid);
1255 }
1256 }
1257 }
1258
1259 public void RemoveCharacter(OdeCharacter chr)
1260 {
1261 lock (_characters)
1262 {
1263 if (_characters.Contains(chr))
1264 {
1265 _characters.Remove(chr);
1266 }
1267 }
1268 }
1269
1270 public void BadCharacter(OdeCharacter chr)
1271 {
1272 lock (_badCharacter)
1273 {
1274 if (!_badCharacter.Contains(chr))
1275 _badCharacter.Add(chr);
1276 }
1277 }
1278
1279 public override void RemoveAvatar(PhysicsActor actor)
1280 {
1281 //m_log.Debug("[PHYSICS]:ODELOCK");
1282 ((OdeCharacter) actor).Destroy();
1283 }
1284
1285
1286 public void addActivePrim(OdePrim activatePrim)
1287 {
1288 // adds active prim..
1289 lock (_activeprims)
1290 {
1291 if (!_activeprims.Contains(activatePrim))
1292 _activeprims.Add(activatePrim);
1293 }
1294 }
1295
1296 public void addActiveGroups(OdePrim activatePrim)
1297 {
1298 lock (_activegroups)
1299 {
1300 if (!_activegroups.Contains(activatePrim))
1301 _activegroups.Add(activatePrim);
1302 }
1303 }
1304
1305 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
1306 PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, byte shapeType, uint localID)
1307 {
1308 OdePrim newPrim;
1309 lock (OdeLock)
1310 {
1311 newPrim = new OdePrim(name, this, position, size, rotation, pbs, isphysical, isPhantom, shapeType, localID);
1312 lock (_prims)
1313 _prims.Add(newPrim);
1314 }
1315 return newPrim;
1316 }
1317
1318 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1319 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, uint localid)
1320 {
1321 return AddPrim(primName, position, size, rotation, pbs, isPhysical, isPhantom, 0 , localid);
1322 }
1323
1324
1325 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1326 Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
1327 {
1328 return AddPrim(primName, position, size, rotation, pbs, isPhysical,false, 0, localid);
1329 }
1330
1331 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1332 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapeType, uint localid)
1333 {
1334
1335 return AddPrim(primName, position, size, rotation, pbs, isPhysical,isPhantom, shapeType, localid);
1336 }
1337
1338 public void remActivePrim(OdePrim deactivatePrim)
1339 {
1340 lock (_activeprims)
1341 {
1342 _activeprims.Remove(deactivatePrim);
1343 }
1344 }
1345 public void remActiveGroup(OdePrim deactivatePrim)
1346 {
1347 lock (_activegroups)
1348 {
1349 _activegroups.Remove(deactivatePrim);
1350 }
1351 }
1352
1353 public override void RemovePrim(PhysicsActor prim)
1354 {
1355 // As with all ODE physics operations, we don't remove the prim immediately but signal that it should be
1356 // removed in the next physics simulate pass.
1357 if (prim is OdePrim)
1358 {
1359// lock (OdeLock)
1360 {
1361
1362 OdePrim p = (OdePrim)prim;
1363 p.setPrimForRemoval();
1364 }
1365 }
1366 }
1367
1368 public void RemovePrimThreadLocked(OdePrim prim)
1369 {
1370 //Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName);
1371 lock (prim)
1372 {
1373// RemoveCollisionEventReporting(prim);
1374 lock (_prims)
1375 _prims.Remove(prim);
1376 }
1377
1378 }
1379
1380 public bool havePrim(OdePrim prm)
1381 {
1382 lock (_prims)
1383 return _prims.Contains(prm);
1384 }
1385
1386 public bool haveActor(PhysicsActor actor)
1387 {
1388 if (actor is OdePrim)
1389 {
1390 lock (_prims)
1391 return _prims.Contains((OdePrim)actor);
1392 }
1393 else if (actor is OdeCharacter)
1394 {
1395 lock (_characters)
1396 return _characters.Contains((OdeCharacter)actor);
1397 }
1398 return false;
1399 }
1400
1401 #endregion
1402
1403 #region Space Separation Calculation
1404
1405 /// <summary>
1406 /// Called when a static prim moves or becomes static
1407 /// Places the prim in a space one the static sub-spaces grid
1408 /// </summary>
1409 /// <param name="geom">the pointer to the geom that moved</param>
1410 /// <param name="pos">the position that the geom moved to</param>
1411 /// <param name="currentspace">a pointer to the space it was in before it was moved.</param>
1412 /// <returns>a pointer to the new space it's in</returns>
1413 public IntPtr MoveGeomToStaticSpace(IntPtr geom, Vector3 pos, IntPtr currentspace)
1414 {
1415 // moves a prim into another static sub-space or from another space into a static sub-space
1416
1417 // Called ODEPrim so
1418 // it's already in locked space.
1419
1420 if (geom == IntPtr.Zero) // shouldn't happen
1421 return IntPtr.Zero;
1422
1423 // get the static sub-space for current position
1424 IntPtr newspace = calculateSpaceForGeom(pos);
1425
1426 if (newspace == currentspace) // if we are there all done
1427 return newspace;
1428
1429 // else remove it from its current space
1430 if (currentspace != IntPtr.Zero && d.SpaceQuery(currentspace, geom))
1431 {
1432 if (d.GeomIsSpace(currentspace))
1433 {
1434 waitForSpaceUnlock(currentspace);
1435 d.SpaceRemove(currentspace, geom);
1436
1437 if (d.SpaceGetSublevel(currentspace) > 2 && d.SpaceGetNumGeoms(currentspace) == 0)
1438 {
1439 d.SpaceDestroy(currentspace);
1440 }
1441 }
1442 else
1443 {
1444 m_log.Info("[Physics]: Invalid or empty Space passed to 'MoveGeomToStaticSpace':" + currentspace +
1445 " Geom:" + geom);
1446 }
1447 }
1448 else // odd currentspace is null or doesn't contain the geom? lets try the geom ideia of current space
1449 {
1450 currentspace = d.GeomGetSpace(geom);
1451 if (currentspace != IntPtr.Zero)
1452 {
1453 if (d.GeomIsSpace(currentspace))
1454 {
1455 waitForSpaceUnlock(currentspace);
1456 d.SpaceRemove(currentspace, geom);
1457
1458 if (d.SpaceGetSublevel(currentspace) > 2 && d.SpaceGetNumGeoms(currentspace) == 0)
1459 {
1460 d.SpaceDestroy(currentspace);
1461 }
1462
1463 }
1464 }
1465 }
1466
1467 // put the geom in the newspace
1468 waitForSpaceUnlock(newspace);
1469 d.SpaceAdd(newspace, geom);
1470
1471 // let caller know this newspace
1472 return newspace;
1473 }
1474
1475 /// <summary>
1476 /// Calculates the space the prim should be in by its position
1477 /// </summary>
1478 /// <param name="pos"></param>
1479 /// <returns>a pointer to the space. This could be a new space or reused space.</returns>
1480 public IntPtr calculateSpaceForGeom(Vector3 pos)
1481 {
1482 int x, y;
1483
1484 if (pos.X < 0)
1485 return staticPrimspaceOffRegion[0];
1486
1487 if (pos.Y < 0)
1488 return staticPrimspaceOffRegion[2];
1489
1490 x = (int)(pos.X * spacesPerMeterX);
1491 if (x > spaceGridMaxX)
1492 return staticPrimspaceOffRegion[1];
1493
1494 y = (int)(pos.Y * spacesPerMeterY);
1495 if (y > spaceGridMaxY)
1496 return staticPrimspaceOffRegion[3];
1497
1498 return staticPrimspace[x, y];
1499 }
1500
1501 #endregion
1502
1503
1504 /// <summary>
1505 /// Called to queue a change to a actor
1506 /// to use in place of old taint mechanism so changes do have a time sequence
1507 /// </summary>
1508
1509 public void AddChange(PhysicsActor actor, changes what, Object arg)
1510 {
1511 ODEchangeitem item = new ODEchangeitem();
1512 item.actor = actor;
1513 item.what = what;
1514 item.arg = arg;
1515 ChangesQueue.Enqueue(item);
1516 }
1517
1518 /// <summary>
1519 /// Called after our prim properties are set Scale, position etc.
1520 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex
1521 /// This assures us that we have no race conditions
1522 /// </summary>
1523 /// <param name="prim"></param>
1524 public override void AddPhysicsActorTaint(PhysicsActor prim)
1525 {
1526 }
1527
1528 // does all pending changes generated during region load process
1529 public override void ProcessPreSimulation()
1530 {
1531 lock (OdeLock)
1532 {
1533 if (world == IntPtr.Zero)
1534 {
1535 ChangesQueue.Clear();
1536 return;
1537 }
1538
1539 ODEchangeitem item;
1540
1541 int donechanges = 0;
1542 if (ChangesQueue.Count > 0)
1543 {
1544 m_log.InfoFormat("[ubOde] start processing pending actor operations");
1545 int tstart = Util.EnvironmentTickCount();
1546
1547 while (ChangesQueue.Dequeue(out item))
1548 {
1549 if (item.actor != null)
1550 {
1551 try
1552 {
1553 if (item.actor is OdeCharacter)
1554 ((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
1555 else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
1556 RemovePrimThreadLocked((OdePrim)item.actor);
1557 }
1558 catch
1559 {
1560 m_log.WarnFormat("[PHYSICS]: Operation failed for a actor {0} {1}",
1561 item.actor.Name, item.what.ToString());
1562 }
1563 }
1564 donechanges++;
1565 }
1566 int time = Util.EnvironmentTickCountSubtract(tstart);
1567 m_log.InfoFormat("[ubOde] finished {0} operations in {1}ms", donechanges, time);
1568 }
1569 m_log.InfoFormat("[ubOde] {0} prim actors loaded",_prims.Count);
1570 }
1571 }
1572
1573 /// <summary>
1574 /// This is our main simulate loop
1575 /// It's thread locked by a Mutex in the scene.
1576 /// It holds Collisions, it instructs ODE to step through the physical reactions
1577 /// It moves the objects around in memory
1578 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
1579 /// </summary>
1580 /// <param name="timeStep"></param>
1581 /// <returns></returns>
1582 public override float Simulate(float reqTimeStep)
1583 {
1584 DateTime now = DateTime.UtcNow;
1585 TimeSpan timedif = now - m_lastframe;
1586 float timeStep = (float)timedif.TotalSeconds;
1587 m_lastframe = now;
1588
1589 // acumulate time so we can reduce error
1590 step_time += timeStep;
1591
1592 if (step_time < HalfOdeStep)
1593 return 0;
1594
1595 if (framecount < 0)
1596 framecount = 0;
1597
1598 framecount++;
1599
1600// checkThread();
1601 int nodeframes = 0;
1602 float fps = 0;
1603
1604 lock (SimulationLock)
1605 lock(OdeLock)
1606 {
1607 if (world == IntPtr.Zero)
1608 {
1609 ChangesQueue.Clear();
1610 return 0;
1611 }
1612
1613 ODEchangeitem item;
1614
1615// d.WorldSetQuickStepNumIterations(world, curphysiteractions);
1616
1617 int loopstartMS = Util.EnvironmentTickCount();
1618 int looptimeMS = 0;
1619 int changestimeMS = 0;
1620 int maxChangestime = (int)(reqTimeStep * 500f); // half the time
1621 int maxLoopTime = (int)(reqTimeStep * 1200f); // 1.2 the time
1622
1623 if (ChangesQueue.Count > 0)
1624 {
1625 while (ChangesQueue.Dequeue(out item))
1626 {
1627 if (item.actor != null)
1628 {
1629 try
1630 {
1631 if (item.actor is OdeCharacter)
1632 ((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
1633 else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
1634 RemovePrimThreadLocked((OdePrim)item.actor);
1635 }
1636 catch
1637 {
1638 m_log.WarnFormat("[PHYSICS]: doChange failed for a actor {0} {1}",
1639 item.actor.Name, item.what.ToString());
1640 }
1641 }
1642 changestimeMS = Util.EnvironmentTickCountSubtract(loopstartMS);
1643 if (changestimeMS > maxChangestime)
1644 break;
1645 }
1646 }
1647
1648 // do simulation taking at most 150ms total time including changes
1649 while (step_time > HalfOdeStep)
1650 {
1651 try
1652 {
1653 // clear pointer/counter to contacts to pass into joints
1654 m_global_contactcount = 0;
1655
1656
1657 // Move characters
1658 lock (_characters)
1659 {
1660 List<OdeCharacter> defects = new List<OdeCharacter>();
1661 foreach (OdeCharacter actor in _characters)
1662 {
1663 if (actor != null)
1664 actor.Move(defects);
1665 }
1666 if (defects.Count != 0)
1667 {
1668 foreach (OdeCharacter defect in defects)
1669 {
1670 RemoveCharacter(defect);
1671 }
1672 defects.Clear();
1673 }
1674 }
1675
1676 // Move other active objects
1677 lock (_activegroups)
1678 {
1679 foreach (OdePrim aprim in _activegroups)
1680 {
1681 aprim.Move();
1682 }
1683 }
1684
1685 m_rayCastManager.ProcessQueuedRequests();
1686
1687 collision_optimized();
1688
1689 foreach (PhysicsActor obj in _collisionEventPrim)
1690 {
1691 if (obj == null)
1692 continue;
1693
1694 switch ((ActorTypes)obj.PhysicsActorType)
1695 {
1696 case ActorTypes.Agent:
1697 OdeCharacter cobj = (OdeCharacter)obj;
1698 cobj.AddCollisionFrameTime((int)(odetimestepMS));
1699 cobj.SendCollisions();
1700 break;
1701
1702 case ActorTypes.Prim:
1703 OdePrim pobj = (OdePrim)obj;
1704 if (pobj.Body == IntPtr.Zero || (d.BodyIsEnabled(pobj.Body) && !pobj.m_outbounds))
1705 if (!pobj.m_outbounds)
1706 {
1707 pobj.AddCollisionFrameTime((int)(odetimestepMS));
1708 pobj.SendCollisions();
1709 }
1710 break;
1711 }
1712 }
1713
1714 foreach (PhysicsActor obj in _collisionEventPrimRemove)
1715 _collisionEventPrim.Remove(obj);
1716
1717 _collisionEventPrimRemove.Clear();
1718
1719 // do a ode simulation step
1720 d.WorldQuickStep(world, ODE_STEPSIZE);
1721 d.JointGroupEmpty(contactgroup);
1722
1723 // update managed ideia of physical data and do updates to core
1724 /*
1725 lock (_characters)
1726 {
1727 foreach (OdeCharacter actor in _characters)
1728 {
1729 if (actor != null)
1730 {
1731 if (actor.bad)
1732 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
1733
1734 actor.UpdatePositionAndVelocity();
1735 }
1736 }
1737 }
1738 */
1739
1740 lock (_activegroups)
1741 {
1742 {
1743 foreach (OdePrim actor in _activegroups)
1744 {
1745 if (actor.IsPhysical)
1746 {
1747 actor.UpdatePositionAndVelocity(framecount);
1748 }
1749 }
1750 }
1751 }
1752 }
1753 catch (Exception e)
1754 {
1755 m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
1756// ode.dunlock(world);
1757 }
1758
1759 step_time -= ODE_STEPSIZE;
1760 nodeframes++;
1761
1762 looptimeMS = Util.EnvironmentTickCountSubtract(loopstartMS);
1763 if (looptimeMS > maxLoopTime)
1764 break;
1765 }
1766
1767 lock (_badCharacter)
1768 {
1769 if (_badCharacter.Count > 0)
1770 {
1771 foreach (OdeCharacter chr in _badCharacter)
1772 {
1773 RemoveCharacter(chr);
1774 }
1775
1776 _badCharacter.Clear();
1777 }
1778 }
1779
1780 timedif = now - m_lastMeshExpire;
1781
1782 if (timedif.Seconds > 10)
1783 {
1784 mesher.ExpireReleaseMeshs();
1785 m_lastMeshExpire = now;
1786 }
1787
1788// information block for in debug breakpoint only
1789/*
1790 int ntopactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
1791 int ntopstaticgeoms = d.SpaceGetNumGeoms(StaticSpace);
1792 int ngroundgeoms = d.SpaceGetNumGeoms(GroundSpace);
1793
1794 int nactivegeoms = 0;
1795 int nactivespaces = 0;
1796
1797 int nstaticgeoms = 0;
1798 int nstaticspaces = 0;
1799 IntPtr sp;
1800
1801 for (int i = 0; i < ntopactivegeoms; i++)
1802 {
1803 sp = d.SpaceGetGeom(ActiveSpace, i);
1804 if (d.GeomIsSpace(sp))
1805 {
1806 nactivespaces++;
1807 nactivegeoms += d.SpaceGetNumGeoms(sp);
1808 }
1809 else
1810 nactivegeoms++;
1811 }
1812
1813 for (int i = 0; i < ntopstaticgeoms; i++)
1814 {
1815 sp = d.SpaceGetGeom(StaticSpace, i);
1816 if (d.GeomIsSpace(sp))
1817 {
1818 nstaticspaces++;
1819 nstaticgeoms += d.SpaceGetNumGeoms(sp);
1820 }
1821 else
1822 nstaticgeoms++;
1823 }
1824
1825 int ntopgeoms = d.SpaceGetNumGeoms(TopSpace);
1826
1827 int totgeoms = nstaticgeoms + nactivegeoms + ngroundgeoms + 1; // one ray
1828 int nbodies = d.NTotalBodies;
1829 int ngeoms = d.NTotalGeoms;
1830*/
1831 // Finished with all sim stepping. If requested, dump world state to file for debugging.
1832 // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed?
1833 // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots?
1834 if (physics_logging && (physics_logging_interval > 0) && (framecount % physics_logging_interval == 0))
1835 {
1836 string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename
1837 string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file
1838
1839 if (physics_logging_append_existing_logfile)
1840 {
1841 string header = "-------------- START OF PHYSICS FRAME " + framecount.ToString() + " --------------";
1842 TextWriter fwriter = File.AppendText(fname);
1843 fwriter.WriteLine(header);
1844 fwriter.Close();
1845 }
1846
1847 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
1848 }
1849
1850 fps = (float)nodeframes * ODE_STEPSIZE / reqTimeStep;
1851
1852 if(step_time < HalfOdeStep)
1853 m_timeDilation = 1.0f;
1854 else if (step_time > m_SkipFramesAtms)
1855 {
1856 // if we lag too much skip frames
1857 m_timeDilation = 0.0f;
1858 step_time = 0;
1859 m_lastframe = DateTime.UtcNow; // skip also the time lost
1860 }
1861 else
1862 {
1863 m_timeDilation = ODE_STEPSIZE / step_time;
1864 if (m_timeDilation > 1)
1865 m_timeDilation = 1;
1866 }
1867 }
1868
1869 return fps;
1870 }
1871
1872 /// <summary>
1873 public override void GetResults()
1874 {
1875 }
1876
1877 public override bool IsThreaded
1878 {
1879 // for now we won't be multithreaded
1880 get { return (false); }
1881 }
1882
1883 public float GetTerrainHeightAtXY(float x, float y)
1884 {
1885
1886 int offsetX = 0;
1887 int offsetY = 0;
1888
1889 if (m_suportCombine)
1890 {
1891 offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1892 offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1893 }
1894
1895 // get region map
1896 IntPtr heightFieldGeom = IntPtr.Zero;
1897 if (!RegionTerrain.TryGetValue(new Vector3(offsetX, offsetY, 0), out heightFieldGeom))
1898 return 0f;
1899
1900 if (heightFieldGeom == IntPtr.Zero)
1901 return 0f;
1902
1903 if (!TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
1904 return 0f;
1905
1906 // TerrainHeightField for ODE as offset 1m
1907 x += 1f - offsetX;
1908 y += 1f - offsetY;
1909
1910 // make position fit into array
1911 if (x < 0)
1912 x = 0;
1913 if (y < 0)
1914 y = 0;
1915
1916 // integer indexs
1917 int ix;
1918 int iy;
1919 // interpolators offset
1920 float dx;
1921 float dy;
1922
1923 int regsizeX = (int)m_regionWidth + 3; // map size see setterrain number of samples
1924 int regsizeY = (int)m_regionHeight + 3; // map size see setterrain number of samples
1925 int regsize = regsizeX;
1926
1927 if (m_OSOdeLib)
1928 {
1929 if (x < regsizeX - 1)
1930 {
1931 ix = (int)x;
1932 dx = x - (float)ix;
1933 }
1934 else // out world use external height
1935 {
1936 ix = regsizeX - 2;
1937 dx = 0;
1938 }
1939 if (y < regsizeY - 1)
1940 {
1941 iy = (int)y;
1942 dy = y - (float)iy;
1943 }
1944 else
1945 {
1946 iy = regsizeY - 2;
1947 dy = 0;
1948 }
1949 }
1950 else
1951 {
1952 // we still have square fixed size regions
1953 // also flip x and y because of how map is done for ODE fliped axis
1954 // so ix,iy,dx and dy are inter exchanged
1955
1956 regsize = regsizeY;
1957
1958 if (x < regsizeX - 1)
1959 {
1960 iy = (int)x;
1961 dy = x - (float)iy;
1962 }
1963 else // out world use external height
1964 {
1965 iy = regsizeX - 2;
1966 dy = 0;
1967 }
1968 if (y < regsizeY - 1)
1969 {
1970 ix = (int)y;
1971 dx = y - (float)ix;
1972 }
1973 else
1974 {
1975 ix = regsizeY - 2;
1976 dx = 0;
1977 }
1978 }
1979
1980 float h0;
1981 float h1;
1982 float h2;
1983
1984 iy *= regsize;
1985 iy += ix; // all indexes have iy + ix
1986
1987 float[] heights = TerrainHeightFieldHeights[heightFieldGeom];
1988 /*
1989 if ((dx + dy) <= 1.0f)
1990 {
1991 h0 = ((float)heights[iy]); // 0,0 vertice
1992 h1 = (((float)heights[iy + 1]) - h0) * dx; // 1,0 vertice minus 0,0
1993 h2 = (((float)heights[iy + regsize]) - h0) * dy; // 0,1 vertice minus 0,0
1994 }
1995 else
1996 {
1997 h0 = ((float)heights[iy + regsize + 1]); // 1,1 vertice
1998 h1 = (((float)heights[iy + 1]) - h0) * (1 - dy); // 1,1 vertice minus 1,0
1999 h2 = (((float)heights[iy + regsize]) - h0) * (1 - dx); // 1,1 vertice minus 0,1
2000 }
2001 */
2002 h0 = ((float)heights[iy]); // 0,0 vertice
2003
2004 if (dy>dx)
2005 {
2006 iy += regsize;
2007 h2 = (float)heights[iy]; // 0,1 vertice
2008 h1 = (h2 - h0) * dy; // 0,1 vertice minus 0,0
2009 h2 = ((float)heights[iy + 1] - h2) * dx; // 1,1 vertice minus 0,1
2010 }
2011 else
2012 {
2013 iy++;
2014 h2 = (float)heights[iy]; // vertice 1,0
2015 h1 = (h2 - h0) * dx; // 1,0 vertice minus 0,0
2016 h2 = (((float)heights[iy + regsize]) - h2) * dy; // 1,1 vertice minus 1,0
2017 }
2018
2019 return h0 + h1 + h2;
2020 }
2021
2022 public Vector3 GetTerrainNormalAtXY(float x, float y)
2023 {
2024 int offsetX = 0;
2025 int offsetY = 0;
2026
2027 if (m_suportCombine)
2028 {
2029 offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
2030 offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
2031 }
2032
2033 // get region map
2034 IntPtr heightFieldGeom = IntPtr.Zero;
2035 Vector3 norm = new Vector3(0, 0, 1);
2036
2037 if (!RegionTerrain.TryGetValue(new Vector3(offsetX, offsetY, 0), out heightFieldGeom))
2038 return norm; ;
2039
2040 if (heightFieldGeom == IntPtr.Zero)
2041 return norm;
2042
2043 if (!TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
2044 return norm;
2045
2046 // TerrainHeightField for ODE as offset 1m
2047 x += 1f - offsetX;
2048 y += 1f - offsetY;
2049
2050 // make position fit into array
2051 if (x < 0)
2052 x = 0;
2053 if (y < 0)
2054 y = 0;
2055
2056 // integer indexs
2057 int ix;
2058 int iy;
2059 // interpolators offset
2060 float dx;
2061 float dy;
2062
2063 int regsizeX = (int)m_regionWidth + 3; // map size see setterrain number of samples
2064 int regsizeY = (int)m_regionHeight + 3; // map size see setterrain number of samples
2065 int regsize = regsizeX;
2066
2067 int xstep = 1;
2068 int ystep = regsizeX;
2069 bool firstTri = false;
2070
2071 if (m_OSOdeLib)
2072 {
2073 if (x < regsizeX - 1)
2074 {
2075 ix = (int)x;
2076 dx = x - (float)ix;
2077 }
2078 else // out world use external height
2079 {
2080 ix = regsizeX - 2;
2081 dx = 0;
2082 }
2083 if (y < regsizeY - 1)
2084 {
2085 iy = (int)y;
2086 dy = y - (float)iy;
2087 }
2088 else
2089 {
2090 iy = regsizeY - 2;
2091 dy = 0;
2092 }
2093 firstTri = dy > dx;
2094 }
2095
2096 else
2097 {
2098 xstep = regsizeY;
2099 ystep = 1;
2100 regsize = regsizeY;
2101
2102 // we still have square fixed size regions
2103 // also flip x and y because of how map is done for ODE fliped axis
2104 // so ix,iy,dx and dy are inter exchanged
2105 if (x < regsizeX - 1)
2106 {
2107 iy = (int)x;
2108 dy = x - (float)iy;
2109 }
2110 else // out world use external height
2111 {
2112 iy = regsizeX - 2;
2113 dy = 0;
2114 }
2115 if (y < regsizeY - 1)
2116 {
2117 ix = (int)y;
2118 dx = y - (float)ix;
2119 }
2120 else
2121 {
2122 ix = regsizeY - 2;
2123 dx = 0;
2124 }
2125 firstTri = dx > dy;
2126 }
2127
2128 float h0;
2129 float h1;
2130 float h2;
2131
2132 iy *= regsize;
2133 iy += ix; // all indexes have iy + ix
2134
2135 float[] heights = TerrainHeightFieldHeights[heightFieldGeom];
2136
2137 if (firstTri)
2138 {
2139 h1 = ((float)heights[iy]); // 0,0 vertice
2140 iy += ystep;
2141 h0 = (float)heights[iy]; // 0,1
2142 h2 = (float)heights[iy+xstep]; // 1,1 vertice
2143 norm.X = h0 - h2;
2144 norm.Y = h1 - h0;
2145 }
2146 else
2147 {
2148 h2 = ((float)heights[iy]); // 0,0 vertice
2149 iy += xstep;
2150 h0 = ((float)heights[iy]); // 1,0 vertice
2151 h1 = (float)heights[iy+ystep]; // vertice 1,1
2152 norm.X = h2 - h0;
2153 norm.Y = h0 - h1;
2154 }
2155 norm.Z = 1;
2156 norm.Normalize();
2157 return norm;
2158 }
2159
2160 public override void SetTerrain(float[] heightMap)
2161 {
2162 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
2163 {
2164 if (m_parentScene is ODEScene)
2165 {
2166 ((ODEScene)m_parentScene).SetTerrain(heightMap, m_worldOffset);
2167 }
2168 }
2169 else
2170 {
2171 SetTerrain(heightMap, m_worldOffset);
2172 }
2173 }
2174
2175 public override void CombineTerrain(float[] heightMap, Vector3 pOffset)
2176 {
2177 if(m_suportCombine)
2178 SetTerrain(heightMap, pOffset);
2179 }
2180
2181 public void SetTerrain(float[] heightMap, Vector3 pOffset)
2182 {
2183 if (m_OSOdeLib)
2184 OSSetTerrain(heightMap, pOffset);
2185 else
2186 OriSetTerrain(heightMap, pOffset);
2187 }
2188
2189 public void OriSetTerrain(float[] heightMap, Vector3 pOffset)
2190 {
2191 // assumes 1m size grid and constante size square regions
2192 // needs to know about sims around in future
2193
2194 float[] _heightmap;
2195
2196 uint regionsizeX = m_regionWidth;
2197 uint regionsizeY = m_regionHeight;
2198
2199 // map is rotated
2200 uint heightmapWidth = regionsizeY + 2;
2201 uint heightmapHeight = regionsizeX + 2;
2202
2203 uint heightmapWidthSamples = heightmapWidth + 1;
2204 uint heightmapHeightSamples = heightmapHeight + 1;
2205
2206 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
2207
2208 const float scale = 1.0f;
2209 const float offset = 0.0f;
2210 const float thickness = 10f;
2211 const int wrap = 0;
2212
2213
2214 float hfmin = float.MaxValue;
2215 float hfmax = float.MinValue;
2216 float val;
2217 uint xx;
2218 uint yy;
2219
2220 uint maxXX = regionsizeX - 1;
2221 uint maxYY = regionsizeY - 1;
2222 // flipping map adding one margin all around so things don't fall in edges
2223
2224 uint xt = 0;
2225 xx = 0;
2226
2227 for (uint x = 0; x < heightmapWidthSamples; x++)
2228 {
2229 if (x > 1 && xx < maxXX)
2230 xx++;
2231 yy = 0;
2232 for (uint y = 0; y < heightmapHeightSamples; y++)
2233 {
2234 if (y > 1 && y < maxYY)
2235 yy += regionsizeX;
2236
2237 val = heightMap[yy + xx];
2238 if (val < 0.0f)
2239 val = 0.0f; // no neg terrain as in chode
2240 _heightmap[xt + y] = val;
2241
2242 if (hfmin > val)
2243 hfmin = val;
2244 if (hfmax < val)
2245 hfmax = val;
2246 }
2247 xt += heightmapHeightSamples;
2248 }
2249
2250 lock (OdeLock)
2251 {
2252 IntPtr GroundGeom = IntPtr.Zero;
2253 if (RegionTerrain.TryGetValue(pOffset, out GroundGeom))
2254 {
2255 RegionTerrain.Remove(pOffset);
2256 if (GroundGeom != IntPtr.Zero)
2257 {
2258 actor_name_map.Remove(GroundGeom);
2259 d.GeomDestroy(GroundGeom);
2260
2261 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
2262 {
2263 TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
2264 TerrainHeightFieldHeightsHandlers.Remove(GroundGeom);
2265 TerrainHeightFieldHeights.Remove(GroundGeom);
2266 }
2267 }
2268 }
2269 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
2270
2271 GCHandle _heightmaphandler = GCHandle.Alloc(_heightmap, GCHandleType.Pinned);
2272
2273 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmaphandler.AddrOfPinnedObject(), 0,
2274 heightmapHeight, heightmapWidth ,
2275 (int)heightmapHeightSamples, (int)heightmapWidthSamples, scale,
2276 offset, thickness, wrap);
2277
2278 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
2279
2280 GroundGeom = d.CreateHeightfield(GroundSpace, HeightmapData, 1);
2281
2282 if (GroundGeom != IntPtr.Zero)
2283 {
2284 d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
2285 d.GeomSetCollideBits(GroundGeom, 0);
2286
2287 PhysicsActor pa = new NullPhysicsActor();
2288 pa.Name = "Terrain";
2289 pa.PhysicsActorType = (int)ActorTypes.Ground;
2290 actor_name_map[GroundGeom] = pa;
2291
2292// geom_name_map[GroundGeom] = "Terrain";
2293
2294 d.Quaternion q = new d.Quaternion();
2295 q.X = 0.5f;
2296 q.Y = 0.5f;
2297 q.Z = 0.5f;
2298 q.W = 0.5f;
2299
2300 d.GeomSetQuaternion(GroundGeom, ref q);
2301 d.GeomSetPosition(GroundGeom, pOffset.X + m_regionWidth * 0.5f, pOffset.Y + m_regionHeight * 0.5f, 0.0f);
2302 RegionTerrain.Add(pOffset, GroundGeom);
2303 TerrainHeightFieldHeights.Add(GroundGeom, _heightmap);
2304 TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler);
2305 }
2306 }
2307 }
2308
2309 public void OSSetTerrain(float[] heightMap, Vector3 pOffset)
2310 {
2311 // assumes 1m size grid and constante size square regions
2312 // needs to know about sims around in future
2313
2314 float[] _heightmap;
2315
2316 uint regionsizeX = m_regionWidth;
2317 uint regionsizeY = m_regionHeight;
2318
2319 uint heightmapWidth = regionsizeX + 2;
2320 uint heightmapHeight = regionsizeY + 2;
2321
2322 uint heightmapWidthSamples = heightmapWidth + 1;
2323 uint heightmapHeightSamples = heightmapHeight + 1;
2324
2325 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
2326
2327
2328 float hfmin = float.MaxValue;
2329// float hfmax = float.MinValue;
2330 float val;
2331
2332
2333 uint maxXX = regionsizeX - 1;
2334 uint maxYY = regionsizeY - 1;
2335 // adding one margin all around so things don't fall in edges
2336
2337 uint xx;
2338 uint yy = 0;
2339 uint yt = 0;
2340
2341 for (uint y = 0; y < heightmapHeightSamples; y++)
2342 {
2343 if (y > 1 && y < maxYY)
2344 yy += regionsizeX;
2345 xx = 0;
2346 for (uint x = 0; x < heightmapWidthSamples; x++)
2347 {
2348 if (x > 1 && x < maxXX)
2349 xx++;
2350
2351 val = heightMap[yy + xx];
2352 if (val < 0.0f)
2353 val = 0.0f; // no neg terrain as in chode
2354 _heightmap[yt + x] = val;
2355
2356 if (hfmin > val)
2357 hfmin = val;
2358// if (hfmax < val)
2359// hfmax = val;
2360 }
2361 yt += heightmapWidthSamples;
2362 }
2363 lock (OdeLock)
2364 {
2365 IntPtr GroundGeom = IntPtr.Zero;
2366 if (RegionTerrain.TryGetValue(pOffset, out GroundGeom))
2367 {
2368 RegionTerrain.Remove(pOffset);
2369 if (GroundGeom != IntPtr.Zero)
2370 {
2371 actor_name_map.Remove(GroundGeom);
2372 d.GeomDestroy(GroundGeom);
2373
2374 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
2375 {
2376 if (TerrainHeightFieldHeightsHandlers[GroundGeom].IsAllocated)
2377 TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
2378 TerrainHeightFieldHeightsHandlers.Remove(GroundGeom);
2379 TerrainHeightFieldHeights.Remove(GroundGeom);
2380 }
2381 }
2382 }
2383 IntPtr HeightmapData = d.GeomOSTerrainDataCreate();
2384
2385 const int wrap = 0;
2386 float thickness = hfmin;
2387 if (thickness < 0)
2388 thickness = 1;
2389
2390 GCHandle _heightmaphandler = GCHandle.Alloc(_heightmap, GCHandleType.Pinned);
2391
2392 d.GeomOSTerrainDataBuild(HeightmapData, _heightmaphandler.AddrOfPinnedObject(), 0, 1.0f,
2393 (int)heightmapWidthSamples, (int)heightmapHeightSamples,
2394 thickness, wrap);
2395
2396// d.GeomOSTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
2397 GroundGeom = d.CreateOSTerrain(GroundSpace, HeightmapData, 1);
2398 if (GroundGeom != IntPtr.Zero)
2399 {
2400 d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
2401 d.GeomSetCollideBits(GroundGeom, 0);
2402
2403
2404 PhysicsActor pa = new NullPhysicsActor();
2405 pa.Name = "Terrain";
2406 pa.PhysicsActorType = (int)ActorTypes.Ground;
2407 actor_name_map[GroundGeom] = pa;
2408
2409// geom_name_map[GroundGeom] = "Terrain";
2410
2411 d.GeomSetPosition(GroundGeom, pOffset.X + m_regionWidth * 0.5f, pOffset.Y + m_regionHeight * 0.5f, 0.0f);
2412 RegionTerrain.Add(pOffset, GroundGeom);
2413 TerrainHeightFieldHeights.Add(GroundGeom, _heightmap);
2414 TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler);
2415 }
2416 }
2417 }
2418
2419 public override void DeleteTerrain()
2420 {
2421 }
2422
2423 public float GetWaterLevel()
2424 {
2425 return waterlevel;
2426 }
2427
2428 public override bool SupportsCombining()
2429 {
2430 return m_suportCombine;
2431 }
2432
2433 public override void SetWaterLevel(float baseheight)
2434 {
2435 waterlevel = baseheight;
2436 }
2437
2438 public override void Dispose()
2439 {
2440 lock (OdeLock)
2441 {
2442 if (world == IntPtr.Zero)
2443 return;
2444
2445 if (m_meshWorker != null)
2446 m_meshWorker.Stop();
2447
2448 if (m_rayCastManager != null)
2449 {
2450 m_rayCastManager.Dispose();
2451 m_rayCastManager = null;
2452 }
2453
2454 lock (_prims)
2455 {
2456 ChangesQueue.Clear();
2457 foreach (OdePrim prm in _prims)
2458 {
2459 prm.DoAChange(changes.Remove, null);
2460 _collisionEventPrim.Remove(prm);
2461 }
2462 _prims.Clear();
2463 }
2464
2465 OdeCharacter[] chtorem;
2466 lock (_characters)
2467 {
2468 chtorem = new OdeCharacter[_characters.Count];
2469 _characters.CopyTo(chtorem);
2470 }
2471
2472 ChangesQueue.Clear();
2473 foreach (OdeCharacter ch in chtorem)
2474 ch.DoAChange(changes.Remove, null);
2475
2476
2477 foreach (IntPtr GroundGeom in RegionTerrain.Values)
2478 {
2479 if (GroundGeom != IntPtr.Zero)
2480 d.GeomDestroy(GroundGeom);
2481 }
2482
2483 RegionTerrain.Clear();
2484
2485 if (TerrainHeightFieldHeightsHandlers.Count > 0)
2486 {
2487 foreach (GCHandle gch in TerrainHeightFieldHeightsHandlers.Values)
2488 {
2489 if (gch.IsAllocated)
2490 gch.Free();
2491 }
2492 }
2493
2494 TerrainHeightFieldHeightsHandlers.Clear();
2495 TerrainHeightFieldHeights.Clear();
2496
2497 if (ContactgeomsArray != IntPtr.Zero)
2498 {
2499 Marshal.FreeHGlobal(ContactgeomsArray);
2500 ContactgeomsArray = IntPtr.Zero;
2501 }
2502 if (GlobalContactsArray != IntPtr.Zero)
2503 {
2504 Marshal.FreeHGlobal(GlobalContactsArray);
2505 GlobalContactsArray = IntPtr.Zero;
2506 }
2507
2508 d.WorldDestroy(world);
2509 world = IntPtr.Zero;
2510 //d.CloseODE();
2511 }
2512 }
2513
2514 public override Dictionary<uint, float> GetTopColliders()
2515 {
2516 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
2517 int cnt = 0;
2518 lock (_prims)
2519 {
2520 foreach (OdePrim prm in _prims)
2521 {
2522 if (prm.CollisionScore > 0)
2523 {
2524 returncolliders.Add(prm.LocalID, prm.CollisionScore);
2525 cnt++;
2526 prm.CollisionScore = 0f;
2527 if (cnt > 25)
2528 {
2529 break;
2530 }
2531 }
2532 }
2533 }
2534 return returncolliders;
2535 }
2536
2537 public override bool SupportsRayCast()
2538 {
2539 return true;
2540 }
2541
2542 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
2543 {
2544 if (retMethod != null)
2545 {
2546 ODERayRequest req = new ODERayRequest();
2547 req.actor = null;
2548 req.callbackMethod = retMethod;
2549 req.length = length;
2550 req.Normal = direction;
2551 req.Origin = position;
2552 req.Count = 0;
2553 req.filter = RayFilterFlags.AllPrims;
2554
2555 m_rayCastManager.QueueRequest(req);
2556 }
2557 }
2558
2559 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod)
2560 {
2561 if (retMethod != null)
2562 {
2563 ODERayRequest req = new ODERayRequest();
2564 req.actor = null;
2565 req.callbackMethod = retMethod;
2566 req.length = length;
2567 req.Normal = direction;
2568 req.Origin = position;
2569 req.Count = Count;
2570 req.filter = RayFilterFlags.AllPrims;
2571
2572 m_rayCastManager.QueueRequest(req);
2573 }
2574 }
2575
2576
2577 public override List<ContactResult> RaycastWorld(Vector3 position, Vector3 direction, float length, int Count)
2578 {
2579 List<ContactResult> ourresults = new List<ContactResult>();
2580 object SyncObject = new object();
2581
2582 RayCallback retMethod = delegate(List<ContactResult> results)
2583 {
2584 lock (SyncObject)
2585 {
2586 ourresults = results;
2587 Monitor.PulseAll(SyncObject);
2588 }
2589 };
2590
2591 ODERayRequest req = new ODERayRequest();
2592 req.actor = null;
2593 req.callbackMethod = retMethod;
2594 req.length = length;
2595 req.Normal = direction;
2596 req.Origin = position;
2597 req.Count = Count;
2598 req.filter = RayFilterFlags.AllPrims;
2599
2600 lock (SyncObject)
2601 {
2602 m_rayCastManager.QueueRequest(req);
2603 if (!Monitor.Wait(SyncObject, 500))
2604 return null;
2605 else
2606 return ourresults;
2607 }
2608 }
2609
2610 public override bool SupportsRaycastWorldFiltered()
2611 {
2612 return true;
2613 }
2614
2615 public override object RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter)
2616 {
2617 object SyncObject = new object();
2618 List<ContactResult> ourresults = new List<ContactResult>();
2619
2620 RayCallback retMethod = delegate(List<ContactResult> results)
2621 {
2622 lock (SyncObject)
2623 {
2624 ourresults = results;
2625 Monitor.PulseAll(SyncObject);
2626 }
2627 };
2628
2629 ODERayRequest req = new ODERayRequest();
2630 req.actor = null;
2631 req.callbackMethod = retMethod;
2632 req.length = length;
2633 req.Normal = direction;
2634 req.Origin = position;
2635 req.Count = Count;
2636 req.filter = filter;
2637
2638 lock (SyncObject)
2639 {
2640 m_rayCastManager.QueueRequest(req);
2641 if (!Monitor.Wait(SyncObject, 500))
2642 return null;
2643 else
2644 return ourresults;
2645 }
2646 }
2647
2648 public override List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags)
2649 {
2650 if (actor == null)
2651 return new List<ContactResult>();
2652
2653 IntPtr geom;
2654 if (actor is OdePrim)
2655 geom = ((OdePrim)actor).prim_geom;
2656 else if (actor is OdeCharacter)
2657 geom = ((OdePrim)actor).prim_geom;
2658 else
2659 return new List<ContactResult>();
2660
2661 if (geom == IntPtr.Zero)
2662 return new List<ContactResult>();
2663
2664 List<ContactResult> ourResults = null;
2665 object SyncObject = new object();
2666
2667 RayCallback retMethod = delegate(List<ContactResult> results)
2668 {
2669 lock (SyncObject)
2670 {
2671 ourResults = results;
2672 Monitor.PulseAll(SyncObject);
2673 }
2674 };
2675
2676 ODERayRequest req = new ODERayRequest();
2677 req.actor = actor;
2678 req.callbackMethod = retMethod;
2679 req.length = length;
2680 req.Normal = direction;
2681 req.Origin = position;
2682 req.Count = Count;
2683 req.filter = flags;
2684
2685 lock (SyncObject)
2686 {
2687 m_rayCastManager.QueueRequest(req);
2688 if (!Monitor.Wait(SyncObject, 500))
2689 return new List<ContactResult>();
2690 }
2691
2692 if (ourResults == null)
2693 return new List<ContactResult>();
2694 return ourResults;
2695 }
2696
2697 public override List<ContactResult> BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags)
2698 {
2699 List<ContactResult> ourResults = null;
2700 object SyncObject = new object();
2701
2702 ProbeBoxCallback retMethod = delegate(List<ContactResult> results)
2703 {
2704 lock (SyncObject)
2705 {
2706 ourResults = results;
2707 Monitor.PulseAll(SyncObject);
2708 }
2709 };
2710
2711 ODERayRequest req = new ODERayRequest();
2712 req.actor = null;
2713 req.callbackMethod = retMethod;
2714 req.Normal = size;
2715 req.Origin = position;
2716 req.orientation = orientation;
2717 req.Count = Count;
2718 req.filter = flags;
2719
2720 lock (SyncObject)
2721 {
2722 m_rayCastManager.QueueRequest(req);
2723 if (!Monitor.Wait(SyncObject, 500))
2724 return new List<ContactResult>();
2725 }
2726
2727 if (ourResults == null)
2728 return new List<ContactResult>();
2729 return ourResults;
2730 }
2731
2732 public override List<ContactResult> SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags)
2733 {
2734 List<ContactResult> ourResults = null;
2735 object SyncObject = new object();
2736
2737 ProbeSphereCallback retMethod = delegate(List<ContactResult> results)
2738 {
2739 ourResults = results;
2740 Monitor.PulseAll(SyncObject);
2741 };
2742
2743 ODERayRequest req = new ODERayRequest();
2744 req.actor = null;
2745 req.callbackMethod = retMethod;
2746 req.length = radius;
2747 req.Origin = position;
2748 req.Count = Count;
2749 req.filter = flags;
2750
2751
2752 lock (SyncObject)
2753 {
2754 m_rayCastManager.QueueRequest(req);
2755 if (!Monitor.Wait(SyncObject, 500))
2756 return new List<ContactResult>();
2757 }
2758
2759 if (ourResults == null)
2760 return new List<ContactResult>();
2761 return ourResults;
2762 }
2763
2764 public override List<ContactResult> PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags)
2765 {
2766 IntPtr geom = IntPtr.Zero;;
2767
2768 if (actor != null)
2769 {
2770 if (actor is OdePrim)
2771 geom = ((OdePrim)actor).prim_geom;
2772 else if (actor is OdeCharacter)
2773 geom = ((OdePrim)actor).prim_geom;
2774 }
2775
2776 List<ContactResult> ourResults = null;
2777 object SyncObject = new object();
2778
2779 ProbePlaneCallback retMethod = delegate(List<ContactResult> results)
2780 {
2781 ourResults = results;
2782 Monitor.PulseAll(SyncObject);
2783 };
2784
2785 ODERayRequest req = new ODERayRequest();
2786 req.actor = null;
2787 req.callbackMethod = retMethod;
2788 req.length = plane.W;
2789 req.Normal.X = plane.X;
2790 req.Normal.Y = plane.Y;
2791 req.Normal.Z = plane.Z;
2792 req.Count = Count;
2793 req.filter = flags;
2794
2795 lock (SyncObject)
2796 {
2797 m_rayCastManager.QueueRequest(req);
2798 if (!Monitor.Wait(SyncObject, 500))
2799 return new List<ContactResult>();
2800 }
2801
2802 if (ourResults == null)
2803 return new List<ContactResult>();
2804 return ourResults;
2805 }
2806
2807 public override int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse)
2808 {
2809 Util.FireAndForget( delegate
2810 {
2811 ODESitAvatar sitAvatar = new ODESitAvatar(this, m_rayCastManager);
2812 if(sitAvatar != null)
2813 sitAvatar.Sit(actor, AbsolutePosition, CameraPosition, offset, AvatarSize, PhysicsSitResponse);
2814 });
2815 return 1;
2816 }
2817
2818 }
2819}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODESitAvatar.cs b/OpenSim/Region/PhysicsModules/ubOde/ODESitAvatar.cs
new file mode 100644
index 0000000..214205d
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODESitAvatar.cs
@@ -0,0 +1,356 @@
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// Ubit Umarov 2012
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Runtime.InteropServices;
32using System.Text;
33using OpenSim.Framework;
34using OpenSim.Region.PhysicsModules.SharedBase;
35using OdeAPI;
36using log4net;
37using OpenMetaverse;
38
39namespace OpenSim.Region.PhysicsModule.ubOde
40{
41 /// <summary>
42 /// </summary>
43 public class ODESitAvatar
44 {
45 private ODEScene m_scene;
46 private ODERayCastRequestManager m_raymanager;
47
48 public ODESitAvatar(ODEScene pScene, ODERayCastRequestManager raymanager)
49 {
50 m_scene = pScene;
51 m_raymanager = raymanager;
52 }
53
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
70
71 public void Sit(PhysicsActor actor, Vector3 avPos, Vector3 avCameraPosition, Vector3 offset, Vector3 avOffset, SitAvatarCallback PhysicsSitResponse)
72 {
73 if (!m_scene.haveActor(actor) || !(actor is OdePrim) || ((OdePrim)actor).prim_geom == IntPtr.Zero)
74 {
75 PhysicsSitResponse(-1, actor.LocalID, offset, Quaternion.Identity);
76 return;
77 }
78
79 IntPtr geom = ((OdePrim)actor).prim_geom;
80
81 Vector3 geopos = d.GeomGetPositionOMV(geom);
82 Quaternion geomOri = d.GeomGetQuaternionOMV(geom);
83
84// Vector3 geopos = actor.Position;
85// Quaternion geomOri = actor.Orientation;
86
87 Quaternion geomInvOri = Quaternion.Conjugate(geomOri);
88
89 Quaternion ori = Quaternion.Identity;
90
91 Vector3 rayDir = geopos + offset - avCameraPosition;
92
93 float raylen = rayDir.Length();
94 if (raylen < 0.001f)
95 {
96 PhysicsSitResponse(-1, actor.LocalID, offset, Quaternion.Identity);
97 return;
98 }
99 float t = 1 / raylen;
100 rayDir.X *= t;
101 rayDir.Y *= t;
102 rayDir.Z *= t;
103
104 raylen += 30f; // focal point may be far
105 List<ContactResult> rayResults;
106
107 rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir, raylen, 1, RaySitFlags);
108 if (rayResults.Count == 0)
109 {
110/* if this fundamental ray failed, then just fail so user can try another spot and not be sitted far on a big prim
111 d.AABB aabb;
112 d.GeomGetAABB(geom, out aabb);
113 offset = new Vector3(avOffset.X, 0, aabb.MaxZ + avOffset.Z - geopos.Z);
114 ori = geomInvOri;
115 offset *= geomInvOri;
116 PhysicsSitResponse(1, actor.LocalID, offset, ori);
117*/
118 PhysicsSitResponse(0, actor.LocalID, offset, ori);
119 return;
120 }
121
122 int status = 1;
123
124 offset = rayResults[0].Pos - geopos;
125
126 d.GeomClassID geoclass = d.GeomGetClass(geom);
127
128 if (geoclass == d.GeomClassID.SphereClass)
129 {
130 float r = d.GeomSphereGetRadius(geom);
131
132 offset.Normalize();
133 offset *= r;
134
135 RotAroundZ(offset.X, offset.Y, ref ori);
136
137 if (r < 0.4f)
138 {
139 offset = new Vector3(0, 0, r);
140 }
141 else
142 {
143 if (offset.Z < 0.4f)
144 {
145 t = offset.Z;
146 float rsq = r * r;
147
148 t = 1.0f / (rsq - t * t);
149 offset.X *= t;
150 offset.Y *= t;
151 offset.Z = 0.4f;
152 t = rsq - 0.16f;
153 offset.X *= t;
154 offset.Y *= t;
155 }
156 else if (r > 0.8f && offset.Z > 0.8f * r)
157 {
158 status = 3;
159 avOffset.X = -avOffset.X;
160 avOffset.Z *= 1.6f;
161 }
162 }
163
164 offset += avOffset * ori;
165
166 ori = geomInvOri * ori;
167 offset *= geomInvOri;
168
169 PhysicsSitResponse(status, actor.LocalID, offset, ori);
170 return;
171 }
172
173 Vector3 norm = rayResults[0].Normal;
174
175 if (norm.Z < -0.4f)
176 {
177 PhysicsSitResponse(0, actor.LocalID, offset, Quaternion.Identity);
178 return;
179 }
180
181
182 float SitNormX = -rayDir.X;
183 float SitNormY = -rayDir.Y;
184
185 Vector3 pivot = geopos + offset;
186
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;
193
194 bool foundEdge = false;
195
196 if (norm.Z < 0.5f)
197 {
198 float rayDist = 4.0f;
199
200 for (int i = 0; i < 6; i++)
201 {
202 pivot.X -= 0.01f * norm.X;
203 pivot.Y -= 0.01f * norm.Y;
204 pivot.Z -= 0.01f * norm.Z;
205
206 rayDir.X = -norm.X * norm.Z;
207 rayDir.Y = -norm.Y * norm.Z;
208 rayDir.Z = 1.0f - norm.Z * norm.Z;
209 rayDir.Normalize();
210
211 rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims);
212 if (rayResults.Count == 0)
213 break;
214
215 if (Math.Abs(rayResults[0].Normal.Z) < 0.7f)
216 {
217 rayDist -= rayResults[0].Depth;
218 if (rayDist < 0f)
219 break;
220
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;
227 }
228 else
229 {
230 foundEdge = true;
231 edgePos = rayResults[0].Pos;
232 break;
233 }
234 }
235
236 if (!foundEdge)
237 {
238 PhysicsSitResponse(0, actor.LocalID, offset, ori);
239 return;
240 }
241 avOffset.X *= 0.5f;
242 }
243
244 else if (norm.Z > 0.866f)
245 {
246 float toCamBaseX = avCameraPosition.X - pivot.X;
247 float toCamBaseY = avCameraPosition.Y - pivot.Y;
248 float toCamX = toCamBaseX;
249 float toCamY = toCamBaseY;
250
251 for (int j = 0; j < 4; j++)
252 {
253 float rayDist = 1.0f;
254 float curEdgeDist = 0.0f;
255
256 for (int i = 0; i < 3; i++)
257 {
258 pivot.Z -= 0.01f;
259 rayDir.X = toCamX;
260 rayDir.Y = toCamY;
261 rayDir.Z = (-toCamX * norm.X - toCamY * norm.Y) / norm.Z;
262 rayDir.Normalize();
263
264 rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims);
265 if (rayResults.Count == 0)
266 break;
267
268 curEdgeDist += rayResults[0].Depth;
269
270 if (rayResults[0].Normal.Z > 0.5f)
271 {
272 rayDist -= rayResults[0].Depth;
273 if (rayDist < 0f)
274 break;
275
276 pivot = rayResults[0].Pos;
277 norm = rayResults[0].Normal;
278 }
279 else
280 {
281 foundEdge = true;
282 if (curEdgeDist < edgeDist)
283 {
284 edgeDist = curEdgeDist;
285 edgeNormalX = rayResults[0].Normal.X;
286 edgeNormalY = rayResults[0].Normal.Y;
287 edgeDirX = rayDir.X;
288 edgeDirY = rayDir.Y;
289 edgePos = rayResults[0].Pos;
290 }
291 break;
292 }
293 }
294 if (foundEdge && edgeDist < 0.2f)
295 break;
296
297 pivot = geopos + offset;
298
299 switch (j)
300 {
301 case 0:
302 toCamX = -toCamBaseY;
303 toCamY = toCamBaseX;
304 break;
305 case 1:
306 toCamX = toCamBaseY;
307 toCamY = -toCamBaseX;
308 break;
309 case 2:
310 toCamX = -toCamBaseX;
311 toCamY = -toCamBaseY;
312 break;
313 default:
314 break;
315 }
316 }
317
318 if (!foundEdge)
319 {
320 avOffset.X = -avOffset.X;
321 avOffset.Z *= 1.6f;
322
323 RotAroundZ(SitNormX, SitNormY, ref ori);
324
325 offset += avOffset * ori;
326
327 ori = geomInvOri * ori;
328 offset *= geomInvOri;
329
330 PhysicsSitResponse(3, actor.LocalID, offset, ori);
331 return;
332 }
333 avOffset.X *= 0.5f;
334 }
335
336 SitNormX = edgeNormalX;
337 SitNormY = edgeNormalY;
338 if (edgeDirX * SitNormX + edgeDirY * SitNormY < 0)
339 {
340 SitNormX = -SitNormX;
341 SitNormY = -SitNormY;
342 }
343
344 RotAroundZ(SitNormX, SitNormY, ref ori);
345
346 offset = edgePos + avOffset * ori;
347 offset -= geopos;
348
349 ori = geomInvOri * ori;
350 offset *= geomInvOri;
351
352 PhysicsSitResponse(1, actor.LocalID, offset, ori);
353 return;
354 }
355 }
356}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/Properties/AssemblyInfo.cs b/OpenSim/Region/PhysicsModules/ubOde/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..293454a
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/Properties/AssemblyInfo.cs
@@ -0,0 +1,61 @@
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.Reflection;
29using System.Runtime.InteropServices;
30using Mono.Addins;
31
32// Information about this assembly is defined by the following
33// attributes.
34//
35// change them to the information which is associated with the assembly
36// you compile.
37
38[assembly : AssemblyTitle("OpenSim.Region.PhysicsModule.ubOde")]
39[assembly : AssemblyDescription("Ubit Variation of ODE")]
40[assembly : AssemblyConfiguration("")]
41[assembly : AssemblyCompany("http://opensimulator.org")]
42[assembly : AssemblyProduct("ubOde")]
43[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")]
44[assembly : AssemblyTrademark("")]
45[assembly : AssemblyCulture("")]
46
47// This sets the default COM visibility of types in the assembly to invisible.
48// If you need to expose a type to COM, use [ComVisible(true)] on that type.
49
50[assembly : ComVisible(false)]
51
52// The assembly version has following format :
53//
54// Major.Minor.Build.Revision
55//
56// You can specify all values by your own or you can build default build and revision
57// numbers with the '*' character (the default):
58
59[assembly : AssemblyVersion("0.8.2.*")]
60[assembly: Addin("OpenSim.Region.PhysicsModule.ubOde", OpenSim.VersionInfo.VersionNumber)]
61[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] \ No newline at end of file