diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 120 |
1 files changed, 40 insertions, 80 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 14eb505..c62c79a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -47,7 +47,6 @@ public sealed class BSPrim : BSPhysObject | |||
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. |
48 | // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. | 48 | // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. |
49 | private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user | 49 | private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user |
50 | // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer | ||
51 | 50 | ||
52 | private bool _grabbed; | 51 | private bool _grabbed; |
53 | private bool _isSelected; | 52 | private bool _isSelected; |
@@ -88,13 +87,13 @@ public sealed class BSPrim : BSPhysObject | |||
88 | 87 | ||
89 | public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, | 88 | public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, |
90 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) | 89 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) |
90 | : base(parent_scene, localID, primName, "BSPrim") | ||
91 | { | 91 | { |
92 | // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); | 92 | // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); |
93 | base.BaseInitialize(parent_scene, localID, primName, "BSPrim"); | ||
94 | _physicsActorType = (int)ActorTypes.Prim; | 93 | _physicsActorType = (int)ActorTypes.Prim; |
95 | _position = pos; | 94 | _position = pos; |
96 | _size = size; | 95 | _size = size; |
97 | Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type | 96 | Scale = size; // the scale will be set by CreateGeom depending on object type |
98 | _orientation = rotation; | 97 | _orientation = rotation; |
99 | _buoyancy = 1f; | 98 | _buoyancy = 1f; |
100 | _velocity = OMV.Vector3.Zero; | 99 | _velocity = OMV.Vector3.Zero; |
@@ -155,6 +154,8 @@ public sealed class BSPrim : BSPhysObject | |||
155 | public override OMV.Vector3 Size { | 154 | public override OMV.Vector3 Size { |
156 | get { return _size; } | 155 | get { return _size; } |
157 | set { | 156 | set { |
157 | // We presume the scale and size are the same. If scale must be changed for | ||
158 | // the physical shape, that is done when the geometry is built. | ||
158 | _size = value; | 159 | _size = value; |
159 | ForceBodyShapeRebuild(false); | 160 | ForceBodyShapeRebuild(false); |
160 | } | 161 | } |
@@ -170,7 +171,7 @@ public sealed class BSPrim : BSPhysObject | |||
170 | } | 171 | } |
171 | } | 172 | } |
172 | // Whatever the linkset wants is what I want. | 173 | // Whatever the linkset wants is what I want. |
173 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape | 174 | public override BSPhysicsShapeType PreferredPhysicalShape |
174 | { get { return Linkset.PreferredPhysicalShape(this); } } | 175 | { get { return Linkset.PreferredPhysicalShape(this); } } |
175 | 176 | ||
176 | public override bool ForceBodyShapeRebuild(bool inTaintTime) | 177 | public override bool ForceBodyShapeRebuild(bool inTaintTime) |
@@ -274,19 +275,19 @@ public sealed class BSPrim : BSPhysObject | |||
274 | if (!Linkset.IsRoot(this)) | 275 | if (!Linkset.IsRoot(this)) |
275 | _position = Linkset.Position(this); | 276 | _position = Linkset.Position(this); |
276 | 277 | ||
277 | // don't do the GetObjectPosition for root elements because this function is called a zillion times | 278 | // don't do the GetObjectPosition for root elements because this function is called a zillion times. |
278 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); | 279 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); |
279 | return _position; | 280 | return _position; |
280 | } | 281 | } |
281 | set { | 282 | set { |
282 | // If you must push the position into the physics engine, use ForcePosition. | 283 | // If the position must be forced into the physics engine, use ForcePosition. |
283 | if (_position == value) | 284 | if (_position == value) |
284 | { | 285 | { |
285 | return; | 286 | return; |
286 | } | 287 | } |
287 | _position = value; | 288 | _position = value; |
288 | // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? | 289 | // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? |
289 | PositionSanityCheck(); | 290 | PositionSanityCheck(false); |
290 | PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() | 291 | PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() |
291 | { | 292 | { |
292 | // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 293 | // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
@@ -302,7 +303,7 @@ public sealed class BSPrim : BSPhysObject | |||
302 | } | 303 | } |
303 | set { | 304 | set { |
304 | _position = value; | 305 | _position = value; |
305 | PositionSanityCheck(); | 306 | // PositionSanityCheck(); // Don't do this! Causes a loop and caller should know better. |
306 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 307 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); |
307 | ActivateIfPhysical(false); | 308 | ActivateIfPhysical(false); |
308 | } | 309 | } |
@@ -311,52 +312,42 @@ public sealed class BSPrim : BSPhysObject | |||
311 | // Check that the current position is sane and, if not, modify the position to make it so. | 312 | // Check that the current position is sane and, if not, modify the position to make it so. |
312 | // Check for being below terrain and being out of bounds. | 313 | // Check for being below terrain and being out of bounds. |
313 | // Returns 'true' of the position was made sane by some action. | 314 | // Returns 'true' of the position was made sane by some action. |
314 | private bool PositionSanityCheck() | 315 | private bool PositionSanityCheck(bool inTaintTime) |
315 | { | 316 | { |
316 | bool ret = false; | 317 | bool ret = false; |
317 | 318 | ||
318 | // If totally below the ground, move the prim up | ||
319 | // TODO: figure out the right solution for this... only for dynamic objects? | ||
320 | /* | ||
321 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); | 319 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); |
320 | OMV.Vector3 upForce = OMV.Vector3.Zero; | ||
322 | if (Position.Z < terrainHeight) | 321 | if (Position.Z < terrainHeight) |
323 | { | 322 | { |
324 | DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); | 323 | DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); |
325 | _position.Z = terrainHeight + 2.0f; | 324 | float targetHeight = terrainHeight + (Size.Z / 2f); |
325 | // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec. | ||
326 | upForce.Z = (terrainHeight - Position.Z) * 1f; | ||
326 | ret = true; | 327 | ret = true; |
327 | } | 328 | } |
328 | */ | 329 | |
329 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) | 330 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) |
330 | { | 331 | { |
331 | float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); | 332 | float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); |
332 | // TODO: a floating motor so object will bob in the water | 333 | // TODO: a floating motor so object will bob in the water |
333 | if (Position.Z < waterHeight) | 334 | if (Math.Abs(Position.Z - waterHeight) > 0.1f) |
334 | { | 335 | { |
335 | _position.Z = waterHeight; | 336 | // Upforce proportional to the distance away from the water. Correct the error in 1 sec. |
337 | upForce.Z = (waterHeight - Position.Z) * 1f; | ||
336 | ret = true; | 338 | ret = true; |
337 | } | 339 | } |
338 | } | 340 | } |
339 | 341 | ||
340 | // TODO: check for out of bounds | 342 | // TODO: check for out of bounds |
341 | return ret; | ||
342 | } | ||
343 | 343 | ||
344 | // A version of the sanity check that also makes sure a new position value is | 344 | // The above code computes a force to apply to correct any out-of-bounds problems. Apply same. |
345 | // pushed to the physics engine. This routine would be used by anyone | 345 | // TODO: This should be intergrated with a geneal physics action mechanism. |
346 | // who is not already pushing the value. | 346 | // TODO: This should be moderated with PID'ness. |
347 | private bool PositionSanityCheck(bool inTaintTime) | 347 | if (ret) |
348 | { | ||
349 | bool ret = false; | ||
350 | if (PositionSanityCheck()) | ||
351 | { | 348 | { |
352 | // The new position value must be pushed into the physics engine but we can't | 349 | // Apply upforce and overcome gravity. |
353 | // just assign to "Position" because of potential call loops. | 350 | AddForce(upForce - PhysicsScene.DefaultGravity, false, inTaintTime); |
354 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate() | ||
355 | { | ||
356 | DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | ||
357 | ForcePosition = _position; | ||
358 | }); | ||
359 | ret = true; | ||
360 | } | 351 | } |
361 | return ret; | 352 | return ret; |
362 | } | 353 | } |
@@ -940,6 +931,7 @@ public sealed class BSPrim : BSPhysObject | |||
940 | public override void AddForce(OMV.Vector3 force, bool pushforce) { | 931 | public override void AddForce(OMV.Vector3 force, bool pushforce) { |
941 | AddForce(force, pushforce, false); | 932 | AddForce(force, pushforce, false); |
942 | } | 933 | } |
934 | // Applying a force just adds this to the total force on the object. | ||
943 | public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { | 935 | public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { |
944 | // for an object, doesn't matter if force is a pushforce or not | 936 | // for an object, doesn't matter if force is a pushforce or not |
945 | if (force.IsFinite()) | 937 | if (force.IsFinite()) |
@@ -971,6 +963,7 @@ public sealed class BSPrim : BSPhysObject | |||
971 | }); | 963 | }); |
972 | } | 964 | } |
973 | 965 | ||
966 | // An impulse force is scaled by the mass of the object. | ||
974 | public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime) | 967 | public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime) |
975 | { | 968 | { |
976 | OMV.Vector3 applyImpulse = impulse; | 969 | OMV.Vector3 applyImpulse = impulse; |
@@ -1387,67 +1380,34 @@ public sealed class BSPrim : BSPhysObject | |||
1387 | 1380 | ||
1388 | public override void UpdateProperties(EntityProperties entprop) | 1381 | public override void UpdateProperties(EntityProperties entprop) |
1389 | { | 1382 | { |
1390 | /* | 1383 | // Updates only for individual prims and for the root object of a linkset. |
1391 | UpdatedProperties changed = 0; | 1384 | if (Linkset.IsRoot(this)) |
1392 | // assign to the local variables so the normal set action does not happen | ||
1393 | // if (_position != entprop.Position) | ||
1394 | if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE)) | ||
1395 | { | ||
1396 | _position = entprop.Position; | ||
1397 | changed |= UpdatedProperties.Position; | ||
1398 | } | ||
1399 | // if (_orientation != entprop.Rotation) | ||
1400 | if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE)) | ||
1401 | { | ||
1402 | _orientation = entprop.Rotation; | ||
1403 | changed |= UpdatedProperties.Rotation; | ||
1404 | } | ||
1405 | // if (_velocity != entprop.Velocity) | ||
1406 | if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE)) | ||
1407 | { | ||
1408 | _velocity = entprop.Velocity; | ||
1409 | changed |= UpdatedProperties.Velocity; | ||
1410 | } | ||
1411 | // if (_acceleration != entprop.Acceleration) | ||
1412 | if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE)) | ||
1413 | { | ||
1414 | _acceleration = entprop.Acceleration; | ||
1415 | changed |= UpdatedProperties.Acceleration; | ||
1416 | } | ||
1417 | // if (_rotationalVelocity != entprop.RotationalVelocity) | ||
1418 | if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE)) | ||
1419 | { | ||
1420 | _rotationalVelocity = entprop.RotationalVelocity; | ||
1421 | changed |= UpdatedProperties.RotationalVel; | ||
1422 | } | ||
1423 | if (changed != 0) | ||
1424 | { | 1385 | { |
1425 | // Only update the position of single objects and linkset roots | 1386 | // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet |
1426 | if (this._parentPrim == null) | 1387 | // TODO: handle physics introduced by Bullet with computed vehicle physics. |
1388 | if (_vehicle.IsActive) | ||
1427 | { | 1389 | { |
1428 | base.RequestPhysicsterseUpdate(); | 1390 | entprop.RotationalVelocity = OMV.Vector3.Zero; |
1429 | } | 1391 | } |
1430 | } | ||
1431 | */ | ||
1432 | |||
1433 | // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. | ||
1434 | 1392 | ||
1435 | // Updates only for individual prims and for the root object of a linkset. | 1393 | // Assign directly to the local variables so the normal set action does not happen |
1436 | if (Linkset.IsRoot(this)) | ||
1437 | { | ||
1438 | // Assign to the local variables so the normal set action does not happen | ||
1439 | _position = entprop.Position; | 1394 | _position = entprop.Position; |
1440 | _orientation = entprop.Rotation; | 1395 | _orientation = entprop.Rotation; |
1441 | _velocity = entprop.Velocity; | 1396 | _velocity = entprop.Velocity; |
1442 | _acceleration = entprop.Acceleration; | 1397 | _acceleration = entprop.Acceleration; |
1443 | _rotationalVelocity = entprop.RotationalVelocity; | 1398 | _rotationalVelocity = entprop.RotationalVelocity; |
1444 | 1399 | ||
1400 | // The sanity check can change the velocity and/or position. | ||
1401 | if (PositionSanityCheck(true)) | ||
1402 | { | ||
1403 | entprop.Position = _position; | ||
1404 | entprop.Velocity = _velocity; | ||
1405 | } | ||
1406 | |||
1445 | // remember the current and last set values | 1407 | // remember the current and last set values |
1446 | LastEntityProperties = CurrentEntityProperties; | 1408 | LastEntityProperties = CurrentEntityProperties; |
1447 | CurrentEntityProperties = entprop; | 1409 | CurrentEntityProperties = entprop; |
1448 | 1410 | ||
1449 | PositionSanityCheck(true); | ||
1450 | |||
1451 | OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; | 1411 | OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; |
1452 | DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", | 1412 | DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", |
1453 | LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); | 1413 | LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); |