feat(SDK & Editor): 为3D Tiles添加侧边配置栏
This commit is contained in:
parent
28a950478b
commit
1f7b232730
@ -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: {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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){
|
||||
|
||||
@ -125,7 +125,7 @@ function getScene(sceneInfo) {
|
||||
|
||||
<n-layout-sider collapse-mode="transform" :collapsed-width="0" :width="siderWidth"
|
||||
:native-scrollbar="false" show-trigger="bar" bordered>
|
||||
<Layout.Sider/>
|
||||
<Layout.Sidebar/>
|
||||
</n-layout-sider>
|
||||
</n-layout>
|
||||
|
||||
|
||||
@ -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<TabsInst | null>(null);
|
||||
const tabs = ref<Array<any>>([]);
|
||||
@ -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(()=>{
|
||||
@ -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 };
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
<script setup lang="ts">
|
||||
import {onBeforeUnmount, onMounted, reactive} from "vue";
|
||||
import {CaretForwardOutline} from "@vicons/ionicons5";
|
||||
import {App,Utils,Hooks,getDefault3DTilesOptions} from "@astral3d/engine";
|
||||
import {t} from "@/language";
|
||||
import Debug from "@/views/editor/layouts/sidebar/tiles/Sidebar.3DTiles.Debug.vue";
|
||||
|
||||
const tilesData = reactive(getDefault3DTilesOptions());
|
||||
|
||||
function updateUI() {
|
||||
const object = App.selected;
|
||||
if(!object) return;
|
||||
|
||||
if (!Utils.is3DTilesObject(object)) return;
|
||||
|
||||
Utils.deepAssign(tilesData, object.options);
|
||||
}
|
||||
|
||||
function update(key:string): void {
|
||||
const object = App.selected;
|
||||
if(!object) return;
|
||||
|
||||
if (!Utils.is3DTilesObject(object)) return;
|
||||
|
||||
switch (key) {
|
||||
case "debug":
|
||||
object.setDebug(tilesData.debug);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
Hooks.useAddSignal("objectSelected", updateUI);
|
||||
|
||||
updateUI();
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
Hooks.useRemoveSignal("objectSelected", updateUI);
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-collapse display-directive="show" :default-expanded-names="['debug']">
|
||||
<template #arrow>
|
||||
<n-icon>
|
||||
<CaretForwardOutline />
|
||||
</n-icon>
|
||||
</template>
|
||||
|
||||
<!-- Debug -->
|
||||
<n-collapse-item :title="t('other.Debug')" name="debug">
|
||||
<Debug :data="tilesData.debug" @update="update" />
|
||||
</n-collapse-item>
|
||||
</n-collapse>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
</style>
|
||||
@ -0,0 +1,65 @@
|
||||
<script setup lang="ts">
|
||||
import {t} from "@/language";
|
||||
import {getDefault3DTilesOptions,TILES_DEBUG_COLOR_MODE} from "@astral3d/engine";
|
||||
|
||||
withDefaults(defineProps<{
|
||||
data: {
|
||||
enabled: boolean,
|
||||
colorMode: string,
|
||||
displayBoxBounds:boolean,
|
||||
displaySphereBounds:boolean,
|
||||
}
|
||||
}>(), {
|
||||
data: () => getDefault3DTilesOptions().debug
|
||||
})
|
||||
|
||||
const emits = defineEmits(['update']);
|
||||
|
||||
function update(){
|
||||
emits('update', "debug");
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="sidebar-config-item">
|
||||
<span>{{ t(`other.Enable`) }}</span>
|
||||
<div>
|
||||
<n-checkbox size="small" v-model:checked="data.enabled" @update:checked="update()"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 颜色模式 -->
|
||||
<div class="sidebar-config-item">
|
||||
<span>{{ t(`layout.sider.tiles.Color mode`) }}</span>
|
||||
<n-select v-model:value="data.colorMode" size="small" :options="[
|
||||
{label: 'None', value: TILES_DEBUG_COLOR_MODE.None },
|
||||
{label: 'Screen error', value: TILES_DEBUG_COLOR_MODE['Screen error']},
|
||||
{label: 'Geometric error', value: TILES_DEBUG_COLOR_MODE['Geometric error']},
|
||||
{label: 'Distance', value: TILES_DEBUG_COLOR_MODE.Distance},
|
||||
{label: 'Depth', value: TILES_DEBUG_COLOR_MODE.Depth},
|
||||
{label: 'Relative depth', value: TILES_DEBUG_COLOR_MODE['Relative depth']},
|
||||
{label: 'Is leaf', value: TILES_DEBUG_COLOR_MODE['Is leaf']},
|
||||
{label: 'Random color', value: TILES_DEBUG_COLOR_MODE['Random color']},
|
||||
{label: 'Random node color', value: TILES_DEBUG_COLOR_MODE['Random node color']},
|
||||
{label: 'Load order', value: TILES_DEBUG_COLOR_MODE['Load order']},
|
||||
]" :disabled="!data.enabled" @update:value="update()" />
|
||||
</div>
|
||||
|
||||
<div class="sidebar-config-item">
|
||||
<span>{{ t(`layout.sider.tiles.Box bounds`) }}</span>
|
||||
<div>
|
||||
<n-checkbox size="small" v-model:checked="data.displayBoxBounds" @update:checked="update()" :disabled="!data.enabled"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-config-item">
|
||||
<span>{{ t(`layout.sider.tiles.Sphere bounds`) }}</span>
|
||||
<div>
|
||||
<n-checkbox size="small" v-model:checked="data.displaySphereBounds" @update:checked="update()" :disabled="!data.enabled"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
</style>
|
||||
11
packages/editor/types/three.d.ts
vendored
Normal file
11
packages/editor/types/three.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 扩展three.js类型声明
|
||||
*/
|
||||
import * as THREE from 'three';
|
||||
|
||||
declare module 'three' {
|
||||
interface Object3D extends THREE.Object3D{
|
||||
/* 强制解决three本身类型声明产生的各种问题 */
|
||||
[key:string]:any;
|
||||
}
|
||||
}
|
||||
@ -40,3 +40,19 @@ export const ROAMING_CHARACTERS = {
|
||||
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,
|
||||
}
|
||||
@ -3,16 +3,18 @@ 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 default class Tiles extends Group{
|
||||
type = "TilesGroup";
|
||||
isTilesGroup = true;
|
||||
|
||||
// 默认配置
|
||||
options: ITiles.options = {
|
||||
export const getDefault3DTilesOptions = ():ITiles.options => ({
|
||||
url:"",
|
||||
reset2origin:true,
|
||||
debug:false,
|
||||
debug: {
|
||||
enabled:false,
|
||||
colorMode: TILES_DEBUG_COLOR_MODE["Screen error"],
|
||||
displayBoxBounds: true,
|
||||
displaySphereBounds: false,
|
||||
},
|
||||
name:"Tiles",
|
||||
errorTarget: 6,
|
||||
LRUCache:{
|
||||
@ -21,7 +23,14 @@ export default class Tiles extends Group{
|
||||
maxBytesSize: 0.4 * 2**30,
|
||||
minBytesSize: 0.3 * 2**30,
|
||||
}
|
||||
};
|
||||
})
|
||||
|
||||
export default class Tiles extends Group{
|
||||
type = "TilesGroup";
|
||||
isTilesGroup = true;
|
||||
|
||||
// 默认配置
|
||||
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方法,因为要接收参数
|
||||
*/
|
||||
|
||||
@ -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";
|
||||
export {default as Tiles, getDefault3DTilesOptions} from "./Tile.ts";
|
||||
@ -330,7 +330,6 @@ export default class Preview extends THREE.EventDispatcher<PreviewerEventMap> {
|
||||
url: fileOrUrl,
|
||||
name: "AstralPreviewTiles",
|
||||
reset2origin:true,
|
||||
debug:false,
|
||||
})
|
||||
this.addTiles(tiles).then(() => {
|
||||
this.modules.controls.fitToBox(tiles,true);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取场景/物体中的所有动画
|
||||
*/
|
||||
|
||||
13
packages/sdk/types/objects/Tile.d.ts
vendored
13
packages/sdk/types/objects/Tile.d.ts
vendored
@ -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 的实用程序类,用于跟踪当前使用的项目,以便渲染的项目不会被卸载
|
||||
|
||||
Loading…
Reference in New Issue
Block a user