From 43ef2f824929d27c00e01df936f2eb958cb885d8 Mon Sep 17 00:00:00 2001 From: luoyifan Date: Tue, 3 Jun 2025 23:25:47 +0800 Subject: [PATCH] Way --- src/core/engine/SceneHelp.ts | 17 ++++++-- src/core/engine/Viewport.ts | 37 ++++++++++------- src/editor/menus/FileMenu.ts | 7 +++- src/example/example1.js | 90 ++++++++++-------------------------------- src/modules/way/WayRenderer.ts | 4 +- 5 files changed, 65 insertions(+), 90 deletions(-) diff --git a/src/core/engine/SceneHelp.ts b/src/core/engine/SceneHelp.ts index f120353..9c34fb4 100644 --- a/src/core/engine/SceneHelp.ts +++ b/src/core/engine/SceneHelp.ts @@ -33,6 +33,7 @@ export default class SceneHelp { if (gridOption.axesEnabled) { this.axesHelper = createAxes(gridOption.axesSize, gridOption.axesColor, gridOption.axesWidth) + this.axesHelper.position.setY(0.03) // 确保网格在地面上方 this.scene.add(this.axesHelper) } @@ -40,7 +41,7 @@ export default class SceneHelp { gridHelper.material.color.setHex(gridOption.gridColor) gridHelper.material.opacity = gridOption.gridOpacity gridHelper.material.transparent = true - // @ts-ignore + gridHelper.position.setY(0.02) // 确保网格在地面上方 gridHelper.material.vertexColors = false if (!gridOption.gridEnabled) { gridHelper.visible = false @@ -49,6 +50,16 @@ export default class SceneHelp { this.gridHelper = gridHelper this.scene.add(this.gridHelper) + const gridHelper2 = new THREE.GridHelper(1000, 100) + gridHelper2.material.color.setHex(gridOption.gridColor) + gridHelper2.material.transparent = false + gridHelper2.material.vertexColors = false + gridHelper2.position.setY(0.01) // 确保网格在地面上方 + if (!gridOption.gridEnabled) { + gridHelper2.visible = false + } + this.scene.add(gridHelper2) + // 光照 const ambientLight = new THREE.AmbientLight(0xffffff, 0.8) this.scene.add(ambientLight) @@ -56,10 +67,10 @@ export default class SceneHelp { // const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5) // directionalLight.position.set(5, 5, 5).multiplyScalar(3) // directionalLight.castShadow = true - // scene.add(directionalLight) + // this.scene.add(directionalLight) // // const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x444444, 1) - // scene.add(hemisphereLight) + // this.scene.add(hemisphereLight) } // /** diff --git a/src/core/engine/Viewport.ts b/src/core/engine/Viewport.ts index 5a39d37..f1f41b2 100644 --- a/src/core/engine/Viewport.ts +++ b/src/core/engine/Viewport.ts @@ -158,12 +158,12 @@ export default class Viewport { $(statsControls.dom).children().css('height', '28px') // 监听事件 - // this.watchList.push(watch(() => this.state.camera.position.y, (newVal) => { - // if (!this.state.isReady) { - // return - // } - // this.updateGridVisibility() - // })) + this.watchList.push(watch(() => this.state.camera.position.y, (newVal) => { + if (!this.state.isReady) { + return + } + this.updateGridVisibility() + })) // 监听窗口大小变化 if (this.resizeObserver) { @@ -359,17 +359,26 @@ export default class Viewport { */ updateGridVisibility() { const cameraDistance = this.state.camera.position.y - const maxVisibleDistance = 60 // 网格完全可见的最大距离 - const fadeStartDistance = 15 // 开始淡出的距离 - - // 计算透明度(0~1) - let opacity = 0.8 - if (cameraDistance > fadeStartDistance) { - opacity = 0.8 - Math.min((cameraDistance - fadeStartDistance) / (maxVisibleDistance - fadeStartDistance) * 0.8, 0.8) + const maxVisibleDistance = 4 // 网格完全不可见的最小距离 + const fadeStartDistance = 9 // 开始淡出的最大距离 + + let opacity + if (cameraDistance >= fadeStartDistance) { + // 如果摄像机位置在淡出开始距离或更远,则网格完全可见 + opacity = 1 + } else if (cameraDistance <= maxVisibleDistance) { + // 如果摄像机位置小于等于最大可见距离,则网格完全不可见 + opacity = 0 + } else { + // 计算透明度,使用线性插值 + opacity = 1 - (fadeStartDistance - cameraDistance) / (fadeStartDistance - maxVisibleDistance) } - // 修改网格材质透明度 + // 设置材质的透明度,并确保材质的transparent属性为true以支持透明 this.gridHelper.material.opacity = opacity + this.gridHelper.material.transparent = true + + // 更新网格是否可见 this.gridHelper.visible = opacity > 0 } diff --git a/src/editor/menus/FileMenu.ts b/src/editor/menus/FileMenu.ts index 9857abd..bcb6d20 100644 --- a/src/editor/menus/FileMenu.ts +++ b/src/editor/menus/FileMenu.ts @@ -2,6 +2,7 @@ import { renderIcon, setQueryParam } from '@/utils/webutils.ts' import { defineMenu } from '@/runtime/DefineMenu.ts' import SvgCode from '@/components/icons/SvgCode' import { nextTick } from 'vue' +import type Viewport from '@/core/engine/Viewport.ts' export default defineMenu((menus) => { menus.insertChildren('file', @@ -34,8 +35,10 @@ export default defineMenu((menus) => { }, { name: 'save', label: '保存', icon: SvgCode.save, order: 2, tip: 'Ctrl+S', - click: () => { - system.msg('保存模型文件') + click: async () => { + const viewport: Viewport = window['viewport'] + const vdata: any = await viewport.stateManager.save() + console.log(system.json5.stringify(vdata.items)) } }, { diff --git a/src/example/example1.js b/src/example/example1.js index 036ba9c..1e3358f 100644 --- a/src/example/example1.js +++ b/src/example/example1.js @@ -15,16 +15,16 @@ export default { gridHelper: { // 网格辅助线 axesEnabled: true, // 是否显示中心轴 axesSize: 5, - axesColor: 0xC7C7C7, + axesColor: 0xDDDDDD, axesWidth: 2, gridEnabled: true, // 是否显示网格 gridSize: 1000, // 网格大小 gridDivisions: 1000, // 网格分割数 - gridColor: 0xC7C7C7, // 网格颜色 + gridColor: 0xDDDDDD, // 网格颜色 gridOpacity: 1, // 网格透明度 - backgroundColor: 0x24292E, // 背景颜色 + backgroundColor: 0xF5F5F5, // 背景颜色 snapEnabled: true, // 是否启用吸附 snapDistance: 0.25 // 吸附距离 } @@ -80,86 +80,38 @@ export default { id: 'P1', t: 'measure', v: true, - tf: [ - [-4, 0.1, 4.75], - [90, 0, 0], - [0.25, 0.25, 0.1] - ], - dt: { - in: [], - out: [], - center: [] - } + tf: [[-4, 0.1, 4], [90, 0, 0], [0.25, 0.25, 0.1]], + dt: { in: [], out: [], center: ['P2'] } }, { id: 'P2', t: 'measure', v: true, - tf: [ - [5, 0.1, 2.75], - [90, 0, 0], - [0.25, 0.25, 0.1] - ], - dt: { - in: [], - out: [], - center: ['P1'] - } + tf: [[5, 0.1, 4], [90, 0, 0], [0.25, 0.25, 0.1]], + dt: { in: [], out: [], center: ['P1', 'P3'] } }, { id: 'P3', t: 'measure', v: true, - tf: [ - [5, 0.1, 5.75], - [90, 0, 0], - [0.25, 0.25, 0.1] - ], - dt: { - in: [], - out: [], - center: ['P2'] - } + tf: [[5, 0.1, 6.25], [90, 0, 0], [0.25, 0.25, 0.1]], + dt: { in: [], out: [], center: ['P2'] } }, { - id: 'P4', - t: 'measure', + id: '39zML1rnSOOQGQYQ2YUMGy', + t: 'way', v: true, - tf: [ - [-1.25, 0.1, 7.25], - [90, 0, 0], - [0.25, 0.25, 0.1] - ], - dt: { - in: [], - out: [], - center: ['P3'] - } + tf: [[-4, 0.1, 2], [90, 0, 0], [0.25, 0.25, 0.1]], + dt: { in: [], out: [], center: ['6wrGKiVJniwgKkoggOoEy6'] } }, { - id: 'P5', - t: 'measure', + id: '39zML1rnSOOQGQYQ2YUMGy', + t: 'way', v: true, - tf: [ - [-2, 0.1, 6], - [90, 0, 0], - [0.25, 0.25, 0.1] - ], - dt: { - in: [], - out: [], - center: ['P4'] - } + tf: [[-4, 0.1, 2], [90, 0, 0], [0.25, 0.25, 0.1]], + dt: { in: [], out: [], center: ['6wrGKiVJniwgKkoggOoEy6'] } }, { - id: 'P6', - t: 'measure', + id: '6wrGKiVJniwgKkoggOoEy6', + t: 'way', v: true, - tf: [ - [-3.5, 0.1, 5.25], - [90, 0, 0], - [0.25, 0.25, 0.1] - ], - dt: { - in: [], - out: [], - center: ['P5'] - } + tf: [[5, 0.1, 2], [90, 0, 0], [0.25, 0.25, 0.1]], + dt: { in: [], out: [], center: ['39zML1rnSOOQGQYQ2YUMGy'] } } ] } diff --git a/src/modules/way/WayRenderer.ts b/src/modules/way/WayRenderer.ts index 775698a..a1e3fee 100644 --- a/src/modules/way/WayRenderer.ts +++ b/src/modules/way/WayRenderer.ts @@ -96,7 +96,7 @@ export default class WayRenderer extends BaseRenderer { .addVectors(startPosition, endPosition) .multiplyScalar(0.5) - const distance = startPosition.distanceTo(endPosition) * 1000 + const distance = (startPosition.distanceTo(endPosition) * 1000).toFixed(0) const label = new Text() label.text = distance @@ -142,7 +142,7 @@ export default class WayRenderer extends BaseRenderer { .addVectors(startPosition, endPosition) .multiplyScalar(0.5) - const distance = startPosition.distanceTo(endPosition) * 1000 + const distance = (startPosition.distanceTo(endPosition) * 1000).toFixed(0) label.text = distance label.quaternion.copy(this.tempViewport.camera.quaternion) label.sync()