From 1f7b23273028c3bcb8329b7b818c666ec1b6f18b Mon Sep 17 00:00:00 2001 From: ErSan Date: Tue, 7 Oct 2025 22:33:16 +0800 Subject: [PATCH] =?UTF-8?q?feat(SDK=20&=20Editor):=20=E4=B8=BA3D=20Tiles?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BE=A7=E8=BE=B9=E9=85=8D=E7=BD=AE=E6=A0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor/src/language/zh-CN-en-US.ts | 13 +-- .../extraPane/resource/builtin/Tiles.vue | 2 - .../extraPane/resource/public/AssetsList.vue | 1 - packages/editor/src/views/editor/index.vue | 2 +- .../editor/layouts/{Sider.vue => Sidebar.vue} | 18 +++- .../editor/src/views/editor/layouts/index.ts | 4 +- .../editor/layouts/sidebar/Sidebar3DTiles.vue | 60 +++++++++++++ .../sidebar/tiles/Sidebar.3DTiles.Debug.vue | 65 ++++++++++++++ packages/editor/types/three.d.ts | 11 +++ packages/sdk/lib/constant/enum.ts | 16 ++++ packages/sdk/lib/core/objects/Tile.ts | 89 +++++++++++++------ packages/sdk/lib/core/objects/index.ts | 2 +- packages/sdk/lib/core/preview/Preview.ts | 1 - packages/sdk/lib/utils/scene/index.ts | 7 ++ packages/sdk/types/objects/Tile.d.ts | 13 ++- 15 files changed, 260 insertions(+), 44 deletions(-) rename packages/editor/src/views/editor/layouts/{Sider.vue => Sidebar.vue} (91%) create mode 100644 packages/editor/src/views/editor/layouts/sidebar/Sidebar3DTiles.vue create mode 100644 packages/editor/src/views/editor/layouts/sidebar/tiles/Sidebar.3DTiles.Debug.vue create mode 100644 packages/editor/types/three.d.ts diff --git a/packages/editor/src/language/zh-CN-en-US.ts b/packages/editor/src/language/zh-CN-en-US.ts index f2527b0..2063112 100644 --- a/packages/editor/src/language/zh-CN-en-US.ts +++ b/packages/editor/src/language/zh-CN-en-US.ts @@ -395,10 +395,6 @@ export default { 'Depth Write': '深度缓冲', Wireframe: '线框', }, - "Scene theme": "场景主题", - sceneTheme: { - 'Blue tone': '蓝田日暖玉生烟', - }, Animations: '动画', animation: { Play: '播放', @@ -542,6 +538,12 @@ export default { "Html panel":"Html面板", htmlPanel: { Content: "内容" + }, + "3D Tiles": "3D Tiles", + tiles: { + "Color mode": "颜色模式", + "Box bounds": "盒边界", + "Sphere bounds": "球形边界", } }, assets: { @@ -606,7 +608,8 @@ export default { Copy: "复制", Focus: '聚焦', Support: '支持', - Upload: '上传' + Upload: '上传', + Debug:"调试", }, /* 提示 */ prompt: { diff --git a/packages/editor/src/views/editor/components/extraPane/resource/builtin/Tiles.vue b/packages/editor/src/views/editor/components/extraPane/resource/builtin/Tiles.vue index d841061..6f17b04 100644 --- a/packages/editor/src/views/editor/components/extraPane/resource/builtin/Tiles.vue +++ b/packages/editor/src/views/editor/components/extraPane/resource/builtin/Tiles.vue @@ -88,7 +88,6 @@ async function handlePreview(item){ // url:import.meta.env.VITE_GLOB_ORIGIN + item.tileset, // name:previewInfo.name, // reset2origin:true, - // debug:false, // }) // // previewer.addTiles(tiles).then(() => { @@ -109,7 +108,6 @@ function addToScene(item, position?: Vector3) { url: url, name:item.name.value || item.name, reset2origin:true, - debug:false, }) if (position && tiles.options.reset2origin) { diff --git a/packages/editor/src/views/editor/components/extraPane/resource/public/AssetsList.vue b/packages/editor/src/views/editor/components/extraPane/resource/public/AssetsList.vue index b9e39ae..0afd67d 100644 --- a/packages/editor/src/views/editor/components/extraPane/resource/public/AssetsList.vue +++ b/packages/editor/src/views/editor/components/extraPane/resource/public/AssetsList.vue @@ -246,7 +246,6 @@ function addToScene(asset: IAssets.Item,positionOrObject?: Vector3 | Object3D) { url: url, name: asset.name, reset2origin:true, - debug:false, }) if(positionOrObject && (positionOrObject as Vector3).isVector3 && tiles.options.reset2origin){ diff --git a/packages/editor/src/views/editor/index.vue b/packages/editor/src/views/editor/index.vue index ff83870..c6f2afd 100644 --- a/packages/editor/src/views/editor/index.vue +++ b/packages/editor/src/views/editor/index.vue @@ -125,7 +125,7 @@ function getScene(sceneInfo) { - + diff --git a/packages/editor/src/views/editor/layouts/Sider.vue b/packages/editor/src/views/editor/layouts/Sidebar.vue similarity index 91% rename from packages/editor/src/views/editor/layouts/Sider.vue rename to packages/editor/src/views/editor/layouts/Sidebar.vue index cbc51c6..866ba26 100644 --- a/packages/editor/src/views/editor/layouts/Sider.vue +++ b/packages/editor/src/views/editor/layouts/Sidebar.vue @@ -17,7 +17,8 @@ import { Opacity, ImageReference, LocationHeart, - LocationCompany + LocationCompany, + ChoroplethMap } from "@vicons/carbon"; import { t } from "@/language"; @@ -30,13 +31,13 @@ import SidebarHistory from "./sidebar/SidebarHistory.vue"; import SidebarObject from "./sidebar/SidebarObject.vue"; import SidebarGeometry from "./sidebar/SidebarGeometry.vue"; import SidebarMaterial from "./sidebar/SidebarMaterial.vue"; -// import SidebarSceneTheme from "./sidebar/SidebarSceneTheme.vue"; import SidebarAnimations from "./sidebar/SidebarAnimations.vue"; import SidebarScript from "./sidebar/SidebarScript.vue"; import SidebarDrawing from "./sidebar/SidebarDrawing.vue"; import SidebarParticle from "./sidebar/SidebarParticle.vue"; import SidebarBillboard from "./sidebar/SidebarBillboard.vue"; import SidebarHtmlPanel from "./sidebar/SidebarHtmlPanel.vue"; +import Sidebar3DTiles from "./sidebar/Sidebar3DTiles.vue"; const tabsInstRef = ref(null); const tabs = ref>([]); @@ -58,7 +59,6 @@ function setTabs(object){ { name: "renderer", icon: { text: 'Renderer config',color:"#A9A9A9", component: markRaw(ImageReference) }, component: markRaw(SidebarRenderer) }, { name: "effect", icon: { text: 'Post processing',color:"#A9A9A9", component: markRaw(MagicWandFilled) }, component: markRaw(SidebarEffect) }, { name: "weather", icon: { text: 'Weather',color:"#A9A9A9", component: markRaw(CloudSnow) }, component: markRaw(SidebarWeather) }, - // {name:"styles",icon:{text:'Scene theme',color:"#A9A9A9",component:markRaw(JoinOuter)},component:markRaw(SidebarSceneTheme)}, { name: "history", icon: { text: 'History',color:"#A9A9A9", component: markRaw(ResultOld) }, component: markRaw(SidebarHistory) }, { name: "drawing", icon: { text: 'Scene drawing',color:"#A9A9A9", component: markRaw(Image) }, component: markRaw(SidebarDrawing) }, ]; @@ -91,6 +91,11 @@ function setTabs(object){ current.value = 'htmlPanel'; break; + case "TilesGroup": + object3DTabs.push({ name: '3DTiles', icon: { text: '3D Tiles',color:"#A9575F", component: markRaw(ChoroplethMap) }, component: markRaw(Sidebar3DTiles) }) + + current.value = '3DTiles'; + break; } } @@ -118,6 +123,13 @@ function setTabs(object){ current.value = 'object'; } } + + // 如果当前选中的对象不是3DTiles,但是侧边栏是3DTiles,则切换到对象侧边栏 + if (current.value === '3DTiles') { + if (!Utils.is3DTilesObject(object)){ + current.value = 'object'; + } + } } onMounted(()=>{ diff --git a/packages/editor/src/views/editor/layouts/index.ts b/packages/editor/src/views/editor/layouts/index.ts index 53949e5..c84f141 100644 --- a/packages/editor/src/views/editor/layouts/index.ts +++ b/packages/editor/src/views/editor/layouts/index.ts @@ -2,7 +2,7 @@ import Header from "./Header.vue"; import Footer from "./Footer.vue"; import Scene from "./Scene.vue"; // import Cesium from "./Cesium.vue"; -import Sider from "./Sider.vue"; +import Sidebar from "./Sidebar.vue"; import Assets from "./Assets.vue"; -export { Header, Footer, Scene,Sider,Assets }; +export { Header, Footer, Scene,Sidebar,Assets }; diff --git a/packages/editor/src/views/editor/layouts/sidebar/Sidebar3DTiles.vue b/packages/editor/src/views/editor/layouts/sidebar/Sidebar3DTiles.vue new file mode 100644 index 0000000..b6e9ecf --- /dev/null +++ b/packages/editor/src/views/editor/layouts/sidebar/Sidebar3DTiles.vue @@ -0,0 +1,60 @@ + + + + + \ No newline at end of file diff --git a/packages/editor/src/views/editor/layouts/sidebar/tiles/Sidebar.3DTiles.Debug.vue b/packages/editor/src/views/editor/layouts/sidebar/tiles/Sidebar.3DTiles.Debug.vue new file mode 100644 index 0000000..91dffc8 --- /dev/null +++ b/packages/editor/src/views/editor/layouts/sidebar/tiles/Sidebar.3DTiles.Debug.vue @@ -0,0 +1,65 @@ + + + + + \ No newline at end of file diff --git a/packages/editor/types/three.d.ts b/packages/editor/types/three.d.ts new file mode 100644 index 0000000..907f67d --- /dev/null +++ b/packages/editor/types/three.d.ts @@ -0,0 +1,11 @@ +/** + * 扩展three.js类型声明 + */ +import * as THREE from 'three'; + +declare module 'three' { + interface Object3D extends THREE.Object3D{ + /* 强制解决three本身类型声明产生的各种问题 */ + [key:string]:any; + } +} diff --git a/packages/sdk/lib/constant/enum.ts b/packages/sdk/lib/constant/enum.ts index c7f89a4..b91b541 100644 --- a/packages/sdk/lib/constant/enum.ts +++ b/packages/sdk/lib/constant/enum.ts @@ -39,4 +39,20 @@ export const ROAMING_CHARACTERS = { WORK_MAN: "Workman", X_BOT: "X_Bot", Y_BOT: "Y_Bot", +} + +/** + * 3DTiles DebugTilesPlugin ColorMode enum + */ +export const TILES_DEBUG_COLOR_MODE = { + "None": 0, + "Screen error": 1, + "Geometric error": 2, + "Distance": 3, + "Depth": 4, + "Relative depth": 5, + "Is leaf": 6, + "Random color": 7, + "Random node color": 8, + "Load order": 10, } \ No newline at end of file diff --git a/packages/sdk/lib/core/objects/Tile.ts b/packages/sdk/lib/core/objects/Tile.ts index bfd2623..d71071a 100644 --- a/packages/sdk/lib/core/objects/Tile.ts +++ b/packages/sdk/lib/core/objects/Tile.ts @@ -3,25 +3,34 @@ import {GLTFExtensionsPlugin,GLTFMeshFeaturesExtension,GLTFStructuralMetadataExt import Loader from "@/core/loader/Loader.ts"; import {PerspectiveCamera, WebGLRenderer, Group, JSONMeta} from "three"; import {deepAssign} from "@/utils"; +import {TILES_DEBUG_COLOR_MODE} from "@/constant"; +import {useDispatchSignal} from "@/hooks"; + +export const getDefault3DTilesOptions = ():ITiles.options => ({ + url:"", + reset2origin:true, + debug: { + enabled:false, + colorMode: TILES_DEBUG_COLOR_MODE["Screen error"], + displayBoxBounds: true, + displaySphereBounds: false, + }, + name:"Tiles", + errorTarget: 6, + LRUCache:{ + maxSize: 4000, + minSize: 3000, + maxBytesSize: 0.4 * 2**30, + minBytesSize: 0.3 * 2**30, + } +}) export default class Tiles extends Group{ type = "TilesGroup"; isTilesGroup = true; // 默认配置 - options: ITiles.options = { - url:"", - reset2origin:true, - debug:false, - name:"Tiles", - errorTarget: 6, - LRUCache:{ - maxSize: 4000, - minSize: 3000, - maxBytesSize: 0.4 * 2**30, - minBytesSize: 0.3 * 2**30, - } - }; + options: ITiles.options = getDefault3DTilesOptions(); renderer: TilesRenderer; @@ -37,6 +46,14 @@ export default class Tiles extends Group{ this.name = this.options.name as string; this.renderer = this.initRenderer(); + + // 设置debug插件 + this.setDebug(this.options.debug,false); + // 瓦片渐显隐 + this.renderer.registerPlugin(new TilesFadePlugin()); + // 从gpu卸载不可见瓦片数据,cpu上仍然存在 + this.renderer.registerPlugin(new UnloadTilesPlugin()); + this.add(this.renderer.group); } @@ -76,19 +93,6 @@ export default class Tiles extends Group{ // tilesRenderer.manager.addHandler( /\.(gltf|glb)$/g, loader ); // }) - // 瓦片渐显隐 - tilesRenderer.registerPlugin(new TilesFadePlugin()); - // 从gpu卸载不可见瓦片数据,cpu上仍然存在 - tilesRenderer.registerPlugin(new UnloadTilesPlugin()); - if(this.options.debug){ - // 注册调试插件 - tilesRenderer.registerPlugin(new DebugTilesPlugin()); - // 获取调试插件 - const debugTilesPlugin = tilesRenderer.getPluginByName('DEBUG_TILES_PLUGIN') as DebugTilesPlugin; - // 显示包围盒的线框 - debugTilesPlugin.displayBoxBounds = true; - } - // 子级瓦片加载 tilesRenderer.addEventListener('load-model', (e) => { e.scene.traverse(c => { @@ -119,6 +123,39 @@ export default class Tiles extends Group{ this.renderer.setResolutionFromRenderer(camera, renderer); } + /** + * 设置debug插件 + */ + setDebug(debugOptions:ITiles.options["debug"], needCreate:boolean = true){ + deepAssign(this.options.debug, debugOptions); + + if(!this.options.debug) return; + + // 获取调试插件 + let debugTilesPlugin:DebugTilesPlugin | null = this.renderer.getPluginByName('DEBUG_TILES_PLUGIN') as DebugTilesPlugin | null; + + if(!debugTilesPlugin){ + if(!needCreate) return; + + // 注册调试插件 + this.renderer.registerPlugin(new DebugTilesPlugin()); + + // 获取debug插件 + debugTilesPlugin = this.renderer.getPluginByName('DEBUG_TILES_PLUGIN') as DebugTilesPlugin; + } + + debugTilesPlugin.enabled = this.options.debug.enabled; + debugTilesPlugin.colorMode = this.options.debug.colorMode; + debugTilesPlugin.displayBoxBounds = this.options.debug.displayBoxBounds; + debugTilesPlugin.displaySphereBounds = this.options.debug.displaySphereBounds; + + if(!needCreate) return; + + // 发起渲染 + this.update(); + useDispatchSignal("sceneGraphChanged"); + } + /** * 重写clone方法,因为要接收参数 */ diff --git a/packages/sdk/lib/core/objects/index.ts b/packages/sdk/lib/core/objects/index.ts index 2acfb08..145e8e1 100644 --- a/packages/sdk/lib/core/objects/index.ts +++ b/packages/sdk/lib/core/objects/index.ts @@ -1,4 +1,4 @@ export {default as Billboard, getDefaultBillboardOptions} from "./Billboard"; export {HtmlPanelConverter, HtmlPanel, HtmlSprite} from "./HtmlPanel"; export {default as ParticleEmitter, getDefaultParticleConfig} from "./ParticleEmitter"; -export {default as Tiles} from "./Tile.ts"; \ No newline at end of file +export {default as Tiles, getDefault3DTilesOptions} from "./Tile.ts"; \ No newline at end of file diff --git a/packages/sdk/lib/core/preview/Preview.ts b/packages/sdk/lib/core/preview/Preview.ts index 60e9b67..4cb5530 100644 --- a/packages/sdk/lib/core/preview/Preview.ts +++ b/packages/sdk/lib/core/preview/Preview.ts @@ -330,7 +330,6 @@ export default class Preview extends THREE.EventDispatcher { url: fileOrUrl, name: "AstralPreviewTiles", reset2origin:true, - debug:false, }) this.addTiles(tiles).then(() => { this.modules.controls.fitToBox(tiles,true); diff --git a/packages/sdk/lib/utils/scene/index.ts b/packages/sdk/lib/utils/scene/index.ts index eee9d3f..1528bc9 100644 --- a/packages/sdk/lib/utils/scene/index.ts +++ b/packages/sdk/lib/utils/scene/index.ts @@ -104,6 +104,13 @@ export function isHtmlPanelObject(object:Object3D | null){ return object && (object.isHtmlPanel || object.isHtmlSprite) && object.element; } +/** + * 判断是否是3DTiles对象 + */ +export function is3DTilesObject(object:Object3D | null){ + return object && (object.isTilesGroup || object.type === "TilesGroup") && object.options; +} + /** * 获取场景/物体中的所有动画 */ diff --git a/packages/sdk/types/objects/Tile.d.ts b/packages/sdk/types/objects/Tile.d.ts index eaa67c8..6eeb54c 100644 --- a/packages/sdk/types/objects/Tile.d.ts +++ b/packages/sdk/types/objects/Tile.d.ts @@ -6,8 +6,17 @@ declare namespace ITiles{ name?:string; // 加载的3d tiles由于坐标原因,一般不在原点。此配置项为true则重置回原点 reset2origin?:boolean; - // 是否开启tiles的debug模式 - debug?:boolean; + // debug模式 + debug?: { + // 是否启用 + enabled:boolean; + // 渲染tile set时使用的颜色模式 + colorMode: number; + // 显示包围盒的线框 + displayBoxBounds: boolean; + // 显示包围球的线框 + displaySphereBounds: boolean; + }; // 目标屏幕空间误差(以像素为单位) errorTarget?: number; // LRU缓存:TilesRenderer 的实用程序类,用于跟踪当前使用的项目,以便渲染的项目不会被卸载