如何开发模型放置工具,解决TransformationExtension类工具拖拽时光标偏移问题
问题原因
偏移问题由两个核心错误导致:
- 现有代码直接将选中模型的自身坐标系原点绑定到光标碰撞点,但绝大多数模型的自身原点和几何包围盒中心并不重合,自然会产生固定间隙
- 原有hitTest的排除列表填写错误,拖拽过程中会命中正在移动的模型本身,进一步放大偏移误差
调整后的完整实现
首先在作用域内新增两个状态变量,记录拖拽初始状态:
let dragOffset = new THREE.Vector3(); // 存储光标与模型中心的初始偏移 let isDragging = false;
补充拖拽开始/结束的状态逻辑:
// 拖拽开始逻辑,绑定鼠标按下事件 document.onmousedown = (event) => { if (!event.ctrlKey || !this.selectedModel) return; // 计算初始点击的命中点,排除当前拖拽模型避免命中自身 const hitRes = this.viewer.impl.hitTest( event.clientX, event.clientY, true, null, [this.selectedModel.getModelId()] ); if (!hitRes) return; isDragging = true; // 计算选中模型世界坐标系下的包围盒中心 const localBox = this.selectedModel.getBoundingBox(); const localCenter = localBox.center(); const worldCenter = this.selectedModel.getPlacementTransform().applyPoint(localCenter); // 计算光标命中点和模型中心的初始偏移 dragOffset.copy(hitRes.intersectPoint).sub(worldCenter); } // 拖拽结束重置状态 document.onmouseup = () => { isDragging = false; }
修改原有的鼠标移动逻辑:
document.onmousemove = (event) => { if (!event.ctrlKey || !isDragging || !this.selectedModel) return; let res = this.viewer.impl.hitTest( event.clientX, event.clientY, true, null, [this.selectedModel.getModelId()] // 修正排除列表,跳过当前拖拽的模型 ); let pt = null; if (res) { pt = res.intersectPoint; } else { pt = viewer.impl.intersectGround(event.clientX, event.clientY); } // 命中点减去初始偏移,得到模型实际要放置的位置 const targetPos = pt.clone().sub(dragOffset); let tr = this.selectedModel.getPlacementTransform(); tr.elements[12] = targetPos.x; tr.elements[13] = targetPos.y; tr.elements[14] = targetPos.z; this.selectedModel.setPlacementTransform(tr); this.viewer.impl.invalidate(true, true, true); };
内容的提问来源于stack exchange,提问作者surya kumara
相关产品推荐
相关产品推荐

