aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
diff options
context:
space:
mode:
authorUbitUmarov2017-03-31 20:55:48 +0100
committerUbitUmarov2017-03-31 20:55:48 +0100
commit6a35a965ff7085b5962745437a10d798c0fb611d (patch)
tree029843113cec9fe04e733049c6232d2d36c2a106 /OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
parentAdapt to a variable name that has changed in core (diff)
downloadopensim-SC-6a35a965ff7085b5962745437a10d798c0fb611d.zip
opensim-SC-6a35a965ff7085b5962745437a10d798c0fb611d.tar.gz
opensim-SC-6a35a965ff7085b5962745437a10d798c0fb611d.tar.bz2
opensim-SC-6a35a965ff7085b5962745437a10d798c0fb611d.tar.xz
add OSSL functions to override linksets total mass, center of mass and inertia. replacing the crude automatic estimation based on prims known to physics and density. Changed parameters are still not saved, and are lost on region crossings. only suported by UbODE. EXPERIMENTAL feature, only test it for now.. don't try to use in products.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs253
1 files changed, 207 insertions, 46 deletions
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
index 45ef273..d560b41 100644
--- a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
@@ -182,14 +182,16 @@ 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;
@@ -465,10 +467,110 @@ namespace OpenSim.Region.PhysicsModule.ubOde
465 } 467 }
466 } 468 }
467 469
470 public override PhysicsInertiaData GetInertiaData()
471 {
472 PhysicsInertiaData inertia;
473 if(childPrim)
474 {
475 if(_parent != null)
476 return _parent.GetInertiaData();
477 else
478 {
479 inertia = new PhysicsInertiaData();
480 inertia.TotalMass = -1;
481 return inertia;
482 }
483 }
484
485 inertia = new PhysicsInertiaData();
486
487 // double buffering
488 if(m_fakeInertiaOverride != null)
489 {
490 d.Mass objdmass = new d.Mass();
491 objdmass.I.M00 = m_fakeInertiaOverride.Inertia.X;
492 objdmass.I.M11 = m_fakeInertiaOverride.Inertia.Y;
493 objdmass.I.M22 = m_fakeInertiaOverride.Inertia.Z;
494
495 objdmass.mass = m_fakeInertiaOverride.TotalMass;
496
497 if(Math.Abs(m_fakeInertiaOverride.InertiaRotation.W) < 0.999)
498 {
499 d.Matrix3 inertiarotmat = new d.Matrix3();
500 d.Quaternion inertiarot = new d.Quaternion();
501
502 inertiarot.X = m_fakeInertiaOverride.InertiaRotation.X;
503 inertiarot.Y = m_fakeInertiaOverride.InertiaRotation.Y;
504 inertiarot.Z = m_fakeInertiaOverride.InertiaRotation.Z;
505 inertiarot.W = m_fakeInertiaOverride.InertiaRotation.W;
506 d.RfromQ(out inertiarotmat, ref inertiarot);
507 d.MassRotate(ref objdmass, ref inertiarotmat);
508 }
509
510 inertia.TotalMass = m_fakeInertiaOverride.TotalMass;
511 inertia.CenterOfMass = m_fakeInertiaOverride.CenterOfMass;
512 inertia.Inertia.X = objdmass.I.M00;
513 inertia.Inertia.Y = objdmass.I.M11;
514 inertia.Inertia.Z = objdmass.I.M22;
515 inertia.InertiaRotation.X = objdmass.I.M01;
516 inertia.InertiaRotation.Y = objdmass.I.M02;
517 inertia.InertiaRotation.Z = objdmass.I.M12;
518 return inertia;
519 }
520
521 inertia.TotalMass = m_mass;
522
523 if(Body == IntPtr.Zero || prim_geom == IntPtr.Zero)
524 {
525 inertia.CenterOfMass = Vector3.Zero;
526 inertia.Inertia = Vector3.Zero;
527 inertia.InertiaRotation = Vector4.Zero;
528 return inertia;
529 }
530
531 d.Vector3 dtmp;
532 d.Mass m = new d.Mass();
533 lock(_parent_scene.OdeLock)
534 {
535 d.AllocateODEDataForThread(0);
536 dtmp = d.GeomGetOffsetPosition(prim_geom);
537 d.BodyGetMass(Body, out m);
538 }
539
540 Vector3 cm = new Vector3(-dtmp.X, -dtmp.Y, -dtmp.Z);
541 inertia.CenterOfMass = cm;
542 inertia.Inertia = new Vector3(m.I.M00, m.I.M11, m.I.M22);
543 inertia.InertiaRotation = new Vector4(m.I.M01, m.I.M02 , m.I.M12, 0);
544
545 return inertia;
546 }
547
548 public override void SetInertiaData(PhysicsInertiaData inertia)
549 {
550 if(childPrim)
551 {
552 if(_parent != null)
553 _parent.SetInertiaData(inertia);
554 return;
555 }
556
557 if(inertia.TotalMass > 0)
558 m_fakeInertiaOverride = new PhysicsInertiaData(inertia);
559 else
560 m_fakeInertiaOverride = null;
561
562 if (inertia.TotalMass > _parent_scene.maximumMassObject)
563 inertia.TotalMass = _parent_scene.maximumMassObject;
564 AddChange(changes.SetInertia,(object)m_fakeInertiaOverride);
565 }
566
468 public override Vector3 CenterOfMass 567 public override Vector3 CenterOfMass
469 { 568 {
470 get 569 get
471 { 570 {
571 if(!childPrim && m_fakeInertiaOverride != null)
572 return m_fakeInertiaOverride.CenterOfMass;
573
472 lock (_parent_scene.OdeLock) 574 lock (_parent_scene.OdeLock)
473 { 575 {
474 d.AllocateODEDataForThread(0); 576 d.AllocateODEDataForThread(0);
@@ -922,8 +1024,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde
922 { 1024 {
923 float old = m_density; 1025 float old = m_density;
924 m_density = value / 100f; 1026 m_density = value / 100f;
925 if(m_density != old) 1027 // if(m_density != old)
926 UpdatePrimBodyData(); 1028 // UpdatePrimBodyData();
927 } 1029 }
928 } 1030 }
929 public override float GravModifier 1031 public override float GravModifier
@@ -1716,26 +1818,29 @@ namespace OpenSim.Region.PhysicsModule.ubOde
1716 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body"); 1818 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body");
1717 } 1819 }
1718 1820
1719 d.Matrix3 mymat = new d.Matrix3(); 1821 bool noInertiaOverride = (m_InertiaOverride == null);
1720 d.Quaternion myrot = new d.Quaternion();
1721 d.Mass objdmass = new d.Mass { };
1722 1822
1723 Body = d.BodyCreate(_parent_scene.world); 1823 Body = d.BodyCreate(_parent_scene.world);
1724 1824
1725 objdmass = primdMass; 1825 d.Matrix3 mymat = new d.Matrix3();
1826 d.Quaternion myrot = new d.Quaternion();
1827 d.Mass objdmass = new d.Mass { };
1726 1828
1727 // rotate inertia
1728 myrot.X = _orientation.X; 1829 myrot.X = _orientation.X;
1729 myrot.Y = _orientation.Y; 1830 myrot.Y = _orientation.Y;
1730 myrot.Z = _orientation.Z; 1831 myrot.Z = _orientation.Z;
1731 myrot.W = _orientation.W; 1832 myrot.W = _orientation.W;
1732
1733 d.RfromQ(out mymat, ref myrot); 1833 d.RfromQ(out mymat, ref myrot);
1734 d.MassRotate(ref objdmass, ref mymat);
1735 1834
1736 // set the body rotation 1835 // set the body rotation
1737 d.BodySetRotation(Body, ref mymat); 1836 d.BodySetRotation(Body, ref mymat);
1738 1837
1838 if(noInertiaOverride)
1839 {
1840 objdmass = primdMass;
1841 d.MassRotate(ref objdmass, ref mymat);
1842 }
1843
1739 // recompute full object inertia if needed 1844 // recompute full object inertia if needed
1740 if (childrenPrim.Count > 0) 1845 if (childrenPrim.Count > 0)
1741 { 1846 {
@@ -1758,27 +1863,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde
1758 continue; 1863 continue;
1759 } 1864 }
1760 1865
1761 tmpdmass = prm.primdMass;
1762
1763 // apply prim current rotation to inertia
1764 quat.X = prm._orientation.X; 1866 quat.X = prm._orientation.X;
1765 quat.Y = prm._orientation.Y; 1867 quat.Y = prm._orientation.Y;
1766 quat.Z = prm._orientation.Z; 1868 quat.Z = prm._orientation.Z;
1767 quat.W = prm._orientation.W; 1869 quat.W = prm._orientation.W;
1768 d.RfromQ(out mat, ref quat); 1870 d.RfromQ(out mat, ref quat);
1769 d.MassRotate(ref tmpdmass, ref mat); 1871
1770
1771 Vector3 ppos = prm._position;
1772 ppos.X -= rcm.X;
1773 ppos.Y -= rcm.Y;
1774 ppos.Z -= rcm.Z;
1775 // refer inertia to root prim center of mass position
1776 d.MassTranslate(ref tmpdmass,
1777 ppos.X,
1778 ppos.Y,
1779 ppos.Z);
1780
1781 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
1782 // fix prim colision cats 1872 // fix prim colision cats
1783 1873
1784 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero) 1874 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero)
@@ -1791,6 +1881,24 @@ namespace OpenSim.Region.PhysicsModule.ubOde
1791 d.GeomSetBody(prm.prim_geom, Body); 1881 d.GeomSetBody(prm.prim_geom, Body);
1792 prm.Body = Body; 1882 prm.Body = Body;
1793 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation 1883 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation
1884
1885 if(noInertiaOverride)
1886 {
1887 tmpdmass = prm.primdMass;
1888
1889 d.MassRotate(ref tmpdmass, ref mat);
1890 Vector3 ppos = prm._position;
1891 ppos.X -= rcm.X;
1892 ppos.Y -= rcm.Y;
1893 ppos.Z -= rcm.Z;
1894 // refer inertia to root prim center of mass position
1895 d.MassTranslate(ref tmpdmass,
1896 ppos.X,
1897 ppos.Y,
1898 ppos.Z);
1899
1900 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
1901 }
1794 } 1902 }
1795 } 1903 }
1796 } 1904 }
@@ -1799,19 +1907,60 @@ namespace OpenSim.Region.PhysicsModule.ubOde
1799 // associate root geom with body 1907 // associate root geom with body
1800 d.GeomSetBody(prim_geom, Body); 1908 d.GeomSetBody(prim_geom, Body);
1801 1909
1802 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z); 1910 if(noInertiaOverride)
1911 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
1912 else
1913 {
1914 Vector3 ncm = m_InertiaOverride.CenterOfMass * _orientation;
1915 d.BodySetPosition(Body,
1916 _position.X + ncm.X,
1917 _position.Y + ncm.Y,
1918 _position.Z + ncm.Z);
1919 }
1920
1803 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z); 1921 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z);
1804 1922
1805 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body 1923 if(noInertiaOverride)
1806 myrot.X = -myrot.X; 1924 {
1807 myrot.Y = -myrot.Y; 1925 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
1808 myrot.Z = -myrot.Z; 1926 myrot.X = -myrot.X;
1927 myrot.Y = -myrot.Y;
1928 myrot.Z = -myrot.Z;
1809 1929
1810 d.RfromQ(out mymat, ref myrot); 1930 d.RfromQ(out mymat, ref myrot);
1811 d.MassRotate(ref objdmass, ref mymat); 1931 d.MassRotate(ref objdmass, ref mymat);
1812 1932
1813 d.BodySetMass(Body, ref objdmass); 1933 d.BodySetMass(Body, ref objdmass);
1814 _mass = objdmass.mass; 1934 m_mass = objdmass.mass;
1935 }
1936 else
1937 {
1938 objdmass.c.X = 0;
1939 objdmass.c.Y = 0;
1940 objdmass.c.Z = 0;
1941
1942 objdmass.I.M00 = m_InertiaOverride.Inertia.X;
1943 objdmass.I.M11 = m_InertiaOverride.Inertia.Y;
1944 objdmass.I.M22 = m_InertiaOverride.Inertia.Z;
1945
1946 objdmass.mass = m_InertiaOverride.TotalMass;
1947
1948 if(Math.Abs(m_InertiaOverride.InertiaRotation.W) < 0.999)
1949 {
1950 d.Matrix3 inertiarotmat = new d.Matrix3();
1951 d.Quaternion inertiarot = new d.Quaternion();
1952
1953 inertiarot.X = m_InertiaOverride.InertiaRotation.X;
1954 inertiarot.Y = m_InertiaOverride.InertiaRotation.Y;
1955 inertiarot.Z = m_InertiaOverride.InertiaRotation.Z;
1956 inertiarot.W = m_InertiaOverride.InertiaRotation.W;
1957 d.RfromQ(out inertiarotmat, ref inertiarot);
1958 d.MassRotate(ref objdmass, ref inertiarotmat);
1959 }
1960 d.BodySetMass(Body, ref objdmass);
1961
1962 m_mass = objdmass.mass;
1963 }
1815 1964
1816 // disconnect from world gravity so we can apply buoyancy 1965 // disconnect from world gravity so we can apply buoyancy
1817 d.BodySetGravityMode(Body, false); 1966 d.BodySetGravityMode(Body, false);
@@ -1990,7 +2139,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
1990 SetInStaticSpace(prm); 2139 SetInStaticSpace(prm);
1991 } 2140 }
1992 prm.Body = IntPtr.Zero; 2141 prm.Body = IntPtr.Zero;
1993 prm._mass = prm.primMass; 2142 prm.m_mass = prm.primMass;
1994 prm.m_collisionscore = 0; 2143 prm.m_collisionscore = 0;
1995 } 2144 }
1996 } 2145 }
@@ -2004,7 +2153,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
2004 } 2153 }
2005 Body = IntPtr.Zero; 2154 Body = IntPtr.Zero;
2006 } 2155 }
2007 _mass = primMass; 2156 m_mass = primMass;
2008 m_collisionscore = 0; 2157 m_collisionscore = 0;
2009 } 2158 }
2010 2159
@@ -2081,7 +2230,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
2081 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z); 2230 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2082 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body 2231 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2083 d.BodySetMass(Body, ref objdmass); 2232 d.BodySetMass(Body, ref objdmass);
2084 _mass = objdmass.mass; 2233 m_mass = objdmass.mass;
2085 } 2234 }
2086 2235
2087 private void FixInertia(Vector3 NewPos) 2236 private void FixInertia(Vector3 NewPos)
@@ -2145,7 +2294,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
2145 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z); 2294 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2146 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body 2295 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2147 d.BodySetMass(Body, ref objdmass); 2296 d.BodySetMass(Body, ref objdmass);
2148 _mass = objdmass.mass; 2297 m_mass = objdmass.mass;
2149 } 2298 }
2150 2299
2151 private void FixInertia(Quaternion newrot) 2300 private void FixInertia(Quaternion newrot)
@@ -2211,7 +2360,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
2211 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z); 2360 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2212 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body 2361 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2213 d.BodySetMass(Body, ref objdmass); 2362 d.BodySetMass(Body, ref objdmass);
2214 _mass = objdmass.mass; 2363 m_mass = objdmass.mass;
2215 } 2364 }
2216 2365
2217 2366
@@ -2226,7 +2375,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
2226 if (primMass > _parent_scene.maximumMassObject) 2375 if (primMass > _parent_scene.maximumMassObject)
2227 primMass = _parent_scene.maximumMassObject; 2376 primMass = _parent_scene.maximumMassObject;
2228 2377
2229 _mass = primMass; // just in case 2378 m_mass = primMass; // just in case
2230 2379
2231 d.MassSetBoxTotal(out primdMass, primMass, 2.0f * m_OBB.X, 2.0f * m_OBB.Y, 2.0f * m_OBB.Z); 2380 d.MassSetBoxTotal(out primdMass, primMass, 2.0f * m_OBB.X, 2.0f * m_OBB.Y, 2.0f * m_OBB.Z);
2232 2381
@@ -3306,6 +3455,15 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3306 m_useHoverPID = active; 3455 m_useHoverPID = active;
3307 } 3456 }
3308 3457
3458 private void changeInertia(PhysicsInertiaData inertia)
3459 {
3460 m_InertiaOverride = inertia;
3461
3462 if (Body != IntPtr.Zero)
3463 DestroyBody();
3464 MakeBody();
3465 }
3466
3309 #endregion 3467 #endregion
3310 3468
3311 public void Move() 3469 public void Move()
@@ -3346,7 +3504,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3346 float fy = 0; 3504 float fy = 0;
3347 float fz = 0; 3505 float fz = 0;
3348 3506
3349 float m_mass = _mass; 3507 float mass = m_mass;
3350 3508
3351 if (m_usePID && m_PIDTau > 0) 3509 if (m_usePID && m_PIDTau > 0)
3352 { 3510 {
@@ -3453,9 +3611,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3453 fz = _parent_scene.gravityz * b; 3611 fz = _parent_scene.gravityz * b;
3454 } 3612 }
3455 3613
3456 fx *= m_mass; 3614 fx *= mass;
3457 fy *= m_mass; 3615 fy *= mass;
3458 fz *= m_mass; 3616 fz *= mass;
3459 3617
3460 // constant force 3618 // constant force
3461 fx += m_force.X; 3619 fx += m_force.X;
@@ -3941,6 +4099,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3941 changePIDHoverActive((bool)arg); 4099 changePIDHoverActive((bool)arg);
3942 break; 4100 break;
3943 4101
4102 case changes.SetInertia:
4103 changeInertia((PhysicsInertiaData) arg);
4104 break;
4105
3944 case changes.Null: 4106 case changes.Null:
3945 donullchange(); 4107 donullchange();
3946 break; 4108 break;
@@ -3957,7 +4119,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
3957 _parent_scene.AddChange((PhysicsActor) this, what, arg); 4119 _parent_scene.AddChange((PhysicsActor) this, what, arg);
3958 } 4120 }
3959 4121
3960
3961 private struct strVehicleBoolParam 4122 private struct strVehicleBoolParam
3962 { 4123 {
3963 public int param; 4124 public int param;