Renderable
是一个 3D 模型,由顶点、材料、纹理等组成。它可以连接到 Node
并作为场景的一部分渲染。本页介绍如何创建和修改 Renderable
。
通过 Android widget 创建
您可以通过标准 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
。ViewRenderable.builder() .setView(this, R.layout.test_view) .build() .thenAccept(renderable -> testViewRenderable = renderable);
此版本的
setView()
可接受未膨胀的布局文件的资源 ID。您还可以调用setView(View)
,通过程序化创建的视图创建可渲染对象。
Sceneform 中的所有 build()
方法都会返回 CompletableFuture
。该对象在单独的线程上构建,回调函数在主线程上执行。
可渲染对象的大小取决于 View
对象的大小。默认情况下,对于视图,每 250dp 会变成 1 米。使用 setSizer(ViewSizer)
更改视图大小的计算方式。
对底层视图的更改会影响可渲染对象的显示方式。附加了视图可渲染对象的节点会将触摸事件分派给视图,因此您可以执行一些操作,例如响应按钮按下动作。
// update button text when the renderable's node is tapped
Button button = (Button) renderable.getView();
button.setOnClickListener((button) -> button.setText("clicked"));
从 3D 素材资源创建
Sceneform 提供了一些工具和插件,可用于将 3D 资源文件 (OBJ、CocoaPods、glTF) 转换为 Sceneform 二进制资源 (SFB),然后这些文件可以内置到 ModelRenderable
中。
如需了解详情,请参阅导入和预览 3D 素材资源。
在运行时创建简单的形状
使用 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 模型,以确保用户获得良好的体验。
为了使用运行时素材资源加载功能,您需要在 app/build.gradle
中添加对素材资源库的依赖关系:
dependencies {
implementation 'com.google.ar.sceneform:assets:1.15.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));