aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs
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/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs
parentAdded CreateObject(regionhandle, userID, itemID) to post objects that are to ... (diff)
downloadopensim-SC-e592d038430ab994ed65df4f66e0cf5c32af476c.zip
opensim-SC-e592d038430ab994ed65df4f66e0cf5c32af476c.tar.gz
opensim-SC-e592d038430ab994ed65df4f66e0cf5c32af476c.tar.bz2
opensim-SC-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/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs')
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs2131
1 files changed, 2131 insertions, 0 deletions
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