diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 741 |
1 files changed, 309 insertions, 432 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index e56276a..15b7090 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -41,7 +41,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
41 | [Serializable] | 41 | [Serializable] |
42 | public class BSPrim : BSPhysObject | 42 | public class BSPrim : BSPhysObject |
43 | { | 43 | { |
44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 44 | protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
45 | private static readonly string LogHeader = "[BULLETS PRIM]"; | 45 | private static readonly string LogHeader = "[BULLETS PRIM]"; |
46 | 46 | ||
47 | // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. | 47 | // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. |
@@ -51,15 +51,8 @@ public class BSPrim : BSPhysObject | |||
51 | private bool _isSelected; | 51 | private bool _isSelected; |
52 | private bool _isVolumeDetect; | 52 | private bool _isVolumeDetect; |
53 | 53 | ||
54 | // _position is what the simulator thinks the positions of the prim is. | ||
55 | private OMV.Vector3 _position; | ||
56 | |||
57 | private float _mass; // the mass of this object | 54 | private float _mass; // the mass of this object |
58 | private OMV.Vector3 _force; | ||
59 | private OMV.Vector3 _velocity; | ||
60 | private OMV.Vector3 _torque; | ||
61 | private OMV.Vector3 _acceleration; | 55 | private OMV.Vector3 _acceleration; |
62 | private OMV.Quaternion _orientation; | ||
63 | private int _physicsActorType; | 56 | private int _physicsActorType; |
64 | private bool _isPhysical; | 57 | private bool _isPhysical; |
65 | private bool _flying; | 58 | private bool _flying; |
@@ -72,17 +65,18 @@ public class BSPrim : BSPhysObject | |||
72 | 65 | ||
73 | private int CrossingFailures { get; set; } | 66 | private int CrossingFailures { get; set; } |
74 | 67 | ||
75 | public BSDynamics VehicleActor; | 68 | // Keep a handle to the vehicle actor so it is easy to set parameters on same. |
76 | public string VehicleActorName = "BasicVehicle"; | 69 | public const string VehicleActorName = "BasicVehicle"; |
77 | |||
78 | private BSVMotor _targetMotor; | ||
79 | private OMV.Vector3 _PIDTarget; | ||
80 | private float _PIDTau; | ||
81 | 70 | ||
82 | private BSFMotor _hoverMotor; | 71 | // Parameters for the hover actor |
83 | private float _PIDHoverHeight; | 72 | public const string HoverActorName = "BSPrim.HoverActor"; |
84 | private PIDHoverType _PIDHoverType; | 73 | // Parameters for the axis lock actor |
85 | private float _PIDHoverTau; | 74 | public const String LockedAxisActorName = "BSPrim.LockedAxis"; |
75 | // Parameters for the move to target actor | ||
76 | public const string MoveToTargetActorName = "BSPrim.MoveToTargetActor"; | ||
77 | // Parameters for the setForce and setTorque actors | ||
78 | public const string SetForceActorName = "BSPrim.SetForceActor"; | ||
79 | public const string SetTorqueActorName = "BSPrim.SetTorqueActor"; | ||
86 | 80 | ||
87 | public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, | 81 | public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, |
88 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) | 82 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) |
@@ -90,32 +84,34 @@ public class BSPrim : BSPhysObject | |||
90 | { | 84 | { |
91 | // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); | 85 | // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); |
92 | _physicsActorType = (int)ActorTypes.Prim; | 86 | _physicsActorType = (int)ActorTypes.Prim; |
93 | _position = pos; | 87 | RawPosition = pos; |
94 | _size = size; | 88 | _size = size; |
95 | Scale = size; // prims are the size the user wants them to be (different for BSCharactes). | 89 | Scale = size; // prims are the size the user wants them to be (different for BSCharactes). |
96 | _orientation = rotation; | 90 | RawOrientation = rotation; |
97 | _buoyancy = 0f; | 91 | _buoyancy = 0f; |
98 | _velocity = OMV.Vector3.Zero; | 92 | RawVelocity = OMV.Vector3.Zero; |
99 | _rotationalVelocity = OMV.Vector3.Zero; | 93 | _rotationalVelocity = OMV.Vector3.Zero; |
100 | BaseShape = pbs; | 94 | BaseShape = pbs; |
101 | _isPhysical = pisPhysical; | 95 | _isPhysical = pisPhysical; |
102 | _isVolumeDetect = false; | 96 | _isVolumeDetect = false; |
103 | 97 | ||
104 | VehicleActor = new BSDynamics(PhysicsScene, this, VehicleActorName); | 98 | // Add a dynamic vehicle to our set of actors that can move this prim. |
105 | PhysicalActors.Add(VehicleActorName, VehicleActor); | 99 | // PhysicalActors.Add(VehicleActorName, new BSDynamics(PhysScene, this, VehicleActorName)); |
106 | 100 | ||
107 | _mass = CalculateMass(); | 101 | _mass = CalculateMass(); |
108 | 102 | ||
109 | // DetailLog("{0},BSPrim.constructor,call", LocalID); | 103 | // DetailLog("{0},BSPrim.constructor,call", LocalID); |
110 | // do the actual object creation at taint time | 104 | // do the actual object creation at taint time |
111 | PhysicsScene.TaintedObject("BSPrim.create", delegate() | 105 | PhysScene.TaintedObject(LocalID, "BSPrim.create", delegate() |
112 | { | 106 | { |
113 | // Make sure the object is being created with some sanity. | 107 | // Make sure the object is being created with some sanity. |
114 | ExtremeSanityCheck(true /* inTaintTime */); | 108 | ExtremeSanityCheck(true /* inTaintTime */); |
115 | 109 | ||
116 | CreateGeomAndObject(true); | 110 | CreateGeomAndObject(true); |
117 | 111 | ||
118 | CurrentCollisionFlags = PhysicsScene.PE.GetCollisionFlags(PhysBody); | 112 | CurrentCollisionFlags = PhysScene.PE.GetCollisionFlags(PhysBody); |
113 | |||
114 | IsInitialized = true; | ||
119 | }); | 115 | }); |
120 | } | 116 | } |
121 | 117 | ||
@@ -123,19 +119,21 @@ public class BSPrim : BSPhysObject | |||
123 | public override void Destroy() | 119 | public override void Destroy() |
124 | { | 120 | { |
125 | // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); | 121 | // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); |
122 | IsInitialized = false; | ||
123 | |||
126 | base.Destroy(); | 124 | base.Destroy(); |
127 | 125 | ||
128 | // Undo any vehicle properties | 126 | // Undo any vehicle properties |
129 | this.VehicleType = (int)Vehicle.TYPE_NONE; | 127 | this.VehicleType = (int)Vehicle.TYPE_NONE; |
130 | 128 | ||
131 | PhysicsScene.TaintedObject("BSPrim.Destroy", delegate() | 129 | PhysScene.TaintedObject(LocalID, "BSPrim.Destroy", delegate() |
132 | { | 130 | { |
133 | DetailLog("{0},BSPrim.Destroy,taint,", LocalID); | 131 | DetailLog("{0},BSPrim.Destroy,taint,", LocalID); |
134 | // If there are physical body and shape, release my use of same. | 132 | // If there are physical body and shape, release my use of same. |
135 | PhysicsScene.Shapes.DereferenceBody(PhysBody, null); | 133 | PhysScene.Shapes.DereferenceBody(PhysBody, null); |
136 | PhysBody.Clear(); | 134 | PhysBody.Clear(); |
137 | PhysicsScene.Shapes.DereferenceShape(PhysShape, null); | 135 | PhysShape.Dereference(PhysScene); |
138 | PhysShape.Clear(); | 136 | PhysShape = new BSShapeNull(); |
139 | }); | 137 | }); |
140 | } | 138 | } |
141 | 139 | ||
@@ -161,25 +159,13 @@ public class BSPrim : BSPhysObject | |||
161 | ForceBodyShapeRebuild(false); | 159 | ForceBodyShapeRebuild(false); |
162 | } | 160 | } |
163 | } | 161 | } |
164 | // 'unknown' says to choose the best type | ||
165 | public override BSPhysicsShapeType PreferredPhysicalShape | ||
166 | { get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } } | ||
167 | |||
168 | public override bool ForceBodyShapeRebuild(bool inTaintTime) | 162 | public override bool ForceBodyShapeRebuild(bool inTaintTime) |
169 | { | 163 | { |
170 | if (inTaintTime) | 164 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ForceBodyShapeRebuild", delegate() |
171 | { | 165 | { |
172 | _mass = CalculateMass(); // changing the shape changes the mass | 166 | _mass = CalculateMass(); // changing the shape changes the mass |
173 | CreateGeomAndObject(true); | 167 | CreateGeomAndObject(true); |
174 | } | 168 | }); |
175 | else | ||
176 | { | ||
177 | PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate() | ||
178 | { | ||
179 | _mass = CalculateMass(); // changing the shape changes the mass | ||
180 | CreateGeomAndObject(true); | ||
181 | }); | ||
182 | } | ||
183 | return true; | 169 | return true; |
184 | } | 170 | } |
185 | public override bool Grabbed { | 171 | public override bool Grabbed { |
@@ -192,7 +178,7 @@ public class BSPrim : BSPhysObject | |||
192 | if (value != _isSelected) | 178 | if (value != _isSelected) |
193 | { | 179 | { |
194 | _isSelected = value; | 180 | _isSelected = value; |
195 | PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() | 181 | PhysScene.TaintedObject(LocalID, "BSPrim.setSelected", delegate() |
196 | { | 182 | { |
197 | DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); | 183 | DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); |
198 | SetObjectDynamic(false); | 184 | SetObjectDynamic(false); |
@@ -233,28 +219,28 @@ public class BSPrim : BSPhysObject | |||
233 | // Called at taint time! | 219 | // Called at taint time! |
234 | public override void ZeroMotion(bool inTaintTime) | 220 | public override void ZeroMotion(bool inTaintTime) |
235 | { | 221 | { |
236 | _velocity = OMV.Vector3.Zero; | 222 | RawVelocity = OMV.Vector3.Zero; |
237 | _acceleration = OMV.Vector3.Zero; | 223 | _acceleration = OMV.Vector3.Zero; |
238 | _rotationalVelocity = OMV.Vector3.Zero; | 224 | _rotationalVelocity = OMV.Vector3.Zero; |
239 | 225 | ||
240 | // Zero some other properties in the physics engine | 226 | // Zero some other properties in the physics engine |
241 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() | 227 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate() |
242 | { | 228 | { |
243 | if (PhysBody.HasPhysicalBody) | 229 | if (PhysBody.HasPhysicalBody) |
244 | PhysicsScene.PE.ClearAllForces(PhysBody); | 230 | PhysScene.PE.ClearAllForces(PhysBody); |
245 | }); | 231 | }); |
246 | } | 232 | } |
247 | public override void ZeroAngularMotion(bool inTaintTime) | 233 | public override void ZeroAngularMotion(bool inTaintTime) |
248 | { | 234 | { |
249 | _rotationalVelocity = OMV.Vector3.Zero; | 235 | _rotationalVelocity = OMV.Vector3.Zero; |
250 | // Zero some other properties in the physics engine | 236 | // Zero some other properties in the physics engine |
251 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() | 237 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate() |
252 | { | 238 | { |
253 | // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); | 239 | // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); |
254 | if (PhysBody.HasPhysicalBody) | 240 | if (PhysBody.HasPhysicalBody) |
255 | { | 241 | { |
256 | PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); | 242 | PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); |
257 | PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); | 243 | PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); |
258 | } | 244 | } |
259 | }); | 245 | }); |
260 | } | 246 | } |
@@ -268,64 +254,58 @@ public class BSPrim : BSPhysObject | |||
268 | if (axis.X != 1) locking.X = 0f; | 254 | if (axis.X != 1) locking.X = 0f; |
269 | if (axis.Y != 1) locking.Y = 0f; | 255 | if (axis.Y != 1) locking.Y = 0f; |
270 | if (axis.Z != 1) locking.Z = 0f; | 256 | if (axis.Z != 1) locking.Z = 0f; |
271 | LockedAxis = locking; | 257 | LockedAngularAxis = locking; |
272 | 258 | ||
273 | if (LockedAxis != LockedAxisFree) | 259 | EnableActor(LockedAngularAxis != LockedAxisFree, LockedAxisActorName, delegate() |
274 | { | 260 | { |
275 | PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate() | 261 | return new BSActorLockAxis(PhysScene, this, LockedAxisActorName); |
276 | { | 262 | }); |
277 | // If there is not already an axis locker, make one | 263 | |
278 | if (!PhysicalActors.HasActor(LockedAxisActorName)) | 264 | // Update parameters so the new actor's Refresh() action is called at the right time. |
279 | { | 265 | PhysScene.TaintedObject(LocalID, "BSPrim.LockAngularMotion", delegate() |
280 | DetailLog("{0},BSPrim.LockAngularMotion,taint,registeringLockAxisActor", LocalID); | 266 | { |
281 | PhysicalActors.Add(LockedAxisActorName, new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName)); | 267 | UpdatePhysicalParameters(); |
282 | } | 268 | }); |
283 | UpdatePhysicalParameters(); | 269 | |
284 | }); | ||
285 | } | ||
286 | return; | 270 | return; |
287 | } | 271 | } |
288 | 272 | ||
289 | public override OMV.Vector3 RawPosition | ||
290 | { | ||
291 | get { return _position; } | ||
292 | set { _position = value; } | ||
293 | } | ||
294 | public override OMV.Vector3 Position { | 273 | public override OMV.Vector3 Position { |
295 | get { | 274 | get { |
296 | // don't do the GetObjectPosition for root elements because this function is called a zillion times. | 275 | // don't do the GetObjectPosition for root elements because this function is called a zillion times. |
297 | // _position = ForcePosition; | 276 | // RawPosition = ForcePosition; |
298 | return _position; | 277 | return RawPosition; |
299 | } | 278 | } |
300 | set { | 279 | set { |
301 | // If the position must be forced into the physics engine, use ForcePosition. | 280 | // If the position must be forced into the physics engine, use ForcePosition. |
302 | // All positions are given in world positions. | 281 | // All positions are given in world positions. |
303 | if (_position == value) | 282 | if (RawPosition == value) |
304 | { | 283 | { |
305 | DetailLog("{0},BSPrim.setPosition,call,positionNotChanging,pos={1},orient={2}", LocalID, _position, _orientation); | 284 | DetailLog("{0},BSPrim.setPosition,call,positionNotChanging,pos={1},orient={2}", LocalID, RawPosition, RawOrientation); |
306 | return; | 285 | return; |
307 | } | 286 | } |
308 | _position = value; | 287 | RawPosition = value; |
309 | PositionSanityCheck(false); | 288 | PositionSanityCheck(false); |
310 | 289 | ||
311 | PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() | 290 | PhysScene.TaintedObject(LocalID, "BSPrim.setPosition", delegate() |
312 | { | 291 | { |
313 | DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 292 | DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation); |
314 | ForcePosition = _position; | 293 | ForcePosition = RawPosition; |
315 | }); | 294 | }); |
316 | } | 295 | } |
317 | } | 296 | } |
318 | 297 | ||
298 | // NOTE: overloaded by BSPrimDisplaced to handle offset for center-of-gravity. | ||
319 | public override OMV.Vector3 ForcePosition { | 299 | public override OMV.Vector3 ForcePosition { |
320 | get { | 300 | get { |
321 | _position = PhysicsScene.PE.GetPosition(PhysBody); | 301 | RawPosition = PhysScene.PE.GetPosition(PhysBody); |
322 | return _position; | 302 | return RawPosition; |
323 | } | 303 | } |
324 | set { | 304 | set { |
325 | _position = value; | 305 | RawPosition = value; |
326 | if (PhysBody.HasPhysicalBody) | 306 | if (PhysBody.HasPhysicalBody) |
327 | { | 307 | { |
328 | PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); | 308 | PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation); |
329 | ActivateIfPhysical(false); | 309 | ActivateIfPhysical(false); |
330 | } | 310 | } |
331 | } | 311 | } |
@@ -342,7 +322,7 @@ public class BSPrim : BSPhysObject | |||
342 | if (!IsPhysicallyActive) | 322 | if (!IsPhysicallyActive) |
343 | return ret; | 323 | return ret; |
344 | 324 | ||
345 | if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) | 325 | if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) |
346 | { | 326 | { |
347 | // The physical object is out of the known/simulated area. | 327 | // The physical object is out of the known/simulated area. |
348 | // Upper levels of code will handle the transition to other areas so, for | 328 | // Upper levels of code will handle the transition to other areas so, for |
@@ -350,7 +330,7 @@ public class BSPrim : BSPhysObject | |||
350 | return ret; | 330 | return ret; |
351 | } | 331 | } |
352 | 332 | ||
353 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); | 333 | float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); |
354 | OMV.Vector3 upForce = OMV.Vector3.Zero; | 334 | OMV.Vector3 upForce = OMV.Vector3.Zero; |
355 | float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z)); | 335 | float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z)); |
356 | if ((RawPosition.Z + approxSize / 2f) < terrainHeight) | 336 | if ((RawPosition.Z + approxSize / 2f) < terrainHeight) |
@@ -359,10 +339,10 @@ public class BSPrim : BSPhysObject | |||
359 | float targetHeight = terrainHeight + (Size.Z / 2f); | 339 | float targetHeight = terrainHeight + (Size.Z / 2f); |
360 | // If the object is below ground it just has to be moved up because pushing will | 340 | // If the object is below ground it just has to be moved up because pushing will |
361 | // not get it through the terrain | 341 | // not get it through the terrain |
362 | _position.Z = targetHeight; | 342 | RawPosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, targetHeight); |
363 | if (inTaintTime) | 343 | if (inTaintTime) |
364 | { | 344 | { |
365 | ForcePosition = _position; | 345 | ForcePosition = RawPosition; |
366 | } | 346 | } |
367 | // If we are throwing the object around, zero its other forces | 347 | // If we are throwing the object around, zero its other forces |
368 | ZeroMotion(inTaintTime); | 348 | ZeroMotion(inTaintTime); |
@@ -371,7 +351,7 @@ public class BSPrim : BSPhysObject | |||
371 | 351 | ||
372 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) | 352 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) |
373 | { | 353 | { |
374 | float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); | 354 | float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition); |
375 | // TODO: a floating motor so object will bob in the water | 355 | // TODO: a floating motor so object will bob in the water |
376 | if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) | 356 | if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) |
377 | { | 357 | { |
@@ -379,8 +359,8 @@ public class BSPrim : BSPhysObject | |||
379 | upForce.Z = (waterHeight - RawPosition.Z) * 1f; | 359 | upForce.Z = (waterHeight - RawPosition.Z) * 1f; |
380 | 360 | ||
381 | // Apply upforce and overcome gravity. | 361 | // Apply upforce and overcome gravity. |
382 | OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity; | 362 | OMV.Vector3 correctionForce = upForce - PhysScene.DefaultGravity; |
383 | DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce); | 363 | DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, RawPosition, upForce, correctionForce); |
384 | AddForce(correctionForce, false, inTaintTime); | 364 | AddForce(correctionForce, false, inTaintTime); |
385 | ret = true; | 365 | ret = true; |
386 | } | 366 | } |
@@ -399,17 +379,17 @@ public class BSPrim : BSPhysObject | |||
399 | uint wayOutThere = Constants.RegionSize * Constants.RegionSize; | 379 | uint wayOutThere = Constants.RegionSize * Constants.RegionSize; |
400 | // There have been instances of objects getting thrown way out of bounds and crashing | 380 | // There have been instances of objects getting thrown way out of bounds and crashing |
401 | // the border crossing code. | 381 | // the border crossing code. |
402 | if ( _position.X < -Constants.RegionSize || _position.X > wayOutThere | 382 | if ( RawPosition.X < -Constants.RegionSize || RawPosition.X > wayOutThere |
403 | || _position.Y < -Constants.RegionSize || _position.Y > wayOutThere | 383 | || RawPosition.Y < -Constants.RegionSize || RawPosition.Y > wayOutThere |
404 | || _position.Z < -Constants.RegionSize || _position.Z > wayOutThere) | 384 | || RawPosition.Z < -Constants.RegionSize || RawPosition.Z > wayOutThere) |
405 | { | 385 | { |
406 | _position = new OMV.Vector3(10, 10, 50); | 386 | RawPosition = new OMV.Vector3(10, 10, 50); |
407 | ZeroMotion(inTaintTime); | 387 | ZeroMotion(inTaintTime); |
408 | ret = true; | 388 | ret = true; |
409 | } | 389 | } |
410 | if (_velocity.LengthSquared() > BSParam.MaxLinearVelocity) | 390 | if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocity) |
411 | { | 391 | { |
412 | _velocity = Util.ClampV(_velocity, BSParam.MaxLinearVelocity); | 392 | RawVelocity = Util.ClampV(RawVelocity, BSParam.MaxLinearVelocity); |
413 | ret = true; | 393 | ret = true; |
414 | } | 394 | } |
415 | if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared) | 395 | if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared) |
@@ -434,7 +414,7 @@ public class BSPrim : BSPhysObject | |||
434 | get { return _mass; } | 414 | get { return _mass; } |
435 | } | 415 | } |
436 | // used when we only want this prim's mass and not the linkset thing | 416 | // used when we only want this prim's mass and not the linkset thing |
437 | public override float RawMass { | 417 | public override float RawMass { |
438 | get { return _mass; } | 418 | get { return _mass; } |
439 | } | 419 | } |
440 | // Set the physical mass to the passed mass. | 420 | // Set the physical mass to the passed mass. |
@@ -445,10 +425,10 @@ public class BSPrim : BSPhysObject | |||
445 | { | 425 | { |
446 | if (IsStatic) | 426 | if (IsStatic) |
447 | { | 427 | { |
448 | PhysicsScene.PE.SetGravity(PhysBody, PhysicsScene.DefaultGravity); | 428 | PhysScene.PE.SetGravity(PhysBody, PhysScene.DefaultGravity); |
449 | Inertia = OMV.Vector3.Zero; | 429 | Inertia = OMV.Vector3.Zero; |
450 | PhysicsScene.PE.SetMassProps(PhysBody, 0f, Inertia); | 430 | PhysScene.PE.SetMassProps(PhysBody, 0f, Inertia); |
451 | PhysicsScene.PE.UpdateInertiaTensor(PhysBody); | 431 | PhysScene.PE.UpdateInertiaTensor(PhysBody); |
452 | } | 432 | } |
453 | else | 433 | else |
454 | { | 434 | { |
@@ -457,16 +437,19 @@ public class BSPrim : BSPhysObject | |||
457 | // Changing interesting properties doesn't change proxy and collision cache | 437 | // Changing interesting properties doesn't change proxy and collision cache |
458 | // information. The Bullet solution is to re-add the object to the world | 438 | // information. The Bullet solution is to re-add the object to the world |
459 | // after parameters are changed. | 439 | // after parameters are changed. |
460 | PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); | 440 | PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody); |
461 | } | 441 | } |
462 | 442 | ||
463 | // The computation of mass props requires gravity to be set on the object. | 443 | // The computation of mass props requires gravity to be set on the object. |
464 | Gravity = ComputeGravity(Buoyancy); | 444 | Gravity = ComputeGravity(Buoyancy); |
465 | PhysicsScene.PE.SetGravity(PhysBody, Gravity); | 445 | PhysScene.PE.SetGravity(PhysBody, Gravity); |
446 | |||
447 | // OMV.Vector3 currentScale = PhysScene.PE.GetLocalScaling(PhysShape.physShapeInfo); // DEBUG DEBUG | ||
448 | // DetailLog("{0},BSPrim.UpdateMassProperties,currentScale{1},shape={2}", LocalID, currentScale, PhysShape.physShapeInfo); // DEBUG DEBUG | ||
466 | 449 | ||
467 | Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); | 450 | Inertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass); |
468 | PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia); | 451 | PhysScene.PE.SetMassProps(PhysBody, physMass, Inertia); |
469 | PhysicsScene.PE.UpdateInertiaTensor(PhysBody); | 452 | PhysScene.PE.UpdateInertiaTensor(PhysBody); |
470 | 453 | ||
471 | DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}", | 454 | DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}", |
472 | LocalID, physMass, Inertia, Gravity, inWorld); | 455 | LocalID, physMass, Inertia, Gravity, inWorld); |
@@ -482,7 +465,7 @@ public class BSPrim : BSPhysObject | |||
482 | // Return what gravity should be set to this very moment | 465 | // Return what gravity should be set to this very moment |
483 | public OMV.Vector3 ComputeGravity(float buoyancy) | 466 | public OMV.Vector3 ComputeGravity(float buoyancy) |
484 | { | 467 | { |
485 | OMV.Vector3 ret = PhysicsScene.DefaultGravity; | 468 | OMV.Vector3 ret = PhysScene.DefaultGravity; |
486 | 469 | ||
487 | if (!IsStatic) | 470 | if (!IsStatic) |
488 | { | 471 | { |
@@ -506,83 +489,121 @@ public class BSPrim : BSPhysObject | |||
506 | } | 489 | } |
507 | 490 | ||
508 | public override OMV.Vector3 Force { | 491 | public override OMV.Vector3 Force { |
509 | get { return _force; } | 492 | get { return RawForce; } |
510 | set { | 493 | set { |
511 | _force = value; | 494 | RawForce = value; |
512 | if (_force != OMV.Vector3.Zero) | 495 | EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate() |
513 | { | 496 | { |
514 | // If the force is non-zero, it must be reapplied each tick because | 497 | return new BSActorSetForce(PhysScene, this, SetForceActorName); |
515 | // Bullet clears the forces applied last frame. | 498 | }); |
516 | RegisterPreStepAction("BSPrim.setForce", LocalID, | 499 | } |
517 | delegate(float timeStep) | 500 | } |
518 | { | ||
519 | if (!IsPhysicallyActive || _force == OMV.Vector3.Zero) | ||
520 | { | ||
521 | UnRegisterPreStepAction("BSPrim.setForce", LocalID); | ||
522 | return; | ||
523 | } | ||
524 | 501 | ||
525 | DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force); | 502 | // Find and return a handle to the current vehicle actor. |
526 | if (PhysBody.HasPhysicalBody) | 503 | // Return 'null' if there is no vehicle actor. |
527 | { | 504 | public BSDynamics GetVehicleActor(bool createIfNone) |
528 | PhysicsScene.PE.ApplyCentralForce(PhysBody, _force); | 505 | { |
529 | ActivateIfPhysical(false); | 506 | BSDynamics ret = null; |
530 | } | 507 | BSActor actor; |
531 | } | 508 | if (PhysicalActors.TryGetActor(VehicleActorName, out actor)) |
532 | ); | 509 | { |
533 | } | 510 | ret = actor as BSDynamics; |
534 | else | 511 | } |
512 | else | ||
513 | { | ||
514 | if (createIfNone) | ||
535 | { | 515 | { |
536 | UnRegisterPreStepAction("BSPrim.setForce", LocalID); | 516 | ret = new BSDynamics(PhysScene, this, VehicleActorName); |
517 | PhysicalActors.Add(ret.ActorName, ret); | ||
537 | } | 518 | } |
538 | } | 519 | } |
520 | return ret; | ||
539 | } | 521 | } |
540 | 522 | ||
541 | public override int VehicleType { | 523 | public override int VehicleType { |
542 | get { | 524 | get { |
543 | return (int)VehicleActor.Type; // if we are a vehicle, return that type | 525 | int ret = (int)Vehicle.TYPE_NONE; |
526 | BSDynamics vehicleActor = GetVehicleActor(false /* createIfNone */); | ||
527 | if (vehicleActor != null) | ||
528 | ret = (int)vehicleActor.Type; | ||
529 | return ret; | ||
544 | } | 530 | } |
545 | set { | 531 | set { |
546 | Vehicle type = (Vehicle)value; | 532 | Vehicle type = (Vehicle)value; |
547 | 533 | ||
548 | PhysicsScene.TaintedObject("setVehicleType", delegate() | 534 | PhysScene.TaintedObject(LocalID, "setVehicleType", delegate() |
549 | { | 535 | { |
550 | // Done at taint time so we're sure the physics engine is not using the variables | 536 | // Some vehicle scripts change vehicle type on the fly as an easy way to |
551 | // Vehicle code changes the parameters for this vehicle type. | 537 | // change all the parameters. Like a plane changing to CAR when on the |
552 | VehicleActor.ProcessTypeChange(type); | 538 | // ground. In this case, don't want to zero motion. |
553 | ActivateIfPhysical(false); | 539 | // ZeroMotion(true /* inTaintTime */); |
540 | if (type == Vehicle.TYPE_NONE) | ||
541 | { | ||
542 | // Vehicle type is 'none' so get rid of any actor that may have been allocated. | ||
543 | BSDynamics vehicleActor = GetVehicleActor(false /* createIfNone */); | ||
544 | if (vehicleActor != null) | ||
545 | { | ||
546 | PhysicalActors.RemoveAndRelease(vehicleActor.ActorName); | ||
547 | } | ||
548 | } | ||
549 | else | ||
550 | { | ||
551 | // Vehicle type is not 'none' so create an actor and set it running. | ||
552 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); | ||
553 | if (vehicleActor != null) | ||
554 | { | ||
555 | vehicleActor.ProcessTypeChange(type); | ||
556 | ActivateIfPhysical(false); | ||
557 | } | ||
558 | } | ||
554 | }); | 559 | }); |
555 | } | 560 | } |
556 | } | 561 | } |
557 | public override void VehicleFloatParam(int param, float value) | 562 | public override void VehicleFloatParam(int param, float value) |
558 | { | 563 | { |
559 | PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() | 564 | PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFloatParam", delegate() |
560 | { | 565 | { |
561 | VehicleActor.ProcessFloatVehicleParam((Vehicle)param, value); | 566 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); |
562 | ActivateIfPhysical(false); | 567 | if (vehicleActor != null) |
568 | { | ||
569 | vehicleActor.ProcessFloatVehicleParam((Vehicle)param, value); | ||
570 | ActivateIfPhysical(false); | ||
571 | } | ||
563 | }); | 572 | }); |
564 | } | 573 | } |
565 | public override void VehicleVectorParam(int param, OMV.Vector3 value) | 574 | public override void VehicleVectorParam(int param, OMV.Vector3 value) |
566 | { | 575 | { |
567 | PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() | 576 | PhysScene.TaintedObject(LocalID, "BSPrim.VehicleVectorParam", delegate() |
568 | { | 577 | { |
569 | VehicleActor.ProcessVectorVehicleParam((Vehicle)param, value); | 578 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); |
570 | ActivateIfPhysical(false); | 579 | if (vehicleActor != null) |
580 | { | ||
581 | vehicleActor.ProcessVectorVehicleParam((Vehicle)param, value); | ||
582 | ActivateIfPhysical(false); | ||
583 | } | ||
571 | }); | 584 | }); |
572 | } | 585 | } |
573 | public override void VehicleRotationParam(int param, OMV.Quaternion rotation) | 586 | public override void VehicleRotationParam(int param, OMV.Quaternion rotation) |
574 | { | 587 | { |
575 | PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() | 588 | PhysScene.TaintedObject(LocalID, "BSPrim.VehicleRotationParam", delegate() |
576 | { | 589 | { |
577 | VehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation); | 590 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); |
578 | ActivateIfPhysical(false); | 591 | if (vehicleActor != null) |
592 | { | ||
593 | vehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation); | ||
594 | ActivateIfPhysical(false); | ||
595 | } | ||
579 | }); | 596 | }); |
580 | } | 597 | } |
581 | public override void VehicleFlags(int param, bool remove) | 598 | public override void VehicleFlags(int param, bool remove) |
582 | { | 599 | { |
583 | PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() | 600 | PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFlags", delegate() |
584 | { | 601 | { |
585 | VehicleActor.ProcessVehicleFlags(param, remove); | 602 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); |
603 | if (vehicleActor != null) | ||
604 | { | ||
605 | vehicleActor.ProcessVehicleFlags(param, remove); | ||
606 | } | ||
586 | }); | 607 | }); |
587 | } | 608 | } |
588 | 609 | ||
@@ -592,7 +613,7 @@ public class BSPrim : BSPhysObject | |||
592 | if (_isVolumeDetect != newValue) | 613 | if (_isVolumeDetect != newValue) |
593 | { | 614 | { |
594 | _isVolumeDetect = newValue; | 615 | _isVolumeDetect = newValue; |
595 | PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() | 616 | PhysScene.TaintedObject(LocalID, "BSPrim.SetVolumeDetect", delegate() |
596 | { | 617 | { |
597 | // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); | 618 | // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); |
598 | SetObjectDynamic(true); | 619 | SetObjectDynamic(true); |
@@ -600,10 +621,14 @@ public class BSPrim : BSPhysObject | |||
600 | } | 621 | } |
601 | return; | 622 | return; |
602 | } | 623 | } |
624 | public override bool IsVolumeDetect | ||
625 | { | ||
626 | get { return _isVolumeDetect; } | ||
627 | } | ||
603 | public override void SetMaterial(int material) | 628 | public override void SetMaterial(int material) |
604 | { | 629 | { |
605 | base.SetMaterial(material); | 630 | base.SetMaterial(material); |
606 | PhysicsScene.TaintedObject("BSPrim.SetMaterial", delegate() | 631 | PhysScene.TaintedObject(LocalID, "BSPrim.SetMaterial", delegate() |
607 | { | 632 | { |
608 | UpdatePhysicalParameters(); | 633 | UpdatePhysicalParameters(); |
609 | }); | 634 | }); |
@@ -616,7 +641,7 @@ public class BSPrim : BSPhysObject | |||
616 | if (base.Friction != value) | 641 | if (base.Friction != value) |
617 | { | 642 | { |
618 | base.Friction = value; | 643 | base.Friction = value; |
619 | PhysicsScene.TaintedObject("BSPrim.setFriction", delegate() | 644 | PhysScene.TaintedObject(LocalID, "BSPrim.setFriction", delegate() |
620 | { | 645 | { |
621 | UpdatePhysicalParameters(); | 646 | UpdatePhysicalParameters(); |
622 | }); | 647 | }); |
@@ -631,7 +656,7 @@ public class BSPrim : BSPhysObject | |||
631 | if (base.Restitution != value) | 656 | if (base.Restitution != value) |
632 | { | 657 | { |
633 | base.Restitution = value; | 658 | base.Restitution = value; |
634 | PhysicsScene.TaintedObject("BSPrim.setRestitution", delegate() | 659 | PhysScene.TaintedObject(LocalID, "BSPrim.setRestitution", delegate() |
635 | { | 660 | { |
636 | UpdatePhysicalParameters(); | 661 | UpdatePhysicalParameters(); |
637 | }); | 662 | }); |
@@ -648,7 +673,7 @@ public class BSPrim : BSPhysObject | |||
648 | if (base.Density != value) | 673 | if (base.Density != value) |
649 | { | 674 | { |
650 | base.Density = value; | 675 | base.Density = value; |
651 | PhysicsScene.TaintedObject("BSPrim.setDensity", delegate() | 676 | PhysScene.TaintedObject(LocalID, "BSPrim.setDensity", delegate() |
652 | { | 677 | { |
653 | UpdatePhysicalParameters(); | 678 | UpdatePhysicalParameters(); |
654 | }); | 679 | }); |
@@ -663,93 +688,66 @@ public class BSPrim : BSPhysObject | |||
663 | if (base.GravModifier != value) | 688 | if (base.GravModifier != value) |
664 | { | 689 | { |
665 | base.GravModifier = value; | 690 | base.GravModifier = value; |
666 | PhysicsScene.TaintedObject("BSPrim.setGravityModifier", delegate() | 691 | PhysScene.TaintedObject(LocalID, "BSPrim.setGravityModifier", delegate() |
667 | { | 692 | { |
668 | UpdatePhysicalParameters(); | 693 | UpdatePhysicalParameters(); |
669 | }); | 694 | }); |
670 | } | 695 | } |
671 | } | 696 | } |
672 | } | 697 | } |
673 | public override OMV.Vector3 RawVelocity | ||
674 | { | ||
675 | get { return _velocity; } | ||
676 | set { _velocity = value; } | ||
677 | } | ||
678 | public override OMV.Vector3 Velocity { | 698 | public override OMV.Vector3 Velocity { |
679 | get { return _velocity; } | 699 | get { return RawVelocity; } |
680 | set { | 700 | set { |
681 | _velocity = value; | 701 | RawVelocity = value; |
682 | PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() | 702 | PhysScene.TaintedObject(LocalID, "BSPrim.setVelocity", delegate() |
683 | { | 703 | { |
684 | // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); | 704 | // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity); |
685 | ForceVelocity = _velocity; | 705 | ForceVelocity = RawVelocity; |
686 | }); | 706 | }); |
687 | } | 707 | } |
688 | } | 708 | } |
689 | public override OMV.Vector3 ForceVelocity { | 709 | public override OMV.Vector3 ForceVelocity { |
690 | get { return _velocity; } | 710 | get { return RawVelocity; } |
691 | set { | 711 | set { |
692 | PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity"); | 712 | PhysScene.AssertInTaintTime("BSPrim.ForceVelocity"); |
693 | 713 | ||
694 | _velocity = Util.ClampV(value, BSParam.MaxLinearVelocity); | 714 | RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity); |
695 | if (PhysBody.HasPhysicalBody) | 715 | if (PhysBody.HasPhysicalBody) |
696 | { | 716 | { |
697 | DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity); | 717 | DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity); |
698 | PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); | 718 | PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity); |
699 | ActivateIfPhysical(false); | 719 | ActivateIfPhysical(false); |
700 | } | 720 | } |
701 | } | 721 | } |
702 | } | 722 | } |
703 | public override OMV.Vector3 Torque { | 723 | public override OMV.Vector3 Torque { |
704 | get { return _torque; } | 724 | get { return RawTorque; } |
705 | set { | 725 | set { |
706 | _torque = value; | 726 | RawTorque = value; |
707 | if (_torque != OMV.Vector3.Zero) | 727 | EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate() |
708 | { | ||
709 | // If the torque is non-zero, it must be reapplied each tick because | ||
710 | // Bullet clears the forces applied last frame. | ||
711 | RegisterPreStepAction("BSPrim.setTorque", LocalID, | ||
712 | delegate(float timeStep) | ||
713 | { | ||
714 | if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero) | ||
715 | { | ||
716 | UnRegisterPreStepAction("BSPrim.setTorque", LocalID); | ||
717 | return; | ||
718 | } | ||
719 | |||
720 | if (PhysBody.HasPhysicalBody) | ||
721 | AddAngularForce(_torque, false, true); | ||
722 | } | ||
723 | ); | ||
724 | } | ||
725 | else | ||
726 | { | 728 | { |
727 | UnRegisterPreStepAction("BSPrim.setTorque", LocalID); | 729 | return new BSActorSetTorque(PhysScene, this, SetTorqueActorName); |
728 | } | 730 | }); |
729 | // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); | 731 | DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque); |
730 | } | 732 | } |
731 | } | 733 | } |
732 | public override OMV.Vector3 Acceleration { | 734 | public override OMV.Vector3 Acceleration { |
733 | get { return _acceleration; } | 735 | get { return _acceleration; } |
734 | set { _acceleration = value; } | 736 | set { _acceleration = value; } |
735 | } | 737 | } |
736 | public override OMV.Quaternion RawOrientation | 738 | |
737 | { | ||
738 | get { return _orientation; } | ||
739 | set { _orientation = value; } | ||
740 | } | ||
741 | public override OMV.Quaternion Orientation { | 739 | public override OMV.Quaternion Orientation { |
742 | get { | 740 | get { |
743 | return _orientation; | 741 | return RawOrientation; |
744 | } | 742 | } |
745 | set { | 743 | set { |
746 | if (_orientation == value) | 744 | if (RawOrientation == value) |
747 | return; | 745 | return; |
748 | _orientation = value; | 746 | RawOrientation = value; |
749 | 747 | ||
750 | PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() | 748 | PhysScene.TaintedObject(LocalID, "BSPrim.setOrientation", delegate() |
751 | { | 749 | { |
752 | ForceOrientation = _orientation; | 750 | ForceOrientation = RawOrientation; |
753 | }); | 751 | }); |
754 | } | 752 | } |
755 | } | 753 | } |
@@ -758,14 +756,14 @@ public class BSPrim : BSPhysObject | |||
758 | { | 756 | { |
759 | get | 757 | get |
760 | { | 758 | { |
761 | _orientation = PhysicsScene.PE.GetOrientation(PhysBody); | 759 | RawOrientation = PhysScene.PE.GetOrientation(PhysBody); |
762 | return _orientation; | 760 | return RawOrientation; |
763 | } | 761 | } |
764 | set | 762 | set |
765 | { | 763 | { |
766 | _orientation = value; | 764 | RawOrientation = value; |
767 | if (PhysBody.HasPhysicalBody) | 765 | if (PhysBody.HasPhysicalBody) |
768 | PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); | 766 | PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation); |
769 | } | 767 | } |
770 | } | 768 | } |
771 | public override int PhysicsActorType { | 769 | public override int PhysicsActorType { |
@@ -778,7 +776,7 @@ public class BSPrim : BSPhysObject | |||
778 | if (_isPhysical != value) | 776 | if (_isPhysical != value) |
779 | { | 777 | { |
780 | _isPhysical = value; | 778 | _isPhysical = value; |
781 | PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() | 779 | PhysScene.TaintedObject(LocalID, "BSPrim.setIsPhysical", delegate() |
782 | { | 780 | { |
783 | DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); | 781 | DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); |
784 | SetObjectDynamic(true); | 782 | SetObjectDynamic(true); |
@@ -822,24 +820,24 @@ public class BSPrim : BSPhysObject | |||
822 | // isSolid: other objects bounce off of this object | 820 | // isSolid: other objects bounce off of this object |
823 | // isVolumeDetect: other objects pass through but can generate collisions | 821 | // isVolumeDetect: other objects pass through but can generate collisions |
824 | // collisionEvents: whether this object returns collision events | 822 | // collisionEvents: whether this object returns collision events |
823 | // NOTE: overloaded by BSPrimLinkable to also update linkset physical parameters. | ||
825 | public virtual void UpdatePhysicalParameters() | 824 | public virtual void UpdatePhysicalParameters() |
826 | { | 825 | { |
827 | if (!PhysBody.HasPhysicalBody) | 826 | if (!PhysBody.HasPhysicalBody) |
828 | { | 827 | { |
829 | // This would only happen if updates are called for during initialization when the body is not set up yet. | 828 | // This would only happen if updates are called for during initialization when the body is not set up yet. |
830 | DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID); | 829 | // DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID); |
831 | return; | 830 | return; |
832 | } | 831 | } |
833 | 832 | ||
834 | // Mangling all the physical properties requires the object not be in the physical world. | 833 | // Mangling all the physical properties requires the object not be in the physical world. |
835 | // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). | 834 | // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). |
836 | PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); | 835 | PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody); |
837 | 836 | ||
838 | // Set up the object physicalness (does gravity and collisions move this object) | 837 | // Set up the object physicalness (does gravity and collisions move this object) |
839 | MakeDynamic(IsStatic); | 838 | MakeDynamic(IsStatic); |
840 | 839 | ||
841 | // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) | 840 | // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) |
842 | VehicleActor.Refresh(); | ||
843 | PhysicalActors.Refresh(); | 841 | PhysicalActors.Refresh(); |
844 | 842 | ||
845 | // Arrange for collision events if the simulator wants them | 843 | // Arrange for collision events if the simulator wants them |
@@ -851,10 +849,11 @@ public class BSPrim : BSPhysObject | |||
851 | AddObjectToPhysicalWorld(); | 849 | AddObjectToPhysicalWorld(); |
852 | 850 | ||
853 | // Rebuild its shape | 851 | // Rebuild its shape |
854 | PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); | 852 | PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody); |
855 | 853 | ||
856 | DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}", | 854 | DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}", |
857 | LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape); | 855 | LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), |
856 | CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape); | ||
858 | } | 857 | } |
859 | 858 | ||
860 | // "Making dynamic" means changing to and from static. | 859 | // "Making dynamic" means changing to and from static. |
@@ -867,28 +866,28 @@ public class BSPrim : BSPhysObject | |||
867 | if (makeStatic) | 866 | if (makeStatic) |
868 | { | 867 | { |
869 | // Become a Bullet 'static' object type | 868 | // Become a Bullet 'static' object type |
870 | CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); | 869 | CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); |
871 | // Stop all movement | 870 | // Stop all movement |
872 | ZeroMotion(true); | 871 | ZeroMotion(true); |
873 | 872 | ||
874 | // Set various physical properties so other object interact properly | 873 | // Set various physical properties so other object interact properly |
875 | PhysicsScene.PE.SetFriction(PhysBody, Friction); | 874 | PhysScene.PE.SetFriction(PhysBody, Friction); |
876 | PhysicsScene.PE.SetRestitution(PhysBody, Restitution); | 875 | PhysScene.PE.SetRestitution(PhysBody, Restitution); |
877 | PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); | 876 | PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); |
878 | 877 | ||
879 | // Mass is zero which disables a bunch of physics stuff in Bullet | 878 | // Mass is zero which disables a bunch of physics stuff in Bullet |
880 | UpdatePhysicalMassProperties(0f, false); | 879 | UpdatePhysicalMassProperties(0f, false); |
881 | // Set collision detection parameters | 880 | // Set collision detection parameters |
882 | if (BSParam.CcdMotionThreshold > 0f) | 881 | if (BSParam.CcdMotionThreshold > 0f) |
883 | { | 882 | { |
884 | PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); | 883 | PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); |
885 | PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); | 884 | PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); |
886 | } | 885 | } |
887 | 886 | ||
888 | // The activation state is 'disabled' so Bullet will not try to act on it. | 887 | // The activation state is 'disabled' so Bullet will not try to act on it. |
889 | // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION); | 888 | // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION); |
890 | // Start it out sleeping and physical actions could wake it up. | 889 | // Start it out sleeping and physical actions could wake it up. |
891 | PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING); | 890 | PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING); |
892 | 891 | ||
893 | // This collides like a static object | 892 | // This collides like a static object |
894 | PhysBody.collisionType = CollisionType.Static; | 893 | PhysBody.collisionType = CollisionType.Static; |
@@ -896,11 +895,11 @@ public class BSPrim : BSPhysObject | |||
896 | else | 895 | else |
897 | { | 896 | { |
898 | // Not a Bullet static object | 897 | // Not a Bullet static object |
899 | CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); | 898 | CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); |
900 | 899 | ||
901 | // Set various physical properties so other object interact properly | 900 | // Set various physical properties so other object interact properly |
902 | PhysicsScene.PE.SetFriction(PhysBody, Friction); | 901 | PhysScene.PE.SetFriction(PhysBody, Friction); |
903 | PhysicsScene.PE.SetRestitution(PhysBody, Restitution); | 902 | PhysScene.PE.SetRestitution(PhysBody, Restitution); |
904 | // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution); | 903 | // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution); |
905 | 904 | ||
906 | // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 | 905 | // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 |
@@ -908,8 +907,8 @@ public class BSPrim : BSPhysObject | |||
908 | // PhysicsScene.PE.ClearAllForces(BSBody); | 907 | // PhysicsScene.PE.ClearAllForces(BSBody); |
909 | 908 | ||
910 | // For good measure, make sure the transform is set through to the motion state | 909 | // For good measure, make sure the transform is set through to the motion state |
911 | ForcePosition = _position; | 910 | ForcePosition = RawPosition; |
912 | ForceVelocity = _velocity; | 911 | ForceVelocity = RawVelocity; |
913 | ForceRotationalVelocity = _rotationalVelocity; | 912 | ForceRotationalVelocity = _rotationalVelocity; |
914 | 913 | ||
915 | // A dynamic object has mass | 914 | // A dynamic object has mass |
@@ -918,22 +917,22 @@ public class BSPrim : BSPhysObject | |||
918 | // Set collision detection parameters | 917 | // Set collision detection parameters |
919 | if (BSParam.CcdMotionThreshold > 0f) | 918 | if (BSParam.CcdMotionThreshold > 0f) |
920 | { | 919 | { |
921 | PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); | 920 | PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); |
922 | PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); | 921 | PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); |
923 | } | 922 | } |
924 | 923 | ||
925 | // Various values for simulation limits | 924 | // Various values for simulation limits |
926 | PhysicsScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping); | 925 | PhysScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping); |
927 | PhysicsScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime); | 926 | PhysScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime); |
928 | PhysicsScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold); | 927 | PhysScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold); |
929 | PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); | 928 | PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); |
930 | 929 | ||
931 | // This collides like an object. | 930 | // This collides like an object. |
932 | PhysBody.collisionType = CollisionType.Dynamic; | 931 | PhysBody.collisionType = CollisionType.Dynamic; |
933 | 932 | ||
934 | // Force activation of the object so Bullet will act on it. | 933 | // Force activation of the object so Bullet will act on it. |
935 | // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. | 934 | // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. |
936 | PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); | 935 | PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); |
937 | } | 936 | } |
938 | } | 937 | } |
939 | 938 | ||
@@ -943,7 +942,7 @@ public class BSPrim : BSPhysObject | |||
943 | // the functions after this one set up the state of a possibly newly created collision body. | 942 | // the functions after this one set up the state of a possibly newly created collision body. |
944 | private void MakeSolid(bool makeSolid) | 943 | private void MakeSolid(bool makeSolid) |
945 | { | 944 | { |
946 | CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(PhysBody); | 945 | CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysScene.PE.GetBodyType(PhysBody); |
947 | if (makeSolid) | 946 | if (makeSolid) |
948 | { | 947 | { |
949 | // Verify the previous code created the correct shape for this type of thing. | 948 | // Verify the previous code created the correct shape for this type of thing. |
@@ -951,7 +950,7 @@ public class BSPrim : BSPhysObject | |||
951 | { | 950 | { |
952 | m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); | 951 | m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); |
953 | } | 952 | } |
954 | CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); | 953 | CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); |
955 | } | 954 | } |
956 | else | 955 | else |
957 | { | 956 | { |
@@ -959,32 +958,23 @@ public class BSPrim : BSPhysObject | |||
959 | { | 958 | { |
960 | m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); | 959 | m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); |
961 | } | 960 | } |
962 | CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); | 961 | CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); |
963 | 962 | ||
964 | // Change collision info from a static object to a ghosty collision object | 963 | // Change collision info from a static object to a ghosty collision object |
965 | PhysBody.collisionType = CollisionType.VolumeDetect; | 964 | PhysBody.collisionType = CollisionType.VolumeDetect; |
966 | } | 965 | } |
967 | } | 966 | } |
968 | 967 | ||
969 | // Enable physical actions. Bullet will keep sleeping non-moving physical objects so | ||
970 | // they need waking up when parameters are changed. | ||
971 | // Called in taint-time!! | ||
972 | private void ActivateIfPhysical(bool forceIt) | ||
973 | { | ||
974 | if (IsPhysical && PhysBody.HasPhysicalBody) | ||
975 | PhysicsScene.PE.Activate(PhysBody, forceIt); | ||
976 | } | ||
977 | |||
978 | // Turn on or off the flag controlling whether collision events are returned to the simulator. | 968 | // Turn on or off the flag controlling whether collision events are returned to the simulator. |
979 | private void EnableCollisions(bool wantsCollisionEvents) | 969 | private void EnableCollisions(bool wantsCollisionEvents) |
980 | { | 970 | { |
981 | if (wantsCollisionEvents) | 971 | if (wantsCollisionEvents) |
982 | { | 972 | { |
983 | CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | 973 | CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); |
984 | } | 974 | } |
985 | else | 975 | else |
986 | { | 976 | { |
987 | CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | 977 | CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); |
988 | } | 978 | } |
989 | } | 979 | } |
990 | 980 | ||
@@ -995,7 +985,7 @@ public class BSPrim : BSPhysObject | |||
995 | { | 985 | { |
996 | if (PhysBody.HasPhysicalBody) | 986 | if (PhysBody.HasPhysicalBody) |
997 | { | 987 | { |
998 | PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); | 988 | PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody); |
999 | } | 989 | } |
1000 | else | 990 | else |
1001 | { | 991 | { |
@@ -1030,12 +1020,12 @@ public class BSPrim : BSPhysObject | |||
1030 | public override bool FloatOnWater { | 1020 | public override bool FloatOnWater { |
1031 | set { | 1021 | set { |
1032 | _floatOnWater = value; | 1022 | _floatOnWater = value; |
1033 | PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() | 1023 | PhysScene.TaintedObject(LocalID, "BSPrim.setFloatOnWater", delegate() |
1034 | { | 1024 | { |
1035 | if (_floatOnWater) | 1025 | if (_floatOnWater) |
1036 | CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); | 1026 | CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); |
1037 | else | 1027 | else |
1038 | CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); | 1028 | CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); |
1039 | }); | 1029 | }); |
1040 | } | 1030 | } |
1041 | } | 1031 | } |
@@ -1047,7 +1037,7 @@ public class BSPrim : BSPhysObject | |||
1047 | _rotationalVelocity = value; | 1037 | _rotationalVelocity = value; |
1048 | Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity); | 1038 | Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity); |
1049 | // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); | 1039 | // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); |
1050 | PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() | 1040 | PhysScene.TaintedObject(LocalID, "BSPrim.setRotationalVelocity", delegate() |
1051 | { | 1041 | { |
1052 | ForceRotationalVelocity = _rotationalVelocity; | 1042 | ForceRotationalVelocity = _rotationalVelocity; |
1053 | }); | 1043 | }); |
@@ -1062,7 +1052,7 @@ public class BSPrim : BSPhysObject | |||
1062 | if (PhysBody.HasPhysicalBody) | 1052 | if (PhysBody.HasPhysicalBody) |
1063 | { | 1053 | { |
1064 | DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); | 1054 | DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); |
1065 | PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); | 1055 | PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); |
1066 | // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); | 1056 | // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); |
1067 | ActivateIfPhysical(false); | 1057 | ActivateIfPhysical(false); |
1068 | } | 1058 | } |
@@ -1078,7 +1068,7 @@ public class BSPrim : BSPhysObject | |||
1078 | get { return _buoyancy; } | 1068 | get { return _buoyancy; } |
1079 | set { | 1069 | set { |
1080 | _buoyancy = value; | 1070 | _buoyancy = value; |
1081 | PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() | 1071 | PhysScene.TaintedObject(LocalID, "BSPrim.setBuoyancy", delegate() |
1082 | { | 1072 | { |
1083 | ForceBuoyancy = _buoyancy; | 1073 | ForceBuoyancy = _buoyancy; |
1084 | }); | 1074 | }); |
@@ -1096,179 +1086,54 @@ public class BSPrim : BSPhysObject | |||
1096 | } | 1086 | } |
1097 | } | 1087 | } |
1098 | 1088 | ||
1099 | // Used for MoveTo | ||
1100 | public override OMV.Vector3 PIDTarget { | ||
1101 | set | ||
1102 | { | ||
1103 | // TODO: add a sanity check -- don't move more than a region or something like that. | ||
1104 | _PIDTarget = value; | ||
1105 | } | ||
1106 | } | ||
1107 | public override float PIDTau { | ||
1108 | set { _PIDTau = value; } | ||
1109 | } | ||
1110 | public override bool PIDActive { | 1089 | public override bool PIDActive { |
1111 | set { | 1090 | set { |
1112 | if (value) | 1091 | base.MoveToTargetActive = value; |
1092 | EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate() | ||
1113 | { | 1093 | { |
1114 | // We're taking over after this. | 1094 | return new BSActorMoveToTarget(PhysScene, this, MoveToTargetActorName); |
1115 | ZeroMotion(true); | 1095 | }); |
1116 | 1096 | } | |
1117 | _targetMotor = new BSVMotor("BSPrim.PIDTarget", | 1097 | } |
1118 | _PIDTau, // timeScale | ||
1119 | BSMotor.Infinite, // decay time scale | ||
1120 | BSMotor.InfiniteVector, // friction timescale | ||
1121 | 1f // efficiency | ||
1122 | ); | ||
1123 | _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
1124 | _targetMotor.SetTarget(_PIDTarget); | ||
1125 | _targetMotor.SetCurrent(RawPosition); | ||
1126 | /* | ||
1127 | _targetMotor = new BSPIDVMotor("BSPrim.PIDTarget"); | ||
1128 | _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
1129 | |||
1130 | _targetMotor.SetTarget(_PIDTarget); | ||
1131 | _targetMotor.SetCurrent(RawPosition); | ||
1132 | _targetMotor.TimeScale = _PIDTau; | ||
1133 | _targetMotor.Efficiency = 1f; | ||
1134 | */ | ||
1135 | |||
1136 | RegisterPreStepAction("BSPrim.PIDTarget", LocalID, delegate(float timeStep) | ||
1137 | { | ||
1138 | if (!IsPhysicallyActive) | ||
1139 | { | ||
1140 | UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID); | ||
1141 | return; | ||
1142 | } | ||
1143 | |||
1144 | OMV.Vector3 origPosition = RawPosition; // DEBUG DEBUG (for printout below) | ||
1145 | |||
1146 | // 'movePosition' is where we'd like the prim to be at this moment. | ||
1147 | OMV.Vector3 movePosition = RawPosition + _targetMotor.Step(timeStep); | ||
1148 | 1098 | ||
1149 | // If we are very close to our target, turn off the movement motor. | 1099 | public override OMV.Vector3 PIDTarget |
1150 | if (_targetMotor.ErrorIsZero()) | 1100 | { |
1151 | { | 1101 | set |
1152 | DetailLog("{0},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}", | 1102 | { |
1153 | LocalID, movePosition, RawPosition, Mass); | 1103 | base.PIDTarget = value; |
1154 | ForcePosition = _targetMotor.TargetValue; | 1104 | BSActor actor; |
1155 | _targetMotor.Enabled = false; | 1105 | if (PhysicalActors.TryGetActor(MoveToTargetActorName, out actor)) |
1156 | } | ||
1157 | else | ||
1158 | { | ||
1159 | _position = movePosition; | ||
1160 | PositionSanityCheck(true /* intaintTime */); | ||
1161 | ForcePosition = _position; | ||
1162 | } | ||
1163 | DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition); | ||
1164 | }); | ||
1165 | } | ||
1166 | else | ||
1167 | { | 1106 | { |
1168 | // Stop any targetting | 1107 | // if the actor exists, tell it to refresh its values. |
1169 | UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID); | 1108 | actor.Refresh(); |
1170 | } | 1109 | } |
1110 | |||
1171 | } | 1111 | } |
1172 | } | 1112 | } |
1173 | |||
1174 | // Used for llSetHoverHeight and maybe vehicle height | 1113 | // Used for llSetHoverHeight and maybe vehicle height |
1175 | // Hover Height will override MoveTo target's Z | 1114 | // Hover Height will override MoveTo target's Z |
1176 | public override bool PIDHoverActive { | 1115 | public override bool PIDHoverActive { |
1177 | set { | 1116 | set { |
1178 | if (value) | 1117 | base.HoverActive = value; |
1118 | EnableActor(HoverActive, HoverActorName, delegate() | ||
1179 | { | 1119 | { |
1180 | // Turning the target on | 1120 | return new BSActorHover(PhysScene, this, HoverActorName); |
1181 | _hoverMotor = new BSFMotor("BSPrim.Hover", | 1121 | }); |
1182 | _PIDHoverTau, // timeScale | ||
1183 | BSMotor.Infinite, // decay time scale | ||
1184 | BSMotor.Infinite, // friction timescale | ||
1185 | 1f // efficiency | ||
1186 | ); | ||
1187 | _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight()); | ||
1188 | _hoverMotor.SetCurrent(RawPosition.Z); | ||
1189 | _hoverMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
1190 | |||
1191 | RegisterPreStepAction("BSPrim.Hover", LocalID, delegate(float timeStep) | ||
1192 | { | ||
1193 | // Don't do hovering while the object is selected. | ||
1194 | if (!IsPhysicallyActive) | ||
1195 | return; | ||
1196 | |||
1197 | _hoverMotor.SetCurrent(RawPosition.Z); | ||
1198 | _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight()); | ||
1199 | float targetHeight = _hoverMotor.Step(timeStep); | ||
1200 | |||
1201 | // 'targetHeight' is where we'd like the Z of the prim to be at this moment. | ||
1202 | // Compute the amount of force to push us there. | ||
1203 | float moveForce = (targetHeight - RawPosition.Z) * Mass; | ||
1204 | // Undo anything the object thinks it's doing at the moment | ||
1205 | moveForce = -RawVelocity.Z * Mass; | ||
1206 | |||
1207 | PhysicsScene.PE.ApplyCentralImpulse(PhysBody, new OMV.Vector3(0f, 0f, moveForce)); | ||
1208 | DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}", LocalID, targetHeight, moveForce, Mass); | ||
1209 | }); | ||
1210 | } | ||
1211 | else | ||
1212 | { | ||
1213 | UnRegisterPreStepAction("BSPrim.Hover", LocalID); | ||
1214 | } | ||
1215 | } | ||
1216 | } | ||
1217 | public override float PIDHoverHeight { | ||
1218 | set { _PIDHoverHeight = value; } | ||
1219 | } | ||
1220 | public override PIDHoverType PIDHoverType { | ||
1221 | set { _PIDHoverType = value; } | ||
1222 | } | ||
1223 | public override float PIDHoverTau { | ||
1224 | set { _PIDHoverTau = value; } | ||
1225 | } | ||
1226 | // Based on current position, determine what we should be hovering at now. | ||
1227 | // Must recompute often. What if we walked offa cliff> | ||
1228 | private float ComputeCurrentPIDHoverHeight() | ||
1229 | { | ||
1230 | float ret = _PIDHoverHeight; | ||
1231 | float groundHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); | ||
1232 | |||
1233 | switch (_PIDHoverType) | ||
1234 | { | ||
1235 | case PIDHoverType.Ground: | ||
1236 | ret = groundHeight + _PIDHoverHeight; | ||
1237 | break; | ||
1238 | case PIDHoverType.GroundAndWater: | ||
1239 | float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition); | ||
1240 | if (groundHeight > waterHeight) | ||
1241 | { | ||
1242 | ret = groundHeight + _PIDHoverHeight; | ||
1243 | } | ||
1244 | else | ||
1245 | { | ||
1246 | ret = waterHeight + _PIDHoverHeight; | ||
1247 | } | ||
1248 | break; | ||
1249 | } | 1122 | } |
1250 | return ret; | ||
1251 | } | 1123 | } |
1252 | 1124 | ||
1253 | |||
1254 | // For RotLookAt | ||
1255 | public override OMV.Quaternion APIDTarget { set { return; } } | ||
1256 | public override bool APIDActive { set { return; } } | ||
1257 | public override float APIDStrength { set { return; } } | ||
1258 | public override float APIDDamping { set { return; } } | ||
1259 | |||
1260 | public override void AddForce(OMV.Vector3 force, bool pushforce) { | 1125 | public override void AddForce(OMV.Vector3 force, bool pushforce) { |
1261 | // Per documentation, max force is limited. | 1126 | // Per documentation, max force is limited. |
1262 | OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); | 1127 | OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); |
1263 | 1128 | ||
1264 | // Since this force is being applied in only one step, make this a force per second. | 1129 | // Since this force is being applied in only one step, make this a force per second. |
1265 | addForce /= PhysicsScene.LastTimeStep; | 1130 | addForce /= PhysScene.LastTimeStep; |
1266 | AddForce(addForce, pushforce, false /* inTaintTime */); | 1131 | AddForce(addForce, pushforce, false /* inTaintTime */); |
1267 | } | 1132 | } |
1268 | 1133 | ||
1269 | // Applying a force just adds this to the total force on the object. | 1134 | // Applying a force just adds this to the total force on the object. |
1270 | // This added force will only last the next simulation tick. | 1135 | // This added force will only last the next simulation tick. |
1271 | public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { | 1136 | public override void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { |
1272 | // for an object, doesn't matter if force is a pushforce or not | 1137 | // for an object, doesn't matter if force is a pushforce or not |
1273 | if (IsPhysicallyActive) | 1138 | if (IsPhysicallyActive) |
1274 | { | 1139 | { |
@@ -1277,13 +1142,15 @@ public class BSPrim : BSPhysObject | |||
1277 | // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); | 1142 | // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); |
1278 | 1143 | ||
1279 | OMV.Vector3 addForce = force; | 1144 | OMV.Vector3 addForce = force; |
1280 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() | 1145 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddForce", delegate() |
1281 | { | 1146 | { |
1282 | // Bullet adds this central force to the total force for this tick | 1147 | // Bullet adds this central force to the total force for this tick. |
1148 | // Deep down in Bullet: | ||
1149 | // linearVelocity += totalForce / mass * timeStep; | ||
1283 | DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce); | 1150 | DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce); |
1284 | if (PhysBody.HasPhysicalBody) | 1151 | if (PhysBody.HasPhysicalBody) |
1285 | { | 1152 | { |
1286 | PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); | 1153 | PhysScene.PE.ApplyCentralForce(PhysBody, addForce); |
1287 | ActivateIfPhysical(false); | 1154 | ActivateIfPhysical(false); |
1288 | } | 1155 | } |
1289 | }); | 1156 | }); |
@@ -1305,13 +1172,13 @@ public class BSPrim : BSPhysObject | |||
1305 | OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude); | 1172 | OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude); |
1306 | // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse); | 1173 | // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse); |
1307 | 1174 | ||
1308 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate() | 1175 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddImpulse", delegate() |
1309 | { | 1176 | { |
1310 | // Bullet adds this impulse immediately to the velocity | 1177 | // Bullet adds this impulse immediately to the velocity |
1311 | DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse); | 1178 | DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse); |
1312 | if (PhysBody.HasPhysicalBody) | 1179 | if (PhysBody.HasPhysicalBody) |
1313 | { | 1180 | { |
1314 | PhysicsScene.PE.ApplyCentralImpulse(PhysBody, addImpulse); | 1181 | PhysScene.PE.ApplyCentralImpulse(PhysBody, addImpulse); |
1315 | ActivateIfPhysical(false); | 1182 | ActivateIfPhysical(false); |
1316 | } | 1183 | } |
1317 | }); | 1184 | }); |
@@ -1324,20 +1191,18 @@ public class BSPrim : BSPhysObject | |||
1324 | } | 1191 | } |
1325 | } | 1192 | } |
1326 | 1193 | ||
1327 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { | 1194 | // BSPhysObject.AddAngularForce() |
1328 | AddAngularForce(force, pushforce, false); | 1195 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) |
1329 | } | ||
1330 | public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) | ||
1331 | { | 1196 | { |
1332 | if (force.IsFinite()) | 1197 | if (force.IsFinite()) |
1333 | { | 1198 | { |
1334 | OMV.Vector3 angForce = force; | 1199 | OMV.Vector3 angForce = force; |
1335 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() | 1200 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddAngularForce", delegate() |
1336 | { | 1201 | { |
1337 | if (PhysBody.HasPhysicalBody) | 1202 | if (PhysBody.HasPhysicalBody) |
1338 | { | 1203 | { |
1339 | DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce); | 1204 | DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce); |
1340 | PhysicsScene.PE.ApplyTorque(PhysBody, angForce); | 1205 | PhysScene.PE.ApplyTorque(PhysBody, angForce); |
1341 | ActivateIfPhysical(false); | 1206 | ActivateIfPhysical(false); |
1342 | } | 1207 | } |
1343 | }); | 1208 | }); |
@@ -1356,11 +1221,11 @@ public class BSPrim : BSPhysObject | |||
1356 | public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) | 1221 | public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) |
1357 | { | 1222 | { |
1358 | OMV.Vector3 applyImpulse = impulse; | 1223 | OMV.Vector3 applyImpulse = impulse; |
1359 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() | 1224 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ApplyTorqueImpulse", delegate() |
1360 | { | 1225 | { |
1361 | if (PhysBody.HasPhysicalBody) | 1226 | if (PhysBody.HasPhysicalBody) |
1362 | { | 1227 | { |
1363 | PhysicsScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse); | 1228 | PhysScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse); |
1364 | ActivateIfPhysical(false); | 1229 | ActivateIfPhysical(false); |
1365 | } | 1230 | } |
1366 | }); | 1231 | }); |
@@ -1649,6 +1514,8 @@ public class BSPrim : BSPhysObject | |||
1649 | 1514 | ||
1650 | returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); | 1515 | returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); |
1651 | // DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass); | 1516 | // DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass); |
1517 | DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3},pathB={4},pathE={5},profB={6},profE={7},siz={8}", | ||
1518 | LocalID, Density, volume, returnMass, pathBegin, pathEnd, profileBegin, profileEnd, _size); | ||
1652 | 1519 | ||
1653 | return returnMass; | 1520 | return returnMass; |
1654 | }// end CalculateMass | 1521 | }// end CalculateMass |
@@ -1661,13 +1528,14 @@ public class BSPrim : BSPhysObject | |||
1661 | { | 1528 | { |
1662 | // Create the correct physical representation for this type of object. | 1529 | // Create the correct physical representation for this type of object. |
1663 | // Updates base.PhysBody and base.PhysShape with the new information. | 1530 | // Updates base.PhysBody and base.PhysShape with the new information. |
1664 | // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. | 1531 | // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary. |
1665 | PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody) | 1532 | PhysScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysScene.World, this, delegate(BulletBody pBody, BulletShape pShape) |
1666 | { | 1533 | { |
1667 | // Called if the current prim body is about to be destroyed. | 1534 | // Called if the current prim body is about to be destroyed. |
1668 | // Remove all the physical dependencies on the old body. | 1535 | // Remove all the physical dependencies on the old body. |
1669 | // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) | 1536 | // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) |
1670 | RemoveBodyDependencies(); | 1537 | // Note: this virtual function is overloaded by BSPrimLinkable to remove linkset constraints. |
1538 | RemoveDependencies(); | ||
1671 | }); | 1539 | }); |
1672 | 1540 | ||
1673 | // Make sure the properties are set on the new object | 1541 | // Make sure the properties are set on the new object |
@@ -1675,27 +1543,45 @@ public class BSPrim : BSPhysObject | |||
1675 | return; | 1543 | return; |
1676 | } | 1544 | } |
1677 | 1545 | ||
1678 | protected virtual void RemoveBodyDependencies() | 1546 | // Called at taint-time |
1547 | protected virtual void RemoveDependencies() | ||
1548 | { | ||
1549 | PhysicalActors.RemoveDependencies(); | ||
1550 | } | ||
1551 | |||
1552 | #region Extension | ||
1553 | public override object Extension(string pFunct, params object[] pParams) | ||
1679 | { | 1554 | { |
1680 | VehicleActor.RemoveBodyDependencies(); | 1555 | DetailLog("{0} BSPrim.Extension,op={1}", LocalID, pFunct); |
1681 | PhysicalActors.RemoveBodyDependencies(); | 1556 | object ret = null; |
1557 | switch (pFunct) | ||
1558 | { | ||
1559 | default: | ||
1560 | ret = base.Extension(pFunct, pParams); | ||
1561 | break; | ||
1562 | } | ||
1563 | return ret; | ||
1682 | } | 1564 | } |
1565 | #endregion // Extension | ||
1683 | 1566 | ||
1684 | // The physics engine says that properties have updated. Update same and inform | 1567 | // The physics engine says that properties have updated. Update same and inform |
1685 | // the world that things have changed. | 1568 | // the world that things have changed. |
1569 | // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimLinkable which modifies updates from root and children prims. | ||
1570 | // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimDisplaced which handles mapping physical position to simulator position. | ||
1686 | public override void UpdateProperties(EntityProperties entprop) | 1571 | public override void UpdateProperties(EntityProperties entprop) |
1687 | { | 1572 | { |
1573 | // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator. | ||
1688 | TriggerPreUpdatePropertyAction(ref entprop); | 1574 | TriggerPreUpdatePropertyAction(ref entprop); |
1689 | 1575 | ||
1690 | // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG | 1576 | // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG |
1691 | 1577 | ||
1692 | // Assign directly to the local variables so the normal set actions do not happen | 1578 | // Assign directly to the local variables so the normal set actions do not happen |
1693 | _position = entprop.Position; | 1579 | RawPosition = entprop.Position; |
1694 | _orientation = entprop.Rotation; | 1580 | RawOrientation = entprop.Rotation; |
1695 | // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be | 1581 | // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be |
1696 | // very sensitive to velocity changes. | 1582 | // very sensitive to velocity changes. |
1697 | if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(_velocity, BSParam.UpdateVelocityChangeThreshold)) | 1583 | if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(RawVelocity, BSParam.UpdateVelocityChangeThreshold)) |
1698 | _velocity = entprop.Velocity; | 1584 | RawVelocity = entprop.Velocity; |
1699 | _acceleration = entprop.Acceleration; | 1585 | _acceleration = entprop.Acceleration; |
1700 | _rotationalVelocity = entprop.RotationalVelocity; | 1586 | _rotationalVelocity = entprop.RotationalVelocity; |
1701 | 1587 | ||
@@ -1704,29 +1590,20 @@ public class BSPrim : BSPhysObject | |||
1704 | // The sanity check can change the velocity and/or position. | 1590 | // The sanity check can change the velocity and/or position. |
1705 | if (PositionSanityCheck(true /* inTaintTime */ )) | 1591 | if (PositionSanityCheck(true /* inTaintTime */ )) |
1706 | { | 1592 | { |
1707 | entprop.Position = _position; | 1593 | entprop.Position = RawPosition; |
1708 | entprop.Velocity = _velocity; | 1594 | entprop.Velocity = RawVelocity; |
1709 | entprop.RotationalVelocity = _rotationalVelocity; | 1595 | entprop.RotationalVelocity = _rotationalVelocity; |
1710 | entprop.Acceleration = _acceleration; | 1596 | entprop.Acceleration = _acceleration; |
1711 | } | 1597 | } |
1712 | 1598 | ||
1713 | OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG | 1599 | OMV.Vector3 direction = OMV.Vector3.UnitX * RawOrientation; // DEBUG DEBUG DEBUG |
1714 | DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction); | 1600 | DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction); |
1715 | 1601 | ||
1716 | // remember the current and last set values | 1602 | // remember the current and last set values |
1717 | LastEntityProperties = CurrentEntityProperties; | 1603 | LastEntityProperties = CurrentEntityProperties; |
1718 | CurrentEntityProperties = entprop; | 1604 | CurrentEntityProperties = entprop; |
1719 | 1605 | ||
1720 | base.RequestPhysicsterseUpdate(); | 1606 | PhysScene.PostUpdate(this); |
1721 | /* | ||
1722 | else | ||
1723 | { | ||
1724 | // For debugging, report the movement of children | ||
1725 | DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | ||
1726 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, | ||
1727 | entprop.Acceleration, entprop.RotationalVelocity); | ||
1728 | } | ||
1729 | */ | ||
1730 | } | 1607 | } |
1731 | } | 1608 | } |
1732 | } | 1609 | } |