three-cad-viewer 2.1.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +3 -2
- package/dist/three-cad-viewer.css +12 -1
- package/dist/three-cad-viewer.esm.js +4653 -2179
- package/dist/three-cad-viewer.esm.min.js +1 -1
- package/dist/three-cad-viewer.js +4653 -2179
- package/dist/three-cad-viewer.min.js +1 -1
- package/package.json +3 -3
- package/src/_version.js +1 -1
- package/src/axes.js +1 -0
- package/src/bbox.js +6 -1
- package/src/cad_tools/measure.js +610 -526
- package/src/cad_tools/tools.js +127 -128
- package/src/cad_tools/ui.js +280 -284
- package/src/camera.js +21 -15
- package/src/clipping.js +274 -89
- package/src/display.js +206 -56
- package/src/font.js +72 -0
- package/src/fontloader/FontLoader.js +107 -140
- package/src/grid.js +90 -14
- package/src/icons.js +0 -2
- package/src/index.html +19 -8
- package/src/nestedgroup.js +115 -53
- package/src/objectgroup.js +20 -12
- package/src/slider.js +1 -1
- package/src/toolbar.js +13 -5
- package/src/treeview.js +11 -1
- package/src/viewer.js +212 -56
package/src/clipping.js
CHANGED
|
@@ -1,124 +1,309 @@
|
|
|
1
1
|
import * as THREE from "three";
|
|
2
|
+
import { ObjectGroup } from "./objectgroup.js";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const normals = [
|
|
5
|
+
new THREE.Vector3(-1, 0, 0),
|
|
6
|
+
new THREE.Vector3(0, -1, 0),
|
|
7
|
+
new THREE.Vector3(0, 0, -1),
|
|
8
|
+
];
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
const planeColors = {
|
|
11
|
+
light: [0xff0000, 0x00ff00, 0x0000ff],
|
|
12
|
+
dark: [0xff4500, 0x32cd32, 0x3b9eff],
|
|
13
|
+
};
|
|
8
14
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
const planeHelperMaterial = new THREE.MeshBasicMaterial({
|
|
16
|
+
opacity: 0.1,
|
|
17
|
+
transparent: true,
|
|
18
|
+
depthWrite: false,
|
|
19
|
+
toneMapped: false,
|
|
20
|
+
side: THREE.DoubleSide,
|
|
21
|
+
});
|
|
15
22
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
// everywhere that the back faces are visible (clipped region) the stencil
|
|
24
|
+
// buffer is incremented by 1.
|
|
25
|
+
const backStencilMaterial = new THREE.MeshBasicMaterial({
|
|
26
|
+
depthWrite: false,
|
|
27
|
+
depthTest: false,
|
|
28
|
+
colorWrite: false,
|
|
29
|
+
side: THREE.BackSide,
|
|
20
30
|
|
|
21
|
-
|
|
22
|
-
|
|
31
|
+
stencilWrite: true,
|
|
32
|
+
stencilFunc: THREE.AlwaysStencilFunc,
|
|
33
|
+
stencilFail: THREE.IncrementWrapStencilOp,
|
|
34
|
+
stencilZFail: THREE.IncrementWrapStencilOp,
|
|
35
|
+
stencilZPass: THREE.IncrementWrapStencilOp,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// everywhere that the front faces are visible the stencil
|
|
39
|
+
// buffer is decremented back to 0.
|
|
40
|
+
const frontStencilMaterial = new THREE.MeshBasicMaterial({
|
|
41
|
+
depthWrite: false,
|
|
42
|
+
depthTest: false,
|
|
43
|
+
colorWrite: false,
|
|
44
|
+
side: THREE.FrontSide,
|
|
45
|
+
|
|
46
|
+
stencilWrite: true,
|
|
47
|
+
stencilFunc: THREE.AlwaysStencilFunc,
|
|
48
|
+
stencilFail: THREE.DecrementWrapStencilOp,
|
|
49
|
+
stencilZFail: THREE.DecrementWrapStencilOp,
|
|
50
|
+
stencilZPass: THREE.DecrementWrapStencilOp,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// draw the plane everywhere that the stencil buffer != 0, which will
|
|
54
|
+
// only be in the clipped region where back faces are visible.
|
|
55
|
+
const stencilPlaneMaterial = new THREE.MeshStandardMaterial({
|
|
56
|
+
metalness: 0.3,
|
|
57
|
+
roughness: 0.65,
|
|
58
|
+
opacity: 1.0,
|
|
59
|
+
transparent: false,
|
|
60
|
+
side: THREE.DoubleSide,
|
|
61
|
+
polygonOffset: true,
|
|
62
|
+
polygonOffsetFactor: 1.0,
|
|
63
|
+
polygonOffsetUnits: 1.0,
|
|
64
|
+
|
|
65
|
+
stencilWrite: true,
|
|
66
|
+
stencilRef: 0,
|
|
67
|
+
stencilFunc: THREE.NotEqualStencilFunc,
|
|
68
|
+
stencilFail: THREE.ReplaceStencilOp,
|
|
69
|
+
stencilZFail: THREE.ReplaceStencilOp,
|
|
70
|
+
stencilZPass: THREE.ReplaceStencilOp,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
class CenteredPlane extends THREE.Plane {
|
|
74
|
+
constructor(normal, constant, center) {
|
|
75
|
+
super(normal, constant);
|
|
76
|
+
this.center = center;
|
|
77
|
+
this.setConstant(constant);
|
|
78
|
+
}
|
|
23
79
|
|
|
80
|
+
setConstant(value) {
|
|
81
|
+
this.centeredConstant = value;
|
|
82
|
+
const c = this.distanceToPoint(new THREE.Vector3(...this.center));
|
|
83
|
+
const z = this.distanceToPoint(new THREE.Vector3(0, 0, 0));
|
|
84
|
+
this.constant = z - c + value;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
class PlaneMesh extends THREE.Mesh {
|
|
89
|
+
static matrix = new THREE.Matrix4();
|
|
90
|
+
|
|
91
|
+
constructor(index, plane, center, size, material, color, type) {
|
|
92
|
+
const meshGeometry = new THREE.PlaneGeometry(2, 2);
|
|
93
|
+
meshGeometry.computeBoundingSphere();
|
|
94
|
+
material.color.set(new THREE.Color(color));
|
|
95
|
+
super(meshGeometry, material);
|
|
96
|
+
|
|
97
|
+
this.type = type;
|
|
98
|
+
this.index = index;
|
|
24
99
|
this.plane = plane;
|
|
25
100
|
this.size = size;
|
|
26
101
|
this.center = center;
|
|
27
|
-
|
|
28
|
-
const positions2 = [
|
|
29
|
-
1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1,
|
|
30
|
-
];
|
|
31
|
-
const geometry2 = new THREE.BufferGeometry();
|
|
32
|
-
geometry2.setAttribute(
|
|
33
|
-
"position",
|
|
34
|
-
new THREE.Float32BufferAttribute(positions2, 3),
|
|
35
|
-
);
|
|
36
|
-
geometry2.computeBoundingSphere();
|
|
37
|
-
|
|
38
|
-
this.planeMesh = new THREE.Mesh(
|
|
39
|
-
geometry2,
|
|
40
|
-
new THREE.MeshBasicMaterial({
|
|
41
|
-
color: color,
|
|
42
|
-
opacity: 0.05,
|
|
43
|
-
transparent: true,
|
|
44
|
-
depthWrite: false,
|
|
45
|
-
toneMapped: false,
|
|
46
|
-
}),
|
|
47
|
-
);
|
|
48
|
-
this.add(this.planeMesh);
|
|
49
102
|
}
|
|
50
103
|
|
|
51
|
-
|
|
52
|
-
|
|
104
|
+
dispose = () => {
|
|
105
|
+
this.geometry.dispose();
|
|
106
|
+
this.material.dispose();
|
|
107
|
+
for (var i = 0; i < this.children.length; i++) {
|
|
108
|
+
this.children[i].geometry.dispose();
|
|
109
|
+
this.children[i].material.dispose();
|
|
110
|
+
}
|
|
111
|
+
};
|
|
53
112
|
|
|
54
|
-
|
|
113
|
+
onAfterRender = (renderer) => {
|
|
114
|
+
if (this.type.startsWith("StencilPlane")) {
|
|
115
|
+
renderer.clearStencil();
|
|
116
|
+
}
|
|
117
|
+
};
|
|
55
118
|
|
|
56
|
-
|
|
119
|
+
// https://discourse.threejs.org/t/center-threejs-planehelper-on-geometry/48516/4
|
|
120
|
+
updateMatrixWorld(force) {
|
|
121
|
+
this.position.set(0, 0, 0);
|
|
122
|
+
this.scale.set(0.5 * this.size, 0.5 * this.size, 1);
|
|
57
123
|
|
|
58
|
-
|
|
59
|
-
this.
|
|
60
|
-
this.lookAt(this.plane.normal);
|
|
124
|
+
PlaneMesh.matrix.lookAt(this.position, this.plane.normal, this.up);
|
|
125
|
+
this.quaternion.setFromRotationMatrix(PlaneMesh.matrix);
|
|
61
126
|
|
|
62
|
-
|
|
127
|
+
this.translateZ(this.plane.constant);
|
|
128
|
+
super.updateMatrixWorld(this, force);
|
|
63
129
|
}
|
|
64
130
|
}
|
|
65
131
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
132
|
+
function createStencil(name, material, geometry, plane) {
|
|
133
|
+
material.clippingPlanes = [plane];
|
|
134
|
+
var mesh = new THREE.Mesh(geometry, material);
|
|
135
|
+
mesh.name = name;
|
|
136
|
+
return mesh;
|
|
137
|
+
}
|
|
70
138
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
139
|
+
class Clipping {
|
|
140
|
+
constructor(center, size, nestedGroup, display, theme) {
|
|
141
|
+
this.center = center;
|
|
142
|
+
this.distance = size / 2;
|
|
143
|
+
this.display = display;
|
|
144
|
+
this.theme = theme;
|
|
145
|
+
this.nestedGroup = nestedGroup;
|
|
76
146
|
|
|
77
147
|
this.clipPlanes = [];
|
|
78
|
-
|
|
79
|
-
for (var i = 0; i < 3; i++) {
|
|
80
|
-
this.clipPlanes.push(new THREE.Plane(normals[i], distance));
|
|
81
|
-
this.uiCallback(i, normals[i].toArray());
|
|
82
|
-
}
|
|
148
|
+
this.reverseClipPlanes = [];
|
|
83
149
|
|
|
84
150
|
this.planeHelpers = new THREE.Group();
|
|
85
|
-
this.planeHelpers.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
new
|
|
96
|
-
|
|
97
|
-
this.
|
|
98
|
-
center,
|
|
99
|
-
size,
|
|
100
|
-
theme === "light" ? 0x00ff00 : 0x32cd32,
|
|
101
|
-
),
|
|
102
|
-
);
|
|
103
|
-
this.planeHelpers.add(
|
|
104
|
-
new PlaneHelper(
|
|
105
|
-
2,
|
|
106
|
-
this.clipPlanes[2],
|
|
151
|
+
this.planeHelpers.name = "PlaneHelpers";
|
|
152
|
+
this.planeHelperMaterials = [];
|
|
153
|
+
this.objectColors = [];
|
|
154
|
+
this.objectColorCaps = false;
|
|
155
|
+
|
|
156
|
+
var i;
|
|
157
|
+
for (i = 0; i < 3; i++) {
|
|
158
|
+
const plane = new CenteredPlane(normals[i], this.distance, center);
|
|
159
|
+
|
|
160
|
+
this.clipPlanes.push(plane);
|
|
161
|
+
const reversePlane = new CenteredPlane(
|
|
162
|
+
normals[i].clone().negate(),
|
|
163
|
+
-this.distance,
|
|
107
164
|
center,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
165
|
+
);
|
|
166
|
+
this.reverseClipPlanes.push(reversePlane);
|
|
167
|
+
|
|
168
|
+
this.display.setNormalLabel(i, normals[i].toArray());
|
|
169
|
+
|
|
170
|
+
const material = planeHelperMaterial.clone();
|
|
171
|
+
material.opacity = (theme === "dark") ? 0.2 : 0.1;
|
|
172
|
+
|
|
173
|
+
this.planeHelperMaterials.push(material);
|
|
174
|
+
this.planeHelpers.add(
|
|
175
|
+
new PlaneMesh(
|
|
176
|
+
i,
|
|
177
|
+
plane,
|
|
178
|
+
center,
|
|
179
|
+
size,
|
|
180
|
+
material,
|
|
181
|
+
planeColors[theme][i],
|
|
182
|
+
"PlaneHelper",
|
|
183
|
+
),
|
|
184
|
+
);
|
|
185
|
+
}
|
|
112
186
|
this.planeHelpers.visible = false;
|
|
187
|
+
|
|
188
|
+
// Add clipping planes to the help planes
|
|
189
|
+
for (i = 0; i < 3; i++) {
|
|
190
|
+
const otherPlanes = this.clipPlanes.filter((_, j) => j !== i);
|
|
191
|
+
this.planeHelpers.children[i].material.clippingPlanes = otherPlanes;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/*
|
|
195
|
+
Stencils
|
|
196
|
+
*/
|
|
197
|
+
var planeMeshGroup = new THREE.Group();
|
|
198
|
+
planeMeshGroup.name = "PlaneMeshes";
|
|
199
|
+
|
|
200
|
+
for (i = 0; i < 3; i++) {
|
|
201
|
+
const plane = this.clipPlanes[i];
|
|
202
|
+
const otherPlanes = this.clipPlanes.filter((_, j) => j !== i);
|
|
203
|
+
var j = 0;
|
|
204
|
+
for (var path in nestedGroup.groups) {
|
|
205
|
+
var clippingGroup = new THREE.Group();
|
|
206
|
+
clippingGroup.name = `clipping-${i}`;
|
|
207
|
+
|
|
208
|
+
var group = nestedGroup.groups[path];
|
|
209
|
+
if (group instanceof ObjectGroup && group.subtype === "solid") {
|
|
210
|
+
this.objectColors.push(group.children[0].material.color.getHex());
|
|
211
|
+
|
|
212
|
+
clippingGroup.add(
|
|
213
|
+
createStencil(
|
|
214
|
+
`frontStencil-${i}-${j}`,
|
|
215
|
+
frontStencilMaterial.clone(),
|
|
216
|
+
group.shapeGeometry,
|
|
217
|
+
plane,
|
|
218
|
+
),
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
clippingGroup.add(
|
|
222
|
+
createStencil(
|
|
223
|
+
`backStencil-${i}-${j}`,
|
|
224
|
+
backStencilMaterial.clone(),
|
|
225
|
+
group.shapeGeometry,
|
|
226
|
+
plane,
|
|
227
|
+
),
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
group.addType(clippingGroup, `clipping-${i}`);
|
|
231
|
+
|
|
232
|
+
var planeMaterial = stencilPlaneMaterial.clone();
|
|
233
|
+
planeMaterial.color.set(new THREE.Color(planeColors[theme][i]));
|
|
234
|
+
planeMaterial.clippingPlanes = otherPlanes;
|
|
235
|
+
|
|
236
|
+
planeMeshGroup.add(
|
|
237
|
+
new PlaneMesh(
|
|
238
|
+
i,
|
|
239
|
+
plane,
|
|
240
|
+
center,
|
|
241
|
+
size,
|
|
242
|
+
planeMaterial,
|
|
243
|
+
planeColors[theme][i],
|
|
244
|
+
`StencilPlane-${i}-${j}`,
|
|
245
|
+
)
|
|
246
|
+
);
|
|
247
|
+
j++;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
nestedGroup.rootGroup.add(planeMeshGroup);
|
|
113
252
|
}
|
|
114
253
|
|
|
254
|
+
|
|
115
255
|
setConstant(index, value) {
|
|
116
|
-
this.clipPlanes[index].
|
|
256
|
+
this.clipPlanes[index].setConstant(value);
|
|
257
|
+
this.reverseClipPlanes[index].setConstant(-value);
|
|
117
258
|
}
|
|
118
259
|
|
|
119
260
|
setNormal = (index, normal) => {
|
|
120
|
-
|
|
121
|
-
this.
|
|
261
|
+
var n = normal.clone();
|
|
262
|
+
this.clipPlanes[index].normal = n;
|
|
263
|
+
this.reverseClipPlanes[index].normal = n.clone().negate();
|
|
264
|
+
this.setConstant(index, this.distance);
|
|
265
|
+
this.display.setNormalLabel(index, n.toArray());
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
getObjectColorCaps = () => {
|
|
269
|
+
return this.objectColorCaps;
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
setObjectColorCaps = (flag) => {
|
|
273
|
+
|
|
274
|
+
var pmGroup;
|
|
275
|
+
for (pmGroup of this.nestedGroup.rootGroup.children) {
|
|
276
|
+
if (pmGroup.name === "PlaneMeshes") {
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
var i = 0, j = -1;
|
|
281
|
+
const len = Object.keys(pmGroup.children).length / 3;
|
|
282
|
+
for (var group of pmGroup.children) {
|
|
283
|
+
if (i % len === 0) {
|
|
284
|
+
j++;
|
|
285
|
+
}
|
|
286
|
+
if (flag) {
|
|
287
|
+
group.material.color.set(new THREE.Color(this.objectColors[i]));
|
|
288
|
+
} else {
|
|
289
|
+
group.material.color.set(new THREE.Color(planeColors[this.theme][j]));
|
|
290
|
+
}
|
|
291
|
+
i++;
|
|
292
|
+
};
|
|
293
|
+
this.objectColorCaps = flag;
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
setVisible = (flag) => {
|
|
297
|
+
|
|
298
|
+
var pmGroup;
|
|
299
|
+
for (pmGroup of this.nestedGroup.rootGroup.children) {
|
|
300
|
+
if (pmGroup.name === "PlaneMeshes") {
|
|
301
|
+
break;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
for (var group of pmGroup.children) {
|
|
305
|
+
group.material.visible = flag;
|
|
306
|
+
};
|
|
122
307
|
};
|
|
123
308
|
}
|
|
124
309
|
|