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.cs371
1 files changed, 193 insertions, 178 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 56924aa..4a468af 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -39,8 +39,6 @@ using log4net;
39using OpenMetaverse; 39using OpenMetaverse;
40 40
41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
42// Debug linkset
43// Test with multiple regions in one simulator
44// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight) 42// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight)
45// Test sculpties 43// Test sculpties
46// Compute physics FPS reasonably 44// Compute physics FPS reasonably
@@ -54,10 +52,8 @@ using OpenMetaverse;
54// Use collision masks for collision with terrain and phantom objects 52// Use collision masks for collision with terrain and phantom objects
55// Check out llVolumeDetect. Must do something for that. 53// Check out llVolumeDetect. Must do something for that.
56// Should prim.link() and prim.delink() membership checking happen at taint time? 54// 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.
58// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once 55// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
59// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 56// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
60// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
61// Implement LockAngularMotion 57// Implement LockAngularMotion
62// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
63// Does NeedsMeshing() really need to exclude all the different shapes? 59// Does NeedsMeshing() really need to exclude all the different shapes?
@@ -78,27 +74,22 @@ public class BSScene : PhysicsScene, IPhysicsParameters
78 74
79 public string BulletSimVersion = "?"; 75 public string BulletSimVersion = "?";
80 76
81 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); 77 public Dictionary<uint, BSPhysObject> PhysObjects = new Dictionary<uint, BSPhysObject>();
82 public Dictionary<uint, BSCharacter> Characters { get { return m_avatars; } }
83
84 private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>();
85 public Dictionary<uint, BSPrim> Prims { get { return m_prims; } }
86 78
79 private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>();
80 // Following is a kludge and can be removed when avatar animation updating is
81 // moved to a better place.
87 private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>(); 82 private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
88 private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>();
89
90 private List<BSPrim> m_vehicles = new List<BSPrim>();
91 83
92 private float[] m_heightMap; 84 // List of all the objects that have vehicle properties and should be called
93 private float m_waterLevel; 85 // to update each physics step.
94 private uint m_worldID; 86 private List<BSPhysObject> m_vehicles = new List<BSPhysObject>();
95 public uint WorldID { get { return m_worldID; } }
96 87
97 // let my minuions use my logger 88 // let my minuions use my logger
98 public ILog Logger { get { return m_log; } } 89 public ILog Logger { get { return m_log; } }
99 90
100 private bool m_initialized = false; 91 // If non-zero, the number of simulation steps between calls to the physics
101 92 // engine to output detailed physics stats. Debug logging level must be on also.
102 private int m_detailedStatsStep = 0; 93 private int m_detailedStatsStep = 0;
103 94
104 public IMesher mesher; 95 public IMesher mesher;
@@ -108,29 +99,31 @@ public class BSScene : PhysicsScene, IPhysicsParameters
108 public float MeshMegaPrimThreshold { get; private set; } 99 public float MeshMegaPrimThreshold { get; private set; }
109 public float SculptLOD { get; private set; } 100 public float SculptLOD { get; private set; }
110 101
111 private BulletSim m_worldSim; 102 public uint WorldID { get; private set; }
112 public BulletSim World 103 public BulletSim World { get; private set; }
113 {
114 get { return m_worldSim; }
115 }
116 private BSConstraintCollection m_constraintCollection;
117 public BSConstraintCollection Constraints
118 {
119 get { return m_constraintCollection; }
120 }
121 104
105 // All the constraints that have been allocated in this instance.
106 public BSConstraintCollection Constraints { get; private set; }
107
108 // Simulation parameters
122 private int m_maxSubSteps; 109 private int m_maxSubSteps;
123 private float m_fixedTimeStep; 110 private float m_fixedTimeStep;
124 private long m_simulationStep = 0; 111 private long m_simulationStep = 0;
125 public long SimulationStep { get { return m_simulationStep; } } 112 public long SimulationStep { get { return m_simulationStep; } }
126 113
114 // The length of the last timestep we were asked to simulate.
115 // This is used by the vehicle code. Since the vehicle code is called
116 // once per simulation step, its constants need to be scaled by this.
127 public float LastSimulatedTimestep { get; private set; } 117 public float LastSimulatedTimestep { get; private set; }
128 118
129 // A value of the time now so all the collision and update routines do not have to get their own 119 // A value of the time now so all the collision and update routines do not have to get their own
130 // Set to 'now' just before all the prims and actors are called for collisions and updates 120 // Set to 'now' just before all the prims and actors are called for collisions and updates
131 private int m_simulationNowTime; 121 public int SimulationNowTime { get; private set; }
132 public int SimulationNowTime { get { return m_simulationNowTime; } } 122
123 // True if initialized and ready to do simulation steps
124 private bool m_initialized = false;
133 125
126 // Pinned memory used to pass step information between managed and unmanaged
134 private int m_maxCollisionsPerFrame; 127 private int m_maxCollisionsPerFrame;
135 private CollisionDesc[] m_collisionArray; 128 private CollisionDesc[] m_collisionArray;
136 private GCHandle m_collisionArrayPinnedHandle; 129 private GCHandle m_collisionArrayPinnedHandle;
@@ -147,6 +140,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
147 140
148 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 141 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
149 public const uint GROUNDPLANE_ID = 1; 142 public const uint GROUNDPLANE_ID = 1;
143 public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
144
145 private float m_waterLevel;
146 public BSTerrainManager TerrainManager { get; private set; }
150 147
151 public ConfigurationParameters Params 148 public ConfigurationParameters Params
152 { 149 {
@@ -157,12 +154,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
157 get { return new Vector3(0f, 0f, Params.gravity); } 154 get { return new Vector3(0f, 0f, Params.gravity); }
158 } 155 }
159 156
160 private float m_maximumObjectMass; 157 public float MaximumObjectMass { get; private set; }
161 public float MaximumObjectMass
162 {
163 get { return m_maximumObjectMass; }
164 }
165 158
159 // When functions in the unmanaged code must be called, it is only
160 // done at a known time just before the simulation step. The taint
161 // system saves all these function calls and executes them in
162 // order before the simulation.
166 public delegate void TaintCallback(); 163 public delegate void TaintCallback();
167 private struct TaintCallbackEntry 164 private struct TaintCallbackEntry
168 { 165 {
@@ -178,6 +175,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
178 private Object _taintLock = new Object(); 175 private Object _taintLock = new Object();
179 176
180 // A pointer to an instance if this structure is passed to the C++ code 177 // A pointer to an instance if this structure is passed to the C++ code
178 // Used to pass basic configuration values to the unmanaged code.
181 ConfigurationParameters[] m_params; 179 ConfigurationParameters[] m_params;
182 GCHandle m_paramsHandle; 180 GCHandle m_paramsHandle;
183 181
@@ -192,10 +190,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
192 private string m_physicsLoggingDir; 190 private string m_physicsLoggingDir;
193 private string m_physicsLoggingPrefix; 191 private string m_physicsLoggingPrefix;
194 private int m_physicsLoggingFileMinutes; 192 private int m_physicsLoggingFileMinutes;
193 // 'true' of the vehicle code is to log lots of details
194 public bool VehicleLoggingEnabled { get; private set; }
195 195
196 private bool m_vehicleLoggingEnabled; 196 #region Construction and Initialization
197 public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
198
199 public BSScene(string identifier) 197 public BSScene(string identifier)
200 { 198 {
201 m_initialized = false; 199 m_initialized = false;
@@ -218,6 +216,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
218 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; 216 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
219 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); 217 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
220 218
219 mesher = meshmerizer;
220 _taintedObjects = new List<TaintCallbackEntry>();
221
221 // Enable very detailed logging. 222 // Enable very detailed logging.
222 // By creating an empty logger when not logging, the log message invocation code 223 // By creating an empty logger when not logging, the log message invocation code
223 // can be left in and every call doesn't have to check for null. 224 // can be left in and every call doesn't have to check for null.
@@ -230,38 +231,43 @@ public class BSScene : PhysicsScene, IPhysicsParameters
230 PhysicsLogging = new Logging.LogWriter(); 231 PhysicsLogging = new Logging.LogWriter();
231 } 232 }
232 233
233 // Get the version of the DLL 234 // If Debug logging level, enable logging from the unmanaged code
234 // TODO: this doesn't work yet. Something wrong with marshaling the returned string. 235 m_DebugLogCallbackHandle = null;
235 // BulletSimVersion = BulletSimAPI.GetVersion();
236 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
237
238 // if Debug, enable logging from the unmanaged code
239 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) 236 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
240 { 237 {
241 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); 238 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
242 if (PhysicsLogging.Enabled) 239 if (PhysicsLogging.Enabled)
240 // The handle is saved in a variable to make sure it doesn't get freed after this call
243 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); 241 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
244 else 242 else
245 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); 243 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
246 // the handle is saved in a variable to make sure it doesn't get freed after this call
247 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
248 } 244 }
249 245
250 _taintedObjects = new List<TaintCallbackEntry>(); 246 // Get the version of the DLL
247 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
248 // BulletSimVersion = BulletSimAPI.GetVersion();
249 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
251 250
252 mesher = meshmerizer; 251 // The bounding box for the simulated world. The origin is 0,0,0 unless we're
253 // The bounding box for the simulated world 252 // a child in a mega-region.
253 // Turns out that Bullet really doesn't care about the extents of the simulated
254 // area. It tracks active objects no matter where they are.
254 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); 255 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f);
255 256
256 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); 257 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
257 m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), 258 WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
258 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), 259 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
259 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); 260 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
261 m_DebugLogCallbackHandle);
260 262
261 // Initialization to support the transition to a new API which puts most of the logic 263 // Initialization to support the transition to a new API which puts most of the logic
262 // into the C# code so it is easier to modify and add to. 264 // into the C# code so it is easier to modify and add to.
263 m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID)); 265 World = new BulletSim(WorldID, this, BulletSimAPI.GetSimHandle2(WorldID));
264 m_constraintCollection = new BSConstraintCollection(World); 266
267 Constraints = new BSConstraintCollection(World);
268
269 TerrainManager = new BSTerrainManager(this);
270 TerrainManager.CreateInitialGroundPlaneAndTerrain();
265 271
266 m_initialized = true; 272 m_initialized = true;
267 } 273 }
@@ -289,7 +295,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
289 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-"); 295 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
290 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); 296 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
291 // Very detailed logging for vehicle debugging 297 // Very detailed logging for vehicle debugging
292 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); 298 VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
293 299
294 // Do any replacements in the parameters 300 // Do any replacements in the parameters
295 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); 301 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
@@ -324,6 +330,38 @@ public class BSScene : PhysicsScene, IPhysicsParameters
324 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); 330 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
325 } 331 }
326 332
333 public override void Dispose()
334 {
335 // m_log.DebugFormat("{0}: Dispose()", LogHeader);
336
337 // make sure no stepping happens while we're deleting stuff
338 m_initialized = false;
339
340 TerrainManager.ReleaseGroundPlaneAndTerrain();
341
342 foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
343 {
344 kvp.Value.Destroy();
345 }
346 PhysObjects.Clear();
347
348 // Now that the prims are all cleaned up, there should be no constraints left
349 if (Constraints != null)
350 {
351 Constraints.Dispose();
352 Constraints = null;
353 }
354
355 // Anything left in the unmanaged code should be cleaned out
356 BulletSimAPI.Shutdown(WorldID);
357
358 // Not logging any more
359 PhysicsLogging.Close();
360 }
361 #endregion // Construction and Initialization
362
363 #region Prim and Avatar addition and removal
364
327 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) 365 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
328 { 366 {
329 m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader); 367 m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader);
@@ -337,7 +375,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
337 if (!m_initialized) return null; 375 if (!m_initialized) return null;
338 376
339 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); 377 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
340 lock (m_avatars) m_avatars.Add(localID, actor); 378 lock (PhysObjects) PhysObjects.Add(localID, actor);
379
380 // TODO: Remove kludge someday.
381 // We must generate a collision for avatars whether they collide or not.
382 // This is required by OpenSim to update avatar animations, etc.
383 lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Add(actor);
384
341 return actor; 385 return actor;
342 } 386 }
343 387
@@ -352,7 +396,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
352 { 396 {
353 try 397 try
354 { 398 {
355 lock (m_avatars) m_avatars.Remove(actor.LocalID); 399 lock (PhysObjects) PhysObjects.Remove(actor.LocalID);
400 // Remove kludge someday
401 lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Remove(bsactor);
356 } 402 }
357 catch (Exception e) 403 catch (Exception e)
358 { 404 {
@@ -374,7 +420,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
374 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); 420 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
375 try 421 try
376 { 422 {
377 lock (m_prims) m_prims.Remove(bsprim.LocalID); 423 lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID);
378 } 424 }
379 catch (Exception e) 425 catch (Exception e)
380 { 426 {
@@ -399,7 +445,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
399 DetailLog("{0},AddPrimShape,call", localID); 445 DetailLog("{0},AddPrimShape,call", localID);
400 446
401 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); 447 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
402 lock (m_prims) m_prims.Add(localID, prim); 448 lock (PhysObjects) PhysObjects.Add(localID, prim);
403 return prim; 449 return prim;
404 } 450 }
405 451
@@ -408,6 +454,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
408 // information call is not needed. 454 // information call is not needed.
409 public override void AddPhysicsActorTaint(PhysicsActor prim) { } 455 public override void AddPhysicsActorTaint(PhysicsActor prim) { }
410 456
457 #endregion // Prim and Avatar addition and removal
458
459 #region Simulation
411 // Simulate one timestep 460 // Simulate one timestep
412 public override float Simulate(float timeStep) 461 public override float Simulate(float timeStep)
413 { 462 {
@@ -424,6 +473,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
424 int simulateStartTime = Util.EnvironmentTickCount(); 473 int simulateStartTime = Util.EnvironmentTickCount();
425 474
426 // update the prim states while we know the physics engine is not busy 475 // update the prim states while we know the physics engine is not busy
476 int numTaints = _taintedObjects.Count;
427 ProcessTaints(); 477 ProcessTaints();
428 478
429 // Some of the prims operate with special vehicle properties 479 // Some of the prims operate with special vehicle properties
@@ -435,14 +485,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
435 int numSubSteps = 0; 485 int numSubSteps = 0;
436 try 486 try
437 { 487 {
438 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, 488 numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
439 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 489 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
440 DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); 490 DetailLog("{0},Simulate,call, nTaints= {1}, substeps={2}, updates={3}, colliders={4}",
491 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
441 } 492 }
442 catch (Exception e) 493 catch (Exception e)
443 { 494 {
444 m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); 495 m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}",
445 // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); 496 LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e);
497 DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}",
498 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
446 updatedEntityCount = 0; 499 updatedEntityCount = 0;
447 collidersCount = 0; 500 collidersCount = 0;
448 } 501 }
@@ -451,7 +504,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
451 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in 504 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in
452 505
453 // Get a value for 'now' so all the collision and update routines don't have to get their own 506 // Get a value for 'now' so all the collision and update routines don't have to get their own
454 m_simulationNowTime = Util.EnvironmentTickCount(); 507 SimulationNowTime = Util.EnvironmentTickCount();
455 508
456 // If there were collisions, process them by sending the event to the prim. 509 // If there were collisions, process them by sending the event to the prim.
457 // Collisions must be processed before updates. 510 // Collisions must be processed before updates.
@@ -470,19 +523,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters
470 523
471 // The above SendCollision's batch up the collisions on the objects. 524 // The above SendCollision's batch up the collisions on the objects.
472 // Now push the collisions into the simulator. 525 // Now push the collisions into the simulator.
473 foreach (BSPrim bsp in m_primsWithCollisions) 526 foreach (BSPhysObject bsp in m_objectsWithCollisions)
474 bsp.SendCollisions(); 527 bsp.SendCollisions();
475 m_primsWithCollisions.Clear(); 528 m_objectsWithCollisions.Clear();
476 529
477 // This is a kludge to get avatar movement updated. 530 // This is a kludge to get avatar movement updated.
478 // Don't send collisions only if there were collisions -- send everytime.
479 // ODE sends collisions even if there are none and this is used to update 531 // ODE sends collisions even if there are none and this is used to update
480 // avatar animations and stuff. 532 // avatar animations and stuff.
481 // foreach (BSCharacter bsc in m_avatarsWithCollisions) 533 foreach (BSPhysObject bpo in m_avatarsWithCollisions)
482 // bsc.SendCollisions(); 534 bpo.SendCollisions();
483 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 535 // m_avatarsWithCollisions.Clear();
484 kvp.Value.SendCollisions();
485 m_avatarsWithCollisions.Clear();
486 536
487 // If any of the objects had updated properties, tell the object it has been changed by the physics engine 537 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
488 if (updatedEntityCount > 0) 538 if (updatedEntityCount > 0)
@@ -490,16 +540,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
490 for (int ii = 0; ii < updatedEntityCount; ii++) 540 for (int ii = 0; ii < updatedEntityCount; ii++)
491 { 541 {
492 EntityProperties entprop = m_updateArray[ii]; 542 EntityProperties entprop = m_updateArray[ii];
493 BSPrim prim; 543 BSPhysObject pobj;
494 if (m_prims.TryGetValue(entprop.ID, out prim)) 544 if (PhysObjects.TryGetValue(entprop.ID, out pobj))
495 {
496 prim.UpdateProperties(entprop);
497 continue;
498 }
499 BSCharacter actor;
500 if (m_avatars.TryGetValue(entprop.ID, out actor))
501 { 545 {
502 actor.UpdateProperties(entprop); 546 pobj.UpdateProperties(entprop);
503 continue; 547 continue;
504 } 548 }
505 } 549 }
@@ -529,58 +573,47 @@ public class BSScene : PhysicsScene, IPhysicsParameters
529 } 573 }
530 574
531 // Something has collided 575 // Something has collided
532 private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration) 576 private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration)
533 { 577 {
534 if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID) 578 if (localID <= TerrainManager.HighestTerrainID)
535 { 579 {
536 return; // don't send collisions to the terrain 580 return; // don't send collisions to the terrain
537 } 581 }
538 582
583 BSPhysObject collider = PhysObjects[localID];
584 // TODO: as of this code, terrain was not in the physical object list.
585 // When BSTerrain is created and it will be in the list, we can remove
586 // the possibility that it's not there and just fetch the collidee.
587 BSPhysObject collidee = null;
588
539 ActorTypes type = ActorTypes.Prim; 589 ActorTypes type = ActorTypes.Prim;
540 if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID) 590 if (collidingWith <= TerrainManager.HighestTerrainID)
591 {
541 type = ActorTypes.Ground; 592 type = ActorTypes.Ground;
542 else if (m_avatars.ContainsKey(collidingWith)) 593 }
543 type = ActorTypes.Agent; 594 else
595 {
596 collidee = PhysObjects[collidingWith];
597 if (collidee is BSCharacter)
598 type = ActorTypes.Agent;
599 }
544 600
545 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); 601 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
546 602
547 BSPrim prim; 603 collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration);
548 if (m_prims.TryGetValue(localID, out prim)) { 604 m_objectsWithCollisions.Add(collider);
549 prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration); 605
550 m_primsWithCollisions.Add(prim);
551 return;
552 }
553 BSCharacter actor;
554 if (m_avatars.TryGetValue(localID, out actor)) {
555 actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
556 m_avatarsWithCollisions.Add(actor);
557 return;
558 }
559 return; 606 return;
560 } 607 }
561 608
562 public override void GetResults() { } 609 #endregion // Simulation
563 610
564 public override void SetTerrain(float[] heightMap) { 611 public override void GetResults() { }
565 m_heightMap = heightMap;
566 this.TaintedObject("BSScene.SetTerrain", delegate()
567 {
568 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
569 });
570 }
571 612
572 // Someday we will have complex terrain with caves and tunnels 613 #region Terrain
573 // For the moment, it's flat and convex
574 public float GetTerrainHeightAtXYZ(Vector3 loc)
575 {
576 return GetTerrainHeightAtXY(loc.X, loc.Y);
577 }
578 614
579 public float GetTerrainHeightAtXY(float tX, float tY) 615 public override void SetTerrain(float[] heightMap) {
580 { 616 TerrainManager.SetTerrain(heightMap);
581 if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize)
582 return 30;
583 return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)];
584 } 617 }
585 618
586 public override void SetWaterLevel(float baseheight) 619 public override void SetWaterLevel(float baseheight)
@@ -598,39 +631,27 @@ public class BSScene : PhysicsScene, IPhysicsParameters
598 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); 631 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
599 } 632 }
600 633
601 public override void Dispose() 634 // Although no one seems to check this, I do support combining.
635 public override bool SupportsCombining()
602 { 636 {
603 // m_log.DebugFormat("{0}: Dispose()", LogHeader); 637 return TerrainManager.SupportsCombining();
604 638 }
605 // make sure no stepping happens while we're deleting stuff 639 // This call says I am a child to region zero in a mega-region. 'pScene' is that
606 m_initialized = false; 640 // of region zero, 'offset' is my offset from regions zero's origin, and
607 641 // 'extents' is the largest XY that is handled in my region.
608 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 642 public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
609 { 643 {
610 kvp.Value.Destroy(); 644 TerrainManager.Combine(pScene, offset, extents);
611 } 645 }
612 m_avatars.Clear();
613
614 foreach (KeyValuePair<uint, BSPrim> kvp in m_prims)
615 {
616 kvp.Value.Destroy();
617 }
618 m_prims.Clear();
619
620 // Now that the prims are all cleaned up, there should be no constraints left
621 if (m_constraintCollection != null)
622 {
623 m_constraintCollection.Dispose();
624 m_constraintCollection = null;
625 }
626
627 // Anything left in the unmanaged code should be cleaned out
628 BulletSimAPI.Shutdown(WorldID);
629 646
630 // Not logging any more 647 // Unhook all the combining that I know about.
631 PhysicsLogging.Close(); 648 public override void UnCombine(PhysicsScene pScene)
649 {
650 TerrainManager.UnCombine(pScene);
632 } 651 }
633 652
653 #endregion // Terrain
654
634 public override Dictionary<uint, float> GetTopColliders() 655 public override Dictionary<uint, float> GetTopColliders()
635 { 656 {
636 return new Dictionary<uint, float>(); 657 return new Dictionary<uint, float>();
@@ -840,14 +861,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters
840 // no locking because only called when physics engine is not busy 861 // no locking because only called when physics engine is not busy
841 private void ProcessVehicles(float timeStep) 862 private void ProcessVehicles(float timeStep)
842 { 863 {
843 foreach (BSPrim prim in m_vehicles) 864 foreach (BSPhysObject pobj in m_vehicles)
844 { 865 {
845 prim.StepVehicle(timeStep); 866 pobj.StepVehicle(timeStep);
846 } 867 }
847 } 868 }
848 #endregion Vehicles 869 #endregion Vehicles
849 870
850 #region Parameters 871 #region INI and command line parameter processing
851 872
852 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); 873 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
853 delegate float ParamGet(BSScene scene); 874 delegate float ParamGet(BSScene scene);
@@ -950,9 +971,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
950 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), 971 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
951 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", 972 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
952 10000.01f, 973 10000.01f,
953 (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); }, 974 (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
954 (s) => { return (float)s.m_maximumObjectMass; }, 975 (s) => { return (float)s.MaximumObjectMass; },
955 (s,p,l,v) => { s.m_maximumObjectMass = v; } ), 976 (s,p,l,v) => { s.MaximumObjectMass = v; } ),
956 977
957 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", 978 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
958 2200f, 979 2200f,
@@ -996,42 +1017,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters
996 0f, 1017 0f,
997 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, 1018 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
998 (s) => { return s.m_params[0].linearDamping; }, 1019 (s) => { return s.m_params[0].linearDamping; },
999 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ), 1020 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); } ),
1000 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 1021 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
1001 0f, 1022 0f,
1002 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, 1023 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
1003 (s) => { return s.m_params[0].angularDamping; }, 1024 (s) => { return s.m_params[0].angularDamping; },
1004 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ), 1025 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); } ),
1005 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 1026 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
1006 0.2f, 1027 0.2f,
1007 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, 1028 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
1008 (s) => { return s.m_params[0].deactivationTime; }, 1029 (s) => { return s.m_params[0].deactivationTime; },
1009 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ), 1030 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); } ),
1010 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 1031 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
1011 0.8f, 1032 0.8f,
1012 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, 1033 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
1013 (s) => { return s.m_params[0].linearSleepingThreshold; }, 1034 (s) => { return s.m_params[0].linearSleepingThreshold; },
1014 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), 1035 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
1015 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 1036 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
1016 1.0f, 1037 1.0f,
1017 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, 1038 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
1018 (s) => { return s.m_params[0].angularSleepingThreshold; }, 1039 (s) => { return s.m_params[0].angularSleepingThreshold; },
1019 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), 1040 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
1020 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 1041 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
1021 0f, // set to zero to disable 1042 0f, // set to zero to disable
1022 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, 1043 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
1023 (s) => { return s.m_params[0].ccdMotionThreshold; }, 1044 (s) => { return s.m_params[0].ccdMotionThreshold; },
1024 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), 1045 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
1025 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 1046 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
1026 0f, 1047 0f,
1027 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, 1048 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
1028 (s) => { return s.m_params[0].ccdSweptSphereRadius; }, 1049 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
1029 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), 1050 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
1030 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 1051 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
1031 0.1f, 1052 0.1f,
1032 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, 1053 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
1033 (s) => { return s.m_params[0].contactProcessingThreshold; }, 1054 (s) => { return s.m_params[0].contactProcessingThreshold; },
1034 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), 1055 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
1035 1056
1036 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 1057 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
1037 0.5f, 1058 0.5f,
@@ -1049,35 +1070,35 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1049 (s) => { return s.m_params[0].terrainRestitution; }, 1070 (s) => { return s.m_params[0].terrainRestitution; },
1050 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), 1071 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
1051 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 1072 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
1052 0.5f, 1073 0.2f,
1053 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, 1074 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
1054 (s) => { return s.m_params[0].avatarFriction; }, 1075 (s) => { return s.m_params[0].avatarFriction; },
1055 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ), 1076 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
1056 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 1077 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
1057 60f, 1078 60f,
1058 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, 1079 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
1059 (s) => { return s.m_params[0].avatarDensity; }, 1080 (s) => { return s.m_params[0].avatarDensity; },
1060 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ), 1081 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ),
1061 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", 1082 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
1062 0f, 1083 0f,
1063 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, 1084 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
1064 (s) => { return s.m_params[0].avatarRestitution; }, 1085 (s) => { return s.m_params[0].avatarRestitution; },
1065 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ), 1086 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ),
1066 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", 1087 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
1067 0.37f, 1088 0.37f,
1068 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, 1089 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
1069 (s) => { return s.m_params[0].avatarCapsuleRadius; }, 1090 (s) => { return s.m_params[0].avatarCapsuleRadius; },
1070 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), 1091 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
1071 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", 1092 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
1072 1.5f, 1093 1.5f,
1073 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, 1094 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
1074 (s) => { return s.m_params[0].avatarCapsuleHeight; }, 1095 (s) => { return s.m_params[0].avatarCapsuleHeight; },
1075 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), 1096 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
1076 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 1097 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
1077 0.1f, 1098 0.1f,
1078 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, 1099 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
1079 (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, 1100 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
1080 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), 1101 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1081 1102
1082 1103
1083 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", 1104 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
@@ -1214,6 +1235,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1214 1235
1215 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; 1236 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
1216 1237
1238 // This creates an array in the correct format for returning the list of
1239 // parameters. This is used by the 'list' option of the 'physics' command.
1217 private void BuildParameterTable() 1240 private void BuildParameterTable()
1218 { 1241 {
1219 if (SettableParameters.Length < ParameterDefinitions.Length) 1242 if (SettableParameters.Length < ParameterDefinitions.Length)
@@ -1264,18 +1287,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1264 } 1287 }
1265 1288
1266 // check to see if we are updating a parameter for a particular or all of the prims 1289 // check to see if we are updating a parameter for a particular or all of the prims
1267 protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) 1290 protected void UpdateParameterObject(ref float loc, string parm, uint localID, float val)
1268 {
1269 List<uint> operateOn;
1270 lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
1271 UpdateParameterSet(operateOn, ref loc, parm, localID, val);
1272 }
1273
1274 // check to see if we are updating a parameter for a particular or all of the avatars
1275 protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
1276 { 1291 {
1277 List<uint> operateOn; 1292 List<uint> operateOn;
1278 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys); 1293 lock (PhysObjects) operateOn = new List<uint>(PhysObjects.Keys);
1279 UpdateParameterSet(operateOn, ref loc, parm, localID, val); 1294 UpdateParameterSet(operateOn, ref loc, parm, localID, val);
1280 } 1295 }
1281 1296
@@ -1298,7 +1313,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1298 TaintedObject("BSScene.UpdateParameterSet", delegate() { 1313 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1299 foreach (uint lID in objectIDs) 1314 foreach (uint lID in objectIDs)
1300 { 1315 {
1301 BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval); 1316 BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval);
1302 } 1317 }
1303 }); 1318 });
1304 break; 1319 break;
@@ -1316,7 +1331,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1316 string xparm = parm.ToLower(); 1331 string xparm = parm.ToLower();
1317 float xval = val; 1332 float xval = val;
1318 TaintedObject("BSScene.TaintedUpdateParameter", delegate() { 1333 TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
1319 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); 1334 BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval);
1320 }); 1335 });
1321 } 1336 }
1322 1337