// Called just before the simulation step. Update the vertical position for hoverness. private 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; } else { m_controllingPrim.ForcePosition = movePosition; } m_physicsScene.DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", m_controllingPrim.LocalID, origPosition, movePosition); }
// 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_controllingPrim.VolumeDetect) { m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotor", 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); // no BSParam.AvatarJumpFrames supported in this Version :( } // '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); } 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; } }