From a50ed2b5232ea9b7640e3bb03e8b7ea414f2b252 Mon Sep 17 00:00:00 2001 From: luoyifan Date: Thu, 22 May 2025 15:52:50 +0800 Subject: [PATCH] =?UTF-8?q?3D=E6=A8=A1=E5=9E=8B=E6=9F=A5=E7=9C=8B=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/designer/Model3DView.vue | 79 +++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/src/designer/Model3DView.vue b/src/designer/Model3DView.vue index c12430b..4f3ddfd 100644 --- a/src/designer/Model3DView.vue +++ b/src/designer/Model3DView.vue @@ -22,6 +22,7 @@ import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader' import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader' import * as dat from 'three/examples/jsm/libs/lil-gui.module.min.js' import Stats from 'three/examples/jsm/libs/stats.module' +import { TransformControls } from 'three/examples/jsm/controls/TransformControls.js' // DOM refs const canvasContainer = ref(null) @@ -31,33 +32,26 @@ const guiPanel = ref(null) let scene, camera, renderer, controls let statsControls, axesHelper, gridHelper let modelGroup = new THREE.Group() -let gui +let gui, transformControls // 状态变量 const state = { - autoRotate: false, showAxesHelper: true, showGridHelper: true, - cameraPosition: [0, 5, 10], - positionX: 0, - positionY: 0, - positionZ: 0, - rotationX: 0, - rotationY: 0, - rotationZ: 0, - scaleX: 1, - scaleY: 1, - scaleZ: 1, + obj: { + position: { x: 0, y: 0, z: 0 }, + rotation: { x: 0, y: 0, z: 0 }, + scale: { x: 1, y: 1, z: 1 } + }, camera: { position: { x: 0, y: 5, z: 10 }, rotation: { x: 0, y: 0, z: 0 } - } + }, + mode: 'translate' } onMounted(() => { - const viewerDom = canvasContainer.value nextTick(() => { - console.log('viewerDom', viewerDom) initThree() initGUI() }) @@ -109,12 +103,24 @@ function initThree() { statsControls.dom.style.position = 'absolute' viewerDom.appendChild(statsControls.dom) + // 转换控制器 TransformControls + transformControls = new TransformControls(camera, renderer.domElement) + transformControls.attach(modelGroup) + + // 监听控制模式变化事件 + transformControls.addEventListener('change', () => { + // 当变换控件发生变化时触发,用于更新渲染 + renderer.render(scene, camera) + }) + + transformControls.addEventListener('dragging-changed', function(event) { + // 在拖动开始或结束时禁用或启用轨道控制器 + controls.enabled = !event.value + }) + // 动画循环 function animate() { requestAnimationFrame(animate) - if (state.autoRotate) { - modelGroup.rotation.y += 0.01 - } renderView() } @@ -133,9 +139,6 @@ function initGUI() { gui = new dat.GUI({ autoPlace: false }) guiDom.appendChild(gui.domElement) - // 自动旋转 - gui.add(state, 'autoRotate').name('自动旋转') - // 显示辅助线 gui.add(state, 'showAxesHelper').name('显示坐标轴').onChange(val => { axesHelper.visible = val @@ -146,7 +149,7 @@ function initGUI() { }) // Position - const cameraPosFolder = gui.addFolder('Camera Position') + const cameraPosFolder = gui.addFolder('摄像机位置') cameraPosFolder.add(state.camera.position, 'x', -100, 100).step(0.1).listen().onChange(val => { camera.position.x = val }) @@ -158,7 +161,7 @@ function initGUI() { }) // Rotation (in radians) - const cameraRotationFolder = gui.addFolder('Camera Rotation') + const cameraRotationFolder = gui.addFolder('摄像机旋转角') cameraRotationFolder.add(state.camera.rotation, 'x', -Math.PI, Math.PI).listen().onChange(val => { camera.rotation.x = val }) @@ -172,40 +175,44 @@ function initGUI() { // Position const positionFolder = gui.addFolder('Position') - positionFolder.add(state, 'positionX', -10, 10).onChange(val => { + positionFolder.add(state.obj.position, 'x', -10, 10).onChange(val => { modelGroup.position.x = val }) - positionFolder.add(state, 'positionY', -10, 10).onChange(val => { + positionFolder.add(state.obj.position, 'y', -10, 10).onChange(val => { modelGroup.position.y = val }) - positionFolder.add(state, 'positionZ', -10, 10).onChange(val => { + positionFolder.add(state.obj.position, 'z', -10, 10).onChange(val => { modelGroup.position.z = val }) // Rotation (in radians) const rotationFolder = gui.addFolder('Rotation') - rotationFolder.add(state, 'rotationX', -Math.PI, Math.PI).onChange(val => { + rotationFolder.add(state.obj.rotation, 'x', -Math.PI, Math.PI).onChange(val => { modelGroup.rotation.x = val }) - rotationFolder.add(state, 'rotationY', -Math.PI, Math.PI).onChange(val => { + rotationFolder.add(state.obj.rotation, 'y', -Math.PI, Math.PI).onChange(val => { modelGroup.rotation.y = val }) - rotationFolder.add(state, 'rotationZ', -Math.PI, Math.PI).onChange(val => { + rotationFolder.add(state.obj.rotation, 'z', -Math.PI, Math.PI).onChange(val => { modelGroup.rotation.z = val }) // Scale const scaleFolder = gui.addFolder('Scale') - scaleFolder.add(state, 'scaleX', 0.001, 10).onChange(val => { + scaleFolder.add(state.obj.scale, 'x', 0.001, 10).onChange(val => { modelGroup.scale.x = val }) - scaleFolder.add(state, 'scaleY', 0.001, 10).onChange(val => { + scaleFolder.add(state.obj.scale, 'y', 0.001, 10).onChange(val => { modelGroup.scale.y = val }) - scaleFolder.add(state, 'scaleZ', 0.001, 10).onChange(val => { + scaleFolder.add(state.obj.scale, 'z', 0.001, 10).onChange(val => { modelGroup.scale.z = val }) + gui.add(state, 'mode', ['translate', 'rotate', 'scale']).onChange(function(value) { + transformControls.setMode(value) + }) + // 相机位置 // const cameraFolder = gui.addFolder('相机位置') // cameraFolder.add(state.cameraPosition, 0, -10, 10).name('X') @@ -269,9 +276,13 @@ function initMode3DCamera() { const cameraNew = new THREE.PerspectiveCamera(25, viewerDom.clientWidth / viewerDom.clientHeight, 1, 2000) //设置相机位置 // cameraNew.position.set(4, 2, -3); - cameraNew.position.set(30, 30, 30) + // cameraNew.position.set(30, 30, 30) + // 2.4,30,1.5; + cameraNew.position.set(2.4, 20, 1.5) //设置相机方向 - cameraNew.lookAt(0, 0, 0) + // cameraNew.lookAt(0, 0, 0) + // -1.57,0,1.57 + cameraNew.rotation.set(-1.57, 0, 1.57) camera = cameraNew scene.add(camera)