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/nestedgroup.js
CHANGED
|
@@ -97,14 +97,16 @@ class NestedGroup {
|
|
|
97
97
|
1.0,
|
|
98
98
|
color == null ? this.edgeColor : color,
|
|
99
99
|
geomtype,
|
|
100
|
-
"edges"
|
|
100
|
+
"edges",
|
|
101
101
|
);
|
|
102
102
|
|
|
103
103
|
var edges = this._renderEdges(
|
|
104
|
-
|
|
104
|
+
edgeList.edges
|
|
105
105
|
? edgeList.edges // protocol version 2
|
|
106
|
-
: edgeList,
|
|
107
|
-
lineWidth,
|
|
106
|
+
: edgeList, // protocol version 1
|
|
107
|
+
lineWidth,
|
|
108
|
+
color,
|
|
109
|
+
state,
|
|
108
110
|
);
|
|
109
111
|
if (name) {
|
|
110
112
|
edges.name = name;
|
|
@@ -124,20 +126,24 @@ class NestedGroup {
|
|
|
124
126
|
1.0,
|
|
125
127
|
color == null ? this.edgeColor : color,
|
|
126
128
|
geomtype,
|
|
127
|
-
"vertices"
|
|
129
|
+
"vertices",
|
|
128
130
|
);
|
|
129
131
|
|
|
130
132
|
const vertex_color = color == null ? this.edgeColor : color;
|
|
131
133
|
|
|
132
134
|
let positions;
|
|
133
|
-
if (vertexList.obj_vertices) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
135
|
+
if (vertexList.obj_vertices) {
|
|
136
|
+
// protocol version 2
|
|
137
|
+
positions =
|
|
138
|
+
vertexList.obj_vertices instanceof Float32Array
|
|
139
|
+
? vertexList.obj_vertices
|
|
140
|
+
: new Float32Array(vertexList.obj_vertices);
|
|
141
|
+
} else {
|
|
142
|
+
// protocol version 1
|
|
143
|
+
positions =
|
|
144
|
+
vertexList instanceof Float32Array
|
|
145
|
+
? vertexList.flat()
|
|
146
|
+
: new Float32Array(vertexList.flat());
|
|
141
147
|
}
|
|
142
148
|
const geometry = new THREE.BufferGeometry();
|
|
143
149
|
geometry.setAttribute(
|
|
@@ -167,7 +173,20 @@ class NestedGroup {
|
|
|
167
173
|
return group;
|
|
168
174
|
}
|
|
169
175
|
|
|
170
|
-
renderShape(
|
|
176
|
+
renderShape(
|
|
177
|
+
shape,
|
|
178
|
+
color,
|
|
179
|
+
alpha,
|
|
180
|
+
renderback,
|
|
181
|
+
path,
|
|
182
|
+
name,
|
|
183
|
+
states,
|
|
184
|
+
geomtype = null,
|
|
185
|
+
subtype = null,
|
|
186
|
+
texture_data = null,
|
|
187
|
+
texture_width = null,
|
|
188
|
+
texture_height = null,
|
|
189
|
+
) {
|
|
171
190
|
const positions =
|
|
172
191
|
shape.vertices instanceof Float32Array
|
|
173
192
|
? shape.vertices
|
|
@@ -199,38 +218,74 @@ class NestedGroup {
|
|
|
199
218
|
} else if (alpha < 1.0) {
|
|
200
219
|
this.transparent = true;
|
|
201
220
|
}
|
|
202
|
-
|
|
203
|
-
shapeGeometry
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
221
|
+
|
|
222
|
+
var shapeGeometry;
|
|
223
|
+
var texture = null;
|
|
224
|
+
var frontMaterial = null;
|
|
225
|
+
|
|
226
|
+
if (texture_data != null) {
|
|
227
|
+
const url = `data:image/${texture_data.format};base64,${texture_data.data}`;
|
|
228
|
+
var img = new Image();
|
|
229
|
+
img.setAttribute("src", url);
|
|
230
|
+
shapeGeometry = new THREE.PlaneGeometry(texture_width, texture_height);
|
|
231
|
+
|
|
232
|
+
texture = new THREE.Texture(img);
|
|
233
|
+
texture.needsUpdate = true;
|
|
234
|
+
texture.colorSpace = THREE.SRGBColorSpace;
|
|
235
|
+
|
|
236
|
+
frontMaterial = new THREE.MeshBasicMaterial({
|
|
237
|
+
color: "#ffffff",
|
|
238
|
+
map: texture,
|
|
239
|
+
side: THREE.DoubleSide,
|
|
240
|
+
});
|
|
241
|
+
renderback = false;
|
|
242
|
+
} else {
|
|
243
|
+
shapeGeometry = new THREE.BufferGeometry();
|
|
244
|
+
shapeGeometry.setAttribute(
|
|
245
|
+
"position",
|
|
246
|
+
new THREE.BufferAttribute(positions, 3),
|
|
247
|
+
);
|
|
248
|
+
shapeGeometry.setAttribute(
|
|
249
|
+
"normal",
|
|
250
|
+
new THREE.BufferAttribute(normals, 3),
|
|
251
|
+
);
|
|
252
|
+
shapeGeometry.setIndex(new THREE.BufferAttribute(triangles, 1));
|
|
253
|
+
group.shapeGeometry = shapeGeometry;
|
|
254
|
+
|
|
255
|
+
// see https://stackoverflow.com/a/37651610
|
|
256
|
+
// "A common draw configuration you see is to draw all the opaque object with depth testing on,
|
|
257
|
+
// turn depth write off, then draw the transparent objects in a back to front order."
|
|
258
|
+
frontMaterial = new THREE.MeshStandardMaterial({
|
|
259
|
+
color: color,
|
|
260
|
+
metalness: this.metalness,
|
|
261
|
+
roughness: this.roughness,
|
|
262
|
+
// envMap: texture,
|
|
263
|
+
polygonOffset: true,
|
|
264
|
+
polygonOffsetFactor: 1.0,
|
|
265
|
+
polygonOffsetUnits: 1.0,
|
|
266
|
+
transparent: true,
|
|
267
|
+
opacity: this.transparent ? this.defaultOpacity * alpha : alpha,
|
|
268
|
+
// turn depth write off for transparent objects
|
|
269
|
+
depthWrite: !this.transparent,
|
|
270
|
+
// but keep depth test
|
|
271
|
+
depthTest: true,
|
|
272
|
+
clipIntersection: false,
|
|
273
|
+
side: THREE.FrontSide,
|
|
274
|
+
visible: states[0] == 1,
|
|
275
|
+
map: texture,
|
|
276
|
+
name:"frontMaterial"
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const backColor =
|
|
281
|
+
group.subtype === "solid"
|
|
282
|
+
? color
|
|
283
|
+
: new THREE.Color(
|
|
284
|
+
Math.round(Math.min(0xffffff, this.edgeColor * 1.25)),
|
|
285
|
+
);
|
|
231
286
|
|
|
232
287
|
const backMaterial = new THREE.MeshBasicMaterial({
|
|
233
|
-
color:
|
|
288
|
+
color: backColor,
|
|
234
289
|
side: THREE.BackSide,
|
|
235
290
|
polygonOffset: true,
|
|
236
291
|
polygonOffsetFactor: 1.0,
|
|
@@ -243,14 +298,15 @@ class NestedGroup {
|
|
|
243
298
|
depthTest: true,
|
|
244
299
|
clipIntersection: false,
|
|
245
300
|
visible: states[0] == 1 && (renderback || this.backVisible),
|
|
301
|
+
name: "backMaterial"
|
|
246
302
|
});
|
|
247
303
|
|
|
248
|
-
const front = new THREE.Mesh(shapeGeometry, frontMaterial);
|
|
249
|
-
front.name = name;
|
|
250
|
-
|
|
251
304
|
const back = new THREE.Mesh(shapeGeometry, backMaterial);
|
|
252
305
|
back.name = name;
|
|
253
306
|
|
|
307
|
+
const front = new THREE.Mesh(shapeGeometry, frontMaterial);
|
|
308
|
+
front.name = name;
|
|
309
|
+
|
|
254
310
|
// ensure, transparent objects will be rendered at the end
|
|
255
311
|
if (alpha < 1.0) {
|
|
256
312
|
back.renderOrder = 999;
|
|
@@ -282,7 +338,7 @@ class NestedGroup {
|
|
|
282
338
|
}
|
|
283
339
|
|
|
284
340
|
renderLoop(shapes, path, states) {
|
|
285
|
-
const _render = (shape) => {
|
|
341
|
+
const _render = (shape, texture, width, height) => {
|
|
286
342
|
var mesh;
|
|
287
343
|
switch (shape.type) {
|
|
288
344
|
case "edges":
|
|
@@ -318,6 +374,9 @@ class NestedGroup {
|
|
|
318
374
|
states[shape.id],
|
|
319
375
|
{ topo: "face", geomtype: shape.geomtype },
|
|
320
376
|
shape.subtype,
|
|
377
|
+
texture,
|
|
378
|
+
width,
|
|
379
|
+
height,
|
|
321
380
|
);
|
|
322
381
|
}
|
|
323
382
|
// support object locations
|
|
@@ -346,7 +405,11 @@ class NestedGroup {
|
|
|
346
405
|
if (shape.parts) {
|
|
347
406
|
group.add(this.renderLoop(shape, path, states));
|
|
348
407
|
} else {
|
|
349
|
-
const
|
|
408
|
+
const has_texture = shape.texture != null;
|
|
409
|
+
var texture = has_texture ? shape.texture.image : null;
|
|
410
|
+
var width = has_texture ? shape.texture.width : null;
|
|
411
|
+
var height = has_texture ? shape.texture.height : null;
|
|
412
|
+
const objectGroup = _render(shape, texture, width, height);
|
|
350
413
|
this.groups[shape.id] = objectGroup;
|
|
351
414
|
group.add(objectGroup);
|
|
352
415
|
}
|
|
@@ -369,10 +432,9 @@ class NestedGroup {
|
|
|
369
432
|
|
|
370
433
|
_traverse(func, flag) {
|
|
371
434
|
for (var path in this.groups) {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
}
|
|
435
|
+
var obj = this.groups[path];
|
|
436
|
+
if (obj instanceof ObjectGroup) {
|
|
437
|
+
obj[func](flag);
|
|
376
438
|
}
|
|
377
439
|
}
|
|
378
440
|
}
|
package/src/objectgroup.js
CHANGED
|
@@ -112,15 +112,19 @@ class ObjectGroup extends THREE.Group {
|
|
|
112
112
|
|
|
113
113
|
setMetalness(value) {
|
|
114
114
|
for (var child of this.children) {
|
|
115
|
-
child.
|
|
116
|
-
|
|
115
|
+
if (!child.name.startsWith("clipping")) {
|
|
116
|
+
child.material.metalness = value;
|
|
117
|
+
child.material.needsUpdate = true;
|
|
118
|
+
}
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
setRoughness(value) {
|
|
121
123
|
for (var child of this.children) {
|
|
122
|
-
child.
|
|
123
|
-
|
|
124
|
+
if (!child.name.startsWith("clipping")) {
|
|
125
|
+
child.material.roughness = value;
|
|
126
|
+
child.material.needsUpdate = true;
|
|
127
|
+
}
|
|
124
128
|
}
|
|
125
129
|
}
|
|
126
130
|
|
|
@@ -134,11 +138,13 @@ class ObjectGroup extends THREE.Group {
|
|
|
134
138
|
: this.alpha;
|
|
135
139
|
}
|
|
136
140
|
for (var child of this.children) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
141
|
+
if (!child.name.startsWith("clipping")){
|
|
142
|
+
// turn depth write off for transparent objects
|
|
143
|
+
child.material.depthWrite = this.alpha < 1.0 ? false : !flag;
|
|
144
|
+
// but keep depth test
|
|
145
|
+
child.material.depthTest = true;
|
|
146
|
+
child.material.needsUpdate = true;
|
|
147
|
+
}
|
|
142
148
|
}
|
|
143
149
|
}
|
|
144
150
|
|
|
@@ -193,9 +199,11 @@ class ObjectGroup extends THREE.Group {
|
|
|
193
199
|
|
|
194
200
|
setClipIntersection(flag) {
|
|
195
201
|
for (var child of this.children) {
|
|
196
|
-
child.
|
|
197
|
-
|
|
198
|
-
|
|
202
|
+
if (!child.name.startsWith("clipping")) {
|
|
203
|
+
child.material.clipIntersection = flag;
|
|
204
|
+
child.material.clipIntersection = flag;
|
|
205
|
+
child.material.clipIntersection = flag;
|
|
206
|
+
}
|
|
199
207
|
}
|
|
200
208
|
}
|
|
201
209
|
|
package/src/slider.js
CHANGED
|
@@ -91,7 +91,7 @@ class Slider {
|
|
|
91
91
|
Math.min(value, this.slider.max),
|
|
92
92
|
this.slider.min,
|
|
93
93
|
);
|
|
94
|
-
this.input.value =
|
|
94
|
+
this.input.value = Math.round(1000 * trimmed_value) / 1000;
|
|
95
95
|
this.slider.value = value;
|
|
96
96
|
this._handle(this.type, this.index, this.input.value);
|
|
97
97
|
this._notify(value, notify);
|
package/src/toolbar.js
CHANGED
|
@@ -145,12 +145,20 @@ class ClickButton extends BaseButton {
|
|
|
145
145
|
}
|
|
146
146
|
};
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
extractIdFromName = (name) => {
|
|
149
|
+
const match = "grid-";
|
|
150
|
+
const start = name.indexOf(match) + match.length;
|
|
151
|
+
const end = name.indexOf("_", start);
|
|
152
|
+
const result = name.slice(start, end);
|
|
153
|
+
return result;
|
|
154
|
+
};
|
|
155
|
+
|
|
149
156
|
handler = (e) => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
e.
|
|
153
|
-
|
|
157
|
+
const id = this.extractIdFromName(e.target.id);
|
|
158
|
+
if (this.dropdown != null && id && this.dropdown.includes(id)) {
|
|
159
|
+
const newstate = e.target.checked;
|
|
160
|
+
this.action(`grid-${id}`, newstate);
|
|
161
|
+
this.checkElems[id].checked = newstate;
|
|
154
162
|
} else if (e.target.type === "button") {
|
|
155
163
|
if (!this.state) {
|
|
156
164
|
this.clearGroup();
|
package/src/treeview.js
CHANGED
|
@@ -26,12 +26,13 @@ const States = {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
class TreeView {
|
|
29
|
-
constructor(states, tree, objectHandler, pickHandler, theme) {
|
|
29
|
+
constructor(states, tree, objectHandler, pickHandler, theme, newTreeBehavior) {
|
|
30
30
|
this.states = states;
|
|
31
31
|
this.tree = tree;
|
|
32
32
|
this.objectHandler = objectHandler;
|
|
33
33
|
this.pickHandler = pickHandler;
|
|
34
34
|
this.theme = theme;
|
|
35
|
+
this.newTreeBehavior = newTreeBehavior;
|
|
35
36
|
this.lastSelection = null;
|
|
36
37
|
|
|
37
38
|
this.setupIcons(theme);
|
|
@@ -401,10 +402,19 @@ class TreeView {
|
|
|
401
402
|
if (type == "leaf") {
|
|
402
403
|
this.updateState(node, icon_id, newState);
|
|
403
404
|
this.updateNodes(this.treeModel, icon_id);
|
|
405
|
+
if (this.newTreeBehavior && icon_id == 0) {
|
|
406
|
+
this.updateState(node, 1, newState);
|
|
407
|
+
this.updateNodes(this.treeModel, 1);
|
|
408
|
+
}
|
|
404
409
|
this.objectHandler(this.states);
|
|
405
410
|
} else if (type == "node") {
|
|
406
411
|
this.propagateChange(node, icon_id, newState);
|
|
407
412
|
this.updateNodes(this.treeModel, icon_id);
|
|
413
|
+
if (this.newTreeBehavior && icon_id == 0) {
|
|
414
|
+
this.objectHandler(this.states);
|
|
415
|
+
this.propagateChange(node, 1, newState);
|
|
416
|
+
this.updateNodes(this.treeModel, 1);
|
|
417
|
+
}
|
|
408
418
|
this.objectHandler(this.states);
|
|
409
419
|
} else {
|
|
410
420
|
console.error(`Error, unknown type '${type}'`);
|