aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs')
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs3958
1 files changed, 3958 insertions, 0 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
new file mode 100644
index 0000000..c9a453d
--- /dev/null
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -0,0 +1,3958 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/* Revision 2011/12 by Ubit Umarov
29 *
30 *
31 */
32
33/*
34 * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces
35 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
36 * ODEPrim.cs contains methods dealing with Prim editing, Prim
37 * characteristics and Kinetic motion.
38 * ODEDynamics.cs contains methods dealing with Prim Physical motion
39 * (dynamics) and the associated settings. Old Linear and angular
40 * motors for dynamic motion have been replace with MoveLinear()
41 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
42 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
43 * switch between 'VEHICLE' parameter use and general dynamics
44 * settings use.
45 */
46
47//#define SPAM
48
49using System;
50using System.Collections.Generic;
51using System.Reflection;
52using System.Runtime.InteropServices;
53using System.Threading;
54using log4net;
55using OpenMetaverse;
56using OdeAPI;
57using OpenSim.Framework;
58using OpenSim.Region.Physics.Manager;
59
60
61namespace OpenSim.Region.Physics.OdePlugin
62{
63 public class OdePrim : PhysicsActor
64 {
65 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
66
67 private bool m_isphysical;
68 private bool m_fakeisphysical;
69 private bool m_isphantom;
70 private bool m_fakeisphantom;
71 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
72 private bool m_fakeisVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
73
74 protected bool m_building;
75 protected bool m_forcePosOrRotation;
76 private bool m_iscolliding;
77
78 internal bool m_isSelected;
79 private bool m_delaySelect;
80 private bool m_lastdoneSelected;
81 internal bool m_outbounds;
82
83 private Quaternion m_lastorientation = new Quaternion();
84 private Quaternion _orientation;
85
86 private Vector3 _position;
87 private Vector3 _velocity;
88 private Vector3 _torque;
89 private Vector3 m_lastVelocity;
90 private Vector3 m_lastposition;
91 private Vector3 m_rotationalVelocity;
92 private Vector3 _size;
93 private Vector3 _acceleration;
94 private Vector3 m_angularlock = Vector3.One;
95 private IntPtr Amotor = IntPtr.Zero;
96
97 private Vector3 m_force;
98 private Vector3 m_forceacc;
99 private Vector3 m_angularForceacc;
100
101 private float m_invTimeStep = 50.0f;
102 private float m_timeStep = .02f;
103
104
105 private Vector3 m_PIDTarget;
106 private float m_PIDTau;
107 private bool m_usePID;
108
109 // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
110 // and are for non-VEHICLES only.
111
112 private float m_PIDHoverHeight;
113 private float m_PIDHoverTau;
114 private bool m_useHoverPID;
115 private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
116 private float m_targetHoverHeight;
117 private float m_groundHeight;
118 private float m_waterHeight;
119 private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
120
121 private int body_autodisable_frames = 5;
122 private int bodydisablecontrol = 0;
123
124
125 // Default we're a Geometry
126 private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
127 // Default colide nonphysical don't try to colide with anything
128 private const CollisionCategories m_default_collisionFlagsNotPhysical = 0;
129
130 private const CollisionCategories m_default_collisionFlagsPhysical = (CollisionCategories.Geom |
131 CollisionCategories.Character |
132 CollisionCategories.Land |
133 CollisionCategories.VolumeDtc);
134
135// private bool m_collidesLand = true;
136 private bool m_collidesWater;
137 public bool m_returnCollisions;
138
139 private bool m_NoColide; // for now only for internal use for bad meshs
140
141
142 // Default, Collide with Other Geometries, spaces and Bodies
143 private CollisionCategories m_collisionFlags = m_default_collisionFlagsNotPhysical;
144
145 public bool m_disabled;
146
147 public uint m_localID;
148
149 private IMesh m_mesh;
150 private object m_meshlock = new object();
151 private PrimitiveBaseShape _pbs;
152 public OdeScene _parent_scene;
153
154 /// <summary>
155 /// The physics space which contains prim geometry
156 /// </summary>
157 public IntPtr m_targetSpace = IntPtr.Zero;
158
159 public IntPtr prim_geom;
160 public IntPtr _triMeshData;
161
162 private PhysicsActor _parent;
163
164 private List<OdePrim> childrenPrim = new List<OdePrim>();
165
166
167 private bool m_throttleUpdates;
168 private int throttleCounter;
169 public float m_collisionscore;
170 int m_colliderfilter = 0;
171
172 public IntPtr collide_geom; // for objects: geom if single prim space it linkset
173
174 private float m_density = 10.000006836f; // Aluminum g/cm3;
175 private byte m_shapetype;
176 public bool _zeroFlag;
177 private bool m_lastUpdateSent;
178
179 public IntPtr Body = IntPtr.Zero;
180 public String Name { get; private set; }
181 private Vector3 _target_velocity;
182
183 public Vector3 primOOBsize; // prim real dimensions from mesh
184 public Vector3 primOOBoffset; // its centroid out of mesh or rest aabb
185 public float primOOBradiusSQ;
186 public d.Mass primdMass; // prim inertia information on it's own referencial
187 float primMass; // prim own mass
188 float primVolume; // prim own volume;
189 float _mass; // object mass acording to case
190 private bool hasOOBoffsetFromMesh = false; // if true we did compute it form mesh centroid, else from aabb
191
192 public int givefakepos = 0;
193 private Vector3 fakepos;
194 public int givefakeori = 0;
195 private Quaternion fakeori;
196
197 public int m_eventsubscription;
198 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
199
200 public volatile bool childPrim;
201
202 public ODEDynamics m_vehicle;
203
204 internal int m_material = (int)Material.Wood;
205 private float mu;
206 private float bounce;
207
208 /// <summary>
209 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
210 /// </summary>
211 public override bool IsPhysical // this is not reliable for internal use
212 {
213 get { return m_fakeisphysical; }
214 set
215 {
216 m_fakeisphysical = value; // we show imediatly to outside that we changed physical
217 // and also to stop imediatly some updates
218 // but real change will only happen in taintprocessing
219
220 if (!value) // Zero the remembered last velocity
221 m_lastVelocity = Vector3.Zero;
222 AddChange(changes.Physical, value);
223 }
224 }
225
226 public override bool IsVolumeDtc
227 {
228 get { return m_fakeisVolumeDetect; }
229 set
230 {
231 m_fakeisVolumeDetect = value;
232 AddChange(changes.VolumeDtc, value);
233 }
234 }
235
236
237 public override bool Phantom // this is not reliable for internal use
238 {
239 get { return m_fakeisphantom; }
240 set
241 {
242 m_fakeisphantom = value;
243 AddChange(changes.Phantom, value);
244 }
245 }
246
247 public override bool Building // this is not reliable for internal use
248 {
249 get { return m_building; }
250 set
251 {
252 if (value)
253 m_building = true;
254 AddChange(changes.building, value);
255 }
256 }
257
258 public override void getContactData(ref ContactData cdata)
259 {
260 cdata.mu = mu;
261 cdata.bounce = bounce;
262
263 // cdata.softcolide = m_softcolide;
264 cdata.softcolide = false;
265
266 if (m_isphysical)
267 {
268 ODEDynamics veh;
269 if (_parent != null)
270 veh = ((OdePrim)_parent).m_vehicle;
271 else
272 veh = m_vehicle;
273
274 if (veh != null && veh.Type != Vehicle.TYPE_NONE)
275 cdata.mu *= veh.FrictionFactor;
276 }
277 }
278
279 public override int PhysicsActorType
280 {
281 get { return (int)ActorTypes.Prim; }
282 set { return; }
283 }
284
285 public override bool SetAlwaysRun
286 {
287 get { return false; }
288 set { return; }
289 }
290
291 public override uint LocalID
292 {
293 get
294 {
295 return m_localID;
296 }
297 set
298 {
299 //m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
300 m_localID = value;
301 }
302 }
303
304 public override bool Grabbed
305 {
306 set { return; }
307 }
308
309 public override bool Selected
310 {
311 set
312 {
313 if (value)
314 m_isSelected = value; // if true set imediatly to stop moves etc
315 AddChange(changes.Selected, value);
316 }
317 }
318
319 public override bool Flying
320 {
321 // no flying prims for you
322 get { return false; }
323 set { }
324 }
325
326 public override bool IsColliding
327 {
328 get { return m_iscolliding; }
329 set
330 {
331 if (value)
332 {
333 m_colliderfilter += 2;
334 if (m_colliderfilter > 2)
335 m_colliderfilter = 2;
336 }
337 else
338 {
339 m_colliderfilter--;
340 if (m_colliderfilter < 0)
341 m_colliderfilter = 0;
342 }
343
344 if (m_colliderfilter == 0)
345 m_iscolliding = false;
346 else
347 m_iscolliding = true;
348 }
349 }
350
351 public override bool CollidingGround
352 {
353 get { return false; }
354 set { return; }
355 }
356
357 public override bool CollidingObj
358 {
359 get { return false; }
360 set { return; }
361 }
362
363 public override bool ThrottleUpdates
364 {
365 get { return m_throttleUpdates; }
366 set { m_throttleUpdates = value; }
367 }
368
369 public override bool Stopped
370 {
371 get { return _zeroFlag; }
372 }
373
374 public override Vector3 Position
375 {
376 get
377 {
378 if (givefakepos > 0)
379 return fakepos;
380 else
381 return _position;
382 }
383
384 set
385 {
386 fakepos = value;
387 givefakepos++;
388 AddChange(changes.Position, value);
389 }
390 }
391
392 public override Vector3 Size
393 {
394 get { return _size; }
395 set
396 {
397 if (value.IsFinite())
398 {
399 AddChange(changes.Size, value);
400 }
401 else
402 {
403 m_log.WarnFormat("[PHYSICS]: Got NaN Size on object {0}", Name);
404 }
405 }
406 }
407
408 public override float Mass
409 {
410 get { return primMass; }
411 }
412
413 public override Vector3 Force
414 {
415 //get { return Vector3.Zero; }
416 get { return m_force; }
417 set
418 {
419 if (value.IsFinite())
420 {
421 AddChange(changes.Force, value);
422 }
423 else
424 {
425 m_log.WarnFormat("[PHYSICS]: NaN in Force Applied to an Object {0}", Name);
426 }
427 }
428 }
429
430 public override void SetVolumeDetect(int param)
431 {
432 m_fakeisVolumeDetect = (param != 0);
433 AddChange(changes.VolumeDtc, m_fakeisVolumeDetect);
434 }
435
436 public override Vector3 GeometricCenter
437 {
438 // this is not real geometric center but a average of positions relative to root prim acording to
439 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
440 // ignoring tortured prims details since sl also seems to ignore
441 // so no real use in doing it on physics
442 get
443 {
444 return Vector3.Zero;
445 }
446 }
447
448 public override Vector3 CenterOfMass
449 {
450 get
451 {
452 d.Vector3 dtmp;
453 if (!childPrim && Body != IntPtr.Zero)
454 {
455 dtmp = d.BodyGetPosition(Body);
456 return new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
457 }
458 else if (prim_geom != IntPtr.Zero)
459 {
460 d.Quaternion dq;
461 d.GeomCopyQuaternion(prim_geom, out dq);
462 Quaternion q;
463 q.X = dq.X;
464 q.Y = dq.Y;
465 q.Z = dq.Z;
466 q.W = dq.W;
467
468 Vector3 Ptot = primOOBoffset * q;
469 dtmp = d.GeomGetPosition(prim_geom);
470 Ptot.X += dtmp.X;
471 Ptot.Y += dtmp.Y;
472 Ptot.Z += dtmp.Z;
473
474// if(childPrim) we only know about physical linksets
475 return Ptot;
476/*
477 float tmass = _mass;
478 Ptot *= tmass;
479
480 float m;
481
482 foreach (OdePrim prm in childrenPrim)
483 {
484 m = prm._mass;
485 Ptot += prm.CenterOfMass * m;
486 tmass += m;
487 }
488
489 if (tmass == 0)
490 tmass = 0;
491 else
492 tmass = 1.0f / tmass;
493
494 Ptot *= tmass;
495 return Ptot;
496 */
497 }
498 else
499 return _position;
500 }
501 }
502 /*
503 public override Vector3 PrimOOBsize
504 {
505 get
506 {
507 return primOOBsize;
508 }
509 }
510
511 public override Vector3 PrimOOBoffset
512 {
513 get
514 {
515 return primOOBoffset;
516 }
517 }
518
519 public override float PrimOOBRadiusSQ
520 {
521 get
522 {
523 return primOOBradiusSQ;
524 }
525 }
526 */
527 public override PrimitiveBaseShape Shape
528 {
529 set
530 {
531/*
532 IMesh mesh = null;
533 if (_parent_scene.needsMeshing(value))
534 {
535 bool convex;
536 if (m_shapetype == 0)
537 convex = false;
538 else
539 convex = true;
540 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true, convex);
541 }
542
543 if (mesh != null)
544 {
545 lock (m_meshlock)
546 m_mesh = mesh;
547 }
548*/
549 AddChange(changes.Shape, value);
550 }
551 }
552
553 public override byte PhysicsShapeType
554 {
555 get
556 {
557 return m_shapetype;
558 }
559 set
560 {
561 m_shapetype = value;
562 AddChange(changes.Shape, null);
563 }
564 }
565
566
567 public override Vector3 Velocity
568 {
569 get
570 {
571 if (_zeroFlag)
572 return Vector3.Zero;
573 return _velocity;
574 }
575 set
576 {
577 if (value.IsFinite())
578 {
579 AddChange(changes.Velocity, value);
580 // _velocity = value;
581
582 }
583 else
584 {
585 m_log.WarnFormat("[PHYSICS]: Got NaN Velocity in Object {0}", Name);
586 }
587
588 }
589 }
590
591 public override Vector3 Torque
592 {
593 get
594 {
595 if (!IsPhysical || Body == IntPtr.Zero)
596 return Vector3.Zero;
597
598 return _torque;
599 }
600
601 set
602 {
603 if (value.IsFinite())
604 {
605 AddChange(changes.Torque, value);
606 }
607 else
608 {
609 m_log.WarnFormat("[PHYSICS]: Got NaN Torque in Object {0}", Name);
610 }
611 }
612 }
613
614 public override float CollisionScore
615 {
616 get { return m_collisionscore; }
617 set { m_collisionscore = value; }
618 }
619
620 public override bool Kinematic
621 {
622 get { return false; }
623 set { }
624 }
625
626 public override Quaternion Orientation
627 {
628 get
629 {
630 if (givefakeori > 0)
631 return fakeori;
632 else
633
634 return _orientation;
635 }
636 set
637 {
638 if (QuaternionIsFinite(value))
639 {
640 fakeori = value;
641 givefakeori++;
642 AddChange(changes.Orientation, value);
643 }
644 else
645 m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name);
646
647 }
648 }
649
650 public override Vector3 Acceleration
651 {
652 get { return _acceleration; }
653 set { }
654 }
655
656 public override Vector3 RotationalVelocity
657 {
658 get
659 {
660 Vector3 pv = Vector3.Zero;
661 if (_zeroFlag)
662 return pv;
663
664 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f))
665 return pv;
666
667 return m_rotationalVelocity;
668 }
669 set
670 {
671 if (value.IsFinite())
672 {
673 m_rotationalVelocity = value;
674 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
675 d.BodyEnable(Body);
676 }
677 else
678 {
679 m_log.WarnFormat("[PHYSICS]: Got NaN RotationalVelocity in Object {0}", Name);
680 }
681 }
682 }
683
684
685 public override float Buoyancy
686 {
687 get { return m_buoyancy; }
688 set
689 {
690 m_buoyancy = value;
691 }
692 }
693
694 public override bool FloatOnWater
695 {
696 set
697 {
698 AddChange(changes.CollidesWater, value);
699 }
700 }
701
702 public override Vector3 PIDTarget
703 {
704 set
705 {
706 if (value.IsFinite())
707 {
708 m_PIDTarget = value;
709 }
710 else
711 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name);
712 }
713 }
714
715 public override bool PIDActive { set { m_usePID = value; } }
716 public override float PIDTau
717 {
718 set
719 {
720 if (value <= 0)
721 m_PIDTau = 0;
722 else
723 {
724 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
725 if (value < mint)
726 m_PIDTau = mint;
727 else
728 m_PIDTau = value;
729 }
730 }
731 }
732
733 public override float PIDHoverHeight
734 {
735 set
736 {
737 m_PIDHoverHeight = value;
738 if (value == 0)
739 m_useHoverPID = false;
740 }
741 }
742 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
743 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
744 public override float PIDHoverTau
745 {
746 set
747 {
748 if (value <= 0)
749 m_PIDHoverTau = 0;
750 else
751 {
752 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
753 if (value < mint)
754 m_PIDHoverTau = mint;
755 else
756 m_PIDHoverTau = value;
757 }
758 }
759 }
760
761 public override Quaternion APIDTarget { set { return; } }
762
763 public override bool APIDActive { set { return; } }
764
765 public override float APIDStrength { set { return; } }
766
767 public override float APIDDamping { set { return; } }
768
769 public override int VehicleType
770 {
771 // we may need to put a fake on this
772 get
773 {
774 if (m_vehicle == null)
775 return (int)Vehicle.TYPE_NONE;
776 else
777 return (int)m_vehicle.Type;
778 }
779 set
780 {
781 AddChange(changes.VehicleType, value);
782 }
783 }
784
785 public override void VehicleFloatParam(int param, float value)
786 {
787 strVehicleFloatParam fp = new strVehicleFloatParam();
788 fp.param = param;
789 fp.value = value;
790 AddChange(changes.VehicleFloatParam, fp);
791 }
792
793 public override void VehicleVectorParam(int param, Vector3 value)
794 {
795 strVehicleVectorParam fp = new strVehicleVectorParam();
796 fp.param = param;
797 fp.value = value;
798 AddChange(changes.VehicleVectorParam, fp);
799 }
800
801 public override void VehicleRotationParam(int param, Quaternion value)
802 {
803 strVehicleQuatParam fp = new strVehicleQuatParam();
804 fp.param = param;
805 fp.value = value;
806 AddChange(changes.VehicleRotationParam, fp);
807 }
808
809 public override void VehicleFlags(int param, bool value)
810 {
811 strVehicleBoolParam bp = new strVehicleBoolParam();
812 bp.param = param;
813 bp.value = value;
814 AddChange(changes.VehicleFlags, bp);
815 }
816
817 public override void SetVehicle(object vdata)
818 {
819 AddChange(changes.SetVehicle, vdata);
820 }
821 public void SetAcceleration(Vector3 accel)
822 {
823 _acceleration = accel;
824 }
825
826 public override void AddForce(Vector3 force, bool pushforce)
827 {
828 if (force.IsFinite())
829 {
830 AddChange(changes.AddForce, force * m_invTimeStep);
831 }
832 else
833 {
834 m_log.WarnFormat("[PHYSICS]: Got Invalid linear force vector from Scene in Object {0}", Name);
835 }
836 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
837 }
838
839 public override void AddAngularForce(Vector3 force, bool pushforce)
840 {
841 if (force.IsFinite())
842 {
843 AddChange(changes.AddAngForce, force * m_invTimeStep);
844 }
845 else
846 {
847 m_log.WarnFormat("[PHYSICS]: Got Invalid Angular force vector from Scene in Object {0}", Name);
848 }
849 }
850
851 public override void CrossingFailure()
852 {
853 if (m_outbounds)
854 {
855 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f);
856 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f);
857 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
858
859 m_lastposition = _position;
860 _velocity.X = 0;
861 _velocity.Y = 0;
862 _velocity.Z = 0;
863
864 m_lastVelocity = _velocity;
865 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
866 m_vehicle.Stop();
867
868 if(Body != IntPtr.Zero)
869 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
870 if (prim_geom != IntPtr.Zero)
871 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
872
873 m_outbounds = false;
874 changeDisable(false);
875 base.RequestPhysicsterseUpdate();
876 }
877 }
878
879 public override void SetMomentum(Vector3 momentum)
880 {
881 }
882
883 public override void SetMaterial(int pMaterial)
884 {
885 m_material = pMaterial;
886 mu = _parent_scene.m_materialContactsData[pMaterial].mu;
887 bounce = _parent_scene.m_materialContactsData[pMaterial].bounce;
888 }
889
890 public void setPrimForRemoval()
891 {
892 AddChange(changes.Remove, null);
893 }
894
895 public override void link(PhysicsActor obj)
896 {
897 AddChange(changes.Link, obj);
898 }
899
900 public override void delink()
901 {
902 AddChange(changes.DeLink, null);
903 }
904
905 public override void LockAngularMotion(Vector3 axis)
906 {
907 // reverse the zero/non zero values for ODE.
908 if (axis.IsFinite())
909 {
910 axis.X = (axis.X > 0) ? 1f : 0f;
911 axis.Y = (axis.Y > 0) ? 1f : 0f;
912 axis.Z = (axis.Z > 0) ? 1f : 0f;
913 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
914 AddChange(changes.AngLock, axis);
915 }
916 else
917 {
918 m_log.WarnFormat("[PHYSICS]: Got NaN locking axis from Scene on Object {0}", Name);
919 }
920 }
921
922 public override void SubscribeEvents(int ms)
923 {
924 m_eventsubscription = ms;
925 _parent_scene.AddCollisionEventReporting(this);
926 }
927
928 public override void UnSubscribeEvents()
929 {
930 _parent_scene.RemoveCollisionEventReporting(this);
931 m_eventsubscription = 0;
932 }
933
934 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
935 {
936 if (CollisionEventsThisFrame == null)
937 CollisionEventsThisFrame = new CollisionEventUpdate();
938
939 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
940 }
941
942 public void SendCollisions()
943 {
944 if (CollisionEventsThisFrame == null)
945 return;
946
947 base.SendCollisionUpdate(CollisionEventsThisFrame);
948
949 if (CollisionEventsThisFrame.m_objCollisionList.Count == 0)
950 CollisionEventsThisFrame = null;
951 else
952 CollisionEventsThisFrame = new CollisionEventUpdate();
953 }
954
955 public override bool SubscribedEvents()
956 {
957 if (m_eventsubscription > 0)
958 return true;
959 return false;
960 }
961
962
963 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
964 Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical,bool pisPhantom,byte _shapeType,uint plocalID)
965 {
966 Name = primName;
967 LocalID = plocalID;
968
969 m_vehicle = null;
970
971 if (!pos.IsFinite())
972 {
973 pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
974 parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
975 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Position for {0}", Name);
976 }
977 _position = pos;
978 givefakepos = 0;
979
980 m_timeStep = parent_scene.ODE_STEPSIZE;
981 m_invTimeStep = 1f / m_timeStep;
982
983 m_density = parent_scene.geomDefaultDensity;
984 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
985 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
986
987 prim_geom = IntPtr.Zero;
988 collide_geom = IntPtr.Zero;
989 Body = IntPtr.Zero;
990
991 if (!size.IsFinite())
992 {
993 size = new Vector3(0.5f, 0.5f, 0.5f);
994 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Size for {0}", Name);
995 }
996
997 if (size.X <= 0) size.X = 0.01f;
998 if (size.Y <= 0) size.Y = 0.01f;
999 if (size.Z <= 0) size.Z = 0.01f;
1000
1001 _size = size;
1002
1003 if (!QuaternionIsFinite(rotation))
1004 {
1005 rotation = Quaternion.Identity;
1006 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Rotation for {0}", Name);
1007 }
1008
1009 _orientation = rotation;
1010 givefakeori = 0;
1011
1012 _pbs = pbs;
1013
1014 _parent_scene = parent_scene;
1015 m_targetSpace = IntPtr.Zero;
1016
1017 if (pos.Z < 0)
1018 {
1019 m_isphysical = false;
1020 }
1021 else
1022 {
1023 m_isphysical = pisPhysical;
1024 }
1025 m_fakeisphysical = m_isphysical;
1026
1027 m_isVolumeDetect = false;
1028 m_fakeisVolumeDetect = false;
1029
1030 m_force = Vector3.Zero;
1031
1032 m_iscolliding = false;
1033 m_colliderfilter = 0;
1034 m_NoColide = false;
1035
1036 hasOOBoffsetFromMesh = false;
1037 _triMeshData = IntPtr.Zero;
1038
1039 m_shapetype = _shapeType;
1040
1041 m_lastdoneSelected = false;
1042 m_isSelected = false;
1043 m_delaySelect = false;
1044
1045 m_isphantom = pisPhantom;
1046 m_fakeisphantom = pisPhantom;
1047
1048 mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
1049 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
1050
1051 CalcPrimBodyData();
1052
1053 m_mesh = null;
1054 if (_parent_scene.needsMeshing(pbs))
1055 {
1056 bool convex;
1057 if (m_shapetype == 0)
1058 convex = false;
1059 else
1060 convex = true;
1061
1062 m_mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true, convex);
1063 }
1064
1065
1066 m_building = true; // control must set this to false when done
1067
1068 AddChange(changes.Add, null);
1069 }
1070
1071 private void resetCollisionAccounting()
1072 {
1073 m_collisionscore = 0;
1074 }
1075
1076 private void UpdateCollisionCatFlags()
1077 {
1078 if(m_isphysical && m_disabled)
1079 {
1080 m_collisionCategories = 0;
1081 m_collisionFlags = 0;
1082 }
1083
1084 else if (m_isSelected)
1085 {
1086 m_collisionCategories = CollisionCategories.Selected;
1087 m_collisionFlags = 0;
1088 }
1089
1090 else if (m_isVolumeDetect)
1091 {
1092 m_collisionCategories = CollisionCategories.VolumeDtc;
1093 if (m_isphysical)
1094 m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character;
1095 else
1096 m_collisionFlags = 0;
1097 }
1098 else if (m_isphantom)
1099 {
1100 m_collisionCategories = CollisionCategories.Phantom;
1101 if (m_isphysical)
1102 m_collisionFlags = CollisionCategories.Land;
1103 else
1104 m_collisionFlags = 0;
1105 }
1106 else
1107 {
1108 m_collisionCategories = CollisionCategories.Geom;
1109 if (m_isphysical)
1110 m_collisionFlags = m_default_collisionFlagsPhysical;
1111 else
1112 m_collisionFlags = m_default_collisionFlagsNotPhysical;
1113 }
1114 }
1115
1116 private void ApplyCollisionCatFlags()
1117 {
1118 if (prim_geom != IntPtr.Zero)
1119 {
1120 if (!childPrim && childrenPrim.Count > 0)
1121 {
1122 foreach (OdePrim prm in childrenPrim)
1123 {
1124 if (m_isphysical && m_disabled)
1125 {
1126 prm.m_collisionCategories = 0;
1127 prm.m_collisionFlags = 0;
1128 }
1129 else
1130 {
1131 // preserve some
1132 if (prm.m_isSelected)
1133 {
1134 prm.m_collisionCategories = CollisionCategories.Selected;
1135 prm.m_collisionFlags = 0;
1136 }
1137 else if (prm.m_isVolumeDetect)
1138 {
1139 prm.m_collisionCategories = CollisionCategories.VolumeDtc;
1140 if (m_isphysical)
1141 prm.m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character;
1142 else
1143 prm.m_collisionFlags = 0;
1144 }
1145 else if (prm.m_isphantom)
1146 {
1147 prm.m_collisionCategories = CollisionCategories.Phantom;
1148 if (m_isphysical)
1149 prm.m_collisionFlags = CollisionCategories.Land;
1150 else
1151 prm.m_collisionFlags = 0;
1152 }
1153 else
1154 {
1155 prm.m_collisionCategories = m_collisionCategories;
1156 prm.m_collisionFlags = m_collisionFlags;
1157 }
1158 }
1159
1160 if (prm.prim_geom != IntPtr.Zero)
1161 {
1162 if (prm.m_NoColide)
1163 {
1164 d.GeomSetCategoryBits(prm.prim_geom, 0);
1165 if (m_isphysical)
1166 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
1167 else
1168 d.GeomSetCollideBits(prm.prim_geom, 0);
1169 }
1170 else
1171 {
1172 d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
1173 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
1174 }
1175 }
1176 }
1177 }
1178
1179 if (m_NoColide)
1180 {
1181 d.GeomSetCategoryBits(prim_geom, 0);
1182 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
1183 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
1184 {
1185 d.GeomSetCategoryBits(collide_geom, 0);
1186 d.GeomSetCollideBits(collide_geom, (uint)CollisionCategories.Land);
1187 }
1188 }
1189 else
1190 {
1191 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1192 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1193 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
1194 {
1195 d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories);
1196 d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags);
1197 }
1198 }
1199 }
1200 }
1201
1202 private void createAMotor(Vector3 axis)
1203 {
1204 if (Body == IntPtr.Zero)
1205 return;
1206
1207 if (Amotor != IntPtr.Zero)
1208 {
1209 d.JointDestroy(Amotor);
1210 Amotor = IntPtr.Zero;
1211 }
1212
1213 int axisnum = 3 - (int)(axis.X + axis.Y + axis.Z);
1214
1215 if (axisnum <= 0)
1216 return;
1217
1218 // stop it
1219 d.BodySetTorque(Body, 0, 0, 0);
1220 d.BodySetAngularVel(Body, 0, 0, 0);
1221
1222 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
1223 d.JointAttach(Amotor, Body, IntPtr.Zero);
1224
1225 d.JointSetAMotorMode(Amotor, 0);
1226
1227 d.JointSetAMotorNumAxes(Amotor, axisnum);
1228
1229 // get current orientation to lock
1230
1231 d.Quaternion dcur = d.BodyGetQuaternion(Body);
1232 Quaternion curr; // crap convertion between identical things
1233 curr.X = dcur.X;
1234 curr.Y = dcur.Y;
1235 curr.Z = dcur.Z;
1236 curr.W = dcur.W;
1237 Vector3 ax;
1238
1239 int i = 0;
1240 int j = 0;
1241 if (axis.X == 0)
1242 {
1243 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X
1244 // ODE should do this with axis relative to body 1 but seems to fail
1245 d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z);
1246 d.JointSetAMotorAngle(Amotor, 0, 0);
1247 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, -0.000001f);
1248 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0.000001f);
1249 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
1250 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
1251 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
1252 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
1253 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f);
1254 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f);
1255 i++;
1256 j = 256; // move to next axis set
1257 }
1258
1259 if (axis.Y == 0)
1260 {
1261 ax = (new Vector3(0, 1, 0)) * curr;
1262 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1263 d.JointSetAMotorAngle(Amotor, i, 0);
1264 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, -0.000001f);
1265 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0.000001f);
1266 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1267 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1268 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1269 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1270 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1271 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1272 i++;
1273 j += 256;
1274 }
1275
1276 if (axis.Z == 0)
1277 {
1278 ax = (new Vector3(0, 0, 1)) * curr;
1279 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1280 d.JointSetAMotorAngle(Amotor, i, 0);
1281 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, -0.000001f);
1282 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0.000001f);
1283 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1284 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1285 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1286 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1287 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1288 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1289 }
1290 }
1291
1292 private bool setMesh(OdeScene parent_scene)
1293 {
1294 IntPtr vertices, indices;
1295 int vertexCount, indexCount;
1296 int vertexStride, triStride;
1297
1298 if (Body != IntPtr.Zero)
1299 {
1300 if (childPrim)
1301 {
1302 if (_parent != null)
1303 {
1304 OdePrim parent = (OdePrim)_parent;
1305 parent.ChildDelink(this, false);
1306 }
1307 }
1308 else
1309 {
1310 DestroyBody();
1311 }
1312 }
1313
1314 IMesh mesh = null;
1315
1316
1317 lock (m_meshlock)
1318 {
1319 if (m_mesh == null)
1320 {
1321 bool convex;
1322 if (m_shapetype == 0)
1323 convex = false;
1324 else
1325 convex = true;
1326
1327 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true, convex);
1328 }
1329 else
1330 {
1331 mesh = m_mesh;
1332 }
1333
1334 if (mesh == null)
1335 {
1336 m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z);
1337 return false;
1338 }
1339
1340
1341 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
1342 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
1343
1344 if (vertexCount == 0 || indexCount == 0)
1345 {
1346 m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. mesh UUID {4}",
1347 Name, _position.X, _position.Y, _position.Z, _pbs.SculptTexture.ToString());
1348 mesh.releaseSourceMeshData();
1349 return false;
1350 }
1351
1352 primOOBoffset = mesh.GetCentroid();
1353 hasOOBoffsetFromMesh = true;
1354
1355 mesh.releaseSourceMeshData();
1356 m_mesh = null;
1357 }
1358
1359 IntPtr geo = IntPtr.Zero;
1360
1361 try
1362 {
1363 _triMeshData = d.GeomTriMeshDataCreate();
1364
1365 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1366 d.GeomTriMeshDataPreprocess(_triMeshData);
1367
1368 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1369 geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null);
1370 }
1371
1372 catch (Exception e)
1373 {
1374 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e);
1375 if (_triMeshData != IntPtr.Zero)
1376 {
1377 d.GeomTriMeshDataDestroy(_triMeshData);
1378 _triMeshData = IntPtr.Zero;
1379 }
1380 return false;
1381 }
1382
1383 SetGeom(geo);
1384 return true;
1385 }
1386
1387 private void SetGeom(IntPtr geom)
1388 {
1389 prim_geom = geom;
1390 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
1391 if (prim_geom != IntPtr.Zero)
1392 {
1393 if (m_NoColide)
1394 {
1395 d.GeomSetCategoryBits(prim_geom, 0);
1396 if (m_isphysical)
1397 {
1398 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
1399 }
1400 else
1401 {
1402 d.GeomSetCollideBits(prim_geom, 0);
1403 d.GeomDisable(prim_geom);
1404 }
1405 }
1406 else
1407 {
1408 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1409 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1410 }
1411
1412 CalcPrimBodyData();
1413
1414 _parent_scene.geom_name_map[prim_geom] = Name;
1415 _parent_scene.actor_name_map[prim_geom] = this;
1416
1417 }
1418 else
1419 m_log.Warn("Setting bad Geom");
1420 }
1421
1422
1423 /// <summary>
1424 /// Create a geometry for the given mesh in the given target space.
1425 /// </summary>
1426 /// <param name="m_targetSpace"></param>
1427 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param>
1428 private void CreateGeom()
1429 {
1430 if (_triMeshData != IntPtr.Zero)
1431 {
1432 d.GeomTriMeshDataDestroy(_triMeshData);
1433 _triMeshData = IntPtr.Zero;
1434 }
1435
1436 bool haveMesh = false;
1437 hasOOBoffsetFromMesh = false;
1438 m_NoColide = false;
1439
1440 if (_parent_scene.needsMeshing(_pbs))
1441 {
1442 haveMesh = setMesh(_parent_scene); // this will give a mesh to non trivial known prims
1443 if (!haveMesh)
1444 m_NoColide = true;
1445 }
1446
1447 if (!haveMesh)
1448 {
1449 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1
1450 && _size.X == _size.Y && _size.Y == _size.Z)
1451 { // it's a sphere
1452 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1453 try
1454 {
1455 SetGeom(d.CreateSphere(m_targetSpace, _size.X * 0.5f));
1456 }
1457 catch (Exception e)
1458 {
1459 m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e);
1460 return;
1461 }
1462 }
1463 else
1464 {// do it as a box
1465 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1466 try
1467 {
1468 //Console.WriteLine(" CreateGeom 4");
1469 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1470 }
1471 catch (Exception e)
1472 {
1473 m_log.Warn("[PHYSICS]: Create box failed: {0}", e);
1474 return;
1475 }
1476 }
1477 }
1478 }
1479
1480 /// <summary>
1481 /// Set a new geometry for this prim.
1482 /// </summary>
1483 /// <param name="geom"></param>
1484 private void RemoveGeom()
1485 {
1486 if (prim_geom != IntPtr.Zero)
1487 {
1488 _parent_scene.geom_name_map.Remove(prim_geom);
1489 _parent_scene.actor_name_map.Remove(prim_geom);
1490 try
1491 {
1492 d.GeomDestroy(prim_geom);
1493 if (_triMeshData != IntPtr.Zero)
1494 {
1495 d.GeomTriMeshDataDestroy(_triMeshData);
1496 _triMeshData = IntPtr.Zero;
1497 }
1498 }
1499 // catch (System.AccessViolationException)
1500 catch (Exception e)
1501 {
1502 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e);
1503 }
1504
1505 prim_geom = IntPtr.Zero;
1506 collide_geom = IntPtr.Zero;
1507 }
1508 else
1509 {
1510 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name);
1511 }
1512 Body = IntPtr.Zero;
1513 hasOOBoffsetFromMesh = false;
1514 CalcPrimBodyData();
1515 }
1516/*
1517 private void ChildSetGeom(OdePrim odePrim)
1518 {
1519 // well..
1520 DestroyBody();
1521 MakeBody();
1522 }
1523*/
1524 //sets non physical prim m_targetSpace to right space in spaces grid for static prims
1525 // should only be called for non physical prims unless they are becoming non physical
1526 private void SetInStaticSpace(OdePrim prim)
1527 {
1528 IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace);
1529 prim.m_targetSpace = targetSpace;
1530 collide_geom = IntPtr.Zero;
1531 }
1532
1533 public void enableBodySoft()
1534 {
1535 m_disabled = false;
1536 if (!childPrim && !m_isSelected)
1537 {
1538 if (m_isphysical && Body != IntPtr.Zero)
1539 {
1540 UpdateCollisionCatFlags();
1541 ApplyCollisionCatFlags();
1542
1543 d.BodyEnable(Body);
1544 }
1545 }
1546 resetCollisionAccounting();
1547 }
1548
1549 private void disableBodySoft()
1550 {
1551 m_disabled = true;
1552 if (!childPrim)
1553 {
1554 if (m_isphysical && Body != IntPtr.Zero)
1555 {
1556 if (m_isSelected)
1557 m_collisionFlags = CollisionCategories.Selected;
1558 else
1559 m_collisionCategories = 0;
1560 m_collisionFlags = 0;
1561 ApplyCollisionCatFlags();
1562 d.BodyDisable(Body);
1563 }
1564 }
1565 }
1566
1567 private void MakeBody()
1568 {
1569 if (!m_isphysical) // only physical get bodies
1570 return;
1571
1572 if (childPrim) // child prims don't get bodies;
1573 return;
1574
1575 if (m_building)
1576 return;
1577
1578 if (prim_geom == IntPtr.Zero)
1579 {
1580 m_log.Warn("[PHYSICS]: Unable to link the linkset. Root has no geom yet");
1581 return;
1582 }
1583
1584 if (Body != IntPtr.Zero)
1585 {
1586 d.BodyDestroy(Body);
1587 Body = IntPtr.Zero;
1588 m_log.Warn("[PHYSICS]: MakeBody called having a body");
1589 }
1590
1591
1592 if (d.GeomGetBody(prim_geom) != IntPtr.Zero)
1593 {
1594 d.GeomSetBody(prim_geom, IntPtr.Zero);
1595 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body");
1596 }
1597
1598 d.Matrix3 mymat = new d.Matrix3();
1599 d.Quaternion myrot = new d.Quaternion();
1600 d.Mass objdmass = new d.Mass { };
1601
1602 Body = d.BodyCreate(_parent_scene.world);
1603
1604 DMassDup(ref primdMass, out objdmass);
1605
1606 // rotate inertia
1607 myrot.X = _orientation.X;
1608 myrot.Y = _orientation.Y;
1609 myrot.Z = _orientation.Z;
1610 myrot.W = _orientation.W;
1611
1612 d.RfromQ(out mymat, ref myrot);
1613 d.MassRotate(ref objdmass, ref mymat);
1614
1615 // set the body rotation
1616 d.BodySetRotation(Body, ref mymat);
1617
1618 // recompute full object inertia if needed
1619 if (childrenPrim.Count > 0)
1620 {
1621 d.Matrix3 mat = new d.Matrix3();
1622 d.Quaternion quat = new d.Quaternion();
1623 d.Mass tmpdmass = new d.Mass { };
1624 Vector3 rcm;
1625
1626 rcm.X = _position.X + objdmass.c.X;
1627 rcm.Y = _position.Y + objdmass.c.Y;
1628 rcm.Z = _position.Z + objdmass.c.Z;
1629
1630 lock (childrenPrim)
1631 {
1632 foreach (OdePrim prm in childrenPrim)
1633 {
1634 if (prm.prim_geom == IntPtr.Zero)
1635 {
1636 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements, skipping it. No geom yet");
1637 continue;
1638 }
1639
1640 DMassCopy(ref prm.primdMass, ref tmpdmass);
1641
1642 // apply prim current rotation to inertia
1643 quat.X = prm._orientation.X;
1644 quat.Y = prm._orientation.Y;
1645 quat.Z = prm._orientation.Z;
1646 quat.W = prm._orientation.W;
1647 d.RfromQ(out mat, ref quat);
1648 d.MassRotate(ref tmpdmass, ref mat);
1649
1650 Vector3 ppos = prm._position;
1651 ppos.X += tmpdmass.c.X - rcm.X;
1652 ppos.Y += tmpdmass.c.Y - rcm.Y;
1653 ppos.Z += tmpdmass.c.Z - rcm.Z;
1654
1655 // refer inertia to root prim center of mass position
1656 d.MassTranslate(ref tmpdmass,
1657 ppos.X,
1658 ppos.Y,
1659 ppos.Z);
1660
1661 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
1662 // fix prim colision cats
1663
1664 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero)
1665 {
1666 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
1667 m_log.Warn("[PHYSICS]: MakeBody child geom already had a body");
1668 }
1669
1670 d.GeomClearOffset(prm.prim_geom);
1671 d.GeomSetBody(prm.prim_geom, Body);
1672 prm.Body = Body;
1673 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation
1674 }
1675 }
1676 }
1677
1678 d.GeomClearOffset(prim_geom); // make sure we don't have a hidden offset
1679 // associate root geom with body
1680 d.GeomSetBody(prim_geom, Body);
1681
1682 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
1683 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z);
1684
1685 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
1686 myrot.W = -myrot.W;
1687 d.RfromQ(out mymat, ref myrot);
1688 d.MassRotate(ref objdmass, ref mymat);
1689 d.BodySetMass(Body, ref objdmass);
1690 _mass = objdmass.mass;
1691
1692 // disconnect from world gravity so we can apply buoyancy
1693 d.BodySetGravityMode(Body, false);
1694
1695 d.BodySetAutoDisableFlag(Body, true);
1696 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1697 // d.BodySetLinearDampingThreshold(Body, 0.01f);
1698 // d.BodySetAngularDampingThreshold(Body, 0.001f);
1699 d.BodySetDamping(Body, .002f, .002f);
1700
1701 if (m_targetSpace != IntPtr.Zero)
1702 {
1703 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1704 if (d.SpaceQuery(m_targetSpace, prim_geom))
1705 d.SpaceRemove(m_targetSpace, prim_geom);
1706 }
1707
1708
1709 if (childrenPrim.Count == 0)
1710 {
1711 collide_geom = prim_geom;
1712 m_targetSpace = _parent_scene.ActiveSpace;
1713 d.SpaceAdd(m_targetSpace, prim_geom);
1714 }
1715 else
1716 {
1717 m_targetSpace = d.HashSpaceCreate(_parent_scene.ActiveSpace);
1718 d.HashSpaceSetLevels(m_targetSpace, -2, 8);
1719 d.SpaceSetSublevel(m_targetSpace, 3);
1720 d.SpaceSetCleanup(m_targetSpace, false);
1721 d.SpaceAdd(m_targetSpace, prim_geom);
1722
1723 d.GeomSetCategoryBits(m_targetSpace, (uint)(CollisionCategories.Space |
1724 CollisionCategories.Geom |
1725 CollisionCategories.Phantom |
1726 CollisionCategories.VolumeDtc
1727 ));
1728 d.GeomSetCollideBits(m_targetSpace, 0);
1729 collide_geom = m_targetSpace;
1730 }
1731
1732 if (m_delaySelect)
1733 {
1734 m_isSelected = true;
1735 m_delaySelect = false;
1736 }
1737
1738 lock (childrenPrim)
1739 {
1740 foreach (OdePrim prm in childrenPrim)
1741 {
1742 if (prm.prim_geom == IntPtr.Zero)
1743 continue;
1744
1745 Vector3 ppos = prm._position;
1746 d.GeomSetOffsetWorldPosition(prm.prim_geom, ppos.X, ppos.Y, ppos.Z); // set relative position
1747
1748 if (prm.m_targetSpace != m_targetSpace)
1749 {
1750 if (prm.m_targetSpace != IntPtr.Zero)
1751 {
1752 _parent_scene.waitForSpaceUnlock(prm.m_targetSpace);
1753 if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom))
1754 d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
1755 }
1756 prm.m_targetSpace = m_targetSpace;
1757 d.SpaceAdd(m_targetSpace, prm.prim_geom);
1758 }
1759
1760 prm.m_collisionscore = 0;
1761
1762 if(!m_disabled)
1763 prm.m_disabled = false;
1764
1765 _parent_scene.addActivePrim(prm);
1766 }
1767 }
1768
1769 // The body doesn't already have a finite rotation mode set here
1770 if ((!m_angularlock.ApproxEquals(Vector3.One, 0.0f)) && _parent == null)
1771 {
1772 createAMotor(m_angularlock);
1773 }
1774
1775 m_collisionscore = 0;
1776
1777 UpdateCollisionCatFlags();
1778 ApplyCollisionCatFlags();
1779
1780 if (m_isSelected || m_disabled)
1781 {
1782 d.BodyDisable(Body);
1783 }
1784 else
1785 {
1786 d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z);
1787 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
1788 }
1789
1790 _parent_scene.addActivePrim(this);
1791 _parent_scene.addActiveGroups(this);
1792 }
1793
1794 private void DestroyBody()
1795 {
1796 if (Body != IntPtr.Zero)
1797 {
1798 _parent_scene.remActivePrim(this);
1799
1800 collide_geom = IntPtr.Zero;
1801
1802 if (m_disabled)
1803 m_collisionCategories = 0;
1804 else if (m_isSelected)
1805 m_collisionCategories = CollisionCategories.Selected;
1806 else if (m_isVolumeDetect)
1807 m_collisionCategories = CollisionCategories.VolumeDtc;
1808 else if (m_isphantom)
1809 m_collisionCategories = CollisionCategories.Phantom;
1810 else
1811 m_collisionCategories = CollisionCategories.Geom;
1812
1813 m_collisionFlags = 0;
1814
1815 if (prim_geom != IntPtr.Zero)
1816 {
1817 if (m_NoColide)
1818 {
1819 d.GeomSetCategoryBits(prim_geom, 0);
1820 d.GeomSetCollideBits(prim_geom, 0);
1821 }
1822 else
1823 {
1824 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1825 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1826 }
1827 UpdateDataFromGeom();
1828 d.GeomSetBody(prim_geom, IntPtr.Zero);
1829 SetInStaticSpace(this);
1830 }
1831
1832 if (!childPrim)
1833 {
1834 lock (childrenPrim)
1835 {
1836 foreach (OdePrim prm in childrenPrim)
1837 {
1838 _parent_scene.remActivePrim(prm);
1839
1840 if (prm.m_isSelected)
1841 prm.m_collisionCategories = CollisionCategories.Selected;
1842 else if (prm.m_isVolumeDetect)
1843 prm.m_collisionCategories = CollisionCategories.VolumeDtc;
1844 else if (prm.m_isphantom)
1845 prm.m_collisionCategories = CollisionCategories.Phantom;
1846 else
1847 prm.m_collisionCategories = CollisionCategories.Geom;
1848
1849 prm.m_collisionFlags = 0;
1850
1851 if (prm.prim_geom != IntPtr.Zero)
1852 {
1853 if (prm.m_NoColide)
1854 {
1855 d.GeomSetCategoryBits(prm.prim_geom, 0);
1856 d.GeomSetCollideBits(prm.prim_geom, 0);
1857 }
1858 else
1859 {
1860 d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
1861 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
1862 }
1863 prm.UpdateDataFromGeom();
1864 SetInStaticSpace(prm);
1865 }
1866 prm.Body = IntPtr.Zero;
1867 prm._mass = prm.primMass;
1868 prm.m_collisionscore = 0;
1869 }
1870 }
1871 if (Amotor != IntPtr.Zero)
1872 {
1873 d.JointDestroy(Amotor);
1874 Amotor = IntPtr.Zero;
1875 }
1876 _parent_scene.remActiveGroup(this);
1877 d.BodyDestroy(Body);
1878 }
1879 Body = IntPtr.Zero;
1880 }
1881 _mass = primMass;
1882 m_collisionscore = 0;
1883 }
1884
1885 private void FixInertia(Vector3 NewPos,Quaternion newrot)
1886 {
1887 d.Matrix3 mat = new d.Matrix3();
1888 d.Quaternion quat = new d.Quaternion();
1889
1890 d.Mass tmpdmass = new d.Mass { };
1891 d.Mass objdmass = new d.Mass { };
1892
1893 d.BodyGetMass(Body, out tmpdmass);
1894 objdmass = tmpdmass;
1895
1896 d.Vector3 dobjpos;
1897 d.Vector3 thispos;
1898
1899 // get current object position and rotation
1900 dobjpos = d.BodyGetPosition(Body);
1901
1902 // get prim own inertia in its local frame
1903 tmpdmass = primdMass;
1904
1905 // transform to object frame
1906 mat = d.GeomGetOffsetRotation(prim_geom);
1907 d.MassRotate(ref tmpdmass, ref mat);
1908
1909 thispos = d.GeomGetOffsetPosition(prim_geom);
1910 d.MassTranslate(ref tmpdmass,
1911 thispos.X,
1912 thispos.Y,
1913 thispos.Z);
1914
1915 // subtract current prim inertia from object
1916 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
1917
1918 // back prim own inertia
1919 tmpdmass = primdMass;
1920
1921 // update to new position and orientation
1922 _position = NewPos;
1923 d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z);
1924 _orientation = newrot;
1925 quat.X = newrot.X;
1926 quat.Y = newrot.Y;
1927 quat.Z = newrot.Z;
1928 quat.W = newrot.W;
1929 d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat);
1930
1931 mat = d.GeomGetOffsetRotation(prim_geom);
1932 d.MassRotate(ref tmpdmass, ref mat);
1933
1934 thispos = d.GeomGetOffsetPosition(prim_geom);
1935 d.MassTranslate(ref tmpdmass,
1936 thispos.X,
1937 thispos.Y,
1938 thispos.Z);
1939
1940 d.MassAdd(ref objdmass, ref tmpdmass);
1941
1942 // fix all positions
1943 IntPtr g = d.BodyGetFirstGeom(Body);
1944 while (g != IntPtr.Zero)
1945 {
1946 thispos = d.GeomGetOffsetPosition(g);
1947 thispos.X -= objdmass.c.X;
1948 thispos.Y -= objdmass.c.Y;
1949 thispos.Z -= objdmass.c.Z;
1950 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
1951 g = d.dBodyGetNextGeom(g);
1952 }
1953 d.BodyVectorToWorld(Body,objdmass.c.X, objdmass.c.Y, objdmass.c.Z,out thispos);
1954
1955 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
1956 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
1957 d.BodySetMass(Body, ref objdmass);
1958 _mass = objdmass.mass;
1959 }
1960
1961
1962
1963 private void FixInertia(Vector3 NewPos)
1964 {
1965 d.Matrix3 primmat = new d.Matrix3();
1966 d.Mass tmpdmass = new d.Mass { };
1967 d.Mass objdmass = new d.Mass { };
1968 d.Mass primmass = new d.Mass { };
1969
1970 d.Vector3 dobjpos;
1971 d.Vector3 thispos;
1972
1973 d.BodyGetMass(Body, out objdmass);
1974
1975 // get prim own inertia in its local frame
1976 primmass = primdMass;
1977 // transform to object frame
1978 primmat = d.GeomGetOffsetRotation(prim_geom);
1979 d.MassRotate(ref primmass, ref primmat);
1980
1981 tmpdmass = primmass;
1982
1983 thispos = d.GeomGetOffsetPosition(prim_geom);
1984 d.MassTranslate(ref tmpdmass,
1985 thispos.X,
1986 thispos.Y,
1987 thispos.Z);
1988
1989 // subtract current prim inertia from object
1990 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
1991
1992 // update to new position
1993 _position = NewPos;
1994 d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z);
1995
1996 thispos = d.GeomGetOffsetPosition(prim_geom);
1997 d.MassTranslate(ref primmass,
1998 thispos.X,
1999 thispos.Y,
2000 thispos.Z);
2001
2002 d.MassAdd(ref objdmass, ref primmass);
2003
2004 // fix all positions
2005 IntPtr g = d.BodyGetFirstGeom(Body);
2006 while (g != IntPtr.Zero)
2007 {
2008 thispos = d.GeomGetOffsetPosition(g);
2009 thispos.X -= objdmass.c.X;
2010 thispos.Y -= objdmass.c.Y;
2011 thispos.Z -= objdmass.c.Z;
2012 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2013 g = d.dBodyGetNextGeom(g);
2014 }
2015
2016 d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos);
2017
2018 // get current object position and rotation
2019 dobjpos = d.BodyGetPosition(Body);
2020
2021 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2022 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2023 d.BodySetMass(Body, ref objdmass);
2024 _mass = objdmass.mass;
2025 }
2026
2027 private void FixInertia(Quaternion newrot)
2028 {
2029 d.Matrix3 mat = new d.Matrix3();
2030 d.Quaternion quat = new d.Quaternion();
2031
2032 d.Mass tmpdmass = new d.Mass { };
2033 d.Mass objdmass = new d.Mass { };
2034 d.Vector3 dobjpos;
2035 d.Vector3 thispos;
2036
2037 d.BodyGetMass(Body, out objdmass);
2038
2039 // get prim own inertia in its local frame
2040 tmpdmass = primdMass;
2041 mat = d.GeomGetOffsetRotation(prim_geom);
2042 d.MassRotate(ref tmpdmass, ref mat);
2043 // transform to object frame
2044 thispos = d.GeomGetOffsetPosition(prim_geom);
2045 d.MassTranslate(ref tmpdmass,
2046 thispos.X,
2047 thispos.Y,
2048 thispos.Z);
2049
2050 // subtract current prim inertia from object
2051 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2052
2053 // update to new orientation
2054 _orientation = newrot;
2055 quat.X = newrot.X;
2056 quat.Y = newrot.Y;
2057 quat.Z = newrot.Z;
2058 quat.W = newrot.W;
2059 d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat);
2060
2061 tmpdmass = primdMass;
2062 mat = d.GeomGetOffsetRotation(prim_geom);
2063 d.MassRotate(ref tmpdmass, ref mat);
2064 d.MassTranslate(ref tmpdmass,
2065 thispos.X,
2066 thispos.Y,
2067 thispos.Z);
2068
2069 d.MassAdd(ref objdmass, ref tmpdmass);
2070
2071 // fix all positions
2072 IntPtr g = d.BodyGetFirstGeom(Body);
2073 while (g != IntPtr.Zero)
2074 {
2075 thispos = d.GeomGetOffsetPosition(g);
2076 thispos.X -= objdmass.c.X;
2077 thispos.Y -= objdmass.c.Y;
2078 thispos.Z -= objdmass.c.Z;
2079 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2080 g = d.dBodyGetNextGeom(g);
2081 }
2082
2083 d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos);
2084 // get current object position and rotation
2085 dobjpos = d.BodyGetPosition(Body);
2086
2087 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2088 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2089 d.BodySetMass(Body, ref objdmass);
2090 _mass = objdmass.mass;
2091 }
2092
2093
2094 #region Mass Calculation
2095
2096 private float CalculatePrimVolume()
2097 {
2098 float volume = _size.X * _size.Y * _size.Z; // default
2099 float tmp;
2100
2101 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
2102 float hollowVolume = hollowAmount * hollowAmount;
2103
2104 switch (_pbs.ProfileShape)
2105 {
2106 case ProfileShape.Square:
2107 // default box
2108
2109 if (_pbs.PathCurve == (byte)Extrusion.Straight)
2110 {
2111 if (hollowAmount > 0.0)
2112 {
2113 switch (_pbs.HollowShape)
2114 {
2115 case HollowShape.Square:
2116 case HollowShape.Same:
2117 break;
2118
2119 case HollowShape.Circle:
2120
2121 hollowVolume *= 0.78539816339f;
2122 break;
2123
2124 case HollowShape.Triangle:
2125
2126 hollowVolume *= (0.5f * .5f);
2127 break;
2128
2129 default:
2130 hollowVolume = 0;
2131 break;
2132 }
2133 volume *= (1.0f - hollowVolume);
2134 }
2135 }
2136
2137 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
2138 {
2139 //a tube
2140
2141 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
2142 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
2143 volume -= volume * tmp * tmp;
2144
2145 if (hollowAmount > 0.0)
2146 {
2147 hollowVolume *= hollowAmount;
2148
2149 switch (_pbs.HollowShape)
2150 {
2151 case HollowShape.Square:
2152 case HollowShape.Same:
2153 break;
2154
2155 case HollowShape.Circle:
2156 hollowVolume *= 0.78539816339f;
2157 break;
2158
2159 case HollowShape.Triangle:
2160 hollowVolume *= 0.5f * 0.5f;
2161 break;
2162 default:
2163 hollowVolume = 0;
2164 break;
2165 }
2166 volume *= (1.0f - hollowVolume);
2167 }
2168 }
2169
2170 break;
2171
2172 case ProfileShape.Circle:
2173
2174 if (_pbs.PathCurve == (byte)Extrusion.Straight)
2175 {
2176 volume *= 0.78539816339f; // elipse base
2177
2178 if (hollowAmount > 0.0)
2179 {
2180 switch (_pbs.HollowShape)
2181 {
2182 case HollowShape.Same:
2183 case HollowShape.Circle:
2184 break;
2185
2186 case HollowShape.Square:
2187 hollowVolume *= 0.5f * 2.5984480504799f;
2188 break;
2189
2190 case HollowShape.Triangle:
2191 hollowVolume *= .5f * 1.27323954473516f;
2192 break;
2193
2194 default:
2195 hollowVolume = 0;
2196 break;
2197 }
2198 volume *= (1.0f - hollowVolume);
2199 }
2200 }
2201
2202 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
2203 {
2204 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
2205 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
2206 volume *= (1.0f - tmp * tmp);
2207
2208 if (hollowAmount > 0.0)
2209 {
2210
2211 // calculate the hollow volume by it's shape compared to the prim shape
2212 hollowVolume *= hollowAmount;
2213
2214 switch (_pbs.HollowShape)
2215 {
2216 case HollowShape.Same:
2217 case HollowShape.Circle:
2218 break;
2219
2220 case HollowShape.Square:
2221 hollowVolume *= 0.5f * 2.5984480504799f;
2222 break;
2223
2224 case HollowShape.Triangle:
2225 hollowVolume *= .5f * 1.27323954473516f;
2226 break;
2227
2228 default:
2229 hollowVolume = 0;
2230 break;
2231 }
2232 volume *= (1.0f - hollowVolume);
2233 }
2234 }
2235 break;
2236
2237 case ProfileShape.HalfCircle:
2238 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
2239 {
2240 volume *= 0.52359877559829887307710723054658f;
2241 }
2242 break;
2243
2244 case ProfileShape.EquilateralTriangle:
2245
2246 if (_pbs.PathCurve == (byte)Extrusion.Straight)
2247 {
2248 volume *= 0.32475953f;
2249
2250 if (hollowAmount > 0.0)
2251 {
2252
2253 // calculate the hollow volume by it's shape compared to the prim shape
2254 switch (_pbs.HollowShape)
2255 {
2256 case HollowShape.Same:
2257 case HollowShape.Triangle:
2258 hollowVolume *= .25f;
2259 break;
2260
2261 case HollowShape.Square:
2262 hollowVolume *= 0.499849f * 3.07920140172638f;
2263 break;
2264
2265 case HollowShape.Circle:
2266 // Hollow shape is a perfect cyllinder in respect to the cube's scale
2267 // Cyllinder hollow volume calculation
2268
2269 hollowVolume *= 0.1963495f * 3.07920140172638f;
2270 break;
2271
2272 default:
2273 hollowVolume = 0;
2274 break;
2275 }
2276 volume *= (1.0f - hollowVolume);
2277 }
2278 }
2279 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
2280 {
2281 volume *= 0.32475953f;
2282 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
2283 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
2284 volume *= (1.0f - tmp * tmp);
2285
2286 if (hollowAmount > 0.0)
2287 {
2288
2289 hollowVolume *= hollowAmount;
2290
2291 switch (_pbs.HollowShape)
2292 {
2293 case HollowShape.Same:
2294 case HollowShape.Triangle:
2295 hollowVolume *= .25f;
2296 break;
2297
2298 case HollowShape.Square:
2299 hollowVolume *= 0.499849f * 3.07920140172638f;
2300 break;
2301
2302 case HollowShape.Circle:
2303
2304 hollowVolume *= 0.1963495f * 3.07920140172638f;
2305 break;
2306
2307 default:
2308 hollowVolume = 0;
2309 break;
2310 }
2311 volume *= (1.0f - hollowVolume);
2312 }
2313 }
2314 break;
2315
2316 default:
2317 break;
2318 }
2319
2320 float taperX1;
2321 float taperY1;
2322 float taperX;
2323 float taperY;
2324 float pathBegin;
2325 float pathEnd;
2326 float profileBegin;
2327 float profileEnd;
2328
2329 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
2330 {
2331 taperX1 = _pbs.PathScaleX * 0.01f;
2332 if (taperX1 > 1.0f)
2333 taperX1 = 2.0f - taperX1;
2334 taperX = 1.0f - taperX1;
2335
2336 taperY1 = _pbs.PathScaleY * 0.01f;
2337 if (taperY1 > 1.0f)
2338 taperY1 = 2.0f - taperY1;
2339 taperY = 1.0f - taperY1;
2340 }
2341 else
2342 {
2343 taperX = _pbs.PathTaperX * 0.01f;
2344 if (taperX < 0.0f)
2345 taperX = -taperX;
2346 taperX1 = 1.0f - taperX;
2347
2348 taperY = _pbs.PathTaperY * 0.01f;
2349 if (taperY < 0.0f)
2350 taperY = -taperY;
2351 taperY1 = 1.0f - taperY;
2352 }
2353
2354 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
2355
2356 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
2357 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
2358 volume *= (pathEnd - pathBegin);
2359
2360 // this is crude aproximation
2361 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
2362 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
2363 volume *= (profileEnd - profileBegin);
2364
2365 return volume;
2366 }
2367
2368
2369 private void CalcPrimBodyData()
2370 {
2371 float volume;
2372
2373 if (prim_geom == IntPtr.Zero)
2374 {
2375 // Ubit let's have a initial basic OOB
2376 primOOBsize.X = _size.X;
2377 primOOBsize.Y = _size.Y;
2378 primOOBsize.Z = _size.Z;
2379 primOOBoffset = Vector3.Zero;
2380 }
2381 else
2382 {
2383 d.AABB AABB;
2384 d.GeomGetAABB(prim_geom, out AABB); // get the AABB from engine geom
2385
2386 primOOBsize.X = (AABB.MaxX - AABB.MinX);
2387 primOOBsize.Y = (AABB.MaxY - AABB.MinY);
2388 primOOBsize.Z = (AABB.MaxZ - AABB.MinZ);
2389 if (!hasOOBoffsetFromMesh)
2390 {
2391 primOOBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f;
2392 primOOBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f;
2393 primOOBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f;
2394 }
2395 }
2396
2397 // also its own inertia and mass
2398 // keep using basic shape mass for now
2399 volume = CalculatePrimVolume();
2400
2401 primVolume = volume;
2402 primMass = m_density * volume;
2403
2404 if (primMass <= 0)
2405 primMass = 0.0001f;//ckrinke: Mass must be greater then zero.
2406 if (primMass > _parent_scene.maximumMassObject)
2407 primMass = _parent_scene.maximumMassObject;
2408
2409 _mass = primMass; // just in case
2410
2411 d.MassSetBoxTotal(out primdMass, primMass, primOOBsize.X, primOOBsize.Y, primOOBsize.Z);
2412
2413 d.MassTranslate(ref primdMass,
2414 primOOBoffset.X,
2415 primOOBoffset.Y,
2416 primOOBoffset.Z);
2417
2418 primOOBsize *= 0.5f; // let obb size be a corner coords
2419 primOOBradiusSQ = primOOBsize.LengthSquared();
2420 }
2421
2422
2423 #endregion
2424
2425
2426 /// <summary>
2427 /// Add a child prim to this parent prim.
2428 /// </summary>
2429 /// <param name="prim">Child prim</param>
2430 // I'm the parent
2431 // prim is the child
2432 public void ParentPrim(OdePrim prim)
2433 {
2434 //Console.WriteLine("ParentPrim " + m_primName);
2435 if (this.m_localID != prim.m_localID)
2436 {
2437 DestroyBody(); // for now we need to rebuil entire object on link change
2438
2439 lock (childrenPrim)
2440 {
2441 // adopt the prim
2442 if (!childrenPrim.Contains(prim))
2443 childrenPrim.Add(prim);
2444
2445 // see if this prim has kids and adopt them also
2446 // should not happen for now
2447 foreach (OdePrim prm in prim.childrenPrim)
2448 {
2449 if (!childrenPrim.Contains(prm))
2450 {
2451 if (prm.Body != IntPtr.Zero)
2452 {
2453 if (prm.prim_geom != IntPtr.Zero)
2454 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
2455 if (prm.Body != prim.Body)
2456 prm.DestroyBody(); // don't loose bodies around
2457 prm.Body = IntPtr.Zero;
2458 }
2459
2460 childrenPrim.Add(prm);
2461 prm._parent = this;
2462 }
2463 }
2464 }
2465 //Remove old children from the prim
2466 prim.childrenPrim.Clear();
2467
2468 if (prim.Body != IntPtr.Zero)
2469 {
2470 if (prim.prim_geom != IntPtr.Zero)
2471 d.GeomSetBody(prim.prim_geom, IntPtr.Zero);
2472 prim.DestroyBody(); // don't loose bodies around
2473 prim.Body = IntPtr.Zero;
2474 }
2475
2476 prim.childPrim = true;
2477 prim._parent = this;
2478
2479 MakeBody(); // full nasty reconstruction
2480 }
2481 }
2482
2483 private void UpdateChildsfromgeom()
2484 {
2485 if (childrenPrim.Count > 0)
2486 {
2487 foreach (OdePrim prm in childrenPrim)
2488 prm.UpdateDataFromGeom();
2489 }
2490 }
2491
2492 private void UpdateDataFromGeom()
2493 {
2494 if (prim_geom != IntPtr.Zero)
2495 {
2496 d.Quaternion qtmp;
2497 d.GeomCopyQuaternion(prim_geom, out qtmp);
2498 _orientation.W = qtmp.W;
2499 _orientation.X = qtmp.X;
2500 _orientation.Y = qtmp.Y;
2501 _orientation.Z = qtmp.Z;
2502
2503 d.Vector3 lpos = d.GeomGetPosition(prim_geom);
2504 _position.X = lpos.X;
2505 _position.Y = lpos.Y;
2506 _position.Z = lpos.Z;
2507 }
2508 }
2509
2510 private void ChildDelink(OdePrim odePrim, bool remakebodies)
2511 {
2512 // Okay, we have a delinked child.. destroy all body and remake
2513 if (odePrim != this && !childrenPrim.Contains(odePrim))
2514 return;
2515
2516 DestroyBody();
2517
2518 if (odePrim == this) // delinking the root prim
2519 {
2520 OdePrim newroot = null;
2521 lock (childrenPrim)
2522 {
2523 if (childrenPrim.Count > 0)
2524 {
2525 newroot = childrenPrim[0];
2526 childrenPrim.RemoveAt(0);
2527 foreach (OdePrim prm in childrenPrim)
2528 {
2529 newroot.childrenPrim.Add(prm);
2530 }
2531 childrenPrim.Clear();
2532 }
2533 if (newroot != null)
2534 {
2535 newroot.childPrim = false;
2536 newroot._parent = null;
2537 if (remakebodies)
2538 newroot.MakeBody();
2539 }
2540 }
2541 }
2542
2543 else
2544 {
2545 lock (childrenPrim)
2546 {
2547 childrenPrim.Remove(odePrim);
2548 odePrim.childPrim = false;
2549 odePrim._parent = null;
2550 // odePrim.UpdateDataFromGeom();
2551 if (remakebodies)
2552 odePrim.MakeBody();
2553 }
2554 }
2555 if (remakebodies)
2556 MakeBody();
2557 }
2558
2559 protected void ChildRemove(OdePrim odePrim, bool reMakeBody)
2560 {
2561 // Okay, we have a delinked child.. destroy all body and remake
2562 if (odePrim != this && !childrenPrim.Contains(odePrim))
2563 return;
2564
2565 DestroyBody();
2566
2567 if (odePrim == this)
2568 {
2569 OdePrim newroot = null;
2570 lock (childrenPrim)
2571 {
2572 if (childrenPrim.Count > 0)
2573 {
2574 newroot = childrenPrim[0];
2575 childrenPrim.RemoveAt(0);
2576 foreach (OdePrim prm in childrenPrim)
2577 {
2578 newroot.childrenPrim.Add(prm);
2579 }
2580 childrenPrim.Clear();
2581 }
2582 if (newroot != null)
2583 {
2584 newroot.childPrim = false;
2585 newroot._parent = null;
2586 newroot.MakeBody();
2587 }
2588 }
2589 if (reMakeBody)
2590 MakeBody();
2591 return;
2592 }
2593 else
2594 {
2595 lock (childrenPrim)
2596 {
2597 childrenPrim.Remove(odePrim);
2598 odePrim.childPrim = false;
2599 odePrim._parent = null;
2600 if (reMakeBody)
2601 odePrim.MakeBody();
2602 }
2603 }
2604 MakeBody();
2605 }
2606
2607 #region changes
2608
2609 private void changeadd()
2610 {
2611 CreateGeom();
2612
2613 if (prim_geom != IntPtr.Zero)
2614 {
2615 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2616 d.Quaternion myrot = new d.Quaternion();
2617 myrot.X = _orientation.X;
2618 myrot.Y = _orientation.Y;
2619 myrot.Z = _orientation.Z;
2620 myrot.W = _orientation.W;
2621 d.GeomSetQuaternion(prim_geom, ref myrot);
2622
2623 if (!m_isphysical)
2624 {
2625 SetInStaticSpace(this);
2626 UpdateCollisionCatFlags();
2627 ApplyCollisionCatFlags();
2628 }
2629 else
2630 MakeBody();
2631 }
2632 }
2633
2634 private void changeAngularLock(Vector3 newLock)
2635 {
2636 // do we have a Physical object?
2637 if (Body != IntPtr.Zero)
2638 {
2639 //Check that we have a Parent
2640 //If we have a parent then we're not authorative here
2641 if (_parent == null)
2642 {
2643 if (!newLock.ApproxEquals(Vector3.One, 0f))
2644 {
2645 createAMotor(newLock);
2646 }
2647 else
2648 {
2649 if (Amotor != IntPtr.Zero)
2650 {
2651 d.JointDestroy(Amotor);
2652 Amotor = IntPtr.Zero;
2653 }
2654 }
2655 }
2656 }
2657 // Store this for later in case we get turned into a separate body
2658 m_angularlock = newLock;
2659 }
2660
2661 private void changeLink(OdePrim NewParent)
2662 {
2663 if (_parent == null && NewParent != null)
2664 {
2665 NewParent.ParentPrim(this);
2666 }
2667 else if (_parent != null)
2668 {
2669 if (_parent is OdePrim)
2670 {
2671 if (NewParent != _parent)
2672 {
2673 (_parent as OdePrim).ChildDelink(this, false); // for now...
2674 childPrim = false;
2675
2676 if (NewParent != null)
2677 {
2678 NewParent.ParentPrim(this);
2679 }
2680 }
2681 }
2682 }
2683 _parent = NewParent;
2684 }
2685
2686
2687 private void Stop()
2688 {
2689 if (!childPrim)
2690 {
2691 m_force = Vector3.Zero;
2692 m_forceacc = Vector3.Zero;
2693 m_angularForceacc = Vector3.Zero;
2694 _torque = Vector3.Zero;
2695 _velocity = Vector3.Zero;
2696 _acceleration = Vector3.Zero;
2697 m_rotationalVelocity = Vector3.Zero;
2698 _target_velocity = Vector3.Zero;
2699 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2700 m_vehicle.Stop();
2701 }
2702
2703 if (Body != IntPtr.Zero)
2704 {
2705 d.BodySetForce(Body, 0f, 0f, 0f);
2706 d.BodySetTorque(Body, 0f, 0f, 0f);
2707 d.BodySetLinearVel(Body, 0f, 0f, 0f);
2708 d.BodySetAngularVel(Body, 0f, 0f, 0f);
2709 }
2710 }
2711
2712 private void changePhantomStatus(bool newval)
2713 {
2714 m_isphantom = newval;
2715
2716 UpdateCollisionCatFlags();
2717 ApplyCollisionCatFlags();
2718 }
2719
2720/* not in use
2721 internal void ChildSelectedChange(bool childSelect)
2722 {
2723 if(childPrim)
2724 return;
2725
2726 if (childSelect == m_isSelected)
2727 return;
2728
2729 if (childSelect)
2730 {
2731 DoSelectedStatus(true);
2732 }
2733
2734 else
2735 {
2736 foreach (OdePrim prm in childrenPrim)
2737 {
2738 if (prm.m_isSelected)
2739 return;
2740 }
2741 DoSelectedStatus(false);
2742 }
2743 }
2744*/
2745 private void changeSelectedStatus(bool newval)
2746 {
2747 if (m_lastdoneSelected == newval)
2748 return;
2749
2750 m_lastdoneSelected = newval;
2751 DoSelectedStatus(newval);
2752 }
2753
2754 private void CheckDelaySelect()
2755 {
2756 if (m_delaySelect)
2757 {
2758 DoSelectedStatus(m_isSelected);
2759 }
2760 }
2761
2762 private void DoSelectedStatus(bool newval)
2763 {
2764 m_isSelected = newval;
2765 Stop();
2766
2767 if (newval)
2768 {
2769 if (!childPrim && Body != IntPtr.Zero)
2770 d.BodyDisable(Body);
2771
2772 if (m_delaySelect || m_isphysical)
2773 {
2774 m_collisionCategories = CollisionCategories.Selected;
2775 m_collisionFlags = 0;
2776
2777 if (!childPrim)
2778 {
2779 foreach (OdePrim prm in childrenPrim)
2780 {
2781 prm.m_collisionCategories = m_collisionCategories;
2782 prm.m_collisionFlags = m_collisionFlags;
2783
2784 if (prm.prim_geom != null)
2785 {
2786
2787 if (prm.m_NoColide)
2788 {
2789 d.GeomSetCategoryBits(prm.prim_geom, 0);
2790 d.GeomSetCollideBits(prm.prim_geom, 0);
2791 }
2792 else
2793 {
2794 d.GeomSetCategoryBits(prm.prim_geom, (uint)m_collisionCategories);
2795 d.GeomSetCollideBits(prm.prim_geom, (uint)m_collisionFlags);
2796 }
2797 }
2798 prm.m_delaySelect = false;
2799 }
2800 }
2801// else if (_parent != null)
2802// ((OdePrim)_parent).ChildSelectedChange(true);
2803
2804
2805 if (prim_geom != null)
2806 {
2807 if (m_NoColide)
2808 {
2809 d.GeomSetCategoryBits(prim_geom, 0);
2810 d.GeomSetCollideBits(prim_geom, 0);
2811 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
2812 {
2813 d.GeomSetCategoryBits(collide_geom, 0);
2814 d.GeomSetCollideBits(collide_geom, 0);
2815 }
2816
2817 }
2818 else
2819 {
2820 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
2821 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
2822 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
2823 {
2824 d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories);
2825 d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags);
2826 }
2827 }
2828 }
2829
2830 m_delaySelect = false;
2831 }
2832 else if(!m_isphysical)
2833 {
2834 m_delaySelect = true;
2835 }
2836 }
2837 else
2838 {
2839 if (!childPrim)
2840 {
2841 if (Body != IntPtr.Zero && !m_disabled)
2842 d.BodyEnable(Body);
2843 }
2844// else if (_parent != null)
2845// ((OdePrim)_parent).ChildSelectedChange(false);
2846
2847 UpdateCollisionCatFlags();
2848 ApplyCollisionCatFlags();
2849
2850 m_delaySelect = false;
2851 }
2852
2853 resetCollisionAccounting();
2854 }
2855
2856 private void changePosition(Vector3 newPos)
2857 {
2858 CheckDelaySelect();
2859 if (m_isphysical)
2860 {
2861 if (childPrim) // inertia is messed, must rebuild
2862 {
2863 if (m_building)
2864 {
2865 _position = newPos;
2866 }
2867
2868 else if (m_forcePosOrRotation && _position != newPos && Body != IntPtr.Zero)
2869 {
2870 FixInertia(newPos);
2871 if (!d.BodyIsEnabled(Body))
2872 d.BodyEnable(Body);
2873 }
2874 }
2875 else
2876 {
2877 if (_position != newPos)
2878 {
2879 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2880 _position = newPos;
2881 }
2882 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2883 d.BodyEnable(Body);
2884 }
2885 }
2886 else
2887 {
2888 if (prim_geom != IntPtr.Zero)
2889 {
2890 if (newPos != _position)
2891 {
2892 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2893 _position = newPos;
2894
2895 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2896 }
2897 }
2898 }
2899 givefakepos--;
2900 if (givefakepos < 0)
2901 givefakepos = 0;
2902 // changeSelectedStatus();
2903 resetCollisionAccounting();
2904 }
2905
2906 private void changeOrientation(Quaternion newOri)
2907 {
2908 CheckDelaySelect();
2909 if (m_isphysical)
2910 {
2911 if (childPrim) // inertia is messed, must rebuild
2912 {
2913 if (m_building)
2914 {
2915 _orientation = newOri;
2916 }
2917 /*
2918 else if (m_forcePosOrRotation && _orientation != newOri && Body != IntPtr.Zero)
2919 {
2920 FixInertia(_position, newOri);
2921 if (!d.BodyIsEnabled(Body))
2922 d.BodyEnable(Body);
2923 }
2924 */
2925 }
2926 else
2927 {
2928 if (newOri != _orientation)
2929 {
2930 d.Quaternion myrot = new d.Quaternion();
2931 myrot.X = newOri.X;
2932 myrot.Y = newOri.Y;
2933 myrot.Z = newOri.Z;
2934 myrot.W = newOri.W;
2935 d.GeomSetQuaternion(prim_geom, ref myrot);
2936 _orientation = newOri;
2937 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f))
2938 createAMotor(m_angularlock);
2939 }
2940 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2941 d.BodyEnable(Body);
2942 }
2943 }
2944 else
2945 {
2946 if (prim_geom != IntPtr.Zero)
2947 {
2948 if (newOri != _orientation)
2949 {
2950 d.Quaternion myrot = new d.Quaternion();
2951 myrot.X = newOri.X;
2952 myrot.Y = newOri.Y;
2953 myrot.Z = newOri.Z;
2954 myrot.W = newOri.W;
2955 d.GeomSetQuaternion(prim_geom, ref myrot);
2956 _orientation = newOri;
2957 }
2958 }
2959 }
2960 givefakeori--;
2961 if (givefakeori < 0)
2962 givefakeori = 0;
2963 resetCollisionAccounting();
2964 }
2965
2966 private void changePositionAndOrientation(Vector3 newPos, Quaternion newOri)
2967 {
2968 CheckDelaySelect();
2969 if (m_isphysical)
2970 {
2971 if (childPrim && m_building) // inertia is messed, must rebuild
2972 {
2973 _position = newPos;
2974 _orientation = newOri;
2975 }
2976 else
2977 {
2978 if (newOri != _orientation)
2979 {
2980 d.Quaternion myrot = new d.Quaternion();
2981 myrot.X = newOri.X;
2982 myrot.Y = newOri.Y;
2983 myrot.Z = newOri.Z;
2984 myrot.W = newOri.W;
2985 d.GeomSetQuaternion(prim_geom, ref myrot);
2986 _orientation = newOri;
2987 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f))
2988 createAMotor(m_angularlock);
2989 }
2990 if (_position != newPos)
2991 {
2992 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2993 _position = newPos;
2994 }
2995 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2996 d.BodyEnable(Body);
2997 }
2998 }
2999 else
3000 {
3001 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
3002 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
3003
3004 if (prim_geom != IntPtr.Zero)
3005 {
3006 if (newOri != _orientation)
3007 {
3008 d.Quaternion myrot = new d.Quaternion();
3009 myrot.X = newOri.X;
3010 myrot.Y = newOri.Y;
3011 myrot.Z = newOri.Z;
3012 myrot.W = newOri.W;
3013 d.GeomSetQuaternion(prim_geom, ref myrot);
3014 _orientation = newOri;
3015 }
3016
3017 if (newPos != _position)
3018 {
3019 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
3020 _position = newPos;
3021
3022 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
3023 }
3024 }
3025 }
3026 givefakepos--;
3027 if (givefakepos < 0)
3028 givefakepos = 0;
3029 givefakeori--;
3030 if (givefakeori < 0)
3031 givefakeori = 0;
3032 resetCollisionAccounting();
3033 }
3034
3035
3036 private void changeDisable(bool disable)
3037 {
3038 if (disable)
3039 {
3040 if (!m_disabled)
3041 disableBodySoft();
3042 }
3043 else
3044 {
3045 if (m_disabled)
3046 enableBodySoft();
3047 }
3048 }
3049
3050 private void changePhysicsStatus(bool NewStatus)
3051 {
3052 CheckDelaySelect();
3053
3054 m_isphysical = NewStatus;
3055
3056 if (!childPrim)
3057 {
3058 if (NewStatus)
3059 {
3060 if (Body == IntPtr.Zero)
3061 MakeBody();
3062 }
3063 else
3064 {
3065 if (Body != IntPtr.Zero)
3066 {
3067 DestroyBody();
3068 }
3069 Stop();
3070 }
3071 }
3072
3073 resetCollisionAccounting();
3074 }
3075
3076 private void changeprimsizeshape()
3077 {
3078 CheckDelaySelect();
3079
3080 OdePrim parent = (OdePrim)_parent;
3081
3082 bool chp = childPrim;
3083
3084 if (chp)
3085 {
3086 if (parent != null)
3087 {
3088 parent.DestroyBody();
3089 }
3090 }
3091 else
3092 {
3093 DestroyBody();
3094 }
3095
3096 RemoveGeom();
3097
3098 // we don't need to do space calculation because the client sends a position update also.
3099 if (_size.X <= 0)
3100 _size.X = 0.01f;
3101 if (_size.Y <= 0)
3102 _size.Y = 0.01f;
3103 if (_size.Z <= 0)
3104 _size.Z = 0.01f;
3105 // Construction of new prim
3106
3107 CreateGeom();
3108
3109 if (prim_geom != IntPtr.Zero)
3110 {
3111 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3112 d.Quaternion myrot = new d.Quaternion();
3113 myrot.X = _orientation.X;
3114 myrot.Y = _orientation.Y;
3115 myrot.Z = _orientation.Z;
3116 myrot.W = _orientation.W;
3117 d.GeomSetQuaternion(prim_geom, ref myrot);
3118 }
3119
3120 if (m_isphysical)
3121 {
3122 if (chp)
3123 {
3124 if (parent != null)
3125 {
3126 parent.MakeBody();
3127 }
3128 }
3129 else
3130 MakeBody();
3131 }
3132
3133 else
3134 {
3135 UpdateCollisionCatFlags();
3136 ApplyCollisionCatFlags();
3137 }
3138
3139 resetCollisionAccounting();
3140 }
3141
3142 private void changeSize(Vector3 newSize)
3143 {
3144 _size = newSize;
3145 changeprimsizeshape();
3146 }
3147
3148 private void changeShape(PrimitiveBaseShape newShape)
3149 {
3150 if(newShape != null)
3151 _pbs = newShape;
3152 changeprimsizeshape();
3153 }
3154
3155 private void changeFloatOnWater(bool newval)
3156 {
3157 m_collidesWater = newval;
3158
3159 UpdateCollisionCatFlags();
3160 ApplyCollisionCatFlags();
3161 }
3162
3163 private void changeSetTorque(Vector3 newtorque)
3164 {
3165 if (!m_isSelected)
3166 {
3167 if (m_isphysical && Body != IntPtr.Zero)
3168 {
3169 if (m_disabled)
3170 enableBodySoft();
3171 else if (!d.BodyIsEnabled(Body))
3172 d.BodyEnable(Body);
3173
3174 }
3175 _torque = newtorque;
3176 }
3177 }
3178
3179 private void changeForce(Vector3 force)
3180 {
3181 m_force = force;
3182 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
3183 d.BodyEnable(Body);
3184 }
3185
3186
3187 private void changeAddImpulse(Vector3 impulse)
3188 {
3189 m_forceacc += impulse * m_invTimeStep;
3190 if (!m_isSelected)
3191 {
3192 lock (this)
3193 {
3194 //m_log.Info("[PHYSICS]: dequeing forcelist");
3195 if (m_isphysical && Body != IntPtr.Zero)
3196 {
3197 if (m_disabled)
3198 enableBodySoft();
3199 else if (!d.BodyIsEnabled(Body))
3200 d.BodyEnable(Body);
3201 }
3202 }
3203
3204 m_collisionscore = 0;
3205 }
3206 }
3207
3208 // actually angular impulse
3209 private void changeAddAngularImpulse(Vector3 aimpulse)
3210 {
3211 m_angularForceacc += aimpulse * m_invTimeStep;
3212 if (!m_isSelected)
3213 {
3214 lock (this)
3215 {
3216 if (m_isphysical && Body != IntPtr.Zero)
3217 {
3218 if (m_disabled)
3219 enableBodySoft();
3220 else if (!d.BodyIsEnabled(Body))
3221 d.BodyEnable(Body);
3222 }
3223 }
3224 m_collisionscore = 0;
3225 }
3226 }
3227
3228 private void changevelocity(Vector3 newVel)
3229 {
3230 if (!m_isSelected)
3231 {
3232 if (Body != IntPtr.Zero)
3233 {
3234 if (m_disabled)
3235 enableBodySoft();
3236 else if (!d.BodyIsEnabled(Body))
3237 d.BodyEnable(Body);
3238
3239 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
3240 }
3241 //resetCollisionAccounting();
3242 }
3243 _velocity = newVel;
3244 }
3245
3246 private void changeVolumedetetion(bool newVolDtc)
3247 {
3248 m_isVolumeDetect = newVolDtc;
3249 m_fakeisVolumeDetect = newVolDtc;
3250 UpdateCollisionCatFlags();
3251 ApplyCollisionCatFlags();
3252 }
3253
3254 protected void changeBuilding(bool newbuilding)
3255 {
3256 if ((bool)newbuilding)
3257 {
3258 m_building = true;
3259 if (!childPrim)
3260 DestroyBody();
3261 }
3262 else
3263 {
3264 m_building = false;
3265 CheckDelaySelect();
3266 if (!childPrim)
3267 MakeBody();
3268 }
3269 if (!childPrim && childrenPrim.Count > 0)
3270 {
3271 foreach (OdePrim prm in childrenPrim)
3272 prm.changeBuilding(m_building); // call directly
3273 }
3274 }
3275
3276 public void changeSetVehicle(VehicleData vdata)
3277 {
3278 if (m_vehicle == null)
3279 m_vehicle = new ODEDynamics(this);
3280 m_vehicle.DoSetVehicle(vdata);
3281 }
3282 private void changeVehicleType(int value)
3283 {
3284 if (value == (int)Vehicle.TYPE_NONE)
3285 {
3286 if (m_vehicle != null)
3287 m_vehicle = null;
3288 }
3289 else
3290 {
3291 if (m_vehicle == null)
3292 m_vehicle = new ODEDynamics(this);
3293
3294 m_vehicle.ProcessTypeChange((Vehicle)value);
3295 }
3296 }
3297
3298 private void changeVehicleFloatParam(strVehicleFloatParam fp)
3299 {
3300 if (m_vehicle == null)
3301 return;
3302
3303 m_vehicle.ProcessFloatVehicleParam((Vehicle)fp.param, fp.value);
3304 }
3305
3306 private void changeVehicleVectorParam(strVehicleVectorParam vp)
3307 {
3308 if (m_vehicle == null)
3309 return;
3310 m_vehicle.ProcessVectorVehicleParam((Vehicle)vp.param, vp.value);
3311 }
3312
3313 private void changeVehicleRotationParam(strVehicleQuatParam qp)
3314 {
3315 if (m_vehicle == null)
3316 return;
3317 m_vehicle.ProcessRotationVehicleParam((Vehicle)qp.param, qp.value);
3318 }
3319
3320 private void changeVehicleFlags(strVehicleBoolParam bp)
3321 {
3322 if (m_vehicle == null)
3323 return;
3324 m_vehicle.ProcessVehicleFlags(bp.param, bp.value);
3325 }
3326
3327 #endregion
3328
3329 public void Move()
3330 {
3331 if (!childPrim && m_isphysical && Body != IntPtr.Zero &&
3332 !m_disabled && !m_isSelected && !m_building && !m_outbounds)
3333 {
3334 if (!d.BodyIsEnabled(Body))
3335 {
3336 // let vehicles sleep
3337 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3338 return;
3339
3340 if (++bodydisablecontrol < 20)
3341 return;
3342
3343 bodydisablecontrol = 0;
3344 d.BodyEnable(Body);
3345 }
3346
3347 // check outside region
3348 d.Vector3 lpos = d.GeomGetPosition(prim_geom); // root position that is seem by rest of simulator
3349
3350 if (lpos.Z < -100 || lpos.Z > 100000f)
3351 {
3352 m_outbounds = true;
3353
3354 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f);
3355 _acceleration.X = 0;
3356 _acceleration.Y = 0;
3357 _acceleration.Z = 0;
3358
3359 _velocity.X = 0;
3360 _velocity.Y = 0;
3361 _velocity.Z = 0;
3362 m_rotationalVelocity.X = 0;
3363 m_rotationalVelocity.Y = 0;
3364 m_rotationalVelocity.Z = 0;
3365
3366 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3367 d.BodySetAngularVel(Body, 0, 0, 0); // stop it
3368 d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere
3369 m_lastposition = _position;
3370 m_lastorientation = _orientation;
3371
3372 base.RequestPhysicsterseUpdate();
3373
3374 throttleCounter = 0;
3375 _zeroFlag = true;
3376
3377 disableBodySoft(); // disable it and colisions
3378 base.RaiseOutOfBounds(_position);
3379 return;
3380 }
3381
3382 if (lpos.X < 0f)
3383 {
3384 _position.X = Util.Clip(lpos.X, -2f, -0.1f);
3385 m_outbounds = true;
3386 }
3387 else if (lpos.X > _parent_scene.WorldExtents.X)
3388 {
3389 _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
3390 m_outbounds = true;
3391 }
3392 if (lpos.Y < 0f)
3393 {
3394 _position.Y = Util.Clip(lpos.Y, -2f, -0.1f);
3395 m_outbounds = true;
3396 }
3397 else if (lpos.Y > _parent_scene.WorldExtents.Y)
3398 {
3399 _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
3400 m_outbounds = true;
3401 }
3402
3403 if (m_outbounds)
3404 {
3405 m_lastposition = _position;
3406 m_lastorientation = _orientation;
3407
3408 d.Vector3 dtmp = d.BodyGetAngularVel(Body);
3409 m_rotationalVelocity.X = dtmp.X;
3410 m_rotationalVelocity.Y = dtmp.Y;
3411 m_rotationalVelocity.Z = dtmp.Z;
3412
3413 dtmp = d.BodyGetLinearVel(Body);
3414 _velocity.X = dtmp.X;
3415 _velocity.Y = dtmp.Y;
3416 _velocity.Z = dtmp.Z;
3417
3418 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3419 d.BodySetAngularVel(Body, 0, 0, 0);
3420 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3421 disableBodySoft(); // stop collisions
3422 base.RequestPhysicsterseUpdate();
3423 return;
3424 }
3425
3426 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3427 {
3428 // 'VEHICLES' are dealt with in ODEDynamics.cs
3429 m_vehicle.Step();
3430 return;
3431 }
3432
3433 float fx = 0;
3434 float fy = 0;
3435 float fz = 0;
3436
3437 float m_mass = _mass;
3438
3439 if (m_usePID && m_PIDTau > 0)
3440 {
3441 // for now position error
3442 _target_velocity =
3443 new Vector3(
3444 (m_PIDTarget.X - lpos.X),
3445 (m_PIDTarget.Y - lpos.Y),
3446 (m_PIDTarget.Z - lpos.Z)
3447 );
3448
3449 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.02f))
3450 {
3451 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
3452 d.BodySetLinearVel(Body, 0, 0, 0);
3453 return;
3454 }
3455 else
3456 {
3457 _zeroFlag = false;
3458
3459 float tmp = 1 / m_PIDTau;
3460 _target_velocity *= tmp;
3461
3462 // apply limits
3463 tmp = _target_velocity.Length();
3464 if (tmp > 50.0f)
3465 {
3466 tmp = 50 / tmp;
3467 _target_velocity *= tmp;
3468 }
3469 else if (tmp < 0.05f)
3470 {
3471 tmp = 0.05f / tmp;
3472 _target_velocity *= tmp;
3473 }
3474
3475 d.Vector3 vel = d.BodyGetLinearVel(Body);
3476 fx = (_target_velocity.X - vel.X) * m_invTimeStep;
3477 fy = (_target_velocity.Y - vel.Y) * m_invTimeStep;
3478 fz = (_target_velocity.Z - vel.Z) * m_invTimeStep;
3479 }
3480 } // end if (m_usePID)
3481
3482 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
3483 else if (m_useHoverPID && m_PIDHoverTau != 0 && m_PIDHoverHeight != 0)
3484 {
3485
3486 // Non-Vehicles have a limited set of Hover options.
3487 // determine what our target height really is based on HoverType
3488
3489 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(lpos.X, lpos.Y);
3490
3491 switch (m_PIDHoverType)
3492 {
3493 case PIDHoverType.Ground:
3494 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3495 break;
3496
3497 case PIDHoverType.GroundAndWater:
3498 m_waterHeight = _parent_scene.GetWaterLevel();
3499 if (m_groundHeight > m_waterHeight)
3500 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3501 else
3502 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
3503 break;
3504 } // end switch (m_PIDHoverType)
3505
3506 // don't go underground unless volumedetector
3507
3508 if (m_targetHoverHeight > m_groundHeight || m_isVolumeDetect)
3509 {
3510 d.Vector3 vel = d.BodyGetLinearVel(Body);
3511
3512 fz = (m_targetHoverHeight - lpos.Z);
3513
3514 // if error is zero, use position control; otherwise, velocity control
3515 if (Math.Abs(fz) < 0.01f)
3516 {
3517 d.BodySetPosition(Body, lpos.X, lpos.Y, m_targetHoverHeight);
3518 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
3519 }
3520 else
3521 {
3522 _zeroFlag = false;
3523 fz /= m_PIDHoverTau;
3524
3525 float tmp = Math.Abs(fz);
3526 if (tmp > 50)
3527 fz = 50 * Math.Sign(fz);
3528 else if (tmp < 0.1)
3529 fz = 0.1f * Math.Sign(fz);
3530
3531 fz = ((fz - vel.Z) * m_invTimeStep);
3532 }
3533 }
3534 }
3535 else
3536 {
3537 float b = (1.0f - m_buoyancy);
3538 fx = _parent_scene.gravityx * b;
3539 fy = _parent_scene.gravityy * b;
3540 fz = _parent_scene.gravityz * b;
3541 }
3542
3543 fx *= m_mass;
3544 fy *= m_mass;
3545 fz *= m_mass;
3546
3547 // constant force
3548 fx += m_force.X;
3549 fy += m_force.Y;
3550 fz += m_force.Z;
3551
3552 fx += m_forceacc.X;
3553 fy += m_forceacc.Y;
3554 fz += m_forceacc.Z;
3555
3556 m_forceacc = Vector3.Zero;
3557
3558 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
3559 if (fx != 0 || fy != 0 || fz != 0)
3560 {
3561 d.BodyAddForce(Body, fx, fy, fz);
3562 //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz);
3563 }
3564
3565 Vector3 trq;
3566
3567 trq = _torque;
3568 trq += m_angularForceacc;
3569 m_angularForceacc = Vector3.Zero;
3570 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0)
3571 {
3572 d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z);
3573 }
3574 }
3575 else
3576 { // is not physical, or is not a body or is selected
3577 // _zeroPosition = d.BodyGetPosition(Body);
3578 return;
3579 //Console.WriteLine("Nothing " + Name);
3580
3581 }
3582 }
3583
3584 public void UpdatePositionAndVelocity()
3585 {
3586 if (_parent == null && !m_disabled && !m_building && !m_outbounds && Body != IntPtr.Zero)
3587 {
3588 if (d.BodyIsEnabled(Body) || !_zeroFlag)
3589 {
3590 bool lastZeroFlag = _zeroFlag;
3591
3592 d.Vector3 lpos = d.GeomGetPosition(prim_geom);
3593
3594 d.Quaternion ori;
3595 d.GeomCopyQuaternion(prim_geom, out ori);
3596
3597 // decide if moving
3598 // use positions since this are integrated quantities
3599 // tolerance values depende a lot on simulation noise...
3600 // use simple math.abs since we dont need to be exact
3601
3602 if (
3603 (Math.Abs(_position.X - lpos.X) < 0.001f)
3604 && (Math.Abs(_position.Y - lpos.Y) < 0.001f)
3605 && (Math.Abs(_position.Z - lpos.Z) < 0.001f)
3606 && (Math.Abs(_orientation.X - ori.X) < 0.0001f)
3607 && (Math.Abs(_orientation.Y - ori.Y) < 0.0001f)
3608 && (Math.Abs(_orientation.Z - ori.Z) < 0.0001f) // ignore W
3609 )
3610 {
3611 _zeroFlag = true;
3612 }
3613 else
3614 _zeroFlag = false;
3615
3616 // update velocities and aceleration
3617 if (!(_zeroFlag && lastZeroFlag))
3618 {
3619 d.Vector3 vel = d.BodyGetLinearVel(Body);
3620
3621 _acceleration = _velocity;
3622
3623 if ((Math.Abs(vel.X) < 0.001f) &&
3624 (Math.Abs(vel.Y) < 0.001f) &&
3625 (Math.Abs(vel.Z) < 0.001f))
3626 {
3627 _velocity = Vector3.Zero;
3628 float t = -m_invTimeStep;
3629 _acceleration = _acceleration * t;
3630 }
3631 else
3632 {
3633 _velocity.X = vel.X;
3634 _velocity.Y = vel.Y;
3635 _velocity.Z = vel.Z;
3636 _acceleration = (_velocity - _acceleration) * m_invTimeStep;
3637 }
3638
3639 if ((Math.Abs(_acceleration.X) < 0.01f) &&
3640 (Math.Abs(_acceleration.Y) < 0.01f) &&
3641 (Math.Abs(_acceleration.Z) < 0.01f))
3642 {
3643 _acceleration = Vector3.Zero;
3644 }
3645
3646 if ((Math.Abs(_orientation.X - ori.X) < 0.0001) &&
3647 (Math.Abs(_orientation.Y - ori.Y) < 0.0001) &&
3648 (Math.Abs(_orientation.Z - ori.Z) < 0.0001)
3649 )
3650 {
3651 m_rotationalVelocity = Vector3.Zero;
3652 }
3653 else
3654 {
3655 vel = d.BodyGetAngularVel(Body);
3656 m_rotationalVelocity.X = vel.X;
3657 m_rotationalVelocity.Y = vel.Y;
3658 m_rotationalVelocity.Z = vel.Z;
3659 }
3660 }
3661
3662 if (_zeroFlag)
3663 {
3664 if (lastZeroFlag)
3665 {
3666 _velocity = Vector3.Zero;
3667 _acceleration = Vector3.Zero;
3668 m_rotationalVelocity = Vector3.Zero;
3669 }
3670
3671 if (!m_lastUpdateSent)
3672 {
3673 base.RequestPhysicsterseUpdate();
3674 if (lastZeroFlag)
3675 m_lastUpdateSent = true;
3676 }
3677 return;
3678 }
3679
3680 _position.X = lpos.X;
3681 _position.Y = lpos.Y;
3682 _position.Z = lpos.Z;
3683
3684 _orientation.X = ori.X;
3685 _orientation.Y = ori.Y;
3686 _orientation.Z = ori.Z;
3687 _orientation.W = ori.W;
3688 base.RequestPhysicsterseUpdate();
3689 m_lastUpdateSent = false;
3690 }
3691 }
3692 }
3693
3694 internal static bool QuaternionIsFinite(Quaternion q)
3695 {
3696 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
3697 return false;
3698 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
3699 return false;
3700 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
3701 return false;
3702 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
3703 return false;
3704 return true;
3705 }
3706
3707 internal static void DMassCopy(ref d.Mass src, ref d.Mass dst)
3708 {
3709 dst.c.W = src.c.W;
3710 dst.c.X = src.c.X;
3711 dst.c.Y = src.c.Y;
3712 dst.c.Z = src.c.Z;
3713 dst.mass = src.mass;
3714 dst.I.M00 = src.I.M00;
3715 dst.I.M01 = src.I.M01;
3716 dst.I.M02 = src.I.M02;
3717 dst.I.M10 = src.I.M10;
3718 dst.I.M11 = src.I.M11;
3719 dst.I.M12 = src.I.M12;
3720 dst.I.M20 = src.I.M20;
3721 dst.I.M21 = src.I.M21;
3722 dst.I.M22 = src.I.M22;
3723 }
3724
3725 internal static void DMassSubPartFromObj(ref d.Mass part, ref d.Mass theobj)
3726 {
3727 // assumes object center of mass is zero
3728 float smass = part.mass;
3729 theobj.mass -= smass;
3730
3731 smass *= 1.0f / (theobj.mass); ;
3732
3733 theobj.c.X -= part.c.X * smass;
3734 theobj.c.Y -= part.c.Y * smass;
3735 theobj.c.Z -= part.c.Z * smass;
3736
3737 theobj.I.M00 -= part.I.M00;
3738 theobj.I.M01 -= part.I.M01;
3739 theobj.I.M02 -= part.I.M02;
3740 theobj.I.M10 -= part.I.M10;
3741 theobj.I.M11 -= part.I.M11;
3742 theobj.I.M12 -= part.I.M12;
3743 theobj.I.M20 -= part.I.M20;
3744 theobj.I.M21 -= part.I.M21;
3745 theobj.I.M22 -= part.I.M22;
3746 }
3747
3748 private static void DMassDup(ref d.Mass src, out d.Mass dst)
3749 {
3750 dst = new d.Mass { };
3751
3752 dst.c.W = src.c.W;
3753 dst.c.X = src.c.X;
3754 dst.c.Y = src.c.Y;
3755 dst.c.Z = src.c.Z;
3756 dst.mass = src.mass;
3757 dst.I.M00 = src.I.M00;
3758 dst.I.M01 = src.I.M01;
3759 dst.I.M02 = src.I.M02;
3760 dst.I.M10 = src.I.M10;
3761 dst.I.M11 = src.I.M11;
3762 dst.I.M12 = src.I.M12;
3763 dst.I.M20 = src.I.M20;
3764 dst.I.M21 = src.I.M21;
3765 dst.I.M22 = src.I.M22;
3766 }
3767 private void donullchange()
3768 {
3769 }
3770
3771 public bool DoAChange(changes what, object arg)
3772 {
3773 if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.Remove)
3774 {
3775 return false;
3776 }
3777
3778 // nasty switch
3779 switch (what)
3780 {
3781 case changes.Add:
3782 changeadd();
3783 break;
3784 case changes.Remove:
3785 //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff...
3786 //When we return true, it destroys all of the prims in the linkset anyway
3787 if (_parent != null)
3788 {
3789 OdePrim parent = (OdePrim)_parent;
3790 parent.ChildRemove(this, false);
3791 }
3792 else
3793 ChildRemove(this, false);
3794
3795 m_vehicle = null;
3796 RemoveGeom();
3797 m_targetSpace = IntPtr.Zero;
3798 if (m_eventsubscription > 0)
3799 UnSubscribeEvents();
3800 return true;
3801
3802 case changes.Link:
3803 OdePrim tmp = (OdePrim)arg;
3804 changeLink(tmp);
3805 break;
3806
3807 case changes.DeLink:
3808 changeLink(null);
3809 break;
3810
3811 case changes.Position:
3812 changePosition((Vector3)arg);
3813 break;
3814
3815 case changes.Orientation:
3816 changeOrientation((Quaternion)arg);
3817 break;
3818
3819 case changes.PosOffset:
3820 donullchange();
3821 break;
3822
3823 case changes.OriOffset:
3824 donullchange();
3825 break;
3826
3827 case changes.Velocity:
3828 changevelocity((Vector3)arg);
3829 break;
3830
3831 // case changes.Acceleration:
3832 // changeacceleration((Vector3)arg);
3833 // break;
3834 // case changes.AngVelocity:
3835 // changeangvelocity((Vector3)arg);
3836 // break;
3837
3838 case changes.Force:
3839 changeForce((Vector3)arg);
3840 break;
3841
3842 case changes.Torque:
3843 changeSetTorque((Vector3)arg);
3844 break;
3845
3846 case changes.AddForce:
3847 changeAddImpulse((Vector3)arg);
3848 break;
3849
3850 case changes.AddAngForce:
3851 changeAddAngularImpulse((Vector3)arg);
3852 break;
3853
3854 case changes.AngLock:
3855 changeAngularLock((Vector3)arg);
3856 break;
3857
3858 case changes.Size:
3859 changeSize((Vector3)arg);
3860 break;
3861
3862 case changes.Shape:
3863 changeShape((PrimitiveBaseShape)arg);
3864 break;
3865
3866 case changes.CollidesWater:
3867 changeFloatOnWater((bool)arg);
3868 break;
3869
3870 case changes.VolumeDtc:
3871 changeVolumedetetion((bool)arg);
3872 break;
3873
3874 case changes.Phantom:
3875 changePhantomStatus((bool)arg);
3876 break;
3877
3878 case changes.Physical:
3879 changePhysicsStatus((bool)arg);
3880 break;
3881
3882 case changes.Selected:
3883 changeSelectedStatus((bool)arg);
3884 break;
3885
3886 case changes.disabled:
3887 changeDisable((bool)arg);
3888 break;
3889
3890 case changes.building:
3891 changeBuilding((bool)arg);
3892 break;
3893
3894 case changes.VehicleType:
3895 changeVehicleType((int)arg);
3896 break;
3897
3898 case changes.VehicleFlags:
3899 changeVehicleFlags((strVehicleBoolParam) arg);
3900 break;
3901
3902 case changes.VehicleFloatParam:
3903 changeVehicleFloatParam((strVehicleFloatParam) arg);
3904 break;
3905
3906 case changes.VehicleVectorParam:
3907 changeVehicleVectorParam((strVehicleVectorParam) arg);
3908 break;
3909
3910 case changes.VehicleRotationParam:
3911 changeVehicleRotationParam((strVehicleQuatParam) arg);
3912 break;
3913
3914 case changes.SetVehicle:
3915 changeSetVehicle((VehicleData) arg);
3916 break;
3917 case changes.Null:
3918 donullchange();
3919 break;
3920
3921 default:
3922 donullchange();
3923 break;
3924 }
3925 return false;
3926 }
3927
3928 public void AddChange(changes what, object arg)
3929 {
3930 _parent_scene.AddChange((PhysicsActor) this, what, arg);
3931 }
3932
3933
3934 private struct strVehicleBoolParam
3935 {
3936 public int param;
3937 public bool value;
3938 }
3939
3940 private struct strVehicleFloatParam
3941 {
3942 public int param;
3943 public float value;
3944 }
3945
3946 private struct strVehicleQuatParam
3947 {
3948 public int param;
3949 public Quaternion value;
3950 }
3951
3952 private struct strVehicleVectorParam
3953 {
3954 public int param;
3955 public Vector3 value;
3956 }
3957 }
3958} \ No newline at end of file