aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/AssemblyInfo.cs58
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs1191
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPlugin.cs65
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPluginStructs.cs60
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs2767
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs776
-rw-r--r--OpenSim/Region/Physics/BulletXPlugin/AssemblyInfo.cs58
-rw-r--r--OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs1855
-rw-r--r--OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs197
9 files changed, 0 insertions, 7027 deletions
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/AssemblyInfo.cs
deleted file mode 100644
index 2830325..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/AssemblyInfo.cs
+++ /dev/null
@@ -1,58 +0,0 @@
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("BulletDotNETPlugin")]
38[assembly : AssemblyDescription("")]
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.3.*")]
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
deleted file mode 100644
index ac4e2b9..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
+++ /dev/null
@@ -1,1191 +0,0 @@
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.Reflection;
30using BulletDotNET;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34using log4net;
35
36namespace OpenSim.Region.Physics.BulletDotNETPlugin
37{
38 public class BulletDotNETCharacter : PhysicsActor
39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
42 public btRigidBody Body;
43 public btCollisionShape Shell;
44 public btVector3 tempVector1;
45 public btVector3 tempVector2;
46 public btVector3 tempVector3;
47 public btVector3 tempVector4;
48
49 public btVector3 tempVector5RayCast;
50 public btVector3 tempVector6RayCast;
51 public btVector3 tempVector7RayCast;
52
53 public btQuaternion tempQuat1;
54 public btTransform tempTrans1;
55
56 public ClosestNotMeRayResultCallback ClosestCastResult;
57 private btTransform m_bodyTransform;
58 private btVector3 m_bodyPosition;
59 private btVector3 m_CapsuleOrientationAxis;
60 private btQuaternion m_bodyOrientation;
61 private btDefaultMotionState m_bodyMotionState;
62 private btGeneric6DofConstraint m_aMotor;
63 // private Vector3 m_movementComparision;
64 private Vector3 m_position;
65 private Vector3 m_zeroPosition;
66 private bool m_zeroFlag = false;
67 private bool m_lastUpdateSent = false;
68 private Vector3 m_velocity;
69 private Vector3 m_target_velocity;
70 private Vector3 m_acceleration;
71 private Vector3 m_rotationalVelocity;
72 private bool m_pidControllerActive = true;
73 public float PID_D = 80.0f;
74 public float PID_P = 90.0f;
75 public float CAPSULE_RADIUS = 0.37f;
76 public float CAPSULE_LENGTH = 2.140599f;
77 public float heightFudgeFactor = 0.52f;
78 public float walkDivisor = 1.3f;
79 public float runDivisor = 0.8f;
80 private float m_mass = 80f;
81 public float m_density = 60f;
82 private bool m_flying = false;
83 private bool m_iscolliding = false;
84 private bool m_iscollidingGround = false;
85 private bool m_wascolliding = false;
86 private bool m_wascollidingGround = false;
87 private bool m_iscollidingObj = false;
88 private bool m_alwaysRun = false;
89 private bool m_hackSentFall = false;
90 private bool m_hackSentFly = false;
91 public uint m_localID = 0;
92 public bool m_returnCollisions = false;
93 // taints and their non-tainted counterparts
94 public bool m_isPhysical = false; // the current physical status
95 public bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing)
96 private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes.
97 private bool m_taintRemove = false;
98 // private bool m_taintedPosition = false;
99 // private Vector3 m_taintedPosition_value;
100 private Vector3 m_taintedForce;
101
102 private float m_buoyancy = 0f;
103
104 // private CollisionLocker ode;
105
106 // private string m_name = String.Empty;
107
108 private bool[] m_colliderarr = new bool[11];
109 private bool[] m_colliderGroundarr = new bool[11];
110
111 private BulletDotNETScene m_parent_scene;
112
113 public int m_eventsubscription = 0;
114 private CollisionEventUpdate CollisionEventsThisFrame = null;
115 private int m_requestedUpdateFrequency = 0;
116
117 public BulletDotNETCharacter(string avName, BulletDotNETScene parent_scene, Vector3 pos, Vector3 size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor)
118 {
119 m_position = pos;
120 m_zeroPosition = pos;
121 m_parent_scene = parent_scene;
122 PID_D = pid_d;
123 PID_P = pid_p;
124 CAPSULE_RADIUS = capsule_radius;
125 m_density = density;
126 heightFudgeFactor = height_fudge_factor;
127 walkDivisor = walk_divisor;
128 runDivisor = rundivisor;
129
130 for (int i = 0; i < 11; i++)
131 {
132 m_colliderarr[i] = false;
133 }
134 for (int i = 0; i < 11; i++)
135 {
136 m_colliderGroundarr[i] = false;
137 }
138 CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
139 m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
140 m_isPhysical = false; // current status: no ODE information exists
141 m_tainted_isPhysical = true; // new tainted status: need to create ODE information
142
143 m_parent_scene.AddPhysicsActorTaint(this);
144
145 // m_name = avName;
146 tempVector1 = new btVector3(0, 0, 0);
147 tempVector2 = new btVector3(0, 0, 0);
148 tempVector3 = new btVector3(0, 0, 0);
149 tempVector4 = new btVector3(0, 0, 0);
150
151 tempVector5RayCast = new btVector3(0, 0, 0);
152 tempVector6RayCast = new btVector3(0, 0, 0);
153 tempVector7RayCast = new btVector3(0, 0, 0);
154
155 tempQuat1 = new btQuaternion(0, 0, 0, 1);
156 tempTrans1 = new btTransform(tempQuat1, tempVector1);
157 // m_movementComparision = new PhysicsVector(0, 0, 0);
158 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
159 }
160
161 /// <summary>
162 /// This creates the Avatar's physical Surrogate at the position supplied
163 /// </summary>
164 /// <param name="npositionX"></param>
165 /// <param name="npositionY"></param>
166 /// <param name="npositionZ"></param>
167
168 // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
169 // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
170 // place that is safe to call this routine AvatarGeomAndBodyCreation.
171 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
172 {
173
174 if (CAPSULE_LENGTH <= 0)
175 {
176 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
177 CAPSULE_LENGTH = 0.01f;
178
179 }
180
181 if (CAPSULE_RADIUS <= 0)
182 {
183 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
184 CAPSULE_RADIUS = 0.01f;
185
186 }
187
188 Shell = new btCapsuleShape(CAPSULE_RADIUS, CAPSULE_LENGTH);
189
190 if (m_bodyPosition == null)
191 m_bodyPosition = new btVector3(npositionX, npositionY, npositionZ);
192
193 m_bodyPosition.setValue(npositionX, npositionY, npositionZ);
194
195 if (m_bodyOrientation == null)
196 m_bodyOrientation = new btQuaternion(m_CapsuleOrientationAxis, (Utils.DEG_TO_RAD * 90));
197
198 if (m_bodyTransform == null)
199 m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
200 else
201 {
202 m_bodyTransform.Dispose();
203 m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
204 }
205
206 if (m_bodyMotionState == null)
207 m_bodyMotionState = new btDefaultMotionState(m_bodyTransform);
208 else
209 m_bodyMotionState.setWorldTransform(m_bodyTransform);
210
211 m_mass = Mass;
212
213 Body = new btRigidBody(m_mass, m_bodyMotionState, Shell);
214 // this is used for self identification. User localID instead of body handle
215 Body.setUserPointer(new IntPtr((int)m_localID));
216
217 if (ClosestCastResult != null)
218 ClosestCastResult.Dispose();
219 ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
220
221 m_parent_scene.AddRigidBody(Body);
222 Body.setActivationState(4);
223 if (m_aMotor != null)
224 {
225 if (m_aMotor.Handle != IntPtr.Zero)
226 {
227 m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
228 m_aMotor.Dispose();
229 }
230 m_aMotor = null;
231 }
232
233 m_aMotor = new btGeneric6DofConstraint(Body, m_parent_scene.TerrainBody,
234 m_parent_scene.TransZero,
235 m_parent_scene.TransZero, false);
236 m_aMotor.setAngularLowerLimit(m_parent_scene.VectorZero);
237 m_aMotor.setAngularUpperLimit(m_parent_scene.VectorZero);
238
239
240 }
241 public void Remove()
242 {
243 m_taintRemove = true;
244 }
245 public override bool Stopped
246 {
247 get { return m_zeroFlag; }
248 }
249
250 public override Vector3 Size
251 {
252 get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
253 set
254 {
255 m_pidControllerActive = true;
256
257 Vector3 SetSize = value;
258 m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
259 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
260
261 Velocity = Vector3.Zero;
262
263 m_parent_scene.AddPhysicsActorTaint(this);
264 }
265 }
266
267 /// <summary>
268 /// turn the PID controller on or off.
269 /// The PID Controller will turn on all by itself in many situations
270 /// </summary>
271 /// <param name="status"></param>
272 public void SetPidStatus(bool status)
273 {
274 m_pidControllerActive = status;
275 }
276
277 public override PrimitiveBaseShape Shape
278 {
279 set { return; }
280 }
281
282 public override uint LocalID
283 {
284 set { m_localID = value; }
285 }
286
287 public override bool Grabbed
288 {
289 set { return; }
290 }
291
292 public override bool Selected
293 {
294 set { return; }
295 }
296
297
298 public override void CrossingFailure()
299 {
300
301 }
302
303 public override void link(PhysicsActor obj)
304 {
305
306 }
307
308 public override void delink()
309 {
310
311 }
312
313 public override void LockAngularMotion(Vector3 axis)
314 {
315
316 }
317
318 public override Vector3 Position
319 {
320 get { return m_position; }
321 set
322 {
323 // m_taintedPosition_value = value;
324 m_position = value;
325 // m_taintedPosition = true;
326 }
327 }
328
329 public override float Mass
330 {
331 get
332 {
333 float AVvolume = (float)(Math.PI * Math.Pow(CAPSULE_RADIUS, 2) * CAPSULE_LENGTH);
334 return m_density * AVvolume;
335 }
336 }
337
338 public override Vector3 Force
339 {
340 get { return m_target_velocity; }
341 set { return; }
342 }
343
344 public override int VehicleType
345 {
346 get { return 0; }
347 set { return; }
348 }
349
350 public override void VehicleFloatParam(int param, float value)
351 {
352
353 }
354
355 public override void VehicleVectorParam(int param, Vector3 value)
356 {
357
358 }
359
360 public override void VehicleRotationParam(int param, Quaternion rotation)
361 {
362
363 }
364
365 public override void VehicleFlags(int param, bool remove)
366 {
367
368 }
369
370 public override void SetVolumeDetect(int param)
371 {
372
373 }
374
375 public override Vector3 GeometricCenter
376 {
377 get { return Vector3.Zero; }
378 }
379
380 public override Vector3 CenterOfMass
381 {
382 get { return Vector3.Zero; }
383 }
384
385 public override Vector3 Velocity
386 {
387 get
388 {
389 if (m_zeroFlag)
390 return Vector3.Zero;
391 m_lastUpdateSent = false;
392 return m_velocity;
393 }
394 set
395 {
396 m_pidControllerActive = true;
397 m_target_velocity = value;
398 }
399 }
400
401 public override Vector3 Torque
402 {
403 get { return Vector3.Zero; }
404 set { return; }
405 }
406
407 public override float CollisionScore
408 {
409 get { return 0f; }
410 set { }
411 }
412
413 public override Vector3 Acceleration
414 {
415 get { return m_acceleration; }
416 }
417
418 public override Quaternion Orientation
419 {
420 get { return Quaternion.Identity; }
421 set
422 {
423
424 }
425 }
426
427 public override int PhysicsActorType
428 {
429 get { return (int)ActorTypes.Agent; }
430 set { return; }
431 }
432
433 public override bool IsPhysical
434 {
435 get { return false; }
436 set { return; }
437 }
438
439 public override bool Flying
440 {
441 get { return m_flying; }
442 set { m_flying = value; }
443 }
444
445 public override bool SetAlwaysRun
446 {
447 get { return m_alwaysRun; }
448 set { m_alwaysRun = value; }
449 }
450
451
452 public override bool ThrottleUpdates
453 {
454 get { return false; }
455 set { return; }
456 }
457
458 /// <summary>
459 /// Returns if the avatar is colliding in general.
460 /// This includes the ground and objects and avatar.
461 /// </summary>
462 public override bool IsColliding
463 {
464 get { return m_iscolliding; }
465 set
466 {
467 int i;
468 int truecount = 0;
469 int falsecount = 0;
470
471 if (m_colliderarr.Length >= 10)
472 {
473 for (i = 0; i < 10; i++)
474 {
475 m_colliderarr[i] = m_colliderarr[i + 1];
476 }
477 }
478 m_colliderarr[10] = value;
479
480 for (i = 0; i < 11; i++)
481 {
482 if (m_colliderarr[i])
483 {
484 truecount++;
485 }
486 else
487 {
488 falsecount++;
489 }
490 }
491
492 // Equal truecounts and false counts means we're colliding with something.
493 m_log.DebugFormat("[PHYSICS]: TrueCount:{0}, FalseCount:{1}",truecount,falsecount);
494 if (falsecount > 1.2 * truecount)
495 {
496 m_iscolliding = false;
497 }
498 else
499 {
500 m_iscolliding = true;
501 }
502 if (m_wascolliding != m_iscolliding)
503 {
504 //base.SendCollisionUpdate(new CollisionEventUpdate());
505 }
506 m_wascolliding = m_iscolliding;
507 }
508 }
509
510 /// <summary>
511 /// Returns if an avatar is colliding with the ground
512 /// </summary>
513 public override bool CollidingGround
514 {
515 get { return m_iscollidingGround; }
516 set
517 {
518 // Collisions against the ground are not really reliable
519 // So, to get a consistant value we have to average the current result over time
520 // Currently we use 1 second = 10 calls to this.
521 int i;
522 int truecount = 0;
523 int falsecount = 0;
524
525 if (m_colliderGroundarr.Length >= 10)
526 {
527 for (i = 0; i < 10; i++)
528 {
529 m_colliderGroundarr[i] = m_colliderGroundarr[i + 1];
530 }
531 }
532 m_colliderGroundarr[10] = value;
533
534 for (i = 0; i < 11; i++)
535 {
536 if (m_colliderGroundarr[i])
537 {
538 truecount++;
539 }
540 else
541 {
542 falsecount++;
543 }
544 }
545
546 // Equal truecounts and false counts means we're colliding with something.
547
548 if (falsecount > 1.2 * truecount)
549 {
550 m_iscollidingGround = false;
551 }
552 else
553 {
554 m_iscollidingGround = true;
555 }
556 if (m_wascollidingGround != m_iscollidingGround)
557 {
558 //base.SendCollisionUpdate(new CollisionEventUpdate());
559 }
560 m_wascollidingGround = m_iscollidingGround;
561 }
562 }
563
564 /// <summary>
565 /// Returns if the avatar is colliding with an object
566 /// </summary>
567 public override bool CollidingObj
568 {
569 get { return m_iscollidingObj; }
570 set
571 {
572 m_iscollidingObj = value;
573 if (value)
574 m_pidControllerActive = false;
575 else
576 m_pidControllerActive = true;
577 }
578 }
579
580
581 public override bool FloatOnWater
582 {
583 set { return; }
584 }
585
586 public override Vector3 RotationalVelocity
587 {
588 get { return m_rotationalVelocity; }
589 set { m_rotationalVelocity = value; }
590 }
591
592 public override bool Kinematic
593 {
594 get { return false; }
595 set { }
596 }
597
598 public override float Buoyancy
599 {
600 get { return m_buoyancy; }
601 set { m_buoyancy = value; }
602 }
603
604 public override Vector3 PIDTarget { set { return; } }
605 public override bool PIDActive { set { return; } }
606 public override float PIDTau { set { return; } }
607
608 public override bool PIDHoverActive
609 {
610 set { return; }
611 }
612
613 public override float PIDHoverHeight
614 {
615 set { return; }
616 }
617
618 public override PIDHoverType PIDHoverType
619 {
620 set { return; }
621 }
622
623 public override float PIDHoverTau
624 {
625 set { return; }
626 }
627
628
629 public override Quaternion APIDTarget
630 {
631 set { return; }
632 }
633
634 public override bool APIDActive
635 {
636 set { return; }
637 }
638
639 public override float APIDStrength
640 {
641 set { return; }
642 }
643
644 public override float APIDDamping
645 {
646 set { return; }
647 }
648
649 /// <summary>
650 /// Adds the force supplied to the Target Velocity
651 /// The PID controller takes this target velocity and tries to make it a reality
652 /// </summary>
653 /// <param name="force"></param>
654 /// <param name="pushforce">Is this a push by a script?</param>
655 public override void AddForce(Vector3 force, bool pushforce)
656 {
657 if (pushforce)
658 {
659 m_pidControllerActive = false;
660 force *= 100f;
661 doForce(force, false);
662 //System.Console.WriteLine("Push!");
663 //_target_velocity.X += force.X;
664 // _target_velocity.Y += force.Y;
665 //_target_velocity.Z += force.Z;
666 }
667 else
668 {
669 m_pidControllerActive = true;
670 m_target_velocity.X += force.X;
671 m_target_velocity.Y += force.Y;
672 m_target_velocity.Z += force.Z;
673 }
674 //m_lastUpdateSent = false;
675 }
676
677 public void doForce(Vector3 force, bool now)
678 {
679
680 tempVector3.setValue(force.X, force.Y, force.Z);
681 if (now)
682 {
683 Body.applyCentralForce(tempVector3);
684 }
685 else
686 {
687 m_taintedForce += force;
688 m_parent_scene.AddPhysicsActorTaint(this);
689 }
690 }
691
692 public void doImpulse(Vector3 force, bool now)
693 {
694
695 tempVector3.setValue(force.X, force.Y, force.Z);
696 if (now)
697 {
698 Body.applyCentralImpulse(tempVector3);
699 }
700 else
701 {
702 m_taintedForce += force;
703 m_parent_scene.AddPhysicsActorTaint(this);
704 }
705 }
706
707 public override void AddAngularForce(Vector3 force, bool pushforce)
708 {
709
710 }
711
712 public override void SetMomentum(Vector3 momentum)
713 {
714
715 }
716
717 public override void SubscribeEvents(int ms)
718 {
719 m_eventsubscription = ms;
720 m_requestedUpdateFrequency = ms;
721 m_parent_scene.addCollisionEventReporting(this);
722 }
723
724 public override void UnSubscribeEvents()
725 {
726 m_parent_scene.remCollisionEventReporting(this);
727 m_eventsubscription = 0;
728 m_requestedUpdateFrequency = 0;
729 }
730
731 public override bool SubscribedEvents()
732 {
733 if (m_eventsubscription > 0)
734 return true;
735 return false;
736 }
737
738 public void AddCollision(uint collideWith, ContactPoint contact)
739 {
740 if (CollisionEventsThisFrame == null)
741 {
742 CollisionEventsThisFrame = new CollisionEventUpdate();
743 }
744 CollisionEventsThisFrame.addCollider(collideWith, contact);
745 }
746
747 public void SendCollisions()
748 {
749 if (m_eventsubscription >= m_requestedUpdateFrequency)
750 {
751 if (CollisionEventsThisFrame != null)
752 {
753 base.SendCollisionUpdate(CollisionEventsThisFrame);
754 }
755 CollisionEventsThisFrame = new CollisionEventUpdate();
756 m_eventsubscription = 0;
757 }
758 return;
759 }
760
761 internal void Dispose()
762 {
763 if (Body.isInWorld())
764 m_parent_scene.removeFromWorld(Body);
765
766 if (m_aMotor.Handle != IntPtr.Zero)
767 m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
768
769 m_aMotor.Dispose(); m_aMotor = null;
770 ClosestCastResult.Dispose(); ClosestCastResult = null;
771 Body.Dispose(); Body = null;
772 Shell.Dispose(); Shell = null;
773 tempQuat1.Dispose();
774 tempTrans1.Dispose();
775 tempVector1.Dispose();
776 tempVector2.Dispose();
777 tempVector3.Dispose();
778 tempVector4.Dispose();
779 tempVector5RayCast.Dispose();
780 tempVector6RayCast.Dispose();
781
782 }
783
784 public void ProcessTaints(float timestep)
785 {
786
787 if (m_tainted_isPhysical != m_isPhysical)
788 {
789 if (m_tainted_isPhysical)
790 {
791 // Create avatar capsule and related ODE data
792 if (!(Shell == null && Body == null))
793 {
794 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
795 + (Shell != null ? "Shell " : "")
796 + (Body != null ? "Body " : ""));
797 }
798 AvatarGeomAndBodyCreation(m_position.X, m_position.Y, m_position.Z);
799
800
801 }
802 else
803 {
804 // destroy avatar capsule and related ODE data
805
806 Dispose();
807 tempVector1 = new btVector3(0, 0, 0);
808 tempVector2 = new btVector3(0, 0, 0);
809 tempVector3 = new btVector3(0, 0, 0);
810 tempVector4 = new btVector3(0, 0, 0);
811
812 tempVector5RayCast = new btVector3(0, 0, 0);
813 tempVector6RayCast = new btVector3(0, 0, 0);
814 tempVector7RayCast = new btVector3(0, 0, 0);
815
816 tempQuat1 = new btQuaternion(0, 0, 0, 1);
817 tempTrans1 = new btTransform(tempQuat1, tempVector1);
818 // m_movementComparision = new PhysicsVector(0, 0, 0);
819 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
820 }
821
822 m_isPhysical = m_tainted_isPhysical;
823 }
824
825 if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH)
826 {
827 if (Body != null)
828 {
829
830 m_pidControllerActive = true;
831 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
832 //d.JointDestroy(Amotor);
833 float prevCapsule = CAPSULE_LENGTH;
834 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
835 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
836 Dispose();
837
838 tempVector1 = new btVector3(0, 0, 0);
839 tempVector2 = new btVector3(0, 0, 0);
840 tempVector3 = new btVector3(0, 0, 0);
841 tempVector4 = new btVector3(0, 0, 0);
842
843 tempVector5RayCast = new btVector3(0, 0, 0);
844 tempVector6RayCast = new btVector3(0, 0, 0);
845 tempVector7RayCast = new btVector3(0, 0, 0);
846
847 tempQuat1 = new btQuaternion(0, 0, 0, 1);
848 tempTrans1 = new btTransform(tempQuat1, tempVector1);
849 // m_movementComparision = new PhysicsVector(0, 0, 0);
850 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
851
852 AvatarGeomAndBodyCreation(m_position.X, m_position.Y,
853 m_position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2));
854 Velocity = Vector3.Zero;
855
856 }
857 else
858 {
859 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
860 + (Shell == null ? "Shell " : "")
861 + (Body == null ? "Body " : ""));
862 }
863 }
864 if (m_taintRemove)
865 {
866 Dispose();
867 }
868 }
869
870 /// <summary>
871 /// Called from Simulate
872 /// This is the avatar's movement control + PID Controller
873 /// </summary>
874 /// <param name="timeStep"></param>
875 public void Move(float timeStep)
876 {
877 // no lock; for now it's only called from within Simulate()
878
879 // If the PID Controller isn't active then we set our force
880 // calculating base velocity to the current position
881 if (Body == null)
882 return;
883 tempTrans1.Dispose();
884 tempTrans1 = Body.getInterpolationWorldTransform();
885 tempVector1.Dispose();
886 tempVector1 = tempTrans1.getOrigin();
887 tempVector2.Dispose();
888 tempVector2 = Body.getInterpolationLinearVelocity();
889
890 if (m_pidControllerActive == false)
891 {
892 m_zeroPosition.X = tempVector1.getX();
893 m_zeroPosition.Y = tempVector1.getY();
894 m_zeroPosition.Z = tempVector1.getZ();
895 }
896 //PidStatus = true;
897
898 Vector3 vec = Vector3.Zero;
899
900 Vector3 vel = new Vector3(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
901
902 float movementdivisor = 1f;
903
904 if (!m_alwaysRun)
905 {
906 movementdivisor = walkDivisor;
907 }
908 else
909 {
910 movementdivisor = runDivisor;
911 }
912
913 // if velocity is zero, use position control; otherwise, velocity control
914 if (m_target_velocity.X == 0.0f && m_target_velocity.Y == 0.0f && m_target_velocity.Z == 0.0f && m_iscolliding)
915 {
916 // keep track of where we stopped. No more slippin' & slidin'
917 if (!m_zeroFlag)
918 {
919 m_zeroFlag = true;
920 m_zeroPosition.X = tempVector1.getX();
921 m_zeroPosition.Y = tempVector1.getY();
922 m_zeroPosition.Z = tempVector1.getZ();
923 }
924 if (m_pidControllerActive)
925 {
926 // We only want to deactivate the PID Controller if we think we want to have our surrogate
927 // react to the physics scene by moving it's position.
928 // Avatar to Avatar collisions
929 // Prim to avatar collisions
930
931 Vector3 pos = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
932 vec.X = (m_target_velocity.X - vel.X) * (PID_D) + (m_zeroPosition.X - pos.X) * (PID_P * 2);
933 vec.Y = (m_target_velocity.Y - vel.Y) * (PID_D) + (m_zeroPosition.Y - pos.Y) * (PID_P * 2);
934 if (m_flying)
935 {
936 vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D) + (m_zeroPosition.Z - pos.Z) * PID_P;
937 }
938 }
939 //PidStatus = true;
940 }
941 else
942 {
943 m_pidControllerActive = true;
944 m_zeroFlag = false;
945 if (m_iscolliding && !m_flying)
946 {
947 // We're standing on something
948 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
949 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
950 }
951 else if (m_iscolliding && m_flying)
952 {
953 // We're flying and colliding with something
954 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
955 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
956 }
957 else if (!m_iscolliding && m_flying)
958 {
959 // we're in mid air suspended
960 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
961 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);
962
963 // We don't want linear velocity to cause our avatar to bounce, so we check target Z and actual velocity X, Y
964 // rebound preventing
965 if (m_target_velocity.Z < 0.025f && m_velocity.X < 0.25f && m_velocity.Y < 0.25f)
966 m_zeroFlag = true;
967 }
968
969 if (m_iscolliding && !m_flying && m_target_velocity.Z > 0.0f)
970 {
971 // We're colliding with something and we're not flying but we're moving
972 // This means we're walking or running.
973 Vector3 pos = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
974 vec.Z = (m_target_velocity.Z - vel.Z) * PID_D + (m_zeroPosition.Z - pos.Z) * PID_P;
975 if (m_target_velocity.X > 0)
976 {
977 vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
978 }
979 if (m_target_velocity.Y > 0)
980 {
981 vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
982 }
983 }
984 else if (!m_iscolliding && !m_flying)
985 {
986 // we're not colliding and we're not flying so that means we're falling!
987 // m_iscolliding includes collisions with the ground.
988
989 // d.Vector3 pos = d.BodyGetPosition(Body);
990 if (m_target_velocity.X > 0)
991 {
992 vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
993 }
994 if (m_target_velocity.Y > 0)
995 {
996 vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
997 }
998 }
999
1000
1001 if (m_flying)
1002 {
1003 vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D);
1004 }
1005 }
1006 if (m_flying)
1007 {
1008 // Slight PID correction
1009 vec.Z += (((-1 * m_parent_scene.gravityz) * m_mass) * 0.06f);
1010
1011
1012 //auto fly height. Kitto Flora
1013 //d.Vector3 pos = d.BodyGetPosition(Body);
1014 float target_altitude = m_parent_scene.GetTerrainHeightAtXY(m_position.X, m_position.Y) + 5.0f;
1015
1016 if (m_position.Z < target_altitude)
1017 {
1018 vec.Z += (target_altitude - m_position.Z) * PID_P * 5.0f;
1019 }
1020
1021 }
1022 if (Body != null && (((m_target_velocity.X > 0.2f || m_target_velocity.X < -0.2f) || (m_target_velocity.Y > 0.2f || m_target_velocity.Y < -0.2f))))
1023 {
1024 Body.setFriction(0.001f);
1025 //m_log.DebugFormat("[PHYSICS]: Avatar force applied: {0}, Target:{1}", vec.ToString(), m_target_velocity.ToString());
1026 }
1027
1028 if (Body != null)
1029 {
1030 int activationstate = Body.getActivationState();
1031 if (activationstate == 0)
1032 {
1033 Body.forceActivationState(1);
1034 }
1035
1036
1037 }
1038 doImpulse(vec, true);
1039 }
1040
1041 /// <summary>
1042 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
1043 /// </summary>
1044 public void UpdatePositionAndVelocity()
1045 {
1046 if (Body == null)
1047 return;
1048 //int val = Environment.TickCount;
1049 CheckIfStandingOnObject();
1050 //m_log.DebugFormat("time:{0}", Environment.TickCount - val);
1051
1052 //IsColliding = Body.checkCollideWith(m_parent_scene.TerrainBody);
1053
1054 tempTrans1.Dispose();
1055 tempTrans1 = Body.getInterpolationWorldTransform();
1056 tempVector1.Dispose();
1057 tempVector1 = tempTrans1.getOrigin();
1058 tempVector2.Dispose();
1059 tempVector2 = Body.getInterpolationLinearVelocity();
1060
1061 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
1062 Vector3 vec = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
1063
1064 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
1065 if (vec.X < -10.0f) vec.X = 0.0f;
1066 if (vec.Y < -10.0f) vec.Y = 0.0f;
1067 if (vec.X > (int)Constants.RegionSize + 10.2f) vec.X = (int)Constants.RegionSize + 10.2f;
1068 if (vec.Y > (int)Constants.RegionSize + 10.2f) vec.Y = (int)Constants.RegionSize + 10.2f;
1069
1070 m_position.X = vec.X;
1071 m_position.Y = vec.Y;
1072 m_position.Z = vec.Z;
1073
1074 // Did we move last? = zeroflag
1075 // This helps keep us from sliding all over
1076
1077 if (m_zeroFlag)
1078 {
1079 m_velocity.X = 0.0f;
1080 m_velocity.Y = 0.0f;
1081 m_velocity.Z = 0.0f;
1082
1083 // Did we send out the 'stopped' message?
1084 if (!m_lastUpdateSent)
1085 {
1086 m_lastUpdateSent = true;
1087 //base.RequestPhysicsterseUpdate();
1088
1089 }
1090 }
1091 else
1092 {
1093 m_lastUpdateSent = false;
1094 vec = new Vector3(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
1095 m_velocity.X = (vec.X);
1096 m_velocity.Y = (vec.Y);
1097
1098 m_velocity.Z = (vec.Z);
1099 //m_log.Debug(m_target_velocity);
1100 if (m_velocity.Z < -6 && !m_hackSentFall)
1101 {
1102 m_hackSentFall = true;
1103 m_pidControllerActive = false;
1104 }
1105 else if (m_flying && !m_hackSentFly)
1106 {
1107 //m_hackSentFly = true;
1108 //base.SendCollisionUpdate(new CollisionEventUpdate());
1109 }
1110 else
1111 {
1112 m_hackSentFly = false;
1113 m_hackSentFall = false;
1114 }
1115 }
1116 if (Body != null)
1117 {
1118 if (Body.getFriction() < 0.9f)
1119 Body.setFriction(0.9f);
1120 }
1121 //if (Body != null)
1122 // Body.clearForces();
1123 }
1124
1125 public void CheckIfStandingOnObject()
1126 {
1127
1128 float capsuleHalfHeight = ((CAPSULE_LENGTH + 2*CAPSULE_RADIUS)*0.5f);
1129
1130 tempVector5RayCast.setValue(m_position.X, m_position.Y, m_position.Z);
1131 tempVector6RayCast.setValue(m_position.X, m_position.Y, m_position.Z - 1 * capsuleHalfHeight * 1.1f);
1132
1133
1134 ClosestCastResult.Dispose();
1135 ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
1136
1137 try
1138 {
1139 m_parent_scene.getBulletWorld().rayTest(tempVector5RayCast, tempVector6RayCast, ClosestCastResult);
1140 }
1141 catch (AccessViolationException)
1142 {
1143 m_log.Debug("BAD!");
1144 }
1145 if (ClosestCastResult.hasHit())
1146 {
1147
1148 if (tempVector7RayCast != null)
1149 tempVector7RayCast.Dispose();
1150
1151 //tempVector7RayCast = ClosestCastResult.getHitPointWorld();
1152
1153 /*if (tempVector7RayCast == null) // null == no result also
1154 {
1155 CollidingObj = false;
1156 IsColliding = false;
1157 CollidingGround = false;
1158
1159 return;
1160 }
1161 float zVal = tempVector7RayCast.getZ();
1162 if (zVal != 0)
1163 m_log.Debug("[PHYSICS]: HAAAA");
1164 if (zVal < m_position.Z && zVal > ((CAPSULE_LENGTH + 2 * CAPSULE_RADIUS) *0.5f))
1165 {
1166 CollidingObj = true;
1167 IsColliding = true;
1168 }
1169 else
1170 {
1171 CollidingObj = false;
1172 IsColliding = false;
1173 CollidingGround = false;
1174 }*/
1175
1176 //height+2*radius = capsule full length
1177 //CollidingObj = true;
1178 //IsColliding = true;
1179 m_iscolliding = true;
1180 }
1181 else
1182 {
1183 //CollidingObj = false;
1184 //IsColliding = false;
1185 //CollidingGround = false;
1186 m_iscolliding = false;
1187 }
1188 }
1189 }
1190
1191}
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPlugin.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPlugin.cs
deleted file mode 100644
index cf75c48..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPlugin.cs
+++ /dev/null
@@ -1,65 +0,0 @@
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 OpenSim.Region.Physics.Manager;
29
30namespace OpenSim.Region.Physics.BulletDotNETPlugin
31{
32 public class BulletDotNetPlugin : IPhysicsPlugin
33 {
34 private BulletDotNETScene m_scene;
35 private const string m_pluginName = "BulletDotNETPlugin";
36
37 #region IPhysicsPlugin Members
38
39 public bool Init()
40 {
41 return true;
42 }
43
44 public PhysicsScene GetScene(string sceneIdentifier)
45 {
46 if (m_scene == null)
47 {
48 m_scene = new BulletDotNETScene(sceneIdentifier);
49 }
50 return m_scene;
51 }
52
53 public string GetName()
54 {
55 return m_pluginName;
56 }
57
58 public void Dispose()
59 {
60
61 }
62
63 #endregion
64 }
65} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPluginStructs.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPluginStructs.cs
deleted file mode 100644
index 578c22a..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPluginStructs.cs
+++ /dev/null
@@ -1,60 +0,0 @@
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;
29
30public enum StatusIndicators : int
31{
32 Generic = 0,
33 Start = 1,
34 End = 2
35}
36
37public struct sCollisionData
38{
39 public uint ColliderLocalId;
40 public uint CollidedWithLocalId;
41 public int NumberOfCollisions;
42 public int CollisionType;
43 public int StatusIndicator;
44 public int lastframe;
45}
46
47[Flags]
48public enum CollisionCategories : int
49{
50 Disabled = 0,
51 Geom = 0x00000001,
52 Body = 0x00000002,
53 Space = 0x00000004,
54 Character = 0x00000008,
55 Land = 0x00000010,
56 Water = 0x00000020,
57 Wind = 0x00000040,
58 Sensor = 0x00000080,
59 Selected = 0x00000100
60} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs
deleted file mode 100644
index dc3229a..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs
+++ /dev/null
@@ -1,2767 +0,0 @@
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 log4net;
34using OpenMetaverse;
35using BulletDotNET;
36using OpenSim.Framework;
37using OpenSim.Region.Physics.Manager;
38
39
40namespace OpenSim.Region.Physics.BulletDotNETPlugin
41{
42 public class BulletDotNETPrim : PhysicsActor
43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 private Vector3 _position;
47 private Vector3 m_zeroPosition;
48 private Vector3 _velocity;
49 private Vector3 _torque;
50 private Vector3 m_lastVelocity;
51 private Vector3 m_lastposition;
52 private Quaternion m_lastorientation = Quaternion.Identity;
53 private Vector3 m_rotationalVelocity;
54 private Vector3 _size;
55 private Vector3 _acceleration;
56 // private d.Vector3 _zeroPosition = new d.Vector3(0.0f, 0.0f, 0.0f);
57 private Quaternion _orientation;
58 private Vector3 m_taintposition;
59 private Vector3 m_taintsize;
60 private Vector3 m_taintVelocity;
61 private Vector3 m_taintTorque;
62 private Quaternion m_taintrot;
63 private Vector3 m_angularlock = Vector3.One;
64 private Vector3 m_taintAngularLock = Vector3.One;
65 // private btGeneric6DofConstraint Amotor;
66
67 private Vector3 m_PIDTarget;
68 private float m_PIDTau;
69 private float m_PIDHoverHeight;
70 private float m_PIDHoverTau;
71 private bool m_useHoverPID;
72 private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
73 private float m_targetHoverHeight;
74 private float m_groundHeight;
75 private float m_waterHeight;
76 private float PID_D = 35f;
77 private float PID_G = 25f;
78 // private float m_tensor = 5f;
79 // private int body_autodisable_frames = 20;
80 private IMesh primMesh;
81
82 private bool m_usePID;
83
84 private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
85 | CollisionCategories.Space
86 | CollisionCategories.Body
87 | CollisionCategories.Character
88 );
89
90 private bool m_taintshape;
91 private bool m_taintPhysics;
92 // private bool m_collidesLand = true;
93 private bool m_collidesWater;
94 public bool m_returnCollisions;
95
96 // Default we're a Geometry
97 // private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
98
99 // Default, Collide with Other Geometries, spaces and Bodies
100 // private CollisionCategories m_collisionFlags = m_default_collisionFlags;
101
102 public bool m_taintremove;
103 public bool m_taintdisable;
104 public bool m_disabled;
105 public bool m_taintadd;
106 public bool m_taintselected;
107 public bool m_taintCollidesWater;
108
109 public uint m_localID;
110
111 //public GCHandle gc;
112 // private CollisionLocker ode;
113
114 private bool m_taintforce;
115 private bool m_taintaddangularforce;
116 private Vector3 m_force;
117 private List<Vector3> m_forcelist = new List<Vector3>();
118 private List<Vector3> m_angularforcelist = new List<Vector3>();
119
120 private IMesh _mesh;
121 private PrimitiveBaseShape _pbs;
122 private BulletDotNETScene _parent_scene;
123 public btCollisionShape prim_geom;
124 public IntPtr _triMeshData;
125
126 private PhysicsActor _parent;
127 private PhysicsActor m_taintparent;
128
129 private List<BulletDotNETPrim> childrenPrim = new List<BulletDotNETPrim>();
130
131 private bool iscolliding;
132 private bool m_isphysical;
133 private bool m_isSelected;
134
135 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
136
137 private bool m_throttleUpdates;
138 // private int throttleCounter;
139 public int m_interpenetrationcount;
140 public float m_collisionscore;
141 public int m_roundsUnderMotionThreshold;
142 private int m_crossingfailures;
143
144 public float m_buoyancy;
145
146 public bool outofBounds;
147 private float m_density = 10.000006836f; // Aluminum g/cm3;
148
149 public bool _zeroFlag;
150 private bool m_lastUpdateSent;
151
152
153 private String m_primName;
154 private Vector3 _target_velocity;
155
156 public int m_eventsubscription;
157 private int m_requestedUpdateFrequency = 0;
158 private CollisionEventUpdate CollisionEventsThisFrame = null;
159
160 public volatile bool childPrim;
161
162 private btVector3 tempPosition1;
163 private btVector3 tempPosition2;
164 private btVector3 tempPosition3;
165 private btVector3 tempSize1;
166 private btVector3 tempSize2;
167 private btVector3 tempLinearVelocity1;
168 private btVector3 tempLinearVelocity2;
169 private btVector3 tempAngularVelocity1;
170 private btVector3 tempAngularVelocity2;
171 private btVector3 tempInertia1;
172 private btVector3 tempInertia2;
173 private btVector3 tempAddForce;
174 private btQuaternion tempOrientation1;
175 private btQuaternion tempOrientation2;
176 private btMotionState tempMotionState1;
177 private btMotionState tempMotionState2;
178 private btMotionState tempMotionState3;
179 private btTransform tempTransform1;
180 private btTransform tempTransform2;
181 private btTransform tempTransform3;
182 private btTransform tempTransform4;
183 private btTriangleIndexVertexArray btshapeArray;
184 private btVector3 AxisLockAngleHigh;
185 private btVector3 AxisLockLinearLow;
186 private btVector3 AxisLockLinearHigh;
187 private bool forceenable = false;
188
189 private btGeneric6DofConstraint m_aMotor;
190
191 public btRigidBody Body;
192
193 public BulletDotNETPrim(String primName, BulletDotNETScene parent_scene, Vector3 pos, Vector3 size,
194 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical)
195 {
196 tempPosition1 = new btVector3(0, 0, 0);
197 tempPosition2 = new btVector3(0, 0, 0);
198 tempPosition3 = new btVector3(0, 0, 0);
199 tempSize1 = new btVector3(0, 0, 0);
200 tempSize2 = new btVector3(0, 0, 0);
201 tempLinearVelocity1 = new btVector3(0, 0, 0);
202 tempLinearVelocity2 = new btVector3(0, 0, 0);
203 tempAngularVelocity1 = new btVector3(0, 0, 0);
204 tempAngularVelocity2 = new btVector3(0, 0, 0);
205 tempInertia1 = new btVector3(0, 0, 0);
206 tempInertia2 = new btVector3(0, 0, 0);
207 tempOrientation1 = new btQuaternion(0, 0, 0, 1);
208 tempOrientation2 = new btQuaternion(0, 0, 0, 1);
209 _parent_scene = parent_scene;
210 tempTransform1 = new btTransform(_parent_scene.QuatIdentity, _parent_scene.VectorZero);
211 tempTransform2 = new btTransform(_parent_scene.QuatIdentity, _parent_scene.VectorZero); ;
212 tempTransform3 = new btTransform(_parent_scene.QuatIdentity, _parent_scene.VectorZero); ;
213 tempTransform4 = new btTransform(_parent_scene.QuatIdentity, _parent_scene.VectorZero); ;
214
215 tempMotionState1 = new btDefaultMotionState(_parent_scene.TransZero);
216 tempMotionState2 = new btDefaultMotionState(_parent_scene.TransZero);
217 tempMotionState3 = new btDefaultMotionState(_parent_scene.TransZero);
218
219
220 AxisLockLinearLow = new btVector3(-1 * (int)Constants.RegionSize, -1 * (int)Constants.RegionSize, -1 * (int)Constants.RegionSize);
221 int regionsize = (int)Constants.RegionSize;
222
223 if (regionsize == 256)
224 regionsize = 512;
225
226 AxisLockLinearHigh = new btVector3((int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionSize);
227
228 _target_velocity = Vector3.Zero;
229 _velocity = Vector3.Zero;
230 _position = pos;
231 m_taintposition = pos;
232 PID_D = parent_scene.bodyPIDD;
233 PID_G = parent_scene.bodyPIDG;
234 m_density = parent_scene.geomDefaultDensity;
235 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
236 // body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
237
238 prim_geom = null;
239 Body = null;
240
241 if (size.X <= 0) size.X = 0.01f;
242 if (size.Y <= 0) size.Y = 0.01f;
243 if (size.Z <= 0) size.Z = 0.01f;
244
245 _size = size;
246 m_taintsize = _size;
247 _acceleration = Vector3.Zero;
248 m_rotationalVelocity = Vector3.Zero;
249 _orientation = rotation;
250 m_taintrot = _orientation;
251 _mesh = mesh;
252 _pbs = pbs;
253
254 _parent_scene = parent_scene;
255
256 if (pos.Z < 0)
257 m_isphysical = false;
258 else
259 {
260 m_isphysical = pisPhysical;
261 // If we're physical, we need to be in the master space for now.
262 // linksets *should* be in a space together.. but are not currently
263 }
264 m_primName = primName;
265 m_taintadd = true;
266 _parent_scene.AddPhysicsActorTaint(this);
267
268 }
269
270 #region PhysicsActor overrides
271
272 public override bool Stopped
273 {
274 get { return _zeroFlag; }
275 }
276
277 public override Vector3 Size
278 {
279 get { return _size; }
280 set { _size = value; }
281 }
282
283 public override PrimitiveBaseShape Shape
284 {
285 set
286 {
287 _pbs = value;
288 m_taintshape = true;
289 }
290 }
291
292 public override uint LocalID
293 {
294 set
295 {
296 //m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
297 m_localID = value;
298 }
299 }
300
301 public override bool Grabbed
302 {
303 set { return; }
304 }
305
306 public override bool Selected
307 {
308 set
309 {
310 // This only makes the object not collidable if the object
311 // is physical or the object is modified somehow *IN THE FUTURE*
312 // without this, if an avatar selects prim, they can walk right
313 // through it while it's selected
314 m_collisionscore = 0;
315 if ((m_isphysical && !_zeroFlag) || !value)
316 {
317 m_taintselected = value;
318 _parent_scene.AddPhysicsActorTaint(this);
319 }
320 else
321 {
322 m_taintselected = value;
323 m_isSelected = value;
324 }
325 }
326 }
327
328 public override void CrossingFailure()
329 {
330 m_crossingfailures++;
331 if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds)
332 {
333 base.RaiseOutOfBounds(_position);
334 return;
335 }
336 else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds)
337 {
338 m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName);
339 }
340 }
341 public override void link(PhysicsActor obj)
342 {
343 m_taintparent = obj;
344 }
345
346 public override void delink()
347 {
348 m_taintparent = null;
349 }
350
351 public override void LockAngularMotion(Vector3 axis)
352 {
353 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
354 m_taintAngularLock = axis;
355 }
356
357 public override Vector3 Position
358 {
359 get { return _position; }
360
361 set
362 {
363 _position = value;
364 //m_log.Info("[PHYSICS]: " + _position.ToString());
365 }
366 }
367
368 public override float Mass
369 {
370 get { return CalculateMass(); }
371 }
372
373 public override Vector3 Force
374 {
375 //get { return Vector3.Zero; }
376 get { return m_force; }
377 set { m_force = value; }
378 }
379
380 public override int VehicleType
381 {
382 get { return 0; }
383 set { return; }
384 }
385
386 public override void VehicleFloatParam(int param, float value)
387 {
388 //TODO:
389 }
390
391 public override void VehicleVectorParam(int param, Vector3 value)
392 {
393 //TODO:
394 }
395
396 public override void VehicleRotationParam(int param, Quaternion rotation)
397 {
398 //TODO:
399 }
400
401 public override void VehicleFlags(int param, bool remove)
402 {
403
404 }
405
406 public override void SetVolumeDetect(int param)
407 {
408 //TODO: GhostObject
409 m_isVolumeDetect = (param != 0);
410
411 }
412
413 public override Vector3 GeometricCenter
414 {
415 get { return Vector3.Zero; }
416 }
417
418 public override Vector3 CenterOfMass
419 {
420 get { return Vector3.Zero; }
421 }
422
423 public override Vector3 Velocity
424 {
425 get
426 {
427 // Averate previous velocity with the new one so
428 // client object interpolation works a 'little' better
429 Vector3 returnVelocity;
430 returnVelocity.X = (m_lastVelocity.X + _velocity.X) / 2;
431 returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) / 2;
432 returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) / 2;
433 return returnVelocity;
434 }
435 set
436 {
437 _velocity = value;
438
439 m_taintVelocity = value;
440 _parent_scene.AddPhysicsActorTaint(this);
441 }
442 }
443
444 public override Vector3 Torque
445 {
446 get
447 {
448 if (!m_isphysical || Body.Handle == IntPtr.Zero)
449 return Vector3.Zero;
450
451 return _torque;
452 }
453
454 set
455 {
456 m_taintTorque = value;
457 _parent_scene.AddPhysicsActorTaint(this);
458 }
459 }
460
461 public override float CollisionScore
462 {
463 get { return m_collisionscore; }
464 set { m_collisionscore = value; }
465 }
466
467 public override Vector3 Acceleration
468 {
469 get { return _acceleration; }
470 }
471
472 public override Quaternion Orientation
473 {
474 get { return _orientation; }
475 set { _orientation = value; }
476 }
477
478 public override int PhysicsActorType
479 {
480 get { return (int)ActorTypes.Prim; }
481 set { return; }
482 }
483
484 public override bool IsPhysical
485 {
486 get { return m_isphysical; }
487 set { m_isphysical = value; }
488 }
489
490 public override bool Flying
491 {
492 // no flying prims for you
493 get { return false; }
494 set { }
495 }
496
497 public override bool SetAlwaysRun
498 {
499 get { return false; }
500 set { return; }
501 }
502
503 public override bool ThrottleUpdates
504 {
505 get { return m_throttleUpdates; }
506 set { m_throttleUpdates = value; }
507 }
508
509 public override bool IsColliding
510 {
511 get { return iscolliding; }
512 set { iscolliding = value; }
513 }
514
515 public override bool CollidingGround
516 {
517 get { return false; }
518 set { return; }
519 }
520
521 public override bool CollidingObj
522 {
523 get { return false; }
524 set { return; }
525 }
526
527 public override bool FloatOnWater
528 {
529 set
530 {
531 m_taintCollidesWater = value;
532 _parent_scene.AddPhysicsActorTaint(this);
533 }
534 }
535
536 public override Vector3 RotationalVelocity
537 {
538 get
539 {
540 Vector3 pv = Vector3.Zero;
541 if (_zeroFlag)
542 return pv;
543 m_lastUpdateSent = false;
544
545 if (m_rotationalVelocity.ApproxEquals(pv, 0.2f))
546 return pv;
547
548 return m_rotationalVelocity;
549 }
550 set { m_rotationalVelocity = value; }
551 }
552
553 public override bool Kinematic
554 {
555 get { return false; }
556 set { }
557 }
558
559 public override float Buoyancy
560 {
561 get { return m_buoyancy; }
562 set { m_buoyancy = value; }
563 }
564
565 public override Vector3 PIDTarget { set { m_PIDTarget = value; ; } }
566 public override bool PIDActive { set { m_usePID = value; } }
567 public override float PIDTau { set { m_PIDTau = value; } }
568
569 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
570 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
571 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
572 public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
573
574 public override Quaternion APIDTarget { set { return; } }
575 public override bool APIDActive { set { return; } }
576 public override float APIDStrength { set { return; } }
577 public override float APIDDamping { set { return; } }
578
579 public override void AddForce(Vector3 force, bool pushforce)
580 {
581 m_forcelist.Add(force);
582 m_taintforce = true;
583 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
584 }
585
586 public override void AddAngularForce(Vector3 force, bool pushforce)
587 {
588 m_angularforcelist.Add(force);
589 m_taintaddangularforce = true;
590 }
591
592 public override void SetMomentum(Vector3 momentum)
593 {
594 }
595
596 public override void SubscribeEvents(int ms)
597 {
598 m_eventsubscription = ms;
599 m_requestedUpdateFrequency = ms;
600 _parent_scene.addCollisionEventReporting(this);
601 }
602
603 public override void UnSubscribeEvents()
604 {
605 _parent_scene.remCollisionEventReporting(this);
606 m_eventsubscription = 0;
607 m_requestedUpdateFrequency = 0;
608 }
609
610 public override bool SubscribedEvents()
611 {
612 return (m_eventsubscription > 0);
613 }
614
615 #endregion
616
617 public void AddCollision(uint collideWith, ContactPoint contact)
618 {
619 if (CollisionEventsThisFrame == null)
620 {
621 CollisionEventsThisFrame = new CollisionEventUpdate();
622 }
623 CollisionEventsThisFrame.addCollider(collideWith, contact);
624 }
625
626 public void SendCollisions()
627 {
628 if (m_eventsubscription >= m_requestedUpdateFrequency)
629 {
630 if (CollisionEventsThisFrame != null)
631 {
632 base.SendCollisionUpdate(CollisionEventsThisFrame);
633 }
634 CollisionEventsThisFrame = null;
635 // m_eventsubscription = 0;
636 }
637 return;
638 }
639
640 internal void Dispose()
641 {
642 //TODO:
643 DisableAxisMotor();
644 DisposeOfBody();
645 SetCollisionShape(null);
646
647 if (tempMotionState3 != null && tempMotionState3.Handle != IntPtr.Zero)
648 {
649 tempMotionState3.Dispose();
650 tempMotionState3 = null;
651 }
652
653 if (tempMotionState2 != null && tempMotionState2.Handle != IntPtr.Zero)
654 {
655 tempMotionState2.Dispose();
656 tempMotionState2 = null;
657 }
658
659 if (tempMotionState1 != null && tempMotionState1.Handle != IntPtr.Zero)
660 {
661 tempMotionState1.Dispose();
662 tempMotionState1 = null;
663 }
664
665 if (tempTransform4 != null && tempTransform4.Handle != IntPtr.Zero)
666 {
667 tempTransform4.Dispose();
668 tempTransform4 = null;
669 }
670
671 if (tempTransform3 != null && tempTransform3.Handle != IntPtr.Zero)
672 {
673 tempTransform3.Dispose();
674 tempTransform3 = null;
675 }
676
677 if (tempTransform2 != null && tempTransform2.Handle != IntPtr.Zero)
678 {
679 tempTransform2.Dispose();
680 tempTransform2 = null;
681 }
682
683 if (tempTransform1 != null && tempTransform1.Handle != IntPtr.Zero)
684 {
685 tempTransform1.Dispose();
686 tempTransform1 = null;
687 }
688
689 if (tempOrientation2 != null && tempOrientation2.Handle != IntPtr.Zero)
690 {
691 tempOrientation2.Dispose();
692 tempOrientation2 = null;
693 }
694
695 if (tempOrientation1 != null && tempOrientation1.Handle != IntPtr.Zero)
696 {
697 tempOrientation1.Dispose();
698 tempOrientation1 = null;
699 }
700
701 if (tempInertia1 != null && tempInertia1.Handle != IntPtr.Zero)
702 {
703 tempInertia1.Dispose();
704 tempInertia1 = null;
705 }
706
707 if (tempInertia2 != null && tempInertia2.Handle != IntPtr.Zero)
708 {
709 tempInertia2.Dispose();
710 tempInertia1 = null;
711 }
712
713
714 if (tempAngularVelocity2 != null && tempAngularVelocity2.Handle != IntPtr.Zero)
715 {
716 tempAngularVelocity2.Dispose();
717 tempAngularVelocity2 = null;
718 }
719
720 if (tempAngularVelocity1 != null && tempAngularVelocity1.Handle != IntPtr.Zero)
721 {
722 tempAngularVelocity1.Dispose();
723 tempAngularVelocity1 = null;
724 }
725
726 if (tempLinearVelocity2 != null && tempLinearVelocity2.Handle != IntPtr.Zero)
727 {
728 tempLinearVelocity2.Dispose();
729 tempLinearVelocity2 = null;
730 }
731
732 if (tempLinearVelocity1 != null && tempLinearVelocity1.Handle != IntPtr.Zero)
733 {
734 tempLinearVelocity1.Dispose();
735 tempLinearVelocity1 = null;
736 }
737
738 if (tempSize2 != null && tempSize2.Handle != IntPtr.Zero)
739 {
740 tempSize2.Dispose();
741 tempSize2 = null;
742 }
743
744 if (tempSize1 != null && tempSize1.Handle != IntPtr.Zero)
745 {
746 tempSize1.Dispose();
747 tempSize1 = null;
748 }
749
750 if (tempPosition3 != null && tempPosition3.Handle != IntPtr.Zero)
751 {
752 tempPosition3.Dispose();
753 tempPosition3 = null;
754 }
755
756 if (tempPosition2 != null && tempPosition2.Handle != IntPtr.Zero)
757 {
758 tempPosition2.Dispose();
759 tempPosition2 = null;
760 }
761
762 if (tempPosition1 != null && tempPosition1.Handle != IntPtr.Zero)
763 {
764 tempPosition1.Dispose();
765 tempPosition1 = null;
766 }
767 if (AxisLockLinearLow != null && AxisLockLinearLow.Handle != IntPtr.Zero)
768 {
769 AxisLockLinearLow.Dispose();
770 AxisLockLinearLow = null;
771 }
772 if (AxisLockLinearHigh != null && AxisLockLinearHigh.Handle != IntPtr.Zero)
773 {
774 AxisLockLinearHigh.Dispose();
775 AxisLockLinearHigh = null;
776 }
777
778 }
779
780
781
782 public void ProcessTaints(float timestep)
783 {
784 if (m_taintadd)
785 {
786 // m_log.Debug("[PHYSICS]: TaintAdd");
787 changeadd(timestep);
788 }
789
790 if (prim_geom == null)
791 {
792 CreateGeom(IntPtr.Zero, primMesh);
793
794 if (IsPhysical)
795 SetBody(Mass);
796 else
797 SetBody(0);
798 // m_log.Debug("[PHYSICS]: GEOM_DOESNT_EXSIT");
799 }
800
801 if (prim_geom.Handle == IntPtr.Zero)
802 {
803 CreateGeom(IntPtr.Zero, primMesh);
804
805 if (IsPhysical)
806 SetBody(Mass);
807 else
808 SetBody(0);
809 // m_log.Debug("[PHYSICS]: GEOM_DOESNT_EXSIT");
810
811 }
812
813 if (!_position.ApproxEquals(m_taintposition, 0f))
814 {
815 // m_log.Debug("[PHYSICS]: TaintMove");
816 changemove(timestep);
817 }
818 if (m_taintrot != _orientation)
819 {
820 // m_log.Debug("[PHYSICS]: TaintRotate");
821 rotate(timestep);
822 } //
823
824 if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent))
825 {
826 // m_log.Debug("[PHYSICS]: TaintPhysics");
827 changePhysicsStatus(timestep);
828 }
829 //
830
831 if (!_size.ApproxEquals(m_taintsize, 0f))
832 {
833 // m_log.Debug("[PHYSICS]: TaintSize");
834 changesize(timestep);
835 }
836
837 //
838
839 if (m_taintshape)
840 {
841 // m_log.Debug("[PHYSICS]: TaintShape");
842 changeshape(timestep);
843 } //
844
845 if (m_taintforce)
846 {
847 // m_log.Debug("[PHYSICS]: TaintForce");
848 changeAddForce(timestep);
849 }
850 if (m_taintaddangularforce)
851 {
852 // m_log.Debug("[PHYSICS]: TaintAngularForce");
853 changeAddAngularForce(timestep);
854 }
855 if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f))
856 {
857 // m_log.Debug("[PHYSICS]: TaintTorque");
858 changeSetTorque(timestep);
859 }
860 if (m_taintdisable)
861 {
862 // m_log.Debug("[PHYSICS]: TaintDisable");
863 changedisable(timestep);
864 }
865 if (m_taintselected != m_isSelected)
866 {
867 // m_log.Debug("[PHYSICS]: TaintSelected");
868 changeSelectedStatus(timestep);
869 }
870 if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f))
871 {
872 // m_log.Debug("[PHYSICS]: TaintVelocity");
873 changevelocity(timestep);
874 }
875 if (m_taintparent != _parent)
876 {
877 // m_log.Debug("[PHYSICS]: TaintLink");
878 changelink(timestep);
879 }
880 if (m_taintCollidesWater != m_collidesWater)
881 {
882 changefloatonwater(timestep);
883 }
884 if (!m_angularlock.ApproxEquals(m_taintAngularLock, 0))
885 {
886 // m_log.Debug("[PHYSICS]: TaintAngularLock");
887 changeAngularLock(timestep);
888 }
889 if (m_taintremove)
890 {
891 DisposeOfBody();
892 Dispose();
893 }
894
895 }
896
897 #region Physics Scene Change Action routines
898
899 private void changeadd(float timestep)
900 {
901 //SetCollisionShape(null);
902 // Construction of new prim
903 if (Body != null)
904 {
905 if (Body.Handle != IntPtr.Zero)
906 {
907 DisableAxisMotor();
908 _parent_scene.removeFromWorld(this, Body);
909 //Body.Dispose();
910 }
911 //Body = null;
912 // TODO: dispose parts that make up body
913 }
914 if (_parent_scene.needsMeshing(_pbs))
915 {
916 // Don't need to re-enable body.. it's done in SetMesh
917 float meshlod = _parent_scene.meshSculptLOD;
918
919 if (IsPhysical)
920 meshlod = _parent_scene.MeshSculptphysicalLOD;
921
922 IMesh mesh = _parent_scene.mesher.CreateMesh(SOPName, _pbs, _size, meshlod, IsPhysical);
923 // createmesh returns null when it doesn't mesh.
924 CreateGeom(IntPtr.Zero, mesh);
925 }
926 else
927 {
928 _mesh = null;
929 CreateGeom(IntPtr.Zero, null);
930 }
931
932 if (IsPhysical)
933 SetBody(Mass);
934 else
935 SetBody(0);
936 //changeSelectedStatus(timestep);
937 m_taintadd = false;
938
939 }
940
941 private void changemove(float timestep)
942 {
943
944 // m_log.Debug("[PHYSICS]: _________ChangeMove");
945 if (!m_isphysical)
946 {
947 tempTransform2 = Body.getWorldTransform();
948 btQuaternion quat = tempTransform2.getRotation();
949 tempPosition2.setValue(_position.X, _position.Y, _position.Z);
950 tempTransform2.Dispose();
951 tempTransform2 = new btTransform(quat, tempPosition2);
952 Body.setWorldTransform(tempTransform2);
953
954 changeSelectedStatus(timestep);
955
956 resetCollisionAccounting();
957 }
958 else
959 {
960 if (Body != null)
961 {
962 if (Body.Handle != IntPtr.Zero)
963 {
964 DisableAxisMotor();
965 _parent_scene.removeFromWorld(this, Body);
966 //Body.Dispose();
967 }
968 //Body = null;
969 // TODO: dispose parts that make up body
970 }
971 /*
972 if (_parent_scene.needsMeshing(_pbs))
973 {
974 // Don't need to re-enable body.. it's done in SetMesh
975 float meshlod = _parent_scene.meshSculptLOD;
976
977 if (IsPhysical)
978 meshlod = _parent_scene.MeshSculptphysicalLOD;
979
980 IMesh mesh = _parent_scene.mesher.CreateMesh(SOPName, _pbs, _size, meshlod, IsPhysical);
981 // createmesh returns null when it doesn't mesh.
982 CreateGeom(IntPtr.Zero, mesh);
983 }
984 else
985 {
986 _mesh = null;
987 CreateGeom(IntPtr.Zero, null);
988 }
989 SetCollisionShape(prim_geom);
990 */
991 if (m_isphysical)
992 SetBody(Mass);
993 else
994 SetBody(0);
995 changeSelectedStatus(timestep);
996
997 resetCollisionAccounting();
998 }
999 m_taintposition = _position;
1000 }
1001
1002 private void rotate(float timestep)
1003 {
1004 // m_log.Debug("[PHYSICS]: _________ChangeRotate");
1005 tempTransform2 = Body.getWorldTransform();
1006 tempOrientation2 = new btQuaternion(_orientation.X, _orientation.Y, _orientation.Z, _orientation.W);
1007 tempTransform2.setRotation(tempOrientation2);
1008 Body.setWorldTransform(tempTransform2);
1009
1010 resetCollisionAccounting();
1011 m_taintrot = _orientation;
1012 }
1013
1014 private void changePhysicsStatus(float timestep)
1015 {
1016 if (Body != null)
1017 {
1018 if (Body.Handle != IntPtr.Zero)
1019 {
1020 DisableAxisMotor();
1021 _parent_scene.removeFromWorld(this, Body);
1022 //Body.Dispose();
1023 }
1024 //Body = null;
1025 // TODO: dispose parts that make up body
1026 }
1027 // m_log.Debug("[PHYSICS]: _________ChangePhysics");
1028
1029 ProcessGeomCreation();
1030
1031 if (m_isphysical)
1032 SetBody(Mass);
1033 else
1034 SetBody(0);
1035 changeSelectedStatus(timestep);
1036
1037 resetCollisionAccounting();
1038 m_taintPhysics = m_isphysical;
1039 }
1040
1041
1042
1043 internal void ProcessGeomCreation()
1044 {
1045 if (_parent_scene.needsMeshing(_pbs))
1046 {
1047 ProcessGeomCreationAsTriMesh(Vector3.Zero, Quaternion.Identity);
1048 // createmesh returns null when it doesn't mesh.
1049 CreateGeom(IntPtr.Zero, _mesh);
1050 }
1051 else
1052 {
1053 _mesh = null;
1054 CreateGeom(IntPtr.Zero, null);
1055 }
1056 SetCollisionShape(prim_geom);
1057 }
1058
1059 internal bool NeedsMeshing()
1060 {
1061 return _parent_scene.needsMeshing(_pbs);
1062 }
1063
1064 internal void ProcessGeomCreationAsTriMesh(Vector3 positionOffset, Quaternion orientation)
1065 {
1066 // Don't need to re-enable body.. it's done in SetMesh
1067 float meshlod = _parent_scene.meshSculptLOD;
1068
1069 if (IsPhysical)
1070 meshlod = _parent_scene.MeshSculptphysicalLOD;
1071
1072 IMesh mesh = _parent_scene.mesher.CreateMesh(SOPName, _pbs, _size, meshlod, IsPhysical);
1073 if (!positionOffset.ApproxEquals(Vector3.Zero, 0.001f) || orientation != Quaternion.Identity)
1074 {
1075
1076 float[] xyz = new float[3];
1077 xyz[0] = positionOffset.X;
1078 xyz[1] = positionOffset.Y;
1079 xyz[2] = positionOffset.Z;
1080
1081 Matrix4 m4 = Matrix4.CreateFromQuaternion(orientation);
1082
1083 float[,] matrix = new float[3, 3];
1084
1085 matrix[0, 0] = m4.M11;
1086 matrix[0, 1] = m4.M12;
1087 matrix[0, 2] = m4.M13;
1088 matrix[1, 0] = m4.M21;
1089 matrix[1, 1] = m4.M22;
1090 matrix[1, 2] = m4.M23;
1091 matrix[2, 0] = m4.M31;
1092 matrix[2, 1] = m4.M32;
1093 matrix[2, 2] = m4.M33;
1094
1095
1096 mesh.TransformLinear(matrix, xyz);
1097
1098
1099
1100 }
1101
1102 _mesh = mesh;
1103 }
1104
1105 private void changesize(float timestep)
1106 {
1107 if (Body != null)
1108 {
1109 if (Body.Handle != IntPtr.Zero)
1110 {
1111 DisableAxisMotor();
1112 _parent_scene.removeFromWorld(this, Body);
1113 //Body.Dispose();
1114 }
1115 //Body = null;
1116 // TODO: dispose parts that make up body
1117 }
1118
1119 // m_log.Debug("[PHYSICS]: _________ChangeSize");
1120 SetCollisionShape(null);
1121 // Construction of new prim
1122 ProcessGeomCreation();
1123
1124 if (IsPhysical)
1125 SetBody(Mass);
1126 else
1127 SetBody(0);
1128
1129 m_taintsize = _size;
1130
1131 }
1132
1133 private void changeshape(float timestep)
1134 {
1135 if (Body != null)
1136 {
1137 if (Body.Handle != IntPtr.Zero)
1138 {
1139 DisableAxisMotor();
1140 _parent_scene.removeFromWorld(this, Body);
1141 //Body.Dispose();
1142 }
1143 //Body = null;
1144 // TODO: dispose parts that make up body
1145 }
1146 // Cleanup of old prim geometry and Bodies
1147 if (IsPhysical && Body != null && Body.Handle != IntPtr.Zero)
1148 {
1149 if (childPrim)
1150 {
1151 if (_parent != null)
1152 {
1153 BulletDotNETPrim parent = (BulletDotNETPrim)_parent;
1154 parent.ChildDelink(this);
1155 }
1156 }
1157 else
1158 {
1159 //disableBody();
1160 }
1161 }
1162 try
1163 {
1164 //SetCollisionShape(null);
1165 }
1166 catch (System.AccessViolationException)
1167 {
1168 //prim_geom = IntPtr.Zero;
1169 m_log.Error("[PHYSICS]: PrimGeom dead");
1170 }
1171
1172 // we don't need to do space calculation because the client sends a position update also.
1173 if (_size.X <= 0) _size.X = 0.01f;
1174 if (_size.Y <= 0) _size.Y = 0.01f;
1175 if (_size.Z <= 0) _size.Z = 0.01f;
1176 // Construction of new prim
1177
1178 ProcessGeomCreation();
1179
1180 tempPosition1.setValue(_position.X, _position.Y, _position.Z);
1181 if (tempOrientation1.Handle != IntPtr.Zero)
1182 tempOrientation1.Dispose();
1183 tempOrientation1 = new btQuaternion(_orientation.X, Orientation.Y, _orientation.Z, _orientation.W);
1184 if (tempTransform1 != null && tempTransform1.Handle != IntPtr.Zero)
1185 tempTransform1.Dispose();
1186 tempTransform1 = new btTransform(tempOrientation1, tempPosition1);
1187
1188
1189
1190
1191 //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
1192 if (IsPhysical)
1193 {
1194 SetBody(Mass);
1195 // Re creates body on size.
1196 // EnableBody also does setMass()
1197
1198 }
1199 else
1200 {
1201 SetBody(0);
1202 }
1203
1204 changeSelectedStatus(timestep);
1205 if (childPrim)
1206 {
1207 if (_parent is BulletDotNETPrim)
1208 {
1209 BulletDotNETPrim parent = (BulletDotNETPrim)_parent;
1210 parent.ChildSetGeom(this);
1211 }
1212 }
1213 resetCollisionAccounting();
1214
1215 m_taintshape = false;
1216 }
1217
1218 private void resetCollisionAccounting()
1219 {
1220 m_collisionscore = 0;
1221 }
1222
1223 private void ChildSetGeom(BulletDotNETPrim bulletDotNETPrim)
1224 {
1225 // TODO: throw new NotImplementedException();
1226 }
1227
1228 private void changeAddForce(float timestep)
1229 {
1230 if (!m_isSelected)
1231 {
1232 lock (m_forcelist)
1233 {
1234 //m_log.Info("[PHYSICS]: dequeing forcelist");
1235 if (IsPhysical)
1236 {
1237 Vector3 iforce = Vector3.Zero;
1238 for (int i = 0; i < m_forcelist.Count; i++)
1239 {
1240 iforce = iforce + m_forcelist[i];
1241 }
1242
1243 if (Body != null && Body.Handle != IntPtr.Zero)
1244 {
1245 if (tempAddForce != null && tempAddForce.Handle != IntPtr.Zero)
1246 tempAddForce.Dispose();
1247 enableBodySoft();
1248 tempAddForce = new btVector3(iforce.X, iforce.Y, iforce.Z);
1249 Body.applyCentralImpulse(tempAddForce);
1250 }
1251 }
1252 m_forcelist.Clear();
1253 }
1254
1255 m_collisionscore = 0;
1256 m_interpenetrationcount = 0;
1257 }
1258
1259 m_taintforce = false;
1260
1261 }
1262
1263 private void changeAddAngularForce(float timestep)
1264 {
1265 if (!m_isSelected)
1266 {
1267 lock (m_angularforcelist)
1268 {
1269 //m_log.Info("[PHYSICS]: dequeing forcelist");
1270 if (IsPhysical)
1271 {
1272 Vector3 iforce = Vector3.Zero;
1273 for (int i = 0; i < m_angularforcelist.Count; i++)
1274 {
1275 iforce = iforce + m_angularforcelist[i];
1276 }
1277
1278 if (Body != null && Body.Handle != IntPtr.Zero)
1279 {
1280 if (tempAddForce != null && tempAddForce.Handle != IntPtr.Zero)
1281 tempAddForce.Dispose();
1282 enableBodySoft();
1283 tempAddForce = new btVector3(iforce.X, iforce.Y, iforce.Z);
1284 Body.applyTorqueImpulse(tempAddForce);
1285 }
1286
1287 }
1288 m_angularforcelist.Clear();
1289 }
1290
1291 m_collisionscore = 0;
1292 m_interpenetrationcount = 0;
1293 }
1294
1295 m_taintaddangularforce = false;
1296 }
1297
1298 private void changeSetTorque(float timestep)
1299 {
1300 if (!m_isSelected)
1301 {
1302 if (IsPhysical)
1303 {
1304 if (Body != null && Body.Handle != IntPtr.Zero)
1305 {
1306 tempAngularVelocity2.setValue(m_taintTorque.X, m_taintTorque.Y, m_taintTorque.Z);
1307 Body.applyTorque(tempAngularVelocity2);
1308 }
1309 }
1310 }
1311 m_taintTorque = Vector3.Zero;
1312 }
1313
1314 private void changedisable(float timestep)
1315 {
1316 // TODO: throw new NotImplementedException();
1317 }
1318
1319 private void changeSelectedStatus(float timestep)
1320 {
1321 // TODO: throw new NotImplementedException();
1322 if (m_taintselected)
1323 {
1324 // Body.setCollisionFlags((int)ContactFlags.CF_NO_CONTACT_RESPONSE);
1325 disableBodySoft();
1326
1327 }
1328 else
1329 {
1330 // Body.setCollisionFlags(0 | (int)ContactFlags.CF_CUSTOM_MATERIAL_CALLBACK);
1331 enableBodySoft();
1332 }
1333 m_isSelected = m_taintselected;
1334
1335 }
1336
1337 private void changevelocity(float timestep)
1338 {
1339 if (!m_isSelected)
1340 {
1341 if (IsPhysical)
1342 {
1343 if (Body != null && Body.Handle != IntPtr.Zero)
1344 {
1345 tempLinearVelocity2.setValue(m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z);
1346 Body.setLinearVelocity(tempLinearVelocity2);
1347 }
1348 }
1349
1350 //resetCollisionAccounting();
1351 }
1352 m_taintVelocity = Vector3.Zero;
1353 }
1354
1355 private void changelink(float timestep)
1356 {
1357 if (IsPhysical)
1358 {
1359 // Construction of new prim
1360 if (Body != null)
1361 {
1362 if (Body.Handle != IntPtr.Zero)
1363 {
1364 DisableAxisMotor();
1365 _parent_scene.removeFromWorld(this, Body);
1366 //Body.Dispose();
1367 }
1368 //Body = null;
1369 // TODO: dispose parts that make up body
1370 }
1371
1372 if (_parent == null && m_taintparent != null)
1373 {
1374
1375 if (m_taintparent is BulletDotNETPrim)
1376 {
1377 BulletDotNETPrim obj = (BulletDotNETPrim)m_taintparent;
1378 obj.ParentPrim(this);
1379 childPrim = true;
1380
1381 }
1382 }
1383 else if (_parent != null && m_taintparent == null)
1384 {
1385 if (_parent is BulletDotNETPrim)
1386 {
1387 BulletDotNETPrim obj = (BulletDotNETPrim)_parent;
1388 obj.ChildDelink(obj);
1389
1390 childPrim = false;
1391 }
1392 }
1393
1394 if (m_taintparent != null)
1395 {
1396 Vector3 taintparentPosition = m_taintparent.Position;
1397 taintparentPosition.Z = m_taintparent.Position.Z + 0.02f;
1398 m_taintparent.Position = taintparentPosition;
1399 _parent_scene.AddPhysicsActorTaint(m_taintparent);
1400 }
1401 }
1402 _parent = m_taintparent;
1403
1404 m_taintPhysics = m_isphysical;
1405
1406 }
1407
1408 private void changefloatonwater(float timestep)
1409 {
1410 // TODO: throw new NotImplementedException();
1411 }
1412
1413 private void changeAngularLock(float timestep)
1414 {
1415 if (IsPhysical && Body != null && Body.Handle != IntPtr.Zero)
1416 {
1417 if (_parent == null)
1418 {
1419 if (!m_taintAngularLock.ApproxEquals(Vector3.One, 0f))
1420 {
1421 //d.BodySetFiniteRotationMode(Body, 0);
1422 //d.BodySetFiniteRotationAxis(Body,m_taintAngularLock.X,m_taintAngularLock.Y,m_taintAngularLock.Z);
1423 EnableAxisMotor(m_taintAngularLock);
1424 }
1425 else
1426 {
1427 DisableAxisMotor();
1428 }
1429 }
1430
1431 }
1432 m_angularlock = m_taintAngularLock;
1433
1434 }
1435 #endregion
1436
1437
1438
1439
1440 internal void Move(float timestep)
1441 {
1442 //TODO:
1443 float fx = 0;
1444 float fy = 0;
1445 float fz = 0;
1446
1447 if (IsPhysical && Body != null && Body.Handle != IntPtr.Zero && !m_isSelected)
1448 {
1449 float m_mass = CalculateMass();
1450
1451 fz = 0f;
1452 //m_log.Info(m_collisionFlags.ToString());
1453
1454 if (m_buoyancy != 0)
1455 {
1456 if (m_buoyancy > 0)
1457 {
1458 fz = (((-1 * _parent_scene.gravityz) * m_buoyancy) * m_mass) * 0.035f;
1459
1460 //d.Vector3 l_velocity = d.BodyGetLinearVel(Body);
1461 //m_log.Info("Using Buoyancy: " + buoyancy + " G: " + (_parent_scene.gravityz * m_buoyancy) + "mass:" + m_mass + " Pos: " + Position.ToString());
1462 }
1463 else
1464 {
1465 fz = (-1 * (((-1 * _parent_scene.gravityz) * (-1 * m_buoyancy)) * m_mass) * 0.035f);
1466 }
1467 }
1468
1469 if (m_usePID)
1470 {
1471 PID_D = 61f;
1472 PID_G = 65f;
1473 //if (!d.BodyIsEnabled(Body))
1474 //d.BodySetForce(Body, 0f, 0f, 0f);
1475 // If we're using the PID controller, then we have no gravity
1476 fz = ((-1 * _parent_scene.gravityz) * m_mass) * 1.025f;
1477
1478 // no lock; for now it's only called from within Simulate()
1479
1480 // If the PID Controller isn't active then we set our force
1481 // calculating base velocity to the current position
1482
1483 if ((m_PIDTau < 1) && (m_PIDTau != 0))
1484 {
1485 //PID_G = PID_G / m_PIDTau;
1486 m_PIDTau = 1;
1487 }
1488
1489 if ((PID_G - m_PIDTau) <= 0)
1490 {
1491 PID_G = m_PIDTau + 1;
1492 }
1493
1494 // TODO: NEED btVector3 for Linear Velocity
1495 // NEED btVector3 for Position
1496
1497 Vector3 pos = _position; //TODO: Insert values gotten from bullet
1498 Vector3 vel = _velocity;
1499
1500 _target_velocity =
1501 new Vector3(
1502 (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep),
1503 (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep),
1504 (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep)
1505 );
1506
1507 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
1508 {
1509
1510 /* TODO: Do Bullet equiv
1511 *
1512 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
1513 d.BodySetLinearVel(Body, 0, 0, 0);
1514 d.BodyAddForce(Body, 0, 0, fz);
1515 return;
1516 */
1517 }
1518 else
1519 {
1520 _zeroFlag = false;
1521
1522 fx = ((_target_velocity.X) - vel.X) * (PID_D);
1523 fy = ((_target_velocity.Y) - vel.Y) * (PID_D);
1524 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1525
1526 }
1527
1528 }
1529
1530 if (m_useHoverPID && !m_usePID)
1531 {
1532 // If we're using the PID controller, then we have no gravity
1533 fz = (-1 * _parent_scene.gravityz) * m_mass;
1534
1535 // no lock; for now it's only called from within Simulate()
1536
1537 // If the PID Controller isn't active then we set our force
1538 // calculating base velocity to the current position
1539
1540 if ((m_PIDTau < 1))
1541 {
1542 PID_G = PID_G / m_PIDTau;
1543 }
1544
1545 if ((PID_G - m_PIDTau) <= 0)
1546 {
1547 PID_G = m_PIDTau + 1;
1548 }
1549 Vector3 pos = Vector3.Zero; //TODO: Insert values gotten from bullet
1550 Vector3 vel = Vector3.Zero;
1551
1552 // determine what our target height really is based on HoverType
1553 switch (m_PIDHoverType)
1554 {
1555 case PIDHoverType.Absolute:
1556 m_targetHoverHeight = m_PIDHoverHeight;
1557 break;
1558 case PIDHoverType.Ground:
1559 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1560 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1561 break;
1562 case PIDHoverType.GroundAndWater:
1563 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1564 m_waterHeight = _parent_scene.GetWaterLevel();
1565 if (m_groundHeight > m_waterHeight)
1566 {
1567 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1568 }
1569 else
1570 {
1571 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
1572 }
1573 break;
1574 case PIDHoverType.Water:
1575 m_waterHeight = _parent_scene.GetWaterLevel();
1576 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
1577 break;
1578 }
1579
1580
1581 _target_velocity =
1582 new Vector3(0.0f, 0.0f,
1583 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
1584 );
1585
1586 // if velocity is zero, use position control; otherwise, velocity control
1587
1588 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
1589 {
1590
1591 /* TODO: Do Bullet Equiv
1592 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
1593 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
1594 d.BodyAddForce(Body, 0, 0, fz);
1595 */
1596 if (Body != null && Body.Handle != IntPtr.Zero)
1597 {
1598 Body.setLinearVelocity(_parent_scene.VectorZero);
1599 Body.clearForces();
1600 }
1601 return;
1602 }
1603 else
1604 {
1605 _zeroFlag = false;
1606
1607 // We're flying and colliding with something
1608 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1609 }
1610 }
1611
1612 fx *= m_mass;
1613 fy *= m_mass;
1614 //fz *= m_mass;
1615
1616 fx += m_force.X;
1617 fy += m_force.Y;
1618 fz += m_force.Z;
1619
1620 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
1621 if (fx != 0 || fy != 0 || fz != 0)
1622 {
1623 /*
1624 * TODO: Do Bullet Equiv
1625 if (!d.BodyIsEnabled(Body))
1626 {
1627 d.BodySetLinearVel(Body, 0f, 0f, 0f);
1628 d.BodySetForce(Body, 0, 0, 0);
1629 enableBodySoft();
1630 }
1631 */
1632 if (!Body.isActive())
1633 {
1634 Body.clearForces();
1635 enableBodySoft();
1636 }
1637 // 35x10 = 350n times the mass per second applied maximum.
1638
1639 float nmax = 35f * m_mass;
1640 float nmin = -35f * m_mass;
1641
1642
1643 if (fx > nmax)
1644 fx = nmax;
1645 if (fx < nmin)
1646 fx = nmin;
1647 if (fy > nmax)
1648 fy = nmax;
1649 if (fy < nmin)
1650 fy = nmin;
1651
1652 // TODO: Do Bullet Equiv
1653 // d.BodyAddForce(Body, fx, fy, fz);
1654 if (Body != null && Body.Handle != IntPtr.Zero)
1655 {
1656 Body.activate(true);
1657 if (tempAddForce != null && tempAddForce.Handle != IntPtr.Zero)
1658 tempAddForce.Dispose();
1659
1660 tempAddForce = new btVector3(fx * 0.01f, fy * 0.01f, fz * 0.01f);
1661 Body.applyCentralImpulse(tempAddForce);
1662 }
1663 }
1664 else
1665 {
1666 // if no forces on the prim, make sure everything is zero
1667 Body.clearForces();
1668 enableBodySoft();
1669 }
1670 }
1671 else
1672 {
1673 if (m_zeroPosition == null)
1674 m_zeroPosition = Vector3.Zero;
1675 m_zeroPosition = _position;
1676 return;
1677 }
1678 }
1679
1680
1681
1682
1683 #region Mass Calculation
1684
1685 private float CalculateMass()
1686 {
1687 float volume = 0;
1688
1689 // No material is passed to the physics engines yet.. soo..
1690 // we're using the m_density constant in the class definition
1691
1692 float returnMass = 0;
1693
1694 switch (_pbs.ProfileShape)
1695 {
1696 case ProfileShape.Square:
1697 // Profile Volume
1698
1699 volume = _size.X * _size.Y * _size.Z;
1700
1701 // If the user has 'hollowed out'
1702 // ProfileHollow is one of those 0 to 50000 values :P
1703 // we like percentages better.. so turning into a percentage
1704
1705 if (((float)_pbs.ProfileHollow / 50000f) > 0.0)
1706 {
1707 float hollowAmount = (float)_pbs.ProfileHollow / 50000f;
1708
1709 // calculate the hollow volume by it's shape compared to the prim shape
1710 float hollowVolume = 0;
1711 switch (_pbs.HollowShape)
1712 {
1713 case HollowShape.Square:
1714 case HollowShape.Same:
1715 // Cube Hollow volume calculation
1716 float hollowsizex = _size.X * hollowAmount;
1717 float hollowsizey = _size.Y * hollowAmount;
1718 float hollowsizez = _size.Z * hollowAmount;
1719 hollowVolume = hollowsizex * hollowsizey * hollowsizez;
1720 break;
1721
1722 case HollowShape.Circle:
1723 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1724 // Cyllinder hollow volume calculation
1725 float hRadius = _size.X / 2;
1726 float hLength = _size.Z;
1727
1728 // pi * r2 * h
1729 hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount);
1730 break;
1731
1732 case HollowShape.Triangle:
1733 // Equilateral Triangular Prism volume hollow calculation
1734 // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
1735
1736 float aLength = _size.Y;
1737 // 1/2 abh
1738 hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount);
1739 break;
1740
1741 default:
1742 hollowVolume = 0;
1743 break;
1744 }
1745 volume = volume - hollowVolume;
1746 }
1747
1748 break;
1749 case ProfileShape.Circle:
1750 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1751 {
1752 // Cylinder
1753 float volume1 = (float)(Math.PI * Math.Pow(_size.X / 2, 2) * _size.Z);
1754 float volume2 = (float)(Math.PI * Math.Pow(_size.Y / 2, 2) * _size.Z);
1755
1756 // Approximating the cylinder's irregularity.
1757 if (volume1 > volume2)
1758 {
1759 volume = (float)volume1 - (volume1 - volume2);
1760 }
1761 else if (volume2 > volume1)
1762 {
1763 volume = (float)volume2 - (volume2 - volume1);
1764 }
1765 else
1766 {
1767 // Regular cylinder
1768 volume = volume1;
1769 }
1770 }
1771 else
1772 {
1773 // We don't know what the shape is yet, so use default
1774 volume = _size.X * _size.Y * _size.Z;
1775 }
1776 // If the user has 'hollowed out'
1777 // ProfileHollow is one of those 0 to 50000 values :P
1778 // we like percentages better.. so turning into a percentage
1779
1780 if (((float)_pbs.ProfileHollow / 50000f) > 0.0)
1781 {
1782 float hollowAmount = (float)_pbs.ProfileHollow / 50000f;
1783
1784 // calculate the hollow volume by it's shape compared to the prim shape
1785 float hollowVolume = 0;
1786 switch (_pbs.HollowShape)
1787 {
1788 case HollowShape.Same:
1789 case HollowShape.Circle:
1790 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1791 // Cyllinder hollow volume calculation
1792 float hRadius = _size.X / 2;
1793 float hLength = _size.Z;
1794
1795 // pi * r2 * h
1796 hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount);
1797 break;
1798
1799 case HollowShape.Square:
1800 // Cube Hollow volume calculation
1801 float hollowsizex = _size.X * hollowAmount;
1802 float hollowsizey = _size.Y * hollowAmount;
1803 float hollowsizez = _size.Z * hollowAmount;
1804 hollowVolume = hollowsizex * hollowsizey * hollowsizez;
1805 break;
1806
1807 case HollowShape.Triangle:
1808 // Equilateral Triangular Prism volume hollow calculation
1809 // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
1810
1811 float aLength = _size.Y;
1812 // 1/2 abh
1813 hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount);
1814 break;
1815
1816 default:
1817 hollowVolume = 0;
1818 break;
1819 }
1820 volume = volume - hollowVolume;
1821 }
1822 break;
1823
1824 case ProfileShape.HalfCircle:
1825 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1826 {
1827 if (_size.X == _size.Y && _size.Z == _size.X)
1828 {
1829 // regular sphere
1830 // v = 4/3 * pi * r^3
1831 float sradius3 = (float)Math.Pow((_size.X / 2), 3);
1832 volume = (float)((4 / 3f) * Math.PI * sradius3);
1833 }
1834 else
1835 {
1836 // we treat this as a box currently
1837 volume = _size.X * _size.Y * _size.Z;
1838 }
1839 }
1840 else
1841 {
1842 // We don't know what the shape is yet, so use default
1843 volume = _size.X * _size.Y * _size.Z;
1844 }
1845 break;
1846
1847 case ProfileShape.EquilateralTriangle:
1848 /*
1849 v = (abs((xB*yA-xA*yB)+(xC*yB-xB*yC)+(xA*yC-xC*yA))/2) * h
1850
1851 // seed mesh
1852 Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f);
1853 Vertex PM = new Vertex(+0.5f, 0f, 0.0f);
1854 Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f);
1855 */
1856 float xA = -0.25f * _size.X;
1857 float yA = -0.45f * _size.Y;
1858
1859 float xB = 0.5f * _size.X;
1860 float yB = 0;
1861
1862 float xC = -0.25f * _size.X;
1863 float yC = 0.45f * _size.Y;
1864
1865 volume = (float)((Math.Abs((xB * yA - xA * yB) + (xC * yB - xB * yC) + (xA * yC - xC * yA)) / 2) * _size.Z);
1866
1867 // If the user has 'hollowed out'
1868 // ProfileHollow is one of those 0 to 50000 values :P
1869 // we like percentages better.. so turning into a percentage
1870 float fhollowFactor = ((float)_pbs.ProfileHollow / 1.9f);
1871 if (((float)fhollowFactor / 50000f) > 0.0)
1872 {
1873 float hollowAmount = (float)fhollowFactor / 50000f;
1874
1875 // calculate the hollow volume by it's shape compared to the prim shape
1876 float hollowVolume = 0;
1877 switch (_pbs.HollowShape)
1878 {
1879 case HollowShape.Same:
1880 case HollowShape.Triangle:
1881 // Equilateral Triangular Prism volume hollow calculation
1882 // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
1883
1884 float aLength = _size.Y;
1885 // 1/2 abh
1886 hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount);
1887 break;
1888
1889 case HollowShape.Square:
1890 // Cube Hollow volume calculation
1891 float hollowsizex = _size.X * hollowAmount;
1892 float hollowsizey = _size.Y * hollowAmount;
1893 float hollowsizez = _size.Z * hollowAmount;
1894 hollowVolume = hollowsizex * hollowsizey * hollowsizez;
1895 break;
1896
1897 case HollowShape.Circle:
1898 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1899 // Cyllinder hollow volume calculation
1900 float hRadius = _size.X / 2;
1901 float hLength = _size.Z;
1902
1903 // pi * r2 * h
1904 hollowVolume = ((float)((Math.PI * Math.Pow(hRadius, 2) * hLength) / 2) * hollowAmount);
1905 break;
1906
1907 default:
1908 hollowVolume = 0;
1909 break;
1910 }
1911 volume = volume - hollowVolume;
1912 }
1913 break;
1914
1915 default:
1916 // we don't have all of the volume formulas yet so
1917 // use the common volume formula for all
1918 volume = _size.X * _size.Y * _size.Z;
1919 break;
1920 }
1921
1922 // Calculate Path cut effect on volume
1923 // Not exact, in the triangle hollow example
1924 // They should never be zero or less then zero..
1925 // we'll ignore it if it's less then zero
1926
1927 // ProfileEnd and ProfileBegin are values
1928 // from 0 to 50000
1929
1930 // Turning them back into percentages so that I can cut that percentage off the volume
1931
1932 float PathCutEndAmount = _pbs.ProfileEnd;
1933 float PathCutStartAmount = _pbs.ProfileBegin;
1934 if (((PathCutStartAmount + PathCutEndAmount) / 50000f) > 0.0f)
1935 {
1936 float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount) / 50000f);
1937
1938 // Check the return amount for sanity
1939 if (pathCutAmount >= 0.99f)
1940 pathCutAmount = 0.99f;
1941
1942 volume = volume - (volume * pathCutAmount);
1943 }
1944 UInt16 taperX = _pbs.PathScaleX;
1945 UInt16 taperY = _pbs.PathScaleY;
1946 float taperFactorX = 0;
1947 float taperFactorY = 0;
1948
1949 // Mass = density * volume
1950 if (taperX != 100)
1951 {
1952 if (taperX > 100)
1953 {
1954 taperFactorX = 1.0f - ((float)taperX / 200);
1955 //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
1956 }
1957 else
1958 {
1959 taperFactorX = 1.0f - ((100 - (float)taperX) / 100);
1960 //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
1961 }
1962 volume = (float)volume * ((taperFactorX / 3f) + 0.001f);
1963 }
1964
1965 if (taperY != 100)
1966 {
1967 if (taperY > 100)
1968 {
1969 taperFactorY = 1.0f - ((float)taperY / 200);
1970 //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
1971 }
1972 else
1973 {
1974 taperFactorY = 1.0f - ((100 - (float)taperY) / 100);
1975 //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
1976 }
1977 volume = (float)volume * ((taperFactorY / 3f) + 0.001f);
1978 }
1979 returnMass = m_density * volume;
1980 if (returnMass <= 0) returnMass = 0.0001f;//ckrinke: Mass must be greater then zero.
1981
1982
1983
1984 // Recursively calculate mass
1985 bool HasChildPrim = false;
1986 lock (childrenPrim)
1987 {
1988 if (childrenPrim.Count > 0)
1989 {
1990 HasChildPrim = true;
1991 }
1992
1993 }
1994 if (HasChildPrim)
1995 {
1996 BulletDotNETPrim[] childPrimArr = new BulletDotNETPrim[0];
1997
1998 lock (childrenPrim)
1999 childPrimArr = childrenPrim.ToArray();
2000
2001 for (int i = 0; i < childPrimArr.Length; i++)
2002 {
2003 if (childPrimArr[i] != null && !childPrimArr[i].m_taintremove)
2004 returnMass += childPrimArr[i].CalculateMass();
2005 // failsafe, this shouldn't happen but with OpenSim, you never know :)
2006 if (i > 256)
2007 break;
2008 }
2009 }
2010
2011
2012
2013
2014
2015 return returnMass;
2016 }
2017
2018 #endregion
2019
2020
2021 public void CreateGeom(IntPtr m_targetSpace, IMesh p_mesh)
2022 {
2023 // m_log.Debug("[PHYSICS]: _________CreateGeom");
2024 if (p_mesh != null)
2025 {
2026 //_mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
2027 _mesh = p_mesh;
2028 setMesh(_parent_scene, _mesh);
2029
2030 }
2031 else
2032 {
2033 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
2034 {
2035 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
2036 {
2037 if (((_size.X / 2f) > 0f))
2038 {
2039 //SetGeom to a Regular Sphere
2040 if (tempSize1 == null)
2041 tempSize1 = new btVector3(0, 0, 0);
2042 tempSize1.setValue(_size.X * 0.5f, _size.Y * 0.5f, _size.Z * 0.5f);
2043 SetCollisionShape(new btSphereShape(_size.X * 0.5f));
2044 }
2045 else
2046 {
2047 // uses halfextents
2048 if (tempSize1 == null)
2049 tempSize1 = new btVector3(0, 0, 0);
2050 tempSize1.setValue(_size.X * 0.5f, _size.Y * 0.5f, _size.Z * 0.5f);
2051 SetCollisionShape(new btBoxShape(tempSize1));
2052 }
2053 }
2054 else
2055 {
2056 // uses halfextents
2057 if (tempSize1 == null)
2058 tempSize1 = new btVector3(0, 0, 0);
2059 tempSize1.setValue(_size.X * 0.5f, _size.Y * 0.5f, _size.Z * 0.5f);
2060 SetCollisionShape(new btBoxShape(tempSize1));
2061 }
2062
2063 }
2064 else
2065 {
2066 if (tempSize1 == null)
2067 tempSize1 = new btVector3(0, 0, 0);
2068 // uses halfextents
2069 tempSize1.setValue(_size.X * 0.5f, _size.Y * 0.5f, _size.Z * 0.5f);
2070 SetCollisionShape(new btBoxShape(tempSize1));
2071 }
2072 }
2073 }
2074
2075 private void setMesh(BulletDotNETScene _parent_scene, IMesh mesh)
2076 {
2077 // TODO: Set Collision Body Mesh
2078 // This sleeper is there to moderate how long it takes between
2079 // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
2080 // m_log.Debug("_________SetMesh");
2081 Thread.Sleep(10);
2082
2083 //Kill Body so that mesh can re-make the geom
2084 if (IsPhysical && Body != null && Body.Handle != IntPtr.Zero)
2085 {
2086 if (childPrim)
2087 {
2088 if (_parent != null)
2089 {
2090 BulletDotNETPrim parent = (BulletDotNETPrim)_parent;
2091 parent.ChildDelink(this);
2092 }
2093 }
2094 else
2095 {
2096 //disableBody();
2097 }
2098 }
2099
2100 //IMesh oldMesh = primMesh;
2101
2102 //primMesh = mesh;
2103
2104 //float[] vertexList = primMesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory
2105 //int[] indexList = primMesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage
2106 ////Array.Reverse(indexList);
2107 //primMesh.releaseSourceMeshData(); // free up the original mesh data to save memory
2108
2109 IMesh oldMesh = primMesh;
2110
2111 primMesh = mesh;
2112
2113 float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory
2114 int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage
2115 //Array.Reverse(indexList);
2116 mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
2117
2118
2119 int VertexCount = vertexList.GetLength(0) / 3;
2120 int IndexCount = indexList.GetLength(0);
2121
2122 if (btshapeArray != null && btshapeArray.Handle != IntPtr.Zero)
2123 btshapeArray.Dispose();
2124 //Array.Reverse(indexList);
2125 btshapeArray = new btTriangleIndexVertexArray(IndexCount / 3, indexList, (3 * sizeof(int)),
2126 VertexCount, vertexList, 3 * sizeof(float));
2127 SetCollisionShape(new btGImpactMeshShape(btshapeArray));
2128 //((btGImpactMeshShape) prim_geom).updateBound();
2129 ((btGImpactMeshShape)prim_geom).setLocalScaling(new btVector3(1, 1, 1));
2130 ((btGImpactMeshShape)prim_geom).updateBound();
2131 _parent_scene.SetUsingGImpact();
2132 //if (oldMesh != null)
2133 //{
2134 // oldMesh.releasePinned();
2135 // oldMesh = null;
2136 //}
2137
2138 }
2139
2140 private void SetCollisionShape(btCollisionShape shape)
2141 {
2142 /*
2143 if (shape == null)
2144 m_log.Debug("[PHYSICS]:SetShape!Null");
2145 else
2146 m_log.Debug("[PHYSICS]:SetShape!");
2147
2148 if (Body != null)
2149 {
2150 DisposeOfBody();
2151 }
2152
2153 if (prim_geom != null)
2154 {
2155 prim_geom.Dispose();
2156 prim_geom = null;
2157 }
2158 */
2159 prim_geom = shape;
2160
2161 //Body.set
2162 }
2163
2164 public void SetBody(float mass)
2165 {
2166
2167 if (!IsPhysical || childrenPrim.Count == 0)
2168 {
2169 if (tempMotionState1 != null && tempMotionState1.Handle != IntPtr.Zero)
2170 tempMotionState1.Dispose();
2171 if (tempTransform2 != null && tempTransform2.Handle != IntPtr.Zero)
2172 tempTransform2.Dispose();
2173 if (tempOrientation2 != null && tempOrientation2.Handle != IntPtr.Zero)
2174 tempOrientation2.Dispose();
2175
2176 if (tempPosition2 != null && tempPosition2.Handle != IntPtr.Zero)
2177 tempPosition2.Dispose();
2178
2179 tempOrientation2 = new btQuaternion(_orientation.X, _orientation.Y, _orientation.Z, _orientation.W);
2180 tempPosition2 = new btVector3(_position.X, _position.Y, _position.Z);
2181 tempTransform2 = new btTransform(tempOrientation2, tempPosition2);
2182 tempMotionState1 = new btDefaultMotionState(tempTransform2, _parent_scene.TransZero);
2183 if (tempInertia1 != null && tempInertia1.Handle != IntPtr.Zero)
2184 tempInertia1.Dispose();
2185 tempInertia1 = new btVector3(0, 0, 0);
2186
2187
2188 prim_geom.calculateLocalInertia(mass, tempInertia1);
2189
2190 if (mass != 0)
2191 _parent_scene.addActivePrim(this);
2192 else
2193 _parent_scene.remActivePrim(this);
2194
2195 // Body = new btRigidBody(mass, tempMotionState1, prim_geom);
2196 //else
2197 // Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1);
2198 if (Body == null)
2199 {
2200 Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1);
2201 // add localID so we can later map bullet object back to OpenSim object
2202 Body.setUserPointer(new IntPtr((int)m_localID));
2203 }
2204
2205
2206 if (prim_geom is btGImpactMeshShape)
2207 {
2208 ((btGImpactMeshShape)prim_geom).setLocalScaling(new btVector3(1, 1, 1));
2209 ((btGImpactMeshShape)prim_geom).updateBound();
2210 }
2211 //Body.setCollisionFlags(Body.getCollisionFlags() | (int)ContactFlags.CF_CUSTOM_MATERIAL_CALLBACK);
2212 //Body.setUserPointer((IntPtr) (int)m_localID);
2213 _parent_scene.AddPrimToScene(this);
2214 }
2215 else
2216 {
2217 // bool hasTrimesh = false;
2218 lock (childrenPrim)
2219 {
2220 foreach (BulletDotNETPrim chld in childrenPrim)
2221 {
2222 if (chld == null)
2223 continue;
2224
2225 // if (chld.NeedsMeshing())
2226 // hasTrimesh = true;
2227 }
2228 }
2229
2230 //if (hasTrimesh)
2231 //{
2232 ProcessGeomCreationAsTriMesh(Vector3.Zero, Quaternion.Identity);
2233 // createmesh returns null when it doesn't mesh.
2234
2235 /*
2236 if (_mesh is Mesh)
2237 {
2238 }
2239 else
2240 {
2241 m_log.Warn("[PHYSICS]: Can't link a OpenSim.Region.Physics.Meshing.Mesh object");
2242 return;
2243 }
2244 */
2245
2246
2247
2248 foreach (BulletDotNETPrim chld in childrenPrim)
2249 {
2250 if (chld == null)
2251 continue;
2252 Vector3 offset = chld.Position - Position;
2253 Vector3 pos = new Vector3(offset.X, offset.Y, offset.Z);
2254 pos *= Quaternion.Inverse(Orientation);
2255 //pos *= Orientation;
2256 offset = pos;
2257 chld.ProcessGeomCreationAsTriMesh(offset, chld.Orientation);
2258
2259 _mesh.Append(chld._mesh);
2260
2261
2262 }
2263 setMesh(_parent_scene, _mesh);
2264
2265 //}
2266
2267 if (tempMotionState1 != null && tempMotionState1.Handle != IntPtr.Zero)
2268 tempMotionState1.Dispose();
2269 if (tempTransform2 != null && tempTransform2.Handle != IntPtr.Zero)
2270 tempTransform2.Dispose();
2271 if (tempOrientation2 != null && tempOrientation2.Handle != IntPtr.Zero)
2272 tempOrientation2.Dispose();
2273
2274 if (tempPosition2 != null && tempPosition2.Handle != IntPtr.Zero)
2275 tempPosition2.Dispose();
2276
2277 tempOrientation2 = new btQuaternion(_orientation.X, _orientation.Y, _orientation.Z, _orientation.W);
2278 tempPosition2 = new btVector3(_position.X, _position.Y, _position.Z);
2279 tempTransform2 = new btTransform(tempOrientation2, tempPosition2);
2280 tempMotionState1 = new btDefaultMotionState(tempTransform2, _parent_scene.TransZero);
2281 if (tempInertia1 != null && tempInertia1.Handle != IntPtr.Zero)
2282 tempInertia1.Dispose();
2283 tempInertia1 = new btVector3(0, 0, 0);
2284
2285
2286 prim_geom.calculateLocalInertia(mass, tempInertia1);
2287
2288 if (mass != 0)
2289 _parent_scene.addActivePrim(this);
2290 else
2291 _parent_scene.remActivePrim(this);
2292
2293 // Body = new btRigidBody(mass, tempMotionState1, prim_geom);
2294 //else
2295 // Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1);
2296 if (Body == null)
2297 {
2298 Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1);
2299 // each body has the localID stored into it so we can identify collision objects
2300 Body.setUserPointer(new IntPtr((int)m_localID));
2301 }
2302
2303 if (prim_geom is btGImpactMeshShape)
2304 {
2305 ((btGImpactMeshShape)prim_geom).setLocalScaling(new btVector3(1, 1, 1));
2306 ((btGImpactMeshShape)prim_geom).updateBound();
2307 }
2308 _parent_scene.AddPrimToScene(this);
2309
2310 }
2311
2312 if (IsPhysical)
2313 changeAngularLock(0);
2314 }
2315
2316 private void DisposeOfBody()
2317 {
2318 if (Body != null)
2319 {
2320 if (Body.Handle != IntPtr.Zero)
2321 {
2322 DisableAxisMotor();
2323 _parent_scene.removeFromWorld(this, Body);
2324 Body.Dispose();
2325 }
2326 Body = null;
2327 // TODO: dispose parts that make up body
2328 }
2329 }
2330
2331 private void ChildDelink(BulletDotNETPrim pPrim)
2332 {
2333 // Okay, we have a delinked child.. need to rebuild the body.
2334 lock (childrenPrim)
2335 {
2336 foreach (BulletDotNETPrim prm in childrenPrim)
2337 {
2338 prm.childPrim = true;
2339 prm.disableBody();
2340
2341 }
2342 }
2343 disableBody();
2344
2345 lock (childrenPrim)
2346 {
2347 childrenPrim.Remove(pPrim);
2348 }
2349
2350
2351
2352
2353 if (Body != null && Body.Handle != IntPtr.Zero)
2354 {
2355 _parent_scene.remActivePrim(this);
2356 }
2357
2358
2359
2360 lock (childrenPrim)
2361 {
2362 foreach (BulletDotNETPrim prm in childrenPrim)
2363 {
2364 ParentPrim(prm);
2365 }
2366 }
2367
2368 }
2369
2370 internal void ParentPrim(BulletDotNETPrim prm)
2371 {
2372 if (prm == null)
2373 return;
2374
2375
2376
2377 lock (childrenPrim)
2378 {
2379 if (!childrenPrim.Contains(prm))
2380 {
2381 childrenPrim.Add(prm);
2382 }
2383 }
2384
2385
2386 }
2387
2388 public void disableBody()
2389 {
2390 //this kills the body so things like 'mesh' can re-create it.
2391 /*
2392 lock (this)
2393 {
2394 if (!childPrim)
2395 {
2396 if (Body != null && Body.Handle != IntPtr.Zero)
2397 {
2398 _parent_scene.remActivePrim(this);
2399
2400 m_collisionCategories &= ~CollisionCategories.Body;
2401 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
2402
2403 if (prim_geom != null && prim_geom.Handle != IntPtr.Zero)
2404 {
2405 // TODO: Set Category bits and Flags
2406 }
2407
2408 // TODO: destroy body
2409 DisposeOfBody();
2410
2411 lock (childrenPrim)
2412 {
2413 if (childrenPrim.Count > 0)
2414 {
2415 foreach (BulletDotNETPrim prm in childrenPrim)
2416 {
2417 _parent_scene.remActivePrim(prm);
2418 prm.DisposeOfBody();
2419 prm.SetCollisionShape(null);
2420 }
2421 }
2422
2423 }
2424
2425 DisposeOfBody();
2426 }
2427 }
2428 else
2429 {
2430 _parent_scene.remActivePrim(this);
2431 m_collisionCategories &= ~CollisionCategories.Body;
2432 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
2433
2434 if (prim_geom != null && prim_geom.Handle != IntPtr.Zero)
2435 {
2436 // TODO: Set Category bits and Flags
2437 }
2438
2439 DisposeOfBody();
2440 }
2441
2442 }
2443 */
2444 DisableAxisMotor();
2445 m_disabled = true;
2446 m_collisionscore = 0;
2447 }
2448
2449 public void disableBodySoft()
2450 {
2451 m_disabled = true;
2452
2453 if (m_isphysical && Body.Handle != IntPtr.Zero)
2454 {
2455 Body.clearForces();
2456 Body.forceActivationState(0);
2457
2458 }
2459
2460 }
2461
2462 public void enableBodySoft()
2463 {
2464 if (!childPrim)
2465 {
2466 if (m_isphysical && Body.Handle != IntPtr.Zero)
2467 {
2468 Body.clearForces();
2469 Body.forceActivationState(4);
2470 forceenable = true;
2471
2472 }
2473 m_disabled = false;
2474 }
2475 }
2476
2477 public void enableBody()
2478 {
2479 if (!childPrim)
2480 {
2481 //SetCollisionShape(prim_geom);
2482 if (IsPhysical)
2483 SetBody(Mass);
2484 else
2485 SetBody(0);
2486
2487 // TODO: Set Collision Category Bits and Flags
2488 // TODO: Set Auto Disable data
2489
2490 m_interpenetrationcount = 0;
2491 m_collisionscore = 0;
2492 m_disabled = false;
2493 // The body doesn't already have a finite rotation mode set here
2494 if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null)
2495 {
2496 // TODO: Create Angular Motor on Axis Lock!
2497 }
2498 _parent_scene.addActivePrim(this);
2499 }
2500 }
2501
2502 public void UpdatePositionAndVelocity()
2503 {
2504 if (!m_isSelected)
2505 {
2506 if (_parent == null)
2507 {
2508 Vector3 pv = Vector3.Zero;
2509 bool lastZeroFlag = _zeroFlag;
2510 if (tempPosition3 != null && tempPosition3.Handle != IntPtr.Zero)
2511 tempPosition3.Dispose();
2512 if (tempTransform3 != null && tempTransform3.Handle != IntPtr.Zero)
2513 tempTransform3.Dispose();
2514
2515 if (tempOrientation2 != null && tempOrientation2.Handle != IntPtr.Zero)
2516 tempOrientation2.Dispose();
2517
2518 if (tempAngularVelocity1 != null && tempAngularVelocity1.Handle != IntPtr.Zero)
2519 tempAngularVelocity1.Dispose();
2520
2521 if (tempLinearVelocity1 != null && tempLinearVelocity1.Handle != IntPtr.Zero)
2522 tempLinearVelocity1.Dispose();
2523
2524
2525
2526 tempTransform3 = Body.getInterpolationWorldTransform();
2527 tempPosition3 = tempTransform3.getOrigin(); // vec
2528 tempOrientation2 = tempTransform3.getRotation(); // ori
2529 tempAngularVelocity1 = Body.getInterpolationAngularVelocity(); //rotvel
2530 tempLinearVelocity1 = Body.getInterpolationLinearVelocity(); // vel
2531
2532 _torque = new Vector3(tempAngularVelocity1.getX(), tempAngularVelocity1.getX(),
2533 tempAngularVelocity1.getZ());
2534 Vector3 l_position = Vector3.Zero;
2535 Quaternion l_orientation = Quaternion.Identity;
2536 m_lastposition = _position;
2537 m_lastorientation = _orientation;
2538
2539 l_position.X = tempPosition3.getX();
2540 l_position.Y = tempPosition3.getY();
2541 l_position.Z = tempPosition3.getZ();
2542 l_orientation.X = tempOrientation2.getX();
2543 l_orientation.Y = tempOrientation2.getY();
2544 l_orientation.Z = tempOrientation2.getZ();
2545 l_orientation.W = tempOrientation2.getW();
2546
2547 if (l_position.X > ((int)Constants.RegionSize - 0.05f) || l_position.X < 0f || l_position.Y > ((int)Constants.RegionSize - 0.05f) || l_position.Y < 0f)
2548 {
2549 //base.RaiseOutOfBounds(l_position);
2550
2551 if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2552 {
2553 _position = l_position;
2554 //_parent_scene.remActivePrim(this);
2555 if (_parent == null)
2556 base.RequestPhysicsterseUpdate();
2557 return;
2558 }
2559 else
2560 {
2561 if (_parent == null)
2562 base.RaiseOutOfBounds(l_position);
2563 return;
2564 }
2565 }
2566
2567 if (l_position.Z < -200000f)
2568 {
2569 // This is so prim that get lost underground don't fall forever and suck up
2570 //
2571 // Sim resources and memory.
2572 // Disables the prim's movement physics....
2573 // It's a hack and will generate a console message if it fails.
2574
2575 //IsPhysical = false;
2576 //if (_parent == null)
2577 //base.RaiseOutOfBounds(_position);
2578
2579 _acceleration.X = 0;
2580 _acceleration.Y = 0;
2581 _acceleration.Z = 0;
2582
2583 _velocity.X = 0;
2584 _velocity.Y = 0;
2585 _velocity.Z = 0;
2586 m_rotationalVelocity.X = 0;
2587 m_rotationalVelocity.Y = 0;
2588 m_rotationalVelocity.Z = 0;
2589
2590 if (_parent == null)
2591 base.RequestPhysicsterseUpdate();
2592
2593 m_throttleUpdates = false;
2594 // throttleCounter = 0;
2595 _zeroFlag = true;
2596 //outofBounds = true;
2597 }
2598
2599 if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
2600 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
2601 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02)
2602 && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.01))
2603 {
2604 _zeroFlag = true;
2605 m_throttleUpdates = false;
2606 }
2607 else
2608 {
2609 //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString());
2610 _zeroFlag = false;
2611 }
2612
2613 if (_zeroFlag)
2614 {
2615 _velocity.X = 0.0f;
2616 _velocity.Y = 0.0f;
2617 _velocity.Z = 0.0f;
2618
2619 _acceleration.X = 0;
2620 _acceleration.Y = 0;
2621 _acceleration.Z = 0;
2622
2623 //_orientation.w = 0f;
2624 //_orientation.X = 0f;
2625 //_orientation.Y = 0f;
2626 //_orientation.Z = 0f;
2627 m_rotationalVelocity.X = 0;
2628 m_rotationalVelocity.Y = 0;
2629 m_rotationalVelocity.Z = 0;
2630 if (!m_lastUpdateSent)
2631 {
2632 m_throttleUpdates = false;
2633 // throttleCounter = 0;
2634 m_rotationalVelocity = pv;
2635
2636 if (_parent == null)
2637 base.RequestPhysicsterseUpdate();
2638
2639 m_lastUpdateSent = true;
2640 }
2641 }
2642 else
2643 {
2644 if (lastZeroFlag != _zeroFlag)
2645 {
2646 if (_parent == null)
2647 base.RequestPhysicsterseUpdate();
2648 }
2649
2650 m_lastVelocity = _velocity;
2651
2652 _position = l_position;
2653
2654 _velocity.X = tempLinearVelocity1.getX();
2655 _velocity.Y = tempLinearVelocity1.getY();
2656 _velocity.Z = tempLinearVelocity1.getZ();
2657
2658 _acceleration = ((_velocity - m_lastVelocity) / 0.1f);
2659 _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f,
2660 _velocity.Y - m_lastVelocity.Y / 0.1f,
2661 _velocity.Z - m_lastVelocity.Z / 0.1f);
2662 //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString());
2663
2664 if (_velocity.ApproxEquals(pv, 0.5f))
2665 {
2666 m_rotationalVelocity = pv;
2667 }
2668 else
2669 {
2670 m_rotationalVelocity = new Vector3(tempAngularVelocity1.getX(), tempAngularVelocity1.getY(), tempAngularVelocity1.getZ());
2671 }
2672
2673 //m_log.Debug("ODE: " + m_rotationalVelocity.ToString());
2674
2675 _orientation.X = l_orientation.X;
2676 _orientation.Y = l_orientation.Y;
2677 _orientation.Z = l_orientation.Z;
2678 _orientation.W = l_orientation.W;
2679 m_lastUpdateSent = false;
2680
2681 //if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate)
2682 //{
2683 if (_parent == null)
2684 base.RequestPhysicsterseUpdate();
2685 // }
2686 // else
2687 // {
2688 // throttleCounter++;
2689 //}
2690
2691 }
2692 m_lastposition = l_position;
2693 if (forceenable)
2694 {
2695 Body.forceActivationState(1);
2696 forceenable = false;
2697 }
2698 }
2699 else
2700 {
2701 // Not a body.. so Make sure the client isn't interpolating
2702 _velocity.X = 0;
2703 _velocity.Y = 0;
2704 _velocity.Z = 0;
2705
2706 _acceleration.X = 0;
2707 _acceleration.Y = 0;
2708 _acceleration.Z = 0;
2709
2710 m_rotationalVelocity.X = 0;
2711 m_rotationalVelocity.Y = 0;
2712 m_rotationalVelocity.Z = 0;
2713 _zeroFlag = true;
2714 }
2715 }
2716 }
2717
2718
2719 internal void setPrimForRemoval()
2720 {
2721 m_taintremove = true;
2722 }
2723
2724 internal void EnableAxisMotor(Vector3 axislock)
2725 {
2726 if (m_aMotor != null)
2727 DisableAxisMotor();
2728
2729 if (Body == null)
2730 return;
2731
2732 if (Body.Handle == IntPtr.Zero)
2733 return;
2734
2735 if (AxisLockAngleHigh != null && AxisLockAngleHigh.Handle != IntPtr.Zero)
2736 AxisLockAngleHigh.Dispose();
2737
2738
2739
2740 m_aMotor = new btGeneric6DofConstraint(Body, _parent_scene.TerrainBody, _parent_scene.TransZero,
2741 _parent_scene.TransZero, false);
2742
2743 float endNoLock = (360 * Utils.DEG_TO_RAD);
2744 AxisLockAngleHigh = new btVector3((axislock.X == 0) ? 0 : endNoLock, (axislock.Y == 0) ? 0 : endNoLock, (axislock.Z == 0) ? 0 : endNoLock);
2745
2746 m_aMotor.setAngularLowerLimit(_parent_scene.VectorZero);
2747 m_aMotor.setAngularUpperLimit(AxisLockAngleHigh);
2748 m_aMotor.setLinearLowerLimit(AxisLockLinearLow);
2749 m_aMotor.setLinearUpperLimit(AxisLockLinearHigh);
2750 _parent_scene.getBulletWorld().addConstraint((btTypedConstraint)m_aMotor);
2751 //m_aMotor.
2752
2753
2754 }
2755 internal void DisableAxisMotor()
2756 {
2757 if (m_aMotor != null && m_aMotor.Handle != IntPtr.Zero)
2758 {
2759 _parent_scene.getBulletWorld().removeConstraint(m_aMotor);
2760 m_aMotor.Dispose();
2761 m_aMotor = null;
2762 }
2763 }
2764
2765 }
2766}
2767
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
deleted file mode 100644
index 0d1bd82..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
+++ /dev/null
@@ -1,776 +0,0 @@
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.IO;
32using System.Diagnostics;
33using System.Threading;
34using log4net;
35using Nini.Config;
36using OpenSim.Framework;
37using OpenSim.Region.Physics.Manager;
38using OpenMetaverse;
39using BulletDotNET;
40
41namespace OpenSim.Region.Physics.BulletDotNETPlugin
42{
43 public class BulletDotNETScene : PhysicsScene
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 // private string m_sceneIdentifier = string.Empty;
48
49 private List<BulletDotNETCharacter> m_characters = new List<BulletDotNETCharacter>();
50 private Dictionary<uint, BulletDotNETCharacter> m_charactersLocalID = new Dictionary<uint, BulletDotNETCharacter>();
51 private List<BulletDotNETPrim> m_prims = new List<BulletDotNETPrim>();
52 private Dictionary<uint, BulletDotNETPrim> m_primsLocalID = new Dictionary<uint, BulletDotNETPrim>();
53 private List<BulletDotNETPrim> m_activePrims = new List<BulletDotNETPrim>();
54 private List<PhysicsActor> m_taintedActors = new List<PhysicsActor>();
55 private btDiscreteDynamicsWorld m_world;
56 private btAxisSweep3 m_broadphase;
57 private btCollisionConfiguration m_collisionConfiguration;
58 private btConstraintSolver m_solver;
59 private btCollisionDispatcher m_dispatcher;
60 private btHeightfieldTerrainShape m_terrainShape;
61 public btRigidBody TerrainBody;
62 private btVector3 m_terrainPosition;
63 private btVector3 m_gravity;
64 public btMotionState m_terrainMotionState;
65 public btTransform m_terrainTransform;
66 public btVector3 VectorZero;
67 public btQuaternion QuatIdentity;
68 public btTransform TransZero;
69
70 public float geomDefaultDensity = 10.000006836f;
71
72 private float avPIDD = 65f;
73 private float avPIDP = 21f;
74 private float avCapRadius = 0.37f;
75 private float avStandupTensor = 2000000f;
76 private float avDensity = 80f;
77 private float avHeightFudgeFactor = 0.52f;
78 private float avMovementDivisorWalk = 1.8f;
79 private float avMovementDivisorRun = 0.8f;
80
81 // private float minimumGroundFlightOffset = 3f;
82
83 public bool meshSculptedPrim = true;
84
85 public float meshSculptLOD = 32;
86 public float MeshSculptphysicalLOD = 16;
87
88 public float bodyPIDD = 35f;
89 public float bodyPIDG = 25;
90 internal int geomCrossingFailuresBeforeOutofbounds = 4;
91
92 public float bodyMotorJointMaxforceTensor = 2;
93
94 public int bodyFramesAutoDisable = 20;
95
96 public float WorldTimeStep = 10f/60f;
97 public const float WorldTimeComp = 1/60f;
98 public float gravityz = -9.8f;
99
100 private float[] _origheightmap; // Used for Fly height. Kitto Flora
101 private bool usingGImpactAlgorithm = false;
102
103 // private IConfigSource m_config;
104 private readonly btVector3 worldAabbMin = new btVector3(-10f, -10f, 0);
105 private readonly btVector3 worldAabbMax = new btVector3((int)Constants.RegionSize + 10f, (int)Constants.RegionSize + 10f, 9000);
106
107 public IMesher mesher;
108 private ContactAddedCallbackHandler m_CollisionInterface;
109
110 public BulletDotNETScene(string sceneIdentifier)
111 {
112 // m_sceneIdentifier = sceneIdentifier;
113 VectorZero = new btVector3(0, 0, 0);
114 QuatIdentity = new btQuaternion(0, 0, 0, 1);
115 TransZero = new btTransform(QuatIdentity, VectorZero);
116 m_gravity = new btVector3(0, 0, gravityz);
117 _origheightmap = new float[(int)Constants.RegionSize * (int)Constants.RegionSize];
118
119 }
120
121 public override void Initialise(IMesher meshmerizer, IConfigSource config)
122 {
123 mesher = meshmerizer;
124 // m_config = config;
125 /*
126 if (Environment.OSVersion.Platform == PlatformID.Unix)
127 {
128 m_log.Fatal("[BulletDotNET]: This configuration is not supported on *nix currently");
129 Thread.Sleep(5000);
130 Environment.Exit(0);
131 }
132 */
133 m_broadphase = new btAxisSweep3(worldAabbMin, worldAabbMax, 16000);
134 m_collisionConfiguration = new btDefaultCollisionConfiguration();
135 m_solver = new btSequentialImpulseConstraintSolver();
136 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
137 m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
138 m_world.setGravity(m_gravity);
139 EnableCollisionInterface();
140
141
142 }
143
144 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
145 {
146 BulletDotNETCharacter chr = new BulletDotNETCharacter(avName, this, position, size, avPIDD, avPIDP,
147 avCapRadius, avStandupTensor, avDensity,
148 avHeightFudgeFactor, avMovementDivisorWalk,
149 avMovementDivisorRun);
150 try
151 {
152 m_characters.Add(chr);
153 m_charactersLocalID.Add(chr.m_localID, chr);
154 }
155 catch
156 {
157 // noop if it's already there
158 m_log.Debug("[PHYSICS] BulletDotNet: adding duplicate avatar localID");
159 }
160 AddPhysicsActorTaint(chr);
161 return chr;
162 }
163
164 public override void RemoveAvatar(PhysicsActor actor)
165 {
166 BulletDotNETCharacter chr = (BulletDotNETCharacter) actor;
167
168 m_charactersLocalID.Remove(chr.m_localID);
169 m_characters.Remove(chr);
170 m_world.removeRigidBody(chr.Body);
171 m_world.removeCollisionObject(chr.Body);
172
173 chr.Remove();
174 AddPhysicsActorTaint(chr);
175 //chr = null;
176 }
177
178 public override void RemovePrim(PhysicsActor prim)
179 {
180 if (prim is BulletDotNETPrim)
181 {
182
183 BulletDotNETPrim p = (BulletDotNETPrim)prim;
184
185 p.setPrimForRemoval();
186 AddPhysicsActorTaint(prim);
187 //RemovePrimThreadLocked(p);
188
189 }
190 }
191
192 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
193 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical)
194 {
195 Vector3 pos = position;
196 //pos.X = position.X;
197 //pos.Y = position.Y;
198 //pos.Z = position.Z;
199 Vector3 siz = Vector3.Zero;
200 siz.X = size.X;
201 siz.Y = size.Y;
202 siz.Z = size.Z;
203 Quaternion rot = rotation;
204
205 BulletDotNETPrim newPrim;
206
207 newPrim = new BulletDotNETPrim(name, this, pos, siz, rot, mesh, pbs, isphysical);
208
209 //lock (m_prims)
210 // m_prims.Add(newPrim);
211
212
213 return newPrim;
214 }
215
216 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
217 {
218 PhysicsActor result;
219 IMesh mesh = null;
220
221 //switch (pbs.ProfileShape)
222 //{
223 // case ProfileShape.Square:
224 // //support simple box & hollow box now; later, more shapes
225 // if (needsMeshing(pbs))
226 // {
227 // mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
228 // }
229
230 // break;
231 //}
232
233 if (needsMeshing(pbs))
234 mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
235
236 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
237
238 return result;
239 }
240
241 public override void AddPhysicsActorTaint(PhysicsActor prim)
242 {
243 lock (m_taintedActors)
244 {
245 if (!m_taintedActors.Contains(prim))
246 {
247 m_taintedActors.Add(prim);
248 }
249 }
250 }
251 internal void SetUsingGImpact()
252 {
253 if (!usingGImpactAlgorithm)
254 btGImpactCollisionAlgorithm.registerAlgorithm(m_dispatcher);
255 usingGImpactAlgorithm = true;
256 }
257
258 public override float Simulate(float timeStep)
259 {
260
261 lock (m_taintedActors)
262 {
263 foreach (PhysicsActor act in m_taintedActors)
264 {
265 if (act is BulletDotNETCharacter)
266 ((BulletDotNETCharacter) act).ProcessTaints(timeStep);
267 if (act is BulletDotNETPrim)
268 ((BulletDotNETPrim)act).ProcessTaints(timeStep);
269 }
270 m_taintedActors.Clear();
271 }
272
273 lock (m_characters)
274 {
275 foreach (BulletDotNETCharacter chr in m_characters)
276 {
277 chr.Move(timeStep);
278 }
279 }
280
281 lock (m_prims)
282 {
283 foreach (BulletDotNETPrim prim in m_prims)
284 {
285 if (prim != null)
286 prim.Move(timeStep);
287 }
288 }
289 float steps = m_world.stepSimulation(timeStep, 10, WorldTimeComp);
290
291 foreach (BulletDotNETCharacter chr in m_characters)
292 {
293 chr.UpdatePositionAndVelocity();
294 }
295
296 foreach (BulletDotNETPrim prm in m_activePrims)
297 {
298 /*
299 if (prm != null)
300 if (prm.Body != null)
301 */
302 prm.UpdatePositionAndVelocity();
303 }
304 if (m_CollisionInterface != null)
305 {
306 List<BulletDotNETPrim> primsWithCollisions = new List<BulletDotNETPrim>();
307 List<BulletDotNETCharacter> charactersWithCollisions = new List<BulletDotNETCharacter>();
308
309 // get the collisions that happened this tick
310 List<BulletDotNET.ContactAddedCallbackHandler.ContactInfo> collisions = m_CollisionInterface.GetContactList();
311 // passed back the localID of the prim so we can associate the prim
312 foreach (BulletDotNET.ContactAddedCallbackHandler.ContactInfo ci in collisions)
313 {
314 // ContactPoint = { contactPoint, contactNormal, penetrationDepth }
315 ContactPoint contact = new ContactPoint(new Vector3(ci.pX, ci.pY, ci.pZ),
316 new Vector3(ci.nX, ci.nY, ci.nZ), ci.depth);
317
318 ProcessContact(ci.contact, ci.contactWith, contact, ref primsWithCollisions, ref charactersWithCollisions);
319 ProcessContact(ci.contactWith, ci.contact, contact, ref primsWithCollisions, ref charactersWithCollisions);
320
321 }
322 m_CollisionInterface.Clear();
323 // for those prims and characters that had collisions cause collision events
324 foreach (BulletDotNETPrim bdnp in primsWithCollisions)
325 {
326 bdnp.SendCollisions();
327 }
328 foreach (BulletDotNETCharacter bdnc in charactersWithCollisions)
329 {
330 bdnc.SendCollisions();
331 }
332 }
333 return steps;
334 }
335
336 private void ProcessContact(uint cont, uint contWith, ContactPoint contact,
337 ref List<BulletDotNETPrim> primsWithCollisions,
338 ref List<BulletDotNETCharacter> charactersWithCollisions)
339 {
340 BulletDotNETPrim bdnp;
341 // collisions with a normal prim?
342 if (m_primsLocalID.TryGetValue(cont, out bdnp))
343 {
344 // Added collision event to the prim. This creates a pile of events
345 // that will be sent to any subscribed listeners.
346 bdnp.AddCollision(contWith, contact);
347 if (!primsWithCollisions.Contains(bdnp))
348 {
349 primsWithCollisions.Add(bdnp);
350 }
351 }
352 else
353 {
354 BulletDotNETCharacter bdnc;
355 // if not a prim, maybe it's one of the characters
356 if (m_charactersLocalID.TryGetValue(cont, out bdnc))
357 {
358 bdnc.AddCollision(contWith, contact);
359 if (!charactersWithCollisions.Contains(bdnc))
360 {
361 charactersWithCollisions.Add(bdnc);
362 }
363 }
364 }
365 }
366
367 public override void GetResults()
368 {
369
370 }
371
372 public override void SetTerrain(float[] heightMap)
373 {
374 if (m_terrainShape != null)
375 DeleteTerrain();
376
377 float hfmax = -9000;
378 float hfmin = 90000;
379
380 for (int i = 0; i <heightMap.Length;i++)
381 {
382 if (Single.IsNaN(heightMap[i]) || Single.IsInfinity(heightMap[i]))
383 {
384 heightMap[i] = 0f;
385 }
386
387 hfmin = (heightMap[i] < hfmin) ? heightMap[i] : hfmin;
388 hfmax = (heightMap[i] > hfmax) ? heightMap[i] : hfmax;
389 }
390 // store this for later reference.
391 // Note, we're storing it after we check it for anomolies above
392 _origheightmap = heightMap;
393
394 hfmin = 0;
395 hfmax = 256;
396
397 m_terrainShape = new btHeightfieldTerrainShape((int)Constants.RegionSize, (int)Constants.RegionSize, heightMap,
398 1.0f, hfmin, hfmax, (int)btHeightfieldTerrainShape.UPAxis.Z,
399 (int)btHeightfieldTerrainShape.PHY_ScalarType.PHY_FLOAT, false);
400 float AabbCenterX = Constants.RegionSize/2f;
401 float AabbCenterY = Constants.RegionSize/2f;
402
403 float AabbCenterZ = 0;
404 float temphfmin, temphfmax;
405
406 temphfmin = hfmin;
407 temphfmax = hfmax;
408
409 if (temphfmin < 0)
410 {
411 temphfmax = 0 - temphfmin;
412 temphfmin = 0 - temphfmin;
413 }
414 else if (temphfmin > 0)
415 {
416 temphfmax = temphfmax + (0 - temphfmin);
417 //temphfmin = temphfmin + (0 - temphfmin);
418 }
419 AabbCenterZ = temphfmax/2f;
420
421 if (m_terrainPosition == null)
422 {
423 m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
424 }
425 else
426 {
427 try
428 {
429 m_terrainPosition.setValue(AabbCenterX, AabbCenterY, AabbCenterZ);
430 }
431 catch (ObjectDisposedException)
432 {
433 m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
434 }
435 }
436 if (m_terrainMotionState != null)
437 {
438 m_terrainMotionState.Dispose();
439 m_terrainMotionState = null;
440 }
441 m_terrainTransform = new btTransform(QuatIdentity, m_terrainPosition);
442 m_terrainMotionState = new btDefaultMotionState(m_terrainTransform);
443 TerrainBody = new btRigidBody(0, m_terrainMotionState, m_terrainShape);
444 TerrainBody.setUserPointer((IntPtr)0);
445 m_world.addRigidBody(TerrainBody);
446
447
448 }
449
450 public override void SetWaterLevel(float baseheight)
451 {
452
453 }
454
455 public override void DeleteTerrain()
456 {
457 if (TerrainBody != null)
458 {
459 m_world.removeRigidBody(TerrainBody);
460 }
461
462 if (m_terrainShape != null)
463 {
464 m_terrainShape.Dispose();
465 m_terrainShape = null;
466 }
467
468 if (m_terrainMotionState != null)
469 {
470 m_terrainMotionState.Dispose();
471 m_terrainMotionState = null;
472 }
473
474 if (m_terrainTransform != null)
475 {
476 m_terrainTransform.Dispose();
477 m_terrainTransform = null;
478 }
479
480 if (m_terrainPosition != null)
481 {
482 m_terrainPosition.Dispose();
483 m_terrainPosition = null;
484 }
485 }
486
487 public override void Dispose()
488 {
489 disposeAllBodies();
490 m_world.Dispose();
491 m_broadphase.Dispose();
492 ((btDefaultCollisionConfiguration) m_collisionConfiguration).Dispose();
493 ((btSequentialImpulseConstraintSolver) m_solver).Dispose();
494 worldAabbMax.Dispose();
495 worldAabbMin.Dispose();
496 VectorZero.Dispose();
497 QuatIdentity.Dispose();
498 m_gravity.Dispose();
499 VectorZero = null;
500 QuatIdentity = null;
501 }
502
503 public override Dictionary<uint, float> GetTopColliders()
504 {
505 return new Dictionary<uint, float>();
506 }
507
508 public btDiscreteDynamicsWorld getBulletWorld()
509 {
510 return m_world;
511 }
512
513 private void disposeAllBodies()
514 {
515 lock (m_prims)
516 {
517 m_primsLocalID.Clear();
518 foreach (BulletDotNETPrim prim in m_prims)
519 {
520 if (prim.Body != null)
521 m_world.removeRigidBody(prim.Body);
522
523 prim.Dispose();
524 }
525 m_prims.Clear();
526
527 foreach (BulletDotNETCharacter chr in m_characters)
528 {
529 if (chr.Body != null)
530 m_world.removeRigidBody(chr.Body);
531 chr.Dispose();
532 }
533 m_characters.Clear();
534 }
535 }
536
537 public override bool IsThreaded
538 {
539 get { return false; }
540 }
541
542 internal void addCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
543 {
544 //TODO: FIXME:
545 }
546
547 internal void remCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
548 {
549 //TODO: FIXME:
550 }
551
552 internal void AddRigidBody(btRigidBody Body)
553 {
554 m_world.addRigidBody(Body);
555 }
556 [Obsolete("bad!")]
557 internal void removeFromWorld(btRigidBody body)
558 {
559
560 m_world.removeRigidBody(body);
561 }
562
563 internal void removeFromWorld(BulletDotNETPrim prm ,btRigidBody body)
564 {
565 lock (m_prims)
566 {
567 if (m_prims.Contains(prm))
568 {
569 m_world.removeRigidBody(body);
570 }
571 remActivePrim(prm);
572 m_primsLocalID.Remove(prm.m_localID);
573 m_prims.Remove(prm);
574 }
575
576 }
577
578 internal float GetWaterLevel()
579 {
580 throw new NotImplementedException();
581 }
582
583 // Recovered for use by fly height. Kitto Flora
584 public float GetTerrainHeightAtXY(float x, float y)
585 {
586 // Teravus: Kitto, this code causes recurring errors that stall physics permenantly unless
587 // the values are checked, so checking below.
588 // Is there any reason that we don't do this in ScenePresence?
589 // The only physics engine that benefits from it in the physics plugin is this one
590
591 if (x > (int)Constants.RegionSize || y > (int)Constants.RegionSize ||
592 x < 0.001f || y < 0.001f)
593 return 0;
594
595 return _origheightmap[(int)y * Constants.RegionSize + (int)x];
596 }
597 // End recovered. Kitto Flora
598
599 /// <summary>
600 /// Routine to figure out if we need to mesh this prim with our mesher
601 /// </summary>
602 /// <param name="pbs"></param>
603 /// <returns></returns>
604 public bool needsMeshing(PrimitiveBaseShape pbs)
605 {
606 // most of this is redundant now as the mesher will return null if it cant mesh a prim
607 // but we still need to check for sculptie meshing being enabled so this is the most
608 // convenient place to do it for now...
609
610 // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f)
611 // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString());
612 int iPropertiesNotSupportedDefault = 0;
613
614 if (pbs.SculptEntry && !meshSculptedPrim)
615 {
616#if SPAM
617 m_log.Warn("NonMesh");
618#endif
619 return false;
620 }
621
622 // 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
623 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
624 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
625 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
626 {
627
628 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
629 && pbs.ProfileHollow == 0
630 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
631 && pbs.PathBegin == 0 && pbs.PathEnd == 0
632 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
633 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
634 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
635 {
636#if SPAM
637 m_log.Warn("NonMesh");
638#endif
639 return false;
640 }
641 }
642
643 if (pbs.ProfileHollow != 0)
644 iPropertiesNotSupportedDefault++;
645
646 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
647 iPropertiesNotSupportedDefault++;
648
649 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
650 iPropertiesNotSupportedDefault++;
651
652 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
653 iPropertiesNotSupportedDefault++;
654
655 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
656 iPropertiesNotSupportedDefault++;
657
658 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
659 iPropertiesNotSupportedDefault++;
660
661 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
662 iPropertiesNotSupportedDefault++;
663
664 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))
665 iPropertiesNotSupportedDefault++;
666
667 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
668 iPropertiesNotSupportedDefault++;
669
670 // test for torus
671 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
672 {
673 if (pbs.PathCurve == (byte)Extrusion.Curve1)
674 {
675 iPropertiesNotSupportedDefault++;
676 }
677 }
678 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
679 {
680 if (pbs.PathCurve == (byte)Extrusion.Straight)
681 {
682 iPropertiesNotSupportedDefault++;
683 }
684
685 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
686 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
687 {
688 iPropertiesNotSupportedDefault++;
689 }
690 }
691 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
692 {
693 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
694 {
695 iPropertiesNotSupportedDefault++;
696 }
697 }
698 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
699 {
700 if (pbs.PathCurve == (byte)Extrusion.Straight)
701 {
702 iPropertiesNotSupportedDefault++;
703 }
704 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
705 {
706 iPropertiesNotSupportedDefault++;
707 }
708 }
709
710
711 if (iPropertiesNotSupportedDefault == 0)
712 {
713#if SPAM
714 m_log.Warn("NonMesh");
715#endif
716 return false;
717 }
718#if SPAM
719 m_log.Debug("Mesh");
720#endif
721 return true;
722 }
723
724 internal void addActivePrim(BulletDotNETPrim pPrim)
725 {
726 lock (m_activePrims)
727 {
728 if (!m_activePrims.Contains(pPrim))
729 {
730 m_activePrims.Add(pPrim);
731 }
732 }
733 }
734
735 public void remActivePrim(BulletDotNETPrim pDeactivatePrim)
736 {
737 lock (m_activePrims)
738 {
739 m_activePrims.Remove(pDeactivatePrim);
740 }
741 }
742
743 internal void AddPrimToScene(BulletDotNETPrim pPrim)
744 {
745 lock (m_prims)
746 {
747 if (!m_prims.Contains(pPrim))
748 {
749 try
750 {
751 m_prims.Add(pPrim);
752 m_primsLocalID.Add(pPrim.m_localID, pPrim);
753 }
754 catch
755 {
756 // noop if it's already there
757 m_log.Debug("[PHYSICS] BulletDotNet: adding duplicate prim localID");
758 }
759 m_world.addRigidBody(pPrim.Body);
760 // m_log.Debug("[PHYSICS] added prim to scene");
761 }
762 }
763 }
764 internal void EnableCollisionInterface()
765 {
766 if (m_CollisionInterface == null)
767 {
768 m_CollisionInterface = new ContactAddedCallbackHandler(m_world);
769 // m_world.SetCollisionAddedCallback(m_CollisionInterface);
770 }
771 }
772
773
774
775 }
776}
diff --git a/OpenSim/Region/Physics/BulletXPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletXPlugin/AssemblyInfo.cs
deleted file mode 100644
index 6383f26..0000000
--- a/OpenSim/Region/Physics/BulletXPlugin/AssemblyInfo.cs
+++ /dev/null
@@ -1,58 +0,0 @@
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("BulletXPlugin")]
38[assembly : AssemblyDescription("")]
39[assembly : AssemblyConfiguration("")]
40[assembly : AssemblyCompany("http://opensimulator.org")]
41[assembly : AssemblyProduct("BulletXPlugin")]
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/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
deleted file mode 100644
index df62dbc..0000000
--- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
+++ /dev/null
@@ -1,1855 +0,0 @@
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#region References
29
30using System;
31using System.Collections.Generic;
32using OpenMetaverse;
33using MonoXnaCompactMaths;
34using OpenSim.Framework;
35using OpenSim.Region.Physics.Manager;
36using XnaDevRu.BulletX;
37using XnaDevRu.BulletX.Dynamics;
38using Nini.Config;
39using Vector3 = MonoXnaCompactMaths.Vector3;
40using Quaternion = MonoXnaCompactMaths.Quaternion;
41
42#endregion
43
44namespace OpenSim.Region.Physics.BulletXPlugin
45{
46 /// <summary>
47 /// BulletXConversions are called now BulletXMaths
48 /// This Class converts objects and types for BulletX and give some operations
49 /// </summary>
50 public class BulletXMaths
51 {
52 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
53
54 //Vector3
55 public static Vector3 PhysicsVectorToXnaVector3(OpenMetaverse.Vector3 physicsVector)
56 {
57 return new Vector3(physicsVector.X, physicsVector.Y, physicsVector.Z);
58 }
59
60 public static OpenMetaverse.Vector3 XnaVector3ToPhysicsVector(Vector3 xnaVector3)
61 {
62 return new OpenMetaverse.Vector3(xnaVector3.X, xnaVector3.Y, xnaVector3.Z);
63 }
64
65 //Quaternion
66 public static Quaternion QuaternionToXnaQuaternion(OpenMetaverse.Quaternion quaternion)
67 {
68 return new Quaternion(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
69 }
70
71 public static OpenMetaverse.Quaternion XnaQuaternionToQuaternion(Quaternion xnaQuaternion)
72 {
73 return new OpenMetaverse.Quaternion(xnaQuaternion.W, xnaQuaternion.X, xnaQuaternion.Y, xnaQuaternion.Z);
74 }
75
76 //Next methods are extracted from XnaDevRu.BulletX(See 3rd party license):
77 //- SetRotation (class MatrixOperations)
78 //- GetRotation (class MatrixOperations)
79 //- GetElement (class MathHelper)
80 //- SetElement (class MathHelper)
81 internal static void SetRotation(ref Matrix m, Quaternion q)
82 {
83 float d = q.LengthSquared();
84 float s = 2f/d;
85 float xs = q.X*s, ys = q.Y*s, zs = q.Z*s;
86 float wx = q.W*xs, wy = q.W*ys, wz = q.W*zs;
87 float xx = q.X*xs, xy = q.X*ys, xz = q.X*zs;
88 float yy = q.Y*ys, yz = q.Y*zs, zz = q.Z*zs;
89 m = new Matrix(1 - (yy + zz), xy - wz, xz + wy, 0,
90 xy + wz, 1 - (xx + zz), yz - wx, 0,
91 xz - wy, yz + wx, 1 - (xx + yy), 0,
92 m.M41, m.M42, m.M43, 1);
93 }
94
95 internal static Quaternion GetRotation(Matrix m)
96 {
97 Quaternion q;
98
99 float trace = m.M11 + m.M22 + m.M33;
100
101 if (trace > 0)
102 {
103 float s = (float) Math.Sqrt(trace + 1);
104 q.W = s*0.5f;
105 s = 0.5f/s;
106
107 q.X = (m.M32 - m.M23)*s;
108 q.Y = (m.M13 - m.M31)*s;
109 q.Z = (m.M21 - m.M12)*s;
110 }
111 else
112 {
113 q.X = q.Y = q.Z = q.W = 0f;
114
115 int i = m.M11 < m.M22
116 ?
117 (m.M22 < m.M33 ? 2 : 1)
118 :
119 (m.M11 < m.M33 ? 2 : 0);
120 int j = (i + 1)%3;
121 int k = (i + 2)%3;
122
123 float s = (float) Math.Sqrt(GetElement(m, i, i) - GetElement(m, j, j) - GetElement(m, k, k) + 1);
124 SetElement(ref q, i, s*0.5f);
125 s = 0.5f/s;
126
127 q.W = (GetElement(m, k, j) - GetElement(m, j, k))*s;
128 SetElement(ref q, j, (GetElement(m, j, i) + GetElement(m, i, j))*s);
129 SetElement(ref q, k, (GetElement(m, k, i) + GetElement(m, i, k))*s);
130 }
131
132 return q;
133 }
134
135 internal static float SetElement(ref Quaternion q, int index, float value)
136 {
137 switch (index)
138 {
139 case 0:
140 q.X = value;
141 break;
142 case 1:
143 q.Y = value;
144 break;
145 case 2:
146 q.Z = value;
147 break;
148 case 3:
149 q.W = value;
150 break;
151 }
152
153 return 0;
154 }
155
156 internal static float GetElement(Matrix mat, int row, int col)
157 {
158 switch (row)
159 {
160 case 0:
161 switch (col)
162 {
163 case 0:
164 return mat.M11;
165 case 1:
166 return mat.M12;
167 case 2:
168 return mat.M13;
169 }
170 break;
171 case 1:
172 switch (col)
173 {
174 case 0:
175 return mat.M21;
176 case 1:
177 return mat.M22;
178 case 2:
179 return mat.M23;
180 }
181 break;
182 case 2:
183 switch (col)
184 {
185 case 0:
186 return mat.M31;
187 case 1:
188 return mat.M32;
189 case 2:
190 return mat.M33;
191 }
192 break;
193 }
194
195 return 0;
196 }
197 }
198
199 /// <summary>
200 /// PhysicsPlugin Class for BulletX
201 /// </summary>
202 public class BulletXPlugin : IPhysicsPlugin
203 {
204 private BulletXScene _mScene;
205
206 public BulletXPlugin()
207 {
208 }
209
210 public bool Init()
211 {
212 return true;
213 }
214
215 public PhysicsScene GetScene(string sceneIdentifier)
216 {
217 if (_mScene == null)
218 {
219 _mScene = new BulletXScene(sceneIdentifier);
220 }
221 return (_mScene);
222 }
223
224 public string GetName()
225 {
226 return ("modified_BulletX"); //Changed!! "BulletXEngine" To "modified_BulletX"
227 }
228
229 public void Dispose()
230 {
231 }
232 }
233
234
235 // Class to detect and debug collisions
236 // Mainly used for debugging purposes
237 internal class CollisionDispatcherLocal : CollisionDispatcher
238 {
239 private BulletXScene relatedScene;
240
241 public CollisionDispatcherLocal(BulletXScene s)
242 : base()
243 {
244 relatedScene = s;
245 }
246
247 public override bool NeedsCollision(CollisionObject bodyA, CollisionObject bodyB)
248 {
249 RigidBody rb;
250 BulletXCharacter bxcA = null;
251 BulletXPrim bxpA = null;
252 Type t = bodyA.GetType();
253 if (t == typeof (RigidBody))
254 {
255 rb = (RigidBody) bodyA;
256 relatedScene._characters.TryGetValue(rb, out bxcA);
257 relatedScene._prims.TryGetValue(rb, out bxpA);
258 }
259// String nameA;
260// if (bxcA != null)
261// nameA = bxcA._name;
262// else if (bxpA != null)
263// nameA = bxpA._name;
264// else
265// nameA = "null";
266
267
268
269 BulletXCharacter bxcB = null;
270 BulletXPrim bxpB = null;
271 t = bodyB.GetType();
272 if (t == typeof (RigidBody))
273 {
274 rb = (RigidBody) bodyB;
275 relatedScene._characters.TryGetValue(rb, out bxcB);
276 relatedScene._prims.TryGetValue(rb, out bxpB);
277 }
278
279// String nameB;
280// if (bxcB != null)
281// nameB = bxcB._name;
282// else if (bxpB != null)
283// nameB = bxpB._name;
284// else
285 // nameB = "null";
286 bool needsCollision;// = base.NeedsCollision(bodyA, bodyB);
287 int c1 = 3;
288 int c2 = 3;
289
290 ////////////////////////////////////////////////////////
291 //BulletX Mesh Collisions
292 //added by Jed zhu
293 //data: May 07,2005
294 ////////////////////////////////////////////////////////
295 #region BulletXMeshCollisions Fields
296
297
298 if (bxcA != null && bxpB != null)
299 c1 = Collision(bxcA, bxpB);
300 if (bxpA != null && bxcB != null)
301 c2 = Collision(bxcB, bxpA);
302 if (c1 < 2)
303 needsCollision = (c1 > 0) ? true : false;
304 else if (c2 < 2)
305 needsCollision = (c2 > 0) ? true : false;
306 else
307 needsCollision = base.NeedsCollision(bodyA, bodyB);
308
309
310 #endregion
311
312
313 //m_log.DebugFormat("[BulletX]: A collision was detected between {0} and {1} --> {2}", nameA, nameB,
314 //needsCollision);
315
316
317 return needsCollision;
318 }
319 //added by jed zhu
320 //calculas the collision between the Prim and Actor
321 //
322 private int Collision(BulletXCharacter actorA, BulletXPrim primB)
323 {
324 int[] indexBase;
325 Vector3[] vertexBase;
326 Vector3 vNormal;
327 // Vector3 vP1;
328 // Vector3 vP2;
329 // Vector3 vP3;
330 IMesh mesh = primB.GetMesh();
331
332 float fdistance;
333 if (primB == null)
334 return 3;
335 if (mesh == null)
336 return 2;
337 if (actorA == null)
338 return 3;
339
340 int iVertexCount = mesh.getVertexList().Count;
341 int iIndexCount = mesh.getIndexListAsInt().Length;
342 if (iVertexCount == 0)
343 return 3;
344 if (iIndexCount == 0)
345 return 3;
346 lock (BulletXScene.BulletXLock)
347 {
348 indexBase = mesh.getIndexListAsInt();
349 vertexBase = new Vector3[iVertexCount];
350
351 for (int i = 0; i < iVertexCount; i++)
352 {
353 OpenMetaverse.Vector3 v = mesh.getVertexList()[i];
354 if (v != null) // Note, null has special meaning. See meshing code for details
355 vertexBase[i] = BulletXMaths.PhysicsVectorToXnaVector3(v);
356 else
357 vertexBase[i] = Vector3.Zero;
358 }
359
360 for (int ix = 0; ix < iIndexCount; ix += 3)
361 {
362 int ia = indexBase[ix + 0];
363 int ib = indexBase[ix + 1];
364 int ic = indexBase[ix + 2];
365 //
366 Vector3 v1 = vertexBase[ib] - vertexBase[ia];
367 Vector3 v2 = vertexBase[ic] - vertexBase[ia];
368
369 Vector3.Cross(ref v1, ref v2, out vNormal);
370 Vector3.Normalize(ref vNormal, out vNormal);
371
372 fdistance = Vector3.Dot(vNormal, vertexBase[ia]) + 0.50f;
373 if (preCheckCollision(actorA, vNormal, fdistance) == 1)
374 {
375 if (CheckCollision(actorA, ia, ib, ic, vNormal, vertexBase) == 1)
376 {
377 //PhysicsVector v = actorA.Position;
378 //Vector3 v3 = BulletXMaths.PhysicsVectorToXnaVector3(v);
379 //Vector3 vp = vNormal * (fdistance - Vector3.Dot(vNormal, v3) + 0.2f);
380 //actorA.Position += BulletXMaths.XnaVector3ToPhysicsVector(vp);
381 return 1;
382 }
383 }
384 }
385 }
386
387
388 return 0;
389 }
390 //added by jed zhu
391 //return value 1: need second check
392 //return value 0: no need check
393
394 private int preCheckCollision(BulletXActor actA, Vector3 vNormal, float fDist)
395 {
396 float fstartSide;
397 OpenMetaverse.Vector3 v = actA.Position;
398 Vector3 v3 = BulletXMaths.PhysicsVectorToXnaVector3(v);
399
400 fstartSide = Vector3.Dot(vNormal, v3) - fDist;
401 if (fstartSide > 0) return 0;
402 else return 1;
403 }
404 //added by jed zhu
405 private int CheckCollision(BulletXActor actA, int ia, int ib, int ic, Vector3 vNormal, Vector3[] vertBase)
406 {
407 Vector3 perPlaneNormal;
408 float fPerPlaneDist;
409 OpenMetaverse.Vector3 v = actA.Position;
410 Vector3 v3 = BulletXMaths.PhysicsVectorToXnaVector3(v);
411 //check AB
412 Vector3 v1;
413 v1 = vertBase[ib] - vertBase[ia];
414 Vector3.Cross(ref vNormal, ref v1, out perPlaneNormal);
415 Vector3.Normalize(ref perPlaneNormal, out perPlaneNormal);
416
417 if (Vector3.Dot((vertBase[ic] - vertBase[ia]), perPlaneNormal) < 0)
418 perPlaneNormal = -perPlaneNormal;
419 fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ia]) - 0.50f;
420
421
422
423 if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) < 0)
424 return 0;
425 fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ic]) + 0.50f;
426 if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) > 0)
427 return 0;
428
429 //check BC
430
431 v1 = vertBase[ic] - vertBase[ib];
432 Vector3.Cross(ref vNormal, ref v1, out perPlaneNormal);
433 Vector3.Normalize(ref perPlaneNormal, out perPlaneNormal);
434
435 if (Vector3.Dot((vertBase[ia] - vertBase[ib]), perPlaneNormal) < 0)
436 perPlaneNormal = -perPlaneNormal;
437 fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ib]) - 0.50f;
438
439
440 if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) < 0)
441 return 0;
442 fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ia]) + 0.50f;
443 if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) > 0)
444 return 0;
445 //check CA
446 v1 = vertBase[ia] - vertBase[ic];
447 Vector3.Cross(ref vNormal, ref v1, out perPlaneNormal);
448 Vector3.Normalize(ref perPlaneNormal, out perPlaneNormal);
449
450 if (Vector3.Dot((vertBase[ib] - vertBase[ic]), perPlaneNormal) < 0)
451 perPlaneNormal = -perPlaneNormal;
452 fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ic]) - 0.50f;
453
454
455 if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) < 0)
456 return 0;
457 fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ib]) + 0.50f;
458 if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) > 0)
459 return 0;
460
461 return 1;
462
463 }
464 }
465
466 /// <summary>
467 /// PhysicsScene Class for BulletX
468 /// </summary>
469 public class BulletXScene : PhysicsScene
470 {
471 #region BulletXScene Fields
472
473 public DiscreteDynamicsWorld ddWorld;
474 private CollisionDispatcher cDispatcher;
475 private OverlappingPairCache opCache;
476 private SequentialImpulseConstraintSolver sicSolver;
477 public static Object BulletXLock = new Object();
478
479 private const int minXY = 0;
480 private const int minZ = 0;
481 private const int maxXY = (int)Constants.RegionSize;
482 private const int maxZ = 4096;
483 private const int maxHandles = 32766; //Why? I don't know
484 private const float gravity = 9.8f;
485 private const float heightLevel0 = 77.0f;
486 private const float heightLevel1 = 200.0f;
487 private const float lowGravityFactor = 0.2f;
488 //OpenSim calls Simulate 10 times per seconds. So FPS = "Simulate Calls" * simulationSubSteps = 100 FPS
489 private const int simulationSubSteps = 10;
490 //private float[] _heightmap;
491 private BulletXPlanet _simFlatPlanet;
492 internal Dictionary<RigidBody, BulletXCharacter> _characters = new Dictionary<RigidBody, BulletXCharacter>();
493 internal Dictionary<RigidBody, BulletXPrim> _prims = new Dictionary<RigidBody, BulletXPrim>();
494
495 public IMesher mesher;
496 // private IConfigSource m_config;
497
498 // protected internal String identifier;
499
500 public BulletXScene(String sceneIdentifier)
501 {
502 //identifier = sceneIdentifier;
503 cDispatcher = new CollisionDispatcherLocal(this);
504 Vector3 worldMinDim = new Vector3((float)minXY, (float)minXY, (float)minZ);
505 Vector3 worldMaxDim = new Vector3((float)maxXY, (float)maxXY, (float)maxZ);
506 opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles);
507 sicSolver = new SequentialImpulseConstraintSolver();
508
509 lock (BulletXLock)
510 {
511 ddWorld = new DiscreteDynamicsWorld(cDispatcher, opCache, sicSolver);
512 ddWorld.Gravity = new Vector3(0, 0, -gravity);
513 }
514 //this._heightmap = new float[65536];
515 }
516
517 public static float Gravity
518 {
519 get { return gravity; }
520 }
521
522 public static float HeightLevel0
523 {
524 get { return heightLevel0; }
525 }
526
527 public static float HeightLevel1
528 {
529 get { return heightLevel1; }
530 }
531
532 public static float LowGravityFactor
533 {
534 get { return lowGravityFactor; }
535 }
536
537 public static int MaxXY
538 {
539 get { return maxXY; }
540 }
541
542 public static int MaxZ
543 {
544 get { return maxZ; }
545 }
546
547 private List<RigidBody> _forgottenRigidBodies = new List<RigidBody>();
548 internal string is_ex_message = "Can't remove rigidBody!: ";
549
550 #endregion
551
552 public BulletXScene()
553 {
554 cDispatcher = new CollisionDispatcherLocal(this);
555 Vector3 worldMinDim = new Vector3((float) minXY, (float) minXY, (float) minZ);
556 Vector3 worldMaxDim = new Vector3((float) maxXY, (float) maxXY, (float) maxZ);
557 opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles);
558 sicSolver = new SequentialImpulseConstraintSolver();
559
560 lock (BulletXLock)
561 {
562 ddWorld = new DiscreteDynamicsWorld(cDispatcher, opCache, sicSolver);
563 ddWorld.Gravity = new Vector3(0, 0, -gravity);
564 }
565 //this._heightmap = new float[65536];
566 }
567
568 public override void Initialise(IMesher meshmerizer, IConfigSource config)
569 {
570 mesher = meshmerizer;
571 // m_config = config;
572 }
573
574 public override void Dispose()
575 {
576
577 }
578
579 public override Dictionary<uint, float> GetTopColliders()
580 {
581 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
582 return returncolliders;
583 }
584
585 public override void SetWaterLevel(float baseheight)
586 {
587
588 }
589
590 public override PhysicsActor AddAvatar(string avName, OpenMetaverse.Vector3 position, OpenMetaverse.Vector3 size, bool isFlying)
591 {
592 OpenMetaverse.Vector3 pos = OpenMetaverse.Vector3.Zero;
593 pos.X = position.X;
594 pos.Y = position.Y;
595 pos.Z = position.Z + 20;
596 BulletXCharacter newAv = null;
597 lock (BulletXLock)
598 {
599 newAv = new BulletXCharacter(avName, this, pos);
600 _characters.Add(newAv.RigidBody, newAv);
601 }
602 newAv.Flying = isFlying;
603 return newAv;
604 }
605
606 public override void RemoveAvatar(PhysicsActor actor)
607 {
608 if (actor is BulletXCharacter)
609 {
610 lock (BulletXLock)
611 {
612 try
613 {
614 ddWorld.RemoveRigidBody(((BulletXCharacter) actor).RigidBody);
615 }
616 catch (Exception ex)
617 {
618 BulletXMessage(is_ex_message + ex.Message, true);
619 ((BulletXCharacter) actor).RigidBody.ActivationState = ActivationState.DisableSimulation;
620 AddForgottenRigidBody(((BulletXCharacter) actor).RigidBody);
621 }
622 _characters.Remove(((BulletXCharacter) actor).RigidBody);
623 }
624 GC.Collect();
625 }
626 }
627
628 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, OpenMetaverse.Vector3 position,
629 OpenMetaverse.Vector3 size, OpenMetaverse.Quaternion rotation, bool isPhysical, uint localid)
630 {
631 PhysicsActor result;
632
633 switch (pbs.ProfileShape)
634 {
635 case ProfileShape.Square:
636 /// support simple box & hollow box now; later, more shapes
637 if (pbs.ProfileHollow == 0)
638 {
639 result = AddPrim(primName, position, size, rotation, null, null, isPhysical);
640 }
641 else
642 {
643 IMesh mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
644 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
645 }
646 break;
647
648 default:
649 result = AddPrim(primName, position, size, rotation, null, null, isPhysical);
650 break;
651 }
652
653 return result;
654 }
655
656 public PhysicsActor AddPrim(String name, OpenMetaverse.Vector3 position, OpenMetaverse.Vector3 size, OpenMetaverse.Quaternion rotation,
657 IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical)
658 {
659 BulletXPrim newPrim = null;
660 lock (BulletXLock)
661 {
662 newPrim = new BulletXPrim(name, this, position, size, rotation, mesh, pbs, isPhysical);
663 _prims.Add(newPrim.RigidBody, newPrim);
664 }
665 return newPrim;
666 }
667
668 public override void RemovePrim(PhysicsActor prim)
669 {
670 if (prim is BulletXPrim)
671 {
672 lock (BulletXLock)
673 {
674 try
675 {
676 ddWorld.RemoveRigidBody(((BulletXPrim) prim).RigidBody);
677 }
678 catch (Exception ex)
679 {
680 BulletXMessage(is_ex_message + ex.Message, true);
681 ((BulletXPrim) prim).RigidBody.ActivationState = ActivationState.DisableSimulation;
682 AddForgottenRigidBody(((BulletXPrim) prim).RigidBody);
683 }
684 _prims.Remove(((BulletXPrim) prim).RigidBody);
685 }
686 GC.Collect();
687 }
688 }
689
690 public override void AddPhysicsActorTaint(PhysicsActor prim)
691 {
692 }
693
694 public override float Simulate(float timeStep)
695 {
696 float fps = 0;
697 lock (BulletXLock)
698 {
699 //Try to remove garbage
700 RemoveForgottenRigidBodies();
701 //End of remove
702 MoveAPrimitives(timeStep);
703
704
705 fps = (timeStep*simulationSubSteps);
706
707 ddWorld.StepSimulation(timeStep, simulationSubSteps, timeStep);
708 //Extra Heightmap Validation: BulletX's HeightFieldTerrain somestimes doesn't work so fine.
709 ValidateHeightForAll();
710 //End heightmap validation.
711 UpdateKineticsForAll();
712 }
713 return fps;
714 }
715
716 private void MoveAPrimitives(float timeStep)
717 {
718 foreach (BulletXCharacter actor in _characters.Values)
719 {
720 actor.Move(timeStep);
721 }
722 }
723
724 private void ValidateHeightForAll()
725 {
726 float _height;
727 foreach (BulletXCharacter actor in _characters.Values)
728 {
729 //_height = HeightValue(actor.RigidBodyPosition);
730 _height = _simFlatPlanet.HeightValue(actor.RigidBodyPosition);
731 actor.ValidateHeight(_height);
732 //if (_simFlatPlanet.heightIsNotValid(actor.RigidBodyPosition, out _height)) actor.ValidateHeight(_height);
733 }
734 foreach (BulletXPrim prim in _prims.Values)
735 {
736 //_height = HeightValue(prim.RigidBodyPosition);
737 _height = _simFlatPlanet.HeightValue(prim.RigidBodyPosition);
738 prim.ValidateHeight(_height);
739 //if (_simFlatPlanet.heightIsNotValid(prim.RigidBodyPosition, out _height)) prim.ValidateHeight(_height);
740 }
741 //foreach (BulletXCharacter actor in _characters)
742 //{
743 // actor.ValidateHeight(0);
744 //}
745 //foreach (BulletXPrim prim in _prims)
746 //{
747 // prim.ValidateHeight(0);
748 //}
749 }
750
751 private void UpdateKineticsForAll()
752 {
753 //UpdatePosition > UpdateKinetics.
754 //Not only position will be updated, also velocity cause acceleration.
755 foreach (BulletXCharacter actor in _characters.Values)
756 {
757 actor.UpdateKinetics();
758 }
759 foreach (BulletXPrim prim in _prims.Values)
760 {
761 prim.UpdateKinetics();
762 }
763 //if (this._simFlatPlanet!=null) this._simFlatPlanet.Restore();
764 }
765
766 public override void GetResults()
767 {
768 }
769
770 public override bool IsThreaded
771 {
772 get
773 {
774 return (false); // for now we won't be multithreaded
775 }
776 }
777
778 public override void SetTerrain(float[] heightMap)
779 {
780 ////As the same as ODE, heightmap (x,y) must be swapped for BulletX
781 //for (int i = 0; i < 65536; i++)
782 //{
783 // // this._heightmap[i] = (double)heightMap[i];
784 // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...)
785 // int x = i & 0xff;
786 // int y = i >> 8;
787 // this._heightmap[i] = heightMap[x * 256 + y];
788 //}
789
790 //float[] swappedHeightMap = new float[65536];
791 ////As the same as ODE, heightmap (x,y) must be swapped for BulletX
792 //for (int i = 0; i < 65536; i++)
793 //{
794 // // this._heightmap[i] = (double)heightMap[i];
795 // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...)
796 // int x = i & 0xff;
797 // int y = i >> 8;
798 // swappedHeightMap[i] = heightMap[x * 256 + y];
799 //}
800 DeleteTerrain();
801 //There is a BulletXLock inside the constructor of BulletXPlanet
802 //this._simFlatPlanet = new BulletXPlanet(this, swappedHeightMap);
803 _simFlatPlanet = new BulletXPlanet(this, heightMap);
804 //this._heightmap = heightMap;
805 }
806
807 public override void DeleteTerrain()
808 {
809 if (_simFlatPlanet != null)
810 {
811 lock (BulletXLock)
812 {
813 try
814 {
815 ddWorld.RemoveRigidBody(_simFlatPlanet.RigidBody);
816 }
817 catch (Exception ex)
818 {
819 BulletXMessage(is_ex_message + ex.Message, true);
820 _simFlatPlanet.RigidBody.ActivationState = ActivationState.DisableSimulation;
821 AddForgottenRigidBody(_simFlatPlanet.RigidBody);
822 }
823 }
824 _simFlatPlanet = null;
825 GC.Collect();
826 BulletXMessage("Terrain erased!", false);
827 }
828
829
830
831 //this._heightmap = null;
832 }
833
834
835
836 internal void AddForgottenRigidBody(RigidBody forgottenRigidBody)
837 {
838 _forgottenRigidBodies.Add(forgottenRigidBody);
839 }
840
841 private void RemoveForgottenRigidBodies()
842 {
843 RigidBody forgottenRigidBody;
844 int nRigidBodies = _forgottenRigidBodies.Count;
845 for (int i = nRigidBodies - 1; i >= 0; i--)
846 {
847 forgottenRigidBody = _forgottenRigidBodies[i];
848 try
849 {
850 ddWorld.RemoveRigidBody(forgottenRigidBody);
851 _forgottenRigidBodies.Remove(forgottenRigidBody);
852 BulletXMessage("Forgotten Rigid Body Removed", false);
853 }
854 catch (Exception ex)
855 {
856 BulletXMessage("Can't remove forgottenRigidBody!: " + ex.Message, false);
857 }
858 }
859 GC.Collect();
860 }
861
862 internal static void BulletXMessage(string message, bool isWarning)
863 {
864 PhysicsPluginManager.PhysicsPluginMessage("[Modified BulletX]:\t" + message, isWarning);
865 }
866
867 //temp
868 //private float HeightValue(MonoXnaCompactMaths.Vector3 position)
869 //{
870 // int li_x, li_y;
871 // float height;
872 // li_x = (int)Math.Round(position.X); if (li_x < 0) li_x = 0;
873 // li_y = (int)Math.Round(position.Y); if (li_y < 0) li_y = 0;
874
875 // height = this._heightmap[li_y * 256 + li_x];
876 // if (height < 0) height = 0;
877 // else if (height > maxZ) height = maxZ;
878
879 // return height;
880 //}
881 }
882
883 /// <summary>
884 /// Generic Physics Actor for BulletX inherit from PhysicActor
885 /// </summary>
886 public class BulletXActor : PhysicsActor
887 {
888 protected bool flying = false;
889 protected bool _physical = false;
890 protected OpenMetaverse.Vector3 _position;
891 protected OpenMetaverse.Vector3 _velocity;
892 protected OpenMetaverse.Vector3 _size;
893 protected OpenMetaverse.Vector3 _acceleration;
894 protected OpenMetaverse.Quaternion _orientation;
895 protected OpenMetaverse.Vector3 m_rotationalVelocity;
896 protected RigidBody rigidBody;
897 protected int m_PhysicsActorType;
898 private Boolean iscolliding = false;
899 internal string _name;
900
901 public BulletXActor(String name)
902 {
903 _name = name;
904 }
905
906 public override bool Stopped
907 {
908 get { return false; }
909 }
910
911 public override OpenMetaverse.Vector3 Position
912 {
913 get { return _position; }
914 set
915 {
916 lock (BulletXScene.BulletXLock)
917 {
918 _position = value;
919 Translate();
920 }
921 }
922 }
923
924 public override OpenMetaverse.Vector3 RotationalVelocity
925 {
926 get { return m_rotationalVelocity; }
927 set { m_rotationalVelocity = value; }
928 }
929
930 public override OpenMetaverse.Vector3 Velocity
931 {
932 get { return _velocity; }
933 set
934 {
935 lock (BulletXScene.BulletXLock)
936 {
937 //Static objects don' have linear velocity
938 if (_physical)
939 {
940 _velocity = value;
941 Speed();
942 }
943 else
944 {
945 _velocity = OpenMetaverse.Vector3.Zero;
946 }
947 }
948 }
949 }
950 public override float CollisionScore
951 {
952 get { return 0f; }
953 set { }
954 }
955 public override OpenMetaverse.Vector3 Size
956 {
957 get { return _size; }
958 set
959 {
960 lock (BulletXScene.BulletXLock)
961 {
962 _size = value;
963 }
964 }
965 }
966
967 public override OpenMetaverse.Vector3 Force
968 {
969 get { return OpenMetaverse.Vector3.Zero; }
970 set { return; }
971 }
972
973 public override int VehicleType
974 {
975 get { return 0; }
976 set { return; }
977 }
978
979 public override void VehicleFloatParam(int param, float value)
980 {
981
982 }
983
984 public override void VehicleVectorParam(int param, OpenMetaverse.Vector3 value)
985 {
986
987 }
988
989 public override void VehicleRotationParam(int param, OpenMetaverse.Quaternion rotation)
990 {
991
992 }
993
994 public override void VehicleFlags(int param, bool remove)
995 {
996
997 }
998
999 public override void SetVolumeDetect(int param)
1000 {
1001
1002 }
1003
1004 public override OpenMetaverse.Vector3 CenterOfMass
1005 {
1006 get { return OpenMetaverse.Vector3.Zero; }
1007 }
1008
1009 public override OpenMetaverse.Vector3 GeometricCenter
1010 {
1011 get { return OpenMetaverse.Vector3.Zero; }
1012 }
1013
1014 public override PrimitiveBaseShape Shape
1015 {
1016 set { return; }
1017 }
1018
1019 public override bool SetAlwaysRun
1020 {
1021 get { return false; }
1022 set { return; }
1023 }
1024
1025 public override OpenMetaverse.Vector3 Acceleration
1026 {
1027 get { return _acceleration; }
1028 }
1029
1030 public override OpenMetaverse.Quaternion Orientation
1031 {
1032 get { return _orientation; }
1033 set
1034 {
1035 lock (BulletXScene.BulletXLock)
1036 {
1037 _orientation = value;
1038 ReOrient();
1039 }
1040 }
1041 }
1042 public override void link(PhysicsActor obj)
1043 {
1044
1045 }
1046
1047 public override void delink()
1048 {
1049
1050 }
1051
1052 public override void LockAngularMotion(OpenMetaverse.Vector3 axis)
1053 {
1054
1055 }
1056
1057 public override float Mass
1058 {
1059 get { return ActorMass; }
1060 }
1061
1062 public virtual float ActorMass
1063 {
1064 get { return 0; }
1065 }
1066
1067 public override int PhysicsActorType
1068 {
1069 get { return (int) m_PhysicsActorType; }
1070 set { m_PhysicsActorType = value; }
1071 }
1072
1073 public RigidBody RigidBody
1074 {
1075 get { return rigidBody; }
1076 }
1077
1078 public Vector3 RigidBodyPosition
1079 {
1080 get { return rigidBody.CenterOfMassPosition; }
1081 }
1082
1083 public override bool IsPhysical
1084 {
1085 get { return _physical; }
1086 set { _physical = value; }
1087 }
1088
1089 public override bool Flying
1090 {
1091 get { return flying; }
1092 set { flying = value; }
1093 }
1094
1095 public override bool ThrottleUpdates
1096 {
1097 get { return false; }
1098 set { return; }
1099 }
1100
1101 public override bool IsColliding
1102 {
1103 get { return iscolliding; }
1104 set { iscolliding = value; }
1105 }
1106
1107 public override bool CollidingGround
1108 {
1109 get { return false; }
1110 set { return; }
1111 }
1112
1113 public override bool CollidingObj
1114 {
1115 get { return false; }
1116 set { return; }
1117 }
1118
1119 public override uint LocalID
1120 {
1121 set { return; }
1122 }
1123
1124 public override bool Grabbed
1125 {
1126 set { return; }
1127 }
1128
1129 public override bool Selected
1130 {
1131 set { return; }
1132 }
1133
1134 public override float Buoyancy
1135 {
1136 get { return 0f; }
1137 set { return; }
1138 }
1139
1140 public override bool FloatOnWater
1141 {
1142 set { return; }
1143 }
1144
1145 public virtual void SetAcceleration(OpenMetaverse.Vector3 accel)
1146 {
1147 lock (BulletXScene.BulletXLock)
1148 {
1149 _acceleration = accel;
1150 }
1151 }
1152
1153 public override bool Kinematic
1154 {
1155 get { return false; }
1156 set { }
1157 }
1158
1159 public override void AddForce(OpenMetaverse.Vector3 force, bool pushforce)
1160 {
1161 }
1162 public override OpenMetaverse.Vector3 Torque
1163 {
1164 get { return OpenMetaverse.Vector3.Zero; }
1165 set { return; }
1166 }
1167 public override void AddAngularForce(OpenMetaverse.Vector3 force, bool pushforce)
1168 {
1169 }
1170
1171 public override void SetMomentum(OpenMetaverse.Vector3 momentum)
1172 {
1173 }
1174
1175 internal virtual void ValidateHeight(float heighmapPositionValue)
1176 {
1177 }
1178
1179 internal virtual void UpdateKinetics()
1180 {
1181 }
1182
1183 #region Methods for updating values of RigidBody
1184
1185 protected internal void Translate()
1186 {
1187 Translate(_position);
1188 }
1189
1190 protected internal void Translate(OpenMetaverse.Vector3 _newPos)
1191 {
1192 Vector3 _translation;
1193 _translation = BulletXMaths.PhysicsVectorToXnaVector3(_newPos) - rigidBody.CenterOfMassPosition;
1194 rigidBody.Translate(_translation);
1195 }
1196
1197 protected internal void Speed()
1198 {
1199 Speed(_velocity);
1200 }
1201
1202 protected internal void Speed(OpenMetaverse.Vector3 _newSpeed)
1203 {
1204 Vector3 _speed;
1205 _speed = BulletXMaths.PhysicsVectorToXnaVector3(_newSpeed);
1206 rigidBody.LinearVelocity = _speed;
1207 }
1208
1209 protected internal void ReOrient()
1210 {
1211 ReOrient(_orientation);
1212 }
1213
1214 protected internal void ReOrient(OpenMetaverse.Quaternion _newOrient)
1215 {
1216 Quaternion _newOrientation;
1217 _newOrientation = BulletXMaths.QuaternionToXnaQuaternion(_newOrient);
1218 Matrix _comTransform = rigidBody.CenterOfMassTransform;
1219 BulletXMaths.SetRotation(ref _comTransform, _newOrientation);
1220 rigidBody.CenterOfMassTransform = _comTransform;
1221 }
1222
1223 protected internal void ReSize()
1224 {
1225 ReSize(_size);
1226 }
1227
1228 protected internal virtual void ReSize(OpenMetaverse.Vector3 _newSize)
1229 {
1230 }
1231
1232 public virtual void ScheduleTerseUpdate()
1233 {
1234 base.RequestPhysicsterseUpdate();
1235 }
1236
1237 #endregion
1238
1239 public override void CrossingFailure()
1240 {
1241
1242 }
1243 public override OpenMetaverse.Vector3 PIDTarget { set { return; } }
1244 public override bool PIDActive { set { return; } }
1245 public override float PIDTau { set { return; } }
1246
1247 public override float PIDHoverHeight { set { return; } }
1248 public override bool PIDHoverActive { set { return; } }
1249 public override PIDHoverType PIDHoverType { set { return; } }
1250 public override float PIDHoverTau { set { return; } }
1251
1252 public override OpenMetaverse.Quaternion APIDTarget
1253 {
1254 set { return; }
1255 }
1256
1257 public override bool APIDActive
1258 {
1259 set { return; }
1260 }
1261
1262 public override float APIDStrength
1263 {
1264 set { return; }
1265 }
1266
1267 public override float APIDDamping
1268 {
1269 set { return; }
1270 }
1271
1272
1273 public override void SubscribeEvents(int ms)
1274 {
1275
1276 }
1277 public override void UnSubscribeEvents()
1278 {
1279
1280 }
1281 public override bool SubscribedEvents()
1282 {
1283 return false;
1284 }
1285 }
1286
1287 /// <summary>
1288 /// PhysicsActor Character Class for BulletX
1289 /// </summary>
1290 public class BulletXCharacter : BulletXActor
1291 {
1292 public BulletXCharacter(BulletXScene parent_scene, OpenMetaverse.Vector3 pos)
1293 : this(String.Empty, parent_scene, pos)
1294 {
1295 }
1296
1297 public BulletXCharacter(String avName, BulletXScene parent_scene, OpenMetaverse.Vector3 pos)
1298 : this(avName, parent_scene, pos, OpenMetaverse.Vector3.Zero, OpenMetaverse.Vector3.Zero, OpenMetaverse.Vector3.Zero,
1299 OpenMetaverse.Quaternion.Identity)
1300 {
1301 }
1302
1303 public BulletXCharacter(String avName, BulletXScene parent_scene, OpenMetaverse.Vector3 pos, OpenMetaverse.Vector3 velocity,
1304 OpenMetaverse.Vector3 size, OpenMetaverse.Vector3 acceleration, OpenMetaverse.Quaternion orientation)
1305 : base(avName)
1306 {
1307 //This fields will be removed. They're temporal
1308 float _sizeX = 0.5f;
1309 float _sizeY = 0.5f;
1310 float _sizeZ = 1.6f;
1311 //.
1312 _position = pos;
1313 _velocity = velocity;
1314 _size = size;
1315 //---
1316 _size.X = _sizeX;
1317 _size.Y = _sizeY;
1318 _size.Z = _sizeZ;
1319 //.
1320 _acceleration = acceleration;
1321 _orientation = orientation;
1322 _physical = true;
1323
1324 float _mass = 50.0f; //This depends of avatar's dimensions
1325 //For RigidBody Constructor. The next values might change
1326 float _linearDamping = 0.0f;
1327 float _angularDamping = 0.0f;
1328 float _friction = 0.5f;
1329 float _restitution = 0.0f;
1330 Matrix _startTransform = Matrix.Identity;
1331 Matrix _centerOfMassOffset = Matrix.Identity;
1332 lock (BulletXScene.BulletXLock)
1333 {
1334 _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos);
1335 //CollisionShape _collisionShape = new BoxShape(new MonoXnaCompactMaths.Vector3(1.0f, 1.0f, 1.60f));
1336 //For now, like ODE, collisionShape = sphere of radious = 1.0
1337 CollisionShape _collisionShape = new SphereShape(1.0f);
1338 DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset);
1339 Vector3 _localInertia = new Vector3();
1340 _collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0
1341 rigidBody =
1342 new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping,
1343 _friction, _restitution);
1344 //rigidBody.ActivationState = ActivationState.DisableDeactivation;
1345 //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition
1346 Vector3 _vDebugTranslation;
1347 _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition;
1348 rigidBody.Translate(_vDebugTranslation);
1349 parent_scene.ddWorld.AddRigidBody(rigidBody);
1350 }
1351 }
1352
1353 public override int PhysicsActorType
1354 {
1355 get { return (int) ActorTypes.Agent; }
1356 set { return; }
1357 }
1358
1359 public override OpenMetaverse.Vector3 Position
1360 {
1361 get { return base.Position; }
1362 set { base.Position = value; }
1363 }
1364
1365 public override OpenMetaverse.Vector3 Velocity
1366 {
1367 get { return base.Velocity; }
1368 set { base.Velocity = value; }
1369 }
1370
1371 public override OpenMetaverse.Vector3 Size
1372 {
1373 get { return base.Size; }
1374 set { base.Size = value; }
1375 }
1376
1377 public override OpenMetaverse.Vector3 Acceleration
1378 {
1379 get { return base.Acceleration; }
1380 }
1381
1382 public override OpenMetaverse.Quaternion Orientation
1383 {
1384 get { return base.Orientation; }
1385 set { base.Orientation = value; }
1386 }
1387
1388 public override bool Flying
1389 {
1390 get { return base.Flying; }
1391 set { base.Flying = value; }
1392 }
1393
1394 public override bool IsColliding
1395 {
1396 get { return base.IsColliding; }
1397 set { base.IsColliding = value; }
1398 }
1399
1400 public override bool Kinematic
1401 {
1402 get { return base.Kinematic; }
1403 set { base.Kinematic = value; }
1404 }
1405
1406 public override void SetAcceleration(OpenMetaverse.Vector3 accel)
1407 {
1408 base.SetAcceleration(accel);
1409 }
1410
1411 public override void AddForce(OpenMetaverse.Vector3 force, bool pushforce)
1412 {
1413 base.AddForce(force, pushforce);
1414 }
1415
1416 public override void SetMomentum(OpenMetaverse.Vector3 momentum)
1417 {
1418 base.SetMomentum(momentum);
1419 }
1420
1421 internal void Move(float timeStep)
1422 {
1423 Vector3 vec = new Vector3();
1424 //At this point it's supossed that:
1425 //_velocity == rigidBody.LinearVelocity
1426 vec.X = _velocity.X;
1427 vec.Y = _velocity.Y;
1428 vec.Z = _velocity.Z;
1429 if ((vec.X != 0.0f) || (vec.Y != 0.0f) || (vec.Z != 0.0f)) rigidBody.Activate();
1430 if (flying)
1431 {
1432 //Antigravity with movement
1433 if (_position.Z <= BulletXScene.HeightLevel0)
1434 {
1435 vec.Z += BulletXScene.Gravity*timeStep;
1436 }
1437 //Lowgravity with movement
1438 else if ((_position.Z > BulletXScene.HeightLevel0)
1439 && (_position.Z <= BulletXScene.HeightLevel1))
1440 {
1441 vec.Z += BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor);
1442 }
1443 //Lowgravity with...
1444 else if (_position.Z > BulletXScene.HeightLevel1)
1445 {
1446 if (vec.Z > 0) //no movement
1447 vec.Z = BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor);
1448 else
1449 vec.Z += BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor);
1450 }
1451 }
1452 rigidBody.LinearVelocity = vec;
1453 }
1454
1455 //This validation is very basic
1456 internal override void ValidateHeight(float heighmapPositionValue)
1457 {
1458 if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z/2.0f)
1459 {
1460 Matrix m = rigidBody.WorldTransform;
1461 Vector3 v3 = m.Translation;
1462 v3.Z = heighmapPositionValue + _size.Z/2.0f;
1463 m.Translation = v3;
1464 rigidBody.WorldTransform = m;
1465 //When an Avie touch the ground it's vertical velocity it's reduced to ZERO
1466 Speed(new OpenMetaverse.Vector3(rigidBody.LinearVelocity.X, rigidBody.LinearVelocity.Y, 0.0f));
1467 }
1468 }
1469
1470 internal override void UpdateKinetics()
1471 {
1472 _position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition);
1473 _velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity);
1474 //Orientation it seems that it will be the default.
1475 ReOrient();
1476 }
1477 }
1478
1479 /// <summary>
1480 /// PhysicsActor Prim Class for BulletX
1481 /// </summary>
1482 public class BulletXPrim : BulletXActor
1483 {
1484 //Density it will depends of material.
1485 //For now all prims have the same density, all prims are made of water. Be water my friend! :D
1486 private const float _density = 1000.0f;
1487 private BulletXScene _parent_scene;
1488 private OpenMetaverse.Vector3 m_prev_position;
1489 private bool m_lastUpdateSent = false;
1490 //added by jed zhu
1491 private IMesh _mesh;
1492 public IMesh GetMesh() { return _mesh; }
1493
1494
1495
1496 public BulletXPrim(String primName, BulletXScene parent_scene, OpenMetaverse.Vector3 pos, OpenMetaverse.Vector3 size,
1497 OpenMetaverse.Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical)
1498 : this(
1499 primName, parent_scene, pos, OpenMetaverse.Vector3.Zero, size, OpenMetaverse.Vector3.Zero, rotation, mesh, pbs,
1500 isPhysical)
1501 {
1502 }
1503
1504 public BulletXPrim(String primName, BulletXScene parent_scene, OpenMetaverse.Vector3 pos, OpenMetaverse.Vector3 velocity,
1505 OpenMetaverse.Vector3 size,
1506 OpenMetaverse.Vector3 acceleration, OpenMetaverse.Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs,
1507 bool isPhysical)
1508 : base(primName)
1509 {
1510 if ((size.X == 0) || (size.Y == 0) || (size.Z == 0))
1511 throw new Exception("Size 0");
1512 if (OpenMetaverse.Quaternion.Normalize(rotation).Length() == 0f)
1513 rotation = OpenMetaverse.Quaternion.Identity;
1514
1515 _position = pos;
1516 _physical = isPhysical;
1517 _velocity = _physical ? velocity : OpenMetaverse.Vector3.Zero;
1518 _size = size;
1519 _acceleration = acceleration;
1520 _orientation = rotation;
1521
1522 _parent_scene = parent_scene;
1523
1524 CreateRigidBody(parent_scene, mesh, pos, size);
1525 }
1526
1527 public override int PhysicsActorType
1528 {
1529 get { return (int) ActorTypes.Prim; }
1530 set { return; }
1531 }
1532
1533 public override OpenMetaverse.Vector3 Position
1534 {
1535 get { return base.Position; }
1536 set { base.Position = value; }
1537 }
1538
1539 public override OpenMetaverse.Vector3 Velocity
1540 {
1541 get { return base.Velocity; }
1542 set { base.Velocity = value; }
1543 }
1544
1545 public override OpenMetaverse.Vector3 Size
1546 {
1547 get { return _size; }
1548 set
1549 {
1550 lock (BulletXScene.BulletXLock)
1551 {
1552 _size = value;
1553 ReSize();
1554 }
1555 }
1556 }
1557
1558 public override OpenMetaverse.Vector3 Acceleration
1559 {
1560 get { return base.Acceleration; }
1561 }
1562
1563 public override OpenMetaverse.Quaternion Orientation
1564 {
1565 get { return base.Orientation; }
1566 set { base.Orientation = value; }
1567 }
1568
1569 public override float ActorMass
1570 {
1571 get
1572 {
1573 //For now all prims are boxes
1574 return (_physical ? 1 : 0)*_density*_size.X*_size.Y*_size.Z;
1575 }
1576 }
1577
1578 public override bool IsPhysical
1579 {
1580 get { return base.IsPhysical; }
1581 set
1582 {
1583 base.IsPhysical = value;
1584 if (value)
1585 {
1586 //---
1587 PhysicsPluginManager.PhysicsPluginMessage("Physical - Recreate", true);
1588 //---
1589 ReCreateRigidBody(_size);
1590 }
1591 else
1592 {
1593 //---
1594 PhysicsPluginManager.PhysicsPluginMessage("Physical - SetMassProps", true);
1595 //---
1596 rigidBody.SetMassProps(Mass, new Vector3());
1597 }
1598 }
1599 }
1600
1601 public override bool Flying
1602 {
1603 get { return base.Flying; }
1604 set { base.Flying = value; }
1605 }
1606
1607 public override bool IsColliding
1608 {
1609 get { return base.IsColliding; }
1610 set { base.IsColliding = value; }
1611 }
1612
1613 public override bool Kinematic
1614 {
1615 get { return base.Kinematic; }
1616 set { base.Kinematic = value; }
1617 }
1618
1619 public override void SetAcceleration(OpenMetaverse.Vector3 accel)
1620 {
1621 lock (BulletXScene.BulletXLock)
1622 {
1623 _acceleration = accel;
1624 }
1625 }
1626
1627 public override void AddForce(OpenMetaverse.Vector3 force, bool pushforce)
1628 {
1629 base.AddForce(force,pushforce);
1630 }
1631
1632 public override void SetMomentum(OpenMetaverse.Vector3 momentum)
1633 {
1634 base.SetMomentum(momentum);
1635 }
1636
1637 internal override void ValidateHeight(float heighmapPositionValue)
1638 {
1639 if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z/2.0f)
1640 {
1641 Matrix m = rigidBody.WorldTransform;
1642 Vector3 v3 = m.Translation;
1643 v3.Z = heighmapPositionValue + _size.Z/2.0f;
1644 m.Translation = v3;
1645 rigidBody.WorldTransform = m;
1646 //When a Prim touch the ground it's vertical velocity it's reduced to ZERO
1647 //Static objects don't have linear velocity
1648 if (_physical)
1649 Speed(new OpenMetaverse.Vector3(rigidBody.LinearVelocity.X, rigidBody.LinearVelocity.Y, 0.0f));
1650 }
1651 }
1652
1653 internal override void UpdateKinetics()
1654 {
1655 if (_physical) //Updates properties. Prim updates its properties physically
1656 {
1657 _position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition);
1658
1659 _velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity);
1660 _orientation = BulletXMaths.XnaQuaternionToQuaternion(rigidBody.Orientation);
1661
1662 if ((Math.Abs(m_prev_position.X - _position.X) < 0.03)
1663 && (Math.Abs(m_prev_position.Y - _position.Y) < 0.03)
1664 && (Math.Abs(m_prev_position.Z - _position.Z) < 0.03))
1665 {
1666 if (!m_lastUpdateSent)
1667 {
1668 _velocity = OpenMetaverse.Vector3.Zero;
1669 base.ScheduleTerseUpdate();
1670 m_lastUpdateSent = true;
1671 }
1672 }
1673 else
1674 {
1675 m_lastUpdateSent = false;
1676 base.ScheduleTerseUpdate();
1677 }
1678 m_prev_position = _position;
1679 }
1680 else //Doesn't updates properties. That's a cancel
1681 {
1682 Translate();
1683 //Speed(); //<- Static objects don't have linear velocity
1684 ReOrient();
1685 }
1686 }
1687
1688 #region Methods for updating values of RigidBody
1689
1690 protected internal void CreateRigidBody(BulletXScene parent_scene, IMesh mesh, OpenMetaverse.Vector3 pos,
1691 OpenMetaverse.Vector3 size)
1692 {
1693 //For RigidBody Constructor. The next values might change
1694 float _linearDamping = 0.0f;
1695 float _angularDamping = 0.0f;
1696 float _friction = 1.0f;
1697 float _restitution = 0.0f;
1698 Matrix _startTransform = Matrix.Identity;
1699 Matrix _centerOfMassOffset = Matrix.Identity;
1700 //added by jed zhu
1701 _mesh = mesh;
1702
1703 lock (BulletXScene.BulletXLock)
1704 {
1705 _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos);
1706 //For now all prims are boxes
1707 CollisionShape _collisionShape;
1708 if (mesh == null)
1709 {
1710 _collisionShape = new BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(size)/2.0f);
1711 }
1712 else
1713 {
1714 int iVertexCount = mesh.getVertexList().Count;
1715 int[] indices = mesh.getIndexListAsInt();
1716 Vector3[] v3Vertices = new Vector3[iVertexCount];
1717 for (int i = 0; i < iVertexCount; i++)
1718 {
1719 OpenMetaverse.Vector3 v = mesh.getVertexList()[i];
1720 if (v != null) // Note, null has special meaning. See meshing code for details
1721 v3Vertices[i] = BulletXMaths.PhysicsVectorToXnaVector3(v);
1722 else
1723 v3Vertices[i] = Vector3.Zero;
1724 }
1725 TriangleIndexVertexArray triMesh = new TriangleIndexVertexArray(indices, v3Vertices);
1726
1727 _collisionShape = new TriangleMeshShape(triMesh);
1728 }
1729 DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset);
1730 Vector3 _localInertia = new Vector3();
1731 if (_physical) _collisionShape.CalculateLocalInertia(Mass, out _localInertia); //Always when mass > 0
1732 rigidBody =
1733 new RigidBody(Mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping,
1734 _friction, _restitution);
1735 //rigidBody.ActivationState = ActivationState.DisableDeactivation;
1736 //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition
1737 Vector3 _vDebugTranslation;
1738 _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition;
1739 rigidBody.Translate(_vDebugTranslation);
1740 //---
1741 parent_scene.ddWorld.AddRigidBody(rigidBody);
1742 }
1743 }
1744
1745 protected internal void ReCreateRigidBody(OpenMetaverse.Vector3 size)
1746 {
1747 //There is a bug when trying to remove a rigidBody that is colliding with something..
1748 try
1749 {
1750 _parent_scene.ddWorld.RemoveRigidBody(rigidBody);
1751 }
1752 catch (Exception ex)
1753 {
1754 BulletXScene.BulletXMessage(_parent_scene.is_ex_message + ex.Message, true);
1755 rigidBody.ActivationState = ActivationState.DisableSimulation;
1756 _parent_scene.AddForgottenRigidBody(rigidBody);
1757 }
1758 CreateRigidBody(_parent_scene, null, _position, size);
1759 // Note, null for the meshing definitely is wrong. It's here for the moment to apease the compiler
1760 if (_physical) Speed(); //Static objects don't have linear velocity
1761 ReOrient();
1762 GC.Collect();
1763 }
1764
1765 protected internal override void ReSize(OpenMetaverse.Vector3 _newSize)
1766 {
1767 //I wonder to know how to resize with a simple instruction in BulletX. It seems that for now there isn't
1768 //so i have to do it manually. That's recreating rigidbody
1769 ReCreateRigidBody(_newSize);
1770 }
1771
1772 #endregion
1773 }
1774
1775 /// <summary>
1776 /// This Class manage a HeighField as a RigidBody. This is for to be added in the BulletXScene
1777 /// </summary>
1778 internal class BulletXPlanet
1779 {
1780 private OpenMetaverse.Vector3 _staticPosition;
1781// private Vector3 _staticVelocity;
1782// private OpenMetaverse.Quaternion _staticOrientation;
1783 private float _mass;
1784 // private BulletXScene _parentscene;
1785 internal float[] _heightField;
1786 private RigidBody _flatPlanet;
1787
1788 internal RigidBody RigidBody
1789 {
1790 get { return _flatPlanet; }
1791 }
1792
1793 internal BulletXPlanet(BulletXScene parent_scene, float[] heightField)
1794 {
1795 _staticPosition = new OpenMetaverse.Vector3(BulletXScene.MaxXY / 2, BulletXScene.MaxXY / 2, 0);
1796// _staticVelocity = new PhysicsVector();
1797// _staticOrientation = OpenMetaverse.Quaternion.Identity;
1798 _mass = 0; //No active
1799 // _parentscene = parent_scene;
1800 _heightField = heightField;
1801
1802 float _linearDamping = 0.0f;
1803 float _angularDamping = 0.0f;
1804 float _friction = 0.5f;
1805 float _restitution = 0.0f;
1806 Matrix _startTransform = Matrix.Identity;
1807 Matrix _centerOfMassOffset = Matrix.Identity;
1808
1809 lock (BulletXScene.BulletXLock)
1810 {
1811 try
1812 {
1813 _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(_staticPosition);
1814 CollisionShape _collisionShape =
1815 new HeightfieldTerrainShape(BulletXScene.MaxXY, BulletXScene.MaxXY, _heightField,
1816 (float) BulletXScene.MaxZ, 2, true, false);
1817 DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset);
1818 Vector3 _localInertia = new Vector3();
1819 //_collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0
1820 _flatPlanet =
1821 new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping,
1822 _angularDamping, _friction, _restitution);
1823 //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition
1824 Vector3 _vDebugTranslation;
1825 _vDebugTranslation = _startTransform.Translation - _flatPlanet.CenterOfMassPosition;
1826 _flatPlanet.Translate(_vDebugTranslation);
1827 parent_scene.ddWorld.AddRigidBody(_flatPlanet);
1828 }
1829 catch (Exception ex)
1830 {
1831 BulletXScene.BulletXMessage(ex.Message, true);
1832 }
1833 }
1834 BulletXScene.BulletXMessage("BulletXPlanet created.", false);
1835 }
1836
1837 internal float HeightValue(Vector3 position)
1838 {
1839 int li_x, li_y;
1840 float height;
1841 li_x = (int) Math.Round(position.X);
1842 if (li_x < 0) li_x = 0;
1843 if (li_x >= BulletXScene.MaxXY) li_x = BulletXScene.MaxXY - 1;
1844 li_y = (int) Math.Round(position.Y);
1845 if (li_y < 0) li_y = 0;
1846 if (li_y >= BulletXScene.MaxXY) li_y = BulletXScene.MaxXY - 1;
1847
1848 height = ((HeightfieldTerrainShape) _flatPlanet.CollisionShape).getHeightFieldValue(li_x, li_y);
1849 if (height < 0) height = 0;
1850 else if (height > BulletXScene.MaxZ) height = BulletXScene.MaxZ;
1851
1852 return height;
1853 }
1854 }
1855}
diff --git a/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs b/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs
deleted file mode 100644
index 637cf6e..0000000
--- a/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs
+++ /dev/null
@@ -1,197 +0,0 @@
1/*
2 Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru
3 Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22/*
23 This file contains a class TriangleIndexVertexArray. I tried using the class with the same name
24 from the BulletX implementation and found it unusable for the purpose of using triangle meshes
25 within BulletX as the implementation was painfully incomplete.
26 The attempt to derive from the original class failed as viable members were hidden.
27 Fiddling around with BulletX itself was not my intention.
28 So I copied the class to the BulletX-plugin and modified it.
29 If you want to fiddle around with it it's up to you to move all this to BulletX.
30 If someone someday implements the missing functionality in BulletX, feel free to remove this class.
31 It's just an ugly hack.
32*/
33
34using System;
35using System.Collections.Generic;
36using MonoXnaCompactMaths;
37using XnaDevRu.BulletX;
38
39namespace OpenSim.Region.Physics.BulletXPlugin
40{
41 /// <summary>
42 /// IndexedMesh indexes into existing vertex and index arrays, in a similar way OpenGL glDrawElements
43 /// instead of the number of indices, we pass the number of triangles
44 /// </summary>
45 public struct IndexedMesh
46 {
47 private int _numTriangles;
48 private int[] _triangleIndexBase;
49 private int _triangleIndexStride;
50 private int _numVertices;
51 private Vector3[] _vertexBase;
52 private int _vertexStride;
53
54 public IndexedMesh(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices,
55 Vector3[] vertexBase, int vertexStride)
56 {
57 _numTriangles = numTriangleIndices;
58 _triangleIndexBase = triangleIndexBase;
59 _triangleIndexStride = triangleIndexStride;
60 _vertexBase = vertexBase;
61 _numVertices = numVertices;
62 _vertexStride = vertexStride;
63 }
64
65 public IndexedMesh(int[] triangleIndexBase, Vector3[] vertexBase)
66 {
67 _numTriangles = triangleIndexBase.Length;
68 _triangleIndexBase = triangleIndexBase;
69 _triangleIndexStride = 32;
70 _vertexBase = vertexBase;
71 _numVertices = vertexBase.Length;
72 _vertexStride = 24;
73 }
74
75 public int TriangleCount
76 {
77 get { return _numTriangles; }
78 set { _numTriangles = value; }
79 }
80
81 public int[] TriangleIndexBase
82 {
83 get { return _triangleIndexBase; }
84 set { _triangleIndexBase = value; }
85 }
86
87 public int TriangleIndexStride
88 {
89 get { return _triangleIndexStride; }
90 set { _triangleIndexStride = value; }
91 }
92
93 public int VertexCount
94 {
95 get { return _numVertices; }
96 set { _numVertices = value; }
97 }
98
99 public Vector3[] VertexBase
100 {
101 get { return _vertexBase; }
102 set { _vertexBase = value; }
103 }
104
105 public int VertexStride
106 {
107 get { return _vertexStride; }
108 set { _vertexStride = value; }
109 }
110 }
111
112 /// <summary>
113 /// TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays.
114 /// Additional meshes can be added using addIndexedMesh
115 /// </summary>
116 public class TriangleIndexVertexArray : StridingMeshInterface
117 {
118 private List<IndexedMesh> _indexedMeshes = new List<IndexedMesh>();
119
120 public TriangleIndexVertexArray()
121 {
122 }
123
124 public TriangleIndexVertexArray(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride,
125 int numVertices, Vector3[] vertexBase, int vertexStride)
126 {
127 IndexedMesh mesh = new IndexedMesh();
128 mesh.TriangleCount = numTriangleIndices;
129 mesh.TriangleIndexBase = triangleIndexBase;
130 mesh.TriangleIndexStride = triangleIndexStride;
131 mesh.VertexBase = vertexBase;
132 mesh.VertexCount = numVertices;
133 mesh.VertexStride = vertexStride;
134
135 AddIndexedMesh(mesh);
136 }
137
138 public TriangleIndexVertexArray(int[] triangleIndexBase, Vector3[] vertexBase)
139 : this(triangleIndexBase.Length, triangleIndexBase, 32, vertexBase.Length, vertexBase, 24)
140 {
141 }
142
143 public void AddIndexedMesh(IndexedMesh indexedMesh)
144 {
145 _indexedMeshes.Add(indexedMesh);
146 }
147
148 public override void GetLockedVertexIndexBase(out List<Vector3> verts, out List<int> indicies, out int numfaces,
149 int subpart)
150 {
151 throw new Exception("The method or operation is not implemented.");
152 }
153
154 public override void GetLockedReadOnlyVertexIndexBase(out List<Vector3> verts, out List<int> indicies,
155 out int numfaces, int subpart)
156 {
157 IndexedMesh m = _indexedMeshes[0];
158 Vector3[] vertexBase = m.VertexBase;
159 verts = new List<Vector3>();
160 foreach (Vector3 v in vertexBase)
161 {
162 verts.Add(v);
163 }
164 int[] indexBase = m.TriangleIndexBase;
165 indicies = new List<int>();
166 foreach (int i in indexBase)
167 {
168 indicies.Add(i);
169 }
170 numfaces = vertexBase.GetLength(0);
171 }
172
173 public override void UnLockVertexBase(int subpart)
174 {
175 throw new Exception("The method or operation is not implemented.");
176 }
177
178 public override void UnLockReadOnlyVertexBase(int subpart)
179 {
180 }
181
182 public override int SubPartsCount()
183 {
184 return _indexedMeshes.Count;
185 }
186
187 public override void PreallocateVertices(int numverts)
188 {
189 throw new Exception("The method or operation is not implemented.");
190 }
191
192 public override void PreallocateIndices(int numindices)
193 {
194 throw new Exception("The method or operation is not implemented.");
195 }
196 }
197}