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,1051 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AddOperation,
|
|
3
|
+
BackSide,
|
|
4
|
+
BufferGeometry,
|
|
5
|
+
ClampToEdgeWrapping,
|
|
6
|
+
Color,
|
|
7
|
+
DoubleSide,
|
|
8
|
+
EquirectangularReflectionMapping,
|
|
9
|
+
EquirectangularRefractionMapping,
|
|
10
|
+
FileLoader,
|
|
11
|
+
Float32BufferAttribute,
|
|
12
|
+
FrontSide,
|
|
13
|
+
LineBasicMaterial,
|
|
14
|
+
LineSegments,
|
|
15
|
+
Loader,
|
|
16
|
+
Mesh,
|
|
17
|
+
MeshPhongMaterial,
|
|
18
|
+
MeshPhysicalMaterial,
|
|
19
|
+
MeshStandardMaterial,
|
|
20
|
+
MirroredRepeatWrapping,
|
|
21
|
+
Points,
|
|
22
|
+
PointsMaterial,
|
|
23
|
+
RepeatWrapping,
|
|
24
|
+
SRGBColorSpace,
|
|
25
|
+
TextureLoader,
|
|
26
|
+
Vector2,
|
|
27
|
+
Vector3
|
|
28
|
+
} from 'three';
|
|
29
|
+
|
|
30
|
+
import { IFFParser } from './lwo/IFFParser.js';
|
|
31
|
+
|
|
32
|
+
let _lwoTree;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A loader for the LWO format.
|
|
36
|
+
*
|
|
37
|
+
* LWO3 and LWO2 formats are supported.
|
|
38
|
+
*
|
|
39
|
+
* References:
|
|
40
|
+
* - [LWO3 format specification](https://static.lightwave3d.com/sdk/2019/html/filefmts/lwo3.html)
|
|
41
|
+
* - [LWO2 format specification](https://static.lightwave3d.com/sdk/2019/html/filefmts/lwo2.html)
|
|
42
|
+
*
|
|
43
|
+
* ```js
|
|
44
|
+
* const loader = new LWOLoader();
|
|
45
|
+
* const lwoData = await loader.loadAsync( 'models/lwo/Objects/LWO3/Demo.lwo' );
|
|
46
|
+
*
|
|
47
|
+
* const mesh = object.meshes[ 0 ];
|
|
48
|
+
* scene.add( mesh );
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @augments Loader
|
|
52
|
+
* @three_import import { LWOLoader } from 'three/addons/loaders/LWOLoader.js';
|
|
53
|
+
* @deprecated since r185.
|
|
54
|
+
*/
|
|
55
|
+
class LWOLoader extends Loader {
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Constructs a new LWO loader.
|
|
59
|
+
*
|
|
60
|
+
* @param {LoadingManager} [manager] - The loading manager.
|
|
61
|
+
* @deprecated since r185.
|
|
62
|
+
*/
|
|
63
|
+
constructor( manager ) {
|
|
64
|
+
|
|
65
|
+
super( manager );
|
|
66
|
+
|
|
67
|
+
console.warn( 'THREE.LWOLoader: The loader has been deprecated and will be removed with r195. Export your LWO files to glTF before using them on the web.' ); // @deprecated, r185
|
|
68
|
+
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Starts loading from the given URL and passes the loaded LWO asset
|
|
73
|
+
* to the `onLoad()` callback.
|
|
74
|
+
*
|
|
75
|
+
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
|
|
76
|
+
* @param {function({meshes:Array<Mesh>,materials:Array<Material>})} onLoad - Executed when the loading process has been finished.
|
|
77
|
+
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
|
|
78
|
+
* @param {onErrorCallback} onError - Executed when errors occur.
|
|
79
|
+
*/
|
|
80
|
+
load( url, onLoad, onProgress, onError ) {
|
|
81
|
+
|
|
82
|
+
const scope = this;
|
|
83
|
+
|
|
84
|
+
const path = ( scope.path === '' ) ? extractParentUrl( url, 'Objects' ) : scope.path;
|
|
85
|
+
|
|
86
|
+
// give the mesh a default name based on the filename
|
|
87
|
+
const modelName = url.split( path ).pop().split( '.' )[ 0 ];
|
|
88
|
+
|
|
89
|
+
const loader = new FileLoader( this.manager );
|
|
90
|
+
loader.setPath( scope.path );
|
|
91
|
+
loader.setResponseType( 'arraybuffer' );
|
|
92
|
+
|
|
93
|
+
loader.load( url, function ( buffer ) {
|
|
94
|
+
|
|
95
|
+
// console.time( 'Total parsing: ' );
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
|
|
99
|
+
onLoad( scope.parse( buffer, path, modelName ) );
|
|
100
|
+
|
|
101
|
+
} catch ( e ) {
|
|
102
|
+
|
|
103
|
+
if ( onError ) {
|
|
104
|
+
|
|
105
|
+
onError( e );
|
|
106
|
+
|
|
107
|
+
} else {
|
|
108
|
+
|
|
109
|
+
console.error( e );
|
|
110
|
+
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
scope.manager.itemError( url );
|
|
114
|
+
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// console.timeEnd( 'Total parsing: ' );
|
|
118
|
+
|
|
119
|
+
}, onProgress, onError );
|
|
120
|
+
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Parses the given LWO data and returns the resulting meshes and materials.
|
|
125
|
+
*
|
|
126
|
+
* @param {ArrayBuffer} iffBuffer - The raw LWO data as an array buffer.
|
|
127
|
+
* @param {string} path - The URL base path.
|
|
128
|
+
* @param {string} modelName - The model name.
|
|
129
|
+
* @return {{meshes:Array<Mesh>,materials:Array<Material>}} An object holding the parse meshes and materials.
|
|
130
|
+
*/
|
|
131
|
+
parse( iffBuffer, path, modelName ) {
|
|
132
|
+
|
|
133
|
+
_lwoTree = new IFFParser().parse( iffBuffer );
|
|
134
|
+
|
|
135
|
+
// console.log( 'lwoTree', lwoTree );
|
|
136
|
+
|
|
137
|
+
const textureLoader = new TextureLoader( this.manager ).setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin );
|
|
138
|
+
|
|
139
|
+
return new LWOTreeParser( textureLoader ).parse( modelName );
|
|
140
|
+
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Parse the lwoTree object
|
|
146
|
+
class LWOTreeParser {
|
|
147
|
+
|
|
148
|
+
constructor( textureLoader ) {
|
|
149
|
+
|
|
150
|
+
this.textureLoader = textureLoader;
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
parse( modelName ) {
|
|
155
|
+
|
|
156
|
+
this.materials = new MaterialParser( this.textureLoader ).parse();
|
|
157
|
+
this.defaultLayerName = modelName;
|
|
158
|
+
|
|
159
|
+
this.meshes = this.parseLayers();
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
materials: this.materials,
|
|
163
|
+
meshes: this.meshes,
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
parseLayers() {
|
|
169
|
+
|
|
170
|
+
// array of all meshes for building hierarchy
|
|
171
|
+
const meshes = [];
|
|
172
|
+
|
|
173
|
+
// final array containing meshes with scene graph hierarchy set up
|
|
174
|
+
const finalMeshes = [];
|
|
175
|
+
|
|
176
|
+
const geometryParser = new GeometryParser();
|
|
177
|
+
|
|
178
|
+
const scope = this;
|
|
179
|
+
_lwoTree.layers.forEach( function ( layer ) {
|
|
180
|
+
|
|
181
|
+
const geometry = geometryParser.parse( layer.geometry, layer );
|
|
182
|
+
|
|
183
|
+
const mesh = scope.parseMesh( geometry, layer );
|
|
184
|
+
|
|
185
|
+
meshes[ layer.number ] = mesh;
|
|
186
|
+
|
|
187
|
+
if ( layer.parent === - 1 ) finalMeshes.push( mesh );
|
|
188
|
+
else meshes[ layer.parent ].add( mesh );
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
} );
|
|
192
|
+
|
|
193
|
+
return finalMeshes;
|
|
194
|
+
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
parseMesh( geometry, layer ) {
|
|
198
|
+
|
|
199
|
+
let mesh;
|
|
200
|
+
|
|
201
|
+
const materials = this.getMaterials( geometry.userData.matNames, layer.geometry.type );
|
|
202
|
+
|
|
203
|
+
if ( layer.geometry.type === 'points' ) mesh = new Points( geometry, materials );
|
|
204
|
+
else if ( layer.geometry.type === 'lines' ) mesh = new LineSegments( geometry, materials );
|
|
205
|
+
else mesh = new Mesh( geometry, materials );
|
|
206
|
+
|
|
207
|
+
if ( layer.name ) mesh.name = layer.name;
|
|
208
|
+
else mesh.name = this.defaultLayerName + '_layer_' + layer.number;
|
|
209
|
+
|
|
210
|
+
const pivot = layer.pivot;
|
|
211
|
+
if ( pivot[ 0 ] !== 0 || pivot[ 1 ] !== 0 || pivot[ 2 ] !== 0 ) {
|
|
212
|
+
|
|
213
|
+
mesh.pivot = new Vector3( pivot[ 0 ], pivot[ 1 ], pivot[ 2 ] );
|
|
214
|
+
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return mesh;
|
|
218
|
+
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
getMaterials( namesArray, type ) {
|
|
222
|
+
|
|
223
|
+
const materials = [];
|
|
224
|
+
|
|
225
|
+
const scope = this;
|
|
226
|
+
|
|
227
|
+
namesArray.forEach( function ( name, i ) {
|
|
228
|
+
|
|
229
|
+
materials[ i ] = scope.getMaterialByName( name );
|
|
230
|
+
|
|
231
|
+
} );
|
|
232
|
+
|
|
233
|
+
// convert materials to line or point mats if required
|
|
234
|
+
if ( type === 'points' || type === 'lines' ) {
|
|
235
|
+
|
|
236
|
+
materials.forEach( function ( mat, i ) {
|
|
237
|
+
|
|
238
|
+
const spec = {
|
|
239
|
+
color: mat.color,
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
if ( type === 'points' ) {
|
|
243
|
+
|
|
244
|
+
spec.size = 0.1;
|
|
245
|
+
spec.map = mat.map;
|
|
246
|
+
materials[ i ] = new PointsMaterial( spec );
|
|
247
|
+
|
|
248
|
+
} else if ( type === 'lines' ) {
|
|
249
|
+
|
|
250
|
+
materials[ i ] = new LineBasicMaterial( spec );
|
|
251
|
+
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
} );
|
|
255
|
+
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// if there is only one material, return that directly instead of array
|
|
259
|
+
const filtered = materials.filter( Boolean );
|
|
260
|
+
if ( filtered.length === 1 ) return filtered[ 0 ];
|
|
261
|
+
|
|
262
|
+
return materials;
|
|
263
|
+
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
getMaterialByName( name ) {
|
|
267
|
+
|
|
268
|
+
return this.materials.filter( function ( m ) {
|
|
269
|
+
|
|
270
|
+
return m.name === name;
|
|
271
|
+
|
|
272
|
+
} )[ 0 ];
|
|
273
|
+
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
class MaterialParser {
|
|
279
|
+
|
|
280
|
+
constructor( textureLoader ) {
|
|
281
|
+
|
|
282
|
+
this.textureLoader = textureLoader;
|
|
283
|
+
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
parse() {
|
|
287
|
+
|
|
288
|
+
const materials = [];
|
|
289
|
+
this.textures = {};
|
|
290
|
+
|
|
291
|
+
for ( const name in _lwoTree.materials ) {
|
|
292
|
+
|
|
293
|
+
if ( _lwoTree.format === 'LWO3' ) {
|
|
294
|
+
|
|
295
|
+
materials.push( this.parseMaterial( _lwoTree.materials[ name ], name, _lwoTree.textures ) );
|
|
296
|
+
|
|
297
|
+
} else if ( _lwoTree.format === 'LWO2' ) {
|
|
298
|
+
|
|
299
|
+
materials.push( this.parseMaterialLwo2( _lwoTree.materials[ name ], name, _lwoTree.textures ) );
|
|
300
|
+
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return materials;
|
|
306
|
+
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
parseMaterial( materialData, name, textures ) {
|
|
310
|
+
|
|
311
|
+
let params = {
|
|
312
|
+
name: name,
|
|
313
|
+
side: this.getSide( materialData.attributes ),
|
|
314
|
+
flatShading: this.getSmooth( materialData.attributes ),
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
const connections = this.parseConnections( materialData.connections, materialData.nodes );
|
|
318
|
+
|
|
319
|
+
const maps = this.parseTextureNodes( connections.maps );
|
|
320
|
+
|
|
321
|
+
this.parseAttributeImageMaps( connections.attributes, textures, maps );
|
|
322
|
+
|
|
323
|
+
const attributes = this.parseAttributes( connections.attributes, maps );
|
|
324
|
+
|
|
325
|
+
this.parseEnvMap( connections, maps, attributes );
|
|
326
|
+
|
|
327
|
+
params = Object.assign( maps, params );
|
|
328
|
+
params = Object.assign( params, attributes );
|
|
329
|
+
|
|
330
|
+
const materialType = this.getMaterialType( connections.attributes );
|
|
331
|
+
|
|
332
|
+
if ( materialType !== MeshPhongMaterial ) delete params.refractionRatio; // PBR materials do not support "refractionRatio"
|
|
333
|
+
|
|
334
|
+
return new materialType( params );
|
|
335
|
+
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
parseMaterialLwo2( materialData, name/*, textures*/ ) {
|
|
339
|
+
|
|
340
|
+
let params = {
|
|
341
|
+
name: name,
|
|
342
|
+
side: this.getSide( materialData.attributes ),
|
|
343
|
+
flatShading: this.getSmooth( materialData.attributes ),
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
const attributes = this.parseAttributes( materialData.attributes, {} );
|
|
347
|
+
params = Object.assign( params, attributes );
|
|
348
|
+
return new MeshPhongMaterial( params );
|
|
349
|
+
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Note: converting from left to right handed coords by switching x -> -x in vertices, and
|
|
353
|
+
// then switching mat FrontSide -> BackSide
|
|
354
|
+
// NB: this means that FrontSide and BackSide have been switched!
|
|
355
|
+
getSide( attributes ) {
|
|
356
|
+
|
|
357
|
+
if ( ! attributes.side ) return BackSide;
|
|
358
|
+
|
|
359
|
+
switch ( attributes.side ) {
|
|
360
|
+
|
|
361
|
+
case 0:
|
|
362
|
+
case 1:
|
|
363
|
+
return BackSide;
|
|
364
|
+
case 2: return FrontSide;
|
|
365
|
+
case 3: return DoubleSide;
|
|
366
|
+
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
getSmooth( attributes ) {
|
|
372
|
+
|
|
373
|
+
if ( ! attributes.smooth ) return true;
|
|
374
|
+
return ! attributes.smooth;
|
|
375
|
+
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
parseConnections( connections, nodes ) {
|
|
379
|
+
|
|
380
|
+
const materialConnections = {
|
|
381
|
+
maps: {}
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
const inputName = connections.inputName;
|
|
385
|
+
const inputNodeName = connections.inputNodeName;
|
|
386
|
+
const nodeName = connections.nodeName;
|
|
387
|
+
|
|
388
|
+
const scope = this;
|
|
389
|
+
inputName.forEach( function ( name, index ) {
|
|
390
|
+
|
|
391
|
+
if ( name === 'Material' ) {
|
|
392
|
+
|
|
393
|
+
const matNode = scope.getNodeByRefName( inputNodeName[ index ], nodes );
|
|
394
|
+
materialConnections.attributes = matNode.attributes;
|
|
395
|
+
materialConnections.envMap = matNode.fileName;
|
|
396
|
+
materialConnections.name = inputNodeName[ index ];
|
|
397
|
+
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
} );
|
|
401
|
+
|
|
402
|
+
nodeName.forEach( function ( name, index ) {
|
|
403
|
+
|
|
404
|
+
if ( name === materialConnections.name ) {
|
|
405
|
+
|
|
406
|
+
materialConnections.maps[ inputName[ index ] ] = scope.getNodeByRefName( inputNodeName[ index ], nodes );
|
|
407
|
+
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
} );
|
|
411
|
+
|
|
412
|
+
return materialConnections;
|
|
413
|
+
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
getNodeByRefName( refName, nodes ) {
|
|
417
|
+
|
|
418
|
+
for ( const name in nodes ) {
|
|
419
|
+
|
|
420
|
+
if ( nodes[ name ].refName === refName ) return nodes[ name ];
|
|
421
|
+
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
parseTextureNodes( textureNodes ) {
|
|
427
|
+
|
|
428
|
+
const maps = {};
|
|
429
|
+
|
|
430
|
+
for ( const name in textureNodes ) {
|
|
431
|
+
|
|
432
|
+
const node = textureNodes[ name ];
|
|
433
|
+
const path = node.fileName;
|
|
434
|
+
|
|
435
|
+
if ( ! path ) return;
|
|
436
|
+
|
|
437
|
+
const texture = this.loadTexture( path );
|
|
438
|
+
|
|
439
|
+
if ( node.widthWrappingMode !== undefined ) texture.wrapS = this.getWrappingType( node.widthWrappingMode );
|
|
440
|
+
if ( node.heightWrappingMode !== undefined ) texture.wrapT = this.getWrappingType( node.heightWrappingMode );
|
|
441
|
+
|
|
442
|
+
switch ( name ) {
|
|
443
|
+
|
|
444
|
+
case 'Color':
|
|
445
|
+
maps.map = texture;
|
|
446
|
+
maps.map.colorSpace = SRGBColorSpace;
|
|
447
|
+
break;
|
|
448
|
+
case 'Roughness':
|
|
449
|
+
maps.roughnessMap = texture;
|
|
450
|
+
maps.roughness = 1;
|
|
451
|
+
break;
|
|
452
|
+
case 'Specular':
|
|
453
|
+
maps.specularMap = texture;
|
|
454
|
+
maps.specularMap.colorSpace = SRGBColorSpace;
|
|
455
|
+
maps.specular = 0xffffff;
|
|
456
|
+
break;
|
|
457
|
+
case 'Luminous':
|
|
458
|
+
maps.emissiveMap = texture;
|
|
459
|
+
maps.emissiveMap.colorSpace = SRGBColorSpace;
|
|
460
|
+
maps.emissive = 0x808080;
|
|
461
|
+
break;
|
|
462
|
+
case 'Luminous Color':
|
|
463
|
+
maps.emissive = 0x808080;
|
|
464
|
+
break;
|
|
465
|
+
case 'Metallic':
|
|
466
|
+
maps.metalnessMap = texture;
|
|
467
|
+
maps.metalness = 1;
|
|
468
|
+
break;
|
|
469
|
+
case 'Transparency':
|
|
470
|
+
case 'Alpha':
|
|
471
|
+
maps.alphaMap = texture;
|
|
472
|
+
maps.transparent = true;
|
|
473
|
+
break;
|
|
474
|
+
case 'Normal':
|
|
475
|
+
maps.normalMap = texture;
|
|
476
|
+
if ( node.amplitude !== undefined ) maps.normalScale = new Vector2( node.amplitude, node.amplitude );
|
|
477
|
+
break;
|
|
478
|
+
case 'Bump':
|
|
479
|
+
maps.bumpMap = texture;
|
|
480
|
+
break;
|
|
481
|
+
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// LWO BSDF materials can have both spec and rough, but this is not valid in three
|
|
487
|
+
if ( maps.roughnessMap && maps.specularMap ) delete maps.specularMap;
|
|
488
|
+
|
|
489
|
+
return maps;
|
|
490
|
+
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// maps can also be defined on individual material attributes, parse those here
|
|
494
|
+
// This occurs on Standard (Phong) surfaces
|
|
495
|
+
parseAttributeImageMaps( attributes, textures, maps ) {
|
|
496
|
+
|
|
497
|
+
for ( const name in attributes ) {
|
|
498
|
+
|
|
499
|
+
const attribute = attributes[ name ];
|
|
500
|
+
|
|
501
|
+
if ( attribute.maps ) {
|
|
502
|
+
|
|
503
|
+
const mapData = attribute.maps[ 0 ];
|
|
504
|
+
|
|
505
|
+
const path = this.getTexturePathByIndex( mapData.imageIndex );
|
|
506
|
+
if ( ! path ) return;
|
|
507
|
+
|
|
508
|
+
const texture = this.loadTexture( path );
|
|
509
|
+
|
|
510
|
+
if ( mapData.wrap !== undefined ) texture.wrapS = this.getWrappingType( mapData.wrap.w );
|
|
511
|
+
if ( mapData.wrap !== undefined ) texture.wrapT = this.getWrappingType( mapData.wrap.h );
|
|
512
|
+
|
|
513
|
+
switch ( name ) {
|
|
514
|
+
|
|
515
|
+
case 'Color':
|
|
516
|
+
maps.map = texture;
|
|
517
|
+
maps.map.colorSpace = SRGBColorSpace;
|
|
518
|
+
break;
|
|
519
|
+
case 'Diffuse':
|
|
520
|
+
maps.aoMap = texture;
|
|
521
|
+
break;
|
|
522
|
+
case 'Roughness':
|
|
523
|
+
maps.roughnessMap = texture;
|
|
524
|
+
maps.roughness = 1;
|
|
525
|
+
break;
|
|
526
|
+
case 'Specular':
|
|
527
|
+
maps.specularMap = texture;
|
|
528
|
+
maps.specularMap.colorSpace = SRGBColorSpace;
|
|
529
|
+
maps.specular = 0xffffff;
|
|
530
|
+
break;
|
|
531
|
+
case 'Luminosity':
|
|
532
|
+
maps.emissiveMap = texture;
|
|
533
|
+
maps.emissiveMap.colorSpace = SRGBColorSpace;
|
|
534
|
+
maps.emissive = 0x808080;
|
|
535
|
+
break;
|
|
536
|
+
case 'Metallic':
|
|
537
|
+
maps.metalnessMap = texture;
|
|
538
|
+
maps.metalness = 1;
|
|
539
|
+
break;
|
|
540
|
+
case 'Transparency':
|
|
541
|
+
case 'Alpha':
|
|
542
|
+
maps.alphaMap = texture;
|
|
543
|
+
maps.transparent = true;
|
|
544
|
+
break;
|
|
545
|
+
case 'Normal':
|
|
546
|
+
maps.normalMap = texture;
|
|
547
|
+
break;
|
|
548
|
+
case 'Bump':
|
|
549
|
+
maps.bumpMap = texture;
|
|
550
|
+
break;
|
|
551
|
+
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
parseAttributes( attributes, maps ) {
|
|
561
|
+
|
|
562
|
+
const params = {};
|
|
563
|
+
|
|
564
|
+
// don't use color data if color map is present
|
|
565
|
+
if ( attributes.Color && ! maps.map ) {
|
|
566
|
+
|
|
567
|
+
params.color = new Color().fromArray( attributes.Color.value );
|
|
568
|
+
|
|
569
|
+
} else {
|
|
570
|
+
|
|
571
|
+
params.color = new Color();
|
|
572
|
+
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
if ( attributes.Transparency && attributes.Transparency.value !== 0 ) {
|
|
577
|
+
|
|
578
|
+
params.opacity = 1 - attributes.Transparency.value;
|
|
579
|
+
params.transparent = true;
|
|
580
|
+
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if ( attributes[ 'Bump Height' ] ) params.bumpScale = attributes[ 'Bump Height' ].value * 0.1;
|
|
584
|
+
|
|
585
|
+
this.parsePhysicalAttributes( params, attributes, maps );
|
|
586
|
+
this.parseStandardAttributes( params, attributes, maps );
|
|
587
|
+
this.parsePhongAttributes( params, attributes, maps );
|
|
588
|
+
|
|
589
|
+
return params;
|
|
590
|
+
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
parsePhysicalAttributes( params, attributes/*, maps*/ ) {
|
|
594
|
+
|
|
595
|
+
if ( attributes.Clearcoat && attributes.Clearcoat.value > 0 ) {
|
|
596
|
+
|
|
597
|
+
params.clearcoat = attributes.Clearcoat.value;
|
|
598
|
+
|
|
599
|
+
if ( attributes[ 'Clearcoat Gloss' ] ) {
|
|
600
|
+
|
|
601
|
+
params.clearcoatRoughness = 0.5 * ( 1 - attributes[ 'Clearcoat Gloss' ].value );
|
|
602
|
+
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
parseStandardAttributes( params, attributes, maps ) {
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
if ( attributes.Luminous ) {
|
|
613
|
+
|
|
614
|
+
params.emissiveIntensity = attributes.Luminous.value;
|
|
615
|
+
|
|
616
|
+
if ( attributes[ 'Luminous Color' ] && ! maps.emissive ) {
|
|
617
|
+
|
|
618
|
+
params.emissive = new Color().fromArray( attributes[ 'Luminous Color' ].value );
|
|
619
|
+
|
|
620
|
+
} else {
|
|
621
|
+
|
|
622
|
+
params.emissive = new Color( 0x808080 );
|
|
623
|
+
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
if ( attributes.Roughness && ! maps.roughnessMap ) params.roughness = attributes.Roughness.value;
|
|
629
|
+
if ( attributes.Metallic && ! maps.metalnessMap ) params.metalness = attributes.Metallic.value;
|
|
630
|
+
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
parsePhongAttributes( params, attributes, maps ) {
|
|
634
|
+
|
|
635
|
+
if ( attributes[ 'Refraction Index' ] ) params.refractionRatio = 0.98 / attributes[ 'Refraction Index' ].value;
|
|
636
|
+
|
|
637
|
+
if ( attributes.Diffuse ) params.color.multiplyScalar( attributes.Diffuse.value );
|
|
638
|
+
|
|
639
|
+
if ( attributes.Reflection ) {
|
|
640
|
+
|
|
641
|
+
params.reflectivity = attributes.Reflection.value;
|
|
642
|
+
params.combine = AddOperation;
|
|
643
|
+
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
if ( attributes.Luminosity ) {
|
|
647
|
+
|
|
648
|
+
params.emissiveIntensity = attributes.Luminosity.value;
|
|
649
|
+
|
|
650
|
+
if ( ! maps.emissiveMap && ! maps.map ) {
|
|
651
|
+
|
|
652
|
+
params.emissive = params.color;
|
|
653
|
+
|
|
654
|
+
} else {
|
|
655
|
+
|
|
656
|
+
params.emissive = new Color( 0x808080 );
|
|
657
|
+
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// parse specular if there is no roughness - we will interpret the material as 'Phong' in this case
|
|
663
|
+
if ( ! attributes.Roughness && attributes.Specular && ! maps.specularMap ) {
|
|
664
|
+
|
|
665
|
+
if ( attributes[ 'Color Highlight' ] ) {
|
|
666
|
+
|
|
667
|
+
params.specular = new Color().setScalar( attributes.Specular.value ).lerp( params.color.clone().multiplyScalar( attributes.Specular.value ), attributes[ 'Color Highlight' ].value );
|
|
668
|
+
|
|
669
|
+
} else {
|
|
670
|
+
|
|
671
|
+
params.specular = new Color().setScalar( attributes.Specular.value );
|
|
672
|
+
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
if ( params.specular && attributes.Glossiness ) params.shininess = 7 + Math.pow( 2, attributes.Glossiness.value * 12 + 2 );
|
|
678
|
+
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
parseEnvMap( connections, maps, attributes ) {
|
|
682
|
+
|
|
683
|
+
if ( connections.envMap ) {
|
|
684
|
+
|
|
685
|
+
const envMap = this.loadTexture( connections.envMap );
|
|
686
|
+
|
|
687
|
+
if ( attributes.transparent && attributes.opacity < 0.999 ) {
|
|
688
|
+
|
|
689
|
+
envMap.mapping = EquirectangularRefractionMapping;
|
|
690
|
+
|
|
691
|
+
// Reflectivity and refraction mapping don't work well together in Phong materials
|
|
692
|
+
if ( attributes.reflectivity !== undefined ) {
|
|
693
|
+
|
|
694
|
+
delete attributes.reflectivity;
|
|
695
|
+
delete attributes.combine;
|
|
696
|
+
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
if ( attributes.metalness !== undefined ) {
|
|
700
|
+
|
|
701
|
+
attributes.metalness = 1; // For most transparent materials metalness should be set to 1 if not otherwise defined. If set to 0 no refraction will be visible
|
|
702
|
+
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
attributes.opacity = 1; // transparency fades out refraction, forcing opacity to 1 ensures a closer visual match to the material in Lightwave.
|
|
706
|
+
|
|
707
|
+
} else envMap.mapping = EquirectangularReflectionMapping;
|
|
708
|
+
|
|
709
|
+
maps.envMap = envMap;
|
|
710
|
+
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// get texture defined at top level by its index
|
|
716
|
+
getTexturePathByIndex( index ) {
|
|
717
|
+
|
|
718
|
+
let fileName = '';
|
|
719
|
+
|
|
720
|
+
if ( ! _lwoTree.textures ) return fileName;
|
|
721
|
+
|
|
722
|
+
_lwoTree.textures.forEach( function ( texture ) {
|
|
723
|
+
|
|
724
|
+
if ( texture.index === index ) fileName = texture.fileName;
|
|
725
|
+
|
|
726
|
+
} );
|
|
727
|
+
|
|
728
|
+
return fileName;
|
|
729
|
+
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
loadTexture( path ) {
|
|
733
|
+
|
|
734
|
+
if ( ! path ) return null;
|
|
735
|
+
|
|
736
|
+
const texture = this.textureLoader.load(
|
|
737
|
+
path,
|
|
738
|
+
undefined,
|
|
739
|
+
undefined,
|
|
740
|
+
function () {
|
|
741
|
+
|
|
742
|
+
console.warn( 'LWOLoader: non-standard resource hierarchy. Use \`resourcePath\` parameter to specify root content directory.' );
|
|
743
|
+
|
|
744
|
+
}
|
|
745
|
+
);
|
|
746
|
+
|
|
747
|
+
return texture;
|
|
748
|
+
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// 0 = Reset, 1 = Repeat, 2 = Mirror, 3 = Edge
|
|
752
|
+
getWrappingType( num ) {
|
|
753
|
+
|
|
754
|
+
switch ( num ) {
|
|
755
|
+
|
|
756
|
+
case 0:
|
|
757
|
+
console.warn( 'LWOLoader: "Reset" texture wrapping type is not supported in three.js' );
|
|
758
|
+
return ClampToEdgeWrapping;
|
|
759
|
+
case 1: return RepeatWrapping;
|
|
760
|
+
case 2: return MirroredRepeatWrapping;
|
|
761
|
+
case 3: return ClampToEdgeWrapping;
|
|
762
|
+
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
getMaterialType( nodeData ) {
|
|
768
|
+
|
|
769
|
+
if ( nodeData.Clearcoat && nodeData.Clearcoat.value > 0 ) return MeshPhysicalMaterial;
|
|
770
|
+
if ( nodeData.Roughness ) return MeshStandardMaterial;
|
|
771
|
+
return MeshPhongMaterial;
|
|
772
|
+
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
class GeometryParser {
|
|
778
|
+
|
|
779
|
+
parse( geoData, layer ) {
|
|
780
|
+
|
|
781
|
+
const geometry = new BufferGeometry();
|
|
782
|
+
|
|
783
|
+
geometry.setAttribute( 'position', new Float32BufferAttribute( geoData.points, 3 ) );
|
|
784
|
+
|
|
785
|
+
const indices = this.splitIndices( geoData.vertexIndices, geoData.polygonDimensions );
|
|
786
|
+
geometry.setIndex( indices );
|
|
787
|
+
|
|
788
|
+
this.parseGroups( geometry, geoData );
|
|
789
|
+
|
|
790
|
+
geometry.computeVertexNormals();
|
|
791
|
+
|
|
792
|
+
this.parseUVs( geometry, layer );
|
|
793
|
+
this.parseMorphTargets( geometry, layer );
|
|
794
|
+
|
|
795
|
+
return geometry;
|
|
796
|
+
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// split quads into tris
|
|
800
|
+
splitIndices( indices, polygonDimensions ) {
|
|
801
|
+
|
|
802
|
+
const remappedIndices = [];
|
|
803
|
+
|
|
804
|
+
let i = 0;
|
|
805
|
+
polygonDimensions.forEach( function ( dim ) {
|
|
806
|
+
|
|
807
|
+
if ( dim < 4 ) {
|
|
808
|
+
|
|
809
|
+
for ( let k = 0; k < dim; k ++ ) remappedIndices.push( indices[ i + k ] );
|
|
810
|
+
|
|
811
|
+
} else if ( dim === 4 ) {
|
|
812
|
+
|
|
813
|
+
remappedIndices.push(
|
|
814
|
+
indices[ i ],
|
|
815
|
+
indices[ i + 1 ],
|
|
816
|
+
indices[ i + 2 ],
|
|
817
|
+
|
|
818
|
+
indices[ i ],
|
|
819
|
+
indices[ i + 2 ],
|
|
820
|
+
indices[ i + 3 ]
|
|
821
|
+
|
|
822
|
+
);
|
|
823
|
+
|
|
824
|
+
} else if ( dim > 4 ) {
|
|
825
|
+
|
|
826
|
+
for ( let k = 1; k < dim - 1; k ++ ) {
|
|
827
|
+
|
|
828
|
+
remappedIndices.push( indices[ i ], indices[ i + k ], indices[ i + k + 1 ] );
|
|
829
|
+
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
console.warn( 'LWOLoader: polygons with greater than 4 sides are not supported' );
|
|
833
|
+
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
i += dim;
|
|
837
|
+
|
|
838
|
+
} );
|
|
839
|
+
|
|
840
|
+
return remappedIndices;
|
|
841
|
+
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// NOTE: currently ignoring poly indices and assuming that they are intelligently ordered
|
|
845
|
+
parseGroups( geometry, geoData ) {
|
|
846
|
+
|
|
847
|
+
const tags = _lwoTree.tags;
|
|
848
|
+
const matNames = [];
|
|
849
|
+
|
|
850
|
+
let elemSize = 3;
|
|
851
|
+
if ( geoData.type === 'lines' ) elemSize = 2;
|
|
852
|
+
if ( geoData.type === 'points' ) elemSize = 1;
|
|
853
|
+
|
|
854
|
+
const remappedIndices = this.splitMaterialIndices( geoData.polygonDimensions, geoData.materialIndices );
|
|
855
|
+
|
|
856
|
+
let indexNum = 0; // create new indices in numerical order
|
|
857
|
+
const indexPairs = {}; // original indices mapped to numerical indices
|
|
858
|
+
|
|
859
|
+
let prevMaterialIndex;
|
|
860
|
+
let materialIndex;
|
|
861
|
+
|
|
862
|
+
let prevStart = 0;
|
|
863
|
+
let currentCount = 0;
|
|
864
|
+
|
|
865
|
+
for ( let i = 0; i < remappedIndices.length; i += 2 ) {
|
|
866
|
+
|
|
867
|
+
materialIndex = remappedIndices[ i + 1 ];
|
|
868
|
+
|
|
869
|
+
if ( i === 0 ) matNames[ indexNum ] = tags[ materialIndex ];
|
|
870
|
+
|
|
871
|
+
if ( prevMaterialIndex === undefined ) prevMaterialIndex = materialIndex;
|
|
872
|
+
|
|
873
|
+
if ( materialIndex !== prevMaterialIndex ) {
|
|
874
|
+
|
|
875
|
+
let currentIndex;
|
|
876
|
+
if ( indexPairs[ tags[ prevMaterialIndex ] ] ) {
|
|
877
|
+
|
|
878
|
+
currentIndex = indexPairs[ tags[ prevMaterialIndex ] ];
|
|
879
|
+
|
|
880
|
+
} else {
|
|
881
|
+
|
|
882
|
+
currentIndex = indexNum;
|
|
883
|
+
indexPairs[ tags[ prevMaterialIndex ] ] = indexNum;
|
|
884
|
+
matNames[ indexNum ] = tags[ prevMaterialIndex ];
|
|
885
|
+
indexNum ++;
|
|
886
|
+
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
geometry.addGroup( prevStart, currentCount, currentIndex );
|
|
890
|
+
|
|
891
|
+
prevStart += currentCount;
|
|
892
|
+
|
|
893
|
+
prevMaterialIndex = materialIndex;
|
|
894
|
+
currentCount = 0;
|
|
895
|
+
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
currentCount += elemSize;
|
|
899
|
+
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// the loop above doesn't add the last group, do that here.
|
|
903
|
+
if ( geometry.groups.length > 0 ) {
|
|
904
|
+
|
|
905
|
+
let currentIndex;
|
|
906
|
+
if ( indexPairs[ tags[ materialIndex ] ] ) {
|
|
907
|
+
|
|
908
|
+
currentIndex = indexPairs[ tags[ materialIndex ] ];
|
|
909
|
+
|
|
910
|
+
} else {
|
|
911
|
+
|
|
912
|
+
currentIndex = indexNum;
|
|
913
|
+
indexPairs[ tags[ materialIndex ] ] = indexNum;
|
|
914
|
+
matNames[ indexNum ] = tags[ materialIndex ];
|
|
915
|
+
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
geometry.addGroup( prevStart, currentCount, currentIndex );
|
|
919
|
+
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
// Mat names from TAGS chunk, used to build up an array of materials for this geometry
|
|
923
|
+
geometry.userData.matNames = matNames;
|
|
924
|
+
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
splitMaterialIndices( polygonDimensions, indices ) {
|
|
928
|
+
|
|
929
|
+
const remappedIndices = [];
|
|
930
|
+
|
|
931
|
+
polygonDimensions.forEach( function ( dim, i ) {
|
|
932
|
+
|
|
933
|
+
if ( dim <= 3 ) {
|
|
934
|
+
|
|
935
|
+
remappedIndices.push( indices[ i * 2 ], indices[ i * 2 + 1 ] );
|
|
936
|
+
|
|
937
|
+
} else if ( dim === 4 ) {
|
|
938
|
+
|
|
939
|
+
remappedIndices.push( indices[ i * 2 ], indices[ i * 2 + 1 ], indices[ i * 2 ], indices[ i * 2 + 1 ] );
|
|
940
|
+
|
|
941
|
+
} else {
|
|
942
|
+
|
|
943
|
+
// ignore > 4 for now
|
|
944
|
+
for ( let k = 0; k < dim - 2; k ++ ) {
|
|
945
|
+
|
|
946
|
+
remappedIndices.push( indices[ i * 2 ], indices[ i * 2 + 1 ] );
|
|
947
|
+
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
} );
|
|
953
|
+
|
|
954
|
+
return remappedIndices;
|
|
955
|
+
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
// UV maps:
|
|
959
|
+
// 1: are defined via index into an array of points, not into a geometry
|
|
960
|
+
// - the geometry is also defined by an index into this array, but the indexes may not match
|
|
961
|
+
// 2: there can be any number of UV maps for a single geometry. Here these are combined,
|
|
962
|
+
// with preference given to the first map encountered
|
|
963
|
+
// 3: UV maps can be partial - that is, defined for only a part of the geometry
|
|
964
|
+
// 4: UV maps can be VMAP or VMAD (discontinuous, to allow for seams). In practice, most
|
|
965
|
+
// UV maps are defined as partially VMAP and partially VMAD
|
|
966
|
+
// VMADs are currently not supported
|
|
967
|
+
parseUVs( geometry, layer ) {
|
|
968
|
+
|
|
969
|
+
// start by creating a UV map set to zero for the whole geometry
|
|
970
|
+
const remappedUVs = Array.from( Array( geometry.attributes.position.count * 2 ), function () {
|
|
971
|
+
|
|
972
|
+
return 0;
|
|
973
|
+
|
|
974
|
+
} );
|
|
975
|
+
|
|
976
|
+
for ( const name in layer.uvs ) {
|
|
977
|
+
|
|
978
|
+
const uvs = layer.uvs[ name ].uvs;
|
|
979
|
+
const uvIndices = layer.uvs[ name ].uvIndices;
|
|
980
|
+
|
|
981
|
+
uvIndices.forEach( function ( i, j ) {
|
|
982
|
+
|
|
983
|
+
remappedUVs[ i * 2 ] = uvs[ j * 2 ];
|
|
984
|
+
remappedUVs[ i * 2 + 1 ] = uvs[ j * 2 + 1 ];
|
|
985
|
+
|
|
986
|
+
} );
|
|
987
|
+
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
geometry.setAttribute( 'uv', new Float32BufferAttribute( remappedUVs, 2 ) );
|
|
991
|
+
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
parseMorphTargets( geometry, layer ) {
|
|
995
|
+
|
|
996
|
+
let num = 0;
|
|
997
|
+
for ( const name in layer.morphTargets ) {
|
|
998
|
+
|
|
999
|
+
const remappedPoints = geometry.attributes.position.array.slice();
|
|
1000
|
+
|
|
1001
|
+
if ( ! geometry.morphAttributes.position ) geometry.morphAttributes.position = [];
|
|
1002
|
+
|
|
1003
|
+
const morphPoints = layer.morphTargets[ name ].points;
|
|
1004
|
+
const morphIndices = layer.morphTargets[ name ].indices;
|
|
1005
|
+
const type = layer.morphTargets[ name ].type;
|
|
1006
|
+
|
|
1007
|
+
morphIndices.forEach( function ( i, j ) {
|
|
1008
|
+
|
|
1009
|
+
if ( type === 'relative' ) {
|
|
1010
|
+
|
|
1011
|
+
remappedPoints[ i * 3 ] += morphPoints[ j * 3 ];
|
|
1012
|
+
remappedPoints[ i * 3 + 1 ] += morphPoints[ j * 3 + 1 ];
|
|
1013
|
+
remappedPoints[ i * 3 + 2 ] += morphPoints[ j * 3 + 2 ];
|
|
1014
|
+
|
|
1015
|
+
} else {
|
|
1016
|
+
|
|
1017
|
+
remappedPoints[ i * 3 ] = morphPoints[ j * 3 ];
|
|
1018
|
+
remappedPoints[ i * 3 + 1 ] = morphPoints[ j * 3 + 1 ];
|
|
1019
|
+
remappedPoints[ i * 3 + 2 ] = morphPoints[ j * 3 + 2 ];
|
|
1020
|
+
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
} );
|
|
1024
|
+
|
|
1025
|
+
geometry.morphAttributes.position[ num ] = new Float32BufferAttribute( remappedPoints, 3 );
|
|
1026
|
+
geometry.morphAttributes.position[ num ].name = name;
|
|
1027
|
+
|
|
1028
|
+
num ++;
|
|
1029
|
+
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
geometry.morphTargetsRelative = false;
|
|
1033
|
+
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
|
|
1039
|
+
// ************** UTILITY FUNCTIONS **************
|
|
1040
|
+
|
|
1041
|
+
function extractParentUrl( url, dir ) {
|
|
1042
|
+
|
|
1043
|
+
const index = url.indexOf( dir );
|
|
1044
|
+
|
|
1045
|
+
if ( index === - 1 ) return './';
|
|
1046
|
+
|
|
1047
|
+
return url.slice( 0, index );
|
|
1048
|
+
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
export { LWOLoader };
|