在 Sceneform 1.16.0 中将 GLB 模型居中

Centering a GLB model in Sceneform 1.16.0

现在 RenderableSource.Builder().setRecenterMode() 已被删除,如何以编程方式将 GLB 模型置于 Android 设备屏幕的中心?

这是我以前在 Sceneform 1.15/1.17.1 中的做法。

ModelRenderable.builder()
    .setSource(
    context,
    RenderableSource.Builder().setSource(context, Uri.parse(uri), RenderableSource.SourceType.GLB)
        .setScale(1f)
        .setRecenterMode(RenderableSource.RecenterMode.CENTER)
        .build()
    )
    .setRegistryId(uri)
    .build()
    .thenAccept { modelRenderable: ModelRenderable ->

改编自 SceneView 的工作解决方案:https://github.com/SceneView/sceneview-android/blob/5ede719cf10c6b72764500366802147d7323aa3f/sceneview/src/main/java/io/github/sceneview/node/ModelNode.kt#L361-L377

/**
 * Centers the 3D model.
 *
 * @param origin Coordinate inside the model unit cube from where it is centered
 * - defaults to [0, 0, 0], which will center the model on the origin
 * - center horizontal | bottom aligned = [0, -1, 0]
 * - left | top aligned: [-1, 1, 0]
 */
fun Node.setCenter(origin: Float3 = Float3(0f, 0f, 0f)) {
    renderableInstance?.filamentAsset?.let { asset ->
        val center = asset.boundingBox.center.let { v -> Float3(v[0], v[1], v[2]) }
        val halfExtent = asset.boundingBox.halfExtent.let { v -> Float3(v[0], v[1], v[2]) }
        val fCenter = -(center + halfExtent * origin) * Float3(1f, 1f, 1f)
        localPosition = Vector3(fCenter.x, fCenter.y, fCenter.z)
    }
}

object Constants {
    const val DEFAULT_RADIUS = 1f
}

operator fun Float3.plus(v: Float3) = Float3(x + v.x, y + v.y, z + v.z)
operator fun Float3.minus(v: Float3) = Float3(x - v.x, y - v.y, z - v.z)
operator fun Float3.times(v: Float3) = Float3(x * v.x, y * v.y, z * v.z)
operator fun Float3.unaryMinus() = Float3(-x, -y, -z)