aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/ubOde
diff options
context:
space:
mode:
authoronefang2019-05-19 21:24:15 +1000
committeronefang2019-05-19 21:24:15 +1000
commit5e4d6cab00cb29cd088ab7b62ab13aff103b64cb (patch)
treea9fbc62df9eb2d1d9ba2698d8552eae71eca20d8 /OpenSim/Region/PhysicsModules/ubOde
parentAdd a build script. (diff)
downloadopensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.zip
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.gz
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.bz2
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.xz
Dump OpenSim 0.9.0.1 into it's own branch.
Diffstat (limited to 'OpenSim/Region/PhysicsModules/ubOde')
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEApi.cs2024
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs2036
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs1205
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs946
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs112
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs4256
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs689
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs2824
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODESitAvatar.cs356
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/Properties/AssemblyInfo.cs61
10 files changed, 14509 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..35adf11
--- /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..0e46471
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs
@@ -0,0 +1,2036 @@
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 Vector3 m_lastFallVel;
84 private Quaternion m_orientation;
85 private Quaternion m_orientation2D;
86 private float m_mass = 80f;
87 public float m_density = 60f;
88 private bool m_pidControllerActive = true;
89
90 const float basePID_D = 0.55f; // scaled for unit mass unit time (2200 /(50*80))
91 const float basePID_P = 0.225f; // scaled for unit mass unit time (900 /(50*80))
92 public float PID_D;
93 public float PID_P;
94
95 private float timeStep;
96 private float invtimeStep;
97
98 private float m_feetOffset = 0;
99 private float feetOff = 0;
100 private float boneOff = 0;
101 private float AvaAvaSizeXsq = 0.3f;
102 private float AvaAvaSizeYsq = 0.2f;
103
104 public float walkDivisor = 1.3f;
105 public float runDivisor = 0.8f;
106 private bool m_flying = false;
107 private bool m_iscolliding = false;
108 private bool m_iscollidingGround = false;
109 private bool m_iscollidingObj = false;
110 private bool m_alwaysRun = false;
111
112 private bool _zeroFlag = false;
113 private bool m_haveLastFallVel = false;
114
115 private uint m_localID = 0;
116 public bool m_returnCollisions = false;
117 // taints and their non-tainted counterparts
118 public bool m_isPhysical = false; // the current physical status
119 public float MinimumGroundFlightOffset = 3f;
120
121 private float m_buoyancy = 0f;
122
123 private bool m_freemove = false;
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 m_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 = new CollisionEventUpdate();
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 m_parent_scene = parent_scene;
173
174 timeStep = parent_scene.ODE_STEPSIZE;
175 invtimeStep = 1 / timeStep;
176
177 if (pos.IsFinite())
178 {
179 if (pos.Z > 99999f)
180 {
181 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
182 }
183 if (pos.Z < -100f) // shouldn't this be 0 ?
184 {
185 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
186 }
187 _position = pos;
188 }
189 else
190 {
191 _position = new Vector3(((float)m_parent_scene.WorldExtents.X * 0.5f), ((float)m_parent_scene.WorldExtents.Y * 0.5f), parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f);
192 m_log.Warn("[PHYSICS]: Got NaN Position on Character Create");
193 }
194
195 m_size.X = pSize.X;
196 m_size.Y = pSize.Y;
197 m_size.Z = pSize.Z;
198
199 if(m_size.X <0.01f)
200 m_size.X = 0.01f;
201 if(m_size.Y <0.01f)
202 m_size.Y = 0.01f;
203 if(m_size.Z <0.01f)
204 m_size.Z = 0.01f;
205
206 m_feetOffset = pfeetOffset;
207 m_orientation = Quaternion.Identity;
208 m_orientation2D = Quaternion.Identity;
209 m_density = density;
210
211 // force lower density for testing
212 m_density = 3.0f;
213
214 mu = m_parent_scene.AvatarFriction;
215
216 walkDivisor = walk_divisor;
217 runDivisor = rundivisor;
218
219 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; ; // sure we have a default
220
221 PID_D = basePID_D * m_mass * invtimeStep;
222 PID_P = basePID_P * m_mass * invtimeStep;
223
224 m_isPhysical = false; // current status: no ODE information exists
225
226 Name = avName;
227
228 AddChange(changes.Add, null);
229 }
230
231 public override int PhysicsActorType
232 {
233 get { return (int)ActorTypes.Agent; }
234 set { return; }
235 }
236
237 public override void getContactData(ref ContactData cdata)
238 {
239 cdata.mu = mu;
240 cdata.bounce = 0;
241 cdata.softcolide = false;
242 }
243
244 public override bool Building { get; set; }
245
246 /// <summary>
247 /// If this is set, the avatar will move faster
248 /// </summary>
249 public override bool SetAlwaysRun
250 {
251 get { return m_alwaysRun; }
252 set { m_alwaysRun = value; }
253 }
254
255 public override uint LocalID
256 {
257 get { return m_localID; }
258 set { m_localID = value; }
259 }
260
261 public override PhysicsActor ParentActor
262 {
263 get { return (PhysicsActor)this; }
264 }
265
266 public override bool Grabbed
267 {
268 set { return; }
269 }
270
271 public override bool Selected
272 {
273 set { return; }
274 }
275
276 public override float Buoyancy
277 {
278 get { return m_buoyancy; }
279 set { m_buoyancy = value; }
280 }
281
282 public override bool FloatOnWater
283 {
284 set { return; }
285 }
286
287 public override bool IsPhysical
288 {
289 get { return m_isPhysical; }
290 set { return; }
291 }
292
293 public override bool ThrottleUpdates
294 {
295 get { return false; }
296 set { return; }
297 }
298
299 public override bool Flying
300 {
301 get { return m_flying; }
302 set
303 {
304 m_flying = value;
305// m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying);
306 }
307 }
308
309 /// <summary>
310 /// Returns if the avatar is colliding in general.
311 /// This includes the ground and objects and avatar.
312 /// </summary>
313 public override bool IsColliding
314 {
315 get { return (m_iscolliding || m_iscollidingGround); }
316 set
317 {
318 if (value)
319 {
320 m_colliderfilter += 3;
321 if (m_colliderfilter > 3)
322 m_colliderfilter = 3;
323 }
324 else
325 {
326 m_colliderfilter--;
327 if (m_colliderfilter < 0)
328 m_colliderfilter = 0;
329 }
330
331 if (m_colliderfilter == 0)
332 m_iscolliding = false;
333 else
334 {
335 m_pidControllerActive = true;
336 m_iscolliding = true;
337 m_freemove = false;
338 }
339 }
340 }
341
342 /// <summary>
343 /// Returns if an avatar is colliding with the ground
344 /// </summary>
345 public override bool CollidingGround
346 {
347 get { return m_iscollidingGround; }
348 set
349 {
350/* we now control this
351 if (value)
352 {
353 m_colliderGroundfilter += 2;
354 if (m_colliderGroundfilter > 2)
355 m_colliderGroundfilter = 2;
356 }
357 else
358 {
359 m_colliderGroundfilter--;
360 if (m_colliderGroundfilter < 0)
361 m_colliderGroundfilter = 0;
362 }
363
364 if (m_colliderGroundfilter == 0)
365 m_iscollidingGround = false;
366 else
367 m_iscollidingGround = true;
368 */
369 }
370
371 }
372
373 /// <summary>
374 /// Returns if the avatar is colliding with an object
375 /// </summary>
376 public override bool CollidingObj
377 {
378 get { return m_iscollidingObj; }
379 set
380 {
381 // Ubit filter this also
382 if (value)
383 {
384 m_colliderObjectfilter += 2;
385 if (m_colliderObjectfilter > 2)
386 m_colliderObjectfilter = 2;
387 }
388 else
389 {
390 m_colliderObjectfilter--;
391 if (m_colliderObjectfilter < 0)
392 m_colliderObjectfilter = 0;
393 }
394
395 if (m_colliderObjectfilter == 0)
396 m_iscollidingObj = false;
397 else
398 m_iscollidingObj = true;
399
400// m_iscollidingObj = value;
401
402 if (m_iscollidingObj)
403 m_pidControllerActive = false;
404 else
405 m_pidControllerActive = true;
406 }
407 }
408
409 /// <summary>
410 /// turn the PID controller on or off.
411 /// The PID Controller will turn on all by itself in many situations
412 /// </summary>
413 /// <param name="status"></param>
414 public void SetPidStatus(bool status)
415 {
416 m_pidControllerActive = status;
417 }
418
419 public override bool Stopped
420 {
421 get { return _zeroFlag; }
422 }
423
424 /// <summary>
425 /// This 'puts' an avatar somewhere in the physics space.
426 /// Not really a good choice unless you 'know' it's a good
427 /// spot otherwise you're likely to orbit the avatar.
428 /// </summary>
429 public override Vector3 Position
430 {
431 get { return _position; }
432 set
433 {
434 if (value.IsFinite())
435 {
436 if (value.Z > 9999999f)
437 {
438 value.Z = m_parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
439 }
440 if (value.Z < -100f)
441 {
442 value.Z = m_parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
443 }
444 AddChange(changes.Position, value);
445 }
446 else
447 {
448 m_log.Warn("[PHYSICS]: Got a NaN Position from Scene on a Character");
449 }
450 }
451 }
452
453 public override Vector3 RotationalVelocity
454 {
455 get { return m_rotationalVelocity; }
456 set { m_rotationalVelocity = value; }
457 }
458
459 /// <summary>
460 /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight
461 /// and use it to offset landings properly
462 /// </summary>
463 public override Vector3 Size
464 {
465 get
466 {
467 return m_size;
468 }
469 set
470 {
471 if (value.IsFinite())
472 {
473 if(value.X <0.01f)
474 value.X = 0.01f;
475 if(value.Y <0.01f)
476 value.Y = 0.01f;
477 if(value.Z <0.01f)
478 value.Z = 0.01f;
479
480 AddChange(changes.Size, value);
481 }
482 else
483 {
484 m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character");
485 }
486 }
487 }
488
489 public override void setAvatarSize(Vector3 size, float feetOffset)
490 {
491 if (size.IsFinite())
492 {
493 if (size.X < 0.01f)
494 size.X = 0.01f;
495 if (size.Y < 0.01f)
496 size.Y = 0.01f;
497 if (size.Z < 0.01f)
498 size.Z = 0.01f;
499
500 strAvatarSize st = new strAvatarSize();
501 st.size = size;
502 st.offset = feetOffset;
503 AddChange(changes.AvatarSize, st);
504 }
505 else
506 {
507 m_log.Warn("[PHYSICS]: Got a NaN AvatarSize from Scene on a Character");
508 }
509
510 }
511 /// <summary>
512 /// This creates the Avatar's physical Surrogate at the position supplied
513 /// </summary>
514 /// <param name="npositionX"></param>
515 /// <param name="npositionY"></param>
516 /// <param name="npositionZ"></param>
517
518 //
519 /// <summary>
520 /// Uses the capped cyllinder volume formula to calculate the avatar's mass.
521 /// This may be used in calculations in the scene/scenepresence
522 /// </summary>
523 public override float Mass
524 {
525 get
526 {
527 return m_mass;
528 }
529 }
530 public override void link(PhysicsActor obj)
531 {
532
533 }
534
535 public override void delink()
536 {
537
538 }
539
540 public override void LockAngularMotion(byte axislocks)
541 {
542
543 }
544
545
546 public override Vector3 Force
547 {
548 get { return _target_velocity; }
549 set { return; }
550 }
551
552 public override int VehicleType
553 {
554 get { return 0; }
555 set { return; }
556 }
557
558 public override void VehicleFloatParam(int param, float value)
559 {
560
561 }
562
563 public override void VehicleVectorParam(int param, Vector3 value)
564 {
565
566 }
567
568 public override void VehicleRotationParam(int param, Quaternion rotation)
569 {
570
571 }
572
573 public override void VehicleFlags(int param, bool remove)
574 {
575
576 }
577
578 public override void SetVolumeDetect(int param)
579 {
580
581 }
582
583 public override Vector3 CenterOfMass
584 {
585 get
586 {
587 Vector3 pos = _position;
588 return pos;
589 }
590 }
591
592 public override Vector3 GeometricCenter
593 {
594 get
595 {
596 Vector3 pos = _position;
597 return pos;
598 }
599 }
600
601 public override PrimitiveBaseShape Shape
602 {
603 set { return; }
604 }
605
606 public override Vector3 rootVelocity
607 {
608 get
609 {
610 return _velocity;
611 }
612 }
613
614 public override Vector3 Velocity
615 {
616 get
617 {
618 return _velocity;
619 }
620 set
621 {
622 if (value.IsFinite())
623 {
624 AddChange(changes.Velocity, value);
625 }
626 else
627 {
628 m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character");
629 }
630 }
631 }
632
633 public override Vector3 TargetVelocity
634 {
635 get
636 {
637 return m_targetVelocity;
638 }
639 set
640 {
641 if (value.IsFinite())
642 {
643 AddChange(changes.TargetVelocity, value);
644 }
645 else
646 {
647 m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character");
648 }
649 }
650 }
651
652 public override Vector3 Torque
653 {
654 get { return Vector3.Zero; }
655 set { return; }
656 }
657
658 public override float CollisionScore
659 {
660 get { return 0f; }
661 set { }
662 }
663
664 public override bool Kinematic
665 {
666 get { return false; }
667 set { }
668 }
669
670 public override Quaternion Orientation
671 {
672 get { return m_orientation; }
673 set
674 {
675// fakeori = value;
676// givefakeori++;
677 value.Normalize();
678 AddChange(changes.Orientation, value);
679 }
680 }
681
682 public override Vector3 Acceleration
683 {
684 get { return _acceleration; }
685 set { }
686 }
687
688 public void SetAcceleration(Vector3 accel)
689 {
690 m_pidControllerActive = true;
691 _acceleration = accel;
692 }
693
694 /// <summary>
695 /// Adds the force supplied to the Target Velocity
696 /// The PID controller takes this target velocity and tries to make it a reality
697 /// </summary>
698 /// <param name="force"></param>
699 public override void AddForce(Vector3 force, bool pushforce)
700 {
701 if (force.IsFinite())
702 {
703 if (pushforce)
704 {
705 AddChange(changes.Force, force * m_density / (m_parent_scene.ODE_STEPSIZE * 28f));
706 }
707 else
708 {
709 AddChange(changes.TargetVelocity, force);
710 }
711 }
712 else
713 {
714 m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character");
715 }
716 //m_lastUpdateSent = false;
717 }
718
719 public override void AddAngularForce(Vector3 force, bool pushforce)
720 {
721
722 }
723
724 public override void SetMomentum(Vector3 momentum)
725 {
726 if (momentum.IsFinite())
727 AddChange(changes.Momentum, momentum);
728 }
729
730
731 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
732 {
733 // sizes one day should came from visual parameters
734 float sx = m_size.X;
735 float sy = m_size.Y;
736 float sz = m_size.Z;
737
738 float bot = -sz * 0.5f + m_feetOffset;
739 boneOff = bot + 0.3f;
740
741 float feetsz = sz * 0.45f;
742 if (feetsz > 0.6f)
743 feetsz = 0.6f;
744
745 feetOff = bot + feetsz;
746
747 AvaAvaSizeXsq = 0.4f * sx;
748 AvaAvaSizeXsq *= AvaAvaSizeXsq;
749 AvaAvaSizeYsq = 0.5f * sy;
750 AvaAvaSizeYsq *= AvaAvaSizeYsq;
751
752 m_parent_scene.waitForSpaceUnlock(m_parent_scene.CharsSpace);
753
754 collider = d.HashSpaceCreate(m_parent_scene.CharsSpace);
755 d.HashSpaceSetLevels(collider, -4, 3);
756 d.SpaceSetSublevel(collider, 3);
757 d.SpaceSetCleanup(collider, false);
758 d.GeomSetCategoryBits(collider, (uint)m_collisionCategories);
759 d.GeomSetCollideBits(collider, (uint)m_collisionFlags);
760
761 float r = m_size.X;
762 if (m_size.Y > r)
763 r = m_size.Y;
764 float l = m_size.Z - r;
765 r *= 0.5f;
766
767 capsule = d.CreateCapsule(collider, r, l);
768
769 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; // update mass
770
771 d.MassSetBoxTotal(out ShellMass, m_mass, m_size.X, m_size.Y, m_size.Z);
772
773 PID_D = basePID_D * m_mass / m_parent_scene.ODE_STEPSIZE;
774 PID_P = basePID_P * m_mass / m_parent_scene.ODE_STEPSIZE;
775
776 Body = d.BodyCreate(m_parent_scene.world);
777
778 _zeroFlag = false;
779 m_pidControllerActive = true;
780 m_freemove = false;
781
782 _velocity = Vector3.Zero;
783
784 d.BodySetAutoDisableFlag(Body, false);
785 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
786
787 _position.X = npositionX;
788 _position.Y = npositionY;
789 _position.Z = npositionZ;
790
791 d.BodySetMass(Body, ref ShellMass);
792 d.GeomSetBody(capsule, Body);
793
794 // The purpose of the AMotor here is to keep the avatar's physical
795 // surrogate from rotating while moving
796 Amotor = d.JointCreateAMotor(m_parent_scene.world, IntPtr.Zero);
797 d.JointAttach(Amotor, Body, IntPtr.Zero);
798
799 d.JointSetAMotorMode(Amotor, 0);
800 d.JointSetAMotorNumAxes(Amotor, 3);
801 d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
802 d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
803 d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
804
805 d.JointSetAMotorAngle(Amotor, 0, 0);
806 d.JointSetAMotorAngle(Amotor, 1, 0);
807 d.JointSetAMotorAngle(Amotor, 2, 0);
808
809 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM, 0f); // make it HARD
810 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM2, 0f);
811 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM3, 0f);
812 d.JointSetAMotorParam(Amotor, (int)dParam.StopERP, 0.8f);
813 d.JointSetAMotorParam(Amotor, (int)dParam.StopERP2, 0.8f);
814 d.JointSetAMotorParam(Amotor, (int)dParam.StopERP3, 0.8f);
815
816 // These lowstops and high stops are effectively (no wiggle room)
817 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -1e-5f);
818 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 1e-5f);
819 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -1e-5f);
820 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 1e-5f);
821 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -1e-5f);
822 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 1e-5f);
823
824 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
825 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel2, 0);
826 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel3, 0);
827
828 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, 5e8f);
829 d.JointSetAMotorParam(Amotor, (int)dParam.FMax2, 5e8f);
830 d.JointSetAMotorParam(Amotor, (int)dParam.FMax3, 5e8f);
831 }
832
833 /// <summary>
834 /// Destroys the avatar body and geom
835
836 private void AvatarGeomAndBodyDestroy()
837 {
838 // Kill the Amotor
839 if (Amotor != IntPtr.Zero)
840 {
841 d.JointDestroy(Amotor);
842 Amotor = IntPtr.Zero;
843 }
844
845 if (Body != IntPtr.Zero)
846 {
847 //kill the body
848 d.BodyDestroy(Body);
849 Body = IntPtr.Zero;
850 }
851
852 //kill the Geoms
853 if (capsule != IntPtr.Zero)
854 {
855 m_parent_scene.actor_name_map.Remove(capsule);
856 m_parent_scene.waitForSpaceUnlock(collider);
857 d.GeomDestroy(capsule);
858 capsule = IntPtr.Zero;
859 }
860
861 if (collider != IntPtr.Zero)
862 {
863 d.SpaceDestroy(collider);
864 collider = IntPtr.Zero;
865 }
866
867 }
868
869 //in place 2D rotation around Z assuming rot is normalised and is a rotation around Z
870 public void RotateXYonZ(ref float x, ref float y, ref Quaternion rot)
871 {
872 float sin = 2.0f * rot.Z * rot.W;
873 float cos = rot.W * rot.W - rot.Z * rot.Z;
874 float tx = x;
875
876 x = tx * cos - y * sin;
877 y = tx * sin + y * cos;
878 }
879 public void RotateXYonZ(ref float x, ref float y, ref float sin, ref float cos)
880 {
881 float tx = x;
882 x = tx * cos - y * sin;
883 y = tx * sin + y * cos;
884 }
885 public void invRotateXYonZ(ref float x, ref float y, ref float sin, ref float cos)
886 {
887 float tx = x;
888 x = tx * cos + y * sin;
889 y = -tx * sin + y * cos;
890 }
891
892 public void invRotateXYonZ(ref float x, ref float y, ref Quaternion rot)
893 {
894 float sin = - 2.0f * rot.Z * rot.W;
895 float cos = rot.W * rot.W - rot.Z * rot.Z;
896 float tx = x;
897
898 x = tx * cos - y * sin;
899 y = tx * sin + y * cos;
900 }
901
902 public bool Collide(IntPtr me, IntPtr other, bool reverse, ref d.ContactGeom contact,
903 ref d.ContactGeom altContact , ref bool useAltcontact, ref bool feetcollision)
904 {
905 feetcollision = false;
906 useAltcontact = false;
907
908 if (me == capsule)
909 {
910 Vector3 offset;
911
912 float h = contact.pos.Z - _position.Z;
913 offset.Z = h - feetOff;
914
915 offset.X = contact.pos.X - _position.X;
916 offset.Y = contact.pos.Y - _position.Y;
917
918 d.GeomClassID gtype = d.GeomGetClass(other);
919 if (gtype == d.GeomClassID.CapsuleClass)
920 {
921 Vector3 roff = offset * Quaternion.Inverse(m_orientation2D);
922 float r = roff.X *roff.X / AvaAvaSizeXsq;
923 r += (roff.Y * roff.Y) / AvaAvaSizeYsq;
924 if (r > 1.0f)
925 return false;
926
927 float dp = 1.0f -(float)Math.Sqrt((double)r);
928 if (dp > 0.05f)
929 dp = 0.05f;
930
931 contact.depth = dp;
932
933 if (offset.Z < 0)
934 {
935 feetcollision = true;
936 if (h < boneOff)
937 {
938 m_collideNormal.X = contact.normal.X;
939 m_collideNormal.Y = contact.normal.Y;
940 m_collideNormal.Z = contact.normal.Z;
941 IsColliding = true;
942 }
943 }
944 return true;
945 }
946
947 if (gtype == d.GeomClassID.SphereClass && d.GeomGetBody(other) != IntPtr.Zero)
948 {
949 if(d.GeomSphereGetRadius(other) < 0.5)
950 return true;
951 }
952
953 if (offset.Z > 0 || contact.normal.Z > 0.35f)
954 {
955 if (offset.Z <= 0)
956 {
957 feetcollision = true;
958 if (h < boneOff)
959 {
960 m_collideNormal.X = contact.normal.X;
961 m_collideNormal.Y = contact.normal.Y;
962 m_collideNormal.Z = contact.normal.Z;
963 IsColliding = true;
964 }
965 }
966 return true;
967 }
968
969 if(m_flying)
970 return true;
971
972 feetcollision = true;
973 if (h < boneOff)
974 {
975 m_collideNormal.X = contact.normal.X;
976 m_collideNormal.Y = contact.normal.Y;
977 m_collideNormal.Z = contact.normal.Z;
978 IsColliding = true;
979 }
980
981 altContact = contact;
982 useAltcontact = true;
983
984 offset.Z -= 0.2f;
985
986 offset.Normalize();
987
988 float tdp = contact.depth;
989 float t = offset.X;
990 t = Math.Abs(t);
991 if(t > 1e-6)
992 {
993 tdp /= t;
994 tdp *= contact.normal.X;
995 }
996 else
997 tdp *= 10;
998
999 if (tdp > 0.25f)
1000 tdp = 0.25f;
1001
1002 altContact.depth = tdp;
1003
1004 if (reverse)
1005 {
1006 altContact.normal.X = offset.X;
1007 altContact.normal.Y = offset.Y;
1008 altContact.normal.Z = offset.Z;
1009 }
1010 else
1011 {
1012 altContact.normal.X = -offset.X;
1013 altContact.normal.Y = -offset.Y;
1014 altContact.normal.Z = -offset.Z;
1015 }
1016 return true;
1017 }
1018 return false;
1019 }
1020
1021 /// <summary>
1022 /// Called from Simulate
1023 /// This is the avatar's movement control + PID Controller
1024 /// </summary>
1025 /// <param name="timeStep"></param>
1026 public void Move(List<OdeCharacter> defects)
1027 {
1028 if (Body == IntPtr.Zero)
1029 return;
1030
1031 d.Vector3 dtmp = d.BodyGetPosition(Body);
1032 Vector3 localpos = new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
1033
1034 // the Amotor still lets avatar rotation to drift during colisions
1035 // so force it back to identity
1036
1037 d.Quaternion qtmp;
1038 qtmp.W = m_orientation2D.W;
1039 qtmp.X = m_orientation2D.X;
1040 qtmp.Y = m_orientation2D.Y;
1041 qtmp.Z = m_orientation2D.Z;
1042 d.BodySetQuaternion(Body, ref qtmp);
1043
1044 if (m_pidControllerActive == false)
1045 {
1046 _zeroPosition = localpos;
1047 }
1048
1049 if (!localpos.IsFinite())
1050 {
1051 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
1052 defects.Add(this);
1053 // _parent_scene.RemoveCharacter(this);
1054
1055 // destroy avatar capsule and related ODE data
1056 AvatarGeomAndBodyDestroy();
1057 return;
1058 }
1059
1060 // check outbounds forcing to be in world
1061 bool fixbody = false;
1062 if (localpos.X < 0.0f)
1063 {
1064 fixbody = true;
1065 localpos.X = 0.1f;
1066 }
1067 else if (localpos.X > m_parent_scene.WorldExtents.X - 0.1f)
1068 {
1069 fixbody = true;
1070 localpos.X = m_parent_scene.WorldExtents.X - 0.1f;
1071 }
1072 if (localpos.Y < 0.0f)
1073 {
1074 fixbody = true;
1075 localpos.Y = 0.1f;
1076 }
1077 else if (localpos.Y > m_parent_scene.WorldExtents.Y - 0.1)
1078 {
1079 fixbody = true;
1080 localpos.Y = m_parent_scene.WorldExtents.Y - 0.1f;
1081 }
1082 if (fixbody)
1083 {
1084 m_freemove = false;
1085 d.BodySetPosition(Body, localpos.X, localpos.Y, localpos.Z);
1086 }
1087
1088 float breakfactor;
1089
1090 Vector3 vec = Vector3.Zero;
1091 dtmp = d.BodyGetLinearVel(Body);
1092 Vector3 vel = new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
1093 float velLengthSquared = vel.LengthSquared();
1094
1095 Vector3 ctz = _target_velocity;
1096
1097 float movementdivisor = 1f;
1098 //Ubit change divisions into multiplications below
1099 if (!m_alwaysRun)
1100 movementdivisor = 1 / walkDivisor;
1101 else
1102 movementdivisor = 1 / runDivisor;
1103
1104 ctz.X *= movementdivisor;
1105 ctz.Y *= movementdivisor;
1106
1107 //******************************************
1108 // colide with land
1109
1110 d.AABB aabb;
1111// d.GeomGetAABB(feetbox, out aabb);
1112 d.GeomGetAABB(capsule, out aabb);
1113 float chrminZ = aabb.MinZ; // move up a bit
1114 Vector3 posch = localpos;
1115
1116 float ftmp;
1117
1118 if (m_flying)
1119 {
1120 ftmp = timeStep;
1121 posch.X += vel.X * ftmp;
1122 posch.Y += vel.Y * ftmp;
1123 }
1124
1125 float terrainheight = m_parent_scene.GetTerrainHeightAtXY(posch.X, posch.Y);
1126 if (chrminZ < terrainheight)
1127 {
1128 if (ctz.Z < 0)
1129 ctz.Z = 0;
1130
1131 if(!m_haveLastFallVel)
1132 {
1133 m_lastFallVel = vel;
1134 m_haveLastFallVel = true;
1135 }
1136
1137 Vector3 n = m_parent_scene.GetTerrainNormalAtXY(posch.X, posch.Y);
1138 float depth = terrainheight - chrminZ;
1139
1140 vec.Z = depth * PID_P * 50;
1141
1142 if (!m_flying)
1143 {
1144 vec.Z += -vel.Z * PID_D;
1145 if(n.Z < 0.4f)
1146 {
1147 vec.X = depth * PID_P * 50 - vel.X * PID_D;
1148 vec.X *= n.X;
1149 vec.Y = depth * PID_P * 50 - vel.Y * PID_D;
1150 vec.Y *= n.Y;
1151 vec.Z *= n.Z;
1152 if(n.Z < 0.1f)
1153 {
1154 // cancel the slope pose
1155 n.X = 0f;
1156 n.Y = 0f;
1157 n.Z = 1.0f;
1158 }
1159 }
1160 }
1161
1162 if (depth < 0.2f)
1163 {
1164 m_colliderGroundfilter++;
1165 if (m_colliderGroundfilter > 2)
1166 {
1167 m_iscolliding = true;
1168 m_colliderfilter = 2;
1169
1170 if (m_colliderGroundfilter > 10)
1171 {
1172 m_colliderGroundfilter = 10;
1173 m_freemove = false;
1174 }
1175
1176 m_collideNormal.X = n.X;
1177 m_collideNormal.Y = n.Y;
1178 m_collideNormal.Z = n.Z;
1179
1180 m_iscollidingGround = true;
1181
1182 ContactPoint contact = new ContactPoint();
1183 contact.PenetrationDepth = depth;
1184 contact.Position.X = localpos.X;
1185 contact.Position.Y = localpos.Y;
1186 contact.Position.Z = terrainheight;
1187 contact.SurfaceNormal.X = -n.X;
1188 contact.SurfaceNormal.Y = -n.Y;
1189 contact.SurfaceNormal.Z = -n.Z;
1190 contact.RelativeSpeed = Vector3.Dot(m_lastFallVel, n);
1191 contact.CharacterFeet = true;
1192 AddCollisionEvent(0, contact);
1193 m_lastFallVel = vel;
1194
1195// vec.Z *= 0.5f;
1196 }
1197 }
1198
1199 else
1200 {
1201 m_colliderGroundfilter -= 5;
1202 if (m_colliderGroundfilter <= 0)
1203 {
1204 m_colliderGroundfilter = 0;
1205 m_iscollidingGround = false;
1206 }
1207 }
1208 }
1209 else
1210 {
1211 m_haveLastFallVel = false;
1212 m_colliderGroundfilter -= 5;
1213 if (m_colliderGroundfilter <= 0)
1214 {
1215 m_colliderGroundfilter = 0;
1216 m_iscollidingGround = false;
1217 }
1218 }
1219
1220 bool hoverPIDActive = false;
1221
1222 if (m_useHoverPID && m_PIDHoverTau != 0 && m_PIDHoverHeight != 0)
1223 {
1224 hoverPIDActive = true;
1225
1226 switch (m_PIDHoverType)
1227 {
1228 case PIDHoverType.Ground:
1229 m_targetHoverHeight = terrainheight + m_PIDHoverHeight;
1230 break;
1231
1232 case PIDHoverType.GroundAndWater:
1233 float waterHeight = m_parent_scene.GetWaterLevel();
1234 if (terrainheight > waterHeight)
1235 m_targetHoverHeight = terrainheight + m_PIDHoverHeight;
1236 else
1237 m_targetHoverHeight = waterHeight + m_PIDHoverHeight;
1238 break;
1239 } // end switch (m_PIDHoverType)
1240
1241 // don't go underground
1242 if (m_targetHoverHeight > terrainheight + 0.5f * (aabb.MaxZ - aabb.MinZ))
1243 {
1244 float fz = (m_targetHoverHeight - localpos.Z);
1245
1246 // if error is zero, use position control; otherwise, velocity control
1247 if (Math.Abs(fz) < 0.01f)
1248 {
1249 ctz.Z = 0;
1250 }
1251 else
1252 {
1253 _zeroFlag = false;
1254 fz /= m_PIDHoverTau;
1255
1256 float tmp = Math.Abs(fz);
1257 if (tmp > 50)
1258 fz = 50 * Math.Sign(fz);
1259 else if (tmp < 0.1)
1260 fz = 0.1f * Math.Sign(fz);
1261
1262 ctz.Z = fz;
1263 }
1264 }
1265 }
1266
1267 //******************************************
1268 if (!m_iscolliding)
1269 m_collideNormal.Z = 0;
1270
1271 bool tviszero = (ctz.X == 0.0f && ctz.Y == 0.0f && ctz.Z == 0.0f);
1272
1273 if (!tviszero)
1274 {
1275 m_freemove = false;
1276
1277 // movement relative to surface if moving on it
1278 // dont disturbe vertical movement, ie jumps
1279 if (m_iscolliding && !m_flying && ctz.Z == 0 && m_collideNormal.Z > 0.2f && m_collideNormal.Z < 0.94f)
1280 {
1281 float p = ctz.X * m_collideNormal.X + ctz.Y * m_collideNormal.Y;
1282 ctz.X *= (float)Math.Sqrt(1 - m_collideNormal.X * m_collideNormal.X);
1283 ctz.Y *= (float)Math.Sqrt(1 - m_collideNormal.Y * m_collideNormal.Y);
1284 ctz.Z -= p;
1285 if (ctz.Z < 0)
1286 ctz.Z *= 2;
1287
1288 }
1289
1290 }
1291
1292 if (!m_freemove)
1293 {
1294
1295 // if velocity is zero, use position control; otherwise, velocity control
1296 if (tviszero && m_iscolliding && !m_flying)
1297 {
1298 // keep track of where we stopped. No more slippin' & slidin'
1299 if (!_zeroFlag)
1300 {
1301 _zeroFlag = true;
1302 _zeroPosition = localpos;
1303 }
1304 if (m_pidControllerActive)
1305 {
1306 // We only want to deactivate the PID Controller if we think we want to have our surrogate
1307 // react to the physics scene by moving it's position.
1308 // Avatar to Avatar collisions
1309 // Prim to avatar collisions
1310
1311 vec.X = -vel.X * PID_D * 2f + (_zeroPosition.X - localpos.X) * (PID_P * 5);
1312 vec.Y = -vel.Y * PID_D * 2f + (_zeroPosition.Y - localpos.Y) * (PID_P * 5);
1313 if(vel.Z > 0)
1314 vec.Z += -vel.Z * PID_D + (_zeroPosition.Z - localpos.Z) * PID_P;
1315 else
1316 vec.Z += (-vel.Z * PID_D + (_zeroPosition.Z - localpos.Z) * PID_P) * 0.2f;
1317/*
1318 if (flying)
1319 {
1320 vec.Z += -vel.Z * PID_D + (_zeroPosition.Z - localpos.Z) * PID_P;
1321 }
1322*/
1323 }
1324 //PidStatus = true;
1325 }
1326 else
1327 {
1328 m_pidControllerActive = true;
1329 _zeroFlag = false;
1330
1331 if (m_iscolliding)
1332 {
1333 if (!m_flying)
1334 {
1335 // we are on a surface
1336 if (ctz.Z > 0f)
1337 {
1338 // moving up or JUMPING
1339 vec.Z += (ctz.Z - vel.Z) * PID_D * 2f;
1340 vec.X += (ctz.X - vel.X) * (PID_D);
1341 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1342 }
1343 else
1344 {
1345 // we are moving down on a surface
1346 if (ctz.Z == 0)
1347 {
1348 if (vel.Z > 0)
1349 vec.Z -= vel.Z * PID_D * 2f;
1350 vec.X += (ctz.X - vel.X) * (PID_D);
1351 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1352 }
1353 // intencionally going down
1354 else
1355 {
1356 if (ctz.Z < vel.Z)
1357 vec.Z += (ctz.Z - vel.Z) * PID_D;
1358 else
1359 {
1360 }
1361
1362 if (Math.Abs(ctz.X) > Math.Abs(vel.X))
1363 vec.X += (ctz.X - vel.X) * (PID_D);
1364 if (Math.Abs(ctz.Y) > Math.Abs(vel.Y))
1365 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1366 }
1367 }
1368
1369 // We're standing on something
1370 }
1371 else
1372 {
1373 // We're flying and colliding with something
1374 vec.X += (ctz.X - vel.X) * (PID_D * 0.0625f);
1375 vec.Y += (ctz.Y - vel.Y) * (PID_D * 0.0625f);
1376 vec.Z += (ctz.Z - vel.Z) * (PID_D * 0.0625f);
1377 }
1378 }
1379 else // ie not colliding
1380 {
1381 if (m_flying || hoverPIDActive) //(!m_iscolliding && flying)
1382 {
1383 // we're in mid air suspended
1384 vec.X += (ctz.X - vel.X) * (PID_D);
1385 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1386 vec.Z += (ctz.Z - vel.Z) * (PID_D);
1387 }
1388
1389 else
1390 {
1391 // we're not colliding and we're not flying so that means we're falling!
1392 // m_iscolliding includes collisions with the ground.
1393
1394 // d.Vector3 pos = d.BodyGetPosition(Body);
1395 vec.X += (ctz.X - vel.X) * PID_D * 0.833f;
1396 vec.Y += (ctz.Y - vel.Y) * PID_D * 0.833f;
1397 // hack for breaking on fall
1398 if (ctz.Z == -9999f)
1399 vec.Z += -vel.Z * PID_D - m_parent_scene.gravityz * m_mass;
1400 }
1401 }
1402 }
1403
1404 if (velLengthSquared > 2500.0f) // 50m/s apply breaks
1405 {
1406 breakfactor = 0.16f * m_mass;
1407 vec.X -= breakfactor * vel.X;
1408 vec.Y -= breakfactor * vel.Y;
1409 vec.Z -= breakfactor * vel.Z;
1410 }
1411 }
1412 else
1413 {
1414 breakfactor = m_mass;
1415 vec.X -= breakfactor * vel.X;
1416 vec.Y -= breakfactor * vel.Y;
1417 if (m_flying)
1418 vec.Z -= 0.5f * breakfactor * vel.Z;
1419 else
1420 vec.Z -= .16f* m_mass * vel.Z;
1421 }
1422
1423 if (m_flying || hoverPIDActive)
1424 {
1425 vec.Z -= m_parent_scene.gravityz * m_mass;
1426
1427 if(!hoverPIDActive)
1428 {
1429 //Added for auto fly height. Kitto Flora
1430 float target_altitude = terrainheight + MinimumGroundFlightOffset;
1431
1432 if (localpos.Z < target_altitude)
1433 {
1434 vec.Z += (target_altitude - localpos.Z) * PID_P * 5.0f;
1435 }
1436 // end add Kitto Flora
1437 }
1438 }
1439
1440 if (vec.IsFinite())
1441 {
1442 if (vec.X != 0 || vec.Y !=0 || vec.Z !=0)
1443 d.BodyAddForce(Body, vec.X, vec.Y, vec.Z);
1444 }
1445 else
1446 {
1447 m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()");
1448 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
1449 defects.Add(this);
1450 // _parent_scene.RemoveCharacter(this);
1451 // destroy avatar capsule and related ODE data
1452 AvatarGeomAndBodyDestroy();
1453 return;
1454 }
1455
1456 // update our local ideia of position velocity and aceleration
1457 // _position = localpos;
1458 _position = localpos;
1459
1460 if (_zeroFlag)
1461 {
1462 _velocity = Vector3.Zero;
1463 _acceleration = Vector3.Zero;
1464 m_rotationalVelocity = Vector3.Zero;
1465 }
1466 else
1467 {
1468 Vector3 a =_velocity; // previus velocity
1469 SetSmooth(ref _velocity, ref vel, 2);
1470 a = (_velocity - a) * invtimeStep;
1471 SetSmooth(ref _acceleration, ref a, 2);
1472
1473 dtmp = d.BodyGetAngularVel(Body);
1474 m_rotationalVelocity.X = 0f;
1475 m_rotationalVelocity.Y = 0f;
1476 m_rotationalVelocity.Z = dtmp.Z;
1477 Math.Round(m_rotationalVelocity.Z,3);
1478 }
1479 }
1480
1481 public void round(ref Vector3 v, int digits)
1482 {
1483 v.X = (float)Math.Round(v.X, digits);
1484 v.Y = (float)Math.Round(v.Y, digits);
1485 v.Z = (float)Math.Round(v.Z, digits);
1486 }
1487
1488 public void SetSmooth(ref Vector3 dst, ref Vector3 value)
1489 {
1490 dst.X = 0.1f * dst.X + 0.9f * value.X;
1491 dst.Y = 0.1f * dst.Y + 0.9f * value.Y;
1492 dst.Z = 0.1f * dst.Z + 0.9f * value.Z;
1493 }
1494
1495 public void SetSmooth(ref Vector3 dst, ref Vector3 value, int rounddigits)
1496 {
1497 dst.X = 0.4f * dst.X + 0.6f * value.X;
1498 dst.X = (float)Math.Round(dst.X, rounddigits);
1499
1500 dst.Y = 0.4f * dst.Y + 0.6f * value.Y;
1501 dst.Y = (float)Math.Round(dst.Y, rounddigits);
1502
1503 dst.Z = 0.4f * dst.Z + 0.6f * value.Z;
1504 dst.Z = (float)Math.Round(dst.Z, rounddigits);
1505 }
1506
1507
1508 /// <summary>
1509 /// Updates the reported position and velocity.
1510 /// Used to copy variables from unmanaged space at heartbeat rate and also trigger scene updates acording
1511 /// also outbounds checking
1512 /// copy and outbounds now done in move(..) at ode rate
1513 ///
1514 /// </summary>
1515 public void UpdatePositionAndVelocity()
1516 {
1517 return;
1518
1519// if (Body == IntPtr.Zero)
1520// return;
1521
1522 }
1523
1524 /// <summary>
1525 /// Cleanup the things we use in the scene.
1526 /// </summary>
1527 public void Destroy()
1528 {
1529 AddChange(changes.Remove, null);
1530 }
1531
1532 public override void CrossingFailure()
1533 {
1534 }
1535
1536 public override Vector3 PIDTarget { set { return; } }
1537 public override bool PIDActive {get {return m_pidControllerActive;} set { return; } }
1538 public override float PIDTau { set { return; } }
1539
1540 public override float PIDHoverHeight
1541 {
1542 set
1543 {
1544 AddChange(changes.PIDHoverHeight,value);
1545 }
1546 }
1547 public override bool PIDHoverActive
1548 {
1549 get
1550 {
1551 return m_useHoverPID;
1552 }
1553 set
1554 {
1555 AddChange(changes.PIDHoverActive, value);
1556 }
1557 }
1558
1559 public override PIDHoverType PIDHoverType
1560 {
1561 set
1562 {
1563 AddChange(changes.PIDHoverType,value);
1564 }
1565 }
1566
1567 public override float PIDHoverTau
1568 {
1569 set
1570 {
1571 float tmp =0;
1572 if (value > 0)
1573 {
1574 float mint = (0.05f > timeStep ? 0.05f : timeStep);
1575 if (value < mint)
1576 tmp = mint;
1577 else
1578 tmp = value;
1579 }
1580 AddChange(changes.PIDHoverTau, tmp);
1581 }
1582 }
1583
1584 public override Quaternion APIDTarget { set { return; } }
1585
1586 public override bool APIDActive { set { return; } }
1587
1588 public override float APIDStrength { set { return; } }
1589
1590 public override float APIDDamping { set { return; } }
1591
1592 public override void SubscribeEvents(int ms)
1593 {
1594 m_eventsubscription = ms;
1595 m_cureventsubscription = 0;
1596 CollisionEventsThisFrame.Clear();
1597 SentEmptyCollisionsEvent = false;
1598 }
1599
1600 public override void UnSubscribeEvents()
1601 {
1602 m_eventsubscription = 0;
1603 m_parent_scene.RemoveCollisionEventReporting(this);
1604 lock(CollisionEventsThisFrame)
1605 CollisionEventsThisFrame.Clear();
1606 }
1607
1608 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1609 {
1610 lock(CollisionEventsThisFrame)
1611 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
1612 m_parent_scene.AddCollisionEventReporting(this);
1613 }
1614
1615 public void SendCollisions(int timestep)
1616 {
1617 if (m_cureventsubscription < 50000)
1618 m_cureventsubscription += timestep;
1619
1620 if (m_cureventsubscription < m_eventsubscription)
1621 return;
1622
1623 lock(CollisionEventsThisFrame)
1624 {
1625 int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count;
1626
1627 if (!SentEmptyCollisionsEvent || ncolisions > 0)
1628 {
1629 base.SendCollisionUpdate(CollisionEventsThisFrame);
1630 m_cureventsubscription = 0;
1631
1632 if (ncolisions == 0)
1633 {
1634 SentEmptyCollisionsEvent = true;
1635 // _parent_scene.RemoveCollisionEventReporting(this);
1636 }
1637 else
1638 {
1639 SentEmptyCollisionsEvent = false;
1640 CollisionEventsThisFrame.Clear();
1641 }
1642 }
1643 }
1644 }
1645
1646 public override bool SubscribedEvents()
1647 {
1648 if (m_eventsubscription > 0)
1649 return true;
1650 return false;
1651 }
1652
1653 private void changePhysicsStatus(bool NewStatus)
1654 {
1655 if (NewStatus != m_isPhysical)
1656 {
1657 if (NewStatus)
1658 {
1659 AvatarGeomAndBodyDestroy();
1660
1661 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z);
1662
1663 m_parent_scene.actor_name_map[collider] = (PhysicsActor)this;
1664 m_parent_scene.actor_name_map[capsule] = (PhysicsActor)this;
1665 m_parent_scene.AddCharacter(this);
1666 }
1667 else
1668 {
1669 m_parent_scene.RemoveCollisionEventReporting(this);
1670 m_parent_scene.RemoveCharacter(this);
1671 // destroy avatar capsule and related ODE data
1672 AvatarGeomAndBodyDestroy();
1673 }
1674 m_freemove = false;
1675 m_isPhysical = NewStatus;
1676 }
1677 }
1678
1679 private void changeAdd()
1680 {
1681 changePhysicsStatus(true);
1682 }
1683
1684 private void changeRemove()
1685 {
1686 changePhysicsStatus(false);
1687 }
1688
1689 private void changeShape(PrimitiveBaseShape arg)
1690 {
1691 }
1692
1693 private void changeAvatarSize(strAvatarSize st)
1694 {
1695 m_feetOffset = st.offset;
1696 changeSize(st.size);
1697 }
1698
1699 private void changeSize(Vector3 pSize)
1700 {
1701 if (pSize.IsFinite())
1702 {
1703 // for now only look to Z changes since viewers also don't change X and Y
1704 if (pSize.Z != m_size.Z)
1705 {
1706 AvatarGeomAndBodyDestroy();
1707
1708 float oldsz = m_size.Z;
1709 m_size = pSize;
1710
1711 AvatarGeomAndBodyCreation(_position.X, _position.Y,
1712 _position.Z + (m_size.Z - oldsz) * 0.5f);
1713
1714// Velocity = Vector3.Zero;
1715 m_targetVelocity = Vector3.Zero;
1716
1717 m_parent_scene.actor_name_map[collider] = (PhysicsActor)this;
1718 m_parent_scene.actor_name_map[capsule] = (PhysicsActor)this;
1719 }
1720 m_freemove = false;
1721 m_pidControllerActive = true;
1722 }
1723 else
1724 {
1725 m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character");
1726 }
1727 }
1728
1729 private void changePosition( Vector3 newPos)
1730 {
1731 if (Body != IntPtr.Zero)
1732 d.BodySetPosition(Body, newPos.X, newPos.Y, newPos.Z);
1733 _position = newPos;
1734 m_freemove = false;
1735 m_pidControllerActive = true;
1736 }
1737
1738 private void changeOrientation(Quaternion newOri)
1739 {
1740 if (m_orientation != newOri)
1741 {
1742 m_orientation = newOri; // keep a copy for core use
1743 // but only use rotations around Z
1744
1745 m_orientation2D.W = newOri.W;
1746 m_orientation2D.Z = newOri.Z;
1747
1748 float t = m_orientation2D.W * m_orientation2D.W + m_orientation2D.Z * m_orientation2D.Z;
1749 if (t > 0)
1750 {
1751 t = 1.0f / (float)Math.Sqrt(t);
1752 m_orientation2D.W *= t;
1753 m_orientation2D.Z *= t;
1754 }
1755 else
1756 {
1757 m_orientation2D.W = 1.0f;
1758 m_orientation2D.Z = 0f;
1759 }
1760 m_orientation2D.Y = 0f;
1761 m_orientation2D.X = 0f;
1762
1763 d.Quaternion myrot = new d.Quaternion();
1764 myrot.X = m_orientation2D.X;
1765 myrot.Y = m_orientation2D.Y;
1766 myrot.Z = m_orientation2D.Z;
1767 myrot.W = m_orientation2D.W;
1768 d.BodySetQuaternion(Body, ref myrot);
1769 }
1770 }
1771
1772 private void changeVelocity(Vector3 newVel)
1773 {
1774 _velocity = newVel;
1775 setFreeMove();
1776
1777 if (Body != IntPtr.Zero)
1778 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
1779 }
1780
1781 private void changeTargetVelocity(Vector3 newVel)
1782 {
1783 m_pidControllerActive = true;
1784 m_freemove = false;
1785 _target_velocity = newVel;
1786 }
1787
1788 private void changeSetTorque(Vector3 newTorque)
1789 {
1790 }
1791
1792 private void changeAddForce(Vector3 newForce)
1793 {
1794 }
1795
1796 private void changeAddAngularForce(Vector3 arg)
1797 {
1798 }
1799
1800 private void changeAngularLock(byte arg)
1801 {
1802 }
1803
1804 private void changeFloatOnWater(bool arg)
1805 {
1806 }
1807
1808 private void changeVolumedetetion(bool arg)
1809 {
1810 }
1811
1812 private void changeSelectedStatus(bool arg)
1813 {
1814 }
1815
1816 private void changeDisable(bool arg)
1817 {
1818 }
1819
1820 private void changeBuilding(bool arg)
1821 {
1822 }
1823
1824 private void setFreeMove()
1825 {
1826 m_pidControllerActive = true;
1827 _zeroFlag = false;
1828 _target_velocity = Vector3.Zero;
1829 m_freemove = true;
1830 m_colliderfilter = -1;
1831 m_colliderObjectfilter = -1;
1832 m_colliderGroundfilter = -1;
1833
1834 m_iscolliding = false;
1835 m_iscollidingGround = false;
1836 m_iscollidingObj = false;
1837
1838 CollisionEventsThisFrame.Clear();
1839 }
1840
1841 private void changeForce(Vector3 newForce)
1842 {
1843 setFreeMove();
1844
1845 if (Body != IntPtr.Zero)
1846 {
1847 if (newForce.X != 0f || newForce.Y != 0f || newForce.Z != 0)
1848 d.BodyAddForce(Body, newForce.X, newForce.Y, newForce.Z);
1849 }
1850 }
1851
1852 // for now momentum is actually velocity
1853 private void changeMomentum(Vector3 newmomentum)
1854 {
1855 _velocity = newmomentum;
1856 setFreeMove();
1857
1858 if (Body != IntPtr.Zero)
1859 d.BodySetLinearVel(Body, newmomentum.X, newmomentum.Y, newmomentum.Z);
1860 }
1861
1862 private void changePIDHoverHeight(float val)
1863 {
1864 m_PIDHoverHeight = val;
1865 if (val == 0)
1866 m_useHoverPID = false;
1867 }
1868
1869 private void changePIDHoverType(PIDHoverType type)
1870 {
1871 m_PIDHoverType = type;
1872 }
1873
1874 private void changePIDHoverTau(float tau)
1875 {
1876 m_PIDHoverTau = tau;
1877 }
1878
1879 private void changePIDHoverActive(bool active)
1880 {
1881 m_useHoverPID = active;
1882 }
1883
1884 private void donullchange()
1885 {
1886 }
1887
1888 public bool DoAChange(changes what, object arg)
1889 {
1890 if (collider == IntPtr.Zero && what != changes.Add && what != changes.Remove)
1891 {
1892 return false;
1893 }
1894
1895 // nasty switch
1896 switch (what)
1897 {
1898 case changes.Add:
1899 changeAdd();
1900 break;
1901 case changes.Remove:
1902 changeRemove();
1903 break;
1904
1905 case changes.Position:
1906 changePosition((Vector3)arg);
1907 break;
1908
1909 case changes.Orientation:
1910 changeOrientation((Quaternion)arg);
1911 break;
1912
1913 case changes.PosOffset:
1914 donullchange();
1915 break;
1916
1917 case changes.OriOffset:
1918 donullchange();
1919 break;
1920
1921 case changes.Velocity:
1922 changeVelocity((Vector3)arg);
1923 break;
1924
1925 case changes.TargetVelocity:
1926 changeTargetVelocity((Vector3)arg);
1927 break;
1928
1929 // case changes.Acceleration:
1930 // changeacceleration((Vector3)arg);
1931 // break;
1932 // case changes.AngVelocity:
1933 // changeangvelocity((Vector3)arg);
1934 // break;
1935
1936 case changes.Force:
1937 changeForce((Vector3)arg);
1938 break;
1939
1940 case changes.Torque:
1941 changeSetTorque((Vector3)arg);
1942 break;
1943
1944 case changes.AddForce:
1945 changeAddForce((Vector3)arg);
1946 break;
1947
1948 case changes.AddAngForce:
1949 changeAddAngularForce((Vector3)arg);
1950 break;
1951
1952 case changes.AngLock:
1953 changeAngularLock((byte)arg);
1954 break;
1955
1956 case changes.Size:
1957 changeSize((Vector3)arg);
1958 break;
1959
1960 case changes.AvatarSize:
1961 changeAvatarSize((strAvatarSize)arg);
1962 break;
1963
1964 case changes.Momentum:
1965 changeMomentum((Vector3)arg);
1966 break;
1967
1968 case changes.PIDHoverHeight:
1969 changePIDHoverHeight((float)arg);
1970 break;
1971
1972 case changes.PIDHoverType:
1973 changePIDHoverType((PIDHoverType)arg);
1974 break;
1975
1976 case changes.PIDHoverTau:
1977 changePIDHoverTau((float)arg);
1978 break;
1979
1980 case changes.PIDHoverActive:
1981 changePIDHoverActive((bool)arg);
1982 break;
1983
1984/* not in use for now
1985 case changes.Shape:
1986 changeShape((PrimitiveBaseShape)arg);
1987 break;
1988
1989 case changes.CollidesWater:
1990 changeFloatOnWater((bool)arg);
1991 break;
1992
1993 case changes.VolumeDtc:
1994 changeVolumedetetion((bool)arg);
1995 break;
1996
1997 case changes.Physical:
1998 changePhysicsStatus((bool)arg);
1999 break;
2000
2001 case changes.Selected:
2002 changeSelectedStatus((bool)arg);
2003 break;
2004
2005 case changes.disabled:
2006 changeDisable((bool)arg);
2007 break;
2008
2009 case changes.building:
2010 changeBuilding((bool)arg);
2011 break;
2012*/
2013 case changes.Null:
2014 donullchange();
2015 break;
2016
2017 default:
2018 donullchange();
2019 break;
2020 }
2021 return false;
2022 }
2023
2024 public void AddChange(changes what, object arg)
2025 {
2026 m_parent_scene.AddChange((PhysicsActor)this, what, arg);
2027 }
2028
2029 private struct strAvatarSize
2030 {
2031 public Vector3 size;
2032 public float offset;
2033 }
2034
2035 }
2036}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs
new file mode 100644
index 0000000..ce10065
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs
@@ -0,0 +1,1205 @@
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 if(float.IsNaN(pValue) || float.IsInfinity(pValue))
247 return;
248
249 switch (pParam)
250 {
251 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
252 if (pValue < 0f) pValue = 0f;
253 if (pValue > 1f) pValue = 1f;
254 m_angularDeflectionEfficiency = pValue;
255 break;
256 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
257 if (pValue < m_timestep) pValue = m_timestep;
258 m_angularDeflectionTimescale = pValue;
259 break;
260 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
261 if (pValue < m_timestep) pValue = m_timestep;
262 else if (pValue > 120) pValue = 120;
263 m_angularMotorDecayTimescale = pValue * m_invtimestep;
264 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
265 break;
266 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
267 if (pValue < m_timestep) pValue = m_timestep;
268 m_angularMotorTimescale = pValue;
269 break;
270 case Vehicle.BANKING_EFFICIENCY:
271 if (pValue < -1f) pValue = -1f;
272 if (pValue > 1f) pValue = 1f;
273 m_bankingEfficiency = pValue;
274 break;
275 case Vehicle.BANKING_MIX:
276 if (pValue < 0f) pValue = 0f;
277 if (pValue > 1f) pValue = 1f;
278 m_bankingMix = pValue;
279 break;
280 case Vehicle.BANKING_TIMESCALE:
281 if (pValue < m_timestep) pValue = m_timestep;
282 m_bankingTimescale = pValue;
283 break;
284 case Vehicle.BUOYANCY:
285 if (pValue < -1f) pValue = -1f;
286 if (pValue > 1f) pValue = 1f;
287 m_VehicleBuoyancy = pValue;
288 break;
289 case Vehicle.HOVER_EFFICIENCY:
290 if (pValue < 0f) pValue = 0f;
291 if (pValue > 1f) pValue = 1f;
292 m_VhoverEfficiency = pValue;
293 break;
294 case Vehicle.HOVER_HEIGHT:
295 m_VhoverHeight = pValue;
296 break;
297 case Vehicle.HOVER_TIMESCALE:
298 if (pValue < m_timestep) pValue = m_timestep;
299 m_VhoverTimescale = pValue;
300 break;
301 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
302 if (pValue < 0f) pValue = 0f;
303 if (pValue > 1f) pValue = 1f;
304 m_linearDeflectionEfficiency = pValue;
305 break;
306 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
307 if (pValue < m_timestep) pValue = m_timestep;
308 m_linearDeflectionTimescale = pValue;
309 break;
310 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
311 if (pValue < m_timestep) pValue = m_timestep;
312 else if (pValue > 120) pValue = 120;
313 m_linearMotorDecayTimescale = (0.2f +pValue) * m_invtimestep;
314 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
315 break;
316 case Vehicle.LINEAR_MOTOR_TIMESCALE:
317 if (pValue < m_timestep) pValue = m_timestep;
318 m_linearMotorTimescale = pValue;
319 break;
320 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
321 if (pValue < 0f) pValue = 0f;
322 if (pValue > 1f) pValue = 1f;
323 m_verticalAttractionEfficiency = pValue;
324 break;
325 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
326 if (pValue < m_timestep) pValue = m_timestep;
327 m_verticalAttractionTimescale = pValue;
328 break;
329
330 // These are vector properties but the engine lets you use a single float value to
331 // set all of the components to the same value
332 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
333 if (pValue < m_timestep) pValue = m_timestep;
334 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
335 break;
336 case Vehicle.ANGULAR_MOTOR_DIRECTION:
337 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
338 len = m_angularMotorDirection.Length();
339 if (len > 12.566f)
340 m_angularMotorDirection *= (12.566f / len);
341
342 m_amEfect = 1.0f ; // turn it on
343 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
344
345 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
346 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
347 d.BodyEnable(rootPrim.Body);
348
349 break;
350 case Vehicle.LINEAR_FRICTION_TIMESCALE:
351 if (pValue < m_timestep) pValue = m_timestep;
352 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
353 break;
354 case Vehicle.LINEAR_MOTOR_DIRECTION:
355 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
356 len = m_linearMotorDirection.Length();
357 if (len > 100.0f)
358 m_linearMotorDirection *= (100.0f / len);
359
360 m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale;
361 m_lmEfect = 1.0f; // turn it on
362
363 m_ffactor = 0.0f;
364 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
365 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
366 d.BodyEnable(rootPrim.Body);
367 break;
368 case Vehicle.LINEAR_MOTOR_OFFSET:
369 m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
370 len = m_linearMotorOffset.Length();
371 if (len > 100.0f)
372 m_linearMotorOffset *= (100.0f / len);
373 break;
374 }
375 }//end ProcessFloatVehicleParam
376
377 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
378 {
379 float len;
380 if(!pValue.IsFinite())
381 return;
382
383 switch (pParam)
384 {
385 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
386 if (pValue.X < m_timestep) pValue.X = m_timestep;
387 if (pValue.Y < m_timestep) pValue.Y = m_timestep;
388 if (pValue.Z < m_timestep) pValue.Z = m_timestep;
389
390 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
391 break;
392 case Vehicle.ANGULAR_MOTOR_DIRECTION:
393 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
394 // Limit requested angular speed to 2 rps= 4 pi rads/sec
395 len = m_angularMotorDirection.Length();
396 if (len > 12.566f)
397 m_angularMotorDirection *= (12.566f / len);
398
399 m_amEfect = 1.0f; // turn it on
400 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
401
402 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
403 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
404 d.BodyEnable(rootPrim.Body);
405 break;
406 case Vehicle.LINEAR_FRICTION_TIMESCALE:
407 if (pValue.X < m_timestep) pValue.X = m_timestep;
408 if (pValue.Y < m_timestep) pValue.Y = m_timestep;
409 if (pValue.Z < m_timestep) pValue.Z = m_timestep;
410 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
411 break;
412 case Vehicle.LINEAR_MOTOR_DIRECTION:
413 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
414 len = m_linearMotorDirection.Length();
415 if (len > 100.0f)
416 m_linearMotorDirection *= (100.0f / len);
417
418 m_lmEfect = 1.0f; // turn it on
419 m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale;
420
421 m_ffactor = 0.0f;
422 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
423 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
424 d.BodyEnable(rootPrim.Body);
425 break;
426 case Vehicle.LINEAR_MOTOR_OFFSET:
427 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
428 len = m_linearMotorOffset.Length();
429 if (len > 100.0f)
430 m_linearMotorOffset *= (100.0f / len);
431 break;
432 case Vehicle.BLOCK_EXIT:
433 m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z);
434 break;
435 }
436 }//end ProcessVectorVehicleParam
437
438 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
439 {
440 switch (pParam)
441 {
442 case Vehicle.REFERENCE_FRAME:
443 // m_referenceFrame = Quaternion.Inverse(pValue);
444 m_referenceFrame = pValue;
445 break;
446 case Vehicle.ROLL_FRAME:
447 m_RollreferenceFrame = pValue;
448 break;
449 }
450 }//end ProcessRotationVehicleParam
451
452 internal void ProcessVehicleFlags(int pParam, bool remove)
453 {
454 if (remove)
455 {
456 m_flags &= ~((VehicleFlag)pParam);
457 }
458 else
459 {
460 m_flags |= (VehicleFlag)pParam;
461 }
462 }//end ProcessVehicleFlags
463
464 internal void ProcessTypeChange(Vehicle pType)
465 {
466 m_lmEfect = 0;
467
468 m_amEfect = 0;
469 m_ffactor = 1f;
470
471 m_linearMotorDirection = Vector3.Zero;
472 m_angularMotorDirection = Vector3.Zero;
473
474 m_BlockingEndPoint = Vector3.Zero;
475 m_RollreferenceFrame = Quaternion.Identity;
476 m_linearMotorOffset = Vector3.Zero;
477
478 m_referenceFrame = Quaternion.Identity;
479
480 // Set Defaults For Type
481 m_type = pType;
482 switch (pType)
483 {
484 case Vehicle.TYPE_NONE:
485 m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
486 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
487 m_linearMotorTimescale = 1000;
488 m_linearMotorDecayTimescale = 120 * m_invtimestep;
489 m_angularMotorTimescale = 1000;
490 m_angularMotorDecayTimescale = 1000 * m_invtimestep;
491 m_VhoverHeight = 0;
492 m_VhoverEfficiency = 1;
493 m_VhoverTimescale = 1000;
494 m_VehicleBuoyancy = 0;
495 m_linearDeflectionEfficiency = 0;
496 m_linearDeflectionTimescale = 1000;
497 m_angularDeflectionEfficiency = 0;
498 m_angularDeflectionTimescale = 1000;
499 m_bankingEfficiency = 0;
500 m_bankingMix = 1;
501 m_bankingTimescale = 1000;
502 m_verticalAttractionEfficiency = 0;
503 m_verticalAttractionTimescale = 1000;
504
505 m_flags = (VehicleFlag)0;
506 break;
507
508 case Vehicle.TYPE_SLED:
509 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
510 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
511 m_linearMotorTimescale = 1000;
512 m_linearMotorDecayTimescale = 120 * m_invtimestep;
513 m_angularMotorTimescale = 1000;
514 m_angularMotorDecayTimescale = 120 * m_invtimestep;
515 m_VhoverHeight = 0;
516 m_VhoverEfficiency = 1;
517 m_VhoverTimescale = 10;
518 m_VehicleBuoyancy = 0;
519 m_linearDeflectionEfficiency = 1;
520 m_linearDeflectionTimescale = 1;
521 m_angularDeflectionEfficiency = 0;
522 m_angularDeflectionTimescale = 10;
523 m_verticalAttractionEfficiency = 1;
524 m_verticalAttractionTimescale = 1000;
525 m_bankingEfficiency = 0;
526 m_bankingMix = 1;
527 m_bankingTimescale = 10;
528 m_flags &=
529 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
530 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
531 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
532 VehicleFlag.LIMIT_ROLL_ONLY |
533 VehicleFlag.LIMIT_MOTOR_UP);
534 break;
535
536 case Vehicle.TYPE_CAR:
537 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
538 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
539 m_linearMotorTimescale = 1;
540 m_linearMotorDecayTimescale = 60 * m_invtimestep;
541 m_angularMotorTimescale = 1;
542 m_angularMotorDecayTimescale = 0.8f * m_invtimestep;
543 m_VhoverHeight = 0;
544 m_VhoverEfficiency = 0;
545 m_VhoverTimescale = 1000;
546 m_VehicleBuoyancy = 0;
547 m_linearDeflectionEfficiency = 1;
548 m_linearDeflectionTimescale = 2;
549 m_angularDeflectionEfficiency = 0;
550 m_angularDeflectionTimescale = 10;
551 m_verticalAttractionEfficiency = 1f;
552 m_verticalAttractionTimescale = 10f;
553 m_bankingEfficiency = -0.2f;
554 m_bankingMix = 1;
555 m_bankingTimescale = 1;
556 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
557 VehicleFlag.HOVER_TERRAIN_ONLY |
558 VehicleFlag.HOVER_GLOBAL_HEIGHT);
559 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
560 VehicleFlag.LIMIT_ROLL_ONLY |
561 VehicleFlag.LIMIT_MOTOR_UP |
562 VehicleFlag.HOVER_UP_ONLY);
563 break;
564 case Vehicle.TYPE_BOAT:
565 m_linearFrictionTimescale = new Vector3(10, 3, 2);
566 m_angularFrictionTimescale = new Vector3(10, 10, 10);
567 m_linearMotorTimescale = 5;
568 m_linearMotorDecayTimescale = 60 * m_invtimestep;
569 m_angularMotorTimescale = 4;
570 m_angularMotorDecayTimescale = 4 * m_invtimestep;
571 m_VhoverHeight = 0;
572 m_VhoverEfficiency = 0.5f;
573 m_VhoverTimescale = 2;
574 m_VehicleBuoyancy = 1;
575 m_linearDeflectionEfficiency = 0.5f;
576 m_linearDeflectionTimescale = 3;
577 m_angularDeflectionEfficiency = 0.5f;
578 m_angularDeflectionTimescale = 5;
579 m_verticalAttractionEfficiency = 0.5f;
580 m_verticalAttractionTimescale = 5f;
581 m_bankingEfficiency = -0.3f;
582 m_bankingMix = 0.8f;
583 m_bankingTimescale = 1;
584 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
585 VehicleFlag.HOVER_GLOBAL_HEIGHT |
586 VehicleFlag.HOVER_UP_ONLY); // |
587// VehicleFlag.LIMIT_ROLL_ONLY);
588 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
589 VehicleFlag.LIMIT_MOTOR_UP |
590 VehicleFlag.HOVER_UP_ONLY | // new sl
591 VehicleFlag.HOVER_WATER_ONLY);
592 break;
593
594 case Vehicle.TYPE_AIRPLANE:
595 m_linearFrictionTimescale = new Vector3(200, 10, 5);
596 m_angularFrictionTimescale = new Vector3(20, 20, 20);
597 m_linearMotorTimescale = 2;
598 m_linearMotorDecayTimescale = 60 * m_invtimestep;
599 m_angularMotorTimescale = 4;
600 m_angularMotorDecayTimescale = 8 * m_invtimestep;
601 m_VhoverHeight = 0;
602 m_VhoverEfficiency = 0.5f;
603 m_VhoverTimescale = 1000;
604 m_VehicleBuoyancy = 0;
605 m_linearDeflectionEfficiency = 0.5f;
606 m_linearDeflectionTimescale = 0.5f;
607 m_angularDeflectionEfficiency = 1;
608 m_angularDeflectionTimescale = 2;
609 m_verticalAttractionEfficiency = 0.9f;
610 m_verticalAttractionTimescale = 2f;
611 m_bankingEfficiency = 1;
612 m_bankingMix = 0.7f;
613 m_bankingTimescale = 2;
614 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
615 VehicleFlag.HOVER_TERRAIN_ONLY |
616 VehicleFlag.HOVER_GLOBAL_HEIGHT |
617 VehicleFlag.HOVER_UP_ONLY |
618 VehicleFlag.NO_DEFLECTION_UP |
619 VehicleFlag.LIMIT_MOTOR_UP);
620 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
621 break;
622
623 case Vehicle.TYPE_BALLOON:
624 m_linearFrictionTimescale = new Vector3(5, 5, 5);
625 m_angularFrictionTimescale = new Vector3(10, 10, 10);
626 m_linearMotorTimescale = 5;
627 m_linearMotorDecayTimescale = 60 * m_invtimestep;
628 m_angularMotorTimescale = 6;
629 m_angularMotorDecayTimescale = 10 * m_invtimestep;
630 m_VhoverHeight = 5;
631 m_VhoverEfficiency = 0.8f;
632 m_VhoverTimescale = 10;
633 m_VehicleBuoyancy = 1;
634 m_linearDeflectionEfficiency = 0;
635 m_linearDeflectionTimescale = 5 * m_invtimestep;
636 m_angularDeflectionEfficiency = 0;
637 m_angularDeflectionTimescale = 5;
638 m_verticalAttractionEfficiency = 1f;
639 m_verticalAttractionTimescale = 1000f;
640 m_bankingEfficiency = 0;
641 m_bankingMix = 0.7f;
642 m_bankingTimescale = 5;
643 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
644 VehicleFlag.HOVER_TERRAIN_ONLY |
645 VehicleFlag.HOVER_UP_ONLY |
646 VehicleFlag.NO_DEFLECTION_UP |
647 VehicleFlag.LIMIT_MOTOR_UP | //);
648 VehicleFlag.LIMIT_ROLL_ONLY | // new sl
649 VehicleFlag.HOVER_GLOBAL_HEIGHT); // new sl
650
651// m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
652// VehicleFlag.HOVER_GLOBAL_HEIGHT);
653 break;
654
655 }
656 // disable mouse steering
657 m_flags &= ~(VehicleFlag.MOUSELOOK_STEER |
658 VehicleFlag.MOUSELOOK_BANK |
659 VehicleFlag.CAMERA_DECOUPLED);
660
661 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
662 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
663
664 }//end SetDefaultsForType
665
666 internal void Stop()
667 {
668 m_lmEfect = 0;
669 m_lmDecay = 0f;
670 m_amEfect = 0;
671 m_amDecay = 0;
672 m_ffactor = 1f;
673 }
674
675 public static Vector3 Xrot(Quaternion rot)
676 {
677 Vector3 vec;
678 rot.Normalize(); // just in case
679 vec.X = 2 * (rot.X * rot.X + rot.W * rot.W) - 1;
680 vec.Y = 2 * (rot.X * rot.Y + rot.Z * rot.W);
681 vec.Z = 2 * (rot.X * rot.Z - rot.Y * rot.W);
682 return vec;
683 }
684
685 public static Vector3 Zrot(Quaternion rot)
686 {
687 Vector3 vec;
688 rot.Normalize(); // just in case
689 vec.X = 2 * (rot.X * rot.Z + rot.Y * rot.W);
690 vec.Y = 2 * (rot.Y * rot.Z - rot.X * rot.W);
691 vec.Z = 2 * (rot.Z * rot.Z + rot.W * rot.W) - 1;
692
693 return vec;
694 }
695
696 private const float pi = (float)Math.PI;
697 private const float halfpi = 0.5f * (float)Math.PI;
698 private const float twopi = 2.0f * pi;
699
700 public static Vector3 ubRot2Euler(Quaternion rot)
701 {
702 // returns roll in X
703 // pitch in Y
704 // yaw in Z
705 Vector3 vec;
706
707 // assuming rot is normalised
708 // rot.Normalize();
709
710 float zX = rot.X * rot.Z + rot.Y * rot.W;
711
712 if (zX < -0.49999f)
713 {
714 vec.X = 0;
715 vec.Y = -halfpi;
716 vec.Z = (float)(-2d * Math.Atan(rot.X / rot.W));
717 }
718 else if (zX > 0.49999f)
719 {
720 vec.X = 0;
721 vec.Y = halfpi;
722 vec.Z = (float)(2d * Math.Atan(rot.X / rot.W));
723 }
724 else
725 {
726 vec.Y = (float)Math.Asin(2 * zX);
727
728 float sqw = rot.W * rot.W;
729
730 float minuszY = rot.X * rot.W - rot.Y * rot.Z;
731 float zZ = rot.Z * rot.Z + sqw - 0.5f;
732
733 vec.X = (float)Math.Atan2(minuszY, zZ);
734
735 float yX = rot.Z * rot.W - rot.X * rot.Y; //( have negative ?)
736 float yY = rot.X * rot.X + sqw - 0.5f;
737 vec.Z = (float)Math.Atan2(yX, yY);
738 }
739 return vec;
740 }
741
742 public static void GetRollPitch(Quaternion rot, out float roll, out float pitch)
743 {
744 // assuming rot is normalised
745 // rot.Normalize();
746
747 float zX = rot.X * rot.Z + rot.Y * rot.W;
748
749 if (zX < -0.49999f)
750 {
751 roll = 0;
752 pitch = -halfpi;
753 }
754 else if (zX > 0.49999f)
755 {
756 roll = 0;
757 pitch = halfpi;
758 }
759 else
760 {
761 pitch = (float)Math.Asin(2 * zX);
762
763 float minuszY = rot.X * rot.W - rot.Y * rot.Z;
764 float zZ = rot.Z * rot.Z + rot.W * rot.W - 0.5f;
765
766 roll = (float)Math.Atan2(minuszY, zZ);
767 }
768 return ;
769 }
770
771 internal void Step()
772 {
773 IntPtr Body = rootPrim.Body;
774
775 d.Mass dmass;
776 d.BodyGetMass(Body, out dmass);
777
778 d.Quaternion rot = d.BodyGetQuaternion(Body);
779 Quaternion objrotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
780 Quaternion rotq = objrotq; // rotq = rotation of object
781 rotq *= m_referenceFrame; // rotq is now rotation in vehicle reference frame
782 Quaternion irotq = Quaternion.Inverse(rotq);
783
784 d.Vector3 dvtmp;
785 Vector3 tmpV;
786 Vector3 curVel; // velocity in world
787 Vector3 curAngVel; // angular velocity in world
788 Vector3 force = Vector3.Zero; // actually linear aceleration until mult by mass in world frame
789 Vector3 torque = Vector3.Zero;// actually angular aceleration until mult by Inertia in vehicle frame
790 d.Vector3 dtorque = new d.Vector3();
791
792 dvtmp = d.BodyGetLinearVel(Body);
793 curVel.X = dvtmp.X;
794 curVel.Y = dvtmp.Y;
795 curVel.Z = dvtmp.Z;
796 Vector3 curLocalVel = curVel * irotq; // current velocity in local
797
798 dvtmp = d.BodyGetAngularVel(Body);
799 curAngVel.X = dvtmp.X;
800 curAngVel.Y = dvtmp.Y;
801 curAngVel.Z = dvtmp.Z;
802 Vector3 curLocalAngVel = curAngVel * irotq; // current angular velocity in local
803
804 float ldampZ = 0;
805
806 bool mousemode = false;
807 bool mousemodebank = false;
808
809 float bankingEfficiency;
810 float verticalAttractionTimescale = m_verticalAttractionTimescale;
811
812 if((m_flags & (VehicleFlag.MOUSELOOK_STEER | VehicleFlag.MOUSELOOK_BANK)) != 0 )
813 {
814 mousemode = true;
815 mousemodebank = (m_flags & VehicleFlag.MOUSELOOK_BANK) != 0;
816 if(mousemodebank)
817 {
818 bankingEfficiency = m_bankingEfficiency;
819 if(verticalAttractionTimescale < 149.9)
820 verticalAttractionTimescale *= 2.0f; // reduce current instability
821 }
822 else
823 bankingEfficiency = 0;
824 }
825 else
826 bankingEfficiency = m_bankingEfficiency;
827
828 // linear motor
829 if (m_lmEfect > 0.01 && m_linearMotorTimescale < 1000)
830 {
831 tmpV = m_linearMotorDirection - curLocalVel; // velocity error
832 tmpV *= m_lmEfect / m_linearMotorTimescale; // error to correct in this timestep
833 tmpV *= rotq; // to world
834
835 if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0)
836 tmpV.Z = 0;
837
838 if (m_linearMotorOffset.X != 0 || m_linearMotorOffset.Y != 0 || m_linearMotorOffset.Z != 0)
839 {
840 // have offset, do it now
841 tmpV *= dmass.mass;
842 d.BodyAddForceAtRelPos(Body, tmpV.X, tmpV.Y, tmpV.Z, m_linearMotorOffset.X, m_linearMotorOffset.Y, m_linearMotorOffset.Z);
843 }
844 else
845 {
846 force.X += tmpV.X;
847 force.Y += tmpV.Y;
848 force.Z += tmpV.Z;
849 }
850
851 m_lmEfect *= m_lmDecay;
852// m_ffactor = 0.01f + 1e-4f * curVel.LengthSquared();
853 m_ffactor = 0.0f;
854 }
855 else
856 {
857 m_lmEfect = 0;
858 m_ffactor = 1f;
859 }
860
861 // hover
862 if (m_VhoverTimescale < 300 && rootPrim.prim_geom != IntPtr.Zero)
863 {
864 // d.Vector3 pos = d.BodyGetPosition(Body);
865 d.Vector3 pos = d.GeomGetPosition(rootPrim.prim_geom);
866 pos.Z -= 0.21f; // minor offset that seems to be always there in sl
867
868 float t = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
869 float perr;
870
871 // default to global but don't go underground
872 perr = m_VhoverHeight - pos.Z;
873
874 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == 0)
875 {
876 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
877 {
878 perr += _pParentScene.GetWaterLevel();
879 }
880 else if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
881 {
882 perr += t;
883 }
884 else
885 {
886 float w = _pParentScene.GetWaterLevel();
887 if (t > w)
888 perr += t;
889 else
890 perr += w;
891 }
892 }
893 else if (t > m_VhoverHeight)
894 perr = t - pos.Z; ;
895
896 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) == 0 || perr > -0.1)
897 {
898 ldampZ = m_VhoverEfficiency * m_invtimestep;
899
900 perr *= (1.0f + ldampZ) / m_VhoverTimescale;
901
902 // force.Z += perr - curVel.Z * tmp;
903 force.Z += perr;
904 ldampZ *= -curVel.Z;
905
906 force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
907 }
908 else // no buoyancy
909 force.Z += _pParentScene.gravityz;
910 }
911 else
912 {
913 // default gravity and Buoyancy
914 force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
915 }
916
917 // linear deflection
918 if (m_linearDeflectionEfficiency > 0)
919 {
920 float len = curVel.Length();
921 if (len > 0.01) // if moving
922 {
923 Vector3 atAxis;
924 atAxis = Xrot(rotq); // where are we pointing to
925 atAxis *= len; // make it same size as world velocity vector
926
927 tmpV = -atAxis; // oposite direction
928 atAxis -= curVel; // error to one direction
929 len = atAxis.LengthSquared();
930
931 tmpV -= curVel; // error to oposite
932 float lens = tmpV.LengthSquared();
933
934 if (len > 0.01 || lens > 0.01) // do nothing if close enougth
935 {
936 if (len < lens)
937 tmpV = atAxis;
938
939 tmpV *= (m_linearDeflectionEfficiency / m_linearDeflectionTimescale); // error to correct in this timestep
940 force.X += tmpV.X;
941 force.Y += tmpV.Y;
942 if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) == 0)
943 force.Z += tmpV.Z;
944 }
945 }
946 }
947
948 // linear friction/damping
949 if (curLocalVel.X != 0 || curLocalVel.Y != 0 || curLocalVel.Z != 0)
950 {
951 tmpV.X = -curLocalVel.X / m_linearFrictionTimescale.X;
952 tmpV.Y = -curLocalVel.Y / m_linearFrictionTimescale.Y;
953 tmpV.Z = -curLocalVel.Z / m_linearFrictionTimescale.Z;
954 tmpV *= rotq; // to world
955
956 if(ldampZ != 0 && Math.Abs(ldampZ) > Math.Abs(tmpV.Z))
957 tmpV.Z = ldampZ;
958 force.X += tmpV.X;
959 force.Y += tmpV.Y;
960 force.Z += tmpV.Z;
961 }
962
963 // vertical atractor
964 if (verticalAttractionTimescale < 300)
965 {
966 float roll;
967 float pitch;
968
969 float ftmp = m_invtimestep / verticalAttractionTimescale / verticalAttractionTimescale;
970
971 float ftmp2;
972 ftmp2 = 0.5f * m_verticalAttractionEfficiency * m_invtimestep;
973 m_amdampX = ftmp2;
974
975 m_ampwr = 1.0f - 0.8f * m_verticalAttractionEfficiency;
976
977 GetRollPitch(irotq, out roll, out pitch);
978
979 if (roll > halfpi)
980 roll = pi - roll;
981 else if (roll < -halfpi)
982 roll = -pi - roll;
983
984 float effroll = pitch / halfpi;
985 effroll *= effroll;
986 effroll = 1 - effroll;
987 effroll *= roll;
988
989 torque.X += effroll * ftmp;
990
991 if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) == 0)
992 {
993 float effpitch = roll / halfpi;
994 effpitch *= effpitch;
995 effpitch = 1 - effpitch;
996 effpitch *= pitch;
997
998 torque.Y += effpitch * ftmp;
999 }
1000
1001 if (bankingEfficiency != 0 && Math.Abs(effroll) > 0.01)
1002 {
1003
1004 float broll = effroll;
1005 /*
1006 if (broll > halfpi)
1007 broll = pi - broll;
1008 else if (broll < -halfpi)
1009 broll = -pi - broll;
1010 */
1011 broll *= m_bankingEfficiency;
1012 if (m_bankingMix != 0)
1013 {
1014 float vfact = Math.Abs(curLocalVel.X) / 10.0f;
1015 if (vfact > 1.0f) vfact = 1.0f;
1016
1017 if (curLocalVel.X >= 0)
1018 broll *= (1 + (vfact - 1) * m_bankingMix);
1019 else
1020 broll *= -(1 + (vfact - 1) * m_bankingMix);
1021 }
1022 // make z rot be in world Z not local as seems to be in sl
1023
1024 broll = broll / m_bankingTimescale;
1025
1026
1027 tmpV = Zrot(irotq);
1028 tmpV *= broll;
1029
1030 torque.X += tmpV.X;
1031 torque.Y += tmpV.Y;
1032 torque.Z += tmpV.Z;
1033
1034 m_amdampZ = Math.Abs(m_bankingEfficiency) / m_bankingTimescale;
1035 m_amdampY = m_amdampZ;
1036
1037 }
1038 else
1039 {
1040 m_amdampZ = 1 / m_angularFrictionTimescale.Z;
1041 m_amdampY = m_amdampX;
1042 }
1043 }
1044 else
1045 {
1046 m_ampwr = 1.0f;
1047 m_amdampX = 1 / m_angularFrictionTimescale.X;
1048 m_amdampY = 1 / m_angularFrictionTimescale.Y;
1049 m_amdampZ = 1 / m_angularFrictionTimescale.Z;
1050 }
1051
1052 if(mousemode)
1053 {
1054 CameraData cam = rootPrim.TryGetCameraData();
1055 if(cam.Valid && cam.MouseLook)
1056 {
1057 Vector3 dirv = cam.CameraAtAxis * irotq;
1058
1059 float invamts = 1.0f/m_angularMotorTimescale;
1060 float tmp;
1061
1062 // get out of x == 0 plane
1063 if(Math.Abs(dirv.X) < 0.001f)
1064 dirv.X = 0.001f;
1065
1066 if (Math.Abs(dirv.Z) > 0.01)
1067 {
1068 tmp = -(float)Math.Atan2(dirv.Z, dirv.X) * m_angularMotorDirection.Y;
1069 if(tmp < -4f)
1070 tmp = -4f;
1071 else if(tmp > 4f)
1072 tmp = 4f;
1073 torque.Y += (tmp - curLocalAngVel.Y) * invamts;
1074 torque.Y -= curLocalAngVel.Y * m_amdampY;
1075 }
1076 else
1077 torque.Y -= curLocalAngVel.Y * m_invtimestep;
1078
1079 if (Math.Abs(dirv.Y) > 0.01)
1080 {
1081 if(mousemodebank)
1082 {
1083 tmp = -(float)Math.Atan2(dirv.Y, dirv.X) * m_angularMotorDirection.X;
1084 if(tmp < -4f)
1085 tmp = -4f;
1086 else if(tmp > 4f)
1087 tmp = 4f;
1088 torque.X += (tmp - curLocalAngVel.X) * invamts;
1089 }
1090 else
1091 {
1092 tmp = (float)Math.Atan2(dirv.Y, dirv.X) * m_angularMotorDirection.Z;
1093 tmp *= invamts;
1094 if(tmp < -4f)
1095 tmp = -4f;
1096 else if(tmp > 4f)
1097 tmp = 4f;
1098 torque.Z += (tmp - curLocalAngVel.Z) * invamts;
1099 }
1100 torque.X -= curLocalAngVel.X * m_amdampX;
1101 torque.Z -= curLocalAngVel.Z * m_amdampZ;
1102 }
1103 else
1104 {
1105 if(mousemodebank)
1106 torque.X -= curLocalAngVel.X * m_invtimestep;
1107 else
1108 torque.Z -= curLocalAngVel.Z * m_invtimestep;
1109 }
1110 }
1111 else
1112 {
1113 if (curLocalAngVel.X != 0 || curLocalAngVel.Y != 0 || curLocalAngVel.Z != 0)
1114 {
1115 torque.X -= curLocalAngVel.X * 10f;
1116 torque.Y -= curLocalAngVel.Y * 10f;
1117 torque.Z -= curLocalAngVel.Z * 10f;
1118 }
1119 }
1120 }
1121 else
1122 {
1123 // angular motor
1124 if (m_amEfect > 0.01 && m_angularMotorTimescale < 1000)
1125 {
1126 tmpV = m_angularMotorDirection - curLocalAngVel; // velocity error
1127 tmpV *= m_amEfect / m_angularMotorTimescale; // error to correct in this timestep
1128 torque.X += tmpV.X * m_ampwr;
1129 torque.Y += tmpV.Y * m_ampwr;
1130 torque.Z += tmpV.Z;
1131
1132 m_amEfect *= m_amDecay;
1133 }
1134 else
1135 m_amEfect = 0;
1136
1137 // angular deflection
1138 if (m_angularDeflectionEfficiency > 0)
1139 {
1140 Vector3 dirv;
1141
1142 if (curLocalVel.X > 0.01f)
1143 dirv = curLocalVel;
1144 else if (curLocalVel.X < -0.01f)
1145 // use oposite
1146 dirv = -curLocalVel;
1147 else
1148 {
1149 // make it fall into small positive x case
1150 dirv.X = 0.01f;
1151 dirv.Y = curLocalVel.Y;
1152 dirv.Z = curLocalVel.Z;
1153 }
1154
1155 float ftmp = m_angularDeflectionEfficiency / m_angularDeflectionTimescale;
1156
1157 if (Math.Abs(dirv.Z) > 0.01)
1158 {
1159 torque.Y += - (float)Math.Atan2(dirv.Z, dirv.X) * ftmp;
1160 }
1161
1162 if (Math.Abs(dirv.Y) > 0.01)
1163 {
1164 torque.Z += (float)Math.Atan2(dirv.Y, dirv.X) * ftmp;
1165 }
1166 }
1167
1168 if (curLocalAngVel.X != 0 || curLocalAngVel.Y != 0 || curLocalAngVel.Z != 0)
1169 {
1170 torque.X -= curLocalAngVel.X * m_amdampX;
1171 torque.Y -= curLocalAngVel.Y * m_amdampY;
1172 torque.Z -= curLocalAngVel.Z * m_amdampZ;
1173 }
1174 }
1175
1176 force *= dmass.mass;
1177
1178 force += rootPrim.m_force;
1179 force += rootPrim.m_forceacc;
1180 rootPrim.m_forceacc = Vector3.Zero;
1181
1182 if (force.X != 0 || force.Y != 0 || force.Z != 0)
1183 {
1184 d.BodyAddForce(Body, force.X, force.Y, force.Z);
1185 }
1186
1187 if (torque.X != 0 || torque.Y != 0 || torque.Z != 0)
1188 {
1189 torque *= m_referenceFrame; // to object frame
1190 dtorque.X = torque.X ;
1191 dtorque.Y = torque.Y;
1192 dtorque.Z = torque.Z;
1193
1194 d.MultiplyM3V3(out dvtmp, ref dmass.I, ref dtorque);
1195 d.BodyAddRelTorque(Body, dvtmp.X, dvtmp.Y, dvtmp.Z); // add torque in object frame
1196 }
1197
1198 torque = rootPrim.m_torque;
1199 torque += rootPrim.m_angularForceacc;
1200 rootPrim.m_angularForceacc = Vector3.Zero;
1201 if (torque.X != 0 || torque.Y != 0 || torque.Z != 0)
1202 d.BodyAddTorque(Body,torque.X, torque.Y, torque.Z);
1203 }
1204 }
1205}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs
new file mode 100644
index 0000000..5465035
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs
@@ -0,0 +1,946 @@
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 bool isTooSmall;
66 public MeshState meshState;
67 public UUID? assetID;
68 public meshWorkerCmnds comand;
69 }
70
71 public class ODEMeshWorker
72 {
73 private ILog m_log;
74 private ODEScene m_scene;
75 private IMesher m_mesher;
76
77 public bool meshSculptedPrim = true;
78 public float meshSculptLOD = 32;
79 public float MeshSculptphysicalLOD = 32;
80 public float MinSizeToMeshmerize = 0.1f;
81
82 private OpenSim.Framework.BlockingQueue<ODEPhysRepData> workQueue = new OpenSim.Framework.BlockingQueue<ODEPhysRepData>();
83 private bool m_running;
84
85 private Thread m_thread;
86
87 public ODEMeshWorker(ODEScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig)
88 {
89 m_scene = pScene;
90 m_log = pLog;
91 m_mesher = pMesher;
92
93 if (pConfig != null)
94 {
95 meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
96 meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
97 MinSizeToMeshmerize = pConfig.GetFloat("mesh_min_size", MinSizeToMeshmerize);
98 MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
99 }
100 m_running = true;
101 m_thread = new Thread(DoWork);
102 m_thread.Name = "OdeMeshWorker";
103 m_thread.Start();
104 }
105
106 private void DoWork()
107 {
108 m_mesher.ExpireFileCache();
109
110 while(m_running)
111 {
112 ODEPhysRepData nextRep = workQueue.Dequeue();
113 if(!m_running)
114 return;
115 if (nextRep == null)
116 continue;
117 if (m_scene.haveActor(nextRep.actor))
118 {
119 switch (nextRep.comand)
120 {
121 case meshWorkerCmnds.changefull:
122 case meshWorkerCmnds.changeshapetype:
123 case meshWorkerCmnds.changesize:
124 GetMesh(nextRep);
125 if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
126 m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
127 break;
128 case meshWorkerCmnds.getmesh:
129 DoRepDataGetMesh(nextRep);
130 break;
131 }
132 }
133 }
134 }
135
136 public void Stop()
137 {
138 try
139 {
140 m_thread.Abort();
141 workQueue.Clear();
142 }
143 catch
144 {
145 }
146 }
147
148 public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
149 Vector3 size, byte shapetype)
150 {
151 ODEPhysRepData repData = new ODEPhysRepData();
152 repData.actor = actor;
153 repData.pbs = pbs;
154 repData.size = size;
155 repData.shapetype = shapetype;
156
157 CheckMesh(repData);
158 CalcVolumeData(repData);
159 m_scene.AddChange(actor, changes.PhysRepData, repData);
160 return;
161 }
162
163 public ODEPhysRepData NewActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
164 Vector3 size, byte shapetype)
165 {
166 ODEPhysRepData repData = new ODEPhysRepData();
167 repData.actor = actor;
168 repData.pbs = pbs;
169 repData.size = size;
170 repData.shapetype = shapetype;
171
172 CheckMesh(repData);
173 CalcVolumeData(repData);
174 m_scene.AddChange(actor, changes.AddPhysRep, repData);
175 return repData;
176 }
177
178 public void RequestMesh(ODEPhysRepData repData)
179 {
180 repData.mesh = null;
181
182 if (repData.meshState == MeshState.needAsset)
183 {
184 PrimitiveBaseShape pbs = repData.pbs;
185
186 // check if we got outdated
187
188 if (!pbs.SculptEntry || pbs.SculptTexture == UUID.Zero)
189 {
190 repData.meshState = MeshState.noNeed;
191 return;
192 }
193
194 repData.assetID = pbs.SculptTexture;
195 repData.meshState = MeshState.loadingAsset;
196
197 repData.comand = meshWorkerCmnds.getmesh;
198 workQueue.Enqueue(repData);
199 }
200 }
201
202 // creates and prepares a mesh to use and calls parameters estimation
203 public bool CreateActorPhysRep(ODEPhysRepData repData)
204 {
205 IMesh mesh = repData.mesh;
206
207 if (mesh != null)
208 {
209 IntPtr vertices, indices;
210 int vertexCount, indexCount;
211 int vertexStride, triStride;
212
213 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
214 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
215
216 if (vertexCount == 0 || indexCount == 0)
217 {
218 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}",
219 repData.actor.Name, repData.pbs.SculptTexture.ToString());
220 repData.meshState = MeshState.MeshFailed;
221 repData.hasOBB = false;
222 repData.mesh = null;
223 m_scene.mesher.ReleaseMesh(mesh);
224 }
225 else
226 {
227 repData.OBBOffset = mesh.GetCentroid();
228 repData.OBB = mesh.GetOBB();
229 repData.hasOBB = true;
230 mesh.releaseSourceMeshData();
231 }
232 }
233 CalcVolumeData(repData);
234 return true;
235 }
236
237 public void AssetLoaded(ODEPhysRepData repData)
238 {
239 if (m_scene.haveActor(repData.actor))
240 {
241 if (needsMeshing(repData)) // no need for pbs now?
242 {
243 repData.comand = meshWorkerCmnds.changefull;
244 workQueue.Enqueue(repData);
245 }
246 }
247 else
248 repData.pbs.SculptData = Utils.EmptyBytes;
249 }
250
251 public void DoRepDataGetMesh(ODEPhysRepData repData)
252 {
253 if (!repData.pbs.SculptEntry)
254 return;
255
256 if (repData.meshState != MeshState.loadingAsset)
257 return;
258
259 if (repData.assetID == null || repData.assetID == UUID.Zero)
260 return;
261
262 if (repData.assetID != repData.pbs.SculptTexture)
263 return;
264
265 // check if it is in cache
266 GetMesh(repData);
267 if (repData.meshState != MeshState.needAsset)
268 {
269 CreateActorPhysRep(repData);
270 m_scene.AddChange(repData.actor, changes.PhysRepData, repData);
271 return;
272 }
273
274 RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
275 if (assetProvider == null)
276 return;
277 ODEAssetRequest asr = new ODEAssetRequest(this, assetProvider, repData, m_log);
278 }
279
280
281 /// <summary>
282 /// Routine to figure out if we need to mesh this prim with our mesher
283 /// </summary>
284 /// <param name="pbs"></param>
285 /// <returns></returns>
286 public bool needsMeshing(ODEPhysRepData repData)
287 {
288 PrimitiveBaseShape pbs = repData.pbs;
289 // check sculpts or meshs
290
291 Vector3 scale = pbs.Scale;
292 if(scale.X <= MinSizeToMeshmerize &&
293 scale.Y <= MinSizeToMeshmerize &&
294 scale.Z <= MinSizeToMeshmerize)
295 {
296 repData.isTooSmall = true;
297 return false;
298 }
299
300 if (pbs.SculptEntry)
301 {
302 if (meshSculptedPrim)
303 return true;
304
305 if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
306 return true;
307
308 return false;
309 }
310
311 // convex shapes have no holes
312 ushort profilehollow = pbs.ProfileHollow;
313 if(repData.shapetype == 2)
314 profilehollow = 0;
315
316 // 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
317
318 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
319 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
320 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
321 {
322
323 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
324 && profilehollow == 0
325 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
326 && pbs.PathBegin == 0 && pbs.PathEnd == 0
327 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
328 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
329 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
330 {
331 return false;
332 }
333 }
334
335 // following code doesn't give meshs to boxes and spheres ever
336 // and it's odd.. so for now just return true if asked to force meshs
337 // hopefully mesher will fail if doesn't suport so things still get basic boxes
338
339 int iPropertiesNotSupportedDefault = 0;
340
341 if (profilehollow != 0)
342 iPropertiesNotSupportedDefault++;
343
344 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
345 iPropertiesNotSupportedDefault++;
346
347 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
348 iPropertiesNotSupportedDefault++;
349
350 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
351 iPropertiesNotSupportedDefault++;
352
353 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
354 iPropertiesNotSupportedDefault++;
355
356 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
357 iPropertiesNotSupportedDefault++;
358
359 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
360 iPropertiesNotSupportedDefault++;
361
362 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))
363 iPropertiesNotSupportedDefault++;
364
365 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
366 iPropertiesNotSupportedDefault++;
367
368 // test for torus
369 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
370 {
371 if (pbs.PathCurve == (byte)Extrusion.Curve1)
372 {
373 iPropertiesNotSupportedDefault++;
374 }
375 }
376 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
377 {
378 if (pbs.PathCurve == (byte)Extrusion.Straight)
379 {
380 iPropertiesNotSupportedDefault++;
381 }
382
383 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
384 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
385 {
386 iPropertiesNotSupportedDefault++;
387 }
388 }
389 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
390 {
391 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
392 {
393 iPropertiesNotSupportedDefault++;
394 }
395 }
396 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
397 {
398 if (pbs.PathCurve == (byte)Extrusion.Straight)
399 {
400 iPropertiesNotSupportedDefault++;
401 }
402 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
403 {
404 iPropertiesNotSupportedDefault++;
405 }
406 }
407
408 if (iPropertiesNotSupportedDefault == 0)
409 {
410 return false;
411 }
412 return true;
413 }
414
415 // see if we need a mesh and if so if we have a cached one
416 // called with a new repData
417 public void CheckMesh(ODEPhysRepData repData)
418 {
419 PhysicsActor actor = repData.actor;
420 PrimitiveBaseShape pbs = repData.pbs;
421
422 if (!needsMeshing(repData))
423 {
424 repData.meshState = MeshState.noNeed;
425 repData.hasOBB = false;
426 return;
427 }
428
429 IMesh mesh = null;
430
431 Vector3 size = repData.size;
432
433 int clod = (int)LevelOfDetail.High;
434 byte shapetype = repData.shapetype;
435 bool convex = shapetype == 2;
436
437 mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
438
439 if (mesh == null)
440 {
441 if (pbs.SculptEntry)
442 {
443 if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero)
444 {
445 repData.assetID = pbs.SculptTexture;
446 repData.meshState = MeshState.needAsset;
447 }
448 else
449 repData.meshState = MeshState.MeshFailed;
450
451 return;
452 }
453 else
454 {
455 repData.meshState = MeshState.needMesh;
456 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
457 if (mesh == null)
458 {
459 repData.meshState = MeshState.MeshFailed;
460 return;
461 }
462 }
463 }
464
465 repData.meshState = MeshState.AssetOK;
466 repData.mesh = mesh;
467 repData.OBB = mesh.GetOBB();
468 repData.OBBOffset = mesh.GetCentroid();
469 repData.hasOBB = true;
470
471 if (pbs.SculptEntry)
472 {
473 repData.assetID = pbs.SculptTexture;
474 }
475
476 pbs.SculptData = Utils.EmptyBytes;
477 return ;
478 }
479
480 public void GetMesh(ODEPhysRepData repData)
481 {
482 PhysicsActor actor = repData.actor;
483
484 PrimitiveBaseShape pbs = repData.pbs;
485
486 repData.mesh = null;
487 repData.hasOBB = false;
488
489 if (!needsMeshing(repData))
490 {
491 repData.meshState = MeshState.noNeed;
492 return;
493 }
494
495 if (repData.meshState == MeshState.MeshFailed)
496 return;
497
498 if (pbs.SculptEntry)
499 {
500 if (repData.meshState == MeshState.AssetFailed)
501 {
502 if (pbs.SculptTexture == repData.assetID)
503 return;
504 }
505 }
506
507 repData.meshState = MeshState.noNeed;
508
509 IMesh mesh = null;
510 Vector3 size = repData.size;
511 byte shapetype = repData.shapetype;
512
513 bool convex;
514 int clod = (int)LevelOfDetail.High;
515 if (shapetype == 0)
516 convex = false;
517 else
518 {
519 convex = true;
520 if (pbs.SculptType != (byte)SculptType.Mesh)
521 clod = (int)LevelOfDetail.Low;
522 }
523
524 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
525
526 if (mesh == null)
527 {
528 if (pbs.SculptEntry)
529 {
530 if (pbs.SculptTexture == UUID.Zero)
531 return;
532
533 repData.assetID = pbs.SculptTexture;
534
535 if (pbs.SculptData == null || pbs.SculptData.Length == 0)
536 {
537 repData.meshState = MeshState.needAsset;
538 return;
539 }
540 }
541 }
542
543 repData.mesh = mesh;
544 repData.pbs.SculptData = Utils.EmptyBytes;
545
546 if (mesh == null)
547 {
548 if (pbs.SculptEntry)
549 repData.meshState = MeshState.AssetFailed;
550 else
551 repData.meshState = MeshState.MeshFailed;
552
553 return;
554 }
555
556 repData.meshState = MeshState.AssetOK;
557
558 return;
559 }
560
561 private void CalculateBasicPrimVolume(ODEPhysRepData repData)
562 {
563 Vector3 _size = repData.size;
564
565 float volume = _size.X * _size.Y * _size.Z; // default
566 if(repData.isTooSmall)
567 {
568 repData.volume = volume;
569 return;
570 }
571
572 PrimitiveBaseShape _pbs = repData.pbs;
573 float tmp;
574
575 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
576 float hollowVolume = hollowAmount * hollowAmount;
577
578 switch (_pbs.ProfileShape)
579 {
580 case ProfileShape.Square:
581 // default box
582
583 if (_pbs.PathCurve == (byte)Extrusion.Straight)
584 {
585 if (hollowAmount > 0.0)
586 {
587 switch (_pbs.HollowShape)
588 {
589 case HollowShape.Square:
590 case HollowShape.Same:
591 break;
592
593 case HollowShape.Circle:
594
595 hollowVolume *= 0.78539816339f;
596 break;
597
598 case HollowShape.Triangle:
599
600 hollowVolume *= (0.5f * .5f);
601 break;
602
603 default:
604 hollowVolume = 0;
605 break;
606 }
607 volume *= (1.0f - hollowVolume);
608 }
609 }
610
611 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
612 {
613 //a tube
614
615 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
616 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
617 volume -= volume * tmp * tmp;
618
619 if (hollowAmount > 0.0)
620 {
621 hollowVolume *= hollowAmount;
622
623 switch (_pbs.HollowShape)
624 {
625 case HollowShape.Square:
626 case HollowShape.Same:
627 break;
628
629 case HollowShape.Circle:
630 hollowVolume *= 0.78539816339f;
631 break;
632
633 case HollowShape.Triangle:
634 hollowVolume *= 0.5f * 0.5f;
635 break;
636 default:
637 hollowVolume = 0;
638 break;
639 }
640 volume *= (1.0f - hollowVolume);
641 }
642 }
643
644 break;
645
646 case ProfileShape.Circle:
647
648 if (_pbs.PathCurve == (byte)Extrusion.Straight)
649 {
650 volume *= 0.78539816339f; // elipse base
651
652 if (hollowAmount > 0.0)
653 {
654 switch (_pbs.HollowShape)
655 {
656 case HollowShape.Same:
657 case HollowShape.Circle:
658 break;
659
660 case HollowShape.Square:
661 hollowVolume *= 0.5f * 2.5984480504799f;
662 break;
663
664 case HollowShape.Triangle:
665 hollowVolume *= .5f * 1.27323954473516f;
666 break;
667
668 default:
669 hollowVolume = 0;
670 break;
671 }
672 volume *= (1.0f - hollowVolume);
673 }
674 }
675
676 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
677 {
678 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
679 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
680 volume *= (1.0f - tmp * tmp);
681
682 if (hollowAmount > 0.0)
683 {
684
685 // calculate the hollow volume by it's shape compared to the prim shape
686 hollowVolume *= hollowAmount;
687
688 switch (_pbs.HollowShape)
689 {
690 case HollowShape.Same:
691 case HollowShape.Circle:
692 break;
693
694 case HollowShape.Square:
695 hollowVolume *= 0.5f * 2.5984480504799f;
696 break;
697
698 case HollowShape.Triangle:
699 hollowVolume *= .5f * 1.27323954473516f;
700 break;
701
702 default:
703 hollowVolume = 0;
704 break;
705 }
706 volume *= (1.0f - hollowVolume);
707 }
708 }
709 break;
710
711 case ProfileShape.HalfCircle:
712 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
713 {
714 volume *= 0.5236f;
715
716 if (hollowAmount > 0.0)
717 {
718 hollowVolume *= hollowAmount;
719
720 switch (_pbs.HollowShape)
721 {
722 case HollowShape.Circle:
723 case HollowShape.Triangle: // diference in sl is minor and odd
724 case HollowShape.Same:
725 break;
726
727 case HollowShape.Square:
728 hollowVolume *= 0.909f;
729 break;
730
731 // case HollowShape.Triangle:
732 // hollowVolume *= .827f;
733 // break;
734 default:
735 hollowVolume = 0;
736 break;
737 }
738 volume *= (1.0f - hollowVolume);
739 }
740
741 }
742 break;
743
744 case ProfileShape.EquilateralTriangle:
745
746 if (_pbs.PathCurve == (byte)Extrusion.Straight)
747 {
748 volume *= 0.32475953f;
749
750 if (hollowAmount > 0.0)
751 {
752
753 // calculate the hollow volume by it's shape compared to the prim shape
754 switch (_pbs.HollowShape)
755 {
756 case HollowShape.Same:
757 case HollowShape.Triangle:
758 hollowVolume *= .25f;
759 break;
760
761 case HollowShape.Square:
762 hollowVolume *= 0.499849f * 3.07920140172638f;
763 break;
764
765 case HollowShape.Circle:
766 // Hollow shape is a perfect cyllinder in respect to the cube's scale
767 // Cyllinder hollow volume calculation
768
769 hollowVolume *= 0.1963495f * 3.07920140172638f;
770 break;
771
772 default:
773 hollowVolume = 0;
774 break;
775 }
776 volume *= (1.0f - hollowVolume);
777 }
778 }
779 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
780 {
781 volume *= 0.32475953f;
782 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
783 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
784 volume *= (1.0f - tmp * tmp);
785
786 if (hollowAmount > 0.0)
787 {
788
789 hollowVolume *= hollowAmount;
790
791 switch (_pbs.HollowShape)
792 {
793 case HollowShape.Same:
794 case HollowShape.Triangle:
795 hollowVolume *= .25f;
796 break;
797
798 case HollowShape.Square:
799 hollowVolume *= 0.499849f * 3.07920140172638f;
800 break;
801
802 case HollowShape.Circle:
803
804 hollowVolume *= 0.1963495f * 3.07920140172638f;
805 break;
806
807 default:
808 hollowVolume = 0;
809 break;
810 }
811 volume *= (1.0f - hollowVolume);
812 }
813 }
814 break;
815
816 default:
817 break;
818 }
819
820 float taperX1;
821 float taperY1;
822 float taperX;
823 float taperY;
824 float pathBegin;
825 float pathEnd;
826 float profileBegin;
827 float profileEnd;
828
829 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
830 {
831 taperX1 = _pbs.PathScaleX * 0.01f;
832 if (taperX1 > 1.0f)
833 taperX1 = 2.0f - taperX1;
834 taperX = 1.0f - taperX1;
835
836 taperY1 = _pbs.PathScaleY * 0.01f;
837 if (taperY1 > 1.0f)
838 taperY1 = 2.0f - taperY1;
839 taperY = 1.0f - taperY1;
840 }
841 else
842 {
843 taperX = _pbs.PathTaperX * 0.01f;
844 if (taperX < 0.0f)
845 taperX = -taperX;
846 taperX1 = 1.0f - taperX;
847
848 taperY = _pbs.PathTaperY * 0.01f;
849 if (taperY < 0.0f)
850 taperY = -taperY;
851 taperY1 = 1.0f - taperY;
852 }
853
854 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
855
856 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
857 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
858 volume *= (pathEnd - pathBegin);
859
860 // this is crude aproximation
861 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
862 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
863 volume *= (profileEnd - profileBegin);
864
865 repData.volume = volume;
866 }
867
868 private void CalcVolumeData(ODEPhysRepData repData)
869 {
870 if (repData.hasOBB)
871 {
872 Vector3 OBB = repData.OBB;
873 }
874 else
875 {
876 Vector3 OBB = repData.size;
877 OBB.X *= 0.5f;
878 OBB.Y *= 0.5f;
879 OBB.Z *= 0.5f;
880
881 repData.OBB = OBB;
882 repData.OBBOffset = Vector3.Zero;
883 }
884
885 CalculateBasicPrimVolume(repData);
886 }
887 }
888
889 public class ODEAssetRequest
890 {
891 ODEMeshWorker m_worker;
892 private ILog m_log;
893 ODEPhysRepData repData;
894
895 public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
896 ODEPhysRepData pRepData, ILog plog)
897 {
898 m_worker = pWorker;
899 m_log = plog;
900 repData = pRepData;
901
902 repData.meshState = MeshState.AssetFailed;
903 if (provider == null)
904 return;
905
906 if (repData.assetID == null)
907 return;
908
909 UUID assetID = (UUID) repData.assetID;
910 if (assetID == UUID.Zero)
911 return;
912
913 repData.meshState = MeshState.loadingAsset;
914 provider(assetID, ODEassetReceived);
915 }
916
917 void ODEassetReceived(AssetBase asset)
918 {
919 repData.meshState = MeshState.AssetFailed;
920 if (asset != null)
921 {
922 if (asset.Data != null && asset.Data.Length > 0)
923 {
924 repData.meshState = MeshState.noNeed;
925
926 if (!repData.pbs.SculptEntry)
927 return;
928 if (repData.pbs.SculptTexture != repData.assetID)
929 return;
930
931// repData.pbs.SculptData = new byte[asset.Data.Length];
932// asset.Data.CopyTo(repData.pbs.SculptData,0);
933 repData.pbs.SculptData = asset.Data;
934 repData.meshState = MeshState.AssetOK;
935 m_worker.AssetLoaded(repData);
936 }
937 else
938 m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
939 repData.actor.Name, asset.ID.ToString());
940 }
941 else
942 m_log.WarnFormat("[PHYSICS]: asset provider returned null asset for mesh of prim {0}.",
943 repData.actor.Name);
944 }
945 }
946}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs
new file mode 100644
index 0000000..4cb1736
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs
@@ -0,0 +1,112 @@
1using System;
2using System.Collections.Generic;
3using System.Reflection;
4using log4net;
5using Nini.Config;
6using Mono.Addins;
7using OdeAPI;
8using OpenSim.Framework;
9using OpenSim.Region.Framework.Scenes;
10using OpenSim.Region.Framework.Interfaces;
11
12namespace OpenSim.Region.PhysicsModule.ubOde
13{
14 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ubODEPhysicsScene")]
15 class ubOdeModule : INonSharedRegionModule
16 {
17 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
18
19 private static Dictionary<Scene, ODEScene> m_scenes = new Dictionary<Scene, ODEScene>();
20 private bool m_Enabled = false;
21 private IConfigSource m_config;
22 private bool OSOdeLib;
23
24
25 #region INonSharedRegionModule
26
27 public string Name
28 {
29 get { return "ubODE"; }
30 }
31
32 public string Version
33 {
34 get { return "1.0"; }
35 }
36
37 public Type ReplaceableInterface
38 {
39 get { return null; }
40 }
41
42 public void Initialise(IConfigSource source)
43 {
44 IConfig config = source.Configs["Startup"];
45 if (config != null)
46 {
47 string physics = config.GetString("physics", string.Empty);
48 if (physics == Name)
49 {
50 m_config = source;
51 m_Enabled = true;
52
53 if (Util.IsWindows())
54 Util.LoadArchSpecificWindowsDll("ode.dll");
55
56 d.InitODE();
57
58 string ode_config = d.GetConfiguration();
59 if (ode_config != null && ode_config != "")
60 {
61 m_log.InfoFormat("[ubODE] ode library configuration: {0}", ode_config);
62
63 if (ode_config.Contains("ODE_OPENSIM"))
64 {
65 OSOdeLib = true;
66 }
67 }
68 }
69 }
70 }
71
72 public void Close()
73 {
74 }
75
76 public void AddRegion(Scene scene)
77 {
78 if (!m_Enabled)
79 return;
80
81 if(m_scenes.ContainsKey(scene)) // ???
82 return;
83 ODEScene newodescene = new ODEScene(scene, m_config, Name, Version, OSOdeLib);
84 m_scenes[scene] = newodescene;
85 }
86
87 public void RemoveRegion(Scene scene)
88 {
89 if (!m_Enabled)
90 return;
91
92 // a odescene.dispose is called later directly by scene.cs
93 // since it is seen as a module interface
94
95 if(m_scenes.ContainsKey(scene))
96 m_scenes.Remove(scene);
97 }
98
99 public void RegionLoaded(Scene scene)
100 {
101 if (!m_Enabled)
102 return;
103
104 if(m_scenes.ContainsKey(scene))
105 {
106 m_scenes[scene].RegionLoaded();
107 }
108
109 }
110 #endregion
111 }
112}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
new file mode 100644
index 0000000..aa208e2
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
@@ -0,0 +1,4256 @@
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 internal 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_lastVelocity;
85 private Vector3 m_lastposition;
86 private Vector3 m_rotationalVelocity;
87 private Vector3 _size;
88 private Vector3 m_acceleration;
89 private IntPtr Amotor;
90
91 internal Vector3 m_force;
92 internal Vector3 m_forceacc;
93 internal Vector3 m_torque;
94 internal 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 m_body_autodisable_frames;
113 public int m_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 private byte m_fakeShapetype;
169 public bool _zeroFlag;
170 private bool m_lastUpdateSent;
171
172 public IntPtr Body;
173
174 private Vector3 _target_velocity;
175
176 public Vector3 m_OBBOffset;
177 public Vector3 m_OBB;
178 public float primOOBradiusSQ;
179
180 private bool m_hasOBB = true;
181
182 private float m_physCost;
183 private float m_streamCost;
184
185 public d.Mass primdMass; // prim inertia information on it's own referencial
186 private PhysicsInertiaData m_InertiaOverride;
187 float primMass; // prim own mass
188 float primVolume; // prim own volume;
189 float m_mass; // object mass acording to case
190
191 public int givefakepos;
192 private Vector3 fakepos;
193 public int givefakeori;
194 private Quaternion fakeori;
195 private PhysicsInertiaData m_fakeInertiaOverride;
196
197 private int m_eventsubscription;
198 private int m_cureventsubscription;
199 private CollisionEventUpdate CollisionEventsThisFrame = null;
200 private CollisionEventUpdate CollisionVDTCEventsThisFrame = null;
201 private bool SentEmptyCollisionsEvent;
202
203 public volatile bool childPrim;
204
205 public ODEDynamics m_vehicle;
206
207 internal int m_material = (int)Material.Wood;
208 private float mu;
209 private float bounce;
210
211 /// <summary>
212 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
213 /// </summary>
214 public override bool IsPhysical // this is not reliable for internal use
215 {
216 get { return m_fakeisphysical; }
217 set
218 {
219 m_fakeisphysical = value; // we show imediatly to outside that we changed physical
220 // and also to stop imediatly some updates
221 // but real change will only happen in taintprocessing
222
223 if (!value) // Zero the remembered last velocity
224 m_lastVelocity = Vector3.Zero;
225 AddChange(changes.Physical, value);
226 }
227 }
228
229 public override bool IsVolumeDtc
230 {
231 get { return m_fakeisVolumeDetect; }
232 set
233 {
234 m_fakeisVolumeDetect = value;
235 AddChange(changes.VolumeDtc, value);
236 }
237 }
238
239 public override bool Phantom // this is not reliable for internal use
240 {
241 get { return m_fakeisphantom; }
242 set
243 {
244 m_fakeisphantom = value;
245 AddChange(changes.Phantom, value);
246 }
247 }
248
249 public override bool Building // this is not reliable for internal use
250 {
251 get { return m_building; }
252 set
253 {
254// if (value)
255// m_building = true;
256 AddChange(changes.building, value);
257 }
258 }
259
260 public override void getContactData(ref ContactData cdata)
261 {
262 cdata.mu = mu;
263 cdata.bounce = bounce;
264
265 // cdata.softcolide = m_softcolide;
266 cdata.softcolide = false;
267
268 if (m_isphysical)
269 {
270 ODEDynamics veh;
271 if (_parent != null)
272 veh = ((OdePrim)_parent).m_vehicle;
273 else
274 veh = m_vehicle;
275
276 if (veh != null && veh.Type != Vehicle.TYPE_NONE)
277 cdata.mu *= veh.FrictionFactor;
278// cdata.mu *= 0;
279 }
280 }
281
282 public override float PhysicsCost
283 {
284 get
285 {
286 return m_physCost;
287 }
288 }
289
290 public override float StreamCost
291 {
292 get
293 {
294 return m_streamCost;
295 }
296 }
297
298 public override int PhysicsActorType
299 {
300 get { return (int)ActorTypes.Prim; }
301 set { return; }
302 }
303
304 public override bool SetAlwaysRun
305 {
306 get { return false; }
307 set { return; }
308 }
309
310 public override uint LocalID
311 {
312 get { return m_localID; }
313 set
314 {
315 uint oldid = m_localID;
316 m_localID = value;
317 _parent_scene.changePrimID(this, oldid);
318 }
319 }
320
321 public override PhysicsActor ParentActor
322 {
323 get
324 {
325 if (childPrim)
326 return _parent;
327 else
328 return (PhysicsActor)this;
329 }
330 }
331
332 public override bool Grabbed
333 {
334 set { return; }
335 }
336
337 public override bool Selected
338 {
339 set
340 {
341 if (value)
342 m_isSelected = value; // if true set imediatly to stop moves etc
343 AddChange(changes.Selected, value);
344 }
345 }
346
347 public override bool Flying
348 {
349 // no flying prims for you
350 get { return false; }
351 set { }
352 }
353
354 public override bool IsColliding
355 {
356 get { return m_iscolliding; }
357 set
358 {
359 if (value)
360 {
361 m_colliderfilter += 2;
362 if (m_colliderfilter > 2)
363 m_colliderfilter = 2;
364 }
365 else
366 {
367 m_colliderfilter--;
368 if (m_colliderfilter < 0)
369 m_colliderfilter = 0;
370 }
371
372 if (m_colliderfilter == 0)
373 m_iscolliding = false;
374 else
375 m_iscolliding = true;
376 }
377 }
378
379 public override bool CollidingGround
380 {
381 get { return false; }
382 set { return; }
383 }
384
385 public override bool CollidingObj
386 {
387 get { return false; }
388 set { return; }
389 }
390
391
392 public override bool ThrottleUpdates {get;set;}
393
394 public override bool Stopped
395 {
396 get { return _zeroFlag; }
397 }
398
399 public override Vector3 Position
400 {
401 get
402 {
403 if (givefakepos > 0)
404 return fakepos;
405 else
406 return _position;
407 }
408
409 set
410 {
411 fakepos = value;
412 givefakepos++;
413 AddChange(changes.Position, value);
414 }
415 }
416
417 public override Vector3 Size
418 {
419 get { return _size; }
420 set
421 {
422 if (value.IsFinite())
423 {
424 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, value, m_fakeShapetype);
425 }
426 else
427 {
428 m_log.WarnFormat("[PHYSICS]: Got NaN Size on object {0}", Name);
429 }
430 }
431 }
432
433 public override float Mass
434 {
435 get { return primMass; }
436 }
437
438 public override Vector3 Force
439 {
440 get { return m_force; }
441 set
442 {
443 if (value.IsFinite())
444 {
445 AddChange(changes.Force, value);
446 }
447 else
448 {
449 m_log.WarnFormat("[PHYSICS]: NaN in Force Applied to an Object {0}", Name);
450 }
451 }
452 }
453
454 public override void SetVolumeDetect(int param)
455 {
456 m_fakeisVolumeDetect = (param != 0);
457 AddChange(changes.VolumeDtc, m_fakeisVolumeDetect);
458 }
459
460 public override Vector3 GeometricCenter
461 {
462 // this is not real geometric center but a average of positions relative to root prim acording to
463 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
464 // ignoring tortured prims details since sl also seems to ignore
465 // so no real use in doing it on physics
466 get
467 {
468 return Vector3.Zero;
469 }
470 }
471
472 public override PhysicsInertiaData GetInertiaData()
473 {
474 PhysicsInertiaData inertia;
475 if(childPrim)
476 {
477 if(_parent != null)
478 return _parent.GetInertiaData();
479 else
480 {
481 inertia = new PhysicsInertiaData();
482 inertia.TotalMass = -1;
483 return inertia;
484 }
485 }
486
487 inertia = new PhysicsInertiaData();
488
489 // double buffering
490 if(m_fakeInertiaOverride != null)
491 {
492 d.Mass objdmass = new d.Mass();
493 objdmass.I.M00 = m_fakeInertiaOverride.Inertia.X;
494 objdmass.I.M11 = m_fakeInertiaOverride.Inertia.Y;
495 objdmass.I.M22 = m_fakeInertiaOverride.Inertia.Z;
496
497 objdmass.mass = m_fakeInertiaOverride.TotalMass;
498
499 if(Math.Abs(m_fakeInertiaOverride.InertiaRotation.W) < 0.999)
500 {
501 d.Matrix3 inertiarotmat = new d.Matrix3();
502 d.Quaternion inertiarot = new d.Quaternion();
503
504 inertiarot.X = m_fakeInertiaOverride.InertiaRotation.X;
505 inertiarot.Y = m_fakeInertiaOverride.InertiaRotation.Y;
506 inertiarot.Z = m_fakeInertiaOverride.InertiaRotation.Z;
507 inertiarot.W = m_fakeInertiaOverride.InertiaRotation.W;
508 d.RfromQ(out inertiarotmat, ref inertiarot);
509 d.MassRotate(ref objdmass, ref inertiarotmat);
510 }
511
512 inertia.TotalMass = m_fakeInertiaOverride.TotalMass;
513 inertia.CenterOfMass = m_fakeInertiaOverride.CenterOfMass;
514 inertia.Inertia.X = objdmass.I.M00;
515 inertia.Inertia.Y = objdmass.I.M11;
516 inertia.Inertia.Z = objdmass.I.M22;
517 inertia.InertiaRotation.X = objdmass.I.M01;
518 inertia.InertiaRotation.Y = objdmass.I.M02;
519 inertia.InertiaRotation.Z = objdmass.I.M12;
520 return inertia;
521 }
522
523 inertia.TotalMass = m_mass;
524
525 if(Body == IntPtr.Zero || prim_geom == IntPtr.Zero)
526 {
527 inertia.CenterOfMass = Vector3.Zero;
528 inertia.Inertia = Vector3.Zero;
529 inertia.InertiaRotation = Vector4.Zero;
530 return inertia;
531 }
532
533 d.Vector3 dtmp;
534 d.Mass m = new d.Mass();
535 lock(_parent_scene.OdeLock)
536 {
537 d.AllocateODEDataForThread(0);
538 dtmp = d.GeomGetOffsetPosition(prim_geom);
539 d.BodyGetMass(Body, out m);
540 }
541
542 Vector3 cm = new Vector3(-dtmp.X, -dtmp.Y, -dtmp.Z);
543 inertia.CenterOfMass = cm;
544 inertia.Inertia = new Vector3(m.I.M00, m.I.M11, m.I.M22);
545 inertia.InertiaRotation = new Vector4(m.I.M01, m.I.M02 , m.I.M12, 0);
546
547 return inertia;
548 }
549
550 public override void SetInertiaData(PhysicsInertiaData inertia)
551 {
552 if(childPrim)
553 {
554 if(_parent != null)
555 _parent.SetInertiaData(inertia);
556 return;
557 }
558
559 if(inertia.TotalMass > 0)
560 m_fakeInertiaOverride = new PhysicsInertiaData(inertia);
561 else
562 m_fakeInertiaOverride = null;
563
564 if (inertia.TotalMass > _parent_scene.maximumMassObject)
565 inertia.TotalMass = _parent_scene.maximumMassObject;
566 AddChange(changes.SetInertia,(object)m_fakeInertiaOverride);
567 }
568
569 public override Vector3 CenterOfMass
570 {
571 get
572 {
573 lock (_parent_scene.OdeLock)
574 {
575 d.AllocateODEDataForThread(0);
576
577 d.Vector3 dtmp;
578 if (!childPrim && Body != IntPtr.Zero)
579 {
580 dtmp = d.BodyGetPosition(Body);
581 return new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
582 }
583 else if (prim_geom != IntPtr.Zero)
584 {
585 d.Quaternion dq;
586 d.GeomCopyQuaternion(prim_geom, out dq);
587 Quaternion q;
588 q.X = dq.X;
589 q.Y = dq.Y;
590 q.Z = dq.Z;
591 q.W = dq.W;
592
593 Vector3 Ptot = m_OBBOffset * q;
594 dtmp = d.GeomGetPosition(prim_geom);
595 Ptot.X += dtmp.X;
596 Ptot.Y += dtmp.Y;
597 Ptot.Z += dtmp.Z;
598
599 // if(childPrim) we only know about physical linksets
600 return Ptot;
601/*
602 float tmass = _mass;
603 Ptot *= tmass;
604
605 float m;
606
607 foreach (OdePrim prm in childrenPrim)
608 {
609 m = prm._mass;
610 Ptot += prm.CenterOfMass * m;
611 tmass += m;
612 }
613
614 if (tmass == 0)
615 tmass = 0;
616 else
617 tmass = 1.0f / tmass;
618
619 Ptot *= tmass;
620 return Ptot;
621*/
622 }
623 else
624 return _position;
625 }
626 }
627 }
628
629 public override PrimitiveBaseShape Shape
630 {
631 set
632 {
633// AddChange(changes.Shape, value);
634 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, value, _size, m_fakeShapetype);
635 }
636 }
637
638 public override byte PhysicsShapeType
639 {
640 get
641 {
642 return m_fakeShapetype;
643 }
644 set
645 {
646 m_fakeShapetype = value;
647 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, _size, value);
648 }
649 }
650
651 public override Vector3 rootVelocity
652 {
653 get
654 {
655 if(_parent != null)
656 return ((OdePrim)_parent).Velocity;
657 return Velocity;
658 }
659 }
660
661 public override Vector3 Velocity
662 {
663 get
664 {
665 if (_zeroFlag)
666 return Vector3.Zero;
667 return _velocity;
668 }
669 set
670 {
671 if (value.IsFinite())
672 {
673 if(m_outbounds)
674 _velocity = value;
675 else
676 AddChange(changes.Velocity, value);
677 }
678 else
679 {
680 m_log.WarnFormat("[PHYSICS]: Got NaN Velocity in Object {0}", Name);
681 }
682 }
683 }
684
685 public override Vector3 Torque
686 {
687 get
688 {
689 if (!IsPhysical || Body == IntPtr.Zero)
690 return Vector3.Zero;
691
692 return m_torque;
693 }
694
695 set
696 {
697 if (value.IsFinite())
698 {
699 AddChange(changes.Torque, value);
700 }
701 else
702 {
703 m_log.WarnFormat("[PHYSICS]: Got NaN Torque in Object {0}", Name);
704 }
705 }
706 }
707
708 public override float CollisionScore
709 {
710 get { return m_collisionscore; }
711 set { m_collisionscore = value; }
712 }
713
714 public override bool Kinematic
715 {
716 get { return false; }
717 set { }
718 }
719
720 public override Quaternion Orientation
721 {
722 get
723 {
724 if (givefakeori > 0)
725 return fakeori;
726 else
727
728 return _orientation;
729 }
730 set
731 {
732 if (QuaternionIsFinite(value))
733 {
734 fakeori = value;
735 givefakeori++;
736
737 value.Normalize();
738
739 AddChange(changes.Orientation, value);
740 }
741 else
742 m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name);
743
744 }
745 }
746
747 public override Vector3 Acceleration
748 {
749 get { return m_acceleration; }
750 set
751 {
752 if(m_outbounds)
753 m_acceleration = value;
754 }
755 }
756
757 public override Vector3 RotationalVelocity
758 {
759 get
760 {
761 Vector3 pv = Vector3.Zero;
762 if (_zeroFlag)
763 return pv;
764
765 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f))
766 return pv;
767
768 return m_rotationalVelocity;
769 }
770 set
771 {
772 if (value.IsFinite())
773 {
774 if(m_outbounds)
775 m_rotationalVelocity = value;
776 else
777 AddChange(changes.AngVelocity, value);
778 }
779 else
780 {
781 m_log.WarnFormat("[PHYSICS]: Got NaN RotationalVelocity in Object {0}", Name);
782 }
783 }
784 }
785
786 public override float Buoyancy
787 {
788 get { return m_buoyancy; }
789 set
790 {
791 AddChange(changes.Buoyancy,value);
792 }
793 }
794
795 public override bool FloatOnWater
796 {
797 set
798 {
799 AddChange(changes.CollidesWater, value);
800 }
801 }
802
803 public override Vector3 PIDTarget
804 {
805 set
806 {
807 if (value.IsFinite())
808 {
809 AddChange(changes.PIDTarget,value);
810 }
811 else
812 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name);
813 }
814 }
815
816 public override bool PIDActive
817 {
818 get
819 {
820 return m_usePID;
821 }
822 set
823 {
824 AddChange(changes.PIDActive,value);
825 }
826 }
827
828 public override float PIDTau
829 {
830 set
831 {
832 float tmp = 0;
833 if (value > 0)
834 {
835 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
836 if (value < mint)
837 tmp = mint;
838 else
839 tmp = value;
840 }
841 AddChange(changes.PIDTau,tmp);
842 }
843 }
844
845 public override float PIDHoverHeight
846 {
847 set
848 {
849 AddChange(changes.PIDHoverHeight,value);
850 }
851 }
852 public override bool PIDHoverActive
853 {
854 get
855 {
856 return m_useHoverPID;
857 }
858 set
859 {
860 AddChange(changes.PIDHoverActive, value);
861 }
862 }
863
864 public override PIDHoverType PIDHoverType
865 {
866 set
867 {
868 AddChange(changes.PIDHoverType,value);
869 }
870 }
871
872 public override float PIDHoverTau
873 {
874 set
875 {
876 float tmp =0;
877 if (value > 0)
878 {
879 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
880 if (value < mint)
881 tmp = mint;
882 else
883 tmp = value;
884 }
885 AddChange(changes.PIDHoverTau, tmp);
886 }
887 }
888
889 public override Quaternion APIDTarget { set { return; } }
890
891 public override bool APIDActive { set { return; } }
892
893 public override float APIDStrength { set { return; } }
894
895 public override float APIDDamping { set { return; } }
896
897 public override int VehicleType
898 {
899 // we may need to put a fake on this
900 get
901 {
902 if (m_vehicle == null)
903 return (int)Vehicle.TYPE_NONE;
904 else
905 return (int)m_vehicle.Type;
906 }
907 set
908 {
909 AddChange(changes.VehicleType, value);
910 }
911 }
912
913 public override void VehicleFloatParam(int param, float value)
914 {
915 strVehicleFloatParam fp = new strVehicleFloatParam();
916 fp.param = param;
917 fp.value = value;
918 AddChange(changes.VehicleFloatParam, fp);
919 }
920
921 public override void VehicleVectorParam(int param, Vector3 value)
922 {
923 strVehicleVectorParam fp = new strVehicleVectorParam();
924 fp.param = param;
925 fp.value = value;
926 AddChange(changes.VehicleVectorParam, fp);
927 }
928
929 public override void VehicleRotationParam(int param, Quaternion value)
930 {
931 strVehicleQuatParam fp = new strVehicleQuatParam();
932 fp.param = param;
933 fp.value = value;
934 AddChange(changes.VehicleRotationParam, fp);
935 }
936
937 public override void VehicleFlags(int param, bool value)
938 {
939 strVehicleBoolParam bp = new strVehicleBoolParam();
940 bp.param = param;
941 bp.value = value;
942 AddChange(changes.VehicleFlags, bp);
943 }
944
945 public override void SetVehicle(object vdata)
946 {
947 AddChange(changes.SetVehicle, vdata);
948 }
949 public void SetAcceleration(Vector3 accel)
950 {
951 m_acceleration = accel;
952 }
953
954 public override void AddForce(Vector3 force, bool pushforce)
955 {
956 if (force.IsFinite())
957 {
958 if(pushforce)
959 AddChange(changes.AddForce, force);
960 else // a impulse
961 AddChange(changes.AddForce, force * m_invTimeStep);
962 }
963 else
964 {
965 m_log.WarnFormat("[PHYSICS]: Got Invalid linear force vector from Scene in Object {0}", Name);
966 }
967 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
968 }
969
970 public override void AddAngularForce(Vector3 force, bool pushforce)
971 {
972 if (force.IsFinite())
973 {
974// if(pushforce) for now applyrotationimpulse seems more happy applied as a force
975 AddChange(changes.AddAngForce, force);
976// else // a impulse
977// AddChange(changes.AddAngForce, force * m_invTimeStep);
978 }
979 else
980 {
981 m_log.WarnFormat("[PHYSICS]: Got Invalid Angular force vector from Scene in Object {0}", Name);
982 }
983 }
984
985 public override void CrossingFailure()
986 {
987 lock(_parent_scene.OdeLock)
988 {
989 if (m_outbounds)
990 {
991 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f);
992 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f);
993 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
994
995 m_lastposition = _position;
996 _velocity.X = 0;
997 _velocity.Y = 0;
998 _velocity.Z = 0;
999
1000 d.AllocateODEDataForThread(0);
1001
1002 m_lastVelocity = _velocity;
1003 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
1004 m_vehicle.Stop();
1005
1006 if(Body != IntPtr.Zero)
1007 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
1008 if (prim_geom != IntPtr.Zero)
1009 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1010
1011 m_outbounds = false;
1012 changeDisable(false);
1013 base.RequestPhysicsterseUpdate();
1014 }
1015 }
1016 }
1017
1018 public override void CrossingStart()
1019 {
1020 lock(_parent_scene.OdeLock)
1021 {
1022 if (m_outbounds || childPrim)
1023 return;
1024
1025 m_outbounds = true;
1026
1027 m_lastposition = _position;
1028 m_lastorientation = _orientation;
1029
1030 d.AllocateODEDataForThread(0);
1031 if(Body != IntPtr.Zero)
1032 {
1033 d.Vector3 dtmp = d.BodyGetAngularVel(Body);
1034 m_rotationalVelocity.X = dtmp.X;
1035 m_rotationalVelocity.Y = dtmp.Y;
1036 m_rotationalVelocity.Z = dtmp.Z;
1037
1038 dtmp = d.BodyGetLinearVel(Body);
1039 _velocity.X = dtmp.X;
1040 _velocity.Y = dtmp.Y;
1041 _velocity.Z = dtmp.Z;
1042
1043 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
1044 d.BodySetAngularVel(Body, 0, 0, 0);
1045 }
1046 if(prim_geom != IntPtr.Zero)
1047 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1048 disableBodySoft(); // stop collisions
1049 UnSubscribeEvents();
1050 }
1051 }
1052
1053 public override void SetMomentum(Vector3 momentum)
1054 {
1055 }
1056
1057 public override void SetMaterial(int pMaterial)
1058 {
1059 m_material = pMaterial;
1060 mu = _parent_scene.m_materialContactsData[pMaterial].mu;
1061 bounce = _parent_scene.m_materialContactsData[pMaterial].bounce;
1062 }
1063
1064 public override float Density
1065 {
1066 get
1067 {
1068 return m_density * 100f;
1069 }
1070 set
1071 {
1072 float old = m_density;
1073 m_density = value / 100f;
1074 // if(m_density != old)
1075 // UpdatePrimBodyData();
1076 }
1077 }
1078 public override float GravModifier
1079 {
1080 get
1081 {
1082 return m_gravmod;
1083 }
1084 set
1085 {
1086 m_gravmod = value;
1087 if (m_vehicle != null)
1088 m_vehicle.GravMod = m_gravmod;
1089 }
1090 }
1091 public override float Friction
1092 {
1093 get
1094 {
1095 return mu;
1096 }
1097 set
1098 {
1099 mu = value;
1100 }
1101 }
1102
1103 public override float Restitution
1104 {
1105 get
1106 {
1107 return bounce;
1108 }
1109 set
1110 {
1111 bounce = value;
1112 }
1113 }
1114
1115 public void setPrimForRemoval()
1116 {
1117 AddChange(changes.Remove, null);
1118 }
1119
1120 public override void link(PhysicsActor obj)
1121 {
1122 AddChange(changes.Link, obj);
1123 }
1124
1125 public override void delink()
1126 {
1127 AddChange(changes.DeLink, null);
1128 }
1129
1130 public override void LockAngularMotion(byte axislock)
1131 {
1132// m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
1133 AddChange(changes.AngLock, axislock);
1134
1135 }
1136
1137 public override void SubscribeEvents(int ms)
1138 {
1139 m_eventsubscription = ms;
1140 m_cureventsubscription = 0;
1141 if (CollisionEventsThisFrame == null)
1142 CollisionEventsThisFrame = new CollisionEventUpdate();
1143 if (CollisionVDTCEventsThisFrame == null)
1144 CollisionVDTCEventsThisFrame = new CollisionEventUpdate();
1145 SentEmptyCollisionsEvent = false;
1146 }
1147
1148 public override void UnSubscribeEvents()
1149 {
1150 if (CollisionVDTCEventsThisFrame != null)
1151 {
1152 CollisionVDTCEventsThisFrame.Clear();
1153 CollisionVDTCEventsThisFrame = null;
1154 }
1155 if (CollisionEventsThisFrame != null)
1156 {
1157 CollisionEventsThisFrame.Clear();
1158 CollisionEventsThisFrame = null;
1159 }
1160 m_eventsubscription = 0;
1161 _parent_scene.RemoveCollisionEventReporting(this);
1162 }
1163
1164 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1165 {
1166 if (CollisionEventsThisFrame == null)
1167 CollisionEventsThisFrame = new CollisionEventUpdate();
1168
1169 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
1170 _parent_scene.AddCollisionEventReporting(this);
1171 }
1172
1173 public override void AddVDTCCollisionEvent(uint CollidedWith, ContactPoint contact)
1174 {
1175 if (CollisionVDTCEventsThisFrame == null)
1176 CollisionVDTCEventsThisFrame = new CollisionEventUpdate();
1177
1178 CollisionVDTCEventsThisFrame.AddCollider(CollidedWith, contact);
1179 _parent_scene.AddCollisionEventReporting(this);
1180 }
1181
1182 internal void SleeperAddCollisionEvents()
1183 {
1184 if(CollisionEventsThisFrame != null && CollisionEventsThisFrame.m_objCollisionList.Count != 0)
1185 {
1186 foreach(KeyValuePair<uint,ContactPoint> kvp in CollisionEventsThisFrame.m_objCollisionList)
1187 {
1188 if(kvp.Key == 0)
1189 continue;
1190 OdePrim other = _parent_scene.getPrim(kvp.Key);
1191 if(other == null)
1192 continue;
1193 ContactPoint cp = kvp.Value;
1194 cp.SurfaceNormal = - cp.SurfaceNormal;
1195 cp.RelativeSpeed = -cp.RelativeSpeed;
1196 other.AddCollisionEvent(ParentActor.LocalID,cp);
1197 }
1198 }
1199 if(CollisionVDTCEventsThisFrame != null && CollisionVDTCEventsThisFrame.m_objCollisionList.Count != 0)
1200 {
1201 foreach(KeyValuePair<uint,ContactPoint> kvp in CollisionVDTCEventsThisFrame.m_objCollisionList)
1202 {
1203 OdePrim other = _parent_scene.getPrim(kvp.Key);
1204 if(other == null)
1205 continue;
1206 ContactPoint cp = kvp.Value;
1207 cp.SurfaceNormal = - cp.SurfaceNormal;
1208 cp.RelativeSpeed = -cp.RelativeSpeed;
1209 other.AddCollisionEvent(ParentActor.LocalID,cp);
1210 }
1211 }
1212 }
1213
1214 internal void clearSleeperCollisions()
1215 {
1216 if(CollisionVDTCEventsThisFrame != null && CollisionVDTCEventsThisFrame.Count >0 )
1217 CollisionVDTCEventsThisFrame.Clear();
1218 }
1219
1220 public void SendCollisions(int timestep)
1221 {
1222 if (m_cureventsubscription < 50000)
1223 m_cureventsubscription += timestep;
1224
1225
1226 if (m_cureventsubscription < m_eventsubscription)
1227 return;
1228
1229 if (CollisionEventsThisFrame == null)
1230 return;
1231
1232 int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count;
1233
1234 if (!SentEmptyCollisionsEvent || ncolisions > 0)
1235 {
1236 base.SendCollisionUpdate(CollisionEventsThisFrame);
1237 m_cureventsubscription = 0;
1238
1239 if (ncolisions == 0)
1240 {
1241 SentEmptyCollisionsEvent = true;
1242// _parent_scene.RemoveCollisionEventReporting(this);
1243 }
1244 else if(Body == IntPtr.Zero || (d.BodyIsEnabled(Body) && m_bodydisablecontrol >= 0 ))
1245 {
1246 SentEmptyCollisionsEvent = false;
1247 CollisionEventsThisFrame.Clear();
1248 }
1249 }
1250 }
1251
1252 public override bool SubscribedEvents()
1253 {
1254 if (m_eventsubscription > 0)
1255 return true;
1256 return false;
1257 }
1258
1259 public OdePrim(String primName, ODEScene parent_scene, Vector3 pos, Vector3 size,
1260 Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical,bool pisPhantom,byte _shapeType,uint plocalID)
1261 {
1262 _parent_scene = parent_scene;
1263
1264 Name = primName;
1265 m_localID = plocalID;
1266
1267 m_vehicle = null;
1268
1269 if (!pos.IsFinite())
1270 {
1271 pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
1272 parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
1273 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Position for {0}", Name);
1274 }
1275 _position = pos;
1276 givefakepos = 0;
1277
1278 m_timeStep = parent_scene.ODE_STEPSIZE;
1279 m_invTimeStep = 1f / m_timeStep;
1280
1281 m_density = parent_scene.geomDefaultDensity;
1282 m_body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
1283
1284 prim_geom = IntPtr.Zero;
1285 collide_geom = IntPtr.Zero;
1286 Body = IntPtr.Zero;
1287
1288 if (!size.IsFinite())
1289 {
1290 size = new Vector3(0.5f, 0.5f, 0.5f);
1291 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Size for {0}", Name);
1292 }
1293
1294 if (size.X <= 0) size.X = 0.01f;
1295 if (size.Y <= 0) size.Y = 0.01f;
1296 if (size.Z <= 0) size.Z = 0.01f;
1297
1298 _size = size;
1299
1300 if (!QuaternionIsFinite(rotation))
1301 {
1302 rotation = Quaternion.Identity;
1303 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Rotation for {0}", Name);
1304 }
1305
1306 _orientation = rotation;
1307 givefakeori = 0;
1308
1309 _pbs = pbs;
1310
1311 m_targetSpace = IntPtr.Zero;
1312
1313 if (pos.Z < 0)
1314 {
1315 m_isphysical = false;
1316 }
1317 else
1318 {
1319 m_isphysical = pisPhysical;
1320 }
1321 m_fakeisphysical = m_isphysical;
1322
1323 m_isVolumeDetect = false;
1324 m_fakeisVolumeDetect = false;
1325
1326 m_force = Vector3.Zero;
1327
1328 m_iscolliding = false;
1329 m_colliderfilter = 0;
1330 m_NoColide = false;
1331
1332 _triMeshData = IntPtr.Zero;
1333
1334 m_fakeShapetype = _shapeType;
1335
1336 m_lastdoneSelected = false;
1337 m_isSelected = false;
1338 m_delaySelect = false;
1339
1340 m_isphantom = pisPhantom;
1341 m_fakeisphantom = pisPhantom;
1342
1343 mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
1344 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
1345
1346 m_building = true; // control must set this to false when done
1347
1348 AddChange(changes.Add, null);
1349
1350 // get basic mass parameters
1351 ODEPhysRepData repData = _parent_scene.m_meshWorker.NewActorPhysRep(this, _pbs, _size, _shapeType);
1352
1353 primVolume = repData.volume;
1354 m_OBB = repData.OBB;
1355 m_OBBOffset = repData.OBBOffset;
1356
1357 UpdatePrimBodyData();
1358 }
1359
1360 private void resetCollisionAccounting()
1361 {
1362 m_collisionscore = 0;
1363 }
1364
1365 private void UpdateCollisionCatFlags()
1366 {
1367 if(m_isphysical && m_disabled)
1368 {
1369 m_collisionCategories = 0;
1370 m_collisionFlags = 0;
1371 }
1372
1373 else if (m_isSelected)
1374 {
1375 m_collisionCategories = CollisionCategories.Selected;
1376 m_collisionFlags = 0;
1377 }
1378
1379 else if (m_isVolumeDetect)
1380 {
1381 m_collisionCategories = CollisionCategories.VolumeDtc;
1382 if (m_isphysical)
1383 m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character;
1384 else
1385 m_collisionFlags = 0;
1386 }
1387 else if (m_isphantom)
1388 {
1389 m_collisionCategories = CollisionCategories.Phantom;
1390 if (m_isphysical)
1391 m_collisionFlags = CollisionCategories.Land;
1392 else
1393 m_collisionFlags = 0;
1394 }
1395 else
1396 {
1397 m_collisionCategories = CollisionCategories.Geom;
1398 if (m_isphysical)
1399 m_collisionFlags = m_default_collisionFlagsPhysical;
1400 else
1401 m_collisionFlags = m_default_collisionFlagsNotPhysical;
1402 }
1403 }
1404
1405 private void ApplyCollisionCatFlags()
1406 {
1407 if (prim_geom != IntPtr.Zero)
1408 {
1409 if (!childPrim && childrenPrim.Count > 0)
1410 {
1411 foreach (OdePrim prm in childrenPrim)
1412 {
1413 if (m_isphysical && m_disabled)
1414 {
1415 prm.m_collisionCategories = 0;
1416 prm.m_collisionFlags = 0;
1417 }
1418 else
1419 {
1420 // preserve some
1421 if (prm.m_isSelected)
1422 {
1423 prm.m_collisionCategories = CollisionCategories.Selected;
1424 prm.m_collisionFlags = 0;
1425 }
1426 else if (prm.m_isVolumeDetect)
1427 {
1428 prm.m_collisionCategories = CollisionCategories.VolumeDtc;
1429 if (m_isphysical)
1430 prm.m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character;
1431 else
1432 prm.m_collisionFlags = 0;
1433 }
1434 else if (prm.m_isphantom)
1435 {
1436 prm.m_collisionCategories = CollisionCategories.Phantom;
1437 if (m_isphysical)
1438 prm.m_collisionFlags = CollisionCategories.Land;
1439 else
1440 prm.m_collisionFlags = 0;
1441 }
1442 else
1443 {
1444 prm.m_collisionCategories = m_collisionCategories;
1445 prm.m_collisionFlags = m_collisionFlags;
1446 }
1447 }
1448
1449 if (prm.prim_geom != IntPtr.Zero)
1450 {
1451 if (prm.m_NoColide)
1452 {
1453 d.GeomSetCategoryBits(prm.prim_geom, 0);
1454 if (m_isphysical)
1455 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
1456 else
1457 d.GeomSetCollideBits(prm.prim_geom, 0);
1458 }
1459 else
1460 {
1461 d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
1462 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
1463 }
1464 }
1465 }
1466 }
1467
1468 if (m_NoColide)
1469 {
1470 d.GeomSetCategoryBits(prim_geom, 0);
1471 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
1472 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
1473 {
1474 d.GeomSetCategoryBits(collide_geom, 0);
1475 d.GeomSetCollideBits(collide_geom, (uint)CollisionCategories.Land);
1476 }
1477 }
1478 else
1479 {
1480 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1481 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1482 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
1483 {
1484 d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories);
1485 d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags);
1486 }
1487 }
1488 }
1489 }
1490
1491 private void createAMotor(byte axislock)
1492 {
1493 if (Body == IntPtr.Zero)
1494 return;
1495
1496 if (Amotor != IntPtr.Zero)
1497 {
1498 d.JointDestroy(Amotor);
1499 Amotor = IntPtr.Zero;
1500 }
1501
1502 int axisnum = 0;
1503 bool axisX = false;
1504 bool axisY = false;
1505 bool axisZ = false;
1506 if((axislock & 0x02) != 0)
1507 {
1508 axisnum++;
1509 axisX = true;
1510 }
1511 if((axislock & 0x04) != 0)
1512 {
1513 axisnum++;
1514 axisY = true;
1515 }
1516 if((axislock & 0x08) != 0)
1517 {
1518 axisnum++;
1519 axisZ = true;
1520 }
1521
1522 if(axisnum == 0)
1523 return;
1524 // stop it
1525 d.BodySetTorque(Body, 0, 0, 0);
1526 d.BodySetAngularVel(Body, 0, 0, 0);
1527
1528 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
1529 d.JointAttach(Amotor, Body, IntPtr.Zero);
1530
1531 d.JointSetAMotorMode(Amotor, 0);
1532
1533 d.JointSetAMotorNumAxes(Amotor, axisnum);
1534
1535 // get current orientation to lock
1536
1537 d.Quaternion dcur = d.BodyGetQuaternion(Body);
1538 Quaternion curr; // crap convertion between identical things
1539 curr.X = dcur.X;
1540 curr.Y = dcur.Y;
1541 curr.Z = dcur.Z;
1542 curr.W = dcur.W;
1543 Vector3 ax;
1544
1545 int i = 0;
1546 int j = 0;
1547 if (axisX)
1548 {
1549 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X
1550 d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z);
1551 d.JointSetAMotorAngle(Amotor, 0, 0);
1552 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, 0f);
1553 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0f);
1554 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
1555 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
1556 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
1557 d.JointSetAMotorParam(Amotor, (int)d.JointParam.CFM, 0f);
1558 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
1559 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f);
1560 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f);
1561 i++;
1562 j = 256; // move to next axis set
1563 }
1564
1565 if (axisY)
1566 {
1567 ax = (new Vector3(0, 1, 0)) * curr;
1568 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1569 d.JointSetAMotorAngle(Amotor, i, 0);
1570 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
1571 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
1572 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1573 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1574 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1575 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
1576 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1577 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1578 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1579 i++;
1580 j += 256;
1581 }
1582
1583 if (axisZ)
1584 {
1585 ax = (new Vector3(0, 0, 1)) * curr;
1586 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1587 d.JointSetAMotorAngle(Amotor, i, 0);
1588 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
1589 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
1590 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1591 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1592 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1593 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
1594 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1595 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1596 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1597 }
1598 }
1599
1600
1601 private void SetGeom(IntPtr geom)
1602 {
1603 prim_geom = geom;
1604 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
1605 if (prim_geom != IntPtr.Zero)
1606 {
1607
1608 if (m_NoColide)
1609 {
1610 d.GeomSetCategoryBits(prim_geom, 0);
1611 if (m_isphysical)
1612 {
1613 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
1614 }
1615 else
1616 {
1617 d.GeomSetCollideBits(prim_geom, 0);
1618 d.GeomDisable(prim_geom);
1619 }
1620 }
1621 else
1622 {
1623 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1624 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1625 }
1626
1627 UpdatePrimBodyData();
1628 _parent_scene.actor_name_map[prim_geom] = this;
1629
1630/*
1631// debug
1632 d.AABB aabb;
1633 d.GeomGetAABB(prim_geom, out aabb);
1634 float x = aabb.MaxX - aabb.MinX;
1635 float y = aabb.MaxY - aabb.MinY;
1636 float z = aabb.MaxZ - aabb.MinZ;
1637 if( x > 60.0f || y > 60.0f || z > 60.0f)
1638 m_log.WarnFormat("[PHYSICS]: large prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}",
1639 Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString());
1640 else if (x < 0.001f || y < 0.001f || z < 0.001f)
1641 m_log.WarnFormat("[PHYSICS]: small prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}",
1642 Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString());
1643*/
1644
1645 }
1646 else
1647 m_log.Warn("Setting bad Geom");
1648 }
1649
1650 private bool GetMeshGeom()
1651 {
1652 IntPtr vertices, indices;
1653 int vertexCount, indexCount;
1654 int vertexStride, triStride;
1655
1656 IMesh mesh = m_mesh;
1657
1658 if (mesh == null)
1659 return false;
1660
1661 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
1662 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
1663
1664 if (vertexCount == 0 || indexCount == 0)
1665 {
1666 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on OdePrim {0}, mesh {1} at {2}",
1667 Name, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh",_position.ToString());
1668
1669 m_hasOBB = false;
1670 m_OBBOffset = Vector3.Zero;
1671 m_OBB = _size * 0.5f;
1672
1673 m_physCost = 0.1f;
1674 m_streamCost = 1.0f;
1675
1676 _parent_scene.mesher.ReleaseMesh(mesh);
1677 m_meshState = MeshState.MeshFailed;
1678 m_mesh = null;
1679 return false;
1680 }
1681
1682 if (vertexCount > 64000 || indexCount > 64000)
1683 {
1684 m_log.WarnFormat("[PHYSICS]: large mesh data on OdePrim {0}, mesh {1} at {2}, {3} vertices, {4} indexes",
1685 Name, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh",
1686 _position.ToString() ,vertexCount , indexCount );
1687 }
1688 IntPtr geo = IntPtr.Zero;
1689
1690 try
1691 {
1692 _triMeshData = d.GeomTriMeshDataCreate();
1693
1694 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1695 d.GeomTriMeshDataPreprocess(_triMeshData);
1696
1697 geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null);
1698 }
1699
1700 catch (Exception e)
1701 {
1702 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e);
1703 if (_triMeshData != IntPtr.Zero)
1704 {
1705 try
1706 {
1707 d.GeomTriMeshDataDestroy(_triMeshData);
1708 }
1709 catch
1710 {
1711 }
1712 }
1713 _triMeshData = IntPtr.Zero;
1714
1715 m_hasOBB = false;
1716 m_OBBOffset = Vector3.Zero;
1717 m_OBB = _size * 0.5f;
1718 m_physCost = 0.1f;
1719 m_streamCost = 1.0f;
1720
1721 _parent_scene.mesher.ReleaseMesh(mesh);
1722 m_meshState = MeshState.MeshFailed;
1723 m_mesh = null;
1724 return false;
1725 }
1726
1727 m_physCost = 0.0013f * (float)indexCount;
1728 // todo
1729 m_streamCost = 1.0f;
1730
1731 SetGeom(geo);
1732
1733 return true;
1734 }
1735
1736 private void CreateGeom(bool OverrideToBox)
1737 {
1738 bool hasMesh = false;
1739
1740 m_NoColide = false;
1741
1742 if ((m_meshState & MeshState.MeshNoColide) != 0)
1743 m_NoColide = true;
1744
1745 else if(!OverrideToBox && m_mesh != null)
1746 {
1747 if (GetMeshGeom())
1748 hasMesh = true;
1749 else
1750 m_NoColide = true;
1751 }
1752
1753
1754 if (!hasMesh)
1755 {
1756 IntPtr geo = IntPtr.Zero;
1757
1758 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1
1759 && _size.X == _size.Y && _size.Y == _size.Z)
1760 { // it's a sphere
1761 try
1762 {
1763 geo = d.CreateSphere(m_targetSpace, _size.X * 0.5f);
1764 }
1765 catch (Exception e)
1766 {
1767 m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e);
1768 return;
1769 }
1770 }
1771 else
1772 {// do it as a box
1773 try
1774 {
1775 geo = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1776 }
1777 catch (Exception e)
1778 {
1779 m_log.Warn("[PHYSICS]: Create box failed: {0}", e);
1780 return;
1781 }
1782 }
1783 m_physCost = 0.1f;
1784 m_streamCost = 1.0f;
1785 SetGeom(geo);
1786 }
1787 }
1788
1789 private void RemoveGeom()
1790 {
1791 if (prim_geom != IntPtr.Zero)
1792 {
1793 _parent_scene.actor_name_map.Remove(prim_geom);
1794
1795 try
1796 {
1797 d.GeomDestroy(prim_geom);
1798 if (_triMeshData != IntPtr.Zero)
1799 {
1800 d.GeomTriMeshDataDestroy(_triMeshData);
1801 _triMeshData = IntPtr.Zero;
1802 }
1803 }
1804 catch (Exception e)
1805 {
1806 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e);
1807 }
1808
1809 prim_geom = IntPtr.Zero;
1810 collide_geom = IntPtr.Zero;
1811 m_targetSpace = IntPtr.Zero;
1812 }
1813 else
1814 {
1815 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name);
1816 }
1817
1818 lock (m_meshlock)
1819 {
1820 if (m_mesh != null)
1821 {
1822 _parent_scene.mesher.ReleaseMesh(m_mesh);
1823 m_mesh = null;
1824 }
1825 }
1826
1827 Body = IntPtr.Zero;
1828 m_hasOBB = false;
1829 }
1830
1831 //sets non physical prim m_targetSpace to right space in spaces grid for static prims
1832 // should only be called for non physical prims unless they are becoming non physical
1833 private void SetInStaticSpace(OdePrim prim)
1834 {
1835 IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace);
1836 prim.m_targetSpace = targetSpace;
1837 collide_geom = IntPtr.Zero;
1838 }
1839
1840 public void enableBodySoft()
1841 {
1842 m_disabled = false;
1843 if (!childPrim && !m_isSelected)
1844 {
1845 if (m_isphysical && Body != IntPtr.Zero)
1846 {
1847 UpdateCollisionCatFlags();
1848 ApplyCollisionCatFlags();
1849
1850 _zeroFlag = true;
1851 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
1852 d.BodyEnable(Body);
1853 }
1854 }
1855 resetCollisionAccounting();
1856 }
1857
1858 private void disableBodySoft()
1859 {
1860 m_disabled = true;
1861 if (!childPrim)
1862 {
1863 if (m_isphysical && Body != IntPtr.Zero)
1864 {
1865 if (m_isSelected)
1866 m_collisionFlags = CollisionCategories.Selected;
1867 else
1868 m_collisionCategories = 0;
1869 m_collisionFlags = 0;
1870 ApplyCollisionCatFlags();
1871 d.BodyDisable(Body);
1872 }
1873 }
1874 }
1875
1876 private void MakeBody()
1877 {
1878 if (!m_isphysical) // only physical get bodies
1879 return;
1880
1881 if (childPrim) // child prims don't get bodies;
1882 return;
1883
1884 if (m_building)
1885 return;
1886
1887 if (prim_geom == IntPtr.Zero)
1888 {
1889 m_log.Warn("[PHYSICS]: Unable to link the linkset. Root has no geom yet");
1890 return;
1891 }
1892
1893 if (Body != IntPtr.Zero)
1894 {
1895 DestroyBody();
1896 m_log.Warn("[PHYSICS]: MakeBody called having a body");
1897 }
1898
1899 if (d.GeomGetBody(prim_geom) != IntPtr.Zero)
1900 {
1901 d.GeomSetBody(prim_geom, IntPtr.Zero);
1902 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body");
1903 }
1904
1905 bool noInertiaOverride = (m_InertiaOverride == null);
1906
1907 Body = d.BodyCreate(_parent_scene.world);
1908
1909 d.Matrix3 mymat = new d.Matrix3();
1910 d.Quaternion myrot = new d.Quaternion();
1911 d.Mass objdmass = new d.Mass { };
1912
1913 myrot.X = _orientation.X;
1914 myrot.Y = _orientation.Y;
1915 myrot.Z = _orientation.Z;
1916 myrot.W = _orientation.W;
1917 d.RfromQ(out mymat, ref myrot);
1918
1919 // set the body rotation
1920 d.BodySetRotation(Body, ref mymat);
1921
1922 if(noInertiaOverride)
1923 {
1924 objdmass = primdMass;
1925 d.MassRotate(ref objdmass, ref mymat);
1926 }
1927
1928 // recompute full object inertia if needed
1929 if (childrenPrim.Count > 0)
1930 {
1931 d.Matrix3 mat = new d.Matrix3();
1932 d.Quaternion quat = new d.Quaternion();
1933 d.Mass tmpdmass = new d.Mass { };
1934 Vector3 rcm;
1935
1936 rcm.X = _position.X;
1937 rcm.Y = _position.Y;
1938 rcm.Z = _position.Z;
1939
1940 lock (childrenPrim)
1941 {
1942 foreach (OdePrim prm in childrenPrim)
1943 {
1944 if (prm.prim_geom == IntPtr.Zero)
1945 {
1946 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements, skipping it. No geom yet");
1947 continue;
1948 }
1949
1950 quat.X = prm._orientation.X;
1951 quat.Y = prm._orientation.Y;
1952 quat.Z = prm._orientation.Z;
1953 quat.W = prm._orientation.W;
1954 d.RfromQ(out mat, ref quat);
1955
1956 // fix prim colision cats
1957
1958 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero)
1959 {
1960 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
1961 m_log.Warn("[PHYSICS]: MakeBody child geom already had a body");
1962 }
1963
1964 d.GeomClearOffset(prm.prim_geom);
1965 d.GeomSetBody(prm.prim_geom, Body);
1966 prm.Body = Body;
1967 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation
1968
1969 if(noInertiaOverride)
1970 {
1971 tmpdmass = prm.primdMass;
1972
1973 d.MassRotate(ref tmpdmass, ref mat);
1974 Vector3 ppos = prm._position;
1975 ppos.X -= rcm.X;
1976 ppos.Y -= rcm.Y;
1977 ppos.Z -= rcm.Z;
1978 // refer inertia to root prim center of mass position
1979 d.MassTranslate(ref tmpdmass,
1980 ppos.X,
1981 ppos.Y,
1982 ppos.Z);
1983
1984 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
1985 }
1986 }
1987 }
1988 }
1989
1990 d.GeomClearOffset(prim_geom); // make sure we don't have a hidden offset
1991 // associate root geom with body
1992 d.GeomSetBody(prim_geom, Body);
1993
1994 if(noInertiaOverride)
1995 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
1996 else
1997 {
1998 Vector3 ncm = m_InertiaOverride.CenterOfMass * _orientation;
1999 d.BodySetPosition(Body,
2000 _position.X + ncm.X,
2001 _position.Y + ncm.Y,
2002 _position.Z + ncm.Z);
2003 }
2004
2005 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z);
2006
2007 if(noInertiaOverride)
2008 {
2009 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2010 myrot.X = -myrot.X;
2011 myrot.Y = -myrot.Y;
2012 myrot.Z = -myrot.Z;
2013
2014 d.RfromQ(out mymat, ref myrot);
2015 d.MassRotate(ref objdmass, ref mymat);
2016
2017 d.BodySetMass(Body, ref objdmass);
2018 m_mass = objdmass.mass;
2019 }
2020 else
2021 {
2022 objdmass.c.X = 0;
2023 objdmass.c.Y = 0;
2024 objdmass.c.Z = 0;
2025
2026 objdmass.I.M00 = m_InertiaOverride.Inertia.X;
2027 objdmass.I.M11 = m_InertiaOverride.Inertia.Y;
2028 objdmass.I.M22 = m_InertiaOverride.Inertia.Z;
2029
2030 objdmass.mass = m_InertiaOverride.TotalMass;
2031
2032 if(Math.Abs(m_InertiaOverride.InertiaRotation.W) < 0.999)
2033 {
2034 d.Matrix3 inertiarotmat = new d.Matrix3();
2035 d.Quaternion inertiarot = new d.Quaternion();
2036
2037 inertiarot.X = m_InertiaOverride.InertiaRotation.X;
2038 inertiarot.Y = m_InertiaOverride.InertiaRotation.Y;
2039 inertiarot.Z = m_InertiaOverride.InertiaRotation.Z;
2040 inertiarot.W = m_InertiaOverride.InertiaRotation.W;
2041 d.RfromQ(out inertiarotmat, ref inertiarot);
2042 d.MassRotate(ref objdmass, ref inertiarotmat);
2043 }
2044 d.BodySetMass(Body, ref objdmass);
2045
2046 m_mass = objdmass.mass;
2047 }
2048
2049 // disconnect from world gravity so we can apply buoyancy
2050 d.BodySetGravityMode(Body, false);
2051
2052 d.BodySetAutoDisableFlag(Body, true);
2053 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
2054 d.BodySetAutoDisableAngularThreshold(Body, 0.05f);
2055 d.BodySetAutoDisableLinearThreshold(Body, 0.05f);
2056 d.BodySetDamping(Body, .004f, .001f);
2057
2058 if (m_targetSpace != IntPtr.Zero)
2059 {
2060 _parent_scene.waitForSpaceUnlock(m_targetSpace);
2061 if (d.SpaceQuery(m_targetSpace, prim_geom))
2062 d.SpaceRemove(m_targetSpace, prim_geom);
2063 }
2064
2065 if (childrenPrim.Count == 0)
2066 {
2067 collide_geom = prim_geom;
2068 m_targetSpace = _parent_scene.ActiveSpace;
2069 }
2070 else
2071 {
2072 m_targetSpace = d.HashSpaceCreate(_parent_scene.ActiveSpace);
2073 d.HashSpaceSetLevels(m_targetSpace, -2, 8);
2074 d.SpaceSetSublevel(m_targetSpace, 3);
2075 d.SpaceSetCleanup(m_targetSpace, false);
2076
2077 d.GeomSetCategoryBits(m_targetSpace, (uint)(CollisionCategories.Space |
2078 CollisionCategories.Geom |
2079 CollisionCategories.Phantom |
2080 CollisionCategories.VolumeDtc
2081 ));
2082 d.GeomSetCollideBits(m_targetSpace, 0);
2083 collide_geom = m_targetSpace;
2084 }
2085
2086 d.SpaceAdd(m_targetSpace, prim_geom);
2087
2088 if (m_delaySelect)
2089 {
2090 m_isSelected = true;
2091 m_delaySelect = false;
2092 }
2093
2094 m_collisionscore = 0;
2095
2096 UpdateCollisionCatFlags();
2097 ApplyCollisionCatFlags();
2098
2099 _parent_scene.addActivePrim(this);
2100
2101 lock (childrenPrim)
2102 {
2103 foreach (OdePrim prm in childrenPrim)
2104 {
2105 if (prm.prim_geom == IntPtr.Zero)
2106 continue;
2107
2108 Vector3 ppos = prm._position;
2109 d.GeomSetOffsetWorldPosition(prm.prim_geom, ppos.X, ppos.Y, ppos.Z); // set relative position
2110
2111 if (prm.m_targetSpace != m_targetSpace)
2112 {
2113 if (prm.m_targetSpace != IntPtr.Zero)
2114 {
2115 _parent_scene.waitForSpaceUnlock(prm.m_targetSpace);
2116 if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom))
2117 d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
2118 }
2119 prm.m_targetSpace = m_targetSpace;
2120 d.SpaceAdd(m_targetSpace, prm.prim_geom);
2121 }
2122
2123 prm.m_collisionscore = 0;
2124
2125 if(!m_disabled)
2126 prm.m_disabled = false;
2127
2128 _parent_scene.addActivePrim(prm);
2129 }
2130 }
2131
2132 // The body doesn't already have a finite rotation mode set here
2133 if (m_angularlocks != 0 && _parent == null)
2134 {
2135 createAMotor(m_angularlocks);
2136 }
2137
2138 if (m_isSelected || m_disabled)
2139 {
2140 d.BodyDisable(Body);
2141 _zeroFlag = true;
2142 }
2143 else
2144 {
2145 d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z);
2146 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
2147
2148 _zeroFlag = false;
2149 m_bodydisablecontrol = 0;
2150 }
2151 _parent_scene.addActiveGroups(this);
2152 }
2153
2154 private void DestroyBody()
2155 {
2156 if (Body != IntPtr.Zero)
2157 {
2158 _parent_scene.remActivePrim(this);
2159
2160 collide_geom = IntPtr.Zero;
2161
2162 if (m_disabled)
2163 m_collisionCategories = 0;
2164 else if (m_isSelected)
2165 m_collisionCategories = CollisionCategories.Selected;
2166 else if (m_isVolumeDetect)
2167 m_collisionCategories = CollisionCategories.VolumeDtc;
2168 else if (m_isphantom)
2169 m_collisionCategories = CollisionCategories.Phantom;
2170 else
2171 m_collisionCategories = CollisionCategories.Geom;
2172
2173 m_collisionFlags = 0;
2174
2175 if (prim_geom != IntPtr.Zero)
2176 {
2177 if (m_NoColide)
2178 {
2179 d.GeomSetCategoryBits(prim_geom, 0);
2180 d.GeomSetCollideBits(prim_geom, 0);
2181 }
2182 else
2183 {
2184 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
2185 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
2186 }
2187 UpdateDataFromGeom();
2188 d.GeomSetBody(prim_geom, IntPtr.Zero);
2189 SetInStaticSpace(this);
2190 }
2191
2192 if (!childPrim)
2193 {
2194 lock (childrenPrim)
2195 {
2196 foreach (OdePrim prm in childrenPrim)
2197 {
2198 _parent_scene.remActivePrim(prm);
2199
2200 if (prm.m_isSelected)
2201 prm.m_collisionCategories = CollisionCategories.Selected;
2202 else if (prm.m_isVolumeDetect)
2203 prm.m_collisionCategories = CollisionCategories.VolumeDtc;
2204 else if (prm.m_isphantom)
2205 prm.m_collisionCategories = CollisionCategories.Phantom;
2206 else
2207 prm.m_collisionCategories = CollisionCategories.Geom;
2208
2209 prm.m_collisionFlags = 0;
2210
2211 if (prm.prim_geom != IntPtr.Zero)
2212 {
2213 if (prm.m_NoColide)
2214 {
2215 d.GeomSetCategoryBits(prm.prim_geom, 0);
2216 d.GeomSetCollideBits(prm.prim_geom, 0);
2217 }
2218 else
2219 {
2220 d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
2221 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
2222 }
2223 prm.UpdateDataFromGeom();
2224 SetInStaticSpace(prm);
2225 }
2226 prm.Body = IntPtr.Zero;
2227 prm.m_mass = prm.primMass;
2228 prm.m_collisionscore = 0;
2229 }
2230 }
2231 if (Amotor != IntPtr.Zero)
2232 {
2233 d.JointDestroy(Amotor);
2234 Amotor = IntPtr.Zero;
2235 }
2236 _parent_scene.remActiveGroup(this);
2237 d.BodyDestroy(Body);
2238 }
2239 Body = IntPtr.Zero;
2240 }
2241 m_mass = primMass;
2242 m_collisionscore = 0;
2243 }
2244
2245 private void FixInertia(Vector3 NewPos,Quaternion newrot)
2246 {
2247 d.Matrix3 mat = new d.Matrix3();
2248 d.Quaternion quat = new d.Quaternion();
2249
2250 d.Mass tmpdmass = new d.Mass { };
2251 d.Mass objdmass = new d.Mass { };
2252
2253 d.BodyGetMass(Body, out tmpdmass);
2254 objdmass = tmpdmass;
2255
2256 d.Vector3 dobjpos;
2257 d.Vector3 thispos;
2258
2259 // get current object position and rotation
2260 dobjpos = d.BodyGetPosition(Body);
2261
2262 // get prim own inertia in its local frame
2263 tmpdmass = primdMass;
2264
2265 // transform to object frame
2266 mat = d.GeomGetOffsetRotation(prim_geom);
2267 d.MassRotate(ref tmpdmass, ref mat);
2268
2269 thispos = d.GeomGetOffsetPosition(prim_geom);
2270 d.MassTranslate(ref tmpdmass,
2271 thispos.X,
2272 thispos.Y,
2273 thispos.Z);
2274
2275 // subtract current prim inertia from object
2276 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2277
2278 // back prim own inertia
2279 tmpdmass = primdMass;
2280
2281 // update to new position and orientation
2282 _position = NewPos;
2283 d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z);
2284 _orientation = newrot;
2285 quat.X = newrot.X;
2286 quat.Y = newrot.Y;
2287 quat.Z = newrot.Z;
2288 quat.W = newrot.W;
2289 d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat);
2290
2291 mat = d.GeomGetOffsetRotation(prim_geom);
2292 d.MassRotate(ref tmpdmass, ref mat);
2293
2294 thispos = d.GeomGetOffsetPosition(prim_geom);
2295 d.MassTranslate(ref tmpdmass,
2296 thispos.X,
2297 thispos.Y,
2298 thispos.Z);
2299
2300 d.MassAdd(ref objdmass, ref tmpdmass);
2301
2302 // fix all positions
2303 IntPtr g = d.BodyGetFirstGeom(Body);
2304 while (g != IntPtr.Zero)
2305 {
2306 thispos = d.GeomGetOffsetPosition(g);
2307 thispos.X -= objdmass.c.X;
2308 thispos.Y -= objdmass.c.Y;
2309 thispos.Z -= objdmass.c.Z;
2310 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2311 g = d.dBodyGetNextGeom(g);
2312 }
2313 d.BodyVectorToWorld(Body,objdmass.c.X, objdmass.c.Y, objdmass.c.Z,out thispos);
2314
2315 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2316 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2317 d.BodySetMass(Body, ref objdmass);
2318 m_mass = objdmass.mass;
2319 }
2320
2321 private void FixInertia(Vector3 NewPos)
2322 {
2323 d.Matrix3 primmat = new d.Matrix3();
2324 d.Mass tmpdmass = new d.Mass { };
2325 d.Mass objdmass = new d.Mass { };
2326 d.Mass primmass = new d.Mass { };
2327
2328 d.Vector3 dobjpos;
2329 d.Vector3 thispos;
2330
2331 d.BodyGetMass(Body, out objdmass);
2332
2333 // get prim own inertia in its local frame
2334 primmass = primdMass;
2335 // transform to object frame
2336 primmat = d.GeomGetOffsetRotation(prim_geom);
2337 d.MassRotate(ref primmass, ref primmat);
2338
2339 tmpdmass = primmass;
2340
2341 thispos = d.GeomGetOffsetPosition(prim_geom);
2342 d.MassTranslate(ref tmpdmass,
2343 thispos.X,
2344 thispos.Y,
2345 thispos.Z);
2346
2347 // subtract current prim inertia from object
2348 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2349
2350 // update to new position
2351 _position = NewPos;
2352 d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z);
2353
2354 thispos = d.GeomGetOffsetPosition(prim_geom);
2355 d.MassTranslate(ref primmass,
2356 thispos.X,
2357 thispos.Y,
2358 thispos.Z);
2359
2360 d.MassAdd(ref objdmass, ref primmass);
2361
2362 // fix all positions
2363 IntPtr g = d.BodyGetFirstGeom(Body);
2364 while (g != IntPtr.Zero)
2365 {
2366 thispos = d.GeomGetOffsetPosition(g);
2367 thispos.X -= objdmass.c.X;
2368 thispos.Y -= objdmass.c.Y;
2369 thispos.Z -= objdmass.c.Z;
2370 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2371 g = d.dBodyGetNextGeom(g);
2372 }
2373
2374 d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos);
2375
2376 // get current object position and rotation
2377 dobjpos = d.BodyGetPosition(Body);
2378
2379 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2380 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2381 d.BodySetMass(Body, ref objdmass);
2382 m_mass = objdmass.mass;
2383 }
2384
2385 private void FixInertia(Quaternion newrot)
2386 {
2387 d.Matrix3 mat = new d.Matrix3();
2388 d.Quaternion quat = new d.Quaternion();
2389
2390 d.Mass tmpdmass = new d.Mass { };
2391 d.Mass objdmass = new d.Mass { };
2392 d.Vector3 dobjpos;
2393 d.Vector3 thispos;
2394
2395 d.BodyGetMass(Body, out objdmass);
2396
2397 // get prim own inertia in its local frame
2398 tmpdmass = primdMass;
2399 mat = d.GeomGetOffsetRotation(prim_geom);
2400 d.MassRotate(ref tmpdmass, ref mat);
2401 // transform to object frame
2402 thispos = d.GeomGetOffsetPosition(prim_geom);
2403 d.MassTranslate(ref tmpdmass,
2404 thispos.X,
2405 thispos.Y,
2406 thispos.Z);
2407
2408 // subtract current prim inertia from object
2409 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2410
2411 // update to new orientation
2412 _orientation = newrot;
2413 quat.X = newrot.X;
2414 quat.Y = newrot.Y;
2415 quat.Z = newrot.Z;
2416 quat.W = newrot.W;
2417 d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat);
2418
2419 tmpdmass = primdMass;
2420 mat = d.GeomGetOffsetRotation(prim_geom);
2421 d.MassRotate(ref tmpdmass, ref mat);
2422 d.MassTranslate(ref tmpdmass,
2423 thispos.X,
2424 thispos.Y,
2425 thispos.Z);
2426
2427 d.MassAdd(ref objdmass, ref tmpdmass);
2428
2429 // fix all positions
2430 IntPtr g = d.BodyGetFirstGeom(Body);
2431 while (g != IntPtr.Zero)
2432 {
2433 thispos = d.GeomGetOffsetPosition(g);
2434 thispos.X -= objdmass.c.X;
2435 thispos.Y -= objdmass.c.Y;
2436 thispos.Z -= objdmass.c.Z;
2437 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2438 g = d.dBodyGetNextGeom(g);
2439 }
2440
2441 d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos);
2442 // get current object position and rotation
2443 dobjpos = d.BodyGetPosition(Body);
2444
2445 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2446 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2447 d.BodySetMass(Body, ref objdmass);
2448 m_mass = objdmass.mass;
2449 }
2450
2451
2452 #region Mass Calculation
2453
2454 private void UpdatePrimBodyData()
2455 {
2456 primMass = m_density * primVolume;
2457
2458 if (primMass <= 0)
2459 primMass = 0.0001f;//ckrinke: Mass must be greater then zero.
2460 if (primMass > _parent_scene.maximumMassObject)
2461 primMass = _parent_scene.maximumMassObject;
2462
2463 m_mass = primMass; // just in case
2464
2465 d.MassSetBoxTotal(out primdMass, primMass, 2.0f * m_OBB.X, 2.0f * m_OBB.Y, 2.0f * m_OBB.Z);
2466
2467 d.MassTranslate(ref primdMass,
2468 m_OBBOffset.X,
2469 m_OBBOffset.Y,
2470 m_OBBOffset.Z);
2471
2472 primOOBradiusSQ = m_OBB.LengthSquared();
2473
2474 if (_triMeshData != IntPtr.Zero)
2475 {
2476 float pc = m_physCost;
2477 float psf = primOOBradiusSQ;
2478 psf *= 1.33f * .2f;
2479 pc *= psf;
2480 if (pc < 0.1f)
2481 pc = 0.1f;
2482
2483 m_physCost = pc;
2484 }
2485 else
2486 m_physCost = 0.1f;
2487
2488 m_streamCost = 1.0f;
2489 }
2490
2491 #endregion
2492
2493
2494 /// <summary>
2495 /// Add a child prim to this parent prim.
2496 /// </summary>
2497 /// <param name="prim">Child prim</param>
2498 // I'm the parent
2499 // prim is the child
2500 public void ParentPrim(OdePrim prim)
2501 {
2502 //Console.WriteLine("ParentPrim " + m_primName);
2503 if (this.m_localID != prim.m_localID)
2504 {
2505 DestroyBody(); // for now we need to rebuil entire object on link change
2506
2507 lock (childrenPrim)
2508 {
2509 // adopt the prim
2510 if (!childrenPrim.Contains(prim))
2511 childrenPrim.Add(prim);
2512
2513 // see if this prim has kids and adopt them also
2514 // should not happen for now
2515 foreach (OdePrim prm in prim.childrenPrim)
2516 {
2517 if (!childrenPrim.Contains(prm))
2518 {
2519 if (prm.Body != IntPtr.Zero)
2520 {
2521 if (prm.prim_geom != IntPtr.Zero)
2522 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
2523 if (prm.Body != prim.Body)
2524 prm.DestroyBody(); // don't loose bodies around
2525 prm.Body = IntPtr.Zero;
2526 }
2527
2528 childrenPrim.Add(prm);
2529 prm._parent = this;
2530 }
2531 }
2532 }
2533 //Remove old children from the prim
2534 prim.childrenPrim.Clear();
2535
2536 if (prim.Body != IntPtr.Zero)
2537 {
2538 if (prim.prim_geom != IntPtr.Zero)
2539 d.GeomSetBody(prim.prim_geom, IntPtr.Zero);
2540 prim.DestroyBody(); // don't loose bodies around
2541 prim.Body = IntPtr.Zero;
2542 }
2543
2544 prim.childPrim = true;
2545 prim._parent = this;
2546
2547 MakeBody(); // full nasty reconstruction
2548 }
2549 }
2550
2551 private void UpdateChildsfromgeom()
2552 {
2553 if (childrenPrim.Count > 0)
2554 {
2555 foreach (OdePrim prm in childrenPrim)
2556 prm.UpdateDataFromGeom();
2557 }
2558 }
2559
2560 private void UpdateDataFromGeom()
2561 {
2562 if (prim_geom != IntPtr.Zero)
2563 {
2564 d.Quaternion qtmp;
2565 d.GeomCopyQuaternion(prim_geom, out qtmp);
2566 _orientation.X = qtmp.X;
2567 _orientation.Y = qtmp.Y;
2568 _orientation.Z = qtmp.Z;
2569 _orientation.W = qtmp.W;
2570/*
2571// Debug
2572 float qlen = _orientation.Length();
2573 if (qlen > 1.01f || qlen < 0.99)
2574 m_log.WarnFormat("[PHYSICS]: Got nonnorm quaternion from geom in Object {0} norm {1}", Name, qlen);
2575//
2576*/
2577 _orientation.Normalize();
2578
2579 d.Vector3 lpos = d.GeomGetPosition(prim_geom);
2580 _position.X = lpos.X;
2581 _position.Y = lpos.Y;
2582 _position.Z = lpos.Z;
2583 }
2584 }
2585
2586 private void ChildDelink(OdePrim odePrim, bool remakebodies)
2587 {
2588 // Okay, we have a delinked child.. destroy all body and remake
2589 if (odePrim != this && !childrenPrim.Contains(odePrim))
2590 return;
2591
2592 DestroyBody();
2593
2594 if (odePrim == this) // delinking the root prim
2595 {
2596 OdePrim newroot = null;
2597 lock (childrenPrim)
2598 {
2599 if (childrenPrim.Count > 0)
2600 {
2601 newroot = childrenPrim[0];
2602 childrenPrim.RemoveAt(0);
2603 foreach (OdePrim prm in childrenPrim)
2604 {
2605 newroot.childrenPrim.Add(prm);
2606 }
2607 childrenPrim.Clear();
2608 }
2609 if (newroot != null)
2610 {
2611 newroot.childPrim = false;
2612 newroot._parent = null;
2613 if (remakebodies)
2614 newroot.MakeBody();
2615 }
2616 }
2617 }
2618
2619 else
2620 {
2621 lock (childrenPrim)
2622 {
2623 childrenPrim.Remove(odePrim);
2624 odePrim.childPrim = false;
2625 odePrim._parent = null;
2626 // odePrim.UpdateDataFromGeom();
2627 if (remakebodies)
2628 odePrim.MakeBody();
2629 }
2630 }
2631 if (remakebodies)
2632 MakeBody();
2633 }
2634
2635 protected void ChildRemove(OdePrim odePrim, bool reMakeBody)
2636 {
2637 // Okay, we have a delinked child.. destroy all body and remake
2638 if (odePrim != this && !childrenPrim.Contains(odePrim))
2639 return;
2640
2641 DestroyBody();
2642
2643 if (odePrim == this)
2644 {
2645 OdePrim newroot = null;
2646 lock (childrenPrim)
2647 {
2648 if (childrenPrim.Count > 0)
2649 {
2650 newroot = childrenPrim[0];
2651 childrenPrim.RemoveAt(0);
2652 foreach (OdePrim prm in childrenPrim)
2653 {
2654 newroot.childrenPrim.Add(prm);
2655 }
2656 childrenPrim.Clear();
2657 }
2658 if (newroot != null)
2659 {
2660 newroot.childPrim = false;
2661 newroot._parent = null;
2662 newroot.MakeBody();
2663 }
2664 }
2665 if (reMakeBody)
2666 MakeBody();
2667 return;
2668 }
2669 else
2670 {
2671 lock (childrenPrim)
2672 {
2673 childrenPrim.Remove(odePrim);
2674 odePrim.childPrim = false;
2675 odePrim._parent = null;
2676 if (reMakeBody)
2677 odePrim.MakeBody();
2678 }
2679 }
2680 MakeBody();
2681 }
2682
2683
2684 #region changes
2685
2686 private void changeadd()
2687 {
2688 _parent_scene.addToPrims(this);
2689 }
2690
2691 private void changeAngularLock(byte newLocks)
2692 {
2693 // do we have a Physical object?
2694 if (Body != IntPtr.Zero)
2695 {
2696 //Check that we have a Parent
2697 //If we have a parent then we're not authorative here
2698 if (_parent == null)
2699 {
2700 if (newLocks != 0)
2701 {
2702 createAMotor(newLocks);
2703 }
2704 else
2705 {
2706 if (Amotor != IntPtr.Zero)
2707 {
2708 d.JointDestroy(Amotor);
2709 Amotor = IntPtr.Zero;
2710 }
2711 }
2712 }
2713 }
2714 // Store this for later in case we get turned into a separate body
2715 m_angularlocks = newLocks;
2716 }
2717
2718 private void changeLink(OdePrim NewParent)
2719 {
2720 if (_parent == null && NewParent != null)
2721 {
2722 NewParent.ParentPrim(this);
2723 }
2724 else if (_parent != null)
2725 {
2726 if (_parent is OdePrim)
2727 {
2728 if (NewParent != _parent)
2729 {
2730 (_parent as OdePrim).ChildDelink(this, false); // for now...
2731 childPrim = false;
2732
2733 if (NewParent != null)
2734 {
2735 NewParent.ParentPrim(this);
2736 }
2737 }
2738 }
2739 }
2740 _parent = NewParent;
2741 }
2742
2743
2744 private void Stop()
2745 {
2746 if (!childPrim)
2747 {
2748// m_force = Vector3.Zero;
2749 m_forceacc = Vector3.Zero;
2750 m_angularForceacc = Vector3.Zero;
2751// m_torque = Vector3.Zero;
2752 _velocity = Vector3.Zero;
2753 m_acceleration = Vector3.Zero;
2754 m_rotationalVelocity = Vector3.Zero;
2755 _target_velocity = Vector3.Zero;
2756 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2757 m_vehicle.Stop();
2758
2759 _zeroFlag = false;
2760 base.RequestPhysicsterseUpdate();
2761 }
2762
2763 if (Body != IntPtr.Zero)
2764 {
2765 d.BodySetForce(Body, 0f, 0f, 0f);
2766 d.BodySetTorque(Body, 0f, 0f, 0f);
2767 d.BodySetLinearVel(Body, 0f, 0f, 0f);
2768 d.BodySetAngularVel(Body, 0f, 0f, 0f);
2769 }
2770 }
2771
2772 private void changePhantomStatus(bool newval)
2773 {
2774 m_isphantom = newval;
2775
2776 UpdateCollisionCatFlags();
2777 ApplyCollisionCatFlags();
2778 }
2779
2780/* not in use
2781 internal void ChildSelectedChange(bool childSelect)
2782 {
2783 if(childPrim)
2784 return;
2785
2786 if (childSelect == m_isSelected)
2787 return;
2788
2789 if (childSelect)
2790 {
2791 DoSelectedStatus(true);
2792 }
2793
2794 else
2795 {
2796 foreach (OdePrim prm in childrenPrim)
2797 {
2798 if (prm.m_isSelected)
2799 return;
2800 }
2801 DoSelectedStatus(false);
2802 }
2803 }
2804*/
2805 private void changeSelectedStatus(bool newval)
2806 {
2807 if (m_lastdoneSelected == newval)
2808 return;
2809
2810 m_lastdoneSelected = newval;
2811 DoSelectedStatus(newval);
2812 }
2813
2814 private void CheckDelaySelect()
2815 {
2816 if (m_delaySelect)
2817 {
2818 DoSelectedStatus(m_isSelected);
2819 }
2820 }
2821
2822 private void DoSelectedStatus(bool newval)
2823 {
2824 m_isSelected = newval;
2825 Stop();
2826
2827 if (newval)
2828 {
2829 if (!childPrim && Body != IntPtr.Zero)
2830 d.BodyDisable(Body);
2831
2832 if (m_delaySelect || m_isphysical)
2833 {
2834 m_collisionCategories = CollisionCategories.Selected;
2835 m_collisionFlags = 0;
2836
2837 if (!childPrim)
2838 {
2839 foreach (OdePrim prm in childrenPrim)
2840 {
2841 prm.m_collisionCategories = m_collisionCategories;
2842 prm.m_collisionFlags = m_collisionFlags;
2843
2844 if (prm.prim_geom != IntPtr.Zero)
2845 {
2846
2847 if (prm.m_NoColide)
2848 {
2849 d.GeomSetCategoryBits(prm.prim_geom, 0);
2850 d.GeomSetCollideBits(prm.prim_geom, 0);
2851 }
2852 else
2853 {
2854 d.GeomSetCategoryBits(prm.prim_geom, (uint)m_collisionCategories);
2855 d.GeomSetCollideBits(prm.prim_geom, (uint)m_collisionFlags);
2856 }
2857 }
2858 prm.m_delaySelect = false;
2859 }
2860 }
2861// else if (_parent != null)
2862// ((OdePrim)_parent).ChildSelectedChange(true);
2863
2864
2865 if (prim_geom != IntPtr.Zero)
2866 {
2867 if (m_NoColide)
2868 {
2869 d.GeomSetCategoryBits(prim_geom, 0);
2870 d.GeomSetCollideBits(prim_geom, 0);
2871 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
2872 {
2873 d.GeomSetCategoryBits(collide_geom, 0);
2874 d.GeomSetCollideBits(collide_geom, 0);
2875 }
2876
2877 }
2878 else
2879 {
2880 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
2881 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
2882 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
2883 {
2884 d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories);
2885 d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags);
2886 }
2887 }
2888 }
2889
2890 m_delaySelect = false;
2891 }
2892 else if(!m_isphysical)
2893 {
2894 m_delaySelect = true;
2895 }
2896 }
2897 else
2898 {
2899 if (!childPrim)
2900 {
2901 if (Body != IntPtr.Zero && !m_disabled)
2902 {
2903 _zeroFlag = true;
2904 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
2905 d.BodyEnable(Body);
2906 }
2907 }
2908// else if (_parent != null)
2909// ((OdePrim)_parent).ChildSelectedChange(false);
2910
2911 UpdateCollisionCatFlags();
2912 ApplyCollisionCatFlags();
2913
2914 m_delaySelect = false;
2915 }
2916
2917 resetCollisionAccounting();
2918 }
2919
2920 private void changePosition(Vector3 newPos)
2921 {
2922 CheckDelaySelect();
2923 if (m_isphysical)
2924 {
2925 if (childPrim) // inertia is messed, must rebuild
2926 {
2927 if (m_building)
2928 {
2929 _position = newPos;
2930 }
2931
2932 else if (m_forcePosOrRotation && _position != newPos && Body != IntPtr.Zero)
2933 {
2934 FixInertia(newPos);
2935 if (!d.BodyIsEnabled(Body))
2936 {
2937 _zeroFlag = true;
2938 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
2939 d.BodyEnable(Body);
2940 }
2941 }
2942 }
2943 else
2944 {
2945 if (_position != newPos)
2946 {
2947 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2948 _position = newPos;
2949 }
2950 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2951 {
2952 _zeroFlag = true;
2953 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
2954 d.BodyEnable(Body);
2955 }
2956 }
2957 }
2958 else
2959 {
2960 if (prim_geom != IntPtr.Zero)
2961 {
2962 if (newPos != _position)
2963 {
2964 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2965 _position = newPos;
2966
2967 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2968 }
2969 }
2970 }
2971 givefakepos--;
2972 if (givefakepos < 0)
2973 givefakepos = 0;
2974// changeSelectedStatus();
2975 resetCollisionAccounting();
2976 }
2977
2978 private void changeOrientation(Quaternion newOri)
2979 {
2980 CheckDelaySelect();
2981 if (m_isphysical)
2982 {
2983 if (childPrim) // inertia is messed, must rebuild
2984 {
2985 if (m_building)
2986 {
2987 _orientation = newOri;
2988 }
2989/*
2990 else if (m_forcePosOrRotation && _orientation != newOri && Body != IntPtr.Zero)
2991 {
2992 FixInertia(_position, newOri);
2993 if (!d.BodyIsEnabled(Body))
2994 d.BodyEnable(Body);
2995 }
2996*/
2997 }
2998 else
2999 {
3000 if (newOri != _orientation)
3001 {
3002 d.Quaternion myrot = new d.Quaternion();
3003 myrot.X = newOri.X;
3004 myrot.Y = newOri.Y;
3005 myrot.Z = newOri.Z;
3006 myrot.W = newOri.W;
3007 d.GeomSetQuaternion(prim_geom, ref myrot);
3008 _orientation = newOri;
3009
3010 if (Body != IntPtr.Zero)
3011 {
3012 if(m_angularlocks != 0)
3013 createAMotor(m_angularlocks);
3014 }
3015 }
3016 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
3017 {
3018 _zeroFlag = true;
3019 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
3020 d.BodyEnable(Body);
3021 }
3022 }
3023 }
3024 else
3025 {
3026 if (prim_geom != IntPtr.Zero)
3027 {
3028 if (newOri != _orientation)
3029 {
3030 d.Quaternion myrot = new d.Quaternion();
3031 myrot.X = newOri.X;
3032 myrot.Y = newOri.Y;
3033 myrot.Z = newOri.Z;
3034 myrot.W = newOri.W;
3035 d.GeomSetQuaternion(prim_geom, ref myrot);
3036 _orientation = newOri;
3037 }
3038 }
3039 }
3040 givefakeori--;
3041 if (givefakeori < 0)
3042 givefakeori = 0;
3043 resetCollisionAccounting();
3044 }
3045
3046 private void changePositionAndOrientation(Vector3 newPos, Quaternion newOri)
3047 {
3048 CheckDelaySelect();
3049 if (m_isphysical)
3050 {
3051 if (childPrim && m_building) // inertia is messed, must rebuild
3052 {
3053 _position = newPos;
3054 _orientation = newOri;
3055 }
3056 else
3057 {
3058 if (newOri != _orientation)
3059 {
3060 d.Quaternion myrot = new d.Quaternion();
3061 myrot.X = newOri.X;
3062 myrot.Y = newOri.Y;
3063 myrot.Z = newOri.Z;
3064 myrot.W = newOri.W;
3065 d.GeomSetQuaternion(prim_geom, ref myrot);
3066 _orientation = newOri;
3067 if (Body != IntPtr.Zero && m_angularlocks != 0)
3068 createAMotor(m_angularlocks);
3069 }
3070 if (_position != newPos)
3071 {
3072 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
3073 _position = newPos;
3074 }
3075 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
3076 {
3077 _zeroFlag = true;
3078 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
3079 d.BodyEnable(Body);
3080 }
3081 }
3082 }
3083 else
3084 {
3085 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
3086 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
3087
3088 if (prim_geom != IntPtr.Zero)
3089 {
3090 if (newOri != _orientation)
3091 {
3092 d.Quaternion myrot = new d.Quaternion();
3093 myrot.X = newOri.X;
3094 myrot.Y = newOri.Y;
3095 myrot.Z = newOri.Z;
3096 myrot.W = newOri.W;
3097 d.GeomSetQuaternion(prim_geom, ref myrot);
3098 _orientation = newOri;
3099 }
3100
3101 if (newPos != _position)
3102 {
3103 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
3104 _position = newPos;
3105
3106 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
3107 }
3108 }
3109 }
3110 givefakepos--;
3111 if (givefakepos < 0)
3112 givefakepos = 0;
3113 givefakeori--;
3114 if (givefakeori < 0)
3115 givefakeori = 0;
3116 resetCollisionAccounting();
3117 }
3118
3119 private void changeDisable(bool disable)
3120 {
3121 if (disable)
3122 {
3123 if (!m_disabled)
3124 disableBodySoft();
3125 }
3126 else
3127 {
3128 if (m_disabled)
3129 enableBodySoft();
3130 }
3131 }
3132
3133 private void changePhysicsStatus(bool NewStatus)
3134 {
3135 CheckDelaySelect();
3136
3137 m_isphysical = NewStatus;
3138
3139 if (!childPrim)
3140 {
3141 if (NewStatus)
3142 {
3143 if (Body == IntPtr.Zero)
3144 MakeBody();
3145 }
3146 else
3147 {
3148 if (Body != IntPtr.Zero)
3149 {
3150 DestroyBody();
3151 }
3152 Stop();
3153 }
3154 }
3155
3156 resetCollisionAccounting();
3157 }
3158
3159 private void changeSize(Vector3 newSize)
3160 {
3161 }
3162
3163 private void changeShape(PrimitiveBaseShape newShape)
3164 {
3165 }
3166
3167 private void changeAddPhysRep(ODEPhysRepData repData)
3168 {
3169 _size = repData.size; //??
3170 _pbs = repData.pbs;
3171
3172 m_mesh = repData.mesh;
3173
3174 m_assetID = repData.assetID;
3175 m_meshState = repData.meshState;
3176
3177 m_hasOBB = repData.hasOBB;
3178 m_OBBOffset = repData.OBBOffset;
3179 m_OBB = repData.OBB;
3180
3181 primVolume = repData.volume;
3182
3183 CreateGeom(repData.isTooSmall);
3184
3185 if (prim_geom != IntPtr.Zero)
3186 {
3187 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3188 d.Quaternion myrot = new d.Quaternion();
3189 myrot.X = _orientation.X;
3190 myrot.Y = _orientation.Y;
3191 myrot.Z = _orientation.Z;
3192 myrot.W = _orientation.W;
3193 d.GeomSetQuaternion(prim_geom, ref myrot);
3194 }
3195
3196 if (!m_isphysical)
3197 {
3198 SetInStaticSpace(this);
3199 UpdateCollisionCatFlags();
3200 ApplyCollisionCatFlags();
3201 }
3202 else
3203 MakeBody();
3204
3205 if ((m_meshState & MeshState.NeedMask) != 0)
3206 {
3207 repData.size = _size;
3208 repData.pbs = _pbs;
3209 repData.shapetype = m_fakeShapetype;
3210 _parent_scene.m_meshWorker.RequestMesh(repData);
3211 }
3212 else
3213 m_shapetype = repData.shapetype;
3214 }
3215
3216 private void changePhysRepData(ODEPhysRepData repData)
3217 {
3218 if(_size == repData.size &&
3219 _pbs == repData.pbs &&
3220 m_shapetype == repData.shapetype &&
3221 m_mesh == repData.mesh &&
3222 primVolume == repData.volume)
3223 return;
3224
3225 CheckDelaySelect();
3226
3227 OdePrim parent = (OdePrim)_parent;
3228
3229 bool chp = childPrim;
3230
3231 if (chp)
3232 {
3233 if (parent != null)
3234 {
3235 parent.DestroyBody();
3236 }
3237 }
3238 else
3239 {
3240 DestroyBody();
3241 }
3242
3243 RemoveGeom();
3244
3245 _size = repData.size;
3246 _pbs = repData.pbs;
3247
3248 m_mesh = repData.mesh;
3249
3250 m_assetID = repData.assetID;
3251 m_meshState = repData.meshState;
3252
3253 m_hasOBB = repData.hasOBB;
3254 m_OBBOffset = repData.OBBOffset;
3255 m_OBB = repData.OBB;
3256
3257 primVolume = repData.volume;
3258
3259 CreateGeom(repData.isTooSmall);
3260
3261 if (prim_geom != IntPtr.Zero)
3262 {
3263 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3264 d.Quaternion myrot = new d.Quaternion();
3265 myrot.X = _orientation.X;
3266 myrot.Y = _orientation.Y;
3267 myrot.Z = _orientation.Z;
3268 myrot.W = _orientation.W;
3269 d.GeomSetQuaternion(prim_geom, ref myrot);
3270 }
3271
3272 if (m_isphysical)
3273 {
3274 if (chp)
3275 {
3276 if (parent != null)
3277 {
3278 parent.MakeBody();
3279 }
3280 }
3281 else
3282 MakeBody();
3283 }
3284 else
3285 {
3286 SetInStaticSpace(this);
3287 UpdateCollisionCatFlags();
3288 ApplyCollisionCatFlags();
3289 }
3290
3291 resetCollisionAccounting();
3292
3293 if ((m_meshState & MeshState.NeedMask) != 0)
3294 {
3295 repData.size = _size;
3296 repData.pbs = _pbs;
3297 repData.shapetype = m_fakeShapetype;
3298 _parent_scene.m_meshWorker.RequestMesh(repData);
3299 }
3300 else
3301 m_shapetype = repData.shapetype;
3302 }
3303
3304 private void changeFloatOnWater(bool newval)
3305 {
3306 m_collidesWater = newval;
3307
3308 UpdateCollisionCatFlags();
3309 ApplyCollisionCatFlags();
3310 }
3311
3312 private void changeSetTorque(Vector3 newtorque)
3313 {
3314 if (!m_isSelected && !m_outbounds)
3315 {
3316 if (m_isphysical && Body != IntPtr.Zero)
3317 {
3318 if (m_disabled)
3319 enableBodySoft();
3320 else if (!d.BodyIsEnabled(Body))
3321 {
3322 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
3323 d.BodyEnable(Body);
3324 }
3325 }
3326 m_torque = newtorque;
3327 }
3328 }
3329
3330 private void changeForce(Vector3 force)
3331 {
3332 m_force = force;
3333 if (!m_isSelected && !m_outbounds && Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
3334 {
3335 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
3336 d.BodyEnable(Body);
3337 }
3338 }
3339
3340 private void changeAddForce(Vector3 theforce)
3341 {
3342 m_forceacc += theforce;
3343 if (!m_isSelected && !m_outbounds)
3344 {
3345 lock (this)
3346 {
3347 //m_log.Info("[PHYSICS]: dequeing forcelist");
3348 if (m_isphysical && Body != IntPtr.Zero)
3349 {
3350 if (m_disabled)
3351 enableBodySoft();
3352 else if (!d.BodyIsEnabled(Body))
3353 {
3354 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
3355 d.BodyEnable(Body);
3356 }
3357 }
3358 }
3359 m_collisionscore = 0;
3360 }
3361 }
3362
3363 // actually angular impulse
3364 private void changeAddAngularImpulse(Vector3 aimpulse)
3365 {
3366 m_angularForceacc += aimpulse * m_invTimeStep;
3367 if (!m_isSelected && !m_outbounds)
3368 {
3369 lock (this)
3370 {
3371 if (m_isphysical && Body != IntPtr.Zero)
3372 {
3373 if (m_disabled)
3374 enableBodySoft();
3375 else if (!d.BodyIsEnabled(Body))
3376 {
3377 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
3378 d.BodyEnable(Body);
3379 }
3380 }
3381 }
3382 m_collisionscore = 0;
3383 }
3384 }
3385
3386 private void changevelocity(Vector3 newVel)
3387 {
3388 float len = newVel.LengthSquared();
3389 if (len > 100000.0f) // limit to 100m/s
3390 {
3391 len = 100.0f / (float)Math.Sqrt(len);
3392 newVel *= len;
3393 }
3394
3395 if (!m_isSelected && !m_outbounds)
3396 {
3397 if (Body != IntPtr.Zero)
3398 {
3399 if (m_disabled)
3400 enableBodySoft();
3401 else if (!d.BodyIsEnabled(Body))
3402 {
3403 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
3404 d.BodyEnable(Body);
3405 }
3406 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
3407 }
3408 //resetCollisionAccounting();
3409 }
3410 _velocity = newVel;
3411 }
3412
3413 private void changeangvelocity(Vector3 newAngVel)
3414 {
3415 float len = newAngVel.LengthSquared();
3416 if (len > _parent_scene.maxAngVelocitySQ)
3417 {
3418 len = _parent_scene.maximumAngularVelocity / (float)Math.Sqrt(len);
3419 newAngVel *= len;
3420 }
3421
3422 if (!m_isSelected && !m_outbounds)
3423 {
3424 if (Body != IntPtr.Zero)
3425 {
3426 if (m_disabled)
3427 enableBodySoft();
3428 else if (!d.BodyIsEnabled(Body))
3429 {
3430 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
3431 d.BodyEnable(Body);
3432 }
3433 d.BodySetAngularVel(Body, newAngVel.X, newAngVel.Y, newAngVel.Z);
3434 }
3435 //resetCollisionAccounting();
3436 }
3437 m_rotationalVelocity = newAngVel;
3438 }
3439
3440 private void changeVolumedetetion(bool newVolDtc)
3441 {
3442 m_isVolumeDetect = newVolDtc;
3443 m_fakeisVolumeDetect = newVolDtc;
3444 UpdateCollisionCatFlags();
3445 ApplyCollisionCatFlags();
3446 }
3447
3448 protected void changeBuilding(bool newbuilding)
3449 {
3450 // Check if we need to do anything
3451 if (newbuilding == m_building)
3452 return;
3453
3454 if ((bool)newbuilding)
3455 {
3456 m_building = true;
3457 if (!childPrim)
3458 DestroyBody();
3459 }
3460 else
3461 {
3462 m_building = false;
3463 CheckDelaySelect();
3464 if (!childPrim)
3465 MakeBody();
3466 }
3467 if (!childPrim && childrenPrim.Count > 0)
3468 {
3469 foreach (OdePrim prm in childrenPrim)
3470 prm.changeBuilding(m_building); // call directly
3471 }
3472 }
3473
3474 public void changeSetVehicle(VehicleData vdata)
3475 {
3476 if (m_vehicle == null)
3477 m_vehicle = new ODEDynamics(this);
3478 m_vehicle.DoSetVehicle(vdata);
3479 }
3480
3481 private void changeVehicleType(int value)
3482 {
3483 if (value == (int)Vehicle.TYPE_NONE)
3484 {
3485 if (m_vehicle != null)
3486 m_vehicle = null;
3487 }
3488 else
3489 {
3490 if (m_vehicle == null)
3491 m_vehicle = new ODEDynamics(this);
3492
3493 m_vehicle.ProcessTypeChange((Vehicle)value);
3494 }
3495 }
3496
3497 private void changeVehicleFloatParam(strVehicleFloatParam fp)
3498 {
3499 if (m_vehicle == null)
3500 return;
3501
3502 m_vehicle.ProcessFloatVehicleParam((Vehicle)fp.param, fp.value);
3503 }
3504
3505 private void changeVehicleVectorParam(strVehicleVectorParam vp)
3506 {
3507 if (m_vehicle == null)
3508 return;
3509 m_vehicle.ProcessVectorVehicleParam((Vehicle)vp.param, vp.value);
3510 }
3511
3512 private void changeVehicleRotationParam(strVehicleQuatParam qp)
3513 {
3514 if (m_vehicle == null)
3515 return;
3516 m_vehicle.ProcessRotationVehicleParam((Vehicle)qp.param, qp.value);
3517 }
3518
3519 private void changeVehicleFlags(strVehicleBoolParam bp)
3520 {
3521 if (m_vehicle == null)
3522 return;
3523 m_vehicle.ProcessVehicleFlags(bp.param, bp.value);
3524 }
3525
3526 private void changeBuoyancy(float b)
3527 {
3528 m_buoyancy = b;
3529 }
3530
3531 private void changePIDTarget(Vector3 trg)
3532 {
3533 m_PIDTarget = trg;
3534 }
3535
3536 private void changePIDTau(float tau)
3537 {
3538 m_PIDTau = tau;
3539 }
3540
3541 private void changePIDActive(bool val)
3542 {
3543 m_usePID = val;
3544 }
3545
3546 private void changePIDHoverHeight(float val)
3547 {
3548 m_PIDHoverHeight = val;
3549 if (val == 0)
3550 m_useHoverPID = false;
3551 }
3552
3553 private void changePIDHoverType(PIDHoverType type)
3554 {
3555 m_PIDHoverType = type;
3556 }
3557
3558 private void changePIDHoverTau(float tau)
3559 {
3560 m_PIDHoverTau = tau;
3561 }
3562
3563 private void changePIDHoverActive(bool active)
3564 {
3565 m_useHoverPID = active;
3566 }
3567
3568 private void changeInertia(PhysicsInertiaData inertia)
3569 {
3570 m_InertiaOverride = inertia;
3571
3572 if (Body != IntPtr.Zero)
3573 DestroyBody();
3574 MakeBody();
3575 }
3576
3577 #endregion
3578
3579 public void Move()
3580 {
3581 if (!childPrim && m_isphysical && Body != IntPtr.Zero &&
3582 !m_disabled && !m_isSelected && !m_building && !m_outbounds)
3583 {
3584 if (!d.BodyIsEnabled(Body))
3585 {
3586 // let vehicles sleep
3587 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3588 return;
3589
3590 if (++m_bodydisablecontrol < 50)
3591 return;
3592
3593 // clear residuals
3594 d.BodySetAngularVel(Body,0f,0f,0f);
3595 d.BodySetLinearVel(Body,0f,0f,0f);
3596 _zeroFlag = true;
3597 d.BodySetAutoDisableSteps(Body, 1);
3598 d.BodyEnable(Body);
3599 m_bodydisablecontrol = -3;
3600 }
3601
3602 if(m_bodydisablecontrol < 0)
3603 m_bodydisablecontrol++;
3604
3605 d.Vector3 lpos = d.GeomGetPosition(prim_geom); // root position that is seem by rest of simulator
3606
3607 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3608 {
3609 // 'VEHICLES' are dealt with in ODEDynamics.cs
3610 m_vehicle.Step();
3611 return;
3612 }
3613
3614 float fx = 0;
3615 float fy = 0;
3616 float fz = 0;
3617
3618 float mass = m_mass;
3619
3620 if (m_usePID && m_PIDTau > 0)
3621 {
3622 // for now position error
3623 _target_velocity =
3624 new Vector3(
3625 (m_PIDTarget.X - lpos.X),
3626 (m_PIDTarget.Y - lpos.Y),
3627 (m_PIDTarget.Z - lpos.Z)
3628 );
3629
3630 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.02f))
3631 {
3632 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
3633 d.BodySetLinearVel(Body, 0, 0, 0);
3634 return;
3635 }
3636 else
3637 {
3638 _zeroFlag = false;
3639
3640 float tmp = 1 / m_PIDTau;
3641 _target_velocity *= tmp;
3642
3643 // apply limits
3644 tmp = _target_velocity.Length();
3645 if (tmp > 50.0f)
3646 {
3647 tmp = 50 / tmp;
3648 _target_velocity *= tmp;
3649 }
3650 else if (tmp < 0.05f)
3651 {
3652 tmp = 0.05f / tmp;
3653 _target_velocity *= tmp;
3654 }
3655
3656 d.Vector3 vel = d.BodyGetLinearVel(Body);
3657 fx = (_target_velocity.X - vel.X) * m_invTimeStep;
3658 fy = (_target_velocity.Y - vel.Y) * m_invTimeStep;
3659 fz = (_target_velocity.Z - vel.Z) * m_invTimeStep;
3660// d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z);
3661 }
3662 } // end if (m_usePID)
3663
3664 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
3665 else if (m_useHoverPID && m_PIDHoverTau != 0 && m_PIDHoverHeight != 0)
3666 {
3667
3668 // Non-Vehicles have a limited set of Hover options.
3669 // determine what our target height really is based on HoverType
3670
3671 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(lpos.X, lpos.Y);
3672
3673 switch (m_PIDHoverType)
3674 {
3675 case PIDHoverType.Ground:
3676 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3677 break;
3678
3679 case PIDHoverType.GroundAndWater:
3680 m_waterHeight = _parent_scene.GetWaterLevel();
3681 if (m_groundHeight > m_waterHeight)
3682 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3683 else
3684 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
3685 break;
3686 } // end switch (m_PIDHoverType)
3687
3688 // don't go underground unless volumedetector
3689
3690 if (m_targetHoverHeight > m_groundHeight || m_isVolumeDetect)
3691 {
3692 d.Vector3 vel = d.BodyGetLinearVel(Body);
3693
3694 fz = (m_targetHoverHeight - lpos.Z);
3695
3696 // if error is zero, use position control; otherwise, velocity control
3697 if (Math.Abs(fz) < 0.01f)
3698 {
3699 d.BodySetPosition(Body, lpos.X, lpos.Y, m_targetHoverHeight);
3700 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
3701 }
3702 else
3703 {
3704 _zeroFlag = false;
3705 fz /= m_PIDHoverTau;
3706
3707 float tmp = Math.Abs(fz);
3708 if (tmp > 50)
3709 fz = 50 * Math.Sign(fz);
3710 else if (tmp < 0.1)
3711 fz = 0.1f * Math.Sign(fz);
3712
3713 fz = ((fz - vel.Z) * m_invTimeStep);
3714 }
3715 }
3716 }
3717 else
3718 {
3719 float b = (1.0f - m_buoyancy) * m_gravmod;
3720 fx = _parent_scene.gravityx * b;
3721 fy = _parent_scene.gravityy * b;
3722 fz = _parent_scene.gravityz * b;
3723 }
3724
3725 fx *= mass;
3726 fy *= mass;
3727 fz *= mass;
3728
3729 // constant force
3730 fx += m_force.X;
3731 fy += m_force.Y;
3732 fz += m_force.Z;
3733
3734 fx += m_forceacc.X;
3735 fy += m_forceacc.Y;
3736 fz += m_forceacc.Z;
3737
3738 m_forceacc = Vector3.Zero;
3739
3740 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
3741 if (fx != 0 || fy != 0 || fz != 0)
3742 {
3743 d.BodyAddForce(Body, fx, fy, fz);
3744 //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz);
3745 }
3746
3747 Vector3 trq;
3748
3749 trq = m_torque;
3750 trq += m_angularForceacc;
3751 m_angularForceacc = Vector3.Zero;
3752 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0)
3753 {
3754 d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z);
3755 }
3756 }
3757 else
3758 { // is not physical, or is not a body or is selected
3759 // _zeroPosition = d.BodyGetPosition(Body);
3760 return;
3761 //Console.WriteLine("Nothing " + Name);
3762
3763 }
3764 }
3765
3766 public void UpdatePositionAndVelocity(int frame)
3767 {
3768 if (_parent == null && !m_isSelected && !m_disabled && !m_building && !m_outbounds && Body != IntPtr.Zero)
3769 {
3770 if(m_bodydisablecontrol < 0)
3771 return;
3772
3773 bool bodyenabled = d.BodyIsEnabled(Body);
3774 if (bodyenabled || !_zeroFlag)
3775 {
3776 bool lastZeroFlag = _zeroFlag;
3777
3778 d.Vector3 lpos = d.GeomGetPosition(prim_geom);
3779
3780 // check outside region
3781 if (lpos.Z < -100 || lpos.Z > 100000f)
3782 {
3783 m_outbounds = true;
3784
3785 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f);
3786 m_acceleration.X = 0;
3787 m_acceleration.Y = 0;
3788 m_acceleration.Z = 0;
3789
3790 _velocity.X = 0;
3791 _velocity.Y = 0;
3792 _velocity.Z = 0;
3793 m_rotationalVelocity.X = 0;
3794 m_rotationalVelocity.Y = 0;
3795 m_rotationalVelocity.Z = 0;
3796
3797 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3798 d.BodySetAngularVel(Body, 0, 0, 0); // stop it
3799 d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere
3800 m_lastposition = _position;
3801 m_lastorientation = _orientation;
3802
3803 base.RequestPhysicsterseUpdate();
3804
3805// throttleCounter = 0;
3806 _zeroFlag = true;
3807
3808 disableBodySoft(); // disable it and colisions
3809 base.RaiseOutOfBounds(_position);
3810 return;
3811 }
3812
3813 if (lpos.X < 0f)
3814 {
3815 _position.X = Util.Clip(lpos.X, -2f, -0.1f);
3816 m_outbounds = true;
3817 }
3818 else if (lpos.X > _parent_scene.WorldExtents.X)
3819 {
3820 _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
3821 m_outbounds = true;
3822 }
3823 if (lpos.Y < 0f)
3824 {
3825 _position.Y = Util.Clip(lpos.Y, -2f, -0.1f);
3826 m_outbounds = true;
3827 }
3828 else if (lpos.Y > _parent_scene.WorldExtents.Y)
3829 {
3830 _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
3831 m_outbounds = true;
3832 }
3833
3834 if (m_outbounds)
3835 {
3836 m_lastposition = _position;
3837 m_lastorientation = _orientation;
3838
3839 d.Vector3 dtmp = d.BodyGetAngularVel(Body);
3840 m_rotationalVelocity.X = dtmp.X;
3841 m_rotationalVelocity.Y = dtmp.Y;
3842 m_rotationalVelocity.Z = dtmp.Z;
3843
3844 dtmp = d.BodyGetLinearVel(Body);
3845 _velocity.X = dtmp.X;
3846 _velocity.Y = dtmp.Y;
3847 _velocity.Z = dtmp.Z;
3848
3849 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3850 d.BodySetAngularVel(Body, 0, 0, 0);
3851 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3852 disableBodySoft(); // stop collisions
3853 UnSubscribeEvents();
3854
3855 base.RequestPhysicsterseUpdate();
3856 return;
3857 }
3858
3859 d.Quaternion ori;
3860 d.GeomCopyQuaternion(prim_geom, out ori);
3861
3862 // decide if moving
3863 // use positions since this are integrated quantities
3864 // tolerance values depende a lot on simulation noise...
3865 // use simple math.abs since we dont need to be exact
3866 if(!bodyenabled)
3867 {
3868 _zeroFlag = true;
3869 }
3870 else
3871 {
3872 float poserror;
3873 float angerror;
3874 if(_zeroFlag)
3875 {
3876 poserror = 0.01f;
3877 angerror = 0.001f;
3878 }
3879 else
3880 {
3881 poserror = 0.005f;
3882 angerror = 0.0005f;
3883 }
3884
3885 if (
3886 (Math.Abs(_position.X - lpos.X) < poserror)
3887 && (Math.Abs(_position.Y - lpos.Y) < poserror)
3888 && (Math.Abs(_position.Z - lpos.Z) < poserror)
3889 && (Math.Abs(_orientation.X - ori.X) < angerror)
3890 && (Math.Abs(_orientation.Y - ori.Y) < angerror)
3891 && (Math.Abs(_orientation.Z - ori.Z) < angerror) // ignore W
3892 )
3893 _zeroFlag = true;
3894 else
3895 _zeroFlag = false;
3896 }
3897
3898 // update position
3899 if (!(_zeroFlag && lastZeroFlag))
3900 {
3901 _position.X = lpos.X;
3902 _position.Y = lpos.Y;
3903 _position.Z = lpos.Z;
3904
3905 _orientation.X = ori.X;
3906 _orientation.Y = ori.Y;
3907 _orientation.Z = ori.Z;
3908 _orientation.W = ori.W;
3909 }
3910
3911 // update velocities and acceleration
3912 if (_zeroFlag || lastZeroFlag)
3913 {
3914 // disable interpolators
3915 _velocity = Vector3.Zero;
3916 m_acceleration = Vector3.Zero;
3917 m_rotationalVelocity = Vector3.Zero;
3918 }
3919 else
3920 {
3921 d.Vector3 vel = d.BodyGetLinearVel(Body);
3922
3923 m_acceleration = _velocity;
3924
3925 if ((Math.Abs(vel.X) < 0.005f) &&
3926 (Math.Abs(vel.Y) < 0.005f) &&
3927 (Math.Abs(vel.Z) < 0.005f))
3928 {
3929 _velocity = Vector3.Zero;
3930 float t = -m_invTimeStep;
3931 m_acceleration = m_acceleration * t;
3932 }
3933 else
3934 {
3935 _velocity.X = vel.X;
3936 _velocity.Y = vel.Y;
3937 _velocity.Z = vel.Z;
3938 m_acceleration = (_velocity - m_acceleration) * m_invTimeStep;
3939 }
3940
3941 if ((Math.Abs(m_acceleration.X) < 0.01f) &&
3942 (Math.Abs(m_acceleration.Y) < 0.01f) &&
3943 (Math.Abs(m_acceleration.Z) < 0.01f))
3944 {
3945 m_acceleration = Vector3.Zero;
3946 }
3947
3948 vel = d.BodyGetAngularVel(Body);
3949 if ((Math.Abs(vel.X) < 0.0001) &&
3950 (Math.Abs(vel.Y) < 0.0001) &&
3951 (Math.Abs(vel.Z) < 0.0001)
3952 )
3953 {
3954 m_rotationalVelocity = Vector3.Zero;
3955 }
3956 else
3957 {
3958 m_rotationalVelocity.X = vel.X;
3959 m_rotationalVelocity.Y = vel.Y;
3960 m_rotationalVelocity.Z = vel.Z;
3961 }
3962 }
3963
3964 if (_zeroFlag)
3965 {
3966 if (!m_lastUpdateSent)
3967 {
3968 base.RequestPhysicsterseUpdate();
3969 if (lastZeroFlag)
3970 m_lastUpdateSent = true;
3971 }
3972 return;
3973 }
3974
3975 base.RequestPhysicsterseUpdate();
3976 m_lastUpdateSent = false;
3977 }
3978 }
3979 }
3980
3981 internal static bool QuaternionIsFinite(Quaternion q)
3982 {
3983 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
3984 return false;
3985 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
3986 return false;
3987 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
3988 return false;
3989 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
3990 return false;
3991 return true;
3992 }
3993
3994 internal static void DMassSubPartFromObj(ref d.Mass part, ref d.Mass theobj)
3995 {
3996 // assumes object center of mass is zero
3997 float smass = part.mass;
3998 theobj.mass -= smass;
3999
4000 smass *= 1.0f / (theobj.mass); ;
4001
4002 theobj.c.X -= part.c.X * smass;
4003 theobj.c.Y -= part.c.Y * smass;
4004 theobj.c.Z -= part.c.Z * smass;
4005
4006 theobj.I.M00 -= part.I.M00;
4007 theobj.I.M01 -= part.I.M01;
4008 theobj.I.M02 -= part.I.M02;
4009 theobj.I.M10 -= part.I.M10;
4010 theobj.I.M11 -= part.I.M11;
4011 theobj.I.M12 -= part.I.M12;
4012 theobj.I.M20 -= part.I.M20;
4013 theobj.I.M21 -= part.I.M21;
4014 theobj.I.M22 -= part.I.M22;
4015 }
4016
4017 private void donullchange()
4018 {
4019 }
4020
4021 public bool DoAChange(changes what, object arg)
4022 {
4023 if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.AddPhysRep && what != changes.Remove)
4024 {
4025 return false;
4026 }
4027
4028 // nasty switch
4029 switch (what)
4030 {
4031 case changes.Add:
4032 changeadd();
4033 break;
4034
4035 case changes.AddPhysRep:
4036 changeAddPhysRep((ODEPhysRepData)arg);
4037 break;
4038
4039 case changes.Remove:
4040 //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff...
4041 //When we return true, it destroys all of the prims in the linkset anyway
4042 if (_parent != null)
4043 {
4044 OdePrim parent = (OdePrim)_parent;
4045 parent.ChildRemove(this, false);
4046 }
4047 else
4048 ChildRemove(this, false);
4049
4050 m_vehicle = null;
4051 RemoveGeom();
4052 m_targetSpace = IntPtr.Zero;
4053 UnSubscribeEvents();
4054 return true;
4055
4056 case changes.Link:
4057 OdePrim tmp = (OdePrim)arg;
4058 changeLink(tmp);
4059 break;
4060
4061 case changes.DeLink:
4062 changeLink(null);
4063 break;
4064
4065 case changes.Position:
4066 changePosition((Vector3)arg);
4067 break;
4068
4069 case changes.Orientation:
4070 changeOrientation((Quaternion)arg);
4071 break;
4072
4073 case changes.PosOffset:
4074 donullchange();
4075 break;
4076
4077 case changes.OriOffset:
4078 donullchange();
4079 break;
4080
4081 case changes.Velocity:
4082 changevelocity((Vector3)arg);
4083 break;
4084
4085 case changes.TargetVelocity:
4086 break;
4087
4088// case changes.Acceleration:
4089// changeacceleration((Vector3)arg);
4090// break;
4091
4092 case changes.AngVelocity:
4093 changeangvelocity((Vector3)arg);
4094 break;
4095
4096 case changes.Force:
4097 changeForce((Vector3)arg);
4098 break;
4099
4100 case changes.Torque:
4101 changeSetTorque((Vector3)arg);
4102 break;
4103
4104 case changes.AddForce:
4105 changeAddForce((Vector3)arg);
4106 break;
4107
4108 case changes.AddAngForce:
4109 changeAddAngularImpulse((Vector3)arg);
4110 break;
4111
4112 case changes.AngLock:
4113 changeAngularLock((byte)arg);
4114 break;
4115
4116 case changes.Size:
4117 changeSize((Vector3)arg);
4118 break;
4119
4120 case changes.Shape:
4121 changeShape((PrimitiveBaseShape)arg);
4122 break;
4123
4124 case changes.PhysRepData:
4125 changePhysRepData((ODEPhysRepData) arg);
4126 break;
4127
4128 case changes.CollidesWater:
4129 changeFloatOnWater((bool)arg);
4130 break;
4131
4132 case changes.VolumeDtc:
4133 changeVolumedetetion((bool)arg);
4134 break;
4135
4136 case changes.Phantom:
4137 changePhantomStatus((bool)arg);
4138 break;
4139
4140 case changes.Physical:
4141 changePhysicsStatus((bool)arg);
4142 break;
4143
4144 case changes.Selected:
4145 changeSelectedStatus((bool)arg);
4146 break;
4147
4148 case changes.disabled:
4149 changeDisable((bool)arg);
4150 break;
4151
4152 case changes.building:
4153 changeBuilding((bool)arg);
4154 break;
4155
4156 case changes.VehicleType:
4157 changeVehicleType((int)arg);
4158 break;
4159
4160 case changes.VehicleFlags:
4161 changeVehicleFlags((strVehicleBoolParam) arg);
4162 break;
4163
4164 case changes.VehicleFloatParam:
4165 changeVehicleFloatParam((strVehicleFloatParam) arg);
4166 break;
4167
4168 case changes.VehicleVectorParam:
4169 changeVehicleVectorParam((strVehicleVectorParam) arg);
4170 break;
4171
4172 case changes.VehicleRotationParam:
4173 changeVehicleRotationParam((strVehicleQuatParam) arg);
4174 break;
4175
4176 case changes.SetVehicle:
4177 changeSetVehicle((VehicleData) arg);
4178 break;
4179
4180 case changes.Buoyancy:
4181 changeBuoyancy((float)arg);
4182 break;
4183
4184 case changes.PIDTarget:
4185 changePIDTarget((Vector3)arg);
4186 break;
4187
4188 case changes.PIDTau:
4189 changePIDTau((float)arg);
4190 break;
4191
4192 case changes.PIDActive:
4193 changePIDActive((bool)arg);
4194 break;
4195
4196 case changes.PIDHoverHeight:
4197 changePIDHoverHeight((float)arg);
4198 break;
4199
4200 case changes.PIDHoverType:
4201 changePIDHoverType((PIDHoverType)arg);
4202 break;
4203
4204 case changes.PIDHoverTau:
4205 changePIDHoverTau((float)arg);
4206 break;
4207
4208 case changes.PIDHoverActive:
4209 changePIDHoverActive((bool)arg);
4210 break;
4211
4212 case changes.SetInertia:
4213 changeInertia((PhysicsInertiaData) arg);
4214 break;
4215
4216 case changes.Null:
4217 donullchange();
4218 break;
4219
4220 default:
4221 donullchange();
4222 break;
4223 }
4224 return false;
4225 }
4226
4227 public void AddChange(changes what, object arg)
4228 {
4229 _parent_scene.AddChange((PhysicsActor) this, what, arg);
4230 }
4231
4232 private struct strVehicleBoolParam
4233 {
4234 public int param;
4235 public bool value;
4236 }
4237
4238 private struct strVehicleFloatParam
4239 {
4240 public int param;
4241 public float value;
4242 }
4243
4244 private struct strVehicleQuatParam
4245 {
4246 public int param;
4247 public Quaternion value;
4248 }
4249
4250 private struct strVehicleVectorParam
4251 {
4252 public int param;
4253 public Vector3 value;
4254 }
4255 }
4256}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs b/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs
new file mode 100644
index 0000000..f671722
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs
@@ -0,0 +1,689 @@
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 {
321 Vector3 t = req.Normal * req.length;
322 float tmp = t.X * t.X + t.Y * t.Y;
323 if(tmp > 2500)
324 {
325 float tmp2 = req.length * req.length - tmp + 2500;
326 tmp2 = (float)Math.Sqrt(tmp2);
327 d.GeomRaySetLength(ray, tmp2);
328 }
329
330 }
331 d.SpaceCollide2(ray, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
332 }
333
334 if (req.callbackMethod is RaycastCallback)
335 {
336 // Define default results
337 bool hitYN = false;
338 uint hitConsumerID = 0;
339 float distance = float.MaxValue;
340 Vector3 closestcontact = Vector3.Zero;
341 Vector3 snormal = Vector3.Zero;
342
343 // Find closest contact and object.
344 lock (m_contactResults)
345 {
346 foreach (ContactResult cResult in m_contactResults)
347 {
348 if(cResult.Depth < distance)
349 {
350 closestcontact = cResult.Pos;
351 hitConsumerID = cResult.ConsumerID;
352 distance = cResult.Depth;
353 snormal = cResult.Normal;
354 }
355 }
356 m_contactResults.Clear();
357 }
358
359 if (distance > 0 && distance < float.MaxValue)
360 hitYN = true;
361 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
362 }
363 else
364 {
365 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
366 lock (m_PendingRequests)
367 {
368 cresult.AddRange(m_contactResults);
369 m_contactResults.Clear();
370 }
371 ((RayCallback)req.callbackMethod)(cresult);
372 }
373 }
374
375 private void doProbe(ODERayRequest req, IntPtr probe)
376 {
377 // Collide tests
378 if ((CurrentRayFilter & FilterActiveSpace) != 0)
379 {
380 d.SpaceCollide2(probe, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
381 d.SpaceCollide2(probe, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
382 }
383 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
384 d.SpaceCollide2(probe, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
385 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
386 d.SpaceCollide2(probe, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
387
388 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
389 lock (m_PendingRequests)
390 {
391 cresult.AddRange(m_contactResults);
392 m_contactResults.Clear();
393 }
394 if (req.callbackMethod is ProbeBoxCallback)
395 ((ProbeBoxCallback)req.callbackMethod)(cresult);
396 else if (req.callbackMethod is ProbeSphereCallback)
397 ((ProbeSphereCallback)req.callbackMethod)(cresult);
398 }
399
400 private void doPlane(ODERayRequest req,IntPtr geom)
401 {
402 // Collide tests
403 if (geom == IntPtr.Zero)
404 {
405 if ((CurrentRayFilter & FilterActiveSpace) != 0)
406 {
407 d.SpaceCollide2(Plane, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
408 d.SpaceCollide2(Plane, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
409 }
410 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
411 d.SpaceCollide2(Plane, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
412 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
413 d.SpaceCollide2(Plane, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
414 }
415 else
416 {
417 d.SpaceCollide2(Plane, geom, IntPtr.Zero, nearCallback);
418 }
419
420 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
421 lock (m_PendingRequests)
422 {
423 cresult.AddRange(m_contactResults);
424 m_contactResults.Clear();
425 }
426
427 ((ProbePlaneCallback)req.callbackMethod)(cresult);
428 }
429
430 /// <summary>
431 /// Method that actually initiates the raycast with a geom
432 /// </summary>
433 /// <param name="req"></param>
434 private void doGeomRay(ODERayRequest req, IntPtr geom)
435 {
436 // Collide test
437 d.SpaceCollide2(ray, geom, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test
438
439 if (req.callbackMethod is RaycastCallback)
440 {
441 // Define default results
442 bool hitYN = false;
443 uint hitConsumerID = 0;
444 float distance = float.MaxValue;
445 Vector3 closestcontact = Vector3.Zero;
446 Vector3 snormal = Vector3.Zero;
447
448 // Find closest contact and object.
449 lock (m_contactResults)
450 {
451 foreach (ContactResult cResult in m_contactResults)
452 {
453 if(cResult.Depth < distance )
454 {
455 closestcontact = cResult.Pos;
456 hitConsumerID = cResult.ConsumerID;
457 distance = cResult.Depth;
458 snormal = cResult.Normal;
459 }
460 }
461 m_contactResults.Clear();
462 }
463
464 if (distance > 0 && distance < float.MaxValue)
465 hitYN = true;
466
467 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
468 }
469 else
470 {
471 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
472 lock (m_PendingRequests)
473 {
474 cresult.AddRange(m_contactResults);
475 m_contactResults.Clear();
476 }
477 ((RayCallback)req.callbackMethod)(cresult);
478 }
479 }
480
481 private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
482 {
483 IntPtr ContactgeomsArray = m_scene.ContactgeomsArray;
484 if (ContactgeomsArray == IntPtr.Zero || index >= CollisionContactGeomsPerTest)
485 return false;
486
487 IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
488 newcontactgeom = (d.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(d.ContactGeom));
489 return true;
490 }
491
492 // This is the standard Near. g1 is the ray
493 private void near(IntPtr space, IntPtr g1, IntPtr g2)
494 {
495 if (g2 == IntPtr.Zero || g1 == g2)
496 return;
497
498 if (m_contactResults.Count >= CurrentMaxCount)
499 return;
500
501 if (d.GeomIsSpace(g2))
502 {
503 try
504 {
505 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
506 }
507 catch (Exception e)
508 {
509 m_log.WarnFormat("[PHYSICS Ray]: Unable to Space collide test an object: {0}", e.Message);
510 }
511 return;
512 }
513
514 int count = 0;
515 try
516 {
517 count = d.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
518 }
519 catch (Exception e)
520 {
521 m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message);
522 return;
523 }
524
525 if (count == 0)
526 return;
527/*
528 uint cat1 = d.GeomGetCategoryBits(g1);
529 uint cat2 = d.GeomGetCategoryBits(g2);
530 uint col1 = d.GeomGetCollideBits(g1);
531 uint col2 = d.GeomGetCollideBits(g2);
532*/
533
534 uint ID = 0;
535 PhysicsActor p2 = null;
536
537 m_scene.actor_name_map.TryGetValue(g2, out p2);
538
539 if (p2 == null)
540 return;
541
542 switch (p2.PhysicsActorType)
543 {
544 case (int)ActorTypes.Prim:
545
546 RayFilterFlags thisFlags;
547
548 if (p2.IsPhysical)
549 thisFlags = RayFilterFlags.physical;
550 else
551 thisFlags = RayFilterFlags.nonphysical;
552
553 if (p2.Phantom)
554 thisFlags |= RayFilterFlags.phantom;
555
556 if (p2.IsVolumeDtc)
557 thisFlags |= RayFilterFlags.volumedtc;
558
559 if ((thisFlags & CurrentRayFilter) == 0)
560 return;
561
562 ID = ((OdePrim)p2).LocalID;
563 break;
564
565 case (int)ActorTypes.Agent:
566
567 if ((CurrentRayFilter & RayFilterFlags.agent) == 0)
568 return;
569 else
570 ID = ((OdeCharacter)p2).LocalID;
571 break;
572
573 case (int)ActorTypes.Ground:
574
575 if ((CurrentRayFilter & RayFilterFlags.land) == 0)
576 return;
577 break;
578
579 case (int)ActorTypes.Water:
580
581 if ((CurrentRayFilter & RayFilterFlags.water) == 0)
582 return;
583 break;
584
585 default:
586 break;
587 }
588
589 d.ContactGeom curcontact = new d.ContactGeom();
590
591 // closestHit for now only works for meshs, so must do it for others
592 if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0)
593 {
594 // Loop all contacts, build results.
595 for (int i = 0; i < count; i++)
596 {
597 if (!GetCurContactGeom(i, ref curcontact))
598 break;
599
600 ContactResult collisionresult = new ContactResult();
601 collisionresult.ConsumerID = ID;
602 collisionresult.Pos.X = curcontact.pos.X;
603 collisionresult.Pos.Y = curcontact.pos.Y;
604 collisionresult.Pos.Z = curcontact.pos.Z;
605 collisionresult.Depth = curcontact.depth;
606 collisionresult.Normal.X = curcontact.normal.X;
607 collisionresult.Normal.Y = curcontact.normal.Y;
608 collisionresult.Normal.Z = curcontact.normal.Z;
609 lock (m_contactResults)
610 {
611 m_contactResults.Add(collisionresult);
612 if (m_contactResults.Count >= CurrentMaxCount)
613 return;
614 }
615 }
616 }
617 else
618 {
619 // keep only closest contact
620 ContactResult collisionresult = new ContactResult();
621 collisionresult.ConsumerID = ID;
622 collisionresult.Depth = float.MaxValue;
623
624 for (int i = 0; i < count; i++)
625 {
626 if (!GetCurContactGeom(i, ref curcontact))
627 break;
628
629 if (curcontact.depth < collisionresult.Depth)
630 {
631 collisionresult.Pos.X = curcontact.pos.X;
632 collisionresult.Pos.Y = curcontact.pos.Y;
633 collisionresult.Pos.Z = curcontact.pos.Z;
634 collisionresult.Depth = curcontact.depth;
635 collisionresult.Normal.X = curcontact.normal.X;
636 collisionresult.Normal.Y = curcontact.normal.Y;
637 collisionresult.Normal.Z = curcontact.normal.Z;
638 }
639 }
640
641 if (collisionresult.Depth != float.MaxValue)
642 {
643 lock (m_contactResults)
644 m_contactResults.Add(collisionresult);
645 }
646 }
647 }
648
649 /// <summary>
650 /// Dereference the creator scene so that it can be garbage collected if needed.
651 /// </summary>
652 internal void Dispose()
653 {
654 m_scene = null;
655 if (ray != IntPtr.Zero)
656 {
657 d.GeomDestroy(ray);
658 ray = IntPtr.Zero;
659 }
660 if (Box != IntPtr.Zero)
661 {
662 d.GeomDestroy(Box);
663 Box = IntPtr.Zero;
664 }
665 if (Sphere != IntPtr.Zero)
666 {
667 d.GeomDestroy(Sphere);
668 Sphere = IntPtr.Zero;
669 }
670 if (Plane != IntPtr.Zero)
671 {
672 d.GeomDestroy(Plane);
673 Plane = IntPtr.Zero;
674 }
675 }
676 }
677
678 public struct ODERayRequest
679 {
680 public PhysicsActor actor;
681 public Vector3 Origin;
682 public Vector3 Normal;
683 public int Count;
684 public float length;
685 public object callbackMethod;
686 public RayFilterFlags filter;
687 public Quaternion orientation;
688 }
689}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs
new file mode 100644
index 0000000..0b51820
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs
@@ -0,0 +1,2824 @@
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.Linq;
34using System.Reflection;
35using System.Runtime.InteropServices;
36using System.Threading;
37using System.IO;
38using System.Diagnostics;
39using log4net;
40using Nini.Config;
41using Mono.Addins;
42using OdeAPI;
43using OpenSim.Framework;
44using OpenSim.Region.Framework.Scenes;
45using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.PhysicsModules.SharedBase;
47using OpenMetaverse;
48
49namespace OpenSim.Region.PhysicsModule.ubOde
50{
51 // colision flags of things others can colide with
52 // rays, sensors, probes removed since can't be colided with
53 // The top space where things are placed provided further selection
54 // ie physical are in active space nonphysical in static
55 // this should be exclusive as possible
56
57 [Flags]
58 public enum CollisionCategories : uint
59 {
60 Disabled = 0,
61 //by 'things' types
62 Space = 0x01,
63 Geom = 0x02, // aka prim/part
64 Character = 0x04,
65 Land = 0x08,
66 Water = 0x010,
67
68 // by state
69 Phantom = 0x01000,
70 VolumeDtc = 0x02000,
71 Selected = 0x04000,
72 NoShape = 0x08000,
73
74
75 All = 0xffffffff
76 }
77
78 /// <summary>
79 /// Material type for a primitive
80 /// </summary>
81 public enum Material : int
82 {
83 /// <summary></summary>
84 Stone = 0,
85 /// <summary></summary>
86 Metal = 1,
87 /// <summary></summary>
88 Glass = 2,
89 /// <summary></summary>
90 Wood = 3,
91 /// <summary></summary>
92 Flesh = 4,
93 /// <summary></summary>
94 Plastic = 5,
95 /// <summary></summary>
96 Rubber = 6,
97
98 light = 7 // compatibility with old viewers
99 }
100
101 public enum changes : int
102 {
103 Add = 0, // arg null. finishs the prim creation. should be used internally only ( to remove later ?)
104 Remove,
105 Link, // arg AuroraODEPrim new parent prim or null to delink. Makes the prim part of a object with prim parent as root
106 // or removes from a object if arg is null
107 DeLink,
108 Position, // arg Vector3 new position in world coords. Changes prim position. Prim must know if it is root or child
109 Orientation, // arg Quaternion new orientation in world coords. Changes prim position. Prim must know it it is root or child
110 PosOffset, // not in use
111 // arg Vector3 new position in local coords. Changes prim position in object
112 OriOffset, // not in use
113 // arg Vector3 new position in local coords. Changes prim position in object
114 Velocity,
115 TargetVelocity,
116 AngVelocity,
117 Acceleration,
118 Force,
119 Torque,
120 Momentum,
121
122 AddForce,
123 AddAngForce,
124 AngLock,
125
126 Buoyancy,
127
128 PIDTarget,
129 PIDTau,
130 PIDActive,
131
132 PIDHoverHeight,
133 PIDHoverType,
134 PIDHoverTau,
135 PIDHoverActive,
136
137 Size,
138 AvatarSize,
139 Shape,
140 PhysRepData,
141 AddPhysRep,
142
143 CollidesWater,
144 VolumeDtc,
145
146 Physical,
147 Phantom,
148 Selected,
149 disabled,
150 building,
151
152 VehicleType,
153 VehicleFloatParam,
154 VehicleVectorParam,
155 VehicleRotationParam,
156 VehicleFlags,
157 SetVehicle,
158 SetInertia,
159
160 Null //keep this last used do dim the methods array. does nothing but pulsing the prim
161 }
162
163 public struct ODEchangeitem
164 {
165 public PhysicsActor actor;
166 public OdeCharacter character;
167 public changes what;
168 public Object arg;
169 }
170
171 public class ODEScene : PhysicsScene
172 {
173 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
174
175 public bool m_OSOdeLib = false;
176 public Scene m_frameWorkScene = null;
177
178// private int threadid = 0;
179
180// const d.ContactFlags comumContactFlags = d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM |d.ContactFlags.Approx1 | d.ContactFlags.Bounce;
181
182 const d.ContactFlags comumContactFlags = d.ContactFlags.Bounce | d.ContactFlags.Approx1 | d.ContactFlags.Slip1 | d.ContactFlags.Slip2;
183 const float comumContactERP = 0.75f;
184 const float comumContactCFM = 0.0001f;
185 const float comumContactSLIP = 0f;
186
187 float frictionMovementMult = 0.8f;
188
189 float TerrainBounce = 0.001f;
190 float TerrainFriction = 0.3f;
191
192 public float AvatarFriction = 0;// 0.9f * 0.5f;
193
194 // this netx dimensions are only relevant for terrain partition (mega regions)
195 // WorldExtents below has the simulation dimensions
196 // they should be identical except on mega regions
197 private uint m_regionWidth = Constants.RegionSize;
198 private uint m_regionHeight = Constants.RegionSize;
199
200 public float ODE_STEPSIZE = 0.020f;
201 public float HalfOdeStep = 0.01f;
202 public int odetimestepMS = 20; // rounded
203 private float metersInSpace = 25.6f;
204 private float m_timeDilation = 1.0f;
205
206 private double m_lastframe;
207 private double m_lastMeshExpire;
208
209 public float gravityx = 0f;
210 public float gravityy = 0f;
211 public float gravityz = -9.8f;
212
213 private float waterlevel = 0f;
214 private int framecount = 0;
215
216 private float avDensity = 80f;
217 private float avMovementDivisorWalk = 1.3f;
218 private float avMovementDivisorRun = 0.8f;
219 private float minimumGroundFlightOffset = 3f;
220 public float maximumMassObject = 10000.01f;
221 public float geomDefaultDensity = 10.0f;
222
223 public float maximumAngularVelocity = 12.0f; // default 12rad/s
224 public float maxAngVelocitySQ = 144f; // squared value
225
226 public float bodyPIDD = 35f;
227 public float bodyPIDG = 25;
228
229 public int bodyFramesAutoDisable = 5;
230
231 private d.NearCallback nearCallback;
232
233 private Dictionary<uint,OdePrim> _prims = new Dictionary<uint,OdePrim>();
234 private HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>();
235 private HashSet<OdePrim> _activeprims = new HashSet<OdePrim>();
236 private HashSet<OdePrim> _activegroups = new HashSet<OdePrim>();
237
238 public OpenSim.Framework.LocklessQueue<ODEchangeitem> ChangesQueue = new OpenSim.Framework.LocklessQueue<ODEchangeitem>();
239
240 /// <summary>
241 /// A list of actors that should receive collision events.
242 /// </summary>
243 private List<PhysicsActor> _collisionEventPrim = new List<PhysicsActor>();
244 private List<PhysicsActor> _collisionEventPrimRemove = new List<PhysicsActor>();
245
246 private HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>();
247 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
248
249 private float contactsurfacelayer = 0.002f;
250
251 private int contactsPerCollision = 80;
252 internal IntPtr ContactgeomsArray = IntPtr.Zero;
253 private IntPtr GlobalContactsArray = IntPtr.Zero;
254 private d.Contact SharedTmpcontact = new d.Contact();
255
256 const int maxContactsbeforedeath = 6000;
257 private volatile int m_global_contactcount = 0;
258
259 private IntPtr contactgroup;
260
261 public ContactData[] m_materialContactsData = new ContactData[8];
262
263 private IntPtr TerrainGeom;
264 private float[] TerrainHeightFieldHeight;
265 private GCHandle TerrainHeightFieldHeightsHandler = new GCHandle();
266
267 private int m_physicsiterations = 15;
268 private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag
269// private PhysicsActor PANull = new NullPhysicsActor();
270 private float step_time = 0.0f;
271
272 public IntPtr world;
273
274 // split the spaces acording to contents type
275 // ActiveSpace contains characters and active prims
276 // StaticSpace contains land and other that is mostly static in enviroment
277 // this can contain subspaces, like the grid in staticspace
278 // as now space only contains this 2 top spaces
279
280 public IntPtr TopSpace; // the global space
281 public IntPtr ActiveSpace; // space for active prims
282 public IntPtr CharsSpace; // space for active prims
283 public IntPtr StaticSpace; // space for the static things around
284 public IntPtr GroundSpace; // space for ground
285
286 // some speedup variables
287 private int spaceGridMaxX;
288 private int spaceGridMaxY;
289 private float spacesPerMeterX;
290 private float spacesPerMeterY;
291
292 // split static geometry collision into a grid as before
293 private IntPtr[,] staticPrimspace;
294 private IntPtr[] staticPrimspaceOffRegion;
295
296 public Object OdeLock;
297 public static Object SimulationLock;
298
299 public IMesher mesher;
300
301 public IConfigSource m_config;
302
303 public bool physics_logging = false;
304 public int physics_logging_interval = 0;
305 public bool physics_logging_append_existing_logfile = false;
306
307 public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
308
309 private ODERayCastRequestManager m_rayCastManager;
310 public ODEMeshWorker m_meshWorker;
311
312 /* maybe needed if ode uses tls
313 private void checkThread()
314 {
315
316 int th = Thread.CurrentThread.ManagedThreadId;
317 if(th != threadid)
318 {
319 threadid = th;
320 d.AllocateODEDataForThread(~0U);
321 }
322 }
323 */
324
325 IConfig physicsconfig = null;
326
327 public ODEScene(Scene pscene, IConfigSource psourceconfig, string pname, string pversion, bool pOSOdeLib)
328 {
329 OdeLock = new Object();
330
331 EngineType = pname;
332 PhysicsSceneName = EngineType + "/" + pscene.RegionInfo.RegionName;
333 EngineName = pname + " " + pversion;
334 m_config = psourceconfig;
335 m_OSOdeLib = pOSOdeLib;
336
337// m_OSOdeLib = false; //debug
338
339 m_frameWorkScene = pscene;
340
341 m_frameWorkScene.RegisterModuleInterface<PhysicsScene>(this);
342
343 Initialization();
344
345 base.Initialise(m_frameWorkScene.PhysicsRequestAsset,
346 (m_frameWorkScene.Heightmap != null ? m_frameWorkScene.Heightmap.GetFloatsSerialised() : new float[m_frameWorkScene.RegionInfo.RegionSizeX * m_frameWorkScene.RegionInfo.RegionSizeY]),
347 (float)m_frameWorkScene.RegionInfo.RegionSettings.WaterHeight);
348 }
349
350 public void RegionLoaded()
351 {
352 mesher = m_frameWorkScene.RequestModuleInterface<IMesher>();
353 if (mesher == null)
354 {
355 m_log.ErrorFormat("[ubOde] No mesher. module disabled");
356 return;
357 }
358
359 m_meshWorker = new ODEMeshWorker(this, m_log, mesher, physicsconfig);
360 m_frameWorkScene.PhysicsEnabled = true;
361 }
362 /// <summary>
363 /// Initiailizes the scene
364 /// Sets many properties that ODE requires to be stable
365 /// These settings need to be tweaked 'exactly' right or weird stuff happens.
366 /// </summary>
367 private void Initialization()
368 {
369 d.AllocateODEDataForThread(~0U);
370
371 SimulationLock = new Object();
372
373 nearCallback = near;
374
375 m_rayCastManager = new ODERayCastRequestManager(this);
376
377 WorldExtents.X = m_frameWorkScene.RegionInfo.RegionSizeX;
378 m_regionWidth = (uint)WorldExtents.X;
379 WorldExtents.Y = m_frameWorkScene.RegionInfo.RegionSizeY;
380 m_regionHeight = (uint)WorldExtents.Y;
381
382 lock (OdeLock)
383 {
384 // Create the world and the first space
385 try
386 {
387 world = d.WorldCreate();
388 TopSpace = d.HashSpaceCreate(IntPtr.Zero);
389
390 // now the major subspaces
391 ActiveSpace = d.HashSpaceCreate(TopSpace);
392 CharsSpace = d.HashSpaceCreate(TopSpace);
393 StaticSpace = d.HashSpaceCreate(TopSpace);
394 GroundSpace = d.HashSpaceCreate(TopSpace);
395 }
396 catch
397 {
398 // i must RtC#FM
399 // i did!
400 }
401
402 d.HashSpaceSetLevels(TopSpace, -5, 12);
403 d.HashSpaceSetLevels(ActiveSpace, -5, 10);
404 d.HashSpaceSetLevels(CharsSpace, -4, 3);
405 d.HashSpaceSetLevels(StaticSpace, -5, 12);
406 d.HashSpaceSetLevels(GroundSpace, 0, 8);
407
408 // demote to second level
409 d.SpaceSetSublevel(ActiveSpace, 1);
410 d.SpaceSetSublevel(CharsSpace, 1);
411 d.SpaceSetSublevel(StaticSpace, 1);
412 d.SpaceSetSublevel(GroundSpace, 1);
413
414 d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space |
415 CollisionCategories.Geom |
416 CollisionCategories.Character |
417 CollisionCategories.Phantom |
418 CollisionCategories.VolumeDtc
419 ));
420 d.GeomSetCollideBits(ActiveSpace, (uint)(CollisionCategories.Space |
421 CollisionCategories.Geom |
422 CollisionCategories.Character |
423 CollisionCategories.Phantom |
424 CollisionCategories.VolumeDtc
425 ));
426 d.GeomSetCategoryBits(CharsSpace, (uint)(CollisionCategories.Space |
427 CollisionCategories.Geom |
428 CollisionCategories.Character |
429 CollisionCategories.Phantom |
430 CollisionCategories.VolumeDtc
431 ));
432 d.GeomSetCollideBits(CharsSpace, 0);
433
434 d.GeomSetCategoryBits(StaticSpace, (uint)(CollisionCategories.Space |
435 CollisionCategories.Geom |
436 // CollisionCategories.Land |
437 // CollisionCategories.Water |
438 CollisionCategories.Phantom |
439 CollisionCategories.VolumeDtc
440 ));
441 d.GeomSetCollideBits(StaticSpace, 0);
442
443 d.GeomSetCategoryBits(GroundSpace, (uint)(CollisionCategories.Land));
444 d.GeomSetCollideBits(GroundSpace, 0);
445
446 contactgroup = d.JointGroupCreate(maxContactsbeforedeath + 1);
447 //contactgroup
448
449 d.WorldSetAutoDisableFlag(world, false);
450 }
451
452
453 // checkThread();
454
455
456 // Defaults
457
458 int contactsPerCollision = 80;
459
460 physicsconfig = null;
461
462 if (m_config != null)
463 {
464 physicsconfig = m_config.Configs["ODEPhysicsSettings"];
465 if (physicsconfig != null)
466 {
467 gravityx = physicsconfig.GetFloat("world_gravityx", gravityx);
468 gravityy = physicsconfig.GetFloat("world_gravityy", gravityy);
469 gravityz = physicsconfig.GetFloat("world_gravityz", gravityz);
470
471 metersInSpace = physicsconfig.GetFloat("meters_in_small_space", metersInSpace);
472
473 // contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", contactsurfacelayer);
474
475 ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", ODE_STEPSIZE);
476
477 avDensity = physicsconfig.GetFloat("av_density", avDensity);
478 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", avMovementDivisorWalk);
479 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", avMovementDivisorRun);
480
481 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", contactsPerCollision);
482
483 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity);
484// bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable);
485
486 physics_logging = physicsconfig.GetBoolean("physics_logging", false);
487 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
488 physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
489
490 minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", minimumGroundFlightOffset);
491 maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", maximumMassObject);
492
493 avDensity *= 3f / 80f; // scale other engines density option to this
494 }
495 }
496
497 float heartbeat = 1/m_frameWorkScene.FrameTime;
498 maximumAngularVelocity = 0.49f * heartbeat *(float)Math.PI;
499 maxAngVelocitySQ = maximumAngularVelocity * maximumAngularVelocity;
500
501 d.WorldSetCFM(world, comumContactCFM);
502 d.WorldSetERP(world, comumContactERP);
503
504 d.WorldSetGravity(world, gravityx, gravityy, gravityz);
505
506 d.WorldSetLinearDamping(world, 0.001f);
507 d.WorldSetAngularDamping(world, 0.002f);
508 d.WorldSetAngularDampingThreshold(world, 0f);
509 d.WorldSetLinearDampingThreshold(world, 0f);
510 d.WorldSetMaxAngularSpeed(world, maximumAngularVelocity);
511
512 d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
513
514 d.WorldSetContactSurfaceLayer(world, contactsurfacelayer);
515 d.WorldSetContactMaxCorrectingVel(world, 60.0f);
516
517 HalfOdeStep = ODE_STEPSIZE * 0.5f;
518 odetimestepMS = (int)(1000.0f * ODE_STEPSIZE + 0.5f);
519
520 ContactgeomsArray = Marshal.AllocHGlobal(contactsPerCollision * d.ContactGeom.unmanagedSizeOf);
521 GlobalContactsArray = Marshal.AllocHGlobal((maxContactsbeforedeath + 100) * d.Contact.unmanagedSizeOf);
522
523 SharedTmpcontact.geom.g1 = IntPtr.Zero;
524 SharedTmpcontact.geom.g2 = IntPtr.Zero;
525
526 SharedTmpcontact.geom.side1 = -1;
527 SharedTmpcontact.geom.side2 = -1;
528
529 SharedTmpcontact.surface.mode = comumContactFlags;
530 SharedTmpcontact.surface.mu = 0;
531 SharedTmpcontact.surface.bounce = 0;
532 SharedTmpcontact.surface.bounce_vel = 1.5f;
533 SharedTmpcontact.surface.soft_cfm = comumContactCFM;
534 SharedTmpcontact.surface.soft_erp = comumContactERP;
535 SharedTmpcontact.surface.slip1 = comumContactSLIP;
536 SharedTmpcontact.surface.slip2 = comumContactSLIP;
537
538 m_materialContactsData[(int)Material.Stone].mu = 0.8f;
539 m_materialContactsData[(int)Material.Stone].bounce = 0.4f;
540
541 m_materialContactsData[(int)Material.Metal].mu = 0.3f;
542 m_materialContactsData[(int)Material.Metal].bounce = 0.4f;
543
544 m_materialContactsData[(int)Material.Glass].mu = 0.2f;
545 m_materialContactsData[(int)Material.Glass].bounce = 0.7f;
546
547 m_materialContactsData[(int)Material.Wood].mu = 0.6f;
548 m_materialContactsData[(int)Material.Wood].bounce = 0.5f;
549
550 m_materialContactsData[(int)Material.Flesh].mu = 0.9f;
551 m_materialContactsData[(int)Material.Flesh].bounce = 0.3f;
552
553 m_materialContactsData[(int)Material.Plastic].mu = 0.4f;
554 m_materialContactsData[(int)Material.Plastic].bounce = 0.7f;
555
556 m_materialContactsData[(int)Material.Rubber].mu = 0.9f;
557 m_materialContactsData[(int)Material.Rubber].bounce = 0.95f;
558
559 m_materialContactsData[(int)Material.light].mu = 0.0f;
560 m_materialContactsData[(int)Material.light].bounce = 0.0f;
561
562
563 spacesPerMeterX = 1.0f / metersInSpace;
564 spacesPerMeterY = spacesPerMeterX;
565 spaceGridMaxX = (int)(WorldExtents.X * spacesPerMeterX);
566 spaceGridMaxY = (int)(WorldExtents.Y * spacesPerMeterY);
567
568 if (spaceGridMaxX > 24)
569 {
570 spaceGridMaxX = 24;
571 spacesPerMeterX = spaceGridMaxX / WorldExtents.X;
572 }
573
574 if (spaceGridMaxY > 24)
575 {
576 spaceGridMaxY = 24;
577 spacesPerMeterY = spaceGridMaxY / WorldExtents.Y;
578 }
579
580 staticPrimspace = new IntPtr[spaceGridMaxX, spaceGridMaxY];
581
582 // create all spaces now
583 int i, j;
584 IntPtr newspace;
585
586 for (i = 0; i < spaceGridMaxX; i++)
587 for (j = 0; j < spaceGridMaxY; j++)
588 {
589 newspace = d.HashSpaceCreate(StaticSpace);
590 d.GeomSetCategoryBits(newspace, (int)CollisionCategories.Space);
591 waitForSpaceUnlock(newspace);
592 d.SpaceSetSublevel(newspace, 2);
593 d.HashSpaceSetLevels(newspace, -2, 8);
594 d.GeomSetCategoryBits(newspace, (uint)(CollisionCategories.Space |
595 CollisionCategories.Geom |
596 CollisionCategories.Land |
597 CollisionCategories.Water |
598 CollisionCategories.Phantom |
599 CollisionCategories.VolumeDtc
600 ));
601 d.GeomSetCollideBits(newspace, 0);
602
603 staticPrimspace[i, j] = newspace;
604 }
605
606 // let this now be index limit
607 spaceGridMaxX--;
608 spaceGridMaxY--;
609
610 // create 4 off world spaces (x<0,x>max,y<0,y>max)
611 staticPrimspaceOffRegion = new IntPtr[4];
612
613 for (i = 0; i < 4; i++)
614 {
615 newspace = d.HashSpaceCreate(StaticSpace);
616 d.GeomSetCategoryBits(newspace, (int)CollisionCategories.Space);
617 waitForSpaceUnlock(newspace);
618 d.SpaceSetSublevel(newspace, 2);
619 d.HashSpaceSetLevels(newspace, -2, 8);
620 d.GeomSetCategoryBits(newspace, (uint)(CollisionCategories.Space |
621 CollisionCategories.Geom |
622 CollisionCategories.Land |
623 CollisionCategories.Water |
624 CollisionCategories.Phantom |
625 CollisionCategories.VolumeDtc
626 ));
627 d.GeomSetCollideBits(newspace, 0);
628
629 staticPrimspaceOffRegion[i] = newspace;
630 }
631
632 m_lastframe = Util.GetTimeStamp();
633 m_lastMeshExpire = m_lastframe;
634 step_time = -1;
635 }
636
637 internal void waitForSpaceUnlock(IntPtr space)
638 {
639 //if (space != IntPtr.Zero)
640 //while (d.SpaceLockQuery(space)) { } // Wait and do nothing
641 }
642
643 #region Collision Detection
644
645 // sets a global contact for a joint for contactgeom , and base contact description)
646 private IntPtr CreateContacJoint(ref d.ContactGeom contactGeom,bool smooth)
647 {
648 if (m_global_contactcount >= maxContactsbeforedeath)
649 return IntPtr.Zero;
650
651 m_global_contactcount++;
652 if(smooth)
653 SharedTmpcontact.geom.depth = contactGeom.depth * 0.05f;
654 else
655 SharedTmpcontact.geom.depth = contactGeom.depth;
656 SharedTmpcontact.geom.pos = contactGeom.pos;
657 SharedTmpcontact.geom.normal = contactGeom.normal;
658
659 IntPtr contact = new IntPtr(GlobalContactsArray.ToInt64() + (Int64)(m_global_contactcount * d.Contact.unmanagedSizeOf));
660 Marshal.StructureToPtr(SharedTmpcontact, contact, true);
661 return d.JointCreateContactPtr(world, contactgroup, contact);
662 }
663
664 private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
665 {
666 if (ContactgeomsArray == IntPtr.Zero || index >= contactsPerCollision)
667 return false;
668
669 IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
670 newcontactgeom = (d.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(d.ContactGeom));
671 return true;
672 }
673
674 /// <summary>
675 /// This is our near callback. A geometry is near a body
676 /// </summary>
677 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
678 /// <param name="g1">a geometry or space</param>
679 /// <param name="g2">another geometry or space</param>
680 ///
681
682 private void near(IntPtr space, IntPtr g1, IntPtr g2)
683 {
684 // no lock here! It's invoked from within Simulate(), which is thread-locked
685
686 if (m_global_contactcount >= maxContactsbeforedeath)
687 return;
688
689 // Test if we're colliding a geom with a space.
690 // If so we have to drill down into the space recursively
691
692 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
693 return;
694
695 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
696 {
697 // We'll be calling near recursivly if one
698 // of them is a space to find all of the
699 // contact points in the space
700 try
701 {
702 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
703 }
704 catch (AccessViolationException)
705 {
706 m_log.Warn("[PHYSICS]: Unable to collide test a space");
707 return;
708 }
709 //here one should check collisions of geoms inside a space
710 // but on each space we only should have geoms that not colide amoung each other
711 // so we don't dig inside spaces
712 return;
713 }
714
715 // get geom bodies to check if we already a joint contact
716 // guess this shouldn't happen now
717 IntPtr b1 = d.GeomGetBody(g1);
718 IntPtr b2 = d.GeomGetBody(g2);
719
720 // d.GeomClassID id = d.GeomGetClass(g1);
721
722 // Figure out how many contact points we have
723 int count = 0;
724 try
725 {
726 // Colliding Geom To Geom
727 // This portion of the function 'was' blatantly ripped off from BoxStack.cs
728
729 if (g1 == g2)
730 return; // Can't collide with yourself
731
732// if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
733// return;
734 /*
735 // debug
736 PhysicsActor dp2;
737 if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
738 {
739 d.AABB aabb;
740 d.GeomGetAABB(g2, out aabb);
741 float x = aabb.MaxX - aabb.MinX;
742 float y = aabb.MaxY - aabb.MinY;
743 float z = aabb.MaxZ - aabb.MinZ;
744 if (x > 60.0f || y > 60.0f || z > 60.0f)
745 {
746 if (!actor_name_map.TryGetValue(g2, out dp2))
747 m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2");
748 else
749 m_log.WarnFormat("[PHYSICS]: land versus large prim geo {0},size {1}, AABBsize <{2},{3},{4}>, at {5} ori {6},({7})",
750 dp2.Name, dp2.Size, x, y, z,
751 dp2.Position.ToString(),
752 dp2.Orientation.ToString(),
753 dp2.Orientation.Length());
754 return;
755 }
756 }
757 //
758 */
759
760
761 if (d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc ||
762 d.GeomGetCategoryBits(g2) == (uint)CollisionCategories.VolumeDtc)
763 {
764 int cflags;
765 unchecked
766 {
767 cflags = (int)(1 | d.CONTACTS_UNIMPORTANT);
768 }
769 count = d.CollidePtr(g1, g2, cflags, ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
770 }
771 else
772 count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
773 }
774 catch (SEHException)
775 {
776 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.");
777 // ode.drelease(world);
778 base.TriggerPhysicsBasedRestart();
779 }
780 catch (Exception e)
781 {
782 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
783 return;
784 }
785
786 // contacts done
787 if (count == 0)
788 return;
789
790 // try get physical actors
791 PhysicsActor p1;
792 PhysicsActor p2;
793
794 if (!actor_name_map.TryGetValue(g1, out p1))
795 {
796 m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 1");
797 return;
798 }
799
800 if (!actor_name_map.TryGetValue(g2, out p2))
801 {
802 m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2");
803 return;
804 }
805
806
807 // get first contact
808 d.ContactGeom curContact = new d.ContactGeom();
809
810 if (!GetCurContactGeom(0, ref curContact))
811 return;
812
813 ContactPoint maxDepthContact = new ContactPoint();
814
815 // do volume detection case
816 if ((p1.IsVolumeDtc || p2.IsVolumeDtc))
817 {
818 maxDepthContact = new ContactPoint(
819 new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z),
820 new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z),
821 curContact.depth, false
822 );
823
824 collision_accounting_events(p1, p2, maxDepthContact);
825 return;
826 }
827
828 // big messy collision analises
829
830 float mu = 0;
831 float bounce = 0;
832// bool IgnoreNegSides = false;
833
834 ContactData contactdata1 = new ContactData(0, 0, false);
835 ContactData contactdata2 = new ContactData(0, 0, false);
836
837 bool dop1ava = false;
838 bool dop2ava = false;
839 bool ignore = false;
840 bool smoothMesh = false;
841
842 switch (p1.PhysicsActorType)
843 {
844 case (int)ActorTypes.Agent:
845 {
846 dop1ava = true;
847 switch (p2.PhysicsActorType)
848 {
849 case (int)ActorTypes.Agent:
850 case (int)ActorTypes.Prim:
851 break;
852
853 default:
854 ignore = true; // avatar to terrain and water ignored
855 break;
856 }
857 break;
858 }
859
860 case (int)ActorTypes.Prim:
861 {
862 switch (p2.PhysicsActorType)
863 {
864 case (int)ActorTypes.Agent:
865 dop2ava = true;
866 break;
867
868 case (int)ActorTypes.Prim:
869 Vector3 relV = p1.rootVelocity - p2.rootVelocity;
870 float relVlenSQ = relV.LengthSquared();
871 if (relVlenSQ > 0.0001f)
872 {
873 p1.CollidingObj = true;
874 p2.CollidingObj = true;
875 }
876 p1.getContactData(ref contactdata1);
877 p2.getContactData(ref contactdata2);
878 bounce = contactdata1.bounce * contactdata2.bounce;
879 mu = (float)Math.Sqrt(contactdata1.mu * contactdata2.mu);
880
881 if (relVlenSQ > 0.01f)
882 mu *= frictionMovementMult;
883
884 if(d.GeomGetClass(g2) == d.GeomClassID.TriMeshClass &&
885 d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass)
886 smoothMesh = true;
887 break;
888
889 case (int)ActorTypes.Ground:
890 p1.getContactData(ref contactdata1);
891 bounce = contactdata1.bounce * TerrainBounce;
892 mu = (float)Math.Sqrt(contactdata1.mu * TerrainFriction);
893
894 Vector3 v1 = p1.rootVelocity;
895 if (Math.Abs(v1.X) > 0.1f || Math.Abs(v1.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 Vector3 v2 = p2.rootVelocity;
922 if (Math.Abs(v2.X) > 0.1f || Math.Abs(v2.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;
957 bool noskip;
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.rootVelocity.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 (p1.rootVelocity.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 if (Joint == IntPtr.Zero)
1005 break;
1006
1007 d.JointAttach(Joint, b1, b2);
1008
1009 ncontacts++;
1010
1011 if (curContact.depth > maxDepthContact.PenetrationDepth)
1012 {
1013 maxDepthContact.Position.X = curContact.pos.X;
1014 maxDepthContact.Position.Y = curContact.pos.Y;
1015 maxDepthContact.Position.Z = curContact.pos.Z;
1016 maxDepthContact.PenetrationDepth = curContact.depth;
1017 maxDepthContact.CharacterFeet = FeetCollision;
1018 }
1019
1020 if (curContact.depth < minDepthContact.PenetrationDepth)
1021 {
1022 minDepthContact.PenetrationDepth = curContact.depth;
1023 minDepthContact.SurfaceNormal.X = curContact.normal.X;
1024 minDepthContact.SurfaceNormal.Y = curContact.normal.Y;
1025 minDepthContact.SurfaceNormal.Z = curContact.normal.Z;
1026 }
1027 }
1028
1029 if (++i >= count)
1030 break;
1031
1032 if (!GetCurContactGeom(i, ref curContact))
1033 break;
1034 }
1035
1036 if (ncontacts > 0)
1037 {
1038 maxDepthContact.SurfaceNormal.X = minDepthContact.SurfaceNormal.X;
1039 maxDepthContact.SurfaceNormal.Y = minDepthContact.SurfaceNormal.Y;
1040 maxDepthContact.SurfaceNormal.Z = minDepthContact.SurfaceNormal.Z;
1041
1042 collision_accounting_events(p1, p2, maxDepthContact);
1043 }
1044 }
1045
1046 private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact)
1047 {
1048 uint obj2LocalID = 0;
1049
1050 // update actors collision score
1051 if (p1.CollisionScore < float.MaxValue)
1052 p1.CollisionScore += 1.0f;
1053 if (p2.CollisionScore < float.MaxValue)
1054 p2.CollisionScore += 1.0f;
1055
1056 bool p1events = p1.SubscribedEvents();
1057 bool p2events = p2.SubscribedEvents();
1058
1059 if (p1.IsVolumeDtc)
1060 p2events = false;
1061 if (p2.IsVolumeDtc)
1062 p1events = false;
1063
1064 if (!p2events && !p1events)
1065 return;
1066
1067 Vector3 vel = Vector3.Zero;
1068 if (p2 != null && p2.IsPhysical)
1069 vel = p2.rootVelocity;
1070
1071 if (p1 != null && p1.IsPhysical)
1072 vel -= p1.rootVelocity;
1073
1074 contact.RelativeSpeed = Vector3.Dot(vel, contact.SurfaceNormal);
1075
1076 switch ((ActorTypes)p1.PhysicsActorType)
1077 {
1078 case ActorTypes.Agent:
1079 case ActorTypes.Prim:
1080 {
1081 switch ((ActorTypes)p2.PhysicsActorType)
1082 {
1083 case ActorTypes.Agent:
1084 case ActorTypes.Prim:
1085 if (p2events)
1086 {
1087 //AddCollisionEventReporting(p2);
1088 p2.AddCollisionEvent(p1.ParentActor.LocalID, contact);
1089 }
1090 else if(p1.IsVolumeDtc)
1091 p2.AddVDTCCollisionEvent(p1.ParentActor.LocalID, contact);
1092
1093 obj2LocalID = p2.ParentActor.LocalID;
1094 break;
1095
1096 case ActorTypes.Ground:
1097 case ActorTypes.Unknown:
1098 default:
1099 obj2LocalID = 0;
1100 break;
1101 }
1102 if (p1events)
1103 {
1104 contact.SurfaceNormal = -contact.SurfaceNormal;
1105 contact.RelativeSpeed = -contact.RelativeSpeed;
1106 //AddCollisionEventReporting(p1);
1107 p1.AddCollisionEvent(obj2LocalID, contact);
1108 }
1109 else if(p2.IsVolumeDtc)
1110 {
1111 contact.SurfaceNormal = -contact.SurfaceNormal;
1112 contact.RelativeSpeed = -contact.RelativeSpeed;
1113 //AddCollisionEventReporting(p1);
1114 p1.AddVDTCCollisionEvent(obj2LocalID, contact);
1115 }
1116 break;
1117 }
1118 case ActorTypes.Ground:
1119 case ActorTypes.Unknown:
1120 default:
1121 {
1122 if (p2events && !p2.IsVolumeDtc)
1123 {
1124 //AddCollisionEventReporting(p2);
1125 p2.AddCollisionEvent(0, contact);
1126 }
1127 break;
1128 }
1129 }
1130 }
1131
1132 /// <summary>
1133 /// This is our collision testing routine in ODE
1134 /// </summary>
1135 /// <param name="timeStep"></param>
1136 private void collision_optimized()
1137 {
1138 lock (_characters)
1139 {
1140 try
1141 {
1142 foreach (OdeCharacter chr in _characters)
1143 {
1144 if (chr == null)
1145 continue;
1146
1147 chr.IsColliding = false;
1148 // chr.CollidingGround = false; not done here
1149 chr.CollidingObj = false;
1150
1151 if(chr.Body == IntPtr.Zero || chr.collider == IntPtr.Zero )
1152 continue;
1153
1154 // do colisions with static space
1155 d.SpaceCollide2(chr.collider, StaticSpace, IntPtr.Zero, nearCallback);
1156
1157 // no coll with gnd
1158 }
1159 // chars with chars
1160 d.SpaceCollide(CharsSpace, IntPtr.Zero, nearCallback);
1161
1162 }
1163 catch (AccessViolationException)
1164 {
1165 m_log.Warn("[PHYSICS]: Unable to collide Character to static space");
1166 }
1167
1168 }
1169
1170 lock (_activeprims)
1171 {
1172 foreach (OdePrim aprim in _activeprims)
1173 {
1174 aprim.CollisionScore = 0;
1175 aprim.IsColliding = false;
1176 if(!aprim.m_outbounds && d.BodyIsEnabled(aprim.Body))
1177 aprim.clearSleeperCollisions();
1178 }
1179 }
1180
1181 lock (_activegroups)
1182 {
1183 try
1184 {
1185 foreach (OdePrim aprim in _activegroups)
1186 {
1187 if(!aprim.m_outbounds && d.BodyIsEnabled(aprim.Body) &&
1188 aprim.collide_geom != IntPtr.Zero)
1189 {
1190 d.SpaceCollide2(StaticSpace, aprim.collide_geom, IntPtr.Zero, nearCallback);
1191 d.SpaceCollide2(GroundSpace, aprim.collide_geom, IntPtr.Zero, nearCallback);
1192 }
1193 }
1194 }
1195 catch (Exception e)
1196 {
1197 m_log.Warn("[PHYSICS]: Unable to collide Active to Static: " + e.Message);
1198 }
1199 }
1200
1201 // colide active amoung them
1202 try
1203 {
1204 d.SpaceCollide(ActiveSpace, IntPtr.Zero, nearCallback);
1205 }
1206 catch (Exception e)
1207 {
1208 m_log.Warn("[PHYSICS]: Unable to collide in Active: " + e.Message);
1209 }
1210
1211 // and with chars
1212 try
1213 {
1214 d.SpaceCollide2(CharsSpace,ActiveSpace, IntPtr.Zero, nearCallback);
1215 }
1216 catch (Exception e)
1217 {
1218 m_log.Warn("[PHYSICS]: Unable to collide Active to Character: " + e.Message);
1219 }
1220 }
1221
1222 #endregion
1223 /// <summary>
1224 /// Add actor to the list that should receive collision events in the simulate loop.
1225 /// </summary>
1226 /// <param name="obj"></param>
1227 public void AddCollisionEventReporting(PhysicsActor obj)
1228 {
1229 if (!_collisionEventPrim.Contains(obj))
1230 _collisionEventPrim.Add(obj);
1231 }
1232
1233 /// <summary>
1234 /// Remove actor from the list that should receive collision events in the simulate loop.
1235 /// </summary>
1236 /// <param name="obj"></param>
1237 public void RemoveCollisionEventReporting(PhysicsActor obj)
1238 {
1239 lock(_collisionEventPrimRemove)
1240 {
1241 if (_collisionEventPrim.Contains(obj) && !_collisionEventPrimRemove.Contains(obj))
1242 _collisionEventPrimRemove.Add(obj);
1243 }
1244 }
1245
1246 public override float TimeDilation
1247 {
1248 get { return m_timeDilation; }
1249 }
1250
1251 public override bool SupportsNINJAJoints
1252 {
1253 get { return false; }
1254 }
1255
1256 #region Add/Remove Entities
1257
1258 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying)
1259 {
1260 return null;
1261 }
1262
1263 public override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, float feetOffset, bool isFlying)
1264 {
1265 OdeCharacter newAv = new OdeCharacter(localID, avName, this, position,
1266 size, feetOffset, avDensity, avMovementDivisorWalk, avMovementDivisorRun);
1267 newAv.Flying = isFlying;
1268 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1269
1270 return newAv;
1271 }
1272
1273 public void AddCharacter(OdeCharacter chr)
1274 {
1275 lock (_characters)
1276 {
1277 if (!_characters.Contains(chr))
1278 {
1279 _characters.Add(chr);
1280 if (chr.bad)
1281 m_log.DebugFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid);
1282 }
1283 }
1284 }
1285
1286 public void RemoveCharacter(OdeCharacter chr)
1287 {
1288 lock (_characters)
1289 {
1290 if (_characters.Contains(chr))
1291 {
1292 _characters.Remove(chr);
1293 }
1294 }
1295 }
1296
1297 public void BadCharacter(OdeCharacter chr)
1298 {
1299 lock (_badCharacter)
1300 {
1301 if (!_badCharacter.Contains(chr))
1302 _badCharacter.Add(chr);
1303 }
1304 }
1305
1306 public override void RemoveAvatar(PhysicsActor actor)
1307 {
1308 //m_log.Debug("[PHYSICS]:ODELOCK");
1309 lock (OdeLock)
1310 {
1311 d.AllocateODEDataForThread(0);
1312 ((OdeCharacter) actor).Destroy();
1313 }
1314 }
1315
1316
1317 public void addActivePrim(OdePrim activatePrim)
1318 {
1319 // adds active prim..
1320 lock (_activeprims)
1321 {
1322 if (!_activeprims.Contains(activatePrim))
1323 _activeprims.Add(activatePrim);
1324 }
1325 }
1326
1327 public void addActiveGroups(OdePrim activatePrim)
1328 {
1329 lock (_activegroups)
1330 {
1331 if (!_activegroups.Contains(activatePrim))
1332 _activegroups.Add(activatePrim);
1333 }
1334 }
1335
1336 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
1337 PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, byte shapeType, uint localID)
1338 {
1339 OdePrim newPrim;
1340 lock (OdeLock)
1341 {
1342
1343 newPrim = new OdePrim(name, this, position, size, rotation, pbs, isphysical, isPhantom, shapeType, localID);
1344 }
1345 return newPrim;
1346 }
1347
1348 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1349 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, uint localid)
1350 {
1351 return AddPrim(primName, position, size, rotation, pbs, isPhysical, isPhantom, 0 , localid);
1352 }
1353
1354
1355 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1356 Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
1357 {
1358 return AddPrim(primName, position, size, rotation, pbs, isPhysical,false, 0, localid);
1359 }
1360
1361 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1362 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapeType, uint localid)
1363 {
1364 return AddPrim(primName, position, size, rotation, pbs, isPhysical,isPhantom, shapeType, localid);
1365 }
1366
1367 public void remActivePrim(OdePrim deactivatePrim)
1368 {
1369 lock (_activeprims)
1370 {
1371 _activeprims.Remove(deactivatePrim);
1372 }
1373 }
1374 public void remActiveGroup(OdePrim deactivatePrim)
1375 {
1376 lock (_activegroups)
1377 {
1378 _activegroups.Remove(deactivatePrim);
1379 }
1380 }
1381
1382 public override void RemovePrim(PhysicsActor prim)
1383 {
1384 // As with all ODE physics operations, we don't remove the prim immediately but signal that it should be
1385 // removed in the next physics simulate pass.
1386 if (prim is OdePrim)
1387 {
1388// lock (OdeLock)
1389 {
1390
1391 OdePrim p = (OdePrim)prim;
1392 p.setPrimForRemoval();
1393 }
1394 }
1395 }
1396
1397 public void RemovePrimThreadLocked(OdePrim prim)
1398 {
1399 //Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName);
1400 lock (prim)
1401 {
1402// RemoveCollisionEventReporting(prim);
1403 lock (_prims)
1404 _prims.Remove(prim.LocalID);
1405 }
1406
1407 }
1408
1409 public void addToPrims(OdePrim prim)
1410 {
1411 lock (_prims)
1412 _prims[prim.LocalID] = prim;
1413 }
1414
1415 public OdePrim getPrim(uint id)
1416 {
1417 lock (_prims)
1418 {
1419 if(_prims.ContainsKey(id))
1420 return _prims[id];
1421 else
1422 return null;
1423 }
1424 }
1425
1426 public bool havePrim(OdePrim prm)
1427 {
1428 lock (_prims)
1429 return _prims.ContainsKey(prm.LocalID);
1430 }
1431
1432 public void changePrimID(OdePrim prim,uint oldID)
1433 {
1434 lock (_prims)
1435 {
1436 if(_prims.ContainsKey(oldID))
1437 _prims.Remove(oldID);
1438 _prims[prim.LocalID] = prim;
1439 }
1440 }
1441
1442 public bool haveActor(PhysicsActor actor)
1443 {
1444 if (actor is OdePrim)
1445 {
1446 lock (_prims)
1447 return _prims.ContainsKey(((OdePrim)actor).LocalID);
1448 }
1449 else if (actor is OdeCharacter)
1450 {
1451 lock (_characters)
1452 return _characters.Contains((OdeCharacter)actor);
1453 }
1454 return false;
1455 }
1456
1457 #endregion
1458
1459 #region Space Separation Calculation
1460
1461 /// <summary>
1462 /// Called when a static prim moves or becomes static
1463 /// Places the prim in a space one the static sub-spaces grid
1464 /// </summary>
1465 /// <param name="geom">the pointer to the geom that moved</param>
1466 /// <param name="pos">the position that the geom moved to</param>
1467 /// <param name="currentspace">a pointer to the space it was in before it was moved.</param>
1468 /// <returns>a pointer to the new space it's in</returns>
1469 public IntPtr MoveGeomToStaticSpace(IntPtr geom, Vector3 pos, IntPtr currentspace)
1470 {
1471 // moves a prim into another static sub-space or from another space into a static sub-space
1472
1473 // Called ODEPrim so
1474 // it's already in locked space.
1475
1476 if (geom == IntPtr.Zero) // shouldn't happen
1477 return IntPtr.Zero;
1478
1479 // get the static sub-space for current position
1480 IntPtr newspace = calculateSpaceForGeom(pos);
1481
1482 if (newspace == currentspace) // if we are there all done
1483 return newspace;
1484
1485 // else remove it from its current space
1486 if (currentspace != IntPtr.Zero && d.SpaceQuery(currentspace, geom))
1487 {
1488 if (d.GeomIsSpace(currentspace))
1489 {
1490 waitForSpaceUnlock(currentspace);
1491 d.SpaceRemove(currentspace, geom);
1492
1493 if (d.SpaceGetSublevel(currentspace) > 2 && d.SpaceGetNumGeoms(currentspace) == 0)
1494 {
1495 d.SpaceDestroy(currentspace);
1496 }
1497 }
1498 else
1499 {
1500 m_log.Info("[Physics]: Invalid or empty Space passed to 'MoveGeomToStaticSpace':" + currentspace +
1501 " Geom:" + geom);
1502 }
1503 }
1504 else // odd currentspace is null or doesn't contain the geom? lets try the geom ideia of current space
1505 {
1506 currentspace = d.GeomGetSpace(geom);
1507 if (currentspace != IntPtr.Zero)
1508 {
1509 if (d.GeomIsSpace(currentspace))
1510 {
1511 waitForSpaceUnlock(currentspace);
1512 d.SpaceRemove(currentspace, geom);
1513
1514 if (d.SpaceGetSublevel(currentspace) > 2 && d.SpaceGetNumGeoms(currentspace) == 0)
1515 {
1516 d.SpaceDestroy(currentspace);
1517 }
1518
1519 }
1520 }
1521 }
1522
1523 // put the geom in the newspace
1524 waitForSpaceUnlock(newspace);
1525 d.SpaceAdd(newspace, geom);
1526
1527 // let caller know this newspace
1528 return newspace;
1529 }
1530
1531 /// <summary>
1532 /// Calculates the space the prim should be in by its position
1533 /// </summary>
1534 /// <param name="pos"></param>
1535 /// <returns>a pointer to the space. This could be a new space or reused space.</returns>
1536 public IntPtr calculateSpaceForGeom(Vector3 pos)
1537 {
1538 int x, y;
1539
1540 if (pos.X < 0)
1541 return staticPrimspaceOffRegion[0];
1542
1543 if (pos.Y < 0)
1544 return staticPrimspaceOffRegion[2];
1545
1546 x = (int)(pos.X * spacesPerMeterX);
1547 if (x > spaceGridMaxX)
1548 return staticPrimspaceOffRegion[1];
1549
1550 y = (int)(pos.Y * spacesPerMeterY);
1551 if (y > spaceGridMaxY)
1552 return staticPrimspaceOffRegion[3];
1553
1554 return staticPrimspace[x, y];
1555 }
1556
1557 #endregion
1558
1559
1560 /// <summary>
1561 /// Called to queue a change to a actor
1562 /// to use in place of old taint mechanism so changes do have a time sequence
1563 /// </summary>
1564
1565 public void AddChange(PhysicsActor actor, changes what, Object arg)
1566 {
1567 ODEchangeitem item = new ODEchangeitem();
1568 item.actor = actor;
1569 item.what = what;
1570 item.arg = arg;
1571 ChangesQueue.Enqueue(item);
1572 }
1573
1574 /// <summary>
1575 /// Called after our prim properties are set Scale, position etc.
1576 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex
1577 /// This assures us that we have no race conditions
1578 /// </summary>
1579 /// <param name="prim"></param>
1580 public override void AddPhysicsActorTaint(PhysicsActor prim)
1581 {
1582 }
1583
1584 // does all pending changes generated during region load process
1585 public override void ProcessPreSimulation()
1586 {
1587 lock (OdeLock)
1588 {
1589 if (world == IntPtr.Zero)
1590 {
1591 ChangesQueue.Clear();
1592 return;
1593 }
1594
1595 d.AllocateODEDataForThread(~0U);
1596
1597 ODEchangeitem item;
1598
1599 int donechanges = 0;
1600 if (ChangesQueue.Count > 0)
1601 {
1602 m_log.InfoFormat("[ubOde] start processing pending actor operations");
1603 int tstart = Util.EnvironmentTickCount();
1604
1605 while (ChangesQueue.Dequeue(out item))
1606 {
1607 if (item.actor != null)
1608 {
1609 try
1610 {
1611 if (item.actor is OdeCharacter)
1612 ((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
1613 else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
1614 RemovePrimThreadLocked((OdePrim)item.actor);
1615 }
1616 catch
1617 {
1618 m_log.WarnFormat("[PHYSICS]: Operation failed for a actor {0} {1}",
1619 item.actor.Name, item.what.ToString());
1620 }
1621 }
1622 donechanges++;
1623 }
1624 int time = Util.EnvironmentTickCountSubtract(tstart);
1625 m_log.InfoFormat("[ubOde] finished {0} operations in {1}ms", donechanges, time);
1626 }
1627 m_log.InfoFormat("[ubOde] {0} prim actors loaded",_prims.Count);
1628 }
1629 m_lastframe = Util.GetTimeStamp() + 0.5;
1630 step_time = -0.5f;
1631 }
1632
1633 /// <summary>
1634 /// This is our main simulate loop
1635 /// It's thread locked by a Mutex in the scene.
1636 /// It holds Collisions, it instructs ODE to step through the physical reactions
1637 /// It moves the objects around in memory
1638 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
1639 /// </summary>
1640 /// <param name="timeStep"></param>
1641 /// <returns></returns>
1642 public override float Simulate(float reqTimeStep)
1643 {
1644 double now = Util.GetTimeStamp();
1645 double timeStep = now - m_lastframe;
1646 m_lastframe = now;
1647
1648 // acumulate time so we can reduce error
1649 step_time += (float)timeStep;
1650
1651 if (step_time < HalfOdeStep)
1652 return 0;
1653
1654 if (framecount < 0)
1655 framecount = 0;
1656
1657 framecount++;
1658
1659// checkThread();
1660 int nodeframes = 0;
1661 float fps = 0;
1662
1663 lock (SimulationLock)
1664 lock(OdeLock)
1665 {
1666 if (world == IntPtr.Zero)
1667 {
1668 ChangesQueue.Clear();
1669 return 0;
1670 }
1671
1672 ODEchangeitem item;
1673
1674// d.WorldSetQuickStepNumIterations(world, curphysiteractions);
1675
1676 double loopstartMS = Util.GetTimeStampMS();
1677 double looptimeMS = 0;
1678 double changestimeMS = 0;
1679 double maxChangestime = (int)(reqTimeStep * 500f); // half the time
1680 double maxLoopTime = (int)(reqTimeStep * 1200f); // 1.2 the time
1681
1682// double collisionTime = 0;
1683// double qstepTIme = 0;
1684// double tmpTime = 0;
1685
1686 d.AllocateODEDataForThread(~0U);
1687
1688 if (ChangesQueue.Count > 0)
1689 {
1690 while (ChangesQueue.Dequeue(out item))
1691 {
1692 if (item.actor != null)
1693 {
1694 try
1695 {
1696 if (item.actor is OdeCharacter)
1697 ((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
1698 else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
1699 RemovePrimThreadLocked((OdePrim)item.actor);
1700 }
1701 catch
1702 {
1703 m_log.WarnFormat("[PHYSICS]: doChange failed for a actor {0} {1}",
1704 item.actor.Name, item.what.ToString());
1705 }
1706 }
1707 changestimeMS = Util.GetTimeStampMS() - loopstartMS;
1708 if (changestimeMS > maxChangestime)
1709 break;
1710 }
1711 }
1712
1713 // do simulation taking at most 150ms total time including changes
1714 while (step_time > HalfOdeStep)
1715 {
1716 try
1717 {
1718 // clear pointer/counter to contacts to pass into joints
1719 m_global_contactcount = 0;
1720
1721
1722 // Move characters
1723 lock (_characters)
1724 {
1725 List<OdeCharacter> defects = new List<OdeCharacter>();
1726 foreach (OdeCharacter actor in _characters)
1727 {
1728 if (actor != null)
1729 actor.Move(defects);
1730 }
1731 if (defects.Count != 0)
1732 {
1733 foreach (OdeCharacter defect in defects)
1734 {
1735 RemoveCharacter(defect);
1736 }
1737 defects.Clear();
1738 }
1739 }
1740
1741 // Move other active objects
1742 lock (_activegroups)
1743 {
1744 foreach (OdePrim aprim in _activegroups)
1745 {
1746 aprim.Move();
1747 }
1748 }
1749
1750 m_rayCastManager.ProcessQueuedRequests();
1751
1752// tmpTime = Util.GetTimeStampMS();
1753 collision_optimized();
1754// collisionTime += Util.GetTimeStampMS() - tmpTime;
1755
1756 lock(_collisionEventPrimRemove)
1757 {
1758 foreach (PhysicsActor obj in _collisionEventPrimRemove)
1759 _collisionEventPrim.Remove(obj);
1760
1761 _collisionEventPrimRemove.Clear();
1762 }
1763
1764 List<OdePrim> sleepers = new List<OdePrim>();
1765 foreach (PhysicsActor obj in _collisionEventPrim)
1766 {
1767 if (obj == null)
1768 continue;
1769
1770 switch ((ActorTypes)obj.PhysicsActorType)
1771 {
1772 case ActorTypes.Agent:
1773 OdeCharacter cobj = (OdeCharacter)obj;
1774 cobj.SendCollisions((int)(odetimestepMS));
1775 break;
1776
1777 case ActorTypes.Prim:
1778 OdePrim pobj = (OdePrim)obj;
1779 if (!pobj.m_outbounds)
1780 {
1781 pobj.SendCollisions((int)(odetimestepMS));
1782 if(pobj.Body != IntPtr.Zero && !pobj.m_isSelected &&
1783 !pobj.m_disabled && !pobj.m_building &&
1784 !d.BodyIsEnabled(pobj.Body))
1785 sleepers.Add(pobj);
1786 }
1787 break;
1788 }
1789 }
1790
1791 foreach(OdePrim prm in sleepers)
1792 prm.SleeperAddCollisionEvents();
1793 sleepers.Clear();
1794
1795 // do a ode simulation step
1796// tmpTime = Util.GetTimeStampMS();
1797 d.WorldQuickStep(world, ODE_STEPSIZE);
1798 d.JointGroupEmpty(contactgroup);
1799// qstepTIme += Util.GetTimeStampMS() - tmpTime;
1800
1801 // update managed ideia of physical data and do updates to core
1802 /*
1803 lock (_characters)
1804 {
1805 foreach (OdeCharacter actor in _characters)
1806 {
1807 if (actor != null)
1808 {
1809 if (actor.bad)
1810 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
1811
1812 actor.UpdatePositionAndVelocity();
1813 }
1814 }
1815 }
1816 */
1817
1818 lock (_activegroups)
1819 {
1820 {
1821 foreach (OdePrim actor in _activegroups)
1822 {
1823 if (actor.IsPhysical)
1824 {
1825 actor.UpdatePositionAndVelocity(framecount);
1826 }
1827 }
1828 }
1829 }
1830 }
1831 catch (Exception e)
1832 {
1833 m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
1834// ode.dunlock(world);
1835 }
1836
1837 step_time -= ODE_STEPSIZE;
1838 nodeframes++;
1839
1840 looptimeMS = Util.GetTimeStampMS() - loopstartMS;
1841 if (looptimeMS > maxLoopTime)
1842 break;
1843 }
1844
1845 lock (_badCharacter)
1846 {
1847 if (_badCharacter.Count > 0)
1848 {
1849 foreach (OdeCharacter chr in _badCharacter)
1850 {
1851 RemoveCharacter(chr);
1852 }
1853
1854 _badCharacter.Clear();
1855 }
1856 }
1857
1858// information block for in debug breakpoint only
1859/*
1860 int ntopactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
1861 int ntopstaticgeoms = d.SpaceGetNumGeoms(StaticSpace);
1862 int ngroundgeoms = d.SpaceGetNumGeoms(GroundSpace);
1863
1864 int nactivegeoms = 0;
1865 int nactivespaces = 0;
1866
1867 int nstaticgeoms = 0;
1868 int nstaticspaces = 0;
1869 IntPtr sp;
1870
1871 for (int i = 0; i < ntopactivegeoms; i++)
1872 {
1873 sp = d.SpaceGetGeom(ActiveSpace, i);
1874 if (d.GeomIsSpace(sp))
1875 {
1876 nactivespaces++;
1877 nactivegeoms += d.SpaceGetNumGeoms(sp);
1878 }
1879 else
1880 nactivegeoms++;
1881 }
1882
1883 for (int i = 0; i < ntopstaticgeoms; i++)
1884 {
1885 sp = d.SpaceGetGeom(StaticSpace, i);
1886 if (d.GeomIsSpace(sp))
1887 {
1888 nstaticspaces++;
1889 nstaticgeoms += d.SpaceGetNumGeoms(sp);
1890 }
1891 else
1892 nstaticgeoms++;
1893 }
1894
1895 int ntopgeoms = d.SpaceGetNumGeoms(TopSpace);
1896
1897 int totgeoms = nstaticgeoms + nactivegeoms + ngroundgeoms + 1; // one ray
1898 int nbodies = d.NTotalBodies;
1899 int ngeoms = d.NTotalGeoms;
1900*/
1901/*
1902 looptimeMS /= nodeframes;
1903 if(looptimeMS > 0.080)
1904 {
1905 collisionTime /= nodeframes;
1906 qstepTIme /= nodeframes;
1907 }
1908*/
1909 // Finished with all sim stepping. If requested, dump world state to file for debugging.
1910 // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed?
1911 // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots?
1912 if (physics_logging && (physics_logging_interval > 0) && (framecount % physics_logging_interval == 0))
1913 {
1914 string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename
1915 string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file
1916
1917 if (physics_logging_append_existing_logfile)
1918 {
1919 string header = "-------------- START OF PHYSICS FRAME " + framecount.ToString() + " --------------";
1920 TextWriter fwriter = File.AppendText(fname);
1921 fwriter.WriteLine(header);
1922 fwriter.Close();
1923 }
1924
1925 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
1926 }
1927
1928 fps = (float)nodeframes * ODE_STEPSIZE / reqTimeStep;
1929
1930 if(step_time < HalfOdeStep)
1931 m_timeDilation = 1.0f;
1932 else if (step_time > m_SkipFramesAtms)
1933 {
1934 // if we lag too much skip frames
1935 m_timeDilation = 0.0f;
1936 step_time = 0;
1937 m_lastframe = Util.GetTimeStamp(); // skip also the time lost
1938 }
1939 else
1940 {
1941 m_timeDilation = ODE_STEPSIZE / step_time;
1942 if (m_timeDilation > 1)
1943 m_timeDilation = 1;
1944 }
1945
1946 if (m_timeDilation == 1 && now - m_lastMeshExpire > 30)
1947 {
1948 mesher.ExpireReleaseMeshs();
1949 m_lastMeshExpire = now;
1950 }
1951
1952
1953 }
1954
1955 return fps;
1956 }
1957
1958 /// <summary>
1959 public override void GetResults()
1960 {
1961 }
1962
1963 public override bool IsThreaded
1964 {
1965 // for now we won't be multithreaded
1966 get { return (false); }
1967 }
1968
1969 public float GetTerrainHeightAtXY(float x, float y)
1970 {
1971 if (TerrainGeom == IntPtr.Zero)
1972 return 0f;
1973
1974 if (TerrainHeightFieldHeight == null || TerrainHeightFieldHeight.Length == 0)
1975 return 0f;
1976
1977 // TerrainHeightField for ODE as offset 1m
1978 x += 1f;
1979 y += 1f;
1980
1981 // make position fit into array
1982 if (x < 0)
1983 x = 0;
1984 if (y < 0)
1985 y = 0;
1986
1987 // integer indexs
1988 int ix;
1989 int iy;
1990 // interpolators offset
1991 float dx;
1992 float dy;
1993
1994 int regsizeX = (int)m_regionWidth + 3; // map size see setterrain number of samples
1995 int regsizeY = (int)m_regionHeight + 3; // map size see setterrain number of samples
1996 int regsize = regsizeX;
1997
1998 if (m_OSOdeLib)
1999 {
2000 if (x < regsizeX - 1)
2001 {
2002 ix = (int)x;
2003 dx = x - (float)ix;
2004 }
2005 else // out world use external height
2006 {
2007 ix = regsizeX - 2;
2008 dx = 0;
2009 }
2010 if (y < regsizeY - 1)
2011 {
2012 iy = (int)y;
2013 dy = y - (float)iy;
2014 }
2015 else
2016 {
2017 iy = regsizeY - 2;
2018 dy = 0;
2019 }
2020 }
2021 else
2022 {
2023 // we still have square fixed size regions
2024 // also flip x and y because of how map is done for ODE fliped axis
2025 // so ix,iy,dx and dy are inter exchanged
2026
2027 regsize = regsizeY;
2028
2029 if (x < regsizeX - 1)
2030 {
2031 iy = (int)x;
2032 dy = x - (float)iy;
2033 }
2034 else // out world use external height
2035 {
2036 iy = regsizeX - 2;
2037 dy = 0;
2038 }
2039 if (y < regsizeY - 1)
2040 {
2041 ix = (int)y;
2042 dx = y - (float)ix;
2043 }
2044 else
2045 {
2046 ix = regsizeY - 2;
2047 dx = 0;
2048 }
2049 }
2050
2051 float h0;
2052 float h1;
2053 float h2;
2054
2055 iy *= regsize;
2056 iy += ix; // all indexes have iy + ix
2057
2058 float[] heights = TerrainHeightFieldHeight;
2059 /*
2060 if ((dx + dy) <= 1.0f)
2061 {
2062 h0 = ((float)heights[iy]); // 0,0 vertice
2063 h1 = (((float)heights[iy + 1]) - h0) * dx; // 1,0 vertice minus 0,0
2064 h2 = (((float)heights[iy + regsize]) - h0) * dy; // 0,1 vertice minus 0,0
2065 }
2066 else
2067 {
2068 h0 = ((float)heights[iy + regsize + 1]); // 1,1 vertice
2069 h1 = (((float)heights[iy + 1]) - h0) * (1 - dy); // 1,1 vertice minus 1,0
2070 h2 = (((float)heights[iy + regsize]) - h0) * (1 - dx); // 1,1 vertice minus 0,1
2071 }
2072 */
2073 h0 = ((float)heights[iy]); // 0,0 vertice
2074
2075 if (dy>dx)
2076 {
2077 iy += regsize;
2078 h2 = (float)heights[iy]; // 0,1 vertice
2079 h1 = (h2 - h0) * dy; // 0,1 vertice minus 0,0
2080 h2 = ((float)heights[iy + 1] - h2) * dx; // 1,1 vertice minus 0,1
2081 }
2082 else
2083 {
2084 iy++;
2085 h2 = (float)heights[iy]; // vertice 1,0
2086 h1 = (h2 - h0) * dx; // 1,0 vertice minus 0,0
2087 h2 = (((float)heights[iy + regsize]) - h2) * dy; // 1,1 vertice minus 1,0
2088 }
2089
2090 return h0 + h1 + h2;
2091 }
2092
2093 public Vector3 GetTerrainNormalAtXY(float x, float y)
2094 {
2095 Vector3 norm = new Vector3(0, 0, 1);
2096
2097 if (TerrainGeom == IntPtr.Zero)
2098 return norm;
2099
2100 if (TerrainHeightFieldHeight == null || TerrainHeightFieldHeight.Length == 0)
2101 return norm;
2102
2103 // TerrainHeightField for ODE as offset 1m
2104 x += 1f;
2105 y += 1f;
2106
2107 // make position fit into array
2108 if (x < 0)
2109 x = 0;
2110 if (y < 0)
2111 y = 0;
2112
2113 // integer indexs
2114 int ix;
2115 int iy;
2116 // interpolators offset
2117 float dx;
2118 float dy;
2119
2120 int regsizeX = (int)m_regionWidth + 3; // map size see setterrain number of samples
2121 int regsizeY = (int)m_regionHeight + 3; // map size see setterrain number of samples
2122 int regsize = regsizeX;
2123
2124 int xstep = 1;
2125 int ystep = regsizeX;
2126 bool firstTri = false;
2127
2128 if (m_OSOdeLib)
2129 {
2130 if (x < regsizeX - 1)
2131 {
2132 ix = (int)x;
2133 dx = x - (float)ix;
2134 }
2135 else // out world use external height
2136 {
2137 ix = regsizeX - 2;
2138 dx = 0;
2139 }
2140 if (y < regsizeY - 1)
2141 {
2142 iy = (int)y;
2143 dy = y - (float)iy;
2144 }
2145 else
2146 {
2147 iy = regsizeY - 2;
2148 dy = 0;
2149 }
2150 firstTri = dy > dx;
2151 }
2152
2153 else
2154 {
2155 xstep = regsizeY;
2156 ystep = 1;
2157 regsize = regsizeY;
2158
2159 // we still have square fixed size regions
2160 // also flip x and y because of how map is done for ODE fliped axis
2161 // so ix,iy,dx and dy are inter exchanged
2162 if (x < regsizeX - 1)
2163 {
2164 iy = (int)x;
2165 dy = x - (float)iy;
2166 }
2167 else // out world use external height
2168 {
2169 iy = regsizeX - 2;
2170 dy = 0;
2171 }
2172 if (y < regsizeY - 1)
2173 {
2174 ix = (int)y;
2175 dx = y - (float)ix;
2176 }
2177 else
2178 {
2179 ix = regsizeY - 2;
2180 dx = 0;
2181 }
2182 firstTri = dx > dy;
2183 }
2184
2185 float h0;
2186 float h1;
2187 float h2;
2188
2189 iy *= regsize;
2190 iy += ix; // all indexes have iy + ix
2191
2192 float[] heights = TerrainHeightFieldHeight;
2193
2194 if (firstTri)
2195 {
2196 h1 = ((float)heights[iy]); // 0,0 vertice
2197 iy += ystep;
2198 h0 = (float)heights[iy]; // 0,1
2199 h2 = (float)heights[iy+xstep]; // 1,1 vertice
2200 norm.X = h0 - h2;
2201 norm.Y = h1 - h0;
2202 }
2203 else
2204 {
2205 h2 = ((float)heights[iy]); // 0,0 vertice
2206 iy += xstep;
2207 h0 = ((float)heights[iy]); // 1,0 vertice
2208 h1 = (float)heights[iy+ystep]; // vertice 1,1
2209 norm.X = h2 - h0;
2210 norm.Y = h0 - h1;
2211 }
2212 norm.Z = 1;
2213 norm.Normalize();
2214 return norm;
2215 }
2216
2217 public override void SetTerrain(float[] heightMap)
2218 {
2219 if (m_OSOdeLib)
2220 OSSetTerrain(heightMap);
2221 else
2222 OriSetTerrain(heightMap);
2223 }
2224
2225 public void OriSetTerrain(float[] heightMap)
2226 {
2227 // assumes 1m size grid and constante size square regions
2228 // needs to know about sims around in future
2229
2230 float[] _heightmap;
2231
2232 uint regionsizeX = m_regionWidth;
2233 uint regionsizeY = m_regionHeight;
2234
2235 // map is rotated
2236 uint heightmapWidth = regionsizeY + 2;
2237 uint heightmapHeight = regionsizeX + 2;
2238
2239 uint heightmapWidthSamples = heightmapWidth + 1;
2240 uint heightmapHeightSamples = heightmapHeight + 1;
2241
2242 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
2243
2244 const float scale = 1.0f;
2245 const float offset = 0.0f;
2246 const float thickness = 10f;
2247 const int wrap = 0;
2248
2249
2250 float hfmin = float.MaxValue;
2251 float hfmax = float.MinValue;
2252 float val;
2253 uint xx;
2254 uint yy;
2255
2256 uint maxXX = regionsizeX - 1;
2257 uint maxYY = regionsizeY - 1;
2258 // flipping map adding one margin all around so things don't fall in edges
2259
2260 uint xt = 0;
2261 xx = 0;
2262
2263 for (uint x = 0; x < heightmapWidthSamples; x++)
2264 {
2265 if (x > 1 && xx < maxXX)
2266 xx++;
2267 yy = 0;
2268 for (uint y = 0; y < heightmapHeightSamples; y++)
2269 {
2270 if (y > 1 && y < maxYY)
2271 yy += regionsizeX;
2272
2273 val = heightMap[yy + xx];
2274 if (val < 0.0f)
2275 val = 0.0f; // no neg terrain as in chode
2276 _heightmap[xt + y] = val;
2277
2278 if (hfmin > val)
2279 hfmin = val;
2280 if (hfmax < val)
2281 hfmax = val;
2282 }
2283 xt += heightmapHeightSamples;
2284 }
2285
2286 lock (OdeLock)
2287 {
2288 d.AllocateODEDataForThread(~0U);
2289
2290 if (TerrainGeom != IntPtr.Zero)
2291 {
2292 actor_name_map.Remove(TerrainGeom);
2293 d.GeomDestroy(TerrainGeom);
2294
2295 }
2296
2297 if (TerrainHeightFieldHeightsHandler.IsAllocated)
2298 TerrainHeightFieldHeightsHandler.Free();
2299
2300 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
2301
2302 TerrainHeightFieldHeightsHandler = GCHandle.Alloc(_heightmap, GCHandleType.Pinned);
2303
2304 d.GeomHeightfieldDataBuildSingle(HeightmapData, TerrainHeightFieldHeightsHandler.AddrOfPinnedObject(), 0,
2305 heightmapHeight, heightmapWidth ,
2306 (int)heightmapHeightSamples, (int)heightmapWidthSamples, scale,
2307 offset, thickness, wrap);
2308
2309 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
2310
2311 TerrainGeom = d.CreateHeightfield(GroundSpace, HeightmapData, 1);
2312
2313 if (TerrainGeom != IntPtr.Zero)
2314 {
2315 d.GeomSetCategoryBits(TerrainGeom, (uint)(CollisionCategories.Land));
2316 d.GeomSetCollideBits(TerrainGeom, 0);
2317
2318 PhysicsActor pa = new NullPhysicsActor();
2319 pa.Name = "Terrain";
2320 pa.PhysicsActorType = (int)ActorTypes.Ground;
2321 actor_name_map[TerrainGeom] = pa;
2322
2323// geom_name_map[GroundGeom] = "Terrain";
2324
2325 d.Quaternion q = new d.Quaternion();
2326 q.X = 0.5f;
2327 q.Y = 0.5f;
2328 q.Z = 0.5f;
2329 q.W = 0.5f;
2330
2331 d.GeomSetQuaternion(TerrainGeom, ref q);
2332 d.GeomSetPosition(TerrainGeom, m_regionWidth * 0.5f, m_regionHeight * 0.5f, 0.0f);
2333 TerrainHeightFieldHeight = _heightmap;
2334 }
2335 else
2336 TerrainHeightFieldHeightsHandler.Free();
2337 }
2338 }
2339
2340 public void OSSetTerrain(float[] heightMap)
2341 {
2342 // assumes 1m size grid and constante size square regions
2343 // needs to know about sims around in future
2344
2345 float[] _heightmap;
2346
2347 uint regionsizeX = m_regionWidth;
2348 uint regionsizeY = m_regionHeight;
2349
2350 uint heightmapWidth = regionsizeX + 2;
2351 uint heightmapHeight = regionsizeY + 2;
2352
2353 uint heightmapWidthSamples = heightmapWidth + 1;
2354 uint heightmapHeightSamples = heightmapHeight + 1;
2355
2356 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
2357
2358
2359 float hfmin = float.MaxValue;
2360// float hfmax = float.MinValue;
2361 float val;
2362
2363
2364 uint maxXX = regionsizeX + 1;
2365 uint maxYY = regionsizeY + 1;
2366 // adding one margin all around so things don't fall in edges
2367
2368 uint xx;
2369 uint yy = 0;
2370 uint yt = 0;
2371
2372 for (uint y = 0; y < heightmapHeightSamples; y++)
2373 {
2374 if (y > 1 && y < maxYY)
2375 yy += regionsizeX;
2376 xx = 0;
2377 for (uint x = 0; x < heightmapWidthSamples; x++)
2378 {
2379 if (x > 1 && x < maxXX)
2380 xx++;
2381
2382 val = heightMap[yy + xx];
2383 if (val < 0.0f)
2384 val = 0.0f; // no neg terrain as in chode
2385 _heightmap[yt + x] = val;
2386
2387 if (hfmin > val)
2388 hfmin = val;
2389// if (hfmax < val)
2390// hfmax = val;
2391 }
2392 yt += heightmapWidthSamples;
2393 }
2394
2395 lock (OdeLock)
2396 {
2397 if (TerrainGeom != IntPtr.Zero)
2398 {
2399 actor_name_map.Remove(TerrainGeom);
2400 d.GeomDestroy(TerrainGeom);
2401 }
2402
2403 if (TerrainHeightFieldHeightsHandler.IsAllocated)
2404 TerrainHeightFieldHeightsHandler.Free();
2405
2406 TerrainHeightFieldHeight = null;
2407
2408 IntPtr HeightmapData = d.GeomOSTerrainDataCreate();
2409
2410 const int wrap = 0;
2411 float thickness = hfmin;
2412 if (thickness < 0)
2413 thickness = 1;
2414
2415 TerrainHeightFieldHeightsHandler = GCHandle.Alloc(_heightmap, GCHandleType.Pinned);
2416
2417 d.GeomOSTerrainDataBuild(HeightmapData, TerrainHeightFieldHeightsHandler.AddrOfPinnedObject(), 0, 1.0f,
2418 (int)heightmapWidthSamples, (int)heightmapHeightSamples,
2419 thickness, wrap);
2420
2421// d.GeomOSTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
2422 TerrainGeom = d.CreateOSTerrain(GroundSpace, HeightmapData, 1);
2423 if (TerrainGeom != IntPtr.Zero)
2424 {
2425 d.GeomSetCategoryBits(TerrainGeom, (uint)(CollisionCategories.Land));
2426 d.GeomSetCollideBits(TerrainGeom, 0);
2427
2428 PhysicsActor pa = new NullPhysicsActor();
2429 pa.Name = "Terrain";
2430 pa.PhysicsActorType = (int)ActorTypes.Ground;
2431 actor_name_map[TerrainGeom] = pa;
2432
2433// geom_name_map[GroundGeom] = "Terrain";
2434
2435 d.GeomSetPosition(TerrainGeom, m_regionWidth * 0.5f, m_regionHeight * 0.5f, 0.0f);
2436 TerrainHeightFieldHeight = _heightmap;
2437 }
2438 else
2439 TerrainHeightFieldHeightsHandler.Free();
2440 }
2441 }
2442
2443 public override void DeleteTerrain()
2444 {
2445 }
2446
2447 public float GetWaterLevel()
2448 {
2449 return waterlevel;
2450 }
2451
2452 public override void SetWaterLevel(float baseheight)
2453 {
2454 waterlevel = baseheight;
2455 }
2456
2457 public override void Dispose()
2458 {
2459 lock (OdeLock)
2460 {
2461
2462 if (world == IntPtr.Zero)
2463 return;
2464
2465 d.AllocateODEDataForThread(~0U);
2466
2467 if (m_meshWorker != null)
2468 m_meshWorker.Stop();
2469
2470 if (m_rayCastManager != null)
2471 {
2472 m_rayCastManager.Dispose();
2473 m_rayCastManager = null;
2474 }
2475
2476 lock (_prims)
2477 {
2478 ChangesQueue.Clear();
2479 foreach (OdePrim prm in _prims.Values)
2480 {
2481 prm.DoAChange(changes.Remove, null);
2482 _collisionEventPrim.Remove(prm);
2483 }
2484 _prims.Clear();
2485 }
2486
2487 OdeCharacter[] chtorem;
2488 lock (_characters)
2489 {
2490 chtorem = new OdeCharacter[_characters.Count];
2491 _characters.CopyTo(chtorem);
2492 }
2493
2494 ChangesQueue.Clear();
2495 foreach (OdeCharacter ch in chtorem)
2496 ch.DoAChange(changes.Remove, null);
2497
2498 if (TerrainGeom != IntPtr.Zero)
2499 d.GeomDestroy(TerrainGeom);
2500 TerrainGeom = IntPtr.Zero;
2501
2502 if (TerrainHeightFieldHeightsHandler.IsAllocated)
2503 TerrainHeightFieldHeightsHandler.Free();
2504
2505 TerrainHeightFieldHeight = null;
2506
2507 if (ContactgeomsArray != IntPtr.Zero)
2508 {
2509 Marshal.FreeHGlobal(ContactgeomsArray);
2510 ContactgeomsArray = IntPtr.Zero;
2511 }
2512 if (GlobalContactsArray != IntPtr.Zero)
2513 {
2514 Marshal.FreeHGlobal(GlobalContactsArray);
2515 GlobalContactsArray = IntPtr.Zero;
2516 }
2517
2518 d.WorldDestroy(world);
2519 world = IntPtr.Zero;
2520 //d.CloseODE();
2521 }
2522 }
2523
2524 private int compareByCollisionsDesc(OdePrim A, OdePrim B)
2525 {
2526 return -A.CollisionScore.CompareTo(B.CollisionScore);
2527 }
2528
2529 public override Dictionary<uint, float> GetTopColliders()
2530 {
2531 Dictionary<uint, float> topColliders;
2532 List<OdePrim> orderedPrims;
2533 lock (_activeprims)
2534 orderedPrims = new List<OdePrim>(_activeprims);
2535
2536 orderedPrims.Sort(compareByCollisionsDesc);
2537 topColliders = orderedPrims.Take(25).ToDictionary(p => p.LocalID, p => p.CollisionScore);
2538
2539 return topColliders;
2540 }
2541
2542 public override bool SupportsRayCast()
2543 {
2544 return true;
2545 }
2546
2547 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
2548 {
2549 if (retMethod != null)
2550 {
2551 ODERayRequest req = new ODERayRequest();
2552 req.actor = null;
2553 req.callbackMethod = retMethod;
2554 req.length = length;
2555 req.Normal = direction;
2556 req.Origin = position;
2557 req.Count = 0;
2558 req.filter = RayFilterFlags.AllPrims;
2559
2560 m_rayCastManager.QueueRequest(req);
2561 }
2562 }
2563
2564 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod)
2565 {
2566 if (retMethod != null)
2567 {
2568 ODERayRequest req = new ODERayRequest();
2569 req.actor = null;
2570 req.callbackMethod = retMethod;
2571 req.length = length;
2572 req.Normal = direction;
2573 req.Origin = position;
2574 req.Count = Count;
2575 req.filter = RayFilterFlags.AllPrims;
2576
2577 m_rayCastManager.QueueRequest(req);
2578 }
2579 }
2580
2581
2582 public override List<ContactResult> RaycastWorld(Vector3 position, Vector3 direction, float length, int Count)
2583 {
2584 List<ContactResult> ourresults = new List<ContactResult>();
2585 object SyncObject = new object();
2586
2587 RayCallback retMethod = delegate(List<ContactResult> results)
2588 {
2589 lock (SyncObject)
2590 {
2591 ourresults = results;
2592 Monitor.PulseAll(SyncObject);
2593 }
2594 };
2595
2596 ODERayRequest req = new ODERayRequest();
2597 req.actor = null;
2598 req.callbackMethod = retMethod;
2599 req.length = length;
2600 req.Normal = direction;
2601 req.Origin = position;
2602 req.Count = Count;
2603 req.filter = RayFilterFlags.AllPrims;
2604
2605 lock (SyncObject)
2606 {
2607 m_rayCastManager.QueueRequest(req);
2608 if (!Monitor.Wait(SyncObject, 500))
2609 return null;
2610 else
2611 return ourresults;
2612 }
2613 }
2614
2615 public override bool SupportsRaycastWorldFiltered()
2616 {
2617 return true;
2618 }
2619
2620 public override object RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter)
2621 {
2622 object SyncObject = new object();
2623 List<ContactResult> ourresults = new List<ContactResult>();
2624
2625 RayCallback retMethod = delegate(List<ContactResult> results)
2626 {
2627 lock (SyncObject)
2628 {
2629 ourresults = results;
2630 Monitor.PulseAll(SyncObject);
2631 }
2632 };
2633
2634 ODERayRequest req = new ODERayRequest();
2635 req.actor = null;
2636 req.callbackMethod = retMethod;
2637 req.length = length;
2638 req.Normal = direction;
2639 req.Origin = position;
2640 req.Count = Count;
2641 req.filter = filter;
2642
2643 lock (SyncObject)
2644 {
2645 m_rayCastManager.QueueRequest(req);
2646 if (!Monitor.Wait(SyncObject, 500))
2647 return null;
2648 else
2649 return ourresults;
2650 }
2651 }
2652
2653 public override List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags)
2654 {
2655 if (actor == null)
2656 return new List<ContactResult>();
2657
2658 IntPtr geom;
2659 if (actor is OdePrim)
2660 geom = ((OdePrim)actor).prim_geom;
2661 else if (actor is OdeCharacter)
2662 geom = ((OdePrim)actor).prim_geom;
2663 else
2664 return new List<ContactResult>();
2665
2666 if (geom == IntPtr.Zero)
2667 return new List<ContactResult>();
2668
2669 List<ContactResult> ourResults = null;
2670 object SyncObject = new object();
2671
2672 RayCallback retMethod = delegate(List<ContactResult> results)
2673 {
2674 lock (SyncObject)
2675 {
2676 ourResults = results;
2677 Monitor.PulseAll(SyncObject);
2678 }
2679 };
2680
2681 ODERayRequest req = new ODERayRequest();
2682 req.actor = actor;
2683 req.callbackMethod = retMethod;
2684 req.length = length;
2685 req.Normal = direction;
2686 req.Origin = position;
2687 req.Count = Count;
2688 req.filter = flags;
2689
2690 lock (SyncObject)
2691 {
2692 m_rayCastManager.QueueRequest(req);
2693 if (!Monitor.Wait(SyncObject, 500))
2694 return new List<ContactResult>();
2695 }
2696
2697 if (ourResults == null)
2698 return new List<ContactResult>();
2699 return ourResults;
2700 }
2701
2702 public override List<ContactResult> BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags)
2703 {
2704 List<ContactResult> ourResults = null;
2705 object SyncObject = new object();
2706
2707 ProbeBoxCallback retMethod = delegate(List<ContactResult> results)
2708 {
2709 lock (SyncObject)
2710 {
2711 ourResults = results;
2712 Monitor.PulseAll(SyncObject);
2713 }
2714 };
2715
2716 ODERayRequest req = new ODERayRequest();
2717 req.actor = null;
2718 req.callbackMethod = retMethod;
2719 req.Normal = size;
2720 req.Origin = position;
2721 req.orientation = orientation;
2722 req.Count = Count;
2723 req.filter = flags;
2724
2725 lock (SyncObject)
2726 {
2727 m_rayCastManager.QueueRequest(req);
2728 if (!Monitor.Wait(SyncObject, 500))
2729 return new List<ContactResult>();
2730 }
2731
2732 if (ourResults == null)
2733 return new List<ContactResult>();
2734 return ourResults;
2735 }
2736
2737 public override List<ContactResult> SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags)
2738 {
2739 List<ContactResult> ourResults = null;
2740 object SyncObject = new object();
2741
2742 ProbeSphereCallback retMethod = delegate(List<ContactResult> results)
2743 {
2744 ourResults = results;
2745 Monitor.PulseAll(SyncObject);
2746 };
2747
2748 ODERayRequest req = new ODERayRequest();
2749 req.actor = null;
2750 req.callbackMethod = retMethod;
2751 req.length = radius;
2752 req.Origin = position;
2753 req.Count = Count;
2754 req.filter = flags;
2755
2756
2757 lock (SyncObject)
2758 {
2759 m_rayCastManager.QueueRequest(req);
2760 if (!Monitor.Wait(SyncObject, 500))
2761 return new List<ContactResult>();
2762 }
2763
2764 if (ourResults == null)
2765 return new List<ContactResult>();
2766 return ourResults;
2767 }
2768
2769 public override List<ContactResult> PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags)
2770 {
2771 IntPtr geom = IntPtr.Zero;;
2772
2773 if (actor != null)
2774 {
2775 if (actor is OdePrim)
2776 geom = ((OdePrim)actor).prim_geom;
2777 else if (actor is OdeCharacter)
2778 geom = ((OdePrim)actor).prim_geom;
2779 }
2780
2781 List<ContactResult> ourResults = null;
2782 object SyncObject = new object();
2783
2784 ProbePlaneCallback retMethod = delegate(List<ContactResult> results)
2785 {
2786 ourResults = results;
2787 Monitor.PulseAll(SyncObject);
2788 };
2789
2790 ODERayRequest req = new ODERayRequest();
2791 req.actor = null;
2792 req.callbackMethod = retMethod;
2793 req.length = plane.W;
2794 req.Normal.X = plane.X;
2795 req.Normal.Y = plane.Y;
2796 req.Normal.Z = plane.Z;
2797 req.Count = Count;
2798 req.filter = flags;
2799
2800 lock (SyncObject)
2801 {
2802 m_rayCastManager.QueueRequest(req);
2803 if (!Monitor.Wait(SyncObject, 500))
2804 return new List<ContactResult>();
2805 }
2806
2807 if (ourResults == null)
2808 return new List<ContactResult>();
2809 return ourResults;
2810 }
2811
2812 public override int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse)
2813 {
2814 Util.FireAndForget( delegate
2815 {
2816 ODESitAvatar sitAvatar = new ODESitAvatar(this, m_rayCastManager);
2817 if(sitAvatar != null)
2818 sitAvatar.Sit(actor, AbsolutePosition, CameraPosition, offset, AvatarSize, PhysicsSitResponse);
2819 });
2820 return 1;
2821 }
2822
2823 }
2824}
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..5baab9f
--- /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(OpenSim.VersionInfo.AssemblyVersionNumber)]
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