aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/Ode
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/PhysicsModules/Ode')
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/AssemblyInfo.cs62
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODEApi.cs2025
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs1408
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODEDynamics.c_comments630
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODEDynamics.cs981
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODEModule.cs89
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs3206
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs384
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/OdePhysicsJoint.cs46
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/OdeScene.cs3541
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs153
11 files changed, 12525 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/Ode/AssemblyInfo.cs b/OpenSim/Region/PhysicsModules/Ode/AssemblyInfo.cs
new file mode 100644
index 0000000..3691d96
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/AssemblyInfo.cs
@@ -0,0 +1,62 @@
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("OdePlugin")]
39[assembly : AssemblyDescription("")]
40[assembly : AssemblyConfiguration("")]
41[assembly : AssemblyCompany("http://opensimulator.org")]
42[assembly : AssemblyProduct("OdePlugin")]
43[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")]
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
61[assembly: Addin("OpenSim.Region.PhysicsModule.ODE", OpenSim.VersionInfo.VersionNumber)]
62[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODEApi.cs b/OpenSim/Region/PhysicsModules/Ode/ODEApi.cs
new file mode 100644
index 0000000..c851b12
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/ODEApi.cs
@@ -0,0 +1,2025 @@
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;
47
48namespace OpenSim.Region.PhysicsModule.ODE
49{
50//#if dDOUBLE
51// don't see much use in double precision with time steps of 20ms and 10 iterations used on opensim
52// at least we save same memory and memory access time, FPU performance on intel usually is similar
53// using dReal = System.Double;
54//#else
55 using dReal = System.Single;
56//#endif
57
58 public static class d
59 {
60 public static dReal Infinity = dReal.MaxValue;
61 public static int NTotalBodies = 0;
62 public static int NTotalGeoms = 0;
63
64 public const uint CONTACTS_UNIMPORTANT = 0x80000000;
65
66 #region Flags and Enumerations
67
68 [Flags]
69 public enum AllocateODEDataFlags : uint
70 {
71 BasicData = 0,
72 CollisionData = 0x00000001,
73 All = ~0u
74 }
75
76 [Flags]
77 public enum IniteODEFlags : uint
78 {
79 dInitFlagManualThreadCleanup = 0x00000001
80 }
81
82 [Flags]
83 public enum ContactFlags : int
84 {
85 Mu2 = 0x001,
86 FDir1 = 0x002,
87 Bounce = 0x004,
88 SoftERP = 0x008,
89 SoftCFM = 0x010,
90 Motion1 = 0x020,
91 Motion2 = 0x040,
92 MotionN = 0x080,
93 Slip1 = 0x100,
94 Slip2 = 0x200,
95 Approx0 = 0x0000,
96 Approx1_1 = 0x1000,
97 Approx1_2 = 0x2000,
98 Approx1 = 0x3000
99 }
100
101 public enum GeomClassID : int
102 {
103 SphereClass,
104 BoxClass,
105 CapsuleClass,
106 CylinderClass,
107 PlaneClass,
108 RayClass,
109 ConvexClass,
110 GeomTransformClass,
111 TriMeshClass,
112 HeightfieldClass,
113 FirstSpaceClass,
114 SimpleSpaceClass = FirstSpaceClass,
115 HashSpaceClass,
116 QuadTreeSpaceClass,
117 LastSpaceClass = QuadTreeSpaceClass,
118 ubtTerrainClass,
119 FirstUserClass,
120 LastUserClass = FirstUserClass + MaxUserClasses - 1,
121 NumClasses,
122 MaxUserClasses = 5
123 }
124
125 public enum JointType : int
126 {
127 None,
128 Ball,
129 Hinge,
130 Slider,
131 Contact,
132 Universal,
133 Hinge2,
134 Fixed,
135 Null,
136 AMotor,
137 LMotor,
138 Plane2D
139 }
140
141 public enum JointParam : int
142 {
143 LoStop,
144 HiStop,
145 Vel,
146 FMax,
147 FudgeFactor,
148 Bounce,
149 CFM,
150 StopERP,
151 StopCFM,
152 SuspensionERP,
153 SuspensionCFM,
154 LoStop2 = 256,
155 HiStop2,
156 Vel2,
157 FMax2,
158 FudgeFactor2,
159 Bounce2,
160 CFM2,
161 StopERP2,
162 StopCFM2,
163 SuspensionERP2,
164 SuspensionCFM2,
165 LoStop3 = 512,
166 HiStop3,
167 Vel3,
168 FMax3,
169 FudgeFactor3,
170 Bounce3,
171 CFM3,
172 StopERP3,
173 StopCFM3,
174 SuspensionERP3,
175 SuspensionCFM3
176 }
177
178 public enum dSweepAndPruneAxis : int
179 {
180 XYZ = ((0)|(1<<2)|(2<<4)),
181 XZY = ((0)|(2<<2)|(1<<4)),
182 YXZ = ((1)|(0<<2)|(2<<4)),
183 YZX = ((1)|(2<<2)|(0<<4)),
184 ZXY = ((2)|(0<<2)|(1<<4)),
185 ZYX = ((2)|(1<<2)|(0<<4))
186 }
187
188 #endregion
189
190 #region Callbacks
191
192 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
193 public delegate int AABBTestFn(IntPtr o1, IntPtr o2, ref AABB aabb);
194
195 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
196 public delegate int ColliderFn(IntPtr o1, IntPtr o2, int flags, out ContactGeom contact, int skip);
197
198 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
199 public delegate void GetAABBFn(IntPtr geom, out AABB aabb);
200
201 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
202 public delegate ColliderFn GetColliderFnFn(int num);
203
204 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
205 public delegate void GeomDtorFn(IntPtr o);
206
207 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
208 public delegate dReal HeightfieldGetHeight(IntPtr p_user_data, int x, int z);
209
210 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
211 public delegate dReal OSTerrainGetHeight(IntPtr p_user_data, int x, int z);
212
213 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
214 public delegate void NearCallback(IntPtr data, IntPtr geom1, IntPtr geom2);
215
216 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
217 public delegate int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex);
218
219 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
220 public delegate int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount);
221
222 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
223 public delegate int TriRayCallback(IntPtr trimesh, IntPtr ray, int triangleIndex, dReal u, dReal v);
224
225 #endregion
226
227 #region Structs
228
229 [StructLayout(LayoutKind.Sequential)]
230 public struct AABB
231 {
232 public dReal MinX, MaxX;
233 public dReal MinY, MaxY;
234 public dReal MinZ, MaxZ;
235 }
236
237
238 [StructLayout(LayoutKind.Sequential)]
239 public struct Contact
240 {
241 public SurfaceParameters surface;
242 public ContactGeom geom;
243 public Vector3 fdir1;
244 public static readonly int unmanagedSizeOf = Marshal.SizeOf(typeof(Contact));
245 }
246
247
248 [StructLayout(LayoutKind.Sequential)]
249 public struct ContactGeom
250 {
251
252 public Vector3 pos;
253 public Vector3 normal;
254 public dReal depth;
255 public IntPtr g1;
256 public IntPtr g2;
257 public int side1;
258 public int side2;
259 public static readonly int unmanagedSizeOf = Marshal.SizeOf(typeof(ContactGeom));
260 }
261
262 [StructLayout(LayoutKind.Sequential)]
263 public struct GeomClass
264 {
265 public int bytes;
266 public GetColliderFnFn collider;
267 public GetAABBFn aabb;
268 public AABBTestFn aabb_test;
269 public GeomDtorFn dtor;
270 }
271
272
273 [StructLayout(LayoutKind.Sequential)]
274 public struct JointFeedback
275 {
276 public Vector3 f1;
277 public Vector3 t1;
278 public Vector3 f2;
279 public Vector3 t2;
280 }
281
282
283 [StructLayout(LayoutKind.Sequential)]
284 public struct Mass
285 {
286 public dReal mass;
287 public Vector4 c;
288 public Matrix3 I;
289 }
290
291
292 [StructLayout(LayoutKind.Sequential)]
293 public struct Matrix3
294 {
295 public Matrix3(dReal m00, dReal m10, dReal m20, dReal m01, dReal m11, dReal m21, dReal m02, dReal m12, dReal m22)
296 {
297 M00 = m00; M10 = m10; M20 = m20; _m30 = 0.0f;
298 M01 = m01; M11 = m11; M21 = m21; _m31 = 0.0f;
299 M02 = m02; M12 = m12; M22 = m22; _m32 = 0.0f;
300 }
301 public dReal M00, M10, M20;
302 private dReal _m30;
303 public dReal M01, M11, M21;
304 private dReal _m31;
305 public dReal M02, M12, M22;
306 private dReal _m32;
307 }
308
309 [StructLayout(LayoutKind.Sequential)]
310 public struct Matrix4
311 {
312 public Matrix4(dReal m00, dReal m10, dReal m20, dReal m30,
313 dReal m01, dReal m11, dReal m21, dReal m31,
314 dReal m02, dReal m12, dReal m22, dReal m32,
315 dReal m03, dReal m13, dReal m23, dReal m33)
316 {
317 M00 = m00; M10 = m10; M20 = m20; M30 = m30;
318 M01 = m01; M11 = m11; M21 = m21; M31 = m31;
319 M02 = m02; M12 = m12; M22 = m22; M32 = m32;
320 M03 = m03; M13 = m13; M23 = m23; M33 = m33;
321 }
322 public dReal M00, M10, M20, M30;
323 public dReal M01, M11, M21, M31;
324 public dReal M02, M12, M22, M32;
325 public dReal M03, M13, M23, M33;
326 }
327
328 [StructLayout(LayoutKind.Sequential)]
329 public struct Quaternion
330 {
331 public dReal W, X, Y, Z;
332 }
333
334
335 [StructLayout(LayoutKind.Sequential)]
336 public struct SurfaceParameters
337 {
338 public ContactFlags mode;
339 public dReal mu;
340 public dReal mu2;
341 public dReal bounce;
342 public dReal bounce_vel;
343 public dReal soft_erp;
344 public dReal soft_cfm;
345 public dReal motion1;
346 public dReal motion2;
347 public dReal motionN;
348 public dReal slip1;
349 public dReal slip2;
350 }
351
352
353 [StructLayout(LayoutKind.Sequential)]
354 public struct Vector3
355 {
356 public Vector3(dReal x, dReal y, dReal z)
357 {
358 X = x; Y = y; Z = z; _w = 0.0f;
359 }
360 public dReal X, Y, Z;
361 private dReal _w;
362 }
363
364
365 [StructLayout(LayoutKind.Sequential)]
366 public struct Vector4
367 {
368 public Vector4(dReal x, dReal y, dReal z, dReal w)
369 {
370 X = x; Y = y; Z = z; W = w;
371 }
372 public dReal X, Y, Z, W;
373 }
374
375 #endregion
376
377 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dAllocateODEDataForThread"), SuppressUnmanagedCodeSecurity]
378 public static extern int AllocateODEDataForThread(uint ODEInitFlags);
379
380 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dAreConnected"), SuppressUnmanagedCodeSecurity]
381 public static extern bool AreConnected(IntPtr b1, IntPtr b2);
382
383 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dAreConnectedExcluding"), SuppressUnmanagedCodeSecurity]
384 public static extern bool AreConnectedExcluding(IntPtr b1, IntPtr b2, JointType joint_type);
385
386 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddForce"), SuppressUnmanagedCodeSecurity]
387 public static extern void BodyAddForce(IntPtr body, dReal fx, dReal fy, dReal fz);
388
389 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddForceAtPos"), SuppressUnmanagedCodeSecurity]
390 public static extern void BodyAddForceAtPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
391
392 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddForceAtRelPos"), SuppressUnmanagedCodeSecurity]
393 public static extern void BodyAddForceAtRelPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
394
395 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelForce"), SuppressUnmanagedCodeSecurity]
396 public static extern void BodyAddRelForce(IntPtr body, dReal fx, dReal fy, dReal fz);
397
398 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelForceAtPos"), SuppressUnmanagedCodeSecurity]
399 public static extern void BodyAddRelForceAtPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
400
401 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelForceAtRelPos"), SuppressUnmanagedCodeSecurity]
402 public static extern void BodyAddRelForceAtRelPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
403
404 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelTorque"), SuppressUnmanagedCodeSecurity]
405 public static extern void BodyAddRelTorque(IntPtr body, dReal fx, dReal fy, dReal fz);
406
407 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddTorque"), SuppressUnmanagedCodeSecurity]
408 public static extern void BodyAddTorque(IntPtr body, dReal fx, dReal fy, dReal fz);
409
410 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyPosition"), SuppressUnmanagedCodeSecurity]
411 public static extern void BodyCopyPosition(IntPtr body, out Vector3 pos);
412
413 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyPosition"), SuppressUnmanagedCodeSecurity]
414 public static extern void BodyCopyPosition(IntPtr body, out dReal X);
415
416 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyQuaternion"), SuppressUnmanagedCodeSecurity]
417 public static extern void BodyCopyQuaternion(IntPtr body, out Quaternion quat);
418
419 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyQuaternion"), SuppressUnmanagedCodeSecurity]
420 public static extern void BodyCopyQuaternion(IntPtr body, out dReal X);
421
422 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyRotation"), SuppressUnmanagedCodeSecurity]
423 public static extern void BodyCopyRotation(IntPtr body, out Matrix3 R);
424
425 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyRotation"), SuppressUnmanagedCodeSecurity]
426 public static extern void BodyCopyRotation(IntPtr body, out dReal M00);
427
428 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCreate"), SuppressUnmanagedCodeSecurity]
429 public static extern IntPtr BodyiCreate(IntPtr world);
430 public static IntPtr BodyCreate(IntPtr world)
431 {
432 NTotalBodies++;
433 return BodyiCreate(world);
434 }
435
436 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyDestroy"), SuppressUnmanagedCodeSecurity]
437 public static extern void BodyiDestroy(IntPtr body);
438 public static void BodyDestroy(IntPtr body)
439 {
440 NTotalBodies--;
441 BodyiDestroy(body);
442 }
443
444 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyDisable"), SuppressUnmanagedCodeSecurity]
445 public static extern void BodyDisable(IntPtr body);
446
447 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyEnable"), SuppressUnmanagedCodeSecurity]
448 public static extern void BodyEnable(IntPtr body);
449
450 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
451 public static extern dReal BodyGetAutoDisableAngularThreshold(IntPtr body);
452
453 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
454 public static extern bool BodyGetAutoDisableFlag(IntPtr body);
455
456 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableDefaults"), SuppressUnmanagedCodeSecurity]
457 public static extern void BodyGetAutoDisableDefaults(IntPtr body);
458
459 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
460 public static extern dReal BodyGetAutoDisableLinearThreshold(IntPtr body);
461
462 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
463 public static extern int BodyGetAutoDisableSteps(IntPtr body);
464
465 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
466 public static extern dReal BodyGetAutoDisableTime(IntPtr body);
467
468 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAngularVel"), SuppressUnmanagedCodeSecurity]
469 public extern unsafe static Vector3* BodyGetAngularVelUnsafe(IntPtr body);
470 public static Vector3 BodyGetAngularVel(IntPtr body)
471 {
472 unsafe { return *(BodyGetAngularVelUnsafe(body)); }
473 }
474
475 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetData"), SuppressUnmanagedCodeSecurity]
476 public static extern IntPtr BodyGetData(IntPtr body);
477
478 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetFiniteRotationMode"), SuppressUnmanagedCodeSecurity]
479 public static extern int BodyGetFiniteRotationMode(IntPtr body);
480
481 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetFiniteRotationAxis"), SuppressUnmanagedCodeSecurity]
482 public static extern void BodyGetFiniteRotationAxis(IntPtr body, out Vector3 result);
483
484 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetForce"), SuppressUnmanagedCodeSecurity]
485 public extern unsafe static Vector3* BodyGetForceUnsafe(IntPtr body);
486 public static Vector3 BodyGetForce(IntPtr body)
487 {
488 unsafe { return *(BodyGetForceUnsafe(body)); }
489 }
490
491 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetGravityMode"), SuppressUnmanagedCodeSecurity]
492 public static extern bool BodyGetGravityMode(IntPtr body);
493
494 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetGyroscopicMode"), SuppressUnmanagedCodeSecurity]
495 public static extern int BodyGetGyroscopicMode(IntPtr body);
496
497 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetJoint"), SuppressUnmanagedCodeSecurity]
498 public static extern IntPtr BodyGetJoint(IntPtr body, int index);
499
500 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetLinearVel"), SuppressUnmanagedCodeSecurity]
501 public extern unsafe static Vector3* BodyGetLinearVelUnsafe(IntPtr body);
502 public static Vector3 BodyGetLinearVel(IntPtr body)
503 {
504 unsafe { return *(BodyGetLinearVelUnsafe(body)); }
505 }
506
507 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetMass"), SuppressUnmanagedCodeSecurity]
508 public static extern void BodyGetMass(IntPtr body, out Mass mass);
509
510 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetNumJoints"), SuppressUnmanagedCodeSecurity]
511 public static extern int BodyGetNumJoints(IntPtr body);
512
513 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetPointVel"), SuppressUnmanagedCodeSecurity]
514 public static extern void BodyGetPointVel(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
515
516 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetPosition"), SuppressUnmanagedCodeSecurity]
517 public extern unsafe static Vector3* BodyGetPositionUnsafe(IntPtr body);
518 public static Vector3 BodyGetPosition(IntPtr body)
519 {
520 unsafe { return *(BodyGetPositionUnsafe(body)); }
521 }
522
523 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetPosRelPoint"), SuppressUnmanagedCodeSecurity]
524 public static extern void BodyGetPosRelPoint(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
525
526 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetQuaternion"), SuppressUnmanagedCodeSecurity]
527 public extern unsafe static Quaternion* BodyGetQuaternionUnsafe(IntPtr body);
528 public static Quaternion BodyGetQuaternion(IntPtr body)
529 {
530 unsafe { return *(BodyGetQuaternionUnsafe(body)); }
531 }
532
533 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetRelPointPos"), SuppressUnmanagedCodeSecurity]
534 public static extern void BodyGetRelPointPos(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
535
536 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetRelPointVel"), SuppressUnmanagedCodeSecurity]
537 public static extern void BodyGetRelPointVel(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
538
539 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetRotation"), SuppressUnmanagedCodeSecurity]
540 public extern unsafe static Matrix3* BodyGetRotationUnsafe(IntPtr body);
541 public static Matrix3 BodyGetRotation(IntPtr body)
542 {
543 unsafe { return *(BodyGetRotationUnsafe(body)); }
544 }
545
546 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetTorque"), SuppressUnmanagedCodeSecurity]
547 public extern unsafe static Vector3* BodyGetTorqueUnsafe(IntPtr body);
548 public static Vector3 BodyGetTorque(IntPtr body)
549 {
550 unsafe { return *(BodyGetTorqueUnsafe(body)); }
551 }
552
553 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetWorld"), SuppressUnmanagedCodeSecurity]
554 public static extern IntPtr BodyGetWorld(IntPtr body);
555
556 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetFirstGeom"), SuppressUnmanagedCodeSecurity]
557 public static extern IntPtr BodyGetFirstGeom(IntPtr body);
558
559 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetNextGeom"), SuppressUnmanagedCodeSecurity]
560 public static extern IntPtr dBodyGetNextGeom(IntPtr Geom);
561
562
563 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyIsEnabled"), SuppressUnmanagedCodeSecurity]
564 public static extern bool BodyIsEnabled(IntPtr body);
565
566 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularVel"), SuppressUnmanagedCodeSecurity]
567 public static extern void BodySetAngularVel(IntPtr body, dReal x, dReal y, dReal z);
568
569 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
570 public static extern void BodySetAutoDisableAngularThreshold(IntPtr body, dReal angular_threshold);
571
572 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableDefaults"), SuppressUnmanagedCodeSecurity]
573 public static extern void BodySetAutoDisableDefaults(IntPtr body);
574
575 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
576 public static extern void BodySetAutoDisableFlag(IntPtr body, bool do_auto_disable);
577
578 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
579 public static extern void BodySetAutoDisableLinearThreshold(IntPtr body, dReal linear_threshold);
580
581 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
582 public static extern void BodySetAutoDisableSteps(IntPtr body, int steps);
583
584 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
585 public static extern void BodySetAutoDisableTime(IntPtr body, dReal time);
586
587 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetData"), SuppressUnmanagedCodeSecurity]
588 public static extern void BodySetData(IntPtr body, IntPtr data);
589
590 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetFiniteRotationMode"), SuppressUnmanagedCodeSecurity]
591 public static extern void BodySetFiniteRotationMode(IntPtr body, int mode);
592
593 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetFiniteRotationAxis"), SuppressUnmanagedCodeSecurity]
594 public static extern void BodySetFiniteRotationAxis(IntPtr body, dReal x, dReal y, dReal z);
595
596 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetLinearDamping"), SuppressUnmanagedCodeSecurity]
597 public static extern void BodySetLinearDamping(IntPtr body, dReal scale);
598
599 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularDamping"), SuppressUnmanagedCodeSecurity]
600 public static extern void BodySetAngularDamping(IntPtr body, dReal scale);
601
602 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetLinearDamping"), SuppressUnmanagedCodeSecurity]
603 public static extern dReal BodyGetLinearDamping(IntPtr body);
604
605 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAngularDamping"), SuppressUnmanagedCodeSecurity]
606 public static extern dReal BodyGetAngularDamping(IntPtr body);
607
608 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularDamping"), SuppressUnmanagedCodeSecurity]
609 public static extern void BodySetDamping(IntPtr body, dReal linear_scale, dReal angular_scale);
610
611 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
612 public static extern void BodySetAngularDampingThreshold(IntPtr body, dReal threshold);
613
614 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
615 public static extern void BodySetLinearDampingThreshold(IntPtr body, dReal threshold);
616
617 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
618 public static extern dReal BodyGetLinearDampingThreshold(IntPtr body);
619
620 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
621 public static extern dReal BodyGetAngularDampingThreshold(IntPtr body);
622
623 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetForce"), SuppressUnmanagedCodeSecurity]
624 public static extern void BodySetForce(IntPtr body, dReal x, dReal y, dReal z);
625
626 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetGravityMode"), SuppressUnmanagedCodeSecurity]
627 public static extern void BodySetGravityMode(IntPtr body, bool mode);
628
629 /// <summary>
630 /// Sets the Gyroscopic term status on the body specified.
631 /// </summary>
632 /// <param name="body">Pointer to body</param>
633 /// <param name="enabled">NonZero enabled, Zero disabled</param>
634 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetGyroscopicMode"), SuppressUnmanagedCodeSecurity]
635 public static extern void dBodySetGyroscopicMode(IntPtr body, int enabled);
636
637 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetLinearVel"), SuppressUnmanagedCodeSecurity]
638 public static extern void BodySetLinearVel(IntPtr body, dReal x, dReal y, dReal z);
639
640 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetMass"), SuppressUnmanagedCodeSecurity]
641 public static extern void BodySetMass(IntPtr body, ref Mass mass);
642
643 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetPosition"), SuppressUnmanagedCodeSecurity]
644 public static extern void BodySetPosition(IntPtr body, dReal x, dReal y, dReal z);
645
646 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetQuaternion"), SuppressUnmanagedCodeSecurity]
647 public static extern void BodySetQuaternion(IntPtr body, ref Quaternion q);
648
649 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetQuaternion"), SuppressUnmanagedCodeSecurity]
650 public static extern void BodySetQuaternion(IntPtr body, ref dReal w);
651
652 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetRotation"), SuppressUnmanagedCodeSecurity]
653 public static extern void BodySetRotation(IntPtr body, ref Matrix3 R);
654
655 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetRotation"), SuppressUnmanagedCodeSecurity]
656 public static extern void BodySetRotation(IntPtr body, ref dReal M00);
657
658 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetTorque"), SuppressUnmanagedCodeSecurity]
659 public static extern void BodySetTorque(IntPtr body, dReal x, dReal y, dReal z);
660
661 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyVectorFromWorld"), SuppressUnmanagedCodeSecurity]
662 public static extern void BodyVectorFromWorld(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
663
664 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyVectorToWorld"), SuppressUnmanagedCodeSecurity]
665 public static extern void BodyVectorToWorld(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
666
667 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBoxBox"), SuppressUnmanagedCodeSecurity]
668 public static extern void BoxBox(ref Vector3 p1, ref Matrix3 R1,
669 ref Vector3 side1, ref Vector3 p2,
670 ref Matrix3 R2, ref Vector3 side2,
671 ref Vector3 normal, out dReal depth, out int return_code,
672 int maxc, out ContactGeom contact, int skip);
673
674 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBoxTouchesBox"), SuppressUnmanagedCodeSecurity]
675 public static extern void BoxTouchesBox(ref Vector3 _p1, ref Matrix3 R1,
676 ref Vector3 side1, ref Vector3 _p2,
677 ref Matrix3 R2, ref Vector3 side2);
678
679 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCleanupODEAllDataForThread"), SuppressUnmanagedCodeSecurity]
680 public static extern void CleanupODEAllDataForThread();
681
682 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dClosestLineSegmentPoints"), SuppressUnmanagedCodeSecurity]
683 public static extern void ClosestLineSegmentPoints(ref Vector3 a1, ref Vector3 a2,
684 ref Vector3 b1, ref Vector3 b2,
685 ref Vector3 cp1, ref Vector3 cp2);
686
687 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCloseODE"), SuppressUnmanagedCodeSecurity]
688 public static extern void CloseODE();
689
690 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCollide"), SuppressUnmanagedCodeSecurity]
691 public static extern int Collide(IntPtr o1, IntPtr o2, int flags, [In, Out] ContactGeom[] contact, int skip);
692 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCollide"), SuppressUnmanagedCodeSecurity]
693 public static extern int CollidePtr(IntPtr o1, IntPtr o2, int flags, IntPtr contactgeomarray, int skip);
694
695 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dConnectingJoint"), SuppressUnmanagedCodeSecurity]
696 public static extern IntPtr ConnectingJoint(IntPtr j1, IntPtr j2);
697
698 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateBox"), SuppressUnmanagedCodeSecurity]
699 public static extern IntPtr CreateiBox(IntPtr space, dReal lx, dReal ly, dReal lz);
700 public static IntPtr CreateBox(IntPtr space, dReal lx, dReal ly, dReal lz)
701 {
702 NTotalGeoms++;
703 return CreateiBox(space, lx, ly, lz);
704 }
705
706 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateCapsule"), SuppressUnmanagedCodeSecurity]
707 public static extern IntPtr CreateiCapsule(IntPtr space, dReal radius, dReal length);
708 public static IntPtr CreateCapsule(IntPtr space, dReal radius, dReal length)
709 {
710 NTotalGeoms++;
711 return CreateiCapsule(space, radius, length);
712 }
713
714 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateConvex"), SuppressUnmanagedCodeSecurity]
715 public static extern IntPtr CreateiConvex(IntPtr space, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
716 public static IntPtr CreateConvex(IntPtr space, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons)
717 {
718 NTotalGeoms++;
719 return CreateiConvex(space, planes, planeCount, points, pointCount, polygons);
720 }
721
722 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateCylinder"), SuppressUnmanagedCodeSecurity]
723 public static extern IntPtr CreateiCylinder(IntPtr space, dReal radius, dReal length);
724 public static IntPtr CreateCylinder(IntPtr space, dReal radius, dReal length)
725 {
726 NTotalGeoms++;
727 return CreateiCylinder(space, radius, length);
728 }
729
730 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateHeightfield"), SuppressUnmanagedCodeSecurity]
731 public static extern IntPtr CreateiHeightfield(IntPtr space, IntPtr data, int bPlaceable);
732 public static IntPtr CreateHeightfield(IntPtr space, IntPtr data, int bPlaceable)
733 {
734 NTotalGeoms++;
735 return CreateiHeightfield(space, data, bPlaceable);
736 }
737
738 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateOSTerrain"), SuppressUnmanagedCodeSecurity]
739 public static extern IntPtr CreateiOSTerrain(IntPtr space, IntPtr data, int bPlaceable);
740 public static IntPtr CreateOSTerrain(IntPtr space, IntPtr data, int bPlaceable)
741 {
742 NTotalGeoms++;
743 return CreateiOSTerrain(space, data, bPlaceable);
744 }
745
746
747
748
749
750 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeom"), SuppressUnmanagedCodeSecurity]
751 public static extern IntPtr CreateiGeom(int classnum);
752 public static IntPtr CreateGeom(int classnum)
753 {
754 NTotalGeoms++;
755 return CreateiGeom(classnum);
756 }
757
758 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeomClass"), SuppressUnmanagedCodeSecurity]
759 public static extern int CreateGeomClass(ref GeomClass classptr);
760
761 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeomTransform"), SuppressUnmanagedCodeSecurity]
762 public static extern IntPtr CreateGeomTransform(IntPtr space);
763
764 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreatePlane"), SuppressUnmanagedCodeSecurity]
765 public static extern IntPtr CreateiPlane(IntPtr space, dReal a, dReal b, dReal c, dReal d);
766 public static IntPtr CreatePlane(IntPtr space, dReal a, dReal b, dReal c, dReal d)
767 {
768 NTotalGeoms++;
769 return CreateiPlane(space, a, b, c, d);
770 }
771
772 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateRay"), SuppressUnmanagedCodeSecurity]
773 public static extern IntPtr CreateiRay(IntPtr space, dReal length);
774 public static IntPtr CreateRay(IntPtr space, dReal length)
775 {
776 NTotalGeoms++;
777 return CreateiRay(space, length);
778 }
779
780 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateSphere"), SuppressUnmanagedCodeSecurity]
781 public static extern IntPtr CreateiSphere(IntPtr space, dReal radius);
782 public static IntPtr CreateSphere(IntPtr space, dReal radius)
783 {
784 NTotalGeoms++;
785 return CreateiSphere(space, radius);
786 }
787
788 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateTriMesh"), SuppressUnmanagedCodeSecurity]
789 public static extern IntPtr CreateiTriMesh(IntPtr space, IntPtr data,
790 TriCallback callback, TriArrayCallback arrayCallback, TriRayCallback rayCallback);
791 public static IntPtr CreateTriMesh(IntPtr space, IntPtr data,
792 TriCallback callback, TriArrayCallback arrayCallback, TriRayCallback rayCallback)
793 {
794 NTotalGeoms++;
795 return CreateiTriMesh(space, data, callback, arrayCallback, rayCallback);
796 }
797 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dDot"), SuppressUnmanagedCodeSecurity]
798 public static extern dReal Dot(ref dReal X0, ref dReal X1, int n);
799
800 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dDQfromW"), SuppressUnmanagedCodeSecurity]
801 public static extern void DQfromW(dReal[] dq, ref Vector3 w, ref Quaternion q);
802
803 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dFactorCholesky"), SuppressUnmanagedCodeSecurity]
804 public static extern int FactorCholesky(ref dReal A00, int n);
805
806 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dFactorLDLT"), SuppressUnmanagedCodeSecurity]
807 public static extern void FactorLDLT(ref dReal A, out dReal d, int n, int nskip);
808
809 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxGetLengths"), SuppressUnmanagedCodeSecurity]
810 public static extern void GeomBoxGetLengths(IntPtr geom, out Vector3 len);
811
812 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxGetLengths"), SuppressUnmanagedCodeSecurity]
813 public static extern void GeomBoxGetLengths(IntPtr geom, out dReal x);
814
815 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxPointDepth"), SuppressUnmanagedCodeSecurity]
816 public static extern dReal GeomBoxPointDepth(IntPtr geom, dReal x, dReal y, dReal z);
817
818 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxSetLengths"), SuppressUnmanagedCodeSecurity]
819 public static extern void GeomBoxSetLengths(IntPtr geom, dReal x, dReal y, dReal z);
820
821 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCapsuleGetParams"), SuppressUnmanagedCodeSecurity]
822 public static extern void GeomCapsuleGetParams(IntPtr geom, out dReal radius, out dReal length);
823
824 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCapsulePointDepth"), SuppressUnmanagedCodeSecurity]
825 public static extern dReal GeomCapsulePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
826
827 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCapsuleSetParams"), SuppressUnmanagedCodeSecurity]
828 public static extern void GeomCapsuleSetParams(IntPtr geom, dReal radius, dReal length);
829
830 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomClearOffset"), SuppressUnmanagedCodeSecurity]
831 public static extern void GeomClearOffset(IntPtr geom);
832
833 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetPosition"), SuppressUnmanagedCodeSecurity]
834 public static extern IntPtr GeomCopyOffsetPosition(IntPtr geom, ref Vector3 pos);
835
836 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetPosition"), SuppressUnmanagedCodeSecurity]
837 public static extern IntPtr GeomCopyOffsetPosition(IntPtr geom, ref dReal X);
838
839 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
840 public static extern void GeomCopyOffsetQuaternion(IntPtr geom, ref Quaternion Q);
841
842 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
843 public static extern void GeomCopyOffsetQuaternion(IntPtr geom, ref dReal X);
844
845 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetRotation"), SuppressUnmanagedCodeSecurity]
846 public static extern IntPtr GeomCopyOffsetRotation(IntPtr geom, ref Matrix3 R);
847
848 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetRotation"), SuppressUnmanagedCodeSecurity]
849 public static extern IntPtr GeomCopyOffsetRotation(IntPtr geom, ref dReal M00);
850
851 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyPosition"), SuppressUnmanagedCodeSecurity]
852 public static extern void GeomCopyPosition(IntPtr geom, out Vector3 pos);
853
854 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyPosition"), SuppressUnmanagedCodeSecurity]
855 public static extern void GeomCopyPosition(IntPtr geom, out dReal X);
856
857 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyRotation"), SuppressUnmanagedCodeSecurity]
858 public static extern void GeomCopyRotation(IntPtr geom, out Matrix3 R);
859
860 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyRotation"), SuppressUnmanagedCodeSecurity]
861 public static extern void GeomCopyRotation(IntPtr geom, out dReal M00);
862
863 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCylinderGetParams"), SuppressUnmanagedCodeSecurity]
864 public static extern void GeomCylinderGetParams(IntPtr geom, out dReal radius, out dReal length);
865
866 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCylinderSetParams"), SuppressUnmanagedCodeSecurity]
867 public static extern void GeomCylinderSetParams(IntPtr geom, dReal radius, dReal length);
868
869 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomDestroy"), SuppressUnmanagedCodeSecurity]
870 public static extern void GeomiDestroy(IntPtr geom);
871 public static void GeomDestroy(IntPtr geom)
872 {
873 NTotalGeoms--;
874 GeomiDestroy(geom);
875 }
876
877
878 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomDisable"), SuppressUnmanagedCodeSecurity]
879 public static extern void GeomDisable(IntPtr geom);
880
881 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomEnable"), SuppressUnmanagedCodeSecurity]
882 public static extern void GeomEnable(IntPtr geom);
883
884 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetAABB"), SuppressUnmanagedCodeSecurity]
885 public static extern void GeomGetAABB(IntPtr geom, out AABB aabb);
886
887 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetAABB"), SuppressUnmanagedCodeSecurity]
888 public static extern void GeomGetAABB(IntPtr geom, out dReal minX);
889
890 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetBody"), SuppressUnmanagedCodeSecurity]
891 public static extern IntPtr GeomGetBody(IntPtr geom);
892
893 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetCategoryBits"), SuppressUnmanagedCodeSecurity]
894 public static extern uint GeomGetCategoryBits(IntPtr geom);
895
896 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetClassData"), SuppressUnmanagedCodeSecurity]
897 public static extern IntPtr GeomGetClassData(IntPtr geom);
898
899 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetCollideBits"), SuppressUnmanagedCodeSecurity]
900 public static extern uint GeomGetCollideBits(IntPtr geom);
901
902 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetClass"), SuppressUnmanagedCodeSecurity]
903 public static extern GeomClassID GeomGetClass(IntPtr geom);
904
905 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetData"), SuppressUnmanagedCodeSecurity]
906 public static extern IntPtr GeomGetData(IntPtr geom);
907
908 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetPosition"), SuppressUnmanagedCodeSecurity]
909 public extern unsafe static Vector3* GeomGetOffsetPositionUnsafe(IntPtr geom);
910 public static Vector3 GeomGetOffsetPosition(IntPtr geom)
911 {
912 unsafe { return *(GeomGetOffsetPositionUnsafe(geom)); }
913 }
914
915 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetRotation"), SuppressUnmanagedCodeSecurity]
916 public extern unsafe static Matrix3* GeomGetOffsetRotationUnsafe(IntPtr geom);
917 public static Matrix3 GeomGetOffsetRotation(IntPtr geom)
918 {
919 unsafe { return *(GeomGetOffsetRotationUnsafe(geom)); }
920 }
921
922 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetPosition"), SuppressUnmanagedCodeSecurity]
923 public extern unsafe static Vector3* GeomGetPositionUnsafe(IntPtr geom);
924 public static Vector3 GeomGetPosition(IntPtr geom)
925 {
926 unsafe { return *(GeomGetPositionUnsafe(geom)); }
927 }
928 public static OMV.Vector3 GeomGetPositionOMV(IntPtr geom)
929 {
930 Vector3 vtmp = GeomGetPosition(geom);
931 return new OMV.Vector3(vtmp.X, vtmp.Y, vtmp.Z);
932 }
933
934 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity]
935 public static extern void GeomCopyQuaternion(IntPtr geom, out Quaternion q);
936 public static OMV.Quaternion GeomGetQuaternionOMV(IntPtr geom)
937 {
938 Quaternion qtmp;
939 GeomCopyQuaternion(geom, out qtmp);
940 return new OMV.Quaternion(qtmp.X, qtmp.Y, qtmp.Z, qtmp.W);
941 }
942
943 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity]
944 public static extern void GeomCopyQuaternion(IntPtr geom, out dReal X);
945
946 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetRotation"), SuppressUnmanagedCodeSecurity]
947 public extern unsafe static Matrix3* GeomGetRotationUnsafe(IntPtr geom);
948 public static Matrix3 GeomGetRotation(IntPtr geom)
949 {
950 unsafe { return *(GeomGetRotationUnsafe(geom)); }
951 }
952
953 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetSpace"), SuppressUnmanagedCodeSecurity]
954 public static extern IntPtr GeomGetSpace(IntPtr geom);
955
956 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildByte"), SuppressUnmanagedCodeSecurity]
957 public static extern void GeomHeightfieldDataBuildByte(IntPtr d, byte[] pHeightData, int bCopyHeightData,
958 dReal width, dReal depth, int widthSamples, int depthSamples,
959 dReal scale, dReal offset, dReal thickness, int bWrap);
960
961 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildByte"), SuppressUnmanagedCodeSecurity]
962 public static extern void GeomHeightfieldDataBuildByte(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
963 dReal width, dReal depth, int widthSamples, int depthSamples,
964 dReal scale, dReal offset, dReal thickness, int bWrap);
965
966 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildCallback"), SuppressUnmanagedCodeSecurity]
967 public static extern void GeomHeightfieldDataBuildCallback(IntPtr d, IntPtr pUserData, HeightfieldGetHeight pCallback,
968 dReal width, dReal depth, int widthSamples, int depthSamples,
969 dReal scale, dReal offset, dReal thickness, int bWrap);
970
971 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
972 public static extern void GeomHeightfieldDataBuildShort(IntPtr d, ushort[] pHeightData, int bCopyHeightData,
973 dReal width, dReal depth, int widthSamples, int depthSamples,
974 dReal scale, dReal offset, dReal thickness, int bWrap);
975
976 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
977 public static extern void GeomHeightfieldDataBuildShort(IntPtr d, short[] pHeightData, int bCopyHeightData,
978 dReal width, dReal depth, int widthSamples, int depthSamples,
979 dReal scale, dReal offset, dReal thickness, int bWrap);
980
981 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
982 public static extern void GeomHeightfieldDataBuildShort(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
983 dReal width, dReal depth, int widthSamples, int depthSamples,
984 dReal scale, dReal offset, dReal thickness, int bWrap);
985
986 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildSingle"), SuppressUnmanagedCodeSecurity]
987 public static extern void GeomHeightfieldDataBuildSingle(IntPtr d, float[] pHeightData, int bCopyHeightData,
988 dReal width, dReal depth, int widthSamples, int depthSamples,
989 dReal scale, dReal offset, dReal thickness, int bWrap);
990
991 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildSingle"), SuppressUnmanagedCodeSecurity]
992 public static extern void GeomHeightfieldDataBuildSingle(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
993 dReal width, dReal depth, int widthSamples, int depthSamples,
994 dReal scale, dReal offset, dReal thickness, int bWrap);
995
996
997
998 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity]
999 public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, double[] pHeightData, int bCopyHeightData,
1000 dReal width, dReal depth, int widthSamples, int depthSamples,
1001 dReal scale, dReal offset, dReal thickness, int bWrap);
1002
1003 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity]
1004 public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
1005 dReal width, dReal depth, int widthSamples, int depthSamples,
1006 dReal scale, dReal offset, dReal thickness, int bWrap);
1007
1008 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataCreate"), SuppressUnmanagedCodeSecurity]
1009 public static extern IntPtr GeomHeightfieldDataCreate();
1010
1011 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataDestroy"), SuppressUnmanagedCodeSecurity]
1012 public static extern void GeomHeightfieldDataDestroy(IntPtr d);
1013
1014 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataSetBounds"), SuppressUnmanagedCodeSecurity]
1015 public static extern void GeomHeightfieldDataSetBounds(IntPtr d, dReal minHeight, dReal maxHeight);
1016
1017 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldGetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1018 public static extern IntPtr GeomHeightfieldGetHeightfieldData(IntPtr g);
1019
1020 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldSetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1021 public static extern void GeomHeightfieldSetHeightfieldData(IntPtr g, IntPtr d);
1022
1023
1024 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataBuild"), SuppressUnmanagedCodeSecurity]
1025 public static extern void GeomOSTerrainDataBuild(IntPtr d, float[] pHeightData, int bCopyHeightData,
1026 dReal sampleSize, int widthSamples, int depthSamples,
1027 dReal offset, dReal thickness, int bWrap);
1028
1029 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataBuild"), SuppressUnmanagedCodeSecurity]
1030 public static extern void GeomOSTerrainDataBuild(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
1031 dReal sampleSize, int widthSamples, int depthSamples,
1032 dReal thickness, int bWrap);
1033
1034 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataCreate"), SuppressUnmanagedCodeSecurity]
1035 public static extern IntPtr GeomOSTerrainDataCreate();
1036
1037 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataDestroy"), SuppressUnmanagedCodeSecurity]
1038 public static extern void GeomOSTerrainDataDestroy(IntPtr d);
1039
1040 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataSetBounds"), SuppressUnmanagedCodeSecurity]
1041 public static extern void GeomOSTerrainDataSetBounds(IntPtr d, dReal minHeight, dReal maxHeight);
1042
1043 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainGetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1044 public static extern IntPtr GeomOSTerrainGetHeightfieldData(IntPtr g);
1045
1046 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainSetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1047 public static extern void GeomOSTerrainSetHeightfieldData(IntPtr g, IntPtr d);
1048
1049
1050 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsEnabled"), SuppressUnmanagedCodeSecurity]
1051 public static extern bool GeomIsEnabled(IntPtr geom);
1052
1053 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsOffset"), SuppressUnmanagedCodeSecurity]
1054 public static extern bool GeomIsOffset(IntPtr geom);
1055
1056 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsSpace"), SuppressUnmanagedCodeSecurity]
1057 public static extern bool GeomIsSpace(IntPtr geom);
1058
1059 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlaneGetParams"), SuppressUnmanagedCodeSecurity]
1060 public static extern void GeomPlaneGetParams(IntPtr geom, ref Vector4 result);
1061
1062 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlaneGetParams"), SuppressUnmanagedCodeSecurity]
1063 public static extern void GeomPlaneGetParams(IntPtr geom, ref dReal A);
1064
1065 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlanePointDepth"), SuppressUnmanagedCodeSecurity]
1066 public static extern dReal GeomPlanePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
1067
1068 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlaneSetParams"), SuppressUnmanagedCodeSecurity]
1069 public static extern void GeomPlaneSetParams(IntPtr plane, dReal a, dReal b, dReal c, dReal d);
1070
1071 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGet"), SuppressUnmanagedCodeSecurity]
1072 public static extern void GeomRayGet(IntPtr ray, ref Vector3 start, ref Vector3 dir);
1073
1074 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGet"), SuppressUnmanagedCodeSecurity]
1075 public static extern void GeomRayGet(IntPtr ray, ref dReal startX, ref dReal dirX);
1076
1077 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGetClosestHit"), SuppressUnmanagedCodeSecurity]
1078 public static extern int GeomRayGetClosestHit(IntPtr ray);
1079
1080 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGetLength"), SuppressUnmanagedCodeSecurity]
1081 public static extern dReal GeomRayGetLength(IntPtr ray);
1082
1083 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGetParams"), SuppressUnmanagedCodeSecurity]
1084 public static extern dReal GeomRayGetParams(IntPtr g, out int firstContact, out int backfaceCull);
1085
1086 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySet"), SuppressUnmanagedCodeSecurity]
1087 public static extern void GeomRaySet(IntPtr ray, dReal px, dReal py, dReal pz, dReal dx, dReal dy, dReal dz);
1088
1089 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySetClosestHit"), SuppressUnmanagedCodeSecurity]
1090 public static extern void GeomRaySetClosestHit(IntPtr ray, int closestHit);
1091
1092 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySetLength"), SuppressUnmanagedCodeSecurity]
1093 public static extern void GeomRaySetLength(IntPtr ray, dReal length);
1094
1095 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySetParams"), SuppressUnmanagedCodeSecurity]
1096 public static extern void GeomRaySetParams(IntPtr ray, int firstContact, int backfaceCull);
1097
1098 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetBody"), SuppressUnmanagedCodeSecurity]
1099 public static extern void GeomSetBody(IntPtr geom, IntPtr body);
1100
1101 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetCategoryBits"), SuppressUnmanagedCodeSecurity]
1102 public static extern void GeomSetCategoryBits(IntPtr geom, uint bits);
1103
1104 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetCollideBits"), SuppressUnmanagedCodeSecurity]
1105 public static extern void GeomSetCollideBits(IntPtr geom, uint bits);
1106
1107 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetConvex"), SuppressUnmanagedCodeSecurity]
1108 public static extern IntPtr GeomSetConvex(IntPtr geom, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
1109
1110 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetData"), SuppressUnmanagedCodeSecurity]
1111 public static extern void GeomSetData(IntPtr geom, IntPtr data);
1112
1113 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetPosition"), SuppressUnmanagedCodeSecurity]
1114 public static extern void GeomSetOffsetPosition(IntPtr geom, dReal x, dReal y, dReal z);
1115
1116 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
1117 public static extern void GeomSetOffsetQuaternion(IntPtr geom, ref Quaternion Q);
1118
1119 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
1120 public static extern void GeomSetOffsetQuaternion(IntPtr geom, ref dReal X);
1121
1122 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetRotation"), SuppressUnmanagedCodeSecurity]
1123 public static extern void GeomSetOffsetRotation(IntPtr geom, ref Matrix3 R);
1124
1125 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetRotation"), SuppressUnmanagedCodeSecurity]
1126 public static extern void GeomSetOffsetRotation(IntPtr geom, ref dReal M00);
1127
1128 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldPosition"), SuppressUnmanagedCodeSecurity]
1129 public static extern void GeomSetOffsetWorldPosition(IntPtr geom, dReal x, dReal y, dReal z);
1130
1131 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldQuaternion"), SuppressUnmanagedCodeSecurity]
1132 public static extern void GeomSetOffsetWorldQuaternion(IntPtr geom, ref Quaternion Q);
1133
1134 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldQuaternion"), SuppressUnmanagedCodeSecurity]
1135 public static extern void GeomSetOffsetWorldQuaternion(IntPtr geom, ref dReal X);
1136
1137 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldRotation"), SuppressUnmanagedCodeSecurity]
1138 public static extern void GeomSetOffsetWorldRotation(IntPtr geom, ref Matrix3 R);
1139
1140 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldRotation"), SuppressUnmanagedCodeSecurity]
1141 public static extern void GeomSetOffsetWorldRotation(IntPtr geom, ref dReal M00);
1142
1143 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetPosition"), SuppressUnmanagedCodeSecurity]
1144 public static extern void GeomSetPosition(IntPtr geom, dReal x, dReal y, dReal z);
1145
1146 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetQuaternion"), SuppressUnmanagedCodeSecurity]
1147 public static extern void GeomSetQuaternion(IntPtr geom, ref Quaternion quat);
1148
1149 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetQuaternion"), SuppressUnmanagedCodeSecurity]
1150 public static extern void GeomSetQuaternion(IntPtr geom, ref dReal w);
1151
1152 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetRotation"), SuppressUnmanagedCodeSecurity]
1153 public static extern void GeomSetRotation(IntPtr geom, ref Matrix3 R);
1154
1155 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetRotation"), SuppressUnmanagedCodeSecurity]
1156 public static extern void GeomSetRotation(IntPtr geom, ref dReal M00);
1157
1158 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSphereGetRadius"), SuppressUnmanagedCodeSecurity]
1159 public static extern dReal GeomSphereGetRadius(IntPtr geom);
1160
1161 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSpherePointDepth"), SuppressUnmanagedCodeSecurity]
1162 public static extern dReal GeomSpherePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
1163
1164 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSphereSetRadius"), SuppressUnmanagedCodeSecurity]
1165 public static extern void GeomSphereSetRadius(IntPtr geom, dReal radius);
1166
1167 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformGetCleanup"), SuppressUnmanagedCodeSecurity]
1168 public static extern int GeomTransformGetCleanup(IntPtr geom);
1169
1170 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformGetGeom"), SuppressUnmanagedCodeSecurity]
1171 public static extern IntPtr GeomTransformGetGeom(IntPtr geom);
1172
1173 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformGetInfo"), SuppressUnmanagedCodeSecurity]
1174 public static extern int GeomTransformGetInfo(IntPtr geom);
1175
1176 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformSetCleanup"), SuppressUnmanagedCodeSecurity]
1177 public static extern void GeomTransformSetCleanup(IntPtr geom, int mode);
1178
1179 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformSetGeom"), SuppressUnmanagedCodeSecurity]
1180 public static extern void GeomTransformSetGeom(IntPtr geom, IntPtr obj);
1181
1182 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformSetInfo"), SuppressUnmanagedCodeSecurity]
1183 public static extern void GeomTransformSetInfo(IntPtr geom, int info);
1184
1185 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble"), SuppressUnmanagedCodeSecurity]
1186 public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
1187 double[] vertices, int vertexStride, int vertexCount,
1188 int[] indices, int indexCount, int triStride);
1189
1190 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble"), SuppressUnmanagedCodeSecurity]
1191 public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
1192 IntPtr vertices, int vertexStride, int vertexCount,
1193 IntPtr indices, int indexCount, int triStride);
1194
1195 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble1"), SuppressUnmanagedCodeSecurity]
1196 public static extern void GeomTriMeshDataBuildDouble1(IntPtr d,
1197 double[] vertices, int vertexStride, int vertexCount,
1198 int[] indices, int indexCount, int triStride,
1199 double[] normals);
1200
1201 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble1"), SuppressUnmanagedCodeSecurity]
1202 public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
1203 IntPtr vertices, int vertexStride, int vertexCount,
1204 IntPtr indices, int indexCount, int triStride,
1205 IntPtr normals);
1206
1207 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple"), SuppressUnmanagedCodeSecurity]
1208 public static extern void GeomTriMeshDataBuildSingle(IntPtr d,
1209 dReal[] vertices, int vertexStride, int vertexCount,
1210 int[] indices, int indexCount, int triStride);
1211
1212 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple"), SuppressUnmanagedCodeSecurity]
1213 public static extern void GeomTriMeshDataBuildSingle(IntPtr d,
1214 IntPtr vertices, int vertexStride, int vertexCount,
1215 IntPtr indices, int indexCount, int triStride);
1216
1217 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple1"), SuppressUnmanagedCodeSecurity]
1218 public static extern void GeomTriMeshDataBuildSingle1(IntPtr d,
1219 dReal[] vertices, int vertexStride, int vertexCount,
1220 int[] indices, int indexCount, int triStride,
1221 dReal[] normals);
1222
1223 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple1"), SuppressUnmanagedCodeSecurity]
1224 public static extern void GeomTriMeshDataBuildSingle1(IntPtr d,
1225 IntPtr vertices, int vertexStride, int vertexCount,
1226 IntPtr indices, int indexCount, int triStride,
1227 IntPtr normals);
1228
1229 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle"), SuppressUnmanagedCodeSecurity]
1230 public static extern void GeomTriMeshDataBuildSimple(IntPtr d,
1231 float[] vertices, int vertexStride, int vertexCount,
1232 int[] indices, int indexCount, int triStride);
1233
1234 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle"), SuppressUnmanagedCodeSecurity]
1235 public static extern void GeomTriMeshDataBuildSimple(IntPtr d,
1236 IntPtr vertices, int vertexStride, int vertexCount,
1237 IntPtr indices, int indexCount, int triStride);
1238
1239 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle1"), SuppressUnmanagedCodeSecurity]
1240 public static extern void GeomTriMeshDataBuildSimple1(IntPtr d,
1241 float[] vertices, int vertexStride, int vertexCount,
1242 int[] indices, int indexCount, int triStride,
1243 float[] normals);
1244
1245 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle1"), SuppressUnmanagedCodeSecurity]
1246 public static extern void GeomTriMeshDataBuildSimple1(IntPtr d,
1247 IntPtr vertices, int vertexStride, int vertexCount,
1248 IntPtr indices, int indexCount, int triStride,
1249 IntPtr normals);
1250
1251 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshClearTCCache"), SuppressUnmanagedCodeSecurity]
1252 public static extern void GeomTriMeshClearTCCache(IntPtr g);
1253
1254 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataCreate"), SuppressUnmanagedCodeSecurity]
1255 public static extern IntPtr GeomTriMeshDataCreate();
1256
1257 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataDestroy"), SuppressUnmanagedCodeSecurity]
1258 public static extern void GeomTriMeshDataDestroy(IntPtr d);
1259
1260 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataGet"), SuppressUnmanagedCodeSecurity]
1261 public static extern IntPtr GeomTriMeshDataGet(IntPtr d, int data_id);
1262
1263 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataPreprocess"), SuppressUnmanagedCodeSecurity]
1264 public static extern void GeomTriMeshDataPreprocess(IntPtr d);
1265
1266 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataSet"), SuppressUnmanagedCodeSecurity]
1267 public static extern void GeomTriMeshDataSet(IntPtr d, int data_id, IntPtr in_data);
1268
1269 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataUpdate"), SuppressUnmanagedCodeSecurity]
1270 public static extern void GeomTriMeshDataUpdate(IntPtr d);
1271
1272 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshEnableTC"), SuppressUnmanagedCodeSecurity]
1273 public static extern void GeomTriMeshEnableTC(IntPtr g, int geomClass, bool enable);
1274
1275 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetArrayCallback"), SuppressUnmanagedCodeSecurity]
1276 public static extern TriArrayCallback GeomTriMeshGetArrayCallback(IntPtr g);
1277
1278 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetCallback"), SuppressUnmanagedCodeSecurity]
1279 public static extern TriCallback GeomTriMeshGetCallback(IntPtr g);
1280
1281 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetData"), SuppressUnmanagedCodeSecurity]
1282 public static extern IntPtr GeomTriMeshGetData(IntPtr g);
1283
1284 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetLastTransform"), SuppressUnmanagedCodeSecurity]
1285 public extern unsafe static Matrix4* GeomTriMeshGetLastTransformUnsafe(IntPtr geom);
1286 public static Matrix4 GeomTriMeshGetLastTransform(IntPtr geom)
1287 {
1288 unsafe { return *(GeomTriMeshGetLastTransformUnsafe(geom)); }
1289 }
1290
1291 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetPoint"), SuppressUnmanagedCodeSecurity]
1292 public extern static void GeomTriMeshGetPoint(IntPtr g, int index, dReal u, dReal v, ref Vector3 outVec);
1293
1294 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetRayCallback"), SuppressUnmanagedCodeSecurity]
1295 public static extern TriRayCallback GeomTriMeshGetRayCallback(IntPtr g);
1296
1297 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetTriangle"), SuppressUnmanagedCodeSecurity]
1298 public extern static void GeomTriMeshGetTriangle(IntPtr g, int index, ref Vector3 v0, ref Vector3 v1, ref Vector3 v2);
1299
1300 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetTriangleCount"), SuppressUnmanagedCodeSecurity]
1301 public extern static int GeomTriMeshGetTriangleCount(IntPtr g);
1302
1303 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetTriMeshDataID"), SuppressUnmanagedCodeSecurity]
1304 public static extern IntPtr GeomTriMeshGetTriMeshDataID(IntPtr g);
1305
1306 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshIsTCEnabled"), SuppressUnmanagedCodeSecurity]
1307 public static extern bool GeomTriMeshIsTCEnabled(IntPtr g, int geomClass);
1308
1309 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetArrayCallback"), SuppressUnmanagedCodeSecurity]
1310 public static extern void GeomTriMeshSetArrayCallback(IntPtr g, TriArrayCallback arrayCallback);
1311
1312 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetCallback"), SuppressUnmanagedCodeSecurity]
1313 public static extern void GeomTriMeshSetCallback(IntPtr g, TriCallback callback);
1314
1315 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetData"), SuppressUnmanagedCodeSecurity]
1316 public static extern void GeomTriMeshSetData(IntPtr g, IntPtr data);
1317
1318 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetLastTransform"), SuppressUnmanagedCodeSecurity]
1319 public static extern void GeomTriMeshSetLastTransform(IntPtr g, ref Matrix4 last_trans);
1320
1321 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetLastTransform"), SuppressUnmanagedCodeSecurity]
1322 public static extern void GeomTriMeshSetLastTransform(IntPtr g, ref dReal M00);
1323
1324 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetRayCallback"), SuppressUnmanagedCodeSecurity]
1325 public static extern void GeomTriMeshSetRayCallback(IntPtr g, TriRayCallback callback);
1326
1327 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGetConfiguration"), SuppressUnmanagedCodeSecurity]
1328 public static extern IntPtr iGetConfiguration();
1329
1330 public static string GetConfiguration()
1331 {
1332 IntPtr ptr = iGetConfiguration();
1333 string s = Marshal.PtrToStringAnsi(ptr);
1334 return s;
1335 }
1336
1337 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dHashSpaceCreate"), SuppressUnmanagedCodeSecurity]
1338 public static extern IntPtr HashSpaceCreate(IntPtr space);
1339
1340 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dHashSpaceGetLevels"), SuppressUnmanagedCodeSecurity]
1341 public static extern void HashSpaceGetLevels(IntPtr space, out int minlevel, out int maxlevel);
1342
1343 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dHashSpaceSetLevels"), SuppressUnmanagedCodeSecurity]
1344 public static extern void HashSpaceSetLevels(IntPtr space, int minlevel, int maxlevel);
1345
1346 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInfiniteAABB"), SuppressUnmanagedCodeSecurity]
1347 public static extern void InfiniteAABB(IntPtr geom, out AABB aabb);
1348
1349 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInitODE"), SuppressUnmanagedCodeSecurity]
1350 public static extern void InitODE();
1351
1352 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInitODE2"), SuppressUnmanagedCodeSecurity]
1353 public static extern int InitODE2(uint ODEInitFlags);
1354
1355 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dIsPositiveDefinite"), SuppressUnmanagedCodeSecurity]
1356 public static extern int IsPositiveDefinite(ref dReal A, int n);
1357
1358 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInvertPDMatrix"), SuppressUnmanagedCodeSecurity]
1359 public static extern int InvertPDMatrix(ref dReal A, out dReal Ainv, int n);
1360
1361 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddAMotorTorques"), SuppressUnmanagedCodeSecurity]
1362 public static extern void JointAddAMotorTorques(IntPtr joint, dReal torque1, dReal torque2, dReal torque3);
1363
1364 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddHingeTorque"), SuppressUnmanagedCodeSecurity]
1365 public static extern void JointAddHingeTorque(IntPtr joint, dReal torque);
1366
1367 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddHinge2Torque"), SuppressUnmanagedCodeSecurity]
1368 public static extern void JointAddHinge2Torques(IntPtr joint, dReal torque1, dReal torque2);
1369
1370 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddPRTorque"), SuppressUnmanagedCodeSecurity]
1371 public static extern void JointAddPRTorque(IntPtr joint, dReal torque);
1372
1373 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddUniversalTorque"), SuppressUnmanagedCodeSecurity]
1374 public static extern void JointAddUniversalTorques(IntPtr joint, dReal torque1, dReal torque2);
1375
1376 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddSliderForce"), SuppressUnmanagedCodeSecurity]
1377 public static extern void JointAddSliderForce(IntPtr joint, dReal force);
1378
1379 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAttach"), SuppressUnmanagedCodeSecurity]
1380 public static extern void JointAttach(IntPtr joint, IntPtr body1, IntPtr body2);
1381
1382 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateAMotor"), SuppressUnmanagedCodeSecurity]
1383 public static extern IntPtr JointCreateAMotor(IntPtr world, IntPtr group);
1384
1385 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateBall"), SuppressUnmanagedCodeSecurity]
1386 public static extern IntPtr JointCreateBall(IntPtr world, IntPtr group);
1387
1388 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateContact"), SuppressUnmanagedCodeSecurity]
1389 public static extern IntPtr JointCreateContact(IntPtr world, IntPtr group, ref Contact contact);
1390 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateContact"), SuppressUnmanagedCodeSecurity]
1391 public static extern IntPtr JointCreateContactPtr(IntPtr world, IntPtr group, IntPtr contact);
1392
1393 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateFixed"), SuppressUnmanagedCodeSecurity]
1394 public static extern IntPtr JointCreateFixed(IntPtr world, IntPtr group);
1395
1396 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateHinge"), SuppressUnmanagedCodeSecurity]
1397 public static extern IntPtr JointCreateHinge(IntPtr world, IntPtr group);
1398
1399 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateHinge2"), SuppressUnmanagedCodeSecurity]
1400 public static extern IntPtr JointCreateHinge2(IntPtr world, IntPtr group);
1401
1402 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateLMotor"), SuppressUnmanagedCodeSecurity]
1403 public static extern IntPtr JointCreateLMotor(IntPtr world, IntPtr group);
1404
1405 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateNull"), SuppressUnmanagedCodeSecurity]
1406 public static extern IntPtr JointCreateNull(IntPtr world, IntPtr group);
1407
1408 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreatePR"), SuppressUnmanagedCodeSecurity]
1409 public static extern IntPtr JointCreatePR(IntPtr world, IntPtr group);
1410
1411 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreatePlane2D"), SuppressUnmanagedCodeSecurity]
1412 public static extern IntPtr JointCreatePlane2D(IntPtr world, IntPtr group);
1413
1414 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateSlider"), SuppressUnmanagedCodeSecurity]
1415 public static extern IntPtr JointCreateSlider(IntPtr world, IntPtr group);
1416
1417 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateUniversal"), SuppressUnmanagedCodeSecurity]
1418 public static extern IntPtr JointCreateUniversal(IntPtr world, IntPtr group);
1419
1420 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointDestroy"), SuppressUnmanagedCodeSecurity]
1421 public static extern void JointDestroy(IntPtr j);
1422
1423 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAngle"), SuppressUnmanagedCodeSecurity]
1424 public static extern dReal JointGetAMotorAngle(IntPtr j, int anum);
1425
1426 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAngleRate"), SuppressUnmanagedCodeSecurity]
1427 public static extern dReal JointGetAMotorAngleRate(IntPtr j, int anum);
1428
1429 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAxis"), SuppressUnmanagedCodeSecurity]
1430 public static extern void JointGetAMotorAxis(IntPtr j, int anum, out Vector3 result);
1431
1432 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAxisRel"), SuppressUnmanagedCodeSecurity]
1433 public static extern int JointGetAMotorAxisRel(IntPtr j, int anum);
1434
1435 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorMode"), SuppressUnmanagedCodeSecurity]
1436 public static extern int JointGetAMotorMode(IntPtr j);
1437
1438 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1439 public static extern int JointGetAMotorNumAxes(IntPtr j);
1440
1441 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorParam"), SuppressUnmanagedCodeSecurity]
1442 public static extern dReal JointGetAMotorParam(IntPtr j, int parameter);
1443
1444 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetBallAnchor"), SuppressUnmanagedCodeSecurity]
1445 public static extern void JointGetBallAnchor(IntPtr j, out Vector3 result);
1446
1447 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetBallAnchor2"), SuppressUnmanagedCodeSecurity]
1448 public static extern void JointGetBallAnchor2(IntPtr j, out Vector3 result);
1449
1450 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetBody"), SuppressUnmanagedCodeSecurity]
1451 public static extern IntPtr JointGetBody(IntPtr j);
1452
1453 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetData"), SuppressUnmanagedCodeSecurity]
1454 public static extern IntPtr JointGetData(IntPtr j);
1455
1456 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetFeedback"), SuppressUnmanagedCodeSecurity]
1457 public extern unsafe static JointFeedback* JointGetFeedbackUnsafe(IntPtr j);
1458 public static JointFeedback JointGetFeedback(IntPtr j)
1459 {
1460 unsafe { return *(JointGetFeedbackUnsafe(j)); }
1461 }
1462
1463 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAnchor"), SuppressUnmanagedCodeSecurity]
1464 public static extern void JointGetHingeAnchor(IntPtr j, out Vector3 result);
1465
1466 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAngle"), SuppressUnmanagedCodeSecurity]
1467 public static extern dReal JointGetHingeAngle(IntPtr j);
1468
1469 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAngleRate"), SuppressUnmanagedCodeSecurity]
1470 public static extern dReal JointGetHingeAngleRate(IntPtr j);
1471
1472 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAxis"), SuppressUnmanagedCodeSecurity]
1473 public static extern void JointGetHingeAxis(IntPtr j, out Vector3 result);
1474
1475 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeParam"), SuppressUnmanagedCodeSecurity]
1476 public static extern dReal JointGetHingeParam(IntPtr j, int parameter);
1477
1478 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Angle1"), SuppressUnmanagedCodeSecurity]
1479 public static extern dReal JointGetHinge2Angle1(IntPtr j);
1480
1481 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Angle1Rate"), SuppressUnmanagedCodeSecurity]
1482 public static extern dReal JointGetHinge2Angle1Rate(IntPtr j);
1483
1484 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Angle2Rate"), SuppressUnmanagedCodeSecurity]
1485 public static extern dReal JointGetHinge2Angle2Rate(IntPtr j);
1486
1487 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAnchor2"), SuppressUnmanagedCodeSecurity]
1488 public static extern void JointGetHingeAnchor2(IntPtr j, out Vector3 result);
1489
1490 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Anchor"), SuppressUnmanagedCodeSecurity]
1491 public static extern void JointGetHinge2Anchor(IntPtr j, out Vector3 result);
1492
1493 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Anchor2"), SuppressUnmanagedCodeSecurity]
1494 public static extern void JointGetHinge2Anchor2(IntPtr j, out Vector3 result);
1495
1496 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Axis1"), SuppressUnmanagedCodeSecurity]
1497 public static extern void JointGetHinge2Axis1(IntPtr j, out Vector3 result);
1498
1499 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Axis2"), SuppressUnmanagedCodeSecurity]
1500 public static extern void JointGetHinge2Axis2(IntPtr j, out Vector3 result);
1501
1502 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Param"), SuppressUnmanagedCodeSecurity]
1503 public static extern dReal JointGetHinge2Param(IntPtr j, int parameter);
1504
1505 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetLMotorAxis"), SuppressUnmanagedCodeSecurity]
1506 public static extern void JointGetLMotorAxis(IntPtr j, int anum, out Vector3 result);
1507
1508 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetLMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1509 public static extern int JointGetLMotorNumAxes(IntPtr j);
1510
1511 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetLMotorParam"), SuppressUnmanagedCodeSecurity]
1512 public static extern dReal JointGetLMotorParam(IntPtr j, int parameter);
1513
1514 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRAnchor"), SuppressUnmanagedCodeSecurity]
1515 public static extern void JointGetPRAnchor(IntPtr j, out Vector3 result);
1516
1517 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRAxis1"), SuppressUnmanagedCodeSecurity]
1518 public static extern void JointGetPRAxis1(IntPtr j, out Vector3 result);
1519
1520 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRAxis2"), SuppressUnmanagedCodeSecurity]
1521 public static extern void JointGetPRAxis2(IntPtr j, out Vector3 result);
1522
1523 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRParam"), SuppressUnmanagedCodeSecurity]
1524 public static extern dReal JointGetPRParam(IntPtr j, int parameter);
1525
1526 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRPosition"), SuppressUnmanagedCodeSecurity]
1527 public static extern dReal JointGetPRPosition(IntPtr j);
1528
1529 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRPositionRate"), SuppressUnmanagedCodeSecurity]
1530 public static extern dReal JointGetPRPositionRate(IntPtr j);
1531
1532 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderAxis"), SuppressUnmanagedCodeSecurity]
1533 public static extern void JointGetSliderAxis(IntPtr j, out Vector3 result);
1534
1535 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderParam"), SuppressUnmanagedCodeSecurity]
1536 public static extern dReal JointGetSliderParam(IntPtr j, int parameter);
1537
1538 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderPosition"), SuppressUnmanagedCodeSecurity]
1539 public static extern dReal JointGetSliderPosition(IntPtr j);
1540
1541 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderPositionRate"), SuppressUnmanagedCodeSecurity]
1542 public static extern dReal JointGetSliderPositionRate(IntPtr j);
1543
1544 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetType"), SuppressUnmanagedCodeSecurity]
1545 public static extern JointType JointGetType(IntPtr j);
1546
1547 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAnchor"), SuppressUnmanagedCodeSecurity]
1548 public static extern void JointGetUniversalAnchor(IntPtr j, out Vector3 result);
1549
1550 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAnchor2"), SuppressUnmanagedCodeSecurity]
1551 public static extern void JointGetUniversalAnchor2(IntPtr j, out Vector3 result);
1552
1553 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle1"), SuppressUnmanagedCodeSecurity]
1554 public static extern dReal JointGetUniversalAngle1(IntPtr j);
1555
1556 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle1Rate"), SuppressUnmanagedCodeSecurity]
1557 public static extern dReal JointGetUniversalAngle1Rate(IntPtr j);
1558
1559 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle2"), SuppressUnmanagedCodeSecurity]
1560 public static extern dReal JointGetUniversalAngle2(IntPtr j);
1561
1562 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle2Rate"), SuppressUnmanagedCodeSecurity]
1563 public static extern dReal JointGetUniversalAngle2Rate(IntPtr j);
1564
1565 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngles"), SuppressUnmanagedCodeSecurity]
1566 public static extern void JointGetUniversalAngles(IntPtr j, out dReal angle1, out dReal angle2);
1567
1568 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAxis1"), SuppressUnmanagedCodeSecurity]
1569 public static extern void JointGetUniversalAxis1(IntPtr j, out Vector3 result);
1570
1571 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAxis2"), SuppressUnmanagedCodeSecurity]
1572 public static extern void JointGetUniversalAxis2(IntPtr j, out Vector3 result);
1573
1574 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalParam"), SuppressUnmanagedCodeSecurity]
1575 public static extern dReal JointGetUniversalParam(IntPtr j, int parameter);
1576
1577 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGroupCreate"), SuppressUnmanagedCodeSecurity]
1578 public static extern IntPtr JointGroupCreate(int max_size);
1579
1580 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGroupDestroy"), SuppressUnmanagedCodeSecurity]
1581 public static extern void JointGroupDestroy(IntPtr group);
1582
1583 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGroupEmpty"), SuppressUnmanagedCodeSecurity]
1584 public static extern void JointGroupEmpty(IntPtr group);
1585
1586 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorAngle"), SuppressUnmanagedCodeSecurity]
1587 public static extern void JointSetAMotorAngle(IntPtr j, int anum, dReal angle);
1588
1589 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorAxis"), SuppressUnmanagedCodeSecurity]
1590 public static extern void JointSetAMotorAxis(IntPtr j, int anum, int rel, dReal x, dReal y, dReal z);
1591
1592 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorMode"), SuppressUnmanagedCodeSecurity]
1593 public static extern void JointSetAMotorMode(IntPtr j, int mode);
1594
1595 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1596 public static extern void JointSetAMotorNumAxes(IntPtr group, int num);
1597
1598 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorParam"), SuppressUnmanagedCodeSecurity]
1599 public static extern void JointSetAMotorParam(IntPtr group, int parameter, dReal value);
1600
1601 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetBallAnchor"), SuppressUnmanagedCodeSecurity]
1602 public static extern void JointSetBallAnchor(IntPtr j, dReal x, dReal y, dReal z);
1603
1604 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetBallAnchor2"), SuppressUnmanagedCodeSecurity]
1605 public static extern void JointSetBallAnchor2(IntPtr j, dReal x, dReal y, dReal z);
1606
1607 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetData"), SuppressUnmanagedCodeSecurity]
1608 public static extern void JointSetData(IntPtr j, IntPtr data);
1609
1610 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetFeedback"), SuppressUnmanagedCodeSecurity]
1611 public static extern void JointSetFeedback(IntPtr j, out JointFeedback feedback);
1612
1613 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetFixed"), SuppressUnmanagedCodeSecurity]
1614 public static extern void JointSetFixed(IntPtr j);
1615
1616 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeAnchor"), SuppressUnmanagedCodeSecurity]
1617 public static extern void JointSetHingeAnchor(IntPtr j, dReal x, dReal y, dReal z);
1618
1619 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeAnchorDelta"), SuppressUnmanagedCodeSecurity]
1620 public static extern void JointSetHingeAnchorDelta(IntPtr j, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
1621
1622 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeAxis"), SuppressUnmanagedCodeSecurity]
1623 public static extern void JointSetHingeAxis(IntPtr j, dReal x, dReal y, dReal z);
1624
1625 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeParam"), SuppressUnmanagedCodeSecurity]
1626 public static extern void JointSetHingeParam(IntPtr j, int parameter, dReal value);
1627
1628 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Anchor"), SuppressUnmanagedCodeSecurity]
1629 public static extern void JointSetHinge2Anchor(IntPtr j, dReal x, dReal y, dReal z);
1630
1631 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Axis1"), SuppressUnmanagedCodeSecurity]
1632 public static extern void JointSetHinge2Axis1(IntPtr j, dReal x, dReal y, dReal z);
1633
1634 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Axis2"), SuppressUnmanagedCodeSecurity]
1635 public static extern void JointSetHinge2Axis2(IntPtr j, dReal x, dReal y, dReal z);
1636
1637 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Param"), SuppressUnmanagedCodeSecurity]
1638 public static extern void JointSetHinge2Param(IntPtr j, int parameter, dReal value);
1639
1640 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetLMotorAxis"), SuppressUnmanagedCodeSecurity]
1641 public static extern void JointSetLMotorAxis(IntPtr j, int anum, int rel, dReal x, dReal y, dReal z);
1642
1643 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetLMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1644 public static extern void JointSetLMotorNumAxes(IntPtr j, int num);
1645
1646 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetLMotorParam"), SuppressUnmanagedCodeSecurity]
1647 public static extern void JointSetLMotorParam(IntPtr j, int parameter, dReal value);
1648
1649 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPlane2DAngleParam"), SuppressUnmanagedCodeSecurity]
1650 public static extern void JointSetPlane2DAngleParam(IntPtr j, int parameter, dReal value);
1651
1652 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPlane2DXParam"), SuppressUnmanagedCodeSecurity]
1653 public static extern void JointSetPlane2DXParam(IntPtr j, int parameter, dReal value);
1654
1655 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPlane2DYParam"), SuppressUnmanagedCodeSecurity]
1656 public static extern void JointSetPlane2DYParam(IntPtr j, int parameter, dReal value);
1657
1658 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRAnchor"), SuppressUnmanagedCodeSecurity]
1659 public static extern void JointSetPRAnchor(IntPtr j, dReal x, dReal y, dReal z);
1660
1661 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRAxis1"), SuppressUnmanagedCodeSecurity]
1662 public static extern void JointSetPRAxis1(IntPtr j, dReal x, dReal y, dReal z);
1663
1664 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRAxis2"), SuppressUnmanagedCodeSecurity]
1665 public static extern void JointSetPRAxis2(IntPtr j, dReal x, dReal y, dReal z);
1666
1667 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRParam"), SuppressUnmanagedCodeSecurity]
1668 public static extern void JointSetPRParam(IntPtr j, int parameter, dReal value);
1669
1670 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetSliderAxis"), SuppressUnmanagedCodeSecurity]
1671 public static extern void JointSetSliderAxis(IntPtr j, dReal x, dReal y, dReal z);
1672
1673 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetSliderAxisDelta"), SuppressUnmanagedCodeSecurity]
1674 public static extern void JointSetSliderAxisDelta(IntPtr j, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
1675
1676 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetSliderParam"), SuppressUnmanagedCodeSecurity]
1677 public static extern void JointSetSliderParam(IntPtr j, int parameter, dReal value);
1678
1679 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalAnchor"), SuppressUnmanagedCodeSecurity]
1680 public static extern void JointSetUniversalAnchor(IntPtr j, dReal x, dReal y, dReal z);
1681
1682 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalAxis1"), SuppressUnmanagedCodeSecurity]
1683 public static extern void JointSetUniversalAxis1(IntPtr j, dReal x, dReal y, dReal z);
1684
1685 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalAxis2"), SuppressUnmanagedCodeSecurity]
1686 public static extern void JointSetUniversalAxis2(IntPtr j, dReal x, dReal y, dReal z);
1687
1688 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalParam"), SuppressUnmanagedCodeSecurity]
1689 public static extern void JointSetUniversalParam(IntPtr j, int parameter, dReal value);
1690
1691 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dLDLTAddTL"), SuppressUnmanagedCodeSecurity]
1692 public static extern void LDLTAddTL(ref dReal L, ref dReal d, ref dReal a, int n, int nskip);
1693
1694 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassAdd"), SuppressUnmanagedCodeSecurity]
1695 public static extern void MassAdd(ref Mass a, ref Mass b);
1696
1697 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassAdjust"), SuppressUnmanagedCodeSecurity]
1698 public static extern void MassAdjust(ref Mass m, dReal newmass);
1699
1700 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassCheck"), SuppressUnmanagedCodeSecurity]
1701 public static extern bool MassCheck(ref Mass m);
1702
1703 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassRotate"), SuppressUnmanagedCodeSecurity]
1704 public static extern void MassRotate(ref Mass mass, ref Matrix3 R);
1705
1706 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassRotate"), SuppressUnmanagedCodeSecurity]
1707 public static extern void MassRotate(ref Mass mass, ref dReal M00);
1708
1709 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetBox"), SuppressUnmanagedCodeSecurity]
1710 public static extern void MassSetBox(out Mass mass, dReal density, dReal lx, dReal ly, dReal lz);
1711
1712 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetBoxTotal"), SuppressUnmanagedCodeSecurity]
1713 public static extern void MassSetBoxTotal(out Mass mass, dReal total_mass, dReal lx, dReal ly, dReal lz);
1714
1715 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCapsule"), SuppressUnmanagedCodeSecurity]
1716 public static extern void MassSetCapsule(out Mass mass, dReal density, int direction, dReal radius, dReal length);
1717
1718 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCapsuleTotal"), SuppressUnmanagedCodeSecurity]
1719 public static extern void MassSetCapsuleTotal(out Mass mass, dReal total_mass, int direction, dReal radius, dReal length);
1720
1721 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCylinder"), SuppressUnmanagedCodeSecurity]
1722 public static extern void MassSetCylinder(out Mass mass, dReal density, int direction, dReal radius, dReal length);
1723
1724 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCylinderTotal"), SuppressUnmanagedCodeSecurity]
1725 public static extern void MassSetCylinderTotal(out Mass mass, dReal total_mass, int direction, dReal radius, dReal length);
1726
1727 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetParameters"), SuppressUnmanagedCodeSecurity]
1728 public static extern void MassSetParameters(out Mass mass, dReal themass,
1729 dReal cgx, dReal cgy, dReal cgz,
1730 dReal i11, dReal i22, dReal i33,
1731 dReal i12, dReal i13, dReal i23);
1732
1733 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetSphere"), SuppressUnmanagedCodeSecurity]
1734 public static extern void MassSetSphere(out Mass mass, dReal density, dReal radius);
1735
1736 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetSphereTotal"), SuppressUnmanagedCodeSecurity]
1737 public static extern void dMassSetSphereTotal(out Mass mass, dReal total_mass, dReal radius);
1738
1739 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetTrimesh"), SuppressUnmanagedCodeSecurity]
1740 public static extern void MassSetTrimesh(out Mass mass, dReal density, IntPtr g);
1741
1742 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetZero"), SuppressUnmanagedCodeSecurity]
1743 public static extern void MassSetZero(out Mass mass);
1744
1745 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassTranslate"), SuppressUnmanagedCodeSecurity]
1746 public static extern void MassTranslate(ref Mass mass, dReal x, dReal y, dReal z);
1747
1748 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply0"), SuppressUnmanagedCodeSecurity]
1749 public static extern void Multiply0(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
1750
1751 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply0"), SuppressUnmanagedCodeSecurity]
1752 private static extern void MultiplyiM3V3(out Vector3 vout, ref Matrix3 matrix, ref Vector3 vect,int p, int q, int r);
1753 public static void MultiplyM3V3(out Vector3 outvector, ref Matrix3 matrix, ref Vector3 invector)
1754 {
1755 MultiplyiM3V3(out outvector, ref matrix, ref invector, 3, 3, 1);
1756 }
1757
1758 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply1"), SuppressUnmanagedCodeSecurity]
1759 public static extern void Multiply1(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
1760
1761 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply2"), SuppressUnmanagedCodeSecurity]
1762 public static extern void Multiply2(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
1763
1764 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQFromAxisAndAngle"), SuppressUnmanagedCodeSecurity]
1765 public static extern void QFromAxisAndAngle(out Quaternion q, dReal ax, dReal ay, dReal az, dReal angle);
1766
1767 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQfromR"), SuppressUnmanagedCodeSecurity]
1768 public static extern void QfromR(out Quaternion q, ref Matrix3 R);
1769
1770 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply0"), SuppressUnmanagedCodeSecurity]
1771 public static extern void QMultiply0(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1772
1773 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply1"), SuppressUnmanagedCodeSecurity]
1774 public static extern void QMultiply1(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1775
1776 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply2"), SuppressUnmanagedCodeSecurity]
1777 public static extern void QMultiply2(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1778
1779 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply3"), SuppressUnmanagedCodeSecurity]
1780 public static extern void QMultiply3(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1781
1782 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQSetIdentity"), SuppressUnmanagedCodeSecurity]
1783 public static extern void QSetIdentity(out Quaternion q);
1784
1785 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQuadTreeSpaceCreate"), SuppressUnmanagedCodeSecurity]
1786 public static extern IntPtr QuadTreeSpaceCreate(IntPtr space, ref Vector3 center, ref Vector3 extents, int depth);
1787
1788 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQuadTreeSpaceCreate"), SuppressUnmanagedCodeSecurity]
1789 public static extern IntPtr QuadTreeSpaceCreate(IntPtr space, ref dReal centerX, ref dReal extentsX, int depth);
1790
1791 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRandReal"), SuppressUnmanagedCodeSecurity]
1792 public static extern dReal RandReal();
1793
1794 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFrom2Axes"), SuppressUnmanagedCodeSecurity]
1795 public static extern void RFrom2Axes(out Matrix3 R, dReal ax, dReal ay, dReal az, dReal bx, dReal by, dReal bz);
1796
1797 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFromAxisAndAngle"), SuppressUnmanagedCodeSecurity]
1798 public static extern void RFromAxisAndAngle(out Matrix3 R, dReal x, dReal y, dReal z, dReal angle);
1799
1800 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFromEulerAngles"), SuppressUnmanagedCodeSecurity]
1801 public static extern void RFromEulerAngles(out Matrix3 R, dReal phi, dReal theta, dReal psi);
1802
1803 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRfromQ"), SuppressUnmanagedCodeSecurity]
1804 public static extern void RfromQ(out Matrix3 R, ref Quaternion q);
1805
1806 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFromZAxis"), SuppressUnmanagedCodeSecurity]
1807 public static extern void RFromZAxis(out Matrix3 R, dReal ax, dReal ay, dReal az);
1808
1809 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRSetIdentity"), SuppressUnmanagedCodeSecurity]
1810 public static extern void RSetIdentity(out Matrix3 R);
1811
1812 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSetValue"), SuppressUnmanagedCodeSecurity]
1813 public static extern void SetValue(out dReal a, int n);
1814
1815 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSetZero"), SuppressUnmanagedCodeSecurity]
1816 public static extern void SetZero(out dReal a, int n);
1817
1818 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSimpleSpaceCreate"), SuppressUnmanagedCodeSecurity]
1819 public static extern IntPtr SimpleSpaceCreate(IntPtr space);
1820
1821 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveCholesky"), SuppressUnmanagedCodeSecurity]
1822 public static extern void SolveCholesky(ref dReal L, out dReal b, int n);
1823
1824 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveL1"), SuppressUnmanagedCodeSecurity]
1825 public static extern void SolveL1(ref dReal L, out dReal b, int n, int nskip);
1826
1827 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveL1T"), SuppressUnmanagedCodeSecurity]
1828 public static extern void SolveL1T(ref dReal L, out dReal b, int n, int nskip);
1829
1830 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveLDLT"), SuppressUnmanagedCodeSecurity]
1831 public static extern void SolveLDLT(ref dReal L, ref dReal d, out dReal b, int n, int nskip);
1832
1833 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceAdd"), SuppressUnmanagedCodeSecurity]
1834 public static extern void SpaceAdd(IntPtr space, IntPtr geom);
1835
1836 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceLockQuery"), SuppressUnmanagedCodeSecurity]
1837 public static extern bool SpaceLockQuery(IntPtr space);
1838
1839 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceClean"), SuppressUnmanagedCodeSecurity]
1840 public static extern void SpaceClean(IntPtr space);
1841
1842 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceCollide"), SuppressUnmanagedCodeSecurity]
1843 public static extern void SpaceCollide(IntPtr space, IntPtr data, NearCallback callback);
1844
1845 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceCollide2"), SuppressUnmanagedCodeSecurity]
1846 public static extern void SpaceCollide2(IntPtr space1, IntPtr space2, IntPtr data, NearCallback callback);
1847
1848 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceDestroy"), SuppressUnmanagedCodeSecurity]
1849 public static extern void SpaceDestroy(IntPtr space);
1850
1851 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetCleanup"), SuppressUnmanagedCodeSecurity]
1852 public static extern bool SpaceGetCleanup(IntPtr space);
1853
1854 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetNumGeoms"), SuppressUnmanagedCodeSecurity]
1855 public static extern int SpaceGetNumGeoms(IntPtr space);
1856
1857 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetGeom"), SuppressUnmanagedCodeSecurity]
1858 public static extern IntPtr SpaceGetGeom(IntPtr space, int i);
1859
1860 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetSublevel"), SuppressUnmanagedCodeSecurity]
1861 public static extern int SpaceGetSublevel(IntPtr space);
1862
1863 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceQuery"), SuppressUnmanagedCodeSecurity]
1864 public static extern bool SpaceQuery(IntPtr space, IntPtr geom);
1865
1866 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceRemove"), SuppressUnmanagedCodeSecurity]
1867 public static extern void SpaceRemove(IntPtr space, IntPtr geom);
1868
1869 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceSetCleanup"), SuppressUnmanagedCodeSecurity]
1870 public static extern void SpaceSetCleanup(IntPtr space, bool mode);
1871
1872 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceSetSublevel"), SuppressUnmanagedCodeSecurity]
1873 public static extern void SpaceSetSublevel(IntPtr space, int sublevel);
1874
1875 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSweepAndPruneSpaceCreate"), SuppressUnmanagedCodeSecurity]
1876 public static extern IntPtr SweepAndPruneSpaceCreate(IntPtr space, int AxisOrder);
1877
1878 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dVectorScale"), SuppressUnmanagedCodeSecurity]
1879 public static extern void VectorScale(out dReal a, ref dReal d, int n);
1880
1881 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldCreate"), SuppressUnmanagedCodeSecurity]
1882 public static extern IntPtr WorldCreate();
1883
1884 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldDestroy"), SuppressUnmanagedCodeSecurity]
1885 public static extern void WorldDestroy(IntPtr world);
1886
1887 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableAverageSamplesCount"), SuppressUnmanagedCodeSecurity]
1888 public static extern int WorldGetAutoDisableAverageSamplesCount(IntPtr world);
1889
1890 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
1891 public static extern dReal WorldGetAutoDisableAngularThreshold(IntPtr world);
1892
1893 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
1894 public static extern bool WorldGetAutoDisableFlag(IntPtr world);
1895
1896 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
1897 public static extern dReal WorldGetAutoDisableLinearThreshold(IntPtr world);
1898
1899 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
1900 public static extern int WorldGetAutoDisableSteps(IntPtr world);
1901
1902 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
1903 public static extern dReal WorldGetAutoDisableTime(IntPtr world);
1904
1905 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoEnableDepthSF1"), SuppressUnmanagedCodeSecurity]
1906 public static extern int WorldGetAutoEnableDepthSF1(IntPtr world);
1907
1908 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetCFM"), SuppressUnmanagedCodeSecurity]
1909 public static extern dReal WorldGetCFM(IntPtr world);
1910
1911 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetERP"), SuppressUnmanagedCodeSecurity]
1912 public static extern dReal WorldGetERP(IntPtr world);
1913
1914 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetGravity"), SuppressUnmanagedCodeSecurity]
1915 public static extern void WorldGetGravity(IntPtr world, out Vector3 gravity);
1916
1917 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetGravity"), SuppressUnmanagedCodeSecurity]
1918 public static extern void WorldGetGravity(IntPtr world, out dReal X);
1919
1920 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetContactMaxCorrectingVel"), SuppressUnmanagedCodeSecurity]
1921 public static extern dReal WorldGetContactMaxCorrectingVel(IntPtr world);
1922
1923 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetContactSurfaceLayer"), SuppressUnmanagedCodeSecurity]
1924 public static extern dReal WorldGetContactSurfaceLayer(IntPtr world);
1925
1926 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAngularDamping"), SuppressUnmanagedCodeSecurity]
1927 public static extern dReal WorldGetAngularDamping(IntPtr world);
1928
1929 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
1930 public static extern dReal WorldGetAngularDampingThreshold(IntPtr world);
1931
1932 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetLinearDamping"), SuppressUnmanagedCodeSecurity]
1933 public static extern dReal WorldGetLinearDamping(IntPtr world);
1934
1935 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
1936 public static extern dReal WorldGetLinearDampingThreshold(IntPtr world);
1937
1938 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetQuickStepNumIterations"), SuppressUnmanagedCodeSecurity]
1939 public static extern int WorldGetQuickStepNumIterations(IntPtr world);
1940
1941 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetQuickStepW"), SuppressUnmanagedCodeSecurity]
1942 public static extern dReal WorldGetQuickStepW(IntPtr world);
1943
1944 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetMaxAngularSpeed"), SuppressUnmanagedCodeSecurity]
1945 public static extern dReal WorldGetMaxAngularSpeed(IntPtr world);
1946
1947 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldImpulseToForce"), SuppressUnmanagedCodeSecurity]
1948 public static extern void WorldImpulseToForce(IntPtr world, dReal stepsize, dReal ix, dReal iy, dReal iz, out Vector3 force);
1949
1950 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldImpulseToForce"), SuppressUnmanagedCodeSecurity]
1951 public static extern void WorldImpulseToForce(IntPtr world, dReal stepsize, dReal ix, dReal iy, dReal iz, out dReal forceX);
1952
1953 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldQuickStep"), SuppressUnmanagedCodeSecurity]
1954 public static extern void WorldQuickStep(IntPtr world, dReal stepsize);
1955
1956 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAngularDamping"), SuppressUnmanagedCodeSecurity]
1957 public static extern void WorldSetAngularDamping(IntPtr world, dReal scale);
1958
1959 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
1960 public static extern void WorldSetAngularDampingThreshold(IntPtr world, dReal threshold);
1961
1962 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
1963 public static extern void WorldSetAutoDisableAngularThreshold(IntPtr world, dReal angular_threshold);
1964
1965 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableAverageSamplesCount"), SuppressUnmanagedCodeSecurity]
1966 public static extern void WorldSetAutoDisableAverageSamplesCount(IntPtr world, int average_samples_count);
1967
1968 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
1969 public static extern void WorldSetAutoDisableFlag(IntPtr world, bool do_auto_disable);
1970
1971 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
1972 public static extern void WorldSetAutoDisableLinearThreshold(IntPtr world, dReal linear_threshold);
1973
1974 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
1975 public static extern void WorldSetAutoDisableSteps(IntPtr world, int steps);
1976
1977 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
1978 public static extern void WorldSetAutoDisableTime(IntPtr world, dReal time);
1979
1980 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoEnableDepthSF1"), SuppressUnmanagedCodeSecurity]
1981 public static extern void WorldSetAutoEnableDepthSF1(IntPtr world, int autoEnableDepth);
1982
1983 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetCFM"), SuppressUnmanagedCodeSecurity]
1984 public static extern void WorldSetCFM(IntPtr world, dReal cfm);
1985
1986 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetContactMaxCorrectingVel"), SuppressUnmanagedCodeSecurity]
1987 public static extern void WorldSetContactMaxCorrectingVel(IntPtr world, dReal vel);
1988
1989 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetContactSurfaceLayer"), SuppressUnmanagedCodeSecurity]
1990 public static extern void WorldSetContactSurfaceLayer(IntPtr world, dReal depth);
1991
1992 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetDamping"), SuppressUnmanagedCodeSecurity]
1993 public static extern void WorldSetDamping(IntPtr world, dReal linear_scale, dReal angular_scale);
1994
1995 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetERP"), SuppressUnmanagedCodeSecurity]
1996 public static extern void WorldSetERP(IntPtr world, dReal erp);
1997
1998 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetGravity"), SuppressUnmanagedCodeSecurity]
1999 public static extern void WorldSetGravity(IntPtr world, dReal x, dReal y, dReal z);
2000
2001 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetLinearDamping"), SuppressUnmanagedCodeSecurity]
2002 public static extern void WorldSetLinearDamping(IntPtr world, dReal scale);
2003
2004 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
2005 public static extern void WorldSetLinearDampingThreshold(IntPtr world, dReal threshold);
2006
2007 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetQuickStepNumIterations"), SuppressUnmanagedCodeSecurity]
2008 public static extern void WorldSetQuickStepNumIterations(IntPtr world, int num);
2009
2010 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetQuickStepW"), SuppressUnmanagedCodeSecurity]
2011 public static extern void WorldSetQuickStepW(IntPtr world, dReal over_relaxation);
2012
2013 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetMaxAngularSpeed"), SuppressUnmanagedCodeSecurity]
2014 public static extern void WorldSetMaxAngularSpeed(IntPtr world, dReal max_speed);
2015
2016 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldStep"), SuppressUnmanagedCodeSecurity]
2017 public static extern void WorldStep(IntPtr world, dReal stepsize);
2018
2019 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldStepFast1"), SuppressUnmanagedCodeSecurity]
2020 public static extern void WorldStepFast1(IntPtr world, dReal stepsize, int maxiterations);
2021
2022 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldExportDIF"), SuppressUnmanagedCodeSecurity]
2023 public static extern void WorldExportDIF(IntPtr world, string filename, bool append, string prefix);
2024 }
2025}
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs b/OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs
new file mode 100644
index 0000000..98bfd1c
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs
@@ -0,0 +1,1408 @@
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 OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.PhysicsModules.SharedBase;
34using log4net;
35
36namespace OpenSim.Region.PhysicsModule.ODE
37{
38 /// <summary>
39 /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
40 /// </summary>
41 public enum dParam : int
42 {
43 LowStop = 0,
44 HiStop = 1,
45 Vel = 2,
46 FMax = 3,
47 FudgeFactor = 4,
48 Bounce = 5,
49 CFM = 6,
50 StopERP = 7,
51 StopCFM = 8,
52 LoStop2 = 256,
53 HiStop2 = 257,
54 Vel2 = 258,
55 FMax2 = 259,
56 StopERP2 = 7 + 256,
57 StopCFM2 = 8 + 256,
58 LoStop3 = 512,
59 HiStop3 = 513,
60 Vel3 = 514,
61 FMax3 = 515,
62 StopERP3 = 7 + 512,
63 StopCFM3 = 8 + 512
64 }
65
66 public class OdeCharacter : PhysicsActor
67 {
68 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
69
70 private Vector3 _position;
71 private d.Vector3 _zeroPosition;
72 private bool _zeroFlag = false;
73 private bool m_lastUpdateSent = false;
74 private Vector3 _velocity;
75 private Vector3 m_taintTargetVelocity;
76 private Vector3 _target_velocity;
77 private Vector3 _acceleration;
78 private Vector3 m_rotationalVelocity;
79 private float m_mass = 80f;
80 private float m_density = 60f;
81 private bool m_pidControllerActive = true;
82 private float PID_D = 800.0f;
83 private float PID_P = 900.0f;
84 //private static float POSTURE_SERVO = 10000.0f;
85 private float CAPSULE_RADIUS = 0.37f;
86 private float CAPSULE_LENGTH = 2.140599f;
87 private float m_tensor = 3800000f;
88// private float heightFudgeFactor = 0.52f;
89 private float walkDivisor = 1.3f;
90 private float runDivisor = 0.8f;
91 private bool flying = false;
92 private bool m_iscolliding = false;
93 private bool m_iscollidingGround = false;
94 private bool m_wascolliding = false;
95 private bool m_wascollidingGround = false;
96 private bool m_iscollidingObj = false;
97 private bool m_alwaysRun = false;
98 private bool m_hackSentFall = false;
99 private bool m_hackSentFly = false;
100 private int m_requestedUpdateFrequency = 0;
101 private Vector3 m_taintPosition;
102 internal bool m_avatarplanted = false;
103 /// <summary>
104 /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force
105 /// while calculatios are going on
106 /// </summary>
107 private Vector3 m_taintForce;
108
109 // taints and their non-tainted counterparts
110 private bool m_isPhysical = false; // the current physical status
111 private bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing)
112 internal float MinimumGroundFlightOffset = 3f;
113
114 private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes.
115
116 /// <summary>
117 /// Base movement for calculating tilt.
118 /// </summary>
119 private float m_tiltBaseMovement = (float)Math.Sqrt(2);
120
121 /// <summary>
122 /// Used to introduce a fixed tilt because a straight-up capsule falls through terrain, probably a bug in terrain collider
123 /// </summary>
124 private float m_tiltMagnitudeWhenProjectedOnXYPlane = 0.1131371f;
125
126 private float m_buoyancy = 0f;
127
128 // private CollisionLocker ode;
129 private bool[] m_colliderarr = new bool[11];
130 private bool[] m_colliderGroundarr = new bool[11];
131
132 // Default we're a Character
133 private CollisionCategories m_collisionCategories = (CollisionCategories.Character);
134
135 // Default, Collide with Other Geometries, spaces, bodies and characters.
136 private CollisionCategories m_collisionFlags = (CollisionCategories.Geom
137 | CollisionCategories.Space
138 | CollisionCategories.Body
139 | CollisionCategories.Character
140 | CollisionCategories.Land);
141 /// <summary>
142 /// Body for dynamics simulation
143 /// </summary>
144 internal IntPtr Body { get; private set; }
145
146 private OdeScene _parent_scene;
147
148 /// <summary>
149 /// Collision geometry
150 /// </summary>
151 internal IntPtr Shell { get; private set; }
152
153 private IntPtr Amotor = IntPtr.Zero;
154 private d.Mass ShellMass;
155
156 private int m_eventsubscription = 0;
157 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
158
159 // unique UUID of this character object
160 internal UUID m_uuid { get; private set; }
161 internal bool bad = false;
162
163 /// <summary>
164 /// ODE Avatar.
165 /// </summary>
166 /// <param name="avName"></param>
167 /// <param name="parent_scene"></param>
168 /// <param name="pos"></param>
169 /// <param name="vel"></param>
170 /// <param name="size"></param>
171 /// <param name="pid_d"></param>
172 /// <param name="pid_p"></param>
173 /// <param name="capsule_radius"></param>
174 /// <param name="tensor"></param>
175 /// <param name="density">
176 /// Only used right now to return information to LSL. Not actually used to set mass in ODE!
177 /// </param>
178 /// <param name="walk_divisor"></param>
179 /// <param name="rundivisor"></param>
180 public OdeCharacter(
181 String avName, OdeScene parent_scene, Vector3 pos, Vector3 vel, Vector3 size, float pid_d, float pid_p,
182 float capsule_radius, float tensor, float density,
183 float walk_divisor, float rundivisor)
184 {
185 m_uuid = UUID.Random();
186
187 if (pos.IsFinite())
188 {
189 if (pos.Z > 9999999f)
190 {
191 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
192 }
193 if (pos.Z < -90000f)
194 {
195 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
196 }
197
198 _position = pos;
199 m_taintPosition = pos;
200 }
201 else
202 {
203 _position
204 = new Vector3(
205 (float)_parent_scene.WorldExtents.X * 0.5f,
206 (float)_parent_scene.WorldExtents.Y * 0.5f,
207 parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f);
208 m_taintPosition = _position;
209
210 m_log.WarnFormat("[ODE CHARACTER]: Got NaN Position on Character Create for {0}", avName);
211 }
212
213 _velocity = vel;
214 m_taintTargetVelocity = vel;
215
216 _parent_scene = parent_scene;
217
218 PID_D = pid_d;
219 PID_P = pid_p;
220 CAPSULE_RADIUS = capsule_radius;
221 m_tensor = tensor;
222 m_density = density;
223// heightFudgeFactor = height_fudge_factor;
224 walkDivisor = walk_divisor;
225 runDivisor = rundivisor;
226
227 // m_StandUpRotation =
228 // new d.Matrix3(0.5f, 0.7071068f, 0.5f, -0.7071068f, 0f, 0.7071068f, 0.5f, -0.7071068f,
229 // 0.5f);
230
231 // We can set taint and actual to be the same here, since the entire character will be set up when the
232 // m_tainted_isPhysical is processed.
233 SetTaintedCapsuleLength(size);
234 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
235
236 m_isPhysical = false; // current status: no ODE information exists
237 m_tainted_isPhysical = true; // new tainted status: need to create ODE information
238
239 _parent_scene.AddPhysicsActorTaint(this);
240
241 Name = avName;
242 }
243
244 public override int PhysicsActorType
245 {
246 get { return (int) ActorTypes.Agent; }
247 set { return; }
248 }
249
250 /// <summary>
251 /// If this is set, the avatar will move faster
252 /// </summary>
253 public override bool SetAlwaysRun
254 {
255 get { return m_alwaysRun; }
256 set { m_alwaysRun = value; }
257 }
258
259 public override bool Grabbed
260 {
261 set { return; }
262 }
263
264 public override bool Selected
265 {
266 set { return; }
267 }
268
269 public override float Buoyancy
270 {
271 get { return m_buoyancy; }
272 set { m_buoyancy = value; }
273 }
274
275 public override bool FloatOnWater
276 {
277 set { return; }
278 }
279
280 public override bool IsPhysical
281 {
282 get { return m_isPhysical; }
283 set { return; }
284 }
285
286 public override bool ThrottleUpdates
287 {
288 get { return false; }
289 set { return; }
290 }
291
292 public override bool Flying
293 {
294 get { return flying; }
295 set
296 {
297 flying = value;
298// m_log.DebugFormat("[ODE CHARACTER]: Set OdeCharacter Flying to {0}", flying);
299 }
300 }
301
302 /// <summary>
303 /// Returns if the avatar is colliding in general.
304 /// This includes the ground and objects and avatar.
305 /// </summary>
306 public override bool IsColliding
307 {
308 get { return m_iscolliding; }
309 set
310 {
311 int i;
312 int truecount = 0;
313 int falsecount = 0;
314
315 if (m_colliderarr.Length >= 10)
316 {
317 for (i = 0; i < 10; i++)
318 {
319 m_colliderarr[i] = m_colliderarr[i + 1];
320 }
321 }
322 m_colliderarr[10] = value;
323
324 for (i = 0; i < 11; i++)
325 {
326 if (m_colliderarr[i])
327 {
328 truecount++;
329 }
330 else
331 {
332 falsecount++;
333 }
334 }
335
336 // Equal truecounts and false counts means we're colliding with something.
337
338 if (falsecount > 1.2*truecount)
339 {
340 m_iscolliding = false;
341 }
342 else
343 {
344 m_iscolliding = true;
345 }
346
347 if (m_wascolliding != m_iscolliding)
348 {
349 //base.SendCollisionUpdate(new CollisionEventUpdate());
350 }
351
352 m_wascolliding = m_iscolliding;
353 }
354 }
355
356 /// <summary>
357 /// Returns if an avatar is colliding with the ground
358 /// </summary>
359 public override bool CollidingGround
360 {
361 get { return m_iscollidingGround; }
362 set
363 {
364 // Collisions against the ground are not really reliable
365 // So, to get a consistant value we have to average the current result over time
366 // Currently we use 1 second = 10 calls to this.
367 int i;
368 int truecount = 0;
369 int falsecount = 0;
370
371 if (m_colliderGroundarr.Length >= 10)
372 {
373 for (i = 0; i < 10; i++)
374 {
375 m_colliderGroundarr[i] = m_colliderGroundarr[i + 1];
376 }
377 }
378 m_colliderGroundarr[10] = value;
379
380 for (i = 0; i < 11; i++)
381 {
382 if (m_colliderGroundarr[i])
383 {
384 truecount++;
385 }
386 else
387 {
388 falsecount++;
389 }
390 }
391
392 // Equal truecounts and false counts means we're colliding with something.
393
394 if (falsecount > 1.2*truecount)
395 {
396 m_iscollidingGround = false;
397 }
398 else
399 {
400 m_iscollidingGround = true;
401 }
402 if (m_wascollidingGround != m_iscollidingGround)
403 {
404 //base.SendCollisionUpdate(new CollisionEventUpdate());
405 }
406 m_wascollidingGround = m_iscollidingGround;
407 }
408 }
409
410 /// <summary>
411 /// Returns if the avatar is colliding with an object
412 /// </summary>
413 public override bool CollidingObj
414 {
415 get { return m_iscollidingObj; }
416 set
417 {
418 m_iscollidingObj = value;
419 if (value && !m_avatarplanted)
420 m_pidControllerActive = false;
421 else
422 m_pidControllerActive = true;
423 }
424 }
425
426 /// <summary>
427 /// turn the PID controller on or off.
428 /// The PID Controller will turn on all by itself in many situations
429 /// </summary>
430 /// <param name="status"></param>
431 public void SetPidStatus(bool status)
432 {
433 m_pidControllerActive = status;
434 }
435
436 public override bool Stopped
437 {
438 get { return _zeroFlag; }
439 }
440
441 /// <summary>
442 /// This 'puts' an avatar somewhere in the physics space.
443 /// Not really a good choice unless you 'know' it's a good
444 /// spot otherwise you're likely to orbit the avatar.
445 /// </summary>
446 public override Vector3 Position
447 {
448 get { return _position; }
449 set
450 {
451 if (Body == IntPtr.Zero || Shell == IntPtr.Zero)
452 {
453 if (value.IsFinite())
454 {
455 if (value.Z > 9999999f)
456 {
457 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
458 }
459 if (value.Z < -90000f)
460 {
461 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
462 }
463
464 m_taintPosition = value;
465 _parent_scene.AddPhysicsActorTaint(this);
466 }
467 else
468 {
469 m_log.WarnFormat("[ODE CHARACTER]: Got a NaN Position from Scene on character {0}", Name);
470 }
471 }
472 }
473 }
474
475 public override Vector3 RotationalVelocity
476 {
477 get { return m_rotationalVelocity; }
478 set { m_rotationalVelocity = value; }
479 }
480
481 /// <summary>
482 /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight
483 /// and use it to offset landings properly
484 /// </summary>
485 public override Vector3 Size
486 {
487 get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
488 set
489 {
490 SetTaintedCapsuleLength(value);
491
492 // If we reset velocity here, then an avatar stalls when it crosses a border for the first time
493 // (as the height of the new root agent is set).
494// Velocity = Vector3.Zero;
495
496 _parent_scene.AddPhysicsActorTaint(this);
497 }
498 }
499
500 private void SetTaintedCapsuleLength(Vector3 size)
501 {
502 if (size.IsFinite())
503 {
504 m_pidControllerActive = true;
505
506 m_tainted_CAPSULE_LENGTH = size.Z - CAPSULE_RADIUS * 2.0f;
507
508 // m_log.InfoFormat("[ODE CHARACTER]: Size = {0}, Capsule Length = {1} (Capsule Radius = {2})",
509 // size, m_tainted_CAPSULE_LENGTH, CAPSULE_RADIUS);
510 }
511 else
512 {
513 m_log.WarnFormat("[ODE CHARACTER]: Got a NaN Size for {0} in {1}", Name, _parent_scene.PhysicsSceneName);
514 }
515 }
516
517 private void AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3 movementVector)
518 {
519 movementVector.Z = 0f;
520 float magnitude = (float)Math.Sqrt((double)(movementVector.X * movementVector.X + movementVector.Y * movementVector.Y));
521 if (magnitude < 0.1f) return;
522
523 // normalize the velocity vector
524 float invMagnitude = 1.0f / magnitude;
525 movementVector.X *= invMagnitude;
526 movementVector.Y *= invMagnitude;
527
528 // if we change the capsule heading too often, the capsule can fall down
529 // therefore we snap movement vector to just 1 of 4 predefined directions (ne, nw, se, sw),
530 // meaning only 4 possible capsule tilt orientations
531 if (movementVector.X > 0)
532 {
533 // east
534 if (movementVector.Y > 0)
535 {
536 // northeast
537 movementVector.X = m_tiltBaseMovement;
538 movementVector.Y = m_tiltBaseMovement;
539 }
540 else
541 {
542 // southeast
543 movementVector.X = m_tiltBaseMovement;
544 movementVector.Y = -m_tiltBaseMovement;
545 }
546 }
547 else
548 {
549 // west
550 if (movementVector.Y > 0)
551 {
552 // northwest
553 movementVector.X = -m_tiltBaseMovement;
554 movementVector.Y = m_tiltBaseMovement;
555 }
556 else
557 {
558 // southwest
559 movementVector.X = -m_tiltBaseMovement;
560 movementVector.Y = -m_tiltBaseMovement;
561 }
562 }
563
564 // movementVector.Z is zero
565
566 // calculate tilt components based on desired amount of tilt and current (snapped) heading.
567 // the "-" sign is to force the tilt to be OPPOSITE the direction of movement.
568 float xTiltComponent = -movementVector.X * m_tiltMagnitudeWhenProjectedOnXYPlane;
569 float yTiltComponent = -movementVector.Y * m_tiltMagnitudeWhenProjectedOnXYPlane;
570
571 //m_log.Debug("[ODE CHARACTER]: changing avatar tilt");
572 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, xTiltComponent);
573 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, xTiltComponent); // must be same as lowstop, else a different, spurious tilt is introduced
574 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, yTiltComponent);
575 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, yTiltComponent); // same as lowstop
576 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, 0f);
577 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop
578 }
579
580 /// <summary>
581 /// Uses the capped cyllinder volume formula to calculate the avatar's mass.
582 /// This may be used in calculations in the scene/scenepresence
583 /// </summary>
584 public override float Mass
585 {
586 get
587 {
588 float AVvolume = (float)(Math.PI * Math.Pow(CAPSULE_RADIUS, 2) * CAPSULE_LENGTH);
589 return m_density * AVvolume;
590 }
591 }
592
593 public override void link(PhysicsActor obj) {}
594
595 public override void delink() {}
596
597 public override void LockAngularMotion(byte axislocks) {}
598
599// This code is very useful. Written by DanX0r. We're just not using it right now.
600// Commented out to prevent a warning.
601//
602// private void standupStraight()
603// {
604// // The purpose of this routine here is to quickly stabilize the Body while it's popped up in the air.
605// // The amotor needs a few seconds to stabilize so without it, the avatar shoots up sky high when you
606// // change appearance and when you enter the simulator
607// // After this routine is done, the amotor stabilizes much quicker
608// d.Vector3 feet;
609// d.Vector3 head;
610// d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
611// d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
612// float posture = head.Z - feet.Z;
613
614// // restoring force proportional to lack of posture:
615// float servo = (2.5f - posture) * POSTURE_SERVO;
616// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
617// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
618// //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
619// //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyFArotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
620// }
621
622 public override Vector3 Force
623 {
624 get { return _target_velocity; }
625 set { return; }
626 }
627
628 public override int VehicleType
629 {
630 get { return 0; }
631 set { return; }
632 }
633
634 public override void VehicleFloatParam(int param, float value)
635 {
636 }
637
638 public override void VehicleVectorParam(int param, Vector3 value)
639 {
640 }
641
642 public override void VehicleRotationParam(int param, Quaternion rotation)
643 {
644 }
645
646 public override void VehicleFlags(int param, bool remove)
647 {
648 }
649
650 public override void SetVolumeDetect(int param)
651 {
652 }
653
654 public override Vector3 CenterOfMass
655 {
656 get { return Vector3.Zero; }
657 }
658
659 public override Vector3 GeometricCenter
660 {
661 get { return Vector3.Zero; }
662 }
663
664 public override PrimitiveBaseShape Shape
665 {
666 set { return; }
667 }
668
669 public override Vector3 TargetVelocity
670 {
671 get
672 {
673 return m_taintTargetVelocity;
674 }
675
676 set
677 {
678 Velocity = value;
679 }
680 }
681
682
683 public override Vector3 Velocity
684 {
685 get
686 {
687 // There's a problem with Vector3.Zero! Don't Use it Here!
688 if (_zeroFlag)
689 return Vector3.Zero;
690 m_lastUpdateSent = false;
691 return _velocity;
692 }
693
694 set
695 {
696 if (value.IsFinite())
697 {
698 m_pidControllerActive = true;
699 m_taintTargetVelocity = value;
700 _parent_scene.AddPhysicsActorTaint(this);
701 }
702 else
703 {
704 m_log.WarnFormat("[ODE CHARACTER]: Got a NaN velocity from Scene for {0}", Name);
705 }
706
707// m_log.DebugFormat("[PHYSICS]: Set target velocity of {0}", m_taintTargetVelocity);
708 }
709 }
710
711 public override Vector3 Torque
712 {
713 get { return Vector3.Zero; }
714 set { return; }
715 }
716
717 public override float CollisionScore
718 {
719 get { return 0f; }
720 set { }
721 }
722
723 public override bool Kinematic
724 {
725 get { return false; }
726 set { }
727 }
728
729 public override Quaternion Orientation
730 {
731 get { return Quaternion.Identity; }
732 set {
733 //Matrix3 or = Orientation.ToRotationMatrix();
734 //d.Matrix3 ord = new d.Matrix3(or.m00, or.m10, or.m20, or.m01, or.m11, or.m21, or.m02, or.m12, or.m22);
735 //d.BodySetRotation(Body, ref ord);
736 }
737 }
738
739 public override Vector3 Acceleration
740 {
741 get { return _acceleration; }
742 set { _acceleration = value; }
743 }
744
745 /// <summary>
746 /// Adds the force supplied to the Target Velocity
747 /// The PID controller takes this target velocity and tries to make it a reality
748 /// </summary>
749 /// <param name="force"></param>
750 public override void AddForce(Vector3 force, bool pushforce)
751 {
752 if (force.IsFinite())
753 {
754 if (pushforce)
755 {
756 m_pidControllerActive = false;
757 force *= 100f;
758 m_taintForce += force;
759 _parent_scene.AddPhysicsActorTaint(this);
760
761 // If uncommented, things get pushed off world
762 //
763 // m_log.Debug("Push!");
764 // m_taintTargetVelocity.X += force.X;
765 // m_taintTargetVelocity.Y += force.Y;
766 // m_taintTargetVelocity.Z += force.Z;
767 }
768 else
769 {
770 m_pidControllerActive = true;
771 m_taintTargetVelocity += force;
772 }
773 }
774 else
775 {
776 m_log.WarnFormat("[ODE CHARACTER]: Got a NaN force applied to {0}", Name);
777 }
778 //m_lastUpdateSent = false;
779 }
780
781 public override void AddAngularForce(Vector3 force, bool pushforce)
782 {
783 }
784
785 public override void SetMomentum(Vector3 momentum)
786 {
787 }
788
789 /// <summary>
790 /// Called from Simulate
791 /// This is the avatar's movement control + PID Controller
792 /// </summary>
793 /// <param name="defects">The character will be added to this list if there is something wrong (non-finite
794 /// position or velocity).
795 /// </param>
796 internal void Move(List<OdeCharacter> defects)
797 {
798 // no lock; for now it's only called from within Simulate()
799
800 // If the PID Controller isn't active then we set our force
801 // calculating base velocity to the current position
802
803 if (Body == IntPtr.Zero)
804 return;
805
806 if (m_pidControllerActive == false)
807 {
808 _zeroPosition = d.BodyGetPosition(Body);
809 }
810 //PidStatus = true;
811
812 d.Vector3 localpos = d.BodyGetPosition(Body);
813 Vector3 localPos = new Vector3(localpos.X, localpos.Y, localpos.Z);
814
815 if (!localPos.IsFinite())
816 {
817 m_log.WarnFormat(
818 "[ODE CHARACTER]: Avatar position of {0} for {1} is non-finite! Removing from physics scene.",
819 localPos, Name);
820
821 defects.Add(this);
822
823 return;
824 }
825
826 Vector3 vec = Vector3.Zero;
827 d.Vector3 vel = d.BodyGetLinearVel(Body);
828
829// m_log.DebugFormat(
830// "[ODE CHARACTER]: Current velocity in Move() is <{0},{1},{2}>, target {3} for {4}",
831// vel.X, vel.Y, vel.Z, _target_velocity, Name);
832
833 float movementdivisor = 1f;
834
835 if (!m_alwaysRun)
836 {
837 movementdivisor = walkDivisor;
838 }
839 else
840 {
841 movementdivisor = runDivisor;
842 }
843
844 // if velocity is zero, use position control; otherwise, velocity control
845 if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
846 {
847 // keep track of where we stopped. No more slippin' & slidin'
848 if (!_zeroFlag)
849 {
850 _zeroFlag = true;
851 _zeroPosition = d.BodyGetPosition(Body);
852 }
853
854 if (m_pidControllerActive)
855 {
856 // We only want to deactivate the PID Controller if we think we want to have our surrogate
857 // react to the physics scene by moving it's position.
858 // Avatar to Avatar collisions
859 // Prim to avatar collisions
860
861 d.Vector3 pos = d.BodyGetPosition(Body);
862 vec.X = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
863 vec.Y = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y)* (PID_P * 2);
864 if (flying)
865 {
866 vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
867 }
868 }
869 //PidStatus = true;
870 }
871 else
872 {
873 m_pidControllerActive = true;
874 _zeroFlag = false;
875 if (m_iscolliding && !flying)
876 {
877 // We're standing on something
878 vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
879 vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
880 }
881 else if (m_iscolliding && flying)
882 {
883 // We're flying and colliding with something
884 vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
885 vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
886 }
887 else if (!m_iscolliding && flying)
888 {
889 // we're in mid air suspended
890 vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
891 vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);
892
893// m_log.DebugFormat(
894// "[ODE CHARACTER]: !m_iscolliding && flying, vec {0}, _target_velocity {1}, movementdivisor {2}, vel {3}",
895// vec, _target_velocity, movementdivisor, vel);
896 }
897
898 if (flying)
899 {
900 // This also acts as anti-gravity so that we hover when flying rather than fall.
901 vec.Z = (_target_velocity.Z - vel.Z) * (PID_D);
902 }
903 else
904 {
905 if (m_iscolliding && _target_velocity.Z > 0.0f)
906 {
907 // We're colliding with something and we're not flying but we're moving
908 // This means we're walking or running.
909 d.Vector3 pos = d.BodyGetPosition(Body);
910 vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
911 vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D;
912 vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
913 }
914 else if (!m_iscolliding)
915 {
916 // we're not colliding and we're not flying so that means we're falling!
917 // m_iscolliding includes collisions with the ground.
918 vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D;
919 vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
920 }
921 }
922 }
923
924 if (flying)
925 {
926 // Anti-gravity so that we hover when flying rather than fall.
927 vec.Z += ((-1 * _parent_scene.gravityz) * m_mass);
928
929 //Added for auto fly height. Kitto Flora
930 //d.Vector3 pos = d.BodyGetPosition(Body);
931 float target_altitude = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y) + MinimumGroundFlightOffset;
932
933 if (_position.Z < target_altitude)
934 {
935 vec.Z += (target_altitude - _position.Z) * PID_P * 5.0f;
936 }
937 // end add Kitto Flora
938 }
939
940 if (vec.IsFinite())
941 {
942 // Apply the total force acting on this avatar
943 d.BodyAddForce(Body, vec.X, vec.Y, vec.Z);
944
945 if (!_zeroFlag)
946 AlignAvatarTiltWithCurrentDirectionOfMovement(vec);
947 }
948 else
949 {
950 m_log.WarnFormat(
951 "[ODE CHARACTER]: Got a NaN force vector {0} in Move() for {1}. Removing character from physics scene.",
952 vec, Name);
953
954 defects.Add(this);
955
956 return;
957 }
958
959 d.Vector3 newVel = d.BodyGetLinearVel(Body);
960 if (newVel.X >= 256 || newVel.X <= 256 || newVel.Y >= 256 || newVel.Y <= 256 || newVel.Z >= 256 || newVel.Z <= 256)
961 {
962// m_log.DebugFormat(
963// "[ODE CHARACTER]: Limiting falling velocity from {0} to {1} for {2}", newVel.Z, -9.8, Name);
964
965 newVel.X = Util.Clamp<float>(newVel.X, -255f, 255f);
966 newVel.Y = Util.Clamp<float>(newVel.Y, -255f, 255f);
967
968 if (!flying)
969 newVel.Z
970 = Util.Clamp<float>(
971 newVel.Z, -_parent_scene.AvatarTerminalVelocity, _parent_scene.AvatarTerminalVelocity);
972 else
973 newVel.Z = Util.Clamp<float>(newVel.Z, -255f, 255f);
974
975 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
976 }
977 }
978
979 /// <summary>
980 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
981 /// </summary>
982 /// <param name="defects">The character will be added to this list if there is something wrong (non-finite
983 /// position or velocity).
984 /// </param>
985 internal void UpdatePositionAndVelocity(List<OdeCharacter> defects)
986 {
987 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
988 d.Vector3 newPos;
989 try
990 {
991 newPos = d.BodyGetPosition(Body);
992 }
993 catch (NullReferenceException)
994 {
995 bad = true;
996 defects.Add(this);
997 newPos = new d.Vector3(_position.X, _position.Y, _position.Z);
998 base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
999 m_log.WarnFormat("[ODE CHARACTER]: Avatar Null reference for Avatar {0}, physical actor {1}", Name, m_uuid);
1000
1001 return;
1002 }
1003
1004 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
1005 if (newPos.X < 0.0f) newPos.X = 0.0f;
1006 if (newPos.Y < 0.0f) newPos.Y = 0.0f;
1007 if (newPos.X > (int)_parent_scene.WorldExtents.X - 0.05f) newPos.X = (int)_parent_scene.WorldExtents.X - 0.05f;
1008 if (newPos.Y > (int)_parent_scene.WorldExtents.Y - 0.05f) newPos.Y = (int)_parent_scene.WorldExtents.Y - 0.05f;
1009
1010 _position.X = newPos.X;
1011 _position.Y = newPos.Y;
1012 _position.Z = newPos.Z;
1013
1014 // I think we need to update the taintPosition too -- Diva 12/24/10
1015 m_taintPosition = _position;
1016
1017 // Did we move last? = zeroflag
1018 // This helps keep us from sliding all over
1019
1020 if (_zeroFlag)
1021 {
1022 _velocity = Vector3.Zero;
1023
1024 // Did we send out the 'stopped' message?
1025 if (!m_lastUpdateSent)
1026 {
1027 m_lastUpdateSent = true;
1028 //base.RequestPhysicsterseUpdate();
1029 }
1030 }
1031 else
1032 {
1033 m_lastUpdateSent = false;
1034 d.Vector3 newVelocity;
1035
1036 try
1037 {
1038 newVelocity = d.BodyGetLinearVel(Body);
1039 }
1040 catch (NullReferenceException)
1041 {
1042 newVelocity.X = _velocity.X;
1043 newVelocity.Y = _velocity.Y;
1044 newVelocity.Z = _velocity.Z;
1045 }
1046
1047 _velocity.X = newVelocity.X;
1048 _velocity.Y = newVelocity.Y;
1049 _velocity.Z = newVelocity.Z;
1050
1051 if (_velocity.Z < -6 && !m_hackSentFall)
1052 {
1053 m_hackSentFall = true;
1054 m_pidControllerActive = false;
1055 }
1056 else if (flying && !m_hackSentFly)
1057 {
1058 //m_hackSentFly = true;
1059 //base.SendCollisionUpdate(new CollisionEventUpdate());
1060 }
1061 else
1062 {
1063 m_hackSentFly = false;
1064 m_hackSentFall = false;
1065 }
1066 }
1067 }
1068
1069 /// <summary>
1070 /// This creates the Avatar's physical Surrogate in ODE at the position supplied
1071 /// </summary>
1072 /// <remarks>
1073 /// WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
1074 /// to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
1075 /// place that is safe to call this routine AvatarGeomAndBodyCreation.
1076 /// </remarks>
1077 /// <param name="npositionX"></param>
1078 /// <param name="npositionY"></param>
1079 /// <param name="npositionZ"></param>
1080 /// <param name="tensor"></param>
1081 private void CreateOdeStructures(float npositionX, float npositionY, float npositionZ, float tensor)
1082 {
1083 if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero))
1084 {
1085 m_log.ErrorFormat(
1086 "[ODE CHARACTER]: Creating ODE structures for {0} even though some already exist. Shell = {1}, Body = {2}, Amotor = {3}",
1087 Name, Shell, Body, Amotor);
1088 }
1089
1090 int dAMotorEuler = 1;
1091// _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1092 if (CAPSULE_LENGTH <= 0)
1093 {
1094 m_log.Warn("[ODE CHARACTER]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
1095 CAPSULE_LENGTH = 0.01f;
1096 }
1097
1098 if (CAPSULE_RADIUS <= 0)
1099 {
1100 m_log.Warn("[ODE CHARACTER]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
1101 CAPSULE_RADIUS = 0.01f;
1102 }
1103
1104// lock (OdeScene.UniversalColliderSyncObject)
1105 Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
1106
1107 d.GeomSetCategoryBits(Shell, (uint)m_collisionCategories);
1108 d.GeomSetCollideBits(Shell, (uint)m_collisionFlags);
1109
1110 d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH);
1111 Body = d.BodyCreate(_parent_scene.world);
1112 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
1113
1114 _position.X = npositionX;
1115 _position.Y = npositionY;
1116 _position.Z = npositionZ;
1117
1118 m_taintPosition = _position;
1119
1120 d.BodySetMass(Body, ref ShellMass);
1121 d.Matrix3 m_caprot;
1122 // 90 Stand up on the cap of the capped cyllinder
1123 if (_parent_scene.IsAvCapsuleTilted)
1124 {
1125 d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2));
1126 }
1127 else
1128 {
1129 d.RFromAxisAndAngle(out m_caprot, 0, 0, 1, (float)(Math.PI / 2));
1130 }
1131
1132 d.GeomSetRotation(Shell, ref m_caprot);
1133 d.BodySetRotation(Body, ref m_caprot);
1134
1135 d.GeomSetBody(Shell, Body);
1136
1137 // The purpose of the AMotor here is to keep the avatar's physical
1138 // surrogate from rotating while moving
1139 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
1140 d.JointAttach(Amotor, Body, IntPtr.Zero);
1141 d.JointSetAMotorMode(Amotor, dAMotorEuler);
1142 d.JointSetAMotorNumAxes(Amotor, 3);
1143 d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
1144 d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
1145 d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
1146 d.JointSetAMotorAngle(Amotor, 0, 0);
1147 d.JointSetAMotorAngle(Amotor, 1, 0);
1148 d.JointSetAMotorAngle(Amotor, 2, 0);
1149
1150 // These lowstops and high stops are effectively (no wiggle room)
1151 if (_parent_scene.IsAvCapsuleTilted)
1152 {
1153 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f);
1154 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f);
1155 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f);
1156 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f);
1157 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f);
1158 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f);
1159 }
1160 else
1161 {
1162 #region Documentation of capsule motor LowStop and HighStop parameters
1163 // Intentionally introduce some tilt into the capsule by setting
1164 // the motor stops to small epsilon values. This small tilt prevents
1165 // the capsule from falling into the terrain; a straight-up capsule
1166 // (with -0..0 motor stops) falls into the terrain for reasons yet
1167 // to be comprehended in their entirety.
1168 #endregion
1169 AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3.Zero);
1170 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0.08f);
1171 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f);
1172 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0.08f);
1173 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.08f); // must be same as lowstop, else a different, spurious tilt is introduced
1174 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop
1175 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.08f); // same as lowstop
1176 }
1177
1178 // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the
1179 // capped cyllinder will fall over
1180 d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f);
1181 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor);
1182
1183 //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
1184 //d.QfromR(
1185 //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068,
1186 //
1187 //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
1188 //standupStraight();
1189
1190 _parent_scene.geom_name_map[Shell] = Name;
1191 _parent_scene.actor_name_map[Shell] = this;
1192 }
1193
1194 /// <summary>
1195 /// Cleanup the things we use in the scene.
1196 /// </summary>
1197 internal void Destroy()
1198 {
1199 m_tainted_isPhysical = false;
1200 _parent_scene.AddPhysicsActorTaint(this);
1201 }
1202
1203 /// <summary>
1204 /// Used internally to destroy the ODE structures associated with this character.
1205 /// </summary>
1206 internal void DestroyOdeStructures()
1207 {
1208 // Create avatar capsule and related ODE data
1209 if (Shell == IntPtr.Zero || Body == IntPtr.Zero || Amotor == IntPtr.Zero)
1210 {
1211 m_log.ErrorFormat(
1212 "[ODE CHARACTER]: Destroying ODE structures for {0} even though some are already null. Shell = {1}, Body = {2}, Amotor = {3}",
1213 Name, Shell, Body, Amotor);
1214 }
1215
1216 // destroy avatar capsule and related ODE data
1217 if (Amotor != IntPtr.Zero)
1218 {
1219 // Kill the Amotor
1220 d.JointDestroy(Amotor);
1221 Amotor = IntPtr.Zero;
1222 }
1223
1224 //kill the Geometry
1225// _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1226
1227 if (Body != IntPtr.Zero)
1228 {
1229 //kill the body
1230 d.BodyDestroy(Body);
1231 Body = IntPtr.Zero;
1232 }
1233
1234 if (Shell != IntPtr.Zero)
1235 {
1236// lock (OdeScene.UniversalColliderSyncObject)
1237 d.GeomDestroy(Shell);
1238
1239 _parent_scene.geom_name_map.Remove(Shell);
1240 _parent_scene.actor_name_map.Remove(Shell);
1241
1242 Shell = IntPtr.Zero;
1243 }
1244 }
1245
1246 public override void CrossingFailure()
1247 {
1248 }
1249
1250 public override Vector3 PIDTarget { set { return; } }
1251 public override bool PIDActive
1252 {
1253 get { return false; }
1254 set { return; }
1255 }
1256 public override float PIDTau { set { return; } }
1257
1258 public override float PIDHoverHeight { set { return; } }
1259 public override bool PIDHoverActive {get {return false;} set { return; } }
1260 public override PIDHoverType PIDHoverType { set { return; } }
1261 public override float PIDHoverTau { set { return; } }
1262
1263 public override Quaternion APIDTarget{ set { return; } }
1264
1265 public override bool APIDActive{ set { return; } }
1266
1267 public override float APIDStrength{ set { return; } }
1268
1269 public override float APIDDamping{ set { return; } }
1270
1271 public override void SubscribeEvents(int ms)
1272 {
1273 m_requestedUpdateFrequency = ms;
1274 m_eventsubscription = ms;
1275
1276 // Don't clear collision event reporting here. This is called directly from scene code and so can lead
1277 // to a race condition with the simulate loop
1278
1279 _parent_scene.AddCollisionEventReporting(this);
1280 }
1281
1282 public override void UnSubscribeEvents()
1283 {
1284 _parent_scene.RemoveCollisionEventReporting(this);
1285
1286 // Don't clear collision event reporting here. This is called directly from scene code and so can lead
1287 // to a race condition with the simulate loop
1288
1289 m_requestedUpdateFrequency = 0;
1290 m_eventsubscription = 0;
1291 }
1292
1293 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1294 {
1295 if (m_eventsubscription > 0)
1296 {
1297// m_log.DebugFormat(
1298// "[PHYSICS]: Adding collision event for {0}, collidedWith {1}, contact {2}", "", CollidedWith, contact);
1299
1300 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
1301 }
1302 }
1303
1304 internal void SendCollisions()
1305 {
1306 if (m_eventsubscription > m_requestedUpdateFrequency)
1307 {
1308 base.SendCollisionUpdate(CollisionEventsThisFrame);
1309
1310 CollisionEventsThisFrame.Clear();
1311 m_eventsubscription = 0;
1312 }
1313 }
1314
1315 public override bool SubscribedEvents()
1316 {
1317 if (m_eventsubscription > 0)
1318 return true;
1319 return false;
1320 }
1321
1322 internal void ProcessTaints()
1323 {
1324 if (m_taintPosition != _position)
1325 {
1326 if (Body != IntPtr.Zero)
1327 {
1328 d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z);
1329 _position = m_taintPosition;
1330 }
1331 }
1332
1333 if (m_taintForce != Vector3.Zero)
1334 {
1335 if (Body != IntPtr.Zero)
1336 {
1337 // FIXME: This is not a good solution since it's subject to a race condition if a force is another
1338 // thread sets a new force while we're in this loop (since it could be obliterated by
1339 // m_taintForce = Vector3.Zero. Need to lock ProcessTaints() when we set a new tainted force.
1340 d.BodyAddForce(Body, m_taintForce.X, m_taintForce.Y, m_taintForce.Z);
1341 }
1342
1343 m_taintForce = Vector3.Zero;
1344 }
1345
1346 if (m_taintTargetVelocity != _target_velocity)
1347 _target_velocity = m_taintTargetVelocity;
1348
1349 if (m_tainted_isPhysical != m_isPhysical)
1350 {
1351 if (m_tainted_isPhysical)
1352 {
1353 CreateOdeStructures(_position.X, _position.Y, _position.Z, m_tensor);
1354 _parent_scene.AddCharacter(this);
1355 }
1356 else
1357 {
1358 _parent_scene.RemoveCharacter(this);
1359 DestroyOdeStructures();
1360 }
1361
1362 m_isPhysical = m_tainted_isPhysical;
1363 }
1364
1365 if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH)
1366 {
1367 if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero)
1368 {
1369// m_log.DebugFormat(
1370// "[ODE CHARACTER]: Changing capsule size from {0} to {1} for {2}",
1371// CAPSULE_LENGTH, m_tainted_CAPSULE_LENGTH, Name);
1372
1373 m_pidControllerActive = true;
1374
1375 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
1376 DestroyOdeStructures();
1377
1378 float prevCapsule = CAPSULE_LENGTH;
1379 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
1380
1381 CreateOdeStructures(
1382 _position.X,
1383 _position.Y,
1384 _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor);
1385
1386 // As with Size, we reset velocity. However, this isn't strictly necessary since it doesn't
1387 // appear to stall initial region crossings when done here. Being done for consistency.
1388// Velocity = Vector3.Zero;
1389 }
1390 else
1391 {
1392 m_log.Warn("[ODE CHARACTER]: trying to change capsule size for " + Name + ", but the following ODE data is missing - "
1393 + (Shell==IntPtr.Zero ? "Shell ":"")
1394 + (Body==IntPtr.Zero ? "Body ":"")
1395 + (Amotor==IntPtr.Zero ? "Amotor ":""));
1396 }
1397 }
1398 }
1399
1400 internal void AddCollisionFrameTime(int p)
1401 {
1402 // protect it from overflow crashing
1403 if (m_eventsubscription + p >= int.MaxValue)
1404 m_eventsubscription = 0;
1405 m_eventsubscription += p;
1406 }
1407 }
1408}
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODEDynamics.c_comments b/OpenSim/Region/PhysicsModules/Ode/ODEDynamics.c_comments
new file mode 100644
index 0000000..1060aa6
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/ODEDynamics.c_comments
@@ -0,0 +1,630 @@
1/*
2 * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces
3 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
4 * ODEPrim.cs contains methods dealing with Prim editing, Prim
5 * characteristics and Kinetic motion.
6 * ODEDynamics.cs contains methods dealing with Prim Physical motion
7 * (dynamics) and the associated settings. Old Linear and angular
8 * motors for dynamic motion have been replace with MoveLinear()
9 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
10 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
11 * switch between 'VEHICLE' parameter use and general dynamics
12 * settings use.
13 *
14 * Copyright (c) Contributors, http://opensimulator.org/
15 * See CONTRIBUTORS.TXT for a full list of copyright holders.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are met:
19 * * Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * * Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * * Neither the name of the OpenSimulator Project nor the
25 * names of its contributors may be used to endorse or promote products
26 * derived from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
29 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */
39
40using System;
41using System.Collections.Generic;
42using System.Reflection;
43using System.Runtime.InteropServices;
44using log4net;
45using OpenMetaverse;
46using Ode.NET;
47using OpenSim.Framework;
48using OpenSim.Region.Physics.Manager;
49
50namespace OpenSim.Region.Physics.OdePlugin
51{
52 public class ODEDynamics
53 {
54 public Vehicle Type
55 {
56 get { return m_type; }
57 }
58
59 public IntPtr Body
60 {
61 get { return m_body; }
62 }
63
64 private int frcount = 0; // Used to limit dynamics debug output to
65 // every 100th frame
66
67 // private OdeScene m_parentScene = null;
68 private IntPtr m_body = IntPtr.Zero;
69 private IntPtr m_jointGroup = IntPtr.Zero;
70 private IntPtr m_aMotor = IntPtr.Zero;
71
72
73 // Vehicle properties
74 private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
75 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
76 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
77 // HOVER_TERRAIN_ONLY
78 // HOVER_GLOBAL_HEIGHT
79 // NO_DEFLECTION_UP
80 // HOVER_WATER_ONLY
81 // HOVER_UP_ONLY
82 // LIMIT_MOTOR_UP
83 // LIMIT_ROLL_ONLY
84
85 // Linear properties
86 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
87 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
88 private Vector3 m_dir = Vector3.Zero; // velocity applied to body
89 private Vector3 m_linearFrictionTimescale = Vector3.Zero;
90 private float m_linearMotorDecayTimescale = 0;
91 private float m_linearMotorTimescale = 0;
92 private Vector3 m_lastLinearVelocityVector = Vector3.Zero;
93 // private bool m_LinearMotorSetLastFrame = false;
94 // private Vector3 m_linearMotorOffset = Vector3.Zero;
95
96 //Angular properties
97 private Vector3 m_angularMotorDirection = Vector3.Zero;
98 private Vector3 m_angularMotorDirectionLASTSET = Vector3.Zero;
99 private Vector3 m_angularFrictionTimescale = Vector3.Zero;
100 private float m_angularMotorDecayTimescale = 0;
101 private float m_angularMotorTimescale = 0;
102 private Vector3 m_lastAngularVelocityVector = Vector3.Zero;
103
104 //Deflection properties
105 // private float m_angularDeflectionEfficiency = 0;
106 // private float m_angularDeflectionTimescale = 0;
107 // private float m_linearDeflectionEfficiency = 0;
108 // private float m_linearDeflectionTimescale = 0;
109
110 //Banking properties
111 // private float m_bankingEfficiency = 0;
112 // private float m_bankingMix = 0;
113 // private float m_bankingTimescale = 0;
114
115 //Hover and Buoyancy properties
116 private float m_VhoverHeight = 0f;
117 private float m_VhoverEfficiency = 0f;
118 private float m_VhoverTimescale = 0f;
119 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
120 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
121 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
122 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
123 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
124
125 //Attractor properties
126 private float m_verticalAttractionEfficiency = 0;
127 private float m_verticalAttractionTimescale = 0;
128
129
130
131
132
133 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
134 {
135 switch (pParam)
136 {
137 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
138 if (pValue < 0.01f) pValue = 0.01f;
139 // m_angularDeflectionEfficiency = pValue;
140 break;
141 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
142 if (pValue < 0.01f) pValue = 0.01f;
143 // m_angularDeflectionTimescale = pValue;
144 break;
145 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
146 if (pValue < 0.01f) pValue = 0.01f;
147 m_angularMotorDecayTimescale = pValue;
148 break;
149 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
150 if (pValue < 0.01f) pValue = 0.01f;
151 m_angularMotorTimescale = pValue;
152 break;
153 case Vehicle.BANKING_EFFICIENCY:
154 if (pValue < 0.01f) pValue = 0.01f;
155 // m_bankingEfficiency = pValue;
156 break;
157 case Vehicle.BANKING_MIX:
158 if (pValue < 0.01f) pValue = 0.01f;
159 // m_bankingMix = pValue;
160 break;
161 case Vehicle.BANKING_TIMESCALE:
162 if (pValue < 0.01f) pValue = 0.01f;
163 // m_bankingTimescale = pValue;
164 break;
165 case Vehicle.BUOYANCY:
166 if (pValue < -1f) pValue = -1f;
167 if (pValue > 1f) pValue = 1f;
168 m_VehicleBuoyancy = pValue;
169 break;
170 case Vehicle.HOVER_EFFICIENCY:
171 if (pValue < 0f) pValue = 0f;
172 if (pValue > 1f) pValue = 1f;
173 m_VhoverEfficiency = pValue;
174 break;
175 case Vehicle.HOVER_HEIGHT:
176 m_VhoverHeight = pValue;
177 break;
178 case Vehicle.HOVER_TIMESCALE:
179 if (pValue < 0.01f) pValue = 0.01f;
180 m_VhoverTimescale = pValue;
181 break;
182 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
183 if (pValue < 0.01f) pValue = 0.01f;
184 // m_linearDeflectionEfficiency = pValue;
185 break;
186 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
187 if (pValue < 0.01f) pValue = 0.01f;
188 // m_linearDeflectionTimescale = pValue;
189 break;
190 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
191 if (pValue < 0.01f) pValue = 0.01f;
192 m_linearMotorDecayTimescale = pValue;
193 break;
194 case Vehicle.LINEAR_MOTOR_TIMESCALE:
195 if (pValue < 0.01f) pValue = 0.01f;
196 m_linearMotorTimescale = pValue;
197 break;
198 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
199 if (pValue < 0.0f) pValue = 0.0f;
200 if (pValue > 1.0f) pValue = 1.0f;
201 m_verticalAttractionEfficiency = pValue;
202 break;
203 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
204 if (pValue < 0.01f) pValue = 0.01f;
205 m_verticalAttractionTimescale = pValue;
206 break;
207
208 // These are vector properties but the engine lets you use a single float value to
209 // set all of the components to the same value
210 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
211 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
212 break;
213 case Vehicle.ANGULAR_MOTOR_DIRECTION:
214 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
215 m_angularMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
216 break;
217 case Vehicle.LINEAR_FRICTION_TIMESCALE:
218 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
219 break;
220 case Vehicle.LINEAR_MOTOR_DIRECTION:
221 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
222 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
223 break;
224 case Vehicle.LINEAR_MOTOR_OFFSET:
225 // m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
226 break;
227
228 }
229
230 }//end ProcessFloatVehicleParam
231
232 internal void ProcessVectorVehicleParam(Vehicle pParam, PhysicsVector pValue)
233 {
234 switch (pParam)
235 {
236 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
237 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
238 break;
239 case Vehicle.ANGULAR_MOTOR_DIRECTION:
240 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
241 m_angularMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
242 break;
243 case Vehicle.LINEAR_FRICTION_TIMESCALE:
244 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
245 break;
246 case Vehicle.LINEAR_MOTOR_DIRECTION:
247 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
248 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
249 break;
250 case Vehicle.LINEAR_MOTOR_OFFSET:
251 // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
252 break;
253 }
254
255 }//end ProcessVectorVehicleParam
256
257 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
258 {
259 switch (pParam)
260 {
261 case Vehicle.REFERENCE_FRAME:
262 // m_referenceFrame = pValue;
263 break;
264 }
265
266 }//end ProcessRotationVehicleParam
267
268 internal void ProcessTypeChange(Vehicle pType)
269 {
270Console.WriteLine("ProcessTypeChange to " + pType);
271
272 // Set Defaults For Type
273 m_type = pType;
274 switch (pType)
275 {
276 case Vehicle.TYPE_SLED:
277 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
278 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
279 m_linearMotorDirection = Vector3.Zero;
280 m_linearMotorTimescale = 1000;
281 m_linearMotorDecayTimescale = 120;
282 m_angularMotorDirection = Vector3.Zero;
283 m_angularMotorTimescale = 1000;
284 m_angularMotorDecayTimescale = 120;
285 m_VhoverHeight = 0;
286 m_VhoverEfficiency = 1;
287 m_VhoverTimescale = 10;
288 m_VehicleBuoyancy = 0;
289 // m_linearDeflectionEfficiency = 1;
290 // m_linearDeflectionTimescale = 1;
291 // m_angularDeflectionEfficiency = 1;
292 // m_angularDeflectionTimescale = 1000;
293 // m_bankingEfficiency = 0;
294 // m_bankingMix = 1;
295 // m_bankingTimescale = 10;
296 // m_referenceFrame = Quaternion.Identity;
297 m_flags &=
298 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
299 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
300 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
301 break;
302 case Vehicle.TYPE_CAR:
303 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
304 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
305 m_linearMotorDirection = Vector3.Zero;
306 m_linearMotorTimescale = 1;
307 m_linearMotorDecayTimescale = 60;
308 m_angularMotorDirection = Vector3.Zero;
309 m_angularMotorTimescale = 1;
310 m_angularMotorDecayTimescale = 0.8f;
311 m_VhoverHeight = 0;
312 m_VhoverEfficiency = 0;
313 m_VhoverTimescale = 1000;
314 m_VehicleBuoyancy = 0;
315 // // m_linearDeflectionEfficiency = 1;
316 // // m_linearDeflectionTimescale = 2;
317 // // m_angularDeflectionEfficiency = 0;
318 // m_angularDeflectionTimescale = 10;
319 m_verticalAttractionEfficiency = 1;
320 m_verticalAttractionTimescale = 10;
321 // m_bankingEfficiency = -0.2f;
322 // m_bankingMix = 1;
323 // m_bankingTimescale = 1;
324 // m_referenceFrame = Quaternion.Identity;
325 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
326 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY |
327 VehicleFlag.LIMIT_MOTOR_UP);
328 break;
329 case Vehicle.TYPE_BOAT:
330 m_linearFrictionTimescale = new Vector3(10, 3, 2);
331 m_angularFrictionTimescale = new Vector3(10,10,10);
332 m_linearMotorDirection = Vector3.Zero;
333 m_linearMotorTimescale = 5;
334 m_linearMotorDecayTimescale = 60;
335 m_angularMotorDirection = Vector3.Zero;
336 m_angularMotorTimescale = 4;
337 m_angularMotorDecayTimescale = 4;
338 m_VhoverHeight = 0;
339 m_VhoverEfficiency = 0.5f;
340 m_VhoverTimescale = 2;
341 m_VehicleBuoyancy = 1;
342 // m_linearDeflectionEfficiency = 0.5f;
343 // m_linearDeflectionTimescale = 3;
344 // m_angularDeflectionEfficiency = 0.5f;
345 // m_angularDeflectionTimescale = 5;
346 m_verticalAttractionEfficiency = 0.5f;
347 m_verticalAttractionTimescale = 5;
348 // m_bankingEfficiency = -0.3f;
349 // m_bankingMix = 0.8f;
350 // m_bankingTimescale = 1;
351 // m_referenceFrame = Quaternion.Identity;
352 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY |
353 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
354 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY |
355 VehicleFlag.LIMIT_MOTOR_UP);
356 break;
357 case Vehicle.TYPE_AIRPLANE:
358 m_linearFrictionTimescale = new Vector3(200, 10, 5);
359 m_angularFrictionTimescale = new Vector3(20, 20, 20);
360 m_linearMotorDirection = Vector3.Zero;
361 m_linearMotorTimescale = 2;
362 m_linearMotorDecayTimescale = 60;
363 m_angularMotorDirection = Vector3.Zero;
364 m_angularMotorTimescale = 4;
365 m_angularMotorDecayTimescale = 4;
366 m_VhoverHeight = 0;
367 m_VhoverEfficiency = 0.5f;
368 m_VhoverTimescale = 1000;
369 m_VehicleBuoyancy = 0;
370 // m_linearDeflectionEfficiency = 0.5f;
371 // m_linearDeflectionTimescale = 3;
372 // m_angularDeflectionEfficiency = 1;
373 // m_angularDeflectionTimescale = 2;
374 m_verticalAttractionEfficiency = 0.9f;
375 m_verticalAttractionTimescale = 2;
376 // m_bankingEfficiency = 1;
377 // m_bankingMix = 0.7f;
378 // m_bankingTimescale = 2;
379 // m_referenceFrame = Quaternion.Identity;
380 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
381 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
382 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
383 break;
384 case Vehicle.TYPE_BALLOON:
385 m_linearFrictionTimescale = new Vector3(5, 5, 5);
386 m_angularFrictionTimescale = new Vector3(10, 10, 10);
387 m_linearMotorDirection = Vector3.Zero;
388 m_linearMotorTimescale = 5;
389 m_linearMotorDecayTimescale = 60;
390 m_angularMotorDirection = Vector3.Zero;
391 m_angularMotorTimescale = 6;
392 m_angularMotorDecayTimescale = 10;
393 m_VhoverHeight = 5;
394 m_VhoverEfficiency = 0.8f;
395 m_VhoverTimescale = 10;
396 m_VehicleBuoyancy = 1;
397 // m_linearDeflectionEfficiency = 0;
398 // m_linearDeflectionTimescale = 5;
399 // m_angularDeflectionEfficiency = 0;
400 // m_angularDeflectionTimescale = 5;
401 m_verticalAttractionEfficiency = 1;
402 m_verticalAttractionTimescale = 1000;
403 // m_bankingEfficiency = 0;
404 // m_bankingMix = 0.7f;
405 // m_bankingTimescale = 5;
406 // m_referenceFrame = Quaternion.Identity;
407 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
408 VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
409 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
410 break;
411
412 }
413 }//end SetDefaultsForType
414
415 internal void Enable(IntPtr pBody, OdeScene pParentScene)
416 {
417//Console.WriteLine("Enable m_type=" + m_type + " m_VehicleBuoyancy=" + m_VehicleBuoyancy);
418 if (m_type == Vehicle.TYPE_NONE)
419 return;
420
421 m_body = pBody;
422 //KF: This used to set up the linear and angular joints
423 }
424
425 internal void Step(float pTimestep, OdeScene pParentScene)
426 {
427 if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE)
428 return;
429 frcount++; // used to limit debug comment output
430 if (frcount > 100)
431 frcount = 0;
432
433 MoveLinear(pTimestep, pParentScene);
434 MoveAngular(pTimestep);
435 }// end Step
436
437 private void MoveLinear(float pTimestep, OdeScene _pParentScene)
438 {
439 if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant
440 {
441 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
442
443 // add drive to body
444 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
445 m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector?
446
447 // This will work temporarily, but we really need to compare speed on an axis
448 // KF: Limit body velocity to applied velocity?
449 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
450 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
451 if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
452 m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y;
453 if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
454 m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
455
456 // decay applied velocity
457 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
458 //Console.WriteLine("decay: " + decayfraction);
459 m_linearMotorDirection -= m_linearMotorDirection * decayfraction;
460 //Console.WriteLine("actual: " + m_linearMotorDirection);
461 }
462 else
463 { // requested is not significant
464 // if what remains of applied is small, zero it.
465 if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
466 m_lastLinearVelocityVector = Vector3.Zero;
467 }
468
469
470 // convert requested object velocity to world-referenced vector
471 m_dir = m_lastLinearVelocityVector;
472 d.Quaternion rot = d.BodyGetQuaternion(Body);
473 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
474 m_dir *= rotq; // apply obj rotation to velocity vector
475
476 // add Gravity andBuoyancy
477 // KF: So far I have found no good method to combine a script-requested
478 // .Z velocity and gravity. Therefore only 0g will used script-requested
479 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
480 Vector3 grav = Vector3.Zero;
481 if(m_VehicleBuoyancy < 1.0f)
482 {
483 // There is some gravity, make a gravity force vector
484 // that is applied after object velocity.
485 d.Mass objMass;
486 d.BodyGetMass(Body, out objMass);
487 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
488 grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy);
489 // Preserve the current Z velocity
490 d.Vector3 vel_now = d.BodyGetLinearVel(Body);
491 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
492 } // else its 1.0, no gravity.
493
494 // Check if hovering
495 if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
496 {
497 // We should hover, get the target height
498 d.Vector3 pos = d.BodyGetPosition(Body);
499 if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY)
500 {
501 m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight;
502 }
503 else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY)
504 {
505 m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
506 }
507 else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT)
508 {
509 m_VhoverTargetHeight = m_VhoverHeight;
510 }
511
512 if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY)
513 {
514 // If body is aready heigher, use its height as target height
515 if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
516 }
517
518// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
519// m_VhoverTimescale = 0f; // time to acheive height
520// pTimestep is time since last frame,in secs
521 float herr0 = pos.Z - m_VhoverTargetHeight;
522//if(frcount == 0) Console.WriteLine("herr0=" + herr0);
523 // Replace Vertical speed with correction figure if significant
524 if(Math.Abs(herr0) > 0.01f )
525 {
526 d.Mass objMass;
527 d.BodyGetMass(Body, out objMass);
528 m_dir.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
529 // m_VhoverEfficiency is not yet implemented
530 }
531 else
532 {
533 m_dir.Z = 0f;
534 }
535 }
536
537 // Apply velocity
538 d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z);
539//if(frcount == 0) Console.WriteLine("Move " + Body + ":"+ m_dir.X + " " + m_dir.Y + " " + m_dir.Z);
540 // apply gravity force
541 d.BodyAddForce(Body, grav.X, grav.Y, grav.Z);
542//if(frcount == 0) Console.WriteLine("Force " + Body + ":" + grav.X + " " + grav.Y + " " + grav.Z);
543
544
545 // apply friction
546 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
547 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
548 } // end MoveLinear()
549
550 private void MoveAngular(float pTimestep)
551 {
552
553 // m_angularMotorDirection is the latest value from the script, and is decayed here
554 // m_angularMotorDirectionLASTSET is the latest value from the script
555 // m_lastAngularVelocityVector is what is being applied to the Body, varied up and down here
556
557 if (!m_angularMotorDirection.ApproxEquals(Vector3.Zero, 0.01f))
558 {
559 if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
560 // ramp up to new value
561 Vector3 addAmount = m_angularMotorDirection / (m_angularMotorTimescale / pTimestep);
562 m_lastAngularVelocityVector += (addAmount * 10f);
563//if(frcount == 0) Console.WriteLine("add: " + addAmount);
564
565 // limit applied value to what was set by script
566 // This will work temporarily, but we really need to compare speed on an axis
567 if (Math.Abs(m_lastAngularVelocityVector.X) > Math.Abs(m_angularMotorDirectionLASTSET.X))
568 m_lastAngularVelocityVector.X = m_angularMotorDirectionLASTSET.X;
569 if (Math.Abs(m_lastAngularVelocityVector.Y) > Math.Abs(m_angularMotorDirectionLASTSET.Y))
570 m_lastAngularVelocityVector.Y = m_angularMotorDirectionLASTSET.Y;
571 if (Math.Abs(m_lastAngularVelocityVector.Z) > Math.Abs(m_angularMotorDirectionLASTSET.Z))
572 m_lastAngularVelocityVector.Z = m_angularMotorDirectionLASTSET.Z;
573
574 // decay the requested value
575 Vector3 decayfraction = ((Vector3.One / (m_angularMotorDecayTimescale / pTimestep)));
576 //Console.WriteLine("decay: " + decayfraction);
577 m_angularMotorDirection -= m_angularMotorDirection * decayfraction;
578 //Console.WriteLine("actual: " + m_linearMotorDirection);
579 }
580 // KF: m_lastAngularVelocityVector is rotational speed in rad/sec ?
581
582 // Vertical attractor section
583
584// d.Mass objMass;
585// d.BodyGetMass(Body, out objMass);
586// float servo = 100f * objMass.mass * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep);
587 float servo = 0.1f * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep);
588 // get present body rotation
589 d.Quaternion rot = d.BodyGetQuaternion(Body);
590 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
591 // make a vector pointing up
592 Vector3 verterr = Vector3.Zero;
593 verterr.Z = 1.0f;
594 // rotate it to Body Angle
595 verterr = verterr * rotq;
596 // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
597 // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
598 // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
599 if (verterr.Z < 0.0f)
600 {
601 verterr.X = 2.0f - verterr.X;
602 verterr.Y = 2.0f - verterr.Y;
603 }
604 // Error is 0 (no error) to +/- 2 (max error)
605 // scale it by servo
606 verterr = verterr * servo;
607
608 // rotate to object frame
609 // verterr = verterr * rotq;
610
611 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
612 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
613 m_lastAngularVelocityVector.X += verterr.Y;
614 m_lastAngularVelocityVector.Y -= verterr.X;
615/*
616if(frcount == 0)
617 {
618// Console.WriteLine("AngleMotor " + m_lastAngularVelocityVector);
619 Console.WriteLine(String.Format("VA Body:{0} servo:{1} err:<{2},{3},{4}> VAE:{5}",
620 Body, servo, verterr.X, verterr.Y, verterr.Z, m_verticalAttractionEfficiency));
621 }
622 */
623 d.BodySetAngularVel (Body, m_lastAngularVelocityVector.X, m_lastAngularVelocityVector.Y, m_lastAngularVelocityVector.Z);
624 // apply friction
625 Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep);
626 m_lastAngularVelocityVector -= m_lastAngularVelocityVector * decayamount;
627
628 } //end MoveAngular
629 }
630}
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODEDynamics.cs b/OpenSim/Region/PhysicsModules/Ode/ODEDynamics.cs
new file mode 100644
index 0000000..7e95d7f
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/ODEDynamics.cs
@@ -0,0 +1,981 @@
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
41using System;
42using System.Collections.Generic;
43using System.Reflection;
44using System.Runtime.InteropServices;
45using log4net;
46using OpenMetaverse;
47using OpenSim.Framework;
48using OpenSim.Region.PhysicsModules.SharedBase;
49
50
51namespace OpenSim.Region.PhysicsModule.ODE
52{
53 public class ODEDynamics
54 {
55 public Vehicle Type
56 {
57 get { return m_type; }
58 }
59
60 public IntPtr Body
61 {
62 get { return m_body; }
63 }
64
65 private int frcount = 0; // Used to limit dynamics debug output to
66 // every 100th frame
67
68 // private OdeScene m_parentScene = null;
69 private IntPtr m_body = IntPtr.Zero;
70// private IntPtr m_jointGroup = IntPtr.Zero;
71// private IntPtr m_aMotor = IntPtr.Zero;
72
73
74 // Vehicle properties
75 private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
76 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
77 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
78 // HOVER_TERRAIN_ONLY
79 // HOVER_GLOBAL_HEIGHT
80 // NO_DEFLECTION_UP
81 // HOVER_WATER_ONLY
82 // HOVER_UP_ONLY
83 // LIMIT_MOTOR_UP
84 // LIMIT_ROLL_ONLY
85 private VehicleFlag m_Hoverflags = (VehicleFlag)0;
86 private Vector3 m_BlockingEndPoint = Vector3.Zero;
87 private Quaternion m_RollreferenceFrame = Quaternion.Identity;
88 // Linear properties
89 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
90 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
91 private Vector3 m_dir = Vector3.Zero; // velocity applied to body
92 private Vector3 m_linearFrictionTimescale = Vector3.Zero;
93 private float m_linearMotorDecayTimescale = 0;
94 private float m_linearMotorTimescale = 0;
95 private Vector3 m_lastLinearVelocityVector = Vector3.Zero;
96 private d.Vector3 m_lastPositionVector = new d.Vector3();
97 // private bool m_LinearMotorSetLastFrame = false;
98 // private Vector3 m_linearMotorOffset = Vector3.Zero;
99
100 //Angular properties
101 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
102 private int m_angularMotorApply = 0; // application frame counter
103 private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity
104 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
105 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
106 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
107 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
108 // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
109
110 //Deflection properties
111 // private float m_angularDeflectionEfficiency = 0;
112 // private float m_angularDeflectionTimescale = 0;
113 // private float m_linearDeflectionEfficiency = 0;
114 // private float m_linearDeflectionTimescale = 0;
115
116 //Banking properties
117 // private float m_bankingEfficiency = 0;
118 // private float m_bankingMix = 0;
119 // private float m_bankingTimescale = 0;
120
121 //Hover and Buoyancy properties
122 private float m_VhoverHeight = 0f;
123// private float m_VhoverEfficiency = 0f;
124 private float m_VhoverTimescale = 0f;
125 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
126 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
127 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
128 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
129 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
130
131 //Attractor properties
132 private float m_verticalAttractionEfficiency = 1.0f; // damped
133 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
134
135 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
136 {
137 switch (pParam)
138 {
139 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
140 if (pValue < 0.01f) pValue = 0.01f;
141 // m_angularDeflectionEfficiency = pValue;
142 break;
143 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
144 if (pValue < 0.01f) pValue = 0.01f;
145 // m_angularDeflectionTimescale = pValue;
146 break;
147 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
148 if (pValue < 0.01f) pValue = 0.01f;
149 m_angularMotorDecayTimescale = pValue;
150 break;
151 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
152 if (pValue < 0.01f) pValue = 0.01f;
153 m_angularMotorTimescale = pValue;
154 break;
155 case Vehicle.BANKING_EFFICIENCY:
156 if (pValue < 0.01f) pValue = 0.01f;
157 // m_bankingEfficiency = pValue;
158 break;
159 case Vehicle.BANKING_MIX:
160 if (pValue < 0.01f) pValue = 0.01f;
161 // m_bankingMix = pValue;
162 break;
163 case Vehicle.BANKING_TIMESCALE:
164 if (pValue < 0.01f) pValue = 0.01f;
165 // m_bankingTimescale = pValue;
166 break;
167 case Vehicle.BUOYANCY:
168 if (pValue < -1f) pValue = -1f;
169 if (pValue > 1f) pValue = 1f;
170 m_VehicleBuoyancy = pValue;
171 break;
172// case Vehicle.HOVER_EFFICIENCY:
173// if (pValue < 0f) pValue = 0f;
174// if (pValue > 1f) pValue = 1f;
175// m_VhoverEfficiency = pValue;
176// break;
177 case Vehicle.HOVER_HEIGHT:
178 m_VhoverHeight = pValue;
179 break;
180 case Vehicle.HOVER_TIMESCALE:
181 if (pValue < 0.01f) pValue = 0.01f;
182 m_VhoverTimescale = pValue;
183 break;
184 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
185 if (pValue < 0.01f) pValue = 0.01f;
186 // m_linearDeflectionEfficiency = pValue;
187 break;
188 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
189 if (pValue < 0.01f) pValue = 0.01f;
190 // m_linearDeflectionTimescale = pValue;
191 break;
192 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
193 if (pValue < 0.01f) pValue = 0.01f;
194 m_linearMotorDecayTimescale = pValue;
195 break;
196 case Vehicle.LINEAR_MOTOR_TIMESCALE:
197 if (pValue < 0.01f) pValue = 0.01f;
198 m_linearMotorTimescale = pValue;
199 break;
200 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
201 if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable
202 if (pValue > 1.0f) pValue = 1.0f;
203 m_verticalAttractionEfficiency = pValue;
204 break;
205 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
206 if (pValue < 0.01f) pValue = 0.01f;
207 m_verticalAttractionTimescale = pValue;
208 break;
209
210 // These are vector properties but the engine lets you use a single float value to
211 // set all of the components to the same value
212 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
213 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
214 break;
215 case Vehicle.ANGULAR_MOTOR_DIRECTION:
216 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
217 m_angularMotorApply = 10;
218 break;
219 case Vehicle.LINEAR_FRICTION_TIMESCALE:
220 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
221 break;
222 case Vehicle.LINEAR_MOTOR_DIRECTION:
223 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
224 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
225 break;
226 case Vehicle.LINEAR_MOTOR_OFFSET:
227 // m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
228 break;
229
230 }
231 }//end ProcessFloatVehicleParam
232
233 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
234 {
235 switch (pParam)
236 {
237 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
238 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
239 break;
240 case Vehicle.ANGULAR_MOTOR_DIRECTION:
241 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
242 // Limit requested angular speed to 2 rps= 4 pi rads/sec
243 if (m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f;
244 if (m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f;
245 if (m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f;
246 if (m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f;
247 if (m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f;
248 if (m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f;
249 m_angularMotorApply = 10;
250 break;
251 case Vehicle.LINEAR_FRICTION_TIMESCALE:
252 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
253 break;
254 case Vehicle.LINEAR_MOTOR_DIRECTION:
255 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
256 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
257 break;
258 case Vehicle.LINEAR_MOTOR_OFFSET:
259 // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
260 break;
261 case Vehicle.BLOCK_EXIT:
262 m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z);
263 break;
264 }
265 }//end ProcessVectorVehicleParam
266
267 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
268 {
269 switch (pParam)
270 {
271 case Vehicle.REFERENCE_FRAME:
272 // m_referenceFrame = pValue;
273 break;
274 case Vehicle.ROLL_FRAME:
275 m_RollreferenceFrame = pValue;
276 break;
277 }
278 }//end ProcessRotationVehicleParam
279
280 internal void ProcessVehicleFlags(int pParam, bool remove)
281 {
282 if (remove)
283 {
284 if (pParam == -1)
285 {
286 m_flags = (VehicleFlag)0;
287 m_Hoverflags = (VehicleFlag)0;
288 return;
289 }
290 if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT)
291 {
292 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != (VehicleFlag)0)
293 m_Hoverflags &= ~(VehicleFlag.HOVER_GLOBAL_HEIGHT);
294 }
295 if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY)
296 {
297 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != (VehicleFlag)0)
298 m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY);
299 }
300 if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY)
301 {
302 if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != (VehicleFlag)0)
303 m_Hoverflags &= ~(VehicleFlag.HOVER_UP_ONLY);
304 }
305 if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY)
306 {
307 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != (VehicleFlag)0)
308 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY);
309 }
310 if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP)
311 {
312 if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != (VehicleFlag)0)
313 m_flags &= ~(VehicleFlag.LIMIT_MOTOR_UP);
314 }
315 if ((pParam & (int)VehicleFlag.LIMIT_ROLL_ONLY) == (int)VehicleFlag.LIMIT_ROLL_ONLY)
316 {
317 if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != (VehicleFlag)0)
318 m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
319 }
320 if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK)
321 {
322 if ((m_flags & VehicleFlag.MOUSELOOK_BANK) != (VehicleFlag)0)
323 m_flags &= ~(VehicleFlag.MOUSELOOK_BANK);
324 }
325 if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER)
326 {
327 if ((m_flags & VehicleFlag.MOUSELOOK_STEER) != (VehicleFlag)0)
328 m_flags &= ~(VehicleFlag.MOUSELOOK_STEER);
329 }
330 if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP)
331 {
332 if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) != (VehicleFlag)0)
333 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP);
334 }
335 if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED)
336 {
337 if ((m_flags & VehicleFlag.CAMERA_DECOUPLED) != (VehicleFlag)0)
338 m_flags &= ~(VehicleFlag.CAMERA_DECOUPLED);
339 }
340 if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X)
341 {
342 if ((m_flags & VehicleFlag.NO_X) != (VehicleFlag)0)
343 m_flags &= ~(VehicleFlag.NO_X);
344 }
345 if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y)
346 {
347 if ((m_flags & VehicleFlag.NO_Y) != (VehicleFlag)0)
348 m_flags &= ~(VehicleFlag.NO_Y);
349 }
350 if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z)
351 {
352 if ((m_flags & VehicleFlag.NO_Z) != (VehicleFlag)0)
353 m_flags &= ~(VehicleFlag.NO_Z);
354 }
355 if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT)
356 {
357 if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != (VehicleFlag)0)
358 m_Hoverflags &= ~(VehicleFlag.LOCK_HOVER_HEIGHT);
359 }
360 if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION)
361 {
362 if ((m_flags & VehicleFlag.NO_DEFLECTION) != (VehicleFlag)0)
363 m_flags &= ~(VehicleFlag.NO_DEFLECTION);
364 }
365 if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION)
366 {
367 if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0)
368 m_flags &= ~(VehicleFlag.LOCK_ROTATION);
369 }
370 }
371 else
372 {
373 if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT)
374 {
375 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags);
376 }
377 if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY)
378 {
379 m_Hoverflags |= (VehicleFlag.HOVER_TERRAIN_ONLY | m_flags);
380 }
381 if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY)
382 {
383 m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY | m_flags);
384 }
385 if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY)
386 {
387 m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY | m_flags);
388 }
389 if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP)
390 {
391 m_flags |= (VehicleFlag.LIMIT_MOTOR_UP | m_flags);
392 }
393 if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK)
394 {
395 m_flags |= (VehicleFlag.MOUSELOOK_BANK | m_flags);
396 }
397 if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER)
398 {
399 m_flags |= (VehicleFlag.MOUSELOOK_STEER | m_flags);
400 }
401 if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP)
402 {
403 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags);
404 }
405 if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED)
406 {
407 m_flags |= (VehicleFlag.CAMERA_DECOUPLED | m_flags);
408 }
409 if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X)
410 {
411 m_flags |= (VehicleFlag.NO_X);
412 }
413 if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y)
414 {
415 m_flags |= (VehicleFlag.NO_Y);
416 }
417 if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z)
418 {
419 m_flags |= (VehicleFlag.NO_Z);
420 }
421 if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT)
422 {
423 m_Hoverflags |= (VehicleFlag.LOCK_HOVER_HEIGHT);
424 }
425 if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION)
426 {
427 m_flags |= (VehicleFlag.NO_DEFLECTION);
428 }
429 if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION)
430 {
431 m_flags |= (VehicleFlag.LOCK_ROTATION);
432 }
433 }
434 }//end ProcessVehicleFlags
435
436 internal void ProcessTypeChange(Vehicle pType)
437 {
438 // Set Defaults For Type
439 m_type = pType;
440 switch (pType)
441 {
442 case Vehicle.TYPE_NONE:
443 m_linearFrictionTimescale = new Vector3(0, 0, 0);
444 m_angularFrictionTimescale = new Vector3(0, 0, 0);
445 m_linearMotorDirection = Vector3.Zero;
446 m_linearMotorTimescale = 0;
447 m_linearMotorDecayTimescale = 0;
448 m_angularMotorDirection = Vector3.Zero;
449 m_angularMotorTimescale = 0;
450 m_angularMotorDecayTimescale = 0;
451 m_VhoverHeight = 0;
452 m_VhoverTimescale = 0;
453 m_VehicleBuoyancy = 0;
454 m_flags = (VehicleFlag)0;
455 break;
456
457 case Vehicle.TYPE_SLED:
458 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
459 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
460 m_linearMotorDirection = Vector3.Zero;
461 m_linearMotorTimescale = 1000;
462 m_linearMotorDecayTimescale = 120;
463 m_angularMotorDirection = Vector3.Zero;
464 m_angularMotorTimescale = 1000;
465 m_angularMotorDecayTimescale = 120;
466 m_VhoverHeight = 0;
467// m_VhoverEfficiency = 1;
468 m_VhoverTimescale = 10;
469 m_VehicleBuoyancy = 0;
470 // m_linearDeflectionEfficiency = 1;
471 // m_linearDeflectionTimescale = 1;
472 // m_angularDeflectionEfficiency = 1;
473 // m_angularDeflectionTimescale = 1000;
474 // m_bankingEfficiency = 0;
475 // m_bankingMix = 1;
476 // m_bankingTimescale = 10;
477 // m_referenceFrame = Quaternion.Identity;
478 m_Hoverflags &=
479 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
480 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
481 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
482 break;
483 case Vehicle.TYPE_CAR:
484 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
485 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
486 m_linearMotorDirection = Vector3.Zero;
487 m_linearMotorTimescale = 1;
488 m_linearMotorDecayTimescale = 60;
489 m_angularMotorDirection = Vector3.Zero;
490 m_angularMotorTimescale = 1;
491 m_angularMotorDecayTimescale = 0.8f;
492 m_VhoverHeight = 0;
493// m_VhoverEfficiency = 0;
494 m_VhoverTimescale = 1000;
495 m_VehicleBuoyancy = 0;
496 // // m_linearDeflectionEfficiency = 1;
497 // // m_linearDeflectionTimescale = 2;
498 // // m_angularDeflectionEfficiency = 0;
499 // m_angularDeflectionTimescale = 10;
500 m_verticalAttractionEfficiency = 1f;
501 m_verticalAttractionTimescale = 10f;
502 // m_bankingEfficiency = -0.2f;
503 // m_bankingMix = 1;
504 // m_bankingTimescale = 1;
505 // m_referenceFrame = Quaternion.Identity;
506 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
507 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
508 VehicleFlag.LIMIT_MOTOR_UP);
509 m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY);
510 break;
511 case Vehicle.TYPE_BOAT:
512 m_linearFrictionTimescale = new Vector3(10, 3, 2);
513 m_angularFrictionTimescale = new Vector3(10,10,10);
514 m_linearMotorDirection = Vector3.Zero;
515 m_linearMotorTimescale = 5;
516 m_linearMotorDecayTimescale = 60;
517 m_angularMotorDirection = Vector3.Zero;
518 m_angularMotorTimescale = 4;
519 m_angularMotorDecayTimescale = 4;
520 m_VhoverHeight = 0;
521// m_VhoverEfficiency = 0.5f;
522 m_VhoverTimescale = 2;
523 m_VehicleBuoyancy = 1;
524 // m_linearDeflectionEfficiency = 0.5f;
525 // m_linearDeflectionTimescale = 3;
526 // m_angularDeflectionEfficiency = 0.5f;
527 // m_angularDeflectionTimescale = 5;
528 m_verticalAttractionEfficiency = 0.5f;
529 m_verticalAttractionTimescale = 5f;
530 // m_bankingEfficiency = -0.3f;
531 // m_bankingMix = 0.8f;
532 // m_bankingTimescale = 1;
533 // m_referenceFrame = Quaternion.Identity;
534 m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
535 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
536 m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
537 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
538 VehicleFlag.LIMIT_MOTOR_UP);
539 m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY);
540 break;
541 case Vehicle.TYPE_AIRPLANE:
542 m_linearFrictionTimescale = new Vector3(200, 10, 5);
543 m_angularFrictionTimescale = new Vector3(20, 20, 20);
544 m_linearMotorDirection = Vector3.Zero;
545 m_linearMotorTimescale = 2;
546 m_linearMotorDecayTimescale = 60;
547 m_angularMotorDirection = Vector3.Zero;
548 m_angularMotorTimescale = 4;
549 m_angularMotorDecayTimescale = 4;
550 m_VhoverHeight = 0;
551// m_VhoverEfficiency = 0.5f;
552 m_VhoverTimescale = 1000;
553 m_VehicleBuoyancy = 0;
554 // m_linearDeflectionEfficiency = 0.5f;
555 // m_linearDeflectionTimescale = 3;
556 // m_angularDeflectionEfficiency = 1;
557 // m_angularDeflectionTimescale = 2;
558 m_verticalAttractionEfficiency = 0.9f;
559 m_verticalAttractionTimescale = 2f;
560 // m_bankingEfficiency = 1;
561 // m_bankingMix = 0.7f;
562 // m_bankingTimescale = 2;
563 // m_referenceFrame = Quaternion.Identity;
564 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
565 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
566 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
567 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
568 break;
569 case Vehicle.TYPE_BALLOON:
570 m_linearFrictionTimescale = new Vector3(5, 5, 5);
571 m_angularFrictionTimescale = new Vector3(10, 10, 10);
572 m_linearMotorDirection = Vector3.Zero;
573 m_linearMotorTimescale = 5;
574 m_linearMotorDecayTimescale = 60;
575 m_angularMotorDirection = Vector3.Zero;
576 m_angularMotorTimescale = 6;
577 m_angularMotorDecayTimescale = 10;
578 m_VhoverHeight = 5;
579// m_VhoverEfficiency = 0.8f;
580 m_VhoverTimescale = 10;
581 m_VehicleBuoyancy = 1;
582 // m_linearDeflectionEfficiency = 0;
583 // m_linearDeflectionTimescale = 5;
584 // m_angularDeflectionEfficiency = 0;
585 // m_angularDeflectionTimescale = 5;
586 m_verticalAttractionEfficiency = 1f;
587 m_verticalAttractionTimescale = 100f;
588 // m_bankingEfficiency = 0;
589 // m_bankingMix = 0.7f;
590 // m_bankingTimescale = 5;
591 // m_referenceFrame = Quaternion.Identity;
592 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
593 VehicleFlag.HOVER_UP_ONLY);
594 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
595 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
596 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT);
597 break;
598
599 }
600 }//end SetDefaultsForType
601
602 internal void Enable(IntPtr pBody, OdeScene pParentScene)
603 {
604 if (m_type == Vehicle.TYPE_NONE)
605 return;
606
607 m_body = pBody;
608 }
609
610 internal void Stop()
611 {
612 m_lastLinearVelocityVector = Vector3.Zero;
613 m_lastAngularVelocity = Vector3.Zero;
614 m_lastPositionVector = d.BodyGetPosition(Body);
615 }
616
617 internal void Step(float pTimestep, OdeScene pParentScene)
618 {
619 if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE)
620 return;
621 frcount++; // used to limit debug comment output
622 if (frcount > 100)
623 frcount = 0;
624
625 MoveLinear(pTimestep, pParentScene);
626 MoveAngular(pTimestep);
627 LimitRotation(pTimestep);
628 }// end Step
629
630 private void MoveLinear(float pTimestep, OdeScene _pParentScene)
631 {
632 if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant
633 {
634 if (!d.BodyIsEnabled(Body))
635 d.BodyEnable(Body);
636
637 // add drive to body
638 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
639 m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector?
640
641 // This will work temporarily, but we really need to compare speed on an axis
642 // KF: Limit body velocity to applied velocity?
643 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
644 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
645 if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
646 m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y;
647 if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
648 m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
649
650 // decay applied velocity
651 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
652 //Console.WriteLine("decay: " + decayfraction);
653 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
654 //Console.WriteLine("actual: " + m_linearMotorDirection);
655 }
656 else
657 { // requested is not significant
658 // if what remains of applied is small, zero it.
659 if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
660 m_lastLinearVelocityVector = Vector3.Zero;
661 }
662
663 // convert requested object velocity to world-referenced vector
664 m_dir = m_lastLinearVelocityVector;
665 d.Quaternion rot = d.BodyGetQuaternion(Body);
666 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
667 m_dir *= rotq; // apply obj rotation to velocity vector
668
669 // add Gravity andBuoyancy
670 // KF: So far I have found no good method to combine a script-requested
671 // .Z velocity and gravity. Therefore only 0g will used script-requested
672 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
673 Vector3 grav = Vector3.Zero;
674 // There is some gravity, make a gravity force vector
675 // that is applied after object velocity.
676 d.Mass objMass;
677 d.BodyGetMass(Body, out objMass);
678 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
679 grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy);
680 // Preserve the current Z velocity
681 d.Vector3 vel_now = d.BodyGetLinearVel(Body);
682 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
683
684 d.Vector3 pos = d.BodyGetPosition(Body);
685// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
686 Vector3 posChange = new Vector3();
687 posChange.X = pos.X - m_lastPositionVector.X;
688 posChange.Y = pos.Y - m_lastPositionVector.Y;
689 posChange.Z = pos.Z - m_lastPositionVector.Z;
690 double Zchange = Math.Abs(posChange.Z);
691 if (m_BlockingEndPoint != Vector3.Zero)
692 {
693 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
694 {
695 pos.X -= posChange.X + 1;
696 d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
697 }
698 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
699 {
700 pos.Y -= posChange.Y + 1;
701 d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
702 }
703 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
704 {
705 pos.Z -= posChange.Z + 1;
706 d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
707 }
708 if (pos.X <= 0)
709 {
710 pos.X += posChange.X + 1;
711 d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
712 }
713 if (pos.Y <= 0)
714 {
715 pos.Y += posChange.Y + 1;
716 d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
717 }
718 }
719 if (pos.Z < _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y))
720 {
721 pos.Z = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2;
722 d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
723 }
724
725 // Check if hovering
726 if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
727 {
728 // We should hover, get the target height
729 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0)
730 {
731 m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight;
732 }
733 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
734 {
735 m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
736 }
737 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
738 {
739 m_VhoverTargetHeight = m_VhoverHeight;
740 }
741
742 if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0)
743 {
744 // If body is aready heigher, use its height as target height
745 if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
746 }
747 if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
748 {
749 if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
750 {
751 d.BodySetPosition(Body, pos.X, pos.Y, m_VhoverTargetHeight);
752 }
753 }
754 else
755 {
756 float herr0 = pos.Z - m_VhoverTargetHeight;
757 // Replace Vertical speed with correction figure if significant
758 if (Math.Abs(herr0) > 0.01f)
759 {
760 m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
761 //KF: m_VhoverEfficiency is not yet implemented
762 }
763 else
764 {
765 m_dir.Z = 0f;
766 }
767 }
768
769// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
770// m_VhoverTimescale = 0f; // time to acheive height
771// pTimestep is time since last frame,in secs
772 }
773
774 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
775 {
776 //Start Experimental Values
777 if (Zchange > .3)
778 {
779 grav.Z = (float)(grav.Z * 3);
780 }
781 if (Zchange > .15)
782 {
783 grav.Z = (float)(grav.Z * 2);
784 }
785 if (Zchange > .75)
786 {
787 grav.Z = (float)(grav.Z * 1.5);
788 }
789 if (Zchange > .05)
790 {
791 grav.Z = (float)(grav.Z * 1.25);
792 }
793 if (Zchange > .025)
794 {
795 grav.Z = (float)(grav.Z * 1.125);
796 }
797 float terraintemp = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
798 float postemp = (pos.Z - terraintemp);
799 if (postemp > 2.5f)
800 {
801 grav.Z = (float)(grav.Z * 1.037125);
802 }
803 //End Experimental Values
804 }
805 if ((m_flags & (VehicleFlag.NO_X)) != 0)
806 {
807 m_dir.X = 0;
808 }
809 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
810 {
811 m_dir.Y = 0;
812 }
813 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
814 {
815 m_dir.Z = 0;
816 }
817
818 m_lastPositionVector = d.BodyGetPosition(Body);
819
820 // Apply velocity
821 d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z);
822 // apply gravity force
823 d.BodyAddForce(Body, grav.X, grav.Y, grav.Z);
824
825
826 // apply friction
827 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
828 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
829 } // end MoveLinear()
830
831 private void MoveAngular(float pTimestep)
832 {
833 /*
834 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
835 private int m_angularMotorApply = 0; // application frame counter
836 private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down)
837 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
838 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
839 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
840 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
841 */
842
843 // Get what the body is doing, this includes 'external' influences
844 d.Vector3 angularVelocity = d.BodyGetAngularVel(Body);
845 // Vector3 angularVelocity = Vector3.Zero;
846
847 if (m_angularMotorApply > 0)
848 {
849 // ramp up to new value
850 // current velocity += error / (time to get there / step interval)
851 // requested speed - last motor speed
852 m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep);
853 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
854 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
855
856 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected
857 // velocity may still be acheived.
858 }
859 else
860 {
861 // no motor recently applied, keep the body velocity
862 /* m_angularMotorVelocity.X = angularVelocity.X;
863 m_angularMotorVelocity.Y = angularVelocity.Y;
864 m_angularMotorVelocity.Z = angularVelocity.Z; */
865
866 // and decay the velocity
867 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
868 } // end motor section
869
870 // Vertical attractor section
871 Vector3 vertattr = Vector3.Zero;
872
873 if (m_verticalAttractionTimescale < 300)
874 {
875 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep);
876 // get present body rotation
877 d.Quaternion rot = d.BodyGetQuaternion(Body);
878 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
879 // make a vector pointing up
880 Vector3 verterr = Vector3.Zero;
881 verterr.Z = 1.0f;
882 // rotate it to Body Angle
883 verterr = verterr * rotq;
884 // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
885 // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
886 // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
887 if (verterr.Z < 0.0f)
888 {
889 verterr.X = 2.0f - verterr.X;
890 verterr.Y = 2.0f - verterr.Y;
891 }
892 // Error is 0 (no error) to +/- 2 (max error)
893 // scale it by VAservo
894 verterr = verterr * VAservo;
895//if (frcount == 0) Console.WriteLine("VAerr=" + verterr);
896
897 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
898 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
899 vertattr.X = verterr.Y;
900 vertattr.Y = - verterr.X;
901 vertattr.Z = 0f;
902
903 // scaling appears better usingsquare-law
904 float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
905 vertattr.X += bounce * angularVelocity.X;
906 vertattr.Y += bounce * angularVelocity.Y;
907
908 } // else vertical attractor is off
909
910 // m_lastVertAttractor = vertattr;
911
912 // Bank section tba
913 // Deflection section tba
914
915 // Sum velocities
916 m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection
917
918 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
919 {
920 m_lastAngularVelocity.X = 0;
921 m_lastAngularVelocity.Y = 0;
922 }
923
924 if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
925 {
926 if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
927 }
928 else
929 {
930 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
931 }
932
933 // apply friction
934 Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep);
935 m_lastAngularVelocity -= m_lastAngularVelocity * decayamount;
936
937 // Apply to the body
938 d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z);
939
940 } //end MoveAngular
941 internal void LimitRotation(float timestep)
942 {
943 d.Quaternion rot = d.BodyGetQuaternion(Body);
944 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
945 d.Quaternion m_rot = new d.Quaternion();
946 bool changed = false;
947 m_rot.X = rotq.X;
948 m_rot.Y = rotq.Y;
949 m_rot.Z = rotq.Z;
950 m_rot.W = rotq.W;
951 if (m_RollreferenceFrame != Quaternion.Identity)
952 {
953 if (rotq.X >= m_RollreferenceFrame.X)
954 {
955 m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2);
956 }
957 if (rotq.Y >= m_RollreferenceFrame.Y)
958 {
959 m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2);
960 }
961 if (rotq.X <= -m_RollreferenceFrame.X)
962 {
963 m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2);
964 }
965 if (rotq.Y <= -m_RollreferenceFrame.Y)
966 {
967 m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2);
968 }
969 changed = true;
970 }
971 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0)
972 {
973 m_rot.X = 0;
974 m_rot.Y = 0;
975 changed = true;
976 }
977 if (changed)
978 d.BodySetQuaternion(Body, ref m_rot);
979 }
980 }
981}
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODEModule.cs b/OpenSim/Region/PhysicsModules/Ode/ODEModule.cs
new file mode 100644
index 0000000..22fc84d
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/ODEModule.cs
@@ -0,0 +1,89 @@
1using System;
2using System.Reflection;
3using log4net;
4using Nini.Config;
5using Mono.Addins;
6using OpenSim.Framework;
7using OpenSim.Region.Framework.Scenes;
8using OpenSim.Region.Framework.Interfaces;
9
10namespace OpenSim.Region.PhysicsModule.ODE
11{
12 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ODEPhysicsScene")]
13 public class OdeModule : INonSharedRegionModule
14 {
15 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
16
17 private bool m_Enabled = false;
18 private IConfigSource m_config;
19 private OdeScene m_scene;
20
21 #region INonSharedRegionModule
22
23 public string Name
24 {
25 get { return "OpenDynamicsEngine"; }
26 }
27
28 public string Version
29 {
30 get { return "1.0"; }
31 }
32
33 public Type ReplaceableInterface
34 {
35 get { return null; }
36 }
37
38 public void Initialise(IConfigSource source)
39 {
40 IConfig config = source.Configs["Startup"];
41 if (config != null)
42 {
43 string physics = config.GetString("physics", string.Empty);
44 if (physics == Name)
45 {
46 m_config = source;
47 m_Enabled = true;
48 }
49 }
50 }
51
52 public void Close()
53 {
54 }
55
56 public void AddRegion(Scene scene)
57 {
58 if (!m_Enabled)
59 return;
60
61 if (Util.IsWindows())
62 Util.LoadArchSpecificWindowsDll("ode.dll");
63
64 // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to
65 // http://opensimulator.org/mantis/view.php?id=2750).
66 d.InitODE();
67
68 m_scene = new OdeScene(scene, m_config, Name, Version);
69 }
70
71 public void RemoveRegion(Scene scene)
72 {
73 if (!m_Enabled || m_scene == null)
74 return;
75
76 m_scene.Dispose();
77 m_scene = null;
78 }
79
80 public void RegionLoaded(Scene scene)
81 {
82 if (!m_Enabled || m_scene == null)
83 return;
84
85 m_scene.RegionLoaded();
86 }
87 #endregion
88 }
89}
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs b/OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs
new file mode 100644
index 0000000..8934330
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs
@@ -0,0 +1,3206 @@
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 OpenSim.Framework;
52using OpenSim.Region.PhysicsModules.SharedBase;
53
54namespace OpenSim.Region.PhysicsModule.ODE
55{
56 /// <summary>
57 /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
58 /// </summary>
59 public class OdePrim : PhysicsActor
60 {
61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62
63 private bool m_isphysical;
64
65 public int ExpectedCollisionContacts { get { return m_expectedCollisionContacts; } }
66 private int m_expectedCollisionContacts = 0;
67
68 /// <summary>
69 /// Gets collide bits so that we can still perform land collisions if a mesh fails to load.
70 /// </summary>
71 private int BadMeshAssetCollideBits
72 {
73 get { return m_isphysical ? (int)CollisionCategories.Land : 0; }
74 }
75
76 /// <summary>
77 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
78 /// </summary>
79 public override bool IsPhysical
80 {
81 get { return m_isphysical; }
82 set
83 {
84 m_isphysical = value;
85 if (!m_isphysical)
86 {
87 _zeroFlag = true; // Zero the remembered last velocity
88 m_lastVelocity = Vector3.Zero;
89 _acceleration = Vector3.Zero;
90 _velocity = Vector3.Zero;
91 m_taintVelocity = Vector3.Zero;
92 m_rotationalVelocity = Vector3.Zero;
93 }
94 }
95 }
96
97 private Vector3 _position;
98 private Vector3 _velocity;
99 private Vector3 _torque;
100 private Vector3 m_lastVelocity;
101 private Vector3 m_lastposition;
102 private Quaternion m_lastorientation = new Quaternion();
103 private Vector3 m_rotationalVelocity;
104 private Vector3 _size;
105 private Vector3 _acceleration;
106 // private d.Vector3 _zeroPosition = new d.Vector3(0.0f, 0.0f, 0.0f);
107 private Quaternion _orientation;
108 private Vector3 m_taintposition;
109 private Vector3 m_taintsize;
110 private Vector3 m_taintVelocity;
111 private Vector3 m_taintTorque;
112 private Quaternion m_taintrot;
113
114 private IntPtr Amotor = IntPtr.Zero;
115
116 private byte m_taintAngularLock = 0;
117 private byte m_angularlock = 0;
118
119 private bool m_assetFailed = false;
120
121 private Vector3 m_PIDTarget;
122 private float m_PIDTau;
123 private float PID_D = 35f;
124 private float PID_G = 25f;
125
126 // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
127 // and are for non-VEHICLES only.
128
129 private float m_PIDHoverHeight;
130 private float m_PIDHoverTau;
131 private bool m_useHoverPID;
132 private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
133 private float m_targetHoverHeight;
134 private float m_groundHeight;
135 private float m_waterHeight;
136 private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
137
138 // private float m_tensor = 5f;
139 private int body_autodisable_frames = 20;
140
141
142 private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
143 | CollisionCategories.Space
144 | CollisionCategories.Body
145 | CollisionCategories.Character
146 );
147 private bool m_taintshape;
148 private bool m_taintPhysics;
149 private bool m_collidesLand = true;
150 private bool m_collidesWater;
151
152 // Default we're a Geometry
153 private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
154
155 // Default, Collide with Other Geometries, spaces and Bodies
156 private CollisionCategories m_collisionFlags = m_default_collisionFlags;
157
158 public bool m_taintremove { get; private set; }
159 public bool m_taintdisable { get; private set; }
160 internal bool m_disabled;
161 public bool m_taintadd { get; private set; }
162 public bool m_taintselected { get; private set; }
163 public bool m_taintCollidesWater { get; private set; }
164
165 private bool m_taintforce = false;
166 private bool m_taintaddangularforce = false;
167 private Vector3 m_force;
168 private List<Vector3> m_forcelist = new List<Vector3>();
169 private List<Vector3> m_angularforcelist = new List<Vector3>();
170
171 private PrimitiveBaseShape _pbs;
172 private OdeScene _parent_scene;
173
174 /// <summary>
175 /// The physics space which contains prim geometries
176 /// </summary>
177 public IntPtr m_targetSpace = IntPtr.Zero;
178
179 /// <summary>
180 /// The prim geometry, used for collision detection.
181 /// </summary>
182 /// <remarks>
183 /// This is never null except for a brief period when the geometry needs to be replaced (due to resizing or
184 /// mesh change) or when the physical prim is being removed from the scene.
185 /// </remarks>
186 public IntPtr prim_geom { get; private set; }
187
188 public IntPtr _triMeshData { get; private set; }
189
190 private IntPtr _linkJointGroup = IntPtr.Zero;
191 private PhysicsActor _parent;
192 private PhysicsActor m_taintparent;
193
194 private List<OdePrim> childrenPrim = new List<OdePrim>();
195
196 private bool iscolliding;
197 private bool m_isSelected;
198
199 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
200
201 private bool m_throttleUpdates;
202 private int throttleCounter;
203 public int m_interpenetrationcount { get; private set; }
204 internal float m_collisionscore;
205 public int m_roundsUnderMotionThreshold { get; private set; }
206
207 public bool outofBounds { get; private set; }
208 private float m_density = 10.000006836f; // Aluminum g/cm3;
209
210 public bool _zeroFlag { get; private set; }
211 private bool m_lastUpdateSent;
212
213 public IntPtr Body = IntPtr.Zero;
214 private Vector3 _target_velocity;
215 private d.Mass pMass;
216
217 private int m_eventsubscription;
218 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
219
220 /// <summary>
221 /// Signal whether there were collisions on the previous frame, so we know if we need to send the
222 /// empty CollisionEventsThisFrame to the prim so that it can detect the end of a collision.
223 /// </summary>
224 /// <remarks>
225 /// This is probably a temporary measure, pending storing this information consistently in CollisionEventUpdate itself.
226 /// </remarks>
227 private bool m_collisionsOnPreviousFrame;
228
229 private IntPtr m_linkJoint = IntPtr.Zero;
230
231 internal volatile bool childPrim;
232
233 private ODEDynamics m_vehicle;
234
235 internal int m_material = (int)Material.Wood;
236
237 public OdePrim(
238 String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
239 Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
240 {
241 Name = primName;
242 m_vehicle = new ODEDynamics();
243 //gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned);
244
245 if (!pos.IsFinite())
246 {
247 pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
248 parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
249 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Position for {0}", Name);
250 }
251 _position = pos;
252 m_taintposition = pos;
253 PID_D = parent_scene.bodyPIDD;
254 PID_G = parent_scene.bodyPIDG;
255 m_density = parent_scene.geomDefaultDensity;
256 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
257 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
258
259 prim_geom = IntPtr.Zero;
260
261 if (!pos.IsFinite())
262 {
263 size = new Vector3(0.5f, 0.5f, 0.5f);
264 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Size for {0}", Name);
265 }
266
267 if (size.X <= 0) size.X = 0.01f;
268 if (size.Y <= 0) size.Y = 0.01f;
269 if (size.Z <= 0) size.Z = 0.01f;
270
271 _size = size;
272 m_taintsize = _size;
273
274 if (!QuaternionIsFinite(rotation))
275 {
276 rotation = Quaternion.Identity;
277 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Rotation for {0}", Name);
278 }
279
280 _orientation = rotation;
281 m_taintrot = _orientation;
282 _pbs = pbs;
283
284 _parent_scene = parent_scene;
285 m_targetSpace = (IntPtr)0;
286
287 if (pos.Z < 0)
288 {
289 IsPhysical = false;
290 }
291 else
292 {
293 IsPhysical = pisPhysical;
294 // If we're physical, we need to be in the master space for now.
295 // linksets *should* be in a space together.. but are not currently
296 if (IsPhysical)
297 m_targetSpace = _parent_scene.space;
298 }
299
300 m_taintadd = true;
301 m_assetFailed = false;
302 _parent_scene.AddPhysicsActorTaint(this);
303 }
304
305 public override int PhysicsActorType
306 {
307 get { return (int) ActorTypes.Prim; }
308 set { return; }
309 }
310
311 public override bool SetAlwaysRun
312 {
313 get { return false; }
314 set { return; }
315 }
316
317 public override bool Grabbed
318 {
319 set { return; }
320 }
321
322 public override bool Selected
323 {
324 set
325 {
326 // This only makes the object not collidable if the object
327 // is physical or the object is modified somehow *IN THE FUTURE*
328 // without this, if an avatar selects prim, they can walk right
329 // through it while it's selected
330 m_collisionscore = 0;
331
332 if ((IsPhysical && !_zeroFlag) || !value)
333 {
334 m_taintselected = value;
335 _parent_scene.AddPhysicsActorTaint(this);
336 }
337 else
338 {
339 m_taintselected = value;
340 m_isSelected = value;
341 }
342
343 if (m_isSelected)
344 disableBodySoft();
345 }
346 }
347
348 /// <summary>
349 /// Set a new geometry for this prim.
350 /// </summary>
351 /// <param name="geom"></param>
352 private void SetGeom(IntPtr geom)
353 {
354 prim_geom = geom;
355//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
356
357 if (m_assetFailed)
358 {
359 d.GeomSetCategoryBits(prim_geom, 0);
360 d.GeomSetCollideBits(prim_geom, (uint)BadMeshAssetCollideBits);
361 }
362 else
363 {
364 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
365 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
366 }
367
368 _parent_scene.geom_name_map[prim_geom] = Name;
369 _parent_scene.actor_name_map[prim_geom] = this;
370
371 if (childPrim)
372 {
373 if (_parent != null && _parent is OdePrim)
374 {
375 OdePrim parent = (OdePrim)_parent;
376//Console.WriteLine("SetGeom calls ChildSetGeom");
377 parent.ChildSetGeom(this);
378 }
379 }
380 //m_log.Warn("Setting Geom to: " + prim_geom);
381 }
382
383 private void enableBodySoft()
384 {
385 if (!childPrim)
386 {
387 if (IsPhysical && Body != IntPtr.Zero)
388 {
389 d.BodyEnable(Body);
390 if (m_vehicle.Type != Vehicle.TYPE_NONE)
391 m_vehicle.Enable(Body, _parent_scene);
392 }
393
394 m_disabled = false;
395 }
396 }
397
398 private void disableBodySoft()
399 {
400 m_disabled = true;
401
402 if (IsPhysical && Body != IntPtr.Zero)
403 {
404 d.BodyDisable(Body);
405 }
406 }
407
408 /// <summary>
409 /// Make a prim subject to physics.
410 /// </summary>
411 private void enableBody()
412 {
413 // Don't enable this body if we're a child prim
414 // this should be taken care of in the parent function not here
415 if (!childPrim)
416 {
417 // Sets the geom to a body
418 Body = d.BodyCreate(_parent_scene.world);
419
420 setMass();
421 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
422 d.Quaternion myrot = new d.Quaternion();
423 myrot.X = _orientation.X;
424 myrot.Y = _orientation.Y;
425 myrot.Z = _orientation.Z;
426 myrot.W = _orientation.W;
427 d.BodySetQuaternion(Body, ref myrot);
428 d.GeomSetBody(prim_geom, Body);
429
430 if (m_assetFailed)
431 {
432 d.GeomSetCategoryBits(prim_geom, 0);
433 d.GeomSetCollideBits(prim_geom, (uint)BadMeshAssetCollideBits);
434 }
435 else
436 {
437 m_collisionCategories |= CollisionCategories.Body;
438 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
439 }
440
441 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
442 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
443
444 d.BodySetAutoDisableFlag(Body, true);
445 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
446
447 // disconnect from world gravity so we can apply buoyancy
448 d.BodySetGravityMode (Body, false);
449
450 m_interpenetrationcount = 0;
451 m_collisionscore = 0;
452 m_disabled = false;
453
454 // The body doesn't already have a finite rotation mode set here
455 if (m_angularlock != 0 && _parent == null)
456 {
457 createAMotor(m_angularlock);
458 }
459 if (m_vehicle.Type != Vehicle.TYPE_NONE)
460 {
461 m_vehicle.Enable(Body, _parent_scene);
462 }
463
464 _parent_scene.ActivatePrim(this);
465 }
466 }
467
468 #region Mass Calculation
469
470 private float CalculateMass()
471 {
472 float volume = _size.X * _size.Y * _size.Z; // default
473 float tmp;
474
475 float returnMass = 0;
476 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
477 float hollowVolume = hollowAmount * hollowAmount;
478
479 switch (_pbs.ProfileShape)
480 {
481 case ProfileShape.Square:
482 // default box
483
484 if (_pbs.PathCurve == (byte)Extrusion.Straight)
485 {
486 if (hollowAmount > 0.0)
487 {
488 switch (_pbs.HollowShape)
489 {
490 case HollowShape.Square:
491 case HollowShape.Same:
492 break;
493
494 case HollowShape.Circle:
495
496 hollowVolume *= 0.78539816339f;
497 break;
498
499 case HollowShape.Triangle:
500
501 hollowVolume *= (0.5f * .5f);
502 break;
503
504 default:
505 hollowVolume = 0;
506 break;
507 }
508 volume *= (1.0f - hollowVolume);
509 }
510 }
511
512 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
513 {
514 //a tube
515
516 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
517 tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY);
518 volume -= volume*tmp*tmp;
519
520 if (hollowAmount > 0.0)
521 {
522 hollowVolume *= hollowAmount;
523
524 switch (_pbs.HollowShape)
525 {
526 case HollowShape.Square:
527 case HollowShape.Same:
528 break;
529
530 case HollowShape.Circle:
531 hollowVolume *= 0.78539816339f;;
532 break;
533
534 case HollowShape.Triangle:
535 hollowVolume *= 0.5f * 0.5f;
536 break;
537 default:
538 hollowVolume = 0;
539 break;
540 }
541 volume *= (1.0f - hollowVolume);
542 }
543 }
544
545 break;
546
547 case ProfileShape.Circle:
548
549 if (_pbs.PathCurve == (byte)Extrusion.Straight)
550 {
551 volume *= 0.78539816339f; // elipse base
552
553 if (hollowAmount > 0.0)
554 {
555 switch (_pbs.HollowShape)
556 {
557 case HollowShape.Same:
558 case HollowShape.Circle:
559 break;
560
561 case HollowShape.Square:
562 hollowVolume *= 0.5f * 2.5984480504799f;
563 break;
564
565 case HollowShape.Triangle:
566 hollowVolume *= .5f * 1.27323954473516f;
567 break;
568
569 default:
570 hollowVolume = 0;
571 break;
572 }
573 volume *= (1.0f - hollowVolume);
574 }
575 }
576
577 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
578 {
579 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
580 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
581 volume *= (1.0f - tmp * tmp);
582
583 if (hollowAmount > 0.0)
584 {
585
586 // calculate the hollow volume by it's shape compared to the prim shape
587 hollowVolume *= hollowAmount;
588
589 switch (_pbs.HollowShape)
590 {
591 case HollowShape.Same:
592 case HollowShape.Circle:
593 break;
594
595 case HollowShape.Square:
596 hollowVolume *= 0.5f * 2.5984480504799f;
597 break;
598
599 case HollowShape.Triangle:
600 hollowVolume *= .5f * 1.27323954473516f;
601 break;
602
603 default:
604 hollowVolume = 0;
605 break;
606 }
607 volume *= (1.0f - hollowVolume);
608 }
609 }
610 break;
611
612 case ProfileShape.HalfCircle:
613 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
614 {
615 volume *= 0.52359877559829887307710723054658f;
616 }
617 break;
618
619 case ProfileShape.EquilateralTriangle:
620
621 if (_pbs.PathCurve == (byte)Extrusion.Straight)
622 {
623 volume *= 0.32475953f;
624
625 if (hollowAmount > 0.0)
626 {
627
628 // calculate the hollow volume by it's shape compared to the prim shape
629 switch (_pbs.HollowShape)
630 {
631 case HollowShape.Same:
632 case HollowShape.Triangle:
633 hollowVolume *= .25f;
634 break;
635
636 case HollowShape.Square:
637 hollowVolume *= 0.499849f * 3.07920140172638f;
638 break;
639
640 case HollowShape.Circle:
641 // Hollow shape is a perfect cyllinder in respect to the cube's scale
642 // Cyllinder hollow volume calculation
643
644 hollowVolume *= 0.1963495f * 3.07920140172638f;
645 break;
646
647 default:
648 hollowVolume = 0;
649 break;
650 }
651 volume *= (1.0f - hollowVolume);
652 }
653 }
654 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
655 {
656 volume *= 0.32475953f;
657 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
658 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
659 volume *= (1.0f - tmp * tmp);
660
661 if (hollowAmount > 0.0)
662 {
663
664 hollowVolume *= hollowAmount;
665
666 switch (_pbs.HollowShape)
667 {
668 case HollowShape.Same:
669 case HollowShape.Triangle:
670 hollowVolume *= .25f;
671 break;
672
673 case HollowShape.Square:
674 hollowVolume *= 0.499849f * 3.07920140172638f;
675 break;
676
677 case HollowShape.Circle:
678
679 hollowVolume *= 0.1963495f * 3.07920140172638f;
680 break;
681
682 default:
683 hollowVolume = 0;
684 break;
685 }
686 volume *= (1.0f - hollowVolume);
687 }
688 }
689 break;
690
691 default:
692 break;
693 }
694
695 float taperX1;
696 float taperY1;
697 float taperX;
698 float taperY;
699 float pathBegin;
700 float pathEnd;
701 float profileBegin;
702 float profileEnd;
703
704 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
705 {
706 taperX1 = _pbs.PathScaleX * 0.01f;
707 if (taperX1 > 1.0f)
708 taperX1 = 2.0f - taperX1;
709 taperX = 1.0f - taperX1;
710
711 taperY1 = _pbs.PathScaleY * 0.01f;
712 if (taperY1 > 1.0f)
713 taperY1 = 2.0f - taperY1;
714 taperY = 1.0f - taperY1;
715 }
716 else
717 {
718 taperX = _pbs.PathTaperX * 0.01f;
719 if (taperX < 0.0f)
720 taperX = -taperX;
721 taperX1 = 1.0f - taperX;
722
723 taperY = _pbs.PathTaperY * 0.01f;
724 if (taperY < 0.0f)
725 taperY = -taperY;
726 taperY1 = 1.0f - taperY;
727 }
728
729 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
730
731 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
732 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
733 volume *= (pathEnd - pathBegin);
734
735// this is crude aproximation
736 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
737 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
738 volume *= (profileEnd - profileBegin);
739
740 returnMass = m_density * volume;
741
742 if (returnMass <= 0)
743 returnMass = 0.0001f;//ckrinke: Mass must be greater then zero.
744// else if (returnMass > _parent_scene.maximumMassObject)
745// returnMass = _parent_scene.maximumMassObject;
746
747 // Recursively calculate mass
748 bool HasChildPrim = false;
749 lock (childrenPrim)
750 {
751 if (childrenPrim.Count > 0)
752 {
753 HasChildPrim = true;
754 }
755 }
756
757 if (HasChildPrim)
758 {
759 OdePrim[] childPrimArr = new OdePrim[0];
760
761 lock (childrenPrim)
762 childPrimArr = childrenPrim.ToArray();
763
764 for (int i = 0; i < childPrimArr.Length; i++)
765 {
766 if (childPrimArr[i] != null && !childPrimArr[i].m_taintremove)
767 returnMass += childPrimArr[i].CalculateMass();
768 // failsafe, this shouldn't happen but with OpenSim, you never know :)
769 if (i > 256)
770 break;
771 }
772 }
773
774 if (returnMass > _parent_scene.maximumMassObject)
775 returnMass = _parent_scene.maximumMassObject;
776
777 return returnMass;
778 }
779
780 #endregion
781
782 private void setMass()
783 {
784 if (Body != (IntPtr) 0)
785 {
786 float newmass = CalculateMass();
787
788 //m_log.Info("[PHYSICS]: New Mass: " + newmass.ToString());
789
790 d.MassSetBoxTotal(out pMass, newmass, _size.X, _size.Y, _size.Z);
791 d.BodySetMass(Body, ref pMass);
792 }
793 }
794
795 private void setAngularVelocity(float x, float y, float z)
796 {
797 if (Body != (IntPtr)0)
798 {
799 d.BodySetAngularVel(Body, x, y, z);
800 }
801 }
802
803 /// <summary>
804 /// Stop a prim from being subject to physics.
805 /// </summary>
806 internal void disableBody()
807 {
808 //this kills the body so things like 'mesh' can re-create it.
809 lock (this)
810 {
811 if (!childPrim)
812 {
813 if (Body != IntPtr.Zero)
814 {
815 _parent_scene.DeactivatePrim(this);
816 m_collisionCategories &= ~CollisionCategories.Body;
817 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
818
819 if (m_assetFailed)
820 {
821 d.GeomSetCategoryBits(prim_geom, 0);
822 d.GeomSetCollideBits(prim_geom, 0);
823 }
824 else
825 {
826 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
827 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
828 }
829
830 d.BodyDestroy(Body);
831 lock (childrenPrim)
832 {
833 if (childrenPrim.Count > 0)
834 {
835 foreach (OdePrim prm in childrenPrim)
836 {
837 _parent_scene.DeactivatePrim(prm);
838 prm.Body = IntPtr.Zero;
839 }
840 }
841 }
842 Body = IntPtr.Zero;
843 }
844 }
845 else
846 {
847 _parent_scene.DeactivatePrim(this);
848
849 m_collisionCategories &= ~CollisionCategories.Body;
850 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
851
852 if (m_assetFailed)
853 {
854 d.GeomSetCategoryBits(prim_geom, 0);
855 d.GeomSetCollideBits(prim_geom, 0);
856 }
857 else
858 {
859
860 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
861 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
862 }
863
864 Body = IntPtr.Zero;
865 }
866 }
867
868 m_disabled = true;
869 m_collisionscore = 0;
870 }
871
872 private static Dictionary<IMesh, IntPtr> m_MeshToTriMeshMap = new Dictionary<IMesh, IntPtr>();
873
874 private void setMesh(OdeScene parent_scene, IMesh mesh)
875 {
876// m_log.DebugFormat("[ODE PRIM]: Setting mesh on {0} to {1}", Name, mesh);
877
878 // This sleeper is there to moderate how long it takes between
879 // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
880
881 //Thread.Sleep(10);
882
883 //Kill Body so that mesh can re-make the geom
884 if (IsPhysical && Body != IntPtr.Zero)
885 {
886 if (childPrim)
887 {
888 if (_parent != null)
889 {
890 OdePrim parent = (OdePrim)_parent;
891 parent.ChildDelink(this);
892 }
893 }
894 else
895 {
896 disableBody();
897 }
898 }
899
900 IntPtr vertices, indices;
901 int vertexCount, indexCount;
902 int vertexStride, triStride;
903 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
904 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
905 m_expectedCollisionContacts = indexCount;
906 mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
907
908 // We must lock here since m_MeshToTriMeshMap is static and multiple scene threads may call this method at
909 // the same time.
910 lock (m_MeshToTriMeshMap)
911 {
912 if (m_MeshToTriMeshMap.ContainsKey(mesh))
913 {
914 _triMeshData = m_MeshToTriMeshMap[mesh];
915 }
916 else
917 {
918 _triMeshData = d.GeomTriMeshDataCreate();
919
920 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
921 d.GeomTriMeshDataPreprocess(_triMeshData);
922 m_MeshToTriMeshMap[mesh] = _triMeshData;
923 }
924 }
925
926// _parent_scene.waitForSpaceUnlock(m_targetSpace);
927 try
928 {
929 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null));
930 }
931 catch (AccessViolationException)
932 {
933 m_log.ErrorFormat("[PHYSICS]: MESH LOCKED FOR {0}", Name);
934 return;
935 }
936
937 // if (IsPhysical && Body == (IntPtr) 0)
938 // {
939 // Recreate the body
940 // m_interpenetrationcount = 0;
941 // m_collisionscore = 0;
942
943 // enableBody();
944 // }
945 }
946
947 internal void ProcessTaints()
948 {
949#if SPAM
950Console.WriteLine("ZProcessTaints for " + Name);
951#endif
952
953 // This must be processed as the very first taint so that later operations have a prim_geom to work with
954 // if this is a new prim.
955 if (m_taintadd)
956 changeadd();
957
958 if (!_position.ApproxEquals(m_taintposition, 0f))
959 changemove();
960
961 if (m_taintrot != _orientation)
962 {
963 if (childPrim && IsPhysical) // For physical child prim...
964 {
965 rotate();
966 // KF: ODE will also rotate the parent prim!
967 // so rotate the root back to where it was
968 OdePrim parent = (OdePrim)_parent;
969 parent.rotate();
970 }
971 else
972 {
973 //Just rotate the prim
974 rotate();
975 }
976 }
977
978 if (m_taintPhysics != IsPhysical && !(m_taintparent != _parent))
979 changePhysicsStatus();
980
981 if (!_size.ApproxEquals(m_taintsize, 0f))
982 changesize();
983
984 if (m_taintshape)
985 changeshape();
986
987 if (m_taintforce)
988 changeAddForce();
989
990 if (m_taintaddangularforce)
991 changeAddAngularForce();
992
993 if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f))
994 changeSetTorque();
995
996 if (m_taintdisable)
997 changedisable();
998
999 if (m_taintselected != m_isSelected)
1000 changeSelectedStatus();
1001
1002 if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f))
1003 changevelocity();
1004
1005 if (m_taintparent != _parent)
1006 changelink();
1007
1008 if (m_taintCollidesWater != m_collidesWater)
1009 changefloatonwater();
1010
1011 if (m_taintAngularLock != m_angularlock)
1012 changeAngularLock();
1013 }
1014
1015 /// <summary>
1016 /// Change prim in response to an angular lock taint.
1017 /// </summary>
1018 private void changeAngularLock()
1019 {
1020 // do we have a Physical object?
1021 if (Body != IntPtr.Zero)
1022 {
1023 //Check that we have a Parent
1024 //If we have a parent then we're not authorative here
1025 if (_parent == null)
1026 {
1027 if (m_taintAngularLock != 0)
1028 {
1029 createAMotor(m_taintAngularLock);
1030 }
1031 else
1032 {
1033 if (Amotor != IntPtr.Zero)
1034 {
1035 d.JointDestroy(Amotor);
1036 Amotor = IntPtr.Zero;
1037 }
1038 }
1039 }
1040 }
1041
1042 m_angularlock = m_taintAngularLock;
1043 }
1044
1045 /// <summary>
1046 /// Change prim in response to a link taint.
1047 /// </summary>
1048 private void changelink()
1049 {
1050 // If the newly set parent is not null
1051 // create link
1052 if (_parent == null && m_taintparent != null)
1053 {
1054 if (m_taintparent.PhysicsActorType == (int)ActorTypes.Prim)
1055 {
1056 OdePrim obj = (OdePrim)m_taintparent;
1057 //obj.disableBody();
1058//Console.WriteLine("changelink calls ParentPrim");
1059 obj.AddChildPrim(this);
1060
1061 /*
1062 if (obj.Body != (IntPtr)0 && Body != (IntPtr)0 && obj.Body != Body)
1063 {
1064 _linkJointGroup = d.JointGroupCreate(0);
1065 m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
1066 d.JointAttach(m_linkJoint, obj.Body, Body);
1067 d.JointSetFixed(m_linkJoint);
1068 }
1069 */
1070 }
1071 }
1072 // If the newly set parent is null
1073 // destroy link
1074 else if (_parent != null && m_taintparent == null)
1075 {
1076//Console.WriteLine(" changelink B");
1077
1078 if (_parent is OdePrim)
1079 {
1080 OdePrim obj = (OdePrim)_parent;
1081 obj.ChildDelink(this);
1082 childPrim = false;
1083 //_parent = null;
1084 }
1085
1086 /*
1087 if (Body != (IntPtr)0 && _linkJointGroup != (IntPtr)0)
1088 d.JointGroupDestroy(_linkJointGroup);
1089
1090 _linkJointGroup = (IntPtr)0;
1091 m_linkJoint = (IntPtr)0;
1092 */
1093 }
1094
1095 _parent = m_taintparent;
1096 m_taintPhysics = IsPhysical;
1097 }
1098
1099 /// <summary>
1100 /// Add a child prim to this parent prim.
1101 /// </summary>
1102 /// <param name="prim">Child prim</param>
1103 private void AddChildPrim(OdePrim prim)
1104 {
1105 if (LocalID == prim.LocalID)
1106 return;
1107
1108 if (Body == IntPtr.Zero)
1109 {
1110 Body = d.BodyCreate(_parent_scene.world);
1111 setMass();
1112 }
1113
1114 lock (childrenPrim)
1115 {
1116 if (childrenPrim.Contains(prim))
1117 return;
1118
1119// m_log.DebugFormat(
1120// "[ODE PRIM]: Linking prim {0} {1} to {2} {3}", prim.Name, prim.LocalID, Name, LocalID);
1121
1122 childrenPrim.Add(prim);
1123
1124 foreach (OdePrim prm in childrenPrim)
1125 {
1126 d.Mass m2;
1127 d.MassSetZero(out m2);
1128 d.MassSetBoxTotal(out m2, prm.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z);
1129
1130 d.Quaternion quat = new d.Quaternion();
1131 quat.W = prm._orientation.W;
1132 quat.X = prm._orientation.X;
1133 quat.Y = prm._orientation.Y;
1134 quat.Z = prm._orientation.Z;
1135
1136 d.Matrix3 mat = new d.Matrix3();
1137 d.RfromQ(out mat, ref quat);
1138 d.MassRotate(ref m2, ref mat);
1139 d.MassTranslate(ref m2, Position.X - prm.Position.X, Position.Y - prm.Position.Y, Position.Z - prm.Position.Z);
1140 d.MassAdd(ref pMass, ref m2);
1141 }
1142
1143 foreach (OdePrim prm in childrenPrim)
1144 {
1145 prm.m_collisionCategories |= CollisionCategories.Body;
1146 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1147
1148//Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + Name);
1149 if (prm.m_assetFailed)
1150 {
1151 d.GeomSetCategoryBits(prm.prim_geom, 0);
1152 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.BadMeshAssetCollideBits);
1153 }
1154 else
1155 {
1156 d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
1157 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
1158 }
1159
1160 d.Quaternion quat = new d.Quaternion();
1161 quat.W = prm._orientation.W;
1162 quat.X = prm._orientation.X;
1163 quat.Y = prm._orientation.Y;
1164 quat.Z = prm._orientation.Z;
1165
1166 d.Matrix3 mat = new d.Matrix3();
1167 d.RfromQ(out mat, ref quat);
1168 if (Body != IntPtr.Zero)
1169 {
1170 d.GeomSetBody(prm.prim_geom, Body);
1171 prm.childPrim = true;
1172 d.GeomSetOffsetWorldPosition(prm.prim_geom, prm.Position.X , prm.Position.Y, prm.Position.Z);
1173 //d.GeomSetOffsetPosition(prim.prim_geom,
1174 // (Position.X - prm.Position.X) - pMass.c.X,
1175 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1176 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1177 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat);
1178 //d.GeomSetOffsetRotation(prm.prim_geom, ref mat);
1179 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1180 d.BodySetMass(Body, ref pMass);
1181 }
1182 else
1183 {
1184 m_log.DebugFormat("[PHYSICS]: {0} ain't got no boooooooooddy, no body", Name);
1185 }
1186
1187 prm.m_interpenetrationcount = 0;
1188 prm.m_collisionscore = 0;
1189 prm.m_disabled = false;
1190
1191 prm.Body = Body;
1192 _parent_scene.ActivatePrim(prm);
1193 }
1194
1195 m_collisionCategories |= CollisionCategories.Body;
1196 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1197
1198 if (m_assetFailed)
1199 {
1200 d.GeomSetCategoryBits(prim_geom, 0);
1201 d.GeomSetCollideBits(prim_geom, (uint)BadMeshAssetCollideBits);
1202 }
1203 else
1204 {
1205 //Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name);
1206 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1207 //Console.WriteLine(" Post GeomSetCategoryBits 2");
1208 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1209 }
1210
1211 d.Quaternion quat2 = new d.Quaternion();
1212 quat2.W = _orientation.W;
1213 quat2.X = _orientation.X;
1214 quat2.Y = _orientation.Y;
1215 quat2.Z = _orientation.Z;
1216
1217 d.Matrix3 mat2 = new d.Matrix3();
1218 d.RfromQ(out mat2, ref quat2);
1219 d.GeomSetBody(prim_geom, Body);
1220 d.GeomSetOffsetWorldPosition(prim_geom, Position.X - pMass.c.X, Position.Y - pMass.c.Y, Position.Z - pMass.c.Z);
1221 //d.GeomSetOffsetPosition(prim.prim_geom,
1222 // (Position.X - prm.Position.X) - pMass.c.X,
1223 // (Position.Y - prm.Position.Y) - pMass.c.Y,
1224 // (Position.Z - prm.Position.Z) - pMass.c.Z);
1225 //d.GeomSetOffsetRotation(prim_geom, ref mat2);
1226 d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1227 d.BodySetMass(Body, ref pMass);
1228
1229 d.BodySetAutoDisableFlag(Body, true);
1230 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1231
1232 m_interpenetrationcount = 0;
1233 m_collisionscore = 0;
1234 m_disabled = false;
1235
1236 // The body doesn't already have a finite rotation mode set here
1237 // or remove
1238 if (_parent == null)
1239 {
1240 createAMotor(m_angularlock);
1241 }
1242
1243 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z);
1244
1245 if (m_vehicle.Type != Vehicle.TYPE_NONE)
1246 m_vehicle.Enable(Body, _parent_scene);
1247
1248 _parent_scene.ActivatePrim(this);
1249 }
1250 }
1251
1252 private void ChildSetGeom(OdePrim odePrim)
1253 {
1254// m_log.DebugFormat(
1255// "[ODE PRIM]: ChildSetGeom {0} {1} for {2} {3}", odePrim.Name, odePrim.LocalID, Name, LocalID);
1256
1257 //if (IsPhysical && Body != IntPtr.Zero)
1258 lock (childrenPrim)
1259 {
1260 foreach (OdePrim prm in childrenPrim)
1261 {
1262 //prm.childPrim = true;
1263 prm.disableBody();
1264 //prm.m_taintparent = null;
1265 //prm._parent = null;
1266 //prm.m_taintPhysics = false;
1267 //prm.m_disabled = true;
1268 //prm.childPrim = false;
1269 }
1270 }
1271
1272 disableBody();
1273
1274 // Spurious - Body == IntPtr.Zero after disableBody()
1275// if (Body != IntPtr.Zero)
1276// {
1277// _parent_scene.DeactivatePrim(this);
1278// }
1279
1280 lock (childrenPrim)
1281 {
1282 foreach (OdePrim prm in childrenPrim)
1283 {
1284//Console.WriteLine("ChildSetGeom calls ParentPrim");
1285 AddChildPrim(prm);
1286 }
1287 }
1288 }
1289
1290 private void ChildDelink(OdePrim odePrim)
1291 {
1292// m_log.DebugFormat(
1293// "[ODE PRIM]: Delinking prim {0} {1} from {2} {3}", odePrim.Name, odePrim.LocalID, Name, LocalID);
1294
1295 // Okay, we have a delinked child.. need to rebuild the body.
1296 lock (childrenPrim)
1297 {
1298 foreach (OdePrim prm in childrenPrim)
1299 {
1300 prm.childPrim = true;
1301 prm.disableBody();
1302 //prm.m_taintparent = null;
1303 //prm._parent = null;
1304 //prm.m_taintPhysics = false;
1305 //prm.m_disabled = true;
1306 //prm.childPrim = false;
1307 }
1308 }
1309
1310 disableBody();
1311
1312 lock (childrenPrim)
1313 {
1314 //Console.WriteLine("childrenPrim.Remove " + odePrim);
1315 childrenPrim.Remove(odePrim);
1316 }
1317
1318 // Spurious - Body == IntPtr.Zero after disableBody()
1319// if (Body != IntPtr.Zero)
1320// {
1321// _parent_scene.DeactivatePrim(this);
1322// }
1323
1324 lock (childrenPrim)
1325 {
1326 foreach (OdePrim prm in childrenPrim)
1327 {
1328//Console.WriteLine("ChildDelink calls ParentPrim");
1329 AddChildPrim(prm);
1330 }
1331 }
1332 }
1333
1334 /// <summary>
1335 /// Change prim in response to a selection taint.
1336 /// </summary>
1337 private void changeSelectedStatus()
1338 {
1339 if (m_taintselected)
1340 {
1341 m_collisionCategories = CollisionCategories.Selected;
1342 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
1343
1344 // We do the body disable soft twice because 'in theory' a collision could have happened
1345 // in between the disabling and the collision properties setting
1346 // which would wake the physical body up from a soft disabling and potentially cause it to fall
1347 // through the ground.
1348
1349 // NOTE FOR JOINTS: this doesn't always work for jointed assemblies because if you select
1350 // just one part of the assembly, the rest of the assembly is non-selected and still simulating,
1351 // so that causes the selected part to wake up and continue moving.
1352
1353 // even if you select all parts of a jointed assembly, it is not guaranteed that the entire
1354 // assembly will stop simulating during the selection, because of the lack of atomicity
1355 // of select operations (their processing could be interrupted by a thread switch, causing
1356 // simulation to continue before all of the selected object notifications trickle down to
1357 // the physics engine).
1358
1359 // e.g. we select 100 prims that are connected by joints. non-atomically, the first 50 are
1360 // selected and disabled. then, due to a thread switch, the selection processing is
1361 // interrupted and the physics engine continues to simulate, so the last 50 items, whose
1362 // selection was not yet processed, continues to simulate. this wakes up ALL of the
1363 // first 50 again. then the last 50 are disabled. then the first 50, which were just woken
1364 // up, start simulating again, which in turn wakes up the last 50.
1365
1366 if (IsPhysical)
1367 {
1368 disableBodySoft();
1369 }
1370
1371 if (m_assetFailed)
1372 {
1373 d.GeomSetCategoryBits(prim_geom, 0);
1374 d.GeomSetCollideBits(prim_geom, 0);
1375 }
1376 else
1377 {
1378 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1379 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1380 }
1381
1382 if (IsPhysical)
1383 {
1384 disableBodySoft();
1385 }
1386 }
1387 else
1388 {
1389 m_collisionCategories = CollisionCategories.Geom;
1390
1391 if (IsPhysical)
1392 m_collisionCategories |= CollisionCategories.Body;
1393
1394 m_collisionFlags = m_default_collisionFlags;
1395
1396 if (m_collidesLand)
1397 m_collisionFlags |= CollisionCategories.Land;
1398 if (m_collidesWater)
1399 m_collisionFlags |= CollisionCategories.Water;
1400
1401 if (m_assetFailed)
1402 {
1403 d.GeomSetCategoryBits(prim_geom, 0);
1404 d.GeomSetCollideBits(prim_geom, (uint)BadMeshAssetCollideBits);
1405 }
1406 else
1407 {
1408 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1409 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1410 }
1411
1412 if (IsPhysical)
1413 {
1414 if (Body != IntPtr.Zero)
1415 {
1416 d.BodySetLinearVel(Body, 0f, 0f, 0f);
1417 d.BodySetForce(Body, 0, 0, 0);
1418 enableBodySoft();
1419 }
1420 }
1421 }
1422
1423 resetCollisionAccounting();
1424 m_isSelected = m_taintselected;
1425 }//end changeSelectedStatus
1426
1427 internal void ResetTaints()
1428 {
1429 m_taintposition = _position;
1430 m_taintrot = _orientation;
1431 m_taintPhysics = IsPhysical;
1432 m_taintselected = m_isSelected;
1433 m_taintsize = _size;
1434 m_taintshape = false;
1435 m_taintforce = false;
1436 m_taintdisable = false;
1437 m_taintVelocity = Vector3.Zero;
1438 }
1439
1440 /// <summary>
1441 /// Create a geometry for the given mesh in the given target space.
1442 /// </summary>
1443 /// <param name="m_targetSpace"></param>
1444 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param>
1445 private void CreateGeom(IntPtr m_targetSpace, IMesh mesh)
1446 {
1447#if SPAM
1448Console.WriteLine("CreateGeom:");
1449#endif
1450 if (mesh != null)
1451 {
1452 setMesh(_parent_scene, mesh);
1453 }
1454 else
1455 {
1456 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
1457 {
1458 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
1459 {
1460 if (((_size.X / 2f) > 0f))
1461 {
1462// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1463 try
1464 {
1465//Console.WriteLine(" CreateGeom 1");
1466 SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
1467 m_expectedCollisionContacts = 3;
1468 }
1469 catch (AccessViolationException)
1470 {
1471 m_log.WarnFormat("[PHYSICS]: Unable to create physics proxy for object {0}", Name);
1472 return;
1473 }
1474 }
1475 else
1476 {
1477// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1478 try
1479 {
1480//Console.WriteLine(" CreateGeom 2");
1481 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1482 m_expectedCollisionContacts = 4;
1483 }
1484 catch (AccessViolationException)
1485 {
1486 m_log.WarnFormat("[PHYSICS]: Unable to create physics proxy for object {0}", Name);
1487 return;
1488 }
1489 }
1490 }
1491 else
1492 {
1493// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1494 try
1495 {
1496//Console.WriteLine(" CreateGeom 3");
1497 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1498 m_expectedCollisionContacts = 4;
1499 }
1500 catch (AccessViolationException)
1501 {
1502 m_log.WarnFormat("[PHYSICS]: Unable to create physics proxy for object {0}", Name);
1503 return;
1504 }
1505 }
1506 }
1507 else
1508 {
1509// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1510 try
1511 {
1512//Console.WriteLine(" CreateGeom 4");
1513 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1514 m_expectedCollisionContacts = 4;
1515 }
1516 catch (AccessViolationException)
1517 {
1518 m_log.WarnFormat("[PHYSICS]: Unable to create physics proxy for object {0}", Name);
1519 return;
1520 }
1521 }
1522 }
1523 }
1524
1525 /// <summary>
1526 /// Remove the existing geom from this prim.
1527 /// </summary>
1528 /// <param name="m_targetSpace"></param>
1529 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param>
1530 /// <returns>true if the geom was successfully removed, false if it was already gone or the remove failed.</returns>
1531 internal bool RemoveGeom()
1532 {
1533 if (prim_geom != IntPtr.Zero)
1534 {
1535 try
1536 {
1537 _parent_scene.geom_name_map.Remove(prim_geom);
1538 _parent_scene.actor_name_map.Remove(prim_geom);
1539 d.GeomDestroy(prim_geom);
1540 m_expectedCollisionContacts = 0;
1541 prim_geom = IntPtr.Zero;
1542 }
1543 catch (System.AccessViolationException)
1544 {
1545 prim_geom = IntPtr.Zero;
1546 m_expectedCollisionContacts = 0;
1547 m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name);
1548
1549 return false;
1550 }
1551
1552 return true;
1553 }
1554 else
1555 {
1556 m_log.WarnFormat(
1557 "[ODE PRIM]: Called RemoveGeom() on {0} {1} where geometry was already null.", Name, LocalID);
1558
1559 return false;
1560 }
1561 }
1562 /// <summary>
1563 /// Add prim in response to an add taint.
1564 /// </summary>
1565 private void changeadd()
1566 {
1567// m_log.DebugFormat("[ODE PRIM]: Adding prim {0}", Name);
1568
1569 int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1570 IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position);
1571
1572 if (targetspace == IntPtr.Zero)
1573 targetspace = _parent_scene.createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
1574
1575 m_targetSpace = targetspace;
1576
1577 IMesh mesh = null;
1578
1579 if (_parent_scene.needsMeshing(_pbs))
1580 {
1581 // Don't need to re-enable body.. it's done in SetMesh
1582 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
1583 // createmesh returns null when it's a shape that isn't a cube.
1584 // m_log.Debug(m_localID);
1585 if (mesh == null)
1586 CheckMeshAsset();
1587 else
1588 m_assetFailed = false;
1589 }
1590
1591#if SPAM
1592Console.WriteLine("changeadd 1");
1593#endif
1594 CreateGeom(m_targetSpace, mesh);
1595
1596 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1597 d.Quaternion myrot = new d.Quaternion();
1598 myrot.X = _orientation.X;
1599 myrot.Y = _orientation.Y;
1600 myrot.Z = _orientation.Z;
1601 myrot.W = _orientation.W;
1602 d.GeomSetQuaternion(prim_geom, ref myrot);
1603
1604 if (IsPhysical && Body == IntPtr.Zero)
1605 enableBody();
1606
1607 changeSelectedStatus();
1608
1609 m_taintadd = false;
1610 }
1611
1612 /// <summary>
1613 /// Move prim in response to a move taint.
1614 /// </summary>
1615 private void changemove()
1616 {
1617 if (IsPhysical)
1618 {
1619 if (!m_disabled && !m_taintremove && !childPrim)
1620 {
1621 if (Body == IntPtr.Zero)
1622 enableBody();
1623
1624 //Prim auto disable after 20 frames,
1625 //if you move it, re-enable the prim manually.
1626 if (_parent != null)
1627 {
1628 if (m_linkJoint != IntPtr.Zero)
1629 {
1630 d.JointDestroy(m_linkJoint);
1631 m_linkJoint = IntPtr.Zero;
1632 }
1633 }
1634
1635 if (Body != IntPtr.Zero)
1636 {
1637 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
1638
1639 if (_parent != null)
1640 {
1641 OdePrim odParent = (OdePrim)_parent;
1642 if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0 && Body != odParent.Body)
1643 {
1644// KF: Fixed Joints were removed? Anyway - this Console.WriteLine does not show up, so routine is not used??
1645Console.WriteLine(" JointCreateFixed");
1646 m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
1647 d.JointAttach(m_linkJoint, Body, odParent.Body);
1648 d.JointSetFixed(m_linkJoint);
1649 }
1650 }
1651 d.BodyEnable(Body);
1652 if (m_vehicle.Type != Vehicle.TYPE_NONE)
1653 {
1654 m_vehicle.Enable(Body, _parent_scene);
1655 }
1656 }
1657 else
1658 {
1659 m_log.WarnFormat("[PHYSICS]: Body for {0} still null after enableBody(). This is a crash scenario.", Name);
1660 }
1661 }
1662 //else
1663 // {
1664 //m_log.Debug("[BUG]: race!");
1665 //}
1666 }
1667
1668 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1669 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1670// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1671
1672 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
1673 m_targetSpace = tempspace;
1674
1675// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1676
1677 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1678
1679// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1680 d.SpaceAdd(m_targetSpace, prim_geom);
1681
1682 changeSelectedStatus();
1683
1684 resetCollisionAccounting();
1685 m_taintposition = _position;
1686 }
1687
1688 internal void Move(float timestep)
1689 {
1690 float fx = 0;
1691 float fy = 0;
1692 float fz = 0;
1693
1694 if (outofBounds)
1695 return;
1696
1697 if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims.
1698 {
1699 if (m_vehicle.Type != Vehicle.TYPE_NONE)
1700 {
1701 // 'VEHICLES' are dealt with in ODEDynamics.cs
1702 m_vehicle.Step(timestep, _parent_scene);
1703 }
1704 else
1705 {
1706//Console.WriteLine("Move " + Name);
1707 if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009
1708
1709 float m_mass = CalculateMass();
1710
1711// fz = 0f;
1712 //m_log.Info(m_collisionFlags.ToString());
1713
1714
1715 //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
1716 // would come from SceneObjectPart.cs, public void SetBuoyancy(float fvalue) , PhysActor.Buoyancy = fvalue; ??
1717 // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up
1718 // gravityz multiplier = 1 - m_buoyancy
1719 fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass;
1720
1721 if (PIDActive)
1722 {
1723//Console.WriteLine("PID " + Name);
1724 // KF - this is for object move? eg. llSetPos() ?
1725 //if (!d.BodyIsEnabled(Body))
1726 //d.BodySetForce(Body, 0f, 0f, 0f);
1727 // If we're using the PID controller, then we have no gravity
1728 //fz = (-1 * _parent_scene.gravityz) * m_mass; //KF: ?? Prims have no global gravity,so simply...
1729 fz = 0f;
1730
1731 // no lock; for now it's only called from within Simulate()
1732
1733 // If the PID Controller isn't active then we set our force
1734 // calculating base velocity to the current position
1735
1736 if ((m_PIDTau < 1) && (m_PIDTau != 0))
1737 {
1738 //PID_G = PID_G / m_PIDTau;
1739 m_PIDTau = 1;
1740 }
1741
1742 if ((PID_G - m_PIDTau) <= 0)
1743 {
1744 PID_G = m_PIDTau + 1;
1745 }
1746 //PidStatus = true;
1747
1748 // PhysicsVector vec = new PhysicsVector();
1749 d.Vector3 vel = d.BodyGetLinearVel(Body);
1750
1751 d.Vector3 pos = d.BodyGetPosition(Body);
1752 _target_velocity =
1753 new Vector3(
1754 (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep),
1755 (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep),
1756 (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep)
1757 );
1758
1759 // if velocity is zero, use position control; otherwise, velocity control
1760
1761 if (_target_velocity.ApproxEquals(Vector3.Zero,0.1f))
1762 {
1763 // keep track of where we stopped. No more slippin' & slidin'
1764
1765 // We only want to deactivate the PID Controller if we think we want to have our surrogate
1766 // react to the physics scene by moving it's position.
1767 // Avatar to Avatar collisions
1768 // Prim to avatar collisions
1769
1770 //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
1771 //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2);
1772 //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
1773 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
1774 d.BodySetLinearVel(Body, 0, 0, 0);
1775 d.BodyAddForce(Body, 0, 0, fz);
1776 return;
1777 }
1778 else
1779 {
1780 _zeroFlag = false;
1781
1782 // We're flying and colliding with something
1783 fx = ((_target_velocity.X) - vel.X) * (PID_D);
1784 fy = ((_target_velocity.Y) - vel.Y) * (PID_D);
1785
1786 // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
1787
1788 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1789 }
1790 } // end if (PIDActive)
1791
1792 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
1793 if (m_useHoverPID && !PIDActive)
1794 {
1795//Console.WriteLine("Hover " + Name);
1796
1797 // If we're using the PID controller, then we have no gravity
1798 fz = (-1 * _parent_scene.gravityz) * m_mass;
1799
1800 // no lock; for now it's only called from within Simulate()
1801
1802 // If the PID Controller isn't active then we set our force
1803 // calculating base velocity to the current position
1804
1805 if ((m_PIDTau < 1))
1806 {
1807 PID_G = PID_G / m_PIDTau;
1808 }
1809
1810 if ((PID_G - m_PIDTau) <= 0)
1811 {
1812 PID_G = m_PIDTau + 1;
1813 }
1814
1815 // Where are we, and where are we headed?
1816 d.Vector3 pos = d.BodyGetPosition(Body);
1817 d.Vector3 vel = d.BodyGetLinearVel(Body);
1818
1819 // Non-Vehicles have a limited set of Hover options.
1820 // determine what our target height really is based on HoverType
1821 switch (m_PIDHoverType)
1822 {
1823 case PIDHoverType.Ground:
1824 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1825 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1826 break;
1827 case PIDHoverType.GroundAndWater:
1828 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1829 m_waterHeight = _parent_scene.GetWaterLevel();
1830 if (m_groundHeight > m_waterHeight)
1831 {
1832 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1833 }
1834 else
1835 {
1836 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
1837 }
1838 break;
1839
1840 } // end switch (m_PIDHoverType)
1841
1842
1843 _target_velocity =
1844 new Vector3(0.0f, 0.0f,
1845 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
1846 );
1847
1848 // if velocity is zero, use position control; otherwise, velocity control
1849
1850 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
1851 {
1852 // keep track of where we stopped. No more slippin' & slidin'
1853
1854 // We only want to deactivate the PID Controller if we think we want to have our surrogate
1855 // react to the physics scene by moving it's position.
1856 // Avatar to Avatar collisions
1857 // Prim to avatar collisions
1858
1859 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
1860 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
1861 d.BodyAddForce(Body, 0, 0, fz);
1862 return;
1863 }
1864 else
1865 {
1866 _zeroFlag = false;
1867
1868 // We're flying and colliding with something
1869 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1870 }
1871 }
1872
1873 fx *= m_mass;
1874 fy *= m_mass;
1875 //fz *= m_mass;
1876
1877 fx += m_force.X;
1878 fy += m_force.Y;
1879 fz += m_force.Z;
1880
1881 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
1882 if (fx != 0 || fy != 0 || fz != 0)
1883 {
1884 //m_taintdisable = true;
1885 //base.RaiseOutOfBounds(Position);
1886 //d.BodySetLinearVel(Body, fx, fy, 0f);
1887 if (!d.BodyIsEnabled(Body))
1888 {
1889 // A physical body at rest on a surface will auto-disable after a while,
1890 // this appears to re-enable it incase the surface it is upon vanishes,
1891 // and the body should fall again.
1892 d.BodySetLinearVel(Body, 0f, 0f, 0f);
1893 d.BodySetForce(Body, 0, 0, 0);
1894 enableBodySoft();
1895 }
1896
1897 // 35x10 = 350n times the mass per second applied maximum.
1898 float nmax = 35f * m_mass;
1899 float nmin = -35f * m_mass;
1900
1901 if (fx > nmax)
1902 fx = nmax;
1903 if (fx < nmin)
1904 fx = nmin;
1905 if (fy > nmax)
1906 fy = nmax;
1907 if (fy < nmin)
1908 fy = nmin;
1909 d.BodyAddForce(Body, fx, fy, fz);
1910//Console.WriteLine("AddForce " + fx + "," + fy + "," + fz);
1911 }
1912 }
1913 }
1914 else
1915 { // is not physical, or is not a body or is selected
1916 // _zeroPosition = d.BodyGetPosition(Body);
1917 return;
1918//Console.WriteLine("Nothing " + Name);
1919
1920 }
1921 }
1922
1923 private void rotate()
1924 {
1925 d.Quaternion myrot = new d.Quaternion();
1926 myrot.X = _orientation.X;
1927 myrot.Y = _orientation.Y;
1928 myrot.Z = _orientation.Z;
1929 myrot.W = _orientation.W;
1930 if (Body != IntPtr.Zero)
1931 {
1932 // KF: If this is a root prim do BodySet
1933 d.BodySetQuaternion(Body, ref myrot);
1934 if (IsPhysical)
1935 {
1936 // create or remove locks
1937 createAMotor(m_angularlock);
1938 }
1939 }
1940 else
1941 {
1942 // daughter prim, do Geom set
1943 d.GeomSetQuaternion(prim_geom, ref myrot);
1944 }
1945
1946 resetCollisionAccounting();
1947 m_taintrot = _orientation;
1948 }
1949
1950 private void resetCollisionAccounting()
1951 {
1952 m_collisionscore = 0;
1953 m_interpenetrationcount = 0;
1954 m_disabled = false;
1955 }
1956
1957 /// <summary>
1958 /// Change prim in response to a disable taint.
1959 /// </summary>
1960 private void changedisable()
1961 {
1962 m_disabled = true;
1963 if (Body != IntPtr.Zero)
1964 {
1965 d.BodyDisable(Body);
1966 Body = IntPtr.Zero;
1967 }
1968
1969 m_taintdisable = false;
1970 }
1971
1972 /// <summary>
1973 /// Change prim in response to a physics status taint
1974 /// </summary>
1975 private void changePhysicsStatus()
1976 {
1977 if (IsPhysical)
1978 {
1979 if (Body == IntPtr.Zero)
1980 {
1981 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
1982 {
1983 changeshape();
1984 }
1985 else
1986 {
1987 enableBody();
1988 }
1989 }
1990 }
1991 else
1992 {
1993 if (Body != IntPtr.Zero)
1994 {
1995 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
1996 {
1997 RemoveGeom();
1998
1999//Console.WriteLine("changePhysicsStatus for " + Name);
2000 changeadd();
2001 }
2002
2003 if (childPrim)
2004 {
2005 if (_parent != null)
2006 {
2007 OdePrim parent = (OdePrim)_parent;
2008 parent.ChildDelink(this);
2009 }
2010 }
2011 else
2012 {
2013 disableBody();
2014 }
2015 }
2016 }
2017
2018 changeSelectedStatus();
2019
2020 resetCollisionAccounting();
2021 m_taintPhysics = IsPhysical;
2022 }
2023
2024 /// <summary>
2025 /// Change prim in response to a size taint.
2026 /// </summary>
2027 private void changesize()
2028 {
2029#if SPAM
2030 m_log.DebugFormat("[ODE PRIM]: Called changesize");
2031#endif
2032
2033 if (_size.X <= 0) _size.X = 0.01f;
2034 if (_size.Y <= 0) _size.Y = 0.01f;
2035 if (_size.Z <= 0) _size.Z = 0.01f;
2036
2037 //kill body to rebuild
2038 if (IsPhysical && Body != IntPtr.Zero)
2039 {
2040 if (childPrim)
2041 {
2042 if (_parent != null)
2043 {
2044 OdePrim parent = (OdePrim)_parent;
2045 parent.ChildDelink(this);
2046 }
2047 }
2048 else
2049 {
2050 disableBody();
2051 }
2052 }
2053
2054 if (d.SpaceQuery(m_targetSpace, prim_geom))
2055 {
2056// _parent_scene.waitForSpaceUnlock(m_targetSpace);
2057 d.SpaceRemove(m_targetSpace, prim_geom);
2058 }
2059
2060 RemoveGeom();
2061
2062 // we don't need to do space calculation because the client sends a position update also.
2063
2064 IMesh mesh = null;
2065
2066 // Construction of new prim
2067 if (_parent_scene.needsMeshing(_pbs))
2068 {
2069 float meshlod = _parent_scene.meshSculptLOD;
2070
2071 if (IsPhysical)
2072 meshlod = _parent_scene.MeshSculptphysicalLOD;
2073 // Don't need to re-enable body.. it's done in SetMesh
2074
2075 if (_parent_scene.needsMeshing(_pbs))
2076 {
2077 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
2078 if (mesh == null)
2079 CheckMeshAsset();
2080 else
2081 m_assetFailed = false;
2082 }
2083
2084 }
2085
2086 CreateGeom(m_targetSpace, mesh);
2087 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2088 d.Quaternion myrot = new d.Quaternion();
2089 myrot.X = _orientation.X;
2090 myrot.Y = _orientation.Y;
2091 myrot.Z = _orientation.Z;
2092 myrot.W = _orientation.W;
2093 d.GeomSetQuaternion(prim_geom, ref myrot);
2094
2095 //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
2096 if (IsPhysical && Body == IntPtr.Zero && !childPrim)
2097 {
2098 // Re creates body on size.
2099 // EnableBody also does setMass()
2100 enableBody();
2101 d.BodyEnable(Body);
2102 }
2103
2104 changeSelectedStatus();
2105
2106 if (childPrim)
2107 {
2108 if (_parent is OdePrim)
2109 {
2110 OdePrim parent = (OdePrim)_parent;
2111 parent.ChildSetGeom(this);
2112 }
2113 }
2114 resetCollisionAccounting();
2115 m_taintsize = _size;
2116 }
2117
2118 /// <summary>
2119 /// Change prim in response to a float on water taint.
2120 /// </summary>
2121 /// <param name="timestep"></param>
2122 private void changefloatonwater()
2123 {
2124 m_collidesWater = m_taintCollidesWater;
2125
2126 if (m_collidesWater)
2127 {
2128 m_collisionFlags |= CollisionCategories.Water;
2129 }
2130 else
2131 {
2132 m_collisionFlags &= ~CollisionCategories.Water;
2133 }
2134
2135 if (m_assetFailed)
2136 d.GeomSetCollideBits(prim_geom, (uint)BadMeshAssetCollideBits);
2137 else
2138
2139 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
2140 }
2141 /// <summary>
2142 /// Change prim in response to a shape taint.
2143 /// </summary>
2144 private void changeshape()
2145 {
2146 m_taintshape = false;
2147
2148 // Cleanup of old prim geometry and Bodies
2149 if (IsPhysical && Body != IntPtr.Zero)
2150 {
2151 if (childPrim)
2152 {
2153 if (_parent != null)
2154 {
2155 OdePrim parent = (OdePrim)_parent;
2156 parent.ChildDelink(this);
2157 }
2158 }
2159 else
2160 {
2161 disableBody();
2162 }
2163 }
2164
2165 RemoveGeom();
2166
2167 // we don't need to do space calculation because the client sends a position update also.
2168 if (_size.X <= 0) _size.X = 0.01f;
2169 if (_size.Y <= 0) _size.Y = 0.01f;
2170 if (_size.Z <= 0) _size.Z = 0.01f;
2171 // Construction of new prim
2172
2173 IMesh mesh = null;
2174
2175
2176 if (_parent_scene.needsMeshing(_pbs))
2177 {
2178 // Don't need to re-enable body.. it's done in CreateMesh
2179 float meshlod = _parent_scene.meshSculptLOD;
2180
2181 if (IsPhysical)
2182 meshlod = _parent_scene.MeshSculptphysicalLOD;
2183
2184 // createmesh returns null when it doesn't mesh.
2185 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
2186 if (mesh == null)
2187 CheckMeshAsset();
2188 else
2189 m_assetFailed = false;
2190 }
2191
2192 CreateGeom(m_targetSpace, mesh);
2193 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2194 d.Quaternion myrot = new d.Quaternion();
2195 //myrot.W = _orientation.w;
2196 myrot.W = _orientation.W;
2197 myrot.X = _orientation.X;
2198 myrot.Y = _orientation.Y;
2199 myrot.Z = _orientation.Z;
2200 d.GeomSetQuaternion(prim_geom, ref myrot);
2201
2202 //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
2203 if (IsPhysical && Body == IntPtr.Zero)
2204 {
2205 // Re creates body on size.
2206 // EnableBody also does setMass()
2207 enableBody();
2208 if (Body != IntPtr.Zero)
2209 {
2210 d.BodyEnable(Body);
2211 }
2212 }
2213
2214 changeSelectedStatus();
2215
2216 if (childPrim)
2217 {
2218 if (_parent is OdePrim)
2219 {
2220 OdePrim parent = (OdePrim)_parent;
2221 parent.ChildSetGeom(this);
2222 }
2223 }
2224
2225 resetCollisionAccounting();
2226// m_taintshape = false;
2227 }
2228
2229 /// <summary>
2230 /// Change prim in response to an add force taint.
2231 /// </summary>
2232 private void changeAddForce()
2233 {
2234 if (!m_isSelected)
2235 {
2236 lock (m_forcelist)
2237 {
2238 //m_log.Info("[PHYSICS]: dequeing forcelist");
2239 if (IsPhysical)
2240 {
2241 Vector3 iforce = Vector3.Zero;
2242 int i = 0;
2243 try
2244 {
2245 for (i = 0; i < m_forcelist.Count; i++)
2246 {
2247
2248 iforce = iforce + (m_forcelist[i] * 100);
2249 }
2250 }
2251 catch (IndexOutOfRangeException)
2252 {
2253 m_forcelist = new List<Vector3>();
2254 m_collisionscore = 0;
2255 m_interpenetrationcount = 0;
2256 m_taintforce = false;
2257 return;
2258 }
2259 catch (ArgumentOutOfRangeException)
2260 {
2261 m_forcelist = new List<Vector3>();
2262 m_collisionscore = 0;
2263 m_interpenetrationcount = 0;
2264 m_taintforce = false;
2265 return;
2266 }
2267 d.BodyEnable(Body);
2268 d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z);
2269 }
2270 m_forcelist.Clear();
2271 }
2272
2273 m_collisionscore = 0;
2274 m_interpenetrationcount = 0;
2275 }
2276
2277 m_taintforce = false;
2278 }
2279
2280 /// <summary>
2281 /// Change prim in response to a torque taint.
2282 /// </summary>
2283 private void changeSetTorque()
2284 {
2285 if (!m_isSelected)
2286 {
2287 if (IsPhysical && Body != IntPtr.Zero)
2288 {
2289 d.BodySetTorque(Body, m_taintTorque.X, m_taintTorque.Y, m_taintTorque.Z);
2290 }
2291 }
2292
2293 m_taintTorque = Vector3.Zero;
2294 }
2295
2296 /// <summary>
2297 /// Change prim in response to an angular force taint.
2298 /// </summary>
2299 private void changeAddAngularForce()
2300 {
2301 if (!m_isSelected)
2302 {
2303 lock (m_angularforcelist)
2304 {
2305 //m_log.Info("[PHYSICS]: dequeing forcelist");
2306 if (IsPhysical)
2307 {
2308 Vector3 iforce = Vector3.Zero;
2309 for (int i = 0; i < m_angularforcelist.Count; i++)
2310 {
2311 iforce = iforce + (m_angularforcelist[i] * 100);
2312 }
2313 d.BodyEnable(Body);
2314 d.BodyAddTorque(Body, iforce.X, iforce.Y, iforce.Z);
2315
2316 }
2317 m_angularforcelist.Clear();
2318 }
2319
2320 m_collisionscore = 0;
2321 m_interpenetrationcount = 0;
2322 }
2323
2324 m_taintaddangularforce = false;
2325 }
2326
2327 /// <summary>
2328 /// Change prim in response to a velocity taint.
2329 /// </summary>
2330 private void changevelocity()
2331 {
2332 if (!m_isSelected)
2333 {
2334 // Not sure exactly why this sleep is here, but from experimentation it appears to stop an avatar
2335 // walking through a default rez size prim if it keeps kicking it around - justincc.
2336 Thread.Sleep(20);
2337
2338 if (IsPhysical)
2339 {
2340 if (Body != IntPtr.Zero)
2341 {
2342 d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z);
2343 }
2344 }
2345
2346 //resetCollisionAccounting();
2347 }
2348
2349 m_taintVelocity = Vector3.Zero;
2350 }
2351
2352 internal void setPrimForRemoval()
2353 {
2354 m_taintremove = true;
2355 }
2356
2357 public override bool Flying
2358 {
2359 // no flying prims for you
2360 get { return false; }
2361 set { }
2362 }
2363
2364 public override bool IsColliding
2365 {
2366 get { return iscolliding; }
2367 set { iscolliding = value; }
2368 }
2369
2370 public override bool CollidingGround
2371 {
2372 get { return false; }
2373 set { return; }
2374 }
2375
2376 public override bool CollidingObj
2377 {
2378 get { return false; }
2379 set { return; }
2380 }
2381
2382 public override bool ThrottleUpdates
2383 {
2384 get { return m_throttleUpdates; }
2385 set { m_throttleUpdates = value; }
2386 }
2387
2388 public override bool Stopped
2389 {
2390 get { return _zeroFlag; }
2391 }
2392
2393 public override Vector3 Position
2394 {
2395 get { return _position; }
2396
2397 set { _position = value;
2398 //m_log.Info("[PHYSICS]: " + _position.ToString());
2399 }
2400 }
2401
2402 public override Vector3 Size
2403 {
2404 get { return _size; }
2405 set
2406 {
2407 if (value.IsFinite())
2408 {
2409 _size = value;
2410// m_log.DebugFormat("[PHYSICS]: Set size on {0} to {1}", Name, value);
2411 }
2412 else
2413 {
2414 m_log.WarnFormat("[PHYSICS]: Got NaN Size on object {0}", Name);
2415 }
2416 }
2417 }
2418
2419 public override float Mass
2420 {
2421 get { return CalculateMass(); }
2422 }
2423
2424 public override Vector3 Force
2425 {
2426 //get { return Vector3.Zero; }
2427 get { return m_force; }
2428 set
2429 {
2430 if (value.IsFinite())
2431 {
2432 m_force = value;
2433 }
2434 else
2435 {
2436 m_log.WarnFormat("[PHYSICS]: NaN in Force Applied to an Object {0}", Name);
2437 }
2438 }
2439 }
2440
2441 public override int VehicleType
2442 {
2443 get { return (int)m_vehicle.Type; }
2444 set { m_vehicle.ProcessTypeChange((Vehicle)value); }
2445 }
2446
2447 public override void VehicleFloatParam(int param, float value)
2448 {
2449 m_vehicle.ProcessFloatVehicleParam((Vehicle) param, value);
2450 }
2451
2452 public override void VehicleVectorParam(int param, Vector3 value)
2453 {
2454 m_vehicle.ProcessVectorVehicleParam((Vehicle) param, value);
2455 }
2456
2457 public override void VehicleRotationParam(int param, Quaternion rotation)
2458 {
2459 m_vehicle.ProcessRotationVehicleParam((Vehicle) param, rotation);
2460 }
2461
2462 public override void VehicleFlags(int param, bool remove)
2463 {
2464 m_vehicle.ProcessVehicleFlags(param, remove);
2465 }
2466
2467 public override void SetVolumeDetect(int param)
2468 {
2469 // We have to lock the scene here so that an entire simulate loop either uses volume detect for all
2470 // possible collisions with this prim or for none of them.
2471 lock (_parent_scene.OdeLock)
2472 {
2473 m_isVolumeDetect = (param != 0);
2474 }
2475 }
2476
2477 public override Vector3 CenterOfMass
2478 {
2479 get { return Vector3.Zero; }
2480 }
2481
2482 public override Vector3 GeometricCenter
2483 {
2484 get { return Vector3.Zero; }
2485 }
2486
2487 public override PrimitiveBaseShape Shape
2488 {
2489 set
2490 {
2491 _pbs = value;
2492 m_assetFailed = false;
2493 m_taintshape = true;
2494 }
2495 }
2496
2497 public override Vector3 Velocity
2498 {
2499 get
2500 {
2501 // Average previous velocity with the new one so
2502 // client object interpolation works a 'little' better
2503 if (_zeroFlag)
2504 return Vector3.Zero;
2505
2506 Vector3 returnVelocity = Vector3.Zero;
2507 returnVelocity.X = (m_lastVelocity.X + _velocity.X) * 0.5f; // 0.5f is mathematically equiv to '/ 2'
2508 returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) * 0.5f;
2509 returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) * 0.5f;
2510 return returnVelocity;
2511 }
2512 set
2513 {
2514 if (value.IsFinite())
2515 {
2516 _velocity = value;
2517
2518 m_taintVelocity = value;
2519 _parent_scene.AddPhysicsActorTaint(this);
2520 }
2521 else
2522 {
2523 m_log.WarnFormat("[PHYSICS]: Got NaN Velocity in Object {0}", Name);
2524 }
2525
2526 }
2527 }
2528
2529 public override Vector3 Torque
2530 {
2531 get
2532 {
2533 if (!IsPhysical || Body == IntPtr.Zero)
2534 return Vector3.Zero;
2535
2536 return _torque;
2537 }
2538
2539 set
2540 {
2541 if (value.IsFinite())
2542 {
2543 m_taintTorque = value;
2544 _parent_scene.AddPhysicsActorTaint(this);
2545 }
2546 else
2547 {
2548 m_log.WarnFormat("[PHYSICS]: Got NaN Torque in Object {0}", Name);
2549 }
2550 }
2551 }
2552
2553 public override float CollisionScore
2554 {
2555 get { return m_collisionscore; }
2556 set { m_collisionscore = value; }
2557 }
2558
2559 public override bool Kinematic
2560 {
2561 get { return false; }
2562 set { }
2563 }
2564
2565 public override Quaternion Orientation
2566 {
2567 get { return _orientation; }
2568 set
2569 {
2570 if (QuaternionIsFinite(value))
2571 _orientation = value;
2572 else
2573 m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name);
2574 }
2575 }
2576
2577 private static bool QuaternionIsFinite(Quaternion q)
2578 {
2579 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
2580 return false;
2581 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
2582 return false;
2583 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
2584 return false;
2585 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
2586 return false;
2587 return true;
2588 }
2589
2590 public override Vector3 Acceleration
2591 {
2592 get { return _acceleration; }
2593 set { _acceleration = value; }
2594 }
2595
2596 public override void AddForce(Vector3 force, bool pushforce)
2597 {
2598 if (force.IsFinite())
2599 {
2600 lock (m_forcelist)
2601 m_forcelist.Add(force);
2602
2603 m_taintforce = true;
2604 }
2605 else
2606 {
2607 m_log.WarnFormat("[PHYSICS]: Got Invalid linear force vector from Scene in Object {0}", Name);
2608 }
2609 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
2610 }
2611
2612 public override void AddAngularForce(Vector3 force, bool pushforce)
2613 {
2614 if (force.IsFinite())
2615 {
2616 m_angularforcelist.Add(force);
2617 m_taintaddangularforce = true;
2618 }
2619 else
2620 {
2621 m_log.WarnFormat("[PHYSICS]: Got Invalid Angular force vector from Scene in Object {0}", Name);
2622 }
2623 }
2624
2625 public override Vector3 RotationalVelocity
2626 {
2627 get
2628 {
2629 Vector3 pv = Vector3.Zero;
2630 if (_zeroFlag)
2631 return pv;
2632 m_lastUpdateSent = false;
2633
2634 if (m_rotationalVelocity.ApproxEquals(pv, 0.2f))
2635 return pv;
2636
2637 return m_rotationalVelocity;
2638 }
2639 set
2640 {
2641 if (value.IsFinite())
2642 {
2643 m_rotationalVelocity = value;
2644 setAngularVelocity(value.X, value.Y, value.Z);
2645 }
2646 else
2647 {
2648 m_log.WarnFormat("[PHYSICS]: Got NaN RotationalVelocity in Object {0}", Name);
2649 }
2650 }
2651 }
2652
2653 public override void CrossingFailure()
2654 {
2655 /*
2656 m_crossingfailures++;
2657 if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2658 {
2659 base.RaiseOutOfBounds(_position);
2660 return;
2661 }
2662 else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2663 {
2664 m_log.Warn("[PHYSICS]: Too many crossing failures for: " + Name);
2665 }
2666 */
2667
2668 d.AllocateODEDataForThread(0U);
2669
2670 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f);
2671 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f);
2672 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
2673
2674 m_lastposition = _position;
2675 _velocity.X = 0;
2676 _velocity.Y = 0;
2677 _velocity.Z = 0;
2678
2679 m_lastVelocity = _velocity;
2680
2681 if (Body != IntPtr.Zero)
2682 {
2683 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
2684 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
2685 }
2686
2687 if(m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2688 m_vehicle.Stop(); // this also updates vehicle last position from the body position
2689
2690 enableBodySoft();
2691
2692 outofBounds = false;
2693 base.RequestPhysicsterseUpdate();
2694
2695 }
2696
2697 public override float Buoyancy
2698 {
2699 get { return m_buoyancy; }
2700 set { m_buoyancy = value; }
2701 }
2702
2703 public override void link(PhysicsActor obj)
2704 {
2705 m_taintparent = obj;
2706 }
2707
2708 public override void delink()
2709 {
2710 m_taintparent = null;
2711 }
2712
2713 public override void LockAngularMotion(byte axislocks)
2714 {
2715 // m_log.DebugFormat("[axislocks]: {0}", axislocks);
2716 m_taintAngularLock = axislocks;
2717 }
2718
2719 internal void UpdatePositionAndVelocity()
2720 {
2721 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
2722 if (outofBounds)
2723 return;
2724 if (_parent == null)
2725 {
2726 Vector3 pv = Vector3.Zero;
2727 bool lastZeroFlag = _zeroFlag;
2728 float m_minvelocity = 0;
2729 if (Body != IntPtr.Zero) // FIXME -> or if it is a joint
2730 {
2731 d.Vector3 vec = d.BodyGetPosition(Body);
2732 d.Quaternion ori = d.BodyGetQuaternion(Body);
2733 d.Vector3 vel = d.BodyGetLinearVel(Body);
2734 d.Vector3 rotvel = d.BodyGetAngularVel(Body);
2735 d.Vector3 torque = d.BodyGetTorque(Body);
2736 _torque = new Vector3(torque.X, torque.Y, torque.Z);
2737 Vector3 l_position = Vector3.Zero;
2738 Quaternion l_orientation = Quaternion.Identity;
2739
2740 m_lastposition = _position;
2741 m_lastorientation = _orientation;
2742
2743 l_position.X = vec.X;
2744 l_position.Y = vec.Y;
2745 l_position.Z = vec.Z;
2746 l_orientation.X = ori.X;
2747 l_orientation.Y = ori.Y;
2748 l_orientation.Z = ori.Z;
2749 l_orientation.W = ori.W;
2750
2751 if (l_position.Z < 0)
2752 {
2753 // This is so prim that get lost underground don't fall forever and suck up
2754 //
2755 // Sim resources and memory.
2756 // Disables the prim's movement physics....
2757 // It's a hack and will generate a console message if it fails.
2758
2759 //IsPhysical = false;
2760
2761 _acceleration.X = 0;
2762 _acceleration.Y = 0;
2763 _acceleration.Z = 0;
2764
2765 _velocity.X = 0;
2766 _velocity.Y = 0;
2767 _velocity.Z = 0;
2768 m_rotationalVelocity.X = 0;
2769 m_rotationalVelocity.Y = 0;
2770 m_rotationalVelocity.Z = 0;
2771
2772 if (_parent == null)
2773 base.RaiseOutOfBounds(_position);
2774
2775 if (_parent == null)
2776 base.RequestPhysicsterseUpdate();
2777
2778 m_throttleUpdates = false;
2779 throttleCounter = 0;
2780 _zeroFlag = true;
2781 //outofBounds = true;
2782 return;
2783 }
2784
2785 if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f)
2786 {
2787 //base.RaiseOutOfBounds(l_position);
2788 /*
2789 if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2790 {
2791 _position = l_position;
2792 //_parent_scene.remActivePrim(this);
2793 if (_parent == null)
2794 base.RequestPhysicsterseUpdate();
2795 return;
2796 }
2797 else
2798 {
2799 if (_parent == null)
2800 base.RaiseOutOfBounds(l_position);
2801 return;
2802 }
2803 */
2804 outofBounds = true;
2805 // part near the border on outside
2806 if (l_position.X < 0)
2807 Util.Clamp(l_position.X, -0.1f, -2f);
2808 else
2809 Util.Clamp(l_position.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
2810 if (l_position.Y < 0)
2811 Util.Clamp(l_position.Y, -0.1f, -2f);
2812 else
2813 Util.Clamp(l_position.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
2814
2815 d.BodySetPosition(Body, l_position.X, l_position.Y, l_position.Z);
2816
2817 // stop it
2818 d.BodySetAngularVel(Body, 0, 0, 0);
2819 d.BodySetLinearVel(Body, 0, 0, 0);
2820 disableBodySoft();
2821
2822 _position = l_position;
2823 // tell framework to fix it
2824 if (_parent == null)
2825 base.RequestPhysicsterseUpdate();
2826 return;
2827 }
2828
2829
2830 //float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation));
2831 //Console.WriteLine("Adiff " + Name + " = " + Adiff);
2832 if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
2833 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
2834 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02)
2835// && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.01))
2836 && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.0001)) // KF 0.01 is far to large
2837 {
2838 _zeroFlag = true;
2839//Console.WriteLine("ZFT 2");
2840 m_throttleUpdates = false;
2841 }
2842 else
2843 {
2844 //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString());
2845 _zeroFlag = false;
2846 m_lastUpdateSent = false;
2847 //m_throttleUpdates = false;
2848 }
2849
2850 if (_zeroFlag)
2851 {
2852 _velocity.X = 0.0f;
2853 _velocity.Y = 0.0f;
2854 _velocity.Z = 0.0f;
2855
2856 _acceleration.X = 0;
2857 _acceleration.Y = 0;
2858 _acceleration.Z = 0;
2859
2860 //_orientation.w = 0f;
2861 //_orientation.X = 0f;
2862 //_orientation.Y = 0f;
2863 //_orientation.Z = 0f;
2864 m_rotationalVelocity.X = 0;
2865 m_rotationalVelocity.Y = 0;
2866 m_rotationalVelocity.Z = 0;
2867 if (!m_lastUpdateSent)
2868 {
2869 m_throttleUpdates = false;
2870 throttleCounter = 0;
2871 m_rotationalVelocity = pv;
2872
2873 if (_parent == null)
2874 {
2875 base.RequestPhysicsterseUpdate();
2876 }
2877
2878 m_lastUpdateSent = true;
2879 }
2880 }
2881 else
2882 {
2883 if (lastZeroFlag != _zeroFlag)
2884 {
2885 if (_parent == null)
2886 {
2887 base.RequestPhysicsterseUpdate();
2888 }
2889 }
2890
2891 m_lastVelocity = _velocity;
2892
2893 _position = l_position;
2894
2895 _velocity.X = vel.X;
2896 _velocity.Y = vel.Y;
2897 _velocity.Z = vel.Z;
2898
2899 _acceleration = ((_velocity - m_lastVelocity) / 0.1f);
2900 _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f);
2901 //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString());
2902
2903 // Note here that linearvelocity is affecting angular velocity... so I'm guessing this is a vehicle specific thing...
2904 // it does make sense to do this for tiny little instabilities with physical prim, however 0.5m/frame is fairly large.
2905 // reducing this to 0.02m/frame seems to help the angular rubberbanding quite a bit, however, to make sure it doesn't affect elevators and vehicles
2906 // adding these logical exclusion situations to maintain this where I think it was intended to be.
2907 if (m_throttleUpdates || PIDActive || (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) || (Amotor != IntPtr.Zero))
2908 {
2909 m_minvelocity = 0.5f;
2910 }
2911 else
2912 {
2913 m_minvelocity = 0.02f;
2914 }
2915
2916 if (_velocity.ApproxEquals(pv, m_minvelocity))
2917 {
2918 m_rotationalVelocity = pv;
2919 }
2920 else
2921 {
2922 m_rotationalVelocity = new Vector3(rotvel.X, rotvel.Y, rotvel.Z);
2923 }
2924
2925 //m_log.Debug("ODE: " + m_rotationalVelocity.ToString());
2926 _orientation.X = ori.X;
2927 _orientation.Y = ori.Y;
2928 _orientation.Z = ori.Z;
2929 _orientation.W = ori.W;
2930 m_lastUpdateSent = false;
2931 if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate)
2932 {
2933 if (_parent == null)
2934 {
2935 base.RequestPhysicsterseUpdate();
2936 }
2937 }
2938 else
2939 {
2940 throttleCounter++;
2941 }
2942 }
2943 m_lastposition = l_position;
2944 }
2945 else
2946 {
2947 // Not a body.. so Make sure the client isn't interpolating
2948 _velocity.X = 0;
2949 _velocity.Y = 0;
2950 _velocity.Z = 0;
2951
2952 _acceleration.X = 0;
2953 _acceleration.Y = 0;
2954 _acceleration.Z = 0;
2955
2956 m_rotationalVelocity.X = 0;
2957 m_rotationalVelocity.Y = 0;
2958 m_rotationalVelocity.Z = 0;
2959 _zeroFlag = true;
2960 }
2961 }
2962 }
2963
2964 public override bool FloatOnWater
2965 {
2966 set {
2967 m_taintCollidesWater = value;
2968 _parent_scene.AddPhysicsActorTaint(this);
2969 }
2970 }
2971
2972 public override void SetMomentum(Vector3 momentum)
2973 {
2974 }
2975
2976 public override Vector3 PIDTarget
2977 {
2978 set
2979 {
2980 if (value.IsFinite())
2981 {
2982 m_PIDTarget = value;
2983 }
2984 else
2985 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name);
2986 }
2987 }
2988
2989 public override bool PIDActive { get; set; }
2990 public override float PIDTau { set { m_PIDTau = value; } }
2991
2992 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
2993 public override bool PIDHoverActive { get { return m_useHoverPID;} set { m_useHoverPID = value; } }
2994 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
2995 public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
2996
2997 public override Quaternion APIDTarget{ set { return; } }
2998
2999 public override bool APIDActive{ set { return; } }
3000
3001 public override float APIDStrength{ set { return; } }
3002
3003 public override float APIDDamping{ set { return; } }
3004
3005 private void createAMotor(byte axislock)
3006 {
3007 if (Body == IntPtr.Zero)
3008 return;
3009
3010 if (Amotor != IntPtr.Zero)
3011 {
3012 d.JointDestroy(Amotor);
3013 Amotor = IntPtr.Zero;
3014 }
3015
3016 if(axislock == 0)
3017 return;
3018
3019 int axisnum = 0;
3020 bool axisX = false;
3021 bool axisY = false;
3022 bool axisZ = false;
3023 if((axislock & 0x02) != 0)
3024 {
3025 axisnum++;
3026 axisX = true;
3027 }
3028 if((axislock & 0x04) != 0)
3029 {
3030 axisnum++;
3031 axisY = true;
3032 }
3033 if((axislock & 0x08) != 0)
3034 {
3035 axisnum++;
3036 axisZ = true;
3037 }
3038
3039 if(axisnum == 0)
3040 return;
3041 // stop it
3042 d.BodySetTorque(Body, 0, 0, 0);
3043 d.BodySetAngularVel(Body, 0, 0, 0);
3044
3045 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
3046 d.JointAttach(Amotor, Body, IntPtr.Zero);
3047
3048 d.JointSetAMotorMode(Amotor, 0);
3049
3050 d.JointSetAMotorNumAxes(Amotor, axisnum);
3051
3052 // get current orientation to lock
3053
3054 d.Quaternion dcur = d.BodyGetQuaternion(Body);
3055 Quaternion curr; // crap convertion between identical things
3056 curr.X = dcur.X;
3057 curr.Y = dcur.Y;
3058 curr.Z = dcur.Z;
3059 curr.W = dcur.W;
3060 Vector3 ax;
3061
3062 int i = 0;
3063 int j = 0;
3064 if (axisX)
3065 {
3066 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X
3067 d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z);
3068 d.JointSetAMotorAngle(Amotor, 0, 0);
3069 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, 0f);
3070 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0f);
3071 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
3072 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
3073 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
3074 d.JointSetAMotorParam(Amotor, (int)d.JointParam.CFM, 0f);
3075 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
3076 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f);
3077 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f);
3078 i++;
3079 j = 256; // move to next axis set
3080 }
3081
3082 if (axisY)
3083 {
3084 ax = (new Vector3(0, 1, 0)) * curr;
3085 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
3086 d.JointSetAMotorAngle(Amotor, i, 0);
3087 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
3088 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
3089 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
3090 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
3091 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
3092 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
3093 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
3094 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
3095 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
3096 i++;
3097 j += 256;
3098 }
3099
3100 if (axisZ)
3101 {
3102 ax = (new Vector3(0, 0, 1)) * curr;
3103 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
3104 d.JointSetAMotorAngle(Amotor, i, 0);
3105 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
3106 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
3107 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
3108 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
3109 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
3110 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
3111 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
3112 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
3113 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
3114 }
3115 }
3116
3117 public override void SubscribeEvents(int ms)
3118 {
3119 m_eventsubscription = ms;
3120 _parent_scene.AddCollisionEventReporting(this);
3121 }
3122
3123 public override void UnSubscribeEvents()
3124 {
3125 _parent_scene.RemoveCollisionEventReporting(this);
3126 m_eventsubscription = 0;
3127 }
3128
3129 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
3130 {
3131 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
3132 }
3133
3134 public void SendCollisions()
3135 {
3136 if (m_collisionsOnPreviousFrame || CollisionEventsThisFrame.Count > 0)
3137 {
3138 base.SendCollisionUpdate(CollisionEventsThisFrame);
3139
3140 if (CollisionEventsThisFrame.Count > 0)
3141 {
3142 m_collisionsOnPreviousFrame = true;
3143 CollisionEventsThisFrame.Clear();
3144 }
3145 else
3146 {
3147 m_collisionsOnPreviousFrame = false;
3148 }
3149 }
3150 }
3151
3152 public override bool SubscribedEvents()
3153 {
3154 if (m_eventsubscription > 0)
3155 return true;
3156 return false;
3157 }
3158
3159 public override void SetMaterial(int pMaterial)
3160 {
3161 m_material = pMaterial;
3162 }
3163
3164 private void CheckMeshAsset()
3165 {
3166 if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero)
3167 {
3168 m_assetFailed = true;
3169 Util.FireAndForget(delegate
3170 {
3171 RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod;
3172 if (assetProvider != null)
3173 assetProvider(_pbs.SculptTexture, MeshAssetReceived);
3174 }, null, "ODEPrim.CheckMeshAsset");
3175 }
3176 }
3177
3178 private void MeshAssetReceived(AssetBase asset)
3179 {
3180 if (asset != null && asset.Data != null && asset.Data.Length > 0)
3181 {
3182 if (!_pbs.SculptEntry)
3183 return;
3184 if (_pbs.SculptTexture.ToString() != asset.ID)
3185 return;
3186
3187 _pbs.SculptData = new byte[asset.Data.Length];
3188 asset.Data.CopyTo(_pbs.SculptData, 0);
3189// m_assetFailed = false;
3190
3191// m_log.DebugFormat(
3192// "[ODE PRIM]: Received mesh/sculpt data asset {0} with {1} bytes for {2} at {3} in {4}",
3193// _pbs.SculptTexture, _pbs.SculptData.Length, Name, _position, _parent_scene.Name);
3194
3195 m_taintshape = true;
3196 _parent_scene.AddPhysicsActorTaint(this);
3197 }
3198 else
3199 {
3200 m_log.WarnFormat(
3201 "[ODE PRIM]: Could not get mesh/sculpt asset {0} for {1} at {2} in {3}",
3202 _pbs.SculptTexture, Name, _position, _parent_scene.PhysicsSceneName);
3203 }
3204 }
3205 }
3206} \ No newline at end of file
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs b/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
new file mode 100644
index 0000000..78dd7de
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
@@ -0,0 +1,384 @@
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 OpenMetaverse;
34using OpenSim.Region.PhysicsModules.SharedBase;
35using log4net;
36
37namespace OpenSim.Region.PhysicsModule.ODE
38{
39 /// <summary>
40 /// Processes raycast requests as ODE is in a state to be able to do them.
41 /// This ensures that it's thread safe and there will be no conflicts.
42 /// Requests get returned by a different thread then they were requested by.
43 /// </summary>
44 public class ODERayCastRequestManager
45 {
46 /// <summary>
47 /// Pending raycast requests
48 /// </summary>
49 protected List<ODERayCastRequest> m_PendingRequests = new List<ODERayCastRequest>();
50
51 /// <summary>
52 /// Pending ray requests
53 /// </summary>
54 protected List<ODERayRequest> m_PendingRayRequests = new List<ODERayRequest>();
55
56 /// <summary>
57 /// Scene that created this object.
58 /// </summary>
59 private OdeScene m_scene;
60
61 /// <summary>
62 /// ODE contact array to be filled by the collision testing
63 /// </summary>
64 d.ContactGeom[] contacts = new d.ContactGeom[5];
65
66 /// <summary>
67 /// ODE near callback delegate
68 /// </summary>
69 private d.NearCallback nearCallback;
70 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
71 private List<ContactResult> m_contactResults = new List<ContactResult>();
72
73
74 public ODERayCastRequestManager(OdeScene pScene)
75 {
76 m_scene = pScene;
77 nearCallback = near;
78
79 }
80
81 /// <summary>
82 /// Queues a raycast
83 /// </summary>
84 /// <param name="position">Origin of Ray</param>
85 /// <param name="direction">Ray normal</param>
86 /// <param name="length">Ray length</param>
87 /// <param name="retMethod">Return method to send the results</param>
88 public void QueueRequest(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
89 {
90 lock (m_PendingRequests)
91 {
92 ODERayCastRequest req = new ODERayCastRequest();
93 req.callbackMethod = retMethod;
94 req.length = length;
95 req.Normal = direction;
96 req.Origin = position;
97
98 m_PendingRequests.Add(req);
99 }
100 }
101
102 /// <summary>
103 /// Queues a raycast
104 /// </summary>
105 /// <param name="position">Origin of Ray</param>
106 /// <param name="direction">Ray normal</param>
107 /// <param name="length">Ray length</param>
108 /// <param name="count"></param>
109 /// <param name="retMethod">Return method to send the results</param>
110 public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod)
111 {
112 lock (m_PendingRequests)
113 {
114 ODERayRequest req = new ODERayRequest();
115 req.callbackMethod = retMethod;
116 req.length = length;
117 req.Normal = direction;
118 req.Origin = position;
119 req.Count = count;
120
121 m_PendingRayRequests.Add(req);
122 }
123 }
124
125 /// <summary>
126 /// Process all queued raycast requests
127 /// </summary>
128 /// <returns>Time in MS the raycasts took to process.</returns>
129 public int ProcessQueuedRequests()
130 {
131 int time = System.Environment.TickCount;
132 lock (m_PendingRequests)
133 {
134 if (m_PendingRequests.Count > 0)
135 {
136 ODERayCastRequest[] reqs = m_PendingRequests.ToArray();
137 for (int i = 0; i < reqs.Length; i++)
138 {
139 if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
140 RayCast(reqs[i]); // if there isn't anyone to send results
141 }
142
143 m_PendingRequests.Clear();
144 }
145 }
146
147 lock (m_PendingRayRequests)
148 {
149 if (m_PendingRayRequests.Count > 0)
150 {
151 ODERayRequest[] reqs = m_PendingRayRequests.ToArray();
152 for (int i = 0; i < reqs.Length; i++)
153 {
154 if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
155 RayCast(reqs[i]); // if there isn't anyone to send results
156 }
157
158 m_PendingRayRequests.Clear();
159 }
160 }
161
162 lock (m_contactResults)
163 m_contactResults.Clear();
164
165 return System.Environment.TickCount - time;
166 }
167
168 /// <summary>
169 /// Method that actually initiates the raycast
170 /// </summary>
171 /// <param name="req"></param>
172 private void RayCast(ODERayCastRequest req)
173 {
174 // NOTE: limit ray length or collisions will take all avaiable stack space
175 // this value may still be too large, depending on machine configuration
176 // of maximum stack
177 float len = req.length;
178 if (len > 100f)
179 len = 100f;
180
181 // Create the ray
182 IntPtr ray = d.CreateRay(m_scene.space, len);
183 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
184
185 // Collide test
186 d.SpaceCollide2(m_scene.space, ray, IntPtr.Zero, nearCallback);
187
188 // Remove Ray
189 d.GeomDestroy(ray);
190
191 // Define default results
192 bool hitYN = false;
193 uint hitConsumerID = 0;
194 float distance = 999999999999f;
195 Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f);
196 Vector3 snormal = Vector3.Zero;
197
198 // Find closest contact and object.
199 lock (m_contactResults)
200 {
201 foreach (ContactResult cResult in m_contactResults)
202 {
203 if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact))
204 {
205 closestcontact = cResult.Pos;
206 hitConsumerID = cResult.ConsumerID;
207 distance = cResult.Depth;
208 hitYN = true;
209 snormal = cResult.Normal;
210 }
211 }
212
213 m_contactResults.Clear();
214 }
215
216 // Return results
217 if (req.callbackMethod != null)
218 req.callbackMethod(hitYN, closestcontact, hitConsumerID, distance, snormal);
219 }
220
221 /// <summary>
222 /// Method that actually initiates the raycast
223 /// </summary>
224 /// <param name="req"></param>
225 private void RayCast(ODERayRequest req)
226 {
227 // limit ray length or collisions will take all avaiable stack space
228 float len = req.length;
229 if (len > 100f)
230 len = 100f;
231
232 // Create the ray
233 IntPtr ray = d.CreateRay(m_scene.space, len);
234 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
235
236 // Collide test
237 d.SpaceCollide2(m_scene.space, ray, IntPtr.Zero, nearCallback);
238
239 // Remove Ray
240 d.GeomDestroy(ray);
241
242 // Find closest contact and object.
243 lock (m_contactResults)
244 {
245 // Return results
246 if (req.callbackMethod != null)
247 req.callbackMethod(m_contactResults);
248 }
249 }
250
251 // This is the standard Near. Uses space AABBs to speed up detection.
252 private void near(IntPtr space, IntPtr g1, IntPtr g2)
253 {
254
255 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
256 return;
257// if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass || d.GeomGetClass(g2) == d.GeomClassID.HeightfieldClass)
258// return;
259
260 // Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms.
261 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
262 {
263 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
264 return;
265
266 // Separating static prim geometry spaces.
267 // We'll be calling near recursivly if one
268 // of them is a space to find all of the
269 // contact points in the space
270 try
271 {
272 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
273 }
274 catch (AccessViolationException)
275 {
276 m_log.Warn("[PHYSICS]: Unable to collide test a space");
277 return;
278 }
279 //Colliding a space or a geom with a space or a geom. so drill down
280
281 //Collide all geoms in each space..
282 //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
283 //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
284 return;
285 }
286
287 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
288 return;
289
290 int count = 0;
291 try
292 {
293
294 if (g1 == g2)
295 return; // Can't collide with yourself
296
297 lock (contacts)
298 {
299 count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.unmanagedSizeOf);
300 }
301 }
302 catch (SEHException)
303 {
304 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.");
305 }
306 catch (Exception e)
307 {
308 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
309 return;
310 }
311
312 PhysicsActor p1 = null;
313 PhysicsActor p2 = null;
314
315 if (g1 != IntPtr.Zero)
316 m_scene.actor_name_map.TryGetValue(g1, out p1);
317
318 if (g2 != IntPtr.Zero)
319 m_scene.actor_name_map.TryGetValue(g1, out p2);
320
321 // Loop over contacts, build results.
322 for (int i = 0; i < count; i++)
323 {
324 if (p1 != null)
325 {
326 if (p1 is OdePrim)
327 {
328 ContactResult collisionresult = new ContactResult();
329
330 collisionresult.ConsumerID = p1.LocalID;
331 collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z);
332 collisionresult.Depth = contacts[i].depth;
333 collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y,
334 contacts[i].normal.Z);
335 lock (m_contactResults)
336 m_contactResults.Add(collisionresult);
337 }
338 }
339
340 if (p2 != null)
341 {
342 if (p2 is OdePrim)
343 {
344 ContactResult collisionresult = new ContactResult();
345
346 collisionresult.ConsumerID = p2.LocalID;
347 collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z);
348 collisionresult.Depth = contacts[i].depth;
349 collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y,
350 contacts[i].normal.Z);
351
352 lock (m_contactResults)
353 m_contactResults.Add(collisionresult);
354 }
355 }
356 }
357 }
358
359 /// <summary>
360 /// Dereference the creator scene so that it can be garbage collected if needed.
361 /// </summary>
362 internal void Dispose()
363 {
364 m_scene = null;
365 }
366 }
367
368 public struct ODERayCastRequest
369 {
370 public Vector3 Origin;
371 public Vector3 Normal;
372 public float length;
373 public RaycastCallback callbackMethod;
374 }
375
376 public struct ODERayRequest
377 {
378 public Vector3 Origin;
379 public Vector3 Normal;
380 public int Count;
381 public float length;
382 public RayCallback callbackMethod;
383 }
384}
diff --git a/OpenSim/Region/PhysicsModules/Ode/OdePhysicsJoint.cs b/OpenSim/Region/PhysicsModules/Ode/OdePhysicsJoint.cs
new file mode 100644
index 0000000..e2578be
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/OdePhysicsJoint.cs
@@ -0,0 +1,46 @@
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 OpenMetaverse;
30using OpenSim.Framework;
31using OpenSim.Region.PhysicsModules.SharedBase;
32
33namespace OpenSim.Region.PhysicsModule.ODE
34{
35 class OdePhysicsJoint : PhysicsJoint
36 {
37 public override bool IsInPhysicsEngine
38 {
39 get
40 {
41 return (jointID != IntPtr.Zero);
42 }
43 }
44 public IntPtr jointID;
45 }
46}
diff --git a/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs b/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
new file mode 100644
index 0000000..d15568e
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
@@ -0,0 +1,3541 @@
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// changes for varsize regions
29// note that raycasts need to have limited range
30// (even in normal regions)
31// or application thread stack may just blowup
32// see RayCast(ODERayCastRequest req)
33
34using System;
35using System.Collections.Generic;
36using System.Diagnostics;
37using System.IO;
38using System.Linq;
39using System.Reflection;
40using System.Runtime.ExceptionServices;
41using System.Runtime.InteropServices;
42using System.Threading;
43using log4net;
44using Nini.Config;
45using Mono.Addins;
46using OpenMetaverse;
47using OpenSim.Framework;
48using OpenSim.Region.PhysicsModules.SharedBase;
49using OpenSim.Region.Framework.Scenes;
50using OpenSim.Region.Framework.Interfaces;
51
52namespace OpenSim.Region.PhysicsModule.ODE
53{
54 public enum StatusIndicators : int
55 {
56 Generic = 0,
57 Start = 1,
58 End = 2
59 }
60
61 [Flags]
62 public enum CollisionCategories : int
63 {
64 Disabled = 0,
65 Geom = 0x00000001,
66 Body = 0x00000002,
67 Space = 0x00000004,
68 Character = 0x00000008,
69 Land = 0x00000010,
70 Water = 0x00000020,
71 Wind = 0x00000040,
72 Sensor = 0x00000080,
73 Selected = 0x00000100
74 }
75
76 /// <summary>
77 /// Material type for a primitive
78 /// </summary>
79 public enum Material : int
80 {
81 /// <summary></summary>
82 Stone = 0,
83 /// <summary></summary>
84 Metal = 1,
85 /// <summary></summary>
86 Glass = 2,
87 /// <summary></summary>
88 Wood = 3,
89 /// <summary></summary>
90 Flesh = 4,
91 /// <summary></summary>
92 Plastic = 5,
93 /// <summary></summary>
94 Rubber = 6
95 }
96
97 public class OdeScene : PhysicsScene
98 {
99 private readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString());
100
101 // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>();
102
103 /// <summary>
104 /// Provide a sync object so that only one thread calls d.Collide() at a time across all OdeScene instances.
105 /// </summary>
106 /// <remarks>
107 /// With ODE as of r1755 (though also tested on r1860), only one thread can call d.Collide() at a
108 /// time, even where physics objects are in entirely different ODE worlds. This is because generating contacts
109 /// uses a static cache at the ODE level.
110 ///
111 /// Without locking, simulators running multiple regions will eventually crash with a native stack trace similar
112 /// to
113 ///
114 /// mono() [0x489171]
115 /// mono() [0x4d154f]
116 /// /lib/x86_64-linux-gnu/libpthread.so.0(+0xfc60) [0x7f6ded592c60]
117 /// .../opensim/bin/libode-x86_64.so(_ZN6Opcode11OBBCollider8_CollideEPKNS_14AABBNoLeafNodeE+0xd7a) [0x7f6dd822628a]
118 ///
119 /// ODE provides an experimental option to cache in thread local storage but compiling ODE with this option
120 /// causes OpenSimulator to immediately crash with a native stack trace similar to
121 ///
122 /// mono() [0x489171]
123 /// mono() [0x4d154f]
124 /// /lib/x86_64-linux-gnu/libpthread.so.0(+0xfc60) [0x7f03c9849c60]
125 /// .../opensim/bin/libode-x86_64.so(_Z12dCollideCCTLP6dxGeomS0_iP12dContactGeomi+0x92) [0x7f03b44bcf82]
126 /// </remarks>
127 internal static Object UniversalColliderSyncObject = new Object();
128 internal static Object SimulationLock = new Object();
129
130 /// <summary>
131 /// Is stats collecting enabled for this ODE scene?
132 /// </summary>
133 public bool CollectStats { get; set; }
134
135 /// <summary>
136 /// Statistics for this scene.
137 /// </summary>
138 private Dictionary<string, float> m_stats = new Dictionary<string, float>();
139
140 /// <summary>
141 /// Stat name for total number of avatars in this ODE scene.
142 /// </summary>
143 public const string ODETotalAvatarsStatName = "ODETotalAvatars";
144
145 /// <summary>
146 /// Stat name for total number of prims in this ODE scene.
147 /// </summary>
148 public const string ODETotalPrimsStatName = "ODETotalPrims";
149
150 /// <summary>
151 /// Stat name for total number of prims with active physics in this ODE scene.
152 /// </summary>
153 public const string ODEActivePrimsStatName = "ODEActivePrims";
154
155 /// <summary>
156 /// Stat name for the total time spent in ODE frame processing.
157 /// </summary>
158 /// <remarks>
159 /// A sanity check for the main scene loop physics time.
160 /// </remarks>
161 public const string ODETotalFrameMsStatName = "ODETotalFrameMS";
162
163 /// <summary>
164 /// Stat name for time spent processing avatar taints per frame
165 /// </summary>
166 public const string ODEAvatarTaintMsStatName = "ODEAvatarTaintFrameMS";
167
168 /// <summary>
169 /// Stat name for time spent processing prim taints per frame
170 /// </summary>
171 public const string ODEPrimTaintMsStatName = "ODEPrimTaintFrameMS";
172
173 /// <summary>
174 /// Stat name for time spent calculating avatar forces per frame.
175 /// </summary>
176 public const string ODEAvatarForcesFrameMsStatName = "ODEAvatarForcesFrameMS";
177
178 /// <summary>
179 /// Stat name for time spent calculating prim forces per frame
180 /// </summary>
181 public const string ODEPrimForcesFrameMsStatName = "ODEPrimForcesFrameMS";
182
183 /// <summary>
184 /// Stat name for time spent fulfilling raycasting requests per frame
185 /// </summary>
186 public const string ODERaycastingFrameMsStatName = "ODERaycastingFrameMS";
187
188 /// <summary>
189 /// Stat name for time spent in native code that actually steps through the simulation.
190 /// </summary>
191 public const string ODENativeStepFrameMsStatName = "ODENativeStepFrameMS";
192
193 /// <summary>
194 /// Stat name for the number of milliseconds that ODE spends in native space collision code.
195 /// </summary>
196 public const string ODENativeSpaceCollisionFrameMsStatName = "ODENativeSpaceCollisionFrameMS";
197
198 /// <summary>
199 /// Stat name for milliseconds that ODE spends in native geom collision code.
200 /// </summary>
201 public const string ODENativeGeomCollisionFrameMsStatName = "ODENativeGeomCollisionFrameMS";
202
203 /// <summary>
204 /// Time spent in collision processing that is not spent in native space or geom collision code.
205 /// </summary>
206 public const string ODEOtherCollisionFrameMsStatName = "ODEOtherCollisionFrameMS";
207
208 /// <summary>
209 /// Stat name for time spent notifying listeners of collisions
210 /// </summary>
211 public const string ODECollisionNotificationFrameMsStatName = "ODECollisionNotificationFrameMS";
212
213 /// <summary>
214 /// Stat name for milliseconds spent updating avatar position and velocity
215 /// </summary>
216 public const string ODEAvatarUpdateFrameMsStatName = "ODEAvatarUpdateFrameMS";
217
218 /// <summary>
219 /// Stat name for the milliseconds spent updating prim position and velocity
220 /// </summary>
221 public const string ODEPrimUpdateFrameMsStatName = "ODEPrimUpdateFrameMS";
222
223 /// <summary>
224 /// Stat name for avatar collisions with another entity.
225 /// </summary>
226 public const string ODEAvatarContactsStatsName = "ODEAvatarContacts";
227
228 /// <summary>
229 /// Stat name for prim collisions with another entity.
230 /// </summary>
231 public const string ODEPrimContactsStatName = "ODEPrimContacts";
232
233 /// <summary>
234 /// Used to hold tick numbers for stat collection purposes.
235 /// </summary>
236 private int m_nativeCollisionStartTick;
237
238 /// <summary>
239 /// A messy way to tell if we need to avoid adding a collision time because this was already done in the callback.
240 /// </summary>
241 private bool m_inCollisionTiming;
242
243 /// <summary>
244 /// A temporary holder for the number of avatar collisions in a frame, so we can work out how many object
245 /// collisions occured using the _perloopcontact if stats collection is enabled.
246 /// </summary>
247 private int m_tempAvatarCollisionsThisFrame;
248
249 /// <summary>
250 /// Used in calculating physics frame time dilation
251 /// </summary>
252 private int tickCountFrameRun;
253
254 /// <summary>
255 /// Used in calculating physics frame time dilation
256 /// </summary>
257 private int latertickcount;
258
259 private Random fluidRandomizer = new Random(Environment.TickCount);
260
261 private uint m_regionWidth = Constants.RegionSize;
262 private uint m_regionHeight = Constants.RegionSize;
263
264 private float ODE_STEPSIZE = 0.0178f;
265 private float metersInSpace = 29.9f;
266 private float m_timeDilation = 1.0f;
267
268 public float gravityx = 0f;
269 public float gravityy = 0f;
270 public float gravityz = -9.8f;
271
272 public float AvatarTerminalVelocity { get; set; }
273
274 private float contactsurfacelayer = 0.001f;
275
276 private int HashspaceLow = -5;
277 private int HashspaceHigh = 12;
278
279 private float waterlevel = 0f;
280 private int framecount = 0;
281 //private int m_returncollisions = 10;
282
283 private IntPtr contactgroup;
284
285// internal IntPtr WaterGeom;
286
287 private float nmTerrainContactFriction = 255.0f;
288 private float nmTerrainContactBounce = 0.1f;
289 private float nmTerrainContactERP = 0.1025f;
290
291 private float mTerrainContactFriction = 75f;
292 private float mTerrainContactBounce = 0.1f;
293 private float mTerrainContactERP = 0.05025f;
294
295 private float nmAvatarObjectContactFriction = 250f;
296 private float nmAvatarObjectContactBounce = 0.1f;
297
298 private float mAvatarObjectContactFriction = 75f;
299 private float mAvatarObjectContactBounce = 0.1f;
300
301 private float avPIDD = 3200f;
302 private float avPIDP = 1400f;
303 private float avCapRadius = 0.37f;
304 private float avStandupTensor = 2000000f;
305
306 /// <summary>
307 /// true = old compatibility mode with leaning capsule; false = new corrected mode
308 /// </summary>
309 /// <remarks>
310 /// Even when set to false, the capsule still tilts but this is done in a different way.
311 /// </remarks>
312 public bool IsAvCapsuleTilted { get; private set; }
313
314 private float avDensity = 80f;
315 private float avMovementDivisorWalk = 1.3f;
316 private float avMovementDivisorRun = 0.8f;
317 private float minimumGroundFlightOffset = 3f;
318 public float maximumMassObject = 10000.01f;
319
320 public bool meshSculptedPrim = true;
321 public bool forceSimplePrimMeshing = false;
322
323 public float meshSculptLOD = 32;
324 public float MeshSculptphysicalLOD = 16;
325
326 public float geomDefaultDensity = 10.000006836f;
327
328 public int geomContactPointsStartthrottle = 3;
329 public int geomUpdatesPerThrottledUpdate = 15;
330 private const int avatarExpectedContacts = 3;
331
332 public float bodyPIDD = 35f;
333 public float bodyPIDG = 25;
334
335 public int bodyFramesAutoDisable = 20;
336
337 private bool m_filterCollisions = true;
338
339 private d.NearCallback nearCallback;
340 public d.TriCallback triCallback;
341 public d.TriArrayCallback triArrayCallback;
342
343 /// <summary>
344 /// Avatars in the physics scene.
345 /// </summary>
346 private readonly HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>();
347
348 /// <summary>
349 /// Prims in the physics scene.
350 /// </summary>
351 private readonly HashSet<OdePrim> _prims = new HashSet<OdePrim>();
352
353 /// <summary>
354 /// Prims in the physics scene that are subject to physics, not just collisions.
355 /// </summary>
356 private readonly HashSet<OdePrim> _activeprims = new HashSet<OdePrim>();
357
358 /// <summary>
359 /// Prims that the simulator has created/deleted/updated and so need updating in ODE.
360 /// </summary>
361 private readonly HashSet<OdePrim> _taintedPrims = new HashSet<OdePrim>();
362
363 /// <summary>
364 /// Record a character that has taints to be processed.
365 /// </summary>
366 private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>();
367
368 /// <summary>
369 /// Keep record of contacts in the physics loop so that we can remove duplicates.
370 /// </summary>
371 private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>();
372
373 /// <summary>
374 /// A dictionary of actors that should receive collision events.
375 /// </summary>
376 private readonly Dictionary<uint, PhysicsActor> m_collisionEventActors = new Dictionary<uint, PhysicsActor>();
377
378 /// <summary>
379 /// A dictionary of collision event changes that are waiting to be processed.
380 /// </summary>
381 private readonly Dictionary<uint, PhysicsActor> m_collisionEventActorsChanges = new Dictionary<uint, PhysicsActor>();
382
383 /// <summary>
384 /// Maps a unique geometry id (a memory location) to a physics actor name.
385 /// </summary>
386 /// <remarks>
387 /// Only actors participating in collisions have geometries. This has to be maintained separately from
388 /// actor_name_map because terrain and water currently don't conceptually have a physics actor of their own
389 /// apart from the singleton PANull
390 /// </remarks>
391 public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>();
392
393 /// <summary>
394 /// Maps a unique geometry id (a memory location) to a physics actor.
395 /// </summary>
396 /// <remarks>
397 /// Only actors participating in collisions have geometries.
398 /// </remarks>
399 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
400
401 /// <summary>
402 /// Defects list to remove characters that no longer have finite positions due to some other bug.
403 /// </summary>
404 /// <remarks>
405 /// Used repeatedly in Simulate() but initialized once here.
406 /// </remarks>
407 private readonly List<OdeCharacter> defects = new List<OdeCharacter>();
408
409 private bool m_NINJA_physics_joints_enabled = false;
410 //private Dictionary<String, IntPtr> jointpart_name_map = new Dictionary<String,IntPtr>();
411 private readonly Dictionary<String, List<PhysicsJoint>> joints_connecting_actor = new Dictionary<String, List<PhysicsJoint>>();
412 private d.ContactGeom[] contacts;
413
414 /// <summary>
415 /// Lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active
416 /// </summary>
417 private readonly List<PhysicsJoint> requestedJointsToBeCreated = new List<PhysicsJoint>();
418
419 /// <summary>
420 /// can lock for longer. accessed only by OdeScene.
421 /// </summary>
422 private readonly List<PhysicsJoint> pendingJoints = new List<PhysicsJoint>();
423
424 /// <summary>
425 /// can lock for longer. accessed only by OdeScene.
426 /// </summary>
427 private readonly List<PhysicsJoint> activeJoints = new List<PhysicsJoint>();
428
429 /// <summary>
430 /// lock only briefly. accessed by external code (to request deletion of joints) and by OdeScene.Simulate() to move those joints out of pending/active
431 /// </summary>
432 private readonly List<string> requestedJointsToBeDeleted = new List<string>();
433
434 private Object externalJointRequestsLock = new Object();
435 private readonly Dictionary<String, PhysicsJoint> SOPName_to_activeJoint = new Dictionary<String, PhysicsJoint>();
436 private readonly Dictionary<String, PhysicsJoint> SOPName_to_pendingJoint = new Dictionary<String, PhysicsJoint>();
437 private readonly DoubleDictionary<Vector3, IntPtr, IntPtr> RegionTerrain = new DoubleDictionary<Vector3, IntPtr, IntPtr>();
438 private readonly Dictionary<IntPtr,float[]> TerrainHeightFieldHeights = new Dictionary<IntPtr, float[]>();
439
440 private d.Contact contact;
441 private d.Contact TerrainContact;
442 private d.Contact AvatarMovementprimContact;
443 private d.Contact AvatarMovementTerrainContact;
444 private d.Contact WaterContact;
445 private d.Contact[,] m_materialContacts;
446
447 private int m_physicsiterations = 10;
448 private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag
449 private readonly PhysicsActor PANull = new NullPhysicsActor();
450 private float step_time = 0.0f;
451 public IntPtr world;
452 private uint obj2LocalID = 0;
453 private OdeCharacter cc1;
454 private OdePrim cp1;
455 private OdeCharacter cc2;
456 private OdePrim cp2;
457 private int p1ExpectedPoints = 0;
458 private int p2ExpectedPoints = 0;
459
460 public IntPtr space;
461
462 // split static geometry collision handling into spaces of 30 meters
463 public IntPtr[,] staticPrimspace;
464
465 /// <summary>
466 /// Used to lock the entire physics scene. Locked during the main part of Simulate()
467 /// </summary>
468 internal Object OdeLock = new Object();
469
470 private bool _worldInitialized = false;
471
472 public IMesher mesher;
473
474 private IConfigSource m_config;
475
476 public bool physics_logging = false;
477 public int physics_logging_interval = 0;
478 public bool physics_logging_append_existing_logfile = false;
479
480 private bool avplanted = false;
481 private bool av_av_collisions_off = false;
482
483 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f);
484 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
485
486 private volatile int m_global_contactcount = 0;
487
488 private Vector3 m_worldOffset = Vector3.Zero;
489 public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
490 private PhysicsScene m_parentScene = null;
491
492 float spacesPerMeterX;
493 float spacesPerMeterY;
494 int spaceGridMaxX;
495 int spaceGridMaxY;
496
497 private ODERayCastRequestManager m_rayCastManager;
498
499 public Scene m_frameWorkScene = null;
500
501 public OdeScene(Scene pscene, IConfigSource psourceconfig, string pname, string pversion)
502 {
503 m_config = psourceconfig;
504 m_frameWorkScene = pscene;
505
506 EngineType = pname;
507 PhysicsSceneName = EngineType + "/" + pscene.RegionInfo.RegionName;
508 EngineName = pname + " " + pversion;
509
510 pscene.RegisterModuleInterface<PhysicsScene>(this);
511 Vector3 extent = new Vector3(pscene.RegionInfo.RegionSizeX, pscene.RegionInfo.RegionSizeY, pscene.RegionInfo.RegionSizeZ);
512 Initialise(extent);
513 InitialiseFromConfig(m_config);
514
515 // This may not be that good since terrain may not be avaiable at this point
516 base.Initialise(pscene.PhysicsRequestAsset,
517 (pscene.Heightmap != null ? pscene.Heightmap.GetFloatsSerialised() : new float[(int)(extent.X * extent.Y)]),
518 (float)pscene.RegionInfo.RegionSettings.WaterHeight);
519
520 }
521
522 public void RegionLoaded()
523 {
524 mesher = m_frameWorkScene.RequestModuleInterface<IMesher>();
525 if (mesher == null)
526 m_log.WarnFormat("[ODE SCENE]: No mesher in {0}. Things will not work well.", PhysicsSceneName);
527
528 m_frameWorkScene.PhysicsEnabled = true;
529 }
530
531 /// <summary>
532 /// Initiailizes the scene
533 /// Sets many properties that ODE requires to be stable
534 /// These settings need to be tweaked 'exactly' right or weird stuff happens.
535 /// </summary>
536 private void Initialise(Vector3 regionExtent)
537 {
538 WorldExtents.X = regionExtent.X;
539 m_regionWidth = (uint)regionExtent.X;
540 WorldExtents.Y = regionExtent.Y;
541 m_regionHeight = (uint)regionExtent.Y;
542
543 nearCallback = near;
544 m_rayCastManager = new ODERayCastRequestManager(this);
545
546 // Create the world and the first space
547 world = d.WorldCreate();
548 space = d.HashSpaceCreate(IntPtr.Zero);
549
550 contactgroup = d.JointGroupCreate(0);
551
552 d.WorldSetAutoDisableFlag(world, false);
553 }
554
555 // Initialize from configs
556 private void InitialiseFromConfig(IConfigSource config)
557 {
558 InitializeExtraStats();
559
560 m_config = config;
561 // Defaults
562
563 avPIDD = 2200.0f;
564 avPIDP = 900.0f;
565 avStandupTensor = 550000f;
566
567 int contactsPerCollision = 80;
568
569 if (m_config != null)
570 {
571 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
572 if (physicsconfig != null)
573 {
574 CollectStats = physicsconfig.GetBoolean("collect_stats", false);
575
576 gravityx = physicsconfig.GetFloat("world_gravityx", 0f);
577 gravityy = physicsconfig.GetFloat("world_gravityy", 0f);
578 gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f);
579
580 float avatarTerminalVelocity = physicsconfig.GetFloat("avatar_terminal_velocity", 54f);
581 AvatarTerminalVelocity = Util.Clamp<float>(avatarTerminalVelocity, 0, 255f);
582 if (AvatarTerminalVelocity != avatarTerminalVelocity)
583 {
584 m_log.WarnFormat(
585 "[ODE SCENE]: avatar_terminal_velocity of {0} is invalid. Clamping to {1}",
586 avatarTerminalVelocity, AvatarTerminalVelocity);
587 }
588
589 HashspaceLow = physicsconfig.GetInt("world_hashspace_level_low", -5);
590 HashspaceHigh = physicsconfig.GetInt("world_hashspace_level_high", 12);
591
592 metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f);
593
594 contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", 0.001f);
595
596 nmTerrainContactFriction = physicsconfig.GetFloat("nm_terraincontact_friction", 255.0f);
597 nmTerrainContactBounce = physicsconfig.GetFloat("nm_terraincontact_bounce", 0.1f);
598 nmTerrainContactERP = physicsconfig.GetFloat("nm_terraincontact_erp", 0.1025f);
599
600 mTerrainContactFriction = physicsconfig.GetFloat("m_terraincontact_friction", 75f);
601 mTerrainContactBounce = physicsconfig.GetFloat("m_terraincontact_bounce", 0.05f);
602 mTerrainContactERP = physicsconfig.GetFloat("m_terraincontact_erp", 0.05025f);
603
604 nmAvatarObjectContactFriction = physicsconfig.GetFloat("objectcontact_friction", 250f);
605 nmAvatarObjectContactBounce = physicsconfig.GetFloat("objectcontact_bounce", 0.2f);
606
607 mAvatarObjectContactFriction = physicsconfig.GetFloat("m_avatarobjectcontact_friction", 75f);
608 mAvatarObjectContactBounce = physicsconfig.GetFloat("m_avatarobjectcontact_bounce", 0.1f);
609
610 ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", ODE_STEPSIZE);
611 m_physicsiterations = physicsconfig.GetInt("world_solver_iterations", 10);
612
613 avDensity = physicsconfig.GetFloat("av_density", 80f);
614// avHeightFudgeFactor = physicsconfig.GetFloat("av_height_fudge_factor", 0.52f);
615 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f);
616 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f);
617 avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f);
618 avplanted = physicsconfig.GetBoolean("av_planted", false);
619 av_av_collisions_off = physicsconfig.GetBoolean("av_av_collisions_off", false);
620
621 IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false);
622
623 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80);
624
625 geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 5);
626 geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15);
627
628 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f);
629 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20);
630
631 bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", 35f);
632 bodyPIDG = physicsconfig.GetFloat("body_pid_gain", 25f);
633
634 forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
635 meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", true);
636 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f);
637 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
638 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
639
640 avPIDD = physicsconfig.GetFloat("av_pid_derivative", 2200.0f);
641 avPIDP = physicsconfig.GetFloat("av_pid_proportional", 900.0f);
642 avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor", 550000f);
643
644 physics_logging = physicsconfig.GetBoolean("physics_logging", false);
645 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
646 physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
647
648// m_NINJA_physics_joints_enabled = physicsconfig.GetBoolean("use_NINJA_physics_joints", false);
649 minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", 3f);
650 maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", 10000.01f);
651 }
652 }
653
654 contacts = new d.ContactGeom[contactsPerCollision];
655
656 spacesPerMeterX = 1.0f / metersInSpace;
657 spacesPerMeterY = 1.0f / metersInSpace;
658
659 spaceGridMaxX = (int)(WorldExtents.X * spacesPerMeterX);
660 spaceGridMaxY = (int)(WorldExtents.Y * spacesPerMeterY);
661
662 // note: limit number of spaces
663 if (spaceGridMaxX > 24)
664 {
665 spaceGridMaxX = 24;
666 spacesPerMeterX = spaceGridMaxX / WorldExtents.X;
667 }
668 if (spaceGridMaxY > 24)
669 {
670 spaceGridMaxY = 24;
671 spacesPerMeterY = spaceGridMaxY / WorldExtents.Y;
672 }
673
674 staticPrimspace = new IntPtr[spaceGridMaxX, spaceGridMaxY];
675
676 // make this index limits
677 spaceGridMaxX--;
678 spaceGridMaxY--;
679
680 // Centeral contact friction and bounce
681 // ckrinke 11/10/08 Enabling soft_erp but not soft_cfm until I figure out why
682 // an avatar falls through in Z but not in X or Y when walking on a prim.
683 contact.surface.mode |= d.ContactFlags.SoftERP;
684 contact.surface.mu = nmAvatarObjectContactFriction;
685 contact.surface.bounce = nmAvatarObjectContactBounce;
686 contact.surface.soft_cfm = 0.010f;
687 contact.surface.soft_erp = 0.010f;
688
689 // Terrain contact friction and Bounce
690 // This is the *non* moving version. Use this when an avatar
691 // isn't moving to keep it in place better
692 TerrainContact.surface.mode |= d.ContactFlags.SoftERP;
693 TerrainContact.surface.mu = nmTerrainContactFriction;
694 TerrainContact.surface.bounce = nmTerrainContactBounce;
695 TerrainContact.surface.soft_erp = nmTerrainContactERP;
696
697 WaterContact.surface.mode |= (d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM);
698 WaterContact.surface.mu = 0f; // No friction
699 WaterContact.surface.bounce = 0.0f; // No bounce
700 WaterContact.surface.soft_cfm = 0.010f;
701 WaterContact.surface.soft_erp = 0.010f;
702
703 // Prim contact friction and bounce
704 // THis is the *non* moving version of friction and bounce
705 // Use this when an avatar comes in contact with a prim
706 // and is moving
707 AvatarMovementprimContact.surface.mu = mAvatarObjectContactFriction;
708 AvatarMovementprimContact.surface.bounce = mAvatarObjectContactBounce;
709
710 // Terrain contact friction bounce and various error correcting calculations
711 // Use this when an avatar is in contact with the terrain and moving.
712 AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP;
713 AvatarMovementTerrainContact.surface.mu = mTerrainContactFriction;
714 AvatarMovementTerrainContact.surface.bounce = mTerrainContactBounce;
715 AvatarMovementTerrainContact.surface.soft_erp = mTerrainContactERP;
716
717 /*
718 <summary></summary>
719 Stone = 0,
720 /// <summary></summary>
721 Metal = 1,
722 /// <summary></summary>
723 Glass = 2,
724 /// <summary></summary>
725 Wood = 3,
726 /// <summary></summary>
727 Flesh = 4,
728 /// <summary></summary>
729 Plastic = 5,
730 /// <summary></summary>
731 Rubber = 6
732 */
733
734 m_materialContacts = new d.Contact[7,2];
735
736 m_materialContacts[(int)Material.Stone, 0] = new d.Contact();
737 m_materialContacts[(int)Material.Stone, 0].surface.mode |= d.ContactFlags.SoftERP;
738 m_materialContacts[(int)Material.Stone, 0].surface.mu = nmAvatarObjectContactFriction;
739 m_materialContacts[(int)Material.Stone, 0].surface.bounce = nmAvatarObjectContactBounce;
740 m_materialContacts[(int)Material.Stone, 0].surface.soft_cfm = 0.010f;
741 m_materialContacts[(int)Material.Stone, 0].surface.soft_erp = 0.010f;
742
743 m_materialContacts[(int)Material.Stone, 1] = new d.Contact();
744 m_materialContacts[(int)Material.Stone, 1].surface.mode |= d.ContactFlags.SoftERP;
745 m_materialContacts[(int)Material.Stone, 1].surface.mu = mAvatarObjectContactFriction;
746 m_materialContacts[(int)Material.Stone, 1].surface.bounce = mAvatarObjectContactBounce;
747 m_materialContacts[(int)Material.Stone, 1].surface.soft_cfm = 0.010f;
748 m_materialContacts[(int)Material.Stone, 1].surface.soft_erp = 0.010f;
749
750 m_materialContacts[(int)Material.Metal, 0] = new d.Contact();
751 m_materialContacts[(int)Material.Metal, 0].surface.mode |= d.ContactFlags.SoftERP;
752 m_materialContacts[(int)Material.Metal, 0].surface.mu = nmAvatarObjectContactFriction;
753 m_materialContacts[(int)Material.Metal, 0].surface.bounce = nmAvatarObjectContactBounce;
754 m_materialContacts[(int)Material.Metal, 0].surface.soft_cfm = 0.010f;
755 m_materialContacts[(int)Material.Metal, 0].surface.soft_erp = 0.010f;
756
757 m_materialContacts[(int)Material.Metal, 1] = new d.Contact();
758 m_materialContacts[(int)Material.Metal, 1].surface.mode |= d.ContactFlags.SoftERP;
759 m_materialContacts[(int)Material.Metal, 1].surface.mu = mAvatarObjectContactFriction;
760 m_materialContacts[(int)Material.Metal, 1].surface.bounce = mAvatarObjectContactBounce;
761 m_materialContacts[(int)Material.Metal, 1].surface.soft_cfm = 0.010f;
762 m_materialContacts[(int)Material.Metal, 1].surface.soft_erp = 0.010f;
763
764 m_materialContacts[(int)Material.Glass, 0] = new d.Contact();
765 m_materialContacts[(int)Material.Glass, 0].surface.mode |= d.ContactFlags.SoftERP;
766 m_materialContacts[(int)Material.Glass, 0].surface.mu = 1f;
767 m_materialContacts[(int)Material.Glass, 0].surface.bounce = 0.5f;
768 m_materialContacts[(int)Material.Glass, 0].surface.soft_cfm = 0.010f;
769 m_materialContacts[(int)Material.Glass, 0].surface.soft_erp = 0.010f;
770
771 /*
772 private float nmAvatarObjectContactFriction = 250f;
773 private float nmAvatarObjectContactBounce = 0.1f;
774
775 private float mAvatarObjectContactFriction = 75f;
776 private float mAvatarObjectContactBounce = 0.1f;
777 */
778 m_materialContacts[(int)Material.Glass, 1] = new d.Contact();
779 m_materialContacts[(int)Material.Glass, 1].surface.mode |= d.ContactFlags.SoftERP;
780 m_materialContacts[(int)Material.Glass, 1].surface.mu = 1f;
781 m_materialContacts[(int)Material.Glass, 1].surface.bounce = 0.5f;
782 m_materialContacts[(int)Material.Glass, 1].surface.soft_cfm = 0.010f;
783 m_materialContacts[(int)Material.Glass, 1].surface.soft_erp = 0.010f;
784
785 m_materialContacts[(int)Material.Wood, 0] = new d.Contact();
786 m_materialContacts[(int)Material.Wood, 0].surface.mode |= d.ContactFlags.SoftERP;
787 m_materialContacts[(int)Material.Wood, 0].surface.mu = nmAvatarObjectContactFriction;
788 m_materialContacts[(int)Material.Wood, 0].surface.bounce = nmAvatarObjectContactBounce;
789 m_materialContacts[(int)Material.Wood, 0].surface.soft_cfm = 0.010f;
790 m_materialContacts[(int)Material.Wood, 0].surface.soft_erp = 0.010f;
791
792 m_materialContacts[(int)Material.Wood, 1] = new d.Contact();
793 m_materialContacts[(int)Material.Wood, 1].surface.mode |= d.ContactFlags.SoftERP;
794 m_materialContacts[(int)Material.Wood, 1].surface.mu = mAvatarObjectContactFriction;
795 m_materialContacts[(int)Material.Wood, 1].surface.bounce = mAvatarObjectContactBounce;
796 m_materialContacts[(int)Material.Wood, 1].surface.soft_cfm = 0.010f;
797 m_materialContacts[(int)Material.Wood, 1].surface.soft_erp = 0.010f;
798
799 m_materialContacts[(int)Material.Flesh, 0] = new d.Contact();
800 m_materialContacts[(int)Material.Flesh, 0].surface.mode |= d.ContactFlags.SoftERP;
801 m_materialContacts[(int)Material.Flesh, 0].surface.mu = nmAvatarObjectContactFriction;
802 m_materialContacts[(int)Material.Flesh, 0].surface.bounce = nmAvatarObjectContactBounce;
803 m_materialContacts[(int)Material.Flesh, 0].surface.soft_cfm = 0.010f;
804 m_materialContacts[(int)Material.Flesh, 0].surface.soft_erp = 0.010f;
805
806 m_materialContacts[(int)Material.Flesh, 1] = new d.Contact();
807 m_materialContacts[(int)Material.Flesh, 1].surface.mode |= d.ContactFlags.SoftERP;
808 m_materialContacts[(int)Material.Flesh, 1].surface.mu = mAvatarObjectContactFriction;
809 m_materialContacts[(int)Material.Flesh, 1].surface.bounce = mAvatarObjectContactBounce;
810 m_materialContacts[(int)Material.Flesh, 1].surface.soft_cfm = 0.010f;
811 m_materialContacts[(int)Material.Flesh, 1].surface.soft_erp = 0.010f;
812
813 m_materialContacts[(int)Material.Plastic, 0] = new d.Contact();
814 m_materialContacts[(int)Material.Plastic, 0].surface.mode |= d.ContactFlags.SoftERP;
815 m_materialContacts[(int)Material.Plastic, 0].surface.mu = nmAvatarObjectContactFriction;
816 m_materialContacts[(int)Material.Plastic, 0].surface.bounce = nmAvatarObjectContactBounce;
817 m_materialContacts[(int)Material.Plastic, 0].surface.soft_cfm = 0.010f;
818 m_materialContacts[(int)Material.Plastic, 0].surface.soft_erp = 0.010f;
819
820 m_materialContacts[(int)Material.Plastic, 1] = new d.Contact();
821 m_materialContacts[(int)Material.Plastic, 1].surface.mode |= d.ContactFlags.SoftERP;
822 m_materialContacts[(int)Material.Plastic, 1].surface.mu = mAvatarObjectContactFriction;
823 m_materialContacts[(int)Material.Plastic, 1].surface.bounce = mAvatarObjectContactBounce;
824 m_materialContacts[(int)Material.Plastic, 1].surface.soft_cfm = 0.010f;
825 m_materialContacts[(int)Material.Plastic, 1].surface.soft_erp = 0.010f;
826
827 m_materialContacts[(int)Material.Rubber, 0] = new d.Contact();
828 m_materialContacts[(int)Material.Rubber, 0].surface.mode |= d.ContactFlags.SoftERP;
829 m_materialContacts[(int)Material.Rubber, 0].surface.mu = nmAvatarObjectContactFriction;
830 m_materialContacts[(int)Material.Rubber, 0].surface.bounce = nmAvatarObjectContactBounce;
831 m_materialContacts[(int)Material.Rubber, 0].surface.soft_cfm = 0.010f;
832 m_materialContacts[(int)Material.Rubber, 0].surface.soft_erp = 0.010f;
833
834 m_materialContacts[(int)Material.Rubber, 1] = new d.Contact();
835 m_materialContacts[(int)Material.Rubber, 1].surface.mode |= d.ContactFlags.SoftERP;
836 m_materialContacts[(int)Material.Rubber, 1].surface.mu = mAvatarObjectContactFriction;
837 m_materialContacts[(int)Material.Rubber, 1].surface.bounce = mAvatarObjectContactBounce;
838 m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.010f;
839 m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.010f;
840
841 d.HashSpaceSetLevels(space, HashspaceLow, HashspaceHigh);
842
843 // Set the gravity,, don't disable things automatically (we set it explicitly on some things)
844
845 d.WorldSetGravity(world, gravityx, gravityy, gravityz);
846 d.WorldSetContactSurfaceLayer(world, contactsurfacelayer);
847
848 d.WorldSetLinearDamping(world, 256f);
849 d.WorldSetAngularDamping(world, 256f);
850 d.WorldSetAngularDampingThreshold(world, 256f);
851 d.WorldSetLinearDampingThreshold(world, 256f);
852 d.WorldSetMaxAngularSpeed(world, 256f);
853
854 d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
855 //d.WorldSetContactMaxCorrectingVel(world, 1000.0f);
856
857 for (int i = 0; i < staticPrimspace.GetLength(0); i++)
858 {
859 for (int j = 0; j < staticPrimspace.GetLength(1); j++)
860 {
861 staticPrimspace[i, j] = IntPtr.Zero;
862 }
863 }
864
865 _worldInitialized = true;
866 }
867
868 #region Collision Detection
869
870 /// <summary>
871 /// Collides two geometries.
872 /// </summary>
873 /// <returns></returns>
874 /// <param name='geom1'></param>
875 /// <param name='geom2'>/param>
876 /// <param name='maxContacts'></param>
877 /// <param name='contactsArray'></param>
878 /// <param name='contactGeomSize'></param>
879 private int CollideGeoms(
880 IntPtr geom1, IntPtr geom2, int maxContacts, d.ContactGeom[] contactsArray, int contactGeomSize)
881 {
882 int count;
883
884 lock (OdeScene.UniversalColliderSyncObject)
885 {
886 // We do this inside the lock so that we don't count any delay in acquiring it
887 if (CollectStats)
888 m_nativeCollisionStartTick = Util.EnvironmentTickCount();
889
890 count = d.Collide(geom1, geom2, maxContacts, contactsArray, contactGeomSize);
891 }
892
893 // We do this outside the lock so that any waiting threads aren't held up, though the effect is probably
894 // negligable
895 if (CollectStats)
896 m_stats[ODENativeGeomCollisionFrameMsStatName]
897 += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick);
898
899 return count;
900 }
901
902 /// <summary>
903 /// Collide two spaces or a space and a geometry.
904 /// </summary>
905 /// <param name='space1'></param>
906 /// <param name='space2'>/param>
907 /// <param name='data'></param>
908 private void CollideSpaces(IntPtr space1, IntPtr space2, IntPtr data)
909 {
910 if (CollectStats)
911 {
912 m_inCollisionTiming = true;
913 m_nativeCollisionStartTick = Util.EnvironmentTickCount();
914 }
915
916 d.SpaceCollide2(space1, space2, data, nearCallback);
917
918 if (CollectStats && m_inCollisionTiming)
919 {
920 m_stats[ODENativeSpaceCollisionFrameMsStatName]
921 += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick);
922 m_inCollisionTiming = false;
923 }
924 }
925
926 /// <summary>
927 /// This is our near callback. A geometry is near a body
928 /// </summary>
929 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
930 /// <param name="g1">a geometry or space</param>
931 /// <param name="g2">another geometry or space</param>
932 private void near(IntPtr space, IntPtr g1, IntPtr g2)
933 {
934 if (CollectStats && m_inCollisionTiming)
935 {
936 m_stats[ODENativeSpaceCollisionFrameMsStatName]
937 += Util.EnvironmentTickCountSubtract(m_nativeCollisionStartTick);
938 m_inCollisionTiming = false;
939 }
940
941// m_log.DebugFormat("[PHYSICS]: Colliding {0} and {1} in {2}", g1, g2, space);
942 // no lock here! It's invoked from within Simulate(), which is thread-locked
943
944 // Test if we're colliding a geom with a space.
945 // If so we have to drill down into the space recursively
946
947 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
948 {
949 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
950 return;
951
952 // Separating static prim geometry spaces.
953 // We'll be calling near recursivly if one
954 // of them is a space to find all of the
955 // contact points in the space
956 try
957 {
958 CollideSpaces(g1, g2, IntPtr.Zero);
959 }
960 catch (AccessViolationException)
961 {
962 m_log.Error("[ODE SCENE]: Unable to collide test a space");
963 return;
964 }
965 //Colliding a space or a geom with a space or a geom. so drill down
966
967 //Collide all geoms in each space..
968 //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
969 //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
970 return;
971 }
972
973 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
974 return;
975
976 IntPtr b1 = d.GeomGetBody(g1);
977 IntPtr b2 = d.GeomGetBody(g2);
978
979 // d.GeomClassID id = d.GeomGetClass(g1);
980
981 String name1 = null;
982 String name2 = null;
983
984 if (!geom_name_map.TryGetValue(g1, out name1))
985 {
986 name1 = "null";
987 }
988 if (!geom_name_map.TryGetValue(g2, out name2))
989 {
990 name2 = "null";
991 }
992
993 // Figure out how many contact points we have
994 int count = 0;
995
996 try
997 {
998 // Colliding Geom To Geom
999 // This portion of the function 'was' blatantly ripped off from BoxStack.cs
1000
1001 if (g1 == g2)
1002 return; // Can't collide with yourself
1003
1004 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
1005 return;
1006
1007 count = CollideGeoms(g1, g2, contacts.Length, contacts, d.ContactGeom.unmanagedSizeOf);
1008
1009 // All code after this is only relevant if we have any collisions
1010 if (count <= 0)
1011 return;
1012
1013 if (count > contacts.Length)
1014 m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
1015 }
1016 catch (SEHException)
1017 {
1018 m_log.Error(
1019 "[ODE SCENE]: 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.");
1020 base.TriggerPhysicsBasedRestart();
1021 }
1022 catch (Exception e)
1023 {
1024 m_log.ErrorFormat("[ODE SCENE]: Unable to collide test an object: {0}", e.Message);
1025 return;
1026 }
1027
1028 PhysicsActor p1;
1029 PhysicsActor p2;
1030
1031 p1ExpectedPoints = 0;
1032 p2ExpectedPoints = 0;
1033
1034 if (!actor_name_map.TryGetValue(g1, out p1))
1035 {
1036 p1 = PANull;
1037 }
1038
1039 if (!actor_name_map.TryGetValue(g2, out p2))
1040 {
1041 p2 = PANull;
1042 }
1043
1044 ContactPoint maxDepthContact = new ContactPoint();
1045 if (p1.CollisionScore + count >= float.MaxValue)
1046 p1.CollisionScore = 0;
1047 p1.CollisionScore += count;
1048
1049 if (p2.CollisionScore + count >= float.MaxValue)
1050 p2.CollisionScore = 0;
1051 p2.CollisionScore += count;
1052
1053 for (int i = 0; i < count; i++)
1054 {
1055 d.ContactGeom curContact = contacts[i];
1056
1057 if (curContact.depth > maxDepthContact.PenetrationDepth)
1058 {
1059 maxDepthContact = new ContactPoint(
1060 new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z),
1061 new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z),
1062 curContact.depth
1063 );
1064 }
1065
1066 //m_log.Warn("[CCOUNT]: " + count);
1067 IntPtr joint;
1068 // If we're colliding with terrain, use 'TerrainContact' instead of contact.
1069 // allows us to have different settings
1070
1071 // We only need to test p2 for 'jump crouch purposes'
1072 if (p2 is OdeCharacter && p1.PhysicsActorType == (int)ActorTypes.Prim)
1073 {
1074 // Testing if the collision is at the feet of the avatar
1075
1076 //m_log.DebugFormat("[PHYSICS]: {0} - {1} - {2} - {3}", curContact.pos.Z, p2.Position.Z, (p2.Position.Z - curContact.pos.Z), (p2.Size.Z * 0.6f));
1077 if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f))
1078 p2.IsColliding = true;
1079 }
1080 else
1081 {
1082 p2.IsColliding = true;
1083 }
1084
1085 //if ((framecount % m_returncollisions) == 0)
1086
1087 switch (p1.PhysicsActorType)
1088 {
1089 case (int)ActorTypes.Agent:
1090 p1ExpectedPoints = avatarExpectedContacts;
1091 p2.CollidingObj = true;
1092 break;
1093 case (int)ActorTypes.Prim:
1094 if (p1 != null && p1 is OdePrim)
1095 p1ExpectedPoints = ((OdePrim) p1).ExpectedCollisionContacts;
1096
1097 if (p2.Velocity.LengthSquared() > 0.0f)
1098 p2.CollidingObj = true;
1099 break;
1100 case (int)ActorTypes.Unknown:
1101 p2.CollidingGround = true;
1102 break;
1103 default:
1104 p2.CollidingGround = true;
1105 break;
1106 }
1107
1108 // we don't want prim or avatar to explode
1109
1110 #region InterPenetration Handling - Unintended physics explosions
1111
1112 if (curContact.depth >= 0.08f)
1113 {
1114 if (curContact.depth >= 1.00f)
1115 {
1116 //m_log.Info("[P]: " + contact.depth.ToString());
1117 if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
1118 p1.PhysicsActorType == (int) ActorTypes.Unknown) ||
1119 (p1.PhysicsActorType == (int) ActorTypes.Agent &&
1120 p2.PhysicsActorType == (int) ActorTypes.Unknown))
1121 {
1122 if (p2.PhysicsActorType == (int) ActorTypes.Agent)
1123 {
1124 if (p2 is OdeCharacter)
1125 {
1126 OdeCharacter character = (OdeCharacter) p2;
1127
1128 //p2.CollidingObj = true;
1129 curContact.depth = 0.00000003f;
1130 p2.Velocity = p2.Velocity + new Vector3(0f, 0f, 0.5f);
1131 curContact.pos =
1132 new d.Vector3(curContact.pos.X + (p1.Size.X/2),
1133 curContact.pos.Y + (p1.Size.Y/2),
1134 curContact.pos.Z + (p1.Size.Z/2));
1135 character.SetPidStatus(true);
1136 }
1137 }
1138
1139 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
1140 {
1141 if (p1 is OdeCharacter)
1142 {
1143 OdeCharacter character = (OdeCharacter) p1;
1144
1145 //p2.CollidingObj = true;
1146 curContact.depth = 0.00000003f;
1147 p1.Velocity = p1.Velocity + new Vector3(0f, 0f, 0.5f);
1148 curContact.pos =
1149 new d.Vector3(curContact.pos.X + (p1.Size.X/2),
1150 curContact.pos.Y + (p1.Size.Y/2),
1151 curContact.pos.Z + (p1.Size.Z/2));
1152 character.SetPidStatus(true);
1153 }
1154 }
1155 }
1156 }
1157 }
1158
1159 #endregion
1160
1161 // Logic for collision handling
1162 // Note, that if *all* contacts are skipped (VolumeDetect)
1163 // The prim still detects (and forwards) collision events but
1164 // appears to be phantom for the world
1165 Boolean skipThisContact = false;
1166
1167 if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect))
1168 skipThisContact = true; // No collision on volume detect prims
1169
1170 if (av_av_collisions_off)
1171 if ((p1 is OdeCharacter) && (p2 is OdeCharacter))
1172 skipThisContact = true;
1173
1174 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect))
1175 skipThisContact = true; // No collision on volume detect prims
1176
1177 if (!skipThisContact && curContact.depth < 0f)
1178 skipThisContact = true;
1179
1180 if (!skipThisContact && checkDupe(curContact, p2.PhysicsActorType))
1181 skipThisContact = true;
1182
1183 const int maxContactsbeforedeath = 4000;
1184 joint = IntPtr.Zero;
1185
1186 if (!skipThisContact)
1187 {
1188 _perloopContact.Add(curContact);
1189
1190 if (name1 == "Terrain" || name2 == "Terrain")
1191 {
1192 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
1193 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
1194 {
1195 p2ExpectedPoints = avatarExpectedContacts;
1196 // Avatar is moving on terrain, use the movement terrain contact
1197 AvatarMovementTerrainContact.geom = curContact;
1198
1199 if (m_global_contactcount < maxContactsbeforedeath)
1200 {
1201 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
1202 m_global_contactcount++;
1203 }
1204 }
1205 else
1206 {
1207 if (p2.PhysicsActorType == (int)ActorTypes.Agent)
1208 {
1209 p2ExpectedPoints = avatarExpectedContacts;
1210 // Avatar is standing on terrain, use the non moving terrain contact
1211 TerrainContact.geom = curContact;
1212
1213 if (m_global_contactcount < maxContactsbeforedeath)
1214 {
1215 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
1216 m_global_contactcount++;
1217 }
1218 }
1219 else
1220 {
1221 if (p2.PhysicsActorType == (int)ActorTypes.Prim && p1.PhysicsActorType == (int)ActorTypes.Prim)
1222 {
1223 // prim prim contact
1224 // int pj294950 = 0;
1225 int movintYN = 0;
1226 int material = (int) Material.Wood;
1227 // prim terrain contact
1228 if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)
1229 {
1230 movintYN = 1;
1231 }
1232
1233 if (p2 is OdePrim)
1234 {
1235 material = ((OdePrim) p2).m_material;
1236 p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts;
1237 }
1238
1239 // Unnessesary because p1 is defined above
1240 //if (p1 is OdePrim)
1241 // {
1242 // p1ExpectedPoints = ((OdePrim)p1).ExpectedCollisionContacts;
1243 // }
1244 //m_log.DebugFormat("Material: {0}", material);
1245
1246 m_materialContacts[material, movintYN].geom = curContact;
1247
1248 if (m_global_contactcount < maxContactsbeforedeath)
1249 {
1250 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]);
1251 m_global_contactcount++;
1252 }
1253 }
1254 else
1255 {
1256 int movintYN = 0;
1257 // prim terrain contact
1258 if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)
1259 {
1260 movintYN = 1;
1261 }
1262
1263 int material = (int)Material.Wood;
1264
1265 if (p2 is OdePrim)
1266 {
1267 material = ((OdePrim)p2).m_material;
1268 p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts;
1269 }
1270
1271 //m_log.DebugFormat("Material: {0}", material);
1272 m_materialContacts[material, movintYN].geom = curContact;
1273
1274 if (m_global_contactcount < maxContactsbeforedeath)
1275 {
1276 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]);
1277 m_global_contactcount++;
1278 }
1279 }
1280 }
1281 }
1282 //if (p2.PhysicsActorType == (int)ActorTypes.Prim)
1283 //{
1284 //m_log.Debug("[PHYSICS]: prim contacting with ground");
1285 //}
1286 }
1287 else if (name1 == "Water" || name2 == "Water")
1288 {
1289 /*
1290 if ((p2.PhysicsActorType == (int) ActorTypes.Prim))
1291 {
1292 }
1293 else
1294 {
1295 }
1296 */
1297 //WaterContact.surface.soft_cfm = 0.0000f;
1298 //WaterContact.surface.soft_erp = 0.00000f;
1299 if (curContact.depth > 0.1f)
1300 {
1301 curContact.depth *= 52;
1302 //contact.normal = new d.Vector3(0, 0, 1);
1303 //contact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f);
1304 }
1305
1306 WaterContact.geom = curContact;
1307
1308 if (m_global_contactcount < maxContactsbeforedeath)
1309 {
1310 joint = d.JointCreateContact(world, contactgroup, ref WaterContact);
1311 m_global_contactcount++;
1312 }
1313 //m_log.Info("[PHYSICS]: Prim Water Contact" + contact.depth);
1314 }
1315 else
1316 {
1317 if ((p2.PhysicsActorType == (int)ActorTypes.Agent))
1318 {
1319 p2ExpectedPoints = avatarExpectedContacts;
1320 if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
1321 {
1322 // Avatar is moving on a prim, use the Movement prim contact
1323 AvatarMovementprimContact.geom = curContact;
1324
1325 if (m_global_contactcount < maxContactsbeforedeath)
1326 {
1327 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact);
1328 m_global_contactcount++;
1329 }
1330 }
1331 else
1332 {
1333 // Avatar is standing still on a prim, use the non movement contact
1334 contact.geom = curContact;
1335
1336 if (m_global_contactcount < maxContactsbeforedeath)
1337 {
1338 joint = d.JointCreateContact(world, contactgroup, ref contact);
1339 m_global_contactcount++;
1340 }
1341 }
1342 }
1343 else if (p2.PhysicsActorType == (int)ActorTypes.Prim)
1344 {
1345 //p1.PhysicsActorType
1346 int material = (int)Material.Wood;
1347
1348 if (p2 is OdePrim)
1349 {
1350 material = ((OdePrim)p2).m_material;
1351 p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts;
1352 }
1353
1354 //m_log.DebugFormat("Material: {0}", material);
1355 m_materialContacts[material, 0].geom = curContact;
1356
1357 if (m_global_contactcount < maxContactsbeforedeath)
1358 {
1359 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, 0]);
1360 m_global_contactcount++;
1361 }
1362 }
1363 }
1364
1365 if (m_global_contactcount < maxContactsbeforedeath && joint != IntPtr.Zero) // stack collide!
1366 {
1367 d.JointAttach(joint, b1, b2);
1368 m_global_contactcount++;
1369 }
1370 }
1371
1372 collision_accounting_events(p1, p2, maxDepthContact);
1373
1374 if (count > ((p1ExpectedPoints + p2ExpectedPoints) * 0.25) + (geomContactPointsStartthrottle))
1375 {
1376 // If there are more then 3 contact points, it's likely
1377 // that we've got a pile of objects, so ...
1378 // We don't want to send out hundreds of terse updates over and over again
1379 // so lets throttle them and send them again after it's somewhat sorted out.
1380 p2.ThrottleUpdates = true;
1381 }
1382 //m_log.Debug(count.ToString());
1383 //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2);
1384 }
1385 }
1386
1387 private bool checkDupe(d.ContactGeom contactGeom, int atype)
1388 {
1389 if (!m_filterCollisions)
1390 return false;
1391
1392 bool result = false;
1393
1394 ActorTypes at = (ActorTypes)atype;
1395
1396 foreach (d.ContactGeom contact in _perloopContact)
1397 {
1398 //if ((contact.g1 == contactGeom.g1 && contact.g2 == contactGeom.g2))
1399 //{
1400 // || (contact.g2 == contactGeom.g1 && contact.g1 == contactGeom.g2)
1401 if (at == ActorTypes.Agent)
1402 {
1403 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f)
1404 && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f)
1405 && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)))
1406 {
1407 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f)
1408 {
1409 result = true;
1410 break;
1411 }
1412 }
1413 }
1414 else if (at == ActorTypes.Prim)
1415 {
1416 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)))
1417 {
1418 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z)
1419 {
1420 if (Math.Abs(contact.depth - contactGeom.depth) < 0.272f)
1421 {
1422 result = true;
1423 break;
1424 }
1425 }
1426 //m_log.DebugFormat("[Collision]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1427 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1428 }
1429 }
1430 }
1431
1432 return result;
1433 }
1434
1435 private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact)
1436 {
1437 // obj1LocalID = 0;
1438 //returncollisions = false;
1439 obj2LocalID = 0;
1440 //ctype = 0;
1441 //cStartStop = 0;
1442// if (!p2.SubscribedEvents() && !p1.SubscribedEvents())
1443// return;
1444 bool p1events = p1.SubscribedEvents();
1445 bool p2events = p2.SubscribedEvents();
1446
1447 if (p1.IsVolumeDtc)
1448 p2events = false;
1449 if (p2.IsVolumeDtc)
1450 p1events = false;
1451
1452 if (!p2events && !p1events)
1453 return;
1454
1455 Vector3 vel = Vector3.Zero;
1456 if (p2 != null && p2.IsPhysical)
1457 vel = p2.Velocity;
1458
1459 if (p1 != null && p1.IsPhysical)
1460 vel -= p1.Velocity;
1461
1462 contact.RelativeSpeed = Vector3.Dot(vel, contact.SurfaceNormal);
1463
1464 switch ((ActorTypes)p2.PhysicsActorType)
1465 {
1466 case ActorTypes.Agent:
1467 cc2 = (OdeCharacter)p2;
1468
1469 // obj1LocalID = cc2.m_localID;
1470 switch ((ActorTypes)p1.PhysicsActorType)
1471 {
1472 case ActorTypes.Agent:
1473 cc1 = (OdeCharacter)p1;
1474 obj2LocalID = cc1.LocalID;
1475 cc1.AddCollisionEvent(cc2.LocalID, contact);
1476 break;
1477
1478 case ActorTypes.Prim:
1479 if (p1 is OdePrim)
1480 {
1481 cp1 = (OdePrim) p1;
1482 obj2LocalID = cp1.LocalID;
1483 cp1.AddCollisionEvent(cc2.LocalID, contact);
1484 }
1485 break;
1486
1487 case ActorTypes.Ground:
1488 case ActorTypes.Unknown:
1489 obj2LocalID = 0;
1490 break;
1491 }
1492
1493 cc2.AddCollisionEvent(obj2LocalID, contact);
1494 break;
1495
1496 case ActorTypes.Prim:
1497
1498 if (p2 is OdePrim)
1499 {
1500 cp2 = (OdePrim) p2;
1501
1502 // obj1LocalID = cp2.m_localID;
1503 switch ((ActorTypes) p1.PhysicsActorType)
1504 {
1505 case ActorTypes.Agent:
1506 if (p1 is OdeCharacter)
1507 {
1508 cc1 = (OdeCharacter) p1;
1509 obj2LocalID = cc1.LocalID;
1510 cc1.AddCollisionEvent(cp2.LocalID, contact);
1511 }
1512 break;
1513 case ActorTypes.Prim:
1514
1515 if (p1 is OdePrim)
1516 {
1517 cp1 = (OdePrim) p1;
1518 obj2LocalID = cp1.LocalID;
1519 cp1.AddCollisionEvent(cp2.LocalID, contact);
1520 }
1521 break;
1522
1523 case ActorTypes.Ground:
1524 case ActorTypes.Unknown:
1525 obj2LocalID = 0;
1526 break;
1527 }
1528
1529 cp2.AddCollisionEvent(obj2LocalID, contact);
1530 }
1531 break;
1532 }
1533 }
1534 /// <summary>
1535 /// This is our collision testing routine in ODE
1536 /// </summary>
1537 private void collision_optimized()
1538 {
1539 _perloopContact.Clear();
1540
1541 foreach (OdeCharacter chr in _characters)
1542 {
1543 // Reset the collision values to false
1544 // since we don't know if we're colliding yet
1545 if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero)
1546 continue;
1547
1548 chr.IsColliding = false;
1549 chr.CollidingGround = false;
1550 chr.CollidingObj = false;
1551
1552 // Test the avatar's geometry for collision with the space
1553 // This will return near and the space that they are the closest to
1554 // And we'll run this again against the avatar and the space segment
1555 // This will return with a bunch of possible objects in the space segment
1556 // and we'll run it again on all of them.
1557 try
1558 {
1559 CollideSpaces(space, chr.Shell, IntPtr.Zero);
1560 }
1561 catch (AccessViolationException)
1562 {
1563 m_log.ErrorFormat("[ODE SCENE]: Unable to space collide {0}", PhysicsSceneName);
1564 }
1565
1566 //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y);
1567 //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10)
1568 //{
1569 //chr.Position.Z = terrainheight + 10.0f;
1570 //forcedZ = true;
1571 //}
1572 }
1573
1574 if (CollectStats)
1575 {
1576 m_tempAvatarCollisionsThisFrame = _perloopContact.Count;
1577 m_stats[ODEAvatarContactsStatsName] += m_tempAvatarCollisionsThisFrame;
1578 }
1579
1580 List<OdePrim> removeprims = null;
1581 foreach (OdePrim chr in _activeprims)
1582 {
1583 if (chr.Body != IntPtr.Zero && d.BodyIsEnabled(chr.Body) && (!chr.m_disabled))
1584 {
1585 try
1586 {
1587 lock (chr)
1588 {
1589 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false)
1590 {
1591 CollideSpaces(space, chr.prim_geom, IntPtr.Zero);
1592 }
1593 else
1594 {
1595 if (removeprims == null)
1596 {
1597 removeprims = new List<OdePrim>();
1598 }
1599 removeprims.Add(chr);
1600 m_log.Error(
1601 "[ODE SCENE]: unable to collide test active prim against space. The space was zero, the geom was zero or it was in the process of being removed. Removed it from the active prim list. This needs to be fixed!");
1602 }
1603 }
1604 }
1605 catch (AccessViolationException)
1606 {
1607 m_log.Error("[ODE SCENE]: Unable to space collide");
1608 }
1609 }
1610 }
1611
1612 if (CollectStats)
1613 m_stats[ODEPrimContactsStatName] += _perloopContact.Count - m_tempAvatarCollisionsThisFrame;
1614
1615 if (removeprims != null)
1616 {
1617 foreach (OdePrim chr in removeprims)
1618 {
1619 _activeprims.Remove(chr);
1620 }
1621 }
1622 }
1623
1624 #endregion
1625
1626 // Recovered for use by fly height. Kitto Flora
1627 internal float GetTerrainHeightAtXY(float x, float y)
1628 {
1629 IntPtr heightFieldGeom = IntPtr.Zero;
1630 int offsetX = 0;
1631 int offsetY = 0;
1632
1633 if(RegionTerrain.TryGetValue(new Vector3(offsetX,offsetY,0), out heightFieldGeom))
1634 {
1635 if (heightFieldGeom != IntPtr.Zero)
1636 {
1637 if (TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
1638 {
1639
1640 int index;
1641
1642
1643 if ((int)x > WorldExtents.X || (int)y > WorldExtents.Y ||
1644 (int)x < 0.001f || (int)y < 0.001f)
1645 return 0;
1646
1647 x = x - offsetX + 1f;
1648 y = y - offsetY + 1f;
1649
1650 // map is rotated
1651 index = (int)x * ((int)m_regionHeight + 3) + (int)y;
1652
1653 if (index < TerrainHeightFieldHeights[heightFieldGeom].Length)
1654 {
1655 //m_log.DebugFormat("x{0} y{1} = {2}", x, y, (float)TerrainHeightFieldHeights[heightFieldGeom][index]);
1656 return (float)TerrainHeightFieldHeights[heightFieldGeom][index];
1657 }
1658
1659 else
1660 return 0f;
1661 }
1662 else
1663 {
1664 return 0f;
1665 }
1666
1667 }
1668 else
1669 {
1670 return 0f;
1671 }
1672
1673 }
1674 else
1675 {
1676 return 0f;
1677 }
1678 }
1679// End recovered. Kitto Flora
1680
1681 /// <summary>
1682 /// Add actor to the list that should receive collision events in the simulate loop.
1683 /// </summary>
1684 /// <param name="obj"></param>
1685 internal void AddCollisionEventReporting(PhysicsActor obj)
1686 {
1687// m_log.DebugFormat("[PHYSICS]: Adding {0} {1} to collision event reporting", obj.SOPName, obj.LocalID);
1688
1689 lock (m_collisionEventActorsChanges)
1690 m_collisionEventActorsChanges[obj.LocalID] = obj;
1691 }
1692
1693 /// <summary>
1694 /// Remove actor from the list that should receive collision events in the simulate loop.
1695 /// </summary>
1696 /// <param name="obj"></param>
1697 internal void RemoveCollisionEventReporting(PhysicsActor obj)
1698 {
1699// m_log.DebugFormat("[PHYSICS]: Removing {0} {1} from collision event reporting", obj.SOPName, obj.LocalID);
1700
1701 lock (m_collisionEventActorsChanges)
1702 m_collisionEventActorsChanges[obj.LocalID] = null;
1703 }
1704
1705 #region Add/Remove Entities
1706
1707 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying)
1708 {
1709 d.AllocateODEDataForThread(0);
1710
1711 OdeCharacter newAv
1712 = new OdeCharacter(
1713 avName, this, position, velocity, size, avPIDD, avPIDP,
1714 avCapRadius, avStandupTensor, avDensity,
1715 avMovementDivisorWalk, avMovementDivisorRun);
1716
1717 newAv.Flying = isFlying;
1718 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1719 newAv.m_avatarplanted = avplanted;
1720
1721 return newAv;
1722 }
1723
1724 public override void RemoveAvatar(PhysicsActor actor)
1725 {
1726// m_log.DebugFormat(
1727// "[ODE SCENE]: Removing physics character {0} {1} from physics scene {2}",
1728// actor.Name, actor.LocalID, Name);
1729
1730 lock (OdeLock)
1731 {
1732 d.AllocateODEDataForThread(0);
1733
1734 ((OdeCharacter) actor).Destroy();
1735 }
1736 }
1737
1738 internal void AddCharacter(OdeCharacter chr)
1739 {
1740 chr.m_avatarplanted = avplanted;
1741 if (!_characters.Contains(chr))
1742 {
1743 _characters.Add(chr);
1744
1745// m_log.DebugFormat(
1746// "[ODE SCENE]: Adding physics character {0} {1} to physics scene {2}. Count now {3}",
1747// chr.Name, chr.LocalID, Name, _characters.Count);
1748
1749 if (chr.bad)
1750 m_log.ErrorFormat("[ODE SCENE]: Added BAD actor {0} to characters list", chr.m_uuid);
1751 }
1752 else
1753 {
1754 m_log.ErrorFormat(
1755 "[ODE SCENE]: Tried to add character {0} {1} but they are already in the set!",
1756 chr.Name, chr.LocalID);
1757 }
1758 }
1759
1760 internal void RemoveCharacter(OdeCharacter chr)
1761 {
1762 if (_characters.Contains(chr))
1763 {
1764 _characters.Remove(chr);
1765
1766// m_log.DebugFormat(
1767// "[ODE SCENE]: Removing physics character {0} {1} from physics scene {2}. Count now {3}",
1768// chr.Name, chr.LocalID, Name, _characters.Count);
1769 }
1770 else
1771 {
1772 m_log.ErrorFormat(
1773 "[ODE SCENE]: Tried to remove character {0} {1} but they are not in the list!",
1774 chr.Name, chr.LocalID);
1775 }
1776 }
1777
1778 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
1779 PrimitiveBaseShape pbs, bool isphysical, uint localID)
1780 {
1781 Vector3 pos = position;
1782 Vector3 siz = size;
1783 Quaternion rot = rotation;
1784
1785
1786 OdePrim newPrim;
1787 lock (OdeLock)
1788 {
1789 d.AllocateODEDataForThread(0);
1790 newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical);
1791
1792 lock (_prims)
1793 _prims.Add(newPrim);
1794 }
1795 newPrim.LocalID = localID;
1796 return newPrim;
1797 }
1798
1799 /// <summary>
1800 /// Make this prim subject to physics.
1801 /// </summary>
1802 /// <param name="prim"></param>
1803 internal void ActivatePrim(OdePrim prim)
1804 {
1805 // adds active prim.. (ones that should be iterated over in collisions_optimized
1806 if (!_activeprims.Contains(prim))
1807 _activeprims.Add(prim);
1808 //else
1809 // m_log.Warn("[PHYSICS]: Double Entry in _activeprims detected, potential crash immenent");
1810 }
1811
1812 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1813 Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
1814 {
1815// m_log.DebugFormat("[ODE SCENE]: Adding physics prim {0} {1} to physics scene {2}", primName, localid, Name);
1816
1817 return AddPrim(primName, position, size, rotation, pbs, isPhysical, localid);
1818 }
1819
1820 public override float TimeDilation
1821 {
1822 get { return m_timeDilation; }
1823 }
1824
1825 public override bool SupportsNINJAJoints
1826 {
1827 get { return m_NINJA_physics_joints_enabled; }
1828 }
1829
1830 // internal utility function: must be called within a lock (OdeLock)
1831 private void InternalAddActiveJoint(PhysicsJoint joint)
1832 {
1833 activeJoints.Add(joint);
1834 SOPName_to_activeJoint.Add(joint.ObjectNameInScene, joint);
1835 }
1836
1837 // internal utility function: must be called within a lock (OdeLock)
1838 private void InternalAddPendingJoint(OdePhysicsJoint joint)
1839 {
1840 pendingJoints.Add(joint);
1841 SOPName_to_pendingJoint.Add(joint.ObjectNameInScene, joint);
1842 }
1843
1844 // internal utility function: must be called within a lock (OdeLock)
1845 private void InternalRemovePendingJoint(PhysicsJoint joint)
1846 {
1847 pendingJoints.Remove(joint);
1848 SOPName_to_pendingJoint.Remove(joint.ObjectNameInScene);
1849 }
1850
1851 // internal utility function: must be called within a lock (OdeLock)
1852 private void InternalRemoveActiveJoint(PhysicsJoint joint)
1853 {
1854 activeJoints.Remove(joint);
1855 SOPName_to_activeJoint.Remove(joint.ObjectNameInScene);
1856 }
1857
1858 public override void DumpJointInfo()
1859 {
1860 string hdr = "[NINJA] JOINTINFO: ";
1861 foreach (PhysicsJoint j in pendingJoints)
1862 {
1863 m_log.Debug(hdr + " pending joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams);
1864 }
1865 m_log.Debug(hdr + pendingJoints.Count + " total pending joints");
1866 foreach (string jointName in SOPName_to_pendingJoint.Keys)
1867 {
1868 m_log.Debug(hdr + " pending joints dict contains Name: " + jointName);
1869 }
1870 m_log.Debug(hdr + SOPName_to_pendingJoint.Keys.Count + " total pending joints dict entries");
1871 foreach (PhysicsJoint j in activeJoints)
1872 {
1873 m_log.Debug(hdr + " active joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams);
1874 }
1875 m_log.Debug(hdr + activeJoints.Count + " total active joints");
1876 foreach (string jointName in SOPName_to_activeJoint.Keys)
1877 {
1878 m_log.Debug(hdr + " active joints dict contains Name: " + jointName);
1879 }
1880 m_log.Debug(hdr + SOPName_to_activeJoint.Keys.Count + " total active joints dict entries");
1881
1882 m_log.Debug(hdr + " Per-body joint connectivity information follows.");
1883 m_log.Debug(hdr + joints_connecting_actor.Keys.Count + " bodies are connected by joints.");
1884 foreach (string actorName in joints_connecting_actor.Keys)
1885 {
1886 m_log.Debug(hdr + " Actor " + actorName + " has the following joints connecting it");
1887 foreach (PhysicsJoint j in joints_connecting_actor[actorName])
1888 {
1889 m_log.Debug(hdr + " * joint Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams);
1890 }
1891 m_log.Debug(hdr + joints_connecting_actor[actorName].Count + " connecting joints total for this actor");
1892 }
1893 }
1894
1895 public override void RequestJointDeletion(string ObjectNameInScene)
1896 {
1897 lock (externalJointRequestsLock)
1898 {
1899 if (!requestedJointsToBeDeleted.Contains(ObjectNameInScene)) // forbid same deletion request from entering twice to prevent spurious deletions processed asynchronously
1900 {
1901 requestedJointsToBeDeleted.Add(ObjectNameInScene);
1902 }
1903 }
1904 }
1905
1906 private void DeleteRequestedJoints()
1907 {
1908 List<string> myRequestedJointsToBeDeleted;
1909 lock (externalJointRequestsLock)
1910 {
1911 // make a local copy of the shared list for processing (threading issues)
1912 myRequestedJointsToBeDeleted = new List<string>(requestedJointsToBeDeleted);
1913 }
1914
1915 foreach (string jointName in myRequestedJointsToBeDeleted)
1916 {
1917 lock (OdeLock)
1918 {
1919 //m_log.Debug("[NINJA] trying to deleting requested joint " + jointName);
1920 if (SOPName_to_activeJoint.ContainsKey(jointName) || SOPName_to_pendingJoint.ContainsKey(jointName))
1921 {
1922 OdePhysicsJoint joint = null;
1923 if (SOPName_to_activeJoint.ContainsKey(jointName))
1924 {
1925 joint = SOPName_to_activeJoint[jointName] as OdePhysicsJoint;
1926 InternalRemoveActiveJoint(joint);
1927 }
1928 else if (SOPName_to_pendingJoint.ContainsKey(jointName))
1929 {
1930 joint = SOPName_to_pendingJoint[jointName] as OdePhysicsJoint;
1931 InternalRemovePendingJoint(joint);
1932 }
1933
1934 if (joint != null)
1935 {
1936 //m_log.Debug("joint.BodyNames.Count is " + joint.BodyNames.Count + " and contents " + joint.BodyNames);
1937 for (int iBodyName = 0; iBodyName < 2; iBodyName++)
1938 {
1939 string bodyName = joint.BodyNames[iBodyName];
1940 if (bodyName != "NULL")
1941 {
1942 joints_connecting_actor[bodyName].Remove(joint);
1943 if (joints_connecting_actor[bodyName].Count == 0)
1944 {
1945 joints_connecting_actor.Remove(bodyName);
1946 }
1947 }
1948 }
1949
1950 DoJointDeactivated(joint);
1951 if (joint.jointID != IntPtr.Zero)
1952 {
1953 d.JointDestroy(joint.jointID);
1954 joint.jointID = IntPtr.Zero;
1955 //DoJointErrorMessage(joint, "successfully destroyed joint " + jointName);
1956 }
1957 else
1958 {
1959 //m_log.Warn("[NINJA] Ignoring re-request to destroy joint " + jointName);
1960 }
1961 }
1962 else
1963 {
1964 // DoJointErrorMessage(joint, "coult not find joint to destroy based on name " + jointName);
1965 }
1966 }
1967 else
1968 {
1969 // DoJointErrorMessage(joint, "WARNING - joint removal failed, joint " + jointName);
1970 }
1971 }
1972 }
1973
1974 // remove processed joints from the shared list
1975 lock (externalJointRequestsLock)
1976 {
1977 foreach (string jointName in myRequestedJointsToBeDeleted)
1978 {
1979 requestedJointsToBeDeleted.Remove(jointName);
1980 }
1981 }
1982 }
1983
1984 // for pending joints we don't know if their associated bodies exist yet or not.
1985 // the joint is actually created during processing of the taints
1986 private void CreateRequestedJoints()
1987 {
1988 List<PhysicsJoint> myRequestedJointsToBeCreated;
1989 lock (externalJointRequestsLock)
1990 {
1991 // make a local copy of the shared list for processing (threading issues)
1992 myRequestedJointsToBeCreated = new List<PhysicsJoint>(requestedJointsToBeCreated);
1993 }
1994
1995 foreach (PhysicsJoint joint in myRequestedJointsToBeCreated)
1996 {
1997 lock (OdeLock)
1998 {
1999 if (SOPName_to_pendingJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_pendingJoint[joint.ObjectNameInScene] != null)
2000 {
2001 DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already pending joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation);
2002 continue;
2003 }
2004 if (SOPName_to_activeJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_activeJoint[joint.ObjectNameInScene] != null)
2005 {
2006 DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already active joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation);
2007 continue;
2008 }
2009
2010 InternalAddPendingJoint(joint as OdePhysicsJoint);
2011
2012 if (joint.BodyNames.Count >= 2)
2013 {
2014 for (int iBodyName = 0; iBodyName < 2; iBodyName++)
2015 {
2016 string bodyName = joint.BodyNames[iBodyName];
2017 if (bodyName != "NULL")
2018 {
2019 if (!joints_connecting_actor.ContainsKey(bodyName))
2020 {
2021 joints_connecting_actor.Add(bodyName, new List<PhysicsJoint>());
2022 }
2023 joints_connecting_actor[bodyName].Add(joint);
2024 }
2025 }
2026 }
2027 }
2028 }
2029
2030 // remove processed joints from shared list
2031 lock (externalJointRequestsLock)
2032 {
2033 foreach (PhysicsJoint joint in myRequestedJointsToBeCreated)
2034 {
2035 requestedJointsToBeCreated.Remove(joint);
2036 }
2037 }
2038 }
2039
2040 /// <summary>
2041 /// Add a request for joint creation.
2042 /// </summary>
2043 /// <remarks>
2044 /// this joint will just be added to a waiting list that is NOT processed during the main
2045 /// Simulate() loop (to avoid deadlocks). After Simulate() is finished, we handle unprocessed joint requests.
2046 /// </remarks>
2047 /// <param name="objectNameInScene"></param>
2048 /// <param name="jointType"></param>
2049 /// <param name="position"></param>
2050 /// <param name="rotation"></param>
2051 /// <param name="parms"></param>
2052 /// <param name="bodyNames"></param>
2053 /// <param name="trackedBodyName"></param>
2054 /// <param name="localRotation"></param>
2055 /// <returns></returns>
2056 public override PhysicsJoint RequestJointCreation(
2057 string objectNameInScene, PhysicsJointType jointType, Vector3 position,
2058 Quaternion rotation, string parms, List<string> bodyNames, string trackedBodyName, Quaternion localRotation)
2059 {
2060 OdePhysicsJoint joint = new OdePhysicsJoint();
2061 joint.ObjectNameInScene = objectNameInScene;
2062 joint.Type = jointType;
2063 joint.Position = position;
2064 joint.Rotation = rotation;
2065 joint.RawParams = parms;
2066 joint.BodyNames = new List<string>(bodyNames);
2067 joint.TrackedBodyName = trackedBodyName;
2068 joint.LocalRotation = localRotation;
2069 joint.jointID = IntPtr.Zero;
2070 joint.ErrorMessageCount = 0;
2071
2072 lock (externalJointRequestsLock)
2073 {
2074 if (!requestedJointsToBeCreated.Contains(joint)) // forbid same creation request from entering twice
2075 {
2076 requestedJointsToBeCreated.Add(joint);
2077 }
2078 }
2079
2080 return joint;
2081 }
2082
2083 private void RemoveAllJointsConnectedToActor(PhysicsActor actor)
2084 {
2085 //m_log.Debug("RemoveAllJointsConnectedToActor: start");
2086 if (actor.SOPName != null && joints_connecting_actor.ContainsKey(actor.SOPName) && joints_connecting_actor[actor.SOPName] != null)
2087 {
2088 List<PhysicsJoint> jointsToRemove = new List<PhysicsJoint>();
2089 //TODO: merge these 2 loops (originally it was needed to avoid altering a list being iterated over, but it is no longer needed due to the joint request queue mechanism)
2090 foreach (PhysicsJoint j in joints_connecting_actor[actor.SOPName])
2091 {
2092 jointsToRemove.Add(j);
2093 }
2094 foreach (PhysicsJoint j in jointsToRemove)
2095 {
2096 //m_log.Debug("RemoveAllJointsConnectedToActor: about to request deletion of " + j.ObjectNameInScene);
2097 RequestJointDeletion(j.ObjectNameInScene);
2098 //m_log.Debug("RemoveAllJointsConnectedToActor: done request deletion of " + j.ObjectNameInScene);
2099 j.TrackedBodyName = null; // *IMMEDIATELY* prevent any further movement of this joint (else a deleted actor might cause spurious tracking motion of the joint for a few frames, leading to the joint proxy object disappearing)
2100 }
2101 }
2102 }
2103
2104 public override void RemoveAllJointsConnectedToActorThreadLocked(PhysicsActor actor)
2105 {
2106 //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: start");
2107 lock (OdeLock)
2108 {
2109 //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: got lock");
2110 RemoveAllJointsConnectedToActor(actor);
2111 }
2112 }
2113
2114 // normally called from within OnJointMoved, which is called from within a lock (OdeLock)
2115 public override Vector3 GetJointAnchor(PhysicsJoint joint)
2116 {
2117 Debug.Assert(joint.IsInPhysicsEngine);
2118 d.Vector3 pos = new d.Vector3();
2119
2120 if (!(joint is OdePhysicsJoint))
2121 {
2122 DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene);
2123 }
2124 else
2125 {
2126 OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint;
2127 switch (odeJoint.Type)
2128 {
2129 case PhysicsJointType.Ball:
2130 d.JointGetBallAnchor(odeJoint.jointID, out pos);
2131 break;
2132 case PhysicsJointType.Hinge:
2133 d.JointGetHingeAnchor(odeJoint.jointID, out pos);
2134 break;
2135 }
2136 }
2137 return new Vector3(pos.X, pos.Y, pos.Z);
2138 }
2139
2140 /// <summary>
2141 /// Get joint axis.
2142 /// </summary>
2143 /// <remarks>
2144 /// normally called from within OnJointMoved, which is called from within a lock (OdeLock)
2145 /// WARNING: ODE sometimes returns <0,0,0> as the joint axis! Therefore this function
2146 /// appears to be unreliable. Fortunately we can compute the joint axis ourselves by
2147 /// keeping track of the joint's original orientation relative to one of the involved bodies.
2148 /// </remarks>
2149 /// <param name="joint"></param>
2150 /// <returns></returns>
2151 public override Vector3 GetJointAxis(PhysicsJoint joint)
2152 {
2153 Debug.Assert(joint.IsInPhysicsEngine);
2154 d.Vector3 axis = new d.Vector3();
2155
2156 if (!(joint is OdePhysicsJoint))
2157 {
2158 DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene);
2159 }
2160 else
2161 {
2162 OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint;
2163 switch (odeJoint.Type)
2164 {
2165 case PhysicsJointType.Ball:
2166 DoJointErrorMessage(joint, "warning - axis requested for ball joint: " + joint.ObjectNameInScene);
2167 break;
2168 case PhysicsJointType.Hinge:
2169 d.JointGetHingeAxis(odeJoint.jointID, out axis);
2170 break;
2171 }
2172 }
2173 return new Vector3(axis.X, axis.Y, axis.Z);
2174 }
2175
2176 /// <summary>
2177 /// Stop this prim being subject to physics
2178 /// </summary>
2179 /// <param name="prim"></param>
2180 internal void DeactivatePrim(OdePrim prim)
2181 {
2182 _activeprims.Remove(prim);
2183 }
2184
2185 public override void RemovePrim(PhysicsActor prim)
2186 {
2187 // As with all ODE physics operations, we don't remove the prim immediately but signal that it should be
2188 // removed in the next physics simulate pass.
2189 if (prim is OdePrim)
2190 {
2191 lock (OdeLock)
2192 {
2193 OdePrim p = (OdePrim) prim;
2194
2195 p.setPrimForRemoval();
2196 AddPhysicsActorTaint(prim);
2197 }
2198 }
2199 }
2200
2201 /// <summary>
2202 /// This is called from within simulate but outside the locked portion
2203 /// We need to do our own locking here
2204 /// (Note: As of 20110801 this no longer appears to be true - this is being called within lock (odeLock) in
2205 /// Simulate() -- justincc).
2206 ///
2207 /// Essentially, we need to remove the prim from our space segment, whatever segment it's in.
2208 ///
2209 /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory
2210 /// that the space was using.
2211 /// </summary>
2212 /// <param name="prim"></param>
2213 internal void RemovePrimThreadLocked(OdePrim prim)
2214 {
2215// m_log.DebugFormat("[ODE SCENE]: Removing physical prim {0} {1}", prim.Name, prim.LocalID);
2216
2217 lock (prim)
2218 {
2219 RemoveCollisionEventReporting(prim);
2220
2221 if (prim.prim_geom != IntPtr.Zero)
2222 {
2223 prim.ResetTaints();
2224
2225 if (prim.IsPhysical)
2226 {
2227 prim.disableBody();
2228 if (prim.childPrim)
2229 {
2230 prim.childPrim = false;
2231 prim.Body = IntPtr.Zero;
2232 prim.m_disabled = true;
2233 prim.IsPhysical = false;
2234 }
2235
2236
2237 }
2238 prim.m_targetSpace = IntPtr.Zero;
2239 if (!prim.RemoveGeom())
2240 m_log.Warn("[ODE SCENE]: Unable to remove prim from physics scene");
2241
2242 lock (_prims)
2243 _prims.Remove(prim);
2244
2245
2246 if (SupportsNINJAJoints)
2247 RemoveAllJointsConnectedToActorThreadLocked(prim);
2248 }
2249 }
2250 }
2251
2252 #endregion
2253
2254 #region Space Separation Calculation
2255
2256 /// <summary>
2257 /// Takes a space pointer and zeros out the array we're using to hold the spaces
2258 /// </summary>
2259 /// <param name="pSpace"></param>
2260 private void resetSpaceArrayItemToZero(IntPtr pSpace)
2261 {
2262 for (int x = 0; x < staticPrimspace.GetLength(0); x++)
2263 {
2264 for (int y = 0; y < staticPrimspace.GetLength(1); y++)
2265 {
2266 if (staticPrimspace[x, y] == pSpace)
2267 staticPrimspace[x, y] = IntPtr.Zero;
2268 }
2269 }
2270 }
2271
2272// private void resetSpaceArrayItemToZero(int arrayitemX, int arrayitemY)
2273// {
2274// staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero;
2275// }
2276
2277 /// <summary>
2278 /// Called when a static prim moves. Allocates a space for the prim based on its position
2279 /// </summary>
2280 /// <param name="geom">the pointer to the geom that moved</param>
2281 /// <param name="pos">the position that the geom moved to</param>
2282 /// <param name="currentspace">a pointer to the space it was in before it was moved.</param>
2283 /// <returns>a pointer to the new space it's in</returns>
2284 internal IntPtr recalculateSpaceForGeom(IntPtr geom, Vector3 pos, IntPtr currentspace)
2285 {
2286 // Called from setting the Position and Size of an ODEPrim so
2287 // it's already in locked space.
2288
2289 // we don't want to remove the main space
2290 // we don't need to test physical here because this function should
2291 // never be called if the prim is physical(active)
2292
2293 // All physical prim end up in the root space
2294 //Thread.Sleep(20);
2295 if (currentspace != space)
2296 {
2297 //m_log.Info("[SPACE]: C:" + currentspace.ToString() + " g:" + geom.ToString());
2298 //if (currentspace == IntPtr.Zero)
2299 //{
2300 //int adfadf = 0;
2301 //}
2302 if (d.SpaceQuery(currentspace, geom) && currentspace != IntPtr.Zero)
2303 {
2304 if (d.GeomIsSpace(currentspace))
2305 {
2306// waitForSpaceUnlock(currentspace);
2307 d.SpaceRemove(currentspace, geom);
2308 }
2309 else
2310 {
2311 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" + currentspace +
2312 " Geom:" + geom);
2313 }
2314 }
2315 else
2316 {
2317 IntPtr sGeomIsIn = d.GeomGetSpace(geom);
2318 if (sGeomIsIn != IntPtr.Zero)
2319 {
2320 if (d.GeomIsSpace(currentspace))
2321 {
2322// waitForSpaceUnlock(sGeomIsIn);
2323 d.SpaceRemove(sGeomIsIn, geom);
2324 }
2325 else
2326 {
2327 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" +
2328 sGeomIsIn + " Geom:" + geom);
2329 }
2330 }
2331 }
2332
2333 //If there are no more geometries in the sub-space, we don't need it in the main space anymore
2334 if (d.SpaceGetNumGeoms(currentspace) == 0)
2335 {
2336 if (currentspace != IntPtr.Zero)
2337 {
2338 if (d.GeomIsSpace(currentspace))
2339 {
2340 d.SpaceRemove(space, currentspace);
2341 // free up memory used by the space.
2342
2343 resetSpaceArrayItemToZero(currentspace);
2344 }
2345 else
2346 {
2347 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" +
2348 currentspace + " Geom:" + geom);
2349 }
2350 }
2351 }
2352 }
2353 else
2354 {
2355 // this is a physical object that got disabled. ;.;
2356 if (currentspace != IntPtr.Zero && geom != IntPtr.Zero)
2357 {
2358 if (d.SpaceQuery(currentspace, geom))
2359 {
2360 if (d.GeomIsSpace(currentspace))
2361 {
2362// waitForSpaceUnlock(currentspace);
2363 d.SpaceRemove(currentspace, geom);
2364 }
2365 else
2366 {
2367 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" +
2368 currentspace + " Geom:" + geom);
2369 }
2370 }
2371 else
2372 {
2373 IntPtr sGeomIsIn = d.GeomGetSpace(geom);
2374 if (sGeomIsIn != IntPtr.Zero)
2375 {
2376 if (d.GeomIsSpace(sGeomIsIn))
2377 {
2378// waitForSpaceUnlock(sGeomIsIn);
2379 d.SpaceRemove(sGeomIsIn, geom);
2380 }
2381 else
2382 {
2383 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" +
2384 sGeomIsIn + " Geom:" + geom);
2385 }
2386 }
2387 }
2388 }
2389 }
2390
2391 // The routines in the Position and Size sections do the 'inserting' into the space,
2392 // so all we have to do is make sure that the space that we're putting the prim into
2393 // is in the 'main' space.
2394 int[] iprimspaceArrItem = calculateSpaceArrayItemFromPos(pos);
2395 IntPtr newspace = calculateSpaceForGeom(pos);
2396
2397 if (newspace == IntPtr.Zero)
2398 {
2399 newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
2400 d.HashSpaceSetLevels(newspace, HashspaceLow, HashspaceHigh);
2401 }
2402
2403 return newspace;
2404 }
2405
2406 /// <summary>
2407 /// Creates a new space at X Y
2408 /// </summary>
2409 /// <param name="iprimspaceArrItemX"></param>
2410 /// <param name="iprimspaceArrItemY"></param>
2411 /// <returns>A pointer to the created space</returns>
2412 internal IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY)
2413 {
2414 // creating a new space for prim and inserting it into main space.
2415 staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero);
2416 d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space);
2417// waitForSpaceUnlock(space);
2418 d.SpaceSetSublevel(space, 1);
2419 d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]);
2420
2421 return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY];
2422 }
2423
2424 /// <summary>
2425 /// Calculates the space the prim should be in by its position
2426 /// </summary>
2427 /// <param name="pos"></param>
2428 /// <returns>a pointer to the space. This could be a new space or reused space.</returns>
2429 internal IntPtr calculateSpaceForGeom(Vector3 pos)
2430 {
2431 int[] xyspace = calculateSpaceArrayItemFromPos(pos);
2432 //m_log.Info("[Physics]: Attempting to use arrayItem: " + xyspace[0].ToString() + "," + xyspace[1].ToString());
2433 return staticPrimspace[xyspace[0], xyspace[1]];
2434 }
2435
2436 /// <summary>
2437 /// Holds the space allocation logic
2438 /// </summary>
2439 /// <param name="pos"></param>
2440 /// <returns>an array item based on the position</returns>
2441 internal int[] calculateSpaceArrayItemFromPos(Vector3 pos)
2442 {
2443 int[] returnint = new int[2];
2444
2445 returnint[0] = (int) (pos.X * spacesPerMeterX);
2446
2447 if (returnint[0] > spaceGridMaxX)
2448 returnint[0] = spaceGridMaxX;
2449 if (returnint[0] < 0)
2450 returnint[0] = 0;
2451
2452 returnint[1] = (int)(pos.Y * spacesPerMeterY);
2453 if (returnint[1] > spaceGridMaxY)
2454 returnint[1] = spaceGridMaxY;
2455 if (returnint[1] < 0)
2456 returnint[1] = 0;
2457
2458 return returnint;
2459 }
2460
2461 #endregion
2462
2463 /// <summary>
2464 /// Routine to figure out if we need to mesh this prim with our mesher
2465 /// </summary>
2466 /// <param name="pbs"></param>
2467 /// <returns></returns>
2468 internal bool needsMeshing(PrimitiveBaseShape pbs)
2469 {
2470 // most of this is redundant now as the mesher will return null if it cant mesh a prim
2471 // but we still need to check for sculptie meshing being enabled so this is the most
2472 // convenient place to do it for now...
2473
2474 // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f)
2475 // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString());
2476 int iPropertiesNotSupportedDefault = 0;
2477
2478 if (pbs.SculptEntry && !meshSculptedPrim)
2479 {
2480#if SPAM
2481 m_log.Warn("NonMesh");
2482#endif
2483 return false;
2484 }
2485
2486 // 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
2487 if (!forceSimplePrimMeshing && !pbs.SculptEntry)
2488 {
2489 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
2490 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
2491 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
2492 {
2493
2494 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
2495 && pbs.ProfileHollow == 0
2496 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
2497 && pbs.PathBegin == 0 && pbs.PathEnd == 0
2498 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
2499 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
2500 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
2501 {
2502#if SPAM
2503 m_log.Warn("NonMesh");
2504#endif
2505 return false;
2506 }
2507 }
2508 }
2509
2510 if (pbs.ProfileHollow != 0)
2511 iPropertiesNotSupportedDefault++;
2512
2513 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
2514 iPropertiesNotSupportedDefault++;
2515
2516 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
2517 iPropertiesNotSupportedDefault++;
2518
2519 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
2520 iPropertiesNotSupportedDefault++;
2521
2522 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
2523 iPropertiesNotSupportedDefault++;
2524
2525 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
2526 iPropertiesNotSupportedDefault++;
2527
2528 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
2529 iPropertiesNotSupportedDefault++;
2530
2531 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))
2532 iPropertiesNotSupportedDefault++;
2533
2534 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1)
2535 iPropertiesNotSupportedDefault++;
2536
2537 // test for torus
2538 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
2539 {
2540 if (pbs.PathCurve == (byte)Extrusion.Curve1)
2541 {
2542 iPropertiesNotSupportedDefault++;
2543 }
2544 }
2545 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
2546 {
2547 if (pbs.PathCurve == (byte)Extrusion.Straight)
2548 {
2549 iPropertiesNotSupportedDefault++;
2550 }
2551
2552 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
2553 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
2554 {
2555 iPropertiesNotSupportedDefault++;
2556 }
2557 }
2558 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
2559 {
2560 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
2561 {
2562 iPropertiesNotSupportedDefault++;
2563 }
2564 }
2565 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
2566 {
2567 if (pbs.PathCurve == (byte)Extrusion.Straight)
2568 {
2569 iPropertiesNotSupportedDefault++;
2570 }
2571 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
2572 {
2573 iPropertiesNotSupportedDefault++;
2574 }
2575 }
2576
2577 if (pbs.SculptEntry && meshSculptedPrim)
2578 iPropertiesNotSupportedDefault++;
2579
2580 if (iPropertiesNotSupportedDefault == 0)
2581 {
2582#if SPAM
2583 m_log.Warn("NonMesh");
2584#endif
2585 return false;
2586 }
2587#if SPAM
2588 m_log.Debug("Mesh");
2589#endif
2590 return true;
2591 }
2592
2593 /// <summary>
2594 /// Called after our prim properties are set Scale, position etc.
2595 /// </summary>
2596 /// <remarks>
2597 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex
2598 /// This assures us that we have no race conditions
2599 /// </remarks>
2600 /// <param name="actor"></param>
2601 public override void AddPhysicsActorTaint(PhysicsActor actor)
2602 {
2603 if (actor is OdePrim)
2604 {
2605 OdePrim taintedprim = ((OdePrim)actor);
2606 lock (_taintedPrims)
2607 _taintedPrims.Add(taintedprim);
2608 }
2609 else if (actor is OdeCharacter)
2610 {
2611 OdeCharacter taintedchar = ((OdeCharacter)actor);
2612 lock (_taintedActors)
2613 {
2614 _taintedActors.Add(taintedchar);
2615 if (taintedchar.bad)
2616 m_log.ErrorFormat("[ODE SCENE]: Added BAD actor {0} to tainted actors", taintedchar.m_uuid);
2617 }
2618 }
2619 }
2620
2621 // does all pending changes generated during region load process
2622 public override void ProcessPreSimulation()
2623 {
2624 lock (OdeLock)
2625 {
2626 if (world == IntPtr.Zero)
2627 {
2628 _taintedPrims.Clear();;
2629 return;
2630 }
2631
2632 int donechanges = 0;
2633 if (_taintedPrims.Count > 0)
2634 {
2635
2636 m_log.InfoFormat("[Ode] start processing pending actor operations");
2637 int tstart = Util.EnvironmentTickCount();
2638
2639 d.AllocateODEDataForThread(0);
2640
2641 lock (_taintedPrims)
2642 {
2643 foreach (OdePrim prim in _taintedPrims)
2644 {
2645 if (prim.m_taintremove)
2646 RemovePrimThreadLocked(prim);
2647 else
2648 prim.ProcessTaints();
2649
2650 prim.m_collisionscore = 0;
2651 donechanges++;
2652 }
2653 _taintedPrims.Clear();
2654 }
2655
2656 int time = Util.EnvironmentTickCountSubtract(tstart);
2657 m_log.InfoFormat("[Ode] finished {0} operations in {1}ms", donechanges, time);
2658 }
2659 m_log.InfoFormat("[Ode] {0} prim actors loaded",_prims.Count);
2660 }
2661 }
2662
2663
2664 /// <summary>
2665 /// This is our main simulate loop
2666 /// </summary>
2667 /// <remarks>
2668 /// It's thread locked by a Mutex in the scene.
2669 /// It holds Collisions, it instructs ODE to step through the physical reactions
2670 /// It moves the objects around in memory
2671 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
2672 /// </remarks>
2673 /// <param name="timeStep"></param>
2674 /// <returns>The number of frames simulated over that period.</returns>
2675 public override float Simulate(float timeStep)
2676 {
2677 if (!_worldInitialized)
2678 return 1.0f;
2679
2680 int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0;
2681 int tempTick = 0, tempTick2 = 0;
2682
2683 if (framecount >= int.MaxValue)
2684 framecount = 0;
2685
2686 framecount++;
2687
2688 float fps = 0;
2689
2690 step_time += timeStep;
2691
2692 float HalfOdeStep = ODE_STEPSIZE * 0.5f;
2693 if (step_time < HalfOdeStep)
2694 return 0;
2695
2696
2697 // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential
2698 // deadlock if the collision event tries to lock something else later on which is already locked by a
2699 // caller that is adding or removing the collision event.
2700 lock (m_collisionEventActorsChanges)
2701 {
2702 foreach (KeyValuePair<uint, PhysicsActor> kvp in m_collisionEventActorsChanges)
2703 {
2704 if (kvp.Value == null)
2705 m_collisionEventActors.Remove(kvp.Key);
2706 else
2707 m_collisionEventActors[kvp.Key] = kvp.Value;
2708 }
2709
2710 m_collisionEventActorsChanges.Clear();
2711 }
2712
2713 if (SupportsNINJAJoints)
2714 {
2715 DeleteRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks
2716 CreateRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks
2717 }
2718
2719
2720 lock (OdeLock)
2721 {
2722 d.AllocateODEDataForThread(~0U);
2723
2724 while (step_time > HalfOdeStep)
2725 {
2726 try
2727 {
2728 if (CollectStats)
2729 tempTick = Util.EnvironmentTickCount();
2730
2731 lock (_taintedActors)
2732 {
2733 foreach (OdeCharacter character in _taintedActors)
2734 character.ProcessTaints();
2735
2736 _taintedActors.Clear();
2737 }
2738
2739 if (CollectStats)
2740 {
2741 tempTick2 = Util.EnvironmentTickCount();
2742 m_stats[ODEAvatarTaintMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
2743 tempTick = tempTick2;
2744 }
2745
2746 lock (_taintedPrims)
2747 {
2748 foreach (OdePrim prim in _taintedPrims)
2749 {
2750 if (prim.m_taintremove)
2751 {
2752// Console.WriteLine("Simulate calls RemovePrimThreadLocked for {0}", prim.Name);
2753 RemovePrimThreadLocked(prim);
2754 }
2755 else
2756 {
2757// Console.WriteLine("Simulate calls ProcessTaints for {0}", prim.Name);
2758 prim.ProcessTaints();
2759 }
2760
2761 prim.m_collisionscore = 0;
2762
2763 // This loop can block up the Heartbeat for a very long time on large regions.
2764 // We need to let the Watchdog know that the Heartbeat is not dead
2765 // NOTE: This is currently commented out, but if things like OAR loading are
2766 // timing the heartbeat out we will need to uncomment it
2767 //Watchdog.UpdateThread();
2768 }
2769
2770 if (SupportsNINJAJoints)
2771 SimulatePendingNINJAJoints();
2772
2773 _taintedPrims.Clear();
2774 }
2775
2776 if (CollectStats)
2777 {
2778 tempTick2 = Util.EnvironmentTickCount();
2779 m_stats[ODEPrimTaintMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
2780 tempTick = tempTick2;
2781 }
2782
2783 // Move characters
2784 foreach (OdeCharacter actor in _characters)
2785 actor.Move(defects);
2786
2787 if (defects.Count != 0)
2788 {
2789 foreach (OdeCharacter actor in defects)
2790 {
2791 m_log.ErrorFormat(
2792 "[ODE SCENE]: Removing physics character {0} {1} from physics scene {2} due to defect found when moving",
2793 actor.Name, actor.LocalID, PhysicsSceneName);
2794
2795 RemoveCharacter(actor);
2796 actor.DestroyOdeStructures();
2797 }
2798
2799 defects.Clear();
2800 }
2801
2802 if (CollectStats)
2803 {
2804 tempTick2 = Util.EnvironmentTickCount();
2805 m_stats[ODEAvatarForcesFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
2806 tempTick = tempTick2;
2807 }
2808
2809 // Move other active objects
2810 foreach (OdePrim prim in _activeprims)
2811 {
2812 prim.m_collisionscore = 0;
2813 prim.Move(timeStep);
2814 }
2815
2816 if (CollectStats)
2817 {
2818 tempTick2 = Util.EnvironmentTickCount();
2819 m_stats[ODEPrimForcesFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
2820 tempTick = tempTick2;
2821 }
2822
2823 m_rayCastManager.ProcessQueuedRequests();
2824
2825 if (CollectStats)
2826 {
2827 tempTick2 = Util.EnvironmentTickCount();
2828 m_stats[ODERaycastingFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
2829 tempTick = tempTick2;
2830 }
2831
2832 collision_optimized();
2833
2834 if (CollectStats)
2835 {
2836 tempTick2 = Util.EnvironmentTickCount();
2837 m_stats[ODEOtherCollisionFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
2838 tempTick = tempTick2;
2839 }
2840
2841 foreach (PhysicsActor obj in m_collisionEventActors.Values)
2842 {
2843 // m_log.DebugFormat("[PHYSICS]: Assessing {0} {1} for collision events", obj.SOPName, obj.LocalID);
2844
2845 switch ((ActorTypes)obj.PhysicsActorType)
2846 {
2847 case ActorTypes.Agent:
2848 OdeCharacter cobj = (OdeCharacter)obj;
2849 cobj.AddCollisionFrameTime(100);
2850 cobj.SendCollisions();
2851 break;
2852
2853 case ActorTypes.Prim:
2854 OdePrim pobj = (OdePrim)obj;
2855 pobj.SendCollisions();
2856 break;
2857 }
2858 }
2859
2860// if (m_global_contactcount > 0)
2861// m_log.DebugFormat(
2862// "[PHYSICS]: Collision contacts to process this frame = {0}", m_global_contactcount);
2863
2864 m_global_contactcount = 0;
2865
2866 if (CollectStats)
2867 {
2868 tempTick2 = Util.EnvironmentTickCount();
2869 m_stats[ODECollisionNotificationFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
2870 tempTick = tempTick2;
2871 }
2872
2873 lock(SimulationLock)
2874 d.WorldQuickStep(world, ODE_STEPSIZE);
2875
2876 if (CollectStats)
2877 m_stats[ODENativeStepFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick);
2878
2879 d.JointGroupEmpty(contactgroup);
2880 }
2881 catch (Exception e)
2882 {
2883 m_log.ErrorFormat("[ODE SCENE]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
2884 }
2885
2886 step_time -= ODE_STEPSIZE;
2887 fps += ODE_STEPSIZE;
2888 }
2889
2890 if (CollectStats)
2891 tempTick = Util.EnvironmentTickCount();
2892
2893 foreach (OdeCharacter actor in _characters)
2894 {
2895 if (actor.bad)
2896 m_log.ErrorFormat("[ODE SCENE]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
2897
2898 actor.UpdatePositionAndVelocity(defects);
2899 }
2900
2901 if (defects.Count != 0)
2902 {
2903 foreach (OdeCharacter actor in defects)
2904 {
2905 m_log.ErrorFormat(
2906 "[ODE SCENE]: Removing physics character {0} {1} from physics scene {2} due to defect found when updating position and velocity",
2907 actor.Name, actor.LocalID, PhysicsSceneName);
2908
2909 RemoveCharacter(actor);
2910 actor.DestroyOdeStructures();
2911 }
2912
2913 defects.Clear();
2914 }
2915
2916 if (CollectStats)
2917 {
2918 tempTick2 = Util.EnvironmentTickCount();
2919 m_stats[ODEAvatarUpdateFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick2, tempTick);
2920 tempTick = tempTick2;
2921 }
2922
2923 //if (timeStep < 0.2f)
2924
2925 foreach (OdePrim prim in _activeprims)
2926 {
2927 if (prim.IsPhysical && (d.BodyIsEnabled(prim.Body) || !prim._zeroFlag))
2928 {
2929 prim.UpdatePositionAndVelocity();
2930
2931 if (SupportsNINJAJoints)
2932 SimulateActorPendingJoints(prim);
2933 }
2934 }
2935
2936 if (CollectStats)
2937 m_stats[ODEPrimUpdateFrameMsStatName] += Util.EnvironmentTickCountSubtract(tempTick);
2938
2939 //DumpJointInfo();
2940
2941 // Finished with all sim stepping. If requested, dump world state to file for debugging.
2942 // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed?
2943 // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots?
2944 if (physics_logging && (physics_logging_interval > 0) && (framecount % physics_logging_interval == 0))
2945 {
2946 string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename
2947 string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file
2948
2949 if (physics_logging_append_existing_logfile)
2950 {
2951 string header = "-------------- START OF PHYSICS FRAME " + framecount.ToString() + " --------------";
2952 TextWriter fwriter = File.AppendText(fname);
2953 fwriter.WriteLine(header);
2954 fwriter.Close();
2955 }
2956
2957 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
2958 }
2959
2960 latertickcount = Util.EnvironmentTickCountSubtract(tickCountFrameRun);
2961
2962 // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics
2963 // has a max of 100 ms to run theoretically.
2964 // If the main loop stalls, it calls Simulate later which makes the tick count ms larger.
2965 // If Physics stalls, it takes longer which makes the tick count ms larger.
2966
2967 if (latertickcount < 100)
2968 {
2969 m_timeDilation = 1.0f;
2970 }
2971 else
2972 {
2973 m_timeDilation = 100f / latertickcount;
2974 //m_timeDilation = Math.Min((Math.Max(100 - (Util.EnvironmentTickCount() - tickCountFrameRun), 1) / 100f), 1.0f);
2975 }
2976
2977 tickCountFrameRun = Util.EnvironmentTickCount();
2978
2979 if (CollectStats)
2980 m_stats[ODETotalFrameMsStatName] += Util.EnvironmentTickCountSubtract(startFrameTick);
2981 }
2982
2983 fps *= 1.0f/timeStep;
2984 return fps;
2985 }
2986
2987 /// <summary>
2988 /// Simulate pending NINJA joints.
2989 /// </summary>
2990 /// <remarks>
2991 /// Called by the main Simulate() loop if NINJA joints are active. Should not be called from anywhere else.
2992 /// </remarks>
2993 private void SimulatePendingNINJAJoints()
2994 {
2995 // Create pending joints, if possible
2996
2997 // joints can only be processed after ALL bodies are processed (and exist in ODE), since creating
2998 // a joint requires specifying the body id of both involved bodies
2999 if (pendingJoints.Count > 0)
3000 {
3001 List<PhysicsJoint> successfullyProcessedPendingJoints = new List<PhysicsJoint>();
3002 //DoJointErrorMessage(joints_connecting_actor, "taint: " + pendingJoints.Count + " pending joints");
3003 foreach (PhysicsJoint joint in pendingJoints)
3004 {
3005 //DoJointErrorMessage(joint, "taint: time to create joint with parms: " + joint.RawParams);
3006 string[] jointParams = joint.RawParams.Split(" ".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries);
3007 List<IntPtr> jointBodies = new List<IntPtr>();
3008 bool allJointBodiesAreReady = true;
3009 foreach (string jointParam in jointParams)
3010 {
3011 if (jointParam == "NULL")
3012 {
3013 //DoJointErrorMessage(joint, "attaching NULL joint to world");
3014 jointBodies.Add(IntPtr.Zero);
3015 }
3016 else
3017 {
3018 //DoJointErrorMessage(joint, "looking for prim name: " + jointParam);
3019 bool foundPrim = false;
3020 lock (_prims)
3021 {
3022 foreach (OdePrim prim in _prims) // FIXME: inefficient
3023 {
3024 if (prim.SOPName == jointParam)
3025 {
3026 //DoJointErrorMessage(joint, "found for prim name: " + jointParam);
3027 if (prim.IsPhysical && prim.Body != IntPtr.Zero)
3028 {
3029 jointBodies.Add(prim.Body);
3030 foundPrim = true;
3031 break;
3032 }
3033 else
3034 {
3035 DoJointErrorMessage(joint, "prim name " + jointParam +
3036 " exists but is not (yet) physical; deferring joint creation. " +
3037 "IsPhysical property is " + prim.IsPhysical +
3038 " and body is " + prim.Body);
3039 foundPrim = false;
3040 break;
3041 }
3042 }
3043 }
3044 }
3045 if (foundPrim)
3046 {
3047 // all is fine
3048 }
3049 else
3050 {
3051 allJointBodiesAreReady = false;
3052 break;
3053 }
3054 }
3055 }
3056
3057 if (allJointBodiesAreReady)
3058 {
3059 //DoJointErrorMessage(joint, "allJointBodiesAreReady for " + joint.ObjectNameInScene + " with parms " + joint.RawParams);
3060 if (jointBodies[0] == jointBodies[1])
3061 {
3062 DoJointErrorMessage(joint, "ERROR: joint cannot be created; the joint bodies are the same, body1==body2. Raw body is " + jointBodies[0] + ". raw parms: " + joint.RawParams);
3063 }
3064 else
3065 {
3066 switch (joint.Type)
3067 {
3068 case PhysicsJointType.Ball:
3069 {
3070 IntPtr odeJoint;
3071 //DoJointErrorMessage(joint, "ODE creating ball joint ");
3072 odeJoint = d.JointCreateBall(world, IntPtr.Zero);
3073 //DoJointErrorMessage(joint, "ODE attaching ball joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
3074 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
3075 //DoJointErrorMessage(joint, "ODE setting ball anchor: " + odeJoint + " to vec:" + joint.Position);
3076 d.JointSetBallAnchor(odeJoint,
3077 joint.Position.X,
3078 joint.Position.Y,
3079 joint.Position.Z);
3080 //DoJointErrorMessage(joint, "ODE joint setting OK");
3081 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b0: ");
3082 //DoJointErrorMessage(joint, "" + (jointBodies[0] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[0]) : "fixed environment"));
3083 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b1: ");
3084 //DoJointErrorMessage(joint, "" + (jointBodies[1] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[1]) : "fixed environment"));
3085
3086 if (joint is OdePhysicsJoint)
3087 {
3088 ((OdePhysicsJoint)joint).jointID = odeJoint;
3089 }
3090 else
3091 {
3092 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
3093 }
3094 }
3095 break;
3096 case PhysicsJointType.Hinge:
3097 {
3098 IntPtr odeJoint;
3099 //DoJointErrorMessage(joint, "ODE creating hinge joint ");
3100 odeJoint = d.JointCreateHinge(world, IntPtr.Zero);
3101 //DoJointErrorMessage(joint, "ODE attaching hinge joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
3102 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
3103 //DoJointErrorMessage(joint, "ODE setting hinge anchor: " + odeJoint + " to vec:" + joint.Position);
3104 d.JointSetHingeAnchor(odeJoint,
3105 joint.Position.X,
3106 joint.Position.Y,
3107 joint.Position.Z);
3108 // We use the orientation of the x-axis of the joint's coordinate frame
3109 // as the axis for the hinge.
3110
3111 // Therefore, we must get the joint's coordinate frame based on the
3112 // joint.Rotation field, which originates from the orientation of the
3113 // joint's proxy object in the scene.
3114
3115 // The joint's coordinate frame is defined as the transformation matrix
3116 // that converts a vector from joint-local coordinates into world coordinates.
3117 // World coordinates are defined as the XYZ coordinate system of the sim,
3118 // as shown in the top status-bar of the viewer.
3119
3120 // Once we have the joint's coordinate frame, we extract its X axis (AtAxis)
3121 // and use that as the hinge axis.
3122
3123 //joint.Rotation.Normalize();
3124 Matrix4 proxyFrame = Matrix4.CreateFromQuaternion(joint.Rotation);
3125
3126 // Now extract the X axis of the joint's coordinate frame.
3127
3128 // Do not try to use proxyFrame.AtAxis or you will become mired in the
3129 // tar pit of transposed, inverted, and generally messed-up orientations.
3130 // (In other words, Matrix4.AtAxis() is borked.)
3131 // Vector3 jointAxis = proxyFrame.AtAxis; <--- this path leadeth to madness
3132
3133 // Instead, compute the X axis of the coordinate frame by transforming
3134 // the (1,0,0) vector. At least that works.
3135
3136 //m_log.Debug("PHY: making axis: complete matrix is " + proxyFrame);
3137 Vector3 jointAxis = Vector3.Transform(Vector3.UnitX, proxyFrame);
3138 //m_log.Debug("PHY: making axis: hinge joint axis is " + jointAxis);
3139 //DoJointErrorMessage(joint, "ODE setting hinge axis: " + odeJoint + " to vec:" + jointAxis);
3140 d.JointSetHingeAxis(odeJoint,
3141 jointAxis.X,
3142 jointAxis.Y,
3143 jointAxis.Z);
3144 //d.JointSetHingeParam(odeJoint, (int)dParam.CFM, 0.1f);
3145 if (joint is OdePhysicsJoint)
3146 {
3147 ((OdePhysicsJoint)joint).jointID = odeJoint;
3148 }
3149 else
3150 {
3151 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
3152 }
3153 }
3154 break;
3155 }
3156 successfullyProcessedPendingJoints.Add(joint);
3157 }
3158 }
3159 else
3160 {
3161 DoJointErrorMessage(joint, "joint could not yet be created; still pending");
3162 }
3163 }
3164
3165 foreach (PhysicsJoint successfullyProcessedJoint in successfullyProcessedPendingJoints)
3166 {
3167 //DoJointErrorMessage(successfullyProcessedJoint, "finalizing succesfully procsssed joint " + successfullyProcessedJoint.ObjectNameInScene + " parms " + successfullyProcessedJoint.RawParams);
3168 //DoJointErrorMessage(successfullyProcessedJoint, "removing from pending");
3169 InternalRemovePendingJoint(successfullyProcessedJoint);
3170 //DoJointErrorMessage(successfullyProcessedJoint, "adding to active");
3171 InternalAddActiveJoint(successfullyProcessedJoint);
3172 //DoJointErrorMessage(successfullyProcessedJoint, "done");
3173 }
3174 }
3175 }
3176
3177 /// <summary>
3178 /// Simulate the joint proxies of a NINJA actor.
3179 /// </summary>
3180 /// <remarks>
3181 /// Called as part of the Simulate() loop if NINJA physics is active. Must only be called from there.
3182 /// </remarks>
3183 /// <param name="actor"></param>
3184 private void SimulateActorPendingJoints(OdePrim actor)
3185 {
3186 // If an actor moved, move its joint proxy objects as well.
3187 // There seems to be an event PhysicsActor.OnPositionUpdate that could be used
3188 // for this purpose but it is never called! So we just do the joint
3189 // movement code here.
3190
3191 if (actor.SOPName != null &&
3192 joints_connecting_actor.ContainsKey(actor.SOPName) &&
3193 joints_connecting_actor[actor.SOPName] != null &&
3194 joints_connecting_actor[actor.SOPName].Count > 0)
3195 {
3196 foreach (PhysicsJoint affectedJoint in joints_connecting_actor[actor.SOPName])
3197 {
3198 if (affectedJoint.IsInPhysicsEngine)
3199 {
3200 DoJointMoved(affectedJoint);
3201 }
3202 else
3203 {
3204 DoJointErrorMessage(affectedJoint, "a body connected to a joint was moved, but the joint doesn't exist yet! this will lead to joint error. joint was: " + affectedJoint.ObjectNameInScene + " parms:" + affectedJoint.RawParams);
3205 }
3206 }
3207 }
3208 }
3209
3210 public override void GetResults()
3211 {
3212 }
3213
3214 public override bool IsThreaded
3215 {
3216 // for now we won't be multithreaded
3217 get { return false; }
3218 }
3219
3220 public override void SetTerrain(float[] heightMap)
3221 {
3222 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
3223 {
3224 if (m_parentScene is OdeScene)
3225 {
3226 ((OdeScene)m_parentScene).SetTerrain(heightMap, m_worldOffset);
3227 }
3228 }
3229 else
3230 {
3231 SetTerrain(heightMap, m_worldOffset);
3232 }
3233 }
3234
3235 private void SetTerrain(float[] heightMap, Vector3 pOffset)
3236 {
3237 int startTime = Util.EnvironmentTickCount();
3238 m_log.DebugFormat("[ODE SCENE]: Setting terrain for {0} with offset {1}", PhysicsSceneName, pOffset);
3239
3240
3241 float[] _heightmap;
3242
3243 // ok im lasy this are just a aliases
3244 uint regionsizeX = m_regionWidth;
3245 uint regionsizeY = m_regionHeight;
3246
3247 // map is rotated
3248 uint heightmapWidth = regionsizeY + 2;
3249 uint heightmapHeight = regionsizeX + 2;
3250
3251 uint heightmapWidthSamples = heightmapWidth + 1;
3252 uint heightmapHeightSamples = heightmapHeight + 1;
3253
3254 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
3255
3256 const float scale = 1.0f;
3257 const float offset = 0.0f;
3258 const float thickness = 10f;
3259 const int wrap = 0;
3260
3261
3262 float hfmin = float.MaxValue;
3263 float hfmax = float.MinValue;
3264 float val;
3265 uint xx;
3266 uint yy;
3267
3268 uint maxXX = regionsizeX - 1;
3269 uint maxYY = regionsizeY - 1;
3270
3271 // flipping map adding one margin all around so things don't fall in edges
3272
3273 uint xt = 0;
3274 xx = 0;
3275
3276
3277 for (uint x = 0; x < heightmapWidthSamples; x++)
3278 {
3279 if (x > 1 && xx < maxXX)
3280 xx++;
3281 yy = 0;
3282 for (uint y = 0; y < heightmapHeightSamples; y++)
3283 {
3284 if (y > 1 && y < maxYY)
3285 yy += regionsizeX;
3286
3287 val = heightMap[yy + xx];
3288 if (val < 0.0f)
3289 val = 0.0f;
3290 _heightmap[xt + y] = val;
3291
3292 if (hfmin > val)
3293 hfmin = val;
3294 if (hfmax < val)
3295 hfmax = val;
3296 }
3297 xt += heightmapHeightSamples;
3298 }
3299
3300 lock (OdeLock)
3301 {
3302 d.AllocateODEDataForThread(~0U);
3303
3304 IntPtr GroundGeom = IntPtr.Zero;
3305 if (RegionTerrain.TryGetValue(pOffset, out GroundGeom))
3306 {
3307 RegionTerrain.Remove(pOffset);
3308 if (GroundGeom != IntPtr.Zero)
3309 {
3310 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
3311 {
3312 TerrainHeightFieldHeights.Remove(GroundGeom);
3313 }
3314 d.SpaceRemove(space, GroundGeom);
3315 d.GeomDestroy(GroundGeom);
3316 }
3317
3318 }
3319 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
3320 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0,
3321 heightmapWidth, heightmapHeight,
3322 (int)heightmapWidthSamples,
3323 (int)heightmapHeightSamples,
3324 scale, offset, thickness, wrap);
3325
3326 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
3327 GroundGeom = d.CreateHeightfield(space, HeightmapData, 1);
3328 if (GroundGeom != IntPtr.Zero)
3329 {
3330 d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land));
3331 d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space));
3332
3333 }
3334 geom_name_map[GroundGeom] = "Terrain";
3335
3336 d.Matrix3 R = new d.Matrix3();
3337
3338 Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
3339 Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);
3340
3341 q1 = q1 * q2;
3342 Vector3 v3;
3343 float angle;
3344 q1.GetAxisAngle(out v3, out angle);
3345
3346 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
3347 d.GeomSetRotation(GroundGeom, ref R);
3348 d.GeomSetPosition(GroundGeom, pOffset.X + regionsizeX * 0.5f, pOffset.Y + regionsizeY * 0.5f, 0.0f);
3349 IntPtr testGround = IntPtr.Zero;
3350 if (RegionTerrain.TryGetValue(pOffset, out testGround))
3351 {
3352 RegionTerrain.Remove(pOffset);
3353 }
3354 RegionTerrain.Add(pOffset, GroundGeom, GroundGeom);
3355 TerrainHeightFieldHeights.Add(GroundGeom,_heightmap);
3356 }
3357
3358 m_log.DebugFormat(
3359 "[ODE SCENE]: Setting terrain for {0} took {1}ms", PhysicsSceneName, Util.EnvironmentTickCountSubtract(startTime));
3360 }
3361
3362 public override void DeleteTerrain()
3363 {
3364 }
3365
3366 internal float GetWaterLevel()
3367 {
3368 return waterlevel;
3369 }
3370
3371 public override void SetWaterLevel(float baseheight)
3372 {
3373 waterlevel = baseheight;
3374 }
3375
3376 [HandleProcessCorruptedStateExceptions]
3377 public override void Dispose()
3378 {
3379 lock(SimulationLock)
3380 lock(OdeLock)
3381 {
3382 if(world == IntPtr.Zero)
3383 return;
3384
3385 _worldInitialized = false;
3386
3387 d.AllocateODEDataForThread(~0U);
3388
3389 if (m_rayCastManager != null)
3390 {
3391 m_rayCastManager.Dispose();
3392 m_rayCastManager = null;
3393 }
3394
3395 lock (_prims)
3396 {
3397 foreach (OdePrim prm in _prims)
3398 {
3399 RemovePrim(prm);
3400 }
3401 }
3402
3403 //foreach (OdeCharacter act in _characters)
3404 //{
3405 //RemoveAvatar(act);
3406 //}
3407 IntPtr GroundGeom = IntPtr.Zero;
3408 if (RegionTerrain.TryGetValue(m_worldOffset, out GroundGeom))
3409 {
3410 RegionTerrain.Remove(m_worldOffset);
3411 if (GroundGeom != IntPtr.Zero)
3412 {
3413 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
3414 TerrainHeightFieldHeights.Remove(GroundGeom);
3415 d.GeomDestroy(GroundGeom);
3416 }
3417 }
3418
3419 try
3420 {
3421 d.WorldDestroy(world);
3422 world = IntPtr.Zero;
3423 }
3424 catch (AccessViolationException e)
3425 {
3426 m_log.ErrorFormat("[ODE SCENE]: exception {0}", e.Message);
3427 }
3428 }
3429 }
3430
3431 private int compareByCollisionsDesc(OdePrim A, OdePrim B)
3432 {
3433 return -A.CollisionScore.CompareTo(B.CollisionScore);
3434 }
3435
3436 public override Dictionary<uint, float> GetTopColliders()
3437 {
3438 Dictionary<uint, float> topColliders;
3439
3440 lock (_prims)
3441 {
3442 List<OdePrim> orderedPrims = new List<OdePrim>(_prims);
3443 orderedPrims.Sort(compareByCollisionsDesc);
3444 topColliders = orderedPrims.Take(25).ToDictionary(p => p.LocalID, p => p.CollisionScore);
3445
3446 foreach (OdePrim p in _prims)
3447 p.CollisionScore = 0;
3448 }
3449
3450 return topColliders;
3451 }
3452
3453 public override bool SupportsRayCast()
3454 {
3455 return true;
3456 }
3457
3458 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
3459 {
3460 if (retMethod != null)
3461 {
3462 m_rayCastManager.QueueRequest(position, direction, length, retMethod);
3463 }
3464 }
3465
3466 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod)
3467 {
3468 if (retMethod != null)
3469 {
3470 m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod);
3471 }
3472 }
3473
3474 public override List<ContactResult> RaycastWorld(Vector3 position, Vector3 direction, float length, int Count)
3475 {
3476 ContactResult[] ourResults = null;
3477 RayCallback retMethod = delegate(List<ContactResult> results)
3478 {
3479 ourResults = new ContactResult[results.Count];
3480 results.CopyTo(ourResults, 0);
3481 };
3482 int waitTime = 0;
3483 m_rayCastManager.QueueRequest(position, direction, length, Count, retMethod);
3484 while (ourResults == null && waitTime < 1000)
3485 {
3486 Thread.Sleep(1);
3487 waitTime++;
3488 }
3489 if (ourResults == null)
3490 return new List<ContactResult> ();
3491 return new List<ContactResult>(ourResults);
3492 }
3493
3494 public override Dictionary<string, float> GetStats()
3495 {
3496 if (!CollectStats)
3497 return null;
3498
3499 Dictionary<string, float> returnStats;
3500
3501 lock (OdeLock)
3502 {
3503 returnStats = new Dictionary<string, float>(m_stats);
3504
3505 // FIXME: This is a SUPER DUMB HACK until we can establish stats that aren't subject to a division by
3506 // 3 from the SimStatsReporter.
3507 returnStats[ODETotalAvatarsStatName] = _characters.Count * 3;
3508 returnStats[ODETotalPrimsStatName] = _prims.Count * 3;
3509 returnStats[ODEActivePrimsStatName] = _activeprims.Count * 3;
3510
3511 InitializeExtraStats();
3512 }
3513
3514 returnStats[ODEOtherCollisionFrameMsStatName]
3515 = returnStats[ODEOtherCollisionFrameMsStatName]
3516 - returnStats[ODENativeSpaceCollisionFrameMsStatName]
3517 - returnStats[ODENativeGeomCollisionFrameMsStatName];
3518
3519 return returnStats;
3520 }
3521
3522 private void InitializeExtraStats()
3523 {
3524 m_stats[ODETotalFrameMsStatName] = 0;
3525 m_stats[ODEAvatarTaintMsStatName] = 0;
3526 m_stats[ODEPrimTaintMsStatName] = 0;
3527 m_stats[ODEAvatarForcesFrameMsStatName] = 0;
3528 m_stats[ODEPrimForcesFrameMsStatName] = 0;
3529 m_stats[ODERaycastingFrameMsStatName] = 0;
3530 m_stats[ODENativeStepFrameMsStatName] = 0;
3531 m_stats[ODENativeSpaceCollisionFrameMsStatName] = 0;
3532 m_stats[ODENativeGeomCollisionFrameMsStatName] = 0;
3533 m_stats[ODEOtherCollisionFrameMsStatName] = 0;
3534 m_stats[ODECollisionNotificationFrameMsStatName] = 0;
3535 m_stats[ODEAvatarContactsStatsName] = 0;
3536 m_stats[ODEPrimContactsStatName] = 0;
3537 m_stats[ODEAvatarUpdateFrameMsStatName] = 0;
3538 m_stats[ODEPrimUpdateFrameMsStatName] = 0;
3539 }
3540 }
3541}
diff --git a/OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs b/OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs
new file mode 100644
index 0000000..2c134e7
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs
@@ -0,0 +1,153 @@
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 Nini.Config;
30using NUnit.Framework;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.PhysicsModules.SharedBase;
34using OpenSim.Region.PhysicsModule.ODE;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Tests.Common;
38using log4net;
39using System.Reflection;
40
41namespace OpenSim.Region.PhysicsModule.ODE.Tests
42{
43 [TestFixture]
44 public class ODETestClass : OpenSimTestCase
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 //private OpenSim.Region.PhysicsModule.ODE.OdePlugin cbt;
49 private PhysicsScene pScene;
50 private OpenSim.Region.PhysicsModule.ODE.OdeModule odemodule;
51
52
53 [SetUp]
54 public void Initialize()
55 {
56 IConfigSource openSimINI = new IniConfigSource();
57 IConfig startupConfig = openSimINI.AddConfig("Startup");
58 startupConfig.Set("physics", "OpenDynamicsEngine");
59 startupConfig.Set("DecodedSculptMapPath", "j2kDecodeCache");
60
61 Vector3 regionExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
62
63 //PhysicsScene pScene = physicsPluginManager.GetPhysicsScene(
64 // "BulletSim", "Meshmerizer", openSimINI, "BSTestRegion", regionExtent);
65 RegionInfo info = new RegionInfo();
66 info.RegionName = "ODETestRegion";
67 info.RegionSizeX = info.RegionSizeY = info.RegionSizeZ = Constants.RegionSize;
68 OpenSim.Region.Framework.Scenes.Scene scene = new OpenSim.Region.Framework.Scenes.Scene(info);
69
70 //IMesher mesher = new OpenSim.Region.PhysicsModule.Meshing.Meshmerizer();
71 //INonSharedRegionModule mod = mesher as INonSharedRegionModule;
72 //mod.Initialise(openSimINI);
73 //mod.AddRegion(scene);
74 //mod.RegionLoaded(scene);
75
76 // pScene = new OdeScene();
77 odemodule = new OpenSim.Region.PhysicsModule.ODE.OdeModule();
78 Console.WriteLine("HERE " + (odemodule == null ? "Null" : "Not null"));
79 odemodule.Initialise(openSimINI);
80 odemodule.AddRegion(scene);
81 odemodule.RegionLoaded(scene);
82
83 // Loading ODEPlugin
84 //cbt = new OdePlugin();
85 // Getting Physics Scene
86 //ps = cbt.GetScene("test");
87 // Initializing Physics Scene.
88 //ps.Initialise(imp.GetMesher(TopConfig), null, Vector3.Zero);
89 float[] _heightmap = new float[(int)Constants.RegionSize * (int)Constants.RegionSize];
90 for (int i = 0; i < ((int)Constants.RegionSize * (int)Constants.RegionSize); i++)
91 {
92 _heightmap[i] = 21f;
93 }
94 pScene = scene.PhysicsScene;
95 pScene.SetTerrain(_heightmap);
96 }
97
98 [TearDown]
99 public void Terminate()
100 {
101 pScene.DeleteTerrain();
102 pScene.Dispose();
103
104 }
105
106 [Test]
107 public void CreateAndDropPhysicalCube()
108 {
109 PrimitiveBaseShape newcube = PrimitiveBaseShape.CreateBox();
110 Vector3 position = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 128f);
111 Vector3 size = new Vector3(0.5f, 0.5f, 0.5f);
112 Quaternion rot = Quaternion.Identity;
113 PhysicsActor prim = pScene.AddPrimShape("CoolShape", newcube, position, size, rot, true, 0);
114 OdePrim oprim = (OdePrim)prim;
115 OdeScene pscene = (OdeScene)pScene;
116
117 Assert.That(oprim.m_taintadd);
118
119 prim.LocalID = 5;
120
121 for (int i = 0; i < 58; i++)
122 {
123 pScene.Simulate(0.133f);
124
125 Assert.That(oprim.prim_geom != (IntPtr)0);
126
127 Assert.That(oprim.m_targetSpace != (IntPtr)0);
128
129 //Assert.That(oprim.m_targetSpace == pscene.space);
130 m_log.Info("TargetSpace: " + oprim.m_targetSpace + " - SceneMainSpace: " + pscene.space);
131
132 Assert.That(!oprim.m_taintadd);
133 m_log.Info("Prim Position (" + oprim.LocalID + "): " + prim.Position);
134
135 // Make sure we're above the ground
136 //Assert.That(prim.Position.Z > 20f);
137 //m_log.Info("PrimCollisionScore (" + oprim.m_localID + "): " + oprim.m_collisionscore);
138
139 // Make sure we've got a Body
140 Assert.That(oprim.Body != (IntPtr)0);
141 //m_log.Info(
142 }
143
144 // Make sure we're not somewhere above the ground
145 Assert.That(prim.Position.Z < 21.5f);
146
147 pScene.RemovePrim(prim);
148 Assert.That(oprim.m_taintremove);
149 pScene.Simulate(0.133f);
150 Assert.That(oprim.Body == (IntPtr)0);
151 }
152 }
153}