aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorTeravus Ovares2009-04-05 08:35:38 +0000
committerTeravus Ovares2009-04-05 08:35:38 +0000
commite592d038430ab994ed65df4f66e0cf5c32af476c (patch)
treefda1471564c4f5d24785df72803668fb117b16c4 /OpenSim
parentAdded CreateObject(regionhandle, userID, itemID) to post objects that are to ... (diff)
downloadopensim-SC_OLD-e592d038430ab994ed65df4f66e0cf5c32af476c.zip
opensim-SC_OLD-e592d038430ab994ed65df4f66e0cf5c32af476c.tar.gz
opensim-SC_OLD-e592d038430ab994ed65df4f66e0cf5c32af476c.tar.bz2
opensim-SC_OLD-e592d038430ab994ed65df4f66e0cf5c32af476c.tar.xz
* Committing what I have on the BulletDotNETPlugin that I have so far.
* It's not ready to try. It doesn't do what you expect in many ways. * It throws errors and prints jibberish on the console * Test it out only if you're brave and you've backed up first. * The opensim.ini line is physics = BulletDotNETPlugin
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/AssemblyInfo.cs58
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs1104
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPlugin.cs65
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPluginStructs.cs33
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs2131
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs642
6 files changed, 4033 insertions, 0 deletions
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/AssemblyInfo.cs
new file mode 100644
index 0000000..d10c8ad
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletDotNETPlugin/AssemblyInfo.cs
@@ -0,0 +1,58 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim 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
new file mode 100644
index 0000000..6791671
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
@@ -0,0 +1,1104 @@
1using System;
2using System.Reflection;
3using BulletDotNET;
4using OpenMetaverse;
5using OpenSim.Framework;
6using OpenSim.Region.Physics.Manager;
7using log4net;
8
9namespace OpenSim.Region.Physics.BulletDotNETPlugin
10{
11 public class BulletDotNETCharacter : PhysicsActor
12 {
13 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
14
15 public btRigidBody Body;
16 public btCollisionShape Shell;
17 public btVector3 tempVector1;
18 public btVector3 tempVector2;
19 public btVector3 tempVector3;
20 public btVector3 tempVector4;
21
22 public btVector3 tempVector5RayCast;
23 public btVector3 tempVector6RayCast;
24 public btVector3 tempVector7RayCast;
25
26 public btQuaternion tempQuat1;
27 public btTransform tempTrans1;
28
29 public ClosestNotMeRayResultCallback ClosestCastResult;
30 private btTransform m_bodyTransform;
31 private btVector3 m_bodyPosition;
32 private btVector3 m_CapsuleOrientationAxis;
33 private btQuaternion m_bodyOrientation;
34 private btDefaultMotionState m_bodyMotionState;
35 private btGeneric6DofConstraint m_aMotor;
36 private PhysicsVector m_movementComparision;
37 private PhysicsVector m_position;
38 private PhysicsVector m_zeroPosition;
39 private bool m_zeroFlag = false;
40 private bool m_lastUpdateSent = false;
41 private PhysicsVector m_velocity;
42 private PhysicsVector m_target_velocity;
43 private PhysicsVector m_acceleration;
44 private PhysicsVector m_rotationalVelocity;
45 private bool m_pidControllerActive = true;
46 public float PID_D = 80.0f;
47 public float PID_P = 90.0f;
48 public float CAPSULE_RADIUS = 0.37f;
49 public float CAPSULE_LENGTH = 2.140599f;
50 public float heightFudgeFactor = 0.52f;
51 public float walkDivisor = 1.3f;
52 public float runDivisor = 0.8f;
53 private float m_mass = 80f;
54 public float m_density = 60f;
55 private bool m_flying = false;
56 private bool m_iscolliding = false;
57 private bool m_iscollidingGround = false;
58 private bool m_wascolliding = false;
59 private bool m_wascollidingGround = false;
60 private bool m_iscollidingObj = false;
61 private bool m_alwaysRun = false;
62 private bool m_hackSentFall = false;
63 private bool m_hackSentFly = false;
64 public uint m_localID = 0;
65 public bool m_returnCollisions = false;
66 // taints and their non-tainted counterparts
67 public bool m_isPhysical = false; // the current physical status
68 public bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing)
69 private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes.
70 private bool m_taintRemove = false;
71 private bool m_taintedPosition = false;
72 private PhysicsVector m_taintedPosition_value;
73 private PhysicsVector m_taintedForce;
74
75 private float m_buoyancy = 0f;
76
77 // private CollisionLocker ode;
78
79 private string m_name = String.Empty;
80
81 private bool[] m_colliderarr = new bool[11];
82 private bool[] m_colliderGroundarr = new bool[11];
83
84
85
86 private BulletDotNETScene m_parent_scene;
87
88 public int m_eventsubscription = 0;
89 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
90
91 public BulletDotNETCharacter(string avName, BulletDotNETScene parent_scene, PhysicsVector pos, PhysicsVector size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor)
92 {
93 m_taintedForce = new PhysicsVector();
94 m_velocity = new PhysicsVector();
95 m_target_velocity = new PhysicsVector();
96 m_position = pos;
97 m_zeroPosition = new PhysicsVector(pos.X, pos.Y, pos.Z); // this is a class, not a struct. Must make new, or m_zeroPosition will == position regardless
98 m_acceleration = new PhysicsVector();
99 m_parent_scene = parent_scene;
100 PID_D = pid_d;
101 PID_P = pid_p;
102 CAPSULE_RADIUS = capsule_radius;
103 m_density = density;
104 heightFudgeFactor = height_fudge_factor;
105 walkDivisor = walk_divisor;
106 runDivisor = rundivisor;
107
108 for (int i = 0; i < 11; i++)
109 {
110 m_colliderarr[i] = false;
111 }
112 for (int i = 0; i < 11; i++)
113 {
114 m_colliderGroundarr[i] = false;
115 }
116 CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
117 m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
118 m_isPhysical = false; // current status: no ODE information exists
119 m_tainted_isPhysical = true; // new tainted status: need to create ODE information
120
121 m_parent_scene.AddPhysicsActorTaint(this);
122
123 m_name = avName;
124 tempVector1 = new btVector3(0, 0, 0);
125 tempVector2 = new btVector3(0, 0, 0);
126 tempVector3 = new btVector3(0, 0, 0);
127 tempVector4 = new btVector3(0, 0, 0);
128
129 tempVector5RayCast = new btVector3(0, 0, 0);
130 tempVector6RayCast = new btVector3(0, 0, 0);
131 tempVector7RayCast = new btVector3(0, 0, 0);
132
133 tempQuat1 = new btQuaternion(0, 0, 0, 1);
134 tempTrans1 = new btTransform(tempQuat1, tempVector1);
135 m_movementComparision = new PhysicsVector(0, 0, 0);
136 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
137
138
139
140 }
141
142 /// <summary>
143 /// This creates the Avatar's physical Surrogate at the position supplied
144 /// </summary>
145 /// <param name="npositionX"></param>
146 /// <param name="npositionY"></param>
147 /// <param name="npositionZ"></param>
148
149 // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
150 // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
151 // place that is safe to call this routine AvatarGeomAndBodyCreation.
152 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
153 {
154
155 if (CAPSULE_LENGTH <= 0)
156 {
157 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
158 CAPSULE_LENGTH = 0.01f;
159
160 }
161
162 if (CAPSULE_RADIUS <= 0)
163 {
164 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
165 CAPSULE_RADIUS = 0.01f;
166
167 }
168
169 Shell = new btCapsuleShape(CAPSULE_RADIUS, CAPSULE_LENGTH);
170
171 if (m_bodyPosition == null)
172 m_bodyPosition = new btVector3(npositionX, npositionY, npositionZ);
173
174 m_bodyPosition.setValue(npositionX, npositionY, npositionZ);
175
176 if (m_bodyOrientation == null)
177 m_bodyOrientation = new btQuaternion(m_CapsuleOrientationAxis, (Utils.DEG_TO_RAD * 90));
178
179 if (m_bodyTransform == null)
180 m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
181 else
182 {
183 m_bodyTransform.Dispose();
184 m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
185 }
186
187 if (m_bodyMotionState == null)
188 m_bodyMotionState = new btDefaultMotionState(m_bodyTransform);
189 else
190 m_bodyMotionState.setWorldTransform(m_bodyTransform);
191
192 m_mass = Mass;
193
194 Body = new btRigidBody(m_mass, m_bodyMotionState, Shell);
195 Body.setUserPointer(new IntPtr((int)Body.Handle));
196
197 if (ClosestCastResult != null)
198 ClosestCastResult.Dispose();
199 ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
200
201 m_parent_scene.AddRigidBody(Body);
202 Body.setActivationState(4);
203 if (m_aMotor != null)
204 {
205 if (m_aMotor.Handle != IntPtr.Zero)
206 {
207 m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
208 m_aMotor.Dispose();
209 }
210 m_aMotor = null;
211 }
212
213 m_aMotor = new btGeneric6DofConstraint(Body, m_parent_scene.TerrainBody,
214 m_parent_scene.TransZero,
215 m_parent_scene.TransZero, false);
216 m_aMotor.setAngularLowerLimit(m_parent_scene.VectorZero);
217 m_aMotor.setAngularUpperLimit(m_parent_scene.VectorZero);
218
219
220 }
221 public void Remove()
222 {
223 m_taintRemove = true;
224 }
225 public override bool Stopped
226 {
227 get { return m_zeroFlag; }
228 }
229
230 public override PhysicsVector Size
231 {
232 get { return new PhysicsVector(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
233 set
234 {
235 m_pidControllerActive = true;
236
237 PhysicsVector SetSize = value;
238 m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
239 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
240
241 Velocity = new PhysicsVector(0f, 0f, 0f);
242
243 m_parent_scene.AddPhysicsActorTaint(this);
244 }
245 }
246
247 /// <summary>
248 /// turn the PID controller on or off.
249 /// The PID Controller will turn on all by itself in many situations
250 /// </summary>
251 /// <param name="status"></param>
252 public void SetPidStatus(bool status)
253 {
254 m_pidControllerActive = status;
255 }
256
257 public override PrimitiveBaseShape Shape
258 {
259 set { return; }
260 }
261
262 public override uint LocalID
263 {
264 set { m_localID = value; }
265 }
266
267 public override bool Grabbed
268 {
269 set { return; }
270 }
271
272 public override bool Selected
273 {
274 set { return; }
275 }
276
277
278 public override void CrossingFailure()
279 {
280
281 }
282
283 public override void link(PhysicsActor obj)
284 {
285
286 }
287
288 public override void delink()
289 {
290
291 }
292
293 public override void LockAngularMotion(PhysicsVector axis)
294 {
295
296 }
297
298 public override PhysicsVector Position
299 {
300 get { return m_position; }
301 set
302 {
303 m_taintedPosition_value = value;
304 m_position = value;
305 m_taintedPosition = true;
306 }
307 }
308
309 public override float Mass
310 {
311 get
312 {
313 float AVvolume = (float)(Math.PI * Math.Pow(CAPSULE_RADIUS, 2) * CAPSULE_LENGTH);
314 return m_density * AVvolume;
315 }
316 }
317
318 public override PhysicsVector Force
319 {
320 get { return new PhysicsVector(m_target_velocity.X, m_target_velocity.Y, m_target_velocity.Z); }
321 set { return; }
322 }
323
324 public override int VehicleType
325 {
326 get { return 0; }
327 set { return; }
328 }
329
330 public override void VehicleFloatParam(int param, float value)
331 {
332
333 }
334
335 public override void VehicleVectorParam(int param, PhysicsVector value)
336 {
337
338 }
339
340 public override void VehicleRotationParam(int param, Quaternion rotation)
341 {
342
343 }
344
345 public override void SetVolumeDetect(int param)
346 {
347
348 }
349
350 public override PhysicsVector GeometricCenter
351 {
352 get { return PhysicsVector.Zero; }
353 }
354
355 public override PhysicsVector CenterOfMass
356 {
357 get { return PhysicsVector.Zero; }
358 }
359
360 public override PhysicsVector Velocity
361 {
362 get
363 {
364 // There's a problem with PhysicsVector.Zero! Don't Use it Here!
365 if (m_zeroFlag)
366 return new PhysicsVector(0f, 0f, 0f);
367 m_lastUpdateSent = false;
368 return m_velocity;
369 }
370 set
371 {
372 m_pidControllerActive = true;
373 m_target_velocity = value;
374 }
375 }
376
377 public override PhysicsVector Torque
378 {
379 get { return PhysicsVector.Zero; }
380 set { return; }
381 }
382
383 public override float CollisionScore
384 {
385 get { return 0f; }
386 set { }
387 }
388
389 public override PhysicsVector Acceleration
390 {
391 get { return m_acceleration; }
392 }
393
394 public override Quaternion Orientation
395 {
396 get { return Quaternion.Identity; }
397 set
398 {
399
400 }
401 }
402
403 public override int PhysicsActorType
404 {
405 get { return (int)ActorTypes.Agent; }
406 set { return; }
407 }
408
409 public override bool IsPhysical
410 {
411 get { return false; }
412 set { return; }
413 }
414
415 public override bool Flying
416 {
417 get { return m_flying; }
418 set { m_flying = value; }
419 }
420
421 public override bool SetAlwaysRun
422 {
423 get { return m_alwaysRun; }
424 set { m_alwaysRun = value; }
425 }
426
427
428 public override bool ThrottleUpdates
429 {
430 get { return false; }
431 set { return; }
432 }
433
434 /// <summary>
435 /// Returns if the avatar is colliding in general.
436 /// This includes the ground and objects and avatar.
437 /// </summary>
438 public override bool IsColliding
439 {
440 get { return m_iscolliding; }
441 set
442 {
443 int i;
444 int truecount = 0;
445 int falsecount = 0;
446
447 if (m_colliderarr.Length >= 10)
448 {
449 for (i = 0; i < 10; i++)
450 {
451 m_colliderarr[i] = m_colliderarr[i + 1];
452 }
453 }
454 m_colliderarr[10] = value;
455
456 for (i = 0; i < 11; i++)
457 {
458 if (m_colliderarr[i])
459 {
460 truecount++;
461 }
462 else
463 {
464 falsecount++;
465 }
466 }
467
468 // Equal truecounts and false counts means we're colliding with something.
469 m_log.DebugFormat("[PHYSICS]: TrueCount:{0}, FalseCount:{1}",truecount,falsecount);
470 if (falsecount > 1.2 * truecount)
471 {
472 m_iscolliding = false;
473 }
474 else
475 {
476 m_iscolliding = true;
477 }
478 if (m_wascolliding != m_iscolliding)
479 {
480 //base.SendCollisionUpdate(new CollisionEventUpdate());
481 }
482 m_wascolliding = m_iscolliding;
483 }
484 }
485
486 /// <summary>
487 /// Returns if an avatar is colliding with the ground
488 /// </summary>
489 public override bool CollidingGround
490 {
491 get { return m_iscollidingGround; }
492 set
493 {
494 // Collisions against the ground are not really reliable
495 // So, to get a consistant value we have to average the current result over time
496 // Currently we use 1 second = 10 calls to this.
497 int i;
498 int truecount = 0;
499 int falsecount = 0;
500
501 if (m_colliderGroundarr.Length >= 10)
502 {
503 for (i = 0; i < 10; i++)
504 {
505 m_colliderGroundarr[i] = m_colliderGroundarr[i + 1];
506 }
507 }
508 m_colliderGroundarr[10] = value;
509
510 for (i = 0; i < 11; i++)
511 {
512 if (m_colliderGroundarr[i])
513 {
514 truecount++;
515 }
516 else
517 {
518 falsecount++;
519 }
520 }
521
522 // Equal truecounts and false counts means we're colliding with something.
523
524 if (falsecount > 1.2 * truecount)
525 {
526 m_iscollidingGround = false;
527 }
528 else
529 {
530 m_iscollidingGround = true;
531 }
532 if (m_wascollidingGround != m_iscollidingGround)
533 {
534 //base.SendCollisionUpdate(new CollisionEventUpdate());
535 }
536 m_wascollidingGround = m_iscollidingGround;
537 }
538 }
539
540 /// <summary>
541 /// Returns if the avatar is colliding with an object
542 /// </summary>
543 public override bool CollidingObj
544 {
545 get { return m_iscollidingObj; }
546 set
547 {
548 m_iscollidingObj = value;
549 if (value)
550 m_pidControllerActive = false;
551 else
552 m_pidControllerActive = true;
553 }
554 }
555
556
557 public override bool FloatOnWater
558 {
559 set { return; }
560 }
561
562 public override PhysicsVector RotationalVelocity
563 {
564 get { return m_rotationalVelocity; }
565 set { m_rotationalVelocity = value; }
566 }
567
568 public override bool Kinematic
569 {
570 get { return false; }
571 set { }
572 }
573
574 public override float Buoyancy
575 {
576 get { return m_buoyancy; }
577 set { m_buoyancy = value; }
578 }
579
580 public override PhysicsVector PIDTarget { set { return; } }
581 public override bool PIDActive { set { return; } }
582 public override float PIDTau { set { return; } }
583
584 public override bool PIDHoverActive
585 {
586 set { return; }
587 }
588
589 public override float PIDHoverHeight
590 {
591 set { return; }
592 }
593
594 public override PIDHoverType PIDHoverType
595 {
596 set { return; }
597 }
598
599 public override float PIDHoverTau
600 {
601 set { return; }
602 }
603
604 /// <summary>
605 /// Adds the force supplied to the Target Velocity
606 /// The PID controller takes this target velocity and tries to make it a reality
607 /// </summary>
608 /// <param name="force"></param>
609 /// <param name="pushforce">Is this a push by a script?</param>
610 public override void AddForce(PhysicsVector force, bool pushforce)
611 {
612 if (pushforce)
613 {
614 m_pidControllerActive = false;
615 force *= 100f;
616 doForce(force, false);
617 //System.Console.WriteLine("Push!");
618 //_target_velocity.X += force.X;
619 // _target_velocity.Y += force.Y;
620 //_target_velocity.Z += force.Z;
621 }
622 else
623 {
624 m_pidControllerActive = true;
625 m_target_velocity.X += force.X;
626 m_target_velocity.Y += force.Y;
627 m_target_velocity.Z += force.Z;
628 }
629 //m_lastUpdateSent = false;
630 }
631
632 public void doForce(PhysicsVector force, bool now)
633 {
634
635 tempVector3.setValue(force.X, force.Y, force.Z);
636 if (now)
637 {
638 Body.applyCentralForce(tempVector3);
639 }
640 else
641 {
642 m_taintedForce += force;
643 m_parent_scene.AddPhysicsActorTaint(this);
644 }
645 }
646
647 public void doImpulse(PhysicsVector force, bool now)
648 {
649
650 tempVector3.setValue(force.X, force.Y, force.Z);
651 if (now)
652 {
653 Body.applyCentralImpulse(tempVector3);
654 }
655 else
656 {
657 m_taintedForce += force;
658 m_parent_scene.AddPhysicsActorTaint(this);
659 }
660 }
661
662 public override void AddAngularForce(PhysicsVector force, bool pushforce)
663 {
664
665 }
666
667 public override void SetMomentum(PhysicsVector momentum)
668 {
669
670 }
671
672 public override void SubscribeEvents(int ms)
673 {
674 m_eventsubscription = ms;
675 m_parent_scene.addCollisionEventReporting(this);
676 }
677
678 public override void UnSubscribeEvents()
679 {
680 m_parent_scene.remCollisionEventReporting(this);
681 m_eventsubscription = 0;
682 }
683
684 public override bool SubscribedEvents()
685 {
686 if (m_eventsubscription > 0)
687 return true;
688 return false;
689 }
690
691 internal void Dispose()
692 {
693 if (Body.isInWorld())
694 m_parent_scene.removeFromWorld(Body);
695
696 if (m_aMotor.Handle != IntPtr.Zero)
697 m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
698
699 m_aMotor.Dispose(); m_aMotor = null;
700 ClosestCastResult.Dispose(); ClosestCastResult = null;
701 Body.Dispose(); Body = null;
702 Shell.Dispose(); Shell = null;
703 tempQuat1.Dispose();
704 tempTrans1.Dispose();
705 tempVector1.Dispose();
706 tempVector2.Dispose();
707 tempVector3.Dispose();
708 tempVector4.Dispose();
709 tempVector5RayCast.Dispose();
710 tempVector6RayCast.Dispose();
711
712 }
713
714 public void ProcessTaints(float timestep)
715 {
716
717 if (m_tainted_isPhysical != m_isPhysical)
718 {
719 if (m_tainted_isPhysical)
720 {
721 // Create avatar capsule and related ODE data
722 if (!(Shell == null && Body == null))
723 {
724 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
725 + (Shell != null ? "Shell " : "")
726 + (Body != null ? "Body " : ""));
727 }
728 AvatarGeomAndBodyCreation(m_position.X, m_position.Y, m_position.Z);
729
730
731 }
732 else
733 {
734 // destroy avatar capsule and related ODE data
735
736 Dispose();
737 tempVector1 = new btVector3(0, 0, 0);
738 tempVector2 = new btVector3(0, 0, 0);
739 tempVector3 = new btVector3(0, 0, 0);
740 tempVector4 = new btVector3(0, 0, 0);
741
742 tempVector5RayCast = new btVector3(0, 0, 0);
743 tempVector6RayCast = new btVector3(0, 0, 0);
744 tempVector7RayCast = new btVector3(0, 0, 0);
745
746 tempQuat1 = new btQuaternion(0, 0, 0, 1);
747 tempTrans1 = new btTransform(tempQuat1, tempVector1);
748 m_movementComparision = new PhysicsVector(0, 0, 0);
749 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
750 }
751
752 m_isPhysical = m_tainted_isPhysical;
753 }
754
755 if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH)
756 {
757 if (Body != null)
758 {
759
760 m_pidControllerActive = true;
761 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
762 //d.JointDestroy(Amotor);
763 float prevCapsule = CAPSULE_LENGTH;
764 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
765 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
766 Dispose();
767
768 tempVector1 = new btVector3(0, 0, 0);
769 tempVector2 = new btVector3(0, 0, 0);
770 tempVector3 = new btVector3(0, 0, 0);
771 tempVector4 = new btVector3(0, 0, 0);
772
773 tempVector5RayCast = new btVector3(0, 0, 0);
774 tempVector6RayCast = new btVector3(0, 0, 0);
775 tempVector7RayCast = new btVector3(0, 0, 0);
776
777 tempQuat1 = new btQuaternion(0, 0, 0, 1);
778 tempTrans1 = new btTransform(tempQuat1, tempVector1);
779 m_movementComparision = new PhysicsVector(0, 0, 0);
780 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
781
782 AvatarGeomAndBodyCreation(m_position.X, m_position.Y,
783 m_position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2));
784 Velocity = new PhysicsVector(0f, 0f, 0f);
785
786 }
787 else
788 {
789 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
790 + (Shell == null ? "Shell " : "")
791 + (Body == null ? "Body " : ""));
792 }
793 }
794 if (m_taintRemove)
795 {
796 Dispose();
797 }
798 }
799
800 /// <summary>
801 /// Called from Simulate
802 /// This is the avatar's movement control + PID Controller
803 /// </summary>
804 /// <param name="timeStep"></param>
805 public void Move(float timeStep)
806 {
807 // no lock; for now it's only called from within Simulate()
808
809 // If the PID Controller isn't active then we set our force
810 // calculating base velocity to the current position
811 if (Body == null)
812 return;
813 tempTrans1.Dispose();
814 tempTrans1 = Body.getInterpolationWorldTransform();
815 tempVector1.Dispose();
816 tempVector1 = tempTrans1.getOrigin();
817 tempVector2.Dispose();
818 tempVector2 = Body.getInterpolationLinearVelocity();
819
820 if (m_pidControllerActive == false)
821 {
822 m_zeroPosition.X = tempVector1.getX();
823 m_zeroPosition.Y = tempVector1.getY();
824 m_zeroPosition.Z = tempVector1.getZ();
825 }
826 //PidStatus = true;
827
828 PhysicsVector vec = new PhysicsVector();
829
830 PhysicsVector vel = new PhysicsVector(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
831
832 float movementdivisor = 1f;
833
834 if (!m_alwaysRun)
835 {
836 movementdivisor = walkDivisor;
837 }
838 else
839 {
840 movementdivisor = runDivisor;
841 }
842
843 // if velocity is zero, use position control; otherwise, velocity control
844 if (m_target_velocity.X == 0.0f && m_target_velocity.Y == 0.0f && m_target_velocity.Z == 0.0f && m_iscolliding)
845 {
846 // keep track of where we stopped. No more slippin' & slidin'
847 if (!m_zeroFlag)
848 {
849 m_zeroFlag = true;
850 m_zeroPosition.X = tempVector1.getX();
851 m_zeroPosition.Y = tempVector1.getY();
852 m_zeroPosition.Z = tempVector1.getZ();
853 }
854 if (m_pidControllerActive)
855 {
856 // We only want to deactivate the PID Controller if we think we want to have our surrogate
857 // react to the physics scene by moving it's position.
858 // Avatar to Avatar collisions
859 // Prim to avatar collisions
860
861 PhysicsVector pos = new PhysicsVector(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
862 vec.X = (m_target_velocity.X - vel.X) * (PID_D) + (m_zeroPosition.X - pos.X) * (PID_P * 2);
863 vec.Y = (m_target_velocity.Y - vel.Y) * (PID_D) + (m_zeroPosition.Y - pos.Y) * (PID_P * 2);
864 if (m_flying)
865 {
866 vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D) + (m_zeroPosition.Z - pos.Z) * PID_P;
867 }
868 }
869 //PidStatus = true;
870 }
871 else
872 {
873 m_pidControllerActive = true;
874 m_zeroFlag = false;
875 if (m_iscolliding && !m_flying)
876 {
877 // We're standing on something
878 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
879 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
880 }
881 else if (m_iscolliding && m_flying)
882 {
883 // We're flying and colliding with something
884 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
885 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
886 }
887 else if (!m_iscolliding && m_flying)
888 {
889 // we're in mid air suspended
890 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
891 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);
892 }
893
894 if (m_iscolliding && !m_flying && m_target_velocity.Z > 0.0f)
895 {
896 // We're colliding with something and we're not flying but we're moving
897 // This means we're walking or running.
898 PhysicsVector pos = new PhysicsVector(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
899 vec.Z = (m_target_velocity.Z - vel.Z) * PID_D + (m_zeroPosition.Z - pos.Z) * PID_P;
900 if (m_target_velocity.X > 0)
901 {
902 vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
903 }
904 if (m_target_velocity.Y > 0)
905 {
906 vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
907 }
908 }
909 else if (!m_iscolliding && !m_flying)
910 {
911 // we're not colliding and we're not flying so that means we're falling!
912 // m_iscolliding includes collisions with the ground.
913
914 // d.Vector3 pos = d.BodyGetPosition(Body);
915 if (m_target_velocity.X > 0)
916 {
917 vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
918 }
919 if (m_target_velocity.Y > 0)
920 {
921 vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
922 }
923 }
924
925
926 if (m_flying)
927 {
928 vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D);
929 }
930 }
931 if (m_flying)
932 {
933 //vec.Z += ((-1 * m_parent_scene.gravityz) * m_mass);
934 }
935 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))))
936 {
937 Body.setFriction(0.001f);
938 //m_log.DebugFormat("[PHYSICS]: Avatar force applied: {0}, Target:{1}", vec.ToString(), m_target_velocity.ToString());
939 }
940
941 if (Body != null)
942 {
943 int activationstate = Body.getActivationState();
944 if (activationstate == 0)
945 {
946 Body.forceActivationState(1);
947 }
948
949
950 }
951 doImpulse(vec, true);
952 }
953
954 /// <summary>
955 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
956 /// </summary>
957 public void UpdatePositionAndVelocity()
958 {
959 if (Body == null)
960 return;
961 //int val = Environment.TickCount;
962 CheckIfStandingOnObject();
963 //m_log.DebugFormat("time:{0}", Environment.TickCount - val);
964
965 //IsColliding = Body.checkCollideWith(m_parent_scene.TerrainBody);
966
967 tempTrans1.Dispose();
968 tempTrans1 = Body.getInterpolationWorldTransform();
969 tempVector1.Dispose();
970 tempVector1 = tempTrans1.getOrigin();
971 tempVector2.Dispose();
972 tempVector2 = Body.getInterpolationLinearVelocity();
973
974 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
975 PhysicsVector vec = new PhysicsVector(tempVector1.getX(),tempVector1.getY(),tempVector1.getZ());
976
977 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
978 if (vec.X < 0.0f) vec.X = 0.0f;
979 if (vec.Y < 0.0f) vec.Y = 0.0f;
980 if (vec.X > (int)Constants.RegionSize - 0.2f) vec.X = (int)Constants.RegionSize - 0.2f;
981 if (vec.Y > (int)Constants.RegionSize - 0.2f) vec.Y = (int)Constants.RegionSize - 0.2f;
982
983 m_position.X = vec.X;
984 m_position.Y = vec.Y;
985 m_position.Z = vec.Z;
986
987 // Did we move last? = zeroflag
988 // This helps keep us from sliding all over
989
990 if (m_zeroFlag)
991 {
992 m_velocity.X = 0.0f;
993 m_velocity.Y = 0.0f;
994 m_velocity.Z = 0.0f;
995
996 // Did we send out the 'stopped' message?
997 if (!m_lastUpdateSent)
998 {
999 m_lastUpdateSent = true;
1000 //base.RequestPhysicsterseUpdate();
1001
1002 }
1003 }
1004 else
1005 {
1006 m_lastUpdateSent = false;
1007 vec = new PhysicsVector(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
1008 m_velocity.X = (vec.X);
1009 m_velocity.Y = (vec.Y);
1010
1011 m_velocity.Z = (vec.Z);
1012
1013 if (m_velocity.Z < -6 && !m_hackSentFall)
1014 {
1015 m_hackSentFall = true;
1016 m_pidControllerActive = false;
1017 }
1018 else if (m_flying && !m_hackSentFly)
1019 {
1020 //m_hackSentFly = true;
1021 //base.SendCollisionUpdate(new CollisionEventUpdate());
1022 }
1023 else
1024 {
1025 m_hackSentFly = false;
1026 m_hackSentFall = false;
1027 }
1028 }
1029 if (Body != null)
1030 {
1031 if (Body.getFriction() < 0.9f)
1032 Body.setFriction(0.9f);
1033 }
1034 //if (Body != null)
1035 // Body.clearForces();
1036 }
1037
1038 public void CheckIfStandingOnObject()
1039 {
1040
1041 float capsuleHalfHeight = ((CAPSULE_LENGTH + 2*CAPSULE_RADIUS)*0.5f);
1042
1043 tempVector5RayCast.setValue(m_position.X, m_position.Y, m_position.Z);
1044 tempVector6RayCast.setValue(m_position.X, m_position.Y, m_position.Z - 1 * capsuleHalfHeight * 1.1f);
1045
1046
1047 ClosestCastResult.Dispose();
1048 ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
1049
1050 try
1051 {
1052 m_parent_scene.getBulletWorld().rayTest(tempVector5RayCast, tempVector6RayCast, ClosestCastResult);
1053 }
1054 catch (AccessViolationException)
1055 {
1056 m_log.Debug("BAD!");
1057 }
1058 if (ClosestCastResult.hasHit())
1059 {
1060
1061 if (tempVector7RayCast != null)
1062 tempVector7RayCast.Dispose();
1063
1064 //tempVector7RayCast = ClosestCastResult.getHitPointWorld();
1065
1066 /*if (tempVector7RayCast == null) // null == no result also
1067 {
1068 CollidingObj = false;
1069 IsColliding = false;
1070 CollidingGround = false;
1071
1072 return;
1073 }
1074 float zVal = tempVector7RayCast.getZ();
1075 if (zVal != 0)
1076 m_log.Debug("[PHYSICS]: HAAAA");
1077 if (zVal < m_position.Z && zVal > ((CAPSULE_LENGTH + 2 * CAPSULE_RADIUS) *0.5f))
1078 {
1079 CollidingObj = true;
1080 IsColliding = true;
1081 }
1082 else
1083 {
1084 CollidingObj = false;
1085 IsColliding = false;
1086 CollidingGround = false;
1087 }*/
1088
1089 //height+2*radius = capsule full length
1090 //CollidingObj = true;
1091 //IsColliding = true;
1092 m_iscolliding = true;
1093 }
1094 else
1095 {
1096 //CollidingObj = false;
1097 //IsColliding = false;
1098 //CollidingGround = false;
1099 m_iscolliding = false;
1100 }
1101 }
1102 }
1103
1104}
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPlugin.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPlugin.cs
new file mode 100644
index 0000000..262e5c3
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPlugin.cs
@@ -0,0 +1,65 @@
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
new file mode 100644
index 0000000..382f445
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPluginStructs.cs
@@ -0,0 +1,33 @@
1using System;
2
3public enum StatusIndicators : int
4{
5 Generic = 0,
6 Start = 1,
7 End = 2
8}
9
10public struct sCollisionData
11{
12 public uint ColliderLocalId;
13 public uint CollidedWithLocalId;
14 public int NumberOfCollisions;
15 public int CollisionType;
16 public int StatusIndicator;
17 public int lastframe;
18}
19
20[Flags]
21public enum CollisionCategories : int
22{
23 Disabled = 0,
24 Geom = 0x00000001,
25 Body = 0x00000002,
26 Space = 0x00000004,
27 Character = 0x00000008,
28 Land = 0x00000010,
29 Water = 0x00000020,
30 Wind = 0x00000040,
31 Sensor = 0x00000080,
32 Selected = 0x00000100
33} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs
new file mode 100644
index 0000000..3e26456
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs
@@ -0,0 +1,2131 @@
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 OpenSim 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 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using System.Runtime.InteropServices;
31using System.Threading;
32using log4net;
33using OpenMetaverse;
34using BulletDotNET;
35using OpenSim.Framework;
36using OpenSim.Region.Physics.Manager;
37
38namespace OpenSim.Region.Physics.BulletDotNETPlugin
39{
40 public class BulletDotNETPrim : PhysicsActor
41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 private PhysicsVector _position;
45 private PhysicsVector _velocity;
46 private PhysicsVector _torque = new PhysicsVector(0, 0, 0);
47 private PhysicsVector m_lastVelocity = new PhysicsVector(0.0f, 0.0f, 0.0f);
48 private PhysicsVector m_lastposition = new PhysicsVector(0.0f, 0.0f, 0.0f);
49 private Quaternion m_lastorientation = new Quaternion();
50 private PhysicsVector m_rotationalVelocity;
51 private PhysicsVector _size;
52 private PhysicsVector _acceleration;
53 // private d.Vector3 _zeroPosition = new d.Vector3(0.0f, 0.0f, 0.0f);
54 private Quaternion _orientation;
55 private PhysicsVector m_taintposition;
56 private PhysicsVector m_taintsize;
57 private PhysicsVector m_taintVelocity = new PhysicsVector(0, 0, 0);
58 private PhysicsVector m_taintTorque = new PhysicsVector(0, 0, 0);
59 private Quaternion m_taintrot;
60 private PhysicsVector m_angularlock = new PhysicsVector(1f, 1f, 1f);
61 private PhysicsVector m_taintAngularLock = new PhysicsVector(1f, 1f, 1f);
62 private btGeneric6DofConstraint Amotor;
63
64 private PhysicsVector m_PIDTarget = new PhysicsVector(0, 0, 0);
65 private float m_PIDTau = 0f;
66 private float m_PIDHoverHeight = 0f;
67 private float m_PIDHoverTau = 0f;
68 private bool m_useHoverPID = false;
69 private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
70 private float m_targetHoverHeight = 0f;
71 private float m_groundHeight = 0f;
72 private float m_waterHeight = 0f;
73 private float PID_D = 35f;
74 private float PID_G = 25f;
75 private float m_tensor = 5f;
76 private int body_autodisable_frames = 20;
77 private IMesh primMesh = null;
78
79 private bool m_usePID = false;
80
81
82 private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
83 | CollisionCategories.Space
84 | CollisionCategories.Body
85 | CollisionCategories.Character
86 );
87
88 private bool m_taintshape = false;
89 private bool m_taintPhysics = false;
90 private bool m_collidesLand = true;
91 private bool m_collidesWater = false;
92 public bool m_returnCollisions = false;
93
94 // Default we're a Geometry
95 private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
96
97 // Default, Collide with Other Geometries, spaces and Bodies
98 private CollisionCategories m_collisionFlags = m_default_collisionFlags;
99
100 public bool m_taintremove = false;
101 public bool m_taintdisable = false;
102 public bool m_disabled = false;
103 public bool m_taintadd = false;
104 public bool m_taintselected = false;
105 public bool m_taintCollidesWater = false;
106
107 public uint m_localID = 0;
108
109 //public GCHandle gc;
110 private CollisionLocker ode;
111
112 private bool m_taintforce = false;
113 private bool m_taintaddangularforce = false;
114 private PhysicsVector m_force = new PhysicsVector(0.0f, 0.0f, 0.0f);
115 private List<PhysicsVector> m_forcelist = new List<PhysicsVector>();
116 private List<PhysicsVector> m_angularforcelist = new List<PhysicsVector>();
117
118 private IMesh _mesh;
119 private PrimitiveBaseShape _pbs;
120 private BulletDotNETScene _parent_scene;
121 public btCollisionShape prim_geom;
122 public IntPtr _triMeshData;
123
124 private PhysicsActor _parent = null;
125 private PhysicsActor m_taintparent = null;
126
127 private List<BulletDotNETPrim> childrenPrim = new List<BulletDotNETPrim>();
128
129 private bool iscolliding = false;
130 private bool m_isphysical = false;
131 private bool m_isSelected = false;
132
133 internal bool m_isVolumeDetect = false; // If true, this prim only detects collisions but doesn't collide actively
134
135 private bool m_throttleUpdates = false;
136 private int throttleCounter = 0;
137 public int m_interpenetrationcount = 0;
138 public float m_collisionscore = 0;
139 public int m_roundsUnderMotionThreshold = 0;
140 private int m_crossingfailures = 0;
141
142 public float m_buoyancy = 0f;
143
144 public bool outofBounds = false;
145 private float m_density = 10.000006836f; // Aluminum g/cm3;
146
147 public bool _zeroFlag = false;
148 private bool m_lastUpdateSent = false;
149
150
151 private String m_primName;
152 private PhysicsVector _target_velocity;
153
154 public int m_eventsubscription = 0;
155 private CollisionEventUpdate CollisionEventsThisFrame = null;
156
157 public volatile bool childPrim = false;
158
159 private btVector3 tempPosition1;
160 private btVector3 tempPosition2;
161 private btVector3 tempPosition3;
162 private btVector3 tempSize1;
163 private btVector3 tempSize2;
164 private btVector3 tempLinearVelocity1;
165 private btVector3 tempLinearVelocity2;
166 private btVector3 tempAngularVelocity1;
167 private btVector3 tempAngularVelocity2;
168 private btVector3 tempInertia1;
169 private btVector3 tempInertia2;
170 private btQuaternion tempOrientation1;
171 private btQuaternion tempOrientation2;
172 private btMotionState tempMotionState1;
173 private btMotionState tempMotionState2;
174 private btMotionState tempMotionState3;
175 private btTransform tempTransform1;
176 private btTransform tempTransform2;
177 private btTransform tempTransform3;
178 private btTransform tempTransform4;
179 private btTriangleIndexVertexArray btshapeArray;
180
181 public btRigidBody Body;
182
183 public BulletDotNETPrim(String primName, BulletDotNETScene parent_scene, PhysicsVector pos, PhysicsVector size,
184 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical)
185 {
186 tempPosition1 = new btVector3(0, 0, 0);
187 tempPosition2 = new btVector3(0, 0, 0);
188 tempPosition3 = new btVector3(0, 0, 0);
189 tempSize1 = new btVector3(0, 0, 0);
190 tempSize2 = new btVector3(0, 0, 0);
191 tempLinearVelocity1 = new btVector3(0, 0, 0);
192 tempLinearVelocity2 = new btVector3(0, 0, 0);
193 tempAngularVelocity1 = new btVector3(0, 0, 0);
194 tempAngularVelocity2 = new btVector3(0, 0, 0);
195 tempInertia1 = new btVector3(0, 0, 0);
196 tempInertia2 = new btVector3(0, 0, 0);
197 tempOrientation1 = new btQuaternion(0,0,0,1);
198 tempOrientation2 = new btQuaternion(0, 0, 0, 1);
199 _parent_scene = parent_scene;
200 tempTransform1 = new btTransform(_parent_scene.QuatIdentity, _parent_scene.VectorZero);
201 tempTransform2 = new btTransform(_parent_scene.QuatIdentity, _parent_scene.VectorZero); ;
202 tempTransform3 = new btTransform(_parent_scene.QuatIdentity, _parent_scene.VectorZero); ;
203 tempTransform4 = new btTransform(_parent_scene.QuatIdentity, _parent_scene.VectorZero); ;
204
205 tempMotionState1 = new btDefaultMotionState(_parent_scene.TransZero);
206 tempMotionState2 = new btDefaultMotionState(_parent_scene.TransZero);
207 tempMotionState3 = new btDefaultMotionState(_parent_scene.TransZero);
208
209 _target_velocity = new PhysicsVector(0, 0, 0);
210 _velocity = new PhysicsVector();
211 _position = pos;
212 m_taintposition = pos;
213 PID_D = parent_scene.bodyPIDD;
214 PID_G = parent_scene.bodyPIDG;
215 m_density = parent_scene.geomDefaultDensity;
216 m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
217 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
218
219 prim_geom = null;
220 Body = null;
221
222 if (size.X <= 0) size.X = 0.01f;
223 if (size.Y <= 0) size.Y = 0.01f;
224 if (size.Z <= 0) size.Z = 0.01f;
225
226 _size = size;
227 m_taintsize = _size;
228 _acceleration = new PhysicsVector();
229 m_rotationalVelocity = PhysicsVector.Zero;
230 _orientation = rotation;
231 m_taintrot = _orientation;
232 _mesh = mesh;
233 _pbs = pbs;
234
235 _parent_scene = parent_scene;
236
237 if (pos.Z < 0)
238 m_isphysical = false;
239 else
240 {
241 m_isphysical = pisPhysical;
242 // If we're physical, we need to be in the master space for now.
243 // linksets *should* be in a space together.. but are not currently
244 }
245 m_primName = primName;
246 m_taintadd = true;
247 _parent_scene.AddPhysicsActorTaint(this);
248
249 }
250
251 #region PhysicsActor overrides
252
253 public override bool Stopped
254 {
255 get { return _zeroFlag; }
256 }
257
258 public override PhysicsVector Size
259 {
260 get { return _size; }
261 set { _size = value; }
262 }
263
264 public override PrimitiveBaseShape Shape
265 {
266 set
267 {
268 _pbs = value;
269 m_taintshape = true;
270 }
271 }
272
273 public override uint LocalID
274 {
275 set
276 {
277 //m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
278 m_localID = value;
279 }
280 }
281
282 public override bool Grabbed
283 {
284 set { return; }
285 }
286
287 public override bool Selected
288 {
289 set
290 {
291 // This only makes the object not collidable if the object
292 // is physical or the object is modified somehow *IN THE FUTURE*
293 // without this, if an avatar selects prim, they can walk right
294 // through it while it's selected
295 m_collisionscore = 0;
296 if ((m_isphysical && !_zeroFlag) || !value)
297 {
298 m_taintselected = value;
299 _parent_scene.AddPhysicsActorTaint(this);
300 }
301 else
302 {
303 m_taintselected = value;
304 m_isSelected = value;
305 }
306 }
307 }
308
309 public override void CrossingFailure()
310 {
311 m_crossingfailures++;
312 if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds)
313 {
314 base.RaiseOutOfBounds(_position);
315 return;
316 }
317 else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds)
318 {
319 m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName);
320 }
321 }
322 public override void link(PhysicsActor obj)
323 {
324 //TODO:
325 }
326
327 public override void delink()
328 {
329 //TODO:
330 }
331
332 public override void LockAngularMotion(PhysicsVector axis)
333 {
334 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
335 m_taintAngularLock = new PhysicsVector(axis.X, axis.Y, axis.Z);
336 }
337
338 public override PhysicsVector Position
339 {
340 get { return _position; }
341
342 set
343 {
344 _position = value;
345 //m_log.Info("[PHYSICS]: " + _position.ToString());
346 }
347 }
348
349 public override float Mass
350 {
351 get { return CalculateMass(); }
352 }
353
354 public override PhysicsVector Force
355 {
356 //get { return PhysicsVector.Zero; }
357 get { return m_force; }
358 set { m_force = value; }
359 }
360
361 public override int VehicleType
362 {
363 get { return 0; }
364 set { return; }
365 }
366
367 public override void VehicleFloatParam(int param, float value)
368 {
369 //TODO:
370 }
371
372 public override void VehicleVectorParam(int param, PhysicsVector value)
373 {
374 //TODO:
375 }
376
377 public override void VehicleRotationParam(int param, Quaternion rotation)
378 {
379 //TODO:
380 }
381
382 public override void SetVolumeDetect(int param)
383 {
384 //TODO: GhostObject
385 m_isVolumeDetect = (param != 0);
386
387 }
388
389 public override PhysicsVector GeometricCenter
390 {
391 get { return PhysicsVector.Zero; }
392 }
393
394 public override PhysicsVector CenterOfMass
395 {
396 get { return PhysicsVector.Zero; }
397 }
398
399 public override PhysicsVector Velocity
400 {
401 get
402 {
403 // Averate previous velocity with the new one so
404 // client object interpolation works a 'little' better
405 PhysicsVector returnVelocity = new PhysicsVector();
406 returnVelocity.X = (m_lastVelocity.X + _velocity.X) / 2;
407 returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) / 2;
408 returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) / 2;
409 return returnVelocity;
410 }
411 set
412 {
413 _velocity = value;
414
415 m_taintVelocity = value;
416 _parent_scene.AddPhysicsActorTaint(this);
417 }
418 }
419
420 public override PhysicsVector Torque
421 {
422 get
423 {
424 if (!m_isphysical || Body.Handle == IntPtr.Zero)
425 return new PhysicsVector(0, 0, 0);
426
427 return _torque;
428 }
429
430 set
431 {
432 m_taintTorque = value;
433 _parent_scene.AddPhysicsActorTaint(this);
434 }
435 }
436
437 public override float CollisionScore
438 {
439 get { return m_collisionscore; }
440 set { m_collisionscore = value; }
441 }
442
443 public override PhysicsVector Acceleration
444 {
445 get { return _acceleration; }
446 }
447
448 public override Quaternion Orientation
449 {
450 get { return _orientation; }
451 set { _orientation = value; }
452 }
453
454 public override int PhysicsActorType
455 {
456 get { return (int)ActorTypes.Prim; }
457 set { return; }
458 }
459
460 public override bool IsPhysical
461 {
462 get { return m_isphysical; }
463 set { m_isphysical = value; }
464 }
465
466 public override bool Flying
467 {
468 // no flying prims for you
469 get { return false; }
470 set { }
471 }
472
473 public override bool SetAlwaysRun
474 {
475 get { return false; }
476 set { return; }
477 }
478
479 public override bool ThrottleUpdates
480 {
481 get { return m_throttleUpdates; }
482 set { m_throttleUpdates = value; }
483 }
484
485 public override bool IsColliding
486 {
487 get { return iscolliding; }
488 set { iscolliding = value; }
489 }
490
491 public override bool CollidingGround
492 {
493 get { return false; }
494 set { return; }
495 }
496
497 public override bool CollidingObj
498 {
499 get { return false; }
500 set { return; }
501 }
502
503 public override bool FloatOnWater
504 {
505 set
506 {
507 m_taintCollidesWater = value;
508 _parent_scene.AddPhysicsActorTaint(this);
509 }
510 }
511
512 public override PhysicsVector RotationalVelocity
513 {
514 get
515 {
516 PhysicsVector pv = new PhysicsVector(0, 0, 0);
517 if (_zeroFlag)
518 return pv;
519 m_lastUpdateSent = false;
520
521 if (m_rotationalVelocity.IsIdentical(pv, 0.2f))
522 return pv;
523
524 return m_rotationalVelocity;
525 }
526 set { m_rotationalVelocity = value; }
527 }
528
529 public override bool Kinematic
530 {
531 get { return false; }
532 set { }
533 }
534
535 public override float Buoyancy
536 {
537 get { return m_buoyancy; }
538 set { m_buoyancy = value; }
539 }
540
541 public override PhysicsVector PIDTarget { set { m_PIDTarget = value; ; } }
542 public override bool PIDActive { set { m_usePID = value; } }
543 public override float PIDTau { set { m_PIDTau = value; } }
544
545 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
546 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
547 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
548 public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
549
550
551 public override void AddForce(PhysicsVector force, bool pushforce)
552 {
553 m_forcelist.Add(force);
554 m_taintforce = true;
555 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
556 }
557
558 public override void AddAngularForce(PhysicsVector force, bool pushforce)
559 {
560 m_angularforcelist.Add(force);
561 m_taintaddangularforce = true;
562 }
563
564 public override void SetMomentum(PhysicsVector momentum)
565 {
566 }
567
568 public override void SubscribeEvents(int ms)
569 {
570 m_eventsubscription = ms;
571 _parent_scene.addCollisionEventReporting(this);
572 }
573
574 public override void UnSubscribeEvents()
575 {
576 _parent_scene.remCollisionEventReporting(this);
577 m_eventsubscription = 0;
578 }
579
580 public override bool SubscribedEvents()
581 {
582 return (m_eventsubscription > 0);
583 }
584
585 #endregion
586
587
588
589 internal void Dispose()
590 {
591 //TODO:
592 DisposeOfBody();
593 SetCollisionShape(null);
594
595 if (tempMotionState3 != null && tempMotionState3.Handle != IntPtr.Zero)
596 {
597 tempMotionState3.Dispose();
598 tempMotionState3 = null;
599 }
600
601 if (tempMotionState2 != null && tempMotionState2.Handle != IntPtr.Zero)
602 {
603 tempMotionState2.Dispose();
604 tempMotionState2 = null;
605 }
606
607 if (tempMotionState1 != null && tempMotionState1.Handle != IntPtr.Zero)
608 {
609 tempMotionState1.Dispose();
610 tempMotionState1 = null;
611 }
612
613 if (tempTransform4 != null && tempTransform4.Handle != IntPtr.Zero)
614 {
615 tempTransform4.Dispose();
616 tempTransform4 = null;
617 }
618
619 if (tempTransform3 != null && tempTransform3.Handle != IntPtr.Zero)
620 {
621 tempTransform3.Dispose();
622 tempTransform3 = null;
623 }
624
625 if (tempTransform2 != null && tempTransform2.Handle != IntPtr.Zero)
626 {
627 tempTransform2.Dispose();
628 tempTransform2 = null;
629 }
630
631 if (tempTransform1 != null && tempTransform1.Handle != IntPtr.Zero)
632 {
633 tempTransform1.Dispose();
634 tempTransform1 = null;
635 }
636
637 if (tempOrientation2 != null && tempOrientation2.Handle != IntPtr.Zero)
638 {
639 tempOrientation2.Dispose();
640 tempOrientation2 = null;
641 }
642
643 if (tempOrientation1 != null && tempOrientation1.Handle != IntPtr.Zero)
644 {
645 tempOrientation1.Dispose();
646 tempOrientation1 = null;
647 }
648
649 if (tempInertia1 != null && tempInertia1.Handle != IntPtr.Zero)
650 {
651 tempInertia1.Dispose();
652 tempInertia1 = null;
653 }
654
655 if (tempInertia2 != null && tempInertia2.Handle != IntPtr.Zero)
656 {
657 tempInertia2.Dispose();
658 tempInertia1 = null;
659 }
660
661
662 if (tempAngularVelocity2 != null && tempAngularVelocity2.Handle != IntPtr.Zero)
663 {
664 tempAngularVelocity2.Dispose();
665 tempAngularVelocity2 = null;
666 }
667
668 if (tempAngularVelocity1 != null && tempAngularVelocity1.Handle != IntPtr.Zero)
669 {
670 tempAngularVelocity1.Dispose();
671 tempAngularVelocity1 = null;
672 }
673
674 if (tempLinearVelocity2 != null && tempLinearVelocity2.Handle != IntPtr.Zero)
675 {
676 tempLinearVelocity2.Dispose();
677 tempLinearVelocity2 = null;
678 }
679
680 if (tempLinearVelocity1 != null && tempLinearVelocity1.Handle != IntPtr.Zero)
681 {
682 tempLinearVelocity1.Dispose();
683 tempLinearVelocity1 = null;
684 }
685
686 if (tempSize2 != null && tempSize2.Handle != IntPtr.Zero)
687 {
688 tempSize2.Dispose();
689 tempSize2 = null;
690 }
691
692 if (tempSize1 != null && tempSize1.Handle != IntPtr.Zero)
693 {
694 tempSize1.Dispose();
695 tempSize1 = null;
696 }
697
698 if (tempPosition3 != null && tempPosition3.Handle != IntPtr.Zero)
699 {
700 tempPosition3.Dispose();
701 tempPosition3 = null;
702 }
703
704 if (tempPosition2 != null && tempPosition2.Handle != IntPtr.Zero)
705 {
706 tempPosition2.Dispose();
707 tempPosition2 = null;
708 }
709
710 if (tempPosition1 != null && tempPosition1.Handle != IntPtr.Zero)
711 {
712 tempPosition1.Dispose();
713 tempPosition1 = null;
714 }
715
716 }
717
718
719
720 public void ProcessTaints(float timestep)
721 {
722 if (m_taintadd)
723 {
724 changeadd(timestep);
725 }
726
727 if (prim_geom.Handle == IntPtr.Zero)
728 {
729 CreateGeom(IntPtr.Zero, primMesh);
730
731 if (IsPhysical)
732 SetBody(Mass);
733 else
734 SetBody(0);
735
736 }
737
738 if (!_position.IsIdentical(m_taintposition, 0f))
739 changemove(timestep);
740
741 if (m_taintrot != _orientation)
742 rotate(timestep);
743 //
744
745 if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent))
746 changePhysicsStatus(timestep);
747 //
748
749 if (!_size.IsIdentical(m_taintsize, 0))
750 changesize(timestep);
751 //
752
753 if (m_taintshape)
754 changeshape(timestep);
755 //
756
757 if (m_taintforce)
758 changeAddForce(timestep);
759
760 if (m_taintaddangularforce)
761 changeAddAngularForce(timestep);
762
763 if (!m_taintTorque.IsIdentical(PhysicsVector.Zero, 0.001f))
764 changeSetTorque(timestep);
765
766 if (m_taintdisable)
767 changedisable(timestep);
768
769 if (m_taintselected != m_isSelected)
770 changeSelectedStatus(timestep);
771
772 if (!m_taintVelocity.IsIdentical(PhysicsVector.Zero, 0.001f))
773 changevelocity(timestep);
774
775 if (m_taintparent != _parent)
776 changelink(timestep);
777
778 if (m_taintCollidesWater != m_collidesWater)
779 changefloatonwater(timestep);
780
781 if (!m_angularlock.IsIdentical(m_taintAngularLock, 0))
782 changeAngularLock(timestep);
783
784
785 }
786
787 #region Physics Scene Change Action routines
788
789 private void changeadd(float timestep)
790 {
791 if (_mesh == null)
792 {
793 if (_parent_scene.needsMeshing(_pbs))
794 {
795 // Don't need to re-enable body.. it's done in SetMesh
796 _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
797 // createmesh returns null when it's a shape that isn't a cube.
798 }
799 }
800 CreateGeom(IntPtr.Zero, primMesh);
801
802 enableBody();
803 changeSelectedStatus(timestep);
804 m_taintadd = false;
805
806 }
807
808 private void changemove(float timestep)
809 {
810
811
812 tempTransform2 = Body.getWorldTransform();
813 btQuaternion quat = tempTransform2.getRotation();
814 tempPosition2.setValue(_position.X, _position.Y, _position.Z);
815 tempTransform2.Dispose();
816 tempTransform2 = new btTransform(quat, tempPosition2);
817 Body.setWorldTransform(tempTransform2);
818
819 changeSelectedStatus(timestep);
820
821 resetCollisionAccounting();
822 m_taintposition = _position;
823 }
824
825 private void rotate(float timestep)
826 {
827
828 tempTransform2 = Body.getWorldTransform();
829 tempOrientation2 = new btQuaternion(_orientation.X, _orientation.Y, _orientation.Z, _orientation.W);
830 tempTransform2.setRotation(tempOrientation2);
831 Body.setWorldTransform(tempTransform2);
832
833 resetCollisionAccounting();
834 m_taintrot = _orientation;
835 }
836
837 private void changePhysicsStatus(float timestep)
838 {
839 SetCollisionShape(prim_geom);
840 SetBody(Mass);
841 changeSelectedStatus(timestep);
842
843 resetCollisionAccounting();
844 m_taintPhysics = m_isphysical;
845 }
846
847 private void changesize(float timestep)
848 {
849 SetCollisionShape(null);
850 // Construction of new prim
851 if (_parent_scene.needsMeshing(_pbs))
852 {
853 float meshlod = _parent_scene.meshSculptLOD;
854
855 if (IsPhysical)
856 meshlod = _parent_scene.MeshSculptphysicalLOD;
857 // Don't need to re-enable body.. it's done in SetMesh
858
859 IMesh mesh = null;
860
861 if (_parent_scene.needsMeshing(_pbs))
862 mesh = _parent_scene.mesher.CreateMesh(SOPName, _pbs, _size, meshlod, IsPhysical);
863
864 //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical);
865
866 CreateGeom(IntPtr.Zero, mesh);
867
868
869 }
870 else
871 {
872 _mesh = null;
873 CreateGeom(IntPtr.Zero, _mesh);
874 }
875
876 if (IsPhysical)
877 SetBody(Mass);
878 else
879 SetBody(0);
880
881 m_taintsize = _size;
882
883 }
884
885 private void changeshape(float timestep)
886 {
887 // Cleanup of old prim geometry and Bodies
888 if (IsPhysical && Body != null && Body.Handle != IntPtr.Zero)
889 {
890 if (childPrim)
891 {
892 if (_parent != null)
893 {
894 BulletDotNETPrim parent = (BulletDotNETPrim)_parent;
895 parent.ChildDelink(this);
896 }
897 }
898 else
899 {
900 disableBody();
901 }
902 }
903 try
904 {
905 SetCollisionShape(null);
906 }
907 catch (System.AccessViolationException)
908 {
909 //prim_geom = IntPtr.Zero;
910 m_log.Error("[PHYSICS]: PrimGeom dead");
911 }
912
913 // we don't need to do space calculation because the client sends a position update also.
914 if (_size.X <= 0) _size.X = 0.01f;
915 if (_size.Y <= 0) _size.Y = 0.01f;
916 if (_size.Z <= 0) _size.Z = 0.01f;
917 // Construction of new prim
918
919 if (_parent_scene.needsMeshing(_pbs))
920 {
921 // Don't need to re-enable body.. it's done in SetMesh
922 float meshlod = _parent_scene.meshSculptLOD;
923
924 if (IsPhysical)
925 meshlod = _parent_scene.MeshSculptphysicalLOD;
926
927 IMesh mesh = _parent_scene.mesher.CreateMesh(SOPName, _pbs, _size, meshlod, IsPhysical);
928 // createmesh returns null when it doesn't mesh.
929 CreateGeom(IntPtr.Zero, mesh);
930 }
931 else
932 {
933 _mesh = null;
934 CreateGeom(IntPtr.Zero, null);
935 }
936 tempPosition1.setValue(_position.X, _position.Y, _position.Z);
937 if (tempOrientation1.Handle != IntPtr.Zero)
938 tempOrientation1.Dispose();
939 tempOrientation1 = new btQuaternion(_orientation.X, Orientation.Y, _orientation.Z, _orientation.W);
940 if (tempTransform1 != null && tempTransform1.Handle != IntPtr.Zero)
941 tempTransform1.Dispose();
942 tempTransform1 = new btTransform(tempOrientation1, tempPosition1);
943
944
945
946
947 //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
948 if (IsPhysical)
949 {
950 SetBody(Mass);
951 // Re creates body on size.
952 // EnableBody also does setMass()
953
954 }
955 else
956 {
957 SetBody(0);
958 }
959
960 changeSelectedStatus(timestep);
961 if (childPrim)
962 {
963 if (_parent is BulletDotNETPrim)
964 {
965 BulletDotNETPrim parent = (BulletDotNETPrim)_parent;
966 parent.ChildSetGeom(this);
967 }
968 }
969 resetCollisionAccounting();
970 m_taintshape = false;
971 }
972
973 private void resetCollisionAccounting()
974 {
975 m_collisionscore = 0;
976 }
977
978 private void ChildSetGeom(BulletDotNETPrim bulletDotNETPrim)
979 {
980 // TODO: throw new NotImplementedException();
981 }
982
983 private void changeAddForce(float timestep)
984 {
985 // TODO: throw new NotImplementedException();
986 }
987
988 private void changeAddAngularForce(float timestep)
989 {
990 // TODO: throw new NotImplementedException();
991 }
992
993 private void changeSetTorque(float timestep)
994 {
995 // TODO: throw new NotImplementedException();
996 }
997
998 private void changedisable(float timestep)
999 {
1000 // TODO: throw new NotImplementedException();
1001 }
1002
1003 private void changeSelectedStatus(float timestep)
1004 {
1005 // TODO: throw new NotImplementedException();
1006 }
1007
1008 private void changevelocity(float timestep)
1009 {
1010 // TODO: throw new NotImplementedException();
1011 }
1012
1013 private void changelink(float timestep)
1014 {
1015 // TODO: throw new NotImplementedException();
1016 }
1017
1018 private void changefloatonwater(float timestep)
1019 {
1020 // TODO: throw new NotImplementedException();
1021 }
1022
1023 private void changeAngularLock(float timestep)
1024 {
1025 // TODO: throw new NotImplementedException();
1026 }
1027 #endregion
1028
1029
1030
1031
1032 internal void Move(float timestep)
1033 {
1034 //TODO:
1035 float fx = 0;
1036 float fy = 0;
1037 float fz = 0;
1038
1039 if (IsPhysical && Body != null && Body.Handle != IntPtr.Zero && !m_isSelected)
1040 {
1041 float m_mass = CalculateMass();
1042
1043 fz = 0f;
1044 //m_log.Info(m_collisionFlags.ToString());
1045
1046 if (m_buoyancy != 0)
1047 {
1048 if (m_buoyancy > 0)
1049 {
1050 fz = (((-1 * _parent_scene.gravityz) * m_buoyancy) * m_mass);
1051
1052 //d.Vector3 l_velocity = d.BodyGetLinearVel(Body);
1053 //m_log.Info("Using Buoyancy: " + buoyancy + " G: " + (_parent_scene.gravityz * m_buoyancy) + "mass:" + m_mass + " Pos: " + Position.ToString());
1054 }
1055 else
1056 {
1057 fz = (-1 * (((-1 * _parent_scene.gravityz) * (-1 * m_buoyancy)) * m_mass));
1058 }
1059 }
1060
1061 if (m_usePID)
1062 {
1063 //if (!d.BodyIsEnabled(Body))
1064 //d.BodySetForce(Body, 0f, 0f, 0f);
1065 // If we're using the PID controller, then we have no gravity
1066 fz = (-1 * _parent_scene.gravityz) * m_mass;
1067
1068 // no lock; for now it's only called from within Simulate()
1069
1070 // If the PID Controller isn't active then we set our force
1071 // calculating base velocity to the current position
1072
1073 if ((m_PIDTau < 1) && (m_PIDTau != 0))
1074 {
1075 //PID_G = PID_G / m_PIDTau;
1076 m_PIDTau = 1;
1077 }
1078
1079 if ((PID_G - m_PIDTau) <= 0)
1080 {
1081 PID_G = m_PIDTau + 1;
1082 }
1083
1084 // TODO: NEED btVector3 for Linear Velocity
1085 // NEED btVector3 for Position
1086
1087 PhysicsVector pos = new PhysicsVector(0, 0, 0); //TODO: Insert values gotten from bullet
1088 PhysicsVector vel = new PhysicsVector(0, 0, 0);
1089
1090 _target_velocity =
1091 new PhysicsVector(
1092 (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep),
1093 (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep),
1094 (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep)
1095 );
1096
1097 if (_target_velocity.IsIdentical(PhysicsVector.Zero, 0.1f))
1098 {
1099
1100 /* TODO: Do Bullet equiv
1101 *
1102 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
1103 d.BodySetLinearVel(Body, 0, 0, 0);
1104 d.BodyAddForce(Body, 0, 0, fz);
1105 return;
1106 */
1107 }
1108 else
1109 {
1110 _zeroFlag = false;
1111
1112 fx = ((_target_velocity.X) - vel.X) * (PID_D);
1113 fy = ((_target_velocity.Y) - vel.Y) * (PID_D);
1114 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1115
1116 }
1117
1118 }
1119
1120 if (m_useHoverPID && !m_usePID)
1121 {
1122 // If we're using the PID controller, then we have no gravity
1123 fz = (-1 * _parent_scene.gravityz) * m_mass;
1124
1125 // no lock; for now it's only called from within Simulate()
1126
1127 // If the PID Controller isn't active then we set our force
1128 // calculating base velocity to the current position
1129
1130 if ((m_PIDTau < 1))
1131 {
1132 PID_G = PID_G / m_PIDTau;
1133 }
1134
1135 if ((PID_G - m_PIDTau) <= 0)
1136 {
1137 PID_G = m_PIDTau + 1;
1138 }
1139 PhysicsVector pos = new PhysicsVector(0, 0, 0); //TODO: Insert values gotten from bullet
1140 PhysicsVector vel = new PhysicsVector(0, 0, 0);
1141
1142 // determine what our target height really is based on HoverType
1143 switch (m_PIDHoverType)
1144 {
1145 case PIDHoverType.Absolute:
1146 m_targetHoverHeight = m_PIDHoverHeight;
1147 break;
1148 case PIDHoverType.Ground:
1149 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1150 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1151 break;
1152 case PIDHoverType.GroundAndWater:
1153 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1154 m_waterHeight = _parent_scene.GetWaterLevel();
1155 if (m_groundHeight > m_waterHeight)
1156 {
1157 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1158 }
1159 else
1160 {
1161 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
1162 }
1163 break;
1164 case PIDHoverType.Water:
1165 m_waterHeight = _parent_scene.GetWaterLevel();
1166 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
1167 break;
1168 }
1169
1170
1171 _target_velocity =
1172 new PhysicsVector(0.0f, 0.0f,
1173 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
1174 );
1175
1176 // if velocity is zero, use position control; otherwise, velocity control
1177
1178 if (_target_velocity.IsIdentical(PhysicsVector.Zero, 0.1f))
1179 {
1180
1181 /* TODO: Do Bullet Equiv
1182 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
1183 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
1184 d.BodyAddForce(Body, 0, 0, fz);
1185 */
1186 return;
1187 }
1188 else
1189 {
1190 _zeroFlag = false;
1191
1192 // We're flying and colliding with something
1193 fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1194 }
1195 }
1196
1197 fx *= m_mass;
1198 fy *= m_mass;
1199 //fz *= m_mass;
1200
1201 fx += m_force.X;
1202 fy += m_force.Y;
1203 fz += m_force.Z;
1204
1205 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
1206 if (fx != 0 || fy != 0 || fz != 0)
1207 {
1208 /*
1209 * TODO: Do Bullet Equiv
1210 if (!d.BodyIsEnabled(Body))
1211 {
1212 d.BodySetLinearVel(Body, 0f, 0f, 0f);
1213 d.BodySetForce(Body, 0, 0, 0);
1214 enableBodySoft();
1215 }
1216 */
1217 // 35x10 = 350n times the mass per second applied maximum.
1218
1219 float nmax = 35f * m_mass;
1220 float nmin = -35f * m_mass;
1221
1222
1223 if (fx > nmax)
1224 fx = nmax;
1225 if (fx < nmin)
1226 fx = nmin;
1227 if (fy > nmax)
1228 fy = nmax;
1229 if (fy < nmin)
1230 fy = nmin;
1231
1232 // TODO: Do Bullet Equiv
1233 // d.BodyAddForce(Body, fx, fy, fz);
1234 }
1235 }
1236 else
1237 {
1238 // _zeroPosition = d.BodyGetPosition(Body);
1239 return;
1240 }
1241 }
1242
1243
1244
1245
1246 #region Mass Calculation
1247
1248 private float CalculateMass()
1249 {
1250 float volume = 0;
1251
1252 // No material is passed to the physics engines yet.. soo..
1253 // we're using the m_density constant in the class definition
1254
1255 float returnMass = 0;
1256
1257 switch (_pbs.ProfileShape)
1258 {
1259 case ProfileShape.Square:
1260 // Profile Volume
1261
1262 volume = _size.X * _size.Y * _size.Z;
1263
1264 // If the user has 'hollowed out'
1265 // ProfileHollow is one of those 0 to 50000 values :P
1266 // we like percentages better.. so turning into a percentage
1267
1268 if (((float)_pbs.ProfileHollow / 50000f) > 0.0)
1269 {
1270 float hollowAmount = (float)_pbs.ProfileHollow / 50000f;
1271
1272 // calculate the hollow volume by it's shape compared to the prim shape
1273 float hollowVolume = 0;
1274 switch (_pbs.HollowShape)
1275 {
1276 case HollowShape.Square:
1277 case HollowShape.Same:
1278 // Cube Hollow volume calculation
1279 float hollowsizex = _size.X * hollowAmount;
1280 float hollowsizey = _size.Y * hollowAmount;
1281 float hollowsizez = _size.Z * hollowAmount;
1282 hollowVolume = hollowsizex * hollowsizey * hollowsizez;
1283 break;
1284
1285 case HollowShape.Circle:
1286 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1287 // Cyllinder hollow volume calculation
1288 float hRadius = _size.X / 2;
1289 float hLength = _size.Z;
1290
1291 // pi * r2 * h
1292 hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount);
1293 break;
1294
1295 case HollowShape.Triangle:
1296 // Equilateral Triangular Prism volume hollow calculation
1297 // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
1298
1299 float aLength = _size.Y;
1300 // 1/2 abh
1301 hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount);
1302 break;
1303
1304 default:
1305 hollowVolume = 0;
1306 break;
1307 }
1308 volume = volume - hollowVolume;
1309 }
1310
1311 break;
1312 case ProfileShape.Circle:
1313 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1314 {
1315 // Cylinder
1316 float volume1 = (float)(Math.PI * Math.Pow(_size.X / 2, 2) * _size.Z);
1317 float volume2 = (float)(Math.PI * Math.Pow(_size.Y / 2, 2) * _size.Z);
1318
1319 // Approximating the cylinder's irregularity.
1320 if (volume1 > volume2)
1321 {
1322 volume = (float)volume1 - (volume1 - volume2);
1323 }
1324 else if (volume2 > volume1)
1325 {
1326 volume = (float)volume2 - (volume2 - volume1);
1327 }
1328 else
1329 {
1330 // Regular cylinder
1331 volume = volume1;
1332 }
1333 }
1334 else
1335 {
1336 // We don't know what the shape is yet, so use default
1337 volume = _size.X * _size.Y * _size.Z;
1338 }
1339 // If the user has 'hollowed out'
1340 // ProfileHollow is one of those 0 to 50000 values :P
1341 // we like percentages better.. so turning into a percentage
1342
1343 if (((float)_pbs.ProfileHollow / 50000f) > 0.0)
1344 {
1345 float hollowAmount = (float)_pbs.ProfileHollow / 50000f;
1346
1347 // calculate the hollow volume by it's shape compared to the prim shape
1348 float hollowVolume = 0;
1349 switch (_pbs.HollowShape)
1350 {
1351 case HollowShape.Same:
1352 case HollowShape.Circle:
1353 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1354 // Cyllinder hollow volume calculation
1355 float hRadius = _size.X / 2;
1356 float hLength = _size.Z;
1357
1358 // pi * r2 * h
1359 hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount);
1360 break;
1361
1362 case HollowShape.Square:
1363 // Cube Hollow volume calculation
1364 float hollowsizex = _size.X * hollowAmount;
1365 float hollowsizey = _size.Y * hollowAmount;
1366 float hollowsizez = _size.Z * hollowAmount;
1367 hollowVolume = hollowsizex * hollowsizey * hollowsizez;
1368 break;
1369
1370 case HollowShape.Triangle:
1371 // Equilateral Triangular Prism volume hollow calculation
1372 // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
1373
1374 float aLength = _size.Y;
1375 // 1/2 abh
1376 hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount);
1377 break;
1378
1379 default:
1380 hollowVolume = 0;
1381 break;
1382 }
1383 volume = volume - hollowVolume;
1384 }
1385 break;
1386
1387 case ProfileShape.HalfCircle:
1388 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1389 {
1390 if (_size.X == _size.Y && _size.Z == _size.X)
1391 {
1392 // regular sphere
1393 // v = 4/3 * pi * r^3
1394 float sradius3 = (float)Math.Pow((_size.X / 2), 3);
1395 volume = (float)((4 / 3f) * Math.PI * sradius3);
1396 }
1397 else
1398 {
1399 // we treat this as a box currently
1400 volume = _size.X * _size.Y * _size.Z;
1401 }
1402 }
1403 else
1404 {
1405 // We don't know what the shape is yet, so use default
1406 volume = _size.X * _size.Y * _size.Z;
1407 }
1408 break;
1409
1410 case ProfileShape.EquilateralTriangle:
1411 /*
1412 v = (abs((xB*yA-xA*yB)+(xC*yB-xB*yC)+(xA*yC-xC*yA))/2) * h
1413
1414 // seed mesh
1415 Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f);
1416 Vertex PM = new Vertex(+0.5f, 0f, 0.0f);
1417 Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f);
1418 */
1419 float xA = -0.25f * _size.X;
1420 float yA = -0.45f * _size.Y;
1421
1422 float xB = 0.5f * _size.X;
1423 float yB = 0;
1424
1425 float xC = -0.25f * _size.X;
1426 float yC = 0.45f * _size.Y;
1427
1428 volume = (float)((Math.Abs((xB * yA - xA * yB) + (xC * yB - xB * yC) + (xA * yC - xC * yA)) / 2) * _size.Z);
1429
1430 // If the user has 'hollowed out'
1431 // ProfileHollow is one of those 0 to 50000 values :P
1432 // we like percentages better.. so turning into a percentage
1433 float fhollowFactor = ((float)_pbs.ProfileHollow / 1.9f);
1434 if (((float)fhollowFactor / 50000f) > 0.0)
1435 {
1436 float hollowAmount = (float)fhollowFactor / 50000f;
1437
1438 // calculate the hollow volume by it's shape compared to the prim shape
1439 float hollowVolume = 0;
1440 switch (_pbs.HollowShape)
1441 {
1442 case HollowShape.Same:
1443 case HollowShape.Triangle:
1444 // Equilateral Triangular Prism volume hollow calculation
1445 // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
1446
1447 float aLength = _size.Y;
1448 // 1/2 abh
1449 hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount);
1450 break;
1451
1452 case HollowShape.Square:
1453 // Cube Hollow volume calculation
1454 float hollowsizex = _size.X * hollowAmount;
1455 float hollowsizey = _size.Y * hollowAmount;
1456 float hollowsizez = _size.Z * hollowAmount;
1457 hollowVolume = hollowsizex * hollowsizey * hollowsizez;
1458 break;
1459
1460 case HollowShape.Circle:
1461 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1462 // Cyllinder hollow volume calculation
1463 float hRadius = _size.X / 2;
1464 float hLength = _size.Z;
1465
1466 // pi * r2 * h
1467 hollowVolume = ((float)((Math.PI * Math.Pow(hRadius, 2) * hLength) / 2) * hollowAmount);
1468 break;
1469
1470 default:
1471 hollowVolume = 0;
1472 break;
1473 }
1474 volume = volume - hollowVolume;
1475 }
1476 break;
1477
1478 default:
1479 // we don't have all of the volume formulas yet so
1480 // use the common volume formula for all
1481 volume = _size.X * _size.Y * _size.Z;
1482 break;
1483 }
1484
1485 // Calculate Path cut effect on volume
1486 // Not exact, in the triangle hollow example
1487 // They should never be zero or less then zero..
1488 // we'll ignore it if it's less then zero
1489
1490 // ProfileEnd and ProfileBegin are values
1491 // from 0 to 50000
1492
1493 // Turning them back into percentages so that I can cut that percentage off the volume
1494
1495 float PathCutEndAmount = _pbs.ProfileEnd;
1496 float PathCutStartAmount = _pbs.ProfileBegin;
1497 if (((PathCutStartAmount + PathCutEndAmount) / 50000f) > 0.0f)
1498 {
1499 float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount) / 50000f);
1500
1501 // Check the return amount for sanity
1502 if (pathCutAmount >= 0.99f)
1503 pathCutAmount = 0.99f;
1504
1505 volume = volume - (volume * pathCutAmount);
1506 }
1507 UInt16 taperX = _pbs.PathScaleX;
1508 UInt16 taperY = _pbs.PathScaleY;
1509 float taperFactorX = 0;
1510 float taperFactorY = 0;
1511
1512 // Mass = density * volume
1513 if (taperX != 100)
1514 {
1515 if (taperX > 100)
1516 {
1517 taperFactorX = 1.0f - ((float)taperX / 200);
1518 //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
1519 }
1520 else
1521 {
1522 taperFactorX = 1.0f - ((100 - (float)taperX) / 100);
1523 //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
1524 }
1525 volume = (float)volume * ((taperFactorX / 3f) + 0.001f);
1526 }
1527
1528 if (taperY != 100)
1529 {
1530 if (taperY > 100)
1531 {
1532 taperFactorY = 1.0f - ((float)taperY / 200);
1533 //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
1534 }
1535 else
1536 {
1537 taperFactorY = 1.0f - ((100 - (float)taperY) / 100);
1538 //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
1539 }
1540 volume = (float)volume * ((taperFactorY / 3f) + 0.001f);
1541 }
1542 returnMass = m_density * volume;
1543 if (returnMass <= 0) returnMass = 0.0001f;//ckrinke: Mass must be greater then zero.
1544
1545
1546
1547 // Recursively calculate mass
1548 bool HasChildPrim = false;
1549 lock (childrenPrim)
1550 {
1551 if (childrenPrim.Count > 0)
1552 {
1553 HasChildPrim = true;
1554 }
1555
1556 }
1557 if (HasChildPrim)
1558 {
1559 BulletDotNETPrim[] childPrimArr = new BulletDotNETPrim[0];
1560
1561 lock (childrenPrim)
1562 childPrimArr = childrenPrim.ToArray();
1563
1564 for (int i = 0; i < childPrimArr.Length; i++)
1565 {
1566 if (childPrimArr[i] != null && !childPrimArr[i].m_taintremove)
1567 returnMass += childPrimArr[i].CalculateMass();
1568 // failsafe, this shouldn't happen but with OpenSim, you never know :)
1569 if (i > 256)
1570 break;
1571 }
1572 }
1573
1574
1575
1576
1577
1578 return returnMass;
1579 }
1580
1581 #endregion
1582
1583
1584 public void CreateGeom(IntPtr m_targetSpace, IMesh p_mesh)
1585 {
1586 if (p_mesh != null)
1587 {
1588 _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
1589 setMesh(_parent_scene, _mesh);
1590
1591 }
1592 else
1593 {
1594 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
1595 {
1596 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
1597 {
1598 if (((_size.X / 2f) > 0f))
1599 {
1600 //SetGeom to a Regular Sphere
1601 tempSize1.setValue(_size.X * 0.5f, _size.Y * 0.5f, _size.Z * 0.5f);
1602 SetCollisionShape(new btSphereShape(_size.X*0.5f));
1603 }
1604 else
1605 {
1606 // uses halfextents
1607 tempSize1.setValue(_size.X*0.5f, _size.Y*0.5f, _size.Z*0.5f);
1608 SetCollisionShape(new btBoxShape(tempSize1));
1609 }
1610 }
1611 else
1612 {
1613 // uses halfextents
1614 tempSize1.setValue(_size.X * 0.5f, _size.Y * 0.5f, _size.Z * 0.5f);
1615 SetCollisionShape(new btBoxShape(tempSize1));
1616 }
1617
1618 }
1619 else
1620 {
1621 // uses halfextents
1622 tempSize1.setValue(_size.X * 0.5f, _size.Y * 0.5f, _size.Z * 0.5f);
1623 SetCollisionShape(new btBoxShape(tempSize1));
1624 }
1625 }
1626 }
1627
1628 private void setMesh(BulletDotNETScene _parent_scene, IMesh mesh)
1629 {
1630 // TODO: Set Collision Body Mesh
1631 // This sleeper is there to moderate how long it takes between
1632 // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
1633
1634 Thread.Sleep(10);
1635
1636 //Kill Body so that mesh can re-make the geom
1637 if (IsPhysical && Body != null && Body.Handle != IntPtr.Zero)
1638 {
1639 if (childPrim)
1640 {
1641 if (_parent != null)
1642 {
1643 BulletDotNETPrim parent = (BulletDotNETPrim)_parent;
1644 parent.ChildDelink(this);
1645 }
1646 }
1647 else
1648 {
1649 disableBody();
1650 }
1651 }
1652
1653 IMesh oldMesh = primMesh;
1654
1655 primMesh = mesh;
1656
1657 float[] vertexList = primMesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory
1658 int[] indexList = primMesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage
1659 //Array.Reverse(indexList);
1660 primMesh.releaseSourceMeshData(); // free up the original mesh data to save memory
1661
1662 int VertexCount = vertexList.GetLength(0) / 3;
1663 int IndexCount = indexList.GetLength(0);
1664
1665 if (btshapeArray != null && btshapeArray.Handle != IntPtr.Zero)
1666 btshapeArray.Dispose();
1667 //Array.Reverse(indexList);
1668 btshapeArray = new btTriangleIndexVertexArray(IndexCount / 3, indexList, (3 * sizeof(int)),
1669 VertexCount, vertexList, 3*sizeof (float));
1670 SetCollisionShape(new btGImpactMeshShape(btshapeArray));
1671 //((btGImpactMeshShape) prim_geom).updateBound();
1672 ((btGImpactMeshShape)prim_geom).setLocalScaling(new btVector3(1,1, 1));
1673 ((btGImpactMeshShape)prim_geom).updateBound();
1674 _parent_scene.SetUsingGImpact();
1675 if (oldMesh != null)
1676 {
1677 oldMesh.releasePinned();
1678 oldMesh = null;
1679 }
1680
1681 }
1682
1683 private void SetCollisionShape(btCollisionShape shape)
1684 {
1685 if (shape == null)
1686 m_log.Debug("[PHYSICS]:SetShape!Null");
1687 else
1688 m_log.Debug("[PHYSICS]:SetShape!");
1689
1690 if (Body != null)
1691 {
1692 DisposeOfBody();
1693 }
1694
1695 if (prim_geom != null)
1696 {
1697 prim_geom.Dispose();
1698 prim_geom = null;
1699 }
1700 prim_geom = shape;
1701
1702 //Body.set
1703 }
1704
1705 public void SetBody(float mass)
1706 {
1707 m_log.DebugFormat("[PHYSICS]: SetBody! {0}",mass);
1708 if (Body != null && Body.Handle != IntPtr.Zero)
1709 {
1710 DisposeOfBody();
1711 }
1712
1713 if (tempMotionState1 != null && tempMotionState1.Handle != IntPtr.Zero)
1714 tempMotionState1.Dispose();
1715 if (tempTransform2 != null && tempTransform2.Handle != IntPtr.Zero)
1716 tempTransform2.Dispose();
1717 if (tempOrientation2 != null && tempOrientation2.Handle != IntPtr.Zero)
1718 tempOrientation2.Dispose();
1719
1720 if (tempPosition2 != null && tempPosition2.Handle != IntPtr.Zero)
1721 tempPosition2.Dispose();
1722
1723 tempOrientation2 = new btQuaternion(_orientation.X, _orientation.Y, _orientation.Z, _orientation.W);
1724 tempPosition2 = new btVector3(_position.X, _position.Y, _position.Z);
1725 tempTransform2 = new btTransform(tempOrientation2, tempPosition2);
1726 tempMotionState1 = new btDefaultMotionState(tempTransform2, _parent_scene.TransZero);
1727 if (tempInertia1 != null && tempInertia1.Handle != IntPtr.Zero)
1728 tempInertia1.Dispose();
1729 tempInertia1 = new btVector3(0, 0, 0);
1730 if (prim_geom.Handle == IntPtr.Zero)
1731 {
1732 m_log.Warn("[PHYSICS]:PrimGeom is Disposed!");
1733 CreateGeom(IntPtr.Zero, primMesh);
1734
1735 }
1736 prim_geom.calculateLocalInertia(mass, tempInertia1);
1737
1738 if (mass == 0)
1739 Body = new btRigidBody(mass, tempMotionState1, prim_geom);
1740 else
1741 Body = new btRigidBody(mass, tempMotionState1, prim_geom, tempInertia1);
1742
1743 if (prim_geom is btGImpactMeshShape)
1744 {
1745 ((btGImpactMeshShape) prim_geom).setLocalScaling(new btVector3(1, 1, 1));
1746 ((btGImpactMeshShape) prim_geom).updateBound();
1747 }
1748 _parent_scene.AddPrimToScene(this);
1749 }
1750
1751 private void DisposeOfBody()
1752 {
1753 if (Body != null)
1754 {
1755 if (Body.Handle != IntPtr.Zero)
1756 {
1757 _parent_scene.removeFromWorld(this,Body);
1758 Body.Dispose();
1759 }
1760 Body = null;
1761 // TODO: dispose parts that make up body
1762 }
1763 }
1764
1765 private void ChildDelink(BulletDotNETPrim pPrim)
1766 {
1767 // Okay, we have a delinked child.. need to rebuild the body.
1768 lock (childrenPrim)
1769 {
1770 foreach (BulletDotNETPrim prm in childrenPrim)
1771 {
1772 prm.childPrim = true;
1773 prm.disableBody();
1774
1775 }
1776 }
1777 disableBody();
1778
1779 lock (childrenPrim)
1780 {
1781 childrenPrim.Remove(pPrim);
1782 }
1783
1784
1785
1786
1787 if (Body != null && Body.Handle != IntPtr.Zero)
1788 {
1789 _parent_scene.remActivePrim(this);
1790 }
1791
1792
1793
1794 lock (childrenPrim)
1795 {
1796 foreach (BulletDotNETPrim prm in childrenPrim)
1797 {
1798 ParentPrim(prm);
1799 }
1800 }
1801
1802 }
1803
1804 private void ParentPrim(BulletDotNETPrim prm)
1805 {
1806 // TODO: Parent Linking algorithm. Use btComplexObject
1807 }
1808
1809 public void disableBody()
1810 {
1811 //this kills the body so things like 'mesh' can re-create it.
1812 lock (this)
1813 {
1814 if (!childPrim)
1815 {
1816 if (Body != null && Body.Handle != IntPtr.Zero)
1817 {
1818 _parent_scene.remActivePrim(this);
1819
1820 m_collisionCategories &= ~CollisionCategories.Body;
1821 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1822
1823 if (prim_geom != null && prim_geom.Handle != IntPtr.Zero)
1824 {
1825 // TODO: Set Category bits and Flags
1826 }
1827
1828 // TODO: destroy body
1829 DisposeOfBody();
1830
1831 lock (childrenPrim)
1832 {
1833 if (childrenPrim.Count > 0)
1834 {
1835 foreach (BulletDotNETPrim prm in childrenPrim)
1836 {
1837 _parent_scene.remActivePrim(prm);
1838 prm.DisposeOfBody();
1839 prm.SetCollisionShape(null);
1840 }
1841 }
1842
1843 }
1844
1845 DisposeOfBody();
1846 }
1847 }
1848 else
1849 {
1850 _parent_scene.remActivePrim(this);
1851 m_collisionCategories &= ~CollisionCategories.Body;
1852 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1853
1854 if (prim_geom != null && prim_geom.Handle != IntPtr.Zero)
1855 {
1856 // TODO: Set Category bits and Flags
1857 }
1858
1859 DisposeOfBody();
1860 }
1861
1862 }
1863 m_disabled = true;
1864 m_collisionscore = 0;
1865 }
1866
1867 public void disableBodySoft()
1868 {
1869 m_disabled = true;
1870
1871 if (m_isphysical && Body.Handle != IntPtr.Zero)
1872 {
1873 Body.clearForces();
1874 Body.forceActivationState(0);
1875
1876 }
1877
1878 }
1879
1880 public void enableBodySoft()
1881 {
1882 if (!childPrim)
1883 {
1884 if (m_isphysical && Body.Handle != IntPtr.Zero)
1885 {
1886 Body.clearForces();
1887 Body.forceActivationState(1);
1888 }
1889 m_disabled = false;
1890 }
1891 }
1892
1893 public void enableBody()
1894 {
1895 if (!childPrim)
1896 {
1897 //SetCollisionShape(prim_geom);
1898 if (IsPhysical)
1899 SetBody(Mass);
1900 else
1901 SetBody(0);
1902
1903 // TODO: Set Collision Category Bits and Flags
1904 // TODO: Set Auto Disable data
1905
1906 m_interpenetrationcount = 0;
1907 m_collisionscore = 0;
1908 m_disabled = false;
1909 // The body doesn't already have a finite rotation mode set here
1910 if ((!m_angularlock.IsIdentical(PhysicsVector.Zero, 0)) && _parent == null)
1911 {
1912 // TODO: Create Angular Motor on Axis Lock!
1913 }
1914 _parent_scene.addActivePrim(this);
1915 }
1916 }
1917
1918 public void UpdatePositionAndVelocity()
1919 {
1920 if (_parent == null)
1921 {
1922 PhysicsVector pv = new PhysicsVector(0, 0, 0);
1923 bool lastZeroFlag = _zeroFlag;
1924 if (tempPosition2 != null && tempPosition2.Handle != IntPtr.Zero)
1925 tempPosition2.Dispose();
1926 if (tempTransform3 != null && tempTransform3.Handle != IntPtr.Zero)
1927 tempTransform3.Dispose();
1928
1929 if (tempOrientation2 != null && tempOrientation2.Handle != IntPtr.Zero)
1930 tempOrientation2.Dispose();
1931
1932 if (tempAngularVelocity1 != null && tempAngularVelocity1.Handle != IntPtr.Zero)
1933 tempAngularVelocity1.Dispose();
1934
1935 if (tempLinearVelocity1 != null && tempLinearVelocity1.Handle != IntPtr.Zero)
1936 tempLinearVelocity1.Dispose();
1937
1938
1939
1940 tempTransform3 = Body.getInterpolationWorldTransform();
1941 tempPosition2 = tempTransform3.getOrigin(); // vec
1942 tempOrientation2 = tempTransform3.getRotation(); // ori
1943 tempAngularVelocity1 = Body.getInterpolationAngularVelocity(); //rotvel
1944 tempLinearVelocity1 = Body.getInterpolationLinearVelocity(); // vel
1945
1946 _torque.setValues(tempAngularVelocity1.getX(), tempAngularVelocity1.getX(), tempAngularVelocity1.getZ());
1947 PhysicsVector l_position = new PhysicsVector();
1948 Quaternion l_orientation = new Quaternion();
1949 m_lastposition = _position;
1950 m_lastorientation = _orientation;
1951
1952 l_position.X = tempPosition2.getX();
1953 l_position.Y = tempPosition2.getY();
1954 l_position.Z = tempPosition2.getZ();
1955 l_orientation.X = tempOrientation2.getX();
1956 l_orientation.Y = tempOrientation2.getY();
1957 l_orientation.Z = tempOrientation2.getZ();
1958 l_orientation.W = tempOrientation2.getW();
1959
1960 if (l_position.X > 255.95f || l_position.X < 0f || l_position.Y > 255.95f || l_position.Y < 0f)
1961 {
1962 //base.RaiseOutOfBounds(l_position);
1963
1964 if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds)
1965 {
1966 _position = l_position;
1967 //_parent_scene.remActivePrim(this);
1968 if (_parent == null)
1969 base.RequestPhysicsterseUpdate();
1970 return;
1971 }
1972 else
1973 {
1974 if (_parent == null)
1975 base.RaiseOutOfBounds(l_position);
1976 return;
1977 }
1978 }
1979
1980 if (l_position.Z < -200000f)
1981 {
1982 // This is so prim that get lost underground don't fall forever and suck up
1983 //
1984 // Sim resources and memory.
1985 // Disables the prim's movement physics....
1986 // It's a hack and will generate a console message if it fails.
1987
1988 //IsPhysical = false;
1989 //if (_parent == null)
1990 //base.RaiseOutOfBounds(_position);
1991
1992 _acceleration.X = 0;
1993 _acceleration.Y = 0;
1994 _acceleration.Z = 0;
1995
1996 _velocity.X = 0;
1997 _velocity.Y = 0;
1998 _velocity.Z = 0;
1999 m_rotationalVelocity.X = 0;
2000 m_rotationalVelocity.Y = 0;
2001 m_rotationalVelocity.Z = 0;
2002
2003 if (_parent == null)
2004 base.RequestPhysicsterseUpdate();
2005
2006 m_throttleUpdates = false;
2007 throttleCounter = 0;
2008 _zeroFlag = true;
2009 //outofBounds = true;
2010 }
2011
2012 if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
2013 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
2014 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02)
2015 && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.01 ))
2016 {
2017 _zeroFlag = true;
2018 m_throttleUpdates = false;
2019 }
2020 else
2021 {
2022 //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString());
2023 _zeroFlag = false;
2024 }
2025
2026 if (_zeroFlag)
2027 {
2028 _velocity.X = 0.0f;
2029 _velocity.Y = 0.0f;
2030 _velocity.Z = 0.0f;
2031
2032 _acceleration.X = 0;
2033 _acceleration.Y = 0;
2034 _acceleration.Z = 0;
2035
2036 //_orientation.w = 0f;
2037 //_orientation.X = 0f;
2038 //_orientation.Y = 0f;
2039 //_orientation.Z = 0f;
2040 m_rotationalVelocity.X = 0;
2041 m_rotationalVelocity.Y = 0;
2042 m_rotationalVelocity.Z = 0;
2043 if (!m_lastUpdateSent)
2044 {
2045 m_throttleUpdates = false;
2046 throttleCounter = 0;
2047 m_rotationalVelocity = pv;
2048
2049 if (_parent == null)
2050 base.RequestPhysicsterseUpdate();
2051
2052 m_lastUpdateSent = true;
2053 }
2054 }
2055 else
2056 {
2057 if (lastZeroFlag != _zeroFlag)
2058 {
2059 if (_parent == null)
2060 base.RequestPhysicsterseUpdate();
2061 }
2062
2063 m_lastVelocity = _velocity;
2064
2065 _position = l_position;
2066
2067 _velocity.X = tempLinearVelocity1.getX();
2068 _velocity.Y = tempLinearVelocity1.getY();
2069 _velocity.Z = tempLinearVelocity1.getZ();
2070
2071 _acceleration = ((_velocity - m_lastVelocity) / 0.1f);
2072 _acceleration = new PhysicsVector(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f);
2073 //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString());
2074
2075 if (_velocity.IsIdentical(pv, 0.5f))
2076 {
2077 m_rotationalVelocity = pv;
2078 }
2079 else
2080 {
2081
2082 m_rotationalVelocity.setValues(tempAngularVelocity1.getX(), tempAngularVelocity1.getY(), tempAngularVelocity1.getZ());
2083 }
2084
2085 //m_log.Debug("ODE: " + m_rotationalVelocity.ToString());
2086
2087 _orientation.X = l_orientation.X;
2088 _orientation.Y = l_orientation.Y;
2089 _orientation.Z = l_orientation.Z;
2090 _orientation.W = l_orientation.W;
2091 m_lastUpdateSent = false;
2092
2093 //if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate)
2094 //{
2095 if (_parent == null)
2096 base.RequestPhysicsterseUpdate();
2097 // }
2098 // else
2099 // {
2100 // throttleCounter++;
2101 //}
2102
2103 }
2104 m_lastposition = l_position;
2105 }
2106 else
2107 {
2108 // Not a body.. so Make sure the client isn't interpolating
2109 _velocity.X = 0;
2110 _velocity.Y = 0;
2111 _velocity.Z = 0;
2112
2113 _acceleration.X = 0;
2114 _acceleration.Y = 0;
2115 _acceleration.Z = 0;
2116
2117 m_rotationalVelocity.X = 0;
2118 m_rotationalVelocity.Y = 0;
2119 m_rotationalVelocity.Z = 0;
2120 _zeroFlag = true;
2121 }
2122 }
2123
2124
2125 internal void setPrimForRemoval()
2126 {
2127 m_taintremove = true;
2128 }
2129 }
2130}
2131
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
new file mode 100644
index 0000000..4fcf035
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
@@ -0,0 +1,642 @@
1using System;
2using System.Collections.Generic;
3using System.Reflection;
4using System.IO;
5using System.Diagnostics;
6using System.Threading;
7using log4net;
8using Nini.Config;
9using OpenSim.Framework;
10using OpenSim.Region.Physics.Manager;
11using OpenMetaverse;
12using BulletDotNET;
13
14namespace OpenSim.Region.Physics.BulletDotNETPlugin
15{
16 public class BulletDotNETScene : PhysicsScene
17 {
18 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
19
20 private string m_sceneIdentifier = string.Empty;
21
22 private List<BulletDotNETCharacter> m_characters = new List<BulletDotNETCharacter>();
23 private List<BulletDotNETPrim> m_prims = new List<BulletDotNETPrim>();
24 private List<BulletDotNETPrim> m_activePrims = new List<BulletDotNETPrim>();
25 private List<PhysicsActor> m_taintedActors = new List<PhysicsActor>();
26 private btDiscreteDynamicsWorld m_world;
27 private btAxisSweep3 m_broadphase;
28 private btCollisionConfiguration m_collisionConfiguration;
29 private btConstraintSolver m_solver;
30 private btCollisionDispatcher m_dispatcher;
31 private btHeightfieldTerrainShape m_terrainShape;
32 public btRigidBody TerrainBody;
33 private btVector3 m_terrainPosition;
34 private btVector3 m_gravity;
35 public btMotionState m_terrainMotionState;
36 public btTransform m_terrainTransform;
37 public btVector3 VectorZero;
38 public btQuaternion QuatIdentity;
39 public btTransform TransZero;
40
41 public float geomDefaultDensity = 10.000006836f;
42
43 private float avPIDD = 65f;
44 private float avPIDP = 28f;
45 private float avCapRadius = 0.37f;
46 private float avStandupTensor = 2000000f;
47 private float avDensity = 80f;
48 private float avHeightFudgeFactor = 0.52f;
49 private float avMovementDivisorWalk = 1.0f;
50 private float avMovementDivisorRun = 0.75f;
51
52 private float minimumGroundFlightOffset = 3f;
53
54 public bool meshSculptedPrim = true;
55
56 public float meshSculptLOD = 32;
57 public float MeshSculptphysicalLOD = 16;
58
59 public float bodyPIDD = 35f;
60 public float bodyPIDG = 25;
61 internal int geomCrossingFailuresBeforeOutofbounds = 4;
62
63 public float bodyMotorJointMaxforceTensor = 2;
64
65 public int bodyFramesAutoDisable = 20;
66
67 public float WorldTimeStep = 10f/60f;
68 public const float WorldTimeComp = 1/60f;
69 public float gravityz = -9.8f;
70
71 private float[] _origheightmap; // Used for Fly height. Kitto Flora
72 private bool usingGImpactAlgorithm = false;
73
74 private IConfigSource m_config;
75 private readonly btVector3 worldAabbMin = new btVector3(0, 0, 0);
76 private readonly btVector3 worldAabbMax = new btVector3(Constants.RegionSize, Constants.RegionSize , 9000);
77
78 public IMesher mesher;
79
80 public BulletDotNETScene(string sceneIdentifier)
81 {
82 m_sceneIdentifier = sceneIdentifier;
83 VectorZero = new btVector3(0, 0, 0);
84 QuatIdentity = new btQuaternion(0, 0, 0, 1);
85 TransZero = new btTransform(QuatIdentity, VectorZero);
86 m_gravity = new btVector3(0, 0, gravityz);
87 _origheightmap = new float[(int)Constants.RegionSize * (int)Constants.RegionSize];
88 }
89
90 public override void Initialise(IMesher meshmerizer, IConfigSource config)
91 {
92 mesher = meshmerizer;
93 m_config = config;
94 if (Environment.OSVersion.Platform == PlatformID.Unix)
95 {
96 m_log.Fatal("[BulletDotNET]: This configuration is not supported on *nix currently");
97 Thread.Sleep(5000);
98 Environment.Exit(0);
99 }
100 m_broadphase = new btAxisSweep3(worldAabbMin, worldAabbMax, 16000);
101 m_collisionConfiguration = new btDefaultCollisionConfiguration();
102 m_solver = new btSequentialImpulseConstraintSolver();
103 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
104 m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
105 m_world.setGravity(m_gravity);
106 }
107
108 public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size, bool isFlying)
109 {
110 BulletDotNETCharacter chr = new BulletDotNETCharacter(avName, this, position, size, avPIDD, avPIDP,
111 avCapRadius, avStandupTensor, avDensity,
112 avHeightFudgeFactor, avMovementDivisorWalk,
113 avMovementDivisorRun);
114 m_characters.Add(chr);
115 AddPhysicsActorTaint(chr);
116 return chr;
117 }
118
119 public override void RemoveAvatar(PhysicsActor actor)
120 {
121 BulletDotNETCharacter chr = (BulletDotNETCharacter) actor;
122
123 m_characters.Remove(chr);
124 m_world.removeRigidBody(chr.Body);
125 m_world.removeCollisionObject(chr.Body);
126
127 chr.Remove();
128 AddPhysicsActorTaint(chr);
129 //chr = null;
130 }
131
132 public override void RemovePrim(PhysicsActor prim)
133 {
134 if (prim is BulletDotNETPrim)
135 {
136
137 BulletDotNETPrim p = (BulletDotNETPrim)prim;
138
139 p.setPrimForRemoval();
140 AddPhysicsActorTaint(prim);
141 //RemovePrimThreadLocked(p);
142
143 }
144 }
145
146 private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation,
147 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical)
148 {
149 PhysicsVector pos = new PhysicsVector(position.X, position.Y, position.Z);
150 //pos.X = position.X;
151 //pos.Y = position.Y;
152 //pos.Z = position.Z;
153 PhysicsVector siz = new PhysicsVector();
154 siz.X = size.X;
155 siz.Y = size.Y;
156 siz.Z = size.Z;
157 Quaternion rot = rotation;
158
159 BulletDotNETPrim newPrim;
160
161 newPrim = new BulletDotNETPrim(name, this, pos, siz, rot, mesh, pbs, isphysical);
162
163 lock (m_prims)
164 m_prims.Add(newPrim);
165
166
167 return newPrim;
168 }
169
170 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quaternion rotation)
171 {
172 return AddPrimShape(primName, pbs, position, size, rotation, false);
173 }
174
175 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quaternion rotation, bool isPhysical)
176 {
177 PhysicsActor result;
178 IMesh mesh = null;
179
180 //switch (pbs.ProfileShape)
181 //{
182 // case ProfileShape.Square:
183 // //support simple box & hollow box now; later, more shapes
184 // if (needsMeshing(pbs))
185 // {
186 // mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
187 // }
188
189 // break;
190 //}
191
192 if (needsMeshing(pbs))
193 mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
194
195 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
196
197 return result;
198 }
199
200 public override void AddPhysicsActorTaint(PhysicsActor prim)
201 {
202 lock (m_taintedActors)
203 {
204 if (!m_taintedActors.Contains(prim))
205 {
206 m_taintedActors.Add(prim);
207 }
208 }
209 }
210 internal void SetUsingGImpact()
211 {
212 if (!usingGImpactAlgorithm)
213 btGImpactCollisionAlgorithm.registerAlgorithm(m_dispatcher);
214 usingGImpactAlgorithm = true;
215 }
216
217 public override float Simulate(float timeStep)
218 {
219 lock (m_taintedActors)
220 {
221 foreach (PhysicsActor act in m_taintedActors)
222 {
223 if (act is BulletDotNETCharacter)
224 ((BulletDotNETCharacter) act).ProcessTaints(timeStep);
225 if (act is BulletDotNETPrim)
226 ((BulletDotNETPrim)act).ProcessTaints(timeStep);
227 }
228 m_taintedActors.Clear();
229 }
230
231 lock (m_characters)
232 {
233 foreach (BulletDotNETCharacter chr in m_characters)
234 {
235 chr.Move(timeStep);
236 }
237 }
238
239 lock (m_prims)
240 {
241 foreach (BulletDotNETPrim prim in m_prims)
242 {
243 prim.Move(timeStep);
244 }
245 }
246 float steps = m_world.stepSimulation(WorldTimeStep, 5, WorldTimeComp);
247
248 foreach (BulletDotNETCharacter chr in m_characters)
249 {
250 chr.UpdatePositionAndVelocity();
251 }
252
253 foreach (BulletDotNETPrim prm in m_activePrims)
254 {
255 prm.UpdatePositionAndVelocity();
256 }
257
258 return steps;
259 }
260
261 public override void GetResults()
262 {
263
264 }
265
266 public override void SetTerrain(float[] heightMap)
267 {
268 if (m_terrainShape != null)
269 DeleteTerrain();
270
271 float hfmax = -9000;
272 float hfmin = 90000;
273
274 for (int i = 0; i <heightMap.Length;i++)
275 {
276 if (Single.IsNaN(heightMap[i]) || Single.IsInfinity(heightMap[i]))
277 {
278 heightMap[i] = 0f;
279 }
280
281 hfmin = (heightMap[i] < hfmin) ? heightMap[i] : hfmin;
282 hfmax = (heightMap[i] > hfmax) ? heightMap[i] : hfmax;
283 }
284 // store this for later reference.
285 // Note, we're storing it after we check it for anomolies above
286 _origheightmap = heightMap;
287
288 hfmin = 0;
289 hfmax = 256;
290
291 m_terrainShape = new btHeightfieldTerrainShape((int)Constants.RegionSize, (int)Constants.RegionSize, heightMap,
292 1.0f, hfmin, hfmax, (int)btHeightfieldTerrainShape.UPAxis.Z,
293 (int)btHeightfieldTerrainShape.PHY_ScalarType.PHY_FLOAT, false);
294 float AabbCenterX = Constants.RegionSize/2f;
295 float AabbCenterY = Constants.RegionSize/2f;
296
297 float AabbCenterZ = 0;
298 float temphfmin, temphfmax;
299
300 temphfmin = hfmin;
301 temphfmax = hfmax;
302
303 if (temphfmin < 0)
304 {
305 temphfmax = 0 - temphfmin;
306 temphfmin = 0 - temphfmin;
307 }
308 else if (temphfmin > 0)
309 {
310 temphfmax = temphfmax + (0 - temphfmin);
311 //temphfmin = temphfmin + (0 - temphfmin);
312 }
313 AabbCenterZ = temphfmax/2f;
314
315 if (m_terrainPosition == null)
316 {
317 m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
318 }
319 else
320 {
321 try
322 {
323 m_terrainPosition.setValue(AabbCenterX, AabbCenterY, AabbCenterZ);
324 }
325 catch (ObjectDisposedException)
326 {
327 m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
328 }
329 }
330 if (m_terrainMotionState != null)
331 {
332 m_terrainMotionState.Dispose();
333 m_terrainMotionState = null;
334 }
335 m_terrainTransform = new btTransform(QuatIdentity, m_terrainPosition);
336 m_terrainMotionState = new btDefaultMotionState(m_terrainTransform);
337 TerrainBody = new btRigidBody(0, m_terrainMotionState, m_terrainShape);
338 m_world.addRigidBody(TerrainBody);
339
340
341 }
342
343 public override void SetWaterLevel(float baseheight)
344 {
345
346 }
347
348 public override void DeleteTerrain()
349 {
350 if (TerrainBody != null)
351 {
352 m_world.removeRigidBody(TerrainBody);
353 }
354
355 if (m_terrainShape != null)
356 {
357 m_terrainShape.Dispose();
358 m_terrainShape = null;
359 }
360
361 if (m_terrainMotionState != null)
362 {
363 m_terrainMotionState.Dispose();
364 m_terrainMotionState = null;
365 }
366
367 if (m_terrainTransform != null)
368 {
369 m_terrainTransform.Dispose();
370 m_terrainTransform = null;
371 }
372
373 if (m_terrainPosition != null)
374 {
375 m_terrainPosition.Dispose();
376 m_terrainPosition = null;
377 }
378 }
379
380 public override void Dispose()
381 {
382 disposeAllBodies();
383 m_world.Dispose();
384 m_broadphase.Dispose();
385 ((btDefaultCollisionConfiguration) m_collisionConfiguration).Dispose();
386 ((btSequentialImpulseConstraintSolver) m_solver).Dispose();
387 worldAabbMax.Dispose();
388 worldAabbMin.Dispose();
389 VectorZero.Dispose();
390 QuatIdentity.Dispose();
391 m_gravity.Dispose();
392 VectorZero = null;
393 QuatIdentity = null;
394 }
395
396 public override Dictionary<uint, float> GetTopColliders()
397 {
398 return new Dictionary<uint, float>();
399 }
400
401 public btDiscreteDynamicsWorld getBulletWorld()
402 {
403 return m_world;
404 }
405
406 private void disposeAllBodies()
407 {
408 lock (m_prims)
409 {
410 foreach ( BulletDotNETPrim prim in m_prims)
411 {
412 if (prim.Body != null)
413 m_world.removeRigidBody(prim.Body);
414
415 prim.Dispose();
416 }
417 m_prims.Clear();
418
419 foreach (BulletDotNETCharacter chr in m_characters)
420 {
421 if (chr.Body != null)
422 m_world.removeRigidBody(chr.Body);
423 chr.Dispose();
424 }
425 m_characters.Clear();
426 }
427 }
428
429 public override bool IsThreaded
430 {
431 get { return false; }
432 }
433
434 internal void addCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
435 {
436 //TODO: FIXME:
437 }
438
439 internal void remCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
440 {
441 //TODO: FIXME:
442 }
443
444 internal void AddRigidBody(btRigidBody Body)
445 {
446 m_world.addRigidBody(Body);
447 }
448 [Obsolete("bad!")]
449 internal void removeFromWorld(btRigidBody body)
450 {
451
452 m_world.removeRigidBody(body);
453 }
454
455 internal void removeFromWorld(BulletDotNETPrim prm ,btRigidBody body)
456 {
457 lock (m_prims)
458 {
459 if (m_prims.Contains(prm))
460 {
461 m_world.removeRigidBody(body);
462 }
463 m_prims.Remove(prm);
464 }
465
466 }
467
468 internal float GetWaterLevel()
469 {
470 throw new NotImplementedException();
471 }
472
473 // Recovered for use by fly height. Kitto Flora
474 public float GetTerrainHeightAtXY(float x, float y)
475 {
476 // Teravus: Kitto, this code causes recurring errors that stall physics permenantly unless
477 // the values are checked, so checking below.
478 // Is there any reason that we don't do this in ScenePresence?
479 // The only physics engine that benefits from it in the physics plugin is this one
480
481 if ((int)x > Constants.RegionSize || (int)y > Constants.RegionSize ||
482 (int)x < 0.001f || (int)y < 0.001f)
483 return 0;
484
485 return _origheightmap[(int)y * Constants.RegionSize + (int)x];
486 }
487 // End recovered. Kitto Flora
488
489 /// <summary>
490 /// Routine to figure out if we need to mesh this prim with our mesher
491 /// </summary>
492 /// <param name="pbs"></param>
493 /// <returns></returns>
494 public bool needsMeshing(PrimitiveBaseShape pbs)
495 {
496 // most of this is redundant now as the mesher will return null if it cant mesh a prim
497 // but we still need to check for sculptie meshing being enabled so this is the most
498 // convenient place to do it for now...
499
500 // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f)
501 // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString());
502 int iPropertiesNotSupportedDefault = 0;
503
504 if (pbs.SculptEntry && !meshSculptedPrim)
505 {
506#if SPAM
507 m_log.Warn("NonMesh");
508#endif
509 return false;
510 }
511
512 // 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
513 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
514 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
515 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
516 {
517
518 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
519 && pbs.ProfileHollow == 0
520 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
521 && pbs.PathBegin == 0 && pbs.PathEnd == 0
522 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
523 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
524 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
525 {
526#if SPAM
527 m_log.Warn("NonMesh");
528#endif
529 return false;
530 }
531 }
532
533 if (pbs.ProfileHollow != 0)
534 iPropertiesNotSupportedDefault++;
535
536 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
537 iPropertiesNotSupportedDefault++;
538
539 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
540 iPropertiesNotSupportedDefault++;
541
542 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
543 iPropertiesNotSupportedDefault++;
544
545 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
546 iPropertiesNotSupportedDefault++;
547
548 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
549 iPropertiesNotSupportedDefault++;
550
551 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))
552 iPropertiesNotSupportedDefault++;
553
554 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
555 iPropertiesNotSupportedDefault++;
556
557 // test for torus
558 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
559 {
560 if (pbs.PathCurve == (byte)Extrusion.Curve1)
561 {
562 iPropertiesNotSupportedDefault++;
563 }
564 }
565 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
566 {
567 if (pbs.PathCurve == (byte)Extrusion.Straight)
568 {
569 iPropertiesNotSupportedDefault++;
570 }
571
572 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
573 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
574 {
575 iPropertiesNotSupportedDefault++;
576 }
577 }
578 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
579 {
580 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
581 {
582 iPropertiesNotSupportedDefault++;
583 }
584 }
585 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
586 {
587 if (pbs.PathCurve == (byte)Extrusion.Straight)
588 {
589 iPropertiesNotSupportedDefault++;
590 }
591 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
592 {
593 iPropertiesNotSupportedDefault++;
594 }
595 }
596
597
598 if (iPropertiesNotSupportedDefault == 0)
599 {
600#if SPAM
601 m_log.Warn("NonMesh");
602#endif
603 return false;
604 }
605#if SPAM
606 m_log.Debug("Mesh");
607#endif
608 return true;
609 }
610
611 internal void addActivePrim(BulletDotNETPrim pPrim)
612 {
613 lock (m_activePrims)
614 {
615 if (!m_activePrims.Contains(pPrim))
616 {
617 m_activePrims.Add(pPrim);
618 }
619 }
620 }
621
622 public void remActivePrim(BulletDotNETPrim pDeactivatePrim)
623 {
624 lock (m_activePrims)
625 {
626 m_activePrims.Remove(pDeactivatePrim);
627 }
628 }
629
630 internal void AddPrimToScene(BulletDotNETPrim pPrim)
631 {
632 lock (m_prims)
633 {
634 if (!m_prims.Contains(pPrim))
635 {
636 m_prims.Add(pPrim);
637 m_world.addRigidBody(pPrim.Body);
638 }
639 }
640 }
641 }
642}