@zephyr3d/scene 0.1.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 (236) hide show
  1. package/dist/animation/animation.js +173 -0
  2. package/dist/animation/animation.js.map +1 -0
  3. package/dist/animation/animationset.js +95 -0
  4. package/dist/animation/animationset.js.map +1 -0
  5. package/dist/animation/animationtrack.js +38 -0
  6. package/dist/animation/animationtrack.js.map +1 -0
  7. package/dist/animation/eulerrotationtrack.js +33 -0
  8. package/dist/animation/eulerrotationtrack.js.map +1 -0
  9. package/dist/animation/rotationtrack.js +37 -0
  10. package/dist/animation/rotationtrack.js.map +1 -0
  11. package/dist/animation/scaletrack.js +36 -0
  12. package/dist/animation/scaletrack.js.map +1 -0
  13. package/dist/animation/skeleton.js +97 -0
  14. package/dist/animation/skeleton.js.map +1 -0
  15. package/dist/animation/translationtrack.js +36 -0
  16. package/dist/animation/translationtrack.js.map +1 -0
  17. package/dist/animation/usertrack.js +47 -0
  18. package/dist/animation/usertrack.js.map +1 -0
  19. package/dist/app.js +173 -0
  20. package/dist/app.js.map +1 -0
  21. package/dist/asset/assetmanager.js +476 -0
  22. package/dist/asset/assetmanager.js.map +1 -0
  23. package/dist/asset/builtin.js +373 -0
  24. package/dist/asset/builtin.js.map +1 -0
  25. package/dist/asset/loaders/dds/dds.js +472 -0
  26. package/dist/asset/loaders/dds/dds.js.map +1 -0
  27. package/dist/asset/loaders/dds/dds_loader.js +38 -0
  28. package/dist/asset/loaders/dds/dds_loader.js.map +1 -0
  29. package/dist/asset/loaders/gltf/gltf_loader.js +981 -0
  30. package/dist/asset/loaders/gltf/gltf_loader.js.map +1 -0
  31. package/dist/asset/loaders/gltf/helpers.js +314 -0
  32. package/dist/asset/loaders/gltf/helpers.js.map +1 -0
  33. package/dist/asset/loaders/hdr/hdr.js +175 -0
  34. package/dist/asset/loaders/hdr/hdr.js.map +1 -0
  35. package/dist/asset/loaders/image/tga_Loader.js +117 -0
  36. package/dist/asset/loaders/image/tga_Loader.js.map +1 -0
  37. package/dist/asset/loaders/image/webimage_loader.js +50 -0
  38. package/dist/asset/loaders/image/webimage_loader.js.map +1 -0
  39. package/dist/asset/loaders/loader.js +45 -0
  40. package/dist/asset/loaders/loader.js.map +1 -0
  41. package/dist/asset/model.js +264 -0
  42. package/dist/asset/model.js.map +1 -0
  43. package/dist/blitter/blitter.js +389 -0
  44. package/dist/blitter/blitter.js.map +1 -0
  45. package/dist/blitter/box.js +118 -0
  46. package/dist/blitter/box.js.map +1 -0
  47. package/dist/blitter/copy.js +22 -0
  48. package/dist/blitter/copy.js.map +1 -0
  49. package/dist/blitter/depthlimitedgaussion.js +166 -0
  50. package/dist/blitter/depthlimitedgaussion.js.map +1 -0
  51. package/dist/blitter/gaussianblur.js +229 -0
  52. package/dist/blitter/gaussianblur.js.map +1 -0
  53. package/dist/camera/base.js +90 -0
  54. package/dist/camera/base.js.map +1 -0
  55. package/dist/camera/camera.js +358 -0
  56. package/dist/camera/camera.js.map +1 -0
  57. package/dist/camera/fps.js +246 -0
  58. package/dist/camera/fps.js.map +1 -0
  59. package/dist/camera/orbit.js +157 -0
  60. package/dist/camera/orbit.js.map +1 -0
  61. package/dist/camera/orthocamera.js +126 -0
  62. package/dist/camera/orthocamera.js.map +1 -0
  63. package/dist/camera/perspectivecamera.js +133 -0
  64. package/dist/camera/perspectivecamera.js.map +1 -0
  65. package/dist/index.d.ts +8402 -0
  66. package/dist/index.js +87 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/input/inputmgr.js +242 -0
  69. package/dist/input/inputmgr.js.map +1 -0
  70. package/dist/material/blinn.js +75 -0
  71. package/dist/material/blinn.js.map +1 -0
  72. package/dist/material/grassmaterial.js +221 -0
  73. package/dist/material/grassmaterial.js.map +1 -0
  74. package/dist/material/lambert.js +52 -0
  75. package/dist/material/lambert.js.map +1 -0
  76. package/dist/material/lightmodel.js +2074 -0
  77. package/dist/material/lightmodel.js.map +1 -0
  78. package/dist/material/lit.js +578 -0
  79. package/dist/material/lit.js.map +1 -0
  80. package/dist/material/material.js +458 -0
  81. package/dist/material/material.js.map +1 -0
  82. package/dist/material/meshmaterial.js +311 -0
  83. package/dist/material/meshmaterial.js.map +1 -0
  84. package/dist/material/mixins/albedocolor.js +130 -0
  85. package/dist/material/mixins/albedocolor.js.map +1 -0
  86. package/dist/material/mixins/texture.js +110 -0
  87. package/dist/material/mixins/texture.js.map +1 -0
  88. package/dist/material/mixins/vertexcolor.js +45 -0
  89. package/dist/material/mixins/vertexcolor.js.map +1 -0
  90. package/dist/material/pbr.js +27 -0
  91. package/dist/material/pbr.js.map +1 -0
  92. package/dist/material/standard.js +282 -0
  93. package/dist/material/standard.js.map +1 -0
  94. package/dist/material/terrainlightmodel.js +259 -0
  95. package/dist/material/terrainlightmodel.js.map +1 -0
  96. package/dist/material/terrainmaterial.js +139 -0
  97. package/dist/material/terrainmaterial.js.map +1 -0
  98. package/dist/material/unlit.js +29 -0
  99. package/dist/material/unlit.js.map +1 -0
  100. package/dist/posteffect/bloom.js +398 -0
  101. package/dist/posteffect/bloom.js.map +1 -0
  102. package/dist/posteffect/compositor.js +264 -0
  103. package/dist/posteffect/compositor.js.map +1 -0
  104. package/dist/posteffect/fxaa.js +291 -0
  105. package/dist/posteffect/fxaa.js.map +1 -0
  106. package/dist/posteffect/grayscale.js +87 -0
  107. package/dist/posteffect/grayscale.js.map +1 -0
  108. package/dist/posteffect/posteffect.js +165 -0
  109. package/dist/posteffect/posteffect.js.map +1 -0
  110. package/dist/posteffect/sao.js +327 -0
  111. package/dist/posteffect/sao.js.map +1 -0
  112. package/dist/posteffect/tonemap.js +112 -0
  113. package/dist/posteffect/tonemap.js.map +1 -0
  114. package/dist/posteffect/water.js +535 -0
  115. package/dist/posteffect/water.js.map +1 -0
  116. package/dist/render/clipmap.js +462 -0
  117. package/dist/render/clipmap.js.map +1 -0
  118. package/dist/render/cluster_light.js +329 -0
  119. package/dist/render/cluster_light.js.map +1 -0
  120. package/dist/render/cull_visitor.js +124 -0
  121. package/dist/render/cull_visitor.js.map +1 -0
  122. package/dist/render/depth_pass.js +47 -0
  123. package/dist/render/depth_pass.js.map +1 -0
  124. package/dist/render/envlight.js +282 -0
  125. package/dist/render/envlight.js.map +1 -0
  126. package/dist/render/forward.js +186 -0
  127. package/dist/render/forward.js.map +1 -0
  128. package/dist/render/forward_pass.js +137 -0
  129. package/dist/render/forward_pass.js.map +1 -0
  130. package/dist/render/helper.js +38 -0
  131. package/dist/render/helper.js.map +1 -0
  132. package/dist/render/primitive.js +246 -0
  133. package/dist/render/primitive.js.map +1 -0
  134. package/dist/render/render_queue.js +163 -0
  135. package/dist/render/render_queue.js.map +1 -0
  136. package/dist/render/renderpass.js +151 -0
  137. package/dist/render/renderpass.js.map +1 -0
  138. package/dist/render/renderscheme.js +61 -0
  139. package/dist/render/renderscheme.js.map +1 -0
  140. package/dist/render/scatteringlut.js +634 -0
  141. package/dist/render/scatteringlut.js.map +1 -0
  142. package/dist/render/shadowmap_pass.js +70 -0
  143. package/dist/render/shadowmap_pass.js.map +1 -0
  144. package/dist/render/sky.js +881 -0
  145. package/dist/render/sky.js.map +1 -0
  146. package/dist/render/temporalcache.js +222 -0
  147. package/dist/render/temporalcache.js.map +1 -0
  148. package/dist/render/watermesh.js +835 -0
  149. package/dist/render/watermesh.js.map +1 -0
  150. package/dist/scene/environment.js +146 -0
  151. package/dist/scene/environment.js.map +1 -0
  152. package/dist/scene/graph_node.js +69 -0
  153. package/dist/scene/graph_node.js.map +1 -0
  154. package/dist/scene/light.js +436 -0
  155. package/dist/scene/light.js.map +1 -0
  156. package/dist/scene/mesh.js +215 -0
  157. package/dist/scene/mesh.js.map +1 -0
  158. package/dist/scene/model.js +111 -0
  159. package/dist/scene/model.js.map +1 -0
  160. package/dist/scene/octree.js +651 -0
  161. package/dist/scene/octree.js.map +1 -0
  162. package/dist/scene/octree_update_visitor.js +16 -0
  163. package/dist/scene/octree_update_visitor.js.map +1 -0
  164. package/dist/scene/raycast_visitor.js +72 -0
  165. package/dist/scene/raycast_visitor.js.map +1 -0
  166. package/dist/scene/scene.js +225 -0
  167. package/dist/scene/scene.js.map +1 -0
  168. package/dist/scene/scene_node.js +299 -0
  169. package/dist/scene/scene_node.js.map +1 -0
  170. package/dist/scene/terrain/grass.js +277 -0
  171. package/dist/scene/terrain/grass.js.map +1 -0
  172. package/dist/scene/terrain/heightfield.js +391 -0
  173. package/dist/scene/terrain/heightfield.js.map +1 -0
  174. package/dist/scene/terrain/patch.js +530 -0
  175. package/dist/scene/terrain/patch.js.map +1 -0
  176. package/dist/scene/terrain/quadtree.js +430 -0
  177. package/dist/scene/terrain/quadtree.js.map +1 -0
  178. package/dist/scene/terrain/terrain.js +258 -0
  179. package/dist/scene/terrain/terrain.js.map +1 -0
  180. package/dist/scene/xform.js +224 -0
  181. package/dist/scene/xform.js.map +1 -0
  182. package/dist/shaders/builtins.js +110 -0
  183. package/dist/shaders/builtins.js.map +1 -0
  184. package/dist/shaders/framework.js +709 -0
  185. package/dist/shaders/framework.js.map +1 -0
  186. package/dist/shaders/lighting.js +335 -0
  187. package/dist/shaders/lighting.js.map +1 -0
  188. package/dist/shaders/misc.js +405 -0
  189. package/dist/shaders/misc.js.map +1 -0
  190. package/dist/shaders/noise.js +157 -0
  191. package/dist/shaders/noise.js.map +1 -0
  192. package/dist/shaders/pbr.js +132 -0
  193. package/dist/shaders/pbr.js.map +1 -0
  194. package/dist/shaders/shadow.js +642 -0
  195. package/dist/shaders/shadow.js.map +1 -0
  196. package/dist/shaders/water.js +630 -0
  197. package/dist/shaders/water.js.map +1 -0
  198. package/dist/shadow/esm.js +235 -0
  199. package/dist/shadow/esm.js.map +1 -0
  200. package/dist/shadow/pcf_opt.js +182 -0
  201. package/dist/shadow/pcf_opt.js.map +1 -0
  202. package/dist/shadow/pcf_pd.js +190 -0
  203. package/dist/shadow/pcf_pd.js.map +1 -0
  204. package/dist/shadow/shadow_impl.js +15 -0
  205. package/dist/shadow/shadow_impl.js.map +1 -0
  206. package/dist/shadow/shadowmapper.js +709 -0
  207. package/dist/shadow/shadowmapper.js.map +1 -0
  208. package/dist/shadow/ssm.js +194 -0
  209. package/dist/shadow/ssm.js.map +1 -0
  210. package/dist/shadow/vsm.js +298 -0
  211. package/dist/shadow/vsm.js.map +1 -0
  212. package/dist/shapes/box.js +313 -0
  213. package/dist/shapes/box.js.map +1 -0
  214. package/dist/shapes/cylinder.js +74 -0
  215. package/dist/shapes/cylinder.js.map +1 -0
  216. package/dist/shapes/plane.js +48 -0
  217. package/dist/shapes/plane.js.map +1 -0
  218. package/dist/shapes/shape.js +33 -0
  219. package/dist/shapes/shape.js.map +1 -0
  220. package/dist/shapes/sphere.js +91 -0
  221. package/dist/shapes/sphere.js.map +1 -0
  222. package/dist/shapes/torus.js +100 -0
  223. package/dist/shapes/torus.js.map +1 -0
  224. package/dist/utility/aabbtree.js +390 -0
  225. package/dist/utility/aabbtree.js.map +1 -0
  226. package/dist/utility/bounding_volume.js +78 -0
  227. package/dist/utility/bounding_volume.js.map +1 -0
  228. package/dist/utility/panorama.js +163 -0
  229. package/dist/utility/panorama.js.map +1 -0
  230. package/dist/utility/pmrem.js +345 -0
  231. package/dist/utility/pmrem.js.map +1 -0
  232. package/dist/utility/shprojection.js +448 -0
  233. package/dist/utility/shprojection.js.map +1 -0
  234. package/dist/values.js +48 -0
  235. package/dist/values.js.map +1 -0
  236. package/package.json +70 -0
@@ -0,0 +1,651 @@
1
+ import { AABB, Vector3 } from '@zephyr3d/base';
2
+ import { GraphNode } from './graph_node.js';
3
+
4
+ var OctreePlacement;
5
+ (function(OctreePlacement) {
6
+ OctreePlacement[OctreePlacement["PPP"] = 0] = "PPP";
7
+ OctreePlacement[OctreePlacement["PPN"] = 1] = "PPN";
8
+ OctreePlacement[OctreePlacement["PNP"] = 2] = "PNP";
9
+ OctreePlacement[OctreePlacement["PNN"] = 3] = "PNN";
10
+ OctreePlacement[OctreePlacement["NPP"] = 4] = "NPP";
11
+ OctreePlacement[OctreePlacement["NPN"] = 5] = "NPN";
12
+ OctreePlacement[OctreePlacement["NNP"] = 6] = "NNP";
13
+ OctreePlacement[OctreePlacement["NNN"] = 7] = "NNN";
14
+ })(OctreePlacement || (OctreePlacement = {}));
15
+ /**
16
+ * Octree node
17
+ * @public
18
+ */ class OctreeNode {
19
+ /** @internal */ _chunk;
20
+ /** @internal */ _position;
21
+ /** @internal */ _references;
22
+ /** @internal */ _nodes;
23
+ /** @internal */ _box;
24
+ /** @internal */ _boxLoosed;
25
+ /**
26
+ * Creates an instance of octree node
27
+ */ constructor(){
28
+ this._chunk = null;
29
+ this._position = 0;
30
+ this._references = 0;
31
+ this._nodes = [];
32
+ this._box = null;
33
+ this._boxLoosed = null;
34
+ }
35
+ /**
36
+ * Get all the scene nodes that this octree node contains
37
+ * @returns An array of the scene nodes
38
+ */ getNodes() {
39
+ return this._nodes;
40
+ }
41
+ /**
42
+ * Gets the level index of the octree node
43
+ * @returns The level index
44
+ */ getLevel() {
45
+ return this._chunk.getLevel();
46
+ }
47
+ /**
48
+ * Adds a scene node to this node
49
+ * @param node - The scene node to be added
50
+ */ addNode(node) {
51
+ if (node && this._nodes.indexOf(node) < 0) {
52
+ this._nodes.push(node);
53
+ }
54
+ }
55
+ /**
56
+ * Removes a scene node from this node
57
+ * @param node - The scene node to be removed
58
+ */ removeNode(node) {
59
+ const index = this._nodes.indexOf(node);
60
+ if (index >= 0) {
61
+ this._nodes.splice(index, 1);
62
+ }
63
+ }
64
+ /** Removes all the scene nodes that this octree node contains */ clearNodes() {
65
+ this._nodes = [];
66
+ }
67
+ /**
68
+ * Sets the octree chunk
69
+ * @param chunk - The octree chunk to be set
70
+ */ setChunk(chunk) {
71
+ console.assert(!!chunk, 'Invalid chunk');
72
+ this._chunk = chunk;
73
+ }
74
+ /**
75
+ * Gets the octree chunk
76
+ * @returns The octree chunk
77
+ */ getChunk() {
78
+ return this._chunk;
79
+ }
80
+ /**
81
+ * Sets the position of the node
82
+ * @param index - Position of the node
83
+ */ setPosition(index) {
84
+ this._position = index;
85
+ }
86
+ /**
87
+ * Gets the position of the octree node
88
+ * @returns Position of the octree node
89
+ */ getPosition() {
90
+ return this._position;
91
+ }
92
+ /**
93
+ * Invalidates the cached box
94
+ */ invalidateBox() {
95
+ this._box = null;
96
+ this.getParent()?.invalidateBox();
97
+ }
98
+ /**
99
+ * Get the bounding box of the octree node
100
+ * @returns The bounding box of the octree node
101
+ */ getBox() {
102
+ if (this._box === null) {
103
+ const box = new AABB();
104
+ box.beginExtend();
105
+ for(let i = 0; i < 8; i++){
106
+ const child = this.getChild(i);
107
+ if (child) {
108
+ const childBox = child.getBox();
109
+ if (childBox) {
110
+ box.extend(childBox.minPoint);
111
+ box.extend(childBox.maxPoint);
112
+ }
113
+ }
114
+ }
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
+ if (box.isValid()) {
125
+ this._box = box;
126
+ }
127
+ }
128
+ return this._box;
129
+ }
130
+ /**
131
+ * Gets the loosed bounding box of the node
132
+ * @returns The loosed bounding box of the node
133
+ */ getBoxLoosed() {
134
+ if (this._boxLoosed === null) {
135
+ console.assert(!!this._chunk, 'Invalid chunk');
136
+ const d = this._chunk.getDimension();
137
+ const nodeSize = this._chunk.getNodeSize();
138
+ const halfWorldSize = this._chunk.getWorldSize() * 0.5;
139
+ const px = this._position % d;
140
+ const py = Math.floor(this._position / d) % d;
141
+ const pz = Math.floor(Math.floor(this._position / d) / d);
142
+ const minPoint = new Vector3(px - 0.5, py - 0.5, pz - 0.5).scaleBy(nodeSize).subBy(new Vector3(halfWorldSize, halfWorldSize, halfWorldSize));
143
+ const maxPoint = new Vector3(minPoint.x + nodeSize * 2, minPoint.y + nodeSize * 2, minPoint.z + nodeSize * 2);
144
+ this._boxLoosed = new AABB(minPoint, maxPoint);
145
+ }
146
+ return this._boxLoosed;
147
+ }
148
+ /**
149
+ * Gets min point of the node
150
+ * @returns Min point of the node
151
+ */ getMinPoint() {
152
+ console.assert(!!this._chunk, 'Invalid chunk');
153
+ const d = this._chunk.getDimension();
154
+ const nodeSize = this._chunk.getNodeSize();
155
+ const halfWorldSize = this._chunk.getWorldSize() * 0.5;
156
+ const px = this._position % d;
157
+ const py = Math.floor(this._position / d) % d;
158
+ const pz = Math.floor(Math.floor(this._position / d) / d);
159
+ return new Vector3(px, py, pz).scaleBy(nodeSize).subBy(new Vector3(halfWorldSize, halfWorldSize, halfWorldSize));
160
+ }
161
+ /**
162
+ * Gets max point of the node
163
+ * @returns Max point of the node
164
+ */ getMaxPoint() {
165
+ console.assert(!!this._chunk, 'Invalid chunk');
166
+ const d = this._chunk.getDimension();
167
+ const nodeSize = this._chunk.getNodeSize();
168
+ const halfWorldSize = this._chunk.getWorldSize() * 0.5;
169
+ const px = this._position % d + 1;
170
+ const py = Math.floor(this._position / d) % d + 1;
171
+ const pz = Math.floor(Math.floor(this._position / d) / d) + 1;
172
+ return new Vector3(px, py, pz).scaleBy(nodeSize).subBy(new Vector3(halfWorldSize, halfWorldSize, halfWorldSize));
173
+ }
174
+ /**
175
+ * Gets the loosed min point of the node
176
+ * @returns Loosed min point of the node
177
+ */ getMinPointLoosed() {
178
+ const halfNodeSize = this._chunk.getNodeSize() * 0.5;
179
+ return this.getMinPoint().subBy(new Vector3(halfNodeSize, halfNodeSize, halfNodeSize));
180
+ }
181
+ /**
182
+ * Gets the loosed max point of the node
183
+ * @returns Loosed max point of the node
184
+ */ getMaxPointLoosed() {
185
+ const halfNodeSize = this._chunk.getNodeSize() * 0.5;
186
+ return this.getMaxPoint().addBy(new Vector3(halfNodeSize, halfNodeSize, halfNodeSize));
187
+ }
188
+ /**
189
+ * Get reference of the node
190
+ * @returns Reference of the node
191
+ */ getReference() {
192
+ return this._references;
193
+ }
194
+ /**
195
+ * Gets the child node by a given placement
196
+ * @param placement - The placement
197
+ * @returns Child node at the given placement
198
+ */ getChild(placement) {
199
+ console.assert(!!this._chunk, 'Invalid chunk');
200
+ const next = this._chunk.getNext();
201
+ return next ? next.getNode(this._chunk.getChildIndex(this._position, placement)) : null;
202
+ }
203
+ /**
204
+ * Gets or creates a child node by a given placement
205
+ * @param placement - The placement
206
+ * @returns The child node fetched
207
+ */ getOrCreateChild(placement) {
208
+ console.assert(!!this._chunk, 'Invalid chunk');
209
+ const next = this._chunk.getNext();
210
+ return next ? next.getOrCreateNode(this._chunk.getChildIndex(this._position, placement)) : null;
211
+ }
212
+ /**
213
+ * Gets parent of the node
214
+ * @returns Parent of the node
215
+ */ getParent() {
216
+ console.assert(!!this._chunk, 'Invalid chunk');
217
+ const prev = this._chunk.getPrev();
218
+ return prev ? prev.getNode(this._chunk.getParentIndex(this._position)) : null;
219
+ }
220
+ /**
221
+ * Gets or creates the parent node
222
+ * @returns The parent node
223
+ */ getOrCreateParent() {
224
+ console.assert(!!this._chunk, 'Invalid chunk');
225
+ const prev = this._chunk.getPrev();
226
+ return prev ? prev.getOrCreateNode(this._chunk.getParentIndex(this._position)) : null;
227
+ }
228
+ /**
229
+ * Creates all children of this node
230
+ */ createChildren() {
231
+ this.getOrCreateChild(OctreePlacement.PPP);
232
+ this.getOrCreateChild(OctreePlacement.PPN);
233
+ this.getOrCreateChild(OctreePlacement.PNP);
234
+ this.getOrCreateChild(OctreePlacement.PNN);
235
+ this.getOrCreateChild(OctreePlacement.NPP);
236
+ this.getOrCreateChild(OctreePlacement.NPN);
237
+ this.getOrCreateChild(OctreePlacement.NNP);
238
+ this.getOrCreateChild(OctreePlacement.NNN);
239
+ }
240
+ /**
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
+ * Traverse this node by a visitor
259
+ * @param v - The visitor
260
+ */ traverse(v) {
261
+ if (v.visit(this)) {
262
+ for(let i = 0; i < 8; i++){
263
+ const child = this.getChild(i);
264
+ if (child) {
265
+ child.traverse(v);
266
+ }
267
+ }
268
+ }
269
+ }
270
+ }
271
+ /**
272
+ * Octree node chunk
273
+ * @public
274
+ */ class OctreeNodeChunk {
275
+ /** @internal */ _level;
276
+ /** @internal */ _dimension;
277
+ /** @internal */ _nodeSize;
278
+ /** @internal */ _prev;
279
+ /** @internal */ _next;
280
+ /** @internal */ _octree;
281
+ /** @internal */ _nodeMap;
282
+ /**
283
+ * Creates an instance of octree chunk
284
+ * @param octree - Octree to which the chunk belongs
285
+ */ constructor(octree){
286
+ this._octree = octree;
287
+ this._level = 0;
288
+ this._dimension = 0;
289
+ this._nodeSize = 0;
290
+ this._next = null;
291
+ this._prev = null;
292
+ this._nodeMap = new Map();
293
+ }
294
+ /**
295
+ * Gets an octree node at a given index
296
+ * @param index - Index of the node
297
+ * @returns The octree node
298
+ */ getNode(index) {
299
+ return this._nodeMap.get(index) || null;
300
+ }
301
+ /**
302
+ * Gets or creates an octree node at a given index
303
+ * @param index - Index of the node
304
+ * @returns The octree node
305
+ */ getOrCreateNode(index) {
306
+ let node = this.getNode(index);
307
+ if (!node) {
308
+ node = new OctreeNode();
309
+ node.setChunk(this);
310
+ node.setPosition(index);
311
+ this._nodeMap.set(index, node);
312
+ }
313
+ return node;
314
+ }
315
+ /**
316
+ * Gets or creates an octree node chain at a given index
317
+ * @param index - Index of the head node
318
+ * @returns The head node of the chain
319
+ */ getOrCreateNodeChain(index) {
320
+ const node = this.getOrCreateNode(index);
321
+ if (this._prev) {
322
+ this._prev.getOrCreateNodeChain(this.getParentIndex(index));
323
+ }
324
+ return node;
325
+ }
326
+ /**
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
+ * Removes all octree nodes of this chunk
347
+ */ clearNodes() {
348
+ for (const key of this._nodeMap.keys()){
349
+ this._nodeMap.get(key).clearNodes();
350
+ this._nodeMap.delete(key);
351
+ }
352
+ }
353
+ /**
354
+ * Gets the index of a child node at given placement
355
+ * @param index - Index of the parent node
356
+ * @param placement - The placement
357
+ * @returns Index of the child
358
+ */ getChildIndex(index, placement) {
359
+ const dim = this._dimension;
360
+ let px = 2 * (index % dim);
361
+ let py = 2 * (Math.floor(index / dim) % dim);
362
+ let pz = 2 * Math.floor(Math.floor(index / dim) / dim);
363
+ switch(placement){
364
+ case OctreePlacement.PPP:
365
+ ++px;
366
+ ++py;
367
+ ++pz;
368
+ break;
369
+ case OctreePlacement.PPN:
370
+ ++px;
371
+ ++py;
372
+ break;
373
+ case OctreePlacement.PNP:
374
+ ++px;
375
+ ++pz;
376
+ break;
377
+ case OctreePlacement.PNN:
378
+ ++px;
379
+ break;
380
+ case OctreePlacement.NPP:
381
+ ++py;
382
+ ++pz;
383
+ break;
384
+ case OctreePlacement.NPN:
385
+ ++py;
386
+ break;
387
+ case OctreePlacement.NNP:
388
+ ++pz;
389
+ break;
390
+ case OctreePlacement.NNN:
391
+ break;
392
+ default:
393
+ console.assert(false, 'getChildIndex: Got invalid index');
394
+ return 0;
395
+ }
396
+ const dimension2 = 2 * dim;
397
+ return pz * dimension2 * dimension2 + py * dimension2 + px;
398
+ }
399
+ /**
400
+ * Gets the index of the parent node
401
+ * @param index - Index of the child node
402
+ * @returns Index of the parent node
403
+ */ getParentIndex(index) {
404
+ const dim = this._dimension;
405
+ const px = index % dim >> 1;
406
+ const py = Math.floor(index / dim) % dim >> 1;
407
+ const pz = Math.floor(Math.floor(index / dim) / dim) >> 1;
408
+ const d = dim >> 1;
409
+ return px + py * d + pz * d * d;
410
+ }
411
+ /**
412
+ * Gets the size of the node in this chunk
413
+ * @returns The size of the node in this chunk
414
+ */ getNodeSize() {
415
+ return this._nodeSize;
416
+ }
417
+ /**
418
+ * Gets the root size of the octree
419
+ * @returns The root size of the octree
420
+ */ getWorldSize() {
421
+ return this._octree.getRootSize();
422
+ }
423
+ /**
424
+ * Gets the dimension of this chunk
425
+ * @returns Dimension of this chunk
426
+ */ getDimension() {
427
+ return this._dimension;
428
+ }
429
+ /**
430
+ * Gets the level index of this chunk
431
+ * @returns Level index of this chunk
432
+ */ getLevel() {
433
+ return this._level;
434
+ }
435
+ /**
436
+ * Check if this chunk is empty
437
+ * @returns true if this chunk is empty, otherwise false
438
+ */ empty() {
439
+ return this._nodeMap.size === 0;
440
+ }
441
+ /**
442
+ * Gets the chunk next to this chunk
443
+ * @returns The next chunk
444
+ */ getNext() {
445
+ return this._next;
446
+ }
447
+ /**
448
+ * Gets the chunk previous to this chunk
449
+ * @returns The previous chunk
450
+ */ getPrev() {
451
+ return this._prev;
452
+ }
453
+ /**
454
+ * Gets the octree that the chunk belongs to
455
+ * @returns The octree
456
+ */ getOctree() {
457
+ return this._octree;
458
+ }
459
+ /**
460
+ * Sets the level index of this chunk
461
+ * @param level - The level index to set
462
+ */ setLevel(level) {
463
+ this._level = level;
464
+ }
465
+ /**
466
+ * Sets the dimension of this chunk
467
+ * @param dimension - The dimension to set
468
+ */ setDimension(dimension) {
469
+ this._dimension = dimension;
470
+ }
471
+ /**
472
+ * Sets the size of octree node in this chunk
473
+ * @param size - The node size to set
474
+ */ setNodeSize(size) {
475
+ this._nodeSize = size;
476
+ }
477
+ /**
478
+ * Sets the next chunk
479
+ * @param chunk - The chunk to set
480
+ */ setNext(chunk) {
481
+ this._next = chunk;
482
+ }
483
+ /**
484
+ * Sets the previous chunk
485
+ * @param chunk - The chunk to set
486
+ */ setPrev(chunk) {
487
+ this._prev = chunk;
488
+ }
489
+ }
490
+ /**
491
+ * Octree class
492
+ * @public
493
+ */ class Octree {
494
+ /** @internal */ _scene;
495
+ /** @internal */ _chunks;
496
+ /** @internal */ _rootSize;
497
+ /** @internal */ _leafSize;
498
+ /** @internal */ _rootNode;
499
+ /** @internal */ _nodeMap;
500
+ /**
501
+ * Creates an instance of octree
502
+ * @param scene - The scene to which the octree belongs
503
+ * @param rootSize - Root size of the octre
504
+ * @param leafSize - Leaf size of the octree
505
+ */ constructor(scene, rootSize = 4096, leafSize = 64){
506
+ this._scene = scene;
507
+ this._chunks = [];
508
+ this._rootSize = 0;
509
+ this._leafSize = 0;
510
+ this._rootNode = null;
511
+ this._nodeMap = new WeakMap();
512
+ this.initialize(rootSize, leafSize);
513
+ }
514
+ /**
515
+ * Initialize the octree with specified root size and leaf size
516
+ * @param rootSize - Root size of the octree
517
+ * @param leafSize - Leaf size of the octree
518
+ */ initialize(rootSize, leafSize) {
519
+ console.assert(rootSize >= leafSize && leafSize > 0, 'Invalid rootSize or leafSize for octree');
520
+ this.finalize();
521
+ this._rootSize = rootSize;
522
+ this._leafSize = leafSize;
523
+ let n = 1;
524
+ for(; rootSize >= leafSize * 2; leafSize *= 2, ++n);
525
+ for(let i = 0; i < n; ++i, rootSize *= 0.5){
526
+ const chunk = new OctreeNodeChunk(this);
527
+ chunk.setLevel(i);
528
+ chunk.setNodeSize(rootSize);
529
+ chunk.setDimension(1 << i);
530
+ this._chunks.push(chunk);
531
+ if (i > 0) {
532
+ this._chunks[i - 1].setNext(chunk);
533
+ chunk.setPrev(this._chunks[i - 1]);
534
+ }
535
+ }
536
+ }
537
+ /** Free up the octree */ finalize() {
538
+ this._chunks = [];
539
+ this._rootSize = 0;
540
+ this._leafSize = 0;
541
+ this._rootNode = null;
542
+ this._nodeMap = new WeakMap();
543
+ }
544
+ /**
545
+ * Gets the scene to which the octree belongs
546
+ * @returns The scene
547
+ */ getScene() {
548
+ return this._scene;
549
+ }
550
+ /**
551
+ * Gets the root size of the octree
552
+ * @returns The root size of the octree
553
+ */ getRootSize() {
554
+ return this._rootSize;
555
+ }
556
+ /**
557
+ * Gets the leaf size of the octree
558
+ * @returns The leaf size of the octree
559
+ */ getLeafSize() {
560
+ return this._leafSize;
561
+ }
562
+ /**
563
+ * Locates a node chain in the octree by a sphere
564
+ * @param candidate - The candidate node
565
+ * @param center - center of the sphere
566
+ * @param radius - radius of the sphere
567
+ * @returns Head node of the located node chain
568
+ */ locateNodeChain(candidate, center, radius) {
569
+ let level = this._chunks.length - 1;
570
+ while(level && this._chunks[level].getNodeSize() < 4 * radius){
571
+ --level;
572
+ }
573
+ const dim = this._chunks[level].getDimension();
574
+ const inv_node_size = 1 / this._chunks[level].getNodeSize();
575
+ let px = Math.floor((center.x + this._rootSize * 0.5) * inv_node_size);
576
+ let py = Math.floor((center.y + this._rootSize * 0.5) * inv_node_size);
577
+ let pz = Math.floor((center.z + this._rootSize * 0.5) * inv_node_size);
578
+ if (px >= dim || py >= dim || pz >= dim) {
579
+ level = 0;
580
+ px = 0;
581
+ py = 0;
582
+ pz = 0;
583
+ }
584
+ const index = px + py * dim + pz * dim * dim;
585
+ if (candidate && candidate.getChunk().getLevel() === level && candidate.getPosition() === index) {
586
+ return candidate;
587
+ }
588
+ return this._chunks[level].getOrCreateNodeChain(index);
589
+ }
590
+ /**
591
+ * Gets the root node of the octree
592
+ * @returns Root node of the octree
593
+ */ getRootNode() {
594
+ if (!this._rootNode) {
595
+ this._rootNode = this._chunks[0].getOrCreateNode(0);
596
+ }
597
+ return this._rootNode;
598
+ }
599
+ /**
600
+ * Gets the number of chunks in the octree
601
+ * @returns The number of chunks in the octree
602
+ */ getNumChunks() {
603
+ return this._chunks.length;
604
+ }
605
+ /**
606
+ * Gets the chunk by a given index
607
+ * @param level - The chunk index
608
+ * @returns The chunk at given index
609
+ */ getChunk(level) {
610
+ return this._chunks[level];
611
+ }
612
+ /**
613
+ * Place a scene node into the octree
614
+ * @param node - The scene node to be placed
615
+ */ placeNode(node) {
616
+ const curNode = this._nodeMap.get(node) || null;
617
+ let locatedNode = this.getRootNode();
618
+ if (node.computedClipMode === GraphNode.CLIP_ENABLED) {
619
+ const bbox = node.getWorldBoundingVolume()?.toAABB();
620
+ if (bbox && bbox.isValid()) {
621
+ const center = bbox.center;
622
+ const extents = bbox.extents;
623
+ const size = Math.max(Math.max(extents.x, extents.y), extents.z);
624
+ locatedNode = this.locateNodeChain(curNode, center, size) || this.getRootNode();
625
+ }
626
+ }
627
+ if (curNode !== locatedNode) {
628
+ curNode?.removeNode(node);
629
+ locatedNode?.addNode(node);
630
+ this._nodeMap.set(node, locatedNode);
631
+ curNode?.invalidateBox();
632
+ locatedNode?.invalidateBox();
633
+ }
634
+ }
635
+ /**
636
+ * Removes a scene node from the octree
637
+ * @param node - The scene node to be removed
638
+ */ removeNode(node) {
639
+ if (node.isGraphNode()) {
640
+ const curNode = this._nodeMap.get(node) || null;
641
+ if (curNode) {
642
+ curNode.removeNode(node);
643
+ curNode.invalidateBox();
644
+ this._nodeMap.delete(node);
645
+ }
646
+ }
647
+ }
648
+ }
649
+
650
+ export { Octree, OctreeNode, OctreeNodeChunk, OctreePlacement };
651
+ //# sourceMappingURL=octree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"octree.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,16 @@
1
+ import { GraphNode } from './graph_node.js';
2
+
3
+ /** @internal */ class OctreeUpdateVisitor {
4
+ /** @internal */ _octree;
5
+ constructor(octree){
6
+ this._octree = octree;
7
+ }
8
+ visit(node) {
9
+ if (node instanceof GraphNode) {
10
+ this._octree.placeNode(node);
11
+ }
12
+ }
13
+ }
14
+
15
+ export { OctreeUpdateVisitor };
16
+ //# sourceMappingURL=octree_update_visitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"octree_update_visitor.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;"}