[ING] - AR1日体験ハッカソンでのサンプルリポジトリ
こちらは、5/19に株式会社メルカリ様にて開催された「AR 1day Hackathon/お試し会」で実装したサンプルになります。基本的には.scn
形式にした3Dモデルを画面内に表示し、SwiftUIを利用したUI関連実装とSceneKitを組み合わせたものになります。
(1)3DモデルとUI実装を組み合わせた解説動画:
YouTubeチャンネル「kavsoft」様のサンプル実装動画も応用を考えていく上で参考になると思います。
- ① SwiftUI 2.0 SceneKit - SwiftUI Loading 3D Objects/Models Using SceneView - SwiftUI 2.0 Tutorials:
- ② SwiftUI 3.0 Pizza Animation Challenge - Complex Animations - Pizza App UI - Xcode: SwiftUI Tutorials:
- ③ SwiftUI 3D Shoe App UI - SceneKit - 3D Objects - Complex UI - Xcode 14 - SwiftUI Tutorials:
(2):3Dモデル表示をSceneKitを利用して実現する
このサンプルでは、Xcodeで変換した.scn形式の3Dモデル表示部分SceneKitを利用しています。UIViewRepresentable
を利用してSCNView
のインスタンスをSwiftUIで表示する形を取っている点がポイントになります。
struct DetailCustomSceneView: UIViewRepresentable {
// MARK: - `@Binding` Property
@Binding var scene: SCNScene?
// MARK: - Function
func makeUIView(context: Context) -> SCNView {
let view = SCNView()
view.allowsCameraControl = false
view.autoenablesDefaultLighting = true
view.antialiasingMode = .multisampling2X
view.scene = scene
view.backgroundColor = .clear
return view
}
func updateUIView(_ uiView: SCNView, context: Context) {}
}
3Dモデル表示と調整対応部分の実装例です。
// 👉 ① View要素内Property定義
// 表示対象SCNScene(SceneKit)をStateとして定義
@State private var scene: SCNScene?
// 👉 ② initializer内での調整処理
// SCNVector3: https://developer.apple.com/documentation/scenekit/scnvector3
// SCNVector4: https://developer.apple.com/documentation/scenekit/scnvector4
// (参考記事) https://appleengine.hatenablog.com/entry/2017/06/02/163647
// 処理1. 少しだけ手前側に斜めに倒すイメージにして見やすくする
self.scene?.rootNode.rotation = SCNVector4(
1, // X軸
0, // Y軸
0, // Z軸
0.1 * Float.pi // 角度(ラジアン)
)
// 処理2. 現在のサイズより1.28倍の拡大表示をする
self.scene?.rootNode.scale = SCNVector3Make(
1.28, // X軸
1.28, // Y軸
1.28 // Z軸
)
SceneKitを利用した3Dモデル表示を回転可能にする部分の実装例です。
// 👉 ① スライダー要素のModifier処理部分の抜粋
.gesture(
// DragGestureと連動して回転する様な形を実現する
DragGesture()
.updating($temporaryOffsetValue, body: { currentValue, outputValue, _ in
// MEMO: -64.0をしているのは調整のため
outputValue = currentValue.location.x - 64.0
})
)
.onChange(of: temporaryOffsetValue) {
// MEMO: 変数「offset」が変更されるので、配置要素が合わせて回転する
rotateSceneViewObject(animate: temporaryOffsetValue == .zero)
}
// 👉 ② Drag処理変化量に合わせて水平方向回転を実施するメソッド
// ②-1: View要素のProperyにDragGesture発動時に一時的に格納するための変数が定義されている
@GestureState private var temporaryOffsetValue: CGFloat = 0
// ②-2: DragGesture発動時に一時的に格納するための変数
private func rotateSceneViewObject(animate: Bool = false) {
// ① Transition処理を開始する
if animate {
SCNTransaction.begin()
SCNTransaction.animationDuration = 0.36
}
// この様な条件分岐にしないと綺麗に回転しなかったんですよねー...😇
scene?.rootNode.eulerAngles.y = Float((temporaryOffsetValue * .pi) / 180.0)
// ② Transition処理を実行する
if animate {
SCNTransaction.commit()
}
}
(3):画面全体の構成
一覧から詳細画面へ遷移する様に見せる構成において、ポイントになり得る部分をまとめています。
// 👉 ① View要素のProperyに表示対象EntityをStateとして定義
@State private var selectedMaterial: MaterialEntity? = nil
// 👉 ② body要素内ではZStackを利用して画面状態に合わせて表示対象の内容をAnimationを利用して切り替える
// ※ 「.matchedGeometryEffect」Modifierの活用して一意なID名と@Namespaceで定義する名前空間との紐付けを利用する
var body: some View {
NavigationStack {
// 全体をZStackにして表示要素を重ねている
// 👉 AndroidやFlutter等でよく見る「Hero」Animationの様なイメージ
ZStack {
// `@State`で定義した変数の状態を元にして表示状態を決定する
if selectedMaterial == nil {
// 一覧表示時のView全体要素 (全体はScrollView + Grid表示構成)
} else {
// 拡大時のView全体要素
}
}
.frame(width: screenWidth)
.navigationTitle("3Dモデルを表示して回転させよう♻️")
.navigationBarTitleDisplayMode(.inline)
}
}
(4):3Dモデル入手する
- https://developer.apple.com/jp/augmented-reality/quick-look/
- https://sketchfab.com/
- 会員登録をすると、無料で提供されている3DモデルをDL可能です。
※注意:
3Dモデルファイルが重かったので、.scn
形式にした3Dモデルについては「Git LFS」を利用しています。
※1. 直接DLする場合は「こちら💁」
※2. Git LFSの導入に関しては、下記にピックアップした資料も参考にできるかと思います。
- 参考資料(about Git LFS)
# すでに「Git LFS」を利用している場合は下記コマンドを実行してください。
$ git clone [email protected]:fumiyasac/ARDemoSample.git
$ git lfs pull
【📊 Presentation】
5/21にWantedly株式会社様で開催された「Mobile勉強会 Wantedly × チームラボ × Sansan #14」でも、こちらの内容を登壇しております。
【🖼️ Screenshots】
List | Detail |
---|---|
![]() |
![]() |
【🎥 Movie】
matched_geometry_sample.mp4
【🍀 Guidance】