Antes de personalizar um modelo 3D, você precisa adicioná-lo ao app. Depois de adicionar um modelo 3D ao app, é possível melhorar a experiência visual e interativa personalizando a aparência e o movimento do modelo 3D.
Por exemplo, é possível reproduzir e controlar animações glTF incorporadas, acessar e mover nós que compõem seu modelo ou até mesmo carregar texturas personalizadas e definir propriedades de material para substituir malhas internas. Esses recursos permitem alterar dinamicamente a aparência e o comportamento de um objeto durante a execução.
Objetos 3D no Android XR
O SDK Jetpack XR é compatível com o padrão aberto glTF 2.0 do Khronos Group para modelos 3D e renderiza esses objetos com técnicas de renderização baseada em física (PBR) especificadas no padrão glTF 2.0 (junto com extensões compatíveis). Um glTF (formato de transmissão da biblioteca de gráficos) é um formato de arquivo padrão para transmitir e carregar cenas e modelos 3D. Um modelo glTF é composto por uma estrutura hierárquica de componentes internos.
Estes são os principais componentes que você precisa entender:
- Nós: definem a estrutura e a hierarquia do modelo. Cada nó pode ter posição, rotação e escala próprias.
- Malhas: a geometria estrutural em 3D que forma o formato de um objeto 3D.
- Materiais: definem a aparência visual das malhas, como cor, rugosidade ou como elas reagem à iluminação.
- Texturas: um recurso de imagem, como um arquivo PNG, que pode ser aplicado à superfície de um modelo 3D para criar padrões, cores, detalhes ou outros efeitos visuais personalizados.
- Animações: são sequências predefinidas ou faixas de animação que contêm mudanças em nós e malhas individuais para criar a aparência de movimento ao longo do tempo.
No Jetpack Compose para XR, você renderiza esses arquivos usando SpatialGltfModel
e acompanha o status de carregamento e animação usando um SpatialGltfModelState.
Para mais informações, consulte Adicionar modelos 3D ao app.
Animar modelos 3D
Os modelos 3D podem ter animações incorporadas. Internamente, as animações usam samplers para definir a marcação de tempo e os valores de um movimento, e canais para conectar esses movimentos a nós e malhas individuais. Animações esqueléticas e do Material Design criadas com a
KHR_animation_pointer extensão glTF são
compatíveis com o SDK Jetpack XR.
Usando o Compose para XR, para tocar uma animação, especifique o nome da faixa
específica na lista de animations. Use animation.start() para começar
a tocar. Se quiser, especifique a velocidade, o tempo de busca e se a animação deve ser repetida ou não usando 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() } }
Manipular nós: poses e rotação
Para manipular partes específicas de um modelo e mudar propriedades como rotação ou pose, é necessário consultar o nodes interno do modelo glTF usando 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" }
Depois de encontrar o nó correto, defina o localPose dele para mudar a posição e a rotação 3D em relação ao elemento pai imediato GltfModelNode ou use modelPose para definir a posição em relação à raiz GltfModelEntity. Da mesma forma, você pode usar localScale/modelScale para mudar a escala do modelo em relação ao pai ou à raiz.
LaunchedEffect(node, degrees) { val rotation = Quaternion.fromEulerAngles(degrees, 0f, degrees) node?.let { it.localPose = Pose(it.localPose.translation, rotation) } }
Personalizar as propriedades de material do modelo 3D
É possível ajustar os atributos de materiais durante o tempo de execução para mudar a aparência de um objeto de forma dinâmica com base na entrada do usuário ou no estado atual do app.
No Jetpack XR, as classes KhronosPbrMaterial e KhronosUnlitMaterial
são usadas para criar e manipular esses materiais. Como o nome sugere, os KhronosUnlitMaterials não são iluminados e não são afetados pela iluminação da cena.
Com KhronosPbrMaterial, é possível personalizar uma variedade maior de propriedades, como cor de brilho, nível de metal ou aspereza de um objeto e se ele emite luz.
Para mais informações sobre cada propriedade compatível e os parâmetros personalizáveis no Android XR, consulte nossa documentação de referência. Para entender melhor essas propriedades, consulte o glossário do Khronos.
Para personalizar as propriedades de material do seu modelo 3D, primeiro crie o
novo material usando KhronosPbrMaterial. Você precisará definir o AlphaMode adequado para a aparência visual que quer alcançar:
Em seguida, defina as propriedades que você quer modificar. Este exemplo usa
setBaseColorFactor para mudar a cor base da malha para roxo. Esse método exige um Vector4, em que os componentes x, y, z e w correspondem aos valores RGBA (vermelho, verde, azul e alfa), respectivamente:
// 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 ) ) }
Carregar texturas personalizadas para seu modelo 3D
Uma Texture é um recurso de imagem que pode ser aplicado à superfície de um modelo 3D para fornecer cor, detalhes ou outras informações de superfície. A API Jetpack XR
Texture permite carregar dados de imagem, como arquivos PNG, da pasta
/assets/ do app de forma assíncrona.
Ao carregar uma textura, é possível especificar um TextureSampler, que controla
como a textura é renderizada. O sampler define propriedades de filtragem (para quando
a textura aparece menor ou maior que o tamanho original) e modos de ajuste
(para processar coordenadas fora do intervalo padrão [0, 1]). Um Texture precisa
ser atribuído a um KhronosPbrMaterial para ter um efeito visual em um modelo
3D.
Para carregar uma textura personalizada, primeiro salve o arquivo de imagem na pasta
/assets/. Como prática recomendada, crie um subdiretório textures nessa pasta também.
Depois de salvar o arquivo no diretório adequado, crie a textura
com a API Texture. É aqui também que você aplicaria um TextureSampler opcional, se necessário.
Este exemplo aplica uma textura de oclusão e define a intensidade da oclusão:
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 ) }
Aplicar materiais e texturas aos objetos 3D
Para aplicar o novo material ou textura, substitua o material atual por um
nó específico no nó glTF. Para fazer isso, chame
setMaterialOverride:
node?.setMaterialOverride( material = material )
Para remover os materiais recém-criados, chame clearMaterialOverride no
nó substituído anteriormente. Isso retorna o modelo 3D ao estado padrão:
if (removeMaterial) { node?.clearMaterialOverride() }
glTF e o logotipo do glTF são marcas registradas da Khronos Group Inc.