add-3d-models
Adding 3D Models to Decentraland Scenes
RULE: Check bounding boxes before placing models
A model's Transform.position is its local origin, not its visual extent. Vegetation and large structural models often extend 6-12 m beyond their origin. A tree placed at x=2 can render at x=-10 — outside scene bounds and invisible.
Before placing any GLB model, determine its actual world-space bounding box. Raw accessor min/max values are NOT sufficient — many models have large node-level scales baked in. You must account for node transforms. Use the bounding box script in {baseDir}/references/model-patterns.md.
Then compute the safe placement zone: safeMinX = -bbox.minX + edgeMargin (>=1m) etc. Place the origin only within the safe zone. When bounding box is unknown, use a conservative 12 m buffer from all edges for trees/large foliage, or 3 m for small props.
RULE: Geometry baked in world coordinates — check the bounds in DCL axes, and probe the axes first
The bounding-box rule above assumes a model built around its own origin and positioned by Transform. The moment you bake world-space placement into the mesh — merged floor/wall chunks for a whole zone, a kitbashed layout exported as one GLB, anything placed by a script in Blender rather than by an entity Transform — the model's placement depends on the axis convention of the exporter, and a wrong guess puts the geometry outside the scene while every number you can read still looks right.
Failure mode, observed 2026-10-08 (cost ~1.5 h): rendering is clipped at the scene boundary, so only the portions of a mesh that fall outside the parcels disappear — the rest of the model stays visible. That is what makes a bad axis guess so confusing: when the whole baked mesh lands outside (e.g. mirrored in X), all of it is clipped, with no error, even though the entity's own Transform.position is inside the scene. Both the Explorer and the Creator Hub editor clip it the same way, and the Creator Hub's get_scene_metrics.entitiesOutOfBoundaries did not list it — under the Bevy renderer that list is a hardcoded empty array (verified in the inspector's BevyRenderer), so it can never warn you; under Babylon it is bounds-based and would. The tell is a contradiction between two reads:
explorer_get_scene_content_statscounts the model's triangles — so the GLB loaded fine;explorer_get_scene_content_breakdownshows the source with NrenderersandvisibleRenderers: 0from every viewpoint;- scene logs are clean.