import * as THREE from 'three' import { loadGltf } from './loadgltf.js' export default class LevelLoader { constructor(inGame) { this.game = inGame } async load(levelData) { let instancedMeshes = [] for(let i = 0; i < levelData.models.length; i++) { let count = levelData.tiles.reduce((count, tile) => { if (tile.model == i) { return ++count } else { return count } }, 0) if(count == 0) { console.warn(`model ${levelData.models[i]} at index ${i} not used.`) continue } let model = levelData.models[i] const tileMeshScene = await loadGltf(this.game, model) let firstMesh tileMeshScene.traverse((child) => { if (child.isMesh) { firstMesh = child return } }) const tileMesh = new THREE.InstancedMesh(firstMesh.geometry, firstMesh.material, count) tileMesh.receiveShadow = true instancedMeshes[i] = tileMesh } const matrix = new THREE.Matrix4() levelData.models.forEach((model, modelIndex) => { levelData.tiles.filter(tile => tile.model == modelIndex).forEach((tile, tileIndex) => { const position = new THREE.Vector3(tile.position[0] * 4, tile.position[1], tile.position[2] * 4) const quaternion = new THREE.Quaternion() quaternion.setFromAxisAngle(THREE.Object3D.DEFAULT_UP, tile.rotation) const scale = new THREE.Vector3(1, 1, 1) matrix.compose(position, quaternion, scale) instancedMeshes[modelIndex].setMatrixAt(tileIndex, matrix) }) }) levelData.meta.shadow.forEach(modelIndex => { if(instancedMeshes[modelIndex]) { instancedMeshes[modelIndex].castShadow = true instancedMeshes[modelIndex].receiveShadow = true } }) return instancedMeshes } }