티스토리 뷰

반응형

 

 

이 글은 절대 정확한 주석이 아닙니다.

 

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace RootMotion.FinalIK {
	
	/// <summary>
	/// A full-body IK solver designed specifically for a VR HMD and hand controllers.
	/// </summary>
	//[HelpURL("http://www.root-motion.com/finalikdox/html/page16.html")]
	[AddComponentMenu("Scripts/RootMotion.FinalIK/IK/VR IK")]
	public class VRIK : IK
    {
        /// <summary>
        /// 이족보행 관련 휴머노이드의 VRIK 관련 게임 오브젝트 클래스
        /// Optional이 붙어있다면, 선택적인 오브젝트 ( 없어도 되고, 있어도 된다. ) 라고 생각하면 됩니다.
        /// 해당 변수들은, 위치값 오브젝트라고 생각하자.
        /// </summary>
        [System.Serializable]
		public class References
        {
            public Transform root;			// 0 , 제일 부모의 오브젝트, 캐릭터 전체를 가지고 있는 부모 오브젝트이다.
			public Transform pelvis;		// 1 , 골반 오브젝트
			public Transform spine;         // 2 , 척추 오브젝트

            [Tooltip("Optional")]
            public Transform chest;         // 3 Optional , 가슴부분 오브젝트

            [Tooltip("Optional")]
            public Transform neck; 			// 4 Optional , 목 오브젝트
			public Transform head;          // 5 머리 오브젝트

            [Tooltip("Optional")]
            public Transform leftShoulder;	// 6 Optional , 왼쪽 어깨 오브젝트
			public Transform leftUpperArm;	// 7, 왼쪽 윗팔 오브젝트
			public Transform leftForearm;	// 8, 왼쪽 아래팔 오브젝트
			public Transform leftHand;      // 9, 왼쪽 손 오브젝트 

            [Tooltip("Optional")]
            public Transform rightShoulder;	// 10 Optional , 오른쪽 어깨 오브젝트
			public Transform rightUpperArm;	// 11, 오른쪽 윗팔 오브젝트
			public Transform rightForearm;	// 12, 오른쪽 아래팔 오브젝트
			public Transform rightHand;     // 13, 오른쪽 손 오브젝트

            [Tooltip("VRIK also supports legless characters.If you do not wish to use legs, leave all leg references empty.")]
            public Transform leftThigh;     // 14 Optional, 왼쪽 허벅지 오브젝트

            [Tooltip("VRIK also supports legless characters.If you do not wish to use legs, leave all leg references empty.")]
            public Transform leftCalf;      // 15 Optional, 왼쪽 장딴지 오브젝트

            [Tooltip("VRIK also supports legless characters.If you do not wish to use legs, leave all leg references empty.")]
            public Transform leftFoot;      // 16 Optional, 왼쪽 발 오브젝트

            [Tooltip("Optional")]
			public Transform leftToes;      // 17 Optional, 왼쪽 발가락 오브젝트

            [Tooltip("VRIK also supports legless characters.If you do not wish to use legs, leave all leg references empty.")]
            public Transform rightThigh;    // 18 Optional, 오른쪽 허벅지 오브젝트

            [Tooltip("VRIK also supports legless characters.If you do not wish to use legs, leave all leg references empty.")]
            public Transform rightCalf;     // 19 Optional, 오른쪽 장딴지 오브젝트

            [Tooltip("VRIK also supports legless characters.If you do not wish to use legs, leave all leg references empty.")]
            public Transform rightFoot;     // 20 Optional, 오른쪽 발 오브젝트

            [Tooltip("Optional")]
            public Transform rightToes;		// 21 Optional, 오른쪽 발가락 오브젝트

            /// <summary>
            /// 정의된 오브젝트들의 위치값을 받아 반환한다.
            /// </summary>
            public Transform[] GetTransforms() {
				return new Transform[22] {
					root, pelvis, spine, chest, neck, head, leftShoulder, leftUpperArm, leftForearm, leftHand, rightShoulder, rightUpperArm, rightForearm, rightHand, leftThigh, leftCalf, leftFoot, leftToes, rightThigh, rightCalf, rightFoot, rightToes
				};
			}

			/// <summary>
			/// 필요한 오브젝트들이 정의되었는 지를 반환한다. (단, 어깨,발가락,목 뼈의 관련 된 건 선택사항 )
			/// </summary>
			public bool isFilled
            {
				get
                {
                    // 부모, 골반, 척추, 머리, 왼쪽 윗팔, 아래팔, 손, 오른쪽 윗팔, 아래팔, 손이 만약에 비어있다면 
                    if ( root == null || pelvis == null || spine == null || head == null || leftUpperArm == null || leftForearm == null || leftHand == null || rightUpperArm == null || rightForearm == null || rightHand == null)
                    {
                        return false;       // isFilled를 false로 반환한다.
                    }

                    // 만약에, 다리에 관련 된 오브젝트들이 전부 비어있다면, noLegBones의 값은 true가 된다.
                    bool noLegBones = leftThigh == null && leftCalf == null && leftFoot == null && rightThigh == null && rightCalf == null && rightFoot == null;

                    // noLegBones의 값이 true라면, isFilled는 true가 된다.
                    if (noLegBones)
                    {
                        return true;
                    }

                    // 다리에 관련 된 오브젝트들이 하나라도 비어있는 지를 체크한다. 하나라도 비어있다면, atLeastOneLegBoneMissing의 값은 true가 된다.
                    bool atLeastOneLegBoneMissing = leftThigh == null || leftCalf == null || leftFoot == null || rightThigh == null || rightCalf == null || rightFoot == null;
                    
                    // atLeastOneLegBoneMissing의 값이 true라면
                    if (atLeastOneLegBoneMissing)
                    {
                        return false;       // isFilled의 값은 false가 된다. 
                    }

                    // 어깨, 발가락, 목 뼈관련 오브젝트는 있어도 되고 없어도 된다.
                    return true;        // 저 위에 모든 조건이 맞지 않는다면, 모든 오브젝트가 정의되어 있기에 isFilled는 true가 된다. 
				}
			}

            /// <summary>
            /// 반환값이 할당되지 않은 경우 true를 반환한다.
            /// </summary>
            public bool isEmpty
            {
                get
                {
                    if (root != null || pelvis != null || spine != null || chest != null ||
                        neck != null || head != null || leftShoulder != null || leftUpperArm != null ||
                        leftForearm != null || leftHand != null || rightShoulder != null || rightUpperArm != null ||
                        rightForearm != null || rightHand != null || leftThigh != null || leftCalf != null ||
                        leftFoot != null || leftToes != null || rightThigh != null || rightCalf != null ||
                        rightFoot != null || rightToes != null) { return false; }

                    return true;
                }
            }

            /// <summary>
            /// VRIK 참조를 자동 감지하고, 루트 게임 오브젝트에서만 휴머노이드 애니메이터와 함께 작동한다.
            /// </summary>
            public static bool AutoDetectReferences(Transform root, out References references)
            {
				references = new References();      // References 클래스를 할당 및 생성

				var animator = root.GetComponentInChildren<Animator>();     // root 또는 자식 오브젝트에 , Animator 컴포넌트가 있는 지를 확인한다. 그리고, animator 변수에 넘겨준다.

				if (animator == null || !animator.isHuman)        // 만약, animator의 값이 없거나, 또는 animator가 휴머노이드 형태가 아니라면
                {
					Debug.LogWarning("VRIK는 이족보행 참조를 자동 감지하려면 휴머노이드 애니메이터가 필요합니다. 참조를 수동으로 지정하십시오.");
					return false;
				}

				references.root = root;                                                         // references의 root에, root를 대입한다.

                // Avatar에 맵핑된 각각의 부위들의 오브젝트들을 불러와서 대입을 해준다.
                references.pelvis = animator.GetBoneTransform(HumanBodyBones.Hips);             
				references.spine = animator.GetBoneTransform(HumanBodyBones.Spine);
				references.chest = animator.GetBoneTransform(HumanBodyBones.Chest);
				references.neck = animator.GetBoneTransform(HumanBodyBones.Neck);
				references.head = animator.GetBoneTransform(HumanBodyBones.Head);
				references.leftShoulder = animator.GetBoneTransform(HumanBodyBones.LeftShoulder);
				references.leftUpperArm = animator.GetBoneTransform(HumanBodyBones.LeftUpperArm);
				references.leftForearm = animator.GetBoneTransform(HumanBodyBones.LeftLowerArm);
				references.leftHand = animator.GetBoneTransform(HumanBodyBones.LeftHand);
				references.rightShoulder = animator.GetBoneTransform(HumanBodyBones.RightShoulder);
				references.rightUpperArm = animator.GetBoneTransform(HumanBodyBones.RightUpperArm);
				references.rightForearm = animator.GetBoneTransform(HumanBodyBones.RightLowerArm);
				references.rightHand = animator.GetBoneTransform(HumanBodyBones.RightHand);
				references.leftThigh = animator.GetBoneTransform(HumanBodyBones.LeftUpperLeg);
				references.leftCalf = animator.GetBoneTransform(HumanBodyBones.LeftLowerLeg);
				references.leftFoot = animator.GetBoneTransform(HumanBodyBones.LeftFoot);
				references.leftToes = animator.GetBoneTransform(HumanBodyBones.LeftToes);
				references.rightThigh = animator.GetBoneTransform(HumanBodyBones.RightUpperLeg);
				references.rightCalf = animator.GetBoneTransform(HumanBodyBones.RightLowerLeg);
				references.rightFoot = animator.GetBoneTransform(HumanBodyBones.RightFoot);
				references.rightToes = animator.GetBoneTransform(HumanBodyBones.RightToes);

				return true;        // true를 반환해준다.
			}
		}

		// Open the User Manual URL
		[ContextMenu("User Manual")]
		protected override void OpenUserManual() {
			Application.OpenURL("http://www.root-motion.com/finalikdox/html/page16.html");
		}
		
		// Open the Script Reference URL
		[ContextMenu("Scrpt Reference")]
		protected override void OpenScriptReference() {
			Application.OpenURL("http://www.root-motion.com/finalikdox/html/class_root_motion_1_1_final_i_k_1_1_v_r_i_k.html");
		}

		// Open a video tutorial about setting up the component
		[ContextMenu("TUTORIAL VIDEO (STEAMVR SETUP)")]
		void OpenSetupTutorial() {
			Application.OpenURL("https://www.youtube.com/watch?v=6Pfx7lYQiIA&feature=youtu.be");
		}

        /// <summary>
        /// Bone mapping. Right-click on the component header and select 'Auto-detect References' of fill in manually if not a Humanoid character. Chest, neck, shoulder and toe bones are optional. VRIK also supports legless characters. If you do not wish to use legs, leave all leg references empty.
        /// </summary>
        [ContextMenuItem("Auto-detect References", "AutoDetectReferences")]
		[Tooltip("휴머노이드가 아닐 경우에는 수동으로 채워야하며, 만약에 지웠다가 자동으로 채우고 싶다면, VRIK 컴포넌트에서, References에 오른쪽 마우스를 클릭하여, Auto-detect References를 클릭하자.")]
		public References references = new References();            // References 클래스 변수를 할당하고 생성한다.
		
		/// <summary>
		/// Solver, 번역하면, 해결자라고도 하는데, Solver를 통해, IK에 필요한 오브젝트의 무게나, 걷는 속도 등등 IK에 필요한 값들을 넣어줄 수 있다.
		/// </summary>
		[Tooltip("The VRIK solver.")]
		public IKSolverVR solver = new IKSolverVR();        // IKSolverVR의 클래스를 할당하고 생성한다.

        /// <summary>
        /// 이 VRIK에 대한 본 참조를 자동 감지합니다. 게임 오브젝트에서만 휴머노이드 애니메이터와 함께 작동합니다.
        /// </summary>
        [ContextMenu("Auto-detect References")]
		public void AutoDetectReferences()          // 자동으로 각각의 오브젝트에 대한 대입을 해주는 함수를 호출하는 함수.
        {
			References.AutoDetectReferences(transform, out references);     // References 클래스의 AutoDetectReferences 함수를 실행한다. transform과, references 변수를 넘긴다.
		}

		/// <summary>
		/// 손 방향을 추측한다.
		/// </summary>
		[ContextMenu("Guess Hand Orientations")]
		public void GuessHandOrientations()         // 손 방향을 추측한다.
        {
			solver.GuessHandOrientations(references, false);        // solver의 GuessHandOrientations 함수를 실행하고, references와, false값을 넘긴다.
		}

		public override IKSolver GetIKSolver()      // IKSolver를 가져온다.
        {
			return solver as IKSolver;      // solver를 IKSolver로 형변환을 하고 반환한다.
		}

		protected override void InitiateSolver()            // Solver를 초기화하는 함수.
        {
			if (references.isEmpty) AutoDetectReferences();         // 만약 하나라도, 각 부위의 오브젝트가 비어있다면 자동감지를 한다.
			if (references.isFilled) solver.SetToReferences(references);    // 필요한 오브젝트들이 모두 정의되어 있다면, references를 넘기고, solver의 SetToReferences 함수를 실행한다.

			base.InitiateSolver();          // 부모클래스의 InitiateSolver 함수를 실행.
		}

		protected override void UpdateSolver()              // Solver를 업데이트 하는 함수.
        {
			if (references.root != null && references.root.localScale == Vector3.zero)      // root의 값이 비어있지 않는데, root의 Scale값이 만약에, 0,0,0이라면
            {
				Debug.LogError("root에 대입 된 오브젝트의 Scale값이 0입니다. 한 번 확인해주세요!", transform);
				enabled = false;        // enabled를 false로 변경
				return;
			}

			base.UpdateSolver();        // 만약, 비어있지도 않았는데, scale값이 0,0,0이 아니라면 부모클래스에 있는 UpdateSolver 함수를 실행.
		}
	}
}

 

지금까지 VR 초보자 Base Of Coding이였습니다.

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함