iT邦幫忙

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

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

Day 15 : 即時高亮網格

前言

即時的高亮(Highlight)滑鼠經過的網格,可以幫助設計者清楚的理解2D轉換到3D場景中所選擇的面,提供更直覺的編輯環境在CAD軟體中也是相當重要的一環。

顏色翻轉

為了高亮網格需要將網格原有的顏色翻轉為相反的色彩,在本文中使用了 color 這個顏色套件,安裝語法如下:

npm install color --save-dev

首先在 Viewer.js 模組內 import 顏色函式。

import QixColor from 'color';

接著到 add 函數中加入隨機生成base色與高亮色,其中高亮色是使用 QixColor 匯入base的rgb顏色,再利用 negate 函數反轉顏色,再轉回Hex碼創建新的THREE.Color。

var baseColor = new THREE.Color(Math.floor(Math.random() * 16777215));
var highlightColor = new THREE.Color(
    QixColor.rgb(
        baseColor.r * 255, baseColor.g * 255, baseColor.b * 255
    ).negate().rgbNumber()
);

最後放進mesh物件內供後續使用。

mesh.baseColor = baseColor;
mesh.highlightColor = highlightColor;

在進行高亮網格之前,除了準備好顏色以外,還需要修改 MeshPhongMaterial 材質的顏色配置,將原本的 color 設定刪除改為使用 vertexColors 進行渲染,並賦予它 FaceColors 的參數表示我們要採用的是face的資訊。

//材質設定
var material = new THREE.MeshPhongMaterial({
    vertexColors: THREE.FaceColors
});

即時高亮網格

首先在 Viewer 宣告一個函數用來存放當前觸碰的網格。

this.intersected = null;

然後在 Viewer 自訂一個 checkHighlight 函數,使用射線法取得網格資料。

var baseColor = null;
var highlightColor = null;
self.raycaster.setFromCamera(self.mouse, self.camera);
self.intersects = self.raycaster.intersectObjects(self.scene.children);

接著再判斷觸碰網格時,若網格已經有被觸碰過,則恢復前一個觸碰的網格顏色,並且無論如何都將當前觸碰的網格上色。值得注意的是,由於網格物件可能有複數個,所以前一個網格與當前的網格都需要加入 colorsNeedUpdate 來告知 Three.js 需要進行網格顏色更新的動作。

//恢復顏色
if (self.intersected) {
    baseColor = self.intersected.object.baseColor;
    self.intersected.face.color.copy(baseColor);
    self.intersected.object.geometry.colorsNeedUpdate = true; //前一個物件也要網格更新
}
//新上色
self.intersected = self.intersects[0];
highlightColor = self.intersected.object.highlightColor;
self.intersected.face.color.copy(highlightColor);
self.intersected.object.geometry.colorsNeedUpdate = true; //下一個物件的網格更新

最後若沒有接觸任何網格了,則將網格顏色恢復為原本的色彩,下圖是本範例的效果。

if (self.intersected) {
    baseColor = self.intersected.object.baseColor;
    self.intersected.face.color.copy(baseColor);
    self.intersected.object.geometry.colorsNeedUpdate = true;
}
self.intersected = null;

https://i.imgur.com/OF2m72y.gif
多個物件高亮網格效果

範例原始碼

https://github.com/QQBoxy/threecad/blob/master/client/example11/Viewer.js

後記

本次的高亮顏色不能使用bufferGeometry,而必須使用geometry才有變更效果,筆者在網路上也沒有找到有人使用 MeshPhongMaterial 的材質範例,本次也算是順便測試了此材質也能使用 vertexColors 進行渲染,有興趣的朋友不妨試試看不同材質的效果如何。


上一篇
Day 14 : 提升設計環境
下一篇
Day 16 : 簡單網格變形
系列文
在Three.js探索CAD的奧秘30

尚未有邦友留言

立即登入留言