import _ from 'lodash' import Example1 from './example1' import { markRaw, reactive } from 'vue' import { Scene } from 'three' import type Viewport from '@/designer/Viewport.ts' import * as THREE from 'three' /** * 世界模型 */ export default class WorldModel { data: any = null allLevels: any = null sceneMap = new Map() viewPorts: Viewport[] = [] constructor() { this.init() this.open() } init() { window['worldModel'] = this } open() { if (this.sceneMap.size > 0) { // 释放旧场景 this.sceneMap.forEach((scene: Scene) => { this.sceneDispose(scene) }) } if (this.viewPorts.length > 0) { // 注销视口 this.viewPorts.forEach((viewport: Viewport) => { this.unregisterViewport(viewport) }) } system.msg('打开世界地图完成') this.data = markRaw(Example1) this.allLevels = reactive(this.data.allLevels) } /** * 获取当前楼层的场景, 如果没有则创建一个新的场景 * @param floor */ getSceneByFloor(floor: string) { if (this.sceneMap.has(floor)) { return this.sceneMap.get(floor) } else { const scene = this.createScene(floor) this.sceneMap.set(floor, scene) return scene } } /** * 创建一个新的场景 */ createScene(floor: string) { const scene = new Scene() scene.background = new THREE.Color(0xeeeeee) return scene } /** * 注册视口 */ registerViewport(viewport: Viewport) { this.viewPorts = this.viewPorts || [] this.viewPorts.push(viewport) } /** * 注销视口 */ unregisterViewport(viewport: Viewport) { const index = this.viewPorts.indexOf(viewport) if (index > -1) { this.viewPorts.splice(index, 1) } } /** * 销毁场景, 释放全部 WebGL 资源 */ sceneDispose(scene: Scene = null) { // 移除旧模型 if (!scene) { return } scene.traverse((obj: any) => { // 释放几何体 if (obj.geometry) { obj.geometry.dispose() } // 释放材质 if (obj.material) { if (Array.isArray(obj.material)) { obj.material.forEach(m => m.dispose()) } else { obj.material.dispose() } } // 释放纹理 if (obj.texture) { obj.texture.dispose() } // 释放渲染目标 if (obj.renderTarget) { obj.renderTarget.dispose() } // 移除事件监听(如 OrbitControls) if (obj.dispose) { obj.dispose() } }) // 清空场景 scene.children = [] } }