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