@needle-tools/materialx 1.1.1-next.b7e5e45 → 1.1.1-next.fb25319

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.
@@ -4,7 +4,6 @@
4
4
  //
5
5
  import * as THREE from 'three';
6
6
  import { debug, debugUpdate } from './utils.js';
7
- import { MaterialX } from './materialx.types.js';
8
7
 
9
8
  const IMAGE_PROPERTY_SEPARATOR = "_";
10
9
  const UADDRESS_MODE_SUFFIX = IMAGE_PROPERTY_SEPARATOR + "uaddressmode";
@@ -13,20 +12,19 @@ const FILTER_TYPE_SUFFIX = IMAGE_PROPERTY_SEPARATOR + "filtertype";
13
12
  const IMAGE_PATH_SEPARATOR = "/";
14
13
 
15
14
  /**
16
- * Initialized the environment texture as MaterialX expects it
15
+ * Initializes the environment texture as MaterialX expects it
17
16
  * @param {THREE.Texture} texture
18
17
  * @param {Object} capabilities
19
18
  * @returns {THREE.Texture}
20
19
  */
21
20
  export function prepareEnvTexture(texture, capabilities) {
22
- let newTexture = new THREE.DataTexture(texture.image.data, texture.image.width, texture.image.height, texture.format, texture.type);
21
+ const newTexture = new THREE.DataTexture(texture.image.data, texture.image.width, texture.image.height, /** @type {any} */(texture.format), texture.type);
23
22
  newTexture.wrapS = THREE.RepeatWrapping;
24
23
  newTexture.anisotropy = capabilities.getMaxAnisotropy();
25
24
  newTexture.minFilter = THREE.LinearMipmapLinearFilter;
26
25
  newTexture.magFilter = THREE.LinearFilter;
27
26
  newTexture.generateMipmaps = true;
28
27
  newTexture.needsUpdate = true;
29
-
30
28
  return newTexture;
31
29
  }
32
30
 
@@ -34,7 +32,7 @@ export function prepareEnvTexture(texture, capabilities) {
34
32
  * Get Three uniform from MaterialX vector
35
33
  * @param {any} value
36
34
  * @param {any} dimension
37
- * @returns {THREE.Uniform}
35
+ * @returns {Array<number>}
38
36
  */
39
37
  function fromVector(value, dimension) {
40
38
  let outValue;
@@ -52,8 +50,11 @@ function fromVector(value, dimension) {
52
50
 
53
51
  /**
54
52
  * Get Three uniform from MaterialX matrix
53
+ * @param {any} matrix
54
+ * @param {number} dimension
55
+ * @returns {Array<number>}
55
56
  */
56
- function fromMatrix(matrix: MaterialX.Matrix, dimension: MaterialX.Matrix["size"]) {
57
+ function fromMatrix(matrix, dimension) {
57
58
  const vec = new Array(dimension);
58
59
  if (matrix) {
59
60
  for (let i = 0; i < matrix.numRows(); ++i) {
@@ -69,19 +70,11 @@ function fromMatrix(matrix: MaterialX.Matrix, dimension: MaterialX.Matrix["size"
69
70
  return vec;
70
71
  }
71
72
 
72
-
73
- export type Callbacks = {
74
- /**
75
- * Cache key for the loaders, used to identify and reuse textures
76
- */
77
- readonly cacheKey?: string;
78
- /**
79
- * Get a texture by path
80
- * @param {string} path - The path to the texture
81
- * @return {Promise<THREE.Texture>} - A promise that resolves to the texture
82
- */
83
- readonly getTexture: (path: string) => Promise<THREE.Texture | null | void>;
84
- }
73
+ /**
74
+ * @typedef {Object} Callbacks
75
+ * @property {string} [cacheKey] - Cache key for the loaders, used to identify and reuse textures
76
+ * @property {(path: string) => Promise<THREE.Texture | null | void>} getTexture - Get a texture by path
77
+ */
85
78
 
86
79
  const defaultTexture = new THREE.Texture();
87
80
  defaultTexture.needsUpdate = true;
@@ -94,21 +87,28 @@ defaultTexture.image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAA
94
87
  // defaultTexture.magFilter = THREE.NearestFilter;
95
88
  // defaultTexture.repeat = new THREE.Vector2(100, 100);
96
89
 
97
-
98
90
  const defaultNormalTexture = new THREE.Texture();
99
91
  defaultNormalTexture.needsUpdate = true;
100
92
  defaultNormalTexture.image = new Image();
101
93
  defaultNormalTexture.image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIBAMAAAA2IaO4AAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAABJQTFRFgYH4gIH4gYH3gIH3gIH5gID4m94ORAAAADFJREFUeJxjZBBkfMdo9P/BB0aBj/8FGB0ufghgFGT4r8wo+P8rD2Pgo3sMjIz8jAwAMLoN0ZjS5hgAAAAASUVORK5CYII=";
102
94
 
103
-
104
- function tryGetFromCache(key: string): any {
95
+ /**
96
+ * @param {string} key
97
+ * @returns {any}
98
+ */
99
+ function tryGetFromCache(key) {
105
100
  const wasEnabled = THREE.Cache.enabled;
106
101
  THREE.Cache.enabled = true;
107
102
  const value = THREE.Cache.get(key);
108
103
  THREE.Cache.enabled = wasEnabled;
109
104
  return value;
110
105
  }
111
- function addToCache(key: string, value: any): void {
106
+
107
+ /**
108
+ * @param {string} key
109
+ * @param {any} value
110
+ */
111
+ function addToCache(key, value) {
112
112
  const wasEnabled = THREE.Cache.enabled;
113
113
  THREE.Cache.enabled = true;
114
114
  THREE.Cache.add(key, value);
@@ -118,10 +118,17 @@ function addToCache(key: string, value: any): void {
118
118
 
119
119
  /**
120
120
  * Get Three uniform from MaterialX value
121
+ * @param {any} uniforms
122
+ * @param {string} type
123
+ * @param {any} value
124
+ * @param {string} name
125
+ * @param {Callbacks} loaders
126
+ * @param {string} searchPath
127
+ * @returns {THREE.Uniform}
121
128
  */
122
- function toThreeUniform(uniforms: any, type: string, value: any, name: string, loaders: Callbacks, searchPath: string): THREE.Uniform {
129
+ function toThreeUniform(uniforms, type, value, name, loaders, searchPath) {
123
130
 
124
- const uniform = new THREE.Uniform<any>(null);
131
+ const uniform = new THREE.Uniform(/** @type {any} */(null));
125
132
 
126
133
  switch (type) {
127
134
  case 'float':
@@ -130,21 +137,21 @@ function toThreeUniform(uniforms: any, type: string, value: any, name: string, l
130
137
  uniform.value = value;
131
138
  break;
132
139
  case 'vector2':
133
- uniform.value = fromVector(value, 2);
140
+ uniform.value = /** @type {any} */ (fromVector(value, 2));
134
141
  break;
135
142
  case 'vector3':
136
143
  case 'color3':
137
- uniform.value = fromVector(value, 3);
144
+ uniform.value = /** @type {any} */ (fromVector(value, 3));
138
145
  break;
139
146
  case 'vector4':
140
147
  case 'color4':
141
- uniform.value = fromVector(value, 4);
148
+ uniform.value = /** @type {any} */ (fromVector(value, 4));
142
149
  break;
143
150
  case 'matrix33':
144
- uniform.value = fromMatrix(value, 9);
151
+ uniform.value = /** @type {any} */ (fromMatrix(value, 9));
145
152
  break;
146
153
  case 'matrix44':
147
- uniform.value = fromMatrix(value, 16);
154
+ uniform.value = /** @type {any} */ (fromMatrix(value, 16));
148
155
  break;
149
156
  case 'filename':
150
157
  if (value) {
@@ -182,8 +189,8 @@ function toThreeUniform(uniforms: any, type: string, value: any, name: string, l
182
189
  else {
183
190
  if (debug) console.log('[MaterialX] Load texture:', texturePath);
184
191
 
185
- if (name.toLowerCase().includes("normal")) uniform.value = defaultNormalTexture;
186
- else uniform.value = defaultTexture;
192
+ if (name.toLowerCase().includes("normal")) uniform.value = /** @type {any} */ (defaultNormalTexture);
193
+ else uniform.value = /** @type {any} */ (defaultTexture);
187
194
  const defaultValue = uniform.value;
188
195
  // Save the loading promise in the cache
189
196
  const promise = loaders.getTexture(texturePath)
@@ -201,9 +208,9 @@ function toThreeUniform(uniforms: any, type: string, value: any, name: string, l
201
208
  });
202
209
 
203
210
  if (checkCache) addToCache(cacheKey, promise);
204
-
211
+
205
212
  promise?.then(res => {
206
- if (res) uniform.value = res;
213
+ if (res) uniform.value = /** @type {any} */ (res);
207
214
  else console.warn(`[MaterialX] Failed to load texture ${name} '${texturePath}'`);
208
215
  });
209
216
  }
@@ -224,12 +231,15 @@ function toThreeUniform(uniforms: any, type: string, value: any, name: string, l
224
231
  return uniform;
225
232
  }
226
233
 
227
- const valueTypeWarningMap = new Map<string, boolean>();
234
+ /** @type {Map<string, boolean>} */
235
+ const valueTypeWarningMap = new Map();
228
236
 
229
237
  /**
230
238
  * Get Three wrapping mode
239
+ * @param {number} mode
240
+ * @returns {THREE.Wrapping}
231
241
  */
232
- function getWrapping(mode: number): THREE.Wrapping {
242
+ function getWrapping(mode) {
233
243
  let wrap;
234
244
  switch (mode) {
235
245
  case 1:
@@ -248,11 +258,14 @@ function getWrapping(mode: number): THREE.Wrapping {
248
258
  return wrap;
249
259
  }
250
260
 
251
-
252
261
  /**
253
262
  * Set Three texture parameters
263
+ * @param {THREE.Texture} texture
264
+ * @param {string} name
265
+ * @param {any} uniforms
266
+ * @param {boolean} [generateMipmaps=true]
254
267
  */
255
- function setTextureParameters(texture: THREE.Texture, name: string, uniforms: any, generateMipmaps = true) {
268
+ function setTextureParameters(texture, name, uniforms, generateMipmaps = true) {
256
269
  const idx = name.lastIndexOf(IMAGE_PROPERTY_SEPARATOR);
257
270
  const base = name.substring(0, idx) || name;
258
271
 
@@ -267,15 +280,16 @@ function setTextureParameters(texture: THREE.Texture, name: string, uniforms: an
267
280
  }
268
281
 
269
282
  const mxFilterType = uniforms.find(base + FILTER_TYPE_SUFFIX) ? uniforms.get(base + FILTER_TYPE_SUFFIX).value : -1;
270
- let minFilter: THREE.TextureFilter = generateMipmaps ? THREE.LinearMipMapLinearFilter : THREE.LinearFilter;
283
+ let minFilter = generateMipmaps ? THREE.LinearMipMapLinearFilter : THREE.LinearFilter;
271
284
  if (mxFilterType === 0) {
272
- minFilter = generateMipmaps ? THREE.NearestMipMapNearestFilter : THREE.NearestFilter;
285
+ minFilter = /** @type {any} */ (generateMipmaps ? THREE.NearestMipMapNearestFilter : THREE.NearestFilter);
273
286
  }
274
287
  texture.minFilter = minFilter;
275
288
  }
276
289
 
277
290
  /**
278
291
  * Return the global light rotation matrix
292
+ * @returns {THREE.Matrix4}
279
293
  */
280
294
  export function getLightRotation() {
281
295
  return new THREE.Matrix4().makeRotationY(Math.PI / 2);
@@ -283,11 +297,11 @@ export function getLightRotation() {
283
297
 
284
298
  /**
285
299
  * Returns all lights nodes in a MaterialX document
286
- * @param {mx.Document} doc
287
- * @returns {Array.<mx.Node>}
300
+ * @param {any} doc
301
+ * @returns {Array<any>}
288
302
  */
289
- export function findLights(doc: MaterialX.Document) {
290
- let lights = new Array<any>;
303
+ export function findLights(doc) {
304
+ let lights = new Array();
291
305
  for (let node of doc.getNodes()) {
292
306
  if (node.getType() === "lightshader")
293
307
  lights.push(node);
@@ -295,14 +309,16 @@ export function findLights(doc: MaterialX.Document) {
295
309
  return lights;
296
310
  }
297
311
 
312
+ /** @type {Object<string, number>} */
298
313
  let lightTypesBound = {};
299
314
 
300
315
  /**
301
316
  * Register lights in shader generation context
302
- * @param {MaterialX.MODULE} mx MaterialX Module
303
- * @param {mx.GenContext} genContext Shader generation context
317
+ * @param {any} mx - MaterialX Module
318
+ * @param {any} genContext - Shader generation context
319
+ * @returns {Promise<void>}
304
320
  */
305
- export async function registerLights(mx: MaterialX.MODULE, genContext: any): Promise<void> {
321
+ export async function registerLights(mx, genContext) {
306
322
  lightTypesBound = {};
307
323
  const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
308
324
  mx.HwShaderGenerator.unbindLightShaders(genContext);
@@ -355,7 +371,12 @@ export async function registerLights(mx: MaterialX.MODULE, genContext: any): Pro
355
371
  if (debug) console.log("Light types bound in MaterialX context", lightTypesBound);
356
372
  }
357
373
 
358
- // Converts Three.js light type to MaterialX node name
374
+ const _lightTypeWarnings = {}
375
+ /**
376
+ * Converts Three.js light type to MaterialX node name
377
+ * @param {string} threeLightType
378
+ * @returns {string|null}
379
+ */
359
380
  function threeLightTypeToMaterialXNodeName(threeLightType) {
360
381
  switch (threeLightType) {
361
382
  case 'PointLight':
@@ -365,26 +386,33 @@ function threeLightTypeToMaterialXNodeName(threeLightType) {
365
386
  case 'SpotLight':
366
387
  return 'ND_spot_light';
367
388
  default:
368
- console.warn('MaterialX: Unsupported light type: ' + threeLightType);
369
- return 'ND_point_light'; // Default to point light
389
+ if (!_lightTypeWarnings[threeLightType]) {
390
+ _lightTypeWarnings[threeLightType] = true;
391
+ console.warn('MaterialX: Unsupported light type: ' + threeLightType);
392
+ }
393
+ return null; // Unsupported light type
370
394
  }
371
- };
372
-
373
- export type LightData = {
374
- type: number, // Light type ID
375
- position: THREE.Vector3, // Position in world space
376
- direction: THREE.Vector3, // Direction in world space
377
- color: THREE.Color, // Color of the light
378
- intensity: number, // Intensity of the light
379
- decay_rate: number, // Decay rate for point and spot lights
380
- inner_angle: number, // Inner angle for spot lights
381
- outer_angle: number, // Outer angle for spot lights
382
395
  }
383
396
 
397
+ /**
398
+ * @typedef {Object} LightData
399
+ * @property {number} type - Light type ID
400
+ * @property {THREE.Vector3} position - Position in world space
401
+ * @property {THREE.Vector3} direction - Direction in world space
402
+ * @property {THREE.Color} color - Color of the light
403
+ * @property {number} intensity - Intensity of the light
404
+ * @property {number} decay_rate - Decay rate for point and spot lights
405
+ * @property {number} inner_angle - Inner angle for spot lights
406
+ * @property {number} outer_angle - Outer angle for spot lights
407
+ */
408
+
384
409
  /**
385
410
  * Update light data for shader uniforms
411
+ * @param {Array<THREE.Light>} lights
412
+ * @param {any} genContext
413
+ * @returns {{ lightData: LightData[], lightCount: number }}
386
414
  */
387
- export function getLightData(lights: Array<THREE.Light>, genContext: any): { lightData: LightData[], lightCount: number } {
415
+ export function getLightData(lights, genContext) {
388
416
  const lightData = new Array();
389
417
  const maxLightCount = genContext.getOptions().hwMaxActiveLightSources;
390
418
 
@@ -397,8 +425,12 @@ export function getLightData(lights: Array<THREE.Light>, genContext: any): { lig
397
425
 
398
426
  const lightDefinitionName = threeLightTypeToMaterialXNodeName(light.type);
399
427
 
400
- if (!lightTypesBound[lightDefinitionName])
401
- console.error("MaterialX: Light type not registered in context. Make sure to register light types before using them.", lightDefinitionName);
428
+ if(!lightDefinitionName){
429
+ continue; // Unsupported light type
430
+ }
431
+ if (!lightTypesBound[lightDefinitionName]) {
432
+ if(debug) console.error("MaterialX: Light type not registered in context. Make sure to register light types before using them.", lightDefinitionName);
433
+ }
402
434
 
403
435
  const wp = light.getWorldPosition(new THREE.Vector3());
404
436
  const wq = light.getWorldQuaternion(new THREE.Quaternion());
@@ -410,8 +442,8 @@ export function getLightData(lights: Array<THREE.Light>, genContext: any): { lig
410
442
  // float cosDir = dot(result.direction, -light.direction);
411
443
  // float spotAttenuation = smoothstep(low, high, cosDir);
412
444
 
413
- const outerAngleRad = (light as THREE.SpotLight).angle;
414
- const innerAngleRad = outerAngleRad * (1 - (light as THREE.SpotLight).penumbra);
445
+ const outerAngleRad = /** @type {THREE.SpotLight} */ (light).angle;
446
+ const innerAngleRad = outerAngleRad * (1 - /** @type {THREE.SpotLight} */ (light).penumbra);
415
447
  const inner_angle = Math.cos(innerAngleRad);
416
448
  const outer_angle = Math.cos(outerAngleRad);
417
449
 
@@ -422,7 +454,7 @@ export function getLightData(lights: Array<THREE.Light>, genContext: any): { lig
422
454
  color: new THREE.Color().fromArray(light.color.toArray()),
423
455
  // Luminous efficacy for converting radiant power in watts (W) to luminous flux in lumens (lm) at a wavelength of 555 nm.
424
456
  // Also, three.js lights don't have PI scale baked in, but MaterialX does, so we need to divide by PI for point and spot lights.
425
- intensity: light.intensity * ((light as THREE.PointLight).isPointLight ? 683.0 / 3.1415 : (light as THREE.SpotLight).isSpotLight ? 683.0 / 3.1415 : 1.0),
457
+ intensity: light.intensity * (/** @type {THREE.PointLight} */ (light).isPointLight ? 683.0 / 3.1415 : /** @type {THREE.SpotLight} */ (light).isSpotLight ? 683.0 / 3.1415 : 1.0),
426
458
  decay_rate: 2.0,
427
459
  // Approximations for testing – the relevant light has 61.57986...129.4445 as inner/outer spot angle
428
460
  inner_angle: inner_angle,
@@ -455,8 +487,13 @@ export function getLightData(lights: Array<THREE.Light>, genContext: any): { lig
455
487
 
456
488
  /**
457
489
  * Get uniform values for a shader
490
+ * @param {any} shaderStage
491
+ * @param {Callbacks} loaders
492
+ * @param {string} searchPath
493
+ * @returns {Object<string, THREE.Uniform>}
458
494
  */
459
- export function getUniformValues(shaderStage: MaterialX.ShaderStage, loaders: Callbacks, searchPath: string) {
495
+ export function getUniformValues(shaderStage, loaders, searchPath) {
496
+ /** @type {Object<string, THREE.Uniform>} */
460
497
  const threeUniforms = {};
461
498
 
462
499
  const uniformBlocks = shaderStage.getUniformBlocks()
@@ -479,7 +516,11 @@ export function getUniformValues(shaderStage: MaterialX.ShaderStage, loaders: Ca
479
516
  return threeUniforms;
480
517
  }
481
518
 
482
- export function generateMaterialPropertiesForUniforms(material: THREE.ShaderMaterial, shaderStage: MaterialX.ShaderStage) {
519
+ /**
520
+ * @param {THREE.ShaderMaterial} material
521
+ * @param {any} shaderStage
522
+ */
523
+ export function generateMaterialPropertiesForUniforms(material, shaderStage) {
483
524
 
484
525
  const uniformBlocks = shaderStage.getUniformBlocks()
485
526
  for (const [blockName, uniforms] of Object.entries(uniformBlocks)) {
@@ -1,30 +1,27 @@
1
- import type { MaterialX as MX } from "./materialx.types.js";
2
1
  import MaterialX from "../bin/JsMaterialXGenShader.js";
3
2
  import { debug } from "./utils.js";
4
3
  import { renderPMREMToEquirect } from "./utils.texture.js";
5
4
  import { Light, Mesh, MeshBasicMaterial, Object3D, PlaneGeometry, PMREMGenerator, Scene, Texture, WebGLRenderer } from "three";
6
- import { registerLights, getLightData, LightData } from "./materialx.helper.js";
7
- import type { MaterialXMaterial } from "./materialx.material.js";
8
-
9
- export type MaterialXContext = {
10
- getTime?(): number,
11
- getFrame?(): number,
12
- }
13
-
5
+ import { registerLights, getLightData } from "./materialx.helper.js";
14
6
 
15
7
  export const state = new class {
16
- materialXModule: MX.MODULE | null = null;
17
- materialXGenerator: any = null;
18
- materialXGenContext: any = null;
19
- materialXStdLib: any = null;
20
- materialXInitPromise: Promise<void> | null = null;
8
+ /** @type {import("./materialx.types.js").MaterialX.MODULE | null} */
9
+ materialXModule = null;
10
+ /** @type {any} */
11
+ materialXGenerator = null;
12
+ /** @type {any} */
13
+ materialXGenContext = null;
14
+ /** @type {any} */
15
+ materialXStdLib = null;
16
+ /** @type {Promise<void> | null} */
17
+ materialXInitPromise = null;
21
18
  }
22
19
 
23
-
24
20
  /**
25
21
  * Wait for the MaterialX WASM module to be ready.
22
+ * @returns {Promise<void>}
26
23
  */
27
- export async function ready(): Promise<void> {
24
+ export async function ready() {
28
25
  if (state.materialXInitPromise) {
29
26
  return state.materialXInitPromise;
30
27
  }
@@ -33,18 +30,19 @@ export async function ready(): Promise<void> {
33
30
  if (debug) console.log("[MaterialX] Initializing WASM module...");
34
31
  try {
35
32
 
36
- const urls: Array<string> = await Promise.all([
33
+ /** @type {Array<string>} */
34
+ const urls = await Promise.all([
37
35
  /** @ts-ignore */
38
- import(`../bin/JsMaterialXCore.wasm?url`).then(m => m.default || m),
36
+ import( /* @vite-ignore */ `../bin/JsMaterialXCore.wasm?url`).then(m => m.default || m),
39
37
  /** @ts-ignore */
40
- import(`../bin/JsMaterialXGenShader.wasm?url`).then(m => m.default || m),
38
+ import( /* @vite-ignore */ `../bin/JsMaterialXGenShader.wasm?url`).then(m => m.default || m),
41
39
  /** @ts-ignore */
42
- import(`../bin/JsMaterialXGenShader.data.txt?url`).then(m => m.default || m),
40
+ import( /* @vite-ignore */ `../bin/JsMaterialXGenShader.data.txt?url`).then(m => m.default || m),
43
41
  ]);
44
42
  const [JsMaterialXCore, JsMaterialXGenShader, JsMaterialXGenShader_data] = urls;
45
43
 
46
44
  const module = await MaterialX({
47
- locateFile: (path: string, scriptDirectory: string) => {
45
+ locateFile: (/** @type {string} */ path, /** @type {string} */ scriptDirectory) => {
48
46
  if (debug) console.debug("[MaterialX] locateFile called:", { path, scriptDirectory });
49
47
 
50
48
  if (path.includes("JsMaterialXCore.wasm")) {
@@ -61,7 +59,7 @@ export async function ready(): Promise<void> {
61
59
  },
62
60
  });
63
61
  if (debug) console.log("[MaterialX] module loaded", module);
64
- state.materialXModule = module as MX.MODULE
62
+ state.materialXModule = /** @type {import("./materialx.types.js").MaterialX.MODULE} */ (module);
65
63
 
66
64
  // Initialize shader generator and context
67
65
  state.materialXGenerator = module.EsslShaderGenerator.create();
@@ -108,45 +106,69 @@ export async function ready(): Promise<void> {
108
106
  })();
109
107
  }
110
108
 
111
- type EnvironmentTextureSet = {
112
- radianceTexture: Texture | null;
113
- irradianceTexture: Texture | null;
114
- }
115
-
109
+ /**
110
+ * @typedef {Object} EnvironmentTextureSet
111
+ * @property {Texture | null} radianceTexture
112
+ * @property {Texture | null} irradianceTexture
113
+ */
116
114
 
117
115
  /**
118
116
  * MaterialXEnvironment manages the environment settings for MaterialX materials.
119
117
  */
120
118
  export class MaterialXEnvironment {
121
119
 
122
- static get(scene: Scene): MaterialXEnvironment | null {
120
+ /**
121
+ * @param {Scene} scene
122
+ * @returns {MaterialXEnvironment | null}
123
+ */
124
+ static get(scene) {
123
125
  return this.getEnvironment(scene);
124
126
  }
125
- private static _environments: WeakMap<Scene, MaterialXEnvironment> = new Map();
126
- private static getEnvironment(scene: Scene): MaterialXEnvironment {
127
+
128
+ /** @type {WeakMap<Scene, MaterialXEnvironment>} */
129
+ static _environments = new Map();
130
+
131
+ /**
132
+ * @param {Scene} scene
133
+ * @returns {MaterialXEnvironment}
134
+ */
135
+ static getEnvironment(scene) {
127
136
  if (this._environments.has(scene)) {
128
- return this._environments.get(scene)!;
137
+ return /** @type {MaterialXEnvironment} */ (this._environments.get(scene));
129
138
  }
130
139
  const env = new MaterialXEnvironment(scene);
131
140
  this._environments.set(scene, env);
132
141
  return env;
133
142
  }
134
143
 
135
-
136
- private _lights: Array<Light> = [];
137
- private _lightData: null | LightData[] = null;
138
- private _lightCount: number = 0;
139
-
140
- private _initializePromise: Promise<boolean> | null = null;
141
- private _isInitialized: boolean = false;
142
- private _lastUpdateFrame: number = -1;
143
-
144
- constructor(private _scene: Scene) {
144
+ /** @type {Array<Light>} */
145
+ _lights = [];
146
+ /** @type {import("./materialx.helper.js").LightData[] | null} */
147
+ _lightData = null;
148
+ /** @type {number} */
149
+ _lightCount = 0;
150
+
151
+ /** @type {Promise<boolean> | null} */
152
+ _initializePromise = null;
153
+ /** @type {boolean} */
154
+ _isInitialized = false;
155
+ /** @type {number} */
156
+ _lastUpdateFrame = -1;
157
+
158
+ /**
159
+ * @param {Scene} _scene
160
+ */
161
+ constructor(_scene) {
162
+ this._scene = _scene;
145
163
  if (debug) console.log("[MaterialX] Environment created");
146
164
  }
147
165
 
148
- // Initialize with Needle Engine context
149
- async initialize(renderer: WebGLRenderer): Promise<boolean> {
166
+ /**
167
+ * Initialize with Needle Engine context
168
+ * @param {WebGLRenderer} renderer
169
+ * @returns {Promise<boolean>}
170
+ */
171
+ async initialize(renderer) {
150
172
  if (this._initializePromise) {
151
173
  return this._initializePromise;
152
174
  }
@@ -154,7 +176,12 @@ export class MaterialXEnvironment {
154
176
  return this._initializePromise;
155
177
  }
156
178
 
157
- update(frame: number, scene: Scene, renderer: WebGLRenderer): void {
179
+ /**
180
+ * @param {number} frame
181
+ * @param {Scene} scene
182
+ * @param {WebGLRenderer} renderer
183
+ */
184
+ update(frame, scene, renderer) {
158
185
  if (!this._initializePromise) {
159
186
  this.initialize(renderer);
160
187
  return;
@@ -220,7 +247,11 @@ export class MaterialXEnvironment {
220
247
  return this._lightData;
221
248
  }
222
249
  get lightCount() { return this._lightCount || 0; }
223
- getTextures(material: MaterialXMaterial) {
250
+
251
+ /**
252
+ * @param {import("./materialx.material.js").MaterialXMaterial} material
253
+ */
254
+ getTextures(material) {
224
255
  if (material.envMap) {
225
256
  // If the material has its own envMap, we don't use the irradiance texture
226
257
  return this._getTextures(material.envMap);
@@ -228,11 +259,18 @@ export class MaterialXEnvironment {
228
259
  return this._getTextures(this._scene.environment);
229
260
  }
230
261
 
231
- private _pmremGenerator: PMREMGenerator | null = null;
232
- private _renderer: WebGLRenderer | null = null;
233
- private readonly _texturesCache: Map<Texture | null, EnvironmentTextureSet> = new Map();
234
-
235
- private async _initialize(renderer: WebGLRenderer): Promise<boolean> {
262
+ /** @type {PMREMGenerator | null} */
263
+ _pmremGenerator = null;
264
+ /** @type {WebGLRenderer | null} */
265
+ _renderer = null;
266
+ /** @type {Map<Texture | null, EnvironmentTextureSet>} */
267
+ _texturesCache = new Map();
268
+
269
+ /**
270
+ * @param {WebGLRenderer} renderer
271
+ * @returns {Promise<boolean>}
272
+ */
273
+ async _initialize(renderer) {
236
274
  this._isInitialized = false;
237
275
  this._pmremGenerator = new PMREMGenerator(renderer);
238
276
  this._renderer = renderer;
@@ -241,11 +279,13 @@ export class MaterialXEnvironment {
241
279
  return true;
242
280
  }
243
281
 
244
- private _getTextures(texture: Texture | null | undefined): {
245
- radianceTexture: Texture | null,
246
- irradianceTexture: Texture | null
247
- } {
248
- let res: EnvironmentTextureSet | undefined = this._texturesCache.get(texture || null);
282
+ /**
283
+ * @param {Texture | null | undefined} texture
284
+ * @returns {{radianceTexture: Texture | null, irradianceTexture: Texture | null}}
285
+ */
286
+ _getTextures(texture) {
287
+ /** @type {EnvironmentTextureSet | undefined} */
288
+ let res = this._texturesCache.get(texture || null);
249
289
  if (res) {
250
290
  return res;
251
291
  }
@@ -271,14 +311,18 @@ export class MaterialXEnvironment {
271
311
  return res;
272
312
  }
273
313
 
274
- private updateLighting = (collectLights: boolean = false) => {
314
+ /**
315
+ * @param {boolean} collectLights
316
+ */
317
+ updateLighting = (collectLights = false) => {
275
318
  if (!this._scene) return;
276
319
  // Find lights in scene
277
320
  if (collectLights) {
278
- const lights = new Array<Light>();
279
- this._scene.traverse((object: Object3D) => {
280
- if ((object as Light).isLight && object.visible)
281
- lights.push(object as Light);
321
+ /** @type {Array<Light>} */
322
+ const lights = new Array();
323
+ this._scene.traverse((/** @type {Object3D} */ object) => {
324
+ if ((/** @type {Light} */ (object)).isLight && object.visible)
325
+ lights.push(/** @type {Light} */ (object));
282
326
  });
283
327
  this._lights = lights;
284
328
  }