根據個人研究,Forge Viewer爲了支持大量的三角片使用了一個自制的Render,而不是使用 Three.js 自帶的,因此它的一些內部幾何數據可能都 Three.js 自帶的不太同樣。本篇博客將提供一個示例讓您知道如何存取 Mesh 的頂點 (Vertices)、面片(Faces) 等信息。javascript
在 library-javascript-viewer-extensions 這個 Autodesk Forge 官方的示例工程裏有一個Autodesk.ADN.Viewing.Extension.MeshData 的擴展,這個擴展會在被 Viewer 加載後在畫面上畫出一些線及圓來表示你在模型裏已選構件的 Mesh 頂點 (Vertices) 及 Mesh 面片(Faces),結果以下圖所示:java
Autodesk.ADN.Viewing.Extension.MeshData
這個示例擴展的重點在於 drawMeshData
這個函數,而在取得Mesh頂點 (Vertices) 後,需將他從本地座標系統投射到世界座標系統,也就是示例裏的 vA
、vB
及 vC
這三個變量,轉換後就能夠將他直接畫下畫面上,獲得上面那張截圖紅點的部份結果;將Mesh頂點用線連起來的話就是截圖裏藍線的部份。最後,三角片參數的說明能夠參考梁老師在這答應的回覆內容。git
/*/////////////////////////////////////////////////////////////////////////////// // MeshData viewer extension // by Philippe Leefsma, July 2015 // ///////////////////////////////////////////////////////////////////////////////*/ AutodeskNamespace("Autodesk.ADN.Viewing.Extension"); Autodesk.ADN.Viewing.Extension.MeshData = function (viewer, options) { Autodesk.Viewing.Extension.call(this, viewer, options); var _self = this; var _lineMaterial = null; var _vertexMaterial = null; /////////////////////////////////////////////////////////////////////////// // load callback // /////////////////////////////////////////////////////////////////////////// _self.load = function () { _lineMaterial = createLineMaterial(); _vertexMaterial = createVertexMaterial(); viewer.addEventListener( Autodesk.Viewing.SELECTION_CHANGED_EVENT, onSelectionChanged); console.log('Autodesk.ADN.Viewing.Extension.MeshData loaded'); return true; }; /////////////////////////////////////////////////////////////////////////// // unload callback // /////////////////////////////////////////////////////////////////////////// _self.unload = function () { console.log('Autodesk.ADN.Viewing.Extension.MeshData unloaded'); return true; }; /////////////////////////////////////////////////////////////////////////// // selection changed callback // /////////////////////////////////////////////////////////////////////////// function onSelectionChanged(event) { event.fragIdsArray.forEach(function(fragId){ drawMeshData(fragId); }); viewer.impl.sceneUpdated(true); } /////////////////////////////////////////////////////////////////////////// // draw vertices and faces // /////////////////////////////////////////////////////////////////////////// function drawMeshData(fragId) { var fragProxy = viewer.impl.getFragmentProxy( viewer.model, fragId); var renderProxy = viewer.impl.getRenderProxy( viewer.model, fragId); fragProxy.updateAnimTransform(); var matrix = new THREE.Matrix4(); fragProxy.getWorldMatrix(matrix); var geometry = renderProxy.geometry; var attributes = geometry.attributes; var vA = new THREE.Vector3(); var vB = new THREE.Vector3(); var vC = new THREE.Vector3(); if (attributes.index !== undefined) { var indices = attributes.index.array || geometry.ib; var positions = geometry.vb ? geometry.vb : attributes.position.array; var stride = geometry.vb ? geometry.vbstride : 3; var offsets = geometry.offsets; if (!offsets || offsets.length === 0) { offsets = [{start: 0, count: indices.length, index: 0}]; } for (var oi = 0, ol = offsets.length; oi < ol; ++oi) { var start = offsets[oi].start; var count = offsets[oi].count; var index = offsets[oi].index; for (var i = start, il = start + count; i < il; i += 3) { var a = index + indices[i]; var b = index + indices[i + 1]; var c = index + indices[i + 2]; vA.fromArray(positions, a * stride); vB.fromArray(positions, b * stride); vC.fromArray(positions, c * stride); vA.applyMatrix4(matrix); vB.applyMatrix4(matrix); vC.applyMatrix4(matrix); drawVertex (vA, 0.05); drawVertex (vB, 0.05); drawVertex (vC, 0.05); drawLine(vA, vB); drawLine(vB, vC); drawLine(vC, vA); } } } else { var positions = geometry.vb ? geometry.vb : attributes.position.array; var stride = geometry.vb ? geometry.vbstride : 3; for (var i = 0, j = 0, il = positions.length; i < il; i += 3, j += 9) { var a = i; var b = i + 1; var c = i + 2; vA.fromArray(positions, a * stride); vB.fromArray(positions, b * stride); vC.fromArray(positions, c * stride); vA.applyMatrix4(matrix); vB.applyMatrix4(matrix); vC.applyMatrix4(matrix); drawVertex (vA, 0.05); drawVertex (vB, 0.05); drawVertex (vC, 0.05); drawLine(vA, vB); drawLine(vB, vC); drawLine(vC, vA); } } } /////////////////////////////////////////////////////////////////////////// // vertex material // /////////////////////////////////////////////////////////////////////////// function createVertexMaterial() { var material = new THREE.MeshPhongMaterial({ color: 0xff0000 }); viewer.impl.matman().addMaterial( 'adn-material-vertex', material, true); return material; } /////////////////////////////////////////////////////////////////////////// // line material // /////////////////////////////////////////////////////////////////////////// function createLineMaterial() { var material = new THREE.LineBasicMaterial({ color: 0x0000ff, linewidth: 2 }); viewer.impl.matman().addMaterial( 'adn-material-line', material, true); return material; } /////////////////////////////////////////////////////////////////////////// // draw a line // /////////////////////////////////////////////////////////////////////////// function drawLine(start, end) { var geometry = new THREE.Geometry(); geometry.vertices.push(new THREE.Vector3( start.x, start.y, start.z)); geometry.vertices.push(new THREE.Vector3( end.x, end.y, end.z)); var line = new THREE.Line(geometry, _lineMaterial); viewer.impl.scene.add(line); } /////////////////////////////////////////////////////////////////////////// // draw a vertex // /////////////////////////////////////////////////////////////////////////// function drawVertex (v, radius) { var vertex = new THREE.Mesh( new THREE.SphereGeometry(radius, 20), _vertexMaterial); vertex.position.set(v.x, v.y, v.z); viewer.impl.scene.add(vertex); } }; Autodesk.ADN.Viewing.Extension.MeshData.prototype = Object.create(Autodesk.Viewing.Extension.prototype); Autodesk.ADN.Viewing.Extension.MeshData.prototype.constructor = Autodesk.ADN.Viewing.Extension.MeshData; Autodesk.Viewing.theExtensionManager.registerExtension( 'Autodesk.ADN.Viewing.Extension.MeshData', Autodesk.ADN.Viewing.Extension.MeshData);