Prima di personalizzare un modello 3D, devi prima aggiungerlo alla tua app. Dopo aver aggiunto un modello 3D alla tua app, puoi migliorare l'esperienza visiva e interattiva personalizzando l'aspetto e il movimento del modello 3D.
Ad esempio, puoi riprodurre e controllare le animazioni glTF incorporate, accedere e spostare i nodi che compongono il modello o persino caricare texture personalizzate e definire le proprietà dei materiali per ignorare i mesh interni. Queste funzionalità ti consentono di modificare dinamicamente l'aspetto e il comportamento di un oggetto in fase di runtime.
Oggetti 3D in Android XR
L'SDK Jetpack XR supporta lo standard aperto glTF 2.0 di Khronos Group per i modelli 3D e il rendering di questi oggetti con tecniche di rendering basato sulla fisica (PBR) specificate nello standard glTF 2.0 (insieme alle estensioni supportate). Il glTF (Graphics Library Transmission Format) è un formato file standard per trasmettere e caricare scene e modelli 3D. Un modello glTF è composto da una struttura gerarchica di componenti interni.
Ecco i componenti chiave da comprendere:
- Nodi: definiscono la struttura e la gerarchia del modello. Ogni nodo può avere la propria posizione, rotazione e scala.
- Mesh: la geometria strutturale 3D che forma la forma di un oggetto 3D.
- Materiali: questi definiscono l'aspetto visivo delle mesh, ad esempio il colore, la rugosità o la reazione all'illuminazione.
- Texture: un asset immagine, ad esempio un file PNG, che puoi applicare alla superficie di un modello 3D per creare pattern, colori, dettagli o altri effetti visivi personalizzati.
- Animazioni: si tratta di sequenze predefinite o tracce di animazione che contengono modifiche a singoli nodi e mesh per creare l'aspetto di movimento nel tempo.
In Jetpack Compose per XR, esegui il rendering di questi file utilizzando SpatialGltfModel
e monitora lo stato di caricamento e animazione utilizzando SpatialGltfModelState.
Per maggiori informazioni, vedi Aggiungere modelli 3D all'app.
Animare modelli 3D
I modelli 3D possono avere animazioni incorporate. Internamente, le animazioni utilizzano
campionatori per definire la tempistica e i valori di un movimento e
canali per collegare questi movimenti a singoli nodi e
mesh. Le animazioni scheletriche e dei materiali create con l'estensione glTF KHR_animation_pointer sono supportate nell'SDK Jetpack XR.
Se utilizzi Compose for XR, per riprodurre un'animazione, specifica il nome della traccia
dall'elenco di animations. Usa animation.start() per iniziare
a giocare. (Facoltativo) Puoi specificare la velocità, il tempo di ricerca e se l'animazione deve essere riprodotta in loop utilizzando 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() } }
Manipolare i nodi: pose e rotazione
Per manipolare parti specifiche di un modello e modificarne le proprietà, come la rotazione o la posa, devi eseguire una query sull'nodes interno del modello glTF utilizzando 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" }
Dopo aver trovato il nodo corretto, puoi impostare il relativo localPose per modificarne la posizione e la rotazione 3D rispetto al nodo padre immediato GltfModelNode oppure utilizzare modelPose per impostare la posizione rispetto alla radice GltfModelEntity. Allo stesso modo, puoi utilizzare localScale/modelScale per
modificare la scala del modello rispetto al relativo elemento padre o radice.
LaunchedEffect(node, degrees) { val rotation = Quaternion.fromEulerAngles(degrees, 0f, degrees) node?.let { it.localPose = Pose(it.localPose.translation, rotation) } }
Personalizzare le proprietà dei materiali del modello 3D
Puoi modificare gli attributi dei materiali durante l'esecuzione per cambiare dinamicamente l'aspetto di un oggetto in base all'input dell'utente o allo stato attuale dell'app.
In Jetpack XR, le classi KhronosPbrMaterial e KhronosUnlitMaterial
vengono utilizzate per creare e manipolare questi materiali. Come suggerisce il nome,
KhronosUnlitMaterials non sono illuminate e non sono influenzate dall'illuminazione della scena.
KhronosPbrMaterial ti consente di personalizzare una gamma più ampia di proprietà, ad esempio il colore della lucentezza, il grado di metallicità o ruvidità di un oggetto e se emette luce.
Per ulteriori informazioni su ogni proprietà supportata e sui parametri personalizzabili in Android XR, consulta la nostra documentazione di riferimento. Per comprendere meglio queste proprietà, consulta il glossario di Khronos.
Per personalizzare le proprietà del materiale del modello 3D, devi prima creare il
nuovo materiale utilizzando KhronosPbrMaterial. Devi impostare il
AlphaMode appropriato per l'aspetto visivo che stai cercando di
ottenere:
Poi, definisci le proprietà che vuoi modificare. Questo esempio utilizza
setBaseColorFactor per modificare il colore di base della mesh in viola. Questo
metodo richiede un Vector4, in cui i componenti x, y, z e w corrispondono
rispettivamente ai valori RGBA (rosso, verde, blu e 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 ) ) }
Caricare texture personalizzate per il modello 3D
Una Texture è un asset immagine che puoi applicare alla superficie di un modello 3D
per fornire colore, dettagli o altre informazioni sulla superficie. L'API Jetpack XR
Texture consente di caricare in modo asincrono i dati delle immagini, ad esempio i file PNG, dalla cartella
/assets/ dell'app.
Quando carichi una texture, puoi specificare un TextureSampler, che controlla
la modalità di rendering della texture. Il campionatore definisce le proprietà di filtro (per quando
la texture appare più piccola o più grande delle dimensioni originali) e le modalità di wrapping
(per la gestione delle coordinate al di fuori dell'intervallo [0, 1] standard). Un Texture deve
essere assegnato a un KhronosPbrMaterial per avere un effetto visivo su un modello 3D.
Per caricare una texture personalizzata, devi prima salvare il file immagine nella cartella
/assets/. Come best practice, ti consigliamo di creare anche una sottodirectory textures
in questa cartella.
Dopo aver salvato il file nella directory appropriata, crea la texture
con l'API Texture. È qui che applicherai anche un eventuale
TextureSampler, se necessario.
Questo esempio applica una texture di occlusione e imposta l'intensità dell'occlusione:
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 ) }
Applicare materiali e texture agli oggetti 3D
Per applicare il nuovo materiale o la nuova texture, sostituisci il materiale esistente per un
nodo specifico del nodo glTF. Per farlo, chiama
setMaterialOverride:
node?.setMaterialOverride( material = material )
Per rimuovere i materiali appena creati, chiama clearMaterialOverride sul
nodo precedentemente sottoposto a override. In questo modo, il modello 3D torna allo stato
predefinito:
if (removeMaterial) { node?.clearMaterialOverride() }
glTF e il logo glTF sono marchi di Khronos Group Inc.