@woosh/meep-engine 2.33.64 → 2.33.69

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 (34) hide show
  1. package/core/FilePath.js +28 -2
  2. package/core/binary/BinaryBuffer.js +13 -0
  3. package/core/geom/2d/quad-tree/QuadTreeNode.js +3 -2
  4. package/core/geom/3d/triangle/computeTriangleRayIntersection.js +3 -9
  5. package/engine/asset/AssetManager.js +1 -1
  6. package/engine/asset/AssetTransformer.js +2 -1
  7. package/engine/asset/loaders/GLTFAssetLoader.js +2 -22
  8. package/engine/asset/loaders/async_traverse_three_object.js +24 -0
  9. package/engine/ecs/fow/shader/screenSpaceFogOfWarShader.js +2 -10
  10. package/engine/ecs/grid/NormalMap2AOMap.js +10 -13
  11. package/engine/ecs/terrain/ecs/BuildLightTexture.js +106 -0
  12. package/engine/ecs/terrain/ecs/PromiseSamplerHeight.js +59 -0
  13. package/engine/ecs/terrain/ecs/Terrain.js +14 -153
  14. package/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js +10 -0
  15. package/engine/graphics/filter/ImageFilter.js +6 -2
  16. package/engine/graphics/geometry/buffered/query/ClippingPlaneContainmentComputingVisitor.js +28 -27
  17. package/engine/graphics/geometry/buffered/query/GeometryVisitor.js +29 -2
  18. package/engine/graphics/geometry/buffered/query/RaycastNearestHitComputingVisitor.js +28 -27
  19. package/engine/graphics/micron/MICRON_GEOMETRY_FIELD.js +1 -0
  20. package/engine/graphics/micron/MICRON_URI_FIELD.js +1 -0
  21. package/engine/graphics/micron/convert_three_object_to_micron.js +31 -5
  22. package/engine/graphics/micron/format/MicronGeometry.js +6 -0
  23. package/engine/graphics/micron/plugin/MicronRenderPlugin.js +110 -6
  24. package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +3 -1
  25. package/engine/graphics/shaders/AmbientOcclusionShader.js +57 -77
  26. package/engine/graphics/shaders/DenoiseShader.js +119 -0
  27. package/engine/graphics/texture/noise_octaves.js +33 -0
  28. package/engine/graphics/texture/sampler/Sampler2D2Texture.js +7 -18
  29. package/engine/graphics/texture/sampler/debug/paintSamplerOnHTML.js +8 -5
  30. package/engine/graphics/texture/sampler/sampler2DToFloat32Texture.js +10 -3
  31. package/generation/example/filters/SampleGroundMoistureFilter.js +2 -1
  32. package/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +29 -13
  33. package/generation/grid/GridData.js +17 -2
  34. package/package.json +1 -1
package/core/FilePath.js CHANGED
@@ -1,3 +1,5 @@
1
+ const PATH_SEPARATOR = '/';
2
+
1
3
  /**
2
4
  * Strips all directories from the path.
3
5
  * @example 'a/b/c' -> 'c'
@@ -9,7 +11,7 @@ function computePathBase(path) {
9
11
  throw new Error('path is not a string');
10
12
  }
11
13
 
12
- const lastSlashIndex = path.lastIndexOf('/');
14
+ const lastSlashIndex = path.lastIndexOf(PATH_SEPARATOR);
13
15
 
14
16
  if (lastSlashIndex !== -1) {
15
17
  return path.substring(lastSlashIndex + 1);
@@ -18,6 +20,30 @@ function computePathBase(path) {
18
20
  }
19
21
  }
20
22
 
23
+ /**
24
+ * Returns the directory name of a path, similar to the Unix dirname command.
25
+ * @param {string} path
26
+ * @return {string}
27
+ */
28
+ export function computePathDirectory(path) {
29
+ if (typeof path !== "string") {
30
+ throw new Error('path is not a string');
31
+ }
32
+
33
+ let lastSlashIndex = path.lastIndexOf(PATH_SEPARATOR);
34
+
35
+ //rewind in case of trailing slashes
36
+ while (lastSlashIndex > 0 && path.charAt(lastSlashIndex - 1) === PATH_SEPARATOR) {
37
+ lastSlashIndex--;
38
+ }
39
+
40
+ if (lastSlashIndex !== -1) {
41
+ return path.substring(0, lastSlashIndex);
42
+ } else {
43
+ return path;
44
+ }
45
+ }
46
+
21
47
  /**
22
48
  *
23
49
  * @param {string} path
@@ -44,4 +70,4 @@ function computeFileExtension(path) {
44
70
  export {
45
71
  computePathBase,
46
72
  computeFileExtension
47
- };
73
+ };
@@ -57,6 +57,19 @@ BinaryBuffer.prototype.fromArrayBuffer = function (arrayBuffer) {
57
57
  this.position = 0;
58
58
  };
59
59
 
60
+ /**
61
+ *
62
+ * @param {ArrayBuffer} v
63
+ * @return {BinaryBuffer}
64
+ */
65
+ BinaryBuffer.fromArrayBuffer = function (v) {
66
+ const r = new BinaryBuffer();
67
+
68
+ r.fromArrayBuffer(v);
69
+
70
+ return r;
71
+ };
72
+
60
73
  /**
61
74
  *
62
75
  * @returns {BinaryBuffer}
@@ -315,8 +315,9 @@ export class QuadTreeNode extends AABB2 {
315
315
  const x1 = this.x1;
316
316
  const y1 = this.y1;
317
317
 
318
- const xm = (x0 + x1) / 2;
319
- const ym = (y0 + y1) / 2;
318
+ // get center point
319
+ const xm = (x0 + x1) * 0.5;
320
+ const ym = (y0 + y1) * 0.5;
320
321
 
321
322
  for (; i < dataLength; i++) {
322
323
  const datum = data[i];
@@ -25,15 +25,9 @@ export function computeTriangleRayIntersection(
25
25
  result,
26
26
  origin_x, origin_y, origin_z,
27
27
  direction_x, direction_y, direction_z,
28
- ax,
29
- ay,
30
- az,
31
- bx,
32
- by,
33
- bz,
34
- cx,
35
- cy,
36
- cz
28
+ ax, ay, az,
29
+ bx, by, bz,
30
+ cx, cy, cz
37
31
  ) {
38
32
 
39
33
  // edge1 = a - b
@@ -231,7 +231,7 @@ AssetManager.prototype.submitRequest = function (path, type, request) {
231
231
  for (let i = 0; i < transformer_count; i++) {
232
232
  const transformer = transformers[i];
233
233
 
234
- const transformed_asset = await transformer.transform(asset);
234
+ const transformed_asset = await transformer.transform(asset, assetDescription);
235
235
 
236
236
  if (typeof transformed_asset !== "object") {
237
237
  console.error('Transformer produced invalid result. Ignoring result.', transformer, assetDescription);
@@ -7,9 +7,10 @@
7
7
  export class AssetTransformer {
8
8
  /**
9
9
  * @param {A} source
10
+ * @param {AssetDescription} asset_description
10
11
  * @returns {A}
11
12
  */
12
- async transform(source) {
13
+ async transform(source, asset_description) {
13
14
  throw new Error('Not Implemented');
14
15
  }
15
16
  }
@@ -25,6 +25,7 @@ import { computeGeometryEquality } from "./geometry/geometry/computeGeometryEqua
25
25
  import { traverseThreeObject } from "../../graphics/ecs/highlight/renderer/traverseThreeObject.js";
26
26
  import { computeTextureHash } from "./material/computeTextureHash.js";
27
27
  import { computeTextureEquality } from "./material/computeTextureEquality.js";
28
+ import { async_traverse_three_object } from "./async_traverse_three_object.js";
28
29
 
29
30
  const animationOptimizer = new AnimationOptimizer();
30
31
  const materialCache = StaticMaterialCache.Global;
@@ -130,26 +131,6 @@ function buildDracoDecoderPath() {
130
131
  return `${pathname}/libs/draco/`;
131
132
  }
132
133
 
133
- /**
134
- *
135
- * @param {THREE.Object3D} object
136
- * @param {function} callback
137
- * @param {*} [thisArg]
138
- */
139
- async function async_traverse(object, callback, thisArg) {
140
- await callback.call(thisArg, object);
141
-
142
- const children = object.children;
143
- const n = children.length;
144
-
145
- for (let i = 0; i < n; i++) {
146
- const child = children[i];
147
-
148
- // TODO we can parallelize this if necessary
149
- await async_traverse(child, callback, thisArg);
150
- }
151
- }
152
-
153
134
  export class GLTFAssetLoader extends AssetLoader {
154
135
 
155
136
  constructor() {
@@ -312,7 +293,6 @@ export class GLTFAssetLoader extends AssetLoader {
312
293
  mesh.geometry = geometry;
313
294
  }
314
295
 
315
-
316
296
  if (this.__enable_texture_cache) {
317
297
  // replace textures from cache
318
298
  replace_material_textures_from_cache(mesh.material, texture_cache);
@@ -387,7 +367,7 @@ export class GLTFAssetLoader extends AssetLoader {
387
367
  }
388
368
 
389
369
 
390
- await async_traverse(root, process_object);
370
+ await async_traverse_three_object(root, process_object);
391
371
 
392
372
 
393
373
  // compute object bounding sphere
@@ -0,0 +1,24 @@
1
+ /**
2
+ *
3
+ * @param {THREE.Object3D} object
4
+ * @param {function} callback
5
+ * @param {*} [thisArg]
6
+ * @param {*} [ctx]
7
+ */
8
+ export async function async_traverse_three_object(object, callback, thisArg, ctx) {
9
+ await callback.call(thisArg, object, ctx);
10
+
11
+ const children = object.children;
12
+ const n = children.length;
13
+
14
+ const child_promises = [];
15
+
16
+ for (let i = 0; i < n; i++) {
17
+ const child = children[i];
18
+
19
+ child_promises.push(async_traverse_three_object(child, callback, thisArg, ctx));
20
+ }
21
+
22
+ // wait for all children at the same time
23
+ await Promise.all(child_promises);
24
+ }
@@ -1,4 +1,5 @@
1
1
  import { Matrix4, NormalBlending, ShaderMaterial, Vector2, Vector4 } from "three";
2
+ import { FULL_SCREEN_QUAD_VERTEX_SHADER } from "../../../graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js";
2
3
 
3
4
  /**
4
5
  Shader for drawing fog of war as a screen-space post-process effect
@@ -6,16 +7,7 @@ import { Matrix4, NormalBlending, ShaderMaterial, Vector2, Vector4 } from "three
6
7
  */
7
8
  export function buildScreenSpaceFogOfWarShader() {
8
9
  function vertexShader() {
9
- return `
10
- varying vec2 vUv;
11
-
12
- void main() {
13
-
14
- vUv = uv;
15
-
16
- gl_Position = vec4( (uv - 0.5)*2.0, 0.0, 1.0 );
17
-
18
- }`;
10
+ return FULL_SCREEN_QUAD_VERTEX_SHADER;
19
11
  }
20
12
 
21
13
  function fragmentShader() {
@@ -5,11 +5,10 @@
5
5
 
6
6
  import { ClampToEdgeWrapping, DataTexture, RGBAFormat, UnsignedByteType, Vector2 } from 'three';
7
7
  import { Sampler2D } from '../../graphics/texture/sampler/Sampler2D.js';
8
- import sampler2D2Texture from '../../graphics/texture/sampler/Sampler2D2Texture.js';
9
8
  import AmbientOcclusionShader from '../../graphics/shaders/AmbientOcclusionShader.js';
10
- import GaussianBlurShader from '../../graphics/shaders/GaussianBlurShader.js';
11
9
  import ImageFilter from '../../graphics/filter/ImageFilter.js';
12
10
  import { sampler2DtoFloat32Texture } from "../../graphics/texture/sampler/sampler2DToFloat32Texture.js";
11
+ import { DenoiseShader } from "../../graphics/shaders/DenoiseShader.js";
13
12
 
14
13
  function filterResult2Texture(data, width, height) {
15
14
  const result = new DataTexture();
@@ -37,6 +36,7 @@ function filterResult2Texture(data, width, height) {
37
36
  * @param {Sampler2D} heightMap
38
37
  * @param {Sampler2D} normalMap
39
38
  * @param {Vector2} resultSize
39
+ * @param worldSize
40
40
  * @param {number} [rayLength]
41
41
  * @returns {Sampler2D}
42
42
  */
@@ -45,13 +45,13 @@ function normalMap2OcclusionMap(
45
45
  heightMap,
46
46
  normalMap,
47
47
  resultSize,
48
+ worldSize = new Vector2(heightMap.width, heightMap.width),
48
49
  rayLength = 17
49
50
  ) {
50
51
  const width = resultSize.x;
51
52
  const height = resultSize.y;
52
- const resolution = new Vector2(heightMap.width, heightMap.height);
53
53
  //
54
- const normalTexture = sampler2D2Texture(normalMap, 255, 0.5);
54
+ const normalTexture = sampler2DtoFloat32Texture(normalMap);
55
55
 
56
56
  const heightTexture = sampler2DtoFloat32Texture(heightMap);
57
57
 
@@ -60,17 +60,16 @@ function normalMap2OcclusionMap(
60
60
  const shaderAO = new AmbientOcclusionShader();
61
61
  shaderAO.uniforms.heightMap.value = heightTexture;
62
62
  shaderAO.uniforms.normalMap.value = normalTexture;
63
- shaderAO.uniforms.resolution.value = resolution;
63
+ shaderAO.uniforms.world_size.value.set(worldSize.x, worldSize.y);
64
64
  shaderAO.uniforms.rayLength.value = rayLength;
65
65
  //perform filtering
66
66
  const rawAO = ImageFilter(renderer, width, height, shaderAO);
67
67
 
68
- const shaderBlur = new GaussianBlurShader();
69
- shaderBlur.uniforms.resolution.value = resolution;
70
- shaderBlur.uniforms.tDiffuse.value = filterResult2Texture(rawAO.array, width, height);
71
- shaderBlur.uniforms.sigma.value.set(1.3, 1.3);
68
+ const shaderDenoise = new DenoiseShader(2);
69
+ shaderDenoise.uniforms.source.value = filterResult2Texture(rawAO.array, width, height);
70
+ shaderDenoise.uniforms.pixelOffset.value.set(1 / width, 1 / height);
72
71
 
73
- const smoothAO = ImageFilter(renderer, width, height, shaderBlur);
72
+ const smoothAO = ImageFilter(renderer, width, height, shaderDenoise);
74
73
 
75
74
  //create the sampler
76
75
  const result = new Sampler2D(new Uint8ClampedArray(width * height), 1, width, height);
@@ -79,9 +78,7 @@ function normalMap2OcclusionMap(
79
78
  const size = width * height;
80
79
 
81
80
  for (let i = 0; i < size; i++) {
82
- const i4 = i * 4;
83
-
84
- result.data[i] = smoothAO.array[i4];
81
+ result.data[i] = smoothAO.array[i * 4];
85
82
  }
86
83
 
87
84
  return result;
@@ -0,0 +1,106 @@
1
+ import normalMap2AOMap from "../../grid/NormalMap2AOMap.js";
2
+ import heightMap2NormalMap from "../../grid/HeightMap2NormalMap.js";
3
+ import { WebGLRendererPool } from "../../../graphics/render/RendererPool.js";
4
+ import Vector2 from "../../../../core/geom/Vector2.js";
5
+ import { writeSample2DDataToDataTexture } from "../../../graphics/texture/sampler/writeSampler2DDataToDataTexture.js";
6
+
7
+ /**
8
+ *
9
+ * @param {WebGLRenderer} renderer
10
+ * @param {Sampler2D} sampler
11
+ * @returns {Promise<Sampler2D>}
12
+ */
13
+ function promiseSamplerNormal(renderer, sampler) {
14
+
15
+ console.time("generating normal map");
16
+ const normalSampler = heightMap2NormalMap(renderer, sampler);
17
+ console.timeEnd("generating normal map");
18
+
19
+
20
+ return Promise.resolve(normalSampler);
21
+ }
22
+
23
+ /**
24
+ *
25
+ * @param {WebGLRenderer} renderer
26
+ * @param {Promise<Sampler2D>} pSamplerNormal
27
+ * @param {Sampler2D} samplerHeight
28
+ * @param {Vector2} resolution
29
+ * @param {Vector2} [wordSize]
30
+ * @param {number} rayLength
31
+ * @returns {Promise<unknown>}
32
+ */
33
+ function promiseSamplerAO(
34
+ {
35
+ renderer,
36
+ pSamplerNormal,
37
+ samplerHeight,
38
+ resolution,
39
+ wordSize = resolution,
40
+ rayLength
41
+ }
42
+ ) {
43
+ return new Promise(function (resolve, reject) {
44
+ Promise.all([pSamplerNormal]).then(function (values) {
45
+ const samplerNormal = values[0];
46
+ console.time("generating AO map");
47
+ const occlusionSampler = normalMap2AOMap(
48
+ renderer,
49
+ samplerHeight,
50
+ samplerNormal,
51
+ wordSize,
52
+ resolution,
53
+ rayLength
54
+ );
55
+ console.timeEnd("generating AO map");
56
+ //console.info(occlusionSampler);
57
+ //
58
+ // paintSamplerOnHTML(samplerHeight, 0, 0, 40, 3);
59
+ // paintSamplerOnHTML(samplerNormal, 1, 0, 128, 1);
60
+ // paintSamplerOnHTML(occlusionSampler, 2, 0, 1, 0);
61
+ //
62
+ //
63
+ resolve(occlusionSampler);
64
+ }, reject);
65
+ });
66
+ }
67
+
68
+ /**
69
+ *
70
+ * @param {THREE.DataTexture} texture
71
+ * @param {Vector2} [resolution]
72
+ * @param {Sampler2D} heightSampler
73
+ * @param {number} [rayLength]
74
+ * @param {Vector2} [worldSize]
75
+ * @returns {Promise}
76
+ */
77
+ export function buildLightTexture({
78
+ texture,
79
+ heightSampler,
80
+ resolution= new Vector2(texture.image.width, texture.image.height),
81
+ rayLength = 11,
82
+ worldSize = resolution
83
+ }) {
84
+
85
+ const renderer = WebGLRendererPool.global.get();
86
+
87
+ const normal = promiseSamplerNormal(renderer, heightSampler);
88
+ const ao = promiseSamplerAO({
89
+ renderer: renderer,
90
+ pSamplerNormal: normal,
91
+ samplerHeight: heightSampler,
92
+ resolution: resolution,
93
+ rayLength: rayLength,
94
+ worldSize
95
+ });
96
+
97
+ const promise = ao.then(sampler => {
98
+ writeSample2DDataToDataTexture(sampler, texture);
99
+ });
100
+
101
+ Promise.all([normal, ao]).finally(() => {
102
+ WebGLRendererPool.global.release(renderer);
103
+ });
104
+
105
+ return promise;
106
+ }
@@ -0,0 +1,59 @@
1
+ import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
2
+ import { deserializeTexture } from "../../../graphics/texture/sampler/TextureBinaryBufferSerializer.js";
3
+ import { Sampler2D } from "../../../graphics/texture/sampler/Sampler2D.js";
4
+ import { GameAssetType } from "../../../asset/GameAssetType.js";
5
+ import rgbaData2valueSampler2D from "../../../graphics/texture/sampler/rgbaData2valueSampler2D.js";
6
+
7
+ /**
8
+ *
9
+ * @param zRange
10
+ * @param heightMapURL
11
+ * @param {AssetManager} assetManager
12
+ * @returns {Promise<any>}
13
+ */
14
+ export function promiseSamplerHeight(zRange, heightMapURL, assetManager) {
15
+ return new Promise(function (fulfill, reject) {
16
+
17
+ function assetObtained(asset) {
18
+ const array = asset.create();
19
+
20
+ const binaryBuffer = new BinaryBuffer();
21
+ //
22
+ // binaryBuffer.writeUint32(2560);
23
+ // binaryBuffer.writeUint32(2560);
24
+ //
25
+ // binaryBuffer.writeUint8(1);
26
+ //
27
+ // binaryBuffer.writeUint8(6);
28
+
29
+ binaryBuffer.writeBytes(new Uint8Array(array), 0, array.length);
30
+
31
+ binaryBuffer.position = 0;
32
+
33
+ const sampler2D = deserializeTexture(binaryBuffer);
34
+ fulfill(sampler2D);
35
+ }
36
+
37
+
38
+ if (heightMapURL === undefined) {
39
+ console.warn('Height map is not specified');
40
+ const defaultSampler = new Sampler2D(new Uint8Array(1), 1, 1, 1);
41
+ fulfill(defaultSampler);
42
+ } else if (heightMapURL.endsWith('.bin')) {
43
+ //load texture from a binary file
44
+ assetManager.get(heightMapURL, GameAssetType.ArrayBuffer, assetObtained, reject);
45
+ } else {
46
+ assetManager.get(heightMapURL, GameAssetType.Image, function (asset) {
47
+ const image = asset.create();
48
+
49
+ // plane
50
+ const imgWidth = image.width;
51
+ const imgHeight = image.height;
52
+
53
+ const samplerHeight = rgbaData2valueSampler2D(image.data, imgWidth, imgHeight, zRange, -zRange / 2);
54
+
55
+ fulfill(samplerHeight);
56
+ }, reject);
57
+ }
58
+ });
59
+ }
@@ -14,9 +14,6 @@ import {
14
14
  } from 'three';
15
15
  import { clamp } from "../../../../core/math/clamp.js";
16
16
  import { Sampler2D } from '../../../graphics/texture/sampler/Sampler2D.js';
17
- import heightMap2NormalMap from '../../grid/HeightMap2NormalMap.js';
18
- import normalMap2AOMap from '../../grid/NormalMap2AOMap.js';
19
- import rgbaData2valueSampler2D from '../../../graphics/texture/sampler/rgbaData2valueSampler2D.js';
20
17
  import { BinaryNode } from '../../../../core/bvh2/BinaryNode.js';
21
18
  import Vector2 from '../../../../core/geom/Vector2.js';
22
19
  import { TerrainOverlay } from '../overlay/TerrainOverlay.js';
@@ -24,13 +21,9 @@ import { TerrainOverlay } from '../overlay/TerrainOverlay.js';
24
21
  import Clouds from '../TerrainClouds.js';
25
22
 
26
23
  import TerrainTileManager from '../tiles/TerrainTileManager.js';
27
- import { WebGLRendererPool } from "../../../graphics/render/RendererPool.js";
28
- import { deserializeTexture } from "../../../graphics/texture/sampler/TextureBinaryBufferSerializer.js";
29
- import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
30
24
  import { TerrainPreview } from "../TerrainPreview.js";
31
25
  import { assert } from "../../../../core/assert.js";
32
26
  import { GameAssetType } from "../../../asset/GameAssetType.js";
33
- import { writeSample2DDataToDataTexture } from "../../../graphics/texture/sampler/writeSampler2DDataToDataTexture.js";
34
27
  import { TerrainLayers } from "./layers/TerrainLayers.js";
35
28
  import { SplatMaterial } from "../../../graphics/material/SplatMaterial.js";
36
29
  import { loadLegacyTerrainSplats, SplatMapping } from "./splat/SplatMapping.js";
@@ -41,147 +34,8 @@ import { MeepSettings } from "../../../MeepSettings.js";
41
34
  import { loadLegacyTerrainLayers } from "./layers/loadLegacyTerrainLayers.js";
42
35
  import { TerrainFlags } from "./TerrainFlags.js";
43
36
  import { IllegalStateException } from "../../../../core/fsm/exceptions/IllegalStateException.js";
44
-
45
- /**
46
- *
47
- * @param zRange
48
- * @param heightMapURL
49
- * @param {AssetManager} assetManager
50
- * @returns {Promise<any>}
51
- */
52
- function promiseSamplerHeight(zRange, heightMapURL, assetManager) {
53
- return new Promise(function (fulfill, reject) {
54
-
55
- function assetObtained(asset) {
56
- const array = asset.create();
57
-
58
- const binaryBuffer = new BinaryBuffer();
59
- //
60
- // binaryBuffer.writeUint32(2560);
61
- // binaryBuffer.writeUint32(2560);
62
- //
63
- // binaryBuffer.writeUint8(1);
64
- //
65
- // binaryBuffer.writeUint8(6);
66
-
67
- binaryBuffer.writeBytes(new Uint8Array(array), 0, array.length);
68
-
69
- binaryBuffer.position = 0;
70
-
71
- const sampler2D = deserializeTexture(binaryBuffer);
72
- fulfill(sampler2D);
73
- }
74
-
75
-
76
- if (heightMapURL === undefined) {
77
- console.warn('Height map is not specified');
78
- const defaultSampler = new Sampler2D(new Uint8Array(1), 1, 1, 1);
79
- fulfill(defaultSampler);
80
- } else if (heightMapURL.endsWith('.bin')) {
81
- //load texture from a binary file
82
- assetManager.get(heightMapURL, GameAssetType.ArrayBuffer, assetObtained, reject);
83
- } else {
84
- assetManager.get(heightMapURL, GameAssetType.Image, function (asset) {
85
- const image = asset.create();
86
-
87
- // plane
88
- const imgWidth = image.width;
89
- const imgHeight = image.height;
90
-
91
- const samplerHeight = rgbaData2valueSampler2D(image.data, imgWidth, imgHeight, zRange, -zRange / 2);
92
-
93
- fulfill(samplerHeight);
94
- }, reject);
95
- }
96
- });
97
- }
98
-
99
- /**
100
- *
101
- * @param {WebGLRenderer} renderer
102
- * @param {Sampler2D} sampler
103
- * @returns {Promise<Sampler2D>}
104
- */
105
- function promiseSamplerNormal(renderer, sampler) {
106
-
107
- console.time("generating normal map");
108
- const normalSampler = heightMap2NormalMap(renderer, sampler);
109
- console.timeEnd("generating normal map");
110
-
111
-
112
- return Promise.resolve(normalSampler);
113
- }
114
-
115
- /**
116
- *
117
- * @param {WebGLRenderer} renderer
118
- * @param {Promise<Sampler2D>} pSamplerNormal
119
- * @param {Sampler2D} samplerHeight
120
- * @param {Vector2} resolution
121
- * @param {number} rayLength
122
- * @returns {Promise<unknown>}
123
- */
124
- function promiseSamplerAO(
125
- renderer,
126
- pSamplerNormal,
127
- samplerHeight,
128
- resolution,
129
- rayLength
130
- ) {
131
- return new Promise(function (resolve, reject) {
132
- Promise.all([pSamplerNormal]).then(function (values) {
133
- const samplerNormal = values[0];
134
- console.time("generating AO map");
135
- const occlusionSampler = normalMap2AOMap(
136
- renderer,
137
- samplerHeight,
138
- samplerNormal,
139
- resolution,
140
- rayLength
141
- );
142
- console.timeEnd("generating AO map");
143
- //console.info(occlusionSampler);
144
- //
145
- // paintSamplerOnHTML(samplerHeight, 0, 0, 40, 3);
146
- // paintSamplerOnHTML(samplerNormal, 1, 0, 128, 1);
147
- // paintSamplerOnHTML(occlusionSampler, 2, 0, 1, 0);
148
- //
149
- //
150
- resolve(occlusionSampler);
151
- }, reject);
152
- });
153
- }
154
-
155
- /**
156
- *
157
- * @param {DataTexture} texture
158
- * @param {Vector2} resolution
159
- * @param {Sampler2D} heightSampler
160
- * @param {number} heightRange
161
- * @param {number} [rayLength]
162
- * @returns {Promise}
163
- */
164
- function buildLightTexture({ texture, heightSampler, resolution, rayLength = 17 }) {
165
-
166
- const renderer = WebGLRendererPool.global.get();
167
-
168
- if (resolution === undefined) {
169
- resolution = new Vector2(texture.image.width, texture.image.height);
170
- }
171
-
172
- const normal = promiseSamplerNormal(renderer, heightSampler);
173
- const ao = promiseSamplerAO(renderer, normal, heightSampler, resolution, rayLength);
174
-
175
- const promise = ao.then(sampler => {
176
- writeSample2DDataToDataTexture(sampler, texture);
177
- });
178
-
179
- Promise.all([normal, ao]).finally(() => {
180
- WebGLRendererPool.global.release(renderer);
181
- });
182
-
183
- return promise;
184
- }
37
+ import { buildLightTexture } from "./BuildLightTexture.js";
38
+ import { promiseSamplerHeight } from "./PromiseSamplerHeight.js";
185
39
 
186
40
  let idCounter = 0;
187
41
 
@@ -903,13 +757,13 @@ class Terrain {
903
757
  this.updateWorkerHeights();
904
758
  }
905
759
 
906
- updateWorkerHeights() {
760
+ async updateWorkerHeights() {
907
761
  const s = this.samplerHeight;
908
762
  const worker = this.buildWorker;
909
763
 
910
- worker.setHeightSampler(s.data, s.itemSize, s.width, s.height);
764
+ await worker.setHeightSampler(s.data, s.itemSize, s.width, s.height);
911
765
 
912
- return worker.computeHeightRange()
766
+ return await worker.computeHeightRange()
913
767
  .then(({ min, max }) => {
914
768
  this.tiles.setHeightRange(min, max);
915
769
  });
@@ -1012,7 +866,12 @@ class Terrain {
1012
866
  this.setFlag(TerrainFlags.Built);
1013
867
  }
1014
868
 
1015
- buildLightMap() {
869
+ /**
870
+ *
871
+ * @param {number} quality resolution in texels per grid cell (4 = 4x4 light map texels per single grid cell)
872
+ * @return {Promise<DataTexture>}
873
+ */
874
+ buildLightMap(quality = 4) {
1016
875
 
1017
876
 
1018
877
  const size_x = this.size.x;
@@ -1035,7 +894,9 @@ class Terrain {
1035
894
 
1036
895
  const promise = buildLightTexture({
1037
896
  texture,
1038
- heightSampler: this.samplerHeight
897
+ heightSampler: this.samplerHeight,
898
+ worldSize: new Vector2(size_x * this.gridScale, size_y * this.gridScale),
899
+ resolution: new Vector2(size_x * quality, size_y *quality)
1039
900
  });
1040
901
 
1041
902