// scene.js import { resolveBlock } from './blockstate.js'; import { mat4Identity, mat4Translate } from './math.js'; // ... imports for loading assets ... export class SceneBuilder { constructor(renderer, atlas) { this.renderer = renderer; this.atlas = atlas; // Cache parsed geometries by model ID so we only build them once this.geometryCache = new Map(); } async buildFromWorld(world) { // 1. Group all instances by their resolved Model ID const instancePool = new Map(); // "block/stone" -> [ matrix1, matrix2, ... ] for (const block of world.blocks.values()) { const stateJSON = await loadBlockstate(block.id); const parts = resolveBlock(stateJSON, block.props); for (const part of parts) { if (!instancePool.has(part.model)) { instancePool.set(part.model, { parts: [], modelId: part.model }); } // Calculate the world position matrix const matrix = mat4Identity(new Float32Array(16)); mat4Translate(matrix, matrix, [block.x, block.y, block.z]); instancePool.get(part.model).parts.push({ matrix: matrix, variant: part // Pass variant so geometry builder handles local rotation }); } } // 2. We now have a list of models and every place they appear. // The next step is to ensure geometry is built, and pack those matrices // into Float32Arrays for the WebGL instanced buffers. return instancePool; } }