Forge Viewer下nwc模型获取对象x/y/z坐标 原rvt适配代码失效
解决NWC模型对象坐标获取失效问题
失效核心原因
RVT格式的构件节点大多直接关联独立fragment片段,变换信息直接存储在fragment的世界矩阵中,因此你的原有代码可以正常运行。但NWC(Navisworks格式)导出时会大量使用实例化复用、层级嵌套变换,单个fragment的基础矩阵未叠加上层节点的层级变换,同时部分复合节点不会直接挂载fragment,因此原有逻辑无法拿到正确坐标。
可行解决方案
方案1:直接获取构件世界中心点坐标(简单快速,满足绝大多数场景需求)
如果仅需要获取构件的中心位置,可直接调用Viewer内置的节点包围盒接口,自动叠加所有层级变换:
function getNodeCenterCoord(nodeId) { const bbox = new THREE.Box3() // 内置方法自动计算NWC节点的世界包围盒,包含所有层级变换 viewer.model.getObjectTree(function (tree) { tree.getNodeWorldBounds(nodeId, bbox) }) const center = bbox.getCenter(new THREE.Vector3()) // center.x / center.y / center.z 即为目标坐标 return { x: center.x, y: center.y, z: center.z } }
方案2:获取完整世界矩阵(适合需要做空间变换、顶点坐标换算的场景)
如果需要拿到完整的世界矩阵用于后续计算,可直接调用内置的节点世界变换接口,无需自行遍历fragment计算:
function getNodeWorldMatrix(nodeId) { const matrix = new THREE.Matrix4() // 自动叠加NWC所有父层级的变换,得到准确的世界矩阵 viewer.model.getWorldTransformForNode(nodeId, matrix) // 如需提取坐标:matrix.elements[12]为x,[13]为y,[14]为z return matrix }
原有代码适配修改(如果你需要保留遍历fragment的逻辑)
如果业务需要保留遍历fragment的逻辑,可在获取fragment矩阵后,叠加节点的层级变换:
getFragmentWorldMatrixByNodeId(nodeId) { let result = { fragId: [], matrix: [], }; let viewer = this.viewer; // 先拿到节点的层级变换矩阵 const nodeTransform = new THREE.Matrix4() viewer.model.getWorldTransformForNode(nodeId, nodeTransform) this.tree.enumNodeFragments(nodeId, function (frag) { let fragProxy = viewer.impl.getFragmentProxy(viewer.model, frag); let matrix = new THREE.Matrix4(); fragProxy.getWorldMatrix(matrix); // 叠加节点层级变换,得到正确的世界矩阵 matrix.multiply(nodeTransform) result.fragId.push(frag); result.matrix.push(matrix); }); return result; }
注意事项
- 所有坐标获取逻辑需要在模型几何完全加载后执行,建议监听
viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, callback)事件触发后再运行 - 如果需要获取构件单个顶点的世界坐标,可从fragment中读取几何顶点数据,乘以对应的世界矩阵即可换算得到
内容的提问来源于stack exchange,提问作者sercanduyar
相关产品推荐
相关产品推荐

