@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.
- package/core/FilePath.js +28 -2
- package/core/binary/BinaryBuffer.js +13 -0
- package/core/geom/2d/quad-tree/QuadTreeNode.js +3 -2
- package/core/geom/3d/triangle/computeTriangleRayIntersection.js +3 -9
- package/engine/asset/AssetManager.js +1 -1
- package/engine/asset/AssetTransformer.js +2 -1
- package/engine/asset/loaders/GLTFAssetLoader.js +2 -22
- package/engine/asset/loaders/async_traverse_three_object.js +24 -0
- package/engine/ecs/fow/shader/screenSpaceFogOfWarShader.js +2 -10
- package/engine/ecs/grid/NormalMap2AOMap.js +10 -13
- package/engine/ecs/terrain/ecs/BuildLightTexture.js +106 -0
- package/engine/ecs/terrain/ecs/PromiseSamplerHeight.js +59 -0
- package/engine/ecs/terrain/ecs/Terrain.js +14 -153
- package/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js +10 -0
- package/engine/graphics/filter/ImageFilter.js +6 -2
- package/engine/graphics/geometry/buffered/query/ClippingPlaneContainmentComputingVisitor.js +28 -27
- package/engine/graphics/geometry/buffered/query/GeometryVisitor.js +29 -2
- package/engine/graphics/geometry/buffered/query/RaycastNearestHitComputingVisitor.js +28 -27
- package/engine/graphics/micron/MICRON_GEOMETRY_FIELD.js +1 -0
- package/engine/graphics/micron/MICRON_URI_FIELD.js +1 -0
- package/engine/graphics/micron/convert_three_object_to_micron.js +31 -5
- package/engine/graphics/micron/format/MicronGeometry.js +6 -0
- package/engine/graphics/micron/plugin/MicronRenderPlugin.js +110 -6
- package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +3 -1
- package/engine/graphics/shaders/AmbientOcclusionShader.js +57 -77
- package/engine/graphics/shaders/DenoiseShader.js +119 -0
- package/engine/graphics/texture/noise_octaves.js +33 -0
- package/engine/graphics/texture/sampler/Sampler2D2Texture.js +7 -18
- package/engine/graphics/texture/sampler/debug/paintSamplerOnHTML.js +8 -5
- package/engine/graphics/texture/sampler/sampler2DToFloat32Texture.js +10 -3
- package/generation/example/filters/SampleGroundMoistureFilter.js +2 -1
- package/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +29 -13
- package/generation/grid/GridData.js +17 -2
- 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
|
-
|
|
319
|
-
const
|
|
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
|
-
|
|
30
|
-
|
|
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
|
|
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 =
|
|
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.
|
|
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
|
|
69
|
-
|
|
70
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|