diff options
author | Kitto Flora | 2011-01-04 21:36:09 +0000 |
---|---|---|
committer | Kitto Flora | 2011-01-04 21:36:09 +0000 |
commit | ba7a2277633804eb2d5e449efa0895e9f43a4ece (patch) | |
tree | 950d41b6bed87f6eccf295111b638d3138250993 /OpenSim/Region | |
parent | Merge branch 'master' into careminster-presence-refactor (diff) | |
download | opensim-SC-ba7a2277633804eb2d5e449efa0895e9f43a4ece.zip opensim-SC-ba7a2277633804eb2d5e449efa0895e9f43a4ece.tar.gz opensim-SC-ba7a2277633804eb2d5e449efa0895e9f43a4ece.tar.bz2 opensim-SC-ba7a2277633804eb2d5e449efa0895e9f43a4ece.tar.xz |
Revise Materials properties; Fix Double-Click Autopilot; Allow non-script sit positions >= 0.1M; Add llLookAt(); Comment out spammy bad adjacent sim message.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 | ||||
-rw-r--r-- | OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 216 | ||||
-rw-r--r-- | OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs | 220 | ||||
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 7 |
4 files changed, 217 insertions, 230 deletions
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 557fc42..208c2a6 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -1758,7 +1758,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1758 | return; | 1758 | return; |
1759 | } | 1759 | } |
1760 | m_moveToPositionInProgress = true; | 1760 | m_moveToPositionInProgress = true; |
1761 | m_moveToPositionTarget = new Vector3(locx, locy, locz); | 1761 | m_moveToPositionTarget = new Vector3(locx, locy, locz + (m_appearance.AvatarHeight / 2.0f)); |
1762 | } | 1762 | } |
1763 | catch (Exception ex) | 1763 | catch (Exception ex) |
1764 | { | 1764 | { |
@@ -2008,7 +2008,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2008 | } | 2008 | } |
2009 | else // Not Scripted | 2009 | else // Not Scripted |
2010 | { | 2010 | { |
2011 | if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) ) | 2011 | if ( (Math.Abs(offset.X) > 0.1f) || (Math.Abs(offset.Y) > 0.1f) ) // Changed 0.5M to 0.1M as they want to be able to sit close together |
2012 | { | 2012 | { |
2013 | // large prim & offset, ignore if other Avs sitting | 2013 | // large prim & offset, ignore if other Avs sitting |
2014 | // offset.Z -= 0.05f; | 2014 | // offset.Z -= 0.05f; |
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 16e90ff..8402082 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | |||
@@ -85,6 +85,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
85 | private float m_APIDStrength = 0.5f; | 85 | private float m_APIDStrength = 0.5f; |
86 | private float m_APIDDamping = 0.5f; | 86 | private float m_APIDDamping = 0.5f; |
87 | private bool m_useAPID = false; | 87 | private bool m_useAPID = false; |
88 | private float m_APIDdamper = 1.0f; | ||
88 | 89 | ||
89 | // These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), | 90 | // These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), |
90 | // do not confuse with VEHICLE HOVER | 91 | // do not confuse with VEHICLE HOVER |
@@ -735,12 +736,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
735 | public override float Buoyancy | 736 | public override float Buoyancy |
736 | { | 737 | { |
737 | get { return m_buoyancy; } | 738 | get { return m_buoyancy; } |
738 | // set { m_buoyancy = value; } | 739 | set { m_buoyancy = value; } |
739 | set { | ||
740 | m_buoyancy = value; | ||
741 | |||
742 | Console.WriteLine("m_buoyancy={0}", m_buoyancy); | ||
743 | } | ||
744 | } | 740 | } |
745 | 741 | ||
746 | public override void link(PhysicsActor obj) | 742 | public override void link(PhysicsActor obj) |
@@ -1293,7 +1289,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1293 | disableBody(); | 1289 | disableBody(); |
1294 | } | 1290 | } |
1295 | } | 1291 | } |
1296 | |||
1297 | IntPtr vertices, indices; | 1292 | IntPtr vertices, indices; |
1298 | int vertexCount, indexCount; | 1293 | int vertexCount, indexCount; |
1299 | int vertexStride, triStride; | 1294 | int vertexStride, triStride; |
@@ -1349,8 +1344,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1349 | if (prim_geom != IntPtr.Zero) | 1344 | if (prim_geom != IntPtr.Zero) |
1350 | { | 1345 | { |
1351 | if (!_position.ApproxEquals(m_taintposition, 0f)) | 1346 | if (!_position.ApproxEquals(m_taintposition, 0f)) |
1347 | { | ||
1352 | changemove(timestep); | 1348 | changemove(timestep); |
1353 | 1349 | } | |
1354 | if (m_taintrot != _orientation) | 1350 | if (m_taintrot != _orientation) |
1355 | { | 1351 | { |
1356 | if(childPrim && IsPhysical) // For physical child prim... | 1352 | if(childPrim && IsPhysical) // For physical child prim... |
@@ -1370,8 +1366,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1370 | // | 1366 | // |
1371 | 1367 | ||
1372 | if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent)) | 1368 | if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent)) |
1369 | { | ||
1373 | changePhysicsStatus(timestep); | 1370 | changePhysicsStatus(timestep); |
1374 | // | 1371 | }// |
1375 | 1372 | ||
1376 | if (!_size.ApproxEquals(m_taintsize,0f)) | 1373 | if (!_size.ApproxEquals(m_taintsize,0f)) |
1377 | changesize(timestep); | 1374 | changesize(timestep); |
@@ -1482,6 +1479,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1482 | if (Body == IntPtr.Zero) | 1479 | if (Body == IntPtr.Zero) |
1483 | { | 1480 | { |
1484 | Body = d.BodyCreate(_parent_scene.world); | 1481 | Body = d.BodyCreate(_parent_scene.world); |
1482 | // disconnect from world gravity so we can apply buoyancy | ||
1483 | d.BodySetGravityMode (Body, false); | ||
1484 | |||
1485 | setMass(); | 1485 | setMass(); |
1486 | } | 1486 | } |
1487 | if (Body != IntPtr.Zero) | 1487 | if (Body != IntPtr.Zero) |
@@ -1522,7 +1522,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1522 | m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements. No geom yet"); | 1522 | m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements. No geom yet"); |
1523 | continue; | 1523 | continue; |
1524 | } | 1524 | } |
1525 | //Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + m_primName); | ||
1526 | d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); | 1525 | d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); |
1527 | d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); | 1526 | d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); |
1528 | 1527 | ||
@@ -1565,9 +1564,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1565 | m_collisionCategories |= CollisionCategories.Body; | 1564 | m_collisionCategories |= CollisionCategories.Body; |
1566 | m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); | 1565 | m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); |
1567 | 1566 | ||
1568 | //Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + m_primName); | ||
1569 | d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); | 1567 | d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); |
1570 | //Console.WriteLine(" Post GeomSetCategoryBits 2"); | ||
1571 | d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); | 1568 | d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); |
1572 | 1569 | ||
1573 | 1570 | ||
@@ -1721,14 +1718,15 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1721 | if (m_isphysical) | 1718 | if (m_isphysical) |
1722 | { | 1719 | { |
1723 | disableBodySoft(); | 1720 | disableBodySoft(); |
1724 | |||
1725 | if (Body != IntPtr.Zero) | ||
1726 | { | ||
1727 | d.BodySetLinearVel(Body, 0f, 0f, 0f); | ||
1728 | d.BodySetForce(Body, 0, 0, 0); | ||
1729 | enableBodySoft(); | ||
1730 | } | ||
1731 | } | 1721 | } |
1722 | if (Body != IntPtr.Zero) | ||
1723 | { | ||
1724 | d.BodySetLinearVel(Body, 0f, 0f, 0f); | ||
1725 | d.BodySetForce(Body, 0f, 0f, 0f); | ||
1726 | d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f); | ||
1727 | d.BodySetTorque (Body, 0.0f, 0.0f, 0.0f); | ||
1728 | } | ||
1729 | |||
1732 | } | 1730 | } |
1733 | else | 1731 | else |
1734 | { | 1732 | { |
@@ -1749,17 +1747,21 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1749 | d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); | 1747 | d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); |
1750 | d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); | 1748 | d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); |
1751 | } | 1749 | } |
1752 | /* Uhhh - stop the motion if the object is _selected_!! | 1750 | if (Body != IntPtr.Zero) |
1751 | { | ||
1752 | d.BodySetLinearVel(Body, 0f, 0f, 0f); | ||
1753 | d.BodySetForce(Body, 0f, 0f, 0f); | ||
1754 | d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f); | ||
1755 | d.BodySetTorque (Body, 0.0f, 0.0f, 0.0f); | ||
1756 | } | ||
1757 | |||
1753 | if (m_isphysical) | 1758 | if (m_isphysical) |
1754 | { | 1759 | { |
1755 | if (Body != IntPtr.Zero) | 1760 | if (Body != IntPtr.Zero) |
1756 | { | 1761 | { |
1757 | d.BodySetLinearVel(Body, 0f, 0f, 0f); | ||
1758 | d.BodySetForce(Body, 0, 0, 0); | ||
1759 | enableBodySoft(); | 1762 | enableBodySoft(); |
1760 | } | 1763 | } |
1761 | } | 1764 | } |
1762 | */ | ||
1763 | } | 1765 | } |
1764 | 1766 | ||
1765 | resetCollisionAccounting(); | 1767 | resetCollisionAccounting(); |
@@ -1781,7 +1783,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1781 | 1783 | ||
1782 | public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh) | 1784 | public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh) |
1783 | { | 1785 | { |
1784 | //Console.WriteLine("CreateGeom:"); | ||
1785 | if (_mesh != null) // Special - make mesh | 1786 | if (_mesh != null) // Special - make mesh |
1786 | { | 1787 | { |
1787 | setMesh(_parent_scene, _mesh); | 1788 | setMesh(_parent_scene, _mesh); |
@@ -1797,7 +1798,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1797 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | 1798 | _parent_scene.waitForSpaceUnlock(m_targetSpace); |
1798 | try | 1799 | try |
1799 | { | 1800 | { |
1800 | //Console.WriteLine(" CreateGeom 1"); | ||
1801 | SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); | 1801 | SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); |
1802 | } | 1802 | } |
1803 | catch (AccessViolationException) | 1803 | catch (AccessViolationException) |
@@ -1812,7 +1812,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1812 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | 1812 | _parent_scene.waitForSpaceUnlock(m_targetSpace); |
1813 | try | 1813 | try |
1814 | { | 1814 | { |
1815 | //Console.WriteLine(" CreateGeom 2"); | ||
1816 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | 1815 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); |
1817 | } | 1816 | } |
1818 | catch (AccessViolationException) | 1817 | catch (AccessViolationException) |
@@ -1828,7 +1827,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1828 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | 1827 | _parent_scene.waitForSpaceUnlock(m_targetSpace); |
1829 | try | 1828 | try |
1830 | { | 1829 | { |
1831 | //Console.WriteLine(" CreateGeom 3"); | ||
1832 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | 1830 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); |
1833 | } | 1831 | } |
1834 | catch (AccessViolationException) | 1832 | catch (AccessViolationException) |
@@ -1845,7 +1843,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1845 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | 1843 | _parent_scene.waitForSpaceUnlock(m_targetSpace); |
1846 | try | 1844 | try |
1847 | { | 1845 | { |
1848 | //Console.WriteLine(" CreateGeom 4"); | ||
1849 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | 1846 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); |
1850 | } | 1847 | } |
1851 | catch (AccessViolationException) | 1848 | catch (AccessViolationException) |
@@ -1890,7 +1887,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1890 | 1887 | ||
1891 | lock (_parent_scene.OdeLock) | 1888 | lock (_parent_scene.OdeLock) |
1892 | { | 1889 | { |
1893 | //Console.WriteLine("changeadd 1"); | ||
1894 | CreateGeom(m_targetSpace, _mesh); | 1890 | CreateGeom(m_targetSpace, _mesh); |
1895 | 1891 | ||
1896 | if (prim_geom != IntPtr.Zero) | 1892 | if (prim_geom != IntPtr.Zero) |
@@ -1917,10 +1913,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1917 | 1913 | ||
1918 | public void changemove(float timestep) | 1914 | public void changemove(float timestep) |
1919 | { | 1915 | { |
1920 | //Console.WriteLine("changemove sing/root {0} to {1}", m_primName, _position ); | ||
1921 | if (m_isphysical) | 1916 | if (m_isphysical) |
1922 | { | 1917 | { |
1923 | //Console.WriteLine("phys {0} {1} {2}", m_disabled, m_taintremove, childPrim); | ||
1924 | // if (!m_disabled && !m_taintremove && !childPrim) After one edit m_disabled is sometimes set, disabling further edits! | 1918 | // if (!m_disabled && !m_taintremove && !childPrim) After one edit m_disabled is sometimes set, disabling further edits! |
1925 | if (!m_taintremove && !childPrim) | 1919 | if (!m_taintremove && !childPrim) |
1926 | { | 1920 | { |
@@ -1946,7 +1940,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1946 | if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0 && Body != odParent.Body) | 1940 | if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0 && Body != odParent.Body) |
1947 | { | 1941 | { |
1948 | // KF: Fixed Joints were removed? Anyway - this Console.WriteLine does not show up, so routine is not used?? | 1942 | // KF: Fixed Joints were removed? Anyway - this Console.WriteLine does not show up, so routine is not used?? |
1949 | Console.WriteLine(" JointCreateFixed"); | 1943 | Console.WriteLine("ODEPrim JointCreateFixed !!!"); |
1950 | m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup); | 1944 | m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup); |
1951 | d.JointAttach(m_linkJoint, Body, odParent.Body); | 1945 | d.JointAttach(m_linkJoint, Body, odParent.Body); |
1952 | d.JointSetFixed(m_linkJoint); | 1946 | d.JointSetFixed(m_linkJoint); |
@@ -2059,7 +2053,6 @@ Console.WriteLine(" JointCreateFixed"); | |||
2059 | if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) | 2053 | if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) |
2060 | { | 2054 | { |
2061 | _mesh = null; | 2055 | _mesh = null; |
2062 | //Console.WriteLine("changePhysicsStatus for " + m_primName ); | ||
2063 | changeadd(2f); | 2056 | changeadd(2f); |
2064 | } | 2057 | } |
2065 | if (childPrim) | 2058 | if (childPrim) |
@@ -2142,7 +2135,6 @@ Console.WriteLine(" JointCreateFixed"); | |||
2142 | } | 2135 | } |
2143 | 2136 | ||
2144 | //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); | 2137 | //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); |
2145 | //Console.WriteLine("changesize 1"); | ||
2146 | CreateGeom(m_targetSpace, mesh); | 2138 | CreateGeom(m_targetSpace, mesh); |
2147 | 2139 | ||
2148 | 2140 | ||
@@ -2150,7 +2142,6 @@ Console.WriteLine(" JointCreateFixed"); | |||
2150 | else | 2142 | else |
2151 | { | 2143 | { |
2152 | _mesh = null; | 2144 | _mesh = null; |
2153 | //Console.WriteLine("changesize 2"); | ||
2154 | CreateGeom(m_targetSpace, _mesh); | 2145 | CreateGeom(m_targetSpace, _mesh); |
2155 | } | 2146 | } |
2156 | 2147 | ||
@@ -2255,7 +2246,6 @@ Console.WriteLine(" JointCreateFixed"); | |||
2255 | else | 2246 | else |
2256 | { | 2247 | { |
2257 | _mesh = null; | 2248 | _mesh = null; |
2258 | //Console.WriteLine("changeshape"); | ||
2259 | CreateGeom(m_targetSpace, null); | 2249 | CreateGeom(m_targetSpace, null); |
2260 | } | 2250 | } |
2261 | 2251 | ||
@@ -2330,6 +2320,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
2330 | return; | 2320 | return; |
2331 | } | 2321 | } |
2332 | d.BodyEnable(Body); | 2322 | d.BodyEnable(Body); |
2323 | |||
2333 | d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z); | 2324 | d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z); |
2334 | } | 2325 | } |
2335 | m_forcelist.Clear(); | 2326 | m_forcelist.Clear(); |
@@ -3107,8 +3098,6 @@ Console.WriteLine(" JointCreateFixed"); | |||
3107 | else | 3098 | else |
3108 | { // Too many tries | 3099 | { // Too many tries |
3109 | if (_parent == null) base.RaiseOutOfBounds(l_position); | 3100 | if (_parent == null) base.RaiseOutOfBounds(l_position); |
3110 | //Console.WriteLine("ROOB 2"); | ||
3111 | |||
3112 | return; // Dont process any other motion? | 3101 | return; // Dont process any other motion? |
3113 | } // end various methods | 3102 | } // end various methods |
3114 | } // end outside region horizontally | 3103 | } // end outside region horizontally |
@@ -3124,7 +3113,6 @@ Console.WriteLine(" JointCreateFixed"); | |||
3124 | 3113 | ||
3125 | //IsPhysical = false; | 3114 | //IsPhysical = false; |
3126 | if (_parent == null) base.RaiseOutOfBounds(_position); | 3115 | if (_parent == null) base.RaiseOutOfBounds(_position); |
3127 | //Console.WriteLine("ROOB 3"); | ||
3128 | 3116 | ||
3129 | 3117 | ||
3130 | _acceleration.X = 0; // This stuff may stop client display but it has no | 3118 | _acceleration.X = 0; // This stuff may stop client display but it has no |
@@ -3147,10 +3135,12 @@ Console.WriteLine(" JointCreateFixed"); | |||
3147 | } // end neg Z check | 3135 | } // end neg Z check |
3148 | 3136 | ||
3149 | // Is it moving? | 3137 | // Is it moving? |
3150 | if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) | 3138 | /* if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) |
3151 | && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) | 3139 | && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) |
3152 | && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) | 3140 | && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) */ |
3153 | && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, _orientation)) < 0.0001)) // KF 0.01 is far to large | 3141 | if ( (Vector3.Mag(_velocity) < 0.01) && // moving very slowly |
3142 | (Vector3.Mag(_velocity) < Vector3.Mag(m_lastVelocity)) && // decelerating | ||
3143 | (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, _orientation)) < 0.0001) ) // spinning very slowly | ||
3154 | { | 3144 | { |
3155 | _zeroFlag = true; | 3145 | _zeroFlag = true; |
3156 | m_throttleUpdates = false; | 3146 | m_throttleUpdates = false; |
@@ -3167,15 +3157,19 @@ Console.WriteLine(" JointCreateFixed"); | |||
3167 | { // Its stopped | 3157 | { // Its stopped |
3168 | _velocity.X = 0.0f; | 3158 | _velocity.X = 0.0f; |
3169 | _velocity.Y = 0.0f; | 3159 | _velocity.Y = 0.0f; |
3170 | _velocity.Z = 0.0f; | 3160 | // _velocity.Z = 0.0f; |
3171 | 3161 | ||
3172 | _acceleration.X = 0; | 3162 | _acceleration.X = 0; |
3173 | _acceleration.Y = 0; | 3163 | _acceleration.Y = 0; |
3174 | _acceleration.Z = 0; | 3164 | // _acceleration.Z = 0; |
3175 | 3165 | ||
3176 | m_rotationalVelocity.X = 0; | 3166 | m_rotationalVelocity.X = 0; |
3177 | m_rotationalVelocity.Y = 0; | 3167 | m_rotationalVelocity.Y = 0; |
3178 | m_rotationalVelocity.Z = 0; | 3168 | m_rotationalVelocity.Z = 0; |
3169 | // Stop it in the phys engine | ||
3170 | d.BodySetLinearVel(Body, 0.0f, 0.0f, _velocity.Z); | ||
3171 | d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f); | ||
3172 | |||
3179 | if (!m_lastUpdateSent) | 3173 | if (!m_lastUpdateSent) |
3180 | { | 3174 | { |
3181 | m_throttleUpdates = false; | 3175 | m_throttleUpdates = false; |
@@ -3221,13 +3215,13 @@ Console.WriteLine(" JointCreateFixed"); | |||
3221 | // Snapshot current angles, set up Amotor(s) | 3215 | // Snapshot current angles, set up Amotor(s) |
3222 | m_rotateEnableUpdate = false; | 3216 | m_rotateEnableUpdate = false; |
3223 | m_rotateEnable = m_rotateEnableRequest; | 3217 | m_rotateEnable = m_rotateEnableRequest; |
3224 | Console.WriteLine("RotEnable {0} = {1}",m_primName, m_rotateEnable); | 3218 | //Console.WriteLine("RotEnable {0} = {1}",m_primName, m_rotateEnable); |
3225 | 3219 | ||
3226 | if (Amotor != IntPtr.Zero) | 3220 | if (Amotor != IntPtr.Zero) |
3227 | { | 3221 | { |
3228 | d.JointDestroy(Amotor); | 3222 | d.JointDestroy(Amotor); |
3229 | Amotor = IntPtr.Zero; | 3223 | Amotor = IntPtr.Zero; |
3230 | Console.WriteLine("Old Amotor Destroyed"); | 3224 | //Console.WriteLine("Old Amotor Destroyed"); |
3231 | } | 3225 | } |
3232 | 3226 | ||
3233 | if (!m_rotateEnable.ApproxEquals(Vector3.One, 0.003f)) | 3227 | if (!m_rotateEnable.ApproxEquals(Vector3.One, 0.003f)) |
@@ -3249,33 +3243,33 @@ Console.WriteLine("Old Amotor Destroyed"); | |||
3249 | Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); | 3243 | Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); |
3250 | d.JointAttach(Amotor, Body, IntPtr.Zero); | 3244 | d.JointAttach(Amotor, Body, IntPtr.Zero); |
3251 | d.JointSetAMotorMode(Amotor, 0); // User mode?? | 3245 | d.JointSetAMotorMode(Amotor, 0); // User mode?? |
3252 | Console.WriteLine("New Amotor Created for {0}", m_primName); | 3246 | //Console.WriteLine("New Amotor Created for {0}", m_primName); |
3253 | 3247 | ||
3254 | float axisnum = 3; // how many to lock | 3248 | float axisnum = 3; // how many to lock |
3255 | axisnum = (axisnum - (m_rotateEnable.X + m_rotateEnable.Y + m_rotateEnable.Z)); | 3249 | axisnum = (axisnum - (m_rotateEnable.X + m_rotateEnable.Y + m_rotateEnable.Z)); |
3256 | d.JointSetAMotorNumAxes(Amotor,(int)axisnum); | 3250 | d.JointSetAMotorNumAxes(Amotor,(int)axisnum); |
3257 | Console.WriteLine("AxisNum={0}",(int)axisnum); | 3251 | //Console.WriteLine("AxisNum={0}",(int)axisnum); |
3258 | 3252 | ||
3259 | int i = 0; | 3253 | int i = 0; |
3260 | 3254 | ||
3261 | if (m_rotateEnable.X == 0) | 3255 | if (m_rotateEnable.X == 0) |
3262 | { | 3256 | { |
3263 | d.JointSetAMotorAxis(Amotor, i, 0, m_lockX.X, m_lockX.Y, m_lockX.Z); | 3257 | d.JointSetAMotorAxis(Amotor, i, 0, m_lockX.X, m_lockX.Y, m_lockX.Z); |
3264 | Console.WriteLine("AxisX {0} set to {1}", i, m_lockX); | 3258 | //Console.WriteLine("AxisX {0} set to {1}", i, m_lockX); |
3265 | i++; | 3259 | i++; |
3266 | } | 3260 | } |
3267 | 3261 | ||
3268 | if (m_rotateEnable.Y == 0) | 3262 | if (m_rotateEnable.Y == 0) |
3269 | { | 3263 | { |
3270 | d.JointSetAMotorAxis(Amotor, i, 0, m_lockY.X, m_lockY.Y, m_lockY.Z); | 3264 | d.JointSetAMotorAxis(Amotor, i, 0, m_lockY.X, m_lockY.Y, m_lockY.Z); |
3271 | Console.WriteLine("AxisY {0} set to {1}", i, m_lockY); | 3265 | //Console.WriteLine("AxisY {0} set to {1}", i, m_lockY); |
3272 | i++; | 3266 | i++; |
3273 | } | 3267 | } |
3274 | 3268 | ||
3275 | if (m_rotateEnable.Z == 0) | 3269 | if (m_rotateEnable.Z == 0) |
3276 | { | 3270 | { |
3277 | d.JointSetAMotorAxis(Amotor, i, 0, m_lockZ.X, m_lockZ.Y, m_lockZ.Z); | 3271 | d.JointSetAMotorAxis(Amotor, i, 0, m_lockZ.X, m_lockZ.Y, m_lockZ.Z); |
3278 | Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ); | 3272 | //Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ); |
3279 | i++; | 3273 | i++; |
3280 | } | 3274 | } |
3281 | 3275 | ||
@@ -3308,7 +3302,6 @@ Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ); | |||
3308 | d.Vector3 velnow = d.BodyGetLinearVel(Body); // this is in world frame | 3302 | d.Vector3 velnow = d.BodyGetLinearVel(Body); // this is in world frame |
3309 | Vector3 vel_now = new Vector3(velnow.X, velnow.Y, velnow.Z); | 3303 | Vector3 vel_now = new Vector3(velnow.X, velnow.Y, velnow.Z); |
3310 | m_lLinObjectVel = vel_now * irotq; | 3304 | m_lLinObjectVel = vel_now * irotq; |
3311 | |||
3312 | if (m_linearMotorDecayTimescale < 300.0f) //setting of 300 or more disables decay rate | 3305 | if (m_linearMotorDecayTimescale < 300.0f) //setting of 300 or more disables decay rate |
3313 | { | 3306 | { |
3314 | if ( Vector3.Mag(m_lLinMotorDVel) < 1.0f) | 3307 | if ( Vector3.Mag(m_lLinMotorDVel) < 1.0f) |
@@ -3434,7 +3427,7 @@ Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ); | |||
3434 | d.BodySetLinearVel(Body, linvel.X, linvel.Y, linvel.Z); | 3427 | d.BodySetLinearVel(Body, linvel.X, linvel.Y, linvel.Z); |
3435 | // apply gravity force | 3428 | // apply gravity force |
3436 | d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); | 3429 | d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); |
3437 | //if(frcount == 0) Console.WriteLine("Grav {0}", grav); | 3430 | //if(frcount == 0) Console.WriteLine("Vel={0} Force={1}",linvel , grav); |
3438 | // end MoveLinear() | 3431 | // end MoveLinear() |
3439 | 3432 | ||
3440 | 3433 | ||
@@ -3608,7 +3601,6 @@ Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ); | |||
3608 | float m_mass = CalculateMass(); | 3601 | float m_mass = CalculateMass(); |
3609 | // calculate z-force due togravity on object. | 3602 | // calculate z-force due togravity on object. |
3610 | fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass | 3603 | fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass |
3611 | |||
3612 | if ((m_usePID) && (m_PIDTau > 0.0f)) // Dynamics llMoveToTarget. | 3604 | if ((m_usePID) && (m_PIDTau > 0.0f)) // Dynamics llMoveToTarget. |
3613 | { | 3605 | { |
3614 | fz = 0; // llMoveToTarget ignores gravity. | 3606 | fz = 0; // llMoveToTarget ignores gravity. |
@@ -3624,6 +3616,7 @@ Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ); | |||
3624 | (m_PIDTarget.Z - pos.Z)); | 3616 | (m_PIDTarget.Z - pos.Z)); |
3625 | if (error.ApproxEquals(Vector3.Zero,0.01f)) | 3617 | if (error.ApproxEquals(Vector3.Zero,0.01f)) |
3626 | { // Very close, Jump there and quit move | 3618 | { // Very close, Jump there and quit move |
3619 | |||
3627 | d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); | 3620 | d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); |
3628 | _target_velocity = Vector3.Zero; | 3621 | _target_velocity = Vector3.Zero; |
3629 | d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z); | 3622 | d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z); |
@@ -3714,11 +3707,10 @@ Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ); | |||
3714 | // Avatar to Avatar collisions | 3707 | // Avatar to Avatar collisions |
3715 | // Prim to avatar collisions | 3708 | // Prim to avatar collisions |
3716 | d.Vector3 dlinvel = vel; | 3709 | d.Vector3 dlinvel = vel; |
3717 | |||
3718 | d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); | 3710 | d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); |
3719 | d.BodySetLinearVel(Body, dlinvel.X, dlinvel.Y, dlinvel.Z); | 3711 | d.BodySetLinearVel(Body, dlinvel.X, dlinvel.Y, dlinvel.Z); |
3720 | d.BodyAddForce(Body, 0, 0, fz); | 3712 | d.BodyAddForce(Body, 0, 0, fz); |
3721 | //KF this prevents furthur motions return; | 3713 | //KF this prevents furthur motions return; |
3722 | } | 3714 | } |
3723 | else | 3715 | else |
3724 | { | 3716 | { |
@@ -3734,7 +3726,6 @@ Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ); | |||
3734 | fx *= m_mass; | 3726 | fx *= m_mass; |
3735 | fy *= m_mass; | 3727 | fy *= m_mass; |
3736 | //fz *= m_mass; | 3728 | //fz *= m_mass; |
3737 | |||
3738 | fx += m_force.X; | 3729 | fx += m_force.X; |
3739 | fy += m_force.Y; | 3730 | fy += m_force.Y; |
3740 | fz += m_force.Z; | 3731 | fz += m_force.Z; |
@@ -3751,7 +3742,7 @@ Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ); | |||
3751 | // this appears to re-enable it incase the surface it is upon vanishes, | 3742 | // this appears to re-enable it incase the surface it is upon vanishes, |
3752 | // and the body should fall again. | 3743 | // and the body should fall again. |
3753 | d.BodySetLinearVel(Body, 0f, 0f, 0f); | 3744 | d.BodySetLinearVel(Body, 0f, 0f, 0f); |
3754 | d.BodySetForce(Body, 0, 0, 0); | 3745 | d.BodySetForce(Body, 0f, 0f, 0f); |
3755 | enableBodySoft(); | 3746 | enableBodySoft(); |
3756 | } | 3747 | } |
3757 | 3748 | ||
@@ -3769,11 +3760,10 @@ Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ); | |||
3769 | if (fy < nmin) | 3760 | if (fy < nmin) |
3770 | fy = nmin; | 3761 | fy = nmin; |
3771 | d.BodyAddForce(Body, fx, fy, fz); | 3762 | d.BodyAddForce(Body, fx, fy, fz); |
3772 | //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz); | ||
3773 | } // end apply forces | 3763 | } // end apply forces |
3774 | } // end Vehicle/Dynamics | 3764 | } // end Vehicle/Dynamics |
3775 | 3765 | ||
3776 | /// RotLookAt ================================================================================= | 3766 | /// RotLookAt / LookAt ================================================================================= |
3777 | if (m_useAPID) | 3767 | if (m_useAPID) |
3778 | { | 3768 | { |
3779 | // RotLookAt, apparently overrides all other rotation sources. Inputs: | 3769 | // RotLookAt, apparently overrides all other rotation sources. Inputs: |
@@ -3784,41 +3774,87 @@ Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ); | |||
3784 | // Factors: | 3774 | // Factors: |
3785 | // get present body rotation | 3775 | // get present body rotation |
3786 | float limit = 1.0f; | 3776 | float limit = 1.0f; |
3787 | float scaler = 50f; // adjusts damping time | 3777 | float rscaler = 50f; // adjusts rotation damping time |
3778 | float lscaler = 10f; // adjusts linear damping time in llLookAt | ||
3788 | float RLAservo = 0f; | 3779 | float RLAservo = 0f; |
3789 | |||
3790 | d.Quaternion rot = d.BodyGetQuaternion(Body); | ||
3791 | Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); | ||
3792 | Quaternion rot_diff = Quaternion.Inverse(rotq) * m_APIDTarget; | ||
3793 | float diff_angle; | ||
3794 | Vector3 diff_axis; | 3780 | Vector3 diff_axis; |
3795 | rot_diff.GetAxisAngle(out diff_axis, out diff_angle); | 3781 | float diff_angle; |
3796 | diff_axis.Normalize(); | 3782 | d.Quaternion rot = d.BodyGetQuaternion(Body); // prim present rotation |
3797 | if(diff_angle > 0.01f) // diff_angle is always +ve | 3783 | Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); |
3784 | Quaternion rtarget = new Quaternion(); | ||
3785 | |||
3786 | if(m_APIDTarget.W == -99.9f) | ||
3798 | { | 3787 | { |
3799 | // PhysicsVector rotforce = new PhysicsVector(diff_axis.X, diff_axis.Y, diff_axis.Z); | 3788 | // this is really a llLookAt(), x,y,z is the target vector |
3800 | Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z); | 3789 | Vector3 target = new Vector3(m_APIDTarget.X, m_APIDTarget.Y, m_APIDTarget.Z); |
3801 | rotforce = rotforce * rotq; | 3790 | Vector3 ospin = new Vector3(1.0f, 0.0f, 0.0f) * rotq; |
3802 | if(diff_angle > limit) diff_angle = limit; // cap the rotate rate | 3791 | Vector3 error = new Vector3(0.0f, 0.0f, 0.0f); |
3803 | // RLAservo = timestep / m_APIDStrength * m_mass * scaler; | 3792 | float twopi = 2.0f * (float)Math.PI; |
3804 | // rotforce = rotforce * RLAservo * diff_angle ; | 3793 | Vector3 dir = target - _position; |
3805 | // d.BodyAddRelTorque(Body, rotforce.X, rotforce.Y, rotforce.Z); | 3794 | dir.Normalize(); |
3806 | RLAservo = timestep / m_APIDStrength * scaler; | 3795 | float tzrot = (float)Math.Atan2(dir.Y, dir.X); |
3807 | rotforce = rotforce * RLAservo * diff_angle ; | 3796 | float txy = (float)Math.Sqrt((dir.X * dir.X) + (dir.Y * dir.Y)); |
3808 | /* | 3797 | float terot = (float)Math.Atan2(dir.Z, txy); |
3809 | if (m_angularEnable.X == 0) | 3798 | float ozrot = (float)Math.Atan2(ospin.Y, ospin.X); |
3810 | rotforce.X = 0; | 3799 | float oxy = (float)Math.Sqrt((ospin.X * ospin.X) + (ospin.Y * ospin.Y)); |
3811 | if (m_angularEnable.Y == 0) | 3800 | float oerot = (float)Math.Atan2(ospin.Z, oxy); |
3812 | rotforce.Y = 0; | 3801 | float ra = 2.0f * ((rotq.W * rotq.X) + (rotq.Y * rotq.Z)); |
3813 | if (m_angularEnable.Z == 0) | 3802 | float rb = 1.0f - 2.0f * ((rotq.Y * rotq.Y)+(rotq.X * rotq.X)); |
3814 | rotforce.Z = 0; | 3803 | float roll = (float)Math.Atan2(ra, rb); |
3815 | */ | 3804 | float errorz = tzrot - ozrot; |
3816 | d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z); | 3805 | if(errorz > (float)Math.PI) errorz -= twopi; |
3817 | //Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo); | 3806 | else if(errorz < -(float)Math.PI) errorz += twopi; |
3807 | float errory = oerot - terot; | ||
3808 | if(errory > (float)Math.PI) errory -= twopi; | ||
3809 | else if(errory < -(float)Math.PI) errory += twopi; | ||
3810 | diff_angle = Math.Abs(errorz) + Math.Abs(errory) + Math.Abs(roll); | ||
3811 | if(diff_angle > 0.01f * m_APIDdamper) | ||
3812 | { | ||
3813 | m_APIDdamper = 1.0f; | ||
3814 | RLAservo = timestep / m_APIDStrength * rscaler; | ||
3815 | errorz *= RLAservo; | ||
3816 | errory *= RLAservo; | ||
3817 | error.X = -roll * 8.0f; | ||
3818 | error.Y = errory; | ||
3819 | error.Z = errorz; | ||
3820 | error *= rotq; | ||
3821 | d.BodySetAngularVel (Body, error.X, error.Y, error.Z); | ||
3822 | } | ||
3823 | else | ||
3824 | { | ||
3825 | d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f); | ||
3826 | m_APIDdamper = 2.0f; | ||
3827 | } | ||
3818 | } | 3828 | } |
3819 | //if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle); | 3829 | else |
3830 | { | ||
3831 | // this is a llRotLookAt() | ||
3832 | rtarget = m_APIDTarget; | ||
3833 | |||
3834 | Quaternion rot_diff = Quaternion.Inverse(rotq) * rtarget; // difference to desired rot | ||
3835 | rot_diff.GetAxisAngle(out diff_axis, out diff_angle); // convert to axis to point at & error angle | ||
3836 | //if(frcount == 0) Console.WriteLine("axis {0} angle {1}",diff_axis * 57.3f, diff_angle); | ||
3837 | |||
3838 | // diff_axis.Normalize(); it already is! | ||
3839 | if(diff_angle > 0.01f * m_APIDdamper) // diff_angle is always +ve // if there is enough error | ||
3840 | { | ||
3841 | m_APIDdamper = 1.0f; | ||
3842 | Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z); | ||
3843 | rotforce = rotforce * rotq; | ||
3844 | if(diff_angle > limit) diff_angle = limit; // cap the rotate rate | ||
3845 | RLAservo = timestep / m_APIDStrength * lscaler; | ||
3846 | rotforce = rotforce * RLAservo * diff_angle ; | ||
3847 | d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z); | ||
3848 | //Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo); | ||
3849 | } | ||
3850 | else | ||
3851 | { // close enough | ||
3852 | d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f); | ||
3853 | m_APIDdamper = 2.0f; | ||
3854 | } | ||
3855 | } // end llLookAt/llRotLookAt | ||
3856 | //if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle); | ||
3820 | } // end m_useAPID | 3857 | } // end m_useAPID |
3821 | |||
3822 | } // end root prims | 3858 | } // end root prims |
3823 | } // end Move() | 3859 | } // end Move() |
3824 | } // end class | 3860 | } // end class |
diff --git a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs index e7455be..88f9658 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs | |||
@@ -264,8 +264,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
264 | private readonly DoubleDictionary<Vector3, IntPtr, IntPtr> RegionTerrain = new DoubleDictionary<Vector3, IntPtr, IntPtr>(); | 264 | private readonly DoubleDictionary<Vector3, IntPtr, IntPtr> RegionTerrain = new DoubleDictionary<Vector3, IntPtr, IntPtr>(); |
265 | private readonly Dictionary<IntPtr,float[]> TerrainHeightFieldHeights = new Dictionary<IntPtr, float[]>(); | 265 | private readonly Dictionary<IntPtr,float[]> TerrainHeightFieldHeights = new Dictionary<IntPtr, float[]>(); |
266 | 266 | ||
267 | private d.Contact contact; | 267 | private d.Contact ContactCopy; // local copy that can be modified |
268 | private d.Contact TerrainContact; | 268 | private d.Contact TerrainContact; |
269 | private d.Contact AvatarStaticprimContact; // was 'contact' | ||
269 | private d.Contact AvatarMovementprimContact; | 270 | private d.Contact AvatarMovementprimContact; |
270 | private d.Contact AvatarMovementTerrainContact; | 271 | private d.Contact AvatarMovementTerrainContact; |
271 | private d.Contact WaterContact; | 272 | private d.Contact WaterContact; |
@@ -491,169 +492,140 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
491 | 492 | ||
492 | staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)]; | 493 | staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)]; |
493 | 494 | ||
494 | // Centeral contact friction and bounce // KF: This appears to be only for static AV on non-phys prim. | 495 | // Avatar static on a Prim parameters |
495 | contact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 496 | AvatarStaticprimContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
496 | contact.surface.mu = 255.0f; | 497 | AvatarStaticprimContact.surface.mu = 255.0f; |
497 | contact.surface.bounce = 0.0f; | 498 | AvatarStaticprimContact.surface.bounce = 0.0f; |
498 | contact.surface.soft_cfm = 0.0f; | 499 | AvatarStaticprimContact.surface.soft_cfm = 0.0f; |
499 | contact.surface.soft_erp = 0.30f; // If this is too small static Av will fall through a sloping prim. 1.0 prevents fall-thru | 500 | AvatarStaticprimContact.surface.soft_erp = 0.30f; // If this is too small static Av will fall through a sloping prim. 1.0 prevents fall-thru |
500 | |||
501 | // Terrain contact friction and Bounce | ||
502 | // This is the *non* moving version. Use this when an avatar | ||
503 | // isn't moving to keep it in place better | ||
504 | /* TerrainContact.surface.mode |= d.ContactFlags.SoftERP; | ||
505 | TerrainContact.surface.mu = nmTerrainContactFriction; | ||
506 | TerrainContact.surface.bounce = nmTerrainContactBounce; | ||
507 | TerrainContact.surface.soft_erp = nmTerrainContactERP; */ | ||
508 | 501 | ||
509 | TerrainContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 502 | // Avatar moving on a Prim parameters |
510 | TerrainContact.surface.mu = 255.0f; | ||
511 | TerrainContact.surface.bounce = 0.0f; | ||
512 | TerrainContact.surface.soft_cfm = 0.0f; | ||
513 | TerrainContact.surface.soft_erp = 0.05f; | ||
514 | |||
515 | WaterContact.surface.mode |= (d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM); | ||
516 | WaterContact.surface.mu = 0.0f; // No friction | ||
517 | WaterContact.surface.bounce = 0.0f; // No bounce | ||
518 | WaterContact.surface.soft_cfm = 0.010f; | ||
519 | WaterContact.surface.soft_erp = 0.010f; | ||
520 | |||
521 | // Prim contact friction and bounce | ||
522 | // THis is the moving version of friction and bounce | ||
523 | // Use this when an avatar comes in contact with a prim | ||
524 | AvatarMovementprimContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 503 | AvatarMovementprimContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
525 | AvatarMovementprimContact.surface.mu = 255.0f; | 504 | AvatarMovementprimContact.surface.mu = 255.0f; |
526 | AvatarMovementprimContact.surface.bounce = 0.0f; | 505 | AvatarMovementprimContact.surface.bounce = 0.0f; |
527 | AvatarMovementprimContact.surface.soft_cfm = 0.0f; // if this is 0.01 then prims become phantom to Avs! | 506 | AvatarMovementprimContact.surface.soft_cfm = 0.0f; // if this is 0.01 then prims become phantom to Avs! |
528 | AvatarMovementprimContact.surface.soft_erp = 0.3f; | 507 | AvatarMovementprimContact.surface.soft_erp = 0.3f; |
529 | 508 | ||
530 | // Terrain contact friction bounce and various error correcting calculations | 509 | // Static Avatar on Terrain parameters |
531 | // Use this when an avatar is in contact with the terrain and moving. | 510 | // Keeps Avatar in place better |
532 | /* | 511 | TerrainContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
533 | AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP; | 512 | TerrainContact.surface.mu = 255.0f; |
534 | AvatarMovementTerrainContact.surface.mu = mTerrainContactFriction; | 513 | TerrainContact.surface.bounce = 0.0f; |
535 | AvatarMovementTerrainContact.surface.bounce = mTerrainContactBounce; | 514 | TerrainContact.surface.soft_cfm = 0.0f; |
536 | AvatarMovementTerrainContact.surface.soft_erp = mTerrainContactERP; | 515 | TerrainContact.surface.soft_erp = 0.05f; |
537 | */ | 516 | |
517 | // Moving Avatar on Terrain parameters | ||
538 | AvatarMovementTerrainContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 518 | AvatarMovementTerrainContact.surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
539 | AvatarMovementTerrainContact.surface.mu = 75f; | 519 | AvatarMovementTerrainContact.surface.mu = 75f; |
540 | AvatarMovementTerrainContact.surface.bounce = 0.0f; | 520 | AvatarMovementTerrainContact.surface.bounce = 0.0f; |
541 | AvatarMovementTerrainContact.surface.soft_cfm = 0.0f; | 521 | AvatarMovementTerrainContact.surface.soft_cfm = 0.0f; |
542 | AvatarMovementTerrainContact.surface.soft_erp = 0.05f; | 522 | AvatarMovementTerrainContact.surface.soft_erp = 0.05f; |
543 | 523 | ||
544 | /* | 524 | // Avatar or prim the the water, this may not be used, possibly water is same as air? |
545 | <summary></summary> | 525 | WaterContact.surface.mode |= (d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM); |
546 | Stone = 0, | 526 | WaterContact.surface.mu = 0.0f; // No friction |
547 | /// <summary></summary> | 527 | WaterContact.surface.bounce = 0.0f; // No bounce |
548 | Metal = 1, | 528 | WaterContact.surface.soft_cfm = 0.010f; |
549 | /// <summary></summary> | 529 | WaterContact.surface.soft_erp = 0.010f; |
550 | Glass = 2, | 530 | |
551 | /// <summary></summary> | ||
552 | Wood = 3, | ||
553 | /// <summary></summary> | ||
554 | Flesh = 4, | ||
555 | /// <summary></summary> | ||
556 | Plastic = 5, | ||
557 | /// <summary></summary> | ||
558 | Rubber = 6 | ||
559 | */ | ||
560 | 531 | ||
532 | // Prim static or moving on a prim, depends on material type | ||
561 | m_materialContacts = new d.Contact[7,2]; | 533 | m_materialContacts = new d.Contact[7,2]; |
562 | // V 1 = Sliding; 0 = static or fell onto | 534 | // V 1 = Sliding; 0 = static or fell onto |
563 | m_materialContacts[(int)Material.Stone, 0] = new d.Contact(); | 535 | m_materialContacts[(int)Material.Stone, 0] = new d.Contact(); |
564 | m_materialContacts[(int)Material.Stone, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 536 | m_materialContacts[(int)Material.Stone, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
565 | m_materialContacts[(int)Material.Stone, 0].surface.mu = 1.8f; // friction, 1 = slippery, 255 = no slip | 537 | m_materialContacts[(int)Material.Stone, 0].surface.mu = 60f; // friction, 1 = slippery, 255 = no slip |
566 | m_materialContacts[(int)Material.Stone, 0].surface.bounce = 0.0f; | 538 | m_materialContacts[(int)Material.Stone, 0].surface.bounce = 0.0f; |
567 | m_materialContacts[(int)Material.Stone, 0].surface.soft_cfm = 0.0f; | 539 | m_materialContacts[(int)Material.Stone, 0].surface.soft_cfm = 0.0f; |
568 | m_materialContacts[(int)Material.Stone, 0].surface.soft_erp = 0.50f; | 540 | m_materialContacts[(int)Material.Stone, 0].surface.soft_erp = 0.50f; // erp also changes friction, more erp=less friction |
569 | 541 | ||
570 | m_materialContacts[(int)Material.Stone, 1] = new d.Contact(); | 542 | m_materialContacts[(int)Material.Stone, 1] = new d.Contact(); |
571 | m_materialContacts[(int)Material.Stone, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 543 | m_materialContacts[(int)Material.Stone, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
572 | m_materialContacts[(int)Material.Stone, 1].surface.mu = 1.8f; | 544 | m_materialContacts[(int)Material.Stone, 1].surface.mu = 40f; |
573 | m_materialContacts[(int)Material.Stone, 1].surface.bounce = 0.0f; | 545 | m_materialContacts[(int)Material.Stone, 1].surface.bounce = 0.0f; |
574 | m_materialContacts[(int)Material.Stone, 1].surface.soft_cfm = 0.0f; | 546 | m_materialContacts[(int)Material.Stone, 1].surface.soft_cfm = 0.0f; |
575 | m_materialContacts[(int)Material.Stone, 1].surface.soft_erp = 0.50f; | 547 | m_materialContacts[(int)Material.Stone, 1].surface.soft_erp = 0.50f; |
576 | 548 | ||
577 | m_materialContacts[(int)Material.Metal, 0] = new d.Contact(); | 549 | m_materialContacts[(int)Material.Metal, 0] = new d.Contact(); |
578 | m_materialContacts[(int)Material.Metal, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 550 | m_materialContacts[(int)Material.Metal, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
579 | m_materialContacts[(int)Material.Metal, 0].surface.mu = 1.3f; | 551 | m_materialContacts[(int)Material.Metal, 0].surface.mu = 15f; |
580 | m_materialContacts[(int)Material.Metal, 0].surface.bounce = 0.2f; | 552 | m_materialContacts[(int)Material.Metal, 0].surface.bounce = 0.2f; |
581 | m_materialContacts[(int)Material.Metal, 0].surface.soft_cfm = 0.0f; | 553 | m_materialContacts[(int)Material.Metal, 0].surface.soft_cfm = 0.0f; |
582 | m_materialContacts[(int)Material.Metal, 0].surface.soft_erp = 0.50f; | 554 | m_materialContacts[(int)Material.Metal, 0].surface.soft_erp = 0.50f; |
583 | 555 | ||
584 | m_materialContacts[(int)Material.Metal, 1] = new d.Contact(); | 556 | m_materialContacts[(int)Material.Metal, 1] = new d.Contact(); |
585 | m_materialContacts[(int)Material.Metal, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 557 | m_materialContacts[(int)Material.Metal, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
586 | m_materialContacts[(int)Material.Metal, 1].surface.mu = 1.3f; | 558 | m_materialContacts[(int)Material.Metal, 1].surface.mu = 10f; |
587 | m_materialContacts[(int)Material.Metal, 1].surface.bounce = 0.2f; | 559 | m_materialContacts[(int)Material.Metal, 1].surface.bounce = 0.2f; |
588 | m_materialContacts[(int)Material.Metal, 1].surface.soft_cfm = 0.0f; | 560 | m_materialContacts[(int)Material.Metal, 1].surface.soft_cfm = 0.0f; |
589 | m_materialContacts[(int)Material.Metal, 1].surface.soft_erp = 0.50f; | 561 | m_materialContacts[(int)Material.Metal, 1].surface.soft_erp = 0.50f; |
590 | 562 | ||
591 | m_materialContacts[(int)Material.Glass, 0] = new d.Contact(); | 563 | m_materialContacts[(int)Material.Glass, 0] = new d.Contact(); |
592 | m_materialContacts[(int)Material.Glass, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 564 | m_materialContacts[(int)Material.Glass, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
593 | m_materialContacts[(int)Material.Glass, 0].surface.mu = 1f; | 565 | m_materialContacts[(int)Material.Glass, 0].surface.mu = 7.5f; |
594 | m_materialContacts[(int)Material.Glass, 0].surface.bounce = 0.0f; | 566 | m_materialContacts[(int)Material.Glass, 0].surface.bounce = 0.0f; |
595 | m_materialContacts[(int)Material.Glass, 0].surface.soft_cfm = 0.01f; | 567 | m_materialContacts[(int)Material.Glass, 0].surface.soft_cfm = 0.0f; |
596 | m_materialContacts[(int)Material.Glass, 0].surface.soft_erp = 0.50f; | 568 | m_materialContacts[(int)Material.Glass, 0].surface.soft_erp = 0.50f; |
597 | 569 | ||
598 | m_materialContacts[(int)Material.Glass, 1] = new d.Contact(); | 570 | m_materialContacts[(int)Material.Glass, 1] = new d.Contact(); |
599 | m_materialContacts[(int)Material.Glass, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 571 | m_materialContacts[(int)Material.Glass, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
600 | m_materialContacts[(int)Material.Glass, 1].surface.mu = 1f; | 572 | m_materialContacts[(int)Material.Glass, 1].surface.mu = 5f; |
601 | m_materialContacts[(int)Material.Glass, 1].surface.bounce = 0.0f; | 573 | m_materialContacts[(int)Material.Glass, 1].surface.bounce = 0.0f; |
602 | m_materialContacts[(int)Material.Glass, 1].surface.soft_cfm = 0.0f; | 574 | m_materialContacts[(int)Material.Glass, 1].surface.soft_cfm = 0.0f; |
603 | m_materialContacts[(int)Material.Glass, 1].surface.soft_erp = 0.30f; | 575 | m_materialContacts[(int)Material.Glass, 1].surface.soft_erp = 0.50f; |
604 | 576 | ||
605 | m_materialContacts[(int)Material.Wood, 0] = new d.Contact(); | 577 | m_materialContacts[(int)Material.Wood, 0] = new d.Contact(); |
606 | m_materialContacts[(int)Material.Wood, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 578 | m_materialContacts[(int)Material.Wood, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
607 | m_materialContacts[(int)Material.Wood, 0].surface.mu = 1.6f; | 579 | m_materialContacts[(int)Material.Wood, 0].surface.mu = 45f; |
608 | m_materialContacts[(int)Material.Wood, 0].surface.bounce = 0.1f; | 580 | m_materialContacts[(int)Material.Wood, 0].surface.bounce = 0.1f; |
609 | m_materialContacts[(int)Material.Wood, 0].surface.soft_cfm = 0.0f; | 581 | m_materialContacts[(int)Material.Wood, 0].surface.soft_cfm = 0.0f; |
610 | m_materialContacts[(int)Material.Wood, 0].surface.soft_erp = 0.50f; | 582 | m_materialContacts[(int)Material.Wood, 0].surface.soft_erp = 0.50f; |
611 | 583 | ||
612 | m_materialContacts[(int)Material.Wood, 1] = new d.Contact(); | 584 | m_materialContacts[(int)Material.Wood, 1] = new d.Contact(); |
613 | m_materialContacts[(int)Material.Wood, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 585 | m_materialContacts[(int)Material.Wood, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
614 | m_materialContacts[(int)Material.Wood, 1].surface.mu = 1.6f; | 586 | m_materialContacts[(int)Material.Wood, 1].surface.mu = 30f; |
615 | m_materialContacts[(int)Material.Wood, 1].surface.bounce = 0.1f; | 587 | m_materialContacts[(int)Material.Wood, 1].surface.bounce = 0.1f; |
616 | m_materialContacts[(int)Material.Wood, 1].surface.soft_cfm = 0.0f; | 588 | m_materialContacts[(int)Material.Wood, 1].surface.soft_cfm = 0.0f; |
617 | m_materialContacts[(int)Material.Wood, 1].surface.soft_erp = 0.50f; | 589 | m_materialContacts[(int)Material.Wood, 1].surface.soft_erp = 0.50f; |
618 | 590 | ||
619 | m_materialContacts[(int)Material.Flesh, 0] = new d.Contact(); | 591 | m_materialContacts[(int)Material.Flesh, 0] = new d.Contact(); |
620 | m_materialContacts[(int)Material.Flesh, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 592 | m_materialContacts[(int)Material.Flesh, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
621 | m_materialContacts[(int)Material.Flesh, 0].surface.mu = 2.0f; | 593 | m_materialContacts[(int)Material.Flesh, 0].surface.mu = 150f; |
622 | m_materialContacts[(int)Material.Flesh, 0].surface.bounce = 0.0f; | 594 | m_materialContacts[(int)Material.Flesh, 0].surface.bounce = 0.0f; |
623 | m_materialContacts[(int)Material.Flesh, 0].surface.soft_cfm = 0.0f; | 595 | m_materialContacts[(int)Material.Flesh, 0].surface.soft_cfm = 0.0f; |
624 | m_materialContacts[(int)Material.Flesh, 0].surface.soft_erp = 0.50f; | 596 | m_materialContacts[(int)Material.Flesh, 0].surface.soft_erp = 0.50f; |
625 | 597 | ||
626 | m_materialContacts[(int)Material.Flesh, 1] = new d.Contact(); | 598 | m_materialContacts[(int)Material.Flesh, 1] = new d.Contact(); |
627 | m_materialContacts[(int)Material.Flesh, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 599 | m_materialContacts[(int)Material.Flesh, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
628 | m_materialContacts[(int)Material.Flesh, 1].surface.mu = 2.0f; | 600 | m_materialContacts[(int)Material.Flesh, 1].surface.mu = 100f; |
629 | m_materialContacts[(int)Material.Flesh, 1].surface.bounce = 0.0f; | 601 | m_materialContacts[(int)Material.Flesh, 1].surface.bounce = 0.0f; |
630 | m_materialContacts[(int)Material.Flesh, 1].surface.soft_cfm = 0.0f; | 602 | m_materialContacts[(int)Material.Flesh, 1].surface.soft_cfm = 0.0f; |
631 | m_materialContacts[(int)Material.Flesh, 1].surface.soft_erp = 0.50f; | 603 | m_materialContacts[(int)Material.Flesh, 1].surface.soft_erp = 0.50f; |
632 | 604 | ||
633 | m_materialContacts[(int)Material.Plastic, 0] = new d.Contact(); | 605 | m_materialContacts[(int)Material.Plastic, 0] = new d.Contact(); |
634 | m_materialContacts[(int)Material.Plastic, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 606 | m_materialContacts[(int)Material.Plastic, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
635 | m_materialContacts[(int)Material.Plastic, 0].surface.mu = 1.5f; | 607 | m_materialContacts[(int)Material.Plastic, 0].surface.mu = 30f; |
636 | m_materialContacts[(int)Material.Plastic, 0].surface.bounce = 0.2f; | 608 | m_materialContacts[(int)Material.Plastic, 0].surface.bounce = 0.2f; |
637 | m_materialContacts[(int)Material.Plastic, 0].surface.soft_cfm = 0.0f; | 609 | m_materialContacts[(int)Material.Plastic, 0].surface.soft_cfm = 0.0f; |
638 | m_materialContacts[(int)Material.Plastic, 0].surface.soft_erp = 0.50f; | 610 | m_materialContacts[(int)Material.Plastic, 0].surface.soft_erp = 0.50f; |
639 | 611 | ||
640 | m_materialContacts[(int)Material.Plastic, 1] = new d.Contact(); | 612 | m_materialContacts[(int)Material.Plastic, 1] = new d.Contact(); |
641 | m_materialContacts[(int)Material.Plastic, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 613 | m_materialContacts[(int)Material.Plastic, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
642 | m_materialContacts[(int)Material.Plastic, 1].surface.mu = 1.5f; | 614 | m_materialContacts[(int)Material.Plastic, 1].surface.mu = 20f; |
643 | m_materialContacts[(int)Material.Plastic, 1].surface.bounce = 0.2f; | 615 | m_materialContacts[(int)Material.Plastic, 1].surface.bounce = 0.2f; |
644 | m_materialContacts[(int)Material.Plastic, 1].surface.soft_cfm = 0.0f; | 616 | m_materialContacts[(int)Material.Plastic, 1].surface.soft_cfm = 0.0f; |
645 | m_materialContacts[(int)Material.Plastic, 1].surface.soft_erp = 0.50f; | 617 | m_materialContacts[(int)Material.Plastic, 1].surface.soft_erp = 0.50f; |
646 | 618 | ||
647 | m_materialContacts[(int)Material.Rubber, 0] = new d.Contact(); | 619 | m_materialContacts[(int)Material.Rubber, 0] = new d.Contact(); |
648 | m_materialContacts[(int)Material.Rubber, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 620 | m_materialContacts[(int)Material.Rubber, 0].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
649 | m_materialContacts[(int)Material.Rubber, 0].surface.mu = 2.0f; | 621 | m_materialContacts[(int)Material.Rubber, 0].surface.mu = 150f; |
650 | m_materialContacts[(int)Material.Rubber, 0].surface.bounce = 0.7f; | 622 | m_materialContacts[(int)Material.Rubber, 0].surface.bounce = 0.7f; |
651 | m_materialContacts[(int)Material.Rubber, 0].surface.soft_cfm = 0.0f; | 623 | m_materialContacts[(int)Material.Rubber, 0].surface.soft_cfm = 0.0f; |
652 | m_materialContacts[(int)Material.Rubber, 0].surface.soft_erp = 0.50f; | 624 | m_materialContacts[(int)Material.Rubber, 0].surface.soft_erp = 0.50f; |
653 | 625 | ||
654 | m_materialContacts[(int)Material.Rubber, 1] = new d.Contact(); | 626 | m_materialContacts[(int)Material.Rubber, 1] = new d.Contact(); |
655 | m_materialContacts[(int)Material.Rubber, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; | 627 | m_materialContacts[(int)Material.Rubber, 1].surface.mode = d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP | d.ContactFlags.Bounce; |
656 | m_materialContacts[(int)Material.Rubber, 1].surface.mu = 2.0f; | 628 | m_materialContacts[(int)Material.Rubber, 1].surface.mu = 100f; |
657 | m_materialContacts[(int)Material.Rubber, 1].surface.bounce = 0.7f; | 629 | m_materialContacts[(int)Material.Rubber, 1].surface.bounce = 0.7f; |
658 | m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.0f; | 630 | m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.0f; |
659 | m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.50f; | 631 | m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.50f; |
@@ -819,11 +791,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
819 | p2 = PANull; | 791 | p2 = PANull; |
820 | } | 792 | } |
821 | 793 | ||
822 | if((p1 is OdePrim ) && (p2 is OdePrim)){ | ||
823 | OdePrim t1 = (OdePrim)p1; | ||
824 | OdePrim t2 = (OdePrim)p2; | ||
825 | Console.WriteLine("Collision {0} {1}", t1.m_primName, t2.m_primName); | ||
826 | } | ||
827 | ContactPoint maxDepthContact = new ContactPoint(); | 794 | ContactPoint maxDepthContact = new ContactPoint(); |
828 | if (p1.CollisionScore + count >= float.MaxValue) | 795 | if (p1.CollisionScore + count >= float.MaxValue) |
829 | p1.CollisionScore = 0; | 796 | p1.CollisionScore = 0; |
@@ -847,7 +814,7 @@ if((p1 is OdePrim ) && (p2 is OdePrim)){ | |||
847 | 814 | ||
848 | //m_log.Warn("[CCOUNT]: " + count); | 815 | //m_log.Warn("[CCOUNT]: " + count); |
849 | IntPtr joint; | 816 | IntPtr joint; |
850 | // If we're colliding with terrain, use 'TerrainContact' instead of contact. | 817 | // If we're colliding with terrain, use 'TerrainContact' instead of AvatarStaticprimContact. |
851 | // allows us to have different settings | 818 | // allows us to have different settings |
852 | 819 | ||
853 | // We only need to test p2 for 'jump crouch purposes' | 820 | // We only need to test p2 for 'jump crouch purposes' |
@@ -898,9 +865,9 @@ if((p1 is OdePrim ) && (p2 is OdePrim)){ | |||
898 | //This is disabled at the moment only because it needs more tweaking | 865 | //This is disabled at the moment only because it needs more tweaking |
899 | //It will eventually be uncommented | 866 | //It will eventually be uncommented |
900 | /* | 867 | /* |
901 | if (contact.depth >= 1.00f) | 868 | if (AvatarStaticprimContact.depth >= 1.00f) |
902 | { | 869 | { |
903 | //m_log.Debug("[PHYSICS]: " + contact.depth.ToString()); | 870 | //m_log.Debug("[PHYSICS]: " + AvatarStaticprimContact.depth.ToString()); |
904 | } | 871 | } |
905 | 872 | ||
906 | //If you interpenetrate a prim with an agent | 873 | //If you interpenetrate a prim with an agent |
@@ -910,37 +877,37 @@ if((p1 is OdePrim ) && (p2 is OdePrim)){ | |||
910 | p2.PhysicsActorType == (int) ActorTypes.Prim)) | 877 | p2.PhysicsActorType == (int) ActorTypes.Prim)) |
911 | { | 878 | { |
912 | 879 | ||
913 | //contact.depth = contact.depth * 4.15f; | 880 | //AvatarStaticprimContact.depth = AvatarStaticprimContact.depth * 4.15f; |
914 | /* | 881 | /* |
915 | if (p2.PhysicsActorType == (int) ActorTypes.Agent) | 882 | if (p2.PhysicsActorType == (int) ActorTypes.Agent) |
916 | { | 883 | { |
917 | p2.CollidingObj = true; | 884 | p2.CollidingObj = true; |
918 | contact.depth = 0.003f; | 885 | AvatarStaticprimContact.depth = 0.003f; |
919 | p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); | 886 | p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); |
920 | OdeCharacter character = (OdeCharacter) p2; | 887 | OdeCharacter character = (OdeCharacter) p2; |
921 | character.SetPidStatus(true); | 888 | character.SetPidStatus(true); |
922 | contact.pos = new d.Vector3(contact.pos.X + (p1.Size.X / 2), contact.pos.Y + (p1.Size.Y / 2), contact.pos.Z + (p1.Size.Z / 2)); | 889 | AvatarStaticprimContact.pos = new d.Vector3(AvatarStaticprimContact.pos.X + (p1.Size.X / 2), AvatarStaticprimContact.pos.Y + (p1.Size.Y / 2), AvatarStaticprimContact.pos.Z + (p1.Size.Z / 2)); |
923 | 890 | ||
924 | } | 891 | } |
925 | else | 892 | else |
926 | { | 893 | { |
927 | 894 | ||
928 | //contact.depth = 0.0000000f; | 895 | //AvatarStaticprimContact.depth = 0.0000000f; |
929 | } | 896 | } |
930 | if (p1.PhysicsActorType == (int) ActorTypes.Agent) | 897 | if (p1.PhysicsActorType == (int) ActorTypes.Agent) |
931 | { | 898 | { |
932 | 899 | ||
933 | p1.CollidingObj = true; | 900 | p1.CollidingObj = true; |
934 | contact.depth = 0.003f; | 901 | AvatarStaticprimContact.depth = 0.003f; |
935 | p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); | 902 | p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); |
936 | contact.pos = new d.Vector3(contact.pos.X + (p2.Size.X / 2), contact.pos.Y + (p2.Size.Y / 2), contact.pos.Z + (p2.Size.Z / 2)); | 903 | AvatarStaticprimContact.pos = new d.Vector3(AvatarStaticprimContact.pos.X + (p2.Size.X / 2), AvatarStaticprimContact.pos.Y + (p2.Size.Y / 2), AvatarStaticprimContact.pos.Z + (p2.Size.Z / 2)); |
937 | OdeCharacter character = (OdeCharacter)p1; | 904 | OdeCharacter character = (OdeCharacter)p1; |
938 | character.SetPidStatus(true); | 905 | character.SetPidStatus(true); |
939 | } | 906 | } |
940 | else | 907 | else |
941 | { | 908 | { |
942 | 909 | ||
943 | //contact.depth = 0.0000000f; | 910 | //AvatarStaticprimContact.depth = 0.0000000f; |
944 | } | 911 | } |
945 | 912 | ||
946 | 913 | ||
@@ -965,7 +932,7 @@ if((p1 is OdePrim ) && (p2 is OdePrim)){ | |||
965 | //AddPhysicsActorTaint(p2); | 932 | //AddPhysicsActorTaint(p2); |
966 | //} | 933 | //} |
967 | 934 | ||
968 | //if (contact.depth >= 0.25f) | 935 | //if (AvatarStaticprimContact.depth >= 0.25f) |
969 | //{ | 936 | //{ |
970 | // Don't collide, one or both prim will expld. | 937 | // Don't collide, one or both prim will expld. |
971 | 938 | ||
@@ -983,13 +950,13 @@ if((p1 is OdePrim ) && (p2 is OdePrim)){ | |||
983 | //AddPhysicsActorTaint(p2); | 950 | //AddPhysicsActorTaint(p2); |
984 | //} | 951 | //} |
985 | 952 | ||
986 | //contact.depth = contact.depth / 8f; | 953 | //AvatarStaticprimContact.depth = AvatarStaticprimContact.depth / 8f; |
987 | //contact.normal = new d.Vector3(0, 0, 1); | 954 | //AvatarStaticprimContact.normal = new d.Vector3(0, 0, 1); |
988 | //} | 955 | //} |
989 | //if (op1.m_disabled || op2.m_disabled) | 956 | //if (op1.m_disabled || op2.m_disabled) |
990 | //{ | 957 | //{ |
991 | //Manually disabled objects stay disabled | 958 | //Manually disabled objects stay disabled |
992 | //contact.depth = 0f; | 959 | //AvatarStaticprimContact.depth = 0f; |
993 | //} | 960 | //} |
994 | #endregion | 961 | #endregion |
995 | } | 962 | } |
@@ -997,7 +964,7 @@ if((p1 is OdePrim ) && (p2 is OdePrim)){ | |||
997 | #endregion | 964 | #endregion |
998 | if (curContact.depth >= 1.00f) | 965 | if (curContact.depth >= 1.00f) |
999 | { | 966 | { |
1000 | //m_log.Info("[P]: " + contact.depth.ToString()); | 967 | //m_log.Info("[P]: " + AvatarStaticprimContact.depth.ToString()); |
1001 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent && | 968 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent && |
1002 | p1.PhysicsActorType == (int) ActorTypes.Unknown) || | 969 | p1.PhysicsActorType == (int) ActorTypes.Unknown) || |
1003 | (p1.PhysicsActorType == (int) ActorTypes.Agent && | 970 | (p1.PhysicsActorType == (int) ActorTypes.Agent && |
@@ -1067,15 +1034,16 @@ if((p1 is OdePrim ) && (p2 is OdePrim)){ | |||
1067 | if (!skipThisContact) | 1034 | if (!skipThisContact) |
1068 | { | 1035 | { |
1069 | // Add contact joints with materials params---------------------------------- | 1036 | // Add contact joints with materials params---------------------------------- |
1037 | // p1 is what is being hit, p2 is the physical object doing the hitting | ||
1070 | int material = (int) Material.Wood; | 1038 | int material = (int) Material.Wood; |
1071 | int movintYN = 0; // 1 = Sliding; 0 = static or fell onto | 1039 | int movintYN = 0; // 1 = Sliding; 0 = static or fell onto |
1040 | if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) movintYN = 1; | ||
1072 | 1041 | ||
1073 | // If we're colliding against terrain | 1042 | // If we're colliding against terrain |
1074 | if (name1 == "Terrain" || name2 == "Terrain") | 1043 | if (name1 == "Terrain" || name2 == "Terrain") |
1075 | { | 1044 | { |
1076 | // If we're moving | 1045 | // If we're moving |
1077 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && | 1046 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && (movintYN == 1)) |
1078 | (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) | ||
1079 | { | 1047 | { |
1080 | //$ Av walk/run on terrain (not falling) Use the Avatar movement terrain contact | 1048 | //$ Av walk/run on terrain (not falling) Use the Avatar movement terrain contact |
1081 | AvatarMovementTerrainContact.geom = curContact; | 1049 | AvatarMovementTerrainContact.geom = curContact; |
@@ -1103,13 +1071,9 @@ if((p1 is OdePrim ) && (p2 is OdePrim)){ | |||
1103 | { | 1071 | { |
1104 | if (p2.PhysicsActorType == (int)ActorTypes.Prim && p1.PhysicsActorType == (int)ActorTypes.Prim) | 1072 | if (p2.PhysicsActorType == (int)ActorTypes.Prim && p1.PhysicsActorType == (int)ActorTypes.Prim) |
1105 | { | 1073 | { |
1106 | //& THIS NEVER HAPPENS prim prim contact //kf Huh? In terrain contact? | 1074 | //& THIS NEVER HAPPENS? prim prim contact In terrain contact? |
1107 | // int pj294950 = 0; | 1075 | // int pj294950 = 0; |
1108 | // prim terrain contact | 1076 | // prim terrain contact |
1109 | if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) | ||
1110 | { | ||
1111 | movintYN = 1; | ||
1112 | } | ||
1113 | 1077 | ||
1114 | if (p2 is OdePrim) | 1078 | if (p2 is OdePrim) |
1115 | material = ((OdePrim)p2).m_material; | 1079 | material = ((OdePrim)p2).m_material; |
@@ -1128,34 +1092,31 @@ if((p1 is OdePrim ) && (p2 is OdePrim)){ | |||
1128 | else | 1092 | else |
1129 | { | 1093 | { |
1130 | //$ prim on terrain contact | 1094 | //$ prim on terrain contact |
1131 | if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) | ||
1132 | { | ||
1133 | movintYN = 1; | ||
1134 | } | ||
1135 | |||
1136 | if (p2 is OdePrim) | 1095 | if (p2 is OdePrim) |
1137 | material = ((OdePrim)p2).m_material; | 1096 | material = ((OdePrim)p2).m_material; |
1138 | //m_log.DebugFormat("Material: {0}", material); | 1097 | //m_log.DebugFormat("Material: {0}", material); |
1139 | m_materialContacts[material, movintYN].geom = curContact; | 1098 | m_materialContacts[material, movintYN].geom = curContact; |
1140 | _perloopContact.Add(curContact); | 1099 | _perloopContact.Add(curContact); |
1141 | 1100 | ||
1101 | ContactCopy = m_materialContacts[material, movintYN]; | ||
1102 | if(movintYN == 1) | ||
1103 | { | ||
1104 | // prevent excessive slide on terrain | ||
1105 | ContactCopy.surface.mu = m_materialContacts[material, movintYN].surface.mu * 30.0f; | ||
1106 | } | ||
1107 | |||
1142 | if (m_global_contactcount < maxContactsbeforedeath) | 1108 | if (m_global_contactcount < maxContactsbeforedeath) |
1143 | { | 1109 | { |
1144 | joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); | 1110 | joint = d.JointCreateContact(world, contactgroup, ref ContactCopy); |
1145 | m_global_contactcount++; | 1111 | m_global_contactcount++; |
1146 | |||
1147 | } | 1112 | } |
1148 | } | 1113 | } |
1149 | } | 1114 | } |
1150 | } | 1115 | } |
1151 | //if (p2.PhysicsActorType == (int)ActorTypes.Prim) | ||
1152 | //{ | ||
1153 | //m_log.Debug("[PHYSICS]: prim contacting with ground"); | ||
1154 | //} | ||
1155 | } | 1116 | } |
1156 | else if (name1 == "Water" || name2 == "Water") | 1117 | else if (name1 == "Water" || name2 == "Water") |
1157 | { | 1118 | { |
1158 | //$ This never happens! | 1119 | //$ This never happens! Perhaps water is treated like air? |
1159 | /* | 1120 | /* |
1160 | if ((p2.PhysicsActorType == (int) ActorTypes.Prim)) | 1121 | if ((p2.PhysicsActorType == (int) ActorTypes.Prim)) |
1161 | { | 1122 | { |
@@ -1169,8 +1130,8 @@ if((p1 is OdePrim ) && (p2 is OdePrim)){ | |||
1169 | if (curContact.depth > 0.1f) | 1130 | if (curContact.depth > 0.1f) |
1170 | { | 1131 | { |
1171 | curContact.depth *= 52; | 1132 | curContact.depth *= 52; |
1172 | //contact.normal = new d.Vector3(0, 0, 1); | 1133 | //AvatarStaticprimContact.normal = new d.Vector3(0, 0, 1); |
1173 | //contact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f); | 1134 | //AvatarStaticprimContact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f); |
1174 | } | 1135 | } |
1175 | WaterContact.geom = curContact; | 1136 | WaterContact.geom = curContact; |
1176 | _perloopContact.Add(curContact); | 1137 | _perloopContact.Add(curContact); |
@@ -1179,7 +1140,7 @@ if((p1 is OdePrim ) && (p2 is OdePrim)){ | |||
1179 | joint = d.JointCreateContact(world, contactgroup, ref WaterContact); | 1140 | joint = d.JointCreateContact(world, contactgroup, ref WaterContact); |
1180 | m_global_contactcount++; | 1141 | m_global_contactcount++; |
1181 | } | 1142 | } |
1182 | //m_log.Info("[PHYSICS]: Prim Water Contact" + contact.depth); | 1143 | //m_log.Info("[PHYSICS]: Prim Water Contact" + AvatarStaticprimContact.depth); |
1183 | } | 1144 | } |
1184 | else | 1145 | else |
1185 | { | 1146 | { |
@@ -1189,7 +1150,7 @@ if((p1 is OdePrim ) && (p2 is OdePrim)){ | |||
1189 | if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) | 1150 | if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) |
1190 | { | 1151 | { |
1191 | //$ Avatar on Prim or other Avatar | 1152 | //$ Avatar on Prim or other Avatar |
1192 | if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) | 1153 | if (movintYN == 1) |
1193 | { | 1154 | { |
1194 | // Use the AV Movement / prim contact | 1155 | // Use the AV Movement / prim contact |
1195 | AvatarMovementprimContact.geom = curContact; | 1156 | AvatarMovementprimContact.geom = curContact; |
@@ -1203,34 +1164,24 @@ if((p1 is OdePrim ) && (p2 is OdePrim)){ | |||
1203 | else | 1164 | else |
1204 | { | 1165 | { |
1205 | // Use the Av non movement / prim contact | 1166 | // Use the Av non movement / prim contact |
1206 | contact.geom = curContact; | 1167 | AvatarStaticprimContact.geom = curContact; |
1207 | _perloopContact.Add(curContact); | 1168 | _perloopContact.Add(curContact); |
1169 | ContactCopy = AvatarStaticprimContact; // local copy so we can change locally | ||
1208 | 1170 | ||
1209 | if (m_global_contactcount < maxContactsbeforedeath) | 1171 | if (m_global_contactcount < maxContactsbeforedeath) |
1210 | { | 1172 | { |
1211 | if (curContact.depth > 0.2) | 1173 | if (curContact.depth > 0.2) |
1212 | { // embedded, eject slowly | 1174 | { // embedded, eject slowly |
1213 | contact.surface.soft_erp = 0.1f; | 1175 | ContactCopy.surface.soft_erp = 0.1f; |
1214 | contact.surface.soft_cfm = 0.1f; | 1176 | ContactCopy.surface.soft_cfm = 0.1f; |
1215 | } | 1177 | } |
1216 | else | 1178 | else |
1217 | { // keep on the surface | 1179 | { // keep on the surface |
1218 | contact.surface.soft_erp = 0.3f; | 1180 | ContactCopy.surface.soft_erp = 0.3f; |
1219 | contact.surface.soft_cfm = 0.0f; | 1181 | ContactCopy.surface.soft_cfm = 0.0f; |
1220 | } | 1182 | } |
1221 | joint = d.JointCreateContact(world, contactgroup, ref contact); | 1183 | joint = d.JointCreateContact(world, contactgroup, ref ContactCopy); |
1222 | m_global_contactcount++; | 1184 | m_global_contactcount++; |
1223 | /* | ||
1224 | Console.WriteLine("Prim | Av collision 2 mode={0} mu={1} bounce={2} bv={3} erp={4} cfm={5} mot={6} depth={7}", | ||
1225 | contact.surface.mode, | ||
1226 | contact.surface.mu, | ||
1227 | contact.surface.bounce, | ||
1228 | contact.surface.bounce_vel, | ||
1229 | contact.surface.soft_erp, | ||
1230 | contact.surface.soft_cfm, | ||
1231 | contact.surface.motion1, | ||
1232 | curContact.depth); | ||
1233 | */ | ||
1234 | } | 1185 | } |
1235 | } | 1186 | } |
1236 | } | 1187 | } |
@@ -1241,16 +1192,11 @@ curContact.depth); | |||
1241 | 1192 | ||
1242 | if (p2 is OdePrim) material = ((OdePrim)p2).m_material; | 1193 | if (p2 is OdePrim) material = ((OdePrim)p2).m_material; |
1243 | //m_log.DebugFormat("Material: {0}", material); | 1194 | //m_log.DebugFormat("Material: {0}", material); |
1244 | |||
1245 | if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) | ||
1246 | { | ||
1247 | movintYN = 1; | ||
1248 | } | ||
1249 | 1195 | ||
1250 | m_materialContacts[material, movintYN].geom = curContact; | 1196 | m_materialContacts[material, movintYN].geom = curContact; |
1251 | _perloopContact.Add(curContact); | 1197 | _perloopContact.Add(curContact); |
1252 | 1198 | ||
1253 | if (m_global_contactcount < maxContactsbeforedeath) | 1199 | if (m_global_contactcount < maxContactsbeforedeath) |
1254 | { | 1200 | { |
1255 | joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); | 1201 | joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); |
1256 | m_global_contactcount++; | 1202 | m_global_contactcount++; |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 613d704..47492ea 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -3019,8 +3019,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3019 | // http://bugs.meta7.com/view.php?id=28 | 3019 | // http://bugs.meta7.com/view.php?id=28 |
3020 | // - Tom | 3020 | // - Tom |
3021 | 3021 | ||
3022 | LSL_Rotation newrot = llGetRot() * llRotBetween(new LSL_Vector(1.0d, 0.0d, 0.0d) * llGetRot(), new LSL_Vector(0.0d, 0.0d, -1.0d)); | 3022 | /* And the following does not do the job either. It has to be performed inside the ODE glue-code. -.- .._. |
3023 | LSL_Rotation newrot = llGetRot() * llRotBetween(new LSL_Vector(1.0d, 0.0d, 0.0d) * llGetRot(), new LSL_Vector(0.0d, 0.0d, -1.0d)); | ||
3023 | llSetRot(newrot * llRotBetween(new LSL_Vector(0.0d,0.0d,1.0d) * newrot, target - llGetPos())); | 3024 | llSetRot(newrot * llRotBetween(new LSL_Vector(0.0d,0.0d,1.0d) * newrot, target - llGetPos())); |
3025 | */ | ||
3026 | // Send the target vector to RotLookAt method inside a 'rotation', the .w -99.9 value indicates it is really a LookAt. | ||
3027 | Quaternion q = new Quaternion((float)target.x, (float)target.y, (float)target.z, -99.9f); | ||
3028 | m_host.RotLookAt(q, (float)strength, (float)damping); | ||
3024 | 3029 | ||
3025 | } | 3030 | } |
3026 | 3031 | ||