Step() public method

public Step ( float timeStep ) : System.Vector3
timeStep float
return System.Vector3
        // Origional mover that set the objects position to move to the target.
        // The problem was that gravity would keep trying to push the object down so
        //    the overall downward velocity would increase to infinity.
        // Called just before the simulation step. Update the vertical position for hoverness.
        void Mover(float timeStep)
        {
            // Don't do hovering while the object is selected.
            if (!isActive)
            {
                return;
            }

            OMV.Vector3 origPosition = m_controllingPrim.RawPosition;     // DEBUG DEBUG (for printout below)

            // 'movePosition' is where we'd like the prim to be at this moment.
            OMV.Vector3 movePosition = m_controllingPrim.RawPosition + m_targetMotor.Step(timeStep);

            // If we are very close to our target, turn off the movement motor.
            if (m_targetMotor.ErrorIsZero())
            {
                m_physicsScene.DetailLog("{0},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}",
                                         m_controllingPrim.LocalID, movePosition, m_controllingPrim.RawPosition, m_controllingPrim.Mass);
                m_controllingPrim.ForcePosition = m_targetMotor.TargetValue;
                m_controllingPrim.ForceVelocity = OMV.Vector3.Zero;
                // Setting the position does not cause the physics engine to generate a property update. Force it.
                m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
            }
            else
            {
                m_controllingPrim.ForcePosition = movePosition;
                // Setting the position does not cause the physics engine to generate a property update. Force it.
                m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
            }
            m_physicsScene.DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", m_controllingPrim.LocalID, origPosition, movePosition);
        }
Example #2
0
        // Called just before the simulation step. Update the vertical position for hoverness.
        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_controllingPrim.VolumeDetect)
                    // new  //if (!m_controllingPrim.ColliderIsMoving && !m_controllingPrim.ColliderIsVolumeDetect)
                    {
                        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 colliding and velocity nearly zero.
                        m_controllingPrim.ZeroMotion(true /* inTaintTime */);
                    }
                    else
                    {
                        //We are falling but are not touching any keys make sure not falling too fast
                        if (m_controllingPrim.RawVelocity.Z < BSParam.AvatarTerminalVelocity)
                        {
                            OMV.Vector3 slowingForce = new OMV.Vector3(0f, 0f, BSParam.AvatarTerminalVelocity - m_controllingPrim.RawVelocity.Z) * m_controllingPrim.Mass;
                            m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, slowingForce);
                        }
                    }
                }


                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;
                    }
                }

                // 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, the avatar must be falling and we do not want that to be too fast.
                        if (m_controllingPrim.RawVelocity.Z < BSParam.AvatarTerminalVelocity)
                        {
                            stepVelocity.Z = BSParam.AvatarTerminalVelocity;
                        }
                        else
                        {
                            stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
                        }
                    }
                    // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
                }

                //Alicia: Maintain minimum height when flying.
                // SL has a flying effect that keeps the avatar flying above the ground by some margin
                if (m_controllingPrim.Flying)
                {
                    float hover_height = m_physicsScene.TerrainManager.GetTerrainHeightAtXYZ(m_controllingPrim.RawPosition)
                                         + BSParam.AvatarFlyingGroundMargin;

                    if (m_controllingPrim.Position.Z < hover_height)
                    {
                        stepVelocity.Z += BSParam.AvatarFlyingGroundUpForce;
                    }
                }

                // '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);

                // i think this fix is working .. :-)
                if (moveForce.IsFinite())
                {
                    m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, moveForce);
                }
            }

            // a bit of jump processing...
            if (m_preJumpStart != 0 && Util.EnvironmentTickCountSubtract(m_preJumpStart) > 300)
            {
                m_controllingPrim.IsPreJumping = false;
                m_controllingPrim.IsJumping    = true;
                m_preJumpStart = 0;

                OMV.Vector3 target = m_jumpDirection;
                target.X *= 1.5f;
                target.Y *= 1.5f;
                target.Z *= 2.5f; //Scale so that we actually jump

                SetVelocityAndTargetInternal(m_controllingPrim.RawVelocity, target, false, 1);
                m_jumpStart = Util.EnvironmentTickCount();
            }
            if (!m_jumpFallState && m_jumpStart != 0 && Util.EnvironmentTickCountSubtract(m_jumpStart) > 500)
            {
                OMV.Vector3 newTarget = m_controllingPrim.RawVelocity;
                newTarget.X *= 1.5f; //Scale so that the jump looks correct
                newTarget.Y *= 1.5f;
                newTarget.Z *= -0.2f;
                SetVelocityAndTargetInternal(m_controllingPrim.RawVelocity, newTarget, false, 3);
                m_jumpFallState = true;
            }
            else if (m_jumpFallState && m_jumpStart != 0 && m_controllingPrim.IsColliding &&
                     Util.EnvironmentTickCountSubtract(m_jumpStart) > 1500 ||
                     (m_jumpStart != 0 && Util.EnvironmentTickCountSubtract(m_jumpStart) > 10000)) //Fallback
            {
                //Reset everything in case something went wrong
                m_disallowTargetVelocitySet    = false;
                m_jumpFallState                = false;
                m_controllingPrim.IsPreJumping = false;
                m_controllingPrim.IsJumping    = false;
                m_jumpStart    = 0;
                m_preJumpStart = 0;
            }
        }