| import { |
| AmbientLight, |
| Box3, |
| Color, |
| Group, |
| Object3D, |
| SRGBColorSpace, |
| Vector3, |
| } from "three"; |
| import {OrbitControls} from "three/examples/jsm/controls/OrbitControls"; |
| import {ItemType, MapItem} from "@/interfaces/interfaces"; |
| import {loadItemTypeModules} from "@/utils/three/model-loader"; |
| import {ThreeSceneBase} from "@/utils/three/ThreeSceneBase"; |
|
|
| export class MapPreviewerRenderer extends ThreeSceneBase { |
| private controls: OrbitControls; |
| private mapContainer: Group; |
| private models: { [key: string]: Group }; |
| private mapItemList: Object3D[]; |
|
|
| constructor(canvas: HTMLCanvasElement) { |
| super(canvas); |
| this.scene.background = new Color(0xeeeeee); |
| this.camera.fov = 45; |
| this.renderer.outputColorSpace = SRGBColorSpace; |
| this.mapContainer = new Group(); |
| this.models = {}; |
| this.mapItemList = []; |
| this.requestAnimationFrameId = -1; |
|
|
| this.scene.add(this.mapContainer); |
|
|
| |
| this.scene.add(new AmbientLight(0xffffff, 4.5)); |
|
|
| |
| this.controls = new OrbitControls(this.camera, canvas); |
|
|
| const loop = () => { |
| this.requestAnimationFrameId = requestAnimationFrame(loop); |
|
|
| this.controls.update(); |
|
|
| super.render(); |
| } |
|
|
| loop(); |
| } |
|
|
| public async loadModels(itemTypeList: ItemType[]) { |
| this.setLoadingMaskVisible(true); |
| const modelList = await loadItemTypeModules(itemTypeList.map((itemType) => itemType)); |
| const tempModelOBJ: { [key: string]: Group } = {}; |
| modelList.forEach((model) => { |
| tempModelOBJ[model.id] = model.glft.scene; |
| }); |
| this.models = tempModelOBJ; |
| this.setLoadingMaskVisible(false); |
| } |
|
|
| public async loadMapItems(mapItemList: MapItem[]) { |
| this.setLoadingMaskVisible(true); |
| mapItemList.forEach((item) => { |
| const tempModule = this.models[item.type.id].clone(); |
| tempModule.scale.set(0.5, 0.5, 0.5); |
| tempModule.position.set(item.x + item.type.size / 2, 0, item.y + item.type.size / 2); |
| tempModule.rotation.y = (Math.PI / 2) * item.rotation; |
| this.mapContainer.add(tempModule); |
| }); |
| this.setLoadingMaskVisible(false); |
| } |
|
|
| public async reloadMapItems(mapItemList: MapItem[]) { |
| this.mapContainer.clear(); |
| await this.loadMapItems(mapItemList); |
| this.lookAtCenter(); |
| } |
|
|
| public lockCamera(isLock: boolean) { |
| this.controls.enabled = !isLock; |
| if (isLock) { |
| this.lookAtCenter(); |
| } |
| } |
|
|
| public lookAtCenter() { |
| |
| const bbox = new Box3().setFromObject(this.mapContainer); |
|
|
| const center = bbox.getCenter(new Vector3()); |
| const size = bbox.getSize(new Vector3()); |
|
|
| const maxSize = Math.max(...[size.x, size.z]); |
|
|
| |
| const distance = maxSize * Math.tan(this.camera.fov / 2) * 2; |
|
|
| this.camera.position.set(center.x, center.y + distance * 1.2, center.z); |
| this.camera.up.set(0, 0, -1); |
| this.camera.lookAt(center); |
| this.controls.target.set(center.x, center.y, center.z); |
| } |
|
|
| public destroy() { |
| super.destroy(); |
| } |
| } |
|
|