diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 814 |
1 files changed, 305 insertions, 509 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 6a5461a..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,16 +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 VehicleController { get; private set; } | 68 | // Keep a handle to the vehicle actor so it is easy to set parameters on same. |
76 | 69 | public const string VehicleActorName = "BasicVehicle"; | |
77 | private BSVMotor _targetMotor; | ||
78 | private OMV.Vector3 _PIDTarget; | ||
79 | private float _PIDTau; | ||
80 | 70 | ||
81 | private BSFMotor _hoverMotor; | 71 | // Parameters for the hover actor |
82 | private float _PIDHoverHeight; | 72 | public const string HoverActorName = "BSPrim.HoverActor"; |
83 | private PIDHoverType _PIDHoverType; | 73 | // Parameters for the axis lock actor |
84 | 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"; | ||
85 | 80 | ||
86 | 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, |
87 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) | 82 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) |
@@ -89,31 +84,34 @@ public class BSPrim : BSPhysObject | |||
89 | { | 84 | { |
90 | // 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); |
91 | _physicsActorType = (int)ActorTypes.Prim; | 86 | _physicsActorType = (int)ActorTypes.Prim; |
92 | _position = pos; | 87 | RawPosition = pos; |
93 | _size = size; | 88 | _size = size; |
94 | 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). |
95 | _orientation = rotation; | 90 | RawOrientation = rotation; |
96 | _buoyancy = 0f; | 91 | _buoyancy = 0f; |
97 | _velocity = OMV.Vector3.Zero; | 92 | RawVelocity = OMV.Vector3.Zero; |
98 | _rotationalVelocity = OMV.Vector3.Zero; | 93 | _rotationalVelocity = OMV.Vector3.Zero; |
99 | BaseShape = pbs; | 94 | BaseShape = pbs; |
100 | _isPhysical = pisPhysical; | 95 | _isPhysical = pisPhysical; |
101 | _isVolumeDetect = false; | 96 | _isVolumeDetect = false; |
102 | 97 | ||
103 | VehicleController = new BSDynamics(PhysicsScene, this); // add vehicleness | 98 | // Add a dynamic vehicle to our set of actors that can move this prim. |
99 | // PhysicalActors.Add(VehicleActorName, new BSDynamics(PhysScene, this, VehicleActorName)); | ||
104 | 100 | ||
105 | _mass = CalculateMass(); | 101 | _mass = CalculateMass(); |
106 | 102 | ||
107 | DetailLog("{0},BSPrim.constructor,call", LocalID); | 103 | // DetailLog("{0},BSPrim.constructor,call", LocalID); |
108 | // do the actual object creation at taint time | 104 | // do the actual object creation at taint time |
109 | PhysicsScene.TaintedObject("BSPrim.create", delegate() | 105 | PhysScene.TaintedObject(LocalID, "BSPrim.create", delegate() |
110 | { | 106 | { |
111 | // Make sure the object is being created with some sanity. | 107 | // Make sure the object is being created with some sanity. |
112 | ExtremeSanityCheck(true /* inTaintTime */); | 108 | ExtremeSanityCheck(true /* inTaintTime */); |
113 | 109 | ||
114 | CreateGeomAndObject(true); | 110 | CreateGeomAndObject(true); |
115 | 111 | ||
116 | CurrentCollisionFlags = PhysicsScene.PE.GetCollisionFlags(PhysBody); | 112 | CurrentCollisionFlags = PhysScene.PE.GetCollisionFlags(PhysBody); |
113 | |||
114 | IsInitialized = true; | ||
117 | }); | 115 | }); |
118 | } | 116 | } |
119 | 117 | ||
@@ -121,19 +119,21 @@ public class BSPrim : BSPhysObject | |||
121 | public override void Destroy() | 119 | public override void Destroy() |
122 | { | 120 | { |
123 | // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); | 121 | // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); |
122 | IsInitialized = false; | ||
123 | |||
124 | base.Destroy(); | 124 | base.Destroy(); |
125 | 125 | ||
126 | // Undo any vehicle properties | 126 | // Undo any vehicle properties |
127 | this.VehicleType = (int)Vehicle.TYPE_NONE; | 127 | this.VehicleType = (int)Vehicle.TYPE_NONE; |
128 | 128 | ||
129 | PhysicsScene.TaintedObject("BSPrim.destroy", delegate() | 129 | PhysScene.TaintedObject(LocalID, "BSPrim.Destroy", delegate() |
130 | { | 130 | { |
131 | DetailLog("{0},BSPrim.Destroy,taint,", LocalID); | 131 | DetailLog("{0},BSPrim.Destroy,taint,", LocalID); |
132 | // 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. |
133 | PhysicsScene.Shapes.DereferenceBody(PhysBody, null); | 133 | PhysScene.Shapes.DereferenceBody(PhysBody, null); |
134 | PhysBody.Clear(); | 134 | PhysBody.Clear(); |
135 | PhysicsScene.Shapes.DereferenceShape(PhysShape, null); | 135 | PhysShape.Dereference(PhysScene); |
136 | PhysShape.Clear(); | 136 | PhysShape = new BSShapeNull(); |
137 | }); | 137 | }); |
138 | } | 138 | } |
139 | 139 | ||
@@ -159,25 +159,13 @@ public class BSPrim : BSPhysObject | |||
159 | ForceBodyShapeRebuild(false); | 159 | ForceBodyShapeRebuild(false); |
160 | } | 160 | } |
161 | } | 161 | } |
162 | // 'unknown' says to choose the best type | ||
163 | public override BSPhysicsShapeType PreferredPhysicalShape | ||
164 | { get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } } | ||
165 | |||
166 | public override bool ForceBodyShapeRebuild(bool inTaintTime) | 162 | public override bool ForceBodyShapeRebuild(bool inTaintTime) |
167 | { | 163 | { |
168 | if (inTaintTime) | 164 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ForceBodyShapeRebuild", delegate() |
169 | { | 165 | { |
170 | _mass = CalculateMass(); // changing the shape changes the mass | 166 | _mass = CalculateMass(); // changing the shape changes the mass |
171 | CreateGeomAndObject(true); | 167 | CreateGeomAndObject(true); |
172 | } | 168 | }); |
173 | else | ||
174 | { | ||
175 | PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate() | ||
176 | { | ||
177 | _mass = CalculateMass(); // changing the shape changes the mass | ||
178 | CreateGeomAndObject(true); | ||
179 | }); | ||
180 | } | ||
181 | return true; | 169 | return true; |
182 | } | 170 | } |
183 | public override bool Grabbed { | 171 | public override bool Grabbed { |
@@ -190,7 +178,7 @@ public class BSPrim : BSPhysObject | |||
190 | if (value != _isSelected) | 178 | if (value != _isSelected) |
191 | { | 179 | { |
192 | _isSelected = value; | 180 | _isSelected = value; |
193 | PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() | 181 | PhysScene.TaintedObject(LocalID, "BSPrim.setSelected", delegate() |
194 | { | 182 | { |
195 | DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); | 183 | DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); |
196 | SetObjectDynamic(false); | 184 | SetObjectDynamic(false); |
@@ -231,165 +219,93 @@ public class BSPrim : BSPhysObject | |||
231 | // Called at taint time! | 219 | // Called at taint time! |
232 | public override void ZeroMotion(bool inTaintTime) | 220 | public override void ZeroMotion(bool inTaintTime) |
233 | { | 221 | { |
234 | _velocity = OMV.Vector3.Zero; | 222 | RawVelocity = OMV.Vector3.Zero; |
235 | _acceleration = OMV.Vector3.Zero; | 223 | _acceleration = OMV.Vector3.Zero; |
236 | _rotationalVelocity = OMV.Vector3.Zero; | 224 | _rotationalVelocity = OMV.Vector3.Zero; |
237 | 225 | ||
238 | // Zero some other properties in the physics engine | 226 | // Zero some other properties in the physics engine |
239 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() | 227 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate() |
240 | { | 228 | { |
241 | if (PhysBody.HasPhysicalBody) | 229 | if (PhysBody.HasPhysicalBody) |
242 | PhysicsScene.PE.ClearAllForces(PhysBody); | 230 | PhysScene.PE.ClearAllForces(PhysBody); |
243 | }); | 231 | }); |
244 | } | 232 | } |
245 | public override void ZeroAngularMotion(bool inTaintTime) | 233 | public override void ZeroAngularMotion(bool inTaintTime) |
246 | { | 234 | { |
247 | _rotationalVelocity = OMV.Vector3.Zero; | 235 | _rotationalVelocity = OMV.Vector3.Zero; |
248 | // Zero some other properties in the physics engine | 236 | // Zero some other properties in the physics engine |
249 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() | 237 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate() |
250 | { | 238 | { |
251 | // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); | 239 | // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); |
252 | if (PhysBody.HasPhysicalBody) | 240 | if (PhysBody.HasPhysicalBody) |
253 | { | 241 | { |
254 | PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); | 242 | PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); |
255 | PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); | 243 | PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); |
256 | } | 244 | } |
257 | }); | 245 | }); |
258 | } | 246 | } |
259 | 247 | ||
260 | bool TryExperimentalLockAxisCode = false; | ||
261 | BSConstraint LockAxisConstraint = null; | ||
262 | public override void LockAngularMotion(OMV.Vector3 axis) | 248 | public override void LockAngularMotion(OMV.Vector3 axis) |
263 | { | 249 | { |
264 | DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); | 250 | DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); |
265 | 251 | ||
266 | // "1" means free, "0" means locked | 252 | // "1" means free, "0" means locked |
267 | OMV.Vector3 locking = new OMV.Vector3(1f, 1f, 1f); | 253 | OMV.Vector3 locking = LockedAxisFree; |
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 (TryExperimentalLockAxisCode && LockedAxis != LockedAxisFree) | 259 | EnableActor(LockedAngularAxis != LockedAxisFree, LockedAxisActorName, delegate() |
274 | { | 260 | { |
275 | // Lock that axis by creating a 6DOF constraint that has one end in the world and | 261 | return new BSActorLockAxis(PhysScene, this, LockedAxisActorName); |
276 | // the other in the object. | 262 | }); |
277 | // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817 | ||
278 | // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380 | ||
279 | |||
280 | PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate() | ||
281 | { | ||
282 | CleanUpLockAxisPhysicals(true /* inTaintTime */); | ||
283 | |||
284 | BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(PhysicsScene.World, PhysBody, | ||
285 | OMV.Vector3.Zero, OMV.Quaternion.Inverse(RawOrientation), | ||
286 | true /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */); | ||
287 | LockAxisConstraint = axisConstrainer; | ||
288 | PhysicsScene.Constraints.AddConstraint(LockAxisConstraint); | ||
289 | |||
290 | // The constraint is tied to the world and oriented to the prim. | ||
291 | |||
292 | // Free to move linearly | ||
293 | OMV.Vector3 linearLow = OMV.Vector3.Zero; | ||
294 | OMV.Vector3 linearHigh = PhysicsScene.TerrainManager.DefaultRegionSize; | ||
295 | axisConstrainer.SetLinearLimits(linearLow, linearHigh); | ||
296 | |||
297 | // Angular with some axis locked | ||
298 | float f2PI = (float)Math.PI * 2f; | ||
299 | OMV.Vector3 angularLow = new OMV.Vector3(-f2PI, -f2PI, -f2PI); | ||
300 | OMV.Vector3 angularHigh = new OMV.Vector3(f2PI, f2PI, f2PI); | ||
301 | if (LockedAxis.X != 1f) | ||
302 | { | ||
303 | angularLow.X = 0f; | ||
304 | angularHigh.X = 0f; | ||
305 | } | ||
306 | if (LockedAxis.Y != 1f) | ||
307 | { | ||
308 | angularLow.Y = 0f; | ||
309 | angularHigh.Y = 0f; | ||
310 | } | ||
311 | if (LockedAxis.Z != 1f) | ||
312 | { | ||
313 | angularLow.Z = 0f; | ||
314 | angularHigh.Z = 0f; | ||
315 | } | ||
316 | axisConstrainer.SetAngularLimits(angularLow, angularHigh); | ||
317 | |||
318 | DetailLog("{0},BSPrim.LockAngularMotion,create,linLow={1},linHi={2},angLow={3},angHi={4}", | ||
319 | LocalID, linearLow, linearHigh, angularLow, angularHigh); | ||
320 | |||
321 | // Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo. | ||
322 | axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f); | ||
323 | 263 | ||
324 | axisConstrainer.RecomputeConstraintVariables(RawMass); | 264 | // Update parameters so the new actor's Refresh() action is called at the right time. |
325 | }); | 265 | PhysScene.TaintedObject(LocalID, "BSPrim.LockAngularMotion", delegate() |
326 | } | ||
327 | else | ||
328 | { | 266 | { |
329 | // Everything seems unlocked | 267 | UpdatePhysicalParameters(); |
330 | CleanUpLockAxisPhysicals(false /* inTaintTime */); | 268 | }); |
331 | } | ||
332 | 269 | ||
333 | return; | 270 | return; |
334 | } | 271 | } |
335 | // Get rid of any constraint built for LockAxis | ||
336 | // Most often the constraint is removed when the constraint collection is cleaned for this prim. | ||
337 | private void CleanUpLockAxisPhysicals(bool inTaintTime) | ||
338 | { | ||
339 | if (LockAxisConstraint != null) | ||
340 | { | ||
341 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.CleanUpLockAxisPhysicals", delegate() | ||
342 | { | ||
343 | if (LockAxisConstraint != null) | ||
344 | { | ||
345 | PhysicsScene.Constraints.RemoveAndDestroyConstraint(LockAxisConstraint); | ||
346 | LockAxisConstraint = null; | ||
347 | DetailLog("{0},BSPrim.CleanUpLockAxisPhysicals,destroyingConstraint", LocalID); | ||
348 | } | ||
349 | }); | ||
350 | } | ||
351 | } | ||
352 | 272 | ||
353 | public override OMV.Vector3 RawPosition | ||
354 | { | ||
355 | get { return _position; } | ||
356 | set { _position = value; } | ||
357 | } | ||
358 | public override OMV.Vector3 Position { | 273 | public override OMV.Vector3 Position { |
359 | get { | 274 | get { |
360 | // 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. |
361 | // _position = ForcePosition; | 276 | // RawPosition = ForcePosition; |
362 | return _position; | 277 | return RawPosition; |
363 | } | 278 | } |
364 | set { | 279 | set { |
365 | // 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. |
366 | // All positions are given in world positions. | 281 | // All positions are given in world positions. |
367 | if (_position == value) | 282 | if (RawPosition == value) |
368 | { | 283 | { |
369 | 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); |
370 | return; | 285 | return; |
371 | } | 286 | } |
372 | _position = value; | 287 | RawPosition = value; |
373 | PositionSanityCheck(false); | 288 | PositionSanityCheck(false); |
374 | 289 | ||
375 | PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() | 290 | PhysScene.TaintedObject(LocalID, "BSPrim.setPosition", delegate() |
376 | { | 291 | { |
377 | 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); |
378 | ForcePosition = _position; | 293 | ForcePosition = RawPosition; |
379 | }); | 294 | }); |
380 | } | 295 | } |
381 | } | 296 | } |
382 | 297 | ||
298 | // NOTE: overloaded by BSPrimDisplaced to handle offset for center-of-gravity. | ||
383 | public override OMV.Vector3 ForcePosition { | 299 | public override OMV.Vector3 ForcePosition { |
384 | get { | 300 | get { |
385 | _position = PhysicsScene.PE.GetPosition(PhysBody); | 301 | RawPosition = PhysScene.PE.GetPosition(PhysBody); |
386 | return _position; | 302 | return RawPosition; |
387 | } | 303 | } |
388 | set { | 304 | set { |
389 | _position = value; | 305 | RawPosition = value; |
390 | if (PhysBody.HasPhysicalBody) | 306 | if (PhysBody.HasPhysicalBody) |
391 | { | 307 | { |
392 | PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); | 308 | PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation); |
393 | ActivateIfPhysical(false); | 309 | ActivateIfPhysical(false); |
394 | } | 310 | } |
395 | } | 311 | } |
@@ -406,7 +322,7 @@ public class BSPrim : BSPhysObject | |||
406 | if (!IsPhysicallyActive) | 322 | if (!IsPhysicallyActive) |
407 | return ret; | 323 | return ret; |
408 | 324 | ||
409 | if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) | 325 | if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) |
410 | { | 326 | { |
411 | // The physical object is out of the known/simulated area. | 327 | // The physical object is out of the known/simulated area. |
412 | // 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 |
@@ -414,7 +330,7 @@ public class BSPrim : BSPhysObject | |||
414 | return ret; | 330 | return ret; |
415 | } | 331 | } |
416 | 332 | ||
417 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); | 333 | float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); |
418 | OMV.Vector3 upForce = OMV.Vector3.Zero; | 334 | OMV.Vector3 upForce = OMV.Vector3.Zero; |
419 | 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)); |
420 | if ((RawPosition.Z + approxSize / 2f) < terrainHeight) | 336 | if ((RawPosition.Z + approxSize / 2f) < terrainHeight) |
@@ -423,10 +339,10 @@ public class BSPrim : BSPhysObject | |||
423 | float targetHeight = terrainHeight + (Size.Z / 2f); | 339 | float targetHeight = terrainHeight + (Size.Z / 2f); |
424 | // 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 |
425 | // not get it through the terrain | 341 | // not get it through the terrain |
426 | _position.Z = targetHeight; | 342 | RawPosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, targetHeight); |
427 | if (inTaintTime) | 343 | if (inTaintTime) |
428 | { | 344 | { |
429 | ForcePosition = _position; | 345 | ForcePosition = RawPosition; |
430 | } | 346 | } |
431 | // If we are throwing the object around, zero its other forces | 347 | // If we are throwing the object around, zero its other forces |
432 | ZeroMotion(inTaintTime); | 348 | ZeroMotion(inTaintTime); |
@@ -435,7 +351,7 @@ public class BSPrim : BSPhysObject | |||
435 | 351 | ||
436 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) | 352 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) |
437 | { | 353 | { |
438 | float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); | 354 | float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition); |
439 | // TODO: a floating motor so object will bob in the water | 355 | // TODO: a floating motor so object will bob in the water |
440 | if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) | 356 | if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) |
441 | { | 357 | { |
@@ -443,8 +359,8 @@ public class BSPrim : BSPhysObject | |||
443 | upForce.Z = (waterHeight - RawPosition.Z) * 1f; | 359 | upForce.Z = (waterHeight - RawPosition.Z) * 1f; |
444 | 360 | ||
445 | // Apply upforce and overcome gravity. | 361 | // Apply upforce and overcome gravity. |
446 | OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity; | 362 | OMV.Vector3 correctionForce = upForce - PhysScene.DefaultGravity; |
447 | 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); |
448 | AddForce(correctionForce, false, inTaintTime); | 364 | AddForce(correctionForce, false, inTaintTime); |
449 | ret = true; | 365 | ret = true; |
450 | } | 366 | } |
@@ -463,17 +379,17 @@ public class BSPrim : BSPhysObject | |||
463 | uint wayOutThere = Constants.RegionSize * Constants.RegionSize; | 379 | uint wayOutThere = Constants.RegionSize * Constants.RegionSize; |
464 | // 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 |
465 | // the border crossing code. | 381 | // the border crossing code. |
466 | if ( _position.X < -Constants.RegionSize || _position.X > wayOutThere | 382 | if ( RawPosition.X < -Constants.RegionSize || RawPosition.X > wayOutThere |
467 | || _position.Y < -Constants.RegionSize || _position.Y > wayOutThere | 383 | || RawPosition.Y < -Constants.RegionSize || RawPosition.Y > wayOutThere |
468 | || _position.Z < -Constants.RegionSize || _position.Z > wayOutThere) | 384 | || RawPosition.Z < -Constants.RegionSize || RawPosition.Z > wayOutThere) |
469 | { | 385 | { |
470 | _position = new OMV.Vector3(10, 10, 50); | 386 | RawPosition = new OMV.Vector3(10, 10, 50); |
471 | ZeroMotion(inTaintTime); | 387 | ZeroMotion(inTaintTime); |
472 | ret = true; | 388 | ret = true; |
473 | } | 389 | } |
474 | if (_velocity.LengthSquared() > BSParam.MaxLinearVelocity) | 390 | if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocity) |
475 | { | 391 | { |
476 | _velocity = Util.ClampV(_velocity, BSParam.MaxLinearVelocity); | 392 | RawVelocity = Util.ClampV(RawVelocity, BSParam.MaxLinearVelocity); |
477 | ret = true; | 393 | ret = true; |
478 | } | 394 | } |
479 | if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared) | 395 | if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared) |
@@ -498,7 +414,7 @@ public class BSPrim : BSPhysObject | |||
498 | get { return _mass; } | 414 | get { return _mass; } |
499 | } | 415 | } |
500 | // 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 |
501 | public override float RawMass { | 417 | public override float RawMass { |
502 | get { return _mass; } | 418 | get { return _mass; } |
503 | } | 419 | } |
504 | // Set the physical mass to the passed mass. | 420 | // Set the physical mass to the passed mass. |
@@ -509,10 +425,10 @@ public class BSPrim : BSPhysObject | |||
509 | { | 425 | { |
510 | if (IsStatic) | 426 | if (IsStatic) |
511 | { | 427 | { |
512 | PhysicsScene.PE.SetGravity(PhysBody, PhysicsScene.DefaultGravity); | 428 | PhysScene.PE.SetGravity(PhysBody, PhysScene.DefaultGravity); |
513 | Inertia = OMV.Vector3.Zero; | 429 | Inertia = OMV.Vector3.Zero; |
514 | PhysicsScene.PE.SetMassProps(PhysBody, 0f, Inertia); | 430 | PhysScene.PE.SetMassProps(PhysBody, 0f, Inertia); |
515 | PhysicsScene.PE.UpdateInertiaTensor(PhysBody); | 431 | PhysScene.PE.UpdateInertiaTensor(PhysBody); |
516 | } | 432 | } |
517 | else | 433 | else |
518 | { | 434 | { |
@@ -521,16 +437,19 @@ public class BSPrim : BSPhysObject | |||
521 | // Changing interesting properties doesn't change proxy and collision cache | 437 | // Changing interesting properties doesn't change proxy and collision cache |
522 | // 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 |
523 | // after parameters are changed. | 439 | // after parameters are changed. |
524 | PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); | 440 | PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody); |
525 | } | 441 | } |
526 | 442 | ||
527 | // 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. |
528 | Gravity = ComputeGravity(Buoyancy); | 444 | Gravity = ComputeGravity(Buoyancy); |
529 | PhysicsScene.PE.SetGravity(PhysBody, Gravity); | 445 | PhysScene.PE.SetGravity(PhysBody, Gravity); |
530 | 446 | ||
531 | Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); | 447 | // OMV.Vector3 currentScale = PhysScene.PE.GetLocalScaling(PhysShape.physShapeInfo); // DEBUG DEBUG |
532 | PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia); | 448 | // DetailLog("{0},BSPrim.UpdateMassProperties,currentScale{1},shape={2}", LocalID, currentScale, PhysShape.physShapeInfo); // DEBUG DEBUG |
533 | PhysicsScene.PE.UpdateInertiaTensor(PhysBody); | 449 | |
450 | Inertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass); | ||
451 | PhysScene.PE.SetMassProps(PhysBody, physMass, Inertia); | ||
452 | PhysScene.PE.UpdateInertiaTensor(PhysBody); | ||
534 | 453 | ||
535 | 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}", |
536 | LocalID, physMass, Inertia, Gravity, inWorld); | 455 | LocalID, physMass, Inertia, Gravity, inWorld); |
@@ -546,7 +465,7 @@ public class BSPrim : BSPhysObject | |||
546 | // Return what gravity should be set to this very moment | 465 | // Return what gravity should be set to this very moment |
547 | public OMV.Vector3 ComputeGravity(float buoyancy) | 466 | public OMV.Vector3 ComputeGravity(float buoyancy) |
548 | { | 467 | { |
549 | OMV.Vector3 ret = PhysicsScene.DefaultGravity; | 468 | OMV.Vector3 ret = PhysScene.DefaultGravity; |
550 | 469 | ||
551 | if (!IsStatic) | 470 | if (!IsStatic) |
552 | { | 471 | { |
@@ -570,95 +489,121 @@ public class BSPrim : BSPhysObject | |||
570 | } | 489 | } |
571 | 490 | ||
572 | public override OMV.Vector3 Force { | 491 | public override OMV.Vector3 Force { |
573 | get { return _force; } | 492 | get { return RawForce; } |
574 | set { | 493 | set { |
575 | _force = value; | 494 | RawForce = value; |
576 | if (_force != OMV.Vector3.Zero) | 495 | EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate() |
577 | { | 496 | { |
578 | // If the force is non-zero, it must be reapplied each tick because | 497 | return new BSActorSetForce(PhysScene, this, SetForceActorName); |
579 | // Bullet clears the forces applied last frame. | 498 | }); |
580 | RegisterPreStepAction("BSPrim.setForce", LocalID, | 499 | } |
581 | delegate(float timeStep) | 500 | } |
582 | { | ||
583 | if (!IsPhysicallyActive || _force == OMV.Vector3.Zero) | ||
584 | { | ||
585 | UnRegisterPreStepAction("BSPrim.setForce", LocalID); | ||
586 | return; | ||
587 | } | ||
588 | 501 | ||
589 | DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force); | 502 | // Find and return a handle to the current vehicle actor. |
590 | if (PhysBody.HasPhysicalBody) | 503 | // Return 'null' if there is no vehicle actor. |
591 | { | 504 | public BSDynamics GetVehicleActor(bool createIfNone) |
592 | PhysicsScene.PE.ApplyCentralForce(PhysBody, _force); | 505 | { |
593 | ActivateIfPhysical(false); | 506 | BSDynamics ret = null; |
594 | } | 507 | BSActor actor; |
595 | } | 508 | if (PhysicalActors.TryGetActor(VehicleActorName, out actor)) |
596 | ); | 509 | { |
597 | } | 510 | ret = actor as BSDynamics; |
598 | else | 511 | } |
512 | else | ||
513 | { | ||
514 | if (createIfNone) | ||
599 | { | 515 | { |
600 | UnRegisterPreStepAction("BSPrim.setForce", LocalID); | 516 | ret = new BSDynamics(PhysScene, this, VehicleActorName); |
517 | PhysicalActors.Add(ret.ActorName, ret); | ||
601 | } | 518 | } |
602 | } | 519 | } |
520 | return ret; | ||
603 | } | 521 | } |
604 | 522 | ||
605 | public override int VehicleType { | 523 | public override int VehicleType { |
606 | get { | 524 | get { |
607 | return (int)VehicleController.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; | ||
608 | } | 530 | } |
609 | set { | 531 | set { |
610 | Vehicle type = (Vehicle)value; | 532 | Vehicle type = (Vehicle)value; |
611 | 533 | ||
612 | PhysicsScene.TaintedObject("setVehicleType", delegate() | 534 | PhysScene.TaintedObject(LocalID, "setVehicleType", delegate() |
613 | { | 535 | { |
614 | // 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 |
615 | // Vehicle code changes the parameters for this vehicle type. | 537 | // change all the parameters. Like a plane changing to CAR when on the |
616 | VehicleController.ProcessTypeChange(type); | 538 | // ground. In this case, don't want to zero motion. |
617 | ActivateIfPhysical(false); | 539 | // ZeroMotion(true /* inTaintTime */); |
618 | 540 | if (type == Vehicle.TYPE_NONE) | |
619 | // If an active vehicle, register the vehicle code to be called before each step | ||
620 | if (VehicleController.Type == Vehicle.TYPE_NONE) | ||
621 | { | 541 | { |
622 | UnRegisterPreStepAction("BSPrim.Vehicle", LocalID); | 542 | // Vehicle type is 'none' so get rid of any actor that may have been allocated. |
623 | UnRegisterPostStepAction("BSPrim.Vehicle", LocalID); | 543 | BSDynamics vehicleActor = GetVehicleActor(false /* createIfNone */); |
544 | if (vehicleActor != null) | ||
545 | { | ||
546 | PhysicalActors.RemoveAndRelease(vehicleActor.ActorName); | ||
547 | } | ||
624 | } | 548 | } |
625 | else | 549 | else |
626 | { | 550 | { |
627 | RegisterPreStepAction("BSPrim.Vehicle", LocalID, VehicleController.Step); | 551 | // Vehicle type is not 'none' so create an actor and set it running. |
628 | RegisterPostStepAction("BSPrim.Vehicle", LocalID, VehicleController.PostStep); | 552 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); |
553 | if (vehicleActor != null) | ||
554 | { | ||
555 | vehicleActor.ProcessTypeChange(type); | ||
556 | ActivateIfPhysical(false); | ||
557 | } | ||
629 | } | 558 | } |
630 | }); | 559 | }); |
631 | } | 560 | } |
632 | } | 561 | } |
633 | public override void VehicleFloatParam(int param, float value) | 562 | public override void VehicleFloatParam(int param, float value) |
634 | { | 563 | { |
635 | PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() | 564 | PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFloatParam", delegate() |
636 | { | 565 | { |
637 | VehicleController.ProcessFloatVehicleParam((Vehicle)param, value); | 566 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); |
638 | ActivateIfPhysical(false); | 567 | if (vehicleActor != null) |
568 | { | ||
569 | vehicleActor.ProcessFloatVehicleParam((Vehicle)param, value); | ||
570 | ActivateIfPhysical(false); | ||
571 | } | ||
639 | }); | 572 | }); |
640 | } | 573 | } |
641 | public override void VehicleVectorParam(int param, OMV.Vector3 value) | 574 | public override void VehicleVectorParam(int param, OMV.Vector3 value) |
642 | { | 575 | { |
643 | PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() | 576 | PhysScene.TaintedObject(LocalID, "BSPrim.VehicleVectorParam", delegate() |
644 | { | 577 | { |
645 | VehicleController.ProcessVectorVehicleParam((Vehicle)param, value); | 578 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); |
646 | ActivateIfPhysical(false); | 579 | if (vehicleActor != null) |
580 | { | ||
581 | vehicleActor.ProcessVectorVehicleParam((Vehicle)param, value); | ||
582 | ActivateIfPhysical(false); | ||
583 | } | ||
647 | }); | 584 | }); |
648 | } | 585 | } |
649 | public override void VehicleRotationParam(int param, OMV.Quaternion rotation) | 586 | public override void VehicleRotationParam(int param, OMV.Quaternion rotation) |
650 | { | 587 | { |
651 | PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() | 588 | PhysScene.TaintedObject(LocalID, "BSPrim.VehicleRotationParam", delegate() |
652 | { | 589 | { |
653 | VehicleController.ProcessRotationVehicleParam((Vehicle)param, rotation); | 590 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); |
654 | ActivateIfPhysical(false); | 591 | if (vehicleActor != null) |
592 | { | ||
593 | vehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation); | ||
594 | ActivateIfPhysical(false); | ||
595 | } | ||
655 | }); | 596 | }); |
656 | } | 597 | } |
657 | public override void VehicleFlags(int param, bool remove) | 598 | public override void VehicleFlags(int param, bool remove) |
658 | { | 599 | { |
659 | PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() | 600 | PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFlags", delegate() |
660 | { | 601 | { |
661 | VehicleController.ProcessVehicleFlags(param, remove); | 602 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); |
603 | if (vehicleActor != null) | ||
604 | { | ||
605 | vehicleActor.ProcessVehicleFlags(param, remove); | ||
606 | } | ||
662 | }); | 607 | }); |
663 | } | 608 | } |
664 | 609 | ||
@@ -668,7 +613,7 @@ public class BSPrim : BSPhysObject | |||
668 | if (_isVolumeDetect != newValue) | 613 | if (_isVolumeDetect != newValue) |
669 | { | 614 | { |
670 | _isVolumeDetect = newValue; | 615 | _isVolumeDetect = newValue; |
671 | PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() | 616 | PhysScene.TaintedObject(LocalID, "BSPrim.SetVolumeDetect", delegate() |
672 | { | 617 | { |
673 | // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); | 618 | // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); |
674 | SetObjectDynamic(true); | 619 | SetObjectDynamic(true); |
@@ -676,10 +621,14 @@ public class BSPrim : BSPhysObject | |||
676 | } | 621 | } |
677 | return; | 622 | return; |
678 | } | 623 | } |
624 | public override bool IsVolumeDetect | ||
625 | { | ||
626 | get { return _isVolumeDetect; } | ||
627 | } | ||
679 | public override void SetMaterial(int material) | 628 | public override void SetMaterial(int material) |
680 | { | 629 | { |
681 | base.SetMaterial(material); | 630 | base.SetMaterial(material); |
682 | PhysicsScene.TaintedObject("BSPrim.SetMaterial", delegate() | 631 | PhysScene.TaintedObject(LocalID, "BSPrim.SetMaterial", delegate() |
683 | { | 632 | { |
684 | UpdatePhysicalParameters(); | 633 | UpdatePhysicalParameters(); |
685 | }); | 634 | }); |
@@ -692,7 +641,7 @@ public class BSPrim : BSPhysObject | |||
692 | if (base.Friction != value) | 641 | if (base.Friction != value) |
693 | { | 642 | { |
694 | base.Friction = value; | 643 | base.Friction = value; |
695 | PhysicsScene.TaintedObject("BSPrim.setFriction", delegate() | 644 | PhysScene.TaintedObject(LocalID, "BSPrim.setFriction", delegate() |
696 | { | 645 | { |
697 | UpdatePhysicalParameters(); | 646 | UpdatePhysicalParameters(); |
698 | }); | 647 | }); |
@@ -707,7 +656,7 @@ public class BSPrim : BSPhysObject | |||
707 | if (base.Restitution != value) | 656 | if (base.Restitution != value) |
708 | { | 657 | { |
709 | base.Restitution = value; | 658 | base.Restitution = value; |
710 | PhysicsScene.TaintedObject("BSPrim.setRestitution", delegate() | 659 | PhysScene.TaintedObject(LocalID, "BSPrim.setRestitution", delegate() |
711 | { | 660 | { |
712 | UpdatePhysicalParameters(); | 661 | UpdatePhysicalParameters(); |
713 | }); | 662 | }); |
@@ -724,7 +673,7 @@ public class BSPrim : BSPhysObject | |||
724 | if (base.Density != value) | 673 | if (base.Density != value) |
725 | { | 674 | { |
726 | base.Density = value; | 675 | base.Density = value; |
727 | PhysicsScene.TaintedObject("BSPrim.setDensity", delegate() | 676 | PhysScene.TaintedObject(LocalID, "BSPrim.setDensity", delegate() |
728 | { | 677 | { |
729 | UpdatePhysicalParameters(); | 678 | UpdatePhysicalParameters(); |
730 | }); | 679 | }); |
@@ -739,93 +688,66 @@ public class BSPrim : BSPhysObject | |||
739 | if (base.GravModifier != value) | 688 | if (base.GravModifier != value) |
740 | { | 689 | { |
741 | base.GravModifier = value; | 690 | base.GravModifier = value; |
742 | PhysicsScene.TaintedObject("BSPrim.setGravityModifier", delegate() | 691 | PhysScene.TaintedObject(LocalID, "BSPrim.setGravityModifier", delegate() |
743 | { | 692 | { |
744 | UpdatePhysicalParameters(); | 693 | UpdatePhysicalParameters(); |
745 | }); | 694 | }); |
746 | } | 695 | } |
747 | } | 696 | } |
748 | } | 697 | } |
749 | public override OMV.Vector3 RawVelocity | ||
750 | { | ||
751 | get { return _velocity; } | ||
752 | set { _velocity = value; } | ||
753 | } | ||
754 | public override OMV.Vector3 Velocity { | 698 | public override OMV.Vector3 Velocity { |
755 | get { return _velocity; } | 699 | get { return RawVelocity; } |
756 | set { | 700 | set { |
757 | _velocity = value; | 701 | RawVelocity = value; |
758 | PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() | 702 | PhysScene.TaintedObject(LocalID, "BSPrim.setVelocity", delegate() |
759 | { | 703 | { |
760 | // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); | 704 | // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity); |
761 | ForceVelocity = _velocity; | 705 | ForceVelocity = RawVelocity; |
762 | }); | 706 | }); |
763 | } | 707 | } |
764 | } | 708 | } |
765 | public override OMV.Vector3 ForceVelocity { | 709 | public override OMV.Vector3 ForceVelocity { |
766 | get { return _velocity; } | 710 | get { return RawVelocity; } |
767 | set { | 711 | set { |
768 | PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity"); | 712 | PhysScene.AssertInTaintTime("BSPrim.ForceVelocity"); |
769 | 713 | ||
770 | _velocity = Util.ClampV(value, BSParam.MaxLinearVelocity); | 714 | RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity); |
771 | if (PhysBody.HasPhysicalBody) | 715 | if (PhysBody.HasPhysicalBody) |
772 | { | 716 | { |
773 | DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity); | 717 | DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity); |
774 | PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); | 718 | PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity); |
775 | ActivateIfPhysical(false); | 719 | ActivateIfPhysical(false); |
776 | } | 720 | } |
777 | } | 721 | } |
778 | } | 722 | } |
779 | public override OMV.Vector3 Torque { | 723 | public override OMV.Vector3 Torque { |
780 | get { return _torque; } | 724 | get { return RawTorque; } |
781 | set { | 725 | set { |
782 | _torque = value; | 726 | RawTorque = value; |
783 | if (_torque != OMV.Vector3.Zero) | 727 | EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate() |
784 | { | 728 | { |
785 | // If the torque is non-zero, it must be reapplied each tick because | 729 | return new BSActorSetTorque(PhysScene, this, SetTorqueActorName); |
786 | // Bullet clears the forces applied last frame. | 730 | }); |
787 | RegisterPreStepAction("BSPrim.setTorque", LocalID, | 731 | DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque); |
788 | delegate(float timeStep) | ||
789 | { | ||
790 | if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero) | ||
791 | { | ||
792 | UnRegisterPreStepAction("BSPrim.setTorque", LocalID); | ||
793 | return; | ||
794 | } | ||
795 | |||
796 | if (PhysBody.HasPhysicalBody) | ||
797 | AddAngularForce(_torque, false, true); | ||
798 | } | ||
799 | ); | ||
800 | } | ||
801 | else | ||
802 | { | ||
803 | UnRegisterPreStepAction("BSPrim.setTorque", LocalID); | ||
804 | } | ||
805 | // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); | ||
806 | } | 732 | } |
807 | } | 733 | } |
808 | public override OMV.Vector3 Acceleration { | 734 | public override OMV.Vector3 Acceleration { |
809 | get { return _acceleration; } | 735 | get { return _acceleration; } |
810 | set { _acceleration = value; } | 736 | set { _acceleration = value; } |
811 | } | 737 | } |
812 | public override OMV.Quaternion RawOrientation | 738 | |
813 | { | ||
814 | get { return _orientation; } | ||
815 | set { _orientation = value; } | ||
816 | } | ||
817 | public override OMV.Quaternion Orientation { | 739 | public override OMV.Quaternion Orientation { |
818 | get { | 740 | get { |
819 | return _orientation; | 741 | return RawOrientation; |
820 | } | 742 | } |
821 | set { | 743 | set { |
822 | if (_orientation == value) | 744 | if (RawOrientation == value) |
823 | return; | 745 | return; |
824 | _orientation = value; | 746 | RawOrientation = value; |
825 | 747 | ||
826 | PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() | 748 | PhysScene.TaintedObject(LocalID, "BSPrim.setOrientation", delegate() |
827 | { | 749 | { |
828 | ForceOrientation = _orientation; | 750 | ForceOrientation = RawOrientation; |
829 | }); | 751 | }); |
830 | } | 752 | } |
831 | } | 753 | } |
@@ -834,14 +756,14 @@ public class BSPrim : BSPhysObject | |||
834 | { | 756 | { |
835 | get | 757 | get |
836 | { | 758 | { |
837 | _orientation = PhysicsScene.PE.GetOrientation(PhysBody); | 759 | RawOrientation = PhysScene.PE.GetOrientation(PhysBody); |
838 | return _orientation; | 760 | return RawOrientation; |
839 | } | 761 | } |
840 | set | 762 | set |
841 | { | 763 | { |
842 | _orientation = value; | 764 | RawOrientation = value; |
843 | if (PhysBody.HasPhysicalBody) | 765 | if (PhysBody.HasPhysicalBody) |
844 | PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); | 766 | PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation); |
845 | } | 767 | } |
846 | } | 768 | } |
847 | public override int PhysicsActorType { | 769 | public override int PhysicsActorType { |
@@ -854,7 +776,7 @@ public class BSPrim : BSPhysObject | |||
854 | if (_isPhysical != value) | 776 | if (_isPhysical != value) |
855 | { | 777 | { |
856 | _isPhysical = value; | 778 | _isPhysical = value; |
857 | PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() | 779 | PhysScene.TaintedObject(LocalID, "BSPrim.setIsPhysical", delegate() |
858 | { | 780 | { |
859 | DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); | 781 | DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); |
860 | SetObjectDynamic(true); | 782 | SetObjectDynamic(true); |
@@ -898,24 +820,25 @@ public class BSPrim : BSPhysObject | |||
898 | // isSolid: other objects bounce off of this object | 820 | // isSolid: other objects bounce off of this object |
899 | // isVolumeDetect: other objects pass through but can generate collisions | 821 | // isVolumeDetect: other objects pass through but can generate collisions |
900 | // 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. | ||
901 | public virtual void UpdatePhysicalParameters() | 824 | public virtual void UpdatePhysicalParameters() |
902 | { | 825 | { |
903 | if (!PhysBody.HasPhysicalBody) | 826 | if (!PhysBody.HasPhysicalBody) |
904 | { | 827 | { |
905 | // 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. |
906 | DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID); | 829 | // DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID); |
907 | return; | 830 | return; |
908 | } | 831 | } |
909 | 832 | ||
910 | // 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. |
911 | // 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). |
912 | PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); | 835 | PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody); |
913 | 836 | ||
914 | // 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) |
915 | MakeDynamic(IsStatic); | 838 | MakeDynamic(IsStatic); |
916 | 839 | ||
917 | // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) | 840 | // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) |
918 | VehicleController.Refresh(); | 841 | PhysicalActors.Refresh(); |
919 | 842 | ||
920 | // Arrange for collision events if the simulator wants them | 843 | // Arrange for collision events if the simulator wants them |
921 | EnableCollisions(SubscribedEvents()); | 844 | EnableCollisions(SubscribedEvents()); |
@@ -926,10 +849,11 @@ public class BSPrim : BSPhysObject | |||
926 | AddObjectToPhysicalWorld(); | 849 | AddObjectToPhysicalWorld(); |
927 | 850 | ||
928 | // Rebuild its shape | 851 | // Rebuild its shape |
929 | PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); | 852 | PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody); |
930 | 853 | ||
931 | 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}", |
932 | LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape); | 855 | LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), |
856 | CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape); | ||
933 | } | 857 | } |
934 | 858 | ||
935 | // "Making dynamic" means changing to and from static. | 859 | // "Making dynamic" means changing to and from static. |
@@ -942,28 +866,28 @@ public class BSPrim : BSPhysObject | |||
942 | if (makeStatic) | 866 | if (makeStatic) |
943 | { | 867 | { |
944 | // Become a Bullet 'static' object type | 868 | // Become a Bullet 'static' object type |
945 | CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); | 869 | CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); |
946 | // Stop all movement | 870 | // Stop all movement |
947 | ZeroMotion(true); | 871 | ZeroMotion(true); |
948 | 872 | ||
949 | // Set various physical properties so other object interact properly | 873 | // Set various physical properties so other object interact properly |
950 | PhysicsScene.PE.SetFriction(PhysBody, Friction); | 874 | PhysScene.PE.SetFriction(PhysBody, Friction); |
951 | PhysicsScene.PE.SetRestitution(PhysBody, Restitution); | 875 | PhysScene.PE.SetRestitution(PhysBody, Restitution); |
952 | PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); | 876 | PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); |
953 | 877 | ||
954 | // 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 |
955 | UpdatePhysicalMassProperties(0f, false); | 879 | UpdatePhysicalMassProperties(0f, false); |
956 | // Set collision detection parameters | 880 | // Set collision detection parameters |
957 | if (BSParam.CcdMotionThreshold > 0f) | 881 | if (BSParam.CcdMotionThreshold > 0f) |
958 | { | 882 | { |
959 | PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); | 883 | PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); |
960 | PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); | 884 | PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); |
961 | } | 885 | } |
962 | 886 | ||
963 | // 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. |
964 | // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION); | 888 | // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION); |
965 | // Start it out sleeping and physical actions could wake it up. | 889 | // Start it out sleeping and physical actions could wake it up. |
966 | PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING); | 890 | PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING); |
967 | 891 | ||
968 | // This collides like a static object | 892 | // This collides like a static object |
969 | PhysBody.collisionType = CollisionType.Static; | 893 | PhysBody.collisionType = CollisionType.Static; |
@@ -971,11 +895,11 @@ public class BSPrim : BSPhysObject | |||
971 | else | 895 | else |
972 | { | 896 | { |
973 | // Not a Bullet static object | 897 | // Not a Bullet static object |
974 | CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); | 898 | CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); |
975 | 899 | ||
976 | // Set various physical properties so other object interact properly | 900 | // Set various physical properties so other object interact properly |
977 | PhysicsScene.PE.SetFriction(PhysBody, Friction); | 901 | PhysScene.PE.SetFriction(PhysBody, Friction); |
978 | PhysicsScene.PE.SetRestitution(PhysBody, Restitution); | 902 | PhysScene.PE.SetRestitution(PhysBody, Restitution); |
979 | // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution); | 903 | // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution); |
980 | 904 | ||
981 | // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 | 905 | // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 |
@@ -983,8 +907,8 @@ public class BSPrim : BSPhysObject | |||
983 | // PhysicsScene.PE.ClearAllForces(BSBody); | 907 | // PhysicsScene.PE.ClearAllForces(BSBody); |
984 | 908 | ||
985 | // 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 |
986 | ForcePosition = _position; | 910 | ForcePosition = RawPosition; |
987 | ForceVelocity = _velocity; | 911 | ForceVelocity = RawVelocity; |
988 | ForceRotationalVelocity = _rotationalVelocity; | 912 | ForceRotationalVelocity = _rotationalVelocity; |
989 | 913 | ||
990 | // A dynamic object has mass | 914 | // A dynamic object has mass |
@@ -993,22 +917,22 @@ public class BSPrim : BSPhysObject | |||
993 | // Set collision detection parameters | 917 | // Set collision detection parameters |
994 | if (BSParam.CcdMotionThreshold > 0f) | 918 | if (BSParam.CcdMotionThreshold > 0f) |
995 | { | 919 | { |
996 | PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); | 920 | PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); |
997 | PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); | 921 | PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); |
998 | } | 922 | } |
999 | 923 | ||
1000 | // Various values for simulation limits | 924 | // Various values for simulation limits |
1001 | PhysicsScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping); | 925 | PhysScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping); |
1002 | PhysicsScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime); | 926 | PhysScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime); |
1003 | PhysicsScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold); | 927 | PhysScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold); |
1004 | PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); | 928 | PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); |
1005 | 929 | ||
1006 | // This collides like an object. | 930 | // This collides like an object. |
1007 | PhysBody.collisionType = CollisionType.Dynamic; | 931 | PhysBody.collisionType = CollisionType.Dynamic; |
1008 | 932 | ||
1009 | // Force activation of the object so Bullet will act on it. | 933 | // Force activation of the object so Bullet will act on it. |
1010 | // 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. |
1011 | PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); | 935 | PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); |
1012 | } | 936 | } |
1013 | } | 937 | } |
1014 | 938 | ||
@@ -1018,7 +942,7 @@ public class BSPrim : BSPhysObject | |||
1018 | // 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. |
1019 | private void MakeSolid(bool makeSolid) | 943 | private void MakeSolid(bool makeSolid) |
1020 | { | 944 | { |
1021 | CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(PhysBody); | 945 | CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysScene.PE.GetBodyType(PhysBody); |
1022 | if (makeSolid) | 946 | if (makeSolid) |
1023 | { | 947 | { |
1024 | // 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. |
@@ -1026,7 +950,7 @@ public class BSPrim : BSPhysObject | |||
1026 | { | 950 | { |
1027 | 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); |
1028 | } | 952 | } |
1029 | CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); | 953 | CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); |
1030 | } | 954 | } |
1031 | else | 955 | else |
1032 | { | 956 | { |
@@ -1034,32 +958,23 @@ public class BSPrim : BSPhysObject | |||
1034 | { | 958 | { |
1035 | 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); |
1036 | } | 960 | } |
1037 | CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); | 961 | CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); |
1038 | 962 | ||
1039 | // 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 |
1040 | PhysBody.collisionType = CollisionType.VolumeDetect; | 964 | PhysBody.collisionType = CollisionType.VolumeDetect; |
1041 | } | 965 | } |
1042 | } | 966 | } |
1043 | 967 | ||
1044 | // Enable physical actions. Bullet will keep sleeping non-moving physical objects so | ||
1045 | // they need waking up when parameters are changed. | ||
1046 | // Called in taint-time!! | ||
1047 | private void ActivateIfPhysical(bool forceIt) | ||
1048 | { | ||
1049 | if (IsPhysical && PhysBody.HasPhysicalBody) | ||
1050 | PhysicsScene.PE.Activate(PhysBody, forceIt); | ||
1051 | } | ||
1052 | |||
1053 | // 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. |
1054 | private void EnableCollisions(bool wantsCollisionEvents) | 969 | private void EnableCollisions(bool wantsCollisionEvents) |
1055 | { | 970 | { |
1056 | if (wantsCollisionEvents) | 971 | if (wantsCollisionEvents) |
1057 | { | 972 | { |
1058 | CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | 973 | CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); |
1059 | } | 974 | } |
1060 | else | 975 | else |
1061 | { | 976 | { |
1062 | CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | 977 | CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); |
1063 | } | 978 | } |
1064 | } | 979 | } |
1065 | 980 | ||
@@ -1070,7 +985,7 @@ public class BSPrim : BSPhysObject | |||
1070 | { | 985 | { |
1071 | if (PhysBody.HasPhysicalBody) | 986 | if (PhysBody.HasPhysicalBody) |
1072 | { | 987 | { |
1073 | PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); | 988 | PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody); |
1074 | } | 989 | } |
1075 | else | 990 | else |
1076 | { | 991 | { |
@@ -1105,12 +1020,12 @@ public class BSPrim : BSPhysObject | |||
1105 | public override bool FloatOnWater { | 1020 | public override bool FloatOnWater { |
1106 | set { | 1021 | set { |
1107 | _floatOnWater = value; | 1022 | _floatOnWater = value; |
1108 | PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() | 1023 | PhysScene.TaintedObject(LocalID, "BSPrim.setFloatOnWater", delegate() |
1109 | { | 1024 | { |
1110 | if (_floatOnWater) | 1025 | if (_floatOnWater) |
1111 | CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); | 1026 | CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); |
1112 | else | 1027 | else |
1113 | CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); | 1028 | CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); |
1114 | }); | 1029 | }); |
1115 | } | 1030 | } |
1116 | } | 1031 | } |
@@ -1122,7 +1037,7 @@ public class BSPrim : BSPhysObject | |||
1122 | _rotationalVelocity = value; | 1037 | _rotationalVelocity = value; |
1123 | Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity); | 1038 | Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity); |
1124 | // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); | 1039 | // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); |
1125 | PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() | 1040 | PhysScene.TaintedObject(LocalID, "BSPrim.setRotationalVelocity", delegate() |
1126 | { | 1041 | { |
1127 | ForceRotationalVelocity = _rotationalVelocity; | 1042 | ForceRotationalVelocity = _rotationalVelocity; |
1128 | }); | 1043 | }); |
@@ -1137,7 +1052,7 @@ public class BSPrim : BSPhysObject | |||
1137 | if (PhysBody.HasPhysicalBody) | 1052 | if (PhysBody.HasPhysicalBody) |
1138 | { | 1053 | { |
1139 | DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); | 1054 | DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); |
1140 | PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); | 1055 | PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); |
1141 | // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); | 1056 | // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); |
1142 | ActivateIfPhysical(false); | 1057 | ActivateIfPhysical(false); |
1143 | } | 1058 | } |
@@ -1153,7 +1068,7 @@ public class BSPrim : BSPhysObject | |||
1153 | get { return _buoyancy; } | 1068 | get { return _buoyancy; } |
1154 | set { | 1069 | set { |
1155 | _buoyancy = value; | 1070 | _buoyancy = value; |
1156 | PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() | 1071 | PhysScene.TaintedObject(LocalID, "BSPrim.setBuoyancy", delegate() |
1157 | { | 1072 | { |
1158 | ForceBuoyancy = _buoyancy; | 1073 | ForceBuoyancy = _buoyancy; |
1159 | }); | 1074 | }); |
@@ -1171,179 +1086,54 @@ public class BSPrim : BSPhysObject | |||
1171 | } | 1086 | } |
1172 | } | 1087 | } |
1173 | 1088 | ||
1174 | // Used for MoveTo | ||
1175 | public override OMV.Vector3 PIDTarget { | ||
1176 | set | ||
1177 | { | ||
1178 | // TODO: add a sanity check -- don't move more than a region or something like that. | ||
1179 | _PIDTarget = value; | ||
1180 | } | ||
1181 | } | ||
1182 | public override float PIDTau { | ||
1183 | set { _PIDTau = value; } | ||
1184 | } | ||
1185 | public override bool PIDActive { | 1089 | public override bool PIDActive { |
1186 | set { | 1090 | set { |
1187 | if (value) | 1091 | base.MoveToTargetActive = value; |
1092 | EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate() | ||
1188 | { | 1093 | { |
1189 | // We're taking over after this. | 1094 | return new BSActorMoveToTarget(PhysScene, this, MoveToTargetActorName); |
1190 | ZeroMotion(true); | 1095 | }); |
1191 | 1096 | } | |
1192 | _targetMotor = new BSVMotor("BSPrim.PIDTarget", | 1097 | } |
1193 | _PIDTau, // timeScale | ||
1194 | BSMotor.Infinite, // decay time scale | ||
1195 | BSMotor.InfiniteVector, // friction timescale | ||
1196 | 1f // efficiency | ||
1197 | ); | ||
1198 | _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
1199 | _targetMotor.SetTarget(_PIDTarget); | ||
1200 | _targetMotor.SetCurrent(RawPosition); | ||
1201 | /* | ||
1202 | _targetMotor = new BSPIDVMotor("BSPrim.PIDTarget"); | ||
1203 | _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
1204 | |||
1205 | _targetMotor.SetTarget(_PIDTarget); | ||
1206 | _targetMotor.SetCurrent(RawPosition); | ||
1207 | _targetMotor.TimeScale = _PIDTau; | ||
1208 | _targetMotor.Efficiency = 1f; | ||
1209 | */ | ||
1210 | |||
1211 | RegisterPreStepAction("BSPrim.PIDTarget", LocalID, delegate(float timeStep) | ||
1212 | { | ||
1213 | if (!IsPhysicallyActive) | ||
1214 | { | ||
1215 | UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID); | ||
1216 | return; | ||
1217 | } | ||
1218 | |||
1219 | OMV.Vector3 origPosition = RawPosition; // DEBUG DEBUG (for printout below) | ||
1220 | |||
1221 | // 'movePosition' is where we'd like the prim to be at this moment. | ||
1222 | OMV.Vector3 movePosition = RawPosition + _targetMotor.Step(timeStep); | ||
1223 | 1098 | ||
1224 | // If we are very close to our target, turn off the movement motor. | 1099 | public override OMV.Vector3 PIDTarget |
1225 | if (_targetMotor.ErrorIsZero()) | 1100 | { |
1226 | { | 1101 | set |
1227 | DetailLog("{0},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}", | 1102 | { |
1228 | LocalID, movePosition, RawPosition, Mass); | 1103 | base.PIDTarget = value; |
1229 | ForcePosition = _targetMotor.TargetValue; | 1104 | BSActor actor; |
1230 | _targetMotor.Enabled = false; | 1105 | if (PhysicalActors.TryGetActor(MoveToTargetActorName, out actor)) |
1231 | } | ||
1232 | else | ||
1233 | { | ||
1234 | _position = movePosition; | ||
1235 | PositionSanityCheck(true /* intaintTime */); | ||
1236 | ForcePosition = _position; | ||
1237 | } | ||
1238 | DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition); | ||
1239 | }); | ||
1240 | } | ||
1241 | else | ||
1242 | { | 1106 | { |
1243 | // Stop any targetting | 1107 | // if the actor exists, tell it to refresh its values. |
1244 | UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID); | 1108 | actor.Refresh(); |
1245 | } | 1109 | } |
1110 | |||
1246 | } | 1111 | } |
1247 | } | 1112 | } |
1248 | |||
1249 | // Used for llSetHoverHeight and maybe vehicle height | 1113 | // Used for llSetHoverHeight and maybe vehicle height |
1250 | // Hover Height will override MoveTo target's Z | 1114 | // Hover Height will override MoveTo target's Z |
1251 | public override bool PIDHoverActive { | 1115 | public override bool PIDHoverActive { |
1252 | set { | 1116 | set { |
1253 | if (value) | 1117 | base.HoverActive = value; |
1118 | EnableActor(HoverActive, HoverActorName, delegate() | ||
1254 | { | 1119 | { |
1255 | // Turning the target on | 1120 | return new BSActorHover(PhysScene, this, HoverActorName); |
1256 | _hoverMotor = new BSFMotor("BSPrim.Hover", | 1121 | }); |
1257 | _PIDHoverTau, // timeScale | ||
1258 | BSMotor.Infinite, // decay time scale | ||
1259 | BSMotor.Infinite, // friction timescale | ||
1260 | 1f // efficiency | ||
1261 | ); | ||
1262 | _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight()); | ||
1263 | _hoverMotor.SetCurrent(RawPosition.Z); | ||
1264 | _hoverMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. | ||
1265 | |||
1266 | RegisterPreStepAction("BSPrim.Hover", LocalID, delegate(float timeStep) | ||
1267 | { | ||
1268 | // Don't do hovering while the object is selected. | ||
1269 | if (!IsPhysicallyActive) | ||
1270 | return; | ||
1271 | |||
1272 | _hoverMotor.SetCurrent(RawPosition.Z); | ||
1273 | _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight()); | ||
1274 | float targetHeight = _hoverMotor.Step(timeStep); | ||
1275 | |||
1276 | // 'targetHeight' is where we'd like the Z of the prim to be at this moment. | ||
1277 | // Compute the amount of force to push us there. | ||
1278 | float moveForce = (targetHeight - RawPosition.Z) * Mass; | ||
1279 | // Undo anything the object thinks it's doing at the moment | ||
1280 | moveForce = -RawVelocity.Z * Mass; | ||
1281 | |||
1282 | PhysicsScene.PE.ApplyCentralImpulse(PhysBody, new OMV.Vector3(0f, 0f, moveForce)); | ||
1283 | DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}", LocalID, targetHeight, moveForce, Mass); | ||
1284 | }); | ||
1285 | } | ||
1286 | else | ||
1287 | { | ||
1288 | UnRegisterPreStepAction("BSPrim.Hover", LocalID); | ||
1289 | } | ||
1290 | } | ||
1291 | } | ||
1292 | public override float PIDHoverHeight { | ||
1293 | set { _PIDHoverHeight = value; } | ||
1294 | } | ||
1295 | public override PIDHoverType PIDHoverType { | ||
1296 | set { _PIDHoverType = value; } | ||
1297 | } | ||
1298 | public override float PIDHoverTau { | ||
1299 | set { _PIDHoverTau = value; } | ||
1300 | } | ||
1301 | // Based on current position, determine what we should be hovering at now. | ||
1302 | // Must recompute often. What if we walked offa cliff> | ||
1303 | private float ComputeCurrentPIDHoverHeight() | ||
1304 | { | ||
1305 | float ret = _PIDHoverHeight; | ||
1306 | float groundHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); | ||
1307 | |||
1308 | switch (_PIDHoverType) | ||
1309 | { | ||
1310 | case PIDHoverType.Ground: | ||
1311 | ret = groundHeight + _PIDHoverHeight; | ||
1312 | break; | ||
1313 | case PIDHoverType.GroundAndWater: | ||
1314 | float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition); | ||
1315 | if (groundHeight > waterHeight) | ||
1316 | { | ||
1317 | ret = groundHeight + _PIDHoverHeight; | ||
1318 | } | ||
1319 | else | ||
1320 | { | ||
1321 | ret = waterHeight + _PIDHoverHeight; | ||
1322 | } | ||
1323 | break; | ||
1324 | } | 1122 | } |
1325 | return ret; | ||
1326 | } | 1123 | } |
1327 | 1124 | ||
1328 | |||
1329 | // For RotLookAt | ||
1330 | public override OMV.Quaternion APIDTarget { set { return; } } | ||
1331 | public override bool APIDActive { set { return; } } | ||
1332 | public override float APIDStrength { set { return; } } | ||
1333 | public override float APIDDamping { set { return; } } | ||
1334 | |||
1335 | public override void AddForce(OMV.Vector3 force, bool pushforce) { | 1125 | public override void AddForce(OMV.Vector3 force, bool pushforce) { |
1336 | // Per documentation, max force is limited. | 1126 | // Per documentation, max force is limited. |
1337 | OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); | 1127 | OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); |
1338 | 1128 | ||
1339 | // 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. |
1340 | addForce /= PhysicsScene.LastTimeStep; | 1130 | addForce /= PhysScene.LastTimeStep; |
1341 | AddForce(addForce, pushforce, false /* inTaintTime */); | 1131 | AddForce(addForce, pushforce, false /* inTaintTime */); |
1342 | } | 1132 | } |
1343 | 1133 | ||
1344 | // 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. |
1345 | // This added force will only last the next simulation tick. | 1135 | // This added force will only last the next simulation tick. |
1346 | public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { | 1136 | public override void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { |
1347 | // 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 |
1348 | if (IsPhysicallyActive) | 1138 | if (IsPhysicallyActive) |
1349 | { | 1139 | { |
@@ -1352,13 +1142,15 @@ public class BSPrim : BSPhysObject | |||
1352 | // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); | 1142 | // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); |
1353 | 1143 | ||
1354 | OMV.Vector3 addForce = force; | 1144 | OMV.Vector3 addForce = force; |
1355 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() | 1145 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddForce", delegate() |
1356 | { | 1146 | { |
1357 | // 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; | ||
1358 | DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce); | 1150 | DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce); |
1359 | if (PhysBody.HasPhysicalBody) | 1151 | if (PhysBody.HasPhysicalBody) |
1360 | { | 1152 | { |
1361 | PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); | 1153 | PhysScene.PE.ApplyCentralForce(PhysBody, addForce); |
1362 | ActivateIfPhysical(false); | 1154 | ActivateIfPhysical(false); |
1363 | } | 1155 | } |
1364 | }); | 1156 | }); |
@@ -1380,13 +1172,13 @@ public class BSPrim : BSPhysObject | |||
1380 | OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude); | 1172 | OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude); |
1381 | // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse); | 1173 | // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse); |
1382 | 1174 | ||
1383 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate() | 1175 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddImpulse", delegate() |
1384 | { | 1176 | { |
1385 | // Bullet adds this impulse immediately to the velocity | 1177 | // Bullet adds this impulse immediately to the velocity |
1386 | DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse); | 1178 | DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse); |
1387 | if (PhysBody.HasPhysicalBody) | 1179 | if (PhysBody.HasPhysicalBody) |
1388 | { | 1180 | { |
1389 | PhysicsScene.PE.ApplyCentralImpulse(PhysBody, addImpulse); | 1181 | PhysScene.PE.ApplyCentralImpulse(PhysBody, addImpulse); |
1390 | ActivateIfPhysical(false); | 1182 | ActivateIfPhysical(false); |
1391 | } | 1183 | } |
1392 | }); | 1184 | }); |
@@ -1399,20 +1191,18 @@ public class BSPrim : BSPhysObject | |||
1399 | } | 1191 | } |
1400 | } | 1192 | } |
1401 | 1193 | ||
1402 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { | 1194 | // BSPhysObject.AddAngularForce() |
1403 | AddAngularForce(force, pushforce, false); | 1195 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) |
1404 | } | ||
1405 | public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) | ||
1406 | { | 1196 | { |
1407 | if (force.IsFinite()) | 1197 | if (force.IsFinite()) |
1408 | { | 1198 | { |
1409 | OMV.Vector3 angForce = force; | 1199 | OMV.Vector3 angForce = force; |
1410 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() | 1200 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddAngularForce", delegate() |
1411 | { | 1201 | { |
1412 | if (PhysBody.HasPhysicalBody) | 1202 | if (PhysBody.HasPhysicalBody) |
1413 | { | 1203 | { |
1414 | DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce); | 1204 | DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce); |
1415 | PhysicsScene.PE.ApplyTorque(PhysBody, angForce); | 1205 | PhysScene.PE.ApplyTorque(PhysBody, angForce); |
1416 | ActivateIfPhysical(false); | 1206 | ActivateIfPhysical(false); |
1417 | } | 1207 | } |
1418 | }); | 1208 | }); |
@@ -1431,11 +1221,11 @@ public class BSPrim : BSPhysObject | |||
1431 | public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) | 1221 | public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) |
1432 | { | 1222 | { |
1433 | OMV.Vector3 applyImpulse = impulse; | 1223 | OMV.Vector3 applyImpulse = impulse; |
1434 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() | 1224 | PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ApplyTorqueImpulse", delegate() |
1435 | { | 1225 | { |
1436 | if (PhysBody.HasPhysicalBody) | 1226 | if (PhysBody.HasPhysicalBody) |
1437 | { | 1227 | { |
1438 | PhysicsScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse); | 1228 | PhysScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse); |
1439 | ActivateIfPhysical(false); | 1229 | ActivateIfPhysical(false); |
1440 | } | 1230 | } |
1441 | }); | 1231 | }); |
@@ -1721,9 +1511,11 @@ public class BSPrim : BSPhysObject | |||
1721 | volume *= (profileEnd - profileBegin); | 1511 | volume *= (profileEnd - profileBegin); |
1722 | 1512 | ||
1723 | returnMass = Density * BSParam.DensityScaleFactor * volume; | 1513 | returnMass = Density * BSParam.DensityScaleFactor * volume; |
1724 | DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass); | ||
1725 | 1514 | ||
1726 | returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); | 1515 | returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); |
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); | ||
1727 | 1519 | ||
1728 | return returnMass; | 1520 | return returnMass; |
1729 | }// end CalculateMass | 1521 | }// end CalculateMass |
@@ -1736,13 +1528,14 @@ public class BSPrim : BSPhysObject | |||
1736 | { | 1528 | { |
1737 | // Create the correct physical representation for this type of object. | 1529 | // Create the correct physical representation for this type of object. |
1738 | // Updates base.PhysBody and base.PhysShape with the new information. | 1530 | // Updates base.PhysBody and base.PhysShape with the new information. |
1739 | // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. | 1531 | // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary. |
1740 | 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) |
1741 | { | 1533 | { |
1742 | // Called if the current prim body is about to be destroyed. | 1534 | // Called if the current prim body is about to be destroyed. |
1743 | // Remove all the physical dependencies on the old body. | 1535 | // Remove all the physical dependencies on the old body. |
1744 | // (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, ...) |
1745 | RemoveBodyDependencies(); | 1537 | // Note: this virtual function is overloaded by BSPrimLinkable to remove linkset constraints. |
1538 | RemoveDependencies(); | ||
1746 | }); | 1539 | }); |
1747 | 1540 | ||
1748 | // Make sure the properties are set on the new object | 1541 | // Make sure the properties are set on the new object |
@@ -1750,33 +1543,45 @@ public class BSPrim : BSPhysObject | |||
1750 | return; | 1543 | return; |
1751 | } | 1544 | } |
1752 | 1545 | ||
1753 | protected virtual void RemoveBodyDependencies() | 1546 | // Called at taint-time |
1547 | protected virtual void RemoveDependencies() | ||
1754 | { | 1548 | { |
1755 | VehicleController.RemoveBodyDependencies(this); | 1549 | PhysicalActors.RemoveDependencies(); |
1550 | } | ||
1551 | |||
1552 | #region Extension | ||
1553 | public override object Extension(string pFunct, params object[] pParams) | ||
1554 | { | ||
1555 | DetailLog("{0} BSPrim.Extension,op={1}", LocalID, pFunct); | ||
1556 | object ret = null; | ||
1557 | switch (pFunct) | ||
1558 | { | ||
1559 | default: | ||
1560 | ret = base.Extension(pFunct, pParams); | ||
1561 | break; | ||
1562 | } | ||
1563 | return ret; | ||
1756 | } | 1564 | } |
1565 | #endregion // Extension | ||
1757 | 1566 | ||
1758 | // 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 |
1759 | // 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. | ||
1760 | public override void UpdateProperties(EntityProperties entprop) | 1571 | public override void UpdateProperties(EntityProperties entprop) |
1761 | { | 1572 | { |
1573 | // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator. | ||
1762 | TriggerPreUpdatePropertyAction(ref entprop); | 1574 | TriggerPreUpdatePropertyAction(ref entprop); |
1763 | 1575 | ||
1764 | // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet | ||
1765 | // TODO: handle physics introduced by Bullet with computed vehicle physics. | ||
1766 | if (VehicleController.IsActive) | ||
1767 | { | ||
1768 | entprop.RotationalVelocity = OMV.Vector3.Zero; | ||
1769 | } | ||
1770 | |||
1771 | // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG | 1576 | // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG |
1772 | 1577 | ||
1773 | // 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 |
1774 | _position = entprop.Position; | 1579 | RawPosition = entprop.Position; |
1775 | _orientation = entprop.Rotation; | 1580 | RawOrientation = entprop.Rotation; |
1776 | // 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 |
1777 | // very sensitive to velocity changes. | 1582 | // very sensitive to velocity changes. |
1778 | 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)) |
1779 | _velocity = entprop.Velocity; | 1584 | RawVelocity = entprop.Velocity; |
1780 | _acceleration = entprop.Acceleration; | 1585 | _acceleration = entprop.Acceleration; |
1781 | _rotationalVelocity = entprop.RotationalVelocity; | 1586 | _rotationalVelocity = entprop.RotationalVelocity; |
1782 | 1587 | ||
@@ -1785,29 +1590,20 @@ public class BSPrim : BSPhysObject | |||
1785 | // The sanity check can change the velocity and/or position. | 1590 | // The sanity check can change the velocity and/or position. |
1786 | if (PositionSanityCheck(true /* inTaintTime */ )) | 1591 | if (PositionSanityCheck(true /* inTaintTime */ )) |
1787 | { | 1592 | { |
1788 | entprop.Position = _position; | 1593 | entprop.Position = RawPosition; |
1789 | entprop.Velocity = _velocity; | 1594 | entprop.Velocity = RawVelocity; |
1790 | entprop.RotationalVelocity = _rotationalVelocity; | 1595 | entprop.RotationalVelocity = _rotationalVelocity; |
1791 | entprop.Acceleration = _acceleration; | 1596 | entprop.Acceleration = _acceleration; |
1792 | } | 1597 | } |
1793 | 1598 | ||
1794 | OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG | 1599 | OMV.Vector3 direction = OMV.Vector3.UnitX * RawOrientation; // DEBUG DEBUG DEBUG |
1795 | 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); |
1796 | 1601 | ||
1797 | // remember the current and last set values | 1602 | // remember the current and last set values |
1798 | LastEntityProperties = CurrentEntityProperties; | 1603 | LastEntityProperties = CurrentEntityProperties; |
1799 | CurrentEntityProperties = entprop; | 1604 | CurrentEntityProperties = entprop; |
1800 | 1605 | ||
1801 | base.RequestPhysicsterseUpdate(); | 1606 | PhysScene.PostUpdate(this); |
1802 | /* | ||
1803 | else | ||
1804 | { | ||
1805 | // For debugging, report the movement of children | ||
1806 | DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | ||
1807 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, | ||
1808 | entprop.Acceleration, entprop.RotationalVelocity); | ||
1809 | } | ||
1810 | */ | ||
1811 | } | 1607 | } |
1812 | } | 1608 | } |
1813 | } | 1609 | } |