iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 20
0
Modern Web

在Three.js探索CAD的奧秘系列 第 20

Day 20 : 網格頂點的平均法向量

前言

網格頂點的平均法向量,是指一個網格頂點,找尋鄰近的三角網格面,將所有面的法向量進行相加,再取單位向量的結果。

https://ithelp.ithome.com.tw/upload/images/20180108/20107175jE5ZrwwYLX.png
八個面的平均法向量

使用點拓樸關係找鄰近的面

首先將上回的 getVertices 函數進行改寫,我們改將 vertices 存入拓樸的vertex以夾帶拓樸資訊。

vertices.push(intersected.object.topology.vertex[ids[i]]);

再將 getNearest 函數改寫,距離資訊要使用拓樸網格資訊中的vector3資料。

distance = vertices[i].vector3.distanceTo(point);

然後建立一個 pointNormal 函數用來計算法向量,我們使用點拓樸中的faceIDs資訊,再由 reduce 來計算總和,其中我們透過 THREE.Vector3 的 add 函數來進行每個法向量的加總,最後再執行向量的正規化。

Editor.prototype.pointNormal = function (point) {
    var self = this;
    var i = 0;
    var intersected = self.viewer.intersects[0];
    return point.faceIDs.reduce((accumlator, currentValue, currentIndex, array) => {
        // 取得每個面的法向量
        var normal = intersected.object.geometry.faces[currentValue].normal;
        //法向量的加總
        return accumlator.add(normal);
    }, new THREE.Vector3()).normalize(); //最後需要將結果正規化
};

最後延續上回的程式在 mouseDown 內執行 pointNormal 就完成了平均法向量的計算。

var normal = self.pointNormal(nearest);

畫出法向量

首先給法向量一個係數,決定向量要畫的長度。

var scalarNormal = normal.multiplyScalar(3);

接著給予兩個點座標,一個是頂點本身,一個是拷貝頂點後加上法向量的新座標,

var geometry = new THREE.Geometry();
geometry.vertices.push(nearest.vector3);
geometry.vertices.push(new THREE.Vector3().copy(nearest.vector3).add(scalarNormal));

最後給予 LineBasicMaterial 材質並建立 THREE.Line 並加到場景就完成這次的畫法向量範例了,結果如下圖。

var material = new THREE.LineBasicMaterial({ color: 0xffff00 });
var line = new THREE.Line(geometry, material);
line.skip = true;
self.viewer.scene.add(line);
self.viewer.meshs.push(line);

https://i.imgur.com/3cUTXcL.gif
點選網格點並計算平均法向量

範例模型下載位置

https://github.com/QQBoxy/threecad/tree/master/models

線上範例

https://qqboxy.github.io/threecad/public/example16.html

範例原始碼

https://github.com/QQBoxy/threecad/blob/master/client/example16/Editor.js

後記

這次教大家如何找尋網格頂點的平均法向量,在建立與網格頂點有關的編輯工具時,經常會需要計算網格頂點的法向量,在撰寫CAD軟體時也是一個普遍需要用到的功能函式。


上一篇
Day 19 : 點選網格頂點
下一篇
Day 21 : 模型塗抹效果
系列文
在Three.js探索CAD的奧秘30

尚未有邦友留言

立即登入留言