top of page

// The following is a redirector, similar to a redirector in THE REDIRECTED WALKING TOOLKIT.

// http://projects.ict.usc.edu/mxr/rdwt/

​

using UnityEngine;
using System.Collections;
using Redirection;

public class MayaRedirector : Redirector {
    public enum AlgorithmChoice { Curvature, Rotation, Distance, ZigZag };

    public AlgorithmChoice algorithm = AlgorithmChoice.Curvature;

    // User Experience Improvement Parameters
    private const float MOVEMENT_THRESHOLD = 0.2f; // meters per second
    private const float ROTATION_THRESHOLD = 1.5f; // degrees per second
    private const float CURVATURE_GAIN_CAP_DEGREES_PER_SECOND = 15;  // degrees per second
    private const float ROTATION_GAIN_CAP_DEGREES_PER_SECOND = 30;  // degrees per second
    private const float SMOOTHING_FACTOR = 0.125f; // Smoothing factor for redirection rotations

    // Auxiliary Parameters
    private float rotationFromCurvatureGain; //Proposed curvature gain based on user speed
    private float rotationFromRotationGain; //Proposed rotation gain based on head's yaw
    private float lastRotationApplied = 0f;

    public override void ApplyRedirection()
    {
        // Get Required Data
        Vector3 deltaPos = redirectionManager.deltaPos;
        float deltaDir = redirectionManager.deltaDir;

        // 1. Curvature example
        // We want to steer in a constant direction relative to the user (for example always clock-wise direction)
        // direction=1 will make the user rotate CCW.
        int desiredSteeringDirection = 1;

        rotationFromCurvatureGain = 0;
        //Compute proposed rotation gain
        rotationFromRotationGain = 0;


        if (deltaPos.magnitude / redirectionManager.GetDeltaTime() > MOVEMENT_THRESHOLD) //User is moving
        {
            rotationFromCurvatureGain = Mathf.Rad2Deg * (deltaPos.magnitude / redirectionManager.CURVATURE_RADIUS);
            rotationFromCurvatureGain = Mathf.Min(rotationFromCurvatureGain, CURVATURE_GAIN_CAP_DEGREES_PER_SECOND * redirectionManager.GetDeltaTime());
        }

        // 2. Rotation example
        if (Mathf.Abs(deltaDir) / redirectionManager.GetDeltaTime() >= ROTATION_THRESHOLD)  //if User is rotating
        {
            if (algorithm == AlgorithmChoice.Rotation) {
                // Increase rotation CCW and decrease CW.
                if (deltaDir < 0) {
                    //Rotating with the user
                    rotationFromRotationGain = Mathf.Min (Mathf.Abs (deltaDir * redirectionManager.MAX_ROT_GAIN), ROTATION_GAIN_CAP_DEGREES_PER_SECOND * redirectionManager.GetDeltaTime ());
                } else { // deltaDir >= 0
                    //Rotating against the user
                    rotationFromRotationGain = Mathf.Min (Mathf.Abs (deltaDir * redirectionManager.MIN_ROT_GAIN), ROTATION_GAIN_CAP_DEGREES_PER_SECOND * redirectionManager.GetDeltaTime ());
                }
            } 
        }

        // 4. ZigZag Example
        if (algorithm == AlgorithmChoice.ZigZag) {
            rotationFromRotationGain = Mathf.Abs (deltaDir * redirectionManager.MAX_ROT_GAIN * 0.2F);
        }

        float rotationProposed = 0;
        Vector3 deltaPosProposed = Vector3.zero;
        if (algorithm == AlgorithmChoice.Curvature) {
            rotationProposed = desiredSteeringDirection * rotationFromCurvatureGain;
        } else if (algorithm == AlgorithmChoice.Rotation) {
            // Always rotate to the same direction.
            rotationProposed = -1 * rotationFromRotationGain;
        } else if (algorithm == AlgorithmChoice.ZigZag) {
            // Always rotate to the same direction.
            rotationProposed = -1 * Mathf.Sign (deltaDir) * rotationFromRotationGain;
        } else if (algorithm == AlgorithmChoice.Distance) {
            // 3. Distance example
            // Decrease speed when going forward, increase when going backwards.
            Vector3 increaseDirection = Vector3.right; // Forward
            if (Vector3.Dot(increaseDirection, deltaPos) > 0) {
                // Going forward, decrease delta.
                deltaPosProposed = redirectionManager.MIN_TRANS_GAIN * deltaPos;
            } else {
                // Going backwards, increase delta.
                deltaPosProposed = redirectionManager.MAX_TRANS_GAIN * deltaPos;
            }
        }

        // Prevent having gains if user is stationary
        if (!Mathf.Approximately (rotationProposed, 0)) {
            // Implement additional rotation with smoothing
            float finalRotation = (1.0f - SMOOTHING_FACTOR) * lastRotationApplied + SMOOTHING_FACTOR * rotationProposed;
            lastRotationApplied = finalRotation;
            if (algorithm == AlgorithmChoice.Curvature) {
                InjectCurvature (finalRotation);
            } else {
                InjectRotation (finalRotation / 5);
            }
        }

        InjectTranslation(deltaPosProposed);
    }
}

 

bottom of page