Skip to content

Conversation

@Rush2k
Copy link
Contributor

@Rush2k Rush2k commented Jan 7, 2026

Description

Preserve texture file paths alongside image data so exporters can reference original texture files instead of re-encoding pixel data.

Changes

  1. genesis/options/textures.py - Allow ImageTexture to have both image_path and image_array
    Changed validation from XOR (exactly one) to "require at least one"
    Only load image from disk if image_array is not already provided
    Preserve image_path even when image_array is present
  2. genesis/engine/mesh.py - Extract path from trimesh materials
    Extract image_path from material.kwargs.get("image_path") when loading SimpleMaterial
    Pass extracted path to create_texture()
  3. genesis/utils/mesh.py - Plumbing for path preservation
    create_texture(): Added image_path parameter, pass to ImageTexture constructor
    create_plane(): Store image_path="textures/checker.png" in plane material
    surface_uvs_to_trimesh_visual(): Store texture.image_path in material kwargs when converting to trimesh
  4. tests/test_mesh.py - Test for path preservation
    Added test_plane_texture_path_preservation() to verify planes preserve texture paths

@Rush2k Rush2k marked this pull request as ready for review January 7, 2026 23:46
@github-actions
Copy link

github-actions bot commented Jan 8, 2026

🔴 Benchmark Regression Detected ➡️ Report

@YilingQiao
Copy link
Collaborator

Please change the code format. Other than that, it looks good to me

Comment on lines +521 to +532
assert len(plane.vgeoms) > 0
vgeom = plane.vgeoms[0]
assert vgeom.vmesh is not None
assert vgeom.vmesh.surface is not None

texture = vgeom.vmesh.surface.diffuse_texture
assert texture is not None
assert isinstance(texture, gs.textures.ImageTexture)

# The texture should have both image_path and image_array
assert texture.image_path is not None
assert texture.image_array is not None
Copy link
Collaborator

@YilingQiao YilingQiao Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those asserts are not helpful

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. Either redundant or out of scope.

Comment on lines +520 to +528
# Check that the plane's vgeom has a texture with a path
assert len(plane.vgeoms) > 0
vgeom = plane.vgeoms[0]
assert vgeom.vmesh is not None
assert vgeom.vmesh.surface is not None

texture = vgeom.vmesh.surface.diffuse_texture
assert texture is not None
assert isinstance(texture, gs.textures.ImageTexture)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand. These checks seem to be completely unrelated to what this test is pretending to check. Either broaden the scope of this unit test (test name, docstring, comments...) or remove these checks.

Comment on lines 234 to +235
color_image = None
color_image_path = None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend not supporting specifying both and raise an exception if it happens. Then load image files directly inside this method if provided.

Comment on lines +503 to +510
def create_texture(image, factor, encoding, image_path=None):
if image is not None:
return gs.textures.ImageTexture(image_array=image, image_color=factor, encoding=encoding)
return gs.textures.ImageTexture(
image_array=image,
image_path=image_path,
image_color=factor,
encoding=encoding,
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same. This API is a bit broken I think. What about adding other method called create_texture_from_path or something, that would do the internal plumbing? Because allowing to specify both image and image_path is weird.

),
material=trimesh.visual.material.SimpleMaterial(
image=Image.open(os.path.join(get_assets_dir(), "textures/checker.png")),
image_path="textures/checker.png",
Copy link
Collaborator

@duburcqa duburcqa Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like dark magic. This is not officially supported by Trimesh from what I know, but maybe I'm wrong.

Comment on lines -115 to +116
if not (self.image_path is None) ^ (self.image_array is None):
# Allow both image_path and image_array, but require at least one
if self.image_path is None and self.image_array is None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it makes sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants