Capítulo 827 de 859

Chapter 827: Loading a .OBJ File (Manual)

Core Idea

Walking through the real-world friction of loading a .OBJ model: OBJ files carry no materials of their own, often need a companion .MTL file and separately-unpacked textures, and models exported without three.js in mind may need double-sided materials or auto-framing to display correctly.

Key Concepts

  • OBJLoader: loads geometry from a .obj file; without materials supplied, it falls back to a default material and can throw errors referencing missing material names.
  • MTLLoader + setMaterials(): loads a companion .mtl file's material definitions and hands them to the OBJLoader before loading the .obj, so named materials resolve correctly.
  • Textures aren't always included: an exported .mtl may reference texture files that were never exported separately — for Blender-sourced assets, "Unpack All Into Files" recovers them.
  • Double-sided materials: thin geometry (like windmill blades/cloth) can disappear from the back because of backface culling — fixable by setting the material to THREE.DoubleSide.
  • Normal vs. bump map naming: MTLLoader expects the norm keyword for normal maps; a .mtl file using the wrong keyword will misinterpret normal maps as bump maps, causing blocky-looking shading up close.
  • Auto-framing an unknown-scale model: compute a bounding box for the loaded scene, then position the camera at whatever distance makes that box fit the current field of view, rather than guessing fixed camera coordinates.

Code Examples

function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
  const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
  const distance = (sizeToFitOnScreen * .5) / Math.tan(halfFovY);

  const direction = new THREE.Vector3()
    .subVectors(camera.position, boxCenter)
    .normalize();

  camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));
  camera.near = boxSize / 100;
  camera.far = boxSize * 100;
  camera.updateProjectionMatrix();
  camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
}
  • What it demonstrates: positioning and framing the camera automatically based on a loaded model's computed bounding box, regardless of the model's actual scale.

Key Takeaways

  1. OBJ files have no built-in materials — expect to pair them with a .mtl file loaded via MTLLoader.setMaterials().
  2. Textures referenced by a .mtl file aren't guaranteed to be exported alongside it; check the source 3D tool for an "unpack embedded textures" option if they're missing.
  3. Thin single-sided-looking geometry disappearing from one angle is usually a backface-culling issue, fixed with material.side = THREE.DoubleSide.
  4. MTLLoader specifically expects the norm keyword for normal maps; a mismatched keyword silently treats a normal map as a bump map.
  5. When a model's real-world scale is unknown, compute its bounding box and derive camera distance/near/far from that instead of hardcoding camera values.

Connects To

  • OBJLoader / MTLLoader: the two loaders this entire lesson revolves around.
  • HemisphereLight / DirectionalLight: the lighting setup reused from the Lights manual chapter for this example scene.