Skip to content

OBJ/MTL: auto-load map_Kd textures relative to the .mtl (make the explicit texture preload optional) #1505

Description

@obiot

Summary

Bring the OBJ/MTL loader to parity with the glTF external-texture support added in #1504: when a material references a texture via map_Kd, load that image automatically (resolved relative to the .mtl folder) so the user no longer has to preload it separately.

Current behavior

preloadMTL parses the .mtl and stores map_Kd as a path string relative to the file, but never loads the image:

// packages/melonjs/src/loader/parsers/mtl.js
current.map_Kd = basePath + parts.slice(1).join(" "); // path only — not fetched

At mesh-build time resolveTextureAtlas(mat.map_Kd)getImage(mat.map_Kd) is a lookup of an already-preloaded image, not a fetch. So today the user must preload all three pieces and either pass texture: explicitly or preload the image under the matching map_Kd key:

loader.preload([
  { name: "fox", type: "obj",   src: "fox.obj" },
  { name: "fox", type: "mtl",   src: "fox.mtl" },   // says: map_Kd fox.png
  { name: "foxtex", type: "image", src: "fox.png" }, // ← required today
]);
new Mesh(0, 0, { model: "fox", material: "fox", texture: "foxtex" });

If the third line is forgotten, the mesh renders untextured (white-pixel fallback).

Desired behavior

The texture image preload becomes optional. With just the model + material preloaded, the map_Kd texture is auto-resolved relative to the .mtl and loaded:

loader.preload([
  { name: "fox", type: "obj", src: "fox.obj" },
  { name: "fox", type: "mtl", src: "fox.mtl" },   // textures come for free
]);
new Mesh(0, 0, { model: "fox", material: "fox" }); // no `texture:` needed

This mirrors the one-call glTF experience (preload the .glb, its external texture is fetched automatically).

Implementation sketch

  • In preloadMTL (mtl.js): after parsing, for each material with a map_Kd, kick off loading that image (the path is already resolved as basePath + filename), registering it in the loader cache so it's available when the mesh is built. Honor loader settings (crossOrigin / nocache), same as feat(gltf): node animation + Sprite-aligned animation API; Light3d as a world renderable #1504's glTF path.
  • The relative-resolution already exists; the missing piece is the fetch + registration (and making preloadMTL's returned resource count / onload await the textures, so the loader's progress + completion callback include them).
  • Mesh already falls back to mat.map_Kd when no explicit texture: is given (mesh.js) — once the image is registered under that key, auto-resolution just works.

Backward compatibility

  • Explicit settings.texture still wins (unchanged).
  • The existing "preload the image yourself" flow keeps working (the auto-load registers under the same map_Kd path key).

Cross-refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions