three-cad-viewer 3.6.3 → 4.1.1
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 +266 -42
- package/dist/_version.d.ts +1 -0
- package/dist/camera/camera.d.ts +150 -0
- package/dist/camera/controls/CADOrbitControls.d.ts +91 -0
- package/dist/camera/controls/CADTrackballControls.d.ts +164 -0
- package/dist/camera/controls.d.ts +186 -0
- package/dist/core/patches.d.ts +10 -0
- package/dist/core/types.d.ts +488 -0
- package/dist/core/viewer-state.d.ts +239 -0
- package/dist/core/viewer.d.ts +1313 -0
- package/dist/index.d.ts +33 -0
- package/dist/rendering/material-factory.d.ts +131 -0
- package/dist/rendering/raycast.d.ts +111 -0
- package/dist/rendering/tree-model.d.ts +172 -0
- package/dist/scene/animation.d.ts +124 -0
- package/dist/scene/axes.d.ts +41 -0
- package/dist/scene/bbox.d.ts +57 -0
- package/dist/scene/clipping.d.ts +158 -0
- package/dist/scene/grid.d.ts +144 -0
- package/dist/scene/nestedgroup.d.ts +282 -0
- package/dist/scene/objectgroup.d.ts +262 -0
- package/dist/scene/orientation.d.ts +61 -0
- package/dist/scene/render-shape.d.ts +85 -0
- package/dist/three-cad-viewer.css +46 -2
- package/dist/three-cad-viewer.esm.js +16970 -11714
- package/dist/three-cad-viewer.esm.js.map +1 -1
- package/dist/three-cad-viewer.esm.min.js +3 -2
- package/dist/three-cad-viewer.js +16980 -11716
- package/dist/three-cad-viewer.min.js +3 -2
- package/dist/tools/cad_tools/measure.d.ts +99 -0
- package/dist/tools/cad_tools/select.d.ts +21 -0
- package/dist/tools/cad_tools/tools.d.ts +105 -0
- package/dist/tools/cad_tools/ui.d.ts +85 -0
- package/dist/tools/cad_tools/zebra.d.ts +70 -0
- package/dist/ui/display.d.ts +540 -0
- package/dist/ui/info.d.ts +64 -0
- package/dist/ui/slider.d.ts +93 -0
- package/dist/ui/toolbar.d.ts +87 -0
- package/dist/ui/treeview.d.ts +267 -0
- package/dist/utils/font.d.ts +31 -0
- package/dist/utils/gpu-tracker.d.ts +124 -0
- package/dist/utils/logger.d.ts +55 -0
- package/dist/utils/sizeof.d.ts +1 -0
- package/dist/utils/timer.d.ts +38 -0
- package/dist/utils/utils.d.ts +136 -0
- package/package.json +74 -9
- package/src/_version.ts +1 -0
- package/src/camera/camera.ts +428 -0
- package/src/camera/controls/CADOrbitControls.ts +241 -0
- package/src/camera/controls/CADTrackballControls.ts +598 -0
- package/src/camera/controls.ts +380 -0
- package/src/core/patches.ts +16 -0
- package/src/core/types.ts +597 -0
- package/src/core/viewer-state.ts +704 -0
- package/src/core/viewer.ts +4390 -0
- package/src/index.ts +128 -0
- package/src/rendering/material-factory.ts +282 -0
- package/src/rendering/raycast.ts +291 -0
- package/src/rendering/tree-model.ts +542 -0
- package/src/scene/animation.ts +342 -0
- package/src/scene/axes.ts +108 -0
- package/src/{bbox.js → scene/bbox.ts} +83 -24
- package/src/scene/clipping.ts +581 -0
- package/src/{grid.js → scene/grid.ts} +317 -117
- package/src/scene/nestedgroup.ts +1040 -0
- package/src/scene/objectgroup.ts +691 -0
- package/src/{orientation.js → scene/orientation.ts} +101 -42
- package/src/scene/render-shape.ts +600 -0
- package/src/tools/cad_tools/measure.ts +811 -0
- package/src/{cad_tools/select.js → tools/cad_tools/select.ts} +32 -21
- package/src/{cad_tools/tools.js → tools/cad_tools/tools.ts} +90 -29
- package/src/tools/cad_tools/ui.ts +454 -0
- package/src/tools/cad_tools/zebra.ts +359 -0
- package/src/types/html.d.ts +5 -0
- package/src/types/three-augmentation.d.ts +60 -0
- package/src/ui/display.ts +2290 -0
- package/src/{index.html → ui/index.html} +60 -7
- package/src/{info.js → ui/info.ts} +75 -19
- package/src/ui/slider.ts +206 -0
- package/src/ui/toolbar.ts +347 -0
- package/src/ui/treeview.ts +945 -0
- package/src/utils/font.ts +60 -0
- package/src/utils/gpu-tracker.ts +265 -0
- package/src/utils/logger.ts +92 -0
- package/src/{sizeof.js → utils/sizeof.ts} +21 -14
- package/src/utils/timer.ts +69 -0
- package/src/utils/utils.ts +433 -0
- package/src/_version.js +0 -1
- package/src/animation.js +0 -192
- package/src/axes.js +0 -67
- package/src/cad_tools/measure.js +0 -619
- package/src/cad_tools/ui.js +0 -406
- package/src/camera.js +0 -347
- package/src/clipping.js +0 -315
- package/src/controls/CameraControls.js +0 -1421
- package/src/controls.js +0 -266
- package/src/display.js +0 -1479
- package/src/font.js +0 -118
- package/src/fontloader/FontLoader.js +0 -150
- package/src/index.js +0 -10
- package/src/nestedgroup.js +0 -752
- package/src/objectgroup.js +0 -331
- package/src/patches.js +0 -33
- package/src/raycast.js +0 -237
- package/src/slider.js +0 -101
- package/src/timer.js +0 -36
- package/src/toolbar.js +0 -254
- package/src/treeview.js +0 -972
- package/src/types.js +0 -336
- package/src/utils.js +0 -191
- package/src/viewer.js +0 -3035
package/Readme.md
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
# A threejs based CAD viewer
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A CAD viewer component based on three.js. The CAD viewer can visualize low level `threejs` objects (tessellated objects)
|
|
4
|
+
|
|
5
|
+

|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
⇒ [Live Examples](https://bernhard-42.github.io/three-cad-viewer/example.html)
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
## Getting started
|
|
10
|
+
|
|
11
|
+
1. [Install yarn](https://classic.yarnpkg.com/en/docs/install) on your system (ie. `npm i -g yarn`) if not already done;
|
|
12
|
+
2. Clone the repository: `git clone https://github.com/bernhard-42/three-cad-viewer.git && cd three-cad-viewer`;
|
|
13
|
+
3. Run `yarn install` to install dependencies
|
|
14
|
+
4. Start web server: `yarn run start` and go to the page displayed in the logs (ie. `127.0.0.1:8080`)
|
|
15
|
+
5. Build project: `yarn run clean; yarn run build; yarn run docs`;
|
|
16
|
+
|
|
17
|
+
## Overview
|
|
8
18
|
|
|
9
19
|
### Shape and Shapes
|
|
10
20
|
|
|
@@ -40,14 +50,6 @@ The value 2 is reserved for nodes and shows a mixed state, i.d. some of the chil
|
|
|
40
50
|
|
|
41
51
|
For the `States` object, see [Class States](https://bernhard-42.github.io/three-cad-viewer/global.html#States)
|
|
42
52
|
|
|
43
|
-
### Getting started
|
|
44
|
-
|
|
45
|
-
1. [Install yarn](https://classic.yarnpkg.com/en/docs/install) on your system (ie. `npm i -g yarn`) if not already done;
|
|
46
|
-
2. Clone the repository: `git clone https://github.com/bernhard-42/three-cad-viewer.git && cd three-cad-viewer`;
|
|
47
|
-
3. Run `yarn install` to install dependencies
|
|
48
|
-
4. Start web server: `yarn run start` and go to the page displayed in the logs (ie. `127.0.0.1:8080`)
|
|
49
|
-
5. Build project: `yarn run clean; yarn run build; yarn run docs`;
|
|
50
|
-
|
|
51
53
|
## Skeleton:
|
|
52
54
|
|
|
53
55
|
```html
|
|
@@ -68,24 +70,24 @@ For the `States` object, see [Class States](https://bernhard-42.github.io/three-
|
|
|
68
70
|
theme: "browser",
|
|
69
71
|
pinning: true,
|
|
70
72
|
keymap: {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
73
|
+
shift: "shiftKey",
|
|
74
|
+
ctrl: "ctrlKey",
|
|
75
|
+
meta: "metaKey",
|
|
76
|
+
},
|
|
75
77
|
};
|
|
76
78
|
|
|
77
79
|
const renderOptions = {
|
|
78
80
|
ambientIntensity: 1.0,
|
|
79
81
|
directIntensity: 1.1,
|
|
80
|
-
metalness: 0.
|
|
82
|
+
metalness: 0.3,
|
|
81
83
|
roughness: 0.65,
|
|
82
84
|
edgeColor: 0x707070,
|
|
83
85
|
defaultOpacity: 0.5,
|
|
84
86
|
normalLen: 0,
|
|
85
87
|
};
|
|
86
88
|
const viewerOptions = {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
target: [0, 0, 0],
|
|
90
|
+
up: "Z",
|
|
89
91
|
};
|
|
90
92
|
|
|
91
93
|
const shapes = {
|
|
@@ -98,36 +100,40 @@ For the `States` object, see [Class States](https://bernhard-42.github.io/three-
|
|
|
98
100
|
name: "Workplane(Solid)",
|
|
99
101
|
shape: {
|
|
100
102
|
vertices: [
|
|
101
|
-
-0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5,
|
|
102
|
-
0.5,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5,
|
|
103
|
+
-0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5,
|
|
104
|
+
0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5,
|
|
105
|
+
0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5,
|
|
106
|
+
-0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5,
|
|
107
|
+
0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5,
|
|
108
|
+
0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5,
|
|
109
|
+
0.5, 0.5, 0.5,
|
|
107
110
|
],
|
|
108
111
|
triangles: [
|
|
109
|
-
1, 2, 0, 1, 3, 2, 5, 4, 6, 5, 6, 7, 11, 8, 9, 11, 10, 8, 15, 13,
|
|
110
|
-
15, 12, 14, 19, 16, 17, 19, 18, 16, 23, 21, 20, 23, 20, 22,
|
|
112
|
+
1, 2, 0, 1, 3, 2, 5, 4, 6, 5, 6, 7, 11, 8, 9, 11, 10, 8, 15, 13,
|
|
113
|
+
12, 15, 12, 14, 19, 16, 17, 19, 18, 16, 23, 21, 20, 23, 20, 22,
|
|
111
114
|
],
|
|
112
115
|
normals: [
|
|
113
|
-
-1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0,
|
|
114
|
-
1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0,
|
|
115
|
-
-
|
|
116
|
-
1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0,
|
|
117
|
-
-
|
|
118
|
-
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
|
|
116
|
+
-1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0,
|
|
117
|
+
0.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0,
|
|
118
|
+
-0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0,
|
|
119
|
+
-1.0, -0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0,
|
|
120
|
+
-0.0, 1.0, 0.0, -0.0, -0.0, -1.0, -0.0, -0.0, -1.0, -0.0, -0.0,
|
|
121
|
+
-1.0, -0.0, -0.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
|
|
122
|
+
1.0, 0.0, 0.0, 1.0,
|
|
119
123
|
],
|
|
120
124
|
edges: [
|
|
121
|
-
-0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5,
|
|
122
|
-
|
|
123
|
-
0.5, -0.5,
|
|
124
|
-
0.5,
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
-0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5,
|
|
126
|
+
0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5,
|
|
127
|
+
0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5,
|
|
128
|
+
0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5,
|
|
129
|
+
0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5,
|
|
130
|
+
0.5, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5,
|
|
131
|
+
0.5, 0.5, 0.5,
|
|
127
132
|
],
|
|
128
133
|
obj_vertices: [
|
|
129
|
-
-0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5,
|
|
130
|
-
0.5,
|
|
134
|
+
-0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5,
|
|
135
|
+
-0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
|
|
136
|
+
-0.5,
|
|
131
137
|
],
|
|
132
138
|
face_types: [0, 0, 0, 0, 0, 0],
|
|
133
139
|
edge_types: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
@@ -154,7 +160,14 @@ For the `States` object, see [Class States](https://bernhard-42.github.io/three-
|
|
|
154
160
|
name: "Group",
|
|
155
161
|
id: "/Group",
|
|
156
162
|
normal_len: 0,
|
|
157
|
-
bb: {
|
|
163
|
+
bb: {
|
|
164
|
+
xmin: -0.5,
|
|
165
|
+
xmax: 0.5,
|
|
166
|
+
ymin: -0.5,
|
|
167
|
+
ymax: 0.5,
|
|
168
|
+
zmin: -0.5,
|
|
169
|
+
zmax: 0.5,
|
|
170
|
+
},
|
|
158
171
|
};
|
|
159
172
|
|
|
160
173
|
// 1) get the container
|
|
@@ -166,9 +179,66 @@ For the `States` object, see [Class States](https://bernhard-42.github.io/three-
|
|
|
166
179
|
// 3) Create the CAD viewer
|
|
167
180
|
const viewer = new Viewer(display, viewerOptions, nc);
|
|
168
181
|
// or viewer.clear() if the viewer exists
|
|
169
|
-
|
|
182
|
+
|
|
170
183
|
// 4) Render the shapes and provide states for the navigation tree in this viewer
|
|
171
184
|
viewer.render(shapes, renderOptions, viewerOptions);
|
|
185
|
+
|
|
186
|
+
// 5) Dynamically add a second box offset by 2 units along X.
|
|
187
|
+
// addPart(parentPath, partData) builds the absolute path from the
|
|
188
|
+
// parent and the part's name: "/Group" + "/" + "Box2" = "/Group/Box2"
|
|
189
|
+
const newPart = {
|
|
190
|
+
version: 3,
|
|
191
|
+
name: "Box2",
|
|
192
|
+
type: "shapes",
|
|
193
|
+
subtype: "solid",
|
|
194
|
+
shape: {
|
|
195
|
+
vertices: [
|
|
196
|
+
1.5, -0.5, -0.5, 1.5, -0.5, 0.5, 1.5, 0.5, -0.5, 1.5, 0.5, 0.5, 2.5,
|
|
197
|
+
-0.5, -0.5, 2.5, -0.5, 0.5, 2.5, 0.5, -0.5, 2.5, 0.5, 0.5, 1.5,
|
|
198
|
+
-0.5, -0.5, 2.5, -0.5, -0.5, 1.5, -0.5, 0.5, 2.5, -0.5, 0.5, 1.5,
|
|
199
|
+
0.5, -0.5, 2.5, 0.5, -0.5, 1.5, 0.5, 0.5, 2.5, 0.5, 0.5, 1.5, -0.5,
|
|
200
|
+
-0.5, 2.5, -0.5, -0.5, 1.5, 0.5, -0.5, 2.5, 0.5, -0.5, 1.5, -0.5,
|
|
201
|
+
0.5, 2.5, -0.5, 0.5, 1.5, 0.5, 0.5, 2.5, 0.5, 0.5,
|
|
202
|
+
],
|
|
203
|
+
triangles: [
|
|
204
|
+
1, 2, 0, 1, 3, 2, 5, 4, 6, 5, 6, 7, 11, 8, 9, 11, 10, 8, 15, 13, 12,
|
|
205
|
+
15, 12, 14, 19, 16, 17, 19, 18, 16, 23, 21, 20, 23, 20, 22,
|
|
206
|
+
],
|
|
207
|
+
normals: [
|
|
208
|
+
-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
|
|
209
|
+
1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0,
|
|
210
|
+
0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1,
|
|
211
|
+
0, 0, 1, 0, 0, 1, 0, 0, 1,
|
|
212
|
+
],
|
|
213
|
+
edges: [
|
|
214
|
+
1.5, -0.5, -0.5, 1.5, -0.5, 0.5, 1.5, -0.5, 0.5, 1.5, 0.5, 0.5, 1.5,
|
|
215
|
+
0.5, -0.5, 1.5, 0.5, 0.5, 1.5, -0.5, -0.5, 1.5, 0.5, -0.5, 2.5,
|
|
216
|
+
-0.5, -0.5, 2.5, -0.5, 0.5, 2.5, -0.5, 0.5, 2.5, 0.5, 0.5, 2.5, 0.5,
|
|
217
|
+
-0.5, 2.5, 0.5, 0.5, 2.5, -0.5, -0.5, 2.5, 0.5, -0.5, 1.5, -0.5,
|
|
218
|
+
-0.5, 2.5, -0.5, -0.5, 1.5, 0.5, -0.5, 2.5, 0.5, -0.5, 1.5, -0.5,
|
|
219
|
+
0.5, 2.5, -0.5, 0.5, 1.5, 0.5, 0.5, 2.5, 0.5, 0.5,
|
|
220
|
+
],
|
|
221
|
+
obj_vertices: [
|
|
222
|
+
1.5, -0.5, 0.5, 1.5, -0.5, -0.5, 1.5, 0.5, 0.5, 1.5, 0.5, -0.5, 2.5,
|
|
223
|
+
-0.5, 0.5, 2.5, -0.5, -0.5, 2.5, 0.5, 0.5, 2.5, 0.5, -0.5,
|
|
224
|
+
],
|
|
225
|
+
face_types: [0, 0, 0, 0, 0, 0],
|
|
226
|
+
edge_types: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
227
|
+
triangles_per_face: [2, 2, 2, 2, 2, 2],
|
|
228
|
+
segments_per_edge: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
|
229
|
+
},
|
|
230
|
+
state: [1, 1],
|
|
231
|
+
color: "#5b9bd5",
|
|
232
|
+
alpha: 1.0,
|
|
233
|
+
renderback: false,
|
|
234
|
+
};
|
|
235
|
+
viewer.addPart("/Group", newPart); // creates "/Group/Box2"
|
|
236
|
+
|
|
237
|
+
// 6) Remove the part again by absolute path
|
|
238
|
+
viewer.removePart("/Group/Box2");
|
|
239
|
+
|
|
240
|
+
// 7) Update an existing part's geometry (see "Dynamic Scene Updates" below)
|
|
241
|
+
viewer.updatePart("/Group/Box2", updatedPartData);
|
|
172
242
|
</script>
|
|
173
243
|
</head>
|
|
174
244
|
|
|
@@ -178,11 +248,108 @@ For the `States` object, see [Class States](https://bernhard-42.github.io/three-
|
|
|
178
248
|
</html>
|
|
179
249
|
```
|
|
180
250
|
|
|
251
|
+
## Dynamic Scene Updates
|
|
252
|
+
|
|
253
|
+
After the initial `viewer.render()`, parts can be added, removed, or updated without re-rendering the entire scene.
|
|
254
|
+
|
|
255
|
+
### addPart / removePart
|
|
256
|
+
|
|
257
|
+
`addPart(parentPath, partData)` creates new Three.js objects (meshes, edges, clipping stencils) from the part data and inserts them into the scene graph and navigation tree. `removePart(path)` disposes the Three.js objects and removes the part from the scene.
|
|
258
|
+
|
|
259
|
+
```js
|
|
260
|
+
viewer.addPart("/Group", partData); // creates "/Group/PartName"
|
|
261
|
+
viewer.removePart("/Group/PartName");
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### updatePart
|
|
265
|
+
|
|
266
|
+
`updatePart(path, partData)` updates an existing part's geometry without tearing down and recreating the Three.js objects. When the mesh topology is unchanged (same number of vertices, triangles, and edge segments), vertex positions, normals, and edge coordinates are written directly into the existing GPU buffers — this is significantly faster than a remove/add cycle. When the topology differs (e.g. a re-tessellation changed the face or edge count), `updatePart` automatically falls back to a batched `removePart` + `addPart` so the caller does not need to handle this case.
|
|
267
|
+
|
|
268
|
+
```js
|
|
269
|
+
viewer.updatePart("/Group/PartName", updatedPartData);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Batching
|
|
273
|
+
|
|
274
|
+
Each of the three methods individually recomputes the bounding box, rebuilds clipping stencils, and (for add/remove) rebuilds the navigation tree. In a loop over N parts this becomes the dominant cost. All three methods accept an optional `{ skipBounds: true }` parameter that defers this work. Call `updateBounds()` once after the loop to perform a single recomputation for the entire batch:
|
|
275
|
+
|
|
276
|
+
```js
|
|
277
|
+
for (const part of partsToUpdate) {
|
|
278
|
+
viewer.updatePart(`/Group/${part.name}`, part, { skipBounds: true });
|
|
279
|
+
}
|
|
280
|
+
for (const part of partsToAdd) {
|
|
281
|
+
viewer.addPart("/Group", part, { skipBounds: true });
|
|
282
|
+
}
|
|
283
|
+
for (const path of pathsToRemove) {
|
|
284
|
+
viewer.removePart(path, { skipBounds: true });
|
|
285
|
+
}
|
|
286
|
+
viewer.updateBounds();
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Add, remove, and update calls can be freely mixed within a single batch.
|
|
290
|
+
|
|
291
|
+
### ensureStencilSize
|
|
292
|
+
|
|
293
|
+
`updateBounds()` rebuilds clipping stencils whenever the scene's bounding box grows beyond the region that stencils were previously built for. This rebuild is the most expensive part of the bounds update. When the maximum extent of the geometry is known upfront (e.g. the full parameter range of a slider), call `ensureStencilSize()` once after the initial render to pre-size the stencil region. All subsequent `updateBounds()` calls whose geometry stays within this region will skip the stencil rebuild entirely:
|
|
294
|
+
|
|
295
|
+
```js
|
|
296
|
+
viewer.render(shapes, renderOptions, viewerOptions);
|
|
297
|
+
|
|
298
|
+
viewer.ensureStencilSize({
|
|
299
|
+
xmin: -200, xmax: 200,
|
|
300
|
+
ymin: -200, ymax: 200,
|
|
301
|
+
zmin: 0, zmax: 300,
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// All updates within these bounds are now stencil-rebuild-free
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Keyboard Shortcuts
|
|
308
|
+
|
|
309
|
+
The keymap serves two purposes:
|
|
310
|
+
|
|
311
|
+
- **Modifier keys** (`shift`, `ctrl`, `meta`, `alt`) remap which physical modifier key is used for mouse interactions (e.g. shift-click to isolate, ctrl-rotate). Values are DOM event properties like `"shiftKey"`, `"ctrlKey"`, `"metaKey"`, `"altKey"`.
|
|
312
|
+
- **Action shortcuts** map single keys (with or without Shift) to toolbar buttons, camera presets, tab switches, and animation control. Only plain keys are supported — Ctrl/Alt/Meta combinations are reserved for modifier-based mouse interactions.
|
|
313
|
+
|
|
314
|
+
Click on the viewer to give it focus, then press shortcut keys to trigger actions. Button tooltips show `[key]` suffixes when shortcuts are configured.
|
|
315
|
+
|
|
316
|
+
The default keymap:
|
|
317
|
+
|
|
318
|
+
```javascript
|
|
319
|
+
keymap: {
|
|
320
|
+
// Modifier keys (remap physical keys for mouse interactions)
|
|
321
|
+
shift: "shiftKey", ctrl: "ctrlKey", meta: "metaKey", alt: "altKey",
|
|
322
|
+
// Toggle buttons
|
|
323
|
+
axes: "a", axes0: "A", grid: "g", gridxy: "G",
|
|
324
|
+
perspective: "p", transparent: "t", blackedges: "b",
|
|
325
|
+
explode: "x", zscale: "L",
|
|
326
|
+
distance: "D", properties: "P", select: "S",
|
|
327
|
+
// Execute buttons
|
|
328
|
+
reset: "R", resize: "r",
|
|
329
|
+
iso: "0", front: "1", rear: "2", top: "3", bottom: "4", left: "5", right: "6",
|
|
330
|
+
// Help
|
|
331
|
+
help: "h",
|
|
332
|
+
// Animation
|
|
333
|
+
play: " ", stop: "Escape",
|
|
334
|
+
// Tab selection
|
|
335
|
+
tree: "T", clip: "C", material: "M", zebra: "Z",
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Pass a partial keymap to override individual bindings — unspecified keys keep their defaults:
|
|
340
|
+
|
|
341
|
+
```javascript
|
|
342
|
+
const displayOptions = {
|
|
343
|
+
keymap: { axes: "q", reset: "!" }, // only these two change
|
|
344
|
+
};
|
|
345
|
+
```
|
|
346
|
+
|
|
181
347
|
## Examples
|
|
182
348
|
|
|
183
349
|
To understand the data format, a look at the simple 1 unit sized box might be helpful:
|
|
184
350
|
|
|
185
351
|
- [1 unit sized box source code](https://github.com/bernhard-42/three-cad-viewer/blob/master/examples/box1.js)
|
|
352
|
+
- [addPart / removePart demo](https://github.com/bernhard-42/three-cad-viewer/blob/master/example-add-remove-part.html) — dynamically adding and removing shapes and subtrees after render
|
|
186
353
|
|
|
187
354
|
## APIs of Viewer, Display, Camera and Controls
|
|
188
355
|
|
|
@@ -190,6 +357,63 @@ To understand the data format, a look at the simple 1 unit sized box might be he
|
|
|
190
357
|
|
|
191
358
|
Back to [Github repo](https://github.com/bernhard-42/three-cad-viewer)
|
|
192
359
|
|
|
360
|
+
## Utilities
|
|
361
|
+
|
|
362
|
+
### Logger
|
|
363
|
+
|
|
364
|
+
Control log verbosity with the built-in logger:
|
|
365
|
+
|
|
366
|
+
```javascript
|
|
367
|
+
import { logger } from "three-cad-viewer";
|
|
368
|
+
|
|
369
|
+
// Default level is "warn" (only warnings and errors shown)
|
|
370
|
+
logger.setLevel("debug"); // Enable all logging
|
|
371
|
+
logger.setLevel("info"); // Info, warnings, and errors
|
|
372
|
+
logger.setLevel("warn"); // Warnings and errors (default)
|
|
373
|
+
logger.setLevel("error"); // Only errors
|
|
374
|
+
logger.setLevel("silent"); // Disable all logging
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### GPU Resource Tracker
|
|
378
|
+
|
|
379
|
+
Track GPU resource allocation to inspect current state or detect memory leaks:
|
|
380
|
+
|
|
381
|
+
```javascript
|
|
382
|
+
import { gpuTracker } from "three-cad-viewer";
|
|
383
|
+
|
|
384
|
+
// Check resource counts at any time
|
|
385
|
+
console.log(gpuTracker.summary);
|
|
386
|
+
// { geometry: 5, material: 10, texture: 1, total: 16 }
|
|
387
|
+
|
|
388
|
+
// Log details of allocated resources
|
|
389
|
+
gpuTracker.details();
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
For detailed allocation info with stack traces:
|
|
393
|
+
|
|
394
|
+
```javascript
|
|
395
|
+
// Enable debug mode BEFORE creating the viewer
|
|
396
|
+
gpuTracker.enableDebug();
|
|
397
|
+
|
|
398
|
+
const display = new Display(container, displayOptions);
|
|
399
|
+
const viewer = new Viewer(display, viewerOptions, nc);
|
|
400
|
+
viewer.render(shapes, renderOptions, viewerOptions);
|
|
401
|
+
|
|
402
|
+
// Inspect current allocations
|
|
403
|
+
gpuTracker.details();
|
|
404
|
+
// [1] geometry: BufferGeometry (shape) for /Assembly/Part1
|
|
405
|
+
// Created at: 1234.56ms
|
|
406
|
+
// Stack:
|
|
407
|
+
// at NestedGroup.renderShape (nestedgroup.ts:425)
|
|
408
|
+
// ...
|
|
409
|
+
|
|
410
|
+
// After disposal, any remaining resources are potential leaks
|
|
411
|
+
viewer.dispose();
|
|
412
|
+
gpuTracker.details();
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
The tracker is also available globally in the browser console as `window.tcv_gpu`.
|
|
416
|
+
|
|
193
417
|
## Development
|
|
194
418
|
|
|
195
419
|
Run a web server in watch and debug mode
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const version: string;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
import type { Vector3Tuple, QuaternionTuple } from "three";
|
|
3
|
+
import type { UpDirection } from "../core/types";
|
|
4
|
+
type CameraDirection = "iso" | "front" | "rear" | "left" | "right" | "top" | "bottom";
|
|
5
|
+
type UpMode = "y_up" | "z_up" | "legacy";
|
|
6
|
+
/**
|
|
7
|
+
* Manages orthographic and perspective cameras for the viewer.
|
|
8
|
+
*
|
|
9
|
+
* Camera wraps both camera types and provides:
|
|
10
|
+
* - Seamless switching between orthographic and perspective
|
|
11
|
+
* - Preset positions (iso, front, top, etc.)
|
|
12
|
+
* - Support for Y-up and Z-up coordinate systems
|
|
13
|
+
* - Synchronized position/zoom across camera types
|
|
14
|
+
*
|
|
15
|
+
* ## Coordinate Systems
|
|
16
|
+
* Supports three modes via `up` parameter:
|
|
17
|
+
* - `"Y"`: Y-up (Fusion 360 compatible)
|
|
18
|
+
* - `"Z"`: Z-up (FreeCAD, OnShape compatible)
|
|
19
|
+
* - Legacy Z-up mode
|
|
20
|
+
*
|
|
21
|
+
* @internal - This is an internal class used by Viewer
|
|
22
|
+
*/
|
|
23
|
+
declare class Camera {
|
|
24
|
+
private static readonly DISTANCE_FACTOR;
|
|
25
|
+
target: THREE.Vector3;
|
|
26
|
+
ortho: boolean;
|
|
27
|
+
up: UpMode;
|
|
28
|
+
yaxis: THREE.Vector3;
|
|
29
|
+
zaxis: THREE.Vector3;
|
|
30
|
+
camera_distance: number;
|
|
31
|
+
pCamera: THREE.PerspectiveCamera;
|
|
32
|
+
oCamera: THREE.OrthographicCamera;
|
|
33
|
+
camera: THREE.PerspectiveCamera | THREE.OrthographicCamera;
|
|
34
|
+
/**
|
|
35
|
+
* Create a combined camera (orthographic and perspective).
|
|
36
|
+
* @param width - canvas width.
|
|
37
|
+
* @param height - canvas height.
|
|
38
|
+
* @param distance - distance from the lookAt point.
|
|
39
|
+
* @param target - target (Vector3) to look at.
|
|
40
|
+
* @param ortho - flag whether the initial camera should be orthographic.
|
|
41
|
+
* @param up - Z or Y to define whether Z or Y direction is camera up.
|
|
42
|
+
*/
|
|
43
|
+
constructor(width: number, height: number, distance: number, target: Vector3Tuple, ortho: boolean, up: UpDirection);
|
|
44
|
+
/**
|
|
45
|
+
* Update the far clipping plane for both cameras.
|
|
46
|
+
* @param distance - The new bounding radius to base the far plane on.
|
|
47
|
+
*/
|
|
48
|
+
updateFarPlane(distance: number): void;
|
|
49
|
+
/**
|
|
50
|
+
* Recalculate camera_distance from a new bounding radius.
|
|
51
|
+
* Uses the same factor as the constructor so that zoom 1.0 frames the scene.
|
|
52
|
+
* @param distance - The new bounding radius (bb_radius).
|
|
53
|
+
*/
|
|
54
|
+
updateCameraDistance(distance: number): void;
|
|
55
|
+
/**
|
|
56
|
+
* Remove assets.
|
|
57
|
+
*/
|
|
58
|
+
dispose(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Get the current camera.
|
|
61
|
+
* @returns Camera object.
|
|
62
|
+
*/
|
|
63
|
+
getCamera(): THREE.PerspectiveCamera | THREE.OrthographicCamera;
|
|
64
|
+
/**
|
|
65
|
+
* Set the lookAt point for the camera to the provided target.
|
|
66
|
+
*/
|
|
67
|
+
lookAtTarget(): void;
|
|
68
|
+
/**
|
|
69
|
+
* Update current camera's projection matrix.
|
|
70
|
+
*/
|
|
71
|
+
updateProjectionMatrix(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Switch between orthographic and perspective camera.
|
|
74
|
+
* @param ortho_flag - true for orthographic camera, else perspective camera.
|
|
75
|
+
*/
|
|
76
|
+
switchCamera(ortho_flag: boolean): void;
|
|
77
|
+
/**
|
|
78
|
+
* Calculate projected size for orthographic camera.
|
|
79
|
+
* @param frustum - View frustum size.
|
|
80
|
+
* @param aspect - Viewer aspect ratio (width / height).
|
|
81
|
+
* @returns Width and height [w, h] for the orthographic camera.
|
|
82
|
+
*/
|
|
83
|
+
projectSize(frustum: number, aspect: number): [number, number];
|
|
84
|
+
/**
|
|
85
|
+
* Setup the current camera.
|
|
86
|
+
* @param relative - flag whether the position is a relative (e.g. [1,1,1] for iso) or absolute point.
|
|
87
|
+
* @param position - the camera position (relative or absolute).
|
|
88
|
+
* @param quaternion - the camera rotation expressed by a quaternion.
|
|
89
|
+
* @param zoom - zoom value.
|
|
90
|
+
*/
|
|
91
|
+
setupCamera(relative: boolean, position?: THREE.Vector3 | null, quaternion?: THREE.Quaternion | null, zoom?: number | null): void;
|
|
92
|
+
/**
|
|
93
|
+
* Move the camera to a given preset.
|
|
94
|
+
* @param dir - can be "iso", "top", "bottom", "front", "rear", "left", "right"
|
|
95
|
+
*/
|
|
96
|
+
presetCamera(dir: CameraDirection, zoom?: number | null): void;
|
|
97
|
+
/**
|
|
98
|
+
* Return current zoom value.
|
|
99
|
+
* @returns zoom value.
|
|
100
|
+
*/
|
|
101
|
+
getZoom(): number;
|
|
102
|
+
/**
|
|
103
|
+
* Set zoom value.
|
|
104
|
+
* @param val - float zoom value.
|
|
105
|
+
*/
|
|
106
|
+
setZoom(val: number): void;
|
|
107
|
+
/**
|
|
108
|
+
* Get the current camera position.
|
|
109
|
+
* @returns camera position.
|
|
110
|
+
*/
|
|
111
|
+
getPosition(): THREE.Vector3;
|
|
112
|
+
/**
|
|
113
|
+
* Set camera position.
|
|
114
|
+
* @param position - position as 3 dim Array [x,y,z] or as Vector3.
|
|
115
|
+
* @param relative - flag whether the position is a relative (e.g. [1,1,1] for iso) or absolute point.
|
|
116
|
+
*/
|
|
117
|
+
setPosition(position: Vector3Tuple | THREE.Vector3, relative: boolean): void;
|
|
118
|
+
/**
|
|
119
|
+
* Get the current camera quaternion.
|
|
120
|
+
* @returns camera quaternion.
|
|
121
|
+
*/
|
|
122
|
+
getQuaternion(): THREE.Quaternion;
|
|
123
|
+
/**
|
|
124
|
+
* Set camera quaternion.
|
|
125
|
+
* @param quaternion - quaternion as 4 dim Array or as Quaternion.
|
|
126
|
+
*/
|
|
127
|
+
setQuaternion(quaternion: QuaternionTuple | THREE.Quaternion): void;
|
|
128
|
+
/**
|
|
129
|
+
* Get the current camera rotation.
|
|
130
|
+
* @returns camera rotation.
|
|
131
|
+
*/
|
|
132
|
+
getRotation(): THREE.Euler;
|
|
133
|
+
/**
|
|
134
|
+
* Get the visible area dimensions at the target plane.
|
|
135
|
+
* @returns The visible width and height.
|
|
136
|
+
*/
|
|
137
|
+
getVisibleArea(): {
|
|
138
|
+
width: number;
|
|
139
|
+
height: number;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Update camera dimensions when viewport size changes.
|
|
143
|
+
* @param distance - Distance used for orthographic frustum calculation.
|
|
144
|
+
* @param width - New viewport width in pixels.
|
|
145
|
+
* @param height - New viewport height in pixels.
|
|
146
|
+
*/
|
|
147
|
+
changeDimensions(distance: number, width: number, height: number): void;
|
|
148
|
+
}
|
|
149
|
+
export { Camera };
|
|
150
|
+
export type { CameraDirection, UpMode };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CADOrbitControls - Extended OrbitControls for CAD applications
|
|
3
|
+
*
|
|
4
|
+
* Adds:
|
|
5
|
+
* - Public rotateLeft/rotateUp methods for programmatic rotation
|
|
6
|
+
* - Quaternion-based saveState/reset
|
|
7
|
+
* - Modifier key rotation restrictions (ctrl: vertical only, meta: horizontal only)
|
|
8
|
+
*
|
|
9
|
+
* Internal OrbitControls methods/properties used (see three-augmentation.d.ts):
|
|
10
|
+
* - _onMouseDown: Replaced to customize modifier key behavior (shift=pan, ctrl/meta=rotate with axis lock)
|
|
11
|
+
* - _handleMouseDownRotate: Called to initialize rotation state
|
|
12
|
+
* - _handleMouseDownDolly: Called to initialize dolly/zoom state
|
|
13
|
+
* - _handleMouseDownPan: Called to initialize pan state
|
|
14
|
+
* - _sphericalDelta: Modified in _rotateLeft/_rotateUp overrides to implement axis locking
|
|
15
|
+
* - state: Set to track current interaction mode (ROTATE/DOLLY/PAN/NONE)
|
|
16
|
+
*/
|
|
17
|
+
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
|
18
|
+
import { Quaternion, Vector3, Camera } from "three";
|
|
19
|
+
declare class CADOrbitControls extends OrbitControls {
|
|
20
|
+
quaternion0: Quaternion;
|
|
21
|
+
private _horizontalRotate;
|
|
22
|
+
private _verticalRotate;
|
|
23
|
+
private _onCADPointerDown?;
|
|
24
|
+
private _onCADPointerUp?;
|
|
25
|
+
state: number;
|
|
26
|
+
_sphericalDelta: {
|
|
27
|
+
theta: number;
|
|
28
|
+
phi: number;
|
|
29
|
+
};
|
|
30
|
+
zoom0: number;
|
|
31
|
+
target0: Vector3;
|
|
32
|
+
position0: Vector3;
|
|
33
|
+
_onMouseDown: (event: MouseEvent) => void;
|
|
34
|
+
_handleMouseDownRotate: (event: MouseEvent) => void;
|
|
35
|
+
_handleMouseDownDolly: (event: MouseEvent) => void;
|
|
36
|
+
_handleMouseDownPan: (event: MouseEvent) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Constructs CAD-enhanced orbit controls.
|
|
39
|
+
*
|
|
40
|
+
* @param object - The camera to control.
|
|
41
|
+
* @param domElement - The HTML element for event listeners.
|
|
42
|
+
*/
|
|
43
|
+
constructor(object: Camera, domElement?: HTMLElement | null);
|
|
44
|
+
/**
|
|
45
|
+
* Handle pointer down to check modifier keys for rotation restriction.
|
|
46
|
+
*/
|
|
47
|
+
private _handleCADPointerDown;
|
|
48
|
+
/**
|
|
49
|
+
* Handle pointer up to reset rotation restrictions.
|
|
50
|
+
*/
|
|
51
|
+
private _handleCADPointerUp;
|
|
52
|
+
/**
|
|
53
|
+
* Override dispose to clean up our event listeners.
|
|
54
|
+
*/
|
|
55
|
+
dispose(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Custom mouse down handler for rotation restriction via modifier keys.
|
|
58
|
+
*
|
|
59
|
+
* Original OrbitControls: ctrl/meta/shift + left mouse = pan
|
|
60
|
+
* CADOrbitControls: ctrl = vertical rotate only, meta = horizontal rotate only,
|
|
61
|
+
* shift = pan (via KeyMapper)
|
|
62
|
+
*/
|
|
63
|
+
private _handleMouseDown;
|
|
64
|
+
/**
|
|
65
|
+
* Override _rotateLeft to respect horizontal rotation restriction.
|
|
66
|
+
*/
|
|
67
|
+
_rotateLeft(angle: number): void;
|
|
68
|
+
/**
|
|
69
|
+
* Override _rotateUp to respect vertical rotation restriction.
|
|
70
|
+
*/
|
|
71
|
+
_rotateUp(angle: number): void;
|
|
72
|
+
/**
|
|
73
|
+
* Save the current state including quaternion.
|
|
74
|
+
*/
|
|
75
|
+
saveState(): void;
|
|
76
|
+
/**
|
|
77
|
+
* Reset to saved state including quaternion.
|
|
78
|
+
*/
|
|
79
|
+
reset(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Rotate camera left (around the up axis).
|
|
82
|
+
* Programmatic rotation bypasses modifier key restrictions.
|
|
83
|
+
*/
|
|
84
|
+
rotateLeft(angle: number): void;
|
|
85
|
+
/**
|
|
86
|
+
* Rotate camera up (around the right axis).
|
|
87
|
+
* Programmatic rotation bypasses modifier key restrictions.
|
|
88
|
+
*/
|
|
89
|
+
rotateUp(angle: number): void;
|
|
90
|
+
}
|
|
91
|
+
export { CADOrbitControls };
|