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