diff options
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 33 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 4 | ||||
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 3 | ||||
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 30 |
4 files changed, 63 insertions, 7 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 7704002..e9a849c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -72,6 +72,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
72 | 72 | ||
73 | private bool m_initialized = false; | 73 | private bool m_initialized = false; |
74 | 74 | ||
75 | private int m_detailedStatsStep = 0; | ||
76 | |||
75 | public IMesher mesher; | 77 | public IMesher mesher; |
76 | private float m_meshLOD; | 78 | private float m_meshLOD; |
77 | public float MeshLOD | 79 | public float MeshLOD |
@@ -192,6 +194,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
192 | m_meshLOD = 8f; | 194 | m_meshLOD = 8f; |
193 | m_sculptLOD = 32f; | 195 | m_sculptLOD = 32f; |
194 | 196 | ||
197 | m_detailedStatsStep = 0; // disabled | ||
198 | |||
195 | m_maxSubSteps = 10; | 199 | m_maxSubSteps = 10; |
196 | m_fixedTimeStep = 1f / 60f; | 200 | m_fixedTimeStep = 1f / 60f; |
197 | m_maxCollisionsPerFrame = 2048; | 201 | m_maxCollisionsPerFrame = 2048; |
@@ -209,8 +213,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
209 | parms.deactivationTime = 0.2f; | 213 | parms.deactivationTime = 0.2f; |
210 | parms.linearSleepingThreshold = 0.8f; | 214 | parms.linearSleepingThreshold = 0.8f; |
211 | parms.angularSleepingThreshold = 1.0f; | 215 | parms.angularSleepingThreshold = 1.0f; |
212 | parms.ccdMotionThreshold = 0.5f; // set to zero to disable | 216 | parms.ccdMotionThreshold = 0.0f; // set to zero to disable |
213 | parms.ccdSweptSphereRadius = 0.2f; | 217 | parms.ccdSweptSphereRadius = 0.0f; |
218 | parms.contactProcessingThreshold = 0.1f; | ||
214 | 219 | ||
215 | parms.terrainFriction = 0.5f; | 220 | parms.terrainFriction = 0.5f; |
216 | parms.terrainHitFraction = 0.8f; | 221 | parms.terrainHitFraction = 0.8f; |
@@ -231,6 +236,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
231 | _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); | 236 | _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); |
232 | _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); | 237 | _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); |
233 | 238 | ||
239 | m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep); | ||
234 | m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD); | 240 | m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD); |
235 | m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD); | 241 | m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD); |
236 | 242 | ||
@@ -253,6 +259,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
253 | parms.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", parms.angularSleepingThreshold); | 259 | parms.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", parms.angularSleepingThreshold); |
254 | parms.ccdMotionThreshold = pConfig.GetFloat("CcdMotionThreshold", parms.ccdMotionThreshold); | 260 | parms.ccdMotionThreshold = pConfig.GetFloat("CcdMotionThreshold", parms.ccdMotionThreshold); |
255 | parms.ccdSweptSphereRadius = pConfig.GetFloat("CcdSweptSphereRadius", parms.ccdSweptSphereRadius); | 261 | parms.ccdSweptSphereRadius = pConfig.GetFloat("CcdSweptSphereRadius", parms.ccdSweptSphereRadius); |
262 | parms.contactProcessingThreshold = pConfig.GetFloat("ContactProcessingThreshold", parms.contactProcessingThreshold); | ||
256 | 263 | ||
257 | parms.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction); | 264 | parms.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction); |
258 | parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction); | 265 | parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction); |
@@ -398,6 +405,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
398 | } | 405 | } |
399 | } | 406 | } |
400 | 407 | ||
408 | if (m_detailedStatsStep > 0) | ||
409 | { | ||
410 | if ((m_simulationStep % m_detailedStatsStep) == 0) | ||
411 | { | ||
412 | BulletSimAPI.DumpBulletStatistics(); | ||
413 | } | ||
414 | } | ||
415 | |||
401 | // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. | 416 | // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. |
402 | return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; | 417 | return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; |
403 | } | 418 | } |
@@ -671,6 +686,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
671 | new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"), | 686 | new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"), |
672 | new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"), | 687 | new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"), |
673 | new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"), | 688 | new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"), |
689 | new PhysParameterEntry("DetailedStats", "Frames between outputting detailed phys stats. Zero is off"), | ||
674 | 690 | ||
675 | new PhysParameterEntry("DefaultFriction", "Friction factor used on new objects"), | 691 | new PhysParameterEntry("DefaultFriction", "Friction factor used on new objects"), |
676 | new PhysParameterEntry("DefaultDensity", "Density for new objects" ), | 692 | new PhysParameterEntry("DefaultDensity", "Density for new objects" ), |
@@ -685,6 +701,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
685 | new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ), | 701 | new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ), |
686 | // new PhysParameterEntry("CcdMotionThreshold", "" ), | 702 | // new PhysParameterEntry("CcdMotionThreshold", "" ), |
687 | // new PhysParameterEntry("CcdSweptSphereRadius", "" ), | 703 | // new PhysParameterEntry("CcdSweptSphereRadius", "" ), |
704 | new PhysParameterEntry("ContactProcessingThreshold", "Distance between contacts before doing collision check" ), | ||
688 | 705 | ||
689 | new PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ), | 706 | new PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ), |
690 | new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ), | 707 | new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ), |
@@ -715,6 +732,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
715 | string lparm = parm.ToLower(); | 732 | string lparm = parm.ToLower(); |
716 | switch (lparm) | 733 | switch (lparm) |
717 | { | 734 | { |
735 | case "detailedstats": m_detailedStatsStep = (int)val; break; | ||
718 | case "meshlod": m_meshLOD = (int)val; break; | 736 | case "meshlod": m_meshLOD = (int)val; break; |
719 | case "sculptlod": m_sculptLOD = (int)val; break; | 737 | case "sculptlod": m_sculptLOD = (int)val; break; |
720 | case "maxsubstep": m_maxSubSteps = (int)val; break; | 738 | case "maxsubstep": m_maxSubSteps = (int)val; break; |
@@ -725,7 +743,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
725 | case "defaultdensity": m_params[0].defaultDensity = val; break; | 743 | case "defaultdensity": m_params[0].defaultDensity = val; break; |
726 | case "defaultrestitution": m_params[0].defaultRestitution = val; break; | 744 | case "defaultrestitution": m_params[0].defaultRestitution = val; break; |
727 | case "collisionmargin": m_params[0].collisionMargin = val; break; | 745 | case "collisionmargin": m_params[0].collisionMargin = val; break; |
728 | case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, PhysParameterEntry.APPLY_TO_NONE, val); break; | 746 | case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, PhysParameterEntry.APPLY_TO_NONE, val); break; |
729 | 747 | ||
730 | case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break; | 748 | case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break; |
731 | case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break; | 749 | case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break; |
@@ -734,6 +752,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
734 | case "angularsleepingthreshold": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break; | 752 | case "angularsleepingthreshold": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break; |
735 | case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break; | 753 | case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break; |
736 | case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break; | 754 | case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break; |
755 | case "contactprocessingthreshold": UpdateParameterPrims(ref m_params[0].contactProcessingThreshold, lparm, localID, val); break; | ||
737 | 756 | ||
738 | // set a terrain physical feature and cause terrain to be recalculated | 757 | // set a terrain physical feature and cause terrain to be recalculated |
739 | case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break; | 758 | case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break; |
@@ -741,10 +760,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
741 | case "terrainrestitution": m_params[0].terrainRestitution = val; TaintedUpdateParameter("terrain", 0, val); break; | 760 | case "terrainrestitution": m_params[0].terrainRestitution = val; TaintedUpdateParameter("terrain", 0, val); break; |
742 | // set an avatar physical feature and cause avatar(s) to be recalculated | 761 | // set an avatar physical feature and cause avatar(s) to be recalculated |
743 | case "avatarfriction": UpdateParameterAvatars(ref m_params[0].avatarFriction, "avatar", localID, val); break; | 762 | case "avatarfriction": UpdateParameterAvatars(ref m_params[0].avatarFriction, "avatar", localID, val); break; |
744 | case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break; | 763 | case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break; |
745 | case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break; | 764 | case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break; |
746 | case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break; | 765 | case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break; |
747 | case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break; | 766 | case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break; |
748 | 767 | ||
749 | default: ret = false; break; | 768 | default: ret = false; break; |
750 | } | 769 | } |
@@ -816,6 +835,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
816 | bool ret = true; | 835 | bool ret = true; |
817 | switch (parm.ToLower()) | 836 | switch (parm.ToLower()) |
818 | { | 837 | { |
838 | case "detailedstats": val = (int)m_detailedStatsStep; break; | ||
819 | case "meshlod": val = (float)m_meshLOD; break; | 839 | case "meshlod": val = (float)m_meshLOD; break; |
820 | case "sculptlod": val = (float)m_sculptLOD; break; | 840 | case "sculptlod": val = (float)m_sculptLOD; break; |
821 | case "maxsubstep": val = (float)m_maxSubSteps; break; | 841 | case "maxsubstep": val = (float)m_maxSubSteps; break; |
@@ -835,6 +855,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
835 | case "angularsleepingthreshold": val = m_params[0].angularDamping; break; | 855 | case "angularsleepingthreshold": val = m_params[0].angularDamping; break; |
836 | case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break; | 856 | case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break; |
837 | case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break; | 857 | case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break; |
858 | case "contactprocessingthreshold": val = m_params[0].contactProcessingThreshold; break; | ||
838 | 859 | ||
839 | case "terrainfriction": val = m_params[0].terrainFriction; break; | 860 | case "terrainfriction": val = m_params[0].terrainFriction; break; |
840 | case "terrainhitfraction": val = m_params[0].terrainHitFraction; break; | 861 | case "terrainhitfraction": val = m_params[0].terrainHitFraction; break; |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index a610c8d..d12bd7d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | |||
@@ -122,6 +122,7 @@ public struct ConfigurationParameters | |||
122 | public float angularSleepingThreshold; | 122 | public float angularSleepingThreshold; |
123 | public float ccdMotionThreshold; | 123 | public float ccdMotionThreshold; |
124 | public float ccdSweptSphereRadius; | 124 | public float ccdSweptSphereRadius; |
125 | public float contactProcessingThreshold; | ||
125 | 126 | ||
126 | public float terrainFriction; | 127 | public float terrainFriction; |
127 | public float terrainHitFraction; | 128 | public float terrainHitFraction; |
@@ -248,6 +249,9 @@ public static extern RaycastHit RayTest(uint worldID, uint id, Vector3 from, Vec | |||
248 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 249 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
249 | public static extern Vector3 RecoverFromPenetration(uint worldID, uint id); | 250 | public static extern Vector3 RecoverFromPenetration(uint worldID, uint id); |
250 | 251 | ||
252 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
253 | public static extern void DumpBulletStatistics(); | ||
254 | |||
251 | // Log a debug message | 255 | // Log a debug message |
252 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | 256 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] |
253 | public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); | 257 | public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); |
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index c6e8286..7c1c046 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | |||
@@ -1048,6 +1048,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1048 | CAPSULE_RADIUS = 0.01f; | 1048 | CAPSULE_RADIUS = 0.01f; |
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | // lock (OdeScene.UniversalColliderSyncObject) | ||
1051 | Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); | 1052 | Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); |
1052 | 1053 | ||
1053 | d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); | 1054 | d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); |
@@ -1179,7 +1180,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1179 | 1180 | ||
1180 | if (Shell != IntPtr.Zero) | 1181 | if (Shell != IntPtr.Zero) |
1181 | { | 1182 | { |
1183 | // lock (OdeScene.UniversalColliderSyncObject) | ||
1182 | d.GeomDestroy(Shell); | 1184 | d.GeomDestroy(Shell); |
1185 | |||
1183 | _parent_scene.geom_name_map.Remove(Shell); | 1186 | _parent_scene.geom_name_map.Remove(Shell); |
1184 | _parent_scene.actor_name_map.Remove(Shell); | 1187 | _parent_scene.actor_name_map.Remove(Shell); |
1185 | 1188 | ||
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 37daf46..4530c09 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs | |||
@@ -105,6 +105,32 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
105 | private readonly ILog m_log; | 105 | private readonly ILog m_log; |
106 | // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>(); | 106 | // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>(); |
107 | 107 | ||
108 | /// <summary> | ||
109 | /// Provide a sync object so that only one thread calls d.Collide() at a time across all OdeScene instances. | ||
110 | /// </summary> | ||
111 | /// <remarks> | ||
112 | /// With ODE as of r1755 (though also tested on r1860), only one thread can call d.Collide() at a | ||
113 | /// time, even where physics objects are in entirely different ODE worlds. This is because generating contacts | ||
114 | /// uses a static cache at the ODE level. | ||
115 | /// | ||
116 | /// Without locking, simulators running multiple regions will eventually crash with a native stack trace similar | ||
117 | /// to | ||
118 | /// | ||
119 | /// mono() [0x489171] | ||
120 | /// mono() [0x4d154f] | ||
121 | /// /lib/x86_64-linux-gnu/libpthread.so.0(+0xfc60) [0x7f6ded592c60] | ||
122 | /// .../opensim/bin/libode-x86_64.so(_ZN6Opcode11OBBCollider8_CollideEPKNS_14AABBNoLeafNodeE+0xd7a) [0x7f6dd822628a] | ||
123 | /// | ||
124 | /// ODE provides an experimental option to cache in thread local storage but compiling ODE with this option | ||
125 | /// causes OpenSimulator to immediately crash with a native stack trace similar to | ||
126 | /// | ||
127 | /// mono() [0x489171] | ||
128 | /// mono() [0x4d154f] | ||
129 | /// /lib/x86_64-linux-gnu/libpthread.so.0(+0xfc60) [0x7f03c9849c60] | ||
130 | /// .../opensim/bin/libode-x86_64.so(_Z12dCollideCCTLP6dxGeomS0_iP12dContactGeomi+0x92) [0x7f03b44bcf82] | ||
131 | /// </remarks> | ||
132 | internal static Object UniversalColliderSyncObject = new Object(); | ||
133 | |||
108 | private Random fluidRandomizer = new Random(Environment.TickCount); | 134 | private Random fluidRandomizer = new Random(Environment.TickCount); |
109 | 135 | ||
110 | private const uint m_regionWidth = Constants.RegionSize; | 136 | private const uint m_regionWidth = Constants.RegionSize; |
@@ -799,7 +825,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
799 | if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) | 825 | if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) |
800 | return; | 826 | return; |
801 | 827 | ||
802 | count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); | 828 | lock (OdeScene.UniversalColliderSyncObject) |
829 | count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); | ||
830 | |||
803 | if (count > contacts.Length) | 831 | if (count > contacts.Length) |
804 | m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); | 832 | m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); |
805 | } | 833 | } |