6

I want to load a GLB model in Python, replace the existing texture with another texture image and save it.

So far I can load, modify and export the model. Also, I found a way to append a local image to the model. But I'm not sure how to find and replace the existing texture.

Example 3D model with one texture file: https://modelviewer.dev/shared-assets/models/Astronaut.glb

from pygltflib import GLTF2
from pygltflib.utils import ImageFormat, Image

filename = "Astronaut.glb"
gltf = GLTF2().load(filename)

image = Image()
image.uri = "new-texture.png"

gltf.images.append(image) 
gltf.convert_images(ImageFormat.DATAURI)
gltf.images[0].uri
gltf.images[0].name

# How to find and replace the existing texture?
# ...

filename2 = "updated-3D-model.glb"
gltf.save(filename2)
Tom
  • 326
  • 2
  • 17
  • Hello Tom, did you manage to find a solution? :) thanks! – JAD Jun 15 '22 at 06:49
  • We have converted the GLB with Blender to an GLTF file with external files texture, and replaced these dynamically on the server. The GLTF file always points to the same texture file, so this was the easiest and fastest solution to change these and not the 3d model. – Tom Jun 22 '22 at 11:54

2 Answers2

0

you could do it with string replace in the gltf file. tried it like that and with python and string replace it works very smooth and fast.

Jan L.
  • 1
  • 1
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 30 '22 at 15:43
  • Hi, can you please add an example on how to do this? – SameeraR Apr 19 '23 at 01:57
0

This is example how to do it

from pygltflib import GLTF2
from pygltflib.utils import ImageFormat, Image, Texture, Material

filename = "Astronaut.glb"
gltf = GLTF2().load(filename)

# Step 1: Find the index of the existing texture you want to replace
# Let's assume the texture you want to replace is at index 1 (you need to replace 1 with the actual index)
existing_texture_index = 1

# Step 2: Remove the old texture and its associated image from the GLB
# Remove the texture
gltf.textures.pop(existing_texture_index)

# Remove the image associated with the texture
existing_image_index = gltf.materials[0].pbrMetallicRoughness.baseColorTexture["index"]
gltf.images.pop(existing_image_index)

# Step 3: Add the new image and texture to the GLB
# Create and add a new image to the glTF (same as before)
new_image = Image()
new_image.uri = "new-texture.png"
gltf.images.append(new_image)

# Create a new texture and associate it with the added image
new_texture = Texture()
new_texture.source = len(gltf.images) - 1  # Index of the newly added image
gltf.textures.append(new_texture)

# Step 4: Assign the new texture to the appropriate material(s) or mesh(es)
# Assuming you have a mesh/primitive that was using the old texture and you want to apply the new texture to it, you need to set the material index for that mesh/primitive.
# Replace 0 with the actual index of the mesh/primitive you want to update.
gltf.meshes[0].primitives[0].material = len(gltf.materials) - 1

# Now you can convert the images to data URIs and save the updated GLB
gltf.convert_images(ImageFormat.DATAURI)

filename2 = "updated-3D-model.glb"
gltf.save(filename2)
Bahae El Hmimdi
  • 364
  • 1
  • 5