aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorUbitUmarov2017-03-31 20:55:48 +0100
committerUbitUmarov2017-03-31 20:55:48 +0100
commit6a35a965ff7085b5962745437a10d798c0fb611d (patch)
tree029843113cec9fe04e733049c6232d2d36c2a106
parentAdapt to a variable name that has changed in core (diff)
downloadopensim-SC_OLD-6a35a965ff7085b5962745437a10d798c0fb611d.zip
opensim-SC_OLD-6a35a965ff7085b5962745437a10d798c0fb611d.tar.gz
opensim-SC_OLD-6a35a965ff7085b5962745437a10d798c0fb611d.tar.bz2
opensim-SC_OLD-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.
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs41
-rw-r--r--OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs36
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs253
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs213
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs26
6 files changed, 531 insertions, 46 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index bf4d60c..77658ef 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -5010,6 +5010,47 @@ namespace OpenSim.Region.Framework.Scenes
5010 return Ptot; 5010 return Ptot;
5011 } 5011 }
5012 5012
5013 public void GetInertiaData(out float TotalMass, out Vector3 CenterOfMass, out Vector3 Inertia, out Vector4 aux )
5014 {
5015 PhysicsActor pa = RootPart.PhysActor;
5016
5017 if(((RootPart.Flags & PrimFlags.Physics) !=0) && pa !=null)
5018 {
5019 PhysicsInertiaData inertia;
5020
5021 inertia = pa.GetInertiaData();
5022
5023 TotalMass = inertia.TotalMass;
5024 CenterOfMass = inertia.CenterOfMass;
5025 Inertia = inertia.Inertia;
5026 aux = inertia.InertiaRotation;
5027
5028 return;
5029 }
5030
5031 TotalMass = GetMass();
5032 CenterOfMass = GetCenterOfMass() - AbsolutePosition;
5033 CenterOfMass *= Quaternion.Conjugate(RootPart.RotationOffset);
5034 Inertia = Vector3.Zero;
5035 aux = Vector4.Zero;
5036 }
5037
5038 public void SetInertiaData(float TotalMass, Vector3 CenterOfMass, Vector3 Inertia, Vector4 aux )
5039 {
5040 PhysicsActor pa = RootPart.PhysActor;
5041
5042 if(pa !=null)
5043 {
5044 PhysicsInertiaData inertia = new PhysicsInertiaData();
5045 inertia.TotalMass = TotalMass;
5046 inertia.CenterOfMass = CenterOfMass;
5047 inertia.Inertia = Inertia;
5048 inertia.InertiaRotation = aux;
5049 pa.SetInertiaData(inertia);
5050 }
5051 }
5052
5053
5013 /// <summary> 5054 /// <summary>
5014 /// Set the user group to which this scene object belongs. 5055 /// Set the user group to which this scene object belongs.
5015 /// </summary> 5056 /// </summary>
diff --git a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
index 33f0337..ad9b28f 100644
--- a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
+++ b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
@@ -55,6 +55,28 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
55 Absolute 55 Absolute
56 } 56 }
57 57
58 public class PhysicsInertiaData
59 {
60 public float TotalMass; // the total mass of a linkset
61 public Vector3 CenterOfMass; // the center of mass position relative to root part position
62 public Vector3 Inertia; // (Ixx, Iyy, Izz) moment of inertia relative to center of mass and principal axis in local coords
63 public Vector4 InertiaRotation; // if principal axis don't match local axis, the principal axis rotation
64 // or the upper triangle of the inertia tensor
65 // Ixy (= Iyx), Ixz (= Izx), Iyz (= Izy))
66
67 public PhysicsInertiaData()
68 {
69 }
70
71 public PhysicsInertiaData(PhysicsInertiaData source)
72 {
73 TotalMass = source.TotalMass;
74 CenterOfMass = source.CenterOfMass;
75 Inertia = source.Inertia;
76 InertiaRotation = source.InertiaRotation;
77 }
78 }
79
58 public struct CameraData 80 public struct CameraData
59 { 81 {
60 public Quaternion CameraRotation; 82 public Quaternion CameraRotation;
@@ -463,6 +485,20 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
463 485
464 public virtual void AddCollisionEvent(uint CollidedWith, ContactPoint contact) { } 486 public virtual void AddCollisionEvent(uint CollidedWith, ContactPoint contact) { }
465 487
488 public virtual PhysicsInertiaData GetInertiaData()
489 {
490 PhysicsInertiaData data = new PhysicsInertiaData();
491 data.TotalMass = this.Mass;
492 data.CenterOfMass = CenterOfMass - Position;
493 data.Inertia = Vector3.Zero;
494 data.InertiaRotation = Vector4.Zero;
495 return data;
496 }
497
498 public virtual void SetInertiaData(PhysicsInertiaData inertia)
499 {
500 }
501
466 // Warning in a parent part it returns itself, not null 502 // Warning in a parent part it returns itself, not null
467 public virtual PhysicsActor ParentActor { get { return this; } } 503 public virtual PhysicsActor ParentActor { get { return this; } }
468 504
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;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 4c3f7ee..6c094ee 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -4404,5 +4404,218 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4404 m_host.ScriptSetVolumeDetect(detect != 0); 4404 m_host.ScriptSetVolumeDetect(detect != 0);
4405 } 4405 }
4406 4406
4407 /// <summary>
4408 /// Get inertial data
4409 /// </summary>
4410 /// <remarks>
4411 /// </remarks>
4412 /// <returns>
4413 /// a LSL list with contents:
4414 /// LSL_Float mass, the total mass of a linkset
4415 /// LSL_Vector CenterOfMass, center mass relative to root prim
4416 /// LSL_Vector Inertia, elements of diagonal of inertia Ixx,Iyy,Izz divided by total mass
4417 /// LSL_Vector aux, elements of upper triagle of inertia Ixy (= Iyx), Ixz (= Izx), Iyz(= Izy) divided by total mass
4418 /// </returns>
4419 public LSL_List osGetInertiaData()
4420 {
4421 LSL_List result = new LSL_List();
4422 float TotalMass;
4423 Vector3 CenterOfMass;
4424 Vector3 Inertia;
4425 Vector4 aux;
4426
4427 SceneObjectGroup sog = m_host.ParentGroup;
4428 if(sog== null || sog.IsDeleted)
4429 return result;
4430
4431 sog.GetInertiaData(out TotalMass, out CenterOfMass, out Inertia, out aux );
4432 if(TotalMass > 0)
4433 {
4434 float t = 1.0f/TotalMass;
4435 Inertia.X *= t;
4436 Inertia.Y *= t;
4437 Inertia.Z *= t;
4438
4439 aux.X *= t;
4440 aux.Y *= t;
4441 aux.Z *= t;
4442 }
4443
4444 result.Add(new LSL_Float(TotalMass));
4445 result.Add(new LSL_Vector(CenterOfMass.X, CenterOfMass.Y, CenterOfMass.Z));
4446 result.Add(new LSL_Vector(Inertia.X, Inertia.Y, Inertia.Z));
4447 result.Add(new LSL_Vector(aux.X, aux.Y, aux.Z));
4448 return result;
4449 }
4450
4451 /// <summary>
4452 /// set inertial data
4453 /// replaces the automatic calculation of mass, center of mass and inertia
4454 ///
4455 /// </summary>
4456 /// <param name="Mass">total mass of linkset</param>
4457 /// <param name="centerOfMass">location of center of mass relative to root prim in local coords</param>
4458 /// <param name="principalInertiaScaled">moment of inertia relative to principal axis and center of mass,Ixx, Iyy, Izz divided by mass</param>
4459 /// <param name="lslrot">rotation of the inertia, relative to local axis</param>
4460 /// <remarks>
4461 /// the inertia argument is is inertia divided by mass, so corresponds only to the geometric distribution of mass and both can be changed independently.
4462 /// </remarks>
4463
4464 public void osSetInertia(LSL_Float mass, LSL_Vector centerOfMass, LSL_Vector principalInertiaScaled, LSL_Rotation lslrot)
4465 {
4466 SceneObjectGroup sog = m_host.ParentGroup;
4467 if(sog== null || sog.IsDeleted)
4468 return;
4469
4470 if(mass < 0 || principalInertiaScaled.x < 0 || principalInertiaScaled.y < 0 || principalInertiaScaled.z < 0)
4471 return;
4472
4473 // need more checks
4474
4475 Vector3 CenterOfMass = new Vector3((float)centerOfMass.x,(float)centerOfMass.y,(float)centerOfMass.z);
4476 Vector3 Inertia;
4477 float m = (float)mass;
4478
4479 Inertia.X = m * (float)principalInertiaScaled.x;
4480 Inertia.Y = m * (float)principalInertiaScaled.y;
4481 Inertia.Z = m * (float)principalInertiaScaled.z;
4482
4483 Vector4 rot = new Vector4((float)lslrot.x, (float)lslrot.y, (float)lslrot.y, (float)lslrot.s);
4484 rot.Normalize();
4485
4486 sog.SetInertiaData(m, CenterOfMass, Inertia, rot );
4487 }
4488
4489 /// <summary>
4490 /// set inertial data as a sphere
4491 /// replaces the automatic calculation of mass, center of mass and inertia
4492 ///
4493 /// </summary>
4494 /// <param name="Mass">total mass of linkset</param>
4495 /// <param name="boxsize">size of the Box</param>
4496 /// <param name="centerOfMass">location of center of mass relative to root prim in local coords</param>
4497 /// <param name="lslrot">rotation of the box, and so inertia, relative to local axis</param>
4498 /// <remarks>
4499 /// </remarks>
4500 public void osSetInertiaAsBox(LSL_Float mass, LSL_Vector boxSize, LSL_Vector centerOfMass, LSL_Rotation lslrot)
4501 {
4502 SceneObjectGroup sog = m_host.ParentGroup;
4503 if(sog== null || sog.IsDeleted)
4504 return;
4505
4506 if(mass < 0)
4507 return;
4508
4509 // need more checks
4510
4511 Vector3 CenterOfMass = new Vector3((float)centerOfMass.x,(float)centerOfMass.y,(float)centerOfMass.z);
4512 Vector3 Inertia;
4513 float lx = (float)boxSize.x;
4514 float ly = (float)boxSize.y;
4515 float lz = (float)boxSize.z;
4516 float m = (float)mass;
4517 float t = m / 12.0f;
4518
4519 Inertia.X = t * (ly*ly + lz*lz);
4520 Inertia.Y = t * (lx*lx + lz*lz);
4521 Inertia.Z = t * (lx*lx + ly*ly);
4522
4523 Vector4 rot = new Vector4((float)lslrot.x, (float)lslrot.y, (float)lslrot.z, (float)lslrot.s);
4524 rot.Normalize();
4525
4526 sog.SetInertiaData(m, CenterOfMass, Inertia, rot );
4527 }
4528
4529 /// <summary>
4530 /// set inertial data as a sphere
4531 /// replaces the automatic calculation of mass, center of mass and inertia
4532 ///
4533 /// </summary>
4534 /// <param name="Mass">total mass of linkset</param>
4535 /// <param name="radius">radius of the sphere</param>
4536 /// <param name="centerOfMass">location of center of mass relative to root prim in local coords</param>
4537 /// <remarks>
4538 /// </remarks>
4539 public void osSetInertiaAsSphere(LSL_Float mass, LSL_Float radius, LSL_Vector centerOfMass)
4540 {
4541 SceneObjectGroup sog = m_host.ParentGroup;
4542 if(sog== null || sog.IsDeleted)
4543 return;
4544
4545 if(mass < 0)
4546 return;
4547
4548 // need more checks
4549
4550 Vector3 CenterOfMass = new Vector3((float)centerOfMass.x,(float)centerOfMass.y,(float)centerOfMass.z);
4551 Vector3 Inertia;
4552 float r = (float)radius;
4553 float m = (float)mass;
4554 float t = 0.4f * m * r * r;
4555
4556 Inertia.X = t;
4557 Inertia.Y = t;
4558 Inertia.Z = t;
4559
4560 sog.SetInertiaData(m, CenterOfMass, Inertia, new Vector4(0f, 0f, 0f,1.0f));
4561 }
4562
4563 /// <summary>
4564 /// set inertial data as a cylinder
4565 /// replaces the automatic calculation of mass, center of mass and inertia
4566 ///
4567 /// </summary>
4568 /// <param name="Mass">total mass of linkset</param>
4569 /// <param name="radius">radius of the cylinder</param>
4570 /// <param name="lenght">lenght of the cylinder</param>
4571 /// <param name="centerOfMass">location of center of mass relative to root prim in local coords</param>
4572 /// <param name="lslrot">rotation of the cylinder, and so inertia, relative to local axis</param>
4573 /// <remarks>
4574 /// cylinder axis aligned with Z axis. For other orientations provide the rotation.
4575 /// </remarks>
4576 public void osSetInertiaAsCylinder(LSL_Float mass, LSL_Float radius, LSL_Float lenght, LSL_Vector centerOfMass, LSL_Rotation lslrot)
4577 {
4578 SceneObjectGroup sog = m_host.ParentGroup;
4579 if(sog== null || sog.IsDeleted)
4580 return;
4581
4582 if(mass < 0)
4583 return;
4584
4585 // need more checks
4586
4587 Vector3 CenterOfMass = new Vector3((float)centerOfMass.x,(float)centerOfMass.y,(float)centerOfMass.z);
4588 Vector3 Inertia;
4589 float m = (float)mass;
4590 float r = (float)radius;
4591 r *= r;
4592 Inertia.Z = 0.5f * m * r;
4593 float t = (float)lenght;
4594 t *= t;
4595 t += 3.0f * r;
4596 t *= 8.333333e-2f * m;
4597
4598 Inertia.X = t;
4599 Inertia.Y = t;
4600
4601 Vector4 rot = new Vector4((float)lslrot.x, (float)lslrot.y, (float)lslrot.z, (float)lslrot.s);
4602 rot.Normalize();
4603
4604 sog.SetInertiaData(m, CenterOfMass, Inertia, rot);
4605 }
4606
4607 /// <summary>
4608 /// removes inertial data manual override
4609 /// default automatic calculation is used again
4610 ///
4611 /// </summary>
4612 public void osClearInertia()
4613 {
4614 SceneObjectGroup sog = m_host.ParentGroup;
4615 if(sog== null || sog.IsDeleted)
4616 return;
4617
4618 sog.SetInertiaData(-1, Vector3.Zero, Vector3.Zero, Vector4.Zero );
4619 }
4407 } 4620 }
4408} 4621}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index bee060a..f76ff7f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -38,6 +38,7 @@ using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
38using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; 38using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
39using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; 39using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
40 40
41
41namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces 42namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
42{ 43{
43 /// <summary> 44 /// <summary>
@@ -486,6 +487,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
486 LSL_String osRequestURL(LSL_List options); 487 LSL_String osRequestURL(LSL_List options);
487 LSL_String osRequestSecureURL(LSL_List options); 488 LSL_String osRequestSecureURL(LSL_List options);
488 void osCollisionSound(string impact_sound, double impact_volume); 489 void osCollisionSound(string impact_sound, double impact_volume);
490
489 void osVolumeDetect(int detect); 491 void osVolumeDetect(int detect);
492
493 LSL_List osGetInertiaData();
494 void osClearInertia();
495 void osSetInertiaAsBox(LSL_Float mass, vector boxSize, vector centerOfMass, rotation rot);
496 void osSetInertiaAsSphere(LSL_Float mass, LSL_Float radius, vector centerOfMass);
497 void osSetInertiaAsCylinder(LSL_Float mass, LSL_Float radius, LSL_Float lenght, vector centerOfMass,rotation lslrot);
490 } 498 }
491} 499}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 6164734..09337e5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -1114,5 +1114,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1114 { 1114 {
1115 m_OSSL_Functions.osVolumeDetect(detect); 1115 m_OSSL_Functions.osVolumeDetect(detect);
1116 } 1116 }
1117
1118 public LSL_List osGetInertiaData()
1119 {
1120 return m_OSSL_Functions.osGetInertiaData();
1121 }
1122
1123 public void osSetInertiaAsBox(LSL_Float mass, vector boxSize, vector centerOfMass, rotation rot)
1124 {
1125 m_OSSL_Functions.osSetInertiaAsBox(mass, boxSize, centerOfMass, rot);
1126 }
1127
1128 public void osSetInertiaAsSphere(LSL_Float mass, LSL_Float radius, vector centerOfMass)
1129 {
1130 m_OSSL_Functions.osSetInertiaAsSphere(mass, radius, centerOfMass);
1131 }
1132
1133 public void osSetInertiaAsCylinder(LSL_Float mass, LSL_Float radius, LSL_Float lenght, vector centerOfMass,rotation lslrot)
1134 {
1135 m_OSSL_Functions.osSetInertiaAsCylinder( mass, radius, lenght, centerOfMass, lslrot);
1136 }
1137
1138 public void osClearInertia()
1139 {
1140 m_OSSL_Functions.osClearInertia();
1141 }
1142
1117 } 1143 }
1118} 1144}