塗塗樂中的掃描框

之前在試玩一些塗塗樂的應用,發現大多數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;
    }

在掃描框內:
這裏寫圖片描述

沒有完全在掃描框內:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章