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

