@woosh/meep-engine 2.33.5 → 2.33.6
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/collection/RingBuffer.js +40 -10
- package/core/collection/array/typed/typed_array_copy.js +2 -2
- package/core/geom/3d/aabb/aabb3_compute_projected_area.js +5 -4
- package/core/process/undo/ActionProcessor.d.ts +2 -0
- package/core/process/undo/ActionProcessor.js +59 -1
- package/core/process/undo/ActionProcessor.spec.js +59 -0
- package/core/process/undo/Mark.js +2 -1
- package/engine/asset/loaders/material/bitmap2sampler_gl.js +19 -0
- package/engine/asset/loaders/material/computeImageBitmapEquality.js +7 -19
- package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +25 -16
- package/engine/graphics/material/SplatMaterial.js +4 -97
- package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +1 -5
- package/engine/graphics/micron/build/fill_patch_geometry_data.js +2 -0
- package/engine/graphics/micron/format/MicronGeometryPatch.js +11 -3
- package/engine/graphics/micron/format/MicronVertexDataSpec.js +25 -3
- package/engine/graphics/micron/render/VirtualGeometryBuilder.js +24 -8
- package/engine/graphics/micron/render/refinement/ActivePatchList.js +6 -25
- package/engine/graphics/micron/render/refinement/RefinementSpec.js +98 -0
- package/engine/graphics/micron/render/refinement/array_normalize_plane.js +25 -0
- package/engine/graphics/micron/render/refinement/array_setFromProjectionMatrix.js +60 -0
- package/engine/graphics/micron/render/v1/MaterialVertexSpec.js +21 -0
- package/engine/graphics/micron/render/v1/VGThreeRenderer.js +12 -9
- package/engine/graphics/render/buffer/buffers/ColorAndDepthFrameBuffer.js +5 -3
- package/engine/graphics/render/forward_plus/prototypeLightManager.js +1 -1
- package/engine/graphics/render/visibility/hiz/prototypeHiZ.js +1 -1
- package/engine/graphics/shadows/ShadowMapRenderer.js +12 -2
- package/engine/graphics/texture/cubemap/load_environment_map.js +29 -3
- package/engine/graphics/texture/sampler/Sampler2D.js +18 -62
- package/engine/graphics/texture/sampler/debug/paintSamplerOnHTML.js +3 -2
- package/engine/graphics/texture/sampler/differenceSampler.js +31 -0
- package/engine/graphics/texture/sampler/typedArrayConstructorByInstance.js +25 -0
- package/engine/graphics/texture/sampler/util/drawSamplerHTML.js +3 -2
- package/package.json +1 -1
- package/view/minimap/gl/MinimapMarkersGL.js +2 -2
- package/engine/graphics/micron/render/RefinementSpec.js +0 -181
|
@@ -7,14 +7,32 @@ export class RingBuffer {
|
|
|
7
7
|
* @constructor
|
|
8
8
|
*/
|
|
9
9
|
constructor(size) {
|
|
10
|
-
assert.
|
|
10
|
+
assert.isNumber(size, 'size');
|
|
11
11
|
assert.greaterThan(size, 0, `size`);
|
|
12
|
+
assert.isNonNegativeInteger(size, 'size');
|
|
12
13
|
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @type {number}
|
|
17
|
+
*/
|
|
13
18
|
this.size = size;
|
|
14
19
|
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
* @type {number}
|
|
23
|
+
*/
|
|
15
24
|
this.head = 0;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
*
|
|
28
|
+
* @type {number}
|
|
29
|
+
*/
|
|
16
30
|
this.tail = 0;
|
|
17
31
|
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
* @type {number}
|
|
35
|
+
*/
|
|
18
36
|
this.count = 0;
|
|
19
37
|
|
|
20
38
|
/**
|
|
@@ -62,13 +80,15 @@ export class RingBuffer {
|
|
|
62
80
|
|
|
63
81
|
this.data[head] = element;
|
|
64
82
|
|
|
65
|
-
const
|
|
83
|
+
const size = this.size;
|
|
84
|
+
|
|
85
|
+
const newHead = (head + 1) % size;
|
|
66
86
|
|
|
67
87
|
this.head = newHead;
|
|
68
88
|
|
|
69
|
-
if (this.count ===
|
|
89
|
+
if (this.count === size) {
|
|
70
90
|
//update tail
|
|
71
|
-
this.tail = (this.tail + 1) %
|
|
91
|
+
this.tail = (this.tail + 1) % size;
|
|
72
92
|
} else {
|
|
73
93
|
this.count++;
|
|
74
94
|
}
|
|
@@ -130,11 +150,15 @@ export class RingBuffer {
|
|
|
130
150
|
* @returns {V|undefined}
|
|
131
151
|
*/
|
|
132
152
|
removeIf(condition, thisArg) {
|
|
153
|
+
const count = this.count;
|
|
154
|
+
const size = this.size;
|
|
133
155
|
|
|
134
|
-
|
|
135
|
-
|
|
156
|
+
const tail = this.tail;
|
|
157
|
+
const data = this.data;
|
|
136
158
|
|
|
137
|
-
|
|
159
|
+
for (let i = 0; i < count; i++) {
|
|
160
|
+
const index = (tail + i) % size;
|
|
161
|
+
const el = data[index];
|
|
138
162
|
|
|
139
163
|
if (condition.call(thisArg, el)) {
|
|
140
164
|
|
|
@@ -151,10 +175,16 @@ export class RingBuffer {
|
|
|
151
175
|
* @param {*} [thisArg]
|
|
152
176
|
*/
|
|
153
177
|
forEach(visitor, thisArg) {
|
|
154
|
-
|
|
155
|
-
|
|
178
|
+
const count = this.count;
|
|
179
|
+
const size = this.size;
|
|
180
|
+
|
|
181
|
+
const tail = this.tail;
|
|
182
|
+
const data = this.data;
|
|
183
|
+
|
|
184
|
+
for (let i = 0; i < count; i++) {
|
|
156
185
|
|
|
157
|
-
const
|
|
186
|
+
const index = (tail + i) % size;
|
|
187
|
+
const el = data[index];
|
|
158
188
|
|
|
159
189
|
visitor.call(thisArg, el);
|
|
160
190
|
}
|
|
@@ -3,8 +3,8 @@ import { array_copy } from "../copyArray.js";
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
*
|
|
6
|
-
* @param {TypedArray} source
|
|
7
|
-
* @param {TypedArray} destination
|
|
6
|
+
* @param {TypedArray|Float32Array} source
|
|
7
|
+
* @param {TypedArray|Float32Array} destination
|
|
8
8
|
*/
|
|
9
9
|
export function typed_array_copy(source, destination) {
|
|
10
10
|
const destination_size = destination.length;
|
|
@@ -56,7 +56,7 @@ export function aabb3_project_to_2d(aabb_corners, projection_matrix) {
|
|
|
56
56
|
const t_w = a3 * _x + b3 * _y + c3 * _z + d3;
|
|
57
57
|
|
|
58
58
|
// perspective divide and normalization (-1,1 space projected to -0.5,0.5)
|
|
59
|
-
const d = 0.5 /
|
|
59
|
+
const d = 0.5 / t_w;
|
|
60
60
|
|
|
61
61
|
// finally compute screen-space coordinates of the corner
|
|
62
62
|
const x = t_x * d;
|
|
@@ -65,13 +65,14 @@ export function aabb3_project_to_2d(aabb_corners, projection_matrix) {
|
|
|
65
65
|
if (x0 > x) {
|
|
66
66
|
x0 = x;
|
|
67
67
|
}
|
|
68
|
-
if (y0 > y) {
|
|
69
|
-
y0 = y;
|
|
70
|
-
}
|
|
71
68
|
|
|
72
69
|
if (x1 < x) {
|
|
73
70
|
x1 = x;
|
|
74
71
|
}
|
|
72
|
+
|
|
73
|
+
if (y0 > y) {
|
|
74
|
+
y0 = y;
|
|
75
|
+
}
|
|
75
76
|
if (y1 < y) {
|
|
76
77
|
y1 = y;
|
|
77
78
|
}
|
|
@@ -202,6 +202,64 @@ export class ActionProcessor {
|
|
|
202
202
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Navigate to a specific mark back or forward
|
|
207
|
+
* @param {M} mark_descriptor specific mark description
|
|
208
|
+
* @returns {boolean} true on success, false otherwise (e.g. mark not found)
|
|
209
|
+
* @throws {Error} when mark is non-unique
|
|
210
|
+
*/
|
|
211
|
+
navigateTo(mark_descriptor) {
|
|
212
|
+
// find all matching marks
|
|
213
|
+
const matching_marks = this.marks.filter(m => m.description === mark_descriptor);
|
|
214
|
+
|
|
215
|
+
if (matching_marks.length === 0) {
|
|
216
|
+
// not found
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (matching_marks.length > 1) {
|
|
221
|
+
throw new Error(`Attempting to navigate to a non-unique mark descriptor '${mark_descriptor}'. Mark descriptor must be unique, instead ${matching_marks.length} matches were found`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const match = matching_marks[0];
|
|
225
|
+
|
|
226
|
+
const target = match.index;
|
|
227
|
+
|
|
228
|
+
let temp_cursor = this.cursor;
|
|
229
|
+
|
|
230
|
+
if (target > this.cursor) {
|
|
231
|
+
|
|
232
|
+
while (target > this.cursor) {
|
|
233
|
+
// navigate forward
|
|
234
|
+
this.redo();
|
|
235
|
+
|
|
236
|
+
if (temp_cursor === this.cursor) {
|
|
237
|
+
// no cursor change
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
temp_cursor = this.cursor;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
} else if (target < this.cursor) {
|
|
245
|
+
|
|
246
|
+
while (target < this.cursor) {
|
|
247
|
+
// navigate backwards
|
|
248
|
+
this.undo();
|
|
249
|
+
|
|
250
|
+
if (temp_cursor === this.cursor) {
|
|
251
|
+
// no cursor change
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
temp_cursor = this.cursor;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
|
|
205
263
|
undo() {
|
|
206
264
|
let markAddress = 0;
|
|
207
265
|
/**
|
|
@@ -226,7 +284,7 @@ export class ActionProcessor {
|
|
|
226
284
|
markAddress = 0;
|
|
227
285
|
}
|
|
228
286
|
|
|
229
|
-
//keep rewinding until we hit mark
|
|
287
|
+
//keep rewinding until we hit a mark
|
|
230
288
|
while (this.cursor > markAddress && this.cursor > 0) {
|
|
231
289
|
this.cursor--;
|
|
232
290
|
const action = this.history.get(this.cursor);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { ActionProcessor } from "./ActionProcessor.js";
|
|
2
|
+
import { Action } from "./Action.js";
|
|
3
|
+
|
|
4
|
+
class DummyContext {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.value = 0;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
class DummyAction extends Action {
|
|
11
|
+
apply(context) {
|
|
12
|
+
// do nothing
|
|
13
|
+
context.value++;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
revert(context) {
|
|
17
|
+
context.value--;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
test('navigateTo backwards', () => {
|
|
22
|
+
const ctx = new DummyContext();
|
|
23
|
+
const ap = new ActionProcessor(ctx);
|
|
24
|
+
|
|
25
|
+
ap.mark('a');
|
|
26
|
+
ap.do(new DummyAction());
|
|
27
|
+
ap.mark('b');
|
|
28
|
+
ap.do(new DummyAction());
|
|
29
|
+
|
|
30
|
+
expect(ap.navigateTo('a')).toBe(true);
|
|
31
|
+
|
|
32
|
+
expect(ctx.value).toBe(0);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('navigateTo forward', () => {
|
|
36
|
+
const ctx = new DummyContext();
|
|
37
|
+
const ap = new ActionProcessor(ctx);
|
|
38
|
+
|
|
39
|
+
ap.mark('a');
|
|
40
|
+
ap.do(new DummyAction());
|
|
41
|
+
ap.mark('b');
|
|
42
|
+
ap.do(new DummyAction());
|
|
43
|
+
ap.mark('c');
|
|
44
|
+
|
|
45
|
+
ap.undo();
|
|
46
|
+
ap.undo();
|
|
47
|
+
ap.undo();
|
|
48
|
+
|
|
49
|
+
expect(ap.navigateTo('c')).toBe(true);
|
|
50
|
+
|
|
51
|
+
expect(ctx.value).toBe(2);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('navigateTo non-existent on empty', () => {
|
|
55
|
+
const ctx = new DummyContext();
|
|
56
|
+
const ap = new ActionProcessor(ctx);
|
|
57
|
+
|
|
58
|
+
expect(ap.navigateTo('a')).toBe(false);
|
|
59
|
+
});
|
|
@@ -8,13 +8,14 @@ export class Mark {
|
|
|
8
8
|
* @constructor
|
|
9
9
|
*/
|
|
10
10
|
constructor(index, description) {
|
|
11
|
-
assert.
|
|
11
|
+
assert.isNumber(index, 'index');
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
*
|
|
15
15
|
* @type {number}
|
|
16
16
|
*/
|
|
17
17
|
this.index = index;
|
|
18
|
+
|
|
18
19
|
/**
|
|
19
20
|
*
|
|
20
21
|
* @type {D}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {WebGL2RenderingContext} gl
|
|
4
|
+
* @param {Sampler2D} sampler
|
|
5
|
+
* @param {ImageBitmap} bitmap
|
|
6
|
+
*/
|
|
7
|
+
export function bitmap2sampler_gl(gl, sampler, bitmap) {
|
|
8
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);
|
|
9
|
+
gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
|
|
10
|
+
|
|
11
|
+
const w = sampler.width;
|
|
12
|
+
const h = sampler.height;
|
|
13
|
+
|
|
14
|
+
if (sampler.itemSize !== 4) {
|
|
15
|
+
throw new Error(`Expected sampler.itemSize to be 4, instead was '${sampler.itemSize}'`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, sampler.data);
|
|
19
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Sampler2D } from "../../../graphics/texture/sampler/Sampler2D.js";
|
|
2
2
|
import { assert } from "../../../../core/assert.js";
|
|
3
3
|
import { isArrayEqualStrict } from "../../../../core/collection/array/isArrayEqualStrict.js";
|
|
4
|
+
import { bitmap2sampler_gl } from "./bitmap2sampler_gl.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
*
|
|
@@ -8,23 +9,6 @@ import { isArrayEqualStrict } from "../../../../core/collection/array/isArrayEqu
|
|
|
8
9
|
*/
|
|
9
10
|
const sampler_cache = new WeakMap();
|
|
10
11
|
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
* @param {WebGL2RenderingContext} gl
|
|
14
|
-
* @param {Sampler2D} sampler
|
|
15
|
-
* @param {ImageBitmap} bitmap
|
|
16
|
-
*/
|
|
17
|
-
function bitmap2sampler_gl(gl, sampler, bitmap) {
|
|
18
|
-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);
|
|
19
|
-
gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
|
|
20
|
-
|
|
21
|
-
const data = new Uint8Array(sampler.width * sampler.height * 4);
|
|
22
|
-
|
|
23
|
-
gl.readPixels(0, 0, sampler.width, sampler.height, gl.RGBA, gl.UNSIGNED_BYTE, data);
|
|
24
|
-
|
|
25
|
-
sampler.data = data;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
12
|
/**
|
|
29
13
|
*
|
|
30
14
|
* @param {ImageBitmap} bitmap
|
|
@@ -45,7 +29,7 @@ function obtainSampler(bitmap, ctx) {
|
|
|
45
29
|
const width = bitmap.width;
|
|
46
30
|
const height = bitmap.height;
|
|
47
31
|
|
|
48
|
-
const sampler =
|
|
32
|
+
const sampler = Sampler2D.uint8(4, width, height);
|
|
49
33
|
|
|
50
34
|
bitmap2sampler_gl(ctx, sampler, bitmap);
|
|
51
35
|
|
|
@@ -75,15 +59,19 @@ function obtainCanvasCtx(width, height) {
|
|
|
75
59
|
|
|
76
60
|
if (ctx_ref === null || (gl = ctx_ref.deref()) === undefined) {
|
|
77
61
|
const canvas = document.createElement('canvas');
|
|
62
|
+
|
|
78
63
|
gl = canvas.getContext("webgl2");
|
|
79
64
|
gl.activeTexture(gl.TEXTURE0);
|
|
65
|
+
|
|
80
66
|
const texture = gl.createTexture();
|
|
67
|
+
|
|
81
68
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
69
|
+
|
|
82
70
|
const framebuffer = gl.createFramebuffer();
|
|
71
|
+
|
|
83
72
|
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
|
84
73
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
|
85
74
|
|
|
86
|
-
|
|
87
75
|
ctx_ref = new WeakRef(gl);
|
|
88
76
|
}
|
|
89
77
|
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
import ThreeFactory from "../../three/ThreeFactory.js";
|
|
9
9
|
import { StaticMaterialCache } from "../../../asset/loaders/material/StaticMaterialCache.js";
|
|
10
10
|
import { composeCompile } from "../../material/composeCompile.js";
|
|
11
|
+
import { typed_array_copy } from "../../../../core/collection/array/typed/typed_array_copy.js";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
*
|
|
@@ -29,14 +30,14 @@ function InstancedMeshGroup() {
|
|
|
29
30
|
* Minimum spare capacity increase during growing
|
|
30
31
|
* @type {number}
|
|
31
32
|
*/
|
|
32
|
-
this.growConstant =
|
|
33
|
+
this.growConstant = 4;
|
|
33
34
|
|
|
34
|
-
this.shrinkFactor = 0.
|
|
35
|
+
this.shrinkFactor = 0.5;
|
|
35
36
|
/**
|
|
36
37
|
* Minimum capacity reduction for shrinkage to occur
|
|
37
38
|
* @type {number}
|
|
38
39
|
*/
|
|
39
|
-
this.shrinkConstant =
|
|
40
|
+
this.shrinkConstant = 64;
|
|
40
41
|
|
|
41
42
|
/**
|
|
42
43
|
*
|
|
@@ -217,14 +218,30 @@ InstancedMeshGroup.prototype.setCapacity = function (size) {
|
|
|
217
218
|
* @param {number} size
|
|
218
219
|
*/
|
|
219
220
|
InstancedMeshGroup.prototype.ensureCapacity = function (size) {
|
|
221
|
+
|
|
220
222
|
const currentCapacity = this.capacity;
|
|
223
|
+
|
|
221
224
|
if (currentCapacity < size) {
|
|
222
|
-
|
|
225
|
+
// grow
|
|
226
|
+
|
|
227
|
+
const newCapacityRaw = Math.max(
|
|
228
|
+
size,
|
|
229
|
+
currentCapacity * this.growFactor,
|
|
230
|
+
currentCapacity + this.growConstant
|
|
231
|
+
);
|
|
232
|
+
|
|
223
233
|
const newCapacityInteger = Math.ceil(newCapacityRaw);
|
|
234
|
+
|
|
224
235
|
this.setCapacity(newCapacityInteger);
|
|
225
|
-
|
|
236
|
+
|
|
237
|
+
} else if (
|
|
238
|
+
currentCapacity * this.shrinkFactor > size
|
|
239
|
+
&& currentCapacity - this.shrinkConstant > size
|
|
240
|
+
) {
|
|
241
|
+
// shrink
|
|
226
242
|
this.setCapacity(size);
|
|
227
243
|
}
|
|
244
|
+
|
|
228
245
|
};
|
|
229
246
|
|
|
230
247
|
/**
|
|
@@ -375,14 +392,6 @@ InstancedMeshGroup.prototype.remove = function (reference) {
|
|
|
375
392
|
this.setCount(this.count - 1);
|
|
376
393
|
};
|
|
377
394
|
|
|
378
|
-
/**
|
|
379
|
-
* @param {Uint8Array|Uint16Array|Uint32Array|Int8Array|Int16Array|Int32Array|Float32Array|Float64Array} source
|
|
380
|
-
* @param {Uint8Array|Uint16Array|Uint32Array|Int8Array|Int16Array|Int32Array|Float32Array|Float64Array}target
|
|
381
|
-
*/
|
|
382
|
-
function copyArray(source, target) {
|
|
383
|
-
target.set(source.subarray(0, Math.min(target.length, source.length)), 0)
|
|
384
|
-
}
|
|
385
|
-
|
|
386
395
|
InstancedMeshGroup.prototype.build = function () {
|
|
387
396
|
if (this.__threeGeometry !== null) {
|
|
388
397
|
// dispose old geometry's GPU memory
|
|
@@ -415,16 +424,16 @@ InstancedMeshGroup.prototype.build = function () {
|
|
|
415
424
|
if (this.__attributePosition !== null) {
|
|
416
425
|
//copy old data
|
|
417
426
|
const oldPositionArray = this.__attributePosition.array;
|
|
418
|
-
|
|
427
|
+
typed_array_copy(oldPositionArray, newPositionArray);
|
|
419
428
|
}
|
|
420
429
|
if (this.__attributeRotation !== null) {
|
|
421
430
|
//copy old data
|
|
422
431
|
const oldRotationArray = this.__attributeRotation.array;
|
|
423
|
-
|
|
432
|
+
typed_array_copy(oldRotationArray, newRotationArray);
|
|
424
433
|
}
|
|
425
434
|
if (this.__attributeScale !== null) {
|
|
426
435
|
const oldScaleArray = this.__attributeScale.array;
|
|
427
|
-
|
|
436
|
+
typed_array_copy(oldScaleArray, newScaleArray);
|
|
428
437
|
|
|
429
438
|
if (newScaleArray.length > oldScaleArray.length) {
|
|
430
439
|
//fill the rest of the array with scale factor of 1 as a default
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import {
|
|
5
5
|
ClampToEdgeWrapping,
|
|
6
6
|
Color,
|
|
7
|
-
|
|
7
|
+
FrontSide,
|
|
8
8
|
GLSL3,
|
|
9
9
|
LinearFilter,
|
|
10
10
|
NormalBlending,
|
|
@@ -15,95 +15,10 @@ import {
|
|
|
15
15
|
Vector4 as ThreeVector4
|
|
16
16
|
} from 'three';
|
|
17
17
|
import TerrainShader from "../shaders/TerrainShader.js";
|
|
18
|
-
import Vector4 from "../../../core/geom/Vector4.js";
|
|
19
18
|
import { Sampler2D } from "../texture/sampler/Sampler2D.js";
|
|
20
19
|
import sampler2D2Texture from "../texture/sampler/Sampler2D2Texture.js";
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
*
|
|
24
|
-
* @param {Vector4} tex0
|
|
25
|
-
* @param {Vector4} tex1
|
|
26
|
-
* @param {Vector4} tex2
|
|
27
|
-
* @param {Vector4} tex3
|
|
28
|
-
* @param {Vector4} splat
|
|
29
|
-
* @param {Vector4} result
|
|
30
|
-
*/
|
|
31
|
-
export function blendSplatTextures(tex0, tex1, tex2, tex3, splat, result) {
|
|
32
|
-
const b0 = splat.x;
|
|
33
|
-
const b1 = splat.y;
|
|
34
|
-
const b2 = splat.z;
|
|
35
|
-
const b3 = splat.w;
|
|
36
|
-
|
|
37
|
-
const bT = b0 + b1 + b2 + b3;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
result.set(
|
|
41
|
-
(tex0.x * b0 + tex1.x * b1 + tex2.x * b2 + tex3.x * b3) / bT,
|
|
42
|
-
(tex0.y * b0 + tex1.y * b1 + tex2.y * b2 + tex3.y * b3) / bT,
|
|
43
|
-
(tex0.z * b0 + tex1.z * b1 + tex2.z * b2 + tex3.z * b3) / bT,
|
|
44
|
-
(tex0.w * b0 + tex1.w * b1 + tex2.w * b2 + tex3.w * b3) / bT
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
*
|
|
50
|
-
* @param {Sampler2D[]} diffuse
|
|
51
|
-
* @param {Vector2} diffuseRepeat
|
|
52
|
-
* @param {Sampler2D} splat
|
|
53
|
-
* @param {Vector2} gridSize
|
|
54
|
-
* @param {Vector2} resultTextureSize
|
|
55
|
-
* @returns {Sampler2D}
|
|
56
|
-
*/
|
|
57
|
-
export function buildTerrainTexture({ diffuse, diffuseRepeat, splat, gridSize, resultTextureSize }) {
|
|
58
|
-
const texture0 = diffuse[0];
|
|
59
|
-
const texture1 = diffuse[1];
|
|
60
|
-
const texture2 = diffuse[2];
|
|
61
|
-
const texture3 = diffuse[3];
|
|
62
|
-
|
|
63
|
-
const resultData = new Uint8Array(resultTextureSize.x * resultTextureSize.y * 4);
|
|
64
|
-
|
|
65
|
-
const result = new Sampler2D(resultData, 4, resultTextureSize.x, resultTextureSize.y);
|
|
66
|
-
|
|
67
|
-
//do the splatting
|
|
68
|
-
let x, y, u, v;
|
|
69
|
-
|
|
70
|
-
const tex0 = new Vector4(0, 0, 0, 0);
|
|
71
|
-
const tex1 = new Vector4(0, 0, 0, 0);
|
|
72
|
-
const tex2 = new Vector4(0, 0, 0, 0);
|
|
73
|
-
const tex3 = new Vector4(0, 0, 0, 0);
|
|
74
|
-
|
|
75
|
-
const vSplat = new Vector4(0, 0, 0, 0);
|
|
76
|
-
|
|
77
|
-
const vTemp = new Vector4(0, 0, 0, 0);
|
|
78
|
-
|
|
79
|
-
for (x = 0; x < resultTextureSize.x; x++) {
|
|
80
|
-
|
|
81
|
-
u = x / (resultTextureSize.x - 1);
|
|
82
|
-
|
|
83
|
-
for (y = 0; y < resultTextureSize.y; y++) {
|
|
84
|
-
|
|
85
|
-
v = y / (resultTextureSize.y - 1);
|
|
86
|
-
|
|
87
|
-
const dU = (u * diffuseRepeat.x) % 1;
|
|
88
|
-
const dV = (v * diffuseRepeat.y) % 1;
|
|
89
|
-
|
|
90
|
-
texture0.sample(dU, dV, tex0);
|
|
91
|
-
texture1.sample(dU, dV, tex1);
|
|
92
|
-
texture2.sample(dU, dV, tex2);
|
|
93
|
-
texture3.sample(dU, dV, tex3);
|
|
94
|
-
|
|
95
|
-
splat.sample(u, v, vSplat);
|
|
96
|
-
|
|
97
|
-
blendSplatTextures(tex0, tex1, tex2, tex3, vSplat, vTemp);
|
|
98
|
-
|
|
99
|
-
result.set(x, y, [vTemp.x, vTemp.y, vTemp.z, 255]);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return result;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function whitePixelTexture() {
|
|
21
|
+
export function whitePixelTexture() {
|
|
107
22
|
const sampler = Sampler2D.uint8(4, 1, 1);
|
|
108
23
|
|
|
109
24
|
for (let i = 0; i < sampler.data.length; i++) {
|
|
@@ -205,17 +120,12 @@ export function SplatMaterial(
|
|
|
205
120
|
uniforms.gridResolution.value.set(gridResolution.x, gridResolution.y);
|
|
206
121
|
}
|
|
207
122
|
|
|
208
|
-
|
|
209
|
-
//this is for the water shader, so that back of the terrain reflects in the water, otherwise edges of shoreline look odd
|
|
210
|
-
//TODO check how this can be removed, it would speed water(and ordinary) rendering if back faces could be culled
|
|
211
|
-
const side = DoubleSide;
|
|
212
|
-
|
|
213
123
|
const sm = new ShaderMaterial({
|
|
214
124
|
|
|
215
125
|
uniforms: uniforms,
|
|
216
126
|
vertexShader: TerrainShader.vertexShader,
|
|
217
127
|
fragmentShader: TerrainShader.fragmentShader,
|
|
218
|
-
side:
|
|
128
|
+
side: FrontSide,
|
|
219
129
|
blending: NormalBlending,
|
|
220
130
|
depthTest: true,
|
|
221
131
|
depthWrite: true,
|
|
@@ -249,11 +159,8 @@ export function SplatMaterial(
|
|
|
249
159
|
sm.aoMap = true;
|
|
250
160
|
uniforms.aoMap.value = lightMap;
|
|
251
161
|
uniforms.aoMapIntensity.value = 0.7;
|
|
252
|
-
//
|
|
253
|
-
// sm.lightMap = true;
|
|
254
|
-
// uniforms.lightMap.value = options.lightMap;
|
|
255
|
-
// uniforms.lightMapIntensity.value = 1;
|
|
256
162
|
}
|
|
163
|
+
|
|
257
164
|
sm.extensions.derivatives = true; //needed for rendering grid
|
|
258
165
|
sm.needsUpdate = true;
|
|
259
166
|
|
|
@@ -4,7 +4,6 @@ import { MicronGeometry } from "../format/MicronGeometry.js";
|
|
|
4
4
|
import { buildAbstractPatchHierarchy } from "./hierarchy/buildAbstractPatchHierarchy.js";
|
|
5
5
|
import { MicronGeometryBufferAttributeSpec } from "../format/MicronGeometryBufferAttributeSpec.js";
|
|
6
6
|
import { typedArrayToDataType } from "../../../../core/collection/array/typedArrayToDataType.js";
|
|
7
|
-
import { RowFirstTableSpec } from "../../../../core/collection/table/RowFirstTableSpec.js";
|
|
8
7
|
import { DataType } from "../../../../core/collection/table/DataType.js";
|
|
9
8
|
import { MicronGeometryPatch } from "../format/MicronGeometryPatch.js";
|
|
10
9
|
import { build_clustering_info } from "./debug/build_clustering_info.js";
|
|
@@ -202,11 +201,8 @@ export async function buildMicronGeometryFromBufferGeometry(input) {
|
|
|
202
201
|
// console.time('build geometry');
|
|
203
202
|
|
|
204
203
|
const vertex_attributes = attributes_from_buffer_geometry(input);
|
|
205
|
-
const data_types = buildVertexDataTypeMap(vertex_attributes);
|
|
206
|
-
const vertex_data_spec = RowFirstTableSpec.get(data_types);
|
|
207
204
|
|
|
208
|
-
r.vertex_spec.
|
|
209
|
-
r.vertex_spec.attributes = vertex_attributes;
|
|
205
|
+
r.vertex_spec.setAttributes(vertex_attributes);
|
|
210
206
|
r.root = compilePatchGraph(root, input, r.vertex_spec);
|
|
211
207
|
|
|
212
208
|
r.initialize();
|
|
@@ -198,6 +198,8 @@ export function fill_patch_geometry_data(result, buffer_geometry, topo, vertex_d
|
|
|
198
198
|
const micron_attributes = vertex_data_spec.attributes;
|
|
199
199
|
const attribute_count = micron_attributes.length;
|
|
200
200
|
|
|
201
|
+
//TODO create a single ArrayBuffer for all attributes to get better cache coherence for rendering
|
|
202
|
+
|
|
201
203
|
for (let i = 0; i < attribute_count; i++) {
|
|
202
204
|
const attribute_spec = micron_attributes[i];
|
|
203
205
|
|
|
@@ -13,22 +13,30 @@ export class MicronGeometryPatch {
|
|
|
13
13
|
*/
|
|
14
14
|
this.id = 0;
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Continuous memory region for various pieces of data to get better memory access patterns
|
|
18
|
+
* All pieces of data end up in a continuous piece of memory, resulting in better cache coherence
|
|
19
|
+
* @type {ArrayBuffer}
|
|
20
|
+
*/
|
|
21
|
+
const array_buffer = new ArrayBuffer((6 + 6 + 24) * 4);
|
|
22
|
+
|
|
16
23
|
/**
|
|
17
24
|
* Bounds are used to determine screen error and whether a patch should be subdivided or not for rendering
|
|
18
25
|
* @type {number[]}
|
|
19
26
|
*/
|
|
20
|
-
this.bounding_box = new Float32Array(6);
|
|
27
|
+
this.bounding_box = new Float32Array(array_buffer, 0, 6);
|
|
21
28
|
|
|
22
29
|
/**
|
|
23
30
|
*
|
|
24
31
|
* @type {number[]|Float32Array}
|
|
25
32
|
*/
|
|
26
|
-
this.group_bounding_box = new Float32Array(6);
|
|
33
|
+
this.group_bounding_box = new Float32Array(array_buffer, 6 * 4, 6);
|
|
34
|
+
|
|
27
35
|
/**
|
|
28
36
|
*
|
|
29
37
|
* @type {number[]|Float32Array}
|
|
30
38
|
*/
|
|
31
|
-
this.group_bounding_box_corners = new Float32Array(24);
|
|
39
|
+
this.group_bounding_box_corners = new Float32Array(array_buffer, 12 * 4, 24);
|
|
32
40
|
|
|
33
41
|
/**
|
|
34
42
|
*
|