@needle-tools/engine 2.35.5-pre → 2.36.0-pre
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 +19 -0
- package/dist/needle-engine.d.ts +160 -110
- package/dist/needle-engine.js +370 -365
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +61 -56
- package/dist/needle-engine.min.js.map +4 -4
- package/lib/engine/debug/debug_overlay.js +12 -1
- package/lib/engine/debug/debug_overlay.js.map +1 -1
- package/lib/engine/engine_element_loading.js +1 -1
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_gameobject.d.ts +1 -0
- package/lib/engine/engine_gameobject.js +13 -1
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_gltf_builtin_components.js +4 -0
- package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
- package/lib/engine/engine_mainloop_utils.d.ts +1 -1
- package/lib/engine/engine_mainloop_utils.js +7 -3
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_physics.d.ts +29 -28
- package/lib/engine/engine_physics.js +85 -86
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_serialization_core.js +14 -6
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_setup.js +1 -1
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_time.d.ts +1 -0
- package/lib/engine/engine_time.js +1 -0
- package/lib/engine/engine_time.js.map +1 -1
- package/lib/engine/engine_types.d.ts +1 -0
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_typestore.d.ts +1 -0
- package/lib/engine/engine_typestore.js +1 -0
- package/lib/engine/engine_typestore.js.map +1 -1
- package/lib/engine/engine_utils.js +1 -1
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_animator_controller_model.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js +5 -0
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
- package/lib/engine-components/Animation.d.ts +5 -1
- package/lib/engine-components/Animation.js +21 -0
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/AnimatorController.d.ts +1 -0
- package/lib/engine-components/AnimatorController.js +14 -7
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/BoxHelperComponent.d.ts +2 -2
- package/lib/engine-components/BoxHelperComponent.js +27 -9
- package/lib/engine-components/BoxHelperComponent.js.map +1 -1
- package/lib/engine-components/Component.d.ts +2 -1
- package/lib/engine-components/Component.js +11 -5
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/GroundProjection.d.ts +2 -0
- package/lib/engine-components/GroundProjection.js +18 -6
- package/lib/engine-components/GroundProjection.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.d.ts +22 -0
- package/lib/engine-components/ReflectionProbe.js +134 -0
- package/lib/engine-components/ReflectionProbe.js.map +1 -0
- package/lib/engine-components/Renderer.d.ts +13 -2
- package/lib/engine-components/Renderer.js +96 -45
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/WebARSessionRoot.d.ts +7 -7
- package/lib/engine-components/WebARSessionRoot.js +7 -7
- package/lib/engine-components/WebARSessionRoot.js.map +1 -1
- package/lib/engine-components/WebXR.d.ts +9 -8
- package/lib/engine-components/WebXR.js +40 -24
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRAvatar.d.ts +4 -5
- package/lib/engine-components/WebXRAvatar.js +9 -8
- package/lib/engine-components/WebXRAvatar.js.map +1 -1
- package/lib/engine-components/WebXRController.d.ts +21 -21
- package/lib/engine-components/WebXRController.js +79 -63
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/WebXRGrabRendering.d.ts +3 -3
- package/lib/engine-components/WebXRGrabRendering.js +2 -2
- package/lib/engine-components/WebXRGrabRendering.js.map +1 -1
- package/lib/engine-components/WebXRSync.d.ts +8 -8
- package/lib/engine-components/WebXRSync.js +15 -15
- package/lib/engine-components/WebXRSync.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +1 -0
- package/lib/engine-components/codegen/components.js +1 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/ui/EventSystem.d.ts +1 -0
- package/lib/engine-components/ui/EventSystem.js +21 -1
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/package.json +1 -1
- package/src/engine/codegen/register_types.js +293 -0
- package/src/engine/debug/debug_overlay.ts +9 -2
- package/src/engine/engine_element_loading.ts +1 -1
- package/src/engine/engine_gameobject.ts +17 -4
- package/src/engine/engine_gltf_builtin_components.ts +5 -1
- package/src/engine/engine_mainloop_utils.ts +7 -3
- package/src/engine/engine_physics.ts +130 -130
- package/src/engine/engine_serialization_core.ts +14 -7
- package/src/engine/engine_setup.ts +1 -1
- package/src/engine/engine_time.ts +2 -0
- package/src/engine/engine_types.ts +1 -0
- package/src/engine/engine_typestore.ts +2 -0
- package/src/engine/engine_utils.ts +3 -2
- package/src/engine/extensions/EXT_texture_exr.js +1 -1
- package/src/engine/extensions/NEEDLE_animator_controller_model.ts +2 -1
- package/src/engine/extensions/NEEDLE_techniques_webgl.ts +7 -0
- package/src/engine-components/Animation.ts +16 -1
- package/src/engine-components/AnimatorController.ts +19 -9
- package/src/engine-components/BoxHelperComponent.ts +29 -9
- package/src/engine-components/Component.ts +11 -5
- package/src/engine-components/GroundProjection.ts +22 -7
- package/src/engine-components/ReflectionProbe.ts +141 -0
- package/src/engine-components/Renderer.ts +796 -737
- package/src/engine-components/WebARSessionRoot.ts +16 -16
- package/src/engine-components/WebXR.ts +53 -48
- package/src/engine-components/WebXRAvatar.ts +16 -16
- package/src/engine-components/WebXRController.ts +129 -107
- package/src/engine-components/WebXRGrabRendering.ts +6 -6
- package/src/engine-components/WebXRSync.ts +20 -20
- package/src/engine-components/codegen/components.ts +1 -0
- package/src/engine-components/ui/EventSystem.ts +26 -3
|
@@ -1,738 +1,797 @@
|
|
|
1
|
-
import { Behaviour, GameObject } from "./Component";
|
|
2
|
-
import * as THREE from "three";
|
|
3
|
-
// import { RendererCustomShader } from "./RendererCustomShader";
|
|
4
|
-
import { RendererLightmap } from "./RendererLightmap";
|
|
5
|
-
import { Context } from "../engine/engine_setup";
|
|
6
|
-
import { getParam } from "../engine/engine_utils";
|
|
7
|
-
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
8
|
-
import { Material, Mesh, Texture, Vector4 } from "three";
|
|
9
|
-
import { NEEDLE_render_objects } from "../engine/extensions/NEEDLE_render_objects";
|
|
10
|
-
import { NEEDLE_deferred_texture } from "../engine/extensions/NEEDLE_deferred_texture";
|
|
11
|
-
import { NEED_UPDATE_INSTANCE_KEY } from "../engine/engine_instancing";
|
|
12
|
-
import { IRenderer, ISharedMaterials } from "../engine/engine_types";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
@serializeable()
|
|
122
|
-
|
|
123
|
-
@serializeable()
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
this.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if (
|
|
208
|
-
for (const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
this.gameObject.
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
this.
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
//
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
if (
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
if (this.
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
if (
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
this.
|
|
500
|
-
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
if (
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
if (
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
this.
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
//
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
this.
|
|
709
|
-
this.inst.
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
1
|
+
import { Behaviour, GameObject } from "./Component";
|
|
2
|
+
import * as THREE from "three";
|
|
3
|
+
// import { RendererCustomShader } from "./RendererCustomShader";
|
|
4
|
+
import { RendererLightmap } from "./RendererLightmap";
|
|
5
|
+
import { Context } from "../engine/engine_setup";
|
|
6
|
+
import { getParam } from "../engine/engine_utils";
|
|
7
|
+
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
8
|
+
import { AxesHelper, Material, Mesh, Object3D, Texture, Vector4 } from "three";
|
|
9
|
+
import { NEEDLE_render_objects } from "../engine/extensions/NEEDLE_render_objects";
|
|
10
|
+
import { NEEDLE_deferred_texture } from "../engine/extensions/NEEDLE_deferred_texture";
|
|
11
|
+
import { NEED_UPDATE_INSTANCE_KEY } from "../engine/engine_instancing";
|
|
12
|
+
import { IRenderer, ISharedMaterials } from "../engine/engine_types";
|
|
13
|
+
import { debug, ReflectionProbe } from "./ReflectionProbe";
|
|
14
|
+
|
|
15
|
+
// for staying compatible with old code
|
|
16
|
+
export { InstancingUtil } from "../engine/engine_instancing";
|
|
17
|
+
|
|
18
|
+
const suppressInstancing = getParam("noInstancing");
|
|
19
|
+
const debugLightmap = getParam("debuglightmaps") ? true : false;
|
|
20
|
+
const debugInstancing = getParam("debuginstancing");
|
|
21
|
+
const debugProgressiveLoading = getParam("debugprogressive");
|
|
22
|
+
const suppressProgressiveLoading = getParam("noprogressive");
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export enum ReflectionProbeUsage {
|
|
26
|
+
Off = 0,
|
|
27
|
+
BlendProbes = 1,
|
|
28
|
+
BlendProbesAndSkybox = 2,
|
|
29
|
+
Simple = 3,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
export class FieldWithDefault {
|
|
34
|
+
public path: string | null = null;
|
|
35
|
+
public asset: object | null = null;
|
|
36
|
+
public default: any;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export enum RenderState {
|
|
40
|
+
Both = 0,
|
|
41
|
+
Back = 1,
|
|
42
|
+
Front = 2,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
// support sharedMaterials[index] assigning materials directly to the objects
|
|
47
|
+
class SharedMaterialArray implements ISharedMaterials {
|
|
48
|
+
|
|
49
|
+
[num: number]: THREE.Material;
|
|
50
|
+
|
|
51
|
+
private _renderer: Renderer;
|
|
52
|
+
private _targets: THREE.Object3D[] = [];
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
is(renderer: Renderer) {
|
|
56
|
+
return this._renderer === renderer;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
constructor(renderer: Renderer) {
|
|
60
|
+
this._renderer = renderer;
|
|
61
|
+
const setMaterial = this.setMaterial.bind(this);
|
|
62
|
+
const getMaterial = this.getMaterial.bind(this);
|
|
63
|
+
const go = renderer.gameObject;
|
|
64
|
+
this._targets = [];
|
|
65
|
+
if (go) {
|
|
66
|
+
switch (go.type) {
|
|
67
|
+
case "Group":
|
|
68
|
+
this._targets = [...go.children];
|
|
69
|
+
break;
|
|
70
|
+
case "Mesh":
|
|
71
|
+
this._targets.push(go);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// this lets us override the javascript indexer, only works in ES6 tho
|
|
77
|
+
// but like that we can use sharedMaterials[index] and it will be assigned to the object directly
|
|
78
|
+
return new Proxy(this, {
|
|
79
|
+
get(target, key) {
|
|
80
|
+
if (typeof key === "string") {
|
|
81
|
+
const index = parseInt(key);
|
|
82
|
+
if (!isNaN(index)) {
|
|
83
|
+
return getMaterial(index);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return target[key];
|
|
87
|
+
},
|
|
88
|
+
set(target, key, value) {
|
|
89
|
+
if (typeof key === "string")
|
|
90
|
+
setMaterial(value, Number.parseInt(key));
|
|
91
|
+
// console.log(target, key, value);
|
|
92
|
+
return Reflect.set(target, key, value);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
get length(): number {
|
|
98
|
+
return this._targets.length;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private setMaterial(mat: Material, index: number) {
|
|
102
|
+
if (index < 0 || index >= this._targets.length) return;
|
|
103
|
+
const target = this._targets[index];
|
|
104
|
+
if (!target || target["material"] === undefined) return;
|
|
105
|
+
target["material"] = mat;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private getMaterial(index: number) {
|
|
109
|
+
if (index < 0) return null;
|
|
110
|
+
const obj = this._targets;
|
|
111
|
+
if (index >= obj.length) return null;
|
|
112
|
+
const target = obj[index];
|
|
113
|
+
if (!target) return null;
|
|
114
|
+
return target["material"];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export class Renderer extends Behaviour implements IRenderer {
|
|
120
|
+
|
|
121
|
+
@serializeable()
|
|
122
|
+
receiveShadows: boolean = false;
|
|
123
|
+
@serializeable()
|
|
124
|
+
shadowCastingMode: ShadowCastingMode = ShadowCastingMode.Off;
|
|
125
|
+
@serializeable()
|
|
126
|
+
lightmapIndex: number = -1;
|
|
127
|
+
@serializeable(Vector4)
|
|
128
|
+
lightmapScaleOffset: THREE.Vector4 = new THREE.Vector4(1, 1, 0, 0);
|
|
129
|
+
@serializeable()
|
|
130
|
+
enableInstancing: boolean[] | undefined = undefined;
|
|
131
|
+
@serializeable()
|
|
132
|
+
renderOrder: number[] | undefined = undefined;
|
|
133
|
+
@serializeable()
|
|
134
|
+
allowOcclusionWhenDynamic: boolean = true;
|
|
135
|
+
|
|
136
|
+
@serializeable(Object3D)
|
|
137
|
+
probeAnchor?: Object3D;
|
|
138
|
+
@serializeable()
|
|
139
|
+
reflectionProbeUsage: ReflectionProbeUsage = ReflectionProbeUsage.Off;
|
|
140
|
+
|
|
141
|
+
// custom shader
|
|
142
|
+
// get materialProperties(): Array<MaterialProperties> | undefined {
|
|
143
|
+
// return this._materialProperties;
|
|
144
|
+
// }
|
|
145
|
+
// set materialProperties(value: Array<MaterialProperties> | undefined) {
|
|
146
|
+
// this._materialProperties = value;
|
|
147
|
+
// }
|
|
148
|
+
|
|
149
|
+
// private customShaderHandler: RendererCustomShader | undefined = undefined;
|
|
150
|
+
|
|
151
|
+
// private _materialProperties: Array<MaterialProperties> | undefined = undefined;
|
|
152
|
+
private _lightmaps?: RendererLightmap[];
|
|
153
|
+
|
|
154
|
+
get sharedMesh(): Mesh | undefined {
|
|
155
|
+
if (this.gameObject.type === "Mesh") {
|
|
156
|
+
return this.gameObject as unknown as Mesh
|
|
157
|
+
}
|
|
158
|
+
else if (this.gameObject.type === "Group") {
|
|
159
|
+
return this.gameObject.children[0] as unknown as Mesh;
|
|
160
|
+
}
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
get sharedMaterial(): THREE.Material {
|
|
165
|
+
return this.sharedMaterials[0];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
set sharedMaterial(mat: THREE.Material) {
|
|
169
|
+
this.sharedMaterials[0] = mat;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**@deprecated please use sharedMaterial */
|
|
173
|
+
get material(): THREE.Material {
|
|
174
|
+
return this.sharedMaterials[0];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**@deprecated please use sharedMaterial */
|
|
178
|
+
set material(mat: THREE.Material) {
|
|
179
|
+
this.sharedMaterials[0] = mat;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private _sharedMaterials!: SharedMaterialArray;
|
|
183
|
+
|
|
184
|
+
get sharedMaterials(): SharedMaterialArray {
|
|
185
|
+
if (!this._sharedMaterials || !this._sharedMaterials.is(this))
|
|
186
|
+
this._sharedMaterials = new SharedMaterialArray(this);
|
|
187
|
+
return this._sharedMaterials!;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public static get shouldSuppressInstancing() {
|
|
191
|
+
return suppressInstancing;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
private _lightmapTextureOverride: Texture | null | undefined = undefined;
|
|
195
|
+
public get lightmap(): Texture | null {
|
|
196
|
+
if (this._lightmaps?.length) {
|
|
197
|
+
return this._lightmaps[0].lightmap;
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
public set lightmap(tex: Texture | null | undefined) {
|
|
202
|
+
this._lightmapTextureOverride = tex;
|
|
203
|
+
// set undefined to return to default
|
|
204
|
+
if (tex === undefined) {
|
|
205
|
+
tex = this.context.lightmaps.tryGetLightmap(this.sourceId, this.lightmapIndex);
|
|
206
|
+
}
|
|
207
|
+
if (this._lightmaps?.length) {
|
|
208
|
+
for (const lm of this._lightmaps) {
|
|
209
|
+
lm.lightmap = tex;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
get hasLightmap(): boolean {
|
|
214
|
+
const lm = this.lightmap;
|
|
215
|
+
return lm !== null && lm !== undefined;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
awake() {
|
|
219
|
+
this.clearInstancingState();
|
|
220
|
+
|
|
221
|
+
if(this.probeAnchor && debug) this.probeAnchor.add(new AxesHelper(.2));
|
|
222
|
+
|
|
223
|
+
this._reflectionProbe = null;
|
|
224
|
+
|
|
225
|
+
const type = this.gameObject.type;
|
|
226
|
+
if (type === "Group") {
|
|
227
|
+
for (const child of this.gameObject.children) {
|
|
228
|
+
this.context.addBeforeRenderListener(child, this.onBeforeRenderThree.bind(this));
|
|
229
|
+
child.layers.mask = this.gameObject.layers.mask;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (this.renderOrder !== undefined) {
|
|
233
|
+
// Objects can have nested renderers (e.g. contain 2 meshes and then again another group)
|
|
234
|
+
// or perhaps just regular child objects that have their own renderer component (?)
|
|
235
|
+
let index = 0;
|
|
236
|
+
for (let i = 0; i < this.gameObject.children.length; i++) {
|
|
237
|
+
const ch = this.gameObject.children[i];
|
|
238
|
+
// ignore nested groups or objects that have their own renderer (aka their own render order settings)
|
|
239
|
+
if (ch.type !== "Mesh" || GameObject.getComponent(ch, Renderer)) continue;
|
|
240
|
+
if (this.renderOrder.length <= index) {
|
|
241
|
+
console.error("Incorrect element count", this);
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
ch.renderOrder = this.renderOrder[index];
|
|
245
|
+
index += 1;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// TODO: custom shader with sub materials
|
|
250
|
+
else if (type === "Mesh" || type === "SkinnedMesh") {
|
|
251
|
+
|
|
252
|
+
this.context.addBeforeRenderListener(this.gameObject, this.onBeforeRenderThree.bind(this));
|
|
253
|
+
|
|
254
|
+
if (this.renderOrder !== undefined && this.renderOrder.length > 0)
|
|
255
|
+
this.gameObject.renderOrder = this.renderOrder[0];
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (this.lightmapIndex >= 0) {
|
|
259
|
+
// use the override lightmap if its not undefined
|
|
260
|
+
const tex = this._lightmapTextureOverride !== undefined
|
|
261
|
+
? this._lightmapTextureOverride
|
|
262
|
+
: this.context.lightmaps.tryGetLightmap(this.sourceId, this.lightmapIndex);
|
|
263
|
+
if (tex) {
|
|
264
|
+
// tex.encoding = THREE.LinearEncoding;
|
|
265
|
+
this._lightmaps = [];
|
|
266
|
+
|
|
267
|
+
if (type === "Mesh") {
|
|
268
|
+
if (!this.gameObject["material"]?.isMeshBasicMaterial === true) {
|
|
269
|
+
const rm = new RendererLightmap(this.gameObject, this.context);// GameObject.addNewComponent(this.gameObject, RendererLightmap);
|
|
270
|
+
this._lightmaps.push(rm);
|
|
271
|
+
rm.init(this.lightmapIndex, this.lightmapScaleOffset, tex, debugLightmap);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// for multi materials we need to loop through children
|
|
275
|
+
// and then we add a lightmap renderer component to each of them
|
|
276
|
+
else if (type === "Group") {
|
|
277
|
+
for (const child of this.gameObject.children) {
|
|
278
|
+
if (!child["material"]?.isMeshBasicMaterial) {
|
|
279
|
+
const rm = new RendererLightmap(child as GameObject, this.context);
|
|
280
|
+
this._lightmaps.push(rm);
|
|
281
|
+
rm.init(this.lightmapIndex, this.lightmapScaleOffset, tex, debugLightmap);
|
|
282
|
+
// onBeforeRender is not called when the renderer is on a group
|
|
283
|
+
// this is an issue we probably also need to handle for custom shaders
|
|
284
|
+
// and need a better solution, but for now this fixes lightmaps for multimaterial objects
|
|
285
|
+
rm.bindOnBeforeRender();
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
private _isInstancingEnabled: boolean = false;
|
|
295
|
+
private handles: InstanceHandle[] | null | undefined = undefined;
|
|
296
|
+
private prevLayers: number[] | null | undefined = undefined;
|
|
297
|
+
|
|
298
|
+
private clearInstancingState() {
|
|
299
|
+
this._isInstancingEnabled = false;
|
|
300
|
+
this.handles = undefined;
|
|
301
|
+
this.prevLayers = undefined;
|
|
302
|
+
}
|
|
303
|
+
setInstancingEnabled(enabled: boolean): boolean {
|
|
304
|
+
if (this._isInstancingEnabled === enabled) return enabled && (this.handles === undefined || this.handles != null && this.handles.length > 0);
|
|
305
|
+
this._isInstancingEnabled = enabled;
|
|
306
|
+
if (enabled) {
|
|
307
|
+
// if handles is undefined we
|
|
308
|
+
if (this.handles === undefined) {
|
|
309
|
+
this.handles = instancing.setup(this.gameObject, this.context, null, { rend: this, foundMeshes: 0 });
|
|
310
|
+
if (this.handles) {
|
|
311
|
+
// const disableSelf = this.gameObject.type === "Mesh" || this.gameObject.children?.length === this.handles.length;
|
|
312
|
+
// this.gameObject.visible = !disableSelf;
|
|
313
|
+
// this.gameObject.type = "Object3D";
|
|
314
|
+
// this.gameObject.material = null;
|
|
315
|
+
// console.log("Using instancing", this.gameObject.visible);
|
|
316
|
+
// this.gameObject.onBeforeRender = () => console.log("SHOULD NOT BE CALLED");
|
|
317
|
+
GameObject.markAsInstancedRendered(this.gameObject, true);
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
else if (this.handles !== null) {
|
|
322
|
+
for (const handler of this.handles) {
|
|
323
|
+
handler.updateInstanceMatrix(true);
|
|
324
|
+
handler.add();
|
|
325
|
+
}
|
|
326
|
+
// this.gameObject.type = "Object3D";
|
|
327
|
+
// this.gameObject.visible = false;
|
|
328
|
+
GameObject.markAsInstancedRendered(this.gameObject, true);
|
|
329
|
+
return true;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
if (this.handles) {
|
|
334
|
+
for (const handler of this.handles) {
|
|
335
|
+
handler.remove();
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
// this.gameObject.visible = true;
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
start() {
|
|
346
|
+
if (this.enableInstancing && !suppressInstancing) {
|
|
347
|
+
this.setInstancingEnabled(true);
|
|
348
|
+
}
|
|
349
|
+
this.gameObject.frustumCulled = this.allowOcclusionWhenDynamic;
|
|
350
|
+
if (this.gameObject.type === "Group") {
|
|
351
|
+
for (let i = 0; i < this.gameObject.children.length; i++) {
|
|
352
|
+
const ch = this.gameObject.children[i];
|
|
353
|
+
ch.frustumCulled = this.allowOcclusionWhenDynamic;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
onEnable() {
|
|
359
|
+
// this.customShaderHandler?.onEnable();
|
|
360
|
+
// if (this.didEnable && this.enabled && (!this.handles || this.handles?.length <= 0))
|
|
361
|
+
// this.gameObject.visible = true;
|
|
362
|
+
if (this._isInstancingEnabled) {
|
|
363
|
+
this.setInstancingEnabled(true);
|
|
364
|
+
}
|
|
365
|
+
else if (this.enabled) {
|
|
366
|
+
this.gameObject.visible = true;
|
|
367
|
+
this.applyStencil();
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
this.updateReflectionProbe();
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
onDisable() {
|
|
374
|
+
// this.customShaderHandler?.onDisable();
|
|
375
|
+
// if (!this.enabled) {
|
|
376
|
+
// this.gameObject.visible = false;
|
|
377
|
+
// }
|
|
378
|
+
if (this.handles && this.handles.length > 0) {
|
|
379
|
+
this.setInstancingEnabled(false);
|
|
380
|
+
// this.gameObject.visible = false;
|
|
381
|
+
}
|
|
382
|
+
else if (!this.enabled) {
|
|
383
|
+
this.gameObject.visible = false;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
onDestroy(): void {
|
|
388
|
+
this.handles = null;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
applyStencil() {
|
|
392
|
+
NEEDLE_render_objects.applyStencil(this);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
static envmap: THREE.Texture | null = null;
|
|
396
|
+
|
|
397
|
+
onBeforeRender() {
|
|
398
|
+
if (!this.gameObject) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
Renderer.envmap = this.scene.environment;
|
|
403
|
+
|
|
404
|
+
const needsUpdate: boolean = this.gameObject[NEED_UPDATE_INSTANCE_KEY] === true || this.gameObject.matrixWorldNeedsUpdate;
|
|
405
|
+
|
|
406
|
+
if (this.gameObject.type === "Group" && this.gameObject.children?.length > 0) {
|
|
407
|
+
for (const ch of this.gameObject.children) {
|
|
408
|
+
this.applySettings(ch);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
this.applySettings(this.gameObject);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (needsUpdate) {
|
|
416
|
+
delete this.gameObject[NEED_UPDATE_INSTANCE_KEY];
|
|
417
|
+
if (this.handles) {
|
|
418
|
+
const remove = false;// Math.random() < .01;
|
|
419
|
+
for (let i = this.handles.length - 1; i >= 0; i--) {
|
|
420
|
+
const h = this.handles[i];
|
|
421
|
+
if (remove) {
|
|
422
|
+
h.remove();
|
|
423
|
+
this.handles.splice(i, 1);
|
|
424
|
+
}
|
|
425
|
+
else
|
|
426
|
+
h.updateInstanceMatrix();
|
|
427
|
+
}
|
|
428
|
+
this.gameObject.matrixWorldNeedsUpdate = false;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (this.handles && this.handles.length <= 0) {
|
|
433
|
+
GameObject.markAsInstancedRendered(this.gameObject, false);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (this._isInstancingEnabled && this.handles) {
|
|
437
|
+
for (let i = 0; i < this.handles.length; i++) {
|
|
438
|
+
const handle = this.handles[i];
|
|
439
|
+
if (!this.prevLayers) this.prevLayers = [];
|
|
440
|
+
const layer = handle.object.layers.mask;
|
|
441
|
+
if (i >= this.prevLayers.length) this.prevLayers.push(layer);
|
|
442
|
+
else this.prevLayers[i] = layer;
|
|
443
|
+
handle.object.layers.disableAll();
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (this.reflectionProbeUsage !== ReflectionProbeUsage.Off && this._reflectionProbe) {
|
|
448
|
+
this._reflectionProbe.onSet(this);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
onBeforeRenderThree(_renderer, _scene, _camera, _geometry, material, _group) {
|
|
454
|
+
|
|
455
|
+
// progressive load before rendering so we only load textures for visible materials
|
|
456
|
+
if (!suppressProgressiveLoading && material._didRequestTextureLOD === undefined) {
|
|
457
|
+
material._didRequestTextureLOD = 0;
|
|
458
|
+
if (debugProgressiveLoading) {
|
|
459
|
+
console.log("Load material LOD (with delay)", material.name);
|
|
460
|
+
setTimeout(() => {
|
|
461
|
+
NEEDLE_deferred_texture.assignTextureLOD(this.context, this.sourceId, material);
|
|
462
|
+
}, 2000);
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
NEEDLE_deferred_texture.assignTextureLOD(this.context, this.sourceId, material);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (material.envMapIntensity !== undefined) {
|
|
470
|
+
const factor = this.hasLightmap ? Math.PI : 1;
|
|
471
|
+
material.envMapIntensity = Math.max(0, this.context.rendererData.environmentIntensity / factor);
|
|
472
|
+
}
|
|
473
|
+
// if (this._reflectionProbe?.texture) {
|
|
474
|
+
// material.envMap = this._reflectionProbe.texture;
|
|
475
|
+
// // this.context.renderer.prop
|
|
476
|
+
// // console.log(material.name);
|
|
477
|
+
// // this.context.renderer.properties.get(material);
|
|
478
|
+
// // this.context.renderer.properties.update(material, "environment", this._reflectionProbe.texture);
|
|
479
|
+
// }
|
|
480
|
+
|
|
481
|
+
// _scene.environment = null;
|
|
482
|
+
// else _scene.environment = Renderer.envmap;
|
|
483
|
+
// if (!material.envmap)
|
|
484
|
+
// material.envMap = Renderer.envmap;
|
|
485
|
+
// material.needsUpdate = true;
|
|
486
|
+
|
|
487
|
+
// if (!camera) {
|
|
488
|
+
// let isXRCamera = false;
|
|
489
|
+
// if (this.context.isInXR) {
|
|
490
|
+
// // @ts-ignore
|
|
491
|
+
// const arr = this.context.renderer.xr.getCamera() as ArrayCamera;
|
|
492
|
+
// if (arr.cameras?.length > 0) {
|
|
493
|
+
// camera = arr;
|
|
494
|
+
// isXRCamera = true;
|
|
495
|
+
// }
|
|
496
|
+
// }
|
|
497
|
+
// }
|
|
498
|
+
|
|
499
|
+
// if (this.customShaderHandler) {
|
|
500
|
+
// this.customShaderHandler.onBeforeRender(renderer, scene, camera, geometry, material, group);
|
|
501
|
+
// }
|
|
502
|
+
// else if (this.rawShaderHandler) {
|
|
503
|
+
// for (const h of this.rawShaderHandler) {
|
|
504
|
+
// h.onBeforeRender(this.gameObject, camera);
|
|
505
|
+
// }
|
|
506
|
+
// }
|
|
507
|
+
|
|
508
|
+
if (this._lightmaps) {
|
|
509
|
+
for (const lm of this._lightmaps) {
|
|
510
|
+
lm.onBeforeRenderThree(material);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
onAfterRender() {
|
|
516
|
+
if (this._isInstancingEnabled && this.handles && this.prevLayers && this.prevLayers.length >= this.handles.length) {
|
|
517
|
+
for (let i = 0; i < this.handles.length; i++) {
|
|
518
|
+
const handle = this.handles[i];
|
|
519
|
+
handle.object.layers.mask = this.prevLayers[i];
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
if (this.reflectionProbeUsage !== ReflectionProbeUsage.Off && this._reflectionProbe) {
|
|
524
|
+
this._reflectionProbe.onUnset(this)
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
private applySettings(go: THREE.Object3D) {
|
|
529
|
+
go.receiveShadow = this.receiveShadows;
|
|
530
|
+
if (this.shadowCastingMode == ShadowCastingMode.On) {
|
|
531
|
+
go.castShadow = true;
|
|
532
|
+
}
|
|
533
|
+
else go.castShadow = false;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
private _reflectionProbe: ReflectionProbe | null = null;
|
|
537
|
+
private updateReflectionProbe() {
|
|
538
|
+
// handle reflection probe
|
|
539
|
+
this._reflectionProbe = null;
|
|
540
|
+
if (this.reflectionProbeUsage !== ReflectionProbeUsage.Off) {
|
|
541
|
+
// if(this.gameObject.name.includes("Tank_Case_Jewlery") === false) return;
|
|
542
|
+
const obj = this.probeAnchor || this.gameObject;
|
|
543
|
+
const isAnchor = this.probeAnchor ? true : false;
|
|
544
|
+
this._reflectionProbe = ReflectionProbe.get(obj, this.context, isAnchor);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
export class MeshRenderer extends Renderer {
|
|
551
|
+
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
export class SkinnedMeshRenderer extends MeshRenderer {
|
|
555
|
+
awake() {
|
|
556
|
+
super.awake();
|
|
557
|
+
// disable skinned mesh occlusion because of https://github.com/mrdoob/three.js/issues/14499
|
|
558
|
+
this.allowOcclusionWhenDynamic = false;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
export enum ShadowCastingMode {
|
|
563
|
+
/// <summary>
|
|
564
|
+
/// <para>No shadows are cast from this object.</para>
|
|
565
|
+
/// </summary>
|
|
566
|
+
Off,
|
|
567
|
+
/// <summary>
|
|
568
|
+
/// <para>Shadows are cast from this object.</para>
|
|
569
|
+
/// </summary>
|
|
570
|
+
On,
|
|
571
|
+
/// <summary>
|
|
572
|
+
/// <para>Shadows are cast from this object, treating it as two-sided.</para>
|
|
573
|
+
/// </summary>
|
|
574
|
+
TwoSided,
|
|
575
|
+
/// <summary>
|
|
576
|
+
/// <para>Object casts shadows, but is otherwise invisible in the Scene.</para>
|
|
577
|
+
/// </summary>
|
|
578
|
+
ShadowsOnly,
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
declare class InstancingSetupArgs { rend: Renderer; foundMeshes: number };
|
|
584
|
+
|
|
585
|
+
class InstancingHandler {
|
|
586
|
+
|
|
587
|
+
public objs: InstancedMeshRenderer[] = [];
|
|
588
|
+
|
|
589
|
+
public setup(obj: THREE.Object3D, context: Context, handlesArray: InstanceHandle[] | null, args: InstancingSetupArgs, level: number = 0)
|
|
590
|
+
: InstanceHandle[] | null {
|
|
591
|
+
|
|
592
|
+
const res = this.tryCreateOrAddInstance(obj, context, args);
|
|
593
|
+
if (res) {
|
|
594
|
+
if (handlesArray === null) handlesArray = [];
|
|
595
|
+
handlesArray.push(res);
|
|
596
|
+
return handlesArray;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
if (level <= 0 && obj.type !== "Mesh") {
|
|
600
|
+
const nextLevel = level + 1;
|
|
601
|
+
for (const ch of obj.children) {
|
|
602
|
+
handlesArray = this.setup(ch, context, handlesArray, args, nextLevel);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
return handlesArray;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
private tryCreateOrAddInstance(obj: THREE.Object3D, context: Context, args: InstancingSetupArgs): InstanceHandle | null {
|
|
609
|
+
if (obj.type === "Mesh") {
|
|
610
|
+
const index = args.foundMeshes;
|
|
611
|
+
args.foundMeshes += 1;
|
|
612
|
+
if (!args.rend.enableInstancing) return null;
|
|
613
|
+
if (index >= args.rend.enableInstancing.length) {
|
|
614
|
+
// console.error("Something is wrong with instance setup", obj, args.rend.enableInstancing, index);
|
|
615
|
+
return null;
|
|
616
|
+
}
|
|
617
|
+
if (!args.rend.enableInstancing[index]) {
|
|
618
|
+
// instancing is disabled
|
|
619
|
+
// console.log("Instancing is disabled", obj);
|
|
620
|
+
return null;
|
|
621
|
+
}
|
|
622
|
+
// instancing is enabled:
|
|
623
|
+
const mesh = obj as THREE.Mesh;
|
|
624
|
+
const geo = mesh.geometry as THREE.BufferGeometry;
|
|
625
|
+
const mat = mesh.material as THREE.Material;
|
|
626
|
+
|
|
627
|
+
for (const i of this.objs) {
|
|
628
|
+
if (i.isFull()) continue;
|
|
629
|
+
if (i.geo === geo && i.material === mat) {
|
|
630
|
+
return i.addInstance(mesh);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
// console.log("Add new instance mesh renderer", obj);
|
|
634
|
+
const i = new InstancedMeshRenderer(obj.name, geo, mat, 200, context);
|
|
635
|
+
this.objs.push(i);
|
|
636
|
+
return i.addInstance(mesh);
|
|
637
|
+
}
|
|
638
|
+
return null;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
const instancing: InstancingHandler = new InstancingHandler();
|
|
642
|
+
|
|
643
|
+
class InstanceHandle {
|
|
644
|
+
|
|
645
|
+
get name(): string {
|
|
646
|
+
return this.object.name;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
instanceIndex: number = -1;
|
|
650
|
+
object: THREE.Mesh;
|
|
651
|
+
instancer: InstancedMeshRenderer;
|
|
652
|
+
|
|
653
|
+
constructor(instanceIndex: number, originalObject: THREE.Mesh, instancer: InstancedMeshRenderer) {
|
|
654
|
+
this.instanceIndex = instanceIndex;
|
|
655
|
+
this.object = originalObject;
|
|
656
|
+
this.instancer = instancer;
|
|
657
|
+
GameObject.markAsInstancedRendered(originalObject, true);
|
|
658
|
+
// this.object.visible = false;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
updateInstanceMatrix(updateChildren: boolean = false) {
|
|
662
|
+
if (this.instanceIndex < 0) return;
|
|
663
|
+
this.object.updateWorldMatrix(true, updateChildren);
|
|
664
|
+
this.instancer.updateInstance(this.object.matrixWorld, this.instanceIndex);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
add() {
|
|
668
|
+
if (this.instanceIndex >= 0) return;
|
|
669
|
+
this.instancer.add(this);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
remove() {
|
|
673
|
+
if (this.instanceIndex < 0) return;
|
|
674
|
+
this.instancer.remove(this);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
class InstancedMeshRenderer {
|
|
679
|
+
|
|
680
|
+
public name: string = "";
|
|
681
|
+
public geo: THREE.BufferGeometry;
|
|
682
|
+
public material: THREE.Material;
|
|
683
|
+
get currentCount(): number { return this.inst.count; }
|
|
684
|
+
|
|
685
|
+
private context: Context;
|
|
686
|
+
private inst: THREE.InstancedMesh;
|
|
687
|
+
private handles: (InstanceHandle | null)[] = [];
|
|
688
|
+
private maxCount: number;
|
|
689
|
+
|
|
690
|
+
private static nullMatrix: THREE.Matrix4 = new THREE.Matrix4();
|
|
691
|
+
|
|
692
|
+
isFull(): boolean {
|
|
693
|
+
return this.currentCount >= this.maxCount;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
constructor(name: string, geo: THREE.BufferGeometry, material: THREE.Material, count: number, context: Context) {
|
|
697
|
+
this.name = name;
|
|
698
|
+
this.geo = geo;
|
|
699
|
+
this.material = material;
|
|
700
|
+
this.context = context;
|
|
701
|
+
this.maxCount = count;
|
|
702
|
+
if (debugInstancing) {
|
|
703
|
+
material = new THREE.MeshBasicMaterial({ color: this.randomColor() });
|
|
704
|
+
}
|
|
705
|
+
this.inst = new THREE.InstancedMesh(geo, material, count);
|
|
706
|
+
this.inst.count = 0;
|
|
707
|
+
this.inst.layers.set(2);
|
|
708
|
+
this.inst.visible = true;
|
|
709
|
+
// this.inst.castShadow = true;
|
|
710
|
+
// this.inst.receiveShadow = true;
|
|
711
|
+
this.context.scene.add(this.inst);
|
|
712
|
+
// console.log(this.inst);
|
|
713
|
+
// this.context.pre_render_callbacks.push(this.onPreRender.bind(this));
|
|
714
|
+
|
|
715
|
+
// setInterval(() => {
|
|
716
|
+
// this.inst.visible = !this.inst.visible;
|
|
717
|
+
// }, 500);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
private randomColor() {
|
|
721
|
+
return new THREE.Color(Math.random(), Math.random(), Math.random());
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
addInstance(obj: THREE.Mesh): InstanceHandle | null {
|
|
725
|
+
if (this.currentCount >= this.maxCount) {
|
|
726
|
+
console.error("TOO MANY INSTANCES - resize is not yet implemented!", this.inst.count); // todo: make it resize
|
|
727
|
+
return null;
|
|
728
|
+
}
|
|
729
|
+
const handle = new InstanceHandle(-1, obj, this);
|
|
730
|
+
this.add(handle);
|
|
731
|
+
return handle;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
add(handle: InstanceHandle) {
|
|
736
|
+
if (handle.instanceIndex < 0) {
|
|
737
|
+
handle.instanceIndex = this.currentCount;
|
|
738
|
+
// console.log(handle.instanceIndex, this.currentCount);
|
|
739
|
+
if (handle.instanceIndex >= this.handles.length)
|
|
740
|
+
this.handles.push(handle);
|
|
741
|
+
else this.handles[handle.instanceIndex] = handle;
|
|
742
|
+
}
|
|
743
|
+
// console.log("Handle instance");
|
|
744
|
+
handle.object.updateWorldMatrix(true, true);
|
|
745
|
+
this.inst.setMatrixAt(handle.instanceIndex, handle.object.matrixWorld);
|
|
746
|
+
this.inst.instanceMatrix.needsUpdate = true;
|
|
747
|
+
this.inst.count += 1;
|
|
748
|
+
|
|
749
|
+
if (this.inst.count > 0)
|
|
750
|
+
this.inst.visible = true;
|
|
751
|
+
|
|
752
|
+
// console.log("Added", this.name, this.inst.count, this.handles);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
remove(handle: InstanceHandle) {
|
|
756
|
+
if (!handle) return;
|
|
757
|
+
if (handle.instanceIndex < 0 || handle.instanceIndex >= this.handles.length || this.inst.count <= 0) {
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
if (this.handles[handle.instanceIndex] !== handle) {
|
|
761
|
+
console.error("instance handle is not part of renderer, was it removed before?", handle.instanceIndex, this.name);
|
|
762
|
+
const index = this.handles.indexOf(handle);
|
|
763
|
+
if (index < 0)
|
|
764
|
+
return;
|
|
765
|
+
handle.instanceIndex = index;
|
|
766
|
+
}
|
|
767
|
+
this.handles[handle.instanceIndex] = null;
|
|
768
|
+
this.inst.setMatrixAt(handle.instanceIndex, InstancedMeshRenderer.nullMatrix);
|
|
769
|
+
const removedLastElement = handle.instanceIndex >= this.currentCount - 1;
|
|
770
|
+
// console.log(removedLastElement, this.currentCount, handle.instanceIndex, this.handles);
|
|
771
|
+
if (!removedLastElement && this.currentCount > 0) {
|
|
772
|
+
const lastElement = this.handles[this.currentCount - 1];
|
|
773
|
+
if (lastElement) {
|
|
774
|
+
lastElement.instanceIndex = handle.instanceIndex;
|
|
775
|
+
lastElement.updateInstanceMatrix();
|
|
776
|
+
this.handles[handle.instanceIndex] = lastElement;
|
|
777
|
+
this.handles[this.currentCount - 1] = null;
|
|
778
|
+
// this.inst.setMatrixAt(handle.instanceIndex, lastElement.object.matrixWorld);
|
|
779
|
+
// this.inst.setMatrixAt(this.currentCount - 1, InstancedMeshRenderer.nullMatrix);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
if (this.inst.count > 0)
|
|
784
|
+
this.inst.count -= 1;
|
|
785
|
+
handle.instanceIndex = -1;
|
|
786
|
+
|
|
787
|
+
if (this.inst.count <= 0)
|
|
788
|
+
this.inst.visible = false;
|
|
789
|
+
|
|
790
|
+
this.inst.instanceMatrix.needsUpdate = true;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
updateInstance(mat: THREE.Matrix4, index: number) {
|
|
794
|
+
this.inst.setMatrixAt(index, mat);
|
|
795
|
+
this.inst.instanceMatrix.needsUpdate = true;
|
|
796
|
+
}
|
|
738
797
|
}
|