Advertisement
Guest User

Untitled

a guest
Mar 3rd, 2015
488
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.16 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. [System.Serializable]
  5. public class BendingSegment {
  6.     public Transform firstTransform;
  7.     public Transform lastTransform;
  8.     public float thresholdAngleDifference = 0;
  9.     public float bendingMultiplier = 0.6f;
  10.     public float maxAngleDifference = 30;
  11.     public float maxBendingAngle = 80;
  12.     public float responsiveness = 5;
  13.     internal float angleH;
  14.     internal float angleV;
  15.     internal Vector3 dirUp;
  16.     internal Vector3 referenceLookDir;
  17.     internal Vector3 referenceUpDir;
  18.     internal int chainLength;
  19.     internal Quaternion[] origRotations;
  20. }
  21.  
  22. [System.Serializable]
  23. public class NonAffectedJoints {
  24.     public Transform joint;
  25.     public float effect = 0;
  26. }
  27.  
  28. public class HeadLookController : MonoBehaviour {
  29.    
  30.     public Transform rootNode;
  31.     public BendingSegment[] segments;
  32.     public NonAffectedJoints[] nonAffectedJoints;
  33.     public Vector3 headLookVector = Vector3.forward;
  34.     public Vector3 headUpVector = Vector3.up;
  35.     public GameObject targetObject = null;
  36.     public GameObject otherObject = null;
  37.     public float effect = 1;
  38.     public bool overrideAnimation = false;
  39.     public bool findBones = true;
  40.     bool isPlayer = false;
  41.     bool lookAtPlayer = true;
  42.     float deltaT = 0f;
  43.    
  44.     void Start () {
  45.         if(findBones)
  46.         {
  47.             find_bones(transform);
  48.         }
  49.        
  50.         if (rootNode == null) {
  51.             rootNode = transform;
  52.         }
  53.        
  54.         // Setup segments
  55.         foreach (BendingSegment segment in segments) {
  56.             Quaternion parentRot = segment.firstTransform.parent.rotation;
  57.             Quaternion parentRotInv = Quaternion.Inverse(parentRot);
  58.             segment.referenceLookDir =
  59.                 parentRotInv * rootNode.rotation * headLookVector.normalized;
  60.             segment.referenceUpDir =
  61.                 parentRotInv * rootNode.rotation * headUpVector.normalized;
  62.             segment.angleH = 0;
  63.             segment.angleV = 0;
  64.             segment.dirUp = segment.referenceUpDir;
  65.            
  66.             segment.chainLength = 1;
  67.             Transform t = segment.lastTransform;
  68.             while (t != segment.firstTransform && t != t.root) {
  69.                 segment.chainLength++;
  70.                 t = t.parent;
  71.             }
  72.            
  73.             segment.origRotations = new Quaternion[segment.chainLength];
  74.             t = segment.lastTransform;
  75.             for (int i=segment.chainLength-1; i>=0; i--) {
  76.                 segment.origRotations[i] = t.localRotation;
  77.                 t = t.parent;
  78.             }
  79.         }
  80.  
  81.         if (targetObject.transform.Find ("OVRCameraRig/CenterEyeAnchor"))
  82.         {
  83.             isPlayer = true;
  84.         }
  85.     }
  86.    
  87.     void LateUpdate () {
  88.         if (Time.deltaTime == 0)
  89.             return;
  90.  
  91.         if(otherObject)
  92.         {
  93.             //shift vision between object every so often
  94.             deltaT += Time.deltaTime;
  95.             if(deltaT > 10f)
  96.             {
  97.                 lookAtPlayer = !lookAtPlayer;
  98.                 deltaT = 0f;
  99.             }
  100.         }
  101.        
  102.         // Remember initial directions of joints that should not be affected
  103.         Vector3[] jointDirections = new Vector3[nonAffectedJoints.Length];
  104.         for (int i=0; i<nonAffectedJoints.Length; i++) {
  105.             foreach (Transform child in nonAffectedJoints[i].joint) {
  106.                 jointDirections[i] = child.position - nonAffectedJoints[i].joint.position;
  107.                 break;
  108.             }
  109.         }
  110.        
  111.         // Handle each segment
  112.         foreach (BendingSegment segment in segments) {
  113.             Transform t = segment.lastTransform;
  114.             if (overrideAnimation) {
  115.                 for (int i=segment.chainLength-1; i>=0; i--) {
  116.                     t.localRotation = segment.origRotations[i];
  117.                     t = t.parent;
  118.                 }
  119.             }
  120.            
  121.             Quaternion parentRot = segment.firstTransform.parent.rotation;
  122.             Quaternion parentRotInv = Quaternion.Inverse(parentRot);
  123.            
  124.             // Desired look direction in world space
  125.             Vector3 lookDirWorld;
  126.  
  127.             if(lookAtPlayer)
  128.             {
  129.                 if(isPlayer)
  130.                 {
  131.                     lookDirWorld = (targetObject.transform.Find("OVRCameraRig/CenterEyeAnchor").position - segment.lastTransform.position).normalized;
  132.                 }
  133.                 else
  134.                 {
  135.                     lookDirWorld = (targetObject.transform.position - segment.lastTransform.position).normalized;
  136.                 }
  137.             }
  138.             else
  139.             {
  140.                 lookDirWorld = (otherObject.transform.position - segment.lastTransform.position).normalized;
  141.             }
  142.            
  143.             // Desired look directions in neck parent space
  144.             Vector3 lookDirGoal = (parentRotInv * lookDirWorld);
  145.            
  146.             // Get the horizontal and vertical rotation angle to look at the target
  147.             float hAngle = AngleAroundAxis(
  148.                 segment.referenceLookDir, lookDirGoal, segment.referenceUpDir
  149.                 );
  150.            
  151.             Vector3 rightOfTarget = Vector3.Cross(segment.referenceUpDir, lookDirGoal);
  152.            
  153.             Vector3 lookDirGoalinHPlane =
  154.                 lookDirGoal - Vector3.Project(lookDirGoal, segment.referenceUpDir);
  155.            
  156.             float vAngle = AngleAroundAxis(
  157.                 lookDirGoalinHPlane, lookDirGoal, rightOfTarget
  158.                 );
  159.            
  160.             // Handle threshold angle difference, bending multiplier,
  161.             // and max angle difference here
  162.             float hAngleThr = Mathf.Max(
  163.                 0, Mathf.Abs(hAngle) - segment.thresholdAngleDifference
  164.                 ) * Mathf.Sign(hAngle);
  165.            
  166.             float vAngleThr = Mathf.Max(
  167.                 0, Mathf.Abs(vAngle) - segment.thresholdAngleDifference
  168.                 ) * Mathf.Sign(vAngle);
  169.            
  170.             hAngle = Mathf.Max(
  171.                 Mathf.Abs(hAngleThr) * Mathf.Abs(segment.bendingMultiplier),
  172.                 Mathf.Abs(hAngle) - segment.maxAngleDifference
  173.                 ) * Mathf.Sign(hAngle) * Mathf.Sign(segment.bendingMultiplier);
  174.            
  175.             vAngle = Mathf.Max(
  176.                 Mathf.Abs(vAngleThr) * Mathf.Abs(segment.bendingMultiplier),
  177.                 Mathf.Abs(vAngle) - segment.maxAngleDifference
  178.                 ) * Mathf.Sign(vAngle) * Mathf.Sign(segment.bendingMultiplier);
  179.            
  180.             // Handle max bending angle here
  181.             hAngle = Mathf.Clamp(hAngle, -segment.maxBendingAngle, segment.maxBendingAngle);
  182.             vAngle = Mathf.Clamp(vAngle, -segment.maxBendingAngle, segment.maxBendingAngle);
  183.            
  184.             Vector3 referenceRightDir =
  185.                 Vector3.Cross(segment.referenceUpDir, segment.referenceLookDir);
  186.            
  187.             // Lerp angles
  188.             segment.angleH = Mathf.Lerp(
  189.                 segment.angleH, hAngle, Time.deltaTime * segment.responsiveness
  190.                 );
  191.             segment.angleV = Mathf.Lerp(
  192.                 segment.angleV, vAngle, Time.deltaTime * segment.responsiveness
  193.                 );
  194.            
  195.             // Get direction
  196.             lookDirGoal = Quaternion.AngleAxis(segment.angleH, segment.referenceUpDir)
  197.                 * Quaternion.AngleAxis(segment.angleV, referenceRightDir)
  198.                     * segment.referenceLookDir;
  199.            
  200.             // Make look and up perpendicular
  201.             Vector3 upDirGoal = segment.referenceUpDir;
  202.             Vector3.OrthoNormalize(ref lookDirGoal, ref upDirGoal);
  203.            
  204.             // Interpolated look and up directions in neck parent space
  205.             Vector3 lookDir = lookDirGoal;
  206.             segment.dirUp = Vector3.Slerp(segment.dirUp, upDirGoal, Time.deltaTime*5);
  207.             Vector3.OrthoNormalize(ref lookDir, ref segment.dirUp);
  208.            
  209.             // Look rotation in world space
  210.             Quaternion lookRot = (
  211.                 (parentRot * Quaternion.LookRotation(lookDir, segment.dirUp))
  212.                 * Quaternion.Inverse(
  213.                 parentRot * Quaternion.LookRotation(
  214.                 segment.referenceLookDir, segment.referenceUpDir
  215.                 )
  216.                 )
  217.                 );
  218.            
  219.             // Distribute rotation over all joints in segment
  220.             Quaternion dividedRotation =
  221.                 Quaternion.Slerp(Quaternion.identity, lookRot, effect / segment.chainLength);
  222.             t = segment.lastTransform;
  223.             for (int i=0; i<segment.chainLength; i++) {
  224.                 t.rotation = dividedRotation * t.rotation;
  225.                 t = t.parent;
  226.             }
  227.         }
  228.        
  229.         // Handle non affected joints
  230.         for (int i=0; i<nonAffectedJoints.Length; i++) {
  231.             Vector3 newJointDirection = Vector3.zero;
  232.            
  233.             foreach (Transform child in nonAffectedJoints[i].joint) {
  234.                 newJointDirection = child.position - nonAffectedJoints[i].joint.position;
  235.                 break;
  236.             }
  237.            
  238.             Vector3 combinedJointDirection = Vector3.Slerp(
  239.                 jointDirections[i], newJointDirection, nonAffectedJoints[i].effect
  240.                 );
  241.            
  242.             nonAffectedJoints[i].joint.rotation = Quaternion.FromToRotation(
  243.                 newJointDirection, combinedJointDirection
  244.                 ) * nonAffectedJoints[i].joint.rotation;
  245.         }
  246.     }
  247.    
  248.     // The angle between dirA and dirB around axis
  249.     public static float AngleAroundAxis (Vector3 dirA, Vector3 dirB, Vector3 axis) {
  250.         // Project A and B onto the plane orthogonal target axis
  251.         dirA = dirA - Vector3.Project(dirA, axis);
  252.         dirB = dirB - Vector3.Project(dirB, axis);
  253.        
  254.         // Find (positive) angle between A and B
  255.         float angle = Vector3.Angle(dirA, dirB);
  256.        
  257.         // Return angle multiplied with 1 or -1
  258.         return angle * (Vector3.Dot(axis, Vector3.Cross(dirA, dirB)) < 0 ? -1 : 1);
  259.     }
  260.  
  261.     void find_bones(Transform parent)
  262.     {
  263.         foreach( Transform t in parent )
  264.         {
  265.             find_bones( t );
  266.  
  267.             string name = t.name.ToLower();
  268.  
  269.             if(name.EndsWith("root"))
  270.             {
  271.                 rootNode = t;
  272.             }
  273.             else if(   segments.Length >= 1
  274.                     && name.EndsWith("torso2"))
  275.             {
  276.                 segments[0].firstTransform = t;
  277.             }
  278.             else if(   segments.Length >= 1
  279.                     && name.EndsWith("neck"))
  280.             {
  281.                 segments[0].lastTransform = t;
  282.  
  283.                 if(segments.Length >= 2)
  284.                     segments[1].firstTransform = t;
  285.             }
  286.             else if(   segments.Length >= 2
  287.                     && name.EndsWith("head"))
  288.             {
  289.                 segments[1].lastTransform = t;
  290.             }
  291.             else if( segments.Length >= 4 )
  292.             {
  293.                 if(name.EndsWith("lefteye"))
  294.                 {
  295.                     segments[2].firstTransform = t;
  296.                 }
  297.                 else if(   name.EndsWith("lefteyetip")
  298.                         || name.EndsWith("hidarimemodo"))
  299.                 {
  300.                     segments[2].lastTransform = t;
  301.                 }
  302.                 else if(name.EndsWith("righteye"))
  303.                 {
  304.                     segments[3].firstTransform = t;
  305.                 }
  306.                 else if(   name.EndsWith("righteyetip")
  307.                         || name.EndsWith("migimemodo"))
  308.                 {
  309.                     segments[3].lastTransform = t;
  310.                 }
  311.             }
  312.         }
  313.     }
  314. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement