diff options
Diffstat (limited to 'OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs')
-rw-r--r-- | OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs | 365 |
1 files changed, 332 insertions, 33 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs index 71aec4c..c4dc793 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs | |||
@@ -70,6 +70,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
70 | private bool m_fakeisphantom; | 70 | private bool m_fakeisphantom; |
71 | 71 | ||
72 | protected bool m_building; | 72 | protected bool m_building; |
73 | protected bool m_forcePosOrRotation; | ||
74 | |||
73 | private Quaternion m_lastorientation = new Quaternion(); | 75 | private Quaternion m_lastorientation = new Quaternion(); |
74 | private Quaternion _orientation; | 76 | private Quaternion _orientation; |
75 | 77 | ||
@@ -128,9 +130,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
128 | 130 | ||
129 | public bool m_disabled; | 131 | public bool m_disabled; |
130 | 132 | ||
131 | |||
132 | public uint m_localID; | 133 | public uint m_localID; |
133 | 134 | ||
135 | private IMesh m_mesh; | ||
136 | private object m_meshlock = new object(); | ||
134 | private PrimitiveBaseShape _pbs; | 137 | private PrimitiveBaseShape _pbs; |
135 | public OdeScene _parent_scene; | 138 | public OdeScene _parent_scene; |
136 | 139 | ||
@@ -482,6 +485,24 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
482 | { | 485 | { |
483 | set | 486 | set |
484 | { | 487 | { |
488 | /* | ||
489 | IMesh mesh = null; | ||
490 | if (_parent_scene.needsMeshing(value)) | ||
491 | { | ||
492 | bool convex; | ||
493 | if (m_shapetype == 0) | ||
494 | convex = false; | ||
495 | else | ||
496 | convex = true; | ||
497 | mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true, convex); | ||
498 | } | ||
499 | |||
500 | if (mesh != null) | ||
501 | { | ||
502 | lock (m_meshlock) | ||
503 | m_mesh = mesh; | ||
504 | } | ||
505 | */ | ||
485 | AddChange(changes.Shape, value); | 506 | AddChange(changes.Shape, value); |
486 | } | 507 | } |
487 | } | 508 | } |
@@ -497,7 +518,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
497 | m_shapetype = value; | 518 | m_shapetype = value; |
498 | AddChange(changes.Shape, null); | 519 | AddChange(changes.Shape, null); |
499 | } | 520 | } |
500 | } | 521 | } |
522 | |||
501 | 523 | ||
502 | public override Vector3 Velocity | 524 | public override Vector3 Velocity |
503 | { | 525 | { |
@@ -947,6 +969,19 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
947 | 969 | ||
948 | CalcPrimBodyData(); | 970 | CalcPrimBodyData(); |
949 | 971 | ||
972 | m_mesh = null; | ||
973 | if (_parent_scene.needsMeshing(pbs)) | ||
974 | { | ||
975 | bool convex; | ||
976 | if (m_shapetype == 0) | ||
977 | convex = false; | ||
978 | else | ||
979 | convex = true; | ||
980 | |||
981 | m_mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true, convex); | ||
982 | } | ||
983 | |||
984 | |||
950 | m_building = true; // control must set this to false when done | 985 | m_building = true; // control must set this to false when done |
951 | 986 | ||
952 | AddChange(changes.Add, null); | 987 | AddChange(changes.Add, null); |
@@ -1049,6 +1084,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1049 | 1084 | ||
1050 | private bool setMesh(OdeScene parent_scene) | 1085 | private bool setMesh(OdeScene parent_scene) |
1051 | { | 1086 | { |
1087 | IntPtr vertices, indices; | ||
1088 | int vertexCount, indexCount; | ||
1089 | int vertexStride, triStride; | ||
1090 | |||
1052 | if (Body != IntPtr.Zero) | 1091 | if (Body != IntPtr.Zero) |
1053 | { | 1092 | { |
1054 | if (childPrim) | 1093 | if (childPrim) |
@@ -1065,38 +1104,50 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1065 | } | 1104 | } |
1066 | } | 1105 | } |
1067 | 1106 | ||
1068 | bool convex; | 1107 | IMesh mesh = null; |
1069 | if (m_shapetype == 0) | 1108 | |
1070 | convex = false; | ||
1071 | else | ||
1072 | convex = true; | ||
1073 | 1109 | ||
1074 | IMesh mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true,convex); | 1110 | lock (m_meshlock) |
1075 | if (mesh == null) | ||
1076 | { | 1111 | { |
1077 | m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z); | 1112 | if (m_mesh == null) |
1078 | return false; | 1113 | { |
1079 | } | 1114 | bool convex; |
1115 | if (m_shapetype == 0) | ||
1116 | convex = false; | ||
1117 | else | ||
1118 | convex = true; | ||
1080 | 1119 | ||
1081 | IntPtr vertices, indices; | 1120 | mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true, convex); |
1082 | int vertexCount, indexCount; | 1121 | } |
1083 | int vertexStride, triStride; | 1122 | else |
1123 | { | ||
1124 | mesh = m_mesh; | ||
1125 | } | ||
1084 | 1126 | ||
1085 | mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap | 1127 | if (mesh == null) |
1086 | mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage | 1128 | { |
1129 | m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z); | ||
1130 | return false; | ||
1131 | } | ||
1087 | 1132 | ||
1088 | if (vertexCount == 0 || indexCount == 0) | ||
1089 | { | ||
1090 | m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. mesh UUID {4}", | ||
1091 | Name, _position.X, _position.Y, _position.Z, _pbs.SculptTexture.ToString()); | ||
1092 | mesh.releaseSourceMeshData(); | ||
1093 | return false; | ||
1094 | } | ||
1095 | 1133 | ||
1096 | primOOBoffset = mesh.GetCentroid(); | 1134 | mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap |
1097 | hasOOBoffsetFromMesh = true; | 1135 | mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage |
1098 | 1136 | ||
1099 | mesh.releaseSourceMeshData(); | 1137 | if (vertexCount == 0 || indexCount == 0) |
1138 | { | ||
1139 | m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. mesh UUID {4}", | ||
1140 | Name, _position.X, _position.Y, _position.Z, _pbs.SculptTexture.ToString()); | ||
1141 | mesh.releaseSourceMeshData(); | ||
1142 | return false; | ||
1143 | } | ||
1144 | |||
1145 | primOOBoffset = mesh.GetCentroid(); | ||
1146 | hasOOBoffsetFromMesh = true; | ||
1147 | |||
1148 | mesh.releaseSourceMeshData(); | ||
1149 | m_mesh = null; | ||
1150 | } | ||
1100 | 1151 | ||
1101 | IntPtr geo = IntPtr.Zero; | 1152 | IntPtr geo = IntPtr.Zero; |
1102 | 1153 | ||
@@ -1429,7 +1480,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1429 | d.RfromQ(out mymat, ref myrot); | 1480 | d.RfromQ(out mymat, ref myrot); |
1430 | d.MassRotate(ref objdmass, ref mymat); | 1481 | d.MassRotate(ref objdmass, ref mymat); |
1431 | 1482 | ||
1432 | // set the body rotation and position | 1483 | // set the body rotation |
1433 | d.BodySetRotation(Body, ref mymat); | 1484 | d.BodySetRotation(Body, ref mymat); |
1434 | 1485 | ||
1435 | // recompute full object inertia if needed | 1486 | // recompute full object inertia if needed |
@@ -1725,6 +1776,215 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1725 | m_collisionscore = 0; | 1776 | m_collisionscore = 0; |
1726 | } | 1777 | } |
1727 | 1778 | ||
1779 | private void FixInertia(Vector3 NewPos,Quaternion newrot) | ||
1780 | { | ||
1781 | d.Matrix3 mat = new d.Matrix3(); | ||
1782 | d.Quaternion quat = new d.Quaternion(); | ||
1783 | |||
1784 | d.Mass tmpdmass = new d.Mass { }; | ||
1785 | d.Mass objdmass = new d.Mass { }; | ||
1786 | |||
1787 | d.BodyGetMass(Body, out tmpdmass); | ||
1788 | objdmass = tmpdmass; | ||
1789 | |||
1790 | d.Vector3 dobjpos; | ||
1791 | d.Vector3 thispos; | ||
1792 | |||
1793 | // get current object position and rotation | ||
1794 | dobjpos = d.BodyGetPosition(Body); | ||
1795 | |||
1796 | // get prim own inertia in its local frame | ||
1797 | tmpdmass = primdMass; | ||
1798 | |||
1799 | // transform to object frame | ||
1800 | mat = d.GeomGetOffsetRotation(prim_geom); | ||
1801 | d.MassRotate(ref tmpdmass, ref mat); | ||
1802 | |||
1803 | thispos = d.GeomGetOffsetPosition(prim_geom); | ||
1804 | d.MassTranslate(ref tmpdmass, | ||
1805 | thispos.X, | ||
1806 | thispos.Y, | ||
1807 | thispos.Z); | ||
1808 | |||
1809 | // subtract current prim inertia from object | ||
1810 | DMassSubPartFromObj(ref tmpdmass, ref objdmass); | ||
1811 | |||
1812 | // back prim own inertia | ||
1813 | tmpdmass = primdMass; | ||
1814 | |||
1815 | // update to new position and orientation | ||
1816 | _position = NewPos; | ||
1817 | d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z); | ||
1818 | _orientation = newrot; | ||
1819 | quat.X = newrot.X; | ||
1820 | quat.Y = newrot.Y; | ||
1821 | quat.Z = newrot.Z; | ||
1822 | quat.W = newrot.W; | ||
1823 | d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat); | ||
1824 | |||
1825 | mat = d.GeomGetOffsetRotation(prim_geom); | ||
1826 | d.MassRotate(ref tmpdmass, ref mat); | ||
1827 | |||
1828 | thispos = d.GeomGetOffsetPosition(prim_geom); | ||
1829 | d.MassTranslate(ref tmpdmass, | ||
1830 | thispos.X, | ||
1831 | thispos.Y, | ||
1832 | thispos.Z); | ||
1833 | |||
1834 | d.MassAdd(ref objdmass, ref tmpdmass); | ||
1835 | |||
1836 | // fix all positions | ||
1837 | IntPtr g = d.BodyGetFirstGeom(Body); | ||
1838 | while (g != IntPtr.Zero) | ||
1839 | { | ||
1840 | thispos = d.GeomGetOffsetPosition(g); | ||
1841 | thispos.X -= objdmass.c.X; | ||
1842 | thispos.Y -= objdmass.c.Y; | ||
1843 | thispos.Z -= objdmass.c.Z; | ||
1844 | d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z); | ||
1845 | g = d.dBodyGetNextGeom(g); | ||
1846 | } | ||
1847 | d.BodyVectorToWorld(Body,objdmass.c.X, objdmass.c.Y, objdmass.c.Z,out thispos); | ||
1848 | |||
1849 | d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z); | ||
1850 | d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body | ||
1851 | d.BodySetMass(Body, ref objdmass); | ||
1852 | _mass = objdmass.mass; | ||
1853 | } | ||
1854 | |||
1855 | |||
1856 | |||
1857 | private void FixInertia(Vector3 NewPos) | ||
1858 | { | ||
1859 | d.Matrix3 primmat = new d.Matrix3(); | ||
1860 | d.Mass tmpdmass = new d.Mass { }; | ||
1861 | d.Mass objdmass = new d.Mass { }; | ||
1862 | d.Mass primmass = new d.Mass { }; | ||
1863 | |||
1864 | d.Vector3 dobjpos; | ||
1865 | d.Vector3 thispos; | ||
1866 | |||
1867 | d.BodyGetMass(Body, out objdmass); | ||
1868 | |||
1869 | // get prim own inertia in its local frame | ||
1870 | primmass = primdMass; | ||
1871 | // transform to object frame | ||
1872 | primmat = d.GeomGetOffsetRotation(prim_geom); | ||
1873 | d.MassRotate(ref primmass, ref primmat); | ||
1874 | |||
1875 | tmpdmass = primmass; | ||
1876 | |||
1877 | thispos = d.GeomGetOffsetPosition(prim_geom); | ||
1878 | d.MassTranslate(ref tmpdmass, | ||
1879 | thispos.X, | ||
1880 | thispos.Y, | ||
1881 | thispos.Z); | ||
1882 | |||
1883 | // subtract current prim inertia from object | ||
1884 | DMassSubPartFromObj(ref tmpdmass, ref objdmass); | ||
1885 | |||
1886 | // update to new position | ||
1887 | _position = NewPos; | ||
1888 | d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z); | ||
1889 | |||
1890 | thispos = d.GeomGetOffsetPosition(prim_geom); | ||
1891 | d.MassTranslate(ref primmass, | ||
1892 | thispos.X, | ||
1893 | thispos.Y, | ||
1894 | thispos.Z); | ||
1895 | |||
1896 | d.MassAdd(ref objdmass, ref primmass); | ||
1897 | |||
1898 | // fix all positions | ||
1899 | IntPtr g = d.BodyGetFirstGeom(Body); | ||
1900 | while (g != IntPtr.Zero) | ||
1901 | { | ||
1902 | thispos = d.GeomGetOffsetPosition(g); | ||
1903 | thispos.X -= objdmass.c.X; | ||
1904 | thispos.Y -= objdmass.c.Y; | ||
1905 | thispos.Z -= objdmass.c.Z; | ||
1906 | d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z); | ||
1907 | g = d.dBodyGetNextGeom(g); | ||
1908 | } | ||
1909 | |||
1910 | d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos); | ||
1911 | |||
1912 | // get current object position and rotation | ||
1913 | dobjpos = d.BodyGetPosition(Body); | ||
1914 | |||
1915 | d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z); | ||
1916 | d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body | ||
1917 | d.BodySetMass(Body, ref objdmass); | ||
1918 | _mass = objdmass.mass; | ||
1919 | } | ||
1920 | |||
1921 | private void FixInertia(Quaternion newrot) | ||
1922 | { | ||
1923 | d.Matrix3 mat = new d.Matrix3(); | ||
1924 | d.Quaternion quat = new d.Quaternion(); | ||
1925 | |||
1926 | d.Mass tmpdmass = new d.Mass { }; | ||
1927 | d.Mass objdmass = new d.Mass { }; | ||
1928 | d.Vector3 dobjpos; | ||
1929 | d.Vector3 thispos; | ||
1930 | |||
1931 | d.BodyGetMass(Body, out objdmass); | ||
1932 | |||
1933 | // get prim own inertia in its local frame | ||
1934 | tmpdmass = primdMass; | ||
1935 | mat = d.GeomGetOffsetRotation(prim_geom); | ||
1936 | d.MassRotate(ref tmpdmass, ref mat); | ||
1937 | // transform to object frame | ||
1938 | thispos = d.GeomGetOffsetPosition(prim_geom); | ||
1939 | d.MassTranslate(ref tmpdmass, | ||
1940 | thispos.X, | ||
1941 | thispos.Y, | ||
1942 | thispos.Z); | ||
1943 | |||
1944 | // subtract current prim inertia from object | ||
1945 | DMassSubPartFromObj(ref tmpdmass, ref objdmass); | ||
1946 | |||
1947 | // update to new orientation | ||
1948 | _orientation = newrot; | ||
1949 | quat.X = newrot.X; | ||
1950 | quat.Y = newrot.Y; | ||
1951 | quat.Z = newrot.Z; | ||
1952 | quat.W = newrot.W; | ||
1953 | d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat); | ||
1954 | |||
1955 | tmpdmass = primdMass; | ||
1956 | mat = d.GeomGetOffsetRotation(prim_geom); | ||
1957 | d.MassRotate(ref tmpdmass, ref mat); | ||
1958 | d.MassTranslate(ref tmpdmass, | ||
1959 | thispos.X, | ||
1960 | thispos.Y, | ||
1961 | thispos.Z); | ||
1962 | |||
1963 | d.MassAdd(ref objdmass, ref tmpdmass); | ||
1964 | |||
1965 | // fix all positions | ||
1966 | IntPtr g = d.BodyGetFirstGeom(Body); | ||
1967 | while (g != IntPtr.Zero) | ||
1968 | { | ||
1969 | thispos = d.GeomGetOffsetPosition(g); | ||
1970 | thispos.X -= objdmass.c.X; | ||
1971 | thispos.Y -= objdmass.c.Y; | ||
1972 | thispos.Z -= objdmass.c.Z; | ||
1973 | d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z); | ||
1974 | g = d.dBodyGetNextGeom(g); | ||
1975 | } | ||
1976 | |||
1977 | d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos); | ||
1978 | // get current object position and rotation | ||
1979 | dobjpos = d.BodyGetPosition(Body); | ||
1980 | |||
1981 | d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z); | ||
1982 | d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body | ||
1983 | d.BodySetMass(Body, ref objdmass); | ||
1984 | _mass = objdmass.mass; | ||
1985 | } | ||
1986 | |||
1987 | |||
1728 | #region Mass Calculation | 1988 | #region Mass Calculation |
1729 | 1989 | ||
1730 | private float CalculatePrimVolume() | 1990 | private float CalculatePrimVolume() |
@@ -2126,17 +2386,18 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2126 | { | 2386 | { |
2127 | if (prim_geom != IntPtr.Zero) | 2387 | if (prim_geom != IntPtr.Zero) |
2128 | { | 2388 | { |
2129 | d.Vector3 lpos; | ||
2130 | d.GeomCopyPosition(prim_geom, out lpos); | ||
2131 | _position.X = lpos.X; | ||
2132 | _position.Y = lpos.Y; | ||
2133 | _position.Z = lpos.Z; | ||
2134 | d.Quaternion qtmp = new d.Quaternion { }; | 2389 | d.Quaternion qtmp = new d.Quaternion { }; |
2135 | d.GeomCopyQuaternion(prim_geom, out qtmp); | 2390 | d.GeomCopyQuaternion(prim_geom, out qtmp); |
2136 | _orientation.W = qtmp.W; | 2391 | _orientation.W = qtmp.W; |
2137 | _orientation.X = qtmp.X; | 2392 | _orientation.X = qtmp.X; |
2138 | _orientation.Y = qtmp.Y; | 2393 | _orientation.Y = qtmp.Y; |
2139 | _orientation.Z = qtmp.Z; | 2394 | _orientation.Z = qtmp.Z; |
2395 | |||
2396 | d.Vector3 lpos; | ||
2397 | d.GeomCopyPosition(prim_geom, out lpos); | ||
2398 | _position.X = lpos.X; | ||
2399 | _position.Y = lpos.Y; | ||
2400 | _position.Z = lpos.Z; | ||
2140 | } | 2401 | } |
2141 | } | 2402 | } |
2142 | 2403 | ||
@@ -2593,6 +2854,13 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2593 | { | 2854 | { |
2594 | _position = newPos; | 2855 | _position = newPos; |
2595 | } | 2856 | } |
2857 | |||
2858 | else if (m_forcePosOrRotation && _position != newPos && Body != IntPtr.Zero) | ||
2859 | { | ||
2860 | FixInertia(newPos); | ||
2861 | if (!d.BodyIsEnabled(Body)) | ||
2862 | d.BodyEnable(Body); | ||
2863 | } | ||
2596 | } | 2864 | } |
2597 | else | 2865 | else |
2598 | { | 2866 | { |
@@ -2637,6 +2905,14 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2637 | { | 2905 | { |
2638 | _orientation = newOri; | 2906 | _orientation = newOri; |
2639 | } | 2907 | } |
2908 | /* | ||
2909 | else if (m_forcePosOrRotation && _orientation != newOri && Body != IntPtr.Zero) | ||
2910 | { | ||
2911 | FixInertia(_position, newOri); | ||
2912 | if (!d.BodyIsEnabled(Body)) | ||
2913 | d.BodyEnable(Body); | ||
2914 | } | ||
2915 | */ | ||
2640 | } | 2916 | } |
2641 | else | 2917 | else |
2642 | { | 2918 | { |
@@ -3512,6 +3788,29 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
3512 | dst.I.M22 = src.I.M22; | 3788 | dst.I.M22 = src.I.M22; |
3513 | } | 3789 | } |
3514 | 3790 | ||
3791 | internal static void DMassSubPartFromObj(ref d.Mass part, ref d.Mass theobj) | ||
3792 | { | ||
3793 | // assumes object center of mass is zero | ||
3794 | float smass = part.mass; | ||
3795 | theobj.mass -= smass; | ||
3796 | |||
3797 | smass *= 1.0f / (theobj.mass); ; | ||
3798 | |||
3799 | theobj.c.X -= part.c.X * smass; | ||
3800 | theobj.c.Y -= part.c.Y * smass; | ||
3801 | theobj.c.Z -= part.c.Z * smass; | ||
3802 | |||
3803 | theobj.I.M00 -= part.I.M00; | ||
3804 | theobj.I.M01 -= part.I.M01; | ||
3805 | theobj.I.M02 -= part.I.M02; | ||
3806 | theobj.I.M10 -= part.I.M10; | ||
3807 | theobj.I.M11 -= part.I.M11; | ||
3808 | theobj.I.M12 -= part.I.M12; | ||
3809 | theobj.I.M20 -= part.I.M20; | ||
3810 | theobj.I.M21 -= part.I.M21; | ||
3811 | theobj.I.M22 -= part.I.M22; | ||
3812 | } | ||
3813 | |||
3515 | private static void DMassDup(ref d.Mass src, out d.Mass dst) | 3814 | private static void DMassDup(ref d.Mass src, out d.Mass dst) |
3516 | { | 3815 | { |
3517 | dst = new d.Mass { }; | 3816 | dst = new d.Mass { }; |