159 lines
4.7 KiB
TypeScript
159 lines
4.7 KiB
TypeScript
import {TilesRenderer} from "3d-tiles-renderer";
|
||
import {GLTFExtensionsPlugin,DebugTilesPlugin} from "3d-tiles-renderer/plugins";
|
||
import Loader from "@/core/loader/Loader.ts";
|
||
import {PerspectiveCamera, WebGLRenderer, Group, JSONMeta} from "three";
|
||
import {deepAssign} from "@/utils";
|
||
|
||
export default class Tiles extends Group{
|
||
type = "TilesGroup";
|
||
isTilesGroup = true;
|
||
|
||
// 默认配置
|
||
options: ITiles.options = {
|
||
url:"",
|
||
reset2origin:true,
|
||
debug:false,
|
||
name:"Tiles",
|
||
errorTarget: 5,
|
||
LRUCache:{
|
||
maxSize: 4000,
|
||
minSize: 3000,
|
||
maxBytesSize: 0.4 * 2**30,
|
||
minBytesSize: 0.3 * 2**30,
|
||
}
|
||
};
|
||
|
||
renderer: TilesRenderer;
|
||
|
||
constructor(options:ITiles.options) {
|
||
super();
|
||
|
||
if(!options.url){
|
||
throw new Error('[Astral 3D]: No url provided.');
|
||
}
|
||
|
||
deepAssign(this.options,options);
|
||
|
||
this.name = this.options.name as string;
|
||
|
||
this.renderer = this.initRenderer();
|
||
this.add(this.renderer.group);
|
||
}
|
||
|
||
get group(){
|
||
return this.renderer.group;
|
||
}
|
||
|
||
/**
|
||
* 初始化Tiles渲染器
|
||
*/
|
||
initRenderer():TilesRenderer{
|
||
const tilesRenderer = new TilesRenderer(this.options.url);
|
||
tilesRenderer.fetchOptions.mode = 'cors';
|
||
tilesRenderer.errorTarget = this.options.errorTarget || 6;
|
||
// LRUCache
|
||
if(this.options.LRUCache){
|
||
tilesRenderer.lruCache.maxSize = this.options.LRUCache.maxSize || 800;
|
||
tilesRenderer.lruCache.minSize = this.options.LRUCache.minSize || 600;
|
||
tilesRenderer.lruCache.maxBytesSize = this.options.LRUCache.maxBytesSize || 0.4 * 2**30;
|
||
tilesRenderer.lruCache.minBytesSize = this.options.LRUCache.minBytesSize || 0.3 * 2**30;
|
||
}
|
||
|
||
// isTilesGroup是只读的,此处绕过 readonly,防止编译报错
|
||
(tilesRenderer.group as { isTilesGroup: boolean }).isTilesGroup = false;
|
||
(tilesRenderer.group as { type: string }).type = "Tiles";
|
||
tilesRenderer.group.isTiles = true;
|
||
tilesRenderer.group.proxy = this;
|
||
|
||
tilesRenderer.registerPlugin(new GLTFExtensionsPlugin({
|
||
dracoLoader: Loader.dracoLoader,
|
||
ktxLoader: Loader.ktx2Loader,
|
||
}));
|
||
// Loader.createGLTFLoader(tilesRenderer.manager).then(loader => {
|
||
// tilesRenderer.manager.addHandler( /\.(gltf|glb)$/g, loader );
|
||
// })
|
||
|
||
// 子级瓦片加载
|
||
tilesRenderer.addEventListener('load-model', (e) => {
|
||
e.scene.traverse(c => {
|
||
c.isTiles = true;
|
||
// 子级瓦片不允许选中,添加proxy属性让点击此瓦片时选中此组
|
||
c.proxy = this;
|
||
|
||
if(c.type === "Group"){
|
||
(c as { type: string }).type = "Tiles";
|
||
}else{
|
||
(c as { type: string }).type = "Tile";
|
||
}
|
||
})
|
||
});
|
||
|
||
tilesRenderer.addEventListener("load-error", (e) => {
|
||
console.error(`${tilesRenderer.group.name} load error:`, e);
|
||
});
|
||
|
||
if(this.options.debug){
|
||
// 注册调试插件
|
||
tilesRenderer.registerPlugin(new DebugTilesPlugin());
|
||
// 获取调试插件
|
||
const debugTilesPlugin = tilesRenderer.getPluginByName('DEBUG_TILES_PLUGIN') as DebugTilesPlugin;
|
||
// 显示包围盒的线框
|
||
debugTilesPlugin.displayBoxBounds = true;
|
||
}
|
||
|
||
return tilesRenderer;
|
||
}
|
||
|
||
/**
|
||
* 设置相机和渲染器
|
||
*/
|
||
setCameraAndRenderer(camera:PerspectiveCamera,renderer:WebGLRenderer){
|
||
this.renderer.setCamera(camera);
|
||
this.renderer.setResolutionFromRenderer(camera, renderer);
|
||
}
|
||
|
||
/**
|
||
* 重写clone方法,因为要接收参数
|
||
*/
|
||
clone(recursive: boolean = true) {
|
||
// 断言为可构造类型
|
||
const Ctor = this.constructor as new (opts: ITiles.options) => this;
|
||
return new Ctor(this.options).copy(this, recursive);
|
||
}
|
||
|
||
/**
|
||
* 重写toJSON
|
||
*/
|
||
toJSON(meta?: JSONMeta){
|
||
const json = super.toJSON(meta);
|
||
json.object.type= "TilesGroup";
|
||
json.object.options = this.options;
|
||
|
||
return json;
|
||
}
|
||
|
||
static fromJSON(data: { options: ITiles.options,[s:string]:any },copyAttr = true){
|
||
const tiles = new Tiles(data.options);
|
||
|
||
if(copyAttr){
|
||
data.children = undefined;
|
||
Loader.objectLoader.copyAttrByData(tiles,data);
|
||
}
|
||
|
||
return tiles;
|
||
}
|
||
|
||
/**
|
||
* 更新/渲染Tiles
|
||
*/
|
||
update(){
|
||
this.renderer.update();
|
||
}
|
||
|
||
/**
|
||
* 自我销毁
|
||
*/
|
||
dispose(){
|
||
this.renderer.dispose();
|
||
}
|
||
} |