AR/MR을 사용하여 다른 좌표계 조정

11473 단어 Unity

AR 및 MR은 좌표계를 처리하기 어렵습니다.


이번에는 전제로 Vuforia를 사용합니다. 3개의 좌표계를 처리해야 하기 때문에 수고하셨으니 필기를 잊지 마세요.
대부분의 경우 AR에 표시하려는 객체를 ImageTarget의 하위 요소로 사용하지만 친자 관계로 인해 조작할 수 없는 제약이 있음
"부자 관계를 만들지 않고 ImageTarget의 이동 및 회전에 따라 객체 그룹 표시를 업데이트합니다."

ImageTarget
Vuforia에 등록된 이미지 태그
AR 개체 장면
이동 Vuforia의 주요 장면과 분리하여 준비한 대상 설정용 장면
ImageTarget 위치 설정
세 개의 다른 좌표계
  • 카메라의 좌표계(ImageTarget 포함)
  • AR 객체는 장면의 좌표계(※ Prefab화 구성)를 사용합니다
  • AR 객체는 장면에 포함된 ImageTarget 중심의 좌표계를 사용합니다
  • 카메라 이미지에 AR 객체용 장면 구성


    실제 카메라의 ImageTarget 위치에 AR 객체 장면 배치
    다음 순서에 따라 설정하다
  • AR 객체를 장면으로 ImageTarget 위치로 이동합니다
  • AR는 객체가 장면에 포함된 ImageTarget을 사용하여 ImageTarget 위치로 이동합니다
  • AR는 객체가 장면에 포함된 ImageTarget을 ImageTarget과 일치하도록 회전합니다
  • 이후 ImageTarget이 회전하거나 이동함에 따라 AR 대상용 장면도 업데이트된다

  • 완성된 코드

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class ARObjectsSetter : MonoBehaviour
    {
        [SerializeField]
        private Transform _actualImageTarget;
        [SerializeField]
        private Transform _arObjectsScene;
    
        [SerializeField]
        private Vector3 _virtualImageTargetPosition;
        [SerializeField]
        private Vector3 _virtualImageTargetRotation;
    
        private GameObject dummyImageTarget;
        private Vector3 relativePosition;
        private Vector3 parentLocalAxis;
        private float rotationAngle;
        private bool _enableUpdate = false;
    
        [ContextMenu("Initialize")]
        private void Initialize()
        {
            // ARオブジェクト用シーンをImageTargetに合わせる
            _arObjectsScene.position = _actualImageTarget.position;
            _arObjectsScene.rotation = _actualImageTarget.rotation;
    
            // ARオブジェクト用シーンのローカル座標からワールド座標でのVirtualImageTargetのPositionを求める
            var offset = _arObjectsScene.TransformPoint(-_virtualImageTargetPosition);
            _arObjectsScene.position = offset;
    
            // 仮想の親オブジェクトを生成し、ARObjectsSceneを子要素のように扱う
            dummyImageTarget = new GameObject("DummyImageTarget");
    
            // DummyImageTargetの位置と回転をVirtualImageTargetに合わせる
            var rot = _actualImageTarget.rotation * Quaternion.Euler(_virtualImageTargetRotation);
            dummyImageTarget.transform.SetPositionAndRotation(_actualImageTarget.position, rot);
    
            // ワールド座標からDummyImageTargetのローカル座標でのPositionを求める
            relativePosition = dummyImageTarget.transform.InverseTransformPoint(_arObjectsScene.position);
    
            // DummyImageTarget(親)のRotationと回転行列Sの積からARObjectsScene(子)のRotationが求まる
            // ARObjectsScene.rotaion = DummyImageTarget.tranform.rotation * S
            // 両辺にDummyImageTarget.transfrom.rotaionの逆行列をかける
            // ※ 回転の合成はQuaternionの積
            var rotationMatrix = _arObjectsScene.rotation * Quaternion.Inverse(dummyImageTarget.transform.rotation);
    
            // rotationMatrixがワールド座標での値なので、回転量(rotaitonAngle)と回転軸(globalAxis)を抽出する
            rotationMatrix.ToAngleAxis(out rotationAngle, out Vector3 globalAxis);
            // globalAxisをワールド座標からDummyImageTargetのローカル座標に変換する
            parentLocalAxis = dummyImageTarget.transform.InverseTransformVector(globalAxis);
    
            // ここまでで親子階層を操作せずに、DummyImageTargetの回転と移動がARObjectsSceneにも影響されるようになったので、
            // DummyImageTargetとImageTargetの回転を一致させる
            dummyImageTarget.transform.rotation = Quaternion.LookRotation(_actualImageTarget.forward);
    
            _enableUpdate = true;
        }
    
        private void LateUpdate()
        {
            if (!_enableUpdate) return;
    
            dummyImageTarget.transform.SetPositionAndRotation(_actualImageTarget.transform.position, _actualImageTarget.transform.rotation);
    
            // あらかじめ計算しておいたDummyImageTargetのローカル座標でのARObjectsSceneのPositionをワールド座標に変換
            var position = dummyImageTarget.transform.TransformPoint(relativePosition);
            // あらかじめ計算しておいたDummyImageTargetのローカル座標での回転軸をワールド座標に変換
            var globalAxis = dummyImageTarget.transform.TransformVector(parentLocalAxis);
            // あらかじめ計算しておいた回転をDummyImageTargetのRotationに合成する
            var rotation = Quaternion.AngleAxis(rotationAngle, globalAxis) * dummyImageTarget.transform.rotation;
    
            _arObjectsScene.SetPositionAndRotation(position, rotation);
        }
    }
    
    

    좋은 웹페이지 즐겨찾기