Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Chapter8/Chapter8.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
C3E575212BF1C633004E3EDC /* SceneReconstruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3E575202BF1C633004E3EDC /* SceneReconstruction.swift */; };
C3E575232BF1D739004E3EDC /* WorldTracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3E575222BF1D739004E3EDC /* WorldTracking.swift */; };
C3E575252BF1FFD9004E3EDC /* ImageTracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3E575242BF1FFD9004E3EDC /* ImageTracking.swift */; };
C82B73A22C756EAD00D36A38 /* MeshResourceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C82B73A12C756EAD00D36A38 /* MeshResourceExtension.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -34,6 +35,7 @@
C3E575202BF1C633004E3EDC /* SceneReconstruction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneReconstruction.swift; sourceTree = "<group>"; };
C3E575222BF1D739004E3EDC /* WorldTracking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorldTracking.swift; sourceTree = "<group>"; };
C3E575242BF1FFD9004E3EDC /* ImageTracking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageTracking.swift; sourceTree = "<group>"; };
C82B73A12C756EAD00D36A38 /* MeshResourceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshResourceExtension.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -76,6 +78,7 @@
C3E575202BF1C633004E3EDC /* SceneReconstruction.swift */,
C3E5751C2BF11433004E3EDC /* HandTracking.swift */,
C3E575222BF1D739004E3EDC /* WorldTracking.swift */,
C82B73A12C756EAD00D36A38 /* MeshResourceExtension.swift */,
C3E575112BEF6563004E3EDC /* Assets.xcassets */,
C3E575162BEF6563004E3EDC /* Info.plist */,
C3E575132BEF6563004E3EDC /* Preview Content */,
Expand Down Expand Up @@ -174,6 +177,7 @@
files = (
C3E575212BF1C633004E3EDC /* SceneReconstruction.swift in Sources */,
C3E5750E2BEF6562004E3EDC /* ContentView.swift in Sources */,
C82B73A22C756EAD00D36A38 /* MeshResourceExtension.swift in Sources */,
C3E5750C2BEF6562004E3EDC /* Chapter8App.swift in Sources */,
C3E5751F2BF1145F004E3EDC /* ShootingLogic.swift in Sources */,
C3E575252BF1FFD9004E3EDC /* ImageTracking.swift in Sources */,
Expand Down
51 changes: 51 additions & 0 deletions Chapter8/Chapter8/MeshResourceExtension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// MeshResourceExtension.swift
// Chapter8
//
// Created by 鷲尾友人 on 2024/07/06.
//

import RealityKit
import ARKit

// 下記サイトを参考に作成。
// https://forums.developer.apple.com/forums/thread/749759
// https://zenn.dev/shu223/articles/visionos_scenemesh
// https://github.com/XRealityZone/what-vision-os-can-do/blob/main/WhatVisionOSCanDo/Extension/GeometrySource.swift

extension MeshResource.Contents {
init(geom: MeshAnchor.Geometry) {
self.init()
self.instances = [MeshResource.Instance(id: "main", model: "model")]
var part = MeshResource.Part(id: "part", materialIndex: 0)
part.positions = MeshBuffer(geom.vertices.asSIMD3(ofType: Float.self))
part.normals = MeshBuffer(geom.normals.asSIMD3(ofType: Float.self))
part.triangleIndices =
MeshBuffer(geom.faces.asArray(ofType: UInt32.self))
self.models = [MeshResource.Model(id: "model", parts: [part])]
}
}

extension GeometrySource {
func asArray<T>(ofType: T.Type) -> [T] {
assert(MemoryLayout<T>.stride == stride)
return (0 ..< self.count).map {
buffer.contents().advanced(by: offset + stride * Int($0))
.assumingMemoryBound(to: T.self).pointee
}
}

func asSIMD3<T>(ofType: T.Type) -> [SIMD3<T>] {
return asArray(ofType: (T, T, T).self).map { .init($0.0, $0.1, $0.2) }
}
}

extension GeometryElement {
func asArray<T>(ofType: T.Type) -> [T] {
assert(MemoryLayout<T>.stride == bytesPerIndex)
return (0 ..< self.count * self.primitive.indexCount).map {
buffer.contents().advanced(by: bytesPerIndex * Int($0))
.assumingMemoryBound(to: T.self).pointee
}
}
}
11 changes: 9 additions & 2 deletions Chapter8/Chapter8/SceneReconstruction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,17 @@ class SceneReconstruction: ObservableObject {
// 障害物用のメッシュを作成
guard let shape = try? await ShapeResource
.generateStaticMesh(from: meshAnchor) else { continue }
guard let mesh = try? await MeshResource(
from: MeshResource.Contents(geom: meshAnchor.geometry)
) else { continue }
switch update.event {
// 障害物が新規に追加された場合
case .added:
// 追加された物体から障害物 Entity を作成、物理演算機能を追加
let entity = ModelEntity()
// 追加された物体から障害物 Entity を作成、隠面処理と物理演算機能を追加
let entity = ModelEntity(
mesh: mesh,
materials: [OcclusionMaterial()]
)
Comment on lines 34 to +46
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここが最も肝となる修正です。

SceneReconstructionProvider から得た MeshAnchor には現実の物体のかたちを表すメッシュ情報が格納されており、それをもとに ShapeResourceCollisionComponent を作成して衝突をシミュレートできるのは本誌で学んだ通りです。この修正ではさらに、このメッシュ情報を用いて MeshResource を作成し、障害物を表すエンティティのかたち(ModelEntitymesh 引数)に設定します。またエンティティのマテリアルを OcclusionMaterial (背後のオブジェクトを隠す不可視のマテリアル)に設定します。

MeshAnchor から MeshResource への変換は、ShapeResource とは異なり簡単な手段がないので(visionOS 1.2時点)、MeshResource.swift に自前の変換関数を用意して実現しています。

entity.transform = Transform(
matrix: meshAnchor.originFromAnchorTransform
)
Expand All @@ -54,6 +60,7 @@ class SceneReconstruction: ObservableObject {
case .updated:
// 物体の id を取得して形状と位置を更新
guard let entity = meshEntities[meshAnchor.id] else { continue }
entity.model?.mesh = mesh
Comment on lines 60 to +63
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

認識される障害物のかたちは刻々と変化します。変化が検知されたらエンティティのかたちも忘れずに更新します。

entity.transform = Transform(
matrix: meshAnchor.originFromAnchorTransform
)
Expand Down