-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
/
WireframeGeometry.js
147 lines (83 loc) · 2.93 KB
/
WireframeGeometry.js
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import { BufferGeometry } from '../core/BufferGeometry.js';
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
import { Vector3 } from '../math/Vector3.js';
class WireframeGeometry extends BufferGeometry {
constructor( geometry = null ) {
super();
this.type = 'WireframeGeometry';
this.parameters = {
geometry: geometry
};
if ( geometry !== null ) {
// buffer
const vertices = [];
const edges = new Set();
// helper variables
const start = new Vector3();
const end = new Vector3();
if ( geometry.index !== null ) {
// indexed BufferGeometry
const position = geometry.attributes.position;
const indices = geometry.index;
let groups = geometry.groups;
if ( groups.length === 0 ) {
groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
}
// create a data structure that contains all edges without duplicates
for ( let o = 0, ol = groups.length; o < ol; ++ o ) {
const group = groups[ o ];
const groupStart = group.start;
const groupCount = group.count;
for ( let i = groupStart, l = ( groupStart + groupCount ); i < l; i += 3 ) {
for ( let j = 0; j < 3; j ++ ) {
const index1 = indices.getX( i + j );
const index2 = indices.getX( i + ( j + 1 ) % 3 );
start.fromBufferAttribute( position, index1 );
end.fromBufferAttribute( position, index2 );
if ( isUniqueEdge( start, end, edges ) === true ) {
vertices.push( start.x, start.y, start.z );
vertices.push( end.x, end.y, end.z );
}
}
}
}
} else {
// non-indexed BufferGeometry
const position = geometry.attributes.position;
for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
for ( let j = 0; j < 3; j ++ ) {
// three edges per triangle, an edge is represented as (index1, index2)
// e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
const index1 = 3 * i + j;
const index2 = 3 * i + ( ( j + 1 ) % 3 );
start.fromBufferAttribute( position, index1 );
end.fromBufferAttribute( position, index2 );
if ( isUniqueEdge( start, end, edges ) === true ) {
vertices.push( start.x, start.y, start.z );
vertices.push( end.x, end.y, end.z );
}
}
}
}
// build geometry
this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
}
}
copy( source ) {
super.copy( source );
this.parameters = Object.assign( {}, source.parameters );
return this;
}
}
function isUniqueEdge( start, end, edges ) {
const hash1 = `${start.x},${start.y},${start.z}-${end.x},${end.y},${end.z}`;
const hash2 = `${end.x},${end.y},${end.z}-${start.x},${start.y},${start.z}`; // coincident edge
if ( edges.has( hash1 ) === true || edges.has( hash2 ) === true ) {
return false;
} else {
edges.add( hash1 );
edges.add( hash2 );
return true;
}
}
export { WireframeGeometry };