https://github.com/google/grafika
using UnityEngine; using System.Collections; using UnityEngine.UI; public class Cursor_UR : MonoBehaviour { public GameObject CUR_Outer; public GameObject CUR_Inner; public GameObject ArgosSphere; public Text d_Position; public GameObject camHead; public class CursorTran { public Vector3 pos; public Transform normProjTrans; public Transform CUR_InnerProjTrans; public bool bValid = false; }; private CursorTran _cursorTran = new CursorTran(); public CursorTran cursorTran { get { return _cursorTran; } } private bool _cursorTrailModeOn; public bool bCursorTrailModeOn { set { _cursorTrailModeOn = value; } get { return _cursorTrailModeOn; } } public bool isCursorValid() { return _cursorTran.bValid; } // Use this for initialization void Start() { //camHead = GameObject.Find("Argos_Camera"); //ArgosSphere = GameObject.Find("Argos_Sphere"); //StartCoroutine(StartCursor(1.5F, "1")); } IEnumerator StartCursor(float waitTime, string jomo) { yield return new WaitForSeconds(waitTime); //togCurs.isOn = true; } // Update is called once per frame void Update() { //if(camHead == null) //{ // camHead = GameObject.Find("Argos_Camera"); //} //else //{ OnPoseUpdated(camHead.transform); //} } public Vector3 getCursorPostiion() { return cursorTran.pos - ArgosSphere.transform.position; } public void MoveScreenIndicator(Vector3 pos, Transform mPose, Vector3 vR) { CUR_Inner.transform.position = pos; //vPaddleVel = (pos - vPaddlePos_Last)/Time.deltaTime; //vPaddlePos_Last = pos; Quaternion rotation = Quaternion.LookRotation(vR.normalized, mPose.up); CUR_Inner.transform.rotation = rotation; _cursorTran.CUR_InnerProjTrans = CUR_Inner.transform; } private bool IsRayIntersecting(Transform mPose) { //Let s be the start point of the ray, and d a unit vector in the direction of the ray. //Let c be the center point of the sphere, and r its radius. Vector3 s = mPose.transform.position; Vector3 d = mPose.transform.forward; Vector3 c = ArgosSphere.transform.position; float r = ArgosSphere.GetComponent<ArgosSphere_Indexing>().radius; // Calculate ray's start offset from the sphere center Vector3 p = s - c; float rSquared = r * r; float p_d = Vector3.Dot(p, d); // The sphere is behind or surrounding the start point. //if (p_d < 0 || Vector3.Dot(p, p) < rSquared) // return false; // Flatten p into the plane passing through c perpendicular to the ray. // This gives the closest approach of the ray to the center. Vector3 a = p - p_d * d; float aSquared = Vector3.Dot(a, a); // Closest approach is outside the sphere. if (aSquared > rSquared) return false; return true; } public void OnPoseUpdated(Transform mPose) { _cursorTran.bValid = IsRayIntersecting(mPose); if (_cursorTran.bValid) { float R = ArgosSphere.GetComponent<ArgosSphere_Indexing>().radius; Vector3 vPC = ArgosSphere.transform.position - mPose.position; Vector3 vBpos = mPose.position + Vector3.Dot(vPC, mPose.forward) * mPose.forward; Vector3 vBC = vBpos - ArgosSphere.transform.position; float BClen = vBC.magnitude; float BDlen = Mathf.Sqrt(R * R - BClen * BClen); Vector3 D = vBpos + mPose.forward * BDlen; //d_Position.text = D.ToString(); CUR_Outer.transform.position = D; _cursorTran.pos = D; Vector3 vR = D - ArgosSphere.transform.position; Quaternion rotation = Quaternion.LookRotation(vR.normalized, Vector3.up); CUR_Outer.transform.rotation = rotation; _cursorTran.normProjTrans = CUR_Outer.transform; MoveScreenIndicator(D, mPose, vR); } //MoveBall(); } }