Universe.Physics.BulletSPlugin.BSActorAvatarMove.WalkUpStairs C# (CSharp) Method

WalkUpStairs() private method

private WalkUpStairs ( ) : OpenMetaverse.Vector3
return OpenMetaverse.Vector3
        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);
            m_physicsScene.DetailLog(
                "{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}",
                m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count,
                m_controllingPrim.Size.Z);

            // 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
                // Note: ther 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) - BSParam.AvatarStepGroundFudge;
                float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;

                // look for a collision point that is near the character's feet and is oriented the same as the character is.
                // find the highest 'good' collision.
                OMV.Vector3 highestTouchPosition = OMV.Vector3.Zero;
                // no m_objCollisionsList :(
                foreach (
                    KeyValuePair<uint, ContactPoint> kvp in m_controllingPrim.CollisionsLastTick.GetCollisionEvents())
                {
                    // 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);
                            const float PIOver2 = 1.571f; // Used to make unit vector axis into approx radian angles
                            // m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,avNormal={1},colNormal={2},diff={3}",
                            //             m_controllingPrim.LocalID, directionFacing, touchNormal,
                            //             Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal)) );
                            if ((Math.Abs(directionFacing.Z) * PIOver2) < BSParam.AvatarStepAngle
                                && (Math.Abs(touchNormal.Z) * PIOver2) < BSParam.AvatarStepAngle)
                            {
                                // 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.
                                float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
                                if (diff < BSParam.AvatarStepApproachFactor)
                                {
                                    if (highestTouchPosition.Z < touchPosition.Z)
                                        highestTouchPosition = touchPosition;
                                }
                            }
                        }
                    }
                }
        

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