Take SwiftUI to the next dimension

니냐뇨·2023년 10월 11일
0

Spatial Computing

목록 보기
5/19
post-thumbnail

영상: https://developer.apple.com/videos/play/wwdc2023/10113/?time=53

이번에 주로 다룰 API는 2D window app에 약간의 3D를 추가하는 것이나 full space를 활용한 몰입된 3D experience에 작동하긴하지만, 이번 세션에서는 3D의 영역을 탐색할 수 있는 좋은 방법을 제공하는 volume container를 사용하는 것에 집중할 것이다.

다른 container에 대해 더 알고 싶다면 Elevate your windowed app for spatial computingGo beyond the window with SwiftUI를 봐라.

Volumes

3D 콘텐츠를 표현하기 위해 Volume을 사용하고, 이 scene에는 main glass window가 없다. 대신 3D contenets를 바로 scene에 표시한다.

거리에 따라 크기가 조절되는 window와는 달리 Volume은 어느 거리에서던 고정된 크기의 container를 제공한다.

Volume은 수평적으로 정렬되며 모든 각도에서 볼 수 있게 제공된다. Volume은 전체 공간을 차지하지 않으면서도 3D content를 보여주기에 좋은 방법이다. 또한 생성하는 방법도 매우 간단하다.

단지 volumetric window stye만 사용하면 된다.

3D views and layout

이를 돕기 위해 RealityKit은 Model3D라는 새로운 API를 제공한다. 이는 USDZ와 같은 3D asset을 불러올 수 있게 한다.

Model3D는 AsyncImage의 counterpart라고 생각하면 된다.

이미 추가한 usdz 파일의 이름을 통해 Model을 생성한다.

phase는 asset의 loading status를 나타낸다.
empty는 로딩이 되기 전을 나타낸다.

가능한 공간에 맞게 조정되도록 .resizable modifier를 사용해준다.

어떠한 행성이라도 부를 수 있게 코드 수정

정면에서 보기에는 좋게 생성 됨.

하지만 다른 각도에서 보면 물체들이 뒷편을 기준으로 정렬 된 것을 확인 할 수 있다.
이건 SwiftUI에서 3D content를 정렬하는 기본 값이다.

이런식으로 하면 앞쪽을 기준으로 위치를 잡을 수도 있다.

각 행성에 Label 추가, glasseffect도 라벨에 추가

괜찮아보이지만 static해보인다.

그래서 TimelineView를 통해 시간에 따라 애니메이션이 발생하도록 해보겠다.

RealityView

Model3D는 view hierachy상으로 간단한 asset을 로딩하고 보여주기에 매우 좋다.
그러나 좀 더 involed된 3D 모델, scene 또는 experience의 경우, RealityView는 SwiftUI가 앱에서 RealityKit의 힘을 발휘하는 시작점이다.

RealityKit의 Entity-Component system을 통해 각 모델을 개별적으로 lighthing이나 orbit paths와 같은 고급 기술을 포함하여 rendering 할 수 있다.

RealityView와 RealityKit에 더 알고 싶으면 Build spatial experiences with RealityKitEnhance your spatial computing app with RealityKit를 봐라.

Attachments API를 통해 RealitView에서 SwiftUI를 사용하는 것을 보겠다.

Attachments는 tag된 SwiftUI view를 entity와 짝지어서 RealityView 안에서 사용할 수 있게 해준다.
Attachments는 annotation이나 특정 entity의 affodance를 편집하는데 용이하다.

SwiftUI의 Canvas API를 사용해봤다면 attachments는 아마 친숙할 것이다. 중요한 차이점은 snapshot이 아닌 live view라는 점이다. 이 말은 state가 바뀌는 것에 대해 반응할 수 있고, 애니메이션을 실행하며, gesture를 다룰 수 있다는 것이다.

지구에 좋아하는 장소들에 mark를 추가할 것이고 이와 관련된 정보를 이미 array에 생성해뒀다.
각 장소에 대해 Text를 생성해준다.

RealityView에서 참조할 수 있는 tag를 만들어준다. tag는 hash 가능한 어느 값이여도 상관 없다.

tag를 이용하여 entity를 추가한다.

3D gestures

이 콘텐츠들과 어떻게 상호작용하는지에 대해 살펴보겠다.

Input에 대해 entity를 어떻게 configure하는지 알려주겠다.

enitity hierachy는 RealityView에서 input을 받기 위해 InputTargetComponent를 필요로한다.
이 component가 entity에 추가되면 entity의 모든 자손들도 다른 정의 없이 input을 받을 수 있게 된다.

RealityKit에서 CollisionComponent는 interative한 영역을 정의하는데 사용된다.

이것들이 SwiftUI의 gesture를 RealityView의 entity에 사용하기 위한 전부이다.

RealityView에 SpatialTapGesture를 추가해준다.

그리고 RealityKit content에 대해 SwiftUI gesture를 훨씬 쉽게 사용하기 위해 새로운 gesture modifier가 등장했다.
바로 targetedToEntity이다. 이를 통해 특정 entity를 target 할 수 있다.
이 entity나 그 자손에 tap이 일어나지 않으면 gesture는 실패하게 된다.

이제 gesture 값을 다뤄보자.
SpatialTapGesture는 새로운 location3D 속성을 가져서 globe 표면의 정확한 tap point를 알 수 있게 해준다.

RealityView의 3D location은 meter가 아닌 SwiftUI의 local 좌표계 point로 나타난다.
따라서 새로운 라벨의 위치를 계산하기 위해서는 RealityView의 scene으로 값을 변환해줘야한다.
targetedToEntity modifier는 이 과정을 매우 쉽게 만들어줬다.
이를 통해 SwiftUI local space를 scene의 coordinate space로 손 쉽게 만들 수 있다.

그리고 마지막으로 방금 계산한 위치에 data를 추가해 줄 수 있다.

살짝 표면 위에 라벨이 위치 될 수 있도록 값 조정.

탭 해서 추가가 가능해졌다.

근데 더 많은 세계를 보고 싶어서 인공 위성을 추가하고 싶다.

이번에는 다른 방법으로 모델을 로딩해보겠다.
attachment에서 인공위성 모델을 추가했다.

RealityView에 모델을 추가한다.

그리고 회전, 크기, 위치 조절을 위한 3D transform을 반환하는 gesture를 정의한다.

drag gesture를 transform으로 변환하기 위해 map을 사용한다.
drag gesture에는 3D를 다루기 위한 새로운 속성들이 있다. translation3D를 통해 시작점에서 얼마나 drag가 움직였는지 알 수 있다.

인공위성에 추가한다.

update modifier를 통해 제스처가 활성화 된 것을 추적한다.

이 state를 활용하여 인터렉션동안 다른 label들이 줄어들게 할 수 있다.
제스처가 실패할 경우 제스처 상태가 자동으로 재설정됨을 보장하기 때문에 업데이트를 사용하여 내가 가진 일시적 제스처 상태를 추적하는 것이 중요하다.

제스쳐 값이 바뀌었을 때, state의 new transform을 설정하고 인공위성 모델의 위치를 잡기 위해 offset modifier를 사용할 수 있다.
그리고 다시 원래로 돌아갈 수 있는 animation을 추가한다.

Drag와 동시에 확대도 하고 싶어서 gesture를 추가한다.

또한 손의 자유로운 3D 회전을 측정할 수 있는 새로운 RotateGesture3D도 추가한다.

entity에 rotation과 scale도 업데이트한다.

인공위성에 추가한다.

익숙한 SwiftUI의 제스처와 targetedToEntity modifier를 통해 복잡한 엔티티 계층 구조 내에서 상호 작용을 빠르게 구축할 수 있다.


profile
열심히 살자.

0개의 댓글