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