如何将Three.js中的svgGroupsvg_test网格移动至M_Top网格中心?
将SVG Mesh移动到目标Mesh中心失败的解决方案
问题背景
从GLB导入场景结构后,尝试将名为svgGroupsvg_test的Mesh移动到M_Top Mesh的中心(红色十字为预期位置),使用以下代码后未达到预期效果:
主函数代码
function engraveSVG(object, value) { // object is the name of the target mesh var svgMeshName = 'svgGroup' + value loadSVGandFit(svgMeshName, object, value).then(res => { var svgMesh = scene.getObjectByName(svgMeshName); svgMesh.scale.set(0.1, 0.1, 1) const axesHelper = new THREE.AxesHelper( 20 ); svgMesh.parent.add(axesHelper) moveCenterMeshToOtherMeshCenter(svgMesh, scene.getObjectByName(object)) }) }
尝试的两个移动函数
function moveCenterMeshToOtherMeshCenter(centerMesh, otherMesh) { // get the center positions of both meshes in the local world const centerMeshPosition = new THREE.Vector3(); const otherMeshPosition = new THREE.Vector3(); centerMesh.getWorldPosition(centerMeshPosition); otherMesh.getWorldPosition(otherMeshPosition); // calculate the difference between the center positions of both meshes const difference = otherMeshPosition.sub(centerMeshPosition); // translate the center mesh by the difference centerMesh.translateX(difference.x); centerMesh.translateY(difference.y); centerMesh.translateZ(difference.z); } function moveCenterToOther(centerMesh, otherMesh) { const centerBox = new THREE.Box3().setFromObject(centerMesh); const otherBox = new THREE.Box3().setFromObject(otherMesh); const centerPosition = centerBox.getCenter(new THREE.Vector3()); const otherPosition = otherBox.getCenter(new THREE.Vector3()); const offset = new THREE.Vector3().subVectors(otherPosition, centerPosition); centerMesh.position.add(offset); }
遇到的问题
调用上述函数时,getCenter()返回值接近0;已将SVG Mesh添加到目标Mesh的同一组,坐标轴处于局部坐标系,但仍无法正确移动。
问题分析与解决方法
核心问题
- 坐标系混用:第一个函数中
getWorldPosition获取世界坐标,但translateX/Y/Z是基于局部坐标系的操作,导致位移计算错误; - 包围盒计算未考虑层级变换:第二个函数中
setFromObject计算的是局部坐标系下的包围盒,若Mesh父级有变换,会导致中心坐标不准确。
修正后的移动函数
function moveMeshToTargetCenter(svgMesh, targetMesh) { // 计算世界空间下的包围盒 const svgBox = new THREE.Box3().setFromObject(svgMesh); const targetBox = new THREE.Box3().setFromObject(targetMesh); // 获取世界空间中的目标Mesh中心坐标 const targetWorldCenter = targetBox.getCenter(new THREE.Vector3()); // 将SVG Mesh的世界位置设置为目标中心,再转换为父级局部坐标(如果有父级) svgMesh.position.copy(targetWorldCenter); if (svgMesh.parent) { svgMesh.parent.worldToLocal(svgMesh.position); } }
额外调试建议
- 给Mesh添加包围盒助手,直观查看包围盒位置:
const svgBoxHelper = new THREE.Box3Helper(new THREE.Box3().setFromObject(svgMesh), 0xff0000); const targetBoxHelper = new THREE.Box3Helper(new THREE.Box3().setFromObject(targetMesh), 0x00ff00); scene.add(svgBoxHelper, targetBoxHelper); - 确保SVG Mesh加载完成后几何体顶点无偏移,可调用
svgMesh.geometry.center()先将自身几何体居中; - 若目标Mesh有复杂层级变换,先将变换应用到几何体:
targetMesh.updateMatrix(); targetMesh.geometry.applyMatrix4(targetMesh.matrix); targetMesh.position.set(0,0,0); targetMesh.rotation.set(0,0,0); targetMesh.scale.set(1,1,1);
内容的提问来源于stack exchange,提问作者Arnaud Coutant
相关产品推荐
相关产品推荐

