aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletDotNETPlugin
diff options
context:
space:
mode:
Diffstat (limited to '')
-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
6 files changed, 0 insertions, 4917 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}