Dostosowywanie modeli 3D w aplikacji

Odpowiednie urządzenia XR
Te wskazówki pomogą Ci tworzyć rozwiązania na te typy urządzeń XR.
Gogle XR
Przewodowe okulary XR

Zanim dostosujesz model 3D, musisz najpierw dodać go do aplikacji. Po dodaniu modelu 3D do aplikacji możesz ulepszyć wrażenia wizualne i interaktywne, dostosowując wygląd i ruch modelu 3D.

Możesz na przykład odtwarzać i kontrolować osadzone animacje glTF, uzyskiwać dostęp do węzłów tworzących model i przesuwać je, a nawet wczytywać niestandardowe tekstury i definiować właściwości materiału, aby zastępować wewnętrzne siatki. Te możliwości pozwalają dynamicznie zmieniać wygląd i zachowanie obiektu w czasie wykonywania.

Obiekty 3D na Androidzie XR

Pakiet Jetpack XR SDK obsługuje otwarty standard glTF 2.0 opracowany przez Khronos Group na potrzeby modeli i renderowania 3D. Obiekty te są renderowane za pomocą technik renderowania opartego na fizyce (PBR) określonych w standardzie glTF 2.0 (wraz z obsługiwanymi rozszerzeniami). Format glTF (Graphics Library Transmission Format) to standardowy format plików do przesyłania i wczytywania scen i modeli 3D. Model glTF składa się z hierarchicznej struktury komponentów wewnętrznych.

Oto kluczowe komponenty, które warto poznać:

  • Węzły: określają strukturę i hierarchię modelu. Każdy węzeł może mieć własną pozycję, rotację i skalę.
  • Siatki: strukturalna geometria 3D, która tworzy kształt obiektu 3D.
  • Materiały: określają wygląd siatek, np. ich kolor, chropowatość lub sposób reagowania na oświetlenie.
  • Tekstury: plik graficzny, np. plik PNG, który możesz zastosować na powierzchni modelu 3D, aby utworzyć niestandardowe wzory, kolory, szczegóły lub inne efekty wizualne.
  • Animacje: są to predefiniowane sekwencje lub ścieżki animacji, które zawierają zmiany poszczególnych węzłów i siatek, aby stworzyć wrażenie ruchu w czasie.

W Jetpack Compose XR renderujesz te pliki za pomocą funkcji SpatialGltfModel i śledzisz stan ich wczytywania oraz animacji za pomocą funkcji SpatialGltfModelState. Więcej informacji znajdziesz w artykule Dodawanie modeli 3D do aplikacji.

Animowanie modeli 3D

Modele 3D mogą zawierać osadzone animacje. Animacje wewnętrznie używają samplerów do określania czasu i wartości ruchu oraz kanałów do łączenia tych ruchów z poszczególnymi węzłami i siatkami. Animacje szkieletowe i animacje materiałów utworzone za pomocą KHR_animation_pointer rozszerzenia glTF są obsługiwane w pakiecie Jetpack XR SDK.

Aby odtworzyć animację za pomocą Compose for XR, podaj nazwę konkretnej ścieżki z listy animations. Aby rozpocząć odtwarzanie, użyj animation.start(). Opcjonalnie możesz określić prędkość, czas wyszukiwania i czy animacja ma być odtwarzana w pętli, używając SpatialGltfModelAnimation:

val animation = modelState.animations.find { it.name == "Walk" }

animation?.animationState?.let { state ->
    LaunchedEffect(state) {
        Log.i("SpatialGltfModelAnimationSample", "Animation State: $state")
    }
}

DisposableEffect(animation) {
    animation?.loop()
    onDispose {
        animation?.stop()
    }
}

Manipulowanie węzłami: pozy i obrót

Aby manipulować określonymi częściami modelu i zmieniać jego właściwości, takie jak rotacja czy pozycja, musisz wysłać zapytanie do wewnętrznego nodes modelu glTF za pomocą SpatialGltfModelState.

// Retrieve the list of nodes (individual components/meshes) defined within the glTF model.
val entityNodes = modelState.nodes

// Find a specific node by name to apply modifications, such as material overrides.
val node = entityNodes.find { it.name == "node_name" }

Po znalezieniu odpowiedniego węzła możesz ustawić jego localPose, aby zmienić jego położenie i obrót 3D względem bezpośredniego węzła nadrzędnego GltfModelNode, lub użyć modelPose, aby ustawić położenie względem węzła głównego GltfModelEntity. Podobnie możesz użyć właściwości localScale/modelScale, aby zmienić skalę modelu względem jego elementu nadrzędnego lub głównego.

LaunchedEffect(node, degrees) {
    val rotation = Quaternion.fromEulerAngles(degrees, 0f, degrees)
    node?.let {
        it.localPose = Pose(it.localPose.translation, rotation)
    }
}

Dostosowywanie właściwości materiału modelu 3D

Możesz dostosowywać atrybuty materiału w czasie działania, aby dynamicznie zmieniać wygląd obiektu na podstawie danych wejściowych użytkownika lub bieżącego stanu aplikacji.

W Jetpack XR klasy KhronosPbrMaterial i KhronosUnlitMaterial służą do tworzenia tych materiałów i manipulowania nimi. Jak sama nazwa wskazuje, KhronosUnlitMaterials są nieoświetlone i nie mają na nie wpływu ustawienia oświetlenia sceny. KhronosPbrMaterial umożliwia dostosowywanie szerszego zakresu właściwości, takich jak kolor połysku, stopień metaliczności lub chropowatości obiektu oraz to, czy emituje on światło.

Więcej informacji o poszczególnych obsługiwanych właściwościach i parametrach, które można dostosowywać w Androidzie XR, znajdziesz w naszej dokumentacji referencyjnej. Aby lepiej zrozumieć te właściwości, zapoznaj się z słowniczkiem Khronos.

Rysunek 1. Przykład zmiany kolorów podstawowych na modelu 3D.

Aby dostosować właściwości materiału modelu 3D, najpierw utwórz nowy materiał za pomocą KhronosPbrMaterial. Musisz ustawić odpowiednią wartość AlphaMode, aby uzyskać pożądany wygląd:

Następnie określ właściwości, które chcesz zmodyfikować. W tym przykładzie użyto kodu setBaseColorFactor, aby zmienić kolor podstawowy siatki na fioletowy. Ta metoda wymaga podania wartości Vector4, gdzie komponenty x, y, z, x, y, zw odpowiadają odpowiednio wartościom RGBA (czerwony, zielony, niebieski i alfa):

// Maintain a reference to the custom material to avoid re-creating it on every recomposition.
var pbrMaterial by remember { mutableStateOf<KhronosPbrMaterial?>(null) }

// Create and apply the custom material once the session is ready and the target node is available.
LaunchedEffect(node) {
    val material = KhronosPbrMaterial.create(
        session = xrSession,
        alphaMode = AlphaMode.OPAQUE
    ).also {
        pbrMaterial = it
        // Apply a base color factor (RGBA) to change the color of the model.
        it.setBaseColorFactor(
            Vector4(
                x = 0.5f,
                y = 0.0f,
                z = 0.5f,
                w = 1.0f
            )
        )
    }

Wczytywanie niestandardowych tekstur do modelu 3D

Texture to komponent z obrazem, który możesz zastosować na powierzchni Modelu 3D, aby dodać kolor, szczegóły lub inne informacje o powierzchni. Interfejs Jetpack XR Texture API umożliwia asynchroniczne wczytywanie danych obrazu, np. plików PNG, z folderu /assets/ aplikacji.

Podczas wczytywania tekstury możesz określić TextureSampler, który kontroluje sposób renderowania tekstury. Sampler określa właściwości filtrowania (gdy tekstura jest mniejsza lub większa niż jej oryginalny rozmiar) i tryby zawijania (do obsługi współrzędnych poza standardowym zakresem [0, 1]). Texture musi być przypisany do KhronosPbrMaterial, aby mieć efekt wizualny na modelu 3D.

Rysunek 2. Przykład zmiany tekstury na modelu 3D.

Aby wczytać teksturę niestandardową, musisz najpierw zapisać plik obrazu w folderze /assets/. Najlepiej jest też utworzyć w tym folderze textures podkatalog.

Po zapisaniu pliku w odpowiednim katalogu utwórz teksturę za pomocą interfejsu Texture API. W razie potrzeby możesz też zastosować opcjonalny TextureSampler.

W tym przykładzie zastosowano teksturę okluzji i ustawiono siłę okluzji:

LaunchedEffect(node) {
    val material = KhronosPbrMaterial.create(
        session = xrSession,
        alphaMode = AlphaMode.OPAQUE
    ).also {
        pbrMaterial = it

        // Load a texture
        val texture = Texture.create(
            session = xrSession,
            path = Path("textures/texture_name.png")
        )

        // Set the texture and configure occlusion to define how the material surface handles ambient lighting.
        it.setOcclusionTexture(
            texture = texture,
            strength = 1.0f
        )
    }
    node?.setMaterialOverride(
        material = material
    )
}

Stosowanie materiałów i tekstur do obiektów 3D

Aby zastosować nowy materiał lub teksturę, zastąp istniejący materiał w przypadku konkretnego węzła w węźle glTF. Aby to zrobić, zadzwoń pod numer setMaterialOverride:

node?.setMaterialOverride(
    material = material
)

Aby usunąć nowo utworzone materiały, wywołaj funkcję clearMaterialOverride na wcześniej zastąpionym węźle. Spowoduje to przywrócenie domyślnego stanu modelu 3D:

if (removeMaterial) {
    node?.clearMaterialOverride()
}


glTF i logo glTF są znakami towarowymi firmy Khronos Group Inc.