From fe16dc09da3f2736fad5a9e792f5f81098b5f9a1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 7 Apr 2013 08:27:49 -0700 Subject: BulletSim: complete movement of physical object action code out of the physical object and into actors for setForce, setTorque, hover, lock axis and avatar move. --- .../Physics/BulletSPlugin/BSActorAvatarMove.cs | 287 +++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs new file mode 100755 index 0000000..634a898 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -0,0 +1,287 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using OpenSim.Region.Physics.Manager; + +using OMV = OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public class BSActorAvatarMove : BSActor +{ + BSVMotor m_velocityMotor; + + public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName) + : base(physicsScene, pObj, actorName) + { + m_velocityMotor = null; + m_physicsScene.DetailLog("{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID); + } + + // BSActor.isActive + public override bool isActive + { + get { return Enabled && m_controllingPrim.IsPhysicallyActive; } + } + + // Release any connections and resources used by the actor. + // BSActor.Dispose() + public override void Dispose() + { + Enabled = false; + } + + // Called when physical parameters (properties set in Bullet) need to be re-applied. + // Called at taint-time. + // BSActor.Refresh() + public override void Refresh() + { + m_physicsScene.DetailLog("{0},BSActorAvatarMove,refresh", m_controllingPrim.LocalID); + + // If not active any more, get rid of me (shouldn't ever happen, but just to be safe) + if (m_controllingPrim.RawForce == OMV.Vector3.Zero) + { + m_physicsScene.DetailLog("{0},BSActorAvatarMove,refresh,notAvatarMove,removing={1}", m_controllingPrim.LocalID, ActorName); + m_controllingPrim.PhysicalActors.RemoveAndRelease(ActorName); + return; + } + + // If the object is physically active, add the hoverer prestep action + if (isActive) + { + ActivateAvatarMove(); + } + else + { + DeactivateAvatarMove(); + } + } + + // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). + // Register a prestep action to restore physical requirements before the next simulation step. + // Called at taint-time. + // BSActor.RemoveBodyDependencies() + public override void RemoveBodyDependencies() + { + // Nothing to do for the hoverer since it is all software at pre-step action time. + } + + public void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime) + { + m_physicsScene.TaintedObject(inTaintTime, "BSActorAvatarMove.setVelocityAndTarget", delegate() + { + m_velocityMotor.Reset(); + m_velocityMotor.SetTarget(targ); + m_velocityMotor.SetCurrent(vel); + m_velocityMotor.Enabled = true; + }); + } + + // If a hover motor has not been created, create one and start the hovering. + private void ActivateAvatarMove() + { + if (m_velocityMotor == null) + { + // Infinite decay and timescale values so motor only changes current to target values. + m_velocityMotor = new BSVMotor("BSCharacter.Velocity", + 0.2f, // time scale + BSMotor.Infinite, // decay time scale + BSMotor.InfiniteVector, // friction timescale + 1f // efficiency + ); + // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. + + m_physicsScene.BeforeStep += Mover; + } + } + + private void DeactivateAvatarMove() + { + if (m_velocityMotor != null) + { + m_physicsScene.BeforeStep -= Mover; + m_velocityMotor = null; + } + } + + // Called just before the simulation step. Update the vertical position for hoverness. + private void Mover(float timeStep) + { + // Don't do movement while the object is selected. + if (!isActive) + return; + + // TODO: Decide if the step parameters should be changed depending on the avatar's + // state (flying, colliding, ...). There is code in ODE to do this. + + // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity + // specified for the avatar is the one that should be used. For falling, if the avatar + // is not flying and is not colliding then it is presumed to be falling and the Z + // component is not fooled with (thus allowing gravity to do its thing). + // When the avatar is standing, though, the user has specified a velocity of zero and + // the avatar should be standing. But if the avatar is pushed by something in the world + // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to + // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity + // errors can creap in and the avatar will slowly float off in some direction. + // So, the problem is that, when an avatar is standing, we cannot tell creaping error + // from real pushing. + // The code below uses whether the collider is static or moving to decide whether to zero motion. + + m_velocityMotor.Step(timeStep); + m_controllingPrim.IsStationary = false; + + // If we're not supposed to be moving, make sure things are zero. + if (m_velocityMotor.ErrorIsZero() && m_velocityMotor.TargetValue == OMV.Vector3.Zero) + { + // The avatar shouldn't be moving + m_velocityMotor.Zero(); + + if (m_controllingPrim.IsColliding) + { + // If we are colliding with a stationary object, presume we're standing and don't move around + if (!m_controllingPrim.ColliderIsMoving) + { + m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID); + m_controllingPrim.IsStationary = true; + m_controllingPrim.ZeroMotion(true /* inTaintTime */); + } + + // Standing has more friction on the ground + if (m_controllingPrim.Friction != BSParam.AvatarStandingFriction) + { + m_controllingPrim.Friction = BSParam.AvatarStandingFriction; + m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); + } + } + else + { + if (m_controllingPrim.Flying) + { + // Flying and not collising and velocity nearly zero. + m_controllingPrim.ZeroMotion(true /* inTaintTime */); + } + } + + m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", + m_controllingPrim.LocalID, m_velocityMotor.TargetValue, m_controllingPrim.IsColliding); + } + else + { + // Supposed to be moving. + OMV.Vector3 stepVelocity = m_velocityMotor.CurrentValue; + + if (m_controllingPrim.Friction != BSParam.AvatarFriction) + { + // Probably starting up walking. Set friction to moving friction. + m_controllingPrim.Friction = BSParam.AvatarFriction; + m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); + } + + // If falling, we keep the world's downward vector no matter what the other axis specify. + // The check for RawVelocity.Z < 0 makes jumping work (temporary upward force). + if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding) + { + if (m_controllingPrim.RawVelocity.Z < 0) + stepVelocity.Z = m_controllingPrim.RawVelocity.Z; + // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); + } + + // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force. + OMV.Vector3 moveForce = (stepVelocity - m_controllingPrim.RawVelocity) * m_controllingPrim.Mass; + + // Should we check for move force being small and forcing velocity to zero? + + // Add special movement force to allow avatars to walk up stepped surfaces. + moveForce += WalkUpStairs(); + + m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", + m_controllingPrim.LocalID, stepVelocity, m_controllingPrim.RawVelocity, m_controllingPrim.Mass, moveForce); + m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, moveForce); + } + } + + // Decide if the character is colliding with a low object and compute a force to pop the + // avatar up so it can walk up and over the low objects. + private OMV.Vector3 WalkUpStairs() + { + OMV.Vector3 ret = OMV.Vector3.Zero; + + // This test is done if moving forward, not flying and is colliding with something. + // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}", + // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count); + if (m_controllingPrim.IsColliding && !m_controllingPrim.Flying && m_controllingPrim.TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */) + { + // The range near the character's feet where we will consider stairs + float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f; + float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight; + + // Look for a collision point that is near the character's feet and is oriented the same as the charactor is + foreach (KeyValuePair kvp in m_controllingPrim.CollisionsLastTick.m_objCollisionList) + { + // Don't care about collisions with the terrain + if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID) + { + OMV.Vector3 touchPosition = kvp.Value.Position; + // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}", + // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition); + if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax) + { + // This contact is within the 'near the feet' range. + // The normal should be our contact point to the object so it is pointing away + // thus the difference between our facing orientation and the normal should be small. + OMV.Vector3 directionFacing = OMV.Vector3.UnitX * m_controllingPrim.RawOrientation; + OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal); + float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal)); + if (diff < BSParam.AvatarStepApproachFactor) + { + // Found the stairs contact point. Push up a little to raise the character. + float upForce = (touchPosition.Z - nearFeetHeightMin) * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor; + ret = new OMV.Vector3(0f, 0f, upForce); + + // Also move the avatar up for the new height + OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f); + m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement; + } + m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}", + m_controllingPrim.LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret); + } + } + } + } + + return ret; + } + +} +} + + -- cgit v1.1 From a7a1b8b7e9269b446e3396a35153b00942c1e35b Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 7 Apr 2013 14:05:35 -0700 Subject: BulletSim: clean up actor code so routines use the same coding pattern. Fix a few enabling problems. --- .../Physics/BulletSPlugin/BSActorAvatarMove.cs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index 634a898..8416740 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -67,14 +67,6 @@ public class BSActorAvatarMove : BSActor { m_physicsScene.DetailLog("{0},BSActorAvatarMove,refresh", m_controllingPrim.LocalID); - // If not active any more, get rid of me (shouldn't ever happen, but just to be safe) - if (m_controllingPrim.RawForce == OMV.Vector3.Zero) - { - m_physicsScene.DetailLog("{0},BSActorAvatarMove,refresh,notAvatarMove,removing={1}", m_controllingPrim.LocalID, ActorName); - m_controllingPrim.PhysicalActors.RemoveAndRelease(ActorName); - return; - } - // If the object is physically active, add the hoverer prestep action if (isActive) { @@ -95,14 +87,19 @@ public class BSActorAvatarMove : BSActor // Nothing to do for the hoverer since it is all software at pre-step action time. } + // Usually called when target velocity changes to set the current velocity and the target + // into the movement motor. public void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime) { m_physicsScene.TaintedObject(inTaintTime, "BSActorAvatarMove.setVelocityAndTarget", delegate() { - m_velocityMotor.Reset(); - m_velocityMotor.SetTarget(targ); - m_velocityMotor.SetCurrent(vel); - m_velocityMotor.Enabled = true; + if (m_velocityMotor != null) + { + m_velocityMotor.Reset(); + m_velocityMotor.SetTarget(targ); + m_velocityMotor.SetCurrent(vel); + m_velocityMotor.Enabled = true; + } }); } @@ -119,6 +116,7 @@ public class BSActorAvatarMove : BSActor 1f // efficiency ); // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. + SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */); m_physicsScene.BeforeStep += Mover; } -- cgit v1.1 From 522ab85045066cb58bb76881032adab7cc6a2d68 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 23 Apr 2013 18:31:12 -0700 Subject: BulletSim: improve avatar stair walking up. Add more parameters to control force of both position change and up force that move avatars over barrier. Default parameters are for steps up to 0.5m in height. --- .../Physics/BulletSPlugin/BSActorAvatarMove.cs | 103 +++++++++++++++++---- 1 file changed, 85 insertions(+), 18 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index 8416740..bd5ee0b1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -40,10 +40,16 @@ public class BSActorAvatarMove : BSActor { BSVMotor m_velocityMotor; + // Set to true if we think we're going up stairs. + // This state is remembered because collisions will turn on and off as we go up stairs. + int m_walkingUpStairs; + float m_lastStepUp; + public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName) : base(physicsScene, pObj, actorName) { m_velocityMotor = null; + m_walkingUpStairs = 0; m_physicsScene.DetailLog("{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID); } @@ -119,6 +125,8 @@ public class BSActorAvatarMove : BSActor SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */); m_physicsScene.BeforeStep += Mover; + + m_walkingUpStairs = 0; } } @@ -216,8 +224,6 @@ public class BSActorAvatarMove : BSActor // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force. OMV.Vector3 moveForce = (stepVelocity - m_controllingPrim.RawVelocity) * m_controllingPrim.Mass; - // Should we check for move force being small and forcing velocity to zero? - // Add special movement force to allow avatars to walk up stepped surfaces. moveForce += WalkUpStairs(); @@ -233,24 +239,33 @@ public class BSActorAvatarMove : BSActor { OMV.Vector3 ret = OMV.Vector3.Zero; + m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}", + m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying, + m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z); // This test is done if moving forward, not flying and is colliding with something. - // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}", - // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count); - if (m_controllingPrim.IsColliding && !m_controllingPrim.Flying && m_controllingPrim.TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */) + // Check for stairs climbing if colliding, not flying and moving forward + if ( m_controllingPrim.IsColliding + && !m_controllingPrim.Flying + && m_controllingPrim.TargetVelocitySpeed > 0.1f ) { // The range near the character's feet where we will consider stairs - float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f; + // float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f; + // Note: there is a problem with the computation of the capsule height. Thus RawPosition is off + // from the height. Revisit size and this computation when height is scaled properly. + float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) - 0.05f; float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight; - // Look for a collision point that is near the character's feet and is oriented the same as the charactor is + // Look for a collision point that is near the character's feet and is oriented the same as the charactor is. + // Find the highest 'good' collision. + OMV.Vector3 highestTouchPosition = OMV.Vector3.Zero; foreach (KeyValuePair kvp in m_controllingPrim.CollisionsLastTick.m_objCollisionList) { // Don't care about collisions with the terrain if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID) { OMV.Vector3 touchPosition = kvp.Value.Position; - // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}", - // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition); + m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}", + m_controllingPrim.LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition); if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax) { // This contact is within the 'near the feet' range. @@ -261,24 +276,76 @@ public class BSActorAvatarMove : BSActor float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal)); if (diff < BSParam.AvatarStepApproachFactor) { - // Found the stairs contact point. Push up a little to raise the character. - float upForce = (touchPosition.Z - nearFeetHeightMin) * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor; - ret = new OMV.Vector3(0f, 0f, upForce); - - // Also move the avatar up for the new height - OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f); - m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement; + if (highestTouchPosition.Z < touchPosition.Z) + highestTouchPosition = touchPosition; } - m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}", - m_controllingPrim.LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret); } } } + m_walkingUpStairs = 0; + // If there is a good step sensing, move the avatar over the step. + if (highestTouchPosition != OMV.Vector3.Zero) + { + // Remember that we are going up stairs. This is needed because collisions + // will stop when we move up so this smoothes out that effect. + m_walkingUpStairs = BSParam.AvatarStepSmoothingSteps; + + m_lastStepUp = highestTouchPosition.Z - nearFeetHeightMin; + ret = ComputeStairCorrection(m_lastStepUp); + m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},ret={3}", + m_controllingPrim.LocalID, highestTouchPosition, nearFeetHeightMin, ret); + } + } + else + { + // If we used to be going up stairs but are not now, smooth the case where collision goes away while + // we are bouncing up the stairs. + if (m_walkingUpStairs > 0) + { + m_walkingUpStairs--; + ret = ComputeStairCorrection(m_lastStepUp); + } } return ret; } + private OMV.Vector3 ComputeStairCorrection(float stepUp) + { + OMV.Vector3 ret = OMV.Vector3.Zero; + OMV.Vector3 displacement = OMV.Vector3.Zero; + + if (stepUp > 0f) + { + // Found the stairs contact point. Push up a little to raise the character. + if (BSParam.AvatarStepForceFactor > 0f) + { + float upForce = stepUp * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor; + ret = new OMV.Vector3(0f, 0f, upForce); + } + + // Also move the avatar up for the new height + if (BSParam.AvatarStepUpCorrectionFactor > 0f) + { + // Move the avatar up related to the height of the collision + displacement = new OMV.Vector3(0f, 0f, stepUp * BSParam.AvatarStepUpCorrectionFactor); + m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement; + } + else + { + if (BSParam.AvatarStepUpCorrectionFactor < 0f) + { + // Move the avatar up about the specified step height + displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight); + m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement; + } + } + m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs.ComputeStairCorrection,disp={1},force={2}", + m_controllingPrim.LocalID, displacement, ret); + + } + return ret; + } } } -- cgit v1.1 From e5582939fd8d78b61c6f1eeda6de45d94f4b4926 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 28 Apr 2013 14:44:21 -0700 Subject: BulletSim: massive refactor of shape classes. Removed shape specific code from BSShapeCollection. Using BSShape* classes to hold references to shape. Simplified shape dependency callbacks. Remove 'PreferredShape' methods and have each class specify shape type. Disable compound shape linkset for a later commit that will simplify linkset implementation. --- OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index bd5ee0b1..ac05979 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -87,8 +87,8 @@ public class BSActorAvatarMove : BSActor // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). // Register a prestep action to restore physical requirements before the next simulation step. // Called at taint-time. - // BSActor.RemoveBodyDependencies() - public override void RemoveBodyDependencies() + // BSActor.RemoveDependencies() + public override void RemoveDependencies() { // Nothing to do for the hoverer since it is all software at pre-step action time. } -- cgit v1.1 From 92ee288d666963aae2a058cc964be009a504f084 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Apr 2013 07:54:50 -0700 Subject: BulletSim: remove trailing white space to make git happier. No functional changes. --- OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index ac05979..4e067b5 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -115,7 +115,7 @@ public class BSActorAvatarMove : BSActor if (m_velocityMotor == null) { // Infinite decay and timescale values so motor only changes current to target values. - m_velocityMotor = new BSVMotor("BSCharacter.Velocity", + m_velocityMotor = new BSVMotor("BSCharacter.Velocity", 0.2f, // time scale BSMotor.Infinite, // decay time scale BSMotor.InfiniteVector, // friction timescale -- cgit v1.1 From 045aaa838ac0a6e129ff1d8ec65053508df1d51a Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 6 May 2013 13:29:19 -0700 Subject: BulletSim: remove friction calcuation from BSMotor and move linear and angular friction computation into linear and angular movement code. The friction wasn't being applied properly. This will make it so vehicles don't drift as much and the drift is tunable by changing the friction timescales. --- OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index 4e067b5..ac8c30c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -118,7 +118,6 @@ public class BSActorAvatarMove : BSActor m_velocityMotor = new BSVMotor("BSCharacter.Velocity", 0.2f, // time scale BSMotor.Infinite, // decay time scale - BSMotor.InfiniteVector, // friction timescale 1f // efficiency ); // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. -- cgit v1.1 From bbeff4b8ca34a4567f2215ed5e90637a00d8c81e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 20 Jun 2013 09:55:40 -0700 Subject: BulletSim: rework velocity updating when not colliding and not flying to prevent infinite jumps. Now jumps last only AvatarJumpFrames long (default 4) which is about as high as in SL. TODO: jumping should only depend on standing (collision with feet) rather than collision anywhere on the avatar. --- .../Physics/BulletSPlugin/BSActorAvatarMove.cs | 44 +++++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index ac8c30c..928b350 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -43,8 +43,14 @@ public class BSActorAvatarMove : BSActor // Set to true if we think we're going up stairs. // This state is remembered because collisions will turn on and off as we go up stairs. int m_walkingUpStairs; + // The amount the step up is applying. Used to smooth stair walking. float m_lastStepUp; + // Jumping happens over several frames. If use applies up force while colliding, start the + // jump and allow the jump to continue for this number of frames. + int m_jumpFrames = 0; + float m_jumpVelocity = 0f; + public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName) : base(physicsScene, pObj, actorName) { @@ -206,17 +212,45 @@ public class BSActorAvatarMove : BSActor if (m_controllingPrim.Friction != BSParam.AvatarFriction) { - // Probably starting up walking. Set friction to moving friction. + // Probably starting to walk. Set friction to moving friction. m_controllingPrim.Friction = BSParam.AvatarFriction; m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); } - // If falling, we keep the world's downward vector no matter what the other axis specify. - // The check for RawVelocity.Z < 0 makes jumping work (temporary upward force). if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding) { - if (m_controllingPrim.RawVelocity.Z < 0) + stepVelocity.Z = m_controllingPrim.RawVelocity.Z; + } + + + // Colliding and not flying with an upward force. The avatar must be trying to jump. + if (!m_controllingPrim.Flying && m_controllingPrim.IsColliding && stepVelocity.Z > 0) + { + // We allow the upward force to happen for this many frames. + m_jumpFrames = BSParam.AvatarJumpFrames; + m_jumpVelocity = stepVelocity.Z; + } + + // The case where the avatar is not colliding and is not flying is special. + // The avatar is either falling or jumping and the user can be applying force to the avatar + // (force in some direction or force up or down). + // If the avatar has negative Z velocity and is not colliding, presume we're falling and keep the velocity. + // If the user is trying to apply upward force but we're not colliding, assume the avatar + // is trying to jump and don't apply the upward force if not touching the ground any more. + if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding) + { + // If upward velocity is being applied, this must be a jump and only allow that to go on so long + if (m_jumpFrames > 0) + { + // Since not touching the ground, only apply upward force for so long. + m_jumpFrames--; + stepVelocity.Z = m_jumpVelocity; + } + else + { + // Since we're not affected by anything, whatever vertical motion the avatar has, continue that. stepVelocity.Z = m_controllingPrim.RawVelocity.Z; + } // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); } @@ -241,7 +275,7 @@ public class BSActorAvatarMove : BSActor m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}", m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying, m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z); - // This test is done if moving forward, not flying and is colliding with something. + // Check for stairs climbing if colliding, not flying and moving forward if ( m_controllingPrim.IsColliding && !m_controllingPrim.Flying -- cgit v1.1 From 1d65b0d80296a672c8023293aee7d0a01bad4066 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 18 Jul 2013 19:09:55 -0700 Subject: BulletSim: add position resetting for stationary avatars so they don't move around when standing on a stationary object. Create proper linkage between BSCharacter and its actor by generating a UpdatedProperties event the same way BSPrim does. --- .../Region/Physics/BulletSPlugin/BSActorAvatarMove.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index 928b350..0f11c4a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -130,6 +130,7 @@ public class BSActorAvatarMove : BSActor SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */); m_physicsScene.BeforeStep += Mover; + m_controllingPrim.OnPreUpdateProperty += Process_OnPreUpdateProperty; m_walkingUpStairs = 0; } @@ -139,6 +140,7 @@ public class BSActorAvatarMove : BSActor { if (m_velocityMotor != null) { + m_controllingPrim.OnPreUpdateProperty -= Process_OnPreUpdateProperty; m_physicsScene.BeforeStep -= Mover; m_velocityMotor = null; } @@ -197,7 +199,7 @@ public class BSActorAvatarMove : BSActor { if (m_controllingPrim.Flying) { - // Flying and not collising and velocity nearly zero. + // Flying and not colliding and velocity nearly zero. m_controllingPrim.ZeroMotion(true /* inTaintTime */); } } @@ -266,6 +268,19 @@ public class BSActorAvatarMove : BSActor } } + // Called just as the property update is received from the physics engine. + // Do any mode necessary for avatar movement. + private void Process_OnPreUpdateProperty(ref EntityProperties entprop) + { + // Don't change position if standing on a stationary object. + if (m_controllingPrim.IsStationary) + { + entprop.Position = m_controllingPrim.RawPosition; + m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation); + } + + } + // Decide if the character is colliding with a low object and compute a force to pop the // avatar up so it can walk up and over the low objects. private OMV.Vector3 WalkUpStairs() -- cgit v1.1 From 2c31fe4614fc193f2600b36eac892ceee86f61e0 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 12 Aug 2013 13:44:53 -0700 Subject: BulletSim: add check in avatar stair step code to verify the collision is not with a volume detect object. This fixes a problem of avatars trying to step over a volume detect object that they collide with. This appeared as the avatar popping up as it started to step up but then continuing on since the object wasn't physically interacting. --- .../Physics/BulletSPlugin/BSActorAvatarMove.cs | 33 +++++++++++++--------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index 0f11c4a..5f232a4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -311,21 +311,28 @@ public class BSActorAvatarMove : BSActor // Don't care about collisions with the terrain if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID) { - OMV.Vector3 touchPosition = kvp.Value.Position; - m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}", - m_controllingPrim.LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition); - if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax) + BSPhysObject collisionObject; + if (m_physicsScene.PhysObjects.TryGetValue(kvp.Key, out collisionObject)) { - // This contact is within the 'near the feet' range. - // The normal should be our contact point to the object so it is pointing away - // thus the difference between our facing orientation and the normal should be small. - OMV.Vector3 directionFacing = OMV.Vector3.UnitX * m_controllingPrim.RawOrientation; - OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal); - float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal)); - if (diff < BSParam.AvatarStepApproachFactor) + if (!collisionObject.IsVolumeDetect) { - if (highestTouchPosition.Z < touchPosition.Z) - highestTouchPosition = touchPosition; + OMV.Vector3 touchPosition = kvp.Value.Position; + m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}", + m_controllingPrim.LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition); + if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax) + { + // This contact is within the 'near the feet' range. + // The normal should be our contact point to the object so it is pointing away + // thus the difference between our facing orientation and the normal should be small. + OMV.Vector3 directionFacing = OMV.Vector3.UnitX * m_controllingPrim.RawOrientation; + OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal); + float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal)); + if (diff < BSParam.AvatarStepApproachFactor) + { + if (highestTouchPosition.Z < touchPosition.Z) + highestTouchPosition = touchPosition; + } + } } } } -- cgit v1.1 From 7c3b71d294987943058c8b3bcb18a424ca70dea5 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 14 Aug 2013 14:13:08 -0700 Subject: BulletSim: add physical object initialized flag so updates and collisions don't happen until the object is completely initialized. This fixes the problem of doing a teleport while the simulator is running. The destruction of the physical object while the engine is running means that the physics parameter update would overwrite the new position of the newly created avatar. --- OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index 5f232a4..c0589cd 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -69,7 +69,9 @@ public class BSActorAvatarMove : BSActor // BSActor.Dispose() public override void Dispose() { - Enabled = false; + base.SetEnabled(false); + // Now that turned off, remove any state we have in the scene. + Refresh(); } // Called when physical parameters (properties set in Bullet) need to be re-applied. -- cgit v1.1 From e8b1e91a1d4bb3ca65886c367c654a82033f4e03 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 14 Aug 2013 14:36:13 -0700 Subject: BulletSim: include check for volume detect in check for zeroing avatar motion. Normally, avatar motion is zeroed if colliding with a stationary object so they don't slide down hills and such. Without volume detect check this also allowed avatars to stand on volume detect objects and to have some jiggling when they were in the volume detect object. This commit fixes both. --- OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index c0589cd..68bc1b9 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -183,7 +183,7 @@ public class BSActorAvatarMove : BSActor if (m_controllingPrim.IsColliding) { // If we are colliding with a stationary object, presume we're standing and don't move around - if (!m_controllingPrim.ColliderIsMoving) + if (!m_controllingPrim.ColliderIsMoving && !m_controllingPrim.ColliderIsVolumeDetect) { m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID); m_controllingPrim.IsStationary = true; -- cgit v1.1 From 995314f91f72eef0048a58f30e8dd8051f6bf14e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Aug 2013 09:20:48 -0700 Subject: BulletSim: add ID parameter to TaintedObject calls so logging will include LocalID of object which created the taint. --- OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index 68bc1b9..04a4a32 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -105,7 +105,7 @@ public class BSActorAvatarMove : BSActor // into the movement motor. public void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime) { - m_physicsScene.TaintedObject(inTaintTime, "BSActorAvatarMove.setVelocityAndTarget", delegate() + m_physicsScene.TaintedObject(inTaintTime, m_controllingPrim.LocalID, "BSActorAvatarMove.setVelocityAndTarget", delegate() { if (m_velocityMotor != null) { -- cgit v1.1 From 07d7a5fd76460a16b97d285a1b2c4a101e5543b6 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 20 Sep 2013 09:36:19 -0700 Subject: BulletSim: zero velocity when avatar not moving. This fixes a movement jitter that happens when an avatar is standing on a tilted surface. --- OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index 04a4a32..8ca55e5 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -278,6 +278,7 @@ public class BSActorAvatarMove : BSActor if (m_controllingPrim.IsStationary) { entprop.Position = m_controllingPrim.RawPosition; + entprop.Velocity = OMV.Vector3.Zero; m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation); } -- cgit v1.1 From 35a6361b2431abf9d49b4413c5b9eaac51934134 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 20 Sep 2013 09:23:12 -0700 Subject: BulletSim: reduce avatar walking stopped threshold. Add parameter for setting the walking stopped threshold. This fixes the slight jump when an avatar stops walking. --- OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index 8ca55e5..1bcf879 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -128,6 +128,7 @@ public class BSActorAvatarMove : BSActor BSMotor.Infinite, // decay time scale 1f // efficiency ); + m_velocityMotor.ErrorZeroThreshold = BSParam.AvatarStopZeroThreshold; // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */); -- cgit v1.1