You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
2.6 KiB
130 lines
2.6 KiB
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<string, Scene>()
|
|
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 = []
|
|
}
|
|
}
|