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