Android Advent Calendar 15日目を担当させていただきます。@hiraokです。
3Dモデルを使って何かしたいなということで面白そうなOSSがあったので試してみました。
JetpackCompose で 3DとARをロードできるものになります。
導入方法は至って簡単でREADMEに記載の通りセットアップすると使えます。
※3Dを使う場合とARを使用する場合でDependencyが異なるので注意してください。
sampleコードもプロジェクトに用意されております。
3Dを読み込むサンプル
・model-viewer-compose
ARを読み込むサンプル
・ar-model-viewer-compose
サンプルを動かすと以下のように動きます。
実装
3D or AR viewerを最低限動かす実装
3D viewer
rememberでEngine、model、HDRなどのアセットのローダーを設定
val engine = rememberEngine()
val modelLoader = rememberModelLoader(engine)
val environmentLoader = rememberEnvironmentLoader(engine)
cameraNodeでcameraのpositionなどを設定(option)
val cameraNode = rememberCameraNode(engine = engine).apply {
position = Position(z = -12.0f, x = 4.0f)
}
設定しない場合はDefaultCameraNodeが使用されます。
SceneにModelNodeの追加と設定値の入力
Scene(modifier = Modifier.fillMaxSize(),
engine = engine,
modelLoader = modelLoader,
childNodes = rememberNodes {
add(
ModelNode(
modelInstance = modelLoader.createModelInstance("models/range.glb"),
)
)
},
environment = environmentLoader.createHDREnvironment("environments/sample.hdr")!!,
cameraNode = cameraNode,
)
実際に3Dモデル、背景を表示する部分です。
engine, modelLoaderを渡して、childNodesがListを受け付けているのでrememberNodes
で
ModelNodeをListに追加してあげます。
ModelNode
についてはModelLoader#createModelInstance()
にapp/src/main/assets/models
に配置したglb
or gltf
形式の3DモデルのFilePathを設定
※Local以外にもネットワークからも非同期でLoadできます。
environment
はシーンの照明環境とスカイボックスを定義します。
スカイボックスとしてHDR(High Dynamic Range)イメージを設定して背景として利用するためassets/environment
に配置した.hdr形式のFilePathをEnvironmentLoader#createHDREnvironment
に設定します。
全体コード
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SceneviewSampleTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
GalleryContent()
}
}
}
}
}
@Composable
fun GalleryContent() {
val engine = rememberEngine()
val modelLoader = rememberModelLoader(engine)
val environmentLoader = rememberEnvironmentLoader(engine)
val cameraNode = rememberCameraNode(engine = engine).apply {
position = Position(z = -12.0f, x = 4.0f)
}
Scene(
modifier = Modifier.fillMaxSize(),
engine = engine,
modelLoader = modelLoader,
childNodes = rememberNodes {
add(
ModelNode(
modelInstance = modelLoader.createModelInstance("models/range.glb"),
)
)
},
environment = environmentLoader.createHDREnvironment("environments/sample.hdr")!!,
cameraNode = cameraNode,
)
}
動き
FreeでとってきたRangeRoverを空に浮かべたgif
AR viewer
とっても簡単でScene
をARScene
に変える、cameraNodeをARCameraNode
に変える
ぐらいでできてしまいます。
全体コード
@Composable
fun GalleryContent() {
val engine = rememberEngine()
val modelLoader = rememberModelLoader(engine)
val environmentLoader = rememberEnvironmentLoader(engine)
val cameraNode = rememberARCameraNode(engine = engine).apply {
position = Position(z = -12.0f, x = 4.0f)
}
ARScene(
modifier = Modifier.fillMaxSize(),
engine = engine,
modelLoader = modelLoader,
childNodes = rememberNodes {
add(
ModelNode(
modelInstance = modelLoader.createModelInstance("models/range.glb"),
scaleToUnits = 1f
)
)
},
environment = environmentLoader.createHDREnvironment("environments/sky.hdr")!!,
cameraNode = cameraNode
)
}
動き
設定が雑なのでモデルがめちゃくちゃデカくなっておりますができてます。
車内も見られるので車のイメージをつかむ用途で使ったりするのもいいかもしれません。
困ったこと
・ロードできるglb or gltfを見つけるのに苦労した
→ 現時点で動く素材がフリーで手に入ることがわかったサイト
https://www.cgtrader.com/
https://polyhaven.com/
・ARを動かしている間スマホがめちゃくちゃ熱くなる
→ 設定次第な気がするので調査
まとめ
JetpackComposeでここまで簡単に3DモデルARを動かしたりすることができるので中身や3Dグラフィックの知識を身につけたらもっとうまくいろいろやれたりできるんだろうなと感じました。以前3DモデルをOpenGLで動かしたときより格段に楽でした。
今後に期待できるので個人的にもいろいろ試してみたいと感じました。
※今回は動かすことに重点を置いているので説明などで欠けていたり間違えていたりすることもあるかもなのでコメントいただけると嬉しいです。