bg2e-js 2.3.11 → 2.3.13

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.
Files changed (148) hide show
  1. package/dist/bg2e-js.js +356 -326
  2. package/dist/bg2e-js.js.map +1 -1
  3. package/package.json +56 -56
  4. package/src/app/AppController.ts +39 -39
  5. package/src/app/Bg2KeyboardEvent.ts +54 -54
  6. package/src/app/Bg2MouseEvent.ts +82 -82
  7. package/src/app/Bg2TouchEvent.ts +18 -18
  8. package/src/app/Canvas.ts +108 -108
  9. package/src/app/EventBase.ts +10 -10
  10. package/src/app/MainLoop.ts +273 -273
  11. package/src/app/index.ts +24 -24
  12. package/src/base/Color.ts +134 -134
  13. package/src/base/Environment.ts +183 -183
  14. package/src/base/Light.ts +192 -192
  15. package/src/base/Material.ts +620 -620
  16. package/src/base/PolyList.ts +365 -365
  17. package/src/base/Texture.ts +620 -620
  18. package/src/base/index.ts +81 -81
  19. package/src/db/Bg2LoaderPlugin.ts +143 -143
  20. package/src/db/DBPluginApi.ts +48 -48
  21. package/src/db/Loader.ts +116 -116
  22. package/src/db/LoaderPlugin.ts +34 -34
  23. package/src/db/MtlParser.ts +7 -7
  24. package/src/db/ObjLoaderPlugin.ts +54 -54
  25. package/src/db/ObjParser.ts +252 -252
  26. package/src/db/ObjWriterPlugin.ts +18 -18
  27. package/src/db/VitscnjLoaderPlugin.ts +112 -112
  28. package/src/db/Writer.ts +52 -52
  29. package/src/db/WriterPlugin.ts +22 -22
  30. package/src/db/index.ts +44 -44
  31. package/src/debug/DebugRenderer.ts +173 -173
  32. package/src/debug/WebGLTextureViewer.ts +75 -75
  33. package/src/debug/index.ts +6 -6
  34. package/src/index.html +11 -11
  35. package/src/index.ts +33 -33
  36. package/src/manipulation/SelectionBuffer.ts +81 -81
  37. package/src/manipulation/SelectionHighlight.ts +105 -84
  38. package/src/manipulation/SelectionIdAssignVisitor.ts +96 -96
  39. package/src/manipulation/SelectionManager.ts +196 -188
  40. package/src/manipulation/SelectionMode.ts +6 -6
  41. package/src/math/Mat3.ts +259 -259
  42. package/src/math/Mat4.ts +710 -710
  43. package/src/math/MatrixStrategy.ts +25 -25
  44. package/src/math/Quat.ts +65 -65
  45. package/src/math/Vec.ts +753 -753
  46. package/src/math/constants.ts +46 -46
  47. package/src/math/functions.ts +103 -103
  48. package/src/math/index.ts +74 -74
  49. package/src/phsics/joint.ts +137 -137
  50. package/src/primitives/arrow.ts +57 -57
  51. package/src/primitives/cone.ts +138 -138
  52. package/src/primitives/cube.ts +60 -60
  53. package/src/primitives/cylinder.ts +216 -216
  54. package/src/primitives/index.ts +13 -13
  55. package/src/primitives/plane.ts +31 -31
  56. package/src/primitives/sphere.ts +809 -809
  57. package/src/react/useBg2e.ts +69 -69
  58. package/src/render/BRDFIntegrationMap.ts +4 -4
  59. package/src/render/Environment.ts +135 -135
  60. package/src/render/FrameBuffer.ts +35 -35
  61. package/src/render/MaterialRenderer.ts +34 -34
  62. package/src/render/Pipeline.ts +108 -108
  63. package/src/render/PolyListRenderer.ts +47 -47
  64. package/src/render/RenderBuffer.ts +197 -197
  65. package/src/render/RenderQueue.ts +198 -198
  66. package/src/render/RenderState.ts +116 -116
  67. package/src/render/Renderer.ts +248 -248
  68. package/src/render/SceneAppController.ts +250 -250
  69. package/src/render/SceneRenderer.ts +387 -387
  70. package/src/render/Shader.ts +32 -32
  71. package/src/render/ShadowRenderer.ts +176 -176
  72. package/src/render/SkyCube.ts +105 -105
  73. package/src/render/SkySphere.ts +117 -117
  74. package/src/render/TextureMergerRenderer.ts +70 -70
  75. package/src/render/TextureRenderer.ts +34 -34
  76. package/src/render/index.ts +67 -67
  77. package/src/render/webgl/FrameBuffer.ts +9 -9
  78. package/src/render/webgl/MaterialRenderer.ts +112 -112
  79. package/src/render/webgl/Pipeline.ts +88 -88
  80. package/src/render/webgl/PolyListRenderer.ts +260 -260
  81. package/src/render/webgl/RenderBuffer.ts +226 -226
  82. package/src/render/webgl/Renderer.ts +262 -262
  83. package/src/render/webgl/SceneRenderer.ts +67 -67
  84. package/src/render/webgl/ShaderProgram.ts +424 -424
  85. package/src/render/webgl/ShadowRenderer.ts +6 -6
  86. package/src/render/webgl/SkyCube.ts +15 -15
  87. package/src/render/webgl/SkySphere.ts +15 -15
  88. package/src/render/webgl/State.ts +152 -152
  89. package/src/render/webgl/TextureRenderer.ts +167 -167
  90. package/src/render/webgl/VertexBuffer.ts +137 -137
  91. package/src/render/webgl/index.ts +35 -35
  92. package/src/scene/Camera.ts +458 -458
  93. package/src/scene/Chain.ts +44 -44
  94. package/src/scene/ChainJoint.ts +58 -58
  95. package/src/scene/Component.ts +177 -177
  96. package/src/scene/ComponentMap.ts +106 -106
  97. package/src/scene/Drawable.ts +154 -154
  98. package/src/scene/EnvironmentComponent.ts +141 -141
  99. package/src/scene/FindNodeVisitor.ts +59 -59
  100. package/src/scene/LightComponent.ts +154 -154
  101. package/src/scene/MatrixState.ts +46 -46
  102. package/src/scene/Node.ts +328 -328
  103. package/src/scene/NodeVisitor.ts +15 -15
  104. package/src/scene/OrbitCameraController.ts +450 -450
  105. package/src/scene/SmoothOrbitCameraController.ts +99 -99
  106. package/src/scene/Transform.ts +73 -73
  107. package/src/scene/index.ts +60 -60
  108. package/src/shaders/BasicDiffuseColorShader.ts +111 -111
  109. package/src/shaders/BasicPBRLightShader.ts +276 -276
  110. package/src/shaders/DebugRenderShader.ts +97 -97
  111. package/src/shaders/DepthRenderShader.ts +127 -127
  112. package/src/shaders/IrradianceMapCubeShader.ts +115 -115
  113. package/src/shaders/PBRLightIBLShader.ts +486 -486
  114. package/src/shaders/PickSelectionShader.ts +101 -101
  115. package/src/shaders/PresentDebugFramebufferShader.ts +118 -118
  116. package/src/shaders/PresentTextureShader.ts +99 -99
  117. package/src/shaders/SelectionHighlightShader.ts +143 -127
  118. package/src/shaders/ShaderFunction.ts +318 -318
  119. package/src/shaders/SkyCubeShader.ts +93 -93
  120. package/src/shaders/SkySphereShader.ts +102 -102
  121. package/src/shaders/SpecularMapCubeShader.ts +164 -164
  122. package/src/shaders/TextureMergerShader.ts +171 -171
  123. package/src/shaders/index.ts +36 -36
  124. package/src/shaders/webgl/color_correction.glsl +47 -47
  125. package/src/shaders/webgl/constants.glsl +6 -6
  126. package/src/shaders/webgl/index.ts +70 -70
  127. package/src/shaders/webgl/normal_map.glsl +9 -9
  128. package/src/shaders/webgl/pbr.glsl +173 -173
  129. package/src/shaders/webgl/uniforms.glsl +91 -91
  130. package/src/shaders/webgl_shader_lib.ts +213 -213
  131. package/src/tools/BinaryResourceProvider.ts +14 -14
  132. package/src/tools/ImageResourceProvider.ts +66 -66
  133. package/src/tools/MaterialModifier.ts +446 -446
  134. package/src/tools/Resource.ts +203 -203
  135. package/src/tools/ResourceProvider.ts +69 -69
  136. package/src/tools/TextResourceProvider.ts +24 -24
  137. package/src/tools/TextureCache.ts +51 -51
  138. package/src/tools/TextureResourceDatabase.ts +100 -100
  139. package/src/tools/UserAgent.ts +362 -362
  140. package/src/tools/VideoResourceProvider.ts +50 -50
  141. package/src/tools/WriteStrategy.ts +22 -22
  142. package/src/tools/base64.ts +11 -11
  143. package/src/tools/crypto.ts +19 -19
  144. package/src/tools/endiantess.ts +13 -13
  145. package/src/tools/image.ts +18 -18
  146. package/src/tools/index.ts +41 -41
  147. package/src/tools/processType.ts +39 -39
  148. package/src/vite-env.d.ts +12 -12
@@ -1,620 +1,620 @@
1
-
2
- import Vec from '../math/Vec';
3
- import Color from './Color';
4
- import Texture, { TextureDataType, TextureFilter, TextureWrap } from './Texture';
5
- import Canvas from '../app/Canvas';
6
- import TextureCache from '../tools/TextureCache';
7
- import { NumericArray } from '../math/constants';
8
-
9
- export enum MaterialType {
10
- PBR = "pbr"
11
- }
12
-
13
- interface TypeLoader {
14
- serialize: (attName: string, obj: any) => any;
15
- deserialize: (attName: string, obj: any, relativePath?: string, canvas?: Canvas | null) => any;
16
- }
17
-
18
- export const textureTypeLoader: TypeLoader = {
19
- serialize: (attName: string, obj: any) => {
20
- if (!obj) {
21
- return null;
22
- }
23
- if (obj instanceof Texture) {
24
- return obj.fileName;
25
- }
26
- else {
27
- throw new Error(`Invalid parameter found in material serialization. The required parameter type is Texture`);
28
- }
29
- },
30
-
31
- deserialize: (attName: string, obj: any, relativePath: string = "", canvas: Canvas | null = null) => {
32
- if (!obj) {
33
- return null;
34
- }
35
- else if (attName === "ambientOcclussion" && typeof(obj) === "number") {
36
- // Compatibility with v1.4 where ambient occlussion could be a float value
37
- return null;
38
- }
39
- else if (typeof(obj) === "string") {
40
- const texturePath = relativePath + obj;
41
- const textureCache = TextureCache.Get(canvas);
42
- if (textureCache.findTexture(texturePath)) {
43
- console.debug(`Texture '${ texturePath }' already loaded. Reusing texture.`);
44
- return textureCache.getTexture(texturePath);
45
- }
46
- else {
47
- console.log(`Texture not found in cache. Loading texture '${ texturePath }'`);
48
- const tex = new Texture(canvas);
49
- tex.fileName = relativePath + obj;
50
- tex.dataType = TextureDataType.IMAGE;
51
- tex.minFilter = TextureFilter.LINEAR_MIPMAP_LINEAR;
52
- tex.magFilter = TextureFilter.LINEAR;
53
- tex.wrapModeX = TextureWrap.REPEAT;
54
- tex.wrapModeY = TextureWrap.REPEAT;
55
- textureCache.registerTexture(tex);
56
- return tex;
57
- }
58
- }
59
- else {
60
- throw new Error(`Invalid parameter found in material deserialization. The required parameter type is string (file path)`);
61
- }
62
- }
63
- }
64
-
65
- export const colorTypeLoader: TypeLoader = {
66
- serialize: (attName: string, obj: any) => {
67
- if (!obj) {
68
- return null;
69
- }
70
-
71
- if (obj instanceof Color) {
72
- return obj;
73
- }
74
- else {
75
- throw new Error(`Invalid parameter found in material serialization. The required parameter type is Color`);
76
- }
77
- },
78
-
79
- deserialize: (attName: string, obj: any) => {
80
- if (!obj) {
81
- return null;
82
- }
83
- else if ((Array.isArray(obj) || obj instanceof NumericArray) &&
84
- (obj.length === 3 || obj.length === 4)
85
- ) {
86
- if (obj.length === 3) {
87
- return new Color([obj[0], obj[1], obj[2], 1]);
88
- }
89
- else if (obj.length === 4) {
90
- return new Color([obj[0], obj[1], obj[2], obj[3]]);
91
- }
92
- }
93
- else {
94
- throw new Error(`Invalid parameter found in material deserialization. The required parameter type is array with 3 or 4 elements`);
95
- }
96
- }
97
- }
98
-
99
- export const vectorTypeLoader: TypeLoader = {
100
- serialize: (attName: string, obj: any) => {
101
- if (!obj) {
102
- return null;
103
- }
104
-
105
- if (obj instanceof Vec) {
106
- return obj;
107
- }
108
- else {
109
- throw new Error(`Invalid parameter found in material serialization. The required parameter type is Vec`);
110
- }
111
- },
112
-
113
- deserialize: (attName: string, obj: any) => {
114
- if (!obj) {
115
- return null;
116
- }
117
- else if (obj.length >= 2 && obj.length <= 4) {
118
- return new Vec(obj);
119
- }
120
- // Retrocompatibility with v1.4
121
- else if (obj._v && obj._v.length >= 2 && obj._v.length <= 4) {
122
- return new Vec(obj._v);
123
- }
124
- else {
125
- throw new Error(`Invalid parameter found in material deserialization. The required parameter type is array with 2, 3 or 4 elements`);
126
- }
127
- }
128
- }
129
-
130
- export const primitiveTypeLoader: TypeLoader = {
131
- serialize: (attName: string, obj: any) => {
132
- if (!obj) {
133
- return null;
134
- }
135
-
136
- return obj;
137
- },
138
-
139
- deserialize: (attName: string, obj: any) => {
140
- return obj;
141
- }
142
- }
143
-
144
- interface MaterialAttribute {
145
- loader: TypeLoader;
146
- }
147
-
148
- export const MaterialAttributeNames: { [key: string]: MaterialAttribute } = {
149
- type: { loader: primitiveTypeLoader },
150
- alphaCutoff: { loader: primitiveTypeLoader },
151
- isTransparent: { loader: primitiveTypeLoader },
152
- albedo: { loader: colorTypeLoader },
153
- albedoTexture: { loader: textureTypeLoader },
154
- albedoScale: { loader: vectorTypeLoader },
155
- albedoUV: { loader: primitiveTypeLoader },
156
- normalTexture: { loader: textureTypeLoader },
157
- normalScale: { loader: vectorTypeLoader },
158
- normalUV: { loader: primitiveTypeLoader },
159
- metalness: { loader: primitiveTypeLoader },
160
- metalnessTexture: { loader: textureTypeLoader },
161
- metalnessChannel: { loader: primitiveTypeLoader },
162
- metalnessScale: { loader: vectorTypeLoader },
163
- metalnessUV: { loader: primitiveTypeLoader },
164
- roughness: { loader: primitiveTypeLoader },
165
- roughnessTexture: { loader: textureTypeLoader },
166
- roughnessChannel: { loader: primitiveTypeLoader },
167
- roughnessScale: { loader: vectorTypeLoader },
168
- roughnessUV: { loader: primitiveTypeLoader },
169
- fresnelTint: { loader: colorTypeLoader },
170
- sheenIntensity: { loader: primitiveTypeLoader },
171
- sheenColor: { loader: colorTypeLoader },
172
- lightEmission: { loader: colorTypeLoader },
173
- lightEmissionTexture: { loader: textureTypeLoader },
174
- lightEmissionChannel: { loader: primitiveTypeLoader },
175
- lightEmissionScale: { loader: vectorTypeLoader },
176
- lightEmissionUV: { loader: primitiveTypeLoader },
177
- ambientOcclussion: { loader: textureTypeLoader },
178
- ambientOcclussionChannel: { loader: primitiveTypeLoader },
179
- ambientOcclussionUV: { loader: primitiveTypeLoader },
180
- heightTexture: { loader: textureTypeLoader },
181
- heightChannel: { loader: primitiveTypeLoader },
182
- heightScale: { loader: vectorTypeLoader },
183
- heightUV: { loader: primitiveTypeLoader },
184
- heightIntensity: { loader: primitiveTypeLoader },
185
- castShadows: { loader: primitiveTypeLoader },
186
- unlit: { loader: primitiveTypeLoader }
187
- };
188
-
189
- export const assertTexture = (v: any, name: string): void => {
190
- if (!(v instanceof Texture)) {
191
- throw new Error(`Invalid parameter setting '${ name }' material attribute. The required parameter type is Texture`);
192
- }
193
- }
194
-
195
- export const assertColor = (v: any, name: string): void => {
196
- if (!(v instanceof Color)) {
197
- throw new Error(`Invalid parameter setting '${ name }' material attribute. The required parameter type is Color`);
198
- }
199
- }
200
-
201
- export const assertScale = (v: any, name: string): void => {
202
- if (!(v instanceof Vec) || v.length != 2) {
203
- throw new Error(`Invalid parameter setting '${ name }' material attribute. The required parameter type is Vec with two elements.`);
204
- }
205
- }
206
-
207
- // Clone the `obj` parameter if it is
208
- // - Vec
209
- // - Color
210
- // - Texture
211
- // Returns the same parameter if not
212
- export const cloneObject = (obj: any): any => {
213
- if (obj instanceof Color) {
214
- return new Color(obj);
215
- }
216
- else if (obj instanceof Vec) {
217
- return new Vec(obj);
218
- }
219
- else if (obj instanceof Texture) {
220
- return obj.clone();
221
- }
222
- else {
223
- return obj;
224
- }
225
- }
226
-
227
- export default class Material {
228
- static async Deserialize(sceneData: any, relativePath: string = "", canvas: Canvas | null = null): Promise<Material> {
229
- const result = new Material(canvas);
230
- await result.deserialize(sceneData, relativePath, canvas);
231
- return result;
232
- }
233
-
234
- private _canvas: Canvas | null;
235
- private _type: string;
236
- private _renderer: any;
237
- private _alphaCutoff: number;
238
- private _isTransparent: boolean;
239
- private _albedo: Color;
240
- private _albedoTexture: Texture | null;
241
- private _albedoScale: Vec;
242
- private _albedoUV: number;
243
- private _normalTexture: Texture | null;
244
- private _normalScale: Vec;
245
- private _normalUV: number;
246
- private _normalChannel: number;
247
- private _metalness: number;
248
- private _metalnessTexture: Texture | null;
249
- private _metalnessChannel: number;
250
- private _metalnessScale: Vec;
251
- private _metalnessUV: number;
252
- private _roughness: number;
253
- private _roughnessTexture: Texture | null;
254
- private _roughnessChannel: number;
255
- private _roughnessScale: Vec;
256
- private _roughnessUV: number;
257
- private _fresnelTint: Color;
258
- private _sheenIntensity: number;
259
- private _sheenColor: Color;
260
- private _lightEmission: Color | number;
261
- private _lightEmissionTexture: Texture | null;
262
- private _lightEmissionChannel: number;
263
- private _lightEmissionScale: Vec;
264
- private _lightEmissionUV: number;
265
- private _ambientOcclussion: Texture | null;
266
- private _ambientOcclussionChannel: number;
267
- private _ambientOcclussionUV: number;
268
- private _heightTexture: Texture | null;
269
- private _heightChannel: number;
270
- private _heightScale: Vec;
271
- private _heightUV: number;
272
- private _heightIntensity: number;
273
- private _castShadows: boolean;
274
- private _unlit: boolean;
275
- private _dirty: boolean;
276
-
277
- constructor(canvas: Canvas | null = null) {
278
- this._canvas = canvas || Canvas.FirstCanvas();
279
- this._type = MaterialType.PBR;
280
- this._renderer = null;
281
-
282
- this._alphaCutoff = 0.5;
283
- this._isTransparent = false;
284
- this._albedo = Color.White();
285
- this._albedoTexture = null;
286
- this._albedoScale = new Vec(1, 1);
287
- this._albedoUV = 0;
288
- this._normalTexture = null;
289
- this._normalScale = new Vec(1, 1);
290
- this._normalUV = 0;
291
- this._normalChannel = 0;
292
- this._metalness = 0;
293
- this._metalnessTexture = null;
294
- this._metalnessChannel = 0;
295
- this._metalnessScale = new Vec(1, 1);
296
- this._metalnessUV = 0;
297
- this._roughness = 1;
298
- this._roughnessTexture = null;
299
- this._roughnessChannel = 0;
300
- this._roughnessScale = new Vec(1, 1);
301
- this._roughnessUV = 0;
302
- this._fresnelTint = Color.White();
303
- this._sheenIntensity = 0.0;
304
- this._sheenColor = Color.White();
305
- this._lightEmission = 0;
306
- this._lightEmissionTexture = null;
307
- this._lightEmissionChannel = 0;
308
- this._lightEmissionScale = new Vec(1, 1);
309
- this._lightEmissionUV = 0;
310
- this._ambientOcclussion = null;
311
- this._ambientOcclussionChannel = 0;
312
- this._ambientOcclussionUV = 1;
313
- this._heightTexture = null;
314
- this._heightChannel = 0;
315
- this._heightScale = new Vec(1, 1);
316
- this._heightUV = 0;
317
- this._heightIntensity = 1.0;
318
- this._castShadows = true;
319
- this._unlit = false;
320
-
321
- this._dirty = true;
322
- }
323
-
324
- get canvas(): Canvas | null {
325
- return this._canvas;
326
- }
327
-
328
- get renderer(): any {
329
- return this._renderer;
330
- }
331
-
332
- get dirty(): boolean {
333
- return this._dirty;
334
- }
335
-
336
- set dirty(d: boolean) {
337
- this._dirty = d;
338
- }
339
-
340
- clone(): Material {
341
- const result = new Material();
342
- result.assign(this);
343
- return result;
344
- }
345
-
346
- assign(other: Material): void {
347
- this._type = other._type;
348
- this._alphaCutoff = other._alphaCutoff;;
349
- this._isTransparent = other._isTransparent;
350
- this._albedo = cloneObject(other._albedo);
351
- this._albedoTexture = cloneObject(other._albedoTexture);
352
- this._albedoScale = cloneObject(other._albedoScale);
353
- this._albedoUV = other._albedoUV;
354
- this._normalTexture = cloneObject(other._normalTexture);
355
- this._normalScale = cloneObject(other._normalScale);
356
- this._normalUV = other._normalUV;
357
- this._metalness = other._metalness;
358
- this._metalnessTexture = cloneObject(other._metalnessTexture);
359
- this._metalnessChannel = other._metalnessChannel;
360
- this._metalnessScale = cloneObject(other._metalnessScale);
361
- this._metalnessUV = other._metalnessUV;
362
- this._roughness = other._roughness;
363
- this._roughnessTexture = cloneObject(other._roughnessTexture);
364
- this._roughnessChannel = other._roughnessChannel;
365
- this._roughnessScale = cloneObject(other._roughnessScale);
366
- this._roughnessUV = other._roughnessUV;
367
- this._fresnelTint = cloneObject(other._fresnelTint);
368
- this._sheenIntensity = other._sheenIntensity;
369
- this._sheenColor = cloneObject(other._sheenColor);
370
- this._lightEmission = other._lightEmission;
371
- this._lightEmissionTexture = cloneObject(other._lightEmissionTexture);
372
- this._lightEmissionChannel = other._lightEmissionChannel;
373
- this._lightEmissionScale = cloneObject(other._lightEmissionScale);
374
- this._lightEmissionUV = other._lightEmissionUV;
375
- this._ambientOcclussion = other._ambientOcclussion;
376
- this._ambientOcclussionChannel = other._ambientOcclussionChannel;
377
- this._ambientOcclussionUV = other._ambientOcclussionUV;
378
- this._heightTexture = cloneObject(other._heightTexture);
379
- this._heightChannel = other._heightChannel;
380
- this._heightScale = cloneObject(other._heightScale);
381
- this._heightUV = other._heightUV;
382
- this._heightIntensity = other._heightIntensity;
383
- this._castShadows = other._castShadows;
384
- this._unlit = other._unlit;
385
-
386
- this._dirty = true;
387
- }
388
-
389
- get type(): string { return this._type; }
390
- set type(v: string) {
391
- // Compatibility with v1.4
392
- if (v === "PBRMaterial") {
393
- v = "pbr";
394
- }
395
- this._type = v;
396
- this._dirty = true;
397
- }
398
-
399
- get albedo(): Color { return this._albedo; }
400
- set albedo(v: Color) {
401
- this._albedo = v;
402
- this._dirty = true;
403
- }
404
- get albedoTexture(): Texture | null { return this._albedoTexture; }
405
- set albedoTexture(v: Texture | null) {
406
- v && assertTexture(v, "albedoTexture");
407
- if (this._albedoTexture instanceof Texture) {
408
- this._albedoTexture.decReferences();
409
- }
410
- this._albedoTexture = v;
411
- if (this._albedoTexture instanceof Texture) {
412
- this._albedoTexture.incReferences();
413
- }
414
- this._dirty = true;
415
- }
416
-
417
- get albedoScale(): Vec { return this._albedoScale; }
418
- set albedoScale(v: Vec) { assertScale(v, "albedoScale"); this._albedoScale = new Vec(v); this._dirty = true; }
419
- get albedoUV(): number { return this._albedoUV; }
420
- set albedoUV(v: number) { this._albedoUV = v; this._dirty = true; }
421
- get alphaCutoff(): number { return this._alphaCutoff; }
422
- set alphaCutoff(v: number) { this._alphaCutoff = v; this._dirty = true; }
423
- get isTransparent(): boolean { return this._isTransparent; }
424
- set isTransparent(v: boolean) { this._isTransparent = v; this._dirty = true; }
425
-
426
- get normalTexture(): Texture | null { return this._normalTexture; }
427
- set normalTexture(v: Texture | null) {
428
- v && assertTexture(v, "normalTexture");
429
- if (this._normalTexture instanceof Texture) {
430
- this._normalTexture.decReferences();
431
- }
432
- this._normalTexture = v;
433
- if (this._normalTexture instanceof Texture) {
434
- this._normalTexture.incReferences();
435
- }
436
- this._dirty = true;
437
- }
438
-
439
- get normalChannel(): number { return this._normalChannel; }
440
- set normalChannel(v: number) { this._normalChannel = v; this._dirty = true; }
441
- get normalScale(): Vec { return this._normalScale; }
442
- set normalScale(v: Vec) { assertScale(v, "normalScale"); this._normalScale = new Vec(v); this._dirty = true; }
443
- get normalUV(): number { return this._normalUV; }
444
- set normalUV(v: number) { this._normalUV = v; this._dirty = true; }
445
-
446
- get metalness(): number { return this._metalness; }
447
- set metalness(v: number) {
448
- this._metalness = v;
449
- this._dirty = true;
450
- }
451
-
452
- get metalnessTexture(): Texture | null { return this._metalnessTexture; }
453
- set metalnessTexture(v: Texture | null) {
454
- v && assertTexture(v, "metalness");
455
- if (this._metalnessTexture instanceof Texture) {
456
- this._metalnessTexture.decReferences();
457
- }
458
- this._metalnessTexture = v;
459
- if (this._metalnessTexture instanceof Texture) {
460
- this._metalnessTexture.incReferences();
461
- }
462
- this._dirty = true;
463
- }
464
-
465
- get metalnessChannel(): number { return this._metalnessChannel; }
466
- set metalnessChannel(v: number) { this._metalnessChannel = v; this._dirty = true; }
467
- get metalnessScale(): Vec { return this._metalnessScale; }
468
- set metalnessScale(v: Vec) { assertScale(v, "metalnessScale"); this._metalnessScale = new Vec(v); this._dirty = true; }
469
- get metalnessUV(): number { return this._metalnessUV; }
470
- set metalnessUV(v: number) { this._metalnessUV = v; this._dirty = true; }
471
-
472
- get roughness(): number { return this._roughness; }
473
- set roughness(v: number) {
474
- this._roughness = v;
475
- this._dirty = true;
476
- }
477
-
478
- get roughnessTexture(): Texture | null { return this._roughnessTexture; }
479
- set roughnessTexture (v: Texture | null) {
480
- v && assertTexture(v, "roughness");
481
- if (this._roughnessTexture instanceof Texture) {
482
- this._roughnessTexture.decReferences();
483
- }
484
- this._roughnessTexture = v;
485
- if (this._roughnessTexture instanceof Texture) {
486
- this._roughnessTexture.incReferences();
487
- }
488
- this._dirty = true;
489
- }
490
-
491
- get roughnessChannel(): number { return this._roughnessChannel; }
492
- set roughnessChannel(v: number) { this._roughnessChannel = v; this._dirty = true; }
493
- get roughnessScale(): Vec { return this._roughnessScale; }
494
- set roughnessScale(v: Vec) { assertScale(v, "roughnessScale"); this._roughnessScale = new Vec(v); this._dirty = true; }
495
- get roughnessUV(): number { return this._roughnessUV; }
496
- set roughnessUV(v: number) { this._roughnessUV = v; this._dirty = true; }
497
-
498
- get fresnelTint(): Color { return this._fresnelTint; }
499
- set fresnelTint(v: Color) { assertColor(v, "fresnelTint"); this._fresnelTint = v; this._dirty = true; }
500
- get sheenIntensity(): number { return this._sheenIntensity; }
501
- set sheenIntensity(v: number) { this._sheenIntensity = v; this._dirty = true; }
502
- get sheenColor(): Color { return this._sheenColor; }
503
- set sheenColor(v: Color) { assertColor(v, "sheenColor"); this._sheenColor = v; this._dirty = true; }
504
-
505
- get lightEmission(): Color | number { return this._lightEmission; }
506
- set lightEmission(v: Color | number) {
507
- if (typeof v === "number") {
508
- v = new Color([v, v, v, 1]);
509
- }
510
- assertColor(v, "lightEmission"); this._lightEmission = v; this._dirty = true;
511
- }
512
- get lightEmissionTexture(): Texture | null { return this._lightEmissionTexture; }
513
- set lightEmissionTexture(v: Texture | null) {
514
- v && assertTexture(v, 'lightEmissionTexture');
515
- if (this._lightEmissionTexture instanceof Texture) {
516
- this._lightEmissionTexture.decReferences();
517
- }
518
- this._lightEmissionTexture = v;
519
- if (this._lightEmissionTexture instanceof Texture) {
520
- this._lightEmissionTexture.incReferences();
521
- }
522
- this._dirty = true;
523
- }
524
-
525
- get lightEmissionChannel(): number { return this._lightEmissionChannel; }
526
- set lightEmissionChannel(v: number) { this._lightEmissionChannel = v; this._dirty = true; }
527
- get lightEmissionScale(): Vec { return this._lightEmissionScale; }
528
- set lightEmissionScale(v: Vec) { assertScale(v, "lightEmissionScale"); this._lightEmissionScale = new Vec(v); this._dirty = true; }
529
- get lightEmissionUV(): number { return this._lightEmissionUV; }
530
- set lightEmissionUV(v: number) { this._lightEmissionUV = v; this._dirty = true; }
531
-
532
- get ambientOcclussion(): Texture | null { return this._ambientOcclussion; }
533
- set ambientOcclussion(v: Texture | null) {
534
- v && assertTexture(v, "ambientOcclussion");
535
- if (this._ambientOcclussion instanceof Texture) {
536
- this._ambientOcclussion.decReferences();
537
- }
538
- this._ambientOcclussion = v;
539
- if (this._ambientOcclussion instanceof Texture) {
540
- this._ambientOcclussion.incReferences();
541
- }
542
- this._dirty = true;
543
- }
544
-
545
- get ambientOcclussionChannel(): number { return this._ambientOcclussionChannel; }
546
- set ambientOcclussionChannel(v: number) { this._ambientOcclussionChannel = v; this._dirty = true; }
547
- get ambientOcclussionUV(): number { return this._ambientOcclussionUV; }
548
- set ambientOcclussionUV(v: number) { this._ambientOcclussionUV = v; this._dirty = true; }
549
-
550
-
551
-
552
- get heightTexture(): Texture | null { return this._heightTexture; }
553
- set heightTexture(v: Texture | null) { assertTexture(v, "heightTexture"); this._heightTexture = v; this._dirty = true; }
554
- get heightChannel(): number { return this._heightChannel; }
555
- set heightChannel(v: number) { this._heightChannel = v; this._dirty = true; }
556
- get heightScale(): Vec { return this._heightScale; }
557
- set heightScale(v: Vec) { assertScale(v, "heightScale"); this._heightScale = new Vec(v); this._dirty = true; }
558
- get heightUV(): number { return this._heightUV; }
559
- set heightUV(v: number) { this._heightUV = v; this._dirty = true; }
560
- get heightIntensity(): number { return this._heightIntensity; }
561
- set heightIntensity(v: number) { this._heightIntensity = v; this._dirty = true; }
562
- get castShadows(): boolean { return this._castShadows; }
563
- set castShadows(v: boolean) { this._castShadows = v; this._dirty = true; }
564
- get unlit(): boolean { return this._unlit; }
565
- set unlit(v: boolean) { this._unlit = v; this._dirty = true; }
566
-
567
- async serialize(sceneData: any): Promise<void> {
568
- for (const att in MaterialAttributeNames) {
569
- const value = MaterialAttributeNames[att].loader.serialize(att, (this as any)[att]);
570
- if (value) {
571
- sceneData[att] = value;
572
- }
573
- }
574
- }
575
-
576
- async deserialize(sceneData: any, relativePath: string, canvas?: Canvas | null): Promise<void> {
577
- const P: Promise<any>[] = [];
578
-
579
- this.type = sceneData.type || MaterialType.PBR;
580
- this.alphaCutoff = sceneData.alphaCutoff || 0.5;
581
- this.isTransparent = sceneData.isTransparent || false;
582
-
583
- for (const attName in MaterialAttributeNames) {
584
- const loader = MaterialAttributeNames[attName]?.loader;
585
- if (loader) {
586
- const value = loader.deserialize(attName, sceneData[attName], relativePath, this.canvas);
587
- if (value instanceof Texture) {
588
- P.push(value.loadImageData());
589
- }
590
-
591
- if (value !== null && value !== undefined) {
592
- (this as any)[attName] = value;
593
- }
594
- }
595
- }
596
- await Promise.all(P);
597
- }
598
-
599
- destroy(): void {
600
- const decReferences = (attrib: string) => {
601
- if ((this as any)[attrib] instanceof Texture) {
602
- (this as any)[attrib].decReferences();
603
- }
604
- }
605
-
606
- decReferences("albedoTexture");
607
- decReferences("normalTexture");
608
- decReferences("metalnessTexture");
609
- decReferences("roughnessTexture");
610
- decReferences("lightEmissionTexture");
611
- decReferences("ambientOcclussion");
612
- decReferences("height");
613
-
614
- this._canvas = null;
615
-
616
- if (this.renderer) {
617
- this.renderer.destroy();
618
- }
619
- }
620
- }
1
+
2
+ import Vec from '../math/Vec';
3
+ import Color from './Color';
4
+ import Texture, { TextureDataType, TextureFilter, TextureWrap } from './Texture';
5
+ import Canvas from '../app/Canvas';
6
+ import TextureCache from '../tools/TextureCache';
7
+ import { NumericArray } from '../math/constants';
8
+
9
+ export enum MaterialType {
10
+ PBR = "pbr"
11
+ }
12
+
13
+ interface TypeLoader {
14
+ serialize: (attName: string, obj: any) => any;
15
+ deserialize: (attName: string, obj: any, relativePath?: string, canvas?: Canvas | null) => any;
16
+ }
17
+
18
+ export const textureTypeLoader: TypeLoader = {
19
+ serialize: (attName: string, obj: any) => {
20
+ if (!obj) {
21
+ return null;
22
+ }
23
+ if (obj instanceof Texture) {
24
+ return obj.fileName;
25
+ }
26
+ else {
27
+ throw new Error(`Invalid parameter found in material serialization. The required parameter type is Texture`);
28
+ }
29
+ },
30
+
31
+ deserialize: (attName: string, obj: any, relativePath: string = "", canvas: Canvas | null = null) => {
32
+ if (!obj) {
33
+ return null;
34
+ }
35
+ else if (attName === "ambientOcclussion" && typeof(obj) === "number") {
36
+ // Compatibility with v1.4 where ambient occlussion could be a float value
37
+ return null;
38
+ }
39
+ else if (typeof(obj) === "string") {
40
+ const texturePath = relativePath + obj;
41
+ const textureCache = TextureCache.Get(canvas);
42
+ if (textureCache.findTexture(texturePath)) {
43
+ console.debug(`Texture '${ texturePath }' already loaded. Reusing texture.`);
44
+ return textureCache.getTexture(texturePath);
45
+ }
46
+ else {
47
+ console.log(`Texture not found in cache. Loading texture '${ texturePath }'`);
48
+ const tex = new Texture(canvas);
49
+ tex.fileName = relativePath + obj;
50
+ tex.dataType = TextureDataType.IMAGE;
51
+ tex.minFilter = TextureFilter.LINEAR_MIPMAP_LINEAR;
52
+ tex.magFilter = TextureFilter.LINEAR;
53
+ tex.wrapModeX = TextureWrap.REPEAT;
54
+ tex.wrapModeY = TextureWrap.REPEAT;
55
+ textureCache.registerTexture(tex);
56
+ return tex;
57
+ }
58
+ }
59
+ else {
60
+ throw new Error(`Invalid parameter found in material deserialization. The required parameter type is string (file path)`);
61
+ }
62
+ }
63
+ }
64
+
65
+ export const colorTypeLoader: TypeLoader = {
66
+ serialize: (attName: string, obj: any) => {
67
+ if (!obj) {
68
+ return null;
69
+ }
70
+
71
+ if (obj instanceof Color) {
72
+ return obj;
73
+ }
74
+ else {
75
+ throw new Error(`Invalid parameter found in material serialization. The required parameter type is Color`);
76
+ }
77
+ },
78
+
79
+ deserialize: (attName: string, obj: any) => {
80
+ if (!obj) {
81
+ return null;
82
+ }
83
+ else if ((Array.isArray(obj) || obj instanceof NumericArray) &&
84
+ (obj.length === 3 || obj.length === 4)
85
+ ) {
86
+ if (obj.length === 3) {
87
+ return new Color([obj[0], obj[1], obj[2], 1]);
88
+ }
89
+ else if (obj.length === 4) {
90
+ return new Color([obj[0], obj[1], obj[2], obj[3]]);
91
+ }
92
+ }
93
+ else {
94
+ throw new Error(`Invalid parameter found in material deserialization. The required parameter type is array with 3 or 4 elements`);
95
+ }
96
+ }
97
+ }
98
+
99
+ export const vectorTypeLoader: TypeLoader = {
100
+ serialize: (attName: string, obj: any) => {
101
+ if (!obj) {
102
+ return null;
103
+ }
104
+
105
+ if (obj instanceof Vec) {
106
+ return obj;
107
+ }
108
+ else {
109
+ throw new Error(`Invalid parameter found in material serialization. The required parameter type is Vec`);
110
+ }
111
+ },
112
+
113
+ deserialize: (attName: string, obj: any) => {
114
+ if (!obj) {
115
+ return null;
116
+ }
117
+ else if (obj.length >= 2 && obj.length <= 4) {
118
+ return new Vec(obj);
119
+ }
120
+ // Retrocompatibility with v1.4
121
+ else if (obj._v && obj._v.length >= 2 && obj._v.length <= 4) {
122
+ return new Vec(obj._v);
123
+ }
124
+ else {
125
+ throw new Error(`Invalid parameter found in material deserialization. The required parameter type is array with 2, 3 or 4 elements`);
126
+ }
127
+ }
128
+ }
129
+
130
+ export const primitiveTypeLoader: TypeLoader = {
131
+ serialize: (attName: string, obj: any) => {
132
+ if (!obj) {
133
+ return null;
134
+ }
135
+
136
+ return obj;
137
+ },
138
+
139
+ deserialize: (attName: string, obj: any) => {
140
+ return obj;
141
+ }
142
+ }
143
+
144
+ interface MaterialAttribute {
145
+ loader: TypeLoader;
146
+ }
147
+
148
+ export const MaterialAttributeNames: { [key: string]: MaterialAttribute } = {
149
+ type: { loader: primitiveTypeLoader },
150
+ alphaCutoff: { loader: primitiveTypeLoader },
151
+ isTransparent: { loader: primitiveTypeLoader },
152
+ albedo: { loader: colorTypeLoader },
153
+ albedoTexture: { loader: textureTypeLoader },
154
+ albedoScale: { loader: vectorTypeLoader },
155
+ albedoUV: { loader: primitiveTypeLoader },
156
+ normalTexture: { loader: textureTypeLoader },
157
+ normalScale: { loader: vectorTypeLoader },
158
+ normalUV: { loader: primitiveTypeLoader },
159
+ metalness: { loader: primitiveTypeLoader },
160
+ metalnessTexture: { loader: textureTypeLoader },
161
+ metalnessChannel: { loader: primitiveTypeLoader },
162
+ metalnessScale: { loader: vectorTypeLoader },
163
+ metalnessUV: { loader: primitiveTypeLoader },
164
+ roughness: { loader: primitiveTypeLoader },
165
+ roughnessTexture: { loader: textureTypeLoader },
166
+ roughnessChannel: { loader: primitiveTypeLoader },
167
+ roughnessScale: { loader: vectorTypeLoader },
168
+ roughnessUV: { loader: primitiveTypeLoader },
169
+ fresnelTint: { loader: colorTypeLoader },
170
+ sheenIntensity: { loader: primitiveTypeLoader },
171
+ sheenColor: { loader: colorTypeLoader },
172
+ lightEmission: { loader: colorTypeLoader },
173
+ lightEmissionTexture: { loader: textureTypeLoader },
174
+ lightEmissionChannel: { loader: primitiveTypeLoader },
175
+ lightEmissionScale: { loader: vectorTypeLoader },
176
+ lightEmissionUV: { loader: primitiveTypeLoader },
177
+ ambientOcclussion: { loader: textureTypeLoader },
178
+ ambientOcclussionChannel: { loader: primitiveTypeLoader },
179
+ ambientOcclussionUV: { loader: primitiveTypeLoader },
180
+ heightTexture: { loader: textureTypeLoader },
181
+ heightChannel: { loader: primitiveTypeLoader },
182
+ heightScale: { loader: vectorTypeLoader },
183
+ heightUV: { loader: primitiveTypeLoader },
184
+ heightIntensity: { loader: primitiveTypeLoader },
185
+ castShadows: { loader: primitiveTypeLoader },
186
+ unlit: { loader: primitiveTypeLoader }
187
+ };
188
+
189
+ export const assertTexture = (v: any, name: string): void => {
190
+ if (!(v instanceof Texture)) {
191
+ throw new Error(`Invalid parameter setting '${ name }' material attribute. The required parameter type is Texture`);
192
+ }
193
+ }
194
+
195
+ export const assertColor = (v: any, name: string): void => {
196
+ if (!(v instanceof Color)) {
197
+ throw new Error(`Invalid parameter setting '${ name }' material attribute. The required parameter type is Color`);
198
+ }
199
+ }
200
+
201
+ export const assertScale = (v: any, name: string): void => {
202
+ if (!(v instanceof Vec) || v.length != 2) {
203
+ throw new Error(`Invalid parameter setting '${ name }' material attribute. The required parameter type is Vec with two elements.`);
204
+ }
205
+ }
206
+
207
+ // Clone the `obj` parameter if it is
208
+ // - Vec
209
+ // - Color
210
+ // - Texture
211
+ // Returns the same parameter if not
212
+ export const cloneObject = (obj: any): any => {
213
+ if (obj instanceof Color) {
214
+ return new Color(obj);
215
+ }
216
+ else if (obj instanceof Vec) {
217
+ return new Vec(obj);
218
+ }
219
+ else if (obj instanceof Texture) {
220
+ return obj.clone();
221
+ }
222
+ else {
223
+ return obj;
224
+ }
225
+ }
226
+
227
+ export default class Material {
228
+ static async Deserialize(sceneData: any, relativePath: string = "", canvas: Canvas | null = null): Promise<Material> {
229
+ const result = new Material(canvas);
230
+ await result.deserialize(sceneData, relativePath, canvas);
231
+ return result;
232
+ }
233
+
234
+ private _canvas: Canvas | null;
235
+ private _type: string;
236
+ private _renderer: any;
237
+ private _alphaCutoff: number;
238
+ private _isTransparent: boolean;
239
+ private _albedo: Color;
240
+ private _albedoTexture: Texture | null;
241
+ private _albedoScale: Vec;
242
+ private _albedoUV: number;
243
+ private _normalTexture: Texture | null;
244
+ private _normalScale: Vec;
245
+ private _normalUV: number;
246
+ private _normalChannel: number;
247
+ private _metalness: number;
248
+ private _metalnessTexture: Texture | null;
249
+ private _metalnessChannel: number;
250
+ private _metalnessScale: Vec;
251
+ private _metalnessUV: number;
252
+ private _roughness: number;
253
+ private _roughnessTexture: Texture | null;
254
+ private _roughnessChannel: number;
255
+ private _roughnessScale: Vec;
256
+ private _roughnessUV: number;
257
+ private _fresnelTint: Color;
258
+ private _sheenIntensity: number;
259
+ private _sheenColor: Color;
260
+ private _lightEmission: Color | number;
261
+ private _lightEmissionTexture: Texture | null;
262
+ private _lightEmissionChannel: number;
263
+ private _lightEmissionScale: Vec;
264
+ private _lightEmissionUV: number;
265
+ private _ambientOcclussion: Texture | null;
266
+ private _ambientOcclussionChannel: number;
267
+ private _ambientOcclussionUV: number;
268
+ private _heightTexture: Texture | null;
269
+ private _heightChannel: number;
270
+ private _heightScale: Vec;
271
+ private _heightUV: number;
272
+ private _heightIntensity: number;
273
+ private _castShadows: boolean;
274
+ private _unlit: boolean;
275
+ private _dirty: boolean;
276
+
277
+ constructor(canvas: Canvas | null = null) {
278
+ this._canvas = canvas || Canvas.FirstCanvas();
279
+ this._type = MaterialType.PBR;
280
+ this._renderer = null;
281
+
282
+ this._alphaCutoff = 0.5;
283
+ this._isTransparent = false;
284
+ this._albedo = Color.White();
285
+ this._albedoTexture = null;
286
+ this._albedoScale = new Vec(1, 1);
287
+ this._albedoUV = 0;
288
+ this._normalTexture = null;
289
+ this._normalScale = new Vec(1, 1);
290
+ this._normalUV = 0;
291
+ this._normalChannel = 0;
292
+ this._metalness = 0;
293
+ this._metalnessTexture = null;
294
+ this._metalnessChannel = 0;
295
+ this._metalnessScale = new Vec(1, 1);
296
+ this._metalnessUV = 0;
297
+ this._roughness = 1;
298
+ this._roughnessTexture = null;
299
+ this._roughnessChannel = 0;
300
+ this._roughnessScale = new Vec(1, 1);
301
+ this._roughnessUV = 0;
302
+ this._fresnelTint = Color.White();
303
+ this._sheenIntensity = 0.0;
304
+ this._sheenColor = Color.White();
305
+ this._lightEmission = 0;
306
+ this._lightEmissionTexture = null;
307
+ this._lightEmissionChannel = 0;
308
+ this._lightEmissionScale = new Vec(1, 1);
309
+ this._lightEmissionUV = 0;
310
+ this._ambientOcclussion = null;
311
+ this._ambientOcclussionChannel = 0;
312
+ this._ambientOcclussionUV = 1;
313
+ this._heightTexture = null;
314
+ this._heightChannel = 0;
315
+ this._heightScale = new Vec(1, 1);
316
+ this._heightUV = 0;
317
+ this._heightIntensity = 1.0;
318
+ this._castShadows = true;
319
+ this._unlit = false;
320
+
321
+ this._dirty = true;
322
+ }
323
+
324
+ get canvas(): Canvas | null {
325
+ return this._canvas;
326
+ }
327
+
328
+ get renderer(): any {
329
+ return this._renderer;
330
+ }
331
+
332
+ get dirty(): boolean {
333
+ return this._dirty;
334
+ }
335
+
336
+ set dirty(d: boolean) {
337
+ this._dirty = d;
338
+ }
339
+
340
+ clone(): Material {
341
+ const result = new Material();
342
+ result.assign(this);
343
+ return result;
344
+ }
345
+
346
+ assign(other: Material): void {
347
+ this._type = other._type;
348
+ this._alphaCutoff = other._alphaCutoff;;
349
+ this._isTransparent = other._isTransparent;
350
+ this._albedo = cloneObject(other._albedo);
351
+ this._albedoTexture = cloneObject(other._albedoTexture);
352
+ this._albedoScale = cloneObject(other._albedoScale);
353
+ this._albedoUV = other._albedoUV;
354
+ this._normalTexture = cloneObject(other._normalTexture);
355
+ this._normalScale = cloneObject(other._normalScale);
356
+ this._normalUV = other._normalUV;
357
+ this._metalness = other._metalness;
358
+ this._metalnessTexture = cloneObject(other._metalnessTexture);
359
+ this._metalnessChannel = other._metalnessChannel;
360
+ this._metalnessScale = cloneObject(other._metalnessScale);
361
+ this._metalnessUV = other._metalnessUV;
362
+ this._roughness = other._roughness;
363
+ this._roughnessTexture = cloneObject(other._roughnessTexture);
364
+ this._roughnessChannel = other._roughnessChannel;
365
+ this._roughnessScale = cloneObject(other._roughnessScale);
366
+ this._roughnessUV = other._roughnessUV;
367
+ this._fresnelTint = cloneObject(other._fresnelTint);
368
+ this._sheenIntensity = other._sheenIntensity;
369
+ this._sheenColor = cloneObject(other._sheenColor);
370
+ this._lightEmission = other._lightEmission;
371
+ this._lightEmissionTexture = cloneObject(other._lightEmissionTexture);
372
+ this._lightEmissionChannel = other._lightEmissionChannel;
373
+ this._lightEmissionScale = cloneObject(other._lightEmissionScale);
374
+ this._lightEmissionUV = other._lightEmissionUV;
375
+ this._ambientOcclussion = other._ambientOcclussion;
376
+ this._ambientOcclussionChannel = other._ambientOcclussionChannel;
377
+ this._ambientOcclussionUV = other._ambientOcclussionUV;
378
+ this._heightTexture = cloneObject(other._heightTexture);
379
+ this._heightChannel = other._heightChannel;
380
+ this._heightScale = cloneObject(other._heightScale);
381
+ this._heightUV = other._heightUV;
382
+ this._heightIntensity = other._heightIntensity;
383
+ this._castShadows = other._castShadows;
384
+ this._unlit = other._unlit;
385
+
386
+ this._dirty = true;
387
+ }
388
+
389
+ get type(): string { return this._type; }
390
+ set type(v: string) {
391
+ // Compatibility with v1.4
392
+ if (v === "PBRMaterial") {
393
+ v = "pbr";
394
+ }
395
+ this._type = v;
396
+ this._dirty = true;
397
+ }
398
+
399
+ get albedo(): Color { return this._albedo; }
400
+ set albedo(v: Color) {
401
+ this._albedo = v;
402
+ this._dirty = true;
403
+ }
404
+ get albedoTexture(): Texture | null { return this._albedoTexture; }
405
+ set albedoTexture(v: Texture | null) {
406
+ v && assertTexture(v, "albedoTexture");
407
+ if (this._albedoTexture instanceof Texture) {
408
+ this._albedoTexture.decReferences();
409
+ }
410
+ this._albedoTexture = v;
411
+ if (this._albedoTexture instanceof Texture) {
412
+ this._albedoTexture.incReferences();
413
+ }
414
+ this._dirty = true;
415
+ }
416
+
417
+ get albedoScale(): Vec { return this._albedoScale; }
418
+ set albedoScale(v: Vec) { assertScale(v, "albedoScale"); this._albedoScale = new Vec(v); this._dirty = true; }
419
+ get albedoUV(): number { return this._albedoUV; }
420
+ set albedoUV(v: number) { this._albedoUV = v; this._dirty = true; }
421
+ get alphaCutoff(): number { return this._alphaCutoff; }
422
+ set alphaCutoff(v: number) { this._alphaCutoff = v; this._dirty = true; }
423
+ get isTransparent(): boolean { return this._isTransparent; }
424
+ set isTransparent(v: boolean) { this._isTransparent = v; this._dirty = true; }
425
+
426
+ get normalTexture(): Texture | null { return this._normalTexture; }
427
+ set normalTexture(v: Texture | null) {
428
+ v && assertTexture(v, "normalTexture");
429
+ if (this._normalTexture instanceof Texture) {
430
+ this._normalTexture.decReferences();
431
+ }
432
+ this._normalTexture = v;
433
+ if (this._normalTexture instanceof Texture) {
434
+ this._normalTexture.incReferences();
435
+ }
436
+ this._dirty = true;
437
+ }
438
+
439
+ get normalChannel(): number { return this._normalChannel; }
440
+ set normalChannel(v: number) { this._normalChannel = v; this._dirty = true; }
441
+ get normalScale(): Vec { return this._normalScale; }
442
+ set normalScale(v: Vec) { assertScale(v, "normalScale"); this._normalScale = new Vec(v); this._dirty = true; }
443
+ get normalUV(): number { return this._normalUV; }
444
+ set normalUV(v: number) { this._normalUV = v; this._dirty = true; }
445
+
446
+ get metalness(): number { return this._metalness; }
447
+ set metalness(v: number) {
448
+ this._metalness = v;
449
+ this._dirty = true;
450
+ }
451
+
452
+ get metalnessTexture(): Texture | null { return this._metalnessTexture; }
453
+ set metalnessTexture(v: Texture | null) {
454
+ v && assertTexture(v, "metalness");
455
+ if (this._metalnessTexture instanceof Texture) {
456
+ this._metalnessTexture.decReferences();
457
+ }
458
+ this._metalnessTexture = v;
459
+ if (this._metalnessTexture instanceof Texture) {
460
+ this._metalnessTexture.incReferences();
461
+ }
462
+ this._dirty = true;
463
+ }
464
+
465
+ get metalnessChannel(): number { return this._metalnessChannel; }
466
+ set metalnessChannel(v: number) { this._metalnessChannel = v; this._dirty = true; }
467
+ get metalnessScale(): Vec { return this._metalnessScale; }
468
+ set metalnessScale(v: Vec) { assertScale(v, "metalnessScale"); this._metalnessScale = new Vec(v); this._dirty = true; }
469
+ get metalnessUV(): number { return this._metalnessUV; }
470
+ set metalnessUV(v: number) { this._metalnessUV = v; this._dirty = true; }
471
+
472
+ get roughness(): number { return this._roughness; }
473
+ set roughness(v: number) {
474
+ this._roughness = v;
475
+ this._dirty = true;
476
+ }
477
+
478
+ get roughnessTexture(): Texture | null { return this._roughnessTexture; }
479
+ set roughnessTexture (v: Texture | null) {
480
+ v && assertTexture(v, "roughness");
481
+ if (this._roughnessTexture instanceof Texture) {
482
+ this._roughnessTexture.decReferences();
483
+ }
484
+ this._roughnessTexture = v;
485
+ if (this._roughnessTexture instanceof Texture) {
486
+ this._roughnessTexture.incReferences();
487
+ }
488
+ this._dirty = true;
489
+ }
490
+
491
+ get roughnessChannel(): number { return this._roughnessChannel; }
492
+ set roughnessChannel(v: number) { this._roughnessChannel = v; this._dirty = true; }
493
+ get roughnessScale(): Vec { return this._roughnessScale; }
494
+ set roughnessScale(v: Vec) { assertScale(v, "roughnessScale"); this._roughnessScale = new Vec(v); this._dirty = true; }
495
+ get roughnessUV(): number { return this._roughnessUV; }
496
+ set roughnessUV(v: number) { this._roughnessUV = v; this._dirty = true; }
497
+
498
+ get fresnelTint(): Color { return this._fresnelTint; }
499
+ set fresnelTint(v: Color) { assertColor(v, "fresnelTint"); this._fresnelTint = v; this._dirty = true; }
500
+ get sheenIntensity(): number { return this._sheenIntensity; }
501
+ set sheenIntensity(v: number) { this._sheenIntensity = v; this._dirty = true; }
502
+ get sheenColor(): Color { return this._sheenColor; }
503
+ set sheenColor(v: Color) { assertColor(v, "sheenColor"); this._sheenColor = v; this._dirty = true; }
504
+
505
+ get lightEmission(): Color | number { return this._lightEmission; }
506
+ set lightEmission(v: Color | number) {
507
+ if (typeof v === "number") {
508
+ v = new Color([v, v, v, 1]);
509
+ }
510
+ assertColor(v, "lightEmission"); this._lightEmission = v; this._dirty = true;
511
+ }
512
+ get lightEmissionTexture(): Texture | null { return this._lightEmissionTexture; }
513
+ set lightEmissionTexture(v: Texture | null) {
514
+ v && assertTexture(v, 'lightEmissionTexture');
515
+ if (this._lightEmissionTexture instanceof Texture) {
516
+ this._lightEmissionTexture.decReferences();
517
+ }
518
+ this._lightEmissionTexture = v;
519
+ if (this._lightEmissionTexture instanceof Texture) {
520
+ this._lightEmissionTexture.incReferences();
521
+ }
522
+ this._dirty = true;
523
+ }
524
+
525
+ get lightEmissionChannel(): number { return this._lightEmissionChannel; }
526
+ set lightEmissionChannel(v: number) { this._lightEmissionChannel = v; this._dirty = true; }
527
+ get lightEmissionScale(): Vec { return this._lightEmissionScale; }
528
+ set lightEmissionScale(v: Vec) { assertScale(v, "lightEmissionScale"); this._lightEmissionScale = new Vec(v); this._dirty = true; }
529
+ get lightEmissionUV(): number { return this._lightEmissionUV; }
530
+ set lightEmissionUV(v: number) { this._lightEmissionUV = v; this._dirty = true; }
531
+
532
+ get ambientOcclussion(): Texture | null { return this._ambientOcclussion; }
533
+ set ambientOcclussion(v: Texture | null) {
534
+ v && assertTexture(v, "ambientOcclussion");
535
+ if (this._ambientOcclussion instanceof Texture) {
536
+ this._ambientOcclussion.decReferences();
537
+ }
538
+ this._ambientOcclussion = v;
539
+ if (this._ambientOcclussion instanceof Texture) {
540
+ this._ambientOcclussion.incReferences();
541
+ }
542
+ this._dirty = true;
543
+ }
544
+
545
+ get ambientOcclussionChannel(): number { return this._ambientOcclussionChannel; }
546
+ set ambientOcclussionChannel(v: number) { this._ambientOcclussionChannel = v; this._dirty = true; }
547
+ get ambientOcclussionUV(): number { return this._ambientOcclussionUV; }
548
+ set ambientOcclussionUV(v: number) { this._ambientOcclussionUV = v; this._dirty = true; }
549
+
550
+
551
+
552
+ get heightTexture(): Texture | null { return this._heightTexture; }
553
+ set heightTexture(v: Texture | null) { assertTexture(v, "heightTexture"); this._heightTexture = v; this._dirty = true; }
554
+ get heightChannel(): number { return this._heightChannel; }
555
+ set heightChannel(v: number) { this._heightChannel = v; this._dirty = true; }
556
+ get heightScale(): Vec { return this._heightScale; }
557
+ set heightScale(v: Vec) { assertScale(v, "heightScale"); this._heightScale = new Vec(v); this._dirty = true; }
558
+ get heightUV(): number { return this._heightUV; }
559
+ set heightUV(v: number) { this._heightUV = v; this._dirty = true; }
560
+ get heightIntensity(): number { return this._heightIntensity; }
561
+ set heightIntensity(v: number) { this._heightIntensity = v; this._dirty = true; }
562
+ get castShadows(): boolean { return this._castShadows; }
563
+ set castShadows(v: boolean) { this._castShadows = v; this._dirty = true; }
564
+ get unlit(): boolean { return this._unlit; }
565
+ set unlit(v: boolean) { this._unlit = v; this._dirty = true; }
566
+
567
+ async serialize(sceneData: any): Promise<void> {
568
+ for (const att in MaterialAttributeNames) {
569
+ const value = MaterialAttributeNames[att].loader.serialize(att, (this as any)[att]);
570
+ if (value) {
571
+ sceneData[att] = value;
572
+ }
573
+ }
574
+ }
575
+
576
+ async deserialize(sceneData: any, relativePath: string, canvas?: Canvas | null): Promise<void> {
577
+ const P: Promise<any>[] = [];
578
+
579
+ this.type = sceneData.type || MaterialType.PBR;
580
+ this.alphaCutoff = sceneData.alphaCutoff || 0.5;
581
+ this.isTransparent = sceneData.isTransparent || false;
582
+
583
+ for (const attName in MaterialAttributeNames) {
584
+ const loader = MaterialAttributeNames[attName]?.loader;
585
+ if (loader) {
586
+ const value = loader.deserialize(attName, sceneData[attName], relativePath, this.canvas);
587
+ if (value instanceof Texture) {
588
+ P.push(value.loadImageData());
589
+ }
590
+
591
+ if (value !== null && value !== undefined) {
592
+ (this as any)[attName] = value;
593
+ }
594
+ }
595
+ }
596
+ await Promise.all(P);
597
+ }
598
+
599
+ destroy(): void {
600
+ const decReferences = (attrib: string) => {
601
+ if ((this as any)[attrib] instanceof Texture) {
602
+ (this as any)[attrib].decReferences();
603
+ }
604
+ }
605
+
606
+ decReferences("albedoTexture");
607
+ decReferences("normalTexture");
608
+ decReferences("metalnessTexture");
609
+ decReferences("roughnessTexture");
610
+ decReferences("lightEmissionTexture");
611
+ decReferences("ambientOcclussion");
612
+ decReferences("height");
613
+
614
+ this._canvas = null;
615
+
616
+ if (this.renderer) {
617
+ this.renderer.destroy();
618
+ }
619
+ }
620
+ }