checkTransparent.js
3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { Vector3 } from "three";
/**
* 網格排序,根據網格與 camera 的距離,重新排序網格拓樸,讓與 camera 距離愈遠的網格拓樸排在陣列愈前面。
* 拓樸在陣列前面代表會先畫,後畫代表網格會顯示在先畫的前面(不會被蓋住),與 camera 愈近的網格愈後畫。
* 對物件本身的透明度顯示進行改善,改善透明顯示下三角網格破碎的情況
* @param {*THREE.BufferGeometry} geometry
* @param {*THREE.Matrix4} matrix 模型移動矩陣
* @param {*THREE.Matrix4} viewMatrix camera視角矩陣
*/
export const checkTransparent = (geometry, matrix, viewMatrix) => {
//camera視角矩陣的 8 9 10 元素為z軸,z軸為 camera 與 camera.lookAt 的軸向
let viewVec0 = viewMatrix.elements[8];
let viewVec1 = viewMatrix.elements[9];
let viewVec2 = viewMatrix.elements[10];
let position = geometry.getAttribute("position");
let vertexLength = position == undefined ? 0 : position.count;
if (vertexLength == 0) return;
let index = geometry.getIndex();
let faceLength = index ? index.count / 3 : Math.round(vertexLength / 3);
let TriZF = new Array(faceLength);
let faceIndex = 0;
while (faceIndex < faceLength) {
let face = getFaceIndices(geometry, faceIndex);
let vertexa = getVertexUsingIndex(geometry, face.a);
let vertexb = getVertexUsingIndex(geometry, face.b);
let vertexc = getVertexUsingIndex(geometry, face.c);
vertexa = new Vector3(vertexa.x, vertexa.y, vertexa.z);
vertexb = new Vector3(vertexb.x, vertexb.y, vertexb.z);
vertexc = new Vector3(vertexc.x, vertexc.y, vertexc.z);
if (vertexa == undefined || vertexb == undefined || vertexc == undefined) {
faceIndex++;
continue;
}
let va = vertexa.applyMatrix4(matrix);
let vb = vertexb.applyMatrix4(matrix);
let vc = vertexc.applyMatrix4(matrix);
let pt = va.add(vb).add(vc).multiplyScalar(0.333);
let Z = viewVec0 * pt.x + viewVec1 * pt.y + viewVec2 * pt.z;
TriZF[faceIndex] = {
Z: Z,
index: faceIndex,
};
faceIndex++;
}
TriZF.sort(function (a, b) {
// Z值有正負號,負值愈大代表距離離camera愈遠
return a.Z - b.Z;
});
let indices = [];
let i = 0;
while (i < TriZF.length) {
if (TriZF[i] == undefined) {
continue;
}
let face = getFaceIndices(geometry, TriZF[i].index);
indices.push(face.a, face.b, face.c);
++i;
}
geometry.setIndex(indices);
TriZF = undefined;
indices = undefined;
};
/**
* 設定網格拓樸
*/
const setIndices = (geometry) => {
let indices = geometry.getIndex();
if (indices == null) {
let position = geometry.getAttribute("position");
let vertexLength = position == undefined ? 0 : position.count;
let indices = [];
for (let id = 0; id < vertexLength; id += 3) {
indices.push(id, id + 1, id + 2);
}
if (indices.length > 0) {
geometry.setIndex(indices);
}
}
};
/**
* 取得 faceIndex 網格面的周圍頂點 index
*/
const getFaceIndices = (geometry, faceIndex) => {
setIndices(geometry);
let a, b, c;
let indices = geometry.getIndex();
a = indices.array[faceIndex * 3 + 0];
b = indices.array[faceIndex * 3 + 1];
c = indices.array[faceIndex * 3 + 2];
return { a: a, b: b, c: c };
};
/**
* 取得 index 頂點座標 x y z
*/
const getVertexUsingIndex = (geometry, index) => {
let position = geometry.getAttribute("position");
if (position == undefined) return new Vector3();
return {
x: position.getX(index),
y: position.getY(index),
z: position.getZ(index),
};
};