A Renderable
is a 3D model and consists of vertices, materials, textures, and more. It can be
attached to a Node
and rendered as part of a scene. This page describes how to create and modify Renderable
s.
Create from Android widgets
You can create a ViewRenderable
from standard android widgets. These are rendered as flat cards in the scene.
To create one:
-
Create a layout file in res > layout. For example:
< 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" / >
-
Build the
ViewRenderable
.ViewRenderable.builder() .setView(this, R.layout.test_view) .build() .thenAccept(renderable -> testViewRenderable = renderable);
This version of
setView()
takes the resource ID of the uninflated layout file. You can also callsetView(View)
to create a renderable from programmatically created views.
All build()
methods in Sceneform return a CompletableFuture
.
The object is built on a separate thread and the callback function is executed
on the main thread.
The size of the renderable is based on the size of the View
object. By
default, every 250dp for the view becomes 1 meter for the renderable. Use setSizer(ViewSizer)
to change how the size of the view is calculated.
Changes to the underlying view affect how the renderable is displayed. Nodes with a view renderable attached will dispatch touch events to the view, so you can, for example respond to a button press.
// update button text when the renderable's node is tapped
Button
button
=
(
Button
)
renderable
.
getView
();
button
.
setOnClickListener
((
button
)
-
>
button
.
setText
(
"clicked"
));
Create from a 3D asset
Sceneform provides tools and plugins for converting 3D assets files (OBJ, FBX,
glTF) to Sceneform binary assets (SFB), which can then be built into a ModelRenderable
.
For more information, see Import and Preview 3D Assets .
Create simple shapes at runtime
Simple shapes such as cubes, spheres and cylinders can be created using ShapeFactory
and MaterialFactory
let your create renderable objects from simple shapes and materials.
Here's how to create a red sphere:
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); });
Load 3D models at runtime
3D models stored as glTF
or glb
files can be loaded at runtime without
conversion. This greatly improves the flexibility of the models rendered in your
application, but the trade-off is the model is read at runtime and does not
benefit from the optimization that is done during build time conversion to sfb
. Because of this, it is recommended you test your application and 3D
models on a wide range of devices and network conditions to make sure your users
have a great experience.
In order to use runtime asset loading you need to add the dependency on the
assets library in the app/build.gradle
:
dependencies
{
implementation
'
com
.
google
.
ar
.
sceneform
:
assets
:
1.15.0
'
}
The RenderableSource
class handles loading the glTF file and creating a source object for ModelRenderable.Builder
that creates the renderable object.
For example, loading a model from the internet looks like this:
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.5
f
)
//
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
;
});
Note: In order to access resources remotely, you need to include the Internet permission in your AndroidManifest.xml:
< manifest
…
>
< !--
Needed
to
load
a
glTF
from
the
internet
.
--
>
< uses
-
permission
android
:
name
=
"android.permission.INTERNET"
/
>
< /
manifest
>
Modify renderables at runtime
If multiple nodes use the renderable, then changes to that renderable apply to
all nodes. To avoid that behavior, call makeCopy()
to create a separate renderable instance. Note this also calls makeCopy()
on every material in the renderable.
blueSphereRenderable = redSphereRenderable.makeCopy();
blueSphereRenderable.getMaterial().setFloat3(
MaterialFactory.MATERIAL_COLOR, new Color(android.graphics.Color.BLUE));