diff options
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; | |||
38 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; | 38 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; |
39 | using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | 39 | using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; |
40 | 40 | ||
41 | |||
41 | namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | 42 | namespace 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 | } |