@nice2dev/ui-3d 1.1.0 → 1.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/dist/cjs/collaborative/collaborativeScene.js +16 -8
- package/dist/cjs/collaborative/collaborativeScene.js.map +1 -1
- package/dist/cjs/core/i18n.js +3 -3
- package/dist/cjs/dance/DanceBridge.js +65 -30
- package/dist/cjs/dance/DanceBridge.js.map +1 -1
- package/dist/cjs/dance/DanceScoreEngine.js +37 -23
- package/dist/cjs/dance/DanceScoreEngine.js.map +1 -1
- package/dist/cjs/dance/PoseDetector.js +92 -49
- package/dist/cjs/dance/PoseDetector.js.map +1 -1
- package/dist/cjs/material/NiceMaterialEditor.js +134 -91
- package/dist/cjs/material/NiceMaterialEditor.js.map +1 -1
- package/dist/cjs/material/materialEditorUtils.js +86 -55
- package/dist/cjs/material/materialEditorUtils.js.map +1 -1
- package/dist/cjs/model/ModelEditor.js +16 -14
- package/dist/cjs/model/ModelEditor.js.map +1 -1
- package/dist/cjs/model/ModelEditorLeftPanel.js +21 -15
- package/dist/cjs/model/ModelEditorLeftPanel.js.map +1 -1
- package/dist/cjs/model/ModelEditorMenuBar.js +23 -10
- package/dist/cjs/model/ModelEditorMenuBar.js.map +1 -1
- package/dist/cjs/model/ModelEditorRightPanel.js +32 -27
- package/dist/cjs/model/ModelEditorRightPanel.js.map +1 -1
- package/dist/cjs/model/ModelEditorSubComponents.js +20 -20
- package/dist/cjs/model/ModelEditorSubComponents.js.map +1 -1
- package/dist/cjs/model/ModelEditorTimeline.js +12 -11
- package/dist/cjs/model/ModelEditorTimeline.js.map +1 -1
- package/dist/cjs/model/ModelEditorToolbar.js +5 -5
- package/dist/cjs/model/ModelEditorToolbar.js.map +1 -1
- package/dist/cjs/model/ModelEditorViewport.js +12 -8
- package/dist/cjs/model/ModelEditorViewport.js.map +1 -1
- package/dist/cjs/model/ModelViewer.js +16 -15
- package/dist/cjs/model/ModelViewer.js.map +1 -1
- package/dist/cjs/model/NiceArmatureEditor.js +53 -30
- package/dist/cjs/model/NiceArmatureEditor.js.map +1 -1
- package/dist/cjs/model/NiceMorphTargetEditor.js +51 -30
- package/dist/cjs/model/NiceMorphTargetEditor.js.map +1 -1
- package/dist/cjs/model/NiceOctree.js +62 -37
- package/dist/cjs/model/NiceOctree.js.map +1 -1
- package/dist/cjs/model/NicePhysicsSimulation.js +74 -36
- package/dist/cjs/model/NicePhysicsSimulation.js.map +1 -1
- package/dist/cjs/model/NiceProceduralGeometry.js +101 -31
- package/dist/cjs/model/NiceProceduralGeometry.js.map +1 -1
- package/dist/cjs/model/NiceTerrainEditor.js +88 -38
- package/dist/cjs/model/NiceTerrainEditor.js.map +1 -1
- package/dist/cjs/model/NiceWeightPainter.js +46 -24
- package/dist/cjs/model/NiceWeightPainter.js.map +1 -1
- package/dist/cjs/model/NiceXRPreview.js +89 -43
- package/dist/cjs/model/NiceXRPreview.js.map +1 -1
- package/dist/cjs/model/cadModeUtils.js +2 -2
- package/dist/cjs/model/cadModeUtils.js.map +1 -1
- package/dist/cjs/model/editorShortcuts.js +69 -35
- package/dist/cjs/model/editorShortcuts.js.map +1 -1
- package/dist/cjs/model/modelEditorTypes.js +56 -52
- package/dist/cjs/model/modelEditorTypes.js.map +1 -1
- package/dist/cjs/model/modelEditorUtils.js +356 -131
- package/dist/cjs/model/modelEditorUtils.js.map +1 -1
- package/dist/cjs/model/simsModeUtils.js +819 -74
- package/dist/cjs/model/simsModeUtils.js.map +1 -1
- package/dist/cjs/model/useModelEditor.js +501 -394
- package/dist/cjs/model/useModelEditor.js.map +1 -1
- package/dist/cjs/model/useModelViewer.js +117 -86
- package/dist/cjs/model/useModelViewer.js.map +1 -1
- package/dist/cjs/particle/NiceParticleEditor.js +126 -69
- package/dist/cjs/particle/NiceParticleEditor.js.map +1 -1
- package/dist/cjs/particle/particleEditorUtils.js +64 -27
- package/dist/cjs/particle/particleEditorUtils.js.map +1 -1
- package/dist/cjs/rendering/NiceCascadedShadows.js +35 -23
- package/dist/cjs/rendering/NiceCascadedShadows.js.map +1 -1
- package/dist/cjs/rendering/NiceRenderExport.js +26 -12
- package/dist/cjs/rendering/NiceRenderExport.js.map +1 -1
- package/dist/cjs/rendering/NiceSSAO.js +28 -23
- package/dist/cjs/rendering/NiceSSAO.js.map +1 -1
- package/dist/cjs/rendering/NiceSSR.js +22 -18
- package/dist/cjs/rendering/NiceSSR.js.map +1 -1
- package/dist/cjs/rendering/NiceWebGPURenderer.js +60 -37
- package/dist/cjs/rendering/NiceWebGPURenderer.js.map +1 -1
- package/dist/cjs/ui/dist/NiceErrorBoundary-D75yr_WE.js +572 -0
- package/dist/cjs/ui/dist/NiceErrorBoundary-D75yr_WE.js.map +1 -0
- package/dist/cjs/ui/dist/NiceForm-CKoJA6NG.js +4979 -0
- package/dist/cjs/ui/dist/NiceForm-CKoJA6NG.js.map +1 -0
- package/dist/cjs/ui/dist/NiceModal-1QX7NhyH.js +98 -0
- package/dist/cjs/ui/dist/NiceModal-1QX7NhyH.js.map +1 -0
- package/dist/cjs/ui/dist/NiceModuleLifecyclePanel-CMrPbSw9.js +5244 -0
- package/dist/cjs/ui/dist/NiceModuleLifecyclePanel-CMrPbSw9.js.map +1 -0
- package/dist/cjs/ui/dist/NicePagination-DbE-uOkl.js +174 -0
- package/dist/cjs/ui/dist/NicePagination-DbE-uOkl.js.map +1 -0
- package/dist/cjs/ui/dist/NicePinCodeInput-B8cI8zu8.js +10459 -0
- package/dist/cjs/ui/dist/NicePinCodeInput-B8cI8zu8.js.map +1 -0
- package/dist/cjs/ui/dist/NiceSavedQueryPanel-CZ5bYOe_.js +6313 -0
- package/dist/cjs/ui/dist/NiceSavedQueryPanel-CZ5bYOe_.js.map +1 -0
- package/dist/cjs/ui/dist/NiceTabs-DzLHzwuA.js +1639 -0
- package/dist/cjs/ui/dist/NiceTabs-DzLHzwuA.js.map +1 -0
- package/dist/cjs/ui/dist/NiceWindow-DeC83yfE.js +807 -0
- package/dist/cjs/ui/dist/NiceWindow-DeC83yfE.js.map +1 -0
- package/dist/cjs/ui/dist/charts-BAS21jkC.js +3833 -0
- package/dist/cjs/ui/dist/charts-BAS21jkC.js.map +1 -0
- package/dist/cjs/ui/dist/core-Da43q-pO.js +11683 -0
- package/dist/cjs/ui/dist/core-Da43q-pO.js.map +1 -0
- package/dist/cjs/ui/dist/index-pAuGTbuB.js +28876 -0
- package/dist/cjs/ui/dist/index-pAuGTbuB.js.map +1 -0
- package/dist/cjs/uv/NiceUVEditor.js +115 -86
- package/dist/cjs/uv/NiceUVEditor.js.map +1 -1
- package/dist/cjs/uv/uvEditorUtils.js +41 -23
- package/dist/cjs/uv/uvEditorUtils.js.map +1 -1
- package/dist/esm/collaborative/collaborativeScene.js +16 -8
- package/dist/esm/collaborative/collaborativeScene.js.map +1 -1
- package/dist/esm/dance/DanceBridge.js +55 -20
- package/dist/esm/dance/DanceBridge.js.map +1 -1
- package/dist/esm/dance/DanceScoreEngine.js +29 -15
- package/dist/esm/dance/DanceScoreEngine.js.map +1 -1
- package/dist/esm/dance/PoseDetector.js +73 -30
- package/dist/esm/dance/PoseDetector.js.map +1 -1
- package/dist/esm/material/NiceMaterialEditor.js +115 -72
- package/dist/esm/material/NiceMaterialEditor.js.map +1 -1
- package/dist/esm/material/materialEditorUtils.js +86 -55
- package/dist/esm/material/materialEditorUtils.js.map +1 -1
- package/dist/esm/model/ModelEditor.js +16 -14
- package/dist/esm/model/ModelEditor.js.map +1 -1
- package/dist/esm/model/ModelEditorLeftPanel.js +21 -15
- package/dist/esm/model/ModelEditorLeftPanel.js.map +1 -1
- package/dist/esm/model/ModelEditorMenuBar.js +23 -10
- package/dist/esm/model/ModelEditorMenuBar.js.map +1 -1
- package/dist/esm/model/ModelEditorRightPanel.js +32 -27
- package/dist/esm/model/ModelEditorRightPanel.js.map +1 -1
- package/dist/esm/model/ModelEditorSubComponents.js +17 -17
- package/dist/esm/model/ModelEditorSubComponents.js.map +1 -1
- package/dist/esm/model/ModelEditorTimeline.js +12 -11
- package/dist/esm/model/ModelEditorTimeline.js.map +1 -1
- package/dist/esm/model/ModelEditorToolbar.js +5 -5
- package/dist/esm/model/ModelEditorToolbar.js.map +1 -1
- package/dist/esm/model/ModelEditorViewport.js +12 -8
- package/dist/esm/model/ModelEditorViewport.js.map +1 -1
- package/dist/esm/model/ModelViewer.js +8 -7
- package/dist/esm/model/ModelViewer.js.map +1 -1
- package/dist/esm/model/NiceArmatureEditor.js +36 -13
- package/dist/esm/model/NiceArmatureEditor.js.map +1 -1
- package/dist/esm/model/NiceMorphTargetEditor.js +34 -13
- package/dist/esm/model/NiceMorphTargetEditor.js.map +1 -1
- package/dist/esm/model/NiceOctree.js +47 -22
- package/dist/esm/model/NiceOctree.js.map +1 -1
- package/dist/esm/model/NicePhysicsSimulation.js +51 -13
- package/dist/esm/model/NicePhysicsSimulation.js.map +1 -1
- package/dist/esm/model/NiceProceduralGeometry.js +94 -24
- package/dist/esm/model/NiceProceduralGeometry.js.map +1 -1
- package/dist/esm/model/NiceTerrainEditor.js +70 -20
- package/dist/esm/model/NiceTerrainEditor.js.map +1 -1
- package/dist/esm/model/NiceWeightPainter.js +33 -11
- package/dist/esm/model/NiceWeightPainter.js.map +1 -1
- package/dist/esm/model/NiceXRPreview.js +72 -26
- package/dist/esm/model/NiceXRPreview.js.map +1 -1
- package/dist/esm/model/cadModeUtils.js +2 -2
- package/dist/esm/model/cadModeUtils.js.map +1 -1
- package/dist/esm/model/editorShortcuts.js +69 -35
- package/dist/esm/model/editorShortcuts.js.map +1 -1
- package/dist/esm/model/modelEditorTypes.js +56 -52
- package/dist/esm/model/modelEditorTypes.js.map +1 -1
- package/dist/esm/model/modelEditorUtils.js +356 -131
- package/dist/esm/model/modelEditorUtils.js.map +1 -1
- package/dist/esm/model/simsModeUtils.js +819 -74
- package/dist/esm/model/simsModeUtils.js.map +1 -1
- package/dist/esm/model/useModelEditor.js +384 -277
- package/dist/esm/model/useModelEditor.js.map +1 -1
- package/dist/esm/model/useModelViewer.js +56 -25
- package/dist/esm/model/useModelViewer.js.map +1 -1
- package/dist/esm/particle/NiceParticleEditor.js +116 -59
- package/dist/esm/particle/NiceParticleEditor.js.map +1 -1
- package/dist/esm/particle/particleEditorUtils.js +64 -27
- package/dist/esm/particle/particleEditorUtils.js.map +1 -1
- package/dist/esm/rendering/NiceCascadedShadows.js +24 -12
- package/dist/esm/rendering/NiceCascadedShadows.js.map +1 -1
- package/dist/esm/rendering/NiceRenderExport.js +22 -8
- package/dist/esm/rendering/NiceRenderExport.js.map +1 -1
- package/dist/esm/rendering/NiceSSAO.js +11 -6
- package/dist/esm/rendering/NiceSSAO.js.map +1 -1
- package/dist/esm/rendering/NiceSSR.js +9 -5
- package/dist/esm/rendering/NiceSSR.js.map +1 -1
- package/dist/esm/rendering/NiceWebGPURenderer.js +40 -17
- package/dist/esm/rendering/NiceWebGPURenderer.js.map +1 -1
- package/dist/esm/ui/dist/NiceErrorBoundary-D75yr_WE.js +563 -0
- package/dist/esm/ui/dist/NiceErrorBoundary-D75yr_WE.js.map +1 -0
- package/dist/esm/ui/dist/NiceForm-CKoJA6NG.js +4960 -0
- package/dist/esm/ui/dist/NiceForm-CKoJA6NG.js.map +1 -0
- package/dist/esm/ui/dist/NiceModal-1QX7NhyH.js +96 -0
- package/dist/esm/ui/dist/NiceModal-1QX7NhyH.js.map +1 -0
- package/dist/esm/ui/dist/NiceModuleLifecyclePanel-CMrPbSw9.js +5201 -0
- package/dist/esm/ui/dist/NiceModuleLifecyclePanel-CMrPbSw9.js.map +1 -0
- package/dist/esm/ui/dist/NicePagination-DbE-uOkl.js +172 -0
- package/dist/esm/ui/dist/NicePagination-DbE-uOkl.js.map +1 -0
- package/dist/esm/ui/dist/NicePinCodeInput-B8cI8zu8.js +10408 -0
- package/dist/esm/ui/dist/NicePinCodeInput-B8cI8zu8.js.map +1 -0
- package/dist/esm/ui/dist/NiceSavedQueryPanel-CZ5bYOe_.js +6296 -0
- package/dist/esm/ui/dist/NiceSavedQueryPanel-CZ5bYOe_.js.map +1 -0
- package/dist/esm/ui/dist/NiceTabs-DzLHzwuA.js +1630 -0
- package/dist/esm/ui/dist/NiceTabs-DzLHzwuA.js.map +1 -0
- package/dist/esm/ui/dist/NiceWindow-DeC83yfE.js +796 -0
- package/dist/esm/ui/dist/NiceWindow-DeC83yfE.js.map +1 -0
- package/dist/esm/ui/dist/charts-BAS21jkC.js +3809 -0
- package/dist/esm/ui/dist/charts-BAS21jkC.js.map +1 -0
- package/dist/esm/ui/dist/core-Da43q-pO.js +11502 -0
- package/dist/esm/ui/dist/core-Da43q-pO.js.map +1 -0
- package/dist/esm/ui/dist/index-pAuGTbuB.js +28792 -0
- package/dist/esm/ui/dist/index-pAuGTbuB.js.map +1 -0
- package/dist/esm/uv/NiceUVEditor.js +91 -62
- package/dist/esm/uv/NiceUVEditor.js.map +1 -1
- package/dist/esm/uv/uvEditorUtils.js +41 -23
- package/dist/esm/uv/uvEditorUtils.js.map +1 -1
- package/package.json +2 -2
|
@@ -46,16 +46,18 @@ class UndoRedoStack {
|
|
|
46
46
|
}
|
|
47
47
|
undo() {
|
|
48
48
|
const action = this.undoStack.pop();
|
|
49
|
-
if (!action)
|
|
49
|
+
if (!action) {
|
|
50
50
|
return null;
|
|
51
|
+
}
|
|
51
52
|
action.undo();
|
|
52
53
|
this.redoStack.push(action);
|
|
53
54
|
return action.label;
|
|
54
55
|
}
|
|
55
56
|
redo() {
|
|
56
57
|
const action = this.redoStack.pop();
|
|
57
|
-
if (!action)
|
|
58
|
+
if (!action) {
|
|
58
59
|
return null;
|
|
60
|
+
}
|
|
59
61
|
action.redo();
|
|
60
62
|
this.undoStack.push(action);
|
|
61
63
|
return action.label;
|
|
@@ -88,11 +90,13 @@ const DEFAULT_LOD_LEVELS = [
|
|
|
88
90
|
* Returns a new geometry with reduced vertex count.
|
|
89
91
|
*/
|
|
90
92
|
function decimateGeometry(geometry, ratio) {
|
|
91
|
-
if (ratio >= 1.0)
|
|
93
|
+
if (ratio >= 1.0) {
|
|
92
94
|
return geometry.clone();
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
}
|
|
96
|
+
const posAttr = geometry.getAttribute('position');
|
|
97
|
+
if (!posAttr) {
|
|
95
98
|
return geometry.clone();
|
|
99
|
+
}
|
|
96
100
|
const positions = Array.from(posAttr.array);
|
|
97
101
|
const vertexCount = posAttr.count;
|
|
98
102
|
const targetCount = Math.max(3, Math.floor(vertexCount * ratio));
|
|
@@ -151,7 +155,7 @@ function decimateGeometry(geometry, ratio) {
|
|
|
151
155
|
}
|
|
152
156
|
}
|
|
153
157
|
const result = new THREE__namespace.BufferGeometry();
|
|
154
|
-
result.setAttribute(
|
|
158
|
+
result.setAttribute('position', new THREE__namespace.BufferAttribute(newPositions, 3));
|
|
155
159
|
result.setIndex(newIndices);
|
|
156
160
|
result.computeVertexNormals();
|
|
157
161
|
return result;
|
|
@@ -161,7 +165,7 @@ function decimateGeometry(geometry, ratio) {
|
|
|
161
165
|
*/
|
|
162
166
|
function generateLOD(mesh, levels = DEFAULT_LOD_LEVELS) {
|
|
163
167
|
const lod = new THREE__namespace.LOD();
|
|
164
|
-
lod.name = mesh.name +
|
|
168
|
+
lod.name = mesh.name + '_LOD';
|
|
165
169
|
lod.position.copy(mesh.position);
|
|
166
170
|
lod.rotation.copy(mesh.rotation);
|
|
167
171
|
lod.scale.copy(mesh.scale);
|
|
@@ -179,44 +183,233 @@ function generateLOD(mesh, levels = DEFAULT_LOD_LEVELS) {
|
|
|
179
183
|
}
|
|
180
184
|
const PBR_PRESETS = [
|
|
181
185
|
// Metals
|
|
182
|
-
{ name:
|
|
183
|
-
{
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
{
|
|
189
|
-
|
|
186
|
+
{ name: 'Gold', category: 'Metal', params: { color: 0xffd700, metalness: 1.0, roughness: 0.15 } },
|
|
187
|
+
{
|
|
188
|
+
name: 'Silver',
|
|
189
|
+
category: 'Metal',
|
|
190
|
+
params: { color: 0xc0c0c0, metalness: 1.0, roughness: 0.1 },
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: 'Copper',
|
|
194
|
+
category: 'Metal',
|
|
195
|
+
params: { color: 0xb87333, metalness: 1.0, roughness: 0.25 },
|
|
196
|
+
},
|
|
197
|
+
{ name: 'Iron', category: 'Metal', params: { color: 0x808080, metalness: 0.95, roughness: 0.6 } },
|
|
198
|
+
{
|
|
199
|
+
name: 'Brushed Steel',
|
|
200
|
+
category: 'Metal',
|
|
201
|
+
params: { color: 0xa0a0a0, metalness: 0.95, roughness: 0.4 },
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
name: 'Chrome',
|
|
205
|
+
category: 'Metal',
|
|
206
|
+
params: { color: 0xdddddd, metalness: 1.0, roughness: 0.02 },
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: 'Bronze',
|
|
210
|
+
category: 'Metal',
|
|
211
|
+
params: { color: 0xcd7f32, metalness: 0.9, roughness: 0.35 },
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
name: 'Aluminum',
|
|
215
|
+
category: 'Metal',
|
|
216
|
+
params: { color: 0xd6d6d6, metalness: 0.85, roughness: 0.2 },
|
|
217
|
+
},
|
|
190
218
|
// Non-metals
|
|
191
|
-
{
|
|
192
|
-
|
|
193
|
-
|
|
219
|
+
{
|
|
220
|
+
name: 'Plastic (White)',
|
|
221
|
+
category: 'Plastic',
|
|
222
|
+
params: { color: 0xf0f0f0, metalness: 0.0, roughness: 0.3 },
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
name: 'Plastic (Red)',
|
|
226
|
+
category: 'Plastic',
|
|
227
|
+
params: { color: 0xcc2222, metalness: 0.0, roughness: 0.35 },
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
name: 'Rubber',
|
|
231
|
+
category: 'Plastic',
|
|
232
|
+
params: { color: 0x333333, metalness: 0.0, roughness: 0.9 },
|
|
233
|
+
},
|
|
194
234
|
// Glass
|
|
195
|
-
{
|
|
196
|
-
|
|
197
|
-
|
|
235
|
+
{
|
|
236
|
+
name: 'Clear Glass',
|
|
237
|
+
category: 'Glass',
|
|
238
|
+
params: {
|
|
239
|
+
color: 0xffffff,
|
|
240
|
+
metalness: 0.0,
|
|
241
|
+
roughness: 0.0,
|
|
242
|
+
opacity: 0.15,
|
|
243
|
+
transparent: true,
|
|
244
|
+
ior: 1.5,
|
|
245
|
+
transmission: 0.95,
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
name: 'Frosted Glass',
|
|
250
|
+
category: 'Glass',
|
|
251
|
+
params: {
|
|
252
|
+
color: 0xeeeeff,
|
|
253
|
+
metalness: 0.0,
|
|
254
|
+
roughness: 0.5,
|
|
255
|
+
opacity: 0.3,
|
|
256
|
+
transparent: true,
|
|
257
|
+
ior: 1.5,
|
|
258
|
+
transmission: 0.7,
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
name: 'Tinted Glass',
|
|
263
|
+
category: 'Glass',
|
|
264
|
+
params: {
|
|
265
|
+
color: 0x224488,
|
|
266
|
+
metalness: 0.0,
|
|
267
|
+
roughness: 0.05,
|
|
268
|
+
opacity: 0.3,
|
|
269
|
+
transparent: true,
|
|
270
|
+
ior: 1.5,
|
|
271
|
+
transmission: 0.8,
|
|
272
|
+
},
|
|
273
|
+
},
|
|
198
274
|
// Natural
|
|
199
|
-
{
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
{
|
|
275
|
+
{
|
|
276
|
+
name: 'Wood (Light)',
|
|
277
|
+
category: 'Natural',
|
|
278
|
+
params: { color: 0xc19a6b, metalness: 0.0, roughness: 0.7 },
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
name: 'Wood (Dark)',
|
|
282
|
+
category: 'Natural',
|
|
283
|
+
params: { color: 0x5c3317, metalness: 0.0, roughness: 0.65 },
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
name: 'Stone',
|
|
287
|
+
category: 'Natural',
|
|
288
|
+
params: { color: 0x888888, metalness: 0.0, roughness: 0.85 },
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
name: 'Marble',
|
|
292
|
+
category: 'Natural',
|
|
293
|
+
params: { color: 0xf0ece0, metalness: 0.0, roughness: 0.15 },
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
name: 'Clay',
|
|
297
|
+
category: 'Natural',
|
|
298
|
+
params: { color: 0xb5651d, metalness: 0.0, roughness: 0.8 },
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
name: 'Concrete',
|
|
302
|
+
category: 'Natural',
|
|
303
|
+
params: { color: 0x999999, metalness: 0.0, roughness: 0.95 },
|
|
304
|
+
},
|
|
205
305
|
// Fabric
|
|
206
|
-
{
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
306
|
+
{
|
|
307
|
+
name: 'Cotton (White)',
|
|
308
|
+
category: 'Fabric',
|
|
309
|
+
params: {
|
|
310
|
+
color: 0xf5f5dc,
|
|
311
|
+
metalness: 0.0,
|
|
312
|
+
roughness: 0.9,
|
|
313
|
+
sheen: 0.5,
|
|
314
|
+
sheenRoughness: 0.8,
|
|
315
|
+
sheenColor: 0xffffff,
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
name: 'Silk',
|
|
320
|
+
category: 'Fabric',
|
|
321
|
+
params: {
|
|
322
|
+
color: 0xe3dac9,
|
|
323
|
+
metalness: 0.0,
|
|
324
|
+
roughness: 0.3,
|
|
325
|
+
sheen: 1.0,
|
|
326
|
+
sheenRoughness: 0.3,
|
|
327
|
+
sheenColor: 0xffeedd,
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
name: 'Velvet',
|
|
332
|
+
category: 'Fabric',
|
|
333
|
+
params: {
|
|
334
|
+
color: 0x800020,
|
|
335
|
+
metalness: 0.0,
|
|
336
|
+
roughness: 0.95,
|
|
337
|
+
sheen: 0.9,
|
|
338
|
+
sheenRoughness: 0.9,
|
|
339
|
+
sheenColor: 0xff4060,
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
name: 'Leather',
|
|
344
|
+
category: 'Fabric',
|
|
345
|
+
params: { color: 0x553322, metalness: 0.0, roughness: 0.6 },
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
name: 'Denim',
|
|
349
|
+
category: 'Fabric',
|
|
350
|
+
params: { color: 0x3b5998, metalness: 0.0, roughness: 0.85 },
|
|
351
|
+
},
|
|
211
352
|
// Skin
|
|
212
|
-
{
|
|
213
|
-
|
|
214
|
-
|
|
353
|
+
{
|
|
354
|
+
name: 'Skin (Light)',
|
|
355
|
+
category: 'Skin',
|
|
356
|
+
params: { color: 0xffdbac, metalness: 0.0, roughness: 0.55 },
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
name: 'Skin (Medium)',
|
|
360
|
+
category: 'Skin',
|
|
361
|
+
params: { color: 0xc68642, metalness: 0.0, roughness: 0.5 },
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
name: 'Skin (Dark)',
|
|
365
|
+
category: 'Skin',
|
|
366
|
+
params: { color: 0x8d5524, metalness: 0.0, roughness: 0.5 },
|
|
367
|
+
},
|
|
215
368
|
// Special
|
|
216
|
-
{
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
369
|
+
{
|
|
370
|
+
name: 'Car Paint',
|
|
371
|
+
category: 'Special',
|
|
372
|
+
params: {
|
|
373
|
+
color: 0xcc0000,
|
|
374
|
+
metalness: 0.5,
|
|
375
|
+
roughness: 0.15,
|
|
376
|
+
clearcoat: 1.0,
|
|
377
|
+
clearcoatRoughness: 0.05,
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
name: 'Emissive (Blue)',
|
|
382
|
+
category: 'Special',
|
|
383
|
+
params: {
|
|
384
|
+
color: 0x111111,
|
|
385
|
+
metalness: 0.0,
|
|
386
|
+
roughness: 0.5,
|
|
387
|
+
emissive: 0x0088ff,
|
|
388
|
+
emissiveIntensity: 2.0,
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
name: 'Emissive (Orange)',
|
|
393
|
+
category: 'Special',
|
|
394
|
+
params: {
|
|
395
|
+
color: 0x111111,
|
|
396
|
+
metalness: 0.0,
|
|
397
|
+
roughness: 0.5,
|
|
398
|
+
emissive: 0xff6600,
|
|
399
|
+
emissiveIntensity: 2.0,
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
name: 'Neon',
|
|
404
|
+
category: 'Special',
|
|
405
|
+
params: {
|
|
406
|
+
color: 0x000000,
|
|
407
|
+
metalness: 0.0,
|
|
408
|
+
roughness: 0.1,
|
|
409
|
+
emissive: 0x00ff88,
|
|
410
|
+
emissiveIntensity: 5.0,
|
|
411
|
+
},
|
|
412
|
+
},
|
|
220
413
|
];
|
|
221
414
|
/**
|
|
222
415
|
* Apply a PBR preset to a MeshStandardMaterial or MeshPhysicalMaterial.
|
|
@@ -230,39 +423,52 @@ function applyPBRPreset(material, preset) {
|
|
|
230
423
|
material.color.setHex(p.color);
|
|
231
424
|
material.metalness = p.metalness;
|
|
232
425
|
material.roughness = p.roughness;
|
|
233
|
-
if (p.emissive != null)
|
|
426
|
+
if (p.emissive != null) {
|
|
234
427
|
material.emissive.setHex(p.emissive);
|
|
235
|
-
|
|
428
|
+
}
|
|
429
|
+
if (p.emissiveIntensity != null) {
|
|
236
430
|
material.emissiveIntensity = p.emissiveIntensity;
|
|
237
|
-
|
|
431
|
+
}
|
|
432
|
+
if (p.opacity != null) {
|
|
238
433
|
material.opacity = p.opacity;
|
|
434
|
+
}
|
|
239
435
|
material.transparent = (_a = p.transparent) !== null && _a !== void 0 ? _a : false;
|
|
240
|
-
if (p.clearcoat != null)
|
|
436
|
+
if (p.clearcoat != null) {
|
|
241
437
|
material.clearcoat = p.clearcoat;
|
|
242
|
-
|
|
438
|
+
}
|
|
439
|
+
if (p.clearcoatRoughness != null) {
|
|
243
440
|
material.clearcoatRoughness = p.clearcoatRoughness;
|
|
244
|
-
|
|
441
|
+
}
|
|
442
|
+
if (p.ior != null) {
|
|
245
443
|
material.ior = p.ior;
|
|
246
|
-
|
|
444
|
+
}
|
|
445
|
+
if (p.transmission != null) {
|
|
247
446
|
material.transmission = p.transmission;
|
|
248
|
-
|
|
447
|
+
}
|
|
448
|
+
if (p.sheen != null) {
|
|
249
449
|
material.sheen = p.sheen;
|
|
250
|
-
|
|
450
|
+
}
|
|
451
|
+
if (p.sheenRoughness != null) {
|
|
251
452
|
material.sheenRoughness = p.sheenRoughness;
|
|
252
|
-
|
|
453
|
+
}
|
|
454
|
+
if (p.sheenColor != null) {
|
|
253
455
|
material.sheenColor.setHex(p.sheenColor);
|
|
456
|
+
}
|
|
254
457
|
material.needsUpdate = true;
|
|
255
458
|
}
|
|
256
459
|
else if (material instanceof THREE__namespace.MeshStandardMaterial && !needsPhysical) {
|
|
257
460
|
material.color.setHex(p.color);
|
|
258
461
|
material.metalness = p.metalness;
|
|
259
462
|
material.roughness = p.roughness;
|
|
260
|
-
if (p.emissive != null)
|
|
463
|
+
if (p.emissive != null) {
|
|
261
464
|
material.emissive.setHex(p.emissive);
|
|
262
|
-
|
|
465
|
+
}
|
|
466
|
+
if (p.emissiveIntensity != null) {
|
|
263
467
|
material.emissiveIntensity = p.emissiveIntensity;
|
|
264
|
-
|
|
468
|
+
}
|
|
469
|
+
if (p.opacity != null) {
|
|
265
470
|
material.opacity = p.opacity;
|
|
471
|
+
}
|
|
266
472
|
material.transparent = (_b = p.transparent) !== null && _b !== void 0 ? _b : false;
|
|
267
473
|
material.needsUpdate = true;
|
|
268
474
|
}
|
|
@@ -299,10 +505,10 @@ function convertToInstanced(parent) {
|
|
|
299
505
|
var _a;
|
|
300
506
|
const groups = new Map();
|
|
301
507
|
parent.traverse((child) => {
|
|
302
|
-
if (child instanceof THREE__namespace.Mesh && !child.name.startsWith(
|
|
508
|
+
if (child instanceof THREE__namespace.Mesh && !child.name.startsWith('__')) {
|
|
303
509
|
const geoId = child.geometry.uuid;
|
|
304
510
|
const matId = Array.isArray(child.material)
|
|
305
|
-
? child.material.map((m) => m.uuid).join(
|
|
511
|
+
? child.material.map((m) => m.uuid).join(',')
|
|
306
512
|
: child.material.uuid;
|
|
307
513
|
const key = `${geoId}|${matId}`;
|
|
308
514
|
let list = groups.get(key);
|
|
@@ -316,11 +522,12 @@ function convertToInstanced(parent) {
|
|
|
316
522
|
let created = 0;
|
|
317
523
|
let removed = 0;
|
|
318
524
|
for (const [, meshes] of groups) {
|
|
319
|
-
if (meshes.length < 2)
|
|
525
|
+
if (meshes.length < 2) {
|
|
320
526
|
continue;
|
|
527
|
+
}
|
|
321
528
|
const source = meshes[0];
|
|
322
529
|
const instancedMesh = new THREE__namespace.InstancedMesh(source.geometry, source.material, meshes.length);
|
|
323
|
-
instancedMesh.name = source.name +
|
|
530
|
+
instancedMesh.name = source.name + '_Instanced';
|
|
324
531
|
instancedMesh.castShadow = source.castShadow;
|
|
325
532
|
instancedMesh.receiveShadow = source.receiveShadow;
|
|
326
533
|
const matrix = new THREE__namespace.Matrix4();
|
|
@@ -352,9 +559,10 @@ function countTriangles(object) {
|
|
|
352
559
|
count += geo.index.count / 3;
|
|
353
560
|
}
|
|
354
561
|
else {
|
|
355
|
-
const pos = geo.getAttribute(
|
|
356
|
-
if (pos)
|
|
562
|
+
const pos = geo.getAttribute('position');
|
|
563
|
+
if (pos) {
|
|
357
564
|
count += pos.count / 3;
|
|
565
|
+
}
|
|
358
566
|
}
|
|
359
567
|
}
|
|
360
568
|
});
|
|
@@ -388,8 +596,8 @@ function measureAngle(a, b, c) {
|
|
|
388
596
|
const HDRI_PRESETS = [
|
|
389
597
|
// Studio
|
|
390
598
|
{
|
|
391
|
-
name:
|
|
392
|
-
category:
|
|
599
|
+
name: 'Studio Soft',
|
|
600
|
+
category: 'Studio',
|
|
393
601
|
bgColor: 0x1a1a2e,
|
|
394
602
|
envIntensity: 1.0,
|
|
395
603
|
ambientColor: 0xffffff,
|
|
@@ -400,8 +608,8 @@ const HDRI_PRESETS = [
|
|
|
400
608
|
exposure: 1.0,
|
|
401
609
|
},
|
|
402
610
|
{
|
|
403
|
-
name:
|
|
404
|
-
category:
|
|
611
|
+
name: 'Studio High Key',
|
|
612
|
+
category: 'Studio',
|
|
405
613
|
bgColor: 0xf0f0f0,
|
|
406
614
|
envIntensity: 1.2,
|
|
407
615
|
ambientColor: 0xffffff,
|
|
@@ -412,8 +620,8 @@ const HDRI_PRESETS = [
|
|
|
412
620
|
exposure: 1.2,
|
|
413
621
|
},
|
|
414
622
|
{
|
|
415
|
-
name:
|
|
416
|
-
category:
|
|
623
|
+
name: 'Studio Low Key',
|
|
624
|
+
category: 'Studio',
|
|
417
625
|
bgColor: 0x0a0a0a,
|
|
418
626
|
envIntensity: 0.5,
|
|
419
627
|
ambientColor: 0x222244,
|
|
@@ -424,8 +632,8 @@ const HDRI_PRESETS = [
|
|
|
424
632
|
exposure: 0.8,
|
|
425
633
|
},
|
|
426
634
|
{
|
|
427
|
-
name:
|
|
428
|
-
category:
|
|
635
|
+
name: 'Studio Rim',
|
|
636
|
+
category: 'Studio',
|
|
429
637
|
bgColor: 0x111111,
|
|
430
638
|
envIntensity: 0.3,
|
|
431
639
|
ambientColor: 0x111122,
|
|
@@ -437,8 +645,8 @@ const HDRI_PRESETS = [
|
|
|
437
645
|
},
|
|
438
646
|
// Outdoor
|
|
439
647
|
{
|
|
440
|
-
name:
|
|
441
|
-
category:
|
|
648
|
+
name: 'Sunny Day',
|
|
649
|
+
category: 'Outdoor',
|
|
442
650
|
bgColor: 0x87ceeb,
|
|
443
651
|
envIntensity: 1.0,
|
|
444
652
|
ambientColor: 0x8ec8f0,
|
|
@@ -449,8 +657,8 @@ const HDRI_PRESETS = [
|
|
|
449
657
|
exposure: 1.0,
|
|
450
658
|
},
|
|
451
659
|
{
|
|
452
|
-
name:
|
|
453
|
-
category:
|
|
660
|
+
name: 'Overcast',
|
|
661
|
+
category: 'Outdoor',
|
|
454
662
|
bgColor: 0xb0b0b8,
|
|
455
663
|
envIntensity: 0.8,
|
|
456
664
|
ambientColor: 0xccccdd,
|
|
@@ -462,8 +670,8 @@ const HDRI_PRESETS = [
|
|
|
462
670
|
exposure: 1.0,
|
|
463
671
|
},
|
|
464
672
|
{
|
|
465
|
-
name:
|
|
466
|
-
category:
|
|
673
|
+
name: 'Golden Hour',
|
|
674
|
+
category: 'Outdoor',
|
|
467
675
|
bgColor: 0xff8844,
|
|
468
676
|
envIntensity: 1.0,
|
|
469
677
|
ambientColor: 0xffaa55,
|
|
@@ -474,8 +682,8 @@ const HDRI_PRESETS = [
|
|
|
474
682
|
exposure: 1.1,
|
|
475
683
|
},
|
|
476
684
|
{
|
|
477
|
-
name:
|
|
478
|
-
category:
|
|
685
|
+
name: 'Blue Hour',
|
|
686
|
+
category: 'Outdoor',
|
|
479
687
|
bgColor: 0x1a2a4a,
|
|
480
688
|
envIntensity: 0.6,
|
|
481
689
|
ambientColor: 0x334466,
|
|
@@ -486,8 +694,8 @@ const HDRI_PRESETS = [
|
|
|
486
694
|
exposure: 0.8,
|
|
487
695
|
},
|
|
488
696
|
{
|
|
489
|
-
name:
|
|
490
|
-
category:
|
|
697
|
+
name: 'Night',
|
|
698
|
+
category: 'Outdoor',
|
|
491
699
|
bgColor: 0x050510,
|
|
492
700
|
envIntensity: 0.1,
|
|
493
701
|
ambientColor: 0x111133,
|
|
@@ -499,8 +707,8 @@ const HDRI_PRESETS = [
|
|
|
499
707
|
},
|
|
500
708
|
// Interior
|
|
501
709
|
{
|
|
502
|
-
name:
|
|
503
|
-
category:
|
|
710
|
+
name: 'Warm Interior',
|
|
711
|
+
category: 'Interior',
|
|
504
712
|
bgColor: 0x2a1a10,
|
|
505
713
|
envIntensity: 0.7,
|
|
506
714
|
ambientColor: 0xffddaa,
|
|
@@ -511,8 +719,8 @@ const HDRI_PRESETS = [
|
|
|
511
719
|
exposure: 1.0,
|
|
512
720
|
},
|
|
513
721
|
{
|
|
514
|
-
name:
|
|
515
|
-
category:
|
|
722
|
+
name: 'Cool Office',
|
|
723
|
+
category: 'Interior',
|
|
516
724
|
bgColor: 0x1a2230,
|
|
517
725
|
envIntensity: 0.8,
|
|
518
726
|
ambientColor: 0xddeeff,
|
|
@@ -523,8 +731,8 @@ const HDRI_PRESETS = [
|
|
|
523
731
|
exposure: 1.0,
|
|
524
732
|
},
|
|
525
733
|
{
|
|
526
|
-
name:
|
|
527
|
-
category:
|
|
734
|
+
name: 'Gallery',
|
|
735
|
+
category: 'Interior',
|
|
528
736
|
bgColor: 0xfafafa,
|
|
529
737
|
envIntensity: 1.0,
|
|
530
738
|
ambientColor: 0xffffff,
|
|
@@ -536,8 +744,8 @@ const HDRI_PRESETS = [
|
|
|
536
744
|
},
|
|
537
745
|
// Dramatic
|
|
538
746
|
{
|
|
539
|
-
name:
|
|
540
|
-
category:
|
|
747
|
+
name: 'Neon City',
|
|
748
|
+
category: 'Dramatic',
|
|
541
749
|
bgColor: 0x0a0015,
|
|
542
750
|
envIntensity: 0.4,
|
|
543
751
|
ambientColor: 0xff00ff,
|
|
@@ -548,8 +756,8 @@ const HDRI_PRESETS = [
|
|
|
548
756
|
exposure: 1.0,
|
|
549
757
|
},
|
|
550
758
|
{
|
|
551
|
-
name:
|
|
552
|
-
category:
|
|
759
|
+
name: 'Cinematic',
|
|
760
|
+
category: 'Dramatic',
|
|
553
761
|
bgColor: 0x0f0f1a,
|
|
554
762
|
envIntensity: 0.5,
|
|
555
763
|
ambientColor: 0x223344,
|
|
@@ -560,8 +768,8 @@ const HDRI_PRESETS = [
|
|
|
560
768
|
exposure: 0.9,
|
|
561
769
|
},
|
|
562
770
|
{
|
|
563
|
-
name:
|
|
564
|
-
category:
|
|
771
|
+
name: 'Sunrise',
|
|
772
|
+
category: 'Dramatic',
|
|
565
773
|
bgColor: 0xff6633,
|
|
566
774
|
envIntensity: 0.8,
|
|
567
775
|
ambientColor: 0xffaa66,
|
|
@@ -572,8 +780,8 @@ const HDRI_PRESETS = [
|
|
|
572
780
|
exposure: 1.2,
|
|
573
781
|
},
|
|
574
782
|
{
|
|
575
|
-
name:
|
|
576
|
-
category:
|
|
783
|
+
name: 'Desert',
|
|
784
|
+
category: 'Dramatic',
|
|
577
785
|
bgColor: 0xe8c888,
|
|
578
786
|
envIntensity: 1.0,
|
|
579
787
|
ambientColor: 0xddcc99,
|
|
@@ -596,10 +804,12 @@ function applyHDRIPreset(scene, renderer, preset) {
|
|
|
596
804
|
let ambient;
|
|
597
805
|
let directional;
|
|
598
806
|
scene.traverse((child) => {
|
|
599
|
-
if (child instanceof THREE__namespace.AmbientLight && !ambient)
|
|
807
|
+
if (child instanceof THREE__namespace.AmbientLight && !ambient) {
|
|
600
808
|
ambient = child;
|
|
601
|
-
|
|
809
|
+
}
|
|
810
|
+
if (child instanceof THREE__namespace.DirectionalLight && !directional) {
|
|
602
811
|
directional = child;
|
|
812
|
+
}
|
|
603
813
|
});
|
|
604
814
|
if (ambient != null) {
|
|
605
815
|
ambient.color.setHex(preset.ambientColor);
|
|
@@ -628,11 +838,13 @@ function snapToVertex(point, scene, maxDistance = Infinity) {
|
|
|
628
838
|
let minDist = maxDistance;
|
|
629
839
|
const tmpV = new THREE__namespace.Vector3();
|
|
630
840
|
scene.traverse((child) => {
|
|
631
|
-
if (!(child instanceof THREE__namespace.Mesh))
|
|
841
|
+
if (!(child instanceof THREE__namespace.Mesh)) {
|
|
632
842
|
return;
|
|
633
|
-
|
|
634
|
-
|
|
843
|
+
}
|
|
844
|
+
const posAttr = child.geometry.getAttribute('position');
|
|
845
|
+
if (!posAttr) {
|
|
635
846
|
return;
|
|
847
|
+
}
|
|
636
848
|
child.updateWorldMatrix(true, false);
|
|
637
849
|
for (let i = 0; i < posAttr.count; i++) {
|
|
638
850
|
tmpV.fromBufferAttribute(posAttr, i);
|
|
@@ -640,7 +852,7 @@ function snapToVertex(point, scene, maxDistance = Infinity) {
|
|
|
640
852
|
const d = point.distanceTo(tmpV);
|
|
641
853
|
if (d < minDist) {
|
|
642
854
|
minDist = d;
|
|
643
|
-
closest = { point: tmpV.clone(), target:
|
|
855
|
+
closest = { point: tmpV.clone(), target: 'vertex', object: child };
|
|
644
856
|
}
|
|
645
857
|
}
|
|
646
858
|
});
|
|
@@ -653,11 +865,13 @@ function snapToEdge(point, scene, maxDistance = Infinity) {
|
|
|
653
865
|
const a = new THREE__namespace.Vector3();
|
|
654
866
|
const b = new THREE__namespace.Vector3();
|
|
655
867
|
scene.traverse((child) => {
|
|
656
|
-
if (!(child instanceof THREE__namespace.Mesh))
|
|
868
|
+
if (!(child instanceof THREE__namespace.Mesh)) {
|
|
657
869
|
return;
|
|
658
|
-
|
|
659
|
-
|
|
870
|
+
}
|
|
871
|
+
const posAttr = child.geometry.getAttribute('position');
|
|
872
|
+
if (!posAttr) {
|
|
660
873
|
return;
|
|
874
|
+
}
|
|
661
875
|
const index = child.geometry.index;
|
|
662
876
|
child.updateWorldMatrix(true, false);
|
|
663
877
|
const processEdge = (i0, i1) => {
|
|
@@ -667,7 +881,7 @@ function snapToEdge(point, scene, maxDistance = Infinity) {
|
|
|
667
881
|
const d = point.distanceTo(closestOnEdge);
|
|
668
882
|
if (d < minDist) {
|
|
669
883
|
minDist = d;
|
|
670
|
-
closest = { point: closestOnEdge.clone(), target:
|
|
884
|
+
closest = { point: closestOnEdge.clone(), target: 'edge', object: child };
|
|
671
885
|
}
|
|
672
886
|
};
|
|
673
887
|
if (index) {
|
|
@@ -699,23 +913,25 @@ function closestPointOnSegment(p, a, b) {
|
|
|
699
913
|
* Multi-mode snap: tries vertex/edge/grid in priority order.
|
|
700
914
|
* Returns the best snap within maxDistance, or grid snap as fallback.
|
|
701
915
|
*/
|
|
702
|
-
function snapMulti(point, scene, gridSize, modes = [
|
|
916
|
+
function snapMulti(point, scene, gridSize, modes = ['vertex', 'edge', 'grid'], maxDistance = 0.5) {
|
|
703
917
|
for (const mode of modes) {
|
|
704
|
-
if (mode ===
|
|
918
|
+
if (mode === 'vertex') {
|
|
705
919
|
const result = snapToVertex(point, scene, maxDistance);
|
|
706
|
-
if (result)
|
|
920
|
+
if (result) {
|
|
707
921
|
return result;
|
|
922
|
+
}
|
|
708
923
|
}
|
|
709
|
-
else if (mode ===
|
|
924
|
+
else if (mode === 'edge') {
|
|
710
925
|
const result = snapToEdge(point, scene, maxDistance);
|
|
711
|
-
if (result)
|
|
926
|
+
if (result) {
|
|
712
927
|
return result;
|
|
928
|
+
}
|
|
713
929
|
}
|
|
714
|
-
else if (mode ===
|
|
715
|
-
return { point: snapToGrid(point, gridSize), target:
|
|
930
|
+
else if (mode === 'grid') {
|
|
931
|
+
return { point: snapToGrid(point, gridSize), target: 'grid' };
|
|
716
932
|
}
|
|
717
933
|
}
|
|
718
|
-
return { point: snapToGrid(point, gridSize), target:
|
|
934
|
+
return { point: snapToGrid(point, gridSize), target: 'grid' };
|
|
719
935
|
}
|
|
720
936
|
/** Evaluate a cubic bezier segment at parameter t (0-1). */
|
|
721
937
|
function cubicBezier(p0, p1, p2, p3, t) {
|
|
@@ -730,15 +946,19 @@ function cubicBezier(p0, p1, p2, p3, t) {
|
|
|
730
946
|
function evaluateTrack(track, time) {
|
|
731
947
|
var _a, _b;
|
|
732
948
|
const { keyframes } = track;
|
|
733
|
-
if (keyframes.length === 0)
|
|
949
|
+
if (keyframes.length === 0) {
|
|
734
950
|
return 0;
|
|
735
|
-
|
|
951
|
+
}
|
|
952
|
+
if (keyframes.length === 1) {
|
|
736
953
|
return keyframes[0].value;
|
|
954
|
+
}
|
|
737
955
|
// Clamp to range
|
|
738
|
-
if (time <= keyframes[0].time)
|
|
956
|
+
if (time <= keyframes[0].time) {
|
|
739
957
|
return keyframes[0].value;
|
|
740
|
-
|
|
958
|
+
}
|
|
959
|
+
if (time >= keyframes[keyframes.length - 1].time) {
|
|
741
960
|
return keyframes[keyframes.length - 1].value;
|
|
961
|
+
}
|
|
742
962
|
// Find surrounding keyframes
|
|
743
963
|
let left = 0;
|
|
744
964
|
for (let i = 1; i < keyframes.length; i++) {
|
|
@@ -751,21 +971,22 @@ function evaluateTrack(track, time) {
|
|
|
751
971
|
const kfL = keyframes[left];
|
|
752
972
|
const kfR = keyframes[right];
|
|
753
973
|
const dt = kfR.time - kfL.time;
|
|
754
|
-
if (dt === 0)
|
|
974
|
+
if (dt === 0) {
|
|
755
975
|
return kfL.value;
|
|
976
|
+
}
|
|
756
977
|
const t = (time - kfL.time) / dt;
|
|
757
978
|
switch (kfL.interpolation) {
|
|
758
|
-
case
|
|
979
|
+
case 'constant':
|
|
759
980
|
return kfL.value;
|
|
760
|
-
case
|
|
981
|
+
case 'linear':
|
|
761
982
|
return kfL.value + (kfR.value - kfL.value) * t;
|
|
762
|
-
case
|
|
983
|
+
case 'ease-in':
|
|
763
984
|
return kfL.value + (kfR.value - kfL.value) * (t * t);
|
|
764
|
-
case
|
|
985
|
+
case 'ease-out':
|
|
765
986
|
return kfL.value + (kfR.value - kfL.value) * (1 - (1 - t) * (1 - t));
|
|
766
|
-
case
|
|
767
|
-
return kfL.value + (kfR.value - kfL.value) * (t < 0.5 ? 2 * t * t : 1 - 2 * (1 - t) * (1 - t));
|
|
768
|
-
case
|
|
987
|
+
case 'ease-in-out':
|
|
988
|
+
return (kfL.value + (kfR.value - kfL.value) * (t < 0.5 ? 2 * t * t : 1 - 2 * (1 - t) * (1 - t)));
|
|
989
|
+
case 'bezier': {
|
|
769
990
|
const handleR = (_a = kfL.handleRight) !== null && _a !== void 0 ? _a : { y: 0 };
|
|
770
991
|
const handleL = (_b = kfR.handleLeft) !== null && _b !== void 0 ? _b : { y: 0 };
|
|
771
992
|
return cubicBezier(kfL.value, kfL.value + handleR.y, kfR.value + handleL.y, kfR.value, t);
|
|
@@ -775,7 +996,7 @@ function evaluateTrack(track, time) {
|
|
|
775
996
|
}
|
|
776
997
|
}
|
|
777
998
|
/** Insert or update a keyframe at a given time. */
|
|
778
|
-
function setKeyframe(track, time, value, interpolation =
|
|
999
|
+
function setKeyframe(track, time, value, interpolation = 'bezier') {
|
|
779
1000
|
// Find existing keyframe at same time (within epsilon)
|
|
780
1001
|
const epsilon = 0.001;
|
|
781
1002
|
const existingIdx = track.keyframes.findIndex((kf) => Math.abs(kf.time - time) < epsilon);
|
|
@@ -825,7 +1046,7 @@ function createAnimationClip(name, tracks, sampleRate = 30) {
|
|
|
825
1046
|
/** Trigger a file download in the browser. */
|
|
826
1047
|
function downloadBlob(blob, filename) {
|
|
827
1048
|
const url = URL.createObjectURL(blob);
|
|
828
|
-
const a = document.createElement(
|
|
1049
|
+
const a = document.createElement('a');
|
|
829
1050
|
a.href = url;
|
|
830
1051
|
a.download = filename;
|
|
831
1052
|
document.body.appendChild(a);
|
|
@@ -850,9 +1071,10 @@ async function exportSceneUSDZ(scene) {
|
|
|
850
1071
|
const { USDZExporter } = await import('three/examples/jsm/exporters/USDZExporter.js');
|
|
851
1072
|
const exporter = new USDZExporter();
|
|
852
1073
|
const arraybuffer = await new Promise((resolve, reject) => {
|
|
1074
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- USDZExporter.parse callback signature varies between three.js minor versions
|
|
853
1075
|
exporter.parse(scene, resolve, reject);
|
|
854
1076
|
});
|
|
855
|
-
return new Blob([arraybuffer], { type:
|
|
1077
|
+
return new Blob([arraybuffer], { type: 'model/vnd.usdz+zip' });
|
|
856
1078
|
}
|
|
857
1079
|
/**
|
|
858
1080
|
* Setup crossfade between two animation actions.
|
|
@@ -883,8 +1105,9 @@ function makeAdditiveAction(mixer, clip, referenceClip) {
|
|
|
883
1105
|
*/
|
|
884
1106
|
function blendAnimations(actions) {
|
|
885
1107
|
const totalWeight = actions.reduce((sum, a) => sum + a.weight, 0);
|
|
886
|
-
if (totalWeight === 0)
|
|
1108
|
+
if (totalWeight === 0) {
|
|
887
1109
|
return;
|
|
1110
|
+
}
|
|
888
1111
|
for (const { action, weight } of actions) {
|
|
889
1112
|
const normalizedWeight = weight / totalWeight;
|
|
890
1113
|
action.setEffectiveWeight(normalizedWeight);
|
|
@@ -908,12 +1131,14 @@ function solveIKChain(skeleton, chain) {
|
|
|
908
1131
|
const bones = [];
|
|
909
1132
|
for (const name of boneNames) {
|
|
910
1133
|
const bone = skeleton.bones.find((b) => b.name === name);
|
|
911
|
-
if (!bone)
|
|
1134
|
+
if (!bone) {
|
|
912
1135
|
return false;
|
|
1136
|
+
}
|
|
913
1137
|
bones.push(bone);
|
|
914
1138
|
}
|
|
915
|
-
if (bones.length < 2)
|
|
1139
|
+
if (bones.length < 2) {
|
|
916
1140
|
return false;
|
|
1141
|
+
}
|
|
917
1142
|
const endEffector = bones[bones.length - 1];
|
|
918
1143
|
const endPos = new THREE__namespace.Vector3();
|
|
919
1144
|
const toEnd = new THREE__namespace.Vector3();
|
|
@@ -963,10 +1188,10 @@ function solveIKChain(skeleton, chain) {
|
|
|
963
1188
|
}
|
|
964
1189
|
/** Standard quad viewport layout. */
|
|
965
1190
|
const QUAD_VIEWPORT = [
|
|
966
|
-
{ preset:
|
|
967
|
-
{ preset:
|
|
968
|
-
{ preset:
|
|
969
|
-
{ preset:
|
|
1191
|
+
{ preset: 'perspective', x: 0.5, y: 0.5, width: 0.5, height: 0.5 },
|
|
1192
|
+
{ preset: 'top', x: 0, y: 0.5, width: 0.5, height: 0.5 },
|
|
1193
|
+
{ preset: 'front', x: 0, y: 0, width: 0.5, height: 0.5 },
|
|
1194
|
+
{ preset: 'right', x: 0.5, y: 0, width: 0.5, height: 0.5 },
|
|
970
1195
|
];
|
|
971
1196
|
/** Camera position/rotation for orthographic viewport presets. */
|
|
972
1197
|
const VIEWPORT_CAMERAS = {
|
|
@@ -984,7 +1209,7 @@ const VIEWPORT_CAMERAS = {
|
|
|
984
1209
|
function createViewportCamera(preset, aspect = 1, frustumSize = 10) {
|
|
985
1210
|
const config = VIEWPORT_CAMERAS[preset];
|
|
986
1211
|
if (config.ortho) {
|
|
987
|
-
const camera = new THREE__namespace.OrthographicCamera(-frustumSize * aspect / 2, frustumSize * aspect / 2, frustumSize / 2, -frustumSize / 2, 0.01, 10000);
|
|
1212
|
+
const camera = new THREE__namespace.OrthographicCamera((-frustumSize * aspect) / 2, (frustumSize * aspect) / 2, frustumSize / 2, -frustumSize / 2, 0.01, 10000);
|
|
988
1213
|
camera.position.set(...config.position);
|
|
989
1214
|
camera.up.set(...config.up);
|
|
990
1215
|
camera.lookAt(0, 0, 0);
|