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