@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,277 @@
1
+ import { nextPowerOf2, Vector2 } from '@zephyr3d/base';
2
+ import { Primitive } from '../../render/primitive.js';
3
+ import '../../material/material.js';
4
+ import '@zephyr3d/device';
5
+ import '../../shaders/framework.js';
6
+ import { Application } from '../../app.js';
7
+ import '../../render/scatteringlut.js';
8
+ import '../../material/lambert.js';
9
+ import '../../material/blinn.js';
10
+ import '../../material/unlit.js';
11
+ import '../../material/lightmodel.js';
12
+ import { GrassMaterial } from '../../material/grassmaterial.js';
13
+
14
+ class GrassCluster {
15
+ _primitive;
16
+ _terrain;
17
+ _numInstances;
18
+ _material;
19
+ constructor(device, terrain, baseVertexBuffer, indexBuffer, material, grassData){
20
+ this._primitive = new Primitive();
21
+ const instanceVertexBuffer = device.createVertexBuffer('tex1_f32x4', grassData);
22
+ this._primitive.setVertexBuffer(baseVertexBuffer, 'vertex');
23
+ this._primitive.setVertexBuffer(instanceVertexBuffer, 'instance');
24
+ this._primitive.setIndexBuffer(indexBuffer);
25
+ this._primitive.primitiveType = 'triangle-list';
26
+ this._terrain = terrain;
27
+ this._numInstances = grassData.length >> 2;
28
+ this._material = material;
29
+ this._material.stateSet.useRasterizerState().setCullMode('none');
30
+ }
31
+ getName() {
32
+ return 'GrassCluster';
33
+ }
34
+ getXForm() {
35
+ return this._terrain;
36
+ }
37
+ getInstanceColor() {
38
+ return this._terrain.getInstanceColor();
39
+ }
40
+ getPickTarget() {
41
+ return this._terrain;
42
+ }
43
+ getBoneMatrices() {
44
+ return null;
45
+ }
46
+ getInvBindMatrix() {
47
+ return null;
48
+ }
49
+ getSortDistance(camera) {
50
+ return this._terrain.getSortDistance(camera);
51
+ }
52
+ isTransparency() {
53
+ return this._terrain.grassMaterial.isTransparent();
54
+ }
55
+ isUnlit() {
56
+ return !this._terrain.grassMaterial.supportLighting();
57
+ }
58
+ isBatchable() {
59
+ return false;
60
+ }
61
+ draw(ctx) {
62
+ this._material.alphaToCoverage = Application.instance.device.getFrameBufferSampleCount() > 1;
63
+ if (this._material.beginDraw(ctx)) {
64
+ this._primitive.drawInstanced(this._numInstances);
65
+ this._terrain.grassMaterial.endDraw();
66
+ }
67
+ }
68
+ }
69
+ class GrassManager {
70
+ _clusterSize;
71
+ _baseVertexBuffer;
72
+ _indexBuffer;
73
+ _layers;
74
+ constructor(clusterSize, density){
75
+ this._clusterSize = clusterSize;
76
+ this._baseVertexBuffer = new Map();
77
+ this._indexBuffer = null;
78
+ this._layers = [];
79
+ }
80
+ getBaseVertexBuffer(device, bladeWidth, bladeHeight) {
81
+ const hash = `${bladeWidth}-${bladeHeight}`;
82
+ let baseVertexBuffer = this._baseVertexBuffer.get(hash);
83
+ if (baseVertexBuffer) {
84
+ return baseVertexBuffer;
85
+ }
86
+ const r = bladeWidth * 0.5;
87
+ const t = bladeHeight;
88
+ const c = r * Math.cos(Math.PI / 3);
89
+ const s = r * Math.sin(Math.PI / 3);
90
+ const vertices = new Float32Array([
91
+ r,
92
+ 0,
93
+ 0,
94
+ 0,
95
+ 1,
96
+ r,
97
+ t,
98
+ 0,
99
+ 0,
100
+ 0,
101
+ -r,
102
+ t,
103
+ 0,
104
+ 1,
105
+ 0,
106
+ -r,
107
+ 0,
108
+ 0,
109
+ 1,
110
+ 1,
111
+ c,
112
+ 0,
113
+ s,
114
+ 0,
115
+ 1,
116
+ -c,
117
+ 0,
118
+ -s,
119
+ 1,
120
+ 1,
121
+ -c,
122
+ t,
123
+ -s,
124
+ 1,
125
+ 0,
126
+ c,
127
+ t,
128
+ s,
129
+ 0,
130
+ 0,
131
+ -c,
132
+ 0,
133
+ s,
134
+ 0,
135
+ 1,
136
+ c,
137
+ 0,
138
+ -s,
139
+ 1,
140
+ 1,
141
+ c,
142
+ t,
143
+ -s,
144
+ 1,
145
+ 0,
146
+ -c,
147
+ t,
148
+ s,
149
+ 0,
150
+ 0
151
+ ]);
152
+ baseVertexBuffer = device.createInterleavedVertexBuffer([
153
+ 'position_f32x3',
154
+ 'tex0_f32x2'
155
+ ], vertices);
156
+ this._baseVertexBuffer.set(hash, baseVertexBuffer);
157
+ return baseVertexBuffer;
158
+ }
159
+ getIndexBuffer(device) {
160
+ if (!this._indexBuffer) {
161
+ this._indexBuffer = device.createIndexBuffer(new Uint16Array([
162
+ 0,
163
+ 1,
164
+ 2,
165
+ 0,
166
+ 2,
167
+ 3,
168
+ 4,
169
+ 5,
170
+ 6,
171
+ 4,
172
+ 6,
173
+ 7,
174
+ 8,
175
+ 9,
176
+ 10,
177
+ 8,
178
+ 10,
179
+ 11
180
+ ]));
181
+ }
182
+ return this._indexBuffer;
183
+ }
184
+ addGrassLayer(device, terrain, density, bladeWidth, bladeHeigh, offset, grassTexture) {
185
+ const densityHeight = density.length;
186
+ const densityWidth = density[0].length;
187
+ const hfScale = terrain.heightFieldScale;
188
+ this._clusterSize = Math.min(nextPowerOf2(this._clusterSize), terrain.width - 1, terrain.height - 1);
189
+ let layer = null;
190
+ terrain.traverseQuadtree((node)=>{
191
+ const size = node.getPatch().getStep() * (terrain.patchSize - 1);
192
+ if (size === this._clusterSize) {
193
+ const bbox = node.getPatch().getBoundingBox();
194
+ const grassData = [];
195
+ const minX = bbox.minPoint.x;
196
+ const minZ = bbox.minPoint.z;
197
+ let index = 0;
198
+ for(let i = 0; i < this._clusterSize; i++){
199
+ for(let j = 0; j < this._clusterSize; j++){
200
+ const x0 = minX + j * hfScale.x;
201
+ const z0 = minZ + i * hfScale.z;
202
+ const x1 = x0 + hfScale.x;
203
+ const z1 = z0 + hfScale.z;
204
+ const u = x0 / terrain.scaledWidth;
205
+ const v = z0 / terrain.scaledHeight;
206
+ const du = densityWidth * u >> 0;
207
+ const dv = densityHeight * v >> 0;
208
+ const val = density[dv][du] * hfScale.x * hfScale.z;
209
+ let grassCount = 0;
210
+ if (val > 0) {
211
+ if (val < 1) {
212
+ grassCount = Math.random() <= val ? 1 : 0;
213
+ } else {
214
+ grassCount = val >> 0;
215
+ }
216
+ }
217
+ //const grassCount = (this._density[dv][du] * hfScale.x * hfScale.z) >> 0;
218
+ for(let k = 0; k < grassCount; k++){
219
+ const x = Math.random() * (x1 - x0) + x0;
220
+ const z = Math.random() * (z1 - z0) + z0;
221
+ const y = terrain.getElevation(x, z);
222
+ const rot = Math.random() * Math.PI * 2;
223
+ grassData[index++] = x;
224
+ grassData[index++] = y + offset;
225
+ grassData[index++] = z;
226
+ grassData[index++] = rot;
227
+ }
228
+ }
229
+ }
230
+ if (grassData.length > 0) {
231
+ if (!layer) {
232
+ layer = {
233
+ material: new GrassMaterial(new Vector2(terrain.scaledWidth, terrain.scaledHeight), terrain.quadtree.normalMap, grassTexture),
234
+ clusters: new Map()
235
+ };
236
+ this._layers.push(layer);
237
+ }
238
+ const cluster = new GrassCluster(device, terrain, this.getBaseVertexBuffer(device, bladeWidth, bladeHeigh), this.getIndexBuffer(device), layer.material, new Float32Array(grassData));
239
+ layer.clusters.set(node, cluster);
240
+ //const cluster = new GrassCluster(device, terrain, this.getBaseVertexBuffer(device, bladeWidth, bladeHeigh), this.getIndexBuffer(device), grassTexture, new Float32Array(grassData));
241
+ node.grassClusters.push(cluster);
242
+ }
243
+ }
244
+ });
245
+ return layer;
246
+ }
247
+ } /*
248
+ function interpolate(val: number, oldMin: number, oldMax: number, newMin: number, newMax: number) {
249
+ return ((val - oldMin) * (newMax - newMin)) / (oldMax - oldMin) + newMin
250
+ }
251
+
252
+ function createGrassBladePrimitive(device: AbstractDevice) {
253
+ const p = new Primitive();
254
+ const positions: number[] = [];
255
+ const uvs: number[] = [];
256
+ const indices: number[] = [];
257
+ }
258
+
259
+ function getPrimitive(device: AbstractDevice): Primitive {
260
+ if (!primitive) {
261
+ primitive = new Primitive();
262
+ const vertices: number[] = [-0.1, 0, 0, 0.1, 0, 0, 0.1, 0.8, 0, -0.1, 0.8, 0];
263
+ const indices: number[] = [0, 1, 2, 0, 2, 3, 0, 2, 1, 0, 3, 2];
264
+ const vb = device.createInterleavedVertexBuffer(['position_f32x3', 'normal_f32x3', 'tex0_f32x2'], new Float32Array(vertices));
265
+ const ib = device.createIndexBuffer(new Uint16Array(indices));
266
+ primitive.setVertexBuffer(vb);
267
+ primitive.setIndexBuffer(ib)
268
+ primitive.indexStart = 0;
269
+ primitive.indexCount = indices.length;
270
+ primitive.primitiveType = 'triangle-list';
271
+ }
272
+ return primitive;
273
+ }
274
+ */
275
+
276
+ export { GrassCluster, GrassManager };
277
+ //# sourceMappingURL=grass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grass.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,391 @@
1
+ import { Vector3, Vector4 } from '@zephyr3d/base';
2
+ import { BoundingBox } from '../../utility/bounding_volume.js';
3
+
4
+ /** @internal */ class HeightfieldBBoxTree {
5
+ _resX;
6
+ _resY;
7
+ _spacingX;
8
+ _spacingZ;
9
+ _heights;
10
+ _rootNode;
11
+ constructor(res_x, res_y, spacing_x, spacing_z, vertices){
12
+ this._rootNode = null;
13
+ this._heights = null;
14
+ this._spacingX = spacing_x;
15
+ this._spacingZ = spacing_z;
16
+ this.create(res_x, res_y, vertices);
17
+ }
18
+ create(res_x, res_y, vertices) {
19
+ this._resX = res_x;
20
+ this._resY = res_y;
21
+ this._rootNode = this.allocNode();
22
+ this._heights = new Float32Array(res_x * res_y);
23
+ for(let i = 0; i < this._heights.length; i++){
24
+ this._heights[i] = vertices[i].y;
25
+ }
26
+ this.createChildNode(this._rootNode, 0, 0, res_x, res_y, vertices);
27
+ return true;
28
+ }
29
+ getHeight(x, y) {
30
+ return this._heights[(this._resY - 1 - y) * this._resX + x];
31
+ }
32
+ getNormal(x, y, normal) {
33
+ normal = normal ?? new Vector3();
34
+ x = Math.max(0, Math.min(x, this._resX - 2));
35
+ y = Math.max(0, Math.min(y, this._resY - 2));
36
+ const h00 = this._heights[x + y * this._resX];
37
+ const h01 = this._heights[x + (y + 1) * this._resX];
38
+ const h11 = this._heights[x + 1 + (y + 1) * this._resX];
39
+ const h10 = this._heights[x + 1 + y * this._resX];
40
+ const sx = (h00 + h01 - h11 - h10) * 0.5;
41
+ const sy = (h00 + h10 - h01 - h11) * 0.5;
42
+ const tileSizeX = (this._rootNode.bbox.maxPoint.x - this._rootNode.bbox.minPoint.x) / (this._resX - 1);
43
+ const tileSizeY = (this._rootNode.bbox.maxPoint.z - this._rootNode.bbox.minPoint.z) / (this._resY - 1);
44
+ normal.setXYZ(sx * tileSizeY, 2 * tileSizeX * tileSizeY, -sy * tileSizeX).inplaceNormalize();
45
+ return normal;
46
+ }
47
+ getRealNormal(x, y, normal) {
48
+ normal = normal ?? new Vector3();
49
+ x -= this._rootNode.bbox.minPoint.x;
50
+ y -= this._rootNode.bbox.minPoint.z;
51
+ const tileSizeX = (this._rootNode.bbox.maxPoint.x - this._rootNode.bbox.minPoint.x) / (this._resX - 1);
52
+ const tileSizeY = (this._rootNode.bbox.maxPoint.z - this._rootNode.bbox.minPoint.z) / (this._resY - 1);
53
+ const x_unscale = x / tileSizeX;
54
+ const y_unscale = y / tileSizeY;
55
+ let l = Math.floor(x_unscale);
56
+ let t = Math.floor(y_unscale);
57
+ let r = l + 1;
58
+ let b = t + 1;
59
+ if (l < 0) {
60
+ l = 0;
61
+ }
62
+ if (t < 0) {
63
+ t = 0;
64
+ }
65
+ if (r >= this._resX) {
66
+ r = this._resX - 1;
67
+ }
68
+ if (b >= this._resY) {
69
+ b = this._resY - 1;
70
+ }
71
+ const ltNormal = this.getNormal(l, t);
72
+ const lbNormal = this.getNormal(l, b);
73
+ const rtNormal = this.getNormal(r, t);
74
+ const rbNormal = this.getNormal(r, b);
75
+ ltNormal.addBy(lbNormal).addBy(rtNormal).addBy(rbNormal).scaleBy(0.25).inplaceNormalize();
76
+ normal.set(ltNormal);
77
+ return normal;
78
+ }
79
+ getRealHeight(x, y) {
80
+ x -= this._rootNode.bbox.minPoint.x;
81
+ y -= this._rootNode.bbox.minPoint.z;
82
+ const tileSizeX = (this._rootNode.bbox.maxPoint.x - this._rootNode.bbox.minPoint.x) / (this._resX - 1);
83
+ const tileSizeY = (this._rootNode.bbox.maxPoint.z - this._rootNode.bbox.minPoint.z) / (this._resY - 1);
84
+ const x_unscale = x / tileSizeX;
85
+ const y_unscale = y / tileSizeY;
86
+ const l = Math.floor(x_unscale);
87
+ const t = Math.floor(y_unscale);
88
+ const r = l + 1;
89
+ const b = t + 1;
90
+ if (l < 0 || t < 0 || r >= this._resX || b >= this._resY) {
91
+ return 0;
92
+ }
93
+ if (l === r) {
94
+ if (t === b) {
95
+ return this.getHeight(l, t);
96
+ } else {
97
+ const ht = this.getHeight(l, t);
98
+ const hb = this.getHeight(l, b);
99
+ return ht + (hb - ht) * (y_unscale - t);
100
+ }
101
+ } else {
102
+ const hlt = this.getHeight(l, t);
103
+ const hrt = this.getHeight(r, t);
104
+ const ht = hlt + (hrt - hlt) * (x_unscale - l);
105
+ if (t === b) {
106
+ return ht;
107
+ } else {
108
+ const hlb = this.getHeight(l, b);
109
+ const hrb = this.getHeight(r, b);
110
+ const hb = hlb + (hrb - hlb) * (x_unscale - l);
111
+ return ht + (hb - ht) * (y_unscale - t);
112
+ }
113
+ }
114
+ }
115
+ getRootNode() {
116
+ return this._rootNode;
117
+ }
118
+ getHeights() {
119
+ return this._heights;
120
+ }
121
+ allocNode() {
122
+ return {
123
+ bbox: new BoundingBox(),
124
+ h: [
125
+ 0,
126
+ 0,
127
+ 0,
128
+ 0
129
+ ],
130
+ rc: {
131
+ x: 0,
132
+ y: 0,
133
+ w: 0,
134
+ h: 0
135
+ },
136
+ left: null,
137
+ right: null
138
+ };
139
+ }
140
+ computeNodeBoundingBox(node, bbox, vertices) {
141
+ bbox.beginExtend();
142
+ for(let i = 0; i < node.rc.w; i++){
143
+ for(let j = 0; j < node.rc.h; j++){
144
+ const index = node.rc.x + i + (node.rc.y + j) * this._resX;
145
+ const vert = vertices[index];
146
+ bbox.extend3(vert.x, vert.y, vert.z);
147
+ }
148
+ }
149
+ }
150
+ createChildNode(node, x, y, w, h, vertices) {
151
+ node.rc.x = x;
152
+ node.rc.y = y;
153
+ node.rc.w = w;
154
+ node.rc.h = h;
155
+ if (w <= 2 && h <= 2) {
156
+ node.left = null;
157
+ node.right = null;
158
+ node.h[0] = this.getHeight(x, y);
159
+ node.h[1] = this.getHeight(x + 1, y);
160
+ node.h[2] = this.getHeight(x + 1, y + 1);
161
+ node.h[3] = this.getHeight(x, y + 1);
162
+ const hMin = Math.min(...node.h);
163
+ const hMax = Math.max(...node.h);
164
+ node.bbox = new BoundingBox(new Vector3(x * this._spacingX, hMin, y * this._spacingZ), new Vector3((x + 1) * this._spacingX, hMax, (y + 1) * this._spacingZ));
165
+ } else {
166
+ if (w >= h) {
167
+ const w1 = w + 1 >> 1;
168
+ const w2 = w - w1 + 1;
169
+ node.left = this.allocNode();
170
+ this.createChildNode(node.left, x, y, w1, h, vertices);
171
+ node.right = this.allocNode();
172
+ this.createChildNode(node.right, x + w1 - 1, y, w2, h, vertices);
173
+ } else {
174
+ const h1 = h + 1 >> 1;
175
+ const h2 = h - h1 + 1;
176
+ node.left = this.allocNode();
177
+ this.createChildNode(node.left, x, y, w, h1, vertices);
178
+ node.right = this.allocNode();
179
+ this.createChildNode(node.right, x, y + h1 - 1, w, h2, vertices);
180
+ }
181
+ node.bbox.beginExtend();
182
+ node.bbox.extend(node.left.bbox.minPoint);
183
+ node.bbox.extend(node.left.bbox.maxPoint);
184
+ node.bbox.extend(node.right.bbox.minPoint);
185
+ node.bbox.extend(node.right.bbox.maxPoint);
186
+ }
187
+ return true;
188
+ }
189
+ rayIntersect(ray) {
190
+ return this.rayIntersectR(ray, this._rootNode);
191
+ }
192
+ rayIntersectR(ray, node) {
193
+ const d = ray.bboxIntersectionTestEx(node.bbox);
194
+ if (d === null) {
195
+ return null;
196
+ }
197
+ if (node.left && node.right) {
198
+ const l = this.rayIntersectR(ray, node.left);
199
+ const r = this.rayIntersectR(ray, node.right);
200
+ if (l !== null && r !== null) {
201
+ return l < r ? l : r;
202
+ } else {
203
+ return l === null ? r : l;
204
+ }
205
+ } else {
206
+ const v00 = new Vector3(node.bbox.minPoint.x, node.h[0], node.bbox.minPoint.z);
207
+ const v01 = new Vector3(node.bbox.maxPoint.x, node.h[1], node.bbox.minPoint.z);
208
+ const v11 = new Vector3(node.bbox.maxPoint.x, node.h[2], node.bbox.maxPoint.z);
209
+ const v10 = new Vector3(node.bbox.minPoint.x, node.h[3], node.bbox.maxPoint.z);
210
+ let intersected = false;
211
+ let dist1 = ray.intersectionTestTriangle(v00, v01, v10, false);
212
+ if (dist1 !== null && dist1 > 0) {
213
+ intersected = true;
214
+ } else {
215
+ dist1 = Number.MAX_VALUE;
216
+ }
217
+ let dist2 = ray.intersectionTestTriangle(v10, v01, v11, false);
218
+ if (dist2 !== null && dist2 > 0) {
219
+ intersected = true;
220
+ } else {
221
+ dist2 = Number.MAX_VALUE;
222
+ }
223
+ if (!intersected) {
224
+ return null;
225
+ } else {
226
+ return dist1 < dist2 ? dist1 : dist2;
227
+ }
228
+ }
229
+ }
230
+ }
231
+ /** @internal */ class HeightField {
232
+ m_v4Range;
233
+ m_scale;
234
+ m_sizeX;
235
+ m_sizeZ;
236
+ m_bboxTree;
237
+ m_normals;
238
+ constructor(){
239
+ this.m_v4Range = Vector4.zero();
240
+ this.m_bboxTree = null;
241
+ this.m_scale = Vector3.one();
242
+ this.m_sizeX = 0;
243
+ this.m_sizeZ = 0;
244
+ this.m_normals = null;
245
+ }
246
+ init(sizeX, sizeZ, offsetX, offsetZ, scaleX, scaleY, scaleZ, heights) {
247
+ const v = [];
248
+ for(let i = 0; i < sizeZ; ++i){
249
+ const srcOffset = i * sizeX;
250
+ const dstOffset = (sizeZ - i - 1) * sizeX;
251
+ for(let j = 0; j < sizeX; ++j){
252
+ v[dstOffset + j] = new Vector4(offsetX + j * scaleX, heights[srcOffset + j] * scaleY, offsetZ + i * scaleZ, 1);
253
+ }
254
+ }
255
+ this.m_bboxTree = new HeightfieldBBoxTree(sizeX, sizeZ, scaleX, scaleZ, v);
256
+ this.m_v4Range.setXYZW(this.m_bboxTree.getRootNode().bbox.minPoint.x, this.m_bboxTree.getRootNode().bbox.minPoint.z, this.m_bboxTree.getRootNode().bbox.extents.x * 2, this.m_bboxTree.getRootNode().bbox.extents.z * 2);
257
+ this.m_scale.setXYZ(scaleX, scaleY, scaleZ);
258
+ this.m_sizeX = sizeX;
259
+ this.m_sizeZ = sizeZ;
260
+ this.m_normals = this.computeNormalVectors();
261
+ return true;
262
+ }
263
+ get normals() {
264
+ return this.m_normals;
265
+ }
266
+ clear() {
267
+ this.m_bboxTree = null;
268
+ this.m_v4Range.setXYZW(0, 0, 0, 0);
269
+ this.m_scale.setXYZ(1, 1, 1);
270
+ this.m_sizeX = 0;
271
+ this.m_sizeZ = 0;
272
+ }
273
+ rayIntersect(ray) {
274
+ return this.m_bboxTree.rayIntersect(ray);
275
+ }
276
+ computeNormals() {
277
+ const scaleX = this.m_scale.x;
278
+ const scaleZ = this.m_scale.z;
279
+ const heights = this.getHeights();
280
+ const v = new Vector3();
281
+ const normals = new Uint8Array((this.m_sizeZ - 1) * (this.m_sizeX - 1) * 4);
282
+ for(let y = 0; y < this.m_sizeZ - 1; ++y){
283
+ for(let x = 0; x < this.m_sizeX - 1; ++x){
284
+ const h00 = heights[x + y * this.m_sizeX];
285
+ const h01 = heights[x + (y + 1) * this.m_sizeX];
286
+ const h11 = heights[x + 1 + (y + 1) * this.m_sizeX];
287
+ const h10 = heights[x + 1 + y * this.m_sizeX];
288
+ const sx = (h00 + h01 - h11 - h10) * 0.5;
289
+ const sy = (h00 + h10 - h01 - h11) * 0.5;
290
+ const index = x + (this.m_sizeZ - 2 - y) * (this.m_sizeX - 1);
291
+ v.setXYZ(sx * scaleZ, 2 * scaleX * scaleZ, -sy * scaleX).inplaceNormalize();
292
+ normals[index * 4 + 0] = Math.floor((v.x * 0.5 + 0.5) * 255);
293
+ normals[index * 4 + 1] = Math.floor((v.y * 0.5 + 0.5) * 255);
294
+ normals[index * 4 + 2] = Math.floor((v.z * 0.5 + 0.5) * 255);
295
+ normals[index * 4 + 3] = 255;
296
+ }
297
+ }
298
+ return normals;
299
+ }
300
+ computeNormalVectors() {
301
+ const scaleX = this.m_scale.x;
302
+ const scaleZ = this.m_scale.z;
303
+ const heights = this.getHeights();
304
+ const normals = [];
305
+ for(let y = 0; y < this.m_sizeZ; ++y){
306
+ for(let x = 0; x < this.m_sizeX; ++x){
307
+ const h = heights[x + y * this.m_sizeX];
308
+ const h00 = x > 0 && y > 0 ? heights[x - 1 + (y - 1) * this.m_sizeX] : h;
309
+ const h01 = y > 0 && y < this.m_sizeZ - 1 ? heights[x - 1 + (y + 1) * this.m_sizeX] : h;
310
+ const h11 = x < this.m_sizeX - 1 && y < this.m_sizeZ - 1 ? heights[x + 1 + (y + 1) * this.m_sizeX] : h;
311
+ const h10 = x < this.m_sizeX - 1 && y > 0 ? heights[x + 1 + (y - 1) * this.m_sizeX] : h;
312
+ const sx = (h00 + h01 - h11 - h10) * 0.5;
313
+ const sy = (h00 + h10 - h01 - h11) * 0.5;
314
+ const index = x + (this.m_sizeZ - 1 - y) * this.m_sizeX;
315
+ normals[index] = new Vector3(sx * scaleZ, 2 * scaleX * scaleZ, -sy * scaleX).inplaceNormalize();
316
+ }
317
+ }
318
+ return normals;
319
+ }
320
+ getBBoxTree() {
321
+ return this.m_bboxTree;
322
+ }
323
+ getSpacingX() {
324
+ return this.m_scale.x;
325
+ }
326
+ getSpacingZ() {
327
+ return this.m_scale.z;
328
+ }
329
+ getVerticalScale() {
330
+ return this.m_scale.y;
331
+ }
332
+ getSizeX() {
333
+ return this.m_sizeX;
334
+ }
335
+ getSizeZ() {
336
+ return this.m_sizeZ;
337
+ }
338
+ getOffsetX() {
339
+ return this.m_v4Range.x;
340
+ }
341
+ getOffsetZ() {
342
+ return this.m_v4Range.y;
343
+ }
344
+ getBoundingbox() {
345
+ return this.m_bboxTree?.getRootNode()?.bbox || null;
346
+ }
347
+ getHeights() {
348
+ return this.m_bboxTree?.getHeights() || null;
349
+ }
350
+ getHeight(x, z) {
351
+ return this.m_bboxTree ? this.m_bboxTree.getHeight(x, z) : 0;
352
+ }
353
+ getRealHeight(x, z) {
354
+ return this.m_bboxTree ? this.m_bboxTree.getRealHeight(x, z) : 0;
355
+ }
356
+ getRealNormal(x, z, normal) {
357
+ normal = normal ?? new Vector3();
358
+ const bboxRootNode = this.m_bboxTree.getRootNode();
359
+ x -= bboxRootNode.bbox.minPoint.x;
360
+ z -= bboxRootNode.bbox.minPoint.z;
361
+ const tileSizeX = (bboxRootNode.bbox.maxPoint.x - bboxRootNode.bbox.minPoint.x) / (this.m_sizeX - 1);
362
+ const tileSizeY = (bboxRootNode.bbox.maxPoint.z - bboxRootNode.bbox.minPoint.z) / (this.m_sizeZ - 1);
363
+ const x_unscale = x / tileSizeX;
364
+ const y_unscale = z / tileSizeY;
365
+ let l = Math.floor(x_unscale);
366
+ let t = Math.floor(y_unscale);
367
+ let r = l + 1;
368
+ let b = t + 1;
369
+ if (l < 0) {
370
+ l = 0;
371
+ }
372
+ if (t < 0) {
373
+ t = 0;
374
+ }
375
+ if (r >= this.m_sizeX) {
376
+ r = this.m_sizeX - 1;
377
+ }
378
+ if (b >= this.m_sizeZ) {
379
+ b = this.m_sizeZ - 1;
380
+ }
381
+ normal.set(this.m_normals[l + t * this.m_sizeX]);
382
+ normal.addBy(this.m_normals[r + t * this.m_sizeX]);
383
+ normal.addBy(this.m_normals[r + b * this.m_sizeX]);
384
+ normal.addBy(this.m_normals[l + b * this.m_sizeX]);
385
+ normal.scaleBy(0.4).inplaceNormalize();
386
+ return normal;
387
+ }
388
+ }
389
+
390
+ export { HeightField, HeightfieldBBoxTree };
391
+ //# sourceMappingURL=heightfield.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heightfield.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}