aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs1190
1 files changed, 0 insertions, 1190 deletions
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
deleted file mode 100644
index f13c323..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
+++ /dev/null
@@ -1,1190 +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 public override Quaternion APIDTarget
629 {
630 set { return; }
631 }
632
633 public override bool APIDActive
634 {
635 set { return; }
636 }
637
638 public override float APIDStrength
639 {
640 set { return; }
641 }
642
643 public override float APIDDamping
644 {
645 set { return; }
646 }
647
648 /// <summary>
649 /// Adds the force supplied to the Target Velocity
650 /// The PID controller takes this target velocity and tries to make it a reality
651 /// </summary>
652 /// <param name="force"></param>
653 /// <param name="pushforce">Is this a push by a script?</param>
654 public override void AddForce(Vector3 force, bool pushforce)
655 {
656 if (pushforce)
657 {
658 m_pidControllerActive = false;
659 force *= 100f;
660 doForce(force, false);
661 //System.Console.WriteLine("Push!");
662 //_target_velocity.X += force.X;
663 // _target_velocity.Y += force.Y;
664 //_target_velocity.Z += force.Z;
665 }
666 else
667 {
668 m_pidControllerActive = true;
669 m_target_velocity.X += force.X;
670 m_target_velocity.Y += force.Y;
671 m_target_velocity.Z += force.Z;
672 }
673 //m_lastUpdateSent = false;
674 }
675
676 public void doForce(Vector3 force, bool now)
677 {
678
679 tempVector3.setValue(force.X, force.Y, force.Z);
680 if (now)
681 {
682 Body.applyCentralForce(tempVector3);
683 }
684 else
685 {
686 m_taintedForce += force;
687 m_parent_scene.AddPhysicsActorTaint(this);
688 }
689 }
690
691 public void doImpulse(Vector3 force, bool now)
692 {
693
694 tempVector3.setValue(force.X, force.Y, force.Z);
695 if (now)
696 {
697 Body.applyCentralImpulse(tempVector3);
698 }
699 else
700 {
701 m_taintedForce += force;
702 m_parent_scene.AddPhysicsActorTaint(this);
703 }
704 }
705
706 public override void AddAngularForce(Vector3 force, bool pushforce)
707 {
708
709 }
710
711 public override void SetMomentum(Vector3 momentum)
712 {
713
714 }
715
716 public override void SubscribeEvents(int ms)
717 {
718 m_eventsubscription = ms;
719 m_requestedUpdateFrequency = ms;
720 m_parent_scene.addCollisionEventReporting(this);
721 }
722
723 public override void UnSubscribeEvents()
724 {
725 m_parent_scene.remCollisionEventReporting(this);
726 m_eventsubscription = 0;
727 m_requestedUpdateFrequency = 0;
728 }
729
730 public override bool SubscribedEvents()
731 {
732 if (m_eventsubscription > 0)
733 return true;
734 return false;
735 }
736
737 public void AddCollision(uint collideWith, ContactPoint contact)
738 {
739 if (CollisionEventsThisFrame == null)
740 {
741 CollisionEventsThisFrame = new CollisionEventUpdate();
742 }
743 CollisionEventsThisFrame.addCollider(collideWith, contact);
744 }
745
746 public void SendCollisions()
747 {
748 if (m_eventsubscription >= m_requestedUpdateFrequency)
749 {
750 if (CollisionEventsThisFrame != null)
751 {
752 base.SendCollisionUpdate(CollisionEventsThisFrame);
753 }
754 CollisionEventsThisFrame = new CollisionEventUpdate();
755 m_eventsubscription = 0;
756 }
757 return;
758 }
759
760 internal void Dispose()
761 {
762 if (Body.isInWorld())
763 m_parent_scene.removeFromWorld(Body);
764
765 if (m_aMotor.Handle != IntPtr.Zero)
766 m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
767
768 m_aMotor.Dispose(); m_aMotor = null;
769 ClosestCastResult.Dispose(); ClosestCastResult = null;
770 Body.Dispose(); Body = null;
771 Shell.Dispose(); Shell = null;
772 tempQuat1.Dispose();
773 tempTrans1.Dispose();
774 tempVector1.Dispose();
775 tempVector2.Dispose();
776 tempVector3.Dispose();
777 tempVector4.Dispose();
778 tempVector5RayCast.Dispose();
779 tempVector6RayCast.Dispose();
780
781 }
782
783 public void ProcessTaints(float timestep)
784 {
785
786 if (m_tainted_isPhysical != m_isPhysical)
787 {
788 if (m_tainted_isPhysical)
789 {
790 // Create avatar capsule and related ODE data
791 if (!(Shell == null && Body == null))
792 {
793 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
794 + (Shell != null ? "Shell " : "")
795 + (Body != null ? "Body " : ""));
796 }
797 AvatarGeomAndBodyCreation(m_position.X, m_position.Y, m_position.Z);
798
799
800 }
801 else
802 {
803 // destroy avatar capsule and related ODE data
804
805 Dispose();
806 tempVector1 = new btVector3(0, 0, 0);
807 tempVector2 = new btVector3(0, 0, 0);
808 tempVector3 = new btVector3(0, 0, 0);
809 tempVector4 = new btVector3(0, 0, 0);
810
811 tempVector5RayCast = new btVector3(0, 0, 0);
812 tempVector6RayCast = new btVector3(0, 0, 0);
813 tempVector7RayCast = new btVector3(0, 0, 0);
814
815 tempQuat1 = new btQuaternion(0, 0, 0, 1);
816 tempTrans1 = new btTransform(tempQuat1, tempVector1);
817 // m_movementComparision = new PhysicsVector(0, 0, 0);
818 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
819 }
820
821 m_isPhysical = m_tainted_isPhysical;
822 }
823
824 if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH)
825 {
826 if (Body != null)
827 {
828
829 m_pidControllerActive = true;
830 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
831 //d.JointDestroy(Amotor);
832 float prevCapsule = CAPSULE_LENGTH;
833 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
834 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
835 Dispose();
836
837 tempVector1 = new btVector3(0, 0, 0);
838 tempVector2 = new btVector3(0, 0, 0);
839 tempVector3 = new btVector3(0, 0, 0);
840 tempVector4 = new btVector3(0, 0, 0);
841
842 tempVector5RayCast = new btVector3(0, 0, 0);
843 tempVector6RayCast = new btVector3(0, 0, 0);
844 tempVector7RayCast = new btVector3(0, 0, 0);
845
846 tempQuat1 = new btQuaternion(0, 0, 0, 1);
847 tempTrans1 = new btTransform(tempQuat1, tempVector1);
848 // m_movementComparision = new PhysicsVector(0, 0, 0);
849 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
850
851 AvatarGeomAndBodyCreation(m_position.X, m_position.Y,
852 m_position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2));
853 Velocity = Vector3.Zero;
854
855 }
856 else
857 {
858 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
859 + (Shell == null ? "Shell " : "")
860 + (Body == null ? "Body " : ""));
861 }
862 }
863 if (m_taintRemove)
864 {
865 Dispose();
866 }
867 }
868
869 /// <summary>
870 /// Called from Simulate
871 /// This is the avatar's movement control + PID Controller
872 /// </summary>
873 /// <param name="timeStep"></param>
874 public void Move(float timeStep)
875 {
876 // no lock; for now it's only called from within Simulate()
877
878 // If the PID Controller isn't active then we set our force
879 // calculating base velocity to the current position
880 if (Body == null)
881 return;
882 tempTrans1.Dispose();
883 tempTrans1 = Body.getInterpolationWorldTransform();
884 tempVector1.Dispose();
885 tempVector1 = tempTrans1.getOrigin();
886 tempVector2.Dispose();
887 tempVector2 = Body.getInterpolationLinearVelocity();
888
889 if (m_pidControllerActive == false)
890 {
891 m_zeroPosition.X = tempVector1.getX();
892 m_zeroPosition.Y = tempVector1.getY();
893 m_zeroPosition.Z = tempVector1.getZ();
894 }
895 //PidStatus = true;
896
897 Vector3 vec = Vector3.Zero;
898
899 Vector3 vel = new Vector3(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
900
901 float movementdivisor = 1f;
902
903 if (!m_alwaysRun)
904 {
905 movementdivisor = walkDivisor;
906 }
907 else
908 {
909 movementdivisor = runDivisor;
910 }
911
912 // if velocity is zero, use position control; otherwise, velocity control
913 if (m_target_velocity.X == 0.0f && m_target_velocity.Y == 0.0f && m_target_velocity.Z == 0.0f && m_iscolliding)
914 {
915 // keep track of where we stopped. No more slippin' & slidin'
916 if (!m_zeroFlag)
917 {
918 m_zeroFlag = true;
919 m_zeroPosition.X = tempVector1.getX();
920 m_zeroPosition.Y = tempVector1.getY();
921 m_zeroPosition.Z = tempVector1.getZ();
922 }
923 if (m_pidControllerActive)
924 {
925 // We only want to deactivate the PID Controller if we think we want to have our surrogate
926 // react to the physics scene by moving it's position.
927 // Avatar to Avatar collisions
928 // Prim to avatar collisions
929
930 Vector3 pos = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
931 vec.X = (m_target_velocity.X - vel.X) * (PID_D) + (m_zeroPosition.X - pos.X) * (PID_P * 2);
932 vec.Y = (m_target_velocity.Y - vel.Y) * (PID_D) + (m_zeroPosition.Y - pos.Y) * (PID_P * 2);
933 if (m_flying)
934 {
935 vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D) + (m_zeroPosition.Z - pos.Z) * PID_P;
936 }
937 }
938 //PidStatus = true;
939 }
940 else
941 {
942 m_pidControllerActive = true;
943 m_zeroFlag = false;
944 if (m_iscolliding && !m_flying)
945 {
946 // We're standing on something
947 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
948 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
949 }
950 else if (m_iscolliding && m_flying)
951 {
952 // We're flying and colliding with something
953 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
954 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
955 }
956 else if (!m_iscolliding && m_flying)
957 {
958 // we're in mid air suspended
959 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
960 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);
961
962 // We don't want linear velocity to cause our avatar to bounce, so we check target Z and actual velocity X, Y
963 // rebound preventing
964 if (m_target_velocity.Z < 0.025f && m_velocity.X < 0.25f && m_velocity.Y < 0.25f)
965 m_zeroFlag = true;
966 }
967
968 if (m_iscolliding && !m_flying && m_target_velocity.Z > 0.0f)
969 {
970 // We're colliding with something and we're not flying but we're moving
971 // This means we're walking or running.
972 Vector3 pos = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
973 vec.Z = (m_target_velocity.Z - vel.Z) * PID_D + (m_zeroPosition.Z - pos.Z) * PID_P;
974 if (m_target_velocity.X > 0)
975 {
976 vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
977 }
978 if (m_target_velocity.Y > 0)
979 {
980 vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
981 }
982 }
983 else if (!m_iscolliding && !m_flying)
984 {
985 // we're not colliding and we're not flying so that means we're falling!
986 // m_iscolliding includes collisions with the ground.
987
988 // d.Vector3 pos = d.BodyGetPosition(Body);
989 if (m_target_velocity.X > 0)
990 {
991 vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
992 }
993 if (m_target_velocity.Y > 0)
994 {
995 vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
996 }
997 }
998
999
1000 if (m_flying)
1001 {
1002 vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D);
1003 }
1004 }
1005 if (m_flying)
1006 {
1007 // Slight PID correction
1008 vec.Z += (((-1 * m_parent_scene.gravityz) * m_mass) * 0.06f);
1009
1010
1011 //auto fly height. Kitto Flora
1012 //d.Vector3 pos = d.BodyGetPosition(Body);
1013 float target_altitude = m_parent_scene.GetTerrainHeightAtXY(m_position.X, m_position.Y) + 5.0f;
1014
1015 if (m_position.Z < target_altitude)
1016 {
1017 vec.Z += (target_altitude - m_position.Z) * PID_P * 5.0f;
1018 }
1019
1020 }
1021 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))))
1022 {
1023 Body.setFriction(0.001f);
1024 //m_log.DebugFormat("[PHYSICS]: Avatar force applied: {0}, Target:{1}", vec.ToString(), m_target_velocity.ToString());
1025 }
1026
1027 if (Body != null)
1028 {
1029 int activationstate = Body.getActivationState();
1030 if (activationstate == 0)
1031 {
1032 Body.forceActivationState(1);
1033 }
1034
1035
1036 }
1037 doImpulse(vec, true);
1038 }
1039
1040 /// <summary>
1041 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
1042 /// </summary>
1043 public void UpdatePositionAndVelocity()
1044 {
1045 if (Body == null)
1046 return;
1047 //int val = Environment.TickCount;
1048 CheckIfStandingOnObject();
1049 //m_log.DebugFormat("time:{0}", Environment.TickCount - val);
1050
1051 //IsColliding = Body.checkCollideWith(m_parent_scene.TerrainBody);
1052
1053 tempTrans1.Dispose();
1054 tempTrans1 = Body.getInterpolationWorldTransform();
1055 tempVector1.Dispose();
1056 tempVector1 = tempTrans1.getOrigin();
1057 tempVector2.Dispose();
1058 tempVector2 = Body.getInterpolationLinearVelocity();
1059
1060 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
1061 Vector3 vec = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
1062
1063 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
1064 if (vec.X < -10.0f) vec.X = 0.0f;
1065 if (vec.Y < -10.0f) vec.Y = 0.0f;
1066 if (vec.X > (int)Constants.RegionSize + 10.2f) vec.X = (int)Constants.RegionSize + 10.2f;
1067 if (vec.Y > (int)Constants.RegionSize + 10.2f) vec.Y = (int)Constants.RegionSize + 10.2f;
1068
1069 m_position.X = vec.X;
1070 m_position.Y = vec.Y;
1071 m_position.Z = vec.Z;
1072
1073 // Did we move last? = zeroflag
1074 // This helps keep us from sliding all over
1075
1076 if (m_zeroFlag)
1077 {
1078 m_velocity.X = 0.0f;
1079 m_velocity.Y = 0.0f;
1080 m_velocity.Z = 0.0f;
1081
1082 // Did we send out the 'stopped' message?
1083 if (!m_lastUpdateSent)
1084 {
1085 m_lastUpdateSent = true;
1086 //base.RequestPhysicsterseUpdate();
1087
1088 }
1089 }
1090 else
1091 {
1092 m_lastUpdateSent = false;
1093 vec = new Vector3(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
1094 m_velocity.X = (vec.X);
1095 m_velocity.Y = (vec.Y);
1096
1097 m_velocity.Z = (vec.Z);
1098 //m_log.Debug(m_target_velocity);
1099 if (m_velocity.Z < -6 && !m_hackSentFall)
1100 {
1101 m_hackSentFall = true;
1102 m_pidControllerActive = false;
1103 }
1104 else if (m_flying && !m_hackSentFly)
1105 {
1106 //m_hackSentFly = true;
1107 //base.SendCollisionUpdate(new CollisionEventUpdate());
1108 }
1109 else
1110 {
1111 m_hackSentFly = false;
1112 m_hackSentFall = false;
1113 }
1114 }
1115 if (Body != null)
1116 {
1117 if (Body.getFriction() < 0.9f)
1118 Body.setFriction(0.9f);
1119 }
1120 //if (Body != null)
1121 // Body.clearForces();
1122 }
1123
1124 public void CheckIfStandingOnObject()
1125 {
1126
1127 float capsuleHalfHeight = ((CAPSULE_LENGTH + 2*CAPSULE_RADIUS)*0.5f);
1128
1129 tempVector5RayCast.setValue(m_position.X, m_position.Y, m_position.Z);
1130 tempVector6RayCast.setValue(m_position.X, m_position.Y, m_position.Z - 1 * capsuleHalfHeight * 1.1f);
1131
1132
1133 ClosestCastResult.Dispose();
1134 ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
1135
1136 try
1137 {
1138 m_parent_scene.getBulletWorld().rayTest(tempVector5RayCast, tempVector6RayCast, ClosestCastResult);
1139 }
1140 catch (AccessViolationException)
1141 {
1142 m_log.Debug("BAD!");
1143 }
1144 if (ClosestCastResult.hasHit())
1145 {
1146
1147 if (tempVector7RayCast != null)
1148 tempVector7RayCast.Dispose();
1149
1150 //tempVector7RayCast = ClosestCastResult.getHitPointWorld();
1151
1152 /*if (tempVector7RayCast == null) // null == no result also
1153 {
1154 CollidingObj = false;
1155 IsColliding = false;
1156 CollidingGround = false;
1157
1158 return;
1159 }
1160 float zVal = tempVector7RayCast.getZ();
1161 if (zVal != 0)
1162 m_log.Debug("[PHYSICS]: HAAAA");
1163 if (zVal < m_position.Z && zVal > ((CAPSULE_LENGTH + 2 * CAPSULE_RADIUS) *0.5f))
1164 {
1165 CollidingObj = true;
1166 IsColliding = true;
1167 }
1168 else
1169 {
1170 CollidingObj = false;
1171 IsColliding = false;
1172 CollidingGround = false;
1173 }*/
1174
1175 //height+2*radius = capsule full length
1176 //CollidingObj = true;
1177 //IsColliding = true;
1178 m_iscolliding = true;
1179 }
1180 else
1181 {
1182 //CollidingObj = false;
1183 //IsColliding = false;
1184 //CollidingGround = false;
1185 m_iscolliding = false;
1186 }
1187 }
1188 }
1189
1190}