sdl-mcp 0.12.2 → 0.12.3
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 +10 -0
- package/config/sdlmcp.config.example.json +53 -8
- package/config/sdlmcp.config.schema.json +530 -106
- package/dist/.tsbuildinfo +1 -1
- package/dist/benchmark/external-manifest.d.ts +162 -0
- package/dist/benchmark/external-manifest.d.ts.map +1 -0
- package/dist/benchmark/external-manifest.js +336 -0
- package/dist/benchmark/external-manifest.js.map +1 -0
- package/dist/benchmark/external-runner.d.ts +100 -0
- package/dist/benchmark/external-runner.d.ts.map +1 -0
- package/dist/benchmark/external-runner.js +1171 -0
- package/dist/benchmark/external-runner.js.map +1 -0
- package/dist/benchmark/output-file.d.ts +3 -0
- package/dist/benchmark/output-file.d.ts.map +1 -0
- package/dist/benchmark/output-file.js +8 -0
- package/dist/benchmark/output-file.js.map +1 -0
- package/dist/cli/argParsing.d.ts.map +1 -1
- package/dist/cli/argParsing.js +6 -0
- package/dist/cli/argParsing.js.map +1 -1
- package/dist/cli/commands/benchmark.d.ts.map +1 -1
- package/dist/cli/commands/benchmark.js +3 -2
- package/dist/cli/commands/benchmark.js.map +1 -1
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +13 -7
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +5 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +73 -3
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/serve.d.ts.map +1 -1
- package/dist/cli/commands/serve.js +2 -0
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/transport/http.d.ts +1 -35
- package/dist/cli/transport/http.d.ts.map +1 -1
- package/dist/cli/transport/http.js +151 -175
- package/dist/cli/transport/http.js.map +1 -1
- package/dist/cli/types.d.ts +1 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/config/constants.d.ts +30 -0
- package/dist/config/constants.d.ts.map +1 -1
- package/dist/config/constants.js +30 -0
- package/dist/config/constants.js.map +1 -1
- package/dist/config/types.d.ts +53 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +62 -14
- package/dist/config/types.js.map +1 -1
- package/dist/db/ladybug-batching.d.ts +1 -0
- package/dist/db/ladybug-batching.d.ts.map +1 -1
- package/dist/db/ladybug-batching.js +1 -0
- package/dist/db/ladybug-batching.js.map +1 -1
- package/dist/db/ladybug-core.d.ts +3 -0
- package/dist/db/ladybug-core.d.ts.map +1 -1
- package/dist/db/ladybug-core.js +72 -2
- package/dist/db/ladybug-core.js.map +1 -1
- package/dist/db/ladybug-embeddings.d.ts +6 -1
- package/dist/db/ladybug-embeddings.d.ts.map +1 -1
- package/dist/db/ladybug-embeddings.js +6 -1
- package/dist/db/ladybug-embeddings.js.map +1 -1
- package/dist/db/ladybug-file-summaries.d.ts.map +1 -1
- package/dist/db/ladybug-file-summaries.js +23 -0
- package/dist/db/ladybug-file-summaries.js.map +1 -1
- package/dist/db/ladybug-queries.js +1 -1
- package/dist/db/ladybug-queries.js.map +1 -1
- package/dist/db/migrations/index.d.ts.map +1 -1
- package/dist/db/migrations/index.js +2 -0
- package/dist/db/migrations/index.js.map +1 -1
- package/dist/db/migrations/m007-copy-embeddings-to-symbol.d.ts +5 -9
- package/dist/db/migrations/m007-copy-embeddings-to-symbol.d.ts.map +1 -1
- package/dist/db/migrations/m007-copy-embeddings-to-symbol.js +24 -126
- package/dist/db/migrations/m007-copy-embeddings-to-symbol.js.map +1 -1
- package/dist/db/migrations/m021-remediate-symbol-embeddings.d.ts +5 -0
- package/dist/db/migrations/m021-remediate-symbol-embeddings.d.ts.map +1 -0
- package/dist/db/migrations/m021-remediate-symbol-embeddings.js +7 -0
- package/dist/db/migrations/m021-remediate-symbol-embeddings.js.map +1 -0
- package/dist/db/migrations/symbol-embedding-remediation.d.ts +57 -0
- package/dist/db/migrations/symbol-embedding-remediation.d.ts.map +1 -0
- package/dist/db/migrations/symbol-embedding-remediation.js +335 -0
- package/dist/db/migrations/symbol-embedding-remediation.js.map +1 -0
- package/dist/graph/layout/force-layout.d.ts +4 -0
- package/dist/graph/layout/force-layout.d.ts.map +1 -0
- package/dist/graph/layout/force-layout.js +127 -0
- package/dist/graph/layout/force-layout.js.map +1 -0
- package/dist/graph/layout/layout-service.d.ts +37 -0
- package/dist/graph/layout/layout-service.d.ts.map +1 -0
- package/dist/graph/layout/layout-service.js +172 -0
- package/dist/graph/layout/layout-service.js.map +1 -0
- package/dist/graph/layout/native-engine.d.ts +9 -0
- package/dist/graph/layout/native-engine.d.ts.map +1 -0
- package/dist/graph/layout/native-engine.js +59 -0
- package/dist/graph/layout/native-engine.js.map +1 -0
- package/dist/graph/layout/prng.d.ts +3 -0
- package/dist/graph/layout/prng.d.ts.map +1 -0
- package/dist/graph/layout/prng.js +19 -0
- package/dist/graph/layout/prng.js.map +1 -0
- package/dist/graph/layout/serializer.d.ts +3 -0
- package/dist/graph/layout/serializer.d.ts.map +1 -0
- package/dist/graph/layout/serializer.js +20 -0
- package/dist/graph/layout/serializer.js.map +1 -0
- package/dist/graph/layout/types.d.ts +30 -0
- package/dist/graph/layout/types.d.ts.map +1 -0
- package/dist/graph/layout/types.js +2 -0
- package/dist/graph/layout/types.js.map +1 -0
- package/dist/indexer/embeddings.d.ts +7 -0
- package/dist/indexer/embeddings.d.ts.map +1 -1
- package/dist/indexer/embeddings.js +44 -4
- package/dist/indexer/embeddings.js.map +1 -1
- package/dist/indexer/file-summary-embeddings.d.ts +12 -0
- package/dist/indexer/file-summary-embeddings.d.ts.map +1 -1
- package/dist/indexer/file-summary-embeddings.js +83 -21
- package/dist/indexer/file-summary-embeddings.js.map +1 -1
- package/dist/indexer/fileWalker.d.ts.map +1 -1
- package/dist/indexer/fileWalker.js +2 -1
- package/dist/indexer/fileWalker.js.map +1 -1
- package/dist/indexer/metrics-updater.d.ts.map +1 -1
- package/dist/indexer/metrics-updater.js +27 -4
- package/dist/indexer/metrics-updater.js.map +1 -1
- package/dist/indexer/watcher.d.ts.map +1 -1
- package/dist/indexer/watcher.js +2 -1
- package/dist/indexer/watcher.js.map +1 -1
- package/dist/mcp/context-response-projection.d.ts.map +1 -1
- package/dist/mcp/context-response-projection.js +49 -13
- package/dist/mcp/context-response-projection.js.map +1 -1
- package/dist/mcp/tools/search-edit/planner.d.ts.map +1 -1
- package/dist/mcp/tools/search-edit/planner.js +10 -3
- package/dist/mcp/tools/search-edit/planner.js.map +1 -1
- package/dist/observability/event-tap.d.ts +2 -1
- package/dist/observability/event-tap.d.ts.map +1 -1
- package/dist/observability/event-tap.js.map +1 -1
- package/dist/observability/service.d.ts +11 -4
- package/dist/observability/service.d.ts.map +1 -1
- package/dist/observability/service.js +83 -13
- package/dist/observability/service.js.map +1 -1
- package/dist/observability/types.d.ts +48 -2
- package/dist/observability/types.d.ts.map +1 -1
- package/dist/ui/.tsbuildinfo +1 -0
- package/dist/ui/vendor/fflate.js +2692 -0
- package/dist/ui/vendor/jsm/controls/ArcballControls.js +3543 -0
- package/dist/ui/vendor/jsm/controls/DragControls.js +452 -0
- package/dist/ui/vendor/jsm/controls/FirstPersonControls.js +488 -0
- package/dist/ui/vendor/jsm/controls/FlyControls.js +384 -0
- package/dist/ui/vendor/jsm/controls/MapControls.js +116 -0
- package/dist/ui/vendor/jsm/controls/OrbitControls.js +1963 -0
- package/dist/ui/vendor/jsm/controls/PointerLockControls.js +264 -0
- package/dist/ui/vendor/jsm/controls/TrackballControls.js +1001 -0
- package/dist/ui/vendor/jsm/controls/TransformControls.js +2003 -0
- package/dist/ui/vendor/jsm/loaders/3DMLoader.js +1836 -0
- package/dist/ui/vendor/jsm/loaders/3MFLoader.js +1621 -0
- package/dist/ui/vendor/jsm/loaders/AMFLoader.js +541 -0
- package/dist/ui/vendor/jsm/loaders/BVHLoader.js +484 -0
- package/dist/ui/vendor/jsm/loaders/ColladaLoader.js +153 -0
- package/dist/ui/vendor/jsm/loaders/DDSLoader.js +385 -0
- package/dist/ui/vendor/jsm/loaders/DRACOLoader.js +772 -0
- package/dist/ui/vendor/jsm/loaders/EXRLoader.js +3395 -0
- package/dist/ui/vendor/jsm/loaders/FBXLoader.js +4580 -0
- package/dist/ui/vendor/jsm/loaders/FontLoader.js +260 -0
- package/dist/ui/vendor/jsm/loaders/GCodeLoader.js +318 -0
- package/dist/ui/vendor/jsm/loaders/GLTFLoader.js +4860 -0
- package/dist/ui/vendor/jsm/loaders/HDRCubeTextureLoader.js +164 -0
- package/dist/ui/vendor/jsm/loaders/HDRLoader.js +463 -0
- package/dist/ui/vendor/jsm/loaders/IESLoader.js +379 -0
- package/dist/ui/vendor/jsm/loaders/KMZLoader.js +163 -0
- package/dist/ui/vendor/jsm/loaders/KTX2Loader.js +1276 -0
- package/dist/ui/vendor/jsm/loaders/KTXLoader.js +197 -0
- package/dist/ui/vendor/jsm/loaders/LDrawLoader.js +2510 -0
- package/dist/ui/vendor/jsm/loaders/LUT3dlLoader.js +205 -0
- package/dist/ui/vendor/jsm/loaders/LUTCubeLoader.js +190 -0
- package/dist/ui/vendor/jsm/loaders/LUTImageLoader.js +190 -0
- package/dist/ui/vendor/jsm/loaders/LWOLoader.js +1051 -0
- package/dist/ui/vendor/jsm/loaders/LottieLoader.js +130 -0
- package/dist/ui/vendor/jsm/loaders/MD2Loader.js +435 -0
- package/dist/ui/vendor/jsm/loaders/MDDLoader.js +147 -0
- package/dist/ui/vendor/jsm/loaders/MTLLoader.js +593 -0
- package/dist/ui/vendor/jsm/loaders/MaterialXLoader.js +1126 -0
- package/dist/ui/vendor/jsm/loaders/NRRDLoader.js +718 -0
- package/dist/ui/vendor/jsm/loaders/OBJLoader.js +955 -0
- package/dist/ui/vendor/jsm/loaders/PCDLoader.js +620 -0
- package/dist/ui/vendor/jsm/loaders/PDBLoader.js +272 -0
- package/dist/ui/vendor/jsm/loaders/PLYLoader.js +968 -0
- package/dist/ui/vendor/jsm/loaders/PVRLoader.js +270 -0
- package/dist/ui/vendor/jsm/loaders/RGBELoader.js +18 -0
- package/dist/ui/vendor/jsm/loaders/STLLoader.js +421 -0
- package/dist/ui/vendor/jsm/loaders/SVGLoader.js +3319 -0
- package/dist/ui/vendor/jsm/loaders/TDSLoader.js +1142 -0
- package/dist/ui/vendor/jsm/loaders/TGALoader.js +538 -0
- package/dist/ui/vendor/jsm/loaders/TIFFLoader.js +59 -0
- package/dist/ui/vendor/jsm/loaders/TTFLoader.js +261 -0
- package/dist/ui/vendor/jsm/loaders/USDLoader.js +303 -0
- package/dist/ui/vendor/jsm/loaders/USDZLoader.js +16 -0
- package/dist/ui/vendor/jsm/loaders/UltraHDRLoader.js +755 -0
- package/dist/ui/vendor/jsm/loaders/VOXLoader.js +919 -0
- package/dist/ui/vendor/jsm/loaders/VRMLLoader.js +3646 -0
- package/dist/ui/vendor/jsm/loaders/VTKLoader.js +1293 -0
- package/dist/ui/vendor/jsm/loaders/XYZLoader.js +143 -0
- package/dist/ui/vendor/jsm/loaders/collada/ColladaComposer.js +3044 -0
- package/dist/ui/vendor/jsm/loaders/collada/ColladaParser.js +1977 -0
- package/dist/ui/vendor/jsm/loaders/lwo/IFFParser.js +1217 -0
- package/dist/ui/vendor/jsm/loaders/lwo/LWO2Parser.js +414 -0
- package/dist/ui/vendor/jsm/loaders/lwo/LWO3Parser.js +373 -0
- package/dist/ui/vendor/jsm/loaders/usd/USDAParser.js +901 -0
- package/dist/ui/vendor/jsm/loaders/usd/USDCParser.js +1878 -0
- package/dist/ui/vendor/jsm/loaders/usd/USDComposer.js +4627 -0
- package/dist/ui/vendor/jsm/utils/BufferGeometryUtils.js +1501 -0
- package/dist/ui/vendor/jsm/utils/CameraUtils.js +82 -0
- package/dist/ui/vendor/jsm/utils/ColorUtils.js +76 -0
- package/dist/ui/vendor/jsm/utils/GeometryCompressionUtils.js +547 -0
- package/dist/ui/vendor/jsm/utils/GeometryUtils.js +226 -0
- package/dist/ui/vendor/jsm/utils/LDrawUtils.js +211 -0
- package/dist/ui/vendor/jsm/utils/SceneOptimizer.js +458 -0
- package/dist/ui/vendor/jsm/utils/SceneUtils.js +363 -0
- package/dist/ui/vendor/jsm/utils/ShadowMapViewer.js +244 -0
- package/dist/ui/vendor/jsm/utils/ShadowMapViewerGPU.js +233 -0
- package/dist/ui/vendor/jsm/utils/SkeletonUtils.js +496 -0
- package/dist/ui/vendor/jsm/utils/SortUtils.js +175 -0
- package/dist/ui/vendor/jsm/utils/UVsDebug.js +173 -0
- package/dist/ui/vendor/jsm/utils/WebGLTextureUtils.js +115 -0
- package/dist/ui/vendor/jsm/utils/WebGPUTextureUtils.js +81 -0
- package/dist/ui/vendor/jsm/utils/WorkerPool.js +167 -0
- package/dist/ui/vendor/three.core.min.js +6 -0
- package/dist/ui/vendor/three.module.min.js +6 -0
- package/dist/ui/viewer/ambient.js +39 -0
- package/dist/ui/viewer/api.js +93 -0
- package/dist/ui/viewer/chrome.js +36 -0
- package/dist/ui/viewer/edges.js +33 -0
- package/dist/ui/viewer/index.html +32 -0
- package/dist/ui/viewer/inspector.js +23 -0
- package/dist/ui/viewer/lenses/activity.js +24 -0
- package/dist/ui/viewer/lenses/community.js +5 -0
- package/dist/ui/viewer/lenses/edges.js +4 -0
- package/dist/ui/viewer/lenses/impact.js +6 -0
- package/dist/ui/viewer/lenses/search.js +69 -0
- package/dist/ui/viewer/lod.js +100 -0
- package/dist/ui/viewer/main.js +92 -0
- package/dist/ui/viewer/picking.js +45 -0
- package/dist/ui/viewer/scene.js +85 -0
- package/dist/ui/viewer/skins/default-skin.js +15 -0
- package/dist/ui/viewer/skins/loader.js +44 -0
- package/dist/ui/viewer/skins/manifest-schema.js +30 -0
- package/dist/ui/viewer/state.js +44 -0
- package/dist/ui/viewer/theme.js +23 -0
- package/dist/ui/viewer/universe.js +151 -0
- package/dist/ui/viewer/viewer.css +85 -0
- package/dist/util/safeRegex.d.ts.map +1 -1
- package/dist/util/safeRegex.js +221 -68
- package/dist/util/safeRegex.js.map +1 -1
- package/dist/viewer/legacy-graph.d.ts +40 -0
- package/dist/viewer/legacy-graph.d.ts.map +1 -0
- package/dist/viewer/legacy-graph.js +152 -0
- package/dist/viewer/legacy-graph.js.map +1 -0
- package/dist/viewer/routes.d.ts +10 -0
- package/dist/viewer/routes.d.ts.map +1 -0
- package/dist/viewer/routes.js +221 -0
- package/dist/viewer/routes.js.map +1 -0
- package/dist/viewer/service.d.ts +44 -0
- package/dist/viewer/service.d.ts.map +1 -0
- package/dist/viewer/service.js +160 -0
- package/dist/viewer/service.js.map +1 -0
- package/dist/viewer/types.d.ts +63 -0
- package/dist/viewer/types.d.ts.map +1 -0
- package/dist/viewer/types.js +2 -0
- package/dist/viewer/types.js.map +1 -0
- package/dist/viewer/viewer-config.d.ts +12 -0
- package/dist/viewer/viewer-config.d.ts.map +1 -0
- package/dist/viewer/viewer-config.js +36 -0
- package/dist/viewer/viewer-config.js.map +1 -0
- package/package.json +18 -9
- package/templates/SDL.md +19 -0
- package/templates/claude-code.json +8 -43
- package/dist/ui/graph.css +0 -108
- package/dist/ui/graph.d.ts +0 -2
- package/dist/ui/graph.d.ts.map +0 -1
- package/dist/ui/graph.html +0 -52
- package/dist/ui/graph.js +0 -259
- package/dist/ui/graph.js.map +0 -1
|
@@ -0,0 +1,919 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BufferGeometry,
|
|
3
|
+
Color,
|
|
4
|
+
Data3DTexture,
|
|
5
|
+
FileLoader,
|
|
6
|
+
Float32BufferAttribute,
|
|
7
|
+
Group,
|
|
8
|
+
Loader,
|
|
9
|
+
LinearFilter,
|
|
10
|
+
Matrix4,
|
|
11
|
+
Mesh,
|
|
12
|
+
MeshStandardMaterial,
|
|
13
|
+
NearestFilter,
|
|
14
|
+
RedFormat,
|
|
15
|
+
SRGBColorSpace
|
|
16
|
+
} from 'three';
|
|
17
|
+
|
|
18
|
+
// Helper function to read a STRING from the data view
|
|
19
|
+
function readString( data, offset ) {
|
|
20
|
+
|
|
21
|
+
const size = data.getUint32( offset, true );
|
|
22
|
+
offset += 4;
|
|
23
|
+
|
|
24
|
+
let str = '';
|
|
25
|
+
for ( let i = 0; i < size; i ++ ) {
|
|
26
|
+
|
|
27
|
+
str += String.fromCharCode( data.getUint8( offset ++ ) );
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return { value: str, size: 4 + size };
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Helper function to read a DICT from the data view
|
|
36
|
+
function readDict( data, offset ) {
|
|
37
|
+
|
|
38
|
+
const dict = {};
|
|
39
|
+
const count = data.getUint32( offset, true );
|
|
40
|
+
offset += 4;
|
|
41
|
+
|
|
42
|
+
let totalSize = 4;
|
|
43
|
+
|
|
44
|
+
for ( let i = 0; i < count; i ++ ) {
|
|
45
|
+
|
|
46
|
+
const key = readString( data, offset );
|
|
47
|
+
offset += key.size;
|
|
48
|
+
totalSize += key.size;
|
|
49
|
+
|
|
50
|
+
const value = readString( data, offset );
|
|
51
|
+
offset += value.size;
|
|
52
|
+
totalSize += value.size;
|
|
53
|
+
|
|
54
|
+
dict[ key.value ] = value.value;
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return { value: dict, size: totalSize };
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Helper function to decode ROTATION byte into a rotation matrix
|
|
63
|
+
function decodeRotation( byte ) {
|
|
64
|
+
|
|
65
|
+
// The rotation is stored as a row-major 3x3 matrix encoded in a single byte
|
|
66
|
+
// Bits 0-1: index of the non-zero entry in the first row
|
|
67
|
+
// Bits 2-3: index of the non-zero entry in the second row
|
|
68
|
+
// Bit 4: sign of the first row entry (0 = positive, 1 = negative)
|
|
69
|
+
// Bit 5: sign of the second row entry
|
|
70
|
+
// Bit 6: sign of the third row entry
|
|
71
|
+
// The third row index is determined by the remaining column
|
|
72
|
+
|
|
73
|
+
const index1 = byte & 0x3;
|
|
74
|
+
const index2 = ( byte >> 2 ) & 0x3;
|
|
75
|
+
const sign1 = ( byte >> 4 ) & 0x1 ? - 1 : 1;
|
|
76
|
+
const sign2 = ( byte >> 5 ) & 0x1 ? - 1 : 1;
|
|
77
|
+
const sign3 = ( byte >> 6 ) & 0x1 ? - 1 : 1;
|
|
78
|
+
|
|
79
|
+
// Find the third row index (the one not used by row 0 or row 1)
|
|
80
|
+
const index3 = 3 - index1 - index2;
|
|
81
|
+
|
|
82
|
+
// Build the VOX rotation matrix (row-major 3x3)
|
|
83
|
+
// r[row][col] - each row has one non-zero entry
|
|
84
|
+
const r = [
|
|
85
|
+
[ 0, 0, 0 ],
|
|
86
|
+
[ 0, 0, 0 ],
|
|
87
|
+
[ 0, 0, 0 ]
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
r[ 0 ][ index1 ] = sign1;
|
|
91
|
+
r[ 1 ][ index2 ] = sign2;
|
|
92
|
+
r[ 2 ][ index3 ] = sign3;
|
|
93
|
+
|
|
94
|
+
// Convert from VOX coordinate system (Z-up) to Three.js (Y-up)
|
|
95
|
+
// VOX: X-right, Y-forward, Z-up
|
|
96
|
+
// Three.js: X-right, Y-up, Z-backward
|
|
97
|
+
// Transformation: x' = x, y' = z, z' = -y
|
|
98
|
+
//
|
|
99
|
+
// To convert rotation matrix R_vox to R_three:
|
|
100
|
+
// R_three = C * R_vox * C^-1
|
|
101
|
+
// where C converts VOX coords to Three.js coords
|
|
102
|
+
|
|
103
|
+
// Apply coordinate change: swap Y and Z, negate new Z
|
|
104
|
+
// This is equivalent to: C * R * C^-1
|
|
105
|
+
const m = new Matrix4();
|
|
106
|
+
m.set(
|
|
107
|
+
r[ 0 ][ 0 ], r[ 0 ][ 2 ], - r[ 0 ][ 1 ], 0,
|
|
108
|
+
r[ 2 ][ 0 ], r[ 2 ][ 2 ], - r[ 2 ][ 1 ], 0,
|
|
109
|
+
- r[ 1 ][ 0 ], - r[ 1 ][ 2 ], r[ 1 ][ 1 ], 0,
|
|
110
|
+
0, 0, 0, 1
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
return m;
|
|
114
|
+
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Apply VOX transform to a Three.js object
|
|
118
|
+
function applyTransform( object, node ) {
|
|
119
|
+
|
|
120
|
+
if ( node.attributes._name ) {
|
|
121
|
+
|
|
122
|
+
object.name = node.attributes._name;
|
|
123
|
+
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if ( node.frames.length > 0 ) {
|
|
127
|
+
|
|
128
|
+
const frame = node.frames[ 0 ];
|
|
129
|
+
|
|
130
|
+
if ( frame.rotation ) {
|
|
131
|
+
|
|
132
|
+
object.applyMatrix4( frame.rotation );
|
|
133
|
+
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if ( frame.translation ) {
|
|
137
|
+
|
|
138
|
+
// VOX uses Z-up, Three.js uses Y-up
|
|
139
|
+
object.position.set(
|
|
140
|
+
frame.translation.x,
|
|
141
|
+
frame.translation.z,
|
|
142
|
+
- frame.translation.y
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Recursively build Three.js object graph from VOX nodes
|
|
152
|
+
function buildObject( nodeId, nodes, chunks ) {
|
|
153
|
+
|
|
154
|
+
const node = nodes[ nodeId ];
|
|
155
|
+
|
|
156
|
+
if ( node.type === 'transform' ) {
|
|
157
|
+
|
|
158
|
+
const childNode = nodes[ node.childNodeId ];
|
|
159
|
+
|
|
160
|
+
// Check if this transform has actual transformation data
|
|
161
|
+
const frame = node.frames[ 0 ];
|
|
162
|
+
const hasTransform = frame && ( frame.rotation || frame.translation );
|
|
163
|
+
|
|
164
|
+
// Flatten: if child is a single-model shape, apply transform directly to mesh
|
|
165
|
+
if ( childNode.type === 'shape' && childNode.models.length === 1 ) {
|
|
166
|
+
|
|
167
|
+
const chunk = chunks[ childNode.models[ 0 ].modelId ];
|
|
168
|
+
const mesh = buildMesh( chunk );
|
|
169
|
+
applyTransform( mesh, node );
|
|
170
|
+
return mesh;
|
|
171
|
+
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// If no transform, just return the child directly (avoid unnecessary group)
|
|
175
|
+
if ( ! hasTransform ) {
|
|
176
|
+
|
|
177
|
+
const child = buildObject( node.childNodeId, nodes, chunks );
|
|
178
|
+
if ( child && node.attributes._name ) child.name = node.attributes._name;
|
|
179
|
+
return child;
|
|
180
|
+
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Otherwise create a group
|
|
184
|
+
const group = new Group();
|
|
185
|
+
applyTransform( group, node );
|
|
186
|
+
|
|
187
|
+
const child = buildObject( node.childNodeId, nodes, chunks );
|
|
188
|
+
if ( child ) group.add( child );
|
|
189
|
+
|
|
190
|
+
return group;
|
|
191
|
+
|
|
192
|
+
} else if ( node.type === 'group' ) {
|
|
193
|
+
|
|
194
|
+
const group = new Group();
|
|
195
|
+
|
|
196
|
+
for ( const childId of node.childIds ) {
|
|
197
|
+
|
|
198
|
+
const child = buildObject( childId, nodes, chunks );
|
|
199
|
+
if ( child ) group.add( child );
|
|
200
|
+
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return group;
|
|
204
|
+
|
|
205
|
+
} else if ( node.type === 'shape' ) {
|
|
206
|
+
|
|
207
|
+
// Shape reached directly (shouldn't happen in well-formed files, but handle it)
|
|
208
|
+
if ( node.models.length === 1 ) {
|
|
209
|
+
|
|
210
|
+
const chunk = chunks[ node.models[ 0 ].modelId ];
|
|
211
|
+
return buildMesh( chunk );
|
|
212
|
+
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const group = new Group();
|
|
216
|
+
|
|
217
|
+
for ( const model of node.models ) {
|
|
218
|
+
|
|
219
|
+
const chunk = chunks[ model.modelId ];
|
|
220
|
+
group.add( buildMesh( chunk ) );
|
|
221
|
+
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return group;
|
|
225
|
+
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return null;
|
|
229
|
+
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* A loader for the VOX format.
|
|
234
|
+
*
|
|
235
|
+
* ```js
|
|
236
|
+
* const loader = new VOXLoader();
|
|
237
|
+
* const result = await loader.loadAsync( 'models/vox/monu10.vox' );
|
|
238
|
+
*
|
|
239
|
+
* scene.add( result.scene.children[ 0 ] );
|
|
240
|
+
* ```
|
|
241
|
+
* @augments Loader
|
|
242
|
+
* @three_import import { VOXLoader } from 'three/addons/loaders/VOXLoader.js';
|
|
243
|
+
*/
|
|
244
|
+
class VOXLoader extends Loader {
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Starts loading from the given URL and passes the loaded VOX asset
|
|
248
|
+
* to the `onLoad()` callback.
|
|
249
|
+
*
|
|
250
|
+
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
|
|
251
|
+
* @param {function(Object)} onLoad - Executed when the loading process has been finished.
|
|
252
|
+
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
|
|
253
|
+
* @param {onErrorCallback} onError - Executed when errors occur.
|
|
254
|
+
*/
|
|
255
|
+
load( url, onLoad, onProgress, onError ) {
|
|
256
|
+
|
|
257
|
+
const scope = this;
|
|
258
|
+
|
|
259
|
+
const loader = new FileLoader( scope.manager );
|
|
260
|
+
loader.setPath( scope.path );
|
|
261
|
+
loader.setResponseType( 'arraybuffer' );
|
|
262
|
+
loader.setRequestHeader( scope.requestHeader );
|
|
263
|
+
loader.load( url, function ( buffer ) {
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
|
|
267
|
+
onLoad( scope.parse( buffer ) );
|
|
268
|
+
|
|
269
|
+
} catch ( e ) {
|
|
270
|
+
|
|
271
|
+
if ( onError ) {
|
|
272
|
+
|
|
273
|
+
onError( e );
|
|
274
|
+
|
|
275
|
+
} else {
|
|
276
|
+
|
|
277
|
+
console.error( e );
|
|
278
|
+
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
scope.manager.itemError( url );
|
|
282
|
+
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
}, onProgress, onError );
|
|
286
|
+
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Parses the given VOX data and returns the result object.
|
|
291
|
+
*
|
|
292
|
+
* @param {ArrayBuffer} buffer - The raw VOX data as an array buffer.
|
|
293
|
+
* @return {Object} The parsed VOX data with properties: chunks, scene.
|
|
294
|
+
*/
|
|
295
|
+
parse( buffer ) {
|
|
296
|
+
|
|
297
|
+
const data = new DataView( buffer );
|
|
298
|
+
|
|
299
|
+
const id = data.getUint32( 0, true );
|
|
300
|
+
const version = data.getUint32( 4, true );
|
|
301
|
+
|
|
302
|
+
if ( id !== 542658390 ) {
|
|
303
|
+
|
|
304
|
+
console.error( 'THREE.VOXLoader: Invalid VOX file.' );
|
|
305
|
+
return;
|
|
306
|
+
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if ( version !== 150 && version !== 200 ) {
|
|
310
|
+
|
|
311
|
+
console.error( 'THREE.VOXLoader: Invalid VOX file. Unsupported version:', version );
|
|
312
|
+
return;
|
|
313
|
+
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const DEFAULT_PALETTE = [
|
|
317
|
+
0x00000000, 0xffffffff, 0xffccffff, 0xff99ffff, 0xff66ffff, 0xff33ffff, 0xff00ffff, 0xffffccff,
|
|
318
|
+
0xffccccff, 0xff99ccff, 0xff66ccff, 0xff33ccff, 0xff00ccff, 0xffff99ff, 0xffcc99ff, 0xff9999ff,
|
|
319
|
+
0xff6699ff, 0xff3399ff, 0xff0099ff, 0xffff66ff, 0xffcc66ff, 0xff9966ff, 0xff6666ff, 0xff3366ff,
|
|
320
|
+
0xff0066ff, 0xffff33ff, 0xffcc33ff, 0xff9933ff, 0xff6633ff, 0xff3333ff, 0xff0033ff, 0xffff00ff,
|
|
321
|
+
0xffcc00ff, 0xff9900ff, 0xff6600ff, 0xff3300ff, 0xff0000ff, 0xffffffcc, 0xffccffcc, 0xff99ffcc,
|
|
322
|
+
0xff66ffcc, 0xff33ffcc, 0xff00ffcc, 0xffffcccc, 0xffcccccc, 0xff99cccc, 0xff66cccc, 0xff33cccc,
|
|
323
|
+
0xff00cccc, 0xffff99cc, 0xffcc99cc, 0xff9999cc, 0xff6699cc, 0xff3399cc, 0xff0099cc, 0xffff66cc,
|
|
324
|
+
0xffcc66cc, 0xff9966cc, 0xff6666cc, 0xff3366cc, 0xff0066cc, 0xffff33cc, 0xffcc33cc, 0xff9933cc,
|
|
325
|
+
0xff6633cc, 0xff3333cc, 0xff0033cc, 0xffff00cc, 0xffcc00cc, 0xff9900cc, 0xff6600cc, 0xff3300cc,
|
|
326
|
+
0xff0000cc, 0xffffff99, 0xffccff99, 0xff99ff99, 0xff66ff99, 0xff33ff99, 0xff00ff99, 0xffffcc99,
|
|
327
|
+
0xffcccc99, 0xff99cc99, 0xff66cc99, 0xff33cc99, 0xff00cc99, 0xffff9999, 0xffcc9999, 0xff999999,
|
|
328
|
+
0xff669999, 0xff339999, 0xff009999, 0xffff6699, 0xffcc6699, 0xff996699, 0xff666699, 0xff336699,
|
|
329
|
+
0xff006699, 0xffff3399, 0xffcc3399, 0xff993399, 0xff663399, 0xff333399, 0xff003399, 0xffff0099,
|
|
330
|
+
0xffcc0099, 0xff990099, 0xff660099, 0xff330099, 0xff000099, 0xffffff66, 0xffccff66, 0xff99ff66,
|
|
331
|
+
0xff66ff66, 0xff33ff66, 0xff00ff66, 0xffffcc66, 0xffcccc66, 0xff99cc66, 0xff66cc66, 0xff33cc66,
|
|
332
|
+
0xff00cc66, 0xffff9966, 0xffcc9966, 0xff999966, 0xff669966, 0xff339966, 0xff009966, 0xffff6666,
|
|
333
|
+
0xffcc6666, 0xff996666, 0xff666666, 0xff336666, 0xff006666, 0xffff3366, 0xffcc3366, 0xff993366,
|
|
334
|
+
0xff663366, 0xff333366, 0xff003366, 0xffff0066, 0xffcc0066, 0xff990066, 0xff660066, 0xff330066,
|
|
335
|
+
0xff000066, 0xffffff33, 0xffccff33, 0xff99ff33, 0xff66ff33, 0xff33ff33, 0xff00ff33, 0xffffcc33,
|
|
336
|
+
0xffcccc33, 0xff99cc33, 0xff66cc33, 0xff33cc33, 0xff00cc33, 0xffff9933, 0xffcc9933, 0xff999933,
|
|
337
|
+
0xff669933, 0xff339933, 0xff009933, 0xffff6633, 0xffcc6633, 0xff996633, 0xff666633, 0xff336633,
|
|
338
|
+
0xff006633, 0xffff3333, 0xffcc3333, 0xff993333, 0xff663333, 0xff333333, 0xff003333, 0xffff0033,
|
|
339
|
+
0xffcc0033, 0xff990033, 0xff660033, 0xff330033, 0xff000033, 0xffffff00, 0xffccff00, 0xff99ff00,
|
|
340
|
+
0xff66ff00, 0xff33ff00, 0xff00ff00, 0xffffcc00, 0xffcccc00, 0xff99cc00, 0xff66cc00, 0xff33cc00,
|
|
341
|
+
0xff00cc00, 0xffff9900, 0xffcc9900, 0xff999900, 0xff669900, 0xff339900, 0xff009900, 0xffff6600,
|
|
342
|
+
0xffcc6600, 0xff996600, 0xff666600, 0xff336600, 0xff006600, 0xffff3300, 0xffcc3300, 0xff993300,
|
|
343
|
+
0xff663300, 0xff333300, 0xff003300, 0xffff0000, 0xffcc0000, 0xff990000, 0xff660000, 0xff330000,
|
|
344
|
+
0xff0000ee, 0xff0000dd, 0xff0000bb, 0xff0000aa, 0xff000088, 0xff000077, 0xff000055, 0xff000044,
|
|
345
|
+
0xff000022, 0xff000011, 0xff00ee00, 0xff00dd00, 0xff00bb00, 0xff00aa00, 0xff008800, 0xff007700,
|
|
346
|
+
0xff005500, 0xff004400, 0xff002200, 0xff001100, 0xffee0000, 0xffdd0000, 0xffbb0000, 0xffaa0000,
|
|
347
|
+
0xff880000, 0xff770000, 0xff550000, 0xff440000, 0xff220000, 0xff110000, 0xffeeeeee, 0xffdddddd,
|
|
348
|
+
0xffbbbbbb, 0xffaaaaaa, 0xff888888, 0xff777777, 0xff555555, 0xff444444, 0xff222222, 0xff111111
|
|
349
|
+
];
|
|
350
|
+
|
|
351
|
+
let i = 8;
|
|
352
|
+
|
|
353
|
+
let chunk;
|
|
354
|
+
const chunks = [];
|
|
355
|
+
|
|
356
|
+
// Extension data
|
|
357
|
+
const nodes = {};
|
|
358
|
+
let palette = DEFAULT_PALETTE;
|
|
359
|
+
|
|
360
|
+
while ( i < data.byteLength ) {
|
|
361
|
+
|
|
362
|
+
let id = '';
|
|
363
|
+
|
|
364
|
+
for ( let j = 0; j < 4; j ++ ) {
|
|
365
|
+
|
|
366
|
+
id += String.fromCharCode( data.getUint8( i ++ ) );
|
|
367
|
+
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const chunkSize = data.getUint32( i, true ); i += 4;
|
|
371
|
+
i += 4; // childChunks
|
|
372
|
+
|
|
373
|
+
if ( id === 'SIZE' ) {
|
|
374
|
+
|
|
375
|
+
const x = data.getUint32( i, true ); i += 4;
|
|
376
|
+
const y = data.getUint32( i, true ); i += 4;
|
|
377
|
+
const z = data.getUint32( i, true ); i += 4;
|
|
378
|
+
|
|
379
|
+
chunk = {
|
|
380
|
+
palette: DEFAULT_PALETTE,
|
|
381
|
+
size: { x: x, y: y, z: z },
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
chunks.push( chunk );
|
|
385
|
+
|
|
386
|
+
i += chunkSize - ( 3 * 4 );
|
|
387
|
+
|
|
388
|
+
} else if ( id === 'XYZI' ) {
|
|
389
|
+
|
|
390
|
+
const numVoxels = data.getUint32( i, true ); i += 4;
|
|
391
|
+
chunk.data = new Uint8Array( buffer, i, numVoxels * 4 );
|
|
392
|
+
|
|
393
|
+
i += numVoxels * 4;
|
|
394
|
+
|
|
395
|
+
} else if ( id === 'RGBA' ) {
|
|
396
|
+
|
|
397
|
+
palette = [ 0 ];
|
|
398
|
+
|
|
399
|
+
for ( let j = 0; j < 256; j ++ ) {
|
|
400
|
+
|
|
401
|
+
palette[ j + 1 ] = data.getUint32( i, true ); i += 4;
|
|
402
|
+
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
chunk.palette = palette;
|
|
406
|
+
|
|
407
|
+
} else if ( id === 'nTRN' ) {
|
|
408
|
+
|
|
409
|
+
// Transform Node
|
|
410
|
+
const nodeId = data.getUint32( i, true ); i += 4;
|
|
411
|
+
const attributes = readDict( data, i );
|
|
412
|
+
i += attributes.size;
|
|
413
|
+
|
|
414
|
+
const childNodeId = data.getUint32( i, true ); i += 4;
|
|
415
|
+
i += 4; // reserved (-1)
|
|
416
|
+
const layerId = data.getInt32( i, true ); i += 4;
|
|
417
|
+
const numFrames = data.getUint32( i, true ); i += 4;
|
|
418
|
+
|
|
419
|
+
const frames = [];
|
|
420
|
+
|
|
421
|
+
for ( let f = 0; f < numFrames; f ++ ) {
|
|
422
|
+
|
|
423
|
+
const frameDict = readDict( data, i );
|
|
424
|
+
i += frameDict.size;
|
|
425
|
+
|
|
426
|
+
const frame = { rotation: null, translation: null };
|
|
427
|
+
|
|
428
|
+
if ( frameDict.value._r !== undefined ) {
|
|
429
|
+
|
|
430
|
+
frame.rotation = decodeRotation( parseInt( frameDict.value._r ) );
|
|
431
|
+
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
if ( frameDict.value._t !== undefined ) {
|
|
435
|
+
|
|
436
|
+
const parts = frameDict.value._t.split( ' ' ).map( Number );
|
|
437
|
+
frame.translation = { x: parts[ 0 ], y: parts[ 1 ], z: parts[ 2 ] };
|
|
438
|
+
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
frames.push( frame );
|
|
442
|
+
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
nodes[ nodeId ] = {
|
|
446
|
+
type: 'transform',
|
|
447
|
+
id: nodeId,
|
|
448
|
+
attributes: attributes.value,
|
|
449
|
+
childNodeId: childNodeId,
|
|
450
|
+
layerId: layerId,
|
|
451
|
+
frames: frames
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
} else if ( id === 'nGRP' ) {
|
|
455
|
+
|
|
456
|
+
// Group Node
|
|
457
|
+
const nodeId = data.getUint32( i, true ); i += 4;
|
|
458
|
+
const attributes = readDict( data, i );
|
|
459
|
+
i += attributes.size;
|
|
460
|
+
|
|
461
|
+
const numChildren = data.getUint32( i, true ); i += 4;
|
|
462
|
+
const childIds = [];
|
|
463
|
+
|
|
464
|
+
for ( let c = 0; c < numChildren; c ++ ) {
|
|
465
|
+
|
|
466
|
+
childIds.push( data.getUint32( i, true ) ); i += 4;
|
|
467
|
+
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
nodes[ nodeId ] = {
|
|
471
|
+
type: 'group',
|
|
472
|
+
id: nodeId,
|
|
473
|
+
attributes: attributes.value,
|
|
474
|
+
childIds: childIds
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
} else if ( id === 'nSHP' ) {
|
|
478
|
+
|
|
479
|
+
// Shape Node
|
|
480
|
+
const nodeId = data.getUint32( i, true ); i += 4;
|
|
481
|
+
const attributes = readDict( data, i );
|
|
482
|
+
i += attributes.size;
|
|
483
|
+
|
|
484
|
+
const numModels = data.getUint32( i, true ); i += 4;
|
|
485
|
+
const models = [];
|
|
486
|
+
|
|
487
|
+
for ( let m = 0; m < numModels; m ++ ) {
|
|
488
|
+
|
|
489
|
+
const modelId = data.getUint32( i, true ); i += 4;
|
|
490
|
+
const modelAttributes = readDict( data, i );
|
|
491
|
+
i += modelAttributes.size;
|
|
492
|
+
|
|
493
|
+
models.push( {
|
|
494
|
+
modelId: modelId,
|
|
495
|
+
attributes: modelAttributes.value
|
|
496
|
+
} );
|
|
497
|
+
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
nodes[ nodeId ] = {
|
|
501
|
+
type: 'shape',
|
|
502
|
+
id: nodeId,
|
|
503
|
+
attributes: attributes.value,
|
|
504
|
+
models: models
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
} else {
|
|
508
|
+
|
|
509
|
+
// Skip unknown chunks
|
|
510
|
+
i += chunkSize;
|
|
511
|
+
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Apply palette to all chunks
|
|
517
|
+
for ( let c = 0; c < chunks.length; c ++ ) {
|
|
518
|
+
|
|
519
|
+
chunks[ c ].palette = palette;
|
|
520
|
+
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Build Three.js scene graph from nodes
|
|
524
|
+
let scene = null;
|
|
525
|
+
|
|
526
|
+
if ( Object.keys( nodes ).length > 0 ) {
|
|
527
|
+
|
|
528
|
+
scene = buildObject( 0, nodes, chunks );
|
|
529
|
+
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Build result object
|
|
533
|
+
const result = {
|
|
534
|
+
chunks: chunks,
|
|
535
|
+
scene: scene
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
// @deprecated, r182
|
|
539
|
+
// Proxy for backwards compatibility with array-like access
|
|
540
|
+
let warned = false;
|
|
541
|
+
|
|
542
|
+
return new Proxy( result, {
|
|
543
|
+
|
|
544
|
+
get( target, prop ) {
|
|
545
|
+
|
|
546
|
+
// Handle numeric indices
|
|
547
|
+
if ( typeof prop === 'string' && /^\d+$/.test( prop ) ) {
|
|
548
|
+
|
|
549
|
+
if ( ! warned ) {
|
|
550
|
+
|
|
551
|
+
console.warn( 'THREE.VOXLoader: Accessing result as an array is deprecated. Use result.chunks[] instead.' );
|
|
552
|
+
warned = true;
|
|
553
|
+
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
return target.chunks[ parseInt( prop ) ];
|
|
557
|
+
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// Handle array properties/methods
|
|
561
|
+
if ( prop === 'length' ) {
|
|
562
|
+
|
|
563
|
+
if ( ! warned ) {
|
|
564
|
+
|
|
565
|
+
console.warn( 'THREE.VOXLoader: Accessing result as an array is deprecated. Use result.chunks instead.' );
|
|
566
|
+
warned = true;
|
|
567
|
+
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return target.chunks.length;
|
|
571
|
+
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Handle iteration
|
|
575
|
+
if ( prop === Symbol.iterator ) {
|
|
576
|
+
|
|
577
|
+
if ( ! warned ) {
|
|
578
|
+
|
|
579
|
+
console.warn( 'THREE.VOXLoader: Iterating result as an array is deprecated. Use result.chunks instead.' );
|
|
580
|
+
warned = true;
|
|
581
|
+
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return target.chunks[ Symbol.iterator ].bind( target.chunks );
|
|
585
|
+
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
return target[ prop ];
|
|
589
|
+
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
} );
|
|
593
|
+
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Builds a mesh from a VOX chunk.
|
|
600
|
+
*
|
|
601
|
+
* @param {Object} chunk - A VOX chunk loaded via {@link VOXLoader}.
|
|
602
|
+
* @return {Mesh} The generated mesh.
|
|
603
|
+
*/
|
|
604
|
+
function buildMesh( chunk ) {
|
|
605
|
+
|
|
606
|
+
const data = chunk.data;
|
|
607
|
+
const size = chunk.size;
|
|
608
|
+
const palette = chunk.palette;
|
|
609
|
+
|
|
610
|
+
const sx = size.x;
|
|
611
|
+
const sy = size.y;
|
|
612
|
+
const sz = size.z;
|
|
613
|
+
|
|
614
|
+
// Build volume with color indices
|
|
615
|
+
|
|
616
|
+
const volume = new Uint8Array( sx * sy * sz );
|
|
617
|
+
|
|
618
|
+
for ( let j = 0; j < data.length; j += 4 ) {
|
|
619
|
+
|
|
620
|
+
const x = data[ j + 0 ];
|
|
621
|
+
const y = data[ j + 1 ];
|
|
622
|
+
const z = data[ j + 2 ];
|
|
623
|
+
const c = data[ j + 3 ];
|
|
624
|
+
|
|
625
|
+
volume[ x + y * sx + z * sx * sy ] = c;
|
|
626
|
+
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// Greedy meshing
|
|
630
|
+
|
|
631
|
+
const vertices = [];
|
|
632
|
+
const indices = [];
|
|
633
|
+
const colors = [];
|
|
634
|
+
|
|
635
|
+
const _color = new Color();
|
|
636
|
+
let hasColors = false;
|
|
637
|
+
|
|
638
|
+
// Process each of the 6 face directions
|
|
639
|
+
// dims: the 3 axis sizes, d: which axis is normal to the face
|
|
640
|
+
const dims = [ sx, sy, sz ];
|
|
641
|
+
|
|
642
|
+
for ( let d = 0; d < 3; d ++ ) {
|
|
643
|
+
|
|
644
|
+
const u = ( d + 1 ) % 3;
|
|
645
|
+
const v = ( d + 2 ) % 3;
|
|
646
|
+
|
|
647
|
+
const dimsD = dims[ d ];
|
|
648
|
+
const dimsU = dims[ u ];
|
|
649
|
+
const dimsV = dims[ v ];
|
|
650
|
+
|
|
651
|
+
const q = [ 0, 0, 0 ];
|
|
652
|
+
const mask = new Int16Array( dimsU * dimsV );
|
|
653
|
+
|
|
654
|
+
q[ d ] = 1;
|
|
655
|
+
|
|
656
|
+
// Sweep through slices
|
|
657
|
+
for ( let slice = 0; slice <= dimsD; slice ++ ) {
|
|
658
|
+
|
|
659
|
+
// Build mask for this slice
|
|
660
|
+
let n = 0;
|
|
661
|
+
|
|
662
|
+
for ( let vv = 0; vv < dimsV; vv ++ ) {
|
|
663
|
+
|
|
664
|
+
for ( let uu = 0; uu < dimsU; uu ++ ) {
|
|
665
|
+
|
|
666
|
+
const pos = [ 0, 0, 0 ];
|
|
667
|
+
pos[ d ] = slice;
|
|
668
|
+
pos[ u ] = uu;
|
|
669
|
+
pos[ v ] = vv;
|
|
670
|
+
|
|
671
|
+
const x0 = pos[ 0 ], y0 = pos[ 1 ], z0 = pos[ 2 ];
|
|
672
|
+
|
|
673
|
+
// Get voxel behind and in front of this face
|
|
674
|
+
const behind = ( slice > 0 ) ? volume[ ( x0 - q[ 0 ] ) + ( y0 - q[ 1 ] ) * sx + ( z0 - q[ 2 ] ) * sx * sy ] : 0;
|
|
675
|
+
const infront = ( slice < dimsD ) ? volume[ x0 + y0 * sx + z0 * sx * sy ] : 0;
|
|
676
|
+
|
|
677
|
+
// Face exists if exactly one side is solid
|
|
678
|
+
if ( behind > 0 && infront === 0 ) {
|
|
679
|
+
|
|
680
|
+
mask[ n ] = behind; // positive face
|
|
681
|
+
|
|
682
|
+
} else if ( infront > 0 && behind === 0 ) {
|
|
683
|
+
|
|
684
|
+
mask[ n ] = - infront; // negative face
|
|
685
|
+
|
|
686
|
+
} else {
|
|
687
|
+
|
|
688
|
+
mask[ n ] = 0;
|
|
689
|
+
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
n ++;
|
|
693
|
+
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
// Greedy merge mask into quads
|
|
699
|
+
n = 0;
|
|
700
|
+
|
|
701
|
+
for ( let vv = 0; vv < dimsV; vv ++ ) {
|
|
702
|
+
|
|
703
|
+
for ( let uu = 0; uu < dimsU; ) {
|
|
704
|
+
|
|
705
|
+
const c = mask[ n ];
|
|
706
|
+
|
|
707
|
+
if ( c !== 0 ) {
|
|
708
|
+
|
|
709
|
+
// Find width
|
|
710
|
+
let w = 1;
|
|
711
|
+
|
|
712
|
+
while ( uu + w < dimsU && mask[ n + w ] === c ) {
|
|
713
|
+
|
|
714
|
+
w ++;
|
|
715
|
+
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Find height
|
|
719
|
+
let h = 1;
|
|
720
|
+
let done = false;
|
|
721
|
+
|
|
722
|
+
while ( vv + h < dimsV && ! done ) {
|
|
723
|
+
|
|
724
|
+
for ( let k = 0; k < w; k ++ ) {
|
|
725
|
+
|
|
726
|
+
if ( mask[ n + k + h * dimsU ] !== c ) {
|
|
727
|
+
|
|
728
|
+
done = true;
|
|
729
|
+
break;
|
|
730
|
+
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
if ( ! done ) h ++;
|
|
736
|
+
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
// Add quad
|
|
740
|
+
const pos = [ 0, 0, 0 ];
|
|
741
|
+
pos[ d ] = slice;
|
|
742
|
+
pos[ u ] = uu;
|
|
743
|
+
pos[ v ] = vv;
|
|
744
|
+
|
|
745
|
+
const du = [ 0, 0, 0 ];
|
|
746
|
+
const dv = [ 0, 0, 0 ];
|
|
747
|
+
du[ u ] = w;
|
|
748
|
+
dv[ v ] = h;
|
|
749
|
+
|
|
750
|
+
// Get color
|
|
751
|
+
const colorIndex = Math.abs( c );
|
|
752
|
+
const hex = palette[ colorIndex ];
|
|
753
|
+
const r = ( hex >> 0 & 0xff ) / 0xff;
|
|
754
|
+
const g = ( hex >> 8 & 0xff ) / 0xff;
|
|
755
|
+
const b = ( hex >> 16 & 0xff ) / 0xff;
|
|
756
|
+
|
|
757
|
+
if ( r > 0 || g > 0 || b > 0 ) hasColors = true;
|
|
758
|
+
|
|
759
|
+
_color.setRGB( r, g, b, SRGBColorSpace );
|
|
760
|
+
|
|
761
|
+
// Convert VOX coords to Three.js coords (Y-up)
|
|
762
|
+
// VOX: X right, Y forward, Z up -> Three.js: X right, Y up, Z back
|
|
763
|
+
const toThree = ( p ) => [
|
|
764
|
+
p[ 0 ] - sx / 2,
|
|
765
|
+
p[ 2 ] - sz / 2,
|
|
766
|
+
- p[ 1 ] + sy / 2
|
|
767
|
+
];
|
|
768
|
+
|
|
769
|
+
const v0 = toThree( pos );
|
|
770
|
+
const v1 = toThree( [ pos[ 0 ] + du[ 0 ], pos[ 1 ] + du[ 1 ], pos[ 2 ] + du[ 2 ] ] );
|
|
771
|
+
const v2 = toThree( [ pos[ 0 ] + du[ 0 ] + dv[ 0 ], pos[ 1 ] + du[ 1 ] + dv[ 1 ], pos[ 2 ] + du[ 2 ] + dv[ 2 ] ] );
|
|
772
|
+
const v3 = toThree( [ pos[ 0 ] + dv[ 0 ], pos[ 1 ] + dv[ 1 ], pos[ 2 ] + dv[ 2 ] ] );
|
|
773
|
+
|
|
774
|
+
const idx = vertices.length / 3;
|
|
775
|
+
|
|
776
|
+
// Winding order depends on face direction
|
|
777
|
+
if ( c > 0 ) {
|
|
778
|
+
|
|
779
|
+
vertices.push( ...v0, ...v1, ...v2, ...v3 );
|
|
780
|
+
indices.push( idx, idx + 1, idx + 2, idx, idx + 2, idx + 3 );
|
|
781
|
+
|
|
782
|
+
} else {
|
|
783
|
+
|
|
784
|
+
vertices.push( ...v0, ...v3, ...v2, ...v1 );
|
|
785
|
+
indices.push( idx, idx + 1, idx + 2, idx, idx + 2, idx + 3 );
|
|
786
|
+
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
colors.push(
|
|
790
|
+
_color.r, _color.g, _color.b,
|
|
791
|
+
_color.r, _color.g, _color.b,
|
|
792
|
+
_color.r, _color.g, _color.b,
|
|
793
|
+
_color.r, _color.g, _color.b
|
|
794
|
+
);
|
|
795
|
+
|
|
796
|
+
// Clear mask
|
|
797
|
+
for ( let hh = 0; hh < h; hh ++ ) {
|
|
798
|
+
|
|
799
|
+
for ( let ww = 0; ww < w; ww ++ ) {
|
|
800
|
+
|
|
801
|
+
mask[ n + ww + hh * dimsU ] = 0;
|
|
802
|
+
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
uu += w;
|
|
808
|
+
n += w;
|
|
809
|
+
|
|
810
|
+
} else {
|
|
811
|
+
|
|
812
|
+
uu ++;
|
|
813
|
+
n ++;
|
|
814
|
+
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
const geometry = new BufferGeometry();
|
|
826
|
+
geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
|
827
|
+
geometry.setIndex( indices );
|
|
828
|
+
geometry.computeVertexNormals();
|
|
829
|
+
|
|
830
|
+
const material = new MeshStandardMaterial();
|
|
831
|
+
|
|
832
|
+
if ( hasColors ) {
|
|
833
|
+
|
|
834
|
+
geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
|
|
835
|
+
material.vertexColors = true;
|
|
836
|
+
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
return new Mesh( geometry, material );
|
|
840
|
+
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Builds a 3D texture from a VOX chunk.
|
|
845
|
+
*
|
|
846
|
+
* @param {Object} chunk - A VOX chunk loaded via {@link VOXLoader}.
|
|
847
|
+
* @return {Data3DTexture} The generated 3D texture.
|
|
848
|
+
*/
|
|
849
|
+
function buildData3DTexture( chunk ) {
|
|
850
|
+
|
|
851
|
+
const data = chunk.data;
|
|
852
|
+
const size = chunk.size;
|
|
853
|
+
|
|
854
|
+
const offsety = size.x;
|
|
855
|
+
const offsetz = size.x * size.y;
|
|
856
|
+
|
|
857
|
+
const array = new Uint8Array( size.x * size.y * size.z );
|
|
858
|
+
|
|
859
|
+
for ( let j = 0; j < data.length; j += 4 ) {
|
|
860
|
+
|
|
861
|
+
const x = data[ j + 0 ];
|
|
862
|
+
const y = data[ j + 1 ];
|
|
863
|
+
const z = data[ j + 2 ];
|
|
864
|
+
|
|
865
|
+
const index = x + ( y * offsety ) + ( z * offsetz );
|
|
866
|
+
|
|
867
|
+
array[ index ] = 255;
|
|
868
|
+
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
const texture = new Data3DTexture( array, size.x, size.y, size.z );
|
|
872
|
+
|
|
873
|
+
texture.format = RedFormat;
|
|
874
|
+
texture.minFilter = NearestFilter;
|
|
875
|
+
texture.magFilter = LinearFilter;
|
|
876
|
+
texture.unpackAlignment = 1;
|
|
877
|
+
texture.needsUpdate = true;
|
|
878
|
+
|
|
879
|
+
return texture;
|
|
880
|
+
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
// @deprecated, r182
|
|
884
|
+
|
|
885
|
+
class VOXMesh extends Mesh {
|
|
886
|
+
|
|
887
|
+
constructor( chunk ) {
|
|
888
|
+
|
|
889
|
+
console.warn( 'VOXMesh has been deprecated. Use buildMesh() instead.' );
|
|
890
|
+
|
|
891
|
+
const mesh = buildMesh( chunk );
|
|
892
|
+
|
|
893
|
+
super( mesh.geometry, mesh.material );
|
|
894
|
+
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
class VOXData3DTexture extends Data3DTexture {
|
|
900
|
+
|
|
901
|
+
constructor( chunk ) {
|
|
902
|
+
|
|
903
|
+
console.warn( 'VOXData3DTexture has been deprecated. Use buildData3DTexture() instead.' );
|
|
904
|
+
|
|
905
|
+
const texture = buildData3DTexture( chunk );
|
|
906
|
+
|
|
907
|
+
super( texture.image.data, texture.image.width, texture.image.height, texture.image.depth );
|
|
908
|
+
|
|
909
|
+
this.format = texture.format;
|
|
910
|
+
this.minFilter = texture.minFilter;
|
|
911
|
+
this.magFilter = texture.magFilter;
|
|
912
|
+
this.unpackAlignment = texture.unpackAlignment;
|
|
913
|
+
this.needsUpdate = true;
|
|
914
|
+
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
export { VOXLoader, buildMesh, buildData3DTexture, VOXMesh, VOXData3DTexture };
|