@woosh/meep-engine 2.71.0 → 2.72.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.
- package/build/bundle-worker-terrain.js +1 -1
- package/build/meep.cjs +2 -2
- package/build/meep.module.js +2 -2
- package/package.json +1 -1
- package/src/core/collection/array/array_get_index_in_range.js +1 -1
- package/src/core/collection/array/array_swap.js +2 -2
- package/src/core/geom/3d/v3_compute_triangle_normal.js +7 -1
- package/src/core/geom/vec3/v3_normalize_array.js +27 -0
- package/src/engine/ecs/terrain/BufferedGeometryArraysBuilder.js +2 -2
- package/src/engine/graphics/geometry/buffered/ComputeNormals.js +11 -26
- package/src/engine/graphics/texture/virtual/v2/NOTES.md +17 -0
- package/src/engine/graphics/texture/virtual/v2/ShaderUsage.js +49 -26
- package/src/engine/graphics/texture/virtual/v2/UsageDebugView.js +51 -0
- package/src/engine/graphics/texture/virtual/v2/UsageMetadata.js +221 -0
- package/src/engine/graphics/texture/virtual/v2/UsagePyramidDebugView.js +239 -0
- package/src/engine/graphics/texture/virtual/v2/VirtualTextureManager.js +248 -0
- package/src/engine/graphics/texture/virtual/v2/prototype.js +104 -31
- package/src/core/geom/2d/quad-tree/PointQuadTree.js +0 -478
- package/src/core/math/random/makeRangedRandom.js +0 -19
- package/src/engine/ecs/terrain/TerrainGeometryBuilder.js +0 -152
- package/src/engine/ecs/terrain/ecs/PromiseSamplerHeight.js +0 -66
- package/src/engine/ecs/terrain/ecs/TerrainClassifier.js +0 -125
- package/src/engine/graphics/texture/sampler/SampleTraverser.js +0 -165
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Created by Alex on 04/05/2016.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { BufferAttribute, BufferGeometry, Vector2, Vector3 } from 'three';
|
|
6
|
-
import BufferedGeometryArraysBuilder from './BufferedGeometryArraysBuilder.js';
|
|
7
|
-
import { Face3, Geometry } from "three/examples/jsm/deprecated/Geometry.js";
|
|
8
|
-
|
|
9
|
-
const createFace = (function () {
|
|
10
|
-
const tempColors = [];
|
|
11
|
-
|
|
12
|
-
const cb = new Vector3(), ab = new Vector3();
|
|
13
|
-
|
|
14
|
-
function createFace(vertices, normals, a, b, c) {
|
|
15
|
-
//compute normal
|
|
16
|
-
const vA = vertices[a];
|
|
17
|
-
const vB = vertices[b];
|
|
18
|
-
const vC = vertices[c];
|
|
19
|
-
|
|
20
|
-
cb.subVectors(vC, vB);
|
|
21
|
-
ab.subVectors(vA, vB);
|
|
22
|
-
cb.cross(ab);
|
|
23
|
-
|
|
24
|
-
cb.normalize();
|
|
25
|
-
//
|
|
26
|
-
const f0 = new Face3(a, b, c, cb.clone(), tempColors);
|
|
27
|
-
//write vertex normals
|
|
28
|
-
const vnA = normals[a];
|
|
29
|
-
const vnB = normals[b];
|
|
30
|
-
const vnC = normals[c];
|
|
31
|
-
vnA.add(cb);
|
|
32
|
-
vnB.add(cb);
|
|
33
|
-
vnC.add(cb);
|
|
34
|
-
f0.vertexNormals = [vnA, vnB, vnC];
|
|
35
|
-
return f0;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return createFace;
|
|
39
|
-
})();
|
|
40
|
-
|
|
41
|
-
function buildGeometry(samplerHeight, position, size, scale, totalSize, resolution) {
|
|
42
|
-
const width = size.x;
|
|
43
|
-
const height = size.y;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const gridX1 = width * resolution;
|
|
47
|
-
const gridY1 = height * resolution;
|
|
48
|
-
|
|
49
|
-
const gridX2 = gridX1 - 1;
|
|
50
|
-
const gridY2 = gridY1 - 1;
|
|
51
|
-
|
|
52
|
-
const xScale = scale.x * (size.x / gridX2);
|
|
53
|
-
const yScale = scale.y * (size.y / gridY2);
|
|
54
|
-
|
|
55
|
-
let offset = 0;
|
|
56
|
-
|
|
57
|
-
const vertexCount = gridX1 * gridY1;
|
|
58
|
-
const geometry = new Geometry();
|
|
59
|
-
const vertices = geometry.vertices = new Array(vertexCount);
|
|
60
|
-
const vertexNormals = new Array(vertexCount);
|
|
61
|
-
const faces = geometry.faces = new Array(gridX2 * gridY2 * 2);
|
|
62
|
-
const tempUVs = new Array(vertexCount);
|
|
63
|
-
let y, x;
|
|
64
|
-
const vMultiplier = (size.y / totalSize.y) / gridY2;
|
|
65
|
-
const uMultiplier = (size.x / totalSize.x) / gridX2;
|
|
66
|
-
const vConst = position.y / totalSize.y;
|
|
67
|
-
const uConst = position.x / totalSize.x;
|
|
68
|
-
const posOffsetX = position.x * scale.x;
|
|
69
|
-
const posOffsetY = position.y * scale.y;
|
|
70
|
-
//fill vertices
|
|
71
|
-
for (y = 0; y < gridY1; y++) {
|
|
72
|
-
|
|
73
|
-
const v = y * vMultiplier + vConst;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
for (x = 0; x < gridX1; x++) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const u = x * uMultiplier + uConst;
|
|
80
|
-
//get sample
|
|
81
|
-
const val = samplerHeight.sample(u, v);
|
|
82
|
-
const v3 = new Vector3(x * xScale + posOffsetX, val, y * yScale + posOffsetY);
|
|
83
|
-
|
|
84
|
-
vertices[offset] = v3;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
tempUVs[offset] = new Vector2(u, 1 - v);
|
|
88
|
-
//normal sampling
|
|
89
|
-
//samplerNormal.sample(u, v, vertexNormal);
|
|
90
|
-
vertexNormals[offset] = new Vector3();
|
|
91
|
-
offset += 1;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
function addFace(a, b, c) {
|
|
97
|
-
const f0 = createFace(vertices, vertexNormals, a, b, c);
|
|
98
|
-
//
|
|
99
|
-
const f0uv = [tempUVs[a], tempUVs[b], tempUVs[c]];
|
|
100
|
-
faces[offset] = f0;
|
|
101
|
-
geometry.faceVertexUvs[0][offset] = f0uv;
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
offset = 0;
|
|
106
|
-
//add faces
|
|
107
|
-
for (y = 0; y < gridY2; y++) {
|
|
108
|
-
|
|
109
|
-
for (x = 0; x < gridX2; x++) {
|
|
110
|
-
const a = x + gridX1 * y;
|
|
111
|
-
const b = x + gridX1 * (y + 1);
|
|
112
|
-
const c = (x + 1) + gridX1 * (y + 1);
|
|
113
|
-
const d = (x + 1) + gridX1 * y;
|
|
114
|
-
addFace(a, b, d);
|
|
115
|
-
offset++;
|
|
116
|
-
addFace(b, c, d);
|
|
117
|
-
offset++;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
//normalize vertex normals
|
|
121
|
-
let i = 0;
|
|
122
|
-
const l = new Vector3().length;
|
|
123
|
-
for (; i < l; i++) {
|
|
124
|
-
new Vector3()[i].normalize();
|
|
125
|
-
}
|
|
126
|
-
geometry.vertexNormals = vertexNormals;
|
|
127
|
-
//CleanupGeometry(geometry);
|
|
128
|
-
return geometry;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
function buildBufferGeometry(samplerHeight, position, size, scale, totalSize, resolution) {
|
|
133
|
-
|
|
134
|
-
const arrays = BufferedGeometryArraysBuilder.build(samplerHeight, position, size, scale, totalSize, resolution);
|
|
135
|
-
|
|
136
|
-
const g = new BufferGeometry();
|
|
137
|
-
g.setIndex(new BufferAttribute(arrays.indices, 1));
|
|
138
|
-
g.setAttribute('position', new BufferAttribute(arrays.vertices, 3));
|
|
139
|
-
g.setAttribute('normal', new BufferAttribute(arrays.normals, 3));
|
|
140
|
-
g.setAttribute('uv', new BufferAttribute(arrays.uvs, 2));
|
|
141
|
-
|
|
142
|
-
//normalize vertex normals
|
|
143
|
-
// g.computeVertexNormals();
|
|
144
|
-
|
|
145
|
-
//CleanupGeometry(geometry);
|
|
146
|
-
return g;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export default {
|
|
150
|
-
buildGeometry: buildGeometry,
|
|
151
|
-
buildBufferGeometry: buildBufferGeometry
|
|
152
|
-
};
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
|
|
2
|
-
import { deserializeTexture } from "../../../graphics/texture/sampler/serialization/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({
|
|
45
|
-
path: heightMapURL,
|
|
46
|
-
type: GameAssetType.ArrayBuffer,
|
|
47
|
-
callback: assetObtained,
|
|
48
|
-
failure: reject
|
|
49
|
-
});
|
|
50
|
-
} else {
|
|
51
|
-
assetManager.get({
|
|
52
|
-
path: heightMapURL, type: GameAssetType.Image, callback: function (asset) {
|
|
53
|
-
const image = asset.create();
|
|
54
|
-
|
|
55
|
-
// plane
|
|
56
|
-
const imgWidth = image.width;
|
|
57
|
-
const imgHeight = image.height;
|
|
58
|
-
|
|
59
|
-
const samplerHeight = rgbaData2valueSampler2D(image.data, imgWidth, imgHeight, zRange, -zRange / 2);
|
|
60
|
-
|
|
61
|
-
fulfill(samplerHeight);
|
|
62
|
-
}, failure: reject
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Created by Alex on 14/07/2017.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { seededRandom } from "../../../../core/math/random/seededRandom.js";
|
|
6
|
-
import SampleTraverser from '../../../graphics/texture/sampler/SampleTraverser.js';
|
|
7
|
-
import Vector2 from '../../../../core/geom/Vector2.js';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
* @enum
|
|
13
|
-
*/
|
|
14
|
-
export const TerrainType = {
|
|
15
|
-
Grass: 0,
|
|
16
|
-
Sand: 1,
|
|
17
|
-
Rock: 2,
|
|
18
|
-
Dirt: 3
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
*
|
|
23
|
-
* @param {TerrainType} type
|
|
24
|
-
* @param {number} value
|
|
25
|
-
* @constructor
|
|
26
|
-
* @property {TerrainType} type
|
|
27
|
-
* @property {number} value
|
|
28
|
-
*/
|
|
29
|
-
function TerrainFeature(type, value) {
|
|
30
|
-
this.type = type;
|
|
31
|
-
this.value = value;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const index2typeMap = [
|
|
35
|
-
TerrainType.Rock,
|
|
36
|
-
TerrainType.Grass,
|
|
37
|
-
TerrainType.Sand,
|
|
38
|
-
TerrainType.Dirt
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
*
|
|
44
|
-
* @param {Terrain} terrain
|
|
45
|
-
* @param {AABB2} mask grid mask along the terrain
|
|
46
|
-
* @returns {Array.<TerrainFeature>}
|
|
47
|
-
*/
|
|
48
|
-
function classify(terrain, mask) {
|
|
49
|
-
|
|
50
|
-
const maskCenter = new Vector2(mask.x0 + mask.x1, mask.y0 + mask.y1).multiplyScalar(0.5).divide(terrain.size);
|
|
51
|
-
const maskSize = new Vector2(mask.getWidth(), mask.getHeight()).divide(terrain.size).length();
|
|
52
|
-
|
|
53
|
-
const maxSamples = 50;
|
|
54
|
-
|
|
55
|
-
const hash = maskCenter.hash();
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
*
|
|
59
|
-
* @type {SplatMapping}
|
|
60
|
-
*/
|
|
61
|
-
const splat = terrain.splat;
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
*
|
|
65
|
-
* @param {number} index
|
|
66
|
-
* @returns {TerrainFeature}
|
|
67
|
-
*/
|
|
68
|
-
function splat2feature(index) {
|
|
69
|
-
const type = index2typeMap[index];
|
|
70
|
-
|
|
71
|
-
let weight = 0;
|
|
72
|
-
let valueSum = 0;
|
|
73
|
-
|
|
74
|
-
const random = seededRandom(hash);
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
*
|
|
78
|
-
* @param {Number} u
|
|
79
|
-
* @param {Number} v
|
|
80
|
-
* @returns {number}
|
|
81
|
-
*/
|
|
82
|
-
function sampleVisitor(u, v) {
|
|
83
|
-
const sampleValue = splat.sampleWeight(u, v,index);
|
|
84
|
-
|
|
85
|
-
const delta = maskCenter._distanceTo(u, v);
|
|
86
|
-
|
|
87
|
-
const influence = (maskSize - delta) / maskSize;
|
|
88
|
-
|
|
89
|
-
valueSum += sampleValue * (influence * influence);
|
|
90
|
-
weight += influence;
|
|
91
|
-
|
|
92
|
-
return 0;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
SampleTraverser.traverseMask(random, mask, terrain.size, maxSamples, sampleVisitor);
|
|
96
|
-
|
|
97
|
-
return new TerrainFeature(type, valueSum / weight);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (splat === null) {
|
|
102
|
-
console.error("it appears splats are not loaded. Classification of terrain failed.");
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
*
|
|
107
|
-
* @type {TerrainFeature[]}
|
|
108
|
-
*/
|
|
109
|
-
const features = [];
|
|
110
|
-
|
|
111
|
-
for (let i = 0; i < 4; i++) {
|
|
112
|
-
const terrainFeature = splat2feature(i);
|
|
113
|
-
|
|
114
|
-
features.push(terrainFeature);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return features;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const TerrainClassifier = {
|
|
121
|
-
classify,
|
|
122
|
-
TerrainFeature
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
export default TerrainClassifier;
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Created by Alex on 30/10/2014.
|
|
3
|
-
*/
|
|
4
|
-
import QuadTree from '../../../../core/geom/2d/quad-tree/PointQuadTree.js';
|
|
5
|
-
import AABB2 from '../../../../core/geom/2d/aabb/AABB2.js';
|
|
6
|
-
import { seededRandom } from "../../../../core/math/random/seededRandom.js";
|
|
7
|
-
import { makeRangedRandom } from "../../../../core/math/random/makeRangedRandom.js";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const Point2 = function (x, y) {
|
|
11
|
-
this.x = x;
|
|
12
|
-
this.y = y;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
function makeFalse() {
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
*
|
|
22
|
-
* @param {function():number} random returns a number between 0 and 1
|
|
23
|
-
* @param {AABB2} mask
|
|
24
|
-
* @param {Vector2} size
|
|
25
|
-
* @param {number} count
|
|
26
|
-
* @param {function(u:number, v:number):number} callback return value controls how many more samples to add
|
|
27
|
-
*/
|
|
28
|
-
function traverseMask(random, mask, size, count, callback) {
|
|
29
|
-
|
|
30
|
-
const uRandom = makeRangedRandom(random, mask.x0 / size.x, mask.x1 / size.x);
|
|
31
|
-
const vRandom = makeRangedRandom(random, mask.y0 / size.y, mask.y1 / size.y);
|
|
32
|
-
|
|
33
|
-
for (let i = 0; i < count; i++) {
|
|
34
|
-
const u = uRandom();
|
|
35
|
-
const v = vRandom();
|
|
36
|
-
|
|
37
|
-
const extraSampleCount = callback(u, v);
|
|
38
|
-
|
|
39
|
-
i -= extraSampleCount;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* @property {AABB2} mask
|
|
45
|
-
* @property {PointQuadTree} quadTree
|
|
46
|
-
* @constructor
|
|
47
|
-
*/
|
|
48
|
-
const SampleTraverser = function () {
|
|
49
|
-
const self = this;
|
|
50
|
-
this.resolveSpace = false;
|
|
51
|
-
this.resolveSpaceSizeMin = 0;
|
|
52
|
-
this.quadTree = void 0;
|
|
53
|
-
|
|
54
|
-
this.mask = new AABB2(0, 0, 1, 1);
|
|
55
|
-
|
|
56
|
-
const random = seededRandom(1);
|
|
57
|
-
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
*
|
|
63
|
-
* @param {Sampler2D} densityMap
|
|
64
|
-
* @param {number} density
|
|
65
|
-
* @param {Vector2} size
|
|
66
|
-
* @param {function(u:number, v:number):void} visitorFunction
|
|
67
|
-
*/
|
|
68
|
-
function traverseSamples(densityMap, density, size, visitorFunction) {
|
|
69
|
-
let rejectSample = false;
|
|
70
|
-
let numRejectedSamples = 0;
|
|
71
|
-
|
|
72
|
-
function spaceCheck() {
|
|
73
|
-
numRejectedSamples++;
|
|
74
|
-
rejectSample = true;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const width = size.x;
|
|
78
|
-
const height = size.y;
|
|
79
|
-
let quadTree;
|
|
80
|
-
const resolveSpace = self.resolveSpace;
|
|
81
|
-
|
|
82
|
-
let resolveSpaceInsert;
|
|
83
|
-
|
|
84
|
-
if (resolveSpace) {
|
|
85
|
-
//convert size to normalized X,Y dimensions
|
|
86
|
-
const uvUnitWidth_2 = 0.5 / width;
|
|
87
|
-
const uvUnitHeight_2 = 0.5 / height;
|
|
88
|
-
//
|
|
89
|
-
if (self.quadTree === void 0) {
|
|
90
|
-
quadTree = new QuadTree(0, 0, 1, 1);
|
|
91
|
-
} else {
|
|
92
|
-
quadTree = self.quadTree;
|
|
93
|
-
}
|
|
94
|
-
resolveSpaceInsert = function (u, v, sampleSize) {
|
|
95
|
-
rejectSample = false;
|
|
96
|
-
const width = sampleSize * uvUnitWidth_2;
|
|
97
|
-
const height = sampleSize * uvUnitHeight_2;
|
|
98
|
-
quadTree.traverseRect(u - width, v - height, u + width, v + height, spaceCheck);
|
|
99
|
-
//
|
|
100
|
-
if (rejectSample) {
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
quadTree.insert(new Point2(u, v));
|
|
104
|
-
|
|
105
|
-
return false;
|
|
106
|
-
};
|
|
107
|
-
} else {
|
|
108
|
-
resolveSpaceInsert = makeFalse;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const mask = self.mask;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const count = density * mask.getWidth() * mask.getHeight();
|
|
115
|
-
|
|
116
|
-
let samplesPlaced = 0;
|
|
117
|
-
//
|
|
118
|
-
const sampleSizeMin = self.resolveSpaceSizeMin;
|
|
119
|
-
const sampleSizeRange = (self.resolveSpaceSizeMax - self.resolveSpaceSizeMin);
|
|
120
|
-
|
|
121
|
-
function pickSampleSize() {
|
|
122
|
-
return sampleSizeMin + random() * sampleSizeRange;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
let rejectedSampleBudget = count * 0.2;
|
|
126
|
-
|
|
127
|
-
traverseMask(random, mask, size, count, function (u, v) {
|
|
128
|
-
|
|
129
|
-
//check tap against density map
|
|
130
|
-
const densityValue = densityMap.sample(u, v);
|
|
131
|
-
if (densityValue === 0) {
|
|
132
|
-
//0 chance
|
|
133
|
-
return 0;
|
|
134
|
-
}
|
|
135
|
-
const densityRoll = random();
|
|
136
|
-
if (densityRoll > densityValue) {
|
|
137
|
-
//probability roll against density value failed
|
|
138
|
-
return 0;
|
|
139
|
-
}
|
|
140
|
-
const sampleSize = pickSampleSize();
|
|
141
|
-
const spaceResolutionCheck = resolveSpaceInsert(u, v, sampleSize);
|
|
142
|
-
if (spaceResolutionCheck === true) {
|
|
143
|
-
//reject sample
|
|
144
|
-
if (rejectedSampleBudget-- > 0) {
|
|
145
|
-
return 1;
|
|
146
|
-
} else {
|
|
147
|
-
//skip sample
|
|
148
|
-
return 0;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
samplesPlaced++;
|
|
152
|
-
visitorFunction(u, v, sampleSize);
|
|
153
|
-
|
|
154
|
-
return 0;
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
// console.log(numRejectedSamples, " samples rejected, ", samplesPlaced, " samples placed, tries: ", count);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
this.traverse = traverseSamples;
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
SampleTraverser.traverseMask = traverseMask;
|
|
164
|
-
|
|
165
|
-
export default SampleTraverser;
|