之前在試玩一些塗塗樂的應用,發現大多數AR掃描時,屏幕都會有一個掃描框。個人覺得這樣的設計非常不錯,只有當需要的識別圖出現在掃描框內時纔可以渲染出模型。
這兩天抽出時間,做了一個簡單的demo。
環境:
- unity5.2.2
- vuforia6.2.10
創建面片
在場景中新建面片Plane,調整面片的位置和大小與Imagetarget重合。
掃描框的四個屏幕座標
首先在Canvas上創建一個Image作爲掃描框,屏幕的分辨率是800*600,而Image的大小爲400*300.單擊canvas在右側的Inspector,把Canvas——Render Mode設置爲Screen Space—overlay。在Canvas Scaler的UI Scale Moder設置爲Scale With Sceen Size。
掃描框的四個座標,如下圖所示:
那麼由此得出
TopLeft_UI = new Vector2 ((Screen.width-400)*0.5f,(Screen.height-300)*0.5f+300f);
BottomLeft_UI = new Vector2 ((Screen.width-400)*0.5f,(Screen.height-300)*0.5f);
TopRight_UI = new Vector2 ((Screen.width-400)*0.5f+400f,(Screen.height-300)*0.5f+300f);
BottomRight_UI = new Vector2 ((Screen.width-400)*0.5f+400f,(Screen.height-300)*0.5f);
計算面片上的四個點的座標
在Plane新建四個空節點,位置調整到plane的四個頂點上。
在腳本上獲取到這四個點的世界座標
public Transform TopLeft_PI; //面片左上角座標
public Transform BottomLeft_PI;//面片左左角座標
public Transform TopRight_PI;//面片右上角座標
public Transform BottomRight_PI;//面片右下角座標
在將這四個點的世界座標轉化成屏幕座標
void Update () {
TopLeft_W_Sc = ToScreenPosition (TopLeft_PI.position);
BottomLeft_W_Sc = ToScreenPosition (BottomLeft_PI.position);
TopRight_W_Sc = ToScreenPosition (TopRight_PI.position);
BottomRight_W_Sc = ToScreenPosition (BottomRight_PI.position);
private Vector2 ToScreenPosition(Vector3 pointPos)
{
return Camera.main.WorldToScreenPoint (pointPos);
}
最後只要比較plane的四個點的屏幕座標是否在Image裏就可以了。把Plane設置成ImageTarget的子節點下,運行時就可以看到效果了。
附上完整代碼:
private Vector2 TopLeft_UI; //掃描框左上角座標
private Vector2 BottomLeft_UI;//掃描框左左角座標
private Vector2 TopRight_UI;//掃描框右上角座標
private Vector2 BottomRight_UI;//掃描框右下角座標
private Vector2 TopLeft_W_Sc; //記錄面片左上角的屏幕座標
private Vector2 BottomLeft_W_Sc;//記錄面片左下角的屏幕座標
private Vector2 TopRight_W_Sc;//記錄面片右上角的屏幕座標
private Vector2 BottomRight_W_Sc;//記錄面片右下角的屏幕座標
public GameObject Plane;
public Transform TopLeft_PI; //面片左上角座標
public Transform BottomLeft_PI;//面片左左角座標
public Transform TopRight_PI;//面片右上角座標
public Transform BottomRight_PI;//面片右下角座標
public Material red;
public Material green;
// Use this for initialization
void Start ()
{
TopLeft_UI = new Vector2 ((Screen.width-400)*0.5f,(Screen.height-300)*0.5f+300f);
BottomLeft_UI = new Vector2 ((Screen.width-400)*0.5f,(Screen.height-300)*0.5f);
TopRight_UI = new Vector2 ((Screen.width-400)*0.5f+400f,(Screen.height-300)*0.5f+300f);
BottomRight_UI = new Vector2 ((Screen.width-400)*0.5f+400f,(Screen.height-300)*0.5f);
}
// Update is called once per frame
void Update () {
TopLeft_W_Sc = ToScreenPosition (TopLeft_PI.position);
BottomLeft_W_Sc = ToScreenPosition (BottomLeft_PI.position);
TopRight_W_Sc = ToScreenPosition (TopRight_PI.position);
BottomRight_W_Sc = ToScreenPosition (BottomRight_PI.position);
if (BeyondOut()) //是否超出掃描框的範圍{
Plane.GetComponent<MeshRenderer> ().material = green;
} else {
Plane.GetComponent<MeshRenderer> ().material = red;
}
}
private Vector2 ToScreenPosition(Vector3 pointPos)
{
return Camera.main.WorldToScreenPoint (pointPos);
}
private bool BeyondOut()
{
return TopLeft_W_Sc.x > TopLeft_UI.x && TopLeft_W_Sc.y < TopLeft_UI.y && BottomLeft_W_Sc.x > BottomLeft_UI.x &&
BottomLeft_W_Sc.y > BottomLeft_UI.y && TopRight_W_Sc.x < TopRight_UI.x && TopRight_W_Sc.y < TopRight_UI.y &&
BottomRight_W_Sc.x < BottomRight_UI.x && BottomRight_W_Sc.y > BottomRight_UI.y ? true : false;
}
在掃描框內:
沒有完全在掃描框內: