可渲染对象是一种 3D 模型,包含顶点、材料和纹理,等等。 它可以连接到 Node
并作为场景的一部分渲染。 本页将介绍如何创建和修改可渲染对象。
从 Android 微件创建
您可以从标准的 Android 微件创建 ViewRenderable
。 它们将在场景中渲染为平坦的卡片。
要创建可渲染对象,请执行以下操作:
在 res > layout 中创建一个布局文件。 例如:
<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/planetInfoCard" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/rounded_bg" android:gravity="center" android:orientation="vertical" android:padding="6dp" android:text="Test" android:textAlignment="center" />
-
ViewRenderable.builder() .setView(this, R.layout.test_view) .build() .thenAccept(renderable -> testViewRenderable = renderable);
此版本的
setView()
将获取未抬高的布局文件的资源 ID。 您还可以调用setView(View)
,从通过编程方式创建的视图创建可渲染对象。
Sceneform 中的所有 build()
函数都可以返回 CompletableFuture
。 此对象在单独的线程上构建,回调函数在主线程上执行。
可渲染对象的大小基于 View
对象的大小。 默认情况下,视图的每 10px 代表可渲染对象的 1cm。 调用 setPixelsToMeters()
可以更改转换比率。
对底层视图的更改会影响可渲染对象的显示方式。 连接了视图可渲染对象的节点会将触摸事件分派给视图,以便让您响应按钮按下操作。
// update button text when the renderable's node is tapped
Button button = (Button) renderable.getView();
button.setOnClickListener((button) -> button.setText("clicked"));
从 3D asset 创建
Sceneform 提供了多种工具和插件,用于将 3D asset 文件(OBJ、FBX、glTF)转换成 Sceneform 二进制 asset (SFB),此 asset 随后可以构建到 ModelRenderable
中。
如需了解详细信息,请参阅导入和预览 3D asset。
在运行时创建简单的形状
可以使用 ShapeFactory
和 MaterialFactory
创建立方体、球体和圆柱体等简单的形状,这些形状让您可以从简单的形状和材料创建可渲染对象。
以下代码可以创建一个红色的球体:
MaterialFactory.makeOpaqueWithColor(this, new Color(android.graphics.Color.RED))
.thenAccept(
material -> {
redSphereRenderable =
ShapeFactory.makeSphere(0.1f, new Vector3(0.0f, 0.15f, 0.0f), material); });
在运行时加载 3D 模型
运行时,无需转换即可加载以 glTF
或 glb
文件形式存储的 3D 模型。
这大大提升了您的应用中渲染的模型的灵活性,但不利的一点是,模型将在运行时读取,并且不会受益于构建时转换成 sfb
期间进行的优化。
因此,建议您在各种设备和网络条件下测试您的应用和 3D 模型,以便确保您的用户获得出色的体验。
要使用运行时 asset 加载,您需要在 asset 库的 app/build.gradle
中添加依赖项:
dependencies {
implementation 'com.google.ar.sceneform:assets:1.5.0'
}
RenderableSource
类可以处理 glTF 文件的加载,并为创建可渲染对象的 ModelRenderable.Builder
创建源对象。
例如,从互联网加载模型应如下所示:
private static final String GLTF_ASSET =
"https://github.com/KhronosGroup/glTF-Sample-Models/raw/master/2.0/Duck/glTF/Duck.gltf";
/* When you build a Renderable, Sceneform loads model and related resources
* in the background while returning a CompletableFuture.
* Call thenAccept(), handle(), or check isDone() before calling get().
*/
ModelRenderable.builder()
.setSource(this, RenderableSource.builder().setSource(
this,
Uri.parse(GLTF_ASSET),
RenderableSource.SourceType.GLTF2)
.setScale(0.5f) // Scale the original model to 50%.
.setRecenterMode(RenderableSource.RecenterMode.ROOT)
.build())
.setRegistryId(GLTF_ASSET)
.build()
.thenAccept(renderable -> duckRenderable = renderable)
.exceptionally(
throwable -> {
Toast toast =
Toast.makeText(this, "Unable to load renderable " +
GLTF_ASSET, Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
return null;
});
注:要远程访问资源,您需要在 AndroidManifest.xml 中添加互联网权限:
<manifest …>
<!-- Needed to load a glTF from the internet. -->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
在运行时修改可渲染对象
如果多个节点使用可渲染对象,则对该可渲染对象的更改将应用到所有节点。 为了避免这一行为,请调用 makeCopy()
,创建一个单独的可渲染对象实例。 请注意,这也会在可渲染对象的每种材料上调用 makeCopy()
。
blueSphereRenderable = redSphereRenderable.makeCopy();
blueSphereRenderable.getMaterial().setFloat3(
MaterialFactory.MATERIAL_COLOR, new Color(android.graphics.Color.BLUE));