IS0
0
IS0
전체 방문자
오늘
어제
  • 분류 전체보기
    • 🎲게임개발
      • 🔫팡팡 바이러스
      • 🐍기생충
      • 🐦갓버드
    • 💻기타 프로젝트
      • 🚛BARO_AR Ruler
    • 📝코딩테스트
    • 🤖강화학습

블로그 메뉴

  • 홈
  • 태그
  • 관리

공지사항

인기 글

태그

  • Unity
  • java
  • c++
  • 큐
  • 정렬
  • VR
  • FPS
  • 해시
  • oculus
  • PYTHON
  • AR Foundation
  • AR
  • ARcore
  • 스택
  • 힙

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
IS0

0

3. AR Ruler①
💻기타 프로젝트/🚛BARO_AR Ruler

3. AR Ruler①

2020. 11. 26. 07:55

이번 포스트에서는 이전 포스트의 HelloAR 예제를 변형해 간단한 Virtual Ruler를 만들어볼 것이다.
평면만 잘 인식된다면 거리를 구하는 코드는 어렵지 않다. 인식한 평면을 기준으로 터치한 위치의 좌표를 뽑아내고, 두 점 사이의 거리를 구하면 된다. 정확도 등을 위해서는 세부적인 조정이 필요할 것으로 보이지만, 일단은 기본적인 ruler부터 구현해 보고자 한다.

 

이번 포스트는 
1. Ruler 코드 - 선언과 초기화

2. Ruler 코드 - Update() 수정: Play버튼으로 볼 수 있게

3. Asset 설정

4. Ruler 코드 - Update() 수정: AR 앱을 실행해서 볼 수 있게
로 이루어져 있다.

 

이번 포스트는 아래 링크들을 참고하였다.

참고 링크: https://assetstore.unity.com/packages/tools/camera/ar-measure-145104

 

AR Measure | 카메라 | Unity Asset Store

Get the AR Measure package from VR Cardboard Buddies and speed up your game development process. Find this & other 카메라 options on the Unity Asset Store.

assetstore.unity.com

https://subscription.packtpub.com/video/application_development/9781789537413/70319/70320/ar-core-ruler

 

AR Core Ruler - Master ARCore 1.3 Unity SDK - Build 6 Augmented Reality Apps [Video]

Learn how to measure distances in Augmented Reality using ARCore in Unity SDK....

subscription.packtpub.com

 


1. Ruler 코드 - 선언과 초기화

우리는 저번에 본 HelloAR예제만을 수정할 것이다. 그러니까 HelloAR 폴더를 열어준다. 그리고 HelloAR > Scripts 폴더의 HelloARController.cs 파일을 열어서 수정할 것이다.

 

전반적인 계획은 다음과 같다. 

전체 코드에는 오브젝트 생성이나 각도 조절 등의 코드가 들어가지만, 이번 포스트의 주제는 Virtual Ruler를 만드는 것이기 때문에 주제 외의 부분은 간단하게 언급만 하고 넘어가도록 할 것이다.

 

우선, 변수 선언을 해줘야한다. 위 그림과 같이 점 오브젝트를 담을 Points[]와 p_index, 라인 오브젝트를 담을 Lines[]와 l_index, 텍스트 오브젝트를 담을 Texts[]와 t_index를 선언해준다. 또한 유니티에서 프리팹과 연결해줄 prefabPoint, prefabLine, prefabText와 중복 생성 방지를 위한 exist를 선언해준다. exist는 false로 초기화 해주는데, 이는 점 오브젝트가 생성되면 true로 바뀌도록 할 것이다. 이 코드는 전부 HelloARController의 가장 상단에 적어주면 된다. 

 

또한 Awake() 위에 Start()를 적어준다. 여기서 배열들을 초기화한다. 배열의 사이즈는 그냥 적당히 큰 수를 골랐다.

 


2. Ruler 코드 - Update() 수정: Play버튼으로 볼 수 있게

이제 update()함수를 수정해야한다. 우선은 유니티 내에서 Play 버튼으로 코드가 잘 실행되는지 볼 수 있도록 코드를 짤 것이다. 그 후 4. Ruler 코드 - Update() 수정 - AR 앱을 실행해서 볼 수 있게 파트에서 여기서 짠 코드를 복사해서 AR 앱에서 Virtual Ruler를 사용할 수 있도록 바꿀 것이다.

 

앱에서는 터치로 원하는 위치에 오브젝트를 생성하게 했지만, Unity에서는 마우스를 클릭해서 오브젝트가 잘 생성되는지 확인해야한다. 따라서 마우스 클릭을 인식할 수 있도록 Input.GetMouseButtonDown(0)을 사용할 것이다. 일단은 마우스로 클릭하면 원하는 위치가 아니라 어느정도의 범위 내에서 랜덤으로 생성되도록 만들어보겠다.

위 코드를 Update() 내부의 가장 상단에 넣어주면 된다. 마우스가 클릭되면, x,z 좌표는 랜덤이고 y좌표만 0으로 고정인 3차원 벡터 pos를 만든다. 그리고 Instantiate를 이용해 점 프리팹인(4. Asset 설정 파트에서 연결해줄 것이다.) prefabPoint를 pos에 생성한다. 생성된 점 오브젝트를 Points[p_index]에 넣어준다. p_index는 0으로 초기화해두었으니 처음 점을 생성하면 Points 배열의 가장 첫번째 자리부터 채워나갈 것이다. 

오브젝트를 생성하고 Points 배열에 넣어주었으면, exist를 true로 바꿔 이미 하나의 점이 생성되었다고 표시해준다. 그리고 Points배열의 인덱스인 p_index를 +1해줘서 다음 점은 Points의 다음 원소로 들어갈 수 있도록 해준다.

여기까지 마우스로 클릭하면 랜덤한 위치에 점 오브젝트를 생성, 해당 오브젝트를 Points 배열에 차례로 추가해주는 코드를 작성하였다.

 

그리고 exist를 매번 체크해줄 수 있는 FixedUpdate()를 만든다. 이는 업데이트 주기마다 exist 변수를 체크하며 exist가 true이면 false로 바꿔준다. 즉, exist는 처음에 false로 시작하여 새로운 점이 생성되면 true가 되고, 한번의 update가 지나가면 다시 false로 바뀐다. FixedUpdate()는 Update() 아래에 새로 작성해주면 된다. 

 

이제 본격적으로 길이를 측정하는 코드를 짜볼 수 있다. 우선, Text를 사용하기 위해 코드 가장 상단, namespace GoogleARCore.Examples.HelloAR의 아래에 using UnityEngine.UI; 라는 코드를 추가해준다. using ~ 이라고 적힌 다른 코드들과 함께 적어주면 된다.

아까 완성한 Update() 이하의 if (Input.GetMouseButtonDown(0))이 있는 코드이다. 이 if문 안에 새로운 if문을 넣어줄 것이다. 위의 주석으로 표시된 곳에 아래의 코드를 넣는다.

이 코드가 두 점 사이의 거리를 구하는 핵심 코드이다.  p_index>0이라는 조건은 점이 둘 이상 생성되었을 때를 의미한다. 즉 앞선 구조도에서 '두번째 점부터는 라인과 텍스트를 함께 생성'된다는 부분을 커버하고자 한다.  Points에 생성되는 점 오브젝트들을 넣어놓았으니, transform.position을 통해 해당 점의 좌표를 구할 수 있다. 가장 최근에 생성된 점(Points[p_index])과 그 전에 생성된 점(Points[p_index-1]) 사이를 잇는 벡터 dir와, 두 점 사이의 중점인 center를 찾아준다. 

이제 두 점 사이에 라인을 생성할 것이다. 우선 아까 선언해준 center를 선의 중점으로 잡는다. 그리고 그 위치에 prefabLine을 Instantiate해주어 Lines[]에 넣는다. 그리고 라인의 각도와 크기를 설정해준다. 

같은 방법으로 텍스트도 생성해준다. 텍스트를 Instantiate하는 코드 아래의 if문은 텍스트의 방향을 조절해주는 코드이다. 그리고 Texts[t_index]아래의 글자를 다루는 Text 컴포넌트에 접근해준다. 여기서는 Text 프리팹 > Canvas > Text 와 같은 단계를 거쳐야 했기에 GetChild(0)을 두 번 해줬다. 그렇게 txScp에 Text프리팹을 대입한 후, txScp의 내용을 cm로 바꾸어 출력해준다.

마지막으로 p_index와 마찬가지로 l_index, t_index를 1 증가시킨다. p_index는 해당 if 문에 들어오지 않아도 생성이 가능하기 때문에 if문의 바깥쪽에 위치한거고, l_index와 t_index는 항상 점에 두 개 이상일때 늘어나므로 if(p_index>0) 안에 작성해준다.

 

여기까지 작성하면 코드 작성은 끝났으니, 유니티로 이동해준다.

 


3. Asset 설정

유니티로 돌아와 우선, HelloAR 폴더 내에 asset이라는 하위폴더를 만들어준다. 이제 여기에 우리가 쓸 에셋을 추가해줄 것이다. 

코드에 우리가 새로 추가한 gameObject는, prefabPoint, prefabLine, prefabText 이렇게 3가지 이다. asset폴더 안에 이 프리팹들을 만들어줄 것이다. 

 

 

 


<prefabPoint>

저번 포스트에서 HelloAR을 실행했을 때 보았듯이, HelloAR은 터치한 위치에 어떤 오브젝트를 생성하는 프로그램이다. prefabPoint도 터치하는 위치에 생성되는 점이므로 HelloAR 예제를 이용하고자 한 것이다.

HelloAR에서 터치시 생성되는 오브젝트는 Assets > GoogleARCore > Examples > Common > Prefabs 안의 ARCorePawn이란 이름의 프리팹이다.

이것을 Hierachy로 드래그한 후 더블클릭한다. 

 

그럼 좌측과 같은 오브젝트가 보인다. 우리는 이것을 더 간단한 형태인, 정육면체로 바꿔볼 것이다. 

 

상단 메뉴에서 GameObject > 3D Object > Cube 를 클릭해 큐브를 만든다. 그리고 scale 툴을 이용해 적당한 크기로 바꿔준다. ARCorePawn 프리팹이 생성했을 때 생각보다 크게 보이기 때문에 해당 오브젝트보다 조금 작게 만드는 것을 추천한다. 큐브를 만들었다면, Hierachy에서 ARCorePawn을 삭제해도된다.

 

큐브를 원하는 색으로 바꿔주기 위해 Material을 추가해볼 것이다. 다시 HelloAR > asset 폴더로 이동해서, 마우스 우클릭 > Create > Material을 누른다. 이름을 point_color로 바꿔준 뒤, point_color > Inspector > Shader > Unlit > Color 로 바꿔준다. 

 

 

그러면 좌측 사진과 같이 변할 것이다. 여기서 Main Color를 원하는 색으로 바꿔준다. 여기서는 눈에 띄는 형광 연두색으로 만들어보았다. 그럼 asset폴더 안에 연두색의 컬러가 생겼을 것이다. 이것을 Scene에 있는 아까 만들어둔 큐브에 드래그한다.

 

 

 

 

왼편의 그림과 같이 큐브에 색이 입혀지는 것을 볼 수 있다. 좌측은 색을 입히기 전, 우측은 색을 입힌 후 이다. 

 

이제 prefabPoint는 끝이다. Hierachy에 있는 Cube를 HelloAR > asset 폴더로 드래그하고, 이름을 prefabPoint로 바꿔준다.

 


<prefabLine>

이번엔 두 점 사이를 연결하는 라인을 만들어볼 것이다. 대부분 아까 prefabPoint을 만들때 했던 방법과 비슷하므로 간단하게 설명하겠다.

여전히 Hierachy에 Cube를 둔 상태로, 똑같이 GameObject > 3D Object > Cube를 만든다. 이번엔 Cube보다 작게 사이즈를 조절해주고, Scale의 x, y를 조절해 선과 같은 형태로 만든다. 그리고 prefabPoint 때와 마찬가지로 Material을 이용해 line_color를 만들어주고, line이 될 새로운 Cube에 드래그 해준다.

 

최종적으로, 왼쪽 사진과 같은 모습이 될 것이다.

 

 

prefabPoint와의 크기 차이는 왼쪽과 같다. 이런 부분은 딱 맞출 필요 없이 자유롭게 만들어도 좋을 것이다. 본 포스트에서도 추후 디자인 적인 부분은 수정될 가능성이 있다.

 

그럼 이번에도 새로 만든 Cube를 asset 폴더로 드래그 해주어 프리팹으로 만들고, 이름을 prefabLine으로 바꿔준다. 

 


<prefabText>

마지막은 라인 위에서 두 점 사이의 길이를 표현하는 텍스트를 만들어야 한다. 텍스트를 만들때는 주의할 점이 있다. 점을 생성하고 잘 보이도록 텍스트를 회전시켜주어야한다는 것인데, 이 부분은 코드에서도 작업할 수 있다. 이번에는 일단 프리팹을 만들때부터 바닥에 눕힌 형태로 텍스트를 만들어 보겠다.

GameObject > CreateEmpty를 통해 빈 오브젝트를 만든다. 빈 오브젝트의 이름을 TextObject 등으로 만들어준 후, 해당 오브젝트를 마우스 우클릭 > UI > Text를 통해 TextObject 이하에 Canvas, Canvas 이하에 Text 형태로 배치되도록 한다. 이는 2. Ruler 코드 에서 마지막 부분에 GetChild(0)을 두 번 해준 이유이다. 이렇게 해야 TextObject > Canvas > Text의 과정을 거쳐 Text에 접근할 수 있기 때문이다.

 

TextObject는 아무 위치에나 두고, Rotation 0,0,0, Scale 1,1,1을 맞춰준다. 중요한건 Canvas이다.

좌측이 이 글에서 설정한 Canvas 설정이다. 처음에는 Canvas의 Rect Transform을 수정하기 위해 봐도 비활성화 되어있을 것이다. 이는 Rect Transform 아래의 Canvas > Render Mode를 Screen Space에서 World Space로 바꿔주면 해결된다.

 

이제 Rect Transform을 만질 수 있다.

Rect Transform에서는 세 가지를 바꿔주었다. 우선, Position(Pos) 설정을 X=Z=0, Y=0.006으로 맞췄다. 이는 글자가 라인보다 약간 (Y축으로) 위에 위치해야 선에 글씨가 가려지는 일이 없기 때문이다.

Width와 Height는 임의로 1500, 600으로 맞춰주었다. 이 부분은 아마 다른 숫자여도 상관없이 잘 작동할 것이다. 추후 여러가지로 바꿔보고 그 결과를 이 포스트에 수정해서 적어보도록 하겠다. 

그리고 위에서 말한 회전이다. Rotation을 X=90, Y=-90으로 바꿔준다. 이는 글씨가 라인과 같은 방향을 바라보도록 하기 위함이다. 유니티가 아니라 코드에서만 작업할 수 있을 것 같은데...아직 해결하지 못했다. 코드에서만 회전을 조절하는 방법을 찾으면 마찬가지로 이 포스트에 추가할 것이다.

 

Canvas 아래에 위치한 Text는 Width와 Height를 모두 0으로 바꿔주고, 글씨가 선명히 보이도록 Character > Font Size를 200정도로 늘려준다. 그리고 Canvas를 넘어가도 글씨가 사라지지 않도록 Paragraph > Horizontal Overflow와 Vertical Overflow를 전부 Overflow로 바꿔준다. 마지막으로 Paragraph > Alignment를 모두 중앙정렬로 바꿔준 뒤, Scale tool을 이용해 글씨의 사이즈를 조절해준다. 그리고 TextObject째로 Hierachy에서 HelloAR안의 asset폴더로 드래그 한다. 이름을 prefabText로 바꿔주면 모든 에셋이 준비되었다! 

위는 최종적인 asset 폴더의 모습이다. 프리팹을 전부 만들어주었다면, Hierachy에 추가했던 Cube들과 TextObject들은 삭제해준다. 


이제 Hierachy에서 HelloARController를 누른다. 그러면 우측 Inspector에 캡쳐와 같은 것들이 생겼을 것이다. 우리가 HelloARController.cs 스크립트를 수정해주었기 때문인데, 수정한 것중 public으로 선언한 변수들이 유니티 내에서도 보이는 것이다. 

처음에는 prefab Point, Line, Text가 전부 비어있을텐데, 여기에 아까 asset폴더 안에 만들어둔 prefabPoint, prefabLine, prefabText를 각각 드래그해서 넣어준다. 그럼 좌측 사진과 같이 들어갈 것이다.

 

여기까지 하면 유니티 내에서의 에셋 설정도 완료. 이제 유니티 내에서 실행시켜볼 수 있다.

 

 

 

Hieracy에서 HelloARDevice를 더블클릭해서 zoom in 해놓은 상태로, 상단에 있는 play 버튼을 눌러 실행시킨다. Game에서 화면을 아무렇게나 클릭하면, 뭔가가 생기는 것을 확인할 수 있다. 이는 Scene에서 더 자세히 확인 가능하다. 아마 아래와 같은 화면이 될 것이다.

 

한 군데를 확대해보면, 좌측 사진과 같이 길이가 표시되고 있는 것을 볼 수 있다. 

 

위 캡쳐에서 Hierachy부분에 prefab들이 많이 생긴 것을 볼 수 있는데, 이는 클릭할때마다 랜덤한 위치에 점과 선, 텍스트가 잘 생성되고 있다는 것을 보여준다. 각 프리팹들을 더블클릭하면 Scene 창에서 확대되며 어떤 오브젝트인지 확인할 수 있다.

 

여기까지 유니티에서 실행되는 AR Ruler를 만들어 보았다. 매번 기능을 수정할때마다 빌드 후 모바일 기기로 잘 작동하는지 확인하는 작업은 꽤 번거롭다. 이렇게 유니티 내에서 AR Ruler를 볼 수 있게 해주면 AR 기능이 꼭 필요하지 않은 부분을 수정하고 확인할때 용이하다. 

 

 


4. Ruler 코드 - Update() 수정: AR 앱을 실행해서 볼 수 있게

이렇게 유니티에서 잘 작동하는 것을 확인했으면, AR 앱으로 빌드해도 잘 작동할 것이라 기대해볼 수 있다. 이제 Update() 함수를 수정해 유니티가 아닌 어플리케이션으로 작동하도록 코드를 수정해 볼 것이다.

 

위에서 수정했던 HelloARController.cs 파일을 열고 Update()함수로 간다.

Update()는 아까 추가해주었던 if문으로 시작할 것이다. 위와 같은 코드가 있을텐데, 우리는 여기서 빨간색으로 표시한 부분, if(p_index>0)부터 p_index+=1까지의 코드를 그대로 복사해 다른 곳에 붙여넣기 후 조금 수정해줄 것이다. 이때, 언제 유니티 내에서 같은 코드를 테스트 해야할 지 알 수 없으므로 위 코드를 잘라내거나 지우지 말고 주석처리 해두는 것을 추천한다. 주석처리는 if(Input.GetMouseButtonDown(0))이하 전부, 즉 위 코드에 해당하는 부분을 전부 주석으로 만들어주면 된다.

 

이제 Update()의 아래로 내려와서, 아래와 같은 코드가 있는 곳을 찾는다. Ctrl+F로 Instantiate를 검색하면 쉽게 찾을 수 있을 것이다.

이 코드가 HelloAR에서 터치한 위치에 오브젝트를 생성해주는 부분이다. 우리는 이 코드부터 Update()가 끝나는 부분까지 전부 주석처리를 하거나, 지우고 우리의 코드를 붙여넣을 것이다.

주석처리를 하면 위와 같다. 원래는 전체를 주석처리하려했지만, 우리는 ARCore에 있는 anchor기능을 이용하기 위해 anchor를 선언하는 부분(빨간펜으로 표시한 부분)은 주석으로 지우지 않았다. anchor는 복사한 코드를 붙여넣은 후에 이용해 보겠다. 

 

전부 주석처리 또는 지운 후, 그 아래에 아까 복사했던 코드를 붙여 넣는다. 그럼 Update()의 가장 아래에 if(p_index>0)으로 시작하는 if 문이 들어가 있을 것이다.

 

그럼 그 위, 즉 주석과 if문 사이에 아래의 코드를 추가해준다. 

첫번째 줄은 아까 보았던 var gameobject = Instantiate~ 와 같은 구조이다. 즉 터치한 위치에 prefabPoint를 생성하고, Points배열의 p_index위치에 넣어준다는 것이다. 

두번째 줄은 생성한 게임오브젝트의 회전을 다루고 있다. 생성했을 때 카메라의 위치에 따라 오브젝트의 회전을 다르게 하는 코드이다.

세번째 줄이 anchor를 사용하는 것이다. anchor에 대해서는 다른 포스트에서 다뤄볼 예정이니 간단하게 설명하자면, 아까 주석처리 하지 않고 남겨두었던 var anchor = hit.Trackable.CreateAnchor(hit.Pose)가 이 세번째 줄의 anchor이다. 즉 생성한 point 오브젝트를 anchor의 자식으로 넣는 것이다. 

 


 

여기까지 수정을 완료했다면, 스크립트를 저장하고 이전 포스트에서 다뤘던 방법과 같이 빌드 후 실행해 볼 수 있다. 

 

좌측 사진은 실제로 apk파일을 실행한 후 테이블에서 터치로 거리를 인식한 예시이다. 

 

이제 기본적인 기능은 모두 구현 완료되었다!

 

다만 직접 빌드 후 사용해보면 알겠지만, 평면 인식이 잘 안되는 경우가 종종 발생한다. 이 코드는 인식한 평면을 바탕으로 좌표를 이용해 길이를 측정하는 방식으로 작동하기 때문에, 평면 인식이 정확하지 못하다면 길이 측정의 오차도 커진다. 

그리고 현재는 디자인도, 편의성도 매우 기초적인 단계이기 때문에, 여러모로 불편함이 많다. 

 

이후 포스트부터는 이런 문제점을 고쳐나가 보려고 한다. 

 

바로 다음 포스트인 4. AR Ruler②에서는 우선 편의성 개선을 먼저 진행해보려고 한다. 클릭한 점을 삭제하는 기능, 방금 클릭한 점이 어떤 점인지, 가장 최근의 점을 포커싱하는 기능, 화면을 가로모드로 고정하는 기능 등을 추가해 볼 예정이다.

 

 

이 포스트는 상황에 따라 추후 업데이트 될 수 있다.
-작성일: 2020.11.26
-2020.12.02 하단 연관 포스트 추가

-Last Updated: 2022.06.29 코드를 Github Gist로 변경

 

연관 포스트

- 1. 유니티에서 ARCore 시작하기

- 2. HelloAR

- 4. AR Ruler②

'💻기타 프로젝트 > 🚛BARO_AR Ruler' 카테고리의 다른 글

AR Foundation으로 Virtual Ruler 구현하기  (0) 2021.05.17
Virtual Ruler 중간정리  (0) 2020.12.08
4. AR Ruler②  (0) 2020.11.26
2. HelloAR  (0) 2020.11.26
1. 유니티에서 ARCore 시작하기  (0) 2020.11.26
    IS0
    IS0

    티스토리툴바