aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorRobert Adams2013-01-07 16:05:02 -0800
committerRobert Adams2013-01-07 16:05:02 -0800
commit8452c0a8702ccf7ea045740dd829c69a6f509845 (patch)
treea2c094fbded7a502dc997d1eb4252659eddbb003
parentBulletSim: fix exception when re-creating the terrain when loading an OAR file (diff)
downloadopensim-SC_OLD-8452c0a8702ccf7ea045740dd829c69a6f509845.zip
opensim-SC_OLD-8452c0a8702ccf7ea045740dd829c69a6f509845.tar.gz
opensim-SC_OLD-8452c0a8702ccf7ea045740dd829c69a6f509845.tar.bz2
opensim-SC_OLD-8452c0a8702ccf7ea045740dd829c69a6f509845.tar.xz
BulletSim: add function to push avatar up when hitting stairs.
It looks like BulletSim and ODE rely on penetration correction to cause the avatar to move up and thus allowing walking up stairs. Object penetration was minimized for walking and flying (so one doesn't go through walls) and this stopped stairs from working. This commit introduces avatar movement code to check for collisions at the feet while walking and attempts to raise the avatar for the steps. Not yet perfect but movement is better.
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs97
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs18
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs27
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt2
5 files changed, 119 insertions, 27 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index fe48166..939d38a 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -184,10 +184,6 @@ public sealed class BSCharacter : BSPhysObject
184 // standing as well as moving. Destruction of the avatar will destroy the pre-step action. 184 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
185 private void SetupMovementMotor() 185 private void SetupMovementMotor()
186 { 186 {
187
188 // Someday, use a PID motor for asymmetric speed up and slow down
189 // _velocityMotor = new BSPIDVMotor("BSCharacter.Velocity", 3f, 5f, BSMotor.InfiniteVector, 1f);
190
191 // Infinite decay and timescale values so motor only changes current to target values. 187 // Infinite decay and timescale values so motor only changes current to target values.
192 _velocityMotor = new BSVMotor("BSCharacter.Velocity", 188 _velocityMotor = new BSVMotor("BSCharacter.Velocity",
193 0.2f, // time scale 189 0.2f, // time scale
@@ -214,25 +210,68 @@ public sealed class BSCharacter : BSPhysObject
214 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force. 210 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
215 OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass; 211 OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass;
216 212
217 /* 213 // Should we check for move force being small and forcing velocity to zero?
218 // If moveForce is very small, zero things so we don't keep sending microscopic updates to the user 214
219 float moveForceMagnitudeSquared = moveForce.LengthSquared(); 215 // Add special movement force to allow avatars to walk up stepped surfaces.
220 if (moveForceMagnitudeSquared < 0.0001) 216 moveForce += WalkUpStairs();
221 { 217
222 DetailLog("{0},BSCharacter.MoveMotor,zeroMovement,stepVel={1},vel={2},mass={3},magSq={4},moveForce={5}", 218 DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
223 LocalID, stepVelocity, _velocity, Mass, moveForceMagnitudeSquared, moveForce);
224 ForceVelocity = OMV.Vector3.Zero;
225 }
226 else
227 {
228 AddForce(moveForce, false, true);
229 }
230 */
231 // DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
232 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce); 219 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce);
233 }); 220 });
234 } 221 }
235 222
223 // Decide of the character is colliding with a low object and compute a force to pop the
224 // avatar up so it has a chance of walking up and over the low object.
225 private OMV.Vector3 WalkUpStairs()
226 {
227 OMV.Vector3 ret = OMV.Vector3.Zero;
228
229 // This test is done if moving forward, not flying and is colliding with something.
230 // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
231 // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
232 if (IsColliding && !Flying && TargetSpeed > 0.1f /* && ForwardSpeed < 0.1f */)
233 {
234 // The range near the character's feet where we will consider stairs
235 float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f;
236 float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
237
238 // Look for a collision point that is near the character's feet and is oriented the same as the charactor is
239 foreach (KeyValuePair<uint, ContactPoint> kvp in CollisionsLastTick.m_objCollisionList)
240 {
241 // Don't care about collisions with the terrain
242 if (kvp.Key > PhysicsScene.TerrainManager.HighestTerrainID)
243 {
244 OMV.Vector3 touchPosition = kvp.Value.Position;
245 // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
246 // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
247 if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
248 {
249 // This contact is within the 'near the feet' range.
250 // The normal should be our contact point to the object so it is pointing away
251 // thus the difference between our facing orientation and the normal should be small.
252 OMV.Vector3 directionFacing = OMV.Vector3.UnitX * RawOrientation;
253 OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
254 float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
255 if (diff < BSParam.AvatarStepApproachFactor)
256 {
257 // Found the stairs contact point. Push up a little to raise the character.
258 float upForce = (touchPosition.Z - nearFeetHeightMin) * Mass * BSParam.AvatarStepForceFactor;
259 ret = new OMV.Vector3(0f, 0f, upForce);
260
261 // Also move the avatar up for the new height
262 OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
263 ForcePosition = RawPosition + displacement;
264 }
265 DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
266 LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
267 }
268 }
269 }
270 }
271
272 return ret;
273 }
274
236 public override void RequestPhysicsterseUpdate() 275 public override void RequestPhysicsterseUpdate()
237 { 276 {
238 base.RequestPhysicsterseUpdate(); 277 base.RequestPhysicsterseUpdate();
@@ -342,13 +381,11 @@ public sealed class BSCharacter : BSPhysObject
342 } 381 }
343 set { 382 set {
344 _position = value; 383 _position = value;
345 PositionSanityCheck();
346 384
347 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() 385 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
348 { 386 {
349 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 387 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
350 if (PhysBody.HasPhysicalBody) 388 ForcePosition = _position;
351 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
352 }); 389 });
353 } 390 }
354 } 391 }
@@ -359,8 +396,11 @@ public sealed class BSCharacter : BSPhysObject
359 } 396 }
360 set { 397 set {
361 _position = value; 398 _position = value;
362 PositionSanityCheck(); 399 if (PhysBody.HasPhysicalBody)
363 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 400 {
401 PositionSanityCheck();
402 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
403 }
364 } 404 }
365 } 405 }
366 406
@@ -373,7 +413,7 @@ public sealed class BSCharacter : BSPhysObject
373 bool ret = false; 413 bool ret = false;
374 414
375 // TODO: check for out of bounds 415 // TODO: check for out of bounds
376 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position)) 416 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
377 { 417 {
378 // The character is out of the known/simulated area. 418 // The character is out of the known/simulated area.
379 // Upper levels of code will handle the transition to other areas so, for 419 // Upper levels of code will handle the transition to other areas so, for
@@ -382,7 +422,7 @@ public sealed class BSCharacter : BSPhysObject
382 } 422 }
383 423
384 // If below the ground, move the avatar up 424 // If below the ground, move the avatar up
385 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); 425 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
386 if (Position.Z < terrainHeight) 426 if (Position.Z < terrainHeight)
387 { 427 {
388 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); 428 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
@@ -485,6 +525,11 @@ public sealed class BSCharacter : BSPhysObject
485 }); 525 });
486 } 526 }
487 } 527 }
528 public override OMV.Vector3 RawVelocity
529 {
530 get { return _velocity; }
531 set { _velocity = value; }
532 }
488 // Directly setting velocity means this is what the user really wants now. 533 // Directly setting velocity means this is what the user really wants now.
489 public override OMV.Vector3 Velocity { 534 public override OMV.Vector3 Velocity {
490 get { return _velocity; } 535 get { return _velocity; }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index b9bd0bf..23d573f 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -75,6 +75,9 @@ public static class BSParam
75 public static float AvatarCapsuleDepth { get; private set; } 75 public static float AvatarCapsuleDepth { get; private set; }
76 public static float AvatarCapsuleHeight { get; private set; } 76 public static float AvatarCapsuleHeight { get; private set; }
77 public static float AvatarContactProcessingThreshold { get; private set; } 77 public static float AvatarContactProcessingThreshold { get; private set; }
78 public static float AvatarStepHeight { get; private set; }
79 public static float AvatarStepApproachFactor { get; private set; }
80 public static float AvatarStepForceFactor { get; private set; }
78 81
79 public static float VehicleAngularDamping { get; private set; } 82 public static float VehicleAngularDamping { get; private set; }
80 83
@@ -403,6 +406,21 @@ public static class BSParam
403 (s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); }, 406 (s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); },
404 (s) => { return AvatarContactProcessingThreshold; }, 407 (s) => { return AvatarContactProcessingThreshold; },
405 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarContactProcessingThreshold=x;}, p, l, v); } ), 408 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarContactProcessingThreshold=x;}, p, l, v); } ),
409 new ParameterDefn("AvatarStepHeight", "Height of a step obstacle to consider step correction",
410 0.3f,
411 (s,cf,p,v) => { AvatarStepHeight = cf.GetFloat(p, v); },
412 (s) => { return AvatarStepHeight; },
413 (s,p,l,v) => { AvatarStepHeight = v; } ),
414 new ParameterDefn("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
415 0.6f,
416 (s,cf,p,v) => { AvatarStepApproachFactor = cf.GetFloat(p, v); },
417 (s) => { return AvatarStepApproachFactor; },
418 (s,p,l,v) => { AvatarStepApproachFactor = v; } ),
419 new ParameterDefn("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
420 2.0f,
421 (s,cf,p,v) => { AvatarStepForceFactor = cf.GetFloat(p, v); },
422 (s) => { return AvatarStepForceFactor; },
423 (s,p,l,v) => { AvatarStepForceFactor = v; } ),
406 424
407 new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)", 425 new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
408 0.95f, 426 0.95f,
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 534f929..e8575f6 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -79,6 +79,7 @@ public abstract class BSPhysObject : PhysicsActor
79 Material = MaterialAttributes.Material.Wood; 79 Material = MaterialAttributes.Material.Wood;
80 80
81 CollisionCollection = new CollisionEventUpdate(); 81 CollisionCollection = new CollisionEventUpdate();
82 CollisionsLastTick = CollisionCollection;
82 SubscribedEventsMs = 0; 83 SubscribedEventsMs = 0;
83 CollidingStep = 0; 84 CollidingStep = 0;
84 CollidingGroundStep = 0; 85 CollidingGroundStep = 0;
@@ -159,6 +160,7 @@ public abstract class BSPhysObject : PhysicsActor
159 public abstract OMV.Quaternion ForceOrientation { get; set; } 160 public abstract OMV.Quaternion ForceOrientation { get; set; }
160 161
161 // The system is telling us the velocity it wants to move at. 162 // The system is telling us the velocity it wants to move at.
163 // Velocity in world coordinates.
162 // protected OMV.Vector3 m_targetVelocity; // use the definition in PhysicsActor 164 // protected OMV.Vector3 m_targetVelocity; // use the definition in PhysicsActor
163 public override OMV.Vector3 TargetVelocity 165 public override OMV.Vector3 TargetVelocity
164 { 166 {
@@ -169,6 +171,15 @@ public abstract class BSPhysObject : PhysicsActor
169 Velocity = value; 171 Velocity = value;
170 } 172 }
171 } 173 }
174 public virtual float TargetSpeed
175 {
176 get
177 {
178 OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
179 return characterOrientedVelocity.X;
180 }
181 }
182 public abstract OMV.Vector3 RawVelocity { get; set; }
172 public abstract OMV.Vector3 ForceVelocity { get; set; } 183 public abstract OMV.Vector3 ForceVelocity { get; set; }
173 184
174 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } 185 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
@@ -177,6 +188,15 @@ public abstract class BSPhysObject : PhysicsActor
177 188
178 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } 189 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
179 190
191 public virtual float ForwardSpeed
192 {
193 get
194 {
195 OMV.Vector3 characterOrientedVelocity = RawVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
196 return characterOrientedVelocity.X;
197 }
198 }
199
180 #region Collisions 200 #region Collisions
181 201
182 // Requested number of milliseconds between collision events. Zero means disabled. 202 // Requested number of milliseconds between collision events. Zero means disabled.
@@ -223,9 +243,13 @@ public abstract class BSPhysObject : PhysicsActor
223 243
224 // The collisions that have been collected this tick 244 // The collisions that have been collected this tick
225 protected CollisionEventUpdate CollisionCollection; 245 protected CollisionEventUpdate CollisionCollection;
246 // Remember collisions from last tick for fancy collision based actions
247 // (like a BSCharacter walking up stairs).
248 protected CollisionEventUpdate CollisionsLastTick;
226 249
227 // The simulation step is telling this object about a collision. 250 // The simulation step is telling this object about a collision.
228 // Return 'true' if a collision was processed and should be sent up. 251 // Return 'true' if a collision was processed and should be sent up.
252 // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision.
229 // Called at taint time from within the Step() function 253 // Called at taint time from within the Step() function
230 public virtual bool Collide(uint collidingWith, BSPhysObject collidee, 254 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
231 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 255 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
@@ -286,6 +310,9 @@ public abstract class BSPhysObject : PhysicsActor
286 // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); 310 // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
287 base.SendCollisionUpdate(CollisionCollection); 311 base.SendCollisionUpdate(CollisionCollection);
288 312
313 // Remember the collisions from this tick for some collision specific processing.
314 CollisionsLastTick = CollisionCollection;
315
289 // The CollisionCollection instance is passed around in the simulator. 316 // The CollisionCollection instance is passed around in the simulator.
290 // Make sure we don't have a handle to that one and that a new one is used for next time. 317 // Make sure we don't have a handle to that one and that a new one is used for next time.
291 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here, 318 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 94b63e5..400d5d6 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -562,7 +562,7 @@ public sealed class BSPrim : BSPhysObject
562 } 562 }
563 return; 563 return;
564 } 564 }
565 public OMV.Vector3 RawVelocity 565 public override OMV.Vector3 RawVelocity
566 { 566 {
567 get { return _velocity; } 567 get { return _velocity; }
568 set { _velocity = value; } 568 set { _velocity = value; }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index 7b59e60..794a6af 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -88,6 +88,8 @@ setForce should set a constant force. Different than AddImpulse.
88Implement raycast. 88Implement raycast.
89Implement ShapeCollection.Dispose() 89Implement ShapeCollection.Dispose()
90Implement water as a plain so raycasting and collisions can happen with same. 90Implement water as a plain so raycasting and collisions can happen with same.
91Add collision penetration return
92 Add field passed back by BulletSim.dll and fill with info in ManifoldConstact.GetDistance()
91Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE 93Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE
92 Also osGetPhysicsEngineVerion() maybe. 94 Also osGetPhysicsEngineVerion() maybe.
93Linkset.Position and Linkset.Orientation requre rewrite to properly return 95Linkset.Position and Linkset.Orientation requre rewrite to properly return