Unreal EngineとiPhoneで始める リアルタイムAR配信

8.8K Views

September 11, 22

スライド概要

profile-image

AR Developer

シェア

埋め込む »CMSなどでJSが使えない場合

各ページのテキスト
1.

iOSDC 2022 Unreal EngineとiPhoneで始める リアルタイムAR配信 Satoshi Hattori @shmdevelop

2.

Unreal Engineと

3.

iPhoneを使って

4.

リアルタイムAR配信...

5.

格好良いぜ...!

6.

今日はその考え方と要点を説明します!

7.

服部 智 CyberAgent - AICG事業部 - xRギルド リーダー - AR Next Expert 最近の興味: Unreal Engine 5、LiveLink Plugin、 iPhoneの映像ワークフロー活用、 NDI、動画倍速視聴・スキップ視聴

8.

Unreal Engine リアルタイム映像処理に向いたゲームエンジン

9.

リアルタイムAR配信

10.

このシーンではPanasonic AW-UE150 使用

11.

前置きとして "多様な実現方法の1パターン" です

12.

前置きとして "半年前の自分が泣いて喜ぶ資料" です

13.

前置きとして "今回はWindows PC使用" です

14.

GALLERIA Windows10 CPU: Core i9 11900K グラフィックボード: GeForce RTX 3080 メモリ: DDR4-3200 16GB

15.

目次 AR合成の概要 カメラトラッキング方法 Unreal Engineを使った基本的なシーン作成 iPhoneを使う手法 bonus: PTZカメラを使う手法

16.

目次 AR合成の概要 カメラトラッキング方法 Unreal Engineを使った基本的なシーン作成 iPhoneを使う手法

17.

現実世界とCG空間をぴったり合わせる作業

18.

AR合成の概要

19.

AR合成の概要 CG原点を決める 現実と同じサイズでCG空間を作成する CG空間のカメラと現実のカメラの情報を合わせる カメラの動きをCG空間に伝える

20.

CG原点を決める

21.

CG原点を決める 現実世界での 動かない、消えない、分かりやすい一点

22.

CG原点を決める

23.

CG原点を決める

24.

CG原点を決める

25.

CG原点を決める

26.

AR合成の概要 CG原点を決める 現実と同じサイズでCG空間を作成する CG空間のカメラと現実のカメラの情報を合わせる カメラの動きをCG空間に伝える

27.

現実と同じサイズでCG空間を作成する

28.

現実と同じサイズでCG空間を作成する

29.

現実と同じサイズでCG空間を作成する

30.

1 Unreal Unit は 現実の1cm

31.

現実と同じサイズでCG空間を作成する

32.

AR合成の概要 CG原点を決める 現実と同じサイズでCG空間を作成する CG空間のカメラと現実のカメラの情報を合わせる カメラの動きをCG空間に伝える

33.

CG空間のカメラと現実のカメラの情報を合わせる

34.

「位置」を合わせる

35.

CG空間のカメラと現実のカメラの情報を合わせる

36.

CG空間のカメラと現実のカメラの情報を合わせる

37.

ボッシュ(BOSCH) レーザー距離計 ZAMO3

38.

「カメラとレンズの特性」を合わせる

39.

カメラの Focal Length (焦点距離)、FOV、Sensor Size (センサーサイズ) の関係 Unity Documentation, 物理カメラの使用 https://docs.unity3d.com/ja/2019.4/Manual/PhysicalCameras.html

40.

CG空間のカメラと現実のカメラの情報を合わせる

41.

CG空間のカメラと現実のカメラの情報を合わせる

42.

AR合成の概要 CG原点を決める 現実と同じサイズでCG空間を作成する CG空間のカメラと現実のカメラの情報を合わせる カメラの動きをCG空間に伝える

43.

カメラの動きをCG空間に伝える

45.

カメラの動きをCG空間に伝える

46.

AR合成の概要 CG原点を決める 現実と同じサイズでCG空間を作成する CG空間のカメラと現実のカメラの情報を合わせる カメラの動きをCG空間に伝える

47.

目次 AR合成の概要 カメラトラッキング方法 Unreal Engineを使った基本的なシーン作成 iPhoneを使う手法

48.

目次 AR合成の概要 カメラトラッキング方法 Unreal Engineを使った基本的なシーン作成 iPhoneを使う手法

49.

カメラトラッキング方式 カメラトラッキング 送信プロトコル

50.

カメラトラッキング方式 光学式 機械式 画像式 その他 慣性センサ 磁気 etc

51.

カメラトラッキング方式 光学式 事前設置した反射マーカー位置を専用カメラで捉えカメラ位置を判定 機械式 画像式 その他 慣性センサ 磁気 etc https://www.nacxr.jp/product/redspy/

52.

カメラトラッキング方式 光学式 機械式 ギアやエンコーダなどの回転角や変位を測定するセンサを使用 画像式 その他 慣性センサ 磁気 etc https://www.nacinc.jp/creative/virtual-products/stypekit/

53.

カメラトラッキング方式 光学式 機械式 画像式 画像の特徴点を取得しトラッキングする その他 慣性センサ 磁気 etc

54.

カメラトラッキング方法 光学式 機械式 画像式 その他 慣性センサ 磁気 etc

55.

カメラトラッキング方式 カメラトラッキング 送信プロトコル

56.

カメラトラッキング 送信プロトコル FreeD NDI

57.

FreeD

58.

FreeD ネットワーク経由で送信されたカメラトラッキングデータを 読み込み、仮想3Dカメラを制御するために使用できるプロトコル FreeD は特定のトラッキングシステム専用ではなく 幅広いハードウェアとソフトウェアに対応しているため 交換プロトコルとして広く普及している

59.

https://www.manualsdir.com/manuals/641433/vinten-radamec-free-d.html

60.

FreeD Type D1

61.

https://github.com/satoshi0212/FreeDSendSimulator

63.

カメラトラッキング 送信プロトコル FreeD NDI

64.

NDI

65.

NDI(Network Device Interface)とは IPネットワークを経由してビデオとオーディオストリームを 伝送する方式のひとつ 現在世界で最も利用されているIP伝送テクノロジーで、 IPを利用したライブ映像制作ワークフロー支援を目的としている

66.

https://speakerdeck.com/satoshi0212/nditoarkitwolian-dong-sasetaxin-siiying-xiang-biao-xian

68.

https://github.com/satoshi0212/NDISenderExample

69.

カメラトラッキング方式 カメラトラッキング 送信プロトコル

70.

目次 AR合成の概要 カメラトラッキング方法 Unreal Engineを使った基本的なシーン作成 iPhoneを使う手法

71.

目次 AR合成の概要 カメラトラッキング方法 Unreal Engineを使った基本的なシーン作成 iPhoneを使う手法

72.

Unreal Engineを使った基本的なシーン作成

73.

今回の話を聞く上で最低限知っておきたい世界観

74.

World Level Actor Actor Actor Actor Actor Actor Actor Actor Actor

76.

Place Actors

77.

Content Browser

78.

ViewPort

79.

ViewPortに追加すると LevelのActorになる

80.

Unreal Engineを使った基本的なシーン作成

81.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定

82.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定 公式サイトからダウンロード

83.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定 Epic Games Launcher

84.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定 Film/VideoのBlankテンプレートから作成

85.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定

86.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定 エディタ設定画面

87.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定 エディタ設定画面

88.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定 プロジェクト設定画面

89.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定 プロジェクト設定画面

90.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定

91.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定

92.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定

93.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定 Actorを親にしてCineCameraActor追加

94.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定

95.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定 Levelブループリントを開く

96.

インストール 新規プロジェクト作成 エディタ初期設定 プロジェクト初期設定 カメラ追加 初期カメラ設定

97.

Play時にPlayerControllerのカメラを指定の物に設定

100.

Unreal Engineを使った基本的なシーン作成 🎉

101.

目次 AR合成の概要 カメラトラッキング方法 Unreal Engineを使った基本的なシーン作成 iPhoneを使う手法

102.

目次 AR合成の概要 カメラトラッキング方法 Unreal Engineを使った基本的なシーン作成 iPhoneを使う手法

103.

iPhoneを使って実現

104.

映像 トラッキング情報

105.

映像 → NDIで送信 トラッキング情報 → NDIのメタデータで送信

106.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映

107.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映

108.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映 公式ページより NDI Toolsインストール

109.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映 NDI SDK for Unreal Engineインストール

110.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映 PluginsよりNDI IO Pluginを有効化

111.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映

112.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

113.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

114.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

115.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

116.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

118.

Texture作成

119.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

120.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

121.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

122.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

123.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

124.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映

125.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映

128.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

129.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

130.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

131.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

132.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

133.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

135.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

136.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ反映

137.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映

138.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映

139.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映 NDIで映像送信 1920x1080 30fps MetaDataにカメラ情報

140.

https://github.com/satoshi0212/NDISenderExample

143.
[beta]
NDIWrapper.m
- (void)send:(CMSampleBufferRef)sampleBuffer
width:(int)width height:(int)height
metadata:(const char *)metadata {
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
NDIlib_video_frame_v2_t video_frame;
video_frame.frame_rate_N = 30000;
video_frame.frame_rate_D = 1000;
video_frame.xres = width;
video_frame.yres = height;
video_frame.FourCC = NDIlib_FourCC_type_BGRA;
video_frame.frame_format_type = NDIlib_frame_format_type_progressive;
video_frame.picture_aspect_ratio = (float)width / (float)height;
video_frame.line_stride_in_bytes = video_frame.xres * 4;
video_frame.p_metadata = metadata;
CVPixelBufferLockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
video_frame.p_data = CVPixelBufferGetBaseAddress(imageBuffer);
CVPixelBufferUnlockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
NDIlib_send_send_video_async_v2(my_ndi_send, &video_frame);
}

144.
[beta]
NDIWrapper.m
- (void)send:(CMSampleBufferRef)sampleBuffer
width:(int)width height:(int)height
metadata:(const char *)metadata {
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
NDIlib_video_frame_v2_t video_frame;
video_frame.frame_rate_N = 30000;
video_frame.frame_rate_D = 1000;
video_frame.xres = width;
video_frame.yres = height;
video_frame.FourCC = NDIlib_FourCC_type_BGRA;
video_frame.frame_format_type = NDIlib_frame_format_type_progressive;
video_frame.picture_aspect_ratio = (float)width / (float)height;
video_frame.line_stride_in_bytes = video_frame.xres * 4;
video_frame.p_metadata = metadata;
CVPixelBufferLockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
video_frame.p_data = CVPixelBufferGetBaseAddress(imageBuffer);
CVPixelBufferUnlockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
NDIlib_send_send_video_async_v2(my_ndi_send, &video_frame);
}

145.
[beta]
NDIWrapper.m
- (void)send:(CMSampleBufferRef)sampleBuffer
width:(int)width height:(int)height
metadata:(const char *)metadata {
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
NDIlib_video_frame_v2_t video_frame;
video_frame.frame_rate_N = 30000;
video_frame.frame_rate_D = 1000;
video_frame.xres = width;
video_frame.yres = height;
video_frame.FourCC = NDIlib_FourCC_type_BGRA;
video_frame.frame_format_type = NDIlib_frame_format_type_progressive;
video_frame.picture_aspect_ratio = (float)width / (float)height;
video_frame.line_stride_in_bytes = video_frame.xres * 4;
video_frame.p_metadata = metadata;
CVPixelBufferLockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
video_frame.p_data = CVPixelBufferGetBaseAddress(imageBuffer);
CVPixelBufferUnlockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
NDIlib_send_send_video_async_v2(my_ndi_send, &video_frame);
}

146.
[beta]
NDIWrapper.m
- (void)send:(CMSampleBufferRef)sampleBuffer
width:(int)width height:(int)height
metadata:(const char *)metadata {
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
NDIlib_video_frame_v2_t video_frame;
video_frame.frame_rate_N = 30000;
video_frame.frame_rate_D = 1000;
video_frame.xres = width;
video_frame.yres = height;
video_frame.FourCC = NDIlib_FourCC_type_BGRA;
video_frame.frame_format_type = NDIlib_frame_format_type_progressive;
video_frame.picture_aspect_ratio = (float)width / (float)height;
video_frame.line_stride_in_bytes = video_frame.xres * 4;
video_frame.p_metadata = metadata;
CVPixelBufferLockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
video_frame.p_data = CVPixelBufferGetBaseAddress(imageBuffer);
CVPixelBufferUnlockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
NDIlib_send_send_video_async_v2(my_ndi_send, &video_frame);
}

147.
[beta]
NDIWrapper.m
- (void)send:(CMSampleBufferRef)sampleBuffer
width:(int)width height:(int)height
metadata:(const char *)metadata {
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
NDIlib_video_frame_v2_t video_frame;
video_frame.frame_rate_N = 30000;
video_frame.frame_rate_D = 1000;
video_frame.xres = width;
video_frame.yres = height;
video_frame.FourCC = NDIlib_FourCC_type_BGRA;
video_frame.frame_format_type = NDIlib_frame_format_type_progressive;
video_frame.picture_aspect_ratio = (float)width / (float)height;
video_frame.line_stride_in_bytes = video_frame.xres * 4;
video_frame.p_metadata = metadata;
CVPixelBufferLockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
video_frame.p_data = CVPixelBufferGetBaseAddress(imageBuffer);
CVPixelBufferUnlockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
NDIlib_send_send_video_async_v2(my_ndi_send, &video_frame);
}

149.

ViewController.swift import CoreMotion private let motionManager = CMMotionManager() private var baseAttitude: CMAttitude? override func viewDidLoad() { super.viewDidLoad() ... motionManager.deviceMotionUpdateInterval = 1.0 / 60.0 motionManager.startDeviceMotionUpdates(using: .xArbitraryCorrectedZVertical) }

150.

ViewController.swift import CoreMotion private let motionManager = CMMotionManager() private var baseAttitude: CMAttitude? override func viewDidLoad() { super.viewDidLoad() ... motionManager.deviceMotionUpdateInterval = 1.0 / 60.0 motionManager.startDeviceMotionUpdates(using: .xArbitraryCorrectedZVertical) }

151.
[beta]
ViewController.swift

private func makeMetaData() -> String {
guard let deviceMotion = motionManager.deviceMotion else { return "" }
let attitude = deviceMotion.attitude
if let baseAttitude = baseAttitude {
attitude.multiply(byInverseOf: baseAttitude)
}
let quat = attitude.quaternion
let arguments = [Float(quat.x), Float(quat.y), Float(quat.z), Float(quat.w)]
return arguments.map { String(format: "%.6f", $0) }.joined(separator: ",")
}

152.
[beta]
ViewController.swift

private func makeMetaData() -> String {
guard let deviceMotion = motionManager.deviceMotion else { return "" }
let attitude = deviceMotion.attitude
if let baseAttitude = baseAttitude {
attitude.multiply(byInverseOf: baseAttitude)
}
let quat = attitude.quaternion
let arguments = [Float(quat.x), Float(quat.y), Float(quat.z), Float(quat.w)]
return arguments.map { String(format: "%.6f", $0) }.joined(separator: ",")
}

153.

なぜオイラー角ではなくクォータニオンを送るのか?

154.

→ ジンバルロックを回避するため

155.

当初はFreeDでオイラー角を送っていた しかしジンバルロック発生のため クォータニオンを送るよう変更

156.

ジンバルロック "3軸の全てに自由な運動がある場合は、機体の回転によって3つ のジンバルリングのうち2つの軸が同一平面上にそろってしまう ジンバルロックという現象が発生しうる。発生すると、本来3あ るはずの自由度が2になってしまう。" https://ja.wikipedia.org/wiki/%E3%82%B8%E3%83%B3%E3%83%90%E3%83%AB

157.

Euler (gimbal lock) Explained https://www.youtube.com/watch?v=zc8b2Jo7mno&t=58s

159.

クォータニオン4:クォータニオンの演算 より https://www.sports-sensing.com/brands/labss/motionmeasurement/motion̲biomechanics/quaternion04.html

160.

ViewController.swift extension ViewController : AVCaptureVideoDataOutputSampleBufferDelegate { func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { guard let ndiWrapper = self.ndiWrapper, isSending else { return } ndiWrapper.send(sampleBuffer, width: 1920, height: 1080, metadata: makeMetaData()) } }

161.

ViewController.swift extension ViewController : AVCaptureVideoDataOutputSampleBufferDelegate { func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { guard let ndiWrapper = self.ndiWrapper, isSending else { return } ndiWrapper.send(sampleBuffer, width: 1920, height: 1080, metadata: makeMetaData()) } }

163.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映

164.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映

165.

現実世界のカメラ情報をCineCameraActorに設定

166.

iPhone 13 Proのカメラ情報をCineCameraActorに設定

167.

iPhone 13 Pro 広角カメラのカメラ情報は?

168.

注: 正直、試行錯誤中です

169.

知りたいのは Sensor Width Focal Length

170.

Sensor Width Apple公式情報なし 調査すると「Sony IMX703」が使用されているようだ サイズは 1/1.66 型 横幅情報が見つからないため 1/1.7 型のサイズ 7.5 5.6 mm を参照

171.

Focal Length https://www.youtube.com/watch?v=EvGOlAkLSLw "26mm focal length" を35mm換算すると5.7

172.

iPhone 13 Pro のField of view func session(_ session: ARSession, didUpdate frame: ARFrame) { let a = Float(frame.camera.imageResolution.width) let b = 2 * frame.camera.intrinsics[0,0] let horizontalFov = 2 * atan(a / b) * 180 / Float.pi print(horizontalFov) } ... 70.362946 70.36179 70.359474 70.35788 70.35992 70.36179 70.36122 ...

173.

動作させながら微調整した暫定値

176.

一旦、平面に映像を表示してみる

177.

Planeを追加し位置とサイズ調整

181.

NDIのTextureをD&D (Materialが自動生成される)

184.

Play

186.

🎉

187.

どの方向を向いても表示するようにする

189.

平面だと、カメラを振った時に 現実世界の映像が切れてしまう

191.

その解決策として

192.

内側を表にした大きな立方体を追加

194.

事前に作成しておいた 「内側を表にした立方体」 をImportし配置

198.

NDIのTextureを描画するMaterialを改修

202.

🎉

203.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映

204.

NDI Plugin インストール NDI Plugin 有効化 NDI Media Receiver作成 BluePrint作成 iPhoneアプリ実装 カメラへ映像を表示 カメラに動作を反映

205.

NDIでフレーム単位で受信している MetaDataのカメラ情報を反映

206.

BluePrintにEventBind追加

213.

位置確認用オブジェクトを置いてみる

214.

Play

215.

FreeDで失敗した動画

217.

NDIで送付

220.

🎉

221.

まとめ AR合成の概要 カメラトラッキング方法 Unreal Engineを使った基本的なシーン作成 iPhoneを使う手法

222.

リアルタイムAR映像配信 皆も実装してみよう!