Renderable
to model 3D składający się z wierzchołków, materiałów, tekstur i innych elementów. Można go dołączyć do elementu Node
i renderować jako część sceny. Na tej stronie opisaliśmy, jak tworzyć i modyfikować Renderable
.
Twórz widżety na Androidzie
ViewRenderable
możesz utworzyć ze standardowych widżetów na Androida. Są one renderowane jako płaskie karty w scenie.
Aby to zrobić:
Utwórz plik układu w res > układ. Przykład:
<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" />
Utwórz
ViewRenderable
.ViewRenderable.builder() .setView(this, R.layout.test_view) .build() .thenAccept(renderable -> testViewRenderable = renderable);
Ta wersja narzędzia
setView()
pobiera identyfikator zasobu nierozszerzonego pliku układu. Możesz też wywołać metodęsetView(View)
, aby utworzyć renderowanie w widokach utworzonych automatycznie.
Wszystkie metody build()
w Sceneform zwracają CompletableFuture
.
Obiekt jest oparty na oddzielnym wątku, a funkcja wywołania zwrotnego jest wykonywana w głównym wątku.
Rozmiar renderowanego elementu zależy od rozmiaru obiektu View
. Domyślnie każde 250 dp w widoku wynosi 1 metr na możliwość renderowania. Kliknij setSizer(ViewSizer)
, aby zmienić sposób obliczania rozmiaru widoku danych.
Zmiany w widoku bazowym wpływają na sposób renderowania renderowania. Węzły z załączonym widokiem renderują zdarzenia dotknięcia do widoku, dzięki czemu możesz na przykład odpowiedzieć na naciśnięcie przycisku.
// update button text when the renderable's node is tapped
Button button = (Button) renderable.getView();
button.setOnClickListener((button) -> button.setText("clicked"));
Tworzenie na podstawie zasobu 3D
Sceneform udostępnia narzędzia i wtyczki do konwertowania plików zasobów 3D (OBJ, Anthos, glTF) na zasoby binarne Sceneform, które można następnie umieścić w narzędziu ModelRenderable
.
Więcej informacji znajdziesz w artykule o importowaniu i wyświetlaniu podglądu zasobów 3D.
Tworzenie prostych kształtów w czasie działania
Proste kształty, takie jak sześciany, sfery i cylindry, można tworzyć za pomocą ShapeFactory
i MaterialFactory
, tworząc bezpretensjonalne obiekty z prostych kształtów i materiałów.
Jak utworzyć czerwoną sferę:
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); });
Wczytywanie modeli 3D podczas działania
Modele 3D przechowywane jako glTF
lub glb
mogą być ładowane w czasie działania bez konwersji. Znacznie zwiększa to elastyczność modeli renderowanych w aplikacji, ale kompromis polega na tym, że model jest odczytywany w czasie działania i nie przynosi korzyści z optymalizacji wykonywanej podczas konwersji w czasie kompilacji do sfb
. Dlatego zalecamy przetestowanie aplikacji i modeli 3D na różnych urządzeniach i w różnych warunkach sieciowych, aby mieć pewność, że będą one wygodne dla użytkowników.
Aby korzystać z wczytywania zasobów środowiska wykonawczego, musisz dodać zależność do biblioteki zasobów w interfejsie app/build.gradle
:
dependencies {
implementation 'com.google.ar.sceneform:assets:1.15.0'
}
Klasa RenderableSource
wczytuje plik glTF i tworzy obiekt źródłowy dla ModelRenderable.Builder
, który tworzy obiekt z możliwością renderowania.
Na przykład załadowanie modelu z internetu wygląda tak:
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;
});
Uwaga: aby uzyskać dostęp zdalny do zasobów, musisz uwzględnić uprawnienie Internet w pliku AndroidManifest.xml:
<manifest …>
<!-- Needed to load a glTF from the internet. -->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
Modyfikowanie renderowania w czasie działania
Jeśli renderowanych jest wiele węzłów, zmiany wprowadzone w tym mechanizmie będą stosowane do wszystkich węzłów. Aby uniknąć tego problemu, wywołaj makeCopy()
, aby utworzyć oddzielną instancję do renderowania. Spowoduje to też wywołanie metody makeCopy()
w przypadku wszystkich materiałów w renderowaniu.
blueSphereRenderable = redSphereRenderable.makeCopy();
blueSphereRenderable.getMaterial().setFloat3(
MaterialFactory.MATERIAL_COLOR, new Color(android.graphics.Color.BLUE));