@zephyr3d/scene 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/asset/assetmanager.js +85 -93
  2. package/dist/asset/assetmanager.js.map +1 -1
  3. package/dist/camera/camera.js +1 -0
  4. package/dist/camera/camera.js.map +1 -1
  5. package/dist/index.d.ts +2511 -2329
  6. package/dist/index.js +2 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/material/blinn.js +5 -5
  9. package/dist/material/grassmaterial.js +14 -14
  10. package/dist/material/material.js +32 -54
  11. package/dist/material/material.js.map +1 -1
  12. package/dist/material/meshmaterial.js +215 -80
  13. package/dist/material/meshmaterial.js.map +1 -1
  14. package/dist/material/mixins/albedocolor.js +11 -7
  15. package/dist/material/mixins/albedocolor.js.map +1 -1
  16. package/dist/material/mixins/foliage.js +7 -7
  17. package/dist/material/mixins/lightmodel/blinnphong.js +5 -5
  18. package/dist/material/mixins/lightmodel/lambert.js +5 -5
  19. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +5 -5
  20. package/dist/material/mixins/lit.js +72 -72
  21. package/dist/material/mixins/pbr/common.js +4 -4
  22. package/dist/material/mixins/texture.js +6 -6
  23. package/dist/material/mixins/vertexcolor.js +5 -5
  24. package/dist/material/pbrmr.js +5 -5
  25. package/dist/material/shader/helper.js +20 -18
  26. package/dist/material/shader/helper.js.map +1 -1
  27. package/dist/material/terrainmaterial.js +12 -12
  28. package/dist/posteffect/bloom.js +1 -0
  29. package/dist/posteffect/bloom.js.map +1 -1
  30. package/dist/posteffect/compositor.js +1 -0
  31. package/dist/posteffect/compositor.js.map +1 -1
  32. package/dist/posteffect/water.js +1 -0
  33. package/dist/posteffect/water.js.map +1 -1
  34. package/dist/render/cull_visitor.js +24 -3
  35. package/dist/render/cull_visitor.js.map +1 -1
  36. package/dist/render/primitive.js +31 -0
  37. package/dist/render/primitive.js.map +1 -1
  38. package/dist/render/render_queue.js +111 -38
  39. package/dist/render/render_queue.js.map +1 -1
  40. package/dist/render/renderer.js +9 -0
  41. package/dist/render/renderer.js.map +1 -1
  42. package/dist/render/sky.js +2 -4
  43. package/dist/render/sky.js.map +1 -1
  44. package/dist/scene/batchgroup.js +126 -0
  45. package/dist/scene/batchgroup.js.map +1 -0
  46. package/dist/scene/environment.js +1 -0
  47. package/dist/scene/environment.js.map +1 -1
  48. package/dist/scene/graph_node.js +8 -0
  49. package/dist/scene/graph_node.js.map +1 -1
  50. package/dist/scene/mesh.js +35 -2
  51. package/dist/scene/mesh.js.map +1 -1
  52. package/dist/scene/octree.js +37 -72
  53. package/dist/scene/octree.js.map +1 -1
  54. package/dist/scene/octree_update_visitor.js +5 -1
  55. package/dist/scene/octree_update_visitor.js.map +1 -1
  56. package/dist/scene/scene.js +7 -17
  57. package/dist/scene/scene.js.map +1 -1
  58. package/dist/scene/scene_node.js +57 -44
  59. package/dist/scene/scene_node.js.map +1 -1
  60. package/dist/scene/xform.js +61 -36
  61. package/dist/scene/xform.js.map +1 -1
  62. package/dist/shadow/esm.js +1 -0
  63. package/dist/shadow/esm.js.map +1 -1
  64. package/dist/shadow/shadowmapper.js +22 -6
  65. package/dist/shadow/shadowmapper.js.map +1 -1
  66. package/dist/shadow/vsm.js +1 -0
  67. package/dist/shadow/vsm.js.map +1 -1
  68. package/dist/shapes/box.js +15 -6
  69. package/dist/shapes/box.js.map +1 -1
  70. package/dist/shapes/cylinder.js +1 -4
  71. package/dist/shapes/cylinder.js.map +1 -1
  72. package/dist/shapes/shape.js +5 -0
  73. package/dist/shapes/shape.js.map +1 -1
  74. package/dist/shapes/sphere.js +3 -0
  75. package/dist/shapes/sphere.js.map +1 -1
  76. package/package.json +6 -6
@@ -1,5 +1,4 @@
1
- import { AABB, Vector3 } from '@zephyr3d/base';
2
- import { GraphNode } from './graph_node.js';
1
+ import { AABB, Vector3, nextPowerOf2 } from '@zephyr3d/base';
3
2
 
4
3
  var OctreePlacement;
5
4
  (function(OctreePlacement) {
@@ -18,7 +17,6 @@ var OctreePlacement;
18
17
  */ class OctreeNode {
19
18
  /** @internal */ _chunk;
20
19
  /** @internal */ _position;
21
- /** @internal */ _references;
22
20
  /** @internal */ _nodes;
23
21
  /** @internal */ _box;
24
22
  /** @internal */ _boxLoosed;
@@ -27,7 +25,6 @@ var OctreePlacement;
27
25
  */ constructor(){
28
26
  this._chunk = null;
29
27
  this._position = 0;
30
- this._references = 0;
31
28
  this._nodes = [];
32
29
  this._box = null;
33
30
  this._boxLoosed = null;
@@ -50,6 +47,7 @@ var OctreePlacement;
50
47
  */ addNode(node) {
51
48
  if (node && this._nodes.indexOf(node) < 0) {
52
49
  this._nodes.push(node);
50
+ node.octreeNode = this;
53
51
  }
54
52
  }
55
53
  /**
@@ -59,9 +57,13 @@ var OctreePlacement;
59
57
  const index = this._nodes.indexOf(node);
60
58
  if (index >= 0) {
61
59
  this._nodes.splice(index, 1);
60
+ node.octreeNode = null;
62
61
  }
63
62
  }
64
63
  /** Removes all the scene nodes that this octree node contains */ clearNodes() {
64
+ for (const node of this._nodes){
65
+ node.octreeNode = null;
66
+ }
65
67
  this._nodes = [];
66
68
  }
67
69
  /**
@@ -90,12 +92,6 @@ var OctreePlacement;
90
92
  return this._position;
91
93
  }
92
94
  /**
93
- * Invalidates the cached box
94
- */ invalidateBox() {
95
- this._box = null;
96
- this.getParent()?.invalidateBox();
97
- }
98
- /**
99
95
  * Get the bounding box of the octree node
100
96
  * @returns The bounding box of the octree node
101
97
  */ getBox() {
@@ -112,15 +108,6 @@ var OctreePlacement;
112
108
  }
113
109
  }
114
110
  }
115
- for (const node of this._nodes){
116
- if (!node.isLight()) {
117
- const bv = node.getWorldBoundingVolume()?.toAABB();
118
- if (bv) {
119
- box.extend(bv.minPoint);
120
- box.extend(bv.maxPoint);
121
- }
122
- }
123
- }
124
111
  if (box.isValid()) {
125
112
  this._box = box;
126
113
  }
@@ -186,12 +173,6 @@ var OctreePlacement;
186
173
  return this.getMaxPoint().addBy(new Vector3(halfNodeSize, halfNodeSize, halfNodeSize));
187
174
  }
188
175
  /**
189
- * Get reference of the node
190
- * @returns Reference of the node
191
- */ getReference() {
192
- return this._references;
193
- }
194
- /**
195
176
  * Gets the child node by a given placement
196
177
  * @param placement - The placement
197
178
  * @returns Child node at the given placement
@@ -238,23 +219,6 @@ var OctreePlacement;
238
219
  this.getOrCreateChild(OctreePlacement.NNN);
239
220
  }
240
221
  /**
241
- * Free up all empty children
242
- * @returns true if some children were freed
243
- */ tidy() {
244
- this._references = 8;
245
- for(let i = 0; i < 8; i++){
246
- const node = this.getChild(i);
247
- if (!node || node.tidy()) {
248
- --this._references;
249
- }
250
- }
251
- if (this._nodes.length === 0 && this._references === 0) {
252
- this._chunk.freeNodeByIndex(this._position);
253
- return true;
254
- }
255
- return false;
256
- }
257
- /**
258
222
  * Traverse this node by a visitor
259
223
  * @param v - The visitor
260
224
  */ traverse(v) {
@@ -291,6 +255,9 @@ var OctreePlacement;
291
255
  this._prev = null;
292
256
  this._nodeMap = new Map();
293
257
  }
258
+ /** @internal */ get nodeMap() {
259
+ return this._nodeMap;
260
+ }
294
261
  /**
295
262
  * Gets an octree node at a given index
296
263
  * @param index - Index of the node
@@ -324,25 +291,6 @@ var OctreePlacement;
324
291
  return node;
325
292
  }
326
293
  /**
327
- * Removes an octree node at given index
328
- * @param index - Index of the node
329
- */ freeNodeByIndex(index) {
330
- const node = this._nodeMap.get(index);
331
- if (node) {
332
- node.clearNodes();
333
- this._nodeMap.delete(index);
334
- }
335
- }
336
- /**
337
- * Removes an octree node
338
- * @param node - The octree node to be removed
339
- */ freeNode(node) {
340
- if (node) {
341
- console.assert(node.getChunk() === this, 'Invalid chunk');
342
- this.freeNodeByIndex(node.getPosition());
343
- }
344
- }
345
- /**
346
294
  * Removes all octree nodes of this chunk
347
295
  */ clearNodes() {
348
296
  for (const key of this._nodeMap.keys()){
@@ -516,10 +464,9 @@ var OctreePlacement;
516
464
  * @param rootSize - Root size of the octree
517
465
  * @param leafSize - Leaf size of the octree
518
466
  */ initialize(rootSize, leafSize) {
519
- console.assert(rootSize >= leafSize && leafSize > 0, 'Invalid rootSize or leafSize for octree');
520
467
  this.finalize();
521
- this._rootSize = rootSize;
522
468
  this._leafSize = leafSize;
469
+ this._rootSize = Math.max(leafSize, rootSize);
523
470
  let n = 1;
524
471
  for(; rootSize >= leafSize * 2; leafSize *= 2, ++n);
525
472
  for(let i = 0; i < n; ++i, rootSize *= 0.5){
@@ -535,6 +482,7 @@ var OctreePlacement;
535
482
  }
536
483
  }
537
484
  /** Free up the octree */ finalize() {
485
+ this._chunks.forEach((chunk)=>chunk.clearNodes());
538
486
  this._chunks = [];
539
487
  this._rootSize = 0;
540
488
  this._leafSize = 0;
@@ -576,10 +524,7 @@ var OctreePlacement;
576
524
  let py = Math.floor((center.y + this._rootSize * 0.5) * inv_node_size);
577
525
  let pz = Math.floor((center.z + this._rootSize * 0.5) * inv_node_size);
578
526
  if (px >= dim || py >= dim || pz >= dim) {
579
- level = 0;
580
- px = 0;
581
- py = 0;
582
- pz = 0;
527
+ return null;
583
528
  }
584
529
  const index = px + py * dim + pz * dim * dim;
585
530
  if (candidate && candidate.getChunk().getLevel() === level && candidate.getPosition() === index) {
@@ -615,21 +560,26 @@ var OctreePlacement;
615
560
  */ placeNode(node) {
616
561
  const curNode = this._nodeMap.get(node) || null;
617
562
  let locatedNode = this.getRootNode();
618
- if (node.computedClipMode === GraphNode.CLIP_ENABLED) {
563
+ if (node.clipTestEnabled) {
619
564
  const bbox = node.getWorldBoundingVolume()?.toAABB();
620
565
  if (bbox && bbox.isValid()) {
621
566
  const center = bbox.center;
622
567
  const extents = bbox.extents;
623
568
  const size = Math.max(Math.max(extents.x, extents.y), extents.z);
624
- locatedNode = this.locateNodeChain(curNode, center, size) || this.getRootNode();
569
+ locatedNode = this.locateNodeChain(curNode, center, size);
570
+ if (!locatedNode) {
571
+ const d = Math.max(...Vector3.abs(bbox.minPoint), ...Vector3.abs(bbox.maxPoint));
572
+ // nodeSize >= 4 * size & octreeSize >= 2 * d
573
+ this.resize(Math.max(d * 2, 4 * size));
574
+ this.placeNode(node);
575
+ return;
576
+ }
625
577
  }
626
578
  }
627
579
  if (curNode !== locatedNode) {
628
580
  curNode?.removeNode(node);
629
581
  locatedNode?.addNode(node);
630
582
  this._nodeMap.set(node, locatedNode);
631
- curNode?.invalidateBox();
632
- locatedNode?.invalidateBox();
633
583
  }
634
584
  }
635
585
  /**
@@ -640,11 +590,26 @@ var OctreePlacement;
640
590
  const curNode = this._nodeMap.get(node) || null;
641
591
  if (curNode) {
642
592
  curNode.removeNode(node);
643
- curNode.invalidateBox();
644
593
  this._nodeMap.delete(node);
645
594
  }
646
595
  }
647
596
  }
597
+ resize(size) {
598
+ size = Math.max(nextPowerOf2(size), this._leafSize);
599
+ if (size === this._rootSize) {
600
+ return;
601
+ }
602
+ const nodes = [];
603
+ for (const chunk of this._chunks){
604
+ chunk.nodeMap.forEach((node)=>{
605
+ nodes.push(...node.getNodes());
606
+ });
607
+ }
608
+ this.initialize(size, this._leafSize);
609
+ for (const node of nodes){
610
+ this.placeNode(node);
611
+ }
612
+ }
648
613
  }
649
614
 
650
615
  export { Octree, OctreeNode, OctreeNodeChunk, OctreePlacement };
@@ -1 +1 @@
1
- {"version":3,"file":"octree.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"octree.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -7,7 +7,11 @@ import { GraphNode } from './graph_node.js';
7
7
  }
8
8
  visit(node) {
9
9
  if (node instanceof GraphNode) {
10
- this._octree.placeNode(node);
10
+ if (node.placeToOctree) {
11
+ this._octree.placeNode(node);
12
+ } else {
13
+ this._octree.removeNode(node);
14
+ }
11
15
  }
12
16
  }
13
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"octree_update_visitor.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"octree_update_visitor.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;"}
@@ -45,7 +45,7 @@ import { Environment } from './environment.js';
45
45
  */ constructor(){
46
46
  super();
47
47
  this._id = ++Scene._nextId;
48
- this._octree = new Octree(this, 2048, 64);
48
+ this._octree = new Octree(this, 8, 8);
49
49
  this._nodePlaceList = new Set();
50
50
  this._env = new Environment();
51
51
  this._updateEvent = new SceneUpdateEvent(this);
@@ -78,7 +78,7 @@ import { Environment } from './environment.js';
78
78
  */ get boundingBox() {
79
79
  this.updateNodePlacement(this._octree, this._nodePlaceList);
80
80
  // this._syncBVChangedList();
81
- return this._octree.getRootNode().getBox() || this._octree.getRootNode().getBoxLoosed();
81
+ return this._octree.getRootNode().getBoxLoosed();
82
82
  }
83
83
  /**
84
84
  * The environment of the scene
@@ -130,13 +130,10 @@ import { Environment } from './environment.js';
130
130
  return new Ray(vEye, vDir);
131
131
  }
132
132
  /** @internal */ invalidateNodePlacement(node) {
133
- if (node.isGraphNode() || node.children.length > 0) {
133
+ if (node.placeToOctree || node.octreeNode) {
134
134
  this._nodePlaceList.add(node);
135
135
  }
136
136
  }
137
- /** @internal */ _xformChanged(node) {
138
- this._nodePlaceList.add(node);
139
- }
140
137
  /** @internal */ frameUpdate() {
141
138
  const frameInfo = Application.instance.device.frameInfo;
142
139
  if (frameInfo.frameCounter !== this._updateFrame) {
@@ -178,17 +175,10 @@ import { Environment } from './environment.js';
178
175
  * Update node placement in the octree
179
176
  */ updateNodePlacement(octree, list) {
180
177
  function placeNode(node, attached) {
181
- if (node.isGraphNode()) {
182
- if (attached && !node.hidden) {
183
- octree.placeNode(node);
184
- } else {
185
- octree.removeNode(node);
186
- }
187
- }
188
- for (const child of node.children){
189
- if (child.isGraphNode()) {
190
- placeNode(child, attached);
191
- }
178
+ if (attached && !node.hidden && node.placeToOctree) {
179
+ octree.placeNode(node);
180
+ } else {
181
+ octree.removeNode(node);
192
182
  }
193
183
  list.delete(node);
194
184
  }
@@ -1 +1 @@
1
- {"version":3,"file":"scene.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"scene.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -12,16 +12,11 @@ import { XForm } from './xform.js';
12
12
  *
13
13
  * @public
14
14
  */ class SceneNode extends XForm {
15
- static CLIP_INHERITED = -1;
16
- static CLIP_DISABLED = 0;
17
- static CLIP_ENABLED = 1;
18
- static SHOW_INHERITED = -1;
19
- static SHOW_HIDE = 0;
20
- static SHOW_DEFAULT = 1;
21
- static PICK_INHERITED = -1;
22
- static PICK_DISABLED = 0;
23
- static PICK_ENABLED = 1;
24
- static BBOXDRAW_INHERITED = -1;
15
+ /*
16
+ static readonly PICK_INHERITED = -1;
17
+ static readonly PICK_DISABLED = 0;
18
+ static readonly PICK_ENABLED = 1;
19
+ */ static BBOXDRAW_INHERITED = -1;
25
20
  static BBOXDRAW_DISABLED = 0;
26
21
  static BBOXDRAW_LOCAL = 1;
27
22
  static BBOXDRAW_WORLD = 2;
@@ -35,6 +30,7 @@ import { XForm } from './xform.js';
35
30
  /** @internal */ _bv;
36
31
  /** @internal */ _bvDirty;
37
32
  /** @internal */ _bvWorld;
33
+ /** @internal */ _placeToOctree;
38
34
  /**
39
35
  * Creates a new scene node
40
36
  * @param scene - Which scene the node belongs to
@@ -45,14 +41,26 @@ import { XForm } from './xform.js';
45
41
  this._bv = null;
46
42
  this._bvWorld = null;
47
43
  this._bvDirty = true;
48
- this._clipMode = SceneNode.CLIP_ENABLED;
44
+ this._clipMode = true;
49
45
  this._boxDrawMode = SceneNode.BBOXDRAW_DISABLED;
50
- this._visible = SceneNode.SHOW_INHERITED;
51
- this._pickMode = SceneNode.PICK_DISABLED;
46
+ this._visible = 'inherit';
47
+ this._pickMode = false;
48
+ this._placeToOctree = true;
52
49
  if (scene && this !== scene.rootNode) {
53
50
  this.reparent(scene.rootNode);
54
51
  }
55
52
  }
53
+ /** @internal */ get placeToOctree() {
54
+ return this._placeToOctree;
55
+ }
56
+ /** @internal */ set placeToOctree(val) {
57
+ if (!!val !== this._placeToOctree) {
58
+ this._placeToOctree = !!val;
59
+ if (this.isGraphNode()) {
60
+ this.scene.invalidateNodePlacement(this);
61
+ }
62
+ }
63
+ }
56
64
  /**
57
65
  * Name of the scene node
58
66
  */ get name() {
@@ -133,6 +141,9 @@ import { XForm } from './xform.js';
133
141
  /** true if this is a mesh node, false otherwise */ isMesh() {
134
142
  return false;
135
143
  }
144
+ /** true if this is a batch group, false otherwise */ isBatchGroup() {
145
+ return false;
146
+ }
136
147
  /** true if this is a terrain node, false otherwise */ isTerrain() {
137
148
  return false;
138
149
  }
@@ -185,36 +196,34 @@ import { XForm } from './xform.js';
185
196
  * Force the bounding volume to be recalculated
186
197
  */ invalidateBoundingVolume() {
187
198
  this._bvDirty = true;
188
- this.invalidateWorldBoundingVolume();
199
+ this.invalidateWorldBoundingVolume(false);
189
200
  }
190
- /** Force the world space bounding volume to be recalculated */ invalidateWorldBoundingVolume() {
201
+ /** Force the world space bounding volume to be recalculated */ invalidateWorldBoundingVolume(transformChanged) {
191
202
  this._bvWorld = null;
192
- this._scene?.invalidateNodePlacement(this);
193
- }
194
- /**
195
- * Computed value of clip mode
196
- */ get computedClipMode() {
197
- if (this._clipMode === SceneNode.CLIP_INHERITED) {
198
- let parent = this.parent;
199
- while(parent && !parent.isGraphNode()){
200
- parent = parent.parent;
203
+ if (this._scene) {
204
+ if (transformChanged) {
205
+ this.iterate((node)=>{
206
+ if (node.isGraphNode()) {
207
+ this._scene.invalidateNodePlacement(node);
208
+ }
209
+ });
210
+ } else if (this.isGraphNode()) {
211
+ this._scene.invalidateNodePlacement(this);
201
212
  }
202
- return parent?.computedClipMode ?? SceneNode.CLIP_ENABLED;
203
213
  }
204
- return this._clipMode;
205
214
  }
206
- /** Clip mode */ get clipMode() {
215
+ /** Clip mode */ get clipTestEnabled() {
207
216
  return this._clipMode;
208
217
  }
209
- set clipMode(val) {
218
+ set clipTestEnabled(val) {
210
219
  this._clipMode = val;
211
220
  }
212
221
  /** Computed value of show state */ get hidden() {
213
222
  let node = this;
214
- while(node && node._visible === SceneNode.SHOW_INHERITED){
223
+ while(node && node._visible === 'inherit'){
215
224
  node = node.parent;
216
225
  }
217
- return node ? node._visible === SceneNode.SHOW_HIDE : false;
226
+ return node ? node._visible === 'hidden' : false;
218
227
  }
219
228
  /** Show state */ get showState() {
220
229
  return this._visible;
@@ -229,17 +238,10 @@ import { XForm } from './xform.js';
229
238
  }
230
239
  }
231
240
  /** Computed value of pick mode */ get pickable() {
232
- let node = this;
233
- while(node && node._pickMode === SceneNode.PICK_INHERITED){
234
- node = node.parent;
235
- }
236
- return node ? node._pickMode === SceneNode.PICK_ENABLED : false;
237
- }
238
- /** Pick mode */ get pickMode() {
239
241
  return this._pickMode;
240
242
  }
241
- set pickMode(val) {
242
- this._pickMode = val;
243
+ set pickable(val) {
244
+ this._pickMode = !!val;
243
245
  }
244
246
  /** Computed value for bounding box draw mode */ get computedBoundingBoxDrawMode() {
245
247
  if (this._boxDrawMode === SceneNode.BBOXDRAW_INHERITED) {
@@ -258,21 +260,32 @@ import { XForm } from './xform.js';
258
260
  this._boxDrawMode = mode;
259
261
  }
260
262
  /** @internal */ _setParent(p) {
261
- if (p !== this._parent) {
263
+ let lastParent = this._parent;
264
+ let newParent = p;
265
+ if (newParent !== lastParent) {
262
266
  const sceneLast = this.attached ? this.scene : null;
263
- const sceneNew = p?.attached ? p.scene : null;
267
+ const sceneNew = newParent?.attached ? newParent.scene : null;
264
268
  const willDetach = sceneLast && sceneLast !== sceneNew;
265
269
  const willAttach = sceneNew && sceneLast !== sceneNew;
266
270
  willDetach && this._willDetach();
267
271
  willAttach && this._willAttach();
268
- super._setParent(p);
272
+ super._setParent(newParent);
269
273
  willDetach && this._detached();
270
274
  willAttach && this._attached();
271
275
  }
276
+ while(lastParent){
277
+ lastParent.dispatchEvent(this, 'noderemoved');
278
+ lastParent = lastParent.parent;
279
+ }
280
+ while(newParent){
281
+ newParent.dispatchEvent(this, 'nodeattached');
282
+ newParent = newParent.parent;
283
+ }
272
284
  }
273
285
  /** @internal */ _onTransformChanged(invalidateLocal) {
274
286
  super._onTransformChanged(invalidateLocal);
275
- this.invalidateWorldBoundingVolume();
287
+ this.invalidateWorldBoundingVolume(true);
288
+ this.dispatchEvent(this, 'transformchanged');
276
289
  }
277
290
  /** @internal */ _willAttach() {}
278
291
  /** @internal */ _attached() {}
@@ -281,7 +294,7 @@ import { XForm } from './xform.js';
281
294
  /** @internal */ notifyHiddenChanged() {
282
295
  this._visibleChanged();
283
296
  for (const child of this._children){
284
- if (child.showState === SceneNode.SHOW_INHERITED) {
297
+ if (child.showState === 'inherit') {
285
298
  child.notifyHiddenChanged();
286
299
  }
287
300
  }
@@ -1 +1 @@
1
- {"version":3,"file":"scene_node.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"scene_node.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,9 +1,9 @@
1
- import { ObservableVector3, ObservableQuaternion, Matrix4x4, Vector3, Vector4 } from '@zephyr3d/base';
1
+ import { makeEventTarget, ObservableVector3, ObservableQuaternion, Matrix4x4, Vector3, Vector4 } from '@zephyr3d/base';
2
2
 
3
3
  /**
4
4
  * Presents a transformation from one space to another
5
5
  * @public
6
- */ class XForm {
6
+ */ class XForm extends makeEventTarget(Object)() {
7
7
  /** @internal */ _parent;
8
8
  /** @internal */ _children;
9
9
  /** @internal */ _position;
@@ -16,20 +16,20 @@ import { ObservableVector3, ObservableQuaternion, Matrix4x4, Vector3, Vector4 }
16
16
  /** @internal */ _tmpLocalMatrix;
17
17
  /** @internal */ _tmpWorldMatrix;
18
18
  /** @internal */ _transformTag;
19
+ /** @internal */ _transformChangeCallback;
19
20
  /**
20
21
  * Creates an instance of XForm
21
22
  */ constructor(){
23
+ super();
22
24
  this._parent = null;
23
25
  this._children = [];
24
- const cb = ()=>{
25
- this._onTransformChanged(true);
26
- };
26
+ this._transformChangeCallback = ()=>this._onTransformChanged(true);
27
27
  this._position = new ObservableVector3(0, 0, 0);
28
- this._position.callback = cb;
28
+ this._position.callback = this._transformChangeCallback;
29
29
  this._scaling = new ObservableVector3(1, 1, 1);
30
- this._scaling.callback = cb;
30
+ this._scaling.callback = this._transformChangeCallback;
31
31
  this._rotation = new ObservableQuaternion();
32
- this._rotation.callback = cb;
32
+ this._rotation.callback = this._transformChangeCallback;
33
33
  this._worldMatrix = null;
34
34
  this._worldMatrixDet = null;
35
35
  this._invWorldMatrix = null;
@@ -51,22 +51,47 @@ import { ObservableVector3, ObservableQuaternion, Matrix4x4, Vector3, Vector4 }
51
51
  return this._children;
52
52
  }
53
53
  /**
54
- * Resets the transformation matrix
55
- * @returns self
56
- */ resetTransform() {
57
- this._position.setXYZ(0, 0, 0);
58
- this._rotation.identity();
59
- this._scaling.setXYZ(1, 1, 1);
60
- return this;
61
- }
62
- /**
63
54
  * Position of the xform relative to it's parent
64
55
  */ get position() {
56
+ if (!this._position) {
57
+ this.syncTRS();
58
+ }
65
59
  return this._position;
66
60
  }
67
61
  set position(val) {
62
+ if (!this._position) {
63
+ this.syncTRS();
64
+ }
68
65
  this._position.setXYZ(val[0], val[1], val[2]);
69
66
  }
67
+ /**
68
+ * Scaling of the xform
69
+ */ get scale() {
70
+ if (!this._scaling) {
71
+ this.syncTRS();
72
+ }
73
+ return this._scaling;
74
+ }
75
+ set scale(val) {
76
+ if (!this._scaling) {
77
+ this.syncTRS();
78
+ }
79
+ this._scaling.setXYZ(val[0], val[1], val[2]);
80
+ }
81
+ /**
82
+ * Rotation of the xform
83
+ */ get rotation() {
84
+ if (!this._rotation) {
85
+ this.syncTRS();
86
+ }
87
+ return this._rotation;
88
+ }
89
+ set rotation(val) {
90
+ if (!this._rotation) {
91
+ this.syncTRS();
92
+ }
93
+ this._rotation.setXYZW(val[0], val[1], val[2], val[3]);
94
+ }
70
95
  worldToThis(v, result) {
71
96
  if (v instanceof Vector3) {
72
97
  result = result || new Vector3();
@@ -118,27 +143,15 @@ import { ObservableVector3, ObservableQuaternion, Matrix4x4, Vector3, Vector4 }
118
143
  return this;
119
144
  }
120
145
  /**
121
- * Scaling of the xform
122
- */ get scale() {
123
- return this._scaling;
124
- }
125
- set scale(val) {
126
- this._scaling.setXYZ(val[0], val[1], val[2]);
127
- }
128
- /**
129
- * Rotation of the xform
130
- */ get rotation() {
131
- return this._rotation;
132
- }
133
- set rotation(val) {
134
- this._rotation.setXYZW(val[0], val[1], val[2], val[3]);
135
- }
136
- /**
137
146
  * Sets the local transform matrix of the xform
138
- * @param m - The transform matrix to set
147
+ * @param matrix - The transform matrix to set
139
148
  * @returns self
140
- */ setLocalTransform(m) {
141
- m.decompose(this._scaling, this._rotation, this._position);
149
+ */ setLocalTransform(matrix) {
150
+ this._localMatrix = matrix;
151
+ this._position = null;
152
+ this._rotation = null;
153
+ this._scaling = null;
154
+ this._onTransformChanged(false);
142
155
  return this;
143
156
  }
144
157
  /** Local transformation matrix of the xform */ get localMatrix() {
@@ -148,6 +161,9 @@ import { ObservableVector3, ObservableQuaternion, Matrix4x4, Vector3, Vector4 }
148
161
  }
149
162
  return this._localMatrix;
150
163
  }
164
+ set localMatrix(matrix) {
165
+ this.setLocalTransform(matrix);
166
+ }
151
167
  /** World transformation matrix of the xform */ get worldMatrix() {
152
168
  if (!this._worldMatrix) {
153
169
  this._worldMatrix = this._tmpWorldMatrix;
@@ -192,6 +208,15 @@ import { ObservableVector3, ObservableQuaternion, Matrix4x4, Vector3, Vector4 }
192
208
  /** @internal */ getTag() {
193
209
  return this._transformTag;
194
210
  }
211
+ /** @internal */ syncTRS() {
212
+ this._position = new ObservableVector3();
213
+ this._rotation = new ObservableQuaternion();
214
+ this._scaling = new ObservableVector3();
215
+ this._localMatrix.decompose(this._scaling, this._rotation, this._position);
216
+ this._position.callback = this._transformChangeCallback;
217
+ this._rotation.callback = this._transformChangeCallback;
218
+ this._scaling.callback = this._transformChangeCallback;
219
+ }
195
220
  /** @internal */ _onTransformChanged(invalidateLocal) {
196
221
  if (invalidateLocal) {
197
222
  this._localMatrix = null;
@@ -1 +1 @@
1
- {"version":3,"file":"xform.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"xform.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,6 +1,7 @@
1
1
  import { ShadowImpl } from './shadow_impl.js';
2
2
  import '@zephyr3d/base';
3
3
  import { Application } from '../app.js';
4
+ import '@zephyr3d/device';
4
5
  import { decodeNormalizedFloatFromRGBA, encodeNormalizedFloatToRGBA } from '../shaders/misc.js';
5
6
  import { GaussianBlurBlitter } from '../blitter/gaussianblur.js';
6
7
  import { computeShadowMapDepth, filterShadowESM } from '../shaders/shadow.js';
@@ -1 +1 @@
1
- {"version":3,"file":"esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}