DAY 18
0
Modern Web

## 所見即得調整模型

``````this.currentObject = null;
this.preFace = new THREE.Face3();
this.preMouse = new THREE.Vector2();
this.preVertices = [];
``````

``````Editor.prototype.mouseDown = function (viewer) {
var self = this;
var intersected = viewer.intersects[0];
self.enable = true;
self.viewer = viewer;
self.preFace.copy(intersected.face);
self.currentObject = viewer.meshs.find((mesh) => (intersected.object.id === mesh.id));
self.preMouse.copy(self.viewer.mouse);

var point = [self.preFace.a, self.preFace.b, self.preFace.c];
self.preVertices = [];
var vid = 0;
for (var v = 0; v < point.length; v++) {
vid = point[v];
var vertex = new THREE.Vector3();
vertex.copy(self.currentObject.geometry.vertices[vid]);
self.preVertices.push(vertex);
}
};
``````

``````Viewer.prototype.animate = function () {
var self = this;

//...

self.action();
};
``````

Editor 中的 action 函數為了完成所見即得的功能，需要即時的更新顯示網格點座標，但是要注意到不需要立刻重新計算網格向量，因為我們只是要暫時的顯示而已。在這裡我們是使用滑鼠拖動的距離作為變形強度係數，達成拖拉時會有即時變形的效果。

``````Editor.prototype.action = function () {
var self = this;
if(!self.enable) return;

var distance = self.preMouse.distanceTo(self.viewer.mouse) * 10;

var geometry = self.currentObject.geometry;
var topology = self.currentObject.topology;

var normal = self.preFace.normal;
var point = [self.preFace.a, self.preFace.b, self.preFace.c];

var vid = 0;
for (var v = 0; v < point.length; v++) {
vid = point[v];

var x = self.preVertices[v].x + normal.x * distance;
var y = self.preVertices[v].y + normal.y * distance;
var z = self.preVertices[v].z + normal.z * distance;

geometry.vertices[vid] = new THREE.Vector3(x, y, z);
topology.vertex[vid].vector3 = new THREE.Vector3(x, y, z);
}
//更新模型資訊
geometry.verticesNeedUpdate = true;
geometry.elementsNeedUpdate = true;
};
``````

``````Editor.prototype.mouseUp = function (viewer) {
var self = this;
if(!self.enable) return;
self.enable = false;

var geometry = self.currentObject.geometry;
var topology = self.currentObject.topology;
var point = [self.preFace.a, self.preFace.b, self.preFace.c];

var faceIDs = [];

var vid = 0;
for (var v = 0; v < point.length; v++) {
vid = point[v];
faceIDs.push(...topology.vertex[vid].faceIDs);
}

//過濾重複的面
faceIDs = faceIDs.filter(function (face, index, arr) {
return arr.indexOf(face) === index;
});

//重新計算面的法向量
for (var i = 0; i < faceIDs.length; i++) {
var id = faceIDs[i];
var cb = new THREE.Vector3();
var ab = new THREE.Vector3();
var vA = geometry.vertices[geometry.faces[id].a];
var vB = geometry.vertices[geometry.faces[id].b];
var vC = geometry.vertices[geometry.faces[id].c];
cb.subVectors(vC, vB);
ab.subVectors(vA, vB);
cb.cross(ab);
geometry.faces[id].normal.copy(cb.normalize());
}
geometry.normalsNeedUpdate = true;
self.preVertices = [];
};
``````

## 範例模型下載位置

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

## 線上範例

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

## 範例原始碼

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