@needle-tools/materialx 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/bin/.gitattributes +4 -0
- package/bin/README.md +6 -0
- package/{index.ts → index.d.ts} +1 -1
- package/index.js +2 -0
- package/{needle.ts → needle.d.ts} +1 -1
- package/needle.js +2 -0
- package/package.json +24 -10
- package/src/index.d.ts +11 -0
- package/src/index.js +11 -0
- package/src/loader/loader.needle.d.ts +15 -0
- package/src/loader/loader.needle.js +62 -0
- package/src/loader/loader.three.d.ts +71 -0
- package/src/loader/loader.three.js +334 -0
- package/src/materialx.d.ts +60 -0
- package/src/materialx.helper.d.ts +31 -0
- package/src/{materialx.helper.ts → materialx.helper.js} +149 -101
- package/src/{materialx.ts → materialx.js} +115 -64
- package/src/materialx.material.d.ts +37 -0
- package/src/{materialx.material.ts → materialx.material.js} +110 -40
- package/src/utils.d.ts +17 -0
- package/src/{utils.ts → utils.js} +21 -4
- package/src/utils.texture.d.ts +13 -0
- package/src/{textureHelper.ts → utils.texture.js} +18 -17
- package/src/index.ts +0 -3
- package/src/loader/loader.needle.ts +0 -43
- package/src/loader/loader.three.ts +0 -322
- package/tsconfig.json +0 -20
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { WebGLRenderer, WebGLRenderTarget, Texture } from 'three';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Renders a PMREM environment map to an equirectangular texture with specified roughness
|
|
5
|
+
*/
|
|
6
|
+
export function renderPMREMToEquirect(
|
|
7
|
+
renderer: WebGLRenderer,
|
|
8
|
+
pmremTexture: Texture,
|
|
9
|
+
roughness?: number,
|
|
10
|
+
width?: number,
|
|
11
|
+
height?: number,
|
|
12
|
+
renderTargetHeight?: number
|
|
13
|
+
): WebGLRenderTarget;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WebGLRenderer, Scene, WebGLRenderTarget, PlaneGeometry, OrthographicCamera, ShaderMaterial, RGBAFormat, FloatType, LinearFilter, Mesh, EquirectangularReflectionMapping, RepeatWrapping, LinearMipMapLinearFilter, Texture
|
|
1
|
+
import { WebGLRenderer, Scene, WebGLRenderTarget, PlaneGeometry, OrthographicCamera, ShaderMaterial, RGBAFormat, FloatType, LinearFilter, Mesh, EquirectangularReflectionMapping, RepeatWrapping, LinearMipMapLinearFilter, Texture } from 'three';
|
|
2
2
|
import { getParam } from './utils.js';
|
|
3
3
|
|
|
4
4
|
const debug = getParam("debugmaterialx");
|
|
@@ -7,25 +7,26 @@ const debug = getParam("debugmaterialx");
|
|
|
7
7
|
* Renders a PMREM environment map to an equirectangular texture with specified roughness
|
|
8
8
|
* @param {WebGLRenderer} renderer - Three.js WebGL renderer
|
|
9
9
|
* @param {Texture} pmremTexture - PMREM texture (2D CubeUV layout) to convert
|
|
10
|
-
* @param {number} roughness - Roughness value (0.0 to 1.0)
|
|
11
|
-
* @param {number} width - Output texture width
|
|
12
|
-
* @param {number} height - Output texture height
|
|
13
|
-
* @param {number} renderTargetHeight - Original render target height (optional, for proper PMREM parameter calculation)
|
|
10
|
+
* @param {number} [roughness=0.0] - Roughness value (0.0 to 1.0)
|
|
11
|
+
* @param {number} [width=1024] - Output texture width
|
|
12
|
+
* @param {number} [height=512] - Output texture height
|
|
13
|
+
* @param {number} [renderTargetHeight] - Original render target height (optional, for proper PMREM parameter calculation)
|
|
14
14
|
* @returns {WebGLRenderTarget} Render target containing the equirectangular texture
|
|
15
|
-
* @example
|
|
15
|
+
* @example
|
|
16
|
+
* // Creating an equirectangular texture from a PMREM environment map at a certain roughness level:
|
|
16
17
|
* const pmremRenderTarget = pmremGenerator.fromEquirectangular(envMap);
|
|
17
18
|
* const equirectRenderTarget = await renderPMREMToEquirect(renderer, pmremRenderTarget.texture, 0.5, 2048, 1024, pmremRenderTarget.height);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
*
|
|
20
|
+
* // Use the rendered equirectangular texture
|
|
21
|
+
* const equirectTexture = equirectRenderTarget.texture;
|
|
22
|
+
*
|
|
23
|
+
* // Apply to your material or save/export
|
|
24
|
+
* someMaterial.map = equirectTexture;
|
|
25
|
+
*
|
|
26
|
+
* // Don't forget to dispose when done
|
|
27
|
+
* // equirectRenderTarget.dispose();
|
|
27
28
|
*/
|
|
28
|
-
export function renderPMREMToEquirect(renderer
|
|
29
|
+
export function renderPMREMToEquirect(renderer, pmremTexture, roughness = 0.0, width = 1024, height = 512, renderTargetHeight) {
|
|
29
30
|
// TODO Validate inputs
|
|
30
31
|
// console.log(renderer, pmremTexture);
|
|
31
32
|
|
|
@@ -167,4 +168,4 @@ export function renderPMREMToEquirect(renderer: WebGLRenderer, pmremTexture: Tex
|
|
|
167
168
|
});
|
|
168
169
|
|
|
169
170
|
return renderTarget;
|
|
170
|
-
}
|
|
171
|
+
}
|
package/src/index.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { addCustomExtensionPlugin } from "@needle-tools/engine";
|
|
2
|
-
import { Context, GLTF, INeedleGLTFExtensionPlugin } from "@needle-tools/engine";
|
|
3
|
-
import type { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
4
|
-
import type { GLTFExporter } from "three/examples/jsm/exporters/GLTFExporter.js";
|
|
5
|
-
import { useNeedleMaterialX as _useNeedleMaterialX, MaterialXLoader } from "./loader.three.js";
|
|
6
|
-
import { debug } from "../utils.js";
|
|
7
|
-
import { MaterialParameters } from "three";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export class MaterialXLoaderPlugin implements INeedleGLTFExtensionPlugin {
|
|
11
|
-
readonly name = "MaterialXLoaderPlugin";
|
|
12
|
-
|
|
13
|
-
private loader: MaterialXLoader | null = null;
|
|
14
|
-
|
|
15
|
-
onImport = (loader: GLTFLoader, url: string, context: Context) => {
|
|
16
|
-
if (debug) console.log("MaterialXLoaderPlugin: Registering MaterialX extension for", url);
|
|
17
|
-
_useNeedleMaterialX(loader, {
|
|
18
|
-
cacheKey: url,
|
|
19
|
-
parameters: {
|
|
20
|
-
precision: context.renderer.capabilities.getMaxPrecision("highp") as MaterialParameters["precision"],
|
|
21
|
-
}
|
|
22
|
-
}, {
|
|
23
|
-
getTime: () => context.time.time,
|
|
24
|
-
getFrame: () => context.time.frame,
|
|
25
|
-
});
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
onLoaded = (url: string, gltf: GLTF, _context: Context) => {
|
|
29
|
-
if (debug) console.log("[MaterialX] MaterialXLoaderPlugin: glTF loaded", { url, scene: gltf.scene, materialX_root_data: this.loader?.materialX_root_data });
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
onExport = (_exporter: GLTFExporter, _context: Context) => {
|
|
33
|
-
console.warn("[MaterialX] Export is not supported");
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Add the MaterialXLoaderPlugin to the Needle Engine.
|
|
40
|
-
*/
|
|
41
|
-
export async function useNeedleMaterialX() {
|
|
42
|
-
addCustomExtensionPlugin(new MaterialXLoaderPlugin());
|
|
43
|
-
}
|
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
import { Material, MeshStandardMaterial, DoubleSide, FrontSide, MaterialParameters } from "three";
|
|
2
|
-
import { GLTFLoader, GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
3
|
-
import { ready, state, MaterialXContext } from "../materialx.js";
|
|
4
|
-
import { debug } from "../utils.js";
|
|
5
|
-
import { MaterialXMaterial } from "../materialx.material.js";
|
|
6
|
-
|
|
7
|
-
// TypeScript interfaces matching the C# data structures
|
|
8
|
-
export type MaterialX_root_extension = {
|
|
9
|
-
/** e.g. 1.39 */
|
|
10
|
-
version: string;
|
|
11
|
-
/** e.g. "Material" */
|
|
12
|
-
name: string;
|
|
13
|
-
/** MaterialX xml content */
|
|
14
|
-
mtlx: string;
|
|
15
|
-
/** MaterialX texture pointers */
|
|
16
|
-
textures: Array<{ name: string, pointer: string }>;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export type MaterialX_material_extension = {
|
|
20
|
-
name: string; // Material name reference
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
type MaterialDefinition = {
|
|
24
|
-
name?: string; // Optional name for the material
|
|
25
|
-
doubleSided?: boolean; // Whether the material is double-sided
|
|
26
|
-
extensions?: {
|
|
27
|
-
[key: string]: any; // Extensions for the material, including MaterialX
|
|
28
|
-
},
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// init.context.getRenderer().capabilities.getMaxPrecision("highp")
|
|
32
|
-
export type MaterialXLoaderOptions = {
|
|
33
|
-
/** The URL of the GLTF file being loaded */
|
|
34
|
-
cacheKey?: string;
|
|
35
|
-
/** Parameters for the MaterialX loader */
|
|
36
|
-
parameters?: Pick<MaterialParameters, "precision">;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// MaterialX loader extension for js GLTFLoader
|
|
40
|
-
export class MaterialXLoader implements GLTFLoaderPlugin {
|
|
41
|
-
readonly name = "NEEDLE_materials_mtlx";
|
|
42
|
-
|
|
43
|
-
private readonly _generatedMaterials: MaterialXMaterial[] = [];
|
|
44
|
-
|
|
45
|
-
private _documentReadyPromise: Promise<any> | null = null;
|
|
46
|
-
|
|
47
|
-
get materialX_root_data() {
|
|
48
|
-
return this.parser.json.extensions?.[this.name] as MaterialX_root_extension | null;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** Generated materialX materials */
|
|
52
|
-
get materials() {
|
|
53
|
-
return this._generatedMaterials;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* MaterialXLoader constructor
|
|
58
|
-
* @param parser The GLTFParser instance
|
|
59
|
-
* @param cacheKey The URL of the GLTF file
|
|
60
|
-
* @param context The context for the GLTF loading process
|
|
61
|
-
*/
|
|
62
|
-
constructor(
|
|
63
|
-
private parser: GLTFParser,
|
|
64
|
-
private options: MaterialXLoaderOptions,
|
|
65
|
-
private context: MaterialXContext
|
|
66
|
-
) {
|
|
67
|
-
if (debug) console.log("MaterialXLoader created for parser");
|
|
68
|
-
// Start loading of MaterialX environment if the root extension exists
|
|
69
|
-
if (this.materialX_root_data) {
|
|
70
|
-
ready();
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
loadMaterial(materialIndex: number): Promise<Material> | null {
|
|
76
|
-
const materialDef = this.parser.json.materials?.[materialIndex];
|
|
77
|
-
if (!materialDef?.extensions?.[this.name]) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
// Wrap the async implementation
|
|
81
|
-
return this._loadMaterialAsync(materialIndex);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Parse the MaterialX document once and cache it
|
|
85
|
-
private async _materialXDocumentReady(): Promise<any> {
|
|
86
|
-
if (this._documentReadyPromise) {
|
|
87
|
-
return this._documentReadyPromise;
|
|
88
|
-
}
|
|
89
|
-
return this._documentReadyPromise = (async () => {
|
|
90
|
-
if (debug) console.log("[MaterialX] Parsing MaterialX root document...");
|
|
91
|
-
|
|
92
|
-
// Ensure MaterialX is initialized
|
|
93
|
-
await ready();
|
|
94
|
-
|
|
95
|
-
if (!state.materialXModule) {
|
|
96
|
-
throw new Error("[MaterialX] module failed to initialize");
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Create MaterialX document and parse ALL the XML data from root
|
|
100
|
-
const doc = state.materialXModule.createDocument();
|
|
101
|
-
doc.setDataLibrary(state.materialXStdLib);
|
|
102
|
-
|
|
103
|
-
// Parse all MaterialX XML strings from the root data
|
|
104
|
-
const root = this.materialX_root_data
|
|
105
|
-
if (root) {
|
|
106
|
-
if (debug) console.log(`[MaterialX] Parsing XML for: ${root.name}`);
|
|
107
|
-
await state.materialXModule.readFromXmlString(doc, root.mtlx, "");
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (debug) console.log("[MaterialX] root document parsed successfully");
|
|
111
|
-
return doc;
|
|
112
|
-
})();
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
private async _loadMaterialAsync(materialIndex: number): Promise<Material> {
|
|
116
|
-
|
|
117
|
-
const materialDef = this.parser.json.materials?.[materialIndex] as MaterialDefinition;
|
|
118
|
-
if (debug) console.log("[MaterialX] extension found in material:", materialDef.extensions?.[this.name]);
|
|
119
|
-
|
|
120
|
-
// Handle different types of MaterialX data
|
|
121
|
-
const ext = materialDef.extensions?.[this.name] as MaterialX_material_extension;
|
|
122
|
-
|
|
123
|
-
if (ext) {
|
|
124
|
-
return this._createMaterialXMaterial(materialDef, ext);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Return fallback material instead of null
|
|
128
|
-
const fallbackMaterial = new MeshStandardMaterial();
|
|
129
|
-
fallbackMaterial.name = "MaterialX_Fallback";
|
|
130
|
-
return fallbackMaterial;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
private async _createMaterialXMaterial(material_def: MaterialDefinition, material_extension: MaterialX_material_extension): Promise<Material> {
|
|
134
|
-
try {
|
|
135
|
-
if (debug) console.log(`Creating MaterialX material: ${material_extension.name}`);
|
|
136
|
-
|
|
137
|
-
const doc = await this._materialXDocumentReady();
|
|
138
|
-
|
|
139
|
-
if (!state.materialXModule || !state.materialXGenerator || !state.materialXGenContext) {
|
|
140
|
-
console.warn("[MaterialX] WASM module not ready, returning fallback material");
|
|
141
|
-
const fallbackMaterial = new MeshStandardMaterial();
|
|
142
|
-
fallbackMaterial.userData.materialX = material_extension;
|
|
143
|
-
fallbackMaterial.name = `MaterialX_Fallback_${material_extension.name}`;
|
|
144
|
-
return fallbackMaterial;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Find the renderable element following MaterialX example pattern exactly
|
|
148
|
-
let renderableElement: any = null;
|
|
149
|
-
let foundRenderable = false;
|
|
150
|
-
|
|
151
|
-
if (debug) console.log("[MaterialX] document", doc);
|
|
152
|
-
|
|
153
|
-
// Search for material nodes first (following the reference pattern)
|
|
154
|
-
const materialNodes = doc.getMaterialNodes();
|
|
155
|
-
if (debug) console.log(`[MaterialX] Found ${materialNodes.length} material nodes in document`, materialNodes);
|
|
156
|
-
|
|
157
|
-
// Handle both array and vector-like APIs
|
|
158
|
-
const materialNodesLength = materialNodes.length;
|
|
159
|
-
for (let i = 0; i < materialNodesLength; ++i) {
|
|
160
|
-
const materialNode = materialNodes[i];
|
|
161
|
-
if (materialNode) {
|
|
162
|
-
const materialName = materialNode.getNamePath();
|
|
163
|
-
if (debug) console.log('[MaterialX] Scan material: ', i, materialName);
|
|
164
|
-
|
|
165
|
-
// Find the matching material
|
|
166
|
-
if (materialName == material_extension.name) {
|
|
167
|
-
renderableElement = materialNode;
|
|
168
|
-
foundRenderable = true;
|
|
169
|
-
if (debug) console.log('[MaterialX] -- add material: ', materialName);
|
|
170
|
-
break;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/*
|
|
176
|
-
// If no material nodes found, search nodeGraphs
|
|
177
|
-
if (!foundRenderable) {
|
|
178
|
-
const nodeGraphs = doc.getNodeGraphs();
|
|
179
|
-
console.log(`Found ${nodeGraphs.length} node graphs in document`);
|
|
180
|
-
const nodeGraphsLength = nodeGraphs.length;
|
|
181
|
-
for (let i = 0; i < nodeGraphsLength; ++i) {
|
|
182
|
-
const nodeGraph = nodeGraphs[i];
|
|
183
|
-
if (nodeGraph) {
|
|
184
|
-
// Skip any nodegraph that has nodedef or sourceUri
|
|
185
|
-
if ((nodeGraph as any).hasAttribute('nodedef') || (nodeGraph as any).hasSourceUri()) {
|
|
186
|
-
continue;
|
|
187
|
-
}
|
|
188
|
-
// Skip any nodegraph that is connected to something downstream
|
|
189
|
-
if ((nodeGraph as any).getDownstreamPorts().length > 0) {
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
const outputs = (nodeGraph as any).getOutputs();
|
|
193
|
-
for (let j = 0; j < outputs.length; ++j) {
|
|
194
|
-
const output = outputs[j];
|
|
195
|
-
if (output && !foundRenderable) {
|
|
196
|
-
renderableElement = output;
|
|
197
|
-
foundRenderable = true;
|
|
198
|
-
break;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
if (foundRenderable) break;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// If still no element found, search document outputs
|
|
207
|
-
if (!foundRenderable) {
|
|
208
|
-
const outputs = doc.getOutputs();
|
|
209
|
-
console.log(`Found ${outputs.length} output nodes in document`);
|
|
210
|
-
const outputsLength = outputs.length;
|
|
211
|
-
for (let i = 0; i < outputsLength; ++i) {
|
|
212
|
-
const output = outputs[i];
|
|
213
|
-
if (output && !foundRenderable) {
|
|
214
|
-
renderableElement = output;
|
|
215
|
-
foundRenderable = true;
|
|
216
|
-
break;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
*/
|
|
221
|
-
|
|
222
|
-
if (!renderableElement) {
|
|
223
|
-
console.warn(`[MaterialX] No renderable element found in MaterialX document (${material_extension.name})`);
|
|
224
|
-
const fallbackMaterial = new MeshStandardMaterial();
|
|
225
|
-
fallbackMaterial.color.set(0xff00ff);
|
|
226
|
-
fallbackMaterial.userData.materialX = material_extension;
|
|
227
|
-
fallbackMaterial.name = `MaterialX_NoRenderable_${material_extension.name}`;
|
|
228
|
-
return fallbackMaterial;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
if (debug) console.log("[MaterialX] Using renderable element for shader generation");
|
|
232
|
-
|
|
233
|
-
// Check transparency and set context options like the reference
|
|
234
|
-
const isTransparent = state.materialXModule.isTransparentSurface(renderableElement, state.materialXGenerator.getTarget());
|
|
235
|
-
state.materialXGenContext.getOptions().hwTransparency = isTransparent;
|
|
236
|
-
|
|
237
|
-
// Generate shaders using the element's name path
|
|
238
|
-
if (debug) console.log("[MaterialX] Generating MaterialX shaders...");
|
|
239
|
-
const elementName = (renderableElement as any).getNamePath ? (renderableElement as any).getNamePath() : (renderableElement as any).getName();
|
|
240
|
-
|
|
241
|
-
const shader = state.materialXGenerator.generate(elementName, renderableElement, state.materialXGenContext);
|
|
242
|
-
|
|
243
|
-
const shaderMaterial = new MaterialXMaterial({
|
|
244
|
-
name: material_extension.name,
|
|
245
|
-
shader,
|
|
246
|
-
context: this.context,
|
|
247
|
-
parameters: {
|
|
248
|
-
transparent: isTransparent,
|
|
249
|
-
side: material_def.doubleSided ? DoubleSide : FrontSide,
|
|
250
|
-
...this.options.parameters,
|
|
251
|
-
},
|
|
252
|
-
loaders: {
|
|
253
|
-
cacheKey: this.options.cacheKey || "",
|
|
254
|
-
getTexture: async url => {
|
|
255
|
-
// Find the index of the texture in the parser
|
|
256
|
-
const filenameWithoutExt = url.split('/').pop()?.split('.').shift() || '';
|
|
257
|
-
|
|
258
|
-
// Resolve the texture from the MaterialX root extension
|
|
259
|
-
const ext = this.materialX_root_data;
|
|
260
|
-
if (ext) {
|
|
261
|
-
const textures = ext.textures || [];
|
|
262
|
-
let index = -1;
|
|
263
|
-
for (const texture of textures) {
|
|
264
|
-
// Find the texture by name and use the pointer string to get the index
|
|
265
|
-
if (texture.name === filenameWithoutExt) {
|
|
266
|
-
const ptr = texture.pointer;
|
|
267
|
-
const indexStr = ptr.substring("/textures/".length);
|
|
268
|
-
index = parseInt(indexStr);
|
|
269
|
-
|
|
270
|
-
if (isNaN(index) || index < 0) {
|
|
271
|
-
console.error("[MaterialX] Invalid texture index in pointer:", ptr);
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
274
|
-
else {
|
|
275
|
-
if (debug) console.log("[MaterialX] Texture index found:", index, "for", filenameWithoutExt);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (index < 0) {
|
|
281
|
-
console.error("[MaterialX] Texture not found in parser:", filenameWithoutExt, this.parser.json);
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
return this.parser.getDependency("texture", index).then(tex => {
|
|
285
|
-
if (debug) console.log("[MaterialX] Texture loaded:" + tex.name, tex);
|
|
286
|
-
return tex;
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
return null;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
// Track this material for later lighting updates
|
|
294
|
-
this._generatedMaterials.push(shaderMaterial);
|
|
295
|
-
|
|
296
|
-
// Add debugging to see if the material compiles correctly
|
|
297
|
-
if (debug) console.log("[MaterialX] material created:", shaderMaterial.name);
|
|
298
|
-
return shaderMaterial;
|
|
299
|
-
|
|
300
|
-
} catch (error) {
|
|
301
|
-
// This is a wasm error (an int) that we need to resolve
|
|
302
|
-
console.error(`[MaterialX] Error creating MaterialX material (${material_extension.name}):`, error);
|
|
303
|
-
// Return a fallback material with stored MaterialX data
|
|
304
|
-
const fallbackMaterial = new MeshStandardMaterial();
|
|
305
|
-
fallbackMaterial.color.set(0xff00ff);
|
|
306
|
-
fallbackMaterial.userData.materialX = material_extension;
|
|
307
|
-
fallbackMaterial.name = `MaterialX_Error_${material_extension.name}`;
|
|
308
|
-
return fallbackMaterial;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
/**
|
|
315
|
-
* Add the MaterialXLoader to the GLTFLoader instance.
|
|
316
|
-
*/
|
|
317
|
-
export function useNeedleMaterialX(loader: GLTFLoader, options?: MaterialXLoaderOptions, context?: MaterialXContext) {
|
|
318
|
-
loader.register(p => {
|
|
319
|
-
const loader = new MaterialXLoader(p, options || {}, context || {});
|
|
320
|
-
return loader;
|
|
321
|
-
});
|
|
322
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ESNext",
|
|
4
|
-
"useDefineForClassFields": true,
|
|
5
|
-
"module": "ESNext",
|
|
6
|
-
"lib": ["ESNext", "DOM"],
|
|
7
|
-
"moduleResolution": "Node",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"sourceMap": true,
|
|
10
|
-
"resolveJsonModule": true,
|
|
11
|
-
"esModuleInterop": true,
|
|
12
|
-
"noEmit": true,
|
|
13
|
-
"noUnusedLocals": false,
|
|
14
|
-
"noUnusedParameters": true,
|
|
15
|
-
"noImplicitReturns": true,
|
|
16
|
-
"noImplicitAny": false,
|
|
17
|
-
"experimentalDecorators": true
|
|
18
|
-
},
|
|
19
|
-
"include": ["."]
|
|
20
|
-
}
|