1. 首页
  2. ARCore

ARCore之路-放置物体

一、可视化平面的另一种方式

  在上一节中, 我们已经实现了可视化检测到的平面,运行后效果良好,通过代码,我们更清楚的了解到了ARCore是如何让检测到的平面可视化的,这对于我们理解ARCore的工作方式会有很大的帮助。其实,ARCore已经简化了这个过程,我们下面来看看可视化平面的另一种实现方式。首先将上节中添加的代码从AppController中删除。然后在Hierarchy窗口右键,选择”Create Empty”,并将生成的空对象命名为”DetectedPlaceGenerater”,如下图所示:

ARCore之路-放置物体

  保持选中”DetectedPlaceGenerater”,Inspector窗口,点击 “Add Component”按钮,在搜索框中输入”Detected”,可以找到DetectedPlaneGenerator,将这个脚本附件到我们的平面上。如下图所示:

ARCore之路-放置物体

将我们制作的平面Prefab拖到DetectedPlacePrefab框中,这样我们完成平面可视的工作。

ARCore之路-放置物体

这比前面我们自己写代码来实现要简单很多。

二、放置位置

  现在,我们有了可供我们放置物体的平面了,我们将要在平面上放置我们物体,但在场景中什么位置放置我们物体呢?我们要知道检测到的平面是三维的,而我们的手机屏幕却是二维的,如何在二维的平面上操作旋转三维的虚拟物体?通常的做法就是作射线检测(Raycast),这与我们在VR中用鼠标拾取物体一样。
 射线检测(Raycast)的基本思路是在三维世界中从一个点沿一个方向发射出一条无限长的射线线,在射线的方向上,一旦与添加了碰撞器的模型发生碰撞,则产生一个碰撞检测到的对象,我们可以利用射线实现子弹击中目标的检测,也可以用射线来检测发生碰撞的位置,例如,我们可以从屏幕中用户点击的点,利用摄像机(AR中就是我们的眼睛)的位置来构建一条射线,与场景中的平面进行碰撞检测,如果发生碰撞则返回碰撞的位置,这样,我们就可以在检测到的平面上放置我们的虚拟对象了。

  ARCore在Frame中为我们准备了四种发射射线检测物体的方法。

ARCore之路-放置物体

TrackableHitFlags用来过滤需要进行碰撞检测的对象类型,其值可以是以下属性值的一个,也可以是几个。

ARCore之路-放置物体

TrackableHit类保存的是发生碰撞检测时的检测到相关信息。

ARCore之路-放置物体

三、放置物体

 有了上面的基础, 我们很容易理解下面的代码。

        TrackableHit hit;
        TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon | TrackableHitFlags.PlaneWithinBounds;

        if (Frame.Raycast(touch.position.x, touch.position.y, raycastFilter, out hit))
        {
            if ((hit.Trackable is DetectedPlane) && Vector3.Dot(FirstPersonCamera.transform.position - hit.Pose.position, hit.Pose.rotation * Vector3.up) < 0)
            {
                Debug.Log("射线击中了DetectedPlane的背面!");
            }
            else
            {
                var FoxObject = Instantiate(prefab, hit.Pose.position, hit.Pose.rotation);
                FoxObject.transform.Rotate(0, mModelRotation, 0, Space.Self);
                var anchor = hit.Trackable.CreateAnchor(hit.Pose);
                FoxObject.transform.parent = anchor.transform;
            }
        }

  首先,我们定义我们过虑器,我们只想检测在多边形内与边界内的平面。然后我们以用户点击点构建射线做碰撞检测。如果发生了碰撞,我们则对碰撞情况进行分析,如果是击中了检测到的平面并且又不是平面的背面,我们则实例化我们的Prefab,同时我们生成一个anchor,并将我们的Prefab挂载到这个anchor上,以便ARCore跟踪这个物体的位置。在代码中Vector3.Dot(FirstPersonCamera.transform.position – hit.Pose.position, hit.Pose.rotation * Vector3.up) < 0),这句代码的意思是对从摄像机发射到碰撞点的向量与碰撞点的法向量做点积,小于0,说明角度大于90度,因此击中的是检测平面的背面。

  为了放置我们的虚拟物体,我们下面我们需要对AppController进行一下设置

ARCore之路-放置物体

  完整的代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GoogleARCore;
using GoogleARCore.Examples.Common;

public class AppController : MonoBehaviour {

    public Camera FirstPersonCamera;
    public GameObject prefab;
    private bool mIsQuitting = false;
    private const float mModelRotation = 180.0f;
    // Use this for initialization
    void Start () {
        OnCheckDevice();
    }

    // Update is called once per frame
    void Update () {
        UpdateApplicationLifecycle();

        Touch touch;
        if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
        {
            return;
        }

        TrackableHit hit;
        TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon | TrackableHitFlags.PlaneWithinBounds;

        if (Frame.Raycast(touch.position.x, touch.position.y, raycastFilter, out hit))
        {
            if ((hit.Trackable is DetectedPlane) && Vector3.Dot(FirstPersonCamera.transform.position - hit.Pose.position, hit.Pose.rotation * Vector3.up) < 0)
            {
                Debug.Log("射线击中了DetectedPlane的背面!");
            }
            else
            {
                var FoxObject = Instantiate(prefab, hit.Pose.position, hit.Pose.rotation);
                FoxObject.transform.Rotate(0, mModelRotation, 0, Space.Self);
                var anchor = hit.Trackable.CreateAnchor(hit.Pose);
                FoxObject.transform.parent = anchor.transform;
            }
        }
    }

运行后的效果如下图:

ARCore之路-放置物体

David Wang原创ARCore文章

作者:yolon3000

原文:https://blog.csdn.net/yolon3000/article/details/82085115

版权声明:本文为博主原创文章,转载请附上博文链接!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

联系我们

AR社区交流群:AR社区交流群

QR code