aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSScene.cs')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs137
1 files changed, 106 insertions, 31 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 417cb5f..8773485 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -29,12 +29,14 @@ using System.Collections.Generic;
29using System.Runtime.InteropServices; 29using System.Runtime.InteropServices;
30using System.Text; 30using System.Text;
31using System.Threading; 31using System.Threading;
32using Nini.Config;
33using log4net;
34using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Framework;
34using OpenSim.Region.CoreModules;
35using Logging = OpenSim.Region.CoreModules.Framework.Statistics.Logging;
35using OpenSim.Region.Physics.Manager; 36using OpenSim.Region.Physics.Manager;
37using Nini.Config;
38using log4net;
36using OpenMetaverse; 39using OpenMetaverse;
37using OpenSim.Region.Framework;
38 40
39// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
40// Debug linkset 42// Debug linkset
@@ -44,15 +46,17 @@ using OpenSim.Region.Framework;
44// Compute physics FPS reasonably 46// Compute physics FPS reasonably
45// Based on material, set density and friction 47// Based on material, set density and friction
46// More efficient memory usage when passing hull information from BSPrim to BulletSim 48// More efficient memory usage when passing hull information from BSPrim to BulletSim
49// Move all logic out of the C++ code and into the C# code for easier future modifications.
47// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? 50// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
48// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) 51// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground)
49// At the moment, physical and phantom causes object to drop through the terrain 52// At the moment, physical and phantom causes object to drop through the terrain
50// Physical phantom objects and related typing (collision options ) 53// Physical phantom objects and related typing (collision options )
54// Use collision masks for collision with terrain and phantom objects
51// Check out llVolumeDetect. Must do something for that. 55// Check out llVolumeDetect. Must do something for that.
52// Should prim.link() and prim.delink() membership checking happen at taint time? 56// Should prim.link() and prim.delink() membership checking happen at taint time?
57// changing the position and orientation of a linked prim must rebuild the constraint with the root.
53// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once 58// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
54// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 59// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
55// Use collision masks for collision with terrain and phantom objects
56// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) 60// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
57// Implement LockAngularMotion 61// Implement LockAngularMotion
58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 62// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
@@ -60,9 +64,6 @@ using OpenSim.Region.Framework;
60// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. 64// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
61// Add PID movement operations. What does ScenePresence.MoveToTarget do? 65// Add PID movement operations. What does ScenePresence.MoveToTarget do?
62// Check terrain size. 128 or 127? 66// Check terrain size. 128 or 127?
63// Multiple contact points on collision?
64// See code in ode::near... calls to collision_accounting_events()
65// (This might not be a problem. ODE collects all the collisions with one object in one tick.)
66// Raycast 67// Raycast
67// 68//
68namespace OpenSim.Region.Physics.BulletSPlugin 69namespace OpenSim.Region.Physics.BulletSPlugin
@@ -72,6 +73,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
72 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
73 private static readonly string LogHeader = "[BULLETS SCENE]"; 74 private static readonly string LogHeader = "[BULLETS SCENE]";
74 75
76 private void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); }
77
75 public string BulletSimVersion = "?"; 78 public string BulletSimVersion = "?";
76 79
77 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); 80 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>();
@@ -105,6 +108,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
105 private long m_simulationStep = 0; 108 private long m_simulationStep = 0;
106 public long SimulationStep { get { return m_simulationStep; } } 109 public long SimulationStep { get { return m_simulationStep; } }
107 110
111 public float LastSimulatedTimestep { get; private set; }
112
108 // A value of the time now so all the collision and update routines do not have to get their own 113 // A value of the time now so all the collision and update routines do not have to get their own
109 // Set to 'now' just before all the prims and actors are called for collisions and updates 114 // Set to 'now' just before all the prims and actors are called for collisions and updates
110 private int m_simulationNowTime; 115 private int m_simulationNowTime;
@@ -121,6 +126,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
121 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed 126 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed
122 private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes 127 private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes
123 128
129 public float PID_D { get; private set; } // derivative
130 public float PID_P { get; private set; } // proportional
131
124 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 132 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
125 public const uint GROUNDPLANE_ID = 1; 133 public const uint GROUNDPLANE_ID = 1;
126 134
@@ -147,8 +155,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters
147 ConfigurationParameters[] m_params; 155 ConfigurationParameters[] m_params;
148 GCHandle m_paramsHandle; 156 GCHandle m_paramsHandle;
149 157
158 public bool shouldDebugLog { get; private set; }
159
150 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; 160 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
151 161
162 // Sometimes you just have to log everything.
163 public Logging.LogWriter PhysicsLogging;
164 private bool m_physicsLoggingEnabled;
165 private string m_physicsLoggingDir;
166 private string m_physicsLoggingPrefix;
167 private int m_physicsLoggingFileMinutes;
168
169 private bool m_vehicleLoggingEnabled;
170 public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
171
152 public BSScene(string identifier) 172 public BSScene(string identifier)
153 { 173 {
154 m_initialized = false; 174 m_initialized = false;
@@ -169,17 +189,32 @@ public class BSScene : PhysicsScene, IPhysicsParameters
169 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; 189 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
170 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); 190 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
171 191
192 // Enable very detailed logging.
193 // By creating an empty logger when not logging, the log message invocation code
194 // can be left in and every call doesn't have to check for null.
195 if (m_physicsLoggingEnabled)
196 {
197 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes);
198 }
199 else
200 {
201 PhysicsLogging = new Logging.LogWriter();
202 }
203
172 // Get the version of the DLL 204 // Get the version of the DLL
173 // TODO: this doesn't work yet. Something wrong with marshaling the returned string. 205 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
174 // BulletSimVersion = BulletSimAPI.GetVersion(); 206 // BulletSimVersion = BulletSimAPI.GetVersion();
175 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); 207 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
176 208
177 // if Debug, enable logging from the unmanaged code 209 // if Debug, enable logging from the unmanaged code
178 if (m_log.IsDebugEnabled) 210 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
179 { 211 {
180 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); 212 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
181 // the handle is saved to it doesn't get freed after this call 213 if (PhysicsLogging.Enabled)
182 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); 214 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
215 else
216 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
217 // the handle is saved in a variable to make sure it doesn't get freed after this call
183 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); 218 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
184 } 219 }
185 220
@@ -209,6 +244,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
209 m_meshLOD = 8f; 244 m_meshLOD = 8f;
210 m_sculptLOD = 32f; 245 m_sculptLOD = 32f;
211 246
247 shouldDebugLog = false;
212 m_detailedStatsStep = 0; // disabled 248 m_detailedStatsStep = 0; // disabled
213 249
214 m_maxSubSteps = 10; 250 m_maxSubSteps = 10;
@@ -217,6 +253,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
217 m_maxUpdatesPerFrame = 2048; 253 m_maxUpdatesPerFrame = 2048;
218 m_maximumObjectMass = 10000.01f; 254 m_maximumObjectMass = 10000.01f;
219 255
256 PID_D = 2200f;
257 PID_P = 900f;
258
220 parms.defaultFriction = 0.5f; 259 parms.defaultFriction = 0.5f;
221 parms.defaultDensity = 10.000006836f; // Aluminum g/cm3 260 parms.defaultDensity = 10.000006836f; // Aluminum g/cm3
222 parms.defaultRestitution = 0f; 261 parms.defaultRestitution = 0f;
@@ -261,7 +300,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
261 _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); 300 _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim);
262 _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); 301 _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing);
263 302
303 shouldDebugLog = pConfig.GetBoolean("ShouldDebugLog", shouldDebugLog);
264 m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep); 304 m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep);
305
265 m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD); 306 m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD);
266 m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD); 307 m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD);
267 308
@@ -271,6 +312,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
271 m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame); 312 m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame);
272 m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass); 313 m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass);
273 314
315 PID_D = pConfig.GetFloat("PIDDerivative", PID_D);
316 PID_P = pConfig.GetFloat("PIDProportional", PID_P);
317
274 parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction); 318 parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction);
275 parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity); 319 parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity);
276 parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution); 320 parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution);
@@ -303,6 +347,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters
303 parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands); 347 parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands);
304 parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching); 348 parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching);
305 parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations); 349 parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations);
350
351 // Very detailed logging for physics debugging
352 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
353 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
354 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-");
355 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
356 // Very detailed logging for vehicle debugging
357 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
306 } 358 }
307 } 359 }
308 m_params[0] = parms; 360 m_params[0] = parms;
@@ -323,12 +375,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
323 return ret; 375 return ret;
324 } 376 }
325 377
326
327 // Called directly from unmanaged code so don't do much 378 // Called directly from unmanaged code so don't do much
328 private void BulletLogger(string msg) 379 private void BulletLogger(string msg)
329 { 380 {
330 m_log.Debug("[BULLETS UNMANAGED]:" + msg); 381 m_log.Debug("[BULLETS UNMANAGED]:" + msg);
331 } 382 }
383
384 // Called directly from unmanaged code so don't do much
385 private void BulletLoggerPhysLog(string msg)
386 {
387 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
388 }
332 389
333 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) 390 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
334 { 391 {
@@ -347,34 +404,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters
347 public override void RemoveAvatar(PhysicsActor actor) 404 public override void RemoveAvatar(PhysicsActor actor)
348 { 405 {
349 // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader); 406 // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader);
350 if (actor is BSCharacter) 407 BSCharacter bsactor = actor as BSCharacter;
351 { 408 if (bsactor != null)
352 ((BSCharacter)actor).Destroy();
353 }
354 try
355 { 409 {
356 lock (m_avatars) m_avatars.Remove(actor.LocalID); 410 try
357 } 411 {
358 catch (Exception e) 412 lock (m_avatars) m_avatars.Remove(actor.LocalID);
359 { 413 }
360 m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e); 414 catch (Exception e)
415 {
416 m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e);
417 }
418 bsactor.Destroy();
419 // bsactor.dispose();
361 } 420 }
362 } 421 }
363 422
364 public override void RemovePrim(PhysicsActor prim) 423 public override void RemovePrim(PhysicsActor prim)
365 { 424 {
366 // m_log.DebugFormat("{0}: RemovePrim", LogHeader); 425 BSPrim bsprim = prim as BSPrim;
367 if (prim is BSPrim) 426 if (bsprim != null)
368 {
369 ((BSPrim)prim).Destroy();
370 }
371 try
372 { 427 {
373 lock (m_prims) m_prims.Remove(prim.LocalID); 428 m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
429 try
430 {
431 lock (m_prims) m_prims.Remove(bsprim.LocalID);
432 }
433 catch (Exception e)
434 {
435 m_log.ErrorFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e);
436 }
437 bsprim.Destroy();
438 // bsprim.dispose();
374 } 439 }
375 catch (Exception e) 440 else
376 { 441 {
377 m_log.WarnFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e); 442 m_log.ErrorFormat("{0}: Attempt to remove prim that is not a BSPrim type.", LogHeader);
378 } 443 }
379 } 444 }
380 445
@@ -400,6 +465,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
400 int collidersCount; 465 int collidersCount;
401 IntPtr collidersPtr; 466 IntPtr collidersPtr;
402 467
468 LastSimulatedTimestep = timeStep;
469
403 // prevent simulation until we've been initialized 470 // prevent simulation until we've been initialized
404 if (!m_initialized) return 10.0f; 471 if (!m_initialized) return 10.0f;
405 472
@@ -459,7 +526,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
459 for (int ii = 0; ii < updatedEntityCount; ii++) 526 for (int ii = 0; ii < updatedEntityCount; ii++)
460 { 527 {
461 EntityProperties entprop = m_updateArray[ii]; 528 EntityProperties entprop = m_updateArray[ii];
462 // m_log.DebugFormat("{0}: entprop[{1}]: id={2}, pos={3}", LogHeader, ii, entprop.ID, entprop.Position);
463 BSPrim prim; 529 BSPrim prim;
464 if (m_prims.TryGetValue(entprop.ID, out prim)) 530 if (m_prims.TryGetValue(entprop.ID, out prim))
465 { 531 {
@@ -532,8 +598,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
532 }); 598 });
533 } 599 }
534 600
601 // Someday we will have complex terrain with caves and tunnels
602 // For the moment, it's flat and convex
603 public float GetTerrainHeightAtXYZ(Vector3 loc)
604 {
605 return GetTerrainHeightAtXY(loc.X, loc.Y);
606 }
607
535 public float GetTerrainHeightAtXY(float tX, float tY) 608 public float GetTerrainHeightAtXY(float tX, float tY)
536 { 609 {
610 if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize)
611 return 30;
537 return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)]; 612 return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)];
538 } 613 }
539 614