aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs')
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs487
1 files changed, 367 insertions, 120 deletions
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
index a2fbf41..9bf71f7 100644
--- a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
@@ -85,7 +85,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
85 private Vector3 m_lastposition; 85 private Vector3 m_lastposition;
86 private Vector3 m_rotationalVelocity; 86 private Vector3 m_rotationalVelocity;
87 private Vector3 _size; 87 private Vector3 _size;
88 private Vector3 _acceleration; 88 private Vector3 m_acceleration;
89 private IntPtr Amotor; 89 private IntPtr Amotor;
90 90
91 internal Vector3 m_force; 91 internal Vector3 m_force;
@@ -109,8 +109,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde
109 private float m_waterHeight; 109 private float m_waterHeight;
110 private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. 110 private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
111 111
112 private int body_autodisable_frames; 112 private int m_body_autodisable_frames;
113 public int bodydisablecontrol = 0; 113 public int m_bodydisablecontrol = 0;
114 private float m_gravmod = 1.0f; 114 private float m_gravmod = 1.0f;
115 115
116 // Default we're a Geometry 116 // Default we're a Geometry
@@ -182,18 +182,21 @@ namespace OpenSim.Region.PhysicsModule.ubOde
182 private float m_streamCost; 182 private float m_streamCost;
183 183
184 public d.Mass primdMass; // prim inertia information on it's own referencial 184 public d.Mass primdMass; // prim inertia information on it's own referencial
185 private PhysicsInertiaData m_InertiaOverride;
185 float primMass; // prim own mass 186 float primMass; // prim own mass
186 float primVolume; // prim own volume; 187 float primVolume; // prim own volume;
187 float _mass; // object mass acording to case 188 float m_mass; // object mass acording to case
188 189
189 public int givefakepos; 190 public int givefakepos;
190 private Vector3 fakepos; 191 private Vector3 fakepos;
191 public int givefakeori; 192 public int givefakeori;
192 private Quaternion fakeori; 193 private Quaternion fakeori;
194 private PhysicsInertiaData m_fakeInertiaOverride;
193 195
194 private int m_eventsubscription; 196 private int m_eventsubscription;
195 private int m_cureventsubscription; 197 private int m_cureventsubscription;
196 private CollisionEventUpdate CollisionEventsThisFrame = null; 198 private CollisionEventUpdate CollisionEventsThisFrame = null;
199 private CollisionEventUpdate CollisionVDTCEventsThisFrame = null;
197 private bool SentEmptyCollisionsEvent; 200 private bool SentEmptyCollisionsEvent;
198 201
199 public volatile bool childPrim; 202 public volatile bool childPrim;
@@ -465,6 +468,103 @@ namespace OpenSim.Region.PhysicsModule.ubOde
465 } 468 }
466 } 469 }
467 470
471 public override PhysicsInertiaData GetInertiaData()
472 {
473 PhysicsInertiaData inertia;
474 if(childPrim)
475 {
476 if(_parent != null)
477 return _parent.GetInertiaData();
478 else
479 {
480 inertia = new PhysicsInertiaData();
481 inertia.TotalMass = -1;
482 return inertia;
483 }
484 }
485
486 inertia = new PhysicsInertiaData();
487
488 // double buffering
489 if(m_fakeInertiaOverride != null)
490 {
491 d.Mass objdmass = new d.Mass();
492 objdmass.I.M00 = m_fakeInertiaOverride.Inertia.X;
493 objdmass.I.M11 = m_fakeInertiaOverride.Inertia.Y;
494 objdmass.I.M22 = m_fakeInertiaOverride.Inertia.Z;
495
496 objdmass.mass = m_fakeInertiaOverride.TotalMass;
497
498 if(Math.Abs(m_fakeInertiaOverride.InertiaRotation.W) < 0.999)
499 {
500 d.Matrix3 inertiarotmat = new d.Matrix3();
501 d.Quaternion inertiarot = new d.Quaternion();
502
503 inertiarot.X = m_fakeInertiaOverride.InertiaRotation.X;
504 inertiarot.Y = m_fakeInertiaOverride.InertiaRotation.Y;
505 inertiarot.Z = m_fakeInertiaOverride.InertiaRotation.Z;
506 inertiarot.W = m_fakeInertiaOverride.InertiaRotation.W;
507 d.RfromQ(out inertiarotmat, ref inertiarot);
508 d.MassRotate(ref objdmass, ref inertiarotmat);
509 }
510
511 inertia.TotalMass = m_fakeInertiaOverride.TotalMass;
512 inertia.CenterOfMass = m_fakeInertiaOverride.CenterOfMass;
513 inertia.Inertia.X = objdmass.I.M00;
514 inertia.Inertia.Y = objdmass.I.M11;
515 inertia.Inertia.Z = objdmass.I.M22;
516 inertia.InertiaRotation.X = objdmass.I.M01;
517 inertia.InertiaRotation.Y = objdmass.I.M02;
518 inertia.InertiaRotation.Z = objdmass.I.M12;
519 return inertia;
520 }
521
522 inertia.TotalMass = m_mass;
523
524 if(Body == IntPtr.Zero || prim_geom == IntPtr.Zero)
525 {
526 inertia.CenterOfMass = Vector3.Zero;
527 inertia.Inertia = Vector3.Zero;
528 inertia.InertiaRotation = Vector4.Zero;
529 return inertia;
530 }
531
532 d.Vector3 dtmp;
533 d.Mass m = new d.Mass();
534 lock(_parent_scene.OdeLock)
535 {
536 d.AllocateODEDataForThread(0);
537 dtmp = d.GeomGetOffsetPosition(prim_geom);
538 d.BodyGetMass(Body, out m);
539 }
540
541 Vector3 cm = new Vector3(-dtmp.X, -dtmp.Y, -dtmp.Z);
542 inertia.CenterOfMass = cm;
543 inertia.Inertia = new Vector3(m.I.M00, m.I.M11, m.I.M22);
544 inertia.InertiaRotation = new Vector4(m.I.M01, m.I.M02 , m.I.M12, 0);
545
546 return inertia;
547 }
548
549 public override void SetInertiaData(PhysicsInertiaData inertia)
550 {
551 if(childPrim)
552 {
553 if(_parent != null)
554 _parent.SetInertiaData(inertia);
555 return;
556 }
557
558 if(inertia.TotalMass > 0)
559 m_fakeInertiaOverride = new PhysicsInertiaData(inertia);
560 else
561 m_fakeInertiaOverride = null;
562
563 if (inertia.TotalMass > _parent_scene.maximumMassObject)
564 inertia.TotalMass = _parent_scene.maximumMassObject;
565 AddChange(changes.SetInertia,(object)m_fakeInertiaOverride);
566 }
567
468 public override Vector3 CenterOfMass 568 public override Vector3 CenterOfMass
469 { 569 {
470 get 570 get
@@ -569,7 +669,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
569 { 669 {
570 if (value.IsFinite()) 670 if (value.IsFinite())
571 { 671 {
572 AddChange(changes.Velocity, value); 672 if(m_outbounds)
673 _velocity = value;
674 else
675 AddChange(changes.Velocity, value);
573 } 676 }
574 else 677 else
575 { 678 {
@@ -642,8 +745,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde
642 745
643 public override Vector3 Acceleration 746 public override Vector3 Acceleration
644 { 747 {
645 get { return _acceleration; } 748 get { return m_acceleration; }
646 set { } 749 set
750 {
751 if(m_outbounds)
752 m_acceleration = value;
753 }
647 } 754 }
648 755
649 public override Vector3 RotationalVelocity 756 public override Vector3 RotationalVelocity
@@ -663,7 +770,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
663 { 770 {
664 if (value.IsFinite()) 771 if (value.IsFinite())
665 { 772 {
666 AddChange(changes.AngVelocity, value); 773 if(m_outbounds)
774 m_rotationalVelocity = value;
775 else
776 AddChange(changes.AngVelocity, value);
667 } 777 }
668 else 778 else
669 { 779 {
@@ -837,7 +947,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
837 } 947 }
838 public void SetAcceleration(Vector3 accel) 948 public void SetAcceleration(Vector3 accel)
839 { 949 {
840 _acceleration = accel; 950 m_acceleration = accel;
841 } 951 }
842 952
843 public override void AddForce(Vector3 force, bool pushforce) 953 public override void AddForce(Vector3 force, bool pushforce)
@@ -873,31 +983,68 @@ namespace OpenSim.Region.PhysicsModule.ubOde
873 983
874 public override void CrossingFailure() 984 public override void CrossingFailure()
875 { 985 {
876 if (m_outbounds) 986 lock(_parent_scene.OdeLock)
987 {
988 if (m_outbounds)
989 {
990 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f);
991 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f);
992 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
993
994 m_lastposition = _position;
995 _velocity.X = 0;
996 _velocity.Y = 0;
997 _velocity.Z = 0;
998
999 d.AllocateODEDataForThread(0);
1000
1001 m_lastVelocity = _velocity;
1002 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
1003 m_vehicle.Stop();
1004
1005 if(Body != IntPtr.Zero)
1006 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
1007 if (prim_geom != IntPtr.Zero)
1008 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1009
1010 m_outbounds = false;
1011 changeDisable(false);
1012 base.RequestPhysicsterseUpdate();
1013 }
1014 }
1015 }
1016
1017 public override void CrossingStart()
1018 {
1019 lock(_parent_scene.OdeLock)
877 { 1020 {
878 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f); 1021 if (m_outbounds || childPrim)
879 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f); 1022 return;
880 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f); 1023
1024 m_outbounds = true;
881 1025
882 m_lastposition = _position; 1026 m_lastposition = _position;
883 _velocity.X = 0; 1027 m_lastorientation = _orientation;
884 _velocity.Y = 0;
885 _velocity.Z = 0;
886 1028
887 d.AllocateODEDataForThread(0); 1029 d.AllocateODEDataForThread(0);
1030 if(Body != IntPtr.Zero)
1031 {
1032 d.Vector3 dtmp = d.BodyGetAngularVel(Body);
1033 m_rotationalVelocity.X = dtmp.X;
1034 m_rotationalVelocity.Y = dtmp.Y;
1035 m_rotationalVelocity.Z = dtmp.Z;
888 1036
889 m_lastVelocity = _velocity; 1037 dtmp = d.BodyGetLinearVel(Body);
890 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) 1038 _velocity.X = dtmp.X;
891 m_vehicle.Stop(); 1039 _velocity.Y = dtmp.Y;
1040 _velocity.Z = dtmp.Z;
892 1041
893 if(Body != IntPtr.Zero)
894 d.BodySetLinearVel(Body, 0, 0, 0); // stop it 1042 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
895 if (prim_geom != IntPtr.Zero) 1043 d.BodySetAngularVel(Body, 0, 0, 0);
896 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 1044 }
897 1045 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
898 m_outbounds = false; 1046 disableBodySoft(); // stop collisions
899 changeDisable(false); 1047 UnSubscribeEvents();
900 base.RequestPhysicsterseUpdate();
901 } 1048 }
902 } 1049 }
903 1050
@@ -920,8 +1067,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
920 } 1067 }
921 set 1068 set
922 { 1069 {
1070 float old = m_density;
923 m_density = value / 100f; 1071 m_density = value / 100f;
924 // for not prim mass is not updated since this implies full rebuild of body inertia TODO 1072 // if(m_density != old)
1073 // UpdatePrimBodyData();
925 } 1074 }
926 } 1075 }
927 public override float GravModifier 1076 public override float GravModifier
@@ -989,11 +1138,18 @@ namespace OpenSim.Region.PhysicsModule.ubOde
989 m_cureventsubscription = 0; 1138 m_cureventsubscription = 0;
990 if (CollisionEventsThisFrame == null) 1139 if (CollisionEventsThisFrame == null)
991 CollisionEventsThisFrame = new CollisionEventUpdate(); 1140 CollisionEventsThisFrame = new CollisionEventUpdate();
1141 if (CollisionVDTCEventsThisFrame == null)
1142 CollisionVDTCEventsThisFrame = new CollisionEventUpdate();
992 SentEmptyCollisionsEvent = false; 1143 SentEmptyCollisionsEvent = false;
993 } 1144 }
994 1145
995 public override void UnSubscribeEvents() 1146 public override void UnSubscribeEvents()
996 { 1147 {
1148 if (CollisionVDTCEventsThisFrame != null)
1149 {
1150 CollisionVDTCEventsThisFrame.Clear();
1151 CollisionVDTCEventsThisFrame = null;
1152 }
997 if (CollisionEventsThisFrame != null) 1153 if (CollisionEventsThisFrame != null)
998 { 1154 {
999 CollisionEventsThisFrame.Clear(); 1155 CollisionEventsThisFrame.Clear();
@@ -1012,37 +1168,67 @@ namespace OpenSim.Region.PhysicsModule.ubOde
1012 _parent_scene.AddCollisionEventReporting(this); 1168 _parent_scene.AddCollisionEventReporting(this);
1013 } 1169 }
1014 1170
1171 public override void AddVDTCCollisionEvent(uint CollidedWith, ContactPoint contact)
1172 {
1173 if (CollisionVDTCEventsThisFrame == null)
1174 CollisionVDTCEventsThisFrame = new CollisionEventUpdate();
1175
1176 CollisionVDTCEventsThisFrame.AddCollider(CollidedWith, contact);
1177 _parent_scene.AddCollisionEventReporting(this);
1178 }
1179
1015 internal void SleeperAddCollisionEvents() 1180 internal void SleeperAddCollisionEvents()
1016 { 1181 {
1017 if (CollisionEventsThisFrame == null) 1182 if(CollisionEventsThisFrame != null && CollisionEventsThisFrame.m_objCollisionList.Count != 0)
1018 return; 1183 {
1019 if(CollisionEventsThisFrame.m_objCollisionList.Count == 0) 1184 foreach(KeyValuePair<uint,ContactPoint> kvp in CollisionEventsThisFrame.m_objCollisionList)
1020 return; 1185 {
1021 foreach(KeyValuePair<uint,ContactPoint> kvp in CollisionEventsThisFrame.m_objCollisionList) 1186 if(kvp.Key == 0)
1187 continue;
1188 OdePrim other = _parent_scene.getPrim(kvp.Key);
1189 if(other == null)
1190 continue;
1191 ContactPoint cp = kvp.Value;
1192 cp.SurfaceNormal = - cp.SurfaceNormal;
1193 cp.RelativeSpeed = -cp.RelativeSpeed;
1194 other.AddCollisionEvent(ParentActor.LocalID,cp);
1195 }
1196 }
1197 if(CollisionVDTCEventsThisFrame != null && CollisionVDTCEventsThisFrame.m_objCollisionList.Count != 0)
1022 { 1198 {
1023 OdePrim other = _parent_scene.getPrim(kvp.Key); 1199 foreach(KeyValuePair<uint,ContactPoint> kvp in CollisionVDTCEventsThisFrame.m_objCollisionList)
1024 if(other == null) 1200 {
1025 continue; 1201 OdePrim other = _parent_scene.getPrim(kvp.Key);
1026 ContactPoint cp = kvp.Value; 1202 if(other == null)
1027 cp.SurfaceNormal = - cp.SurfaceNormal; 1203 continue;
1028 cp.RelativeSpeed = -cp.RelativeSpeed; 1204 ContactPoint cp = kvp.Value;
1029 other.AddCollisionEvent(ParentActor.LocalID,cp); 1205 cp.SurfaceNormal = - cp.SurfaceNormal;
1206 cp.RelativeSpeed = -cp.RelativeSpeed;
1207 other.AddCollisionEvent(ParentActor.LocalID,cp);
1208 }
1030 } 1209 }
1031 } 1210 }
1032 1211
1212 internal void clearSleeperCollisions()
1213 {
1214 if(CollisionVDTCEventsThisFrame != null && CollisionVDTCEventsThisFrame.Count >0 )
1215 CollisionVDTCEventsThisFrame.Clear();
1216 }
1217
1033 public void SendCollisions(int timestep) 1218 public void SendCollisions(int timestep)
1034 { 1219 {
1035 if (m_cureventsubscription < 50000) 1220 if (m_cureventsubscription < 50000)
1036 m_cureventsubscription += timestep; 1221 m_cureventsubscription += timestep;
1037 1222
1223
1224 if (m_cureventsubscription < m_eventsubscription)
1225 return;
1226
1038 if (CollisionEventsThisFrame == null) 1227 if (CollisionEventsThisFrame == null)
1039 return; 1228 return;
1040 1229
1041 int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count; 1230 int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count;
1042 1231
1043 if (m_cureventsubscription < m_eventsubscription)
1044 return;
1045
1046 if (!SentEmptyCollisionsEvent || ncolisions > 0) 1232 if (!SentEmptyCollisionsEvent || ncolisions > 0)
1047 { 1233 {
1048 base.SendCollisionUpdate(CollisionEventsThisFrame); 1234 base.SendCollisionUpdate(CollisionEventsThisFrame);
@@ -1091,7 +1277,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
1091 m_invTimeStep = 1f / m_timeStep; 1277 m_invTimeStep = 1f / m_timeStep;
1092 1278
1093 m_density = parent_scene.geomDefaultDensity; 1279 m_density = parent_scene.geomDefaultDensity;
1094 body_autodisable_frames = parent_scene.bodyFramesAutoDisable; 1280 m_body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
1095 1281
1096 prim_geom = IntPtr.Zero; 1282 prim_geom = IntPtr.Zero;
1097 collide_geom = IntPtr.Zero; 1283 collide_geom = IntPtr.Zero;
@@ -1714,26 +1900,29 @@ namespace OpenSim.Region.PhysicsModule.ubOde
1714 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body"); 1900 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body");
1715 } 1901 }
1716 1902
1717 d.Matrix3 mymat = new d.Matrix3(); 1903 bool noInertiaOverride = (m_InertiaOverride == null);
1718 d.Quaternion myrot = new d.Quaternion();
1719 d.Mass objdmass = new d.Mass { };
1720 1904
1721 Body = d.BodyCreate(_parent_scene.world); 1905 Body = d.BodyCreate(_parent_scene.world);
1722 1906
1723 objdmass = primdMass; 1907 d.Matrix3 mymat = new d.Matrix3();
1908 d.Quaternion myrot = new d.Quaternion();
1909 d.Mass objdmass = new d.Mass { };
1724 1910
1725 // rotate inertia
1726 myrot.X = _orientation.X; 1911 myrot.X = _orientation.X;
1727 myrot.Y = _orientation.Y; 1912 myrot.Y = _orientation.Y;
1728 myrot.Z = _orientation.Z; 1913 myrot.Z = _orientation.Z;
1729 myrot.W = _orientation.W; 1914 myrot.W = _orientation.W;
1730
1731 d.RfromQ(out mymat, ref myrot); 1915 d.RfromQ(out mymat, ref myrot);
1732 d.MassRotate(ref objdmass, ref mymat);
1733 1916
1734 // set the body rotation 1917 // set the body rotation
1735 d.BodySetRotation(Body, ref mymat); 1918 d.BodySetRotation(Body, ref mymat);
1736 1919
1920 if(noInertiaOverride)
1921 {
1922 objdmass = primdMass;
1923 d.MassRotate(ref objdmass, ref mymat);
1924 }
1925
1737 // recompute full object inertia if needed 1926 // recompute full object inertia if needed
1738 if (childrenPrim.Count > 0) 1927 if (childrenPrim.Count > 0)
1739 { 1928 {
@@ -1756,27 +1945,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde
1756 continue; 1945 continue;
1757 } 1946 }
1758 1947
1759 tmpdmass = prm.primdMass;
1760
1761 // apply prim current rotation to inertia
1762 quat.X = prm._orientation.X; 1948 quat.X = prm._orientation.X;
1763 quat.Y = prm._orientation.Y; 1949 quat.Y = prm._orientation.Y;
1764 quat.Z = prm._orientation.Z; 1950 quat.Z = prm._orientation.Z;
1765 quat.W = prm._orientation.W; 1951 quat.W = prm._orientation.W;
1766 d.RfromQ(out mat, ref quat); 1952 d.RfromQ(out mat, ref quat);
1767 d.MassRotate(ref tmpdmass, ref mat); 1953
1768
1769 Vector3 ppos = prm._position;
1770 ppos.X -= rcm.X;
1771 ppos.Y -= rcm.Y;
1772 ppos.Z -= rcm.Z;
1773 // refer inertia to root prim center of mass position
1774 d.MassTranslate(ref tmpdmass,
1775 ppos.X,
1776 ppos.Y,
1777 ppos.Z);
1778
1779 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
1780 // fix prim colision cats 1954 // fix prim colision cats
1781 1955
1782 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero) 1956 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero)
@@ -1789,6 +1963,24 @@ namespace OpenSim.Region.PhysicsModule.ubOde
1789 d.GeomSetBody(prm.prim_geom, Body); 1963 d.GeomSetBody(prm.prim_geom, Body);
1790 prm.Body = Body; 1964 prm.Body = Body;
1791 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation 1965 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation
1966
1967 if(noInertiaOverride)
1968 {
1969 tmpdmass = prm.primdMass;
1970
1971 d.MassRotate(ref tmpdmass, ref mat);
1972 Vector3 ppos = prm._position;
1973 ppos.X -= rcm.X;
1974 ppos.Y -= rcm.Y;
1975 ppos.Z -= rcm.Z;
1976 // refer inertia to root prim center of mass position
1977 d.MassTranslate(ref tmpdmass,
1978 ppos.X,
1979 ppos.Y,
1980 ppos.Z);
1981
1982 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
1983 }
1792 } 1984 }
1793 } 1985 }
1794 } 1986 }
@@ -1797,25 +1989,66 @@ namespace OpenSim.Region.PhysicsModule.ubOde
1797 // associate root geom with body 1989 // associate root geom with body
1798 d.GeomSetBody(prim_geom, Body); 1990 d.GeomSetBody(prim_geom, Body);
1799 1991
1800 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z); 1992 if(noInertiaOverride)
1993 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
1994 else
1995 {
1996 Vector3 ncm = m_InertiaOverride.CenterOfMass * _orientation;
1997 d.BodySetPosition(Body,
1998 _position.X + ncm.X,
1999 _position.Y + ncm.Y,
2000 _position.Z + ncm.Z);
2001 }
2002
1801 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z); 2003 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z);
1802 2004
1803 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body 2005 if(noInertiaOverride)
1804 myrot.X = -myrot.X; 2006 {
1805 myrot.Y = -myrot.Y; 2007 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
1806 myrot.Z = -myrot.Z; 2008 myrot.X = -myrot.X;
2009 myrot.Y = -myrot.Y;
2010 myrot.Z = -myrot.Z;
1807 2011
1808 d.RfromQ(out mymat, ref myrot); 2012 d.RfromQ(out mymat, ref myrot);
1809 d.MassRotate(ref objdmass, ref mymat); 2013 d.MassRotate(ref objdmass, ref mymat);
1810 2014
1811 d.BodySetMass(Body, ref objdmass); 2015 d.BodySetMass(Body, ref objdmass);
1812 _mass = objdmass.mass; 2016 m_mass = objdmass.mass;
2017 }
2018 else
2019 {
2020 objdmass.c.X = 0;
2021 objdmass.c.Y = 0;
2022 objdmass.c.Z = 0;
2023
2024 objdmass.I.M00 = m_InertiaOverride.Inertia.X;
2025 objdmass.I.M11 = m_InertiaOverride.Inertia.Y;
2026 objdmass.I.M22 = m_InertiaOverride.Inertia.Z;
2027
2028 objdmass.mass = m_InertiaOverride.TotalMass;
2029
2030 if(Math.Abs(m_InertiaOverride.InertiaRotation.W) < 0.999)
2031 {
2032 d.Matrix3 inertiarotmat = new d.Matrix3();
2033 d.Quaternion inertiarot = new d.Quaternion();
2034
2035 inertiarot.X = m_InertiaOverride.InertiaRotation.X;
2036 inertiarot.Y = m_InertiaOverride.InertiaRotation.Y;
2037 inertiarot.Z = m_InertiaOverride.InertiaRotation.Z;
2038 inertiarot.W = m_InertiaOverride.InertiaRotation.W;
2039 d.RfromQ(out inertiarotmat, ref inertiarot);
2040 d.MassRotate(ref objdmass, ref inertiarotmat);
2041 }
2042 d.BodySetMass(Body, ref objdmass);
2043
2044 m_mass = objdmass.mass;
2045 }
1813 2046
1814 // disconnect from world gravity so we can apply buoyancy 2047 // disconnect from world gravity so we can apply buoyancy
1815 d.BodySetGravityMode(Body, false); 2048 d.BodySetGravityMode(Body, false);
1816 2049
1817 d.BodySetAutoDisableFlag(Body, true); 2050 d.BodySetAutoDisableFlag(Body, true);
1818 d.BodySetAutoDisableSteps(Body, body_autodisable_frames); 2051 d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
1819 d.BodySetAutoDisableAngularThreshold(Body, 0.05f); 2052 d.BodySetAutoDisableAngularThreshold(Body, 0.05f);
1820 d.BodySetAutoDisableLinearThreshold(Body, 0.05f); 2053 d.BodySetAutoDisableLinearThreshold(Body, 0.05f);
1821 d.BodySetDamping(Body, .004f, .001f); 2054 d.BodySetDamping(Body, .004f, .001f);
@@ -1909,8 +2142,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde
1909 { 2142 {
1910 d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z); 2143 d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z);
1911 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z); 2144 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
2145
1912 _zeroFlag = false; 2146 _zeroFlag = false;
1913 bodydisablecontrol = 0; 2147 m_bodydisablecontrol = 0;
1914 } 2148 }
1915 _parent_scene.addActiveGroups(this); 2149 _parent_scene.addActiveGroups(this);
1916 } 2150 }
@@ -1988,7 +2222,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
1988 SetInStaticSpace(prm); 2222 SetInStaticSpace(prm);
1989 } 2223 }
1990 prm.Body = IntPtr.Zero; 2224 prm.Body = IntPtr.Zero;
1991 prm._mass = prm.primMass; 2225 prm.m_mass = prm.primMass;
1992 prm.m_collisionscore = 0; 2226 prm.m_collisionscore = 0;
1993 } 2227 }
1994 } 2228 }
@@ -2002,7 +2236,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
2002 } 2236 }
2003 Body = IntPtr.Zero; 2237 Body = IntPtr.Zero;
2004 } 2238 }
2005 _mass = primMass; 2239 m_mass = primMass;
2006 m_collisionscore = 0; 2240 m_collisionscore = 0;
2007 } 2241 }
2008 2242
@@ -2079,7 +2313,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
2079 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z); 2313 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2080 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body 2314 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2081 d.BodySetMass(Body, ref objdmass); 2315 d.BodySetMass(Body, ref objdmass);
2082 _mass = objdmass.mass; 2316 m_mass = objdmass.mass;
2083 } 2317 }
2084 2318
2085 private void FixInertia(Vector3 NewPos) 2319 private void FixInertia(Vector3 NewPos)
@@ -2143,7 +2377,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
2143 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z); 2377 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2144 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body 2378 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2145 d.BodySetMass(Body, ref objdmass); 2379 d.BodySetMass(Body, ref objdmass);
2146 _mass = objdmass.mass; 2380 m_mass = objdmass.mass;
2147 } 2381 }
2148 2382
2149 private void FixInertia(Quaternion newrot) 2383 private void FixInertia(Quaternion newrot)
@@ -2209,7 +2443,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
2209 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z); 2443 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2210 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body 2444 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2211 d.BodySetMass(Body, ref objdmass); 2445 d.BodySetMass(Body, ref objdmass);
2212 _mass = objdmass.mass; 2446 m_mass = objdmass.mass;
2213 } 2447 }
2214 2448
2215 2449
@@ -2224,7 +2458,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
2224 if (primMass > _parent_scene.maximumMassObject) 2458 if (primMass > _parent_scene.maximumMassObject)
2225 primMass = _parent_scene.maximumMassObject; 2459 primMass = _parent_scene.maximumMassObject;
2226 2460
2227 _mass = primMass; // just in case 2461 m_mass = primMass; // just in case
2228 2462
2229 d.MassSetBoxTotal(out primdMass, primMass, 2.0f * m_OBB.X, 2.0f * m_OBB.Y, 2.0f * m_OBB.Z); 2463 d.MassSetBoxTotal(out primdMass, primMass, 2.0f * m_OBB.X, 2.0f * m_OBB.Y, 2.0f * m_OBB.Z);
2230 2464
@@ -2514,7 +2748,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
2514 m_angularForceacc = Vector3.Zero; 2748 m_angularForceacc = Vector3.Zero;
2515// m_torque = Vector3.Zero; 2749// m_torque = Vector3.Zero;
2516 _velocity = Vector3.Zero; 2750 _velocity = Vector3.Zero;
2517 _acceleration = Vector3.Zero; 2751 m_acceleration = Vector3.Zero;
2518 m_rotationalVelocity = Vector3.Zero; 2752 m_rotationalVelocity = Vector3.Zero;
2519 _target_velocity = Vector3.Zero; 2753 _target_velocity = Vector3.Zero;
2520 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) 2754 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
@@ -2767,8 +3001,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde
2767 myrot.W = newOri.W; 3001 myrot.W = newOri.W;
2768 d.GeomSetQuaternion(prim_geom, ref myrot); 3002 d.GeomSetQuaternion(prim_geom, ref myrot);
2769 _orientation = newOri; 3003 _orientation = newOri;
2770 if (Body != IntPtr.Zero && m_angularlocks != 0) 3004
2771 createAMotor(m_angularlocks); 3005 if (Body != IntPtr.Zero)
3006 {
3007 if(m_angularlocks != 0)
3008 createAMotor(m_angularlocks);
3009 }
2772 } 3010 }
2773 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) 3011 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2774 { 3012 {
@@ -3064,7 +3302,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3064 3302
3065 private void changeSetTorque(Vector3 newtorque) 3303 private void changeSetTorque(Vector3 newtorque)
3066 { 3304 {
3067 if (!m_isSelected) 3305 if (!m_isSelected && !m_outbounds)
3068 { 3306 {
3069 if (m_isphysical && Body != IntPtr.Zero) 3307 if (m_isphysical && Body != IntPtr.Zero)
3070 { 3308 {
@@ -3081,14 +3319,14 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3081 private void changeForce(Vector3 force) 3319 private void changeForce(Vector3 force)
3082 { 3320 {
3083 m_force = force; 3321 m_force = force;
3084 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) 3322 if (!m_isSelected && !m_outbounds && Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
3085 d.BodyEnable(Body); 3323 d.BodyEnable(Body);
3086 } 3324 }
3087 3325
3088 private void changeAddForce(Vector3 theforce) 3326 private void changeAddForce(Vector3 theforce)
3089 { 3327 {
3090 m_forceacc += theforce; 3328 m_forceacc += theforce;
3091 if (!m_isSelected) 3329 if (!m_isSelected && !m_outbounds)
3092 { 3330 {
3093 lock (this) 3331 lock (this)
3094 { 3332 {
@@ -3109,7 +3347,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3109 private void changeAddAngularImpulse(Vector3 aimpulse) 3347 private void changeAddAngularImpulse(Vector3 aimpulse)
3110 { 3348 {
3111 m_angularForceacc += aimpulse * m_invTimeStep; 3349 m_angularForceacc += aimpulse * m_invTimeStep;
3112 if (!m_isSelected) 3350 if (!m_isSelected && !m_outbounds)
3113 { 3351 {
3114 lock (this) 3352 lock (this)
3115 { 3353 {
@@ -3134,7 +3372,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3134 newVel *= len; 3372 newVel *= len;
3135 } 3373 }
3136 3374
3137 if (!m_isSelected) 3375 if (!m_isSelected && !m_outbounds)
3138 { 3376 {
3139 if (Body != IntPtr.Zero) 3377 if (Body != IntPtr.Zero)
3140 { 3378 {
@@ -3142,7 +3380,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3142 enableBodySoft(); 3380 enableBodySoft();
3143 else if (!d.BodyIsEnabled(Body)) 3381 else if (!d.BodyIsEnabled(Body))
3144 d.BodyEnable(Body); 3382 d.BodyEnable(Body);
3145
3146 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z); 3383 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
3147 } 3384 }
3148 //resetCollisionAccounting(); 3385 //resetCollisionAccounting();
@@ -3159,7 +3396,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3159 newAngVel *= len; 3396 newAngVel *= len;
3160 } 3397 }
3161 3398
3162 if (!m_isSelected) 3399 if (!m_isSelected && !m_outbounds)
3163 { 3400 {
3164 if (Body != IntPtr.Zero) 3401 if (Body != IntPtr.Zero)
3165 { 3402 {
@@ -3167,8 +3404,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3167 enableBodySoft(); 3404 enableBodySoft();
3168 else if (!d.BodyIsEnabled(Body)) 3405 else if (!d.BodyIsEnabled(Body))
3169 d.BodyEnable(Body); 3406 d.BodyEnable(Body);
3170
3171
3172 d.BodySetAngularVel(Body, newAngVel.X, newAngVel.Y, newAngVel.Z); 3407 d.BodySetAngularVel(Body, newAngVel.X, newAngVel.Y, newAngVel.Z);
3173 } 3408 }
3174 //resetCollisionAccounting(); 3409 //resetCollisionAccounting();
@@ -3304,6 +3539,15 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3304 m_useHoverPID = active; 3539 m_useHoverPID = active;
3305 } 3540 }
3306 3541
3542 private void changeInertia(PhysicsInertiaData inertia)
3543 {
3544 m_InertiaOverride = inertia;
3545
3546 if (Body != IntPtr.Zero)
3547 DestroyBody();
3548 MakeBody();
3549 }
3550
3307 #endregion 3551 #endregion
3308 3552
3309 public void Move() 3553 public void Move()
@@ -3317,7 +3561,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3317 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) 3561 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3318 return; 3562 return;
3319 3563
3320 if (++bodydisablecontrol < 50) 3564 if (++m_bodydisablecontrol < 50)
3321 return; 3565 return;
3322 3566
3323 // clear residuals 3567 // clear residuals
@@ -3325,11 +3569,11 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3325 d.BodySetLinearVel(Body,0f,0f,0f); 3569 d.BodySetLinearVel(Body,0f,0f,0f);
3326 _zeroFlag = true; 3570 _zeroFlag = true;
3327 d.BodyEnable(Body); 3571 d.BodyEnable(Body);
3328 bodydisablecontrol = -4; 3572 m_bodydisablecontrol = -4;
3329 } 3573 }
3330 3574
3331 if(bodydisablecontrol < 0) 3575 if(m_bodydisablecontrol < 0)
3332 bodydisablecontrol ++; 3576 m_bodydisablecontrol ++;
3333 3577
3334 d.Vector3 lpos = d.GeomGetPosition(prim_geom); // root position that is seem by rest of simulator 3578 d.Vector3 lpos = d.GeomGetPosition(prim_geom); // root position that is seem by rest of simulator
3335 3579
@@ -3344,7 +3588,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3344 float fy = 0; 3588 float fy = 0;
3345 float fz = 0; 3589 float fz = 0;
3346 3590
3347 float m_mass = _mass; 3591 float mass = m_mass;
3348 3592
3349 if (m_usePID && m_PIDTau > 0) 3593 if (m_usePID && m_PIDTau > 0)
3350 { 3594 {
@@ -3451,9 +3695,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3451 fz = _parent_scene.gravityz * b; 3695 fz = _parent_scene.gravityz * b;
3452 } 3696 }
3453 3697
3454 fx *= m_mass; 3698 fx *= mass;
3455 fy *= m_mass; 3699 fy *= mass;
3456 fz *= m_mass; 3700 fz *= mass;
3457 3701
3458 // constant force 3702 // constant force
3459 fx += m_force.X; 3703 fx += m_force.X;
@@ -3498,7 +3742,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3498 { 3742 {
3499 bool bodyenabled = d.BodyIsEnabled(Body); 3743 bool bodyenabled = d.BodyIsEnabled(Body);
3500 3744
3501 if(bodydisablecontrol < 0) 3745 if(m_bodydisablecontrol < 0)
3502 return; 3746 return;
3503 3747
3504 if (bodyenabled || !_zeroFlag) 3748 if (bodyenabled || !_zeroFlag)
@@ -3513,9 +3757,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3513 m_outbounds = true; 3757 m_outbounds = true;
3514 3758
3515 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f); 3759 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f);
3516 _acceleration.X = 0; 3760 m_acceleration.X = 0;
3517 _acceleration.Y = 0; 3761 m_acceleration.Y = 0;
3518 _acceleration.Z = 0; 3762 m_acceleration.Z = 0;
3519 3763
3520 _velocity.X = 0; 3764 _velocity.X = 0;
3521 _velocity.Y = 0; 3765 _velocity.Y = 0;
@@ -3638,19 +3882,19 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3638 _orientation.W = ori.W; 3882 _orientation.W = ori.W;
3639 } 3883 }
3640 3884
3641 // update velocities and aceleration 3885 // update velocities and acceleration
3642 if (_zeroFlag || lastZeroFlag) 3886 if (_zeroFlag || lastZeroFlag)
3643 { 3887 {
3644 // disable interpolators 3888 // disable interpolators
3645 _velocity = Vector3.Zero; 3889 _velocity = Vector3.Zero;
3646 _acceleration = Vector3.Zero; 3890 m_acceleration = Vector3.Zero;
3647 m_rotationalVelocity = Vector3.Zero; 3891 m_rotationalVelocity = Vector3.Zero;
3648 } 3892 }
3649 else 3893 else
3650 { 3894 {
3651 d.Vector3 vel = d.BodyGetLinearVel(Body); 3895 d.Vector3 vel = d.BodyGetLinearVel(Body);
3652 3896
3653 _acceleration = _velocity; 3897 m_acceleration = _velocity;
3654 3898
3655 if ((Math.Abs(vel.X) < 0.005f) && 3899 if ((Math.Abs(vel.X) < 0.005f) &&
3656 (Math.Abs(vel.Y) < 0.005f) && 3900 (Math.Abs(vel.Y) < 0.005f) &&
@@ -3658,28 +3902,28 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3658 { 3902 {
3659 _velocity = Vector3.Zero; 3903 _velocity = Vector3.Zero;
3660 float t = -m_invTimeStep; 3904 float t = -m_invTimeStep;
3661 _acceleration = _acceleration * t; 3905 m_acceleration = m_acceleration * t;
3662 } 3906 }
3663 else 3907 else
3664 { 3908 {
3665 _velocity.X = vel.X; 3909 _velocity.X = vel.X;
3666 _velocity.Y = vel.Y; 3910 _velocity.Y = vel.Y;
3667 _velocity.Z = vel.Z; 3911 _velocity.Z = vel.Z;
3668 _acceleration = (_velocity - _acceleration) * m_invTimeStep; 3912 m_acceleration = (_velocity - m_acceleration) * m_invTimeStep;
3669 } 3913 }
3670 3914
3671 if ((Math.Abs(_acceleration.X) < 0.01f) && 3915 if ((Math.Abs(m_acceleration.X) < 0.01f) &&
3672 (Math.Abs(_acceleration.Y) < 0.01f) && 3916 (Math.Abs(m_acceleration.Y) < 0.01f) &&
3673 (Math.Abs(_acceleration.Z) < 0.01f)) 3917 (Math.Abs(m_acceleration.Z) < 0.01f))
3674 { 3918 {
3675 _acceleration = Vector3.Zero; 3919 m_acceleration = Vector3.Zero;
3676 } 3920 }
3677 3921
3678 vel = d.BodyGetAngularVel(Body); 3922 vel = d.BodyGetAngularVel(Body);
3679 if ((Math.Abs(vel.X) < 0.0001) && 3923 if ((Math.Abs(vel.X) < 0.0001) &&
3680 (Math.Abs(vel.Y) < 0.0001) && 3924 (Math.Abs(vel.Y) < 0.0001) &&
3681 (Math.Abs(vel.Z) < 0.0001) 3925 (Math.Abs(vel.Z) < 0.0001)
3682 ) 3926 )
3683 { 3927 {
3684 m_rotationalVelocity = Vector3.Zero; 3928 m_rotationalVelocity = Vector3.Zero;
3685 } 3929 }
@@ -3939,6 +4183,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3939 changePIDHoverActive((bool)arg); 4183 changePIDHoverActive((bool)arg);
3940 break; 4184 break;
3941 4185
4186 case changes.SetInertia:
4187 changeInertia((PhysicsInertiaData) arg);
4188 break;
4189
3942 case changes.Null: 4190 case changes.Null:
3943 donullchange(); 4191 donullchange();
3944 break; 4192 break;
@@ -3955,7 +4203,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3955 _parent_scene.AddChange((PhysicsActor) this, what, arg); 4203 _parent_scene.AddChange((PhysicsActor) this, what, arg);
3956 } 4204 }
3957 4205
3958
3959 private struct strVehicleBoolParam 4206 private struct strVehicleBoolParam
3960 { 4207 {
3961 public int param; 4208 public int param;