@woosh/meep-engine 2.39.43 → 2.40.1
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/binary/BinaryBuffer.js +14 -1
- package/core/bvh2/aabb3/AABB3.js +0 -133
- package/core/bvh2/aabb3/aabb3_intersects_line_segment.js +1 -1
- package/core/geom/3d/matrix/MATRIX_4_IDENTITY.js +9 -0
- package/core/geom/Quaternion.js +8 -8
- package/core/geom/Quaternion.spec.js +13 -0
- package/core/geom/Vector1.d.ts +2 -0
- package/core/parser/simple/DataType.js +2 -2
- package/editor/tools/v2/BlenderCameraOrientationGizmo.js +28 -4
- package/editor/view/EditorView.js +25 -22
- package/editor/view/ecs/components/common/NumberController.js +56 -9
- package/engine/EngineHarness.js +2 -4
- package/engine/asset/loaders/image/png/PNG.js +6 -0
- package/engine/asset/loaders/image/png/PNGReader.js +82 -2
- package/engine/asset/loaders/image/png/crc.js +66 -0
- package/engine/ecs/speaker/VoiceSystem.js +1 -1
- package/engine/ecs/terrain/ecs/Terrain.js +58 -36
- package/engine/ecs/terrain/ecs/TerrainSystem.js +22 -4
- package/engine/ecs/terrain/tiles/TerrainTile.js +109 -131
- package/engine/ecs/terrain/tiles/TerrainTileManager.js +100 -121
- package/engine/graphics/ecs/camera/Camera.js +1 -1
- package/engine/graphics/ecs/light/binding/fp/FPLightBinding.js +4 -4
- package/engine/graphics/geometry/bvh/buffered/BVHGeometryRaycaster.js +0 -78
- package/engine/graphics/geometry/optimization/merge/merge_geometry_hierarchy.js +0 -9
- package/engine/graphics/render/forward_plus/LightManager.js +25 -0
- package/engine/graphics/render/forward_plus/data/TextureBackedMemoryRegion.js +6 -2
- package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +6 -11
- package/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +268 -2
- package/engine/graphics/texture/atlas/AtlasPatch.js +12 -6
- package/engine/intelligence/behavior/util/LogMessageBehavior.js +29 -0
- package/engine/logging/ConsoleLoggerBackend.js +15 -0
- package/engine/logging/Logger.js +24 -1
- package/engine/logging/LoggerBackend.js +1 -0
- package/engine/physics/fluid/FluidField.js +9 -0
- package/engine/physics/fluid/effector/AbstractFluidEffector.js +6 -0
- package/engine/physics/fluid/effector/GlobalFluidEffector.js +12 -0
- package/engine/physics/fluid/effector/WakeFluidEffector.js +8 -0
- package/package.json +1 -1
|
@@ -18,13 +18,14 @@ import ThreeFactory from '../../../graphics/three/ThreeFactory.js';
|
|
|
18
18
|
|
|
19
19
|
import { LeafNode } from '../../../../core/bvh2/LeafNode.js';
|
|
20
20
|
|
|
21
|
-
import BVHFromBufferGeometry from '../../../graphics/geometry/bvh/buffered/BVHFromBufferGeometry.js';
|
|
22
|
-
|
|
23
21
|
import IndexedBinaryBVH from '../../../../core/bvh2/binary/IndexedBinaryBVH.js';
|
|
24
22
|
import { BVHGeometryRaycaster } from "../../../graphics/geometry/bvh/buffered/BVHGeometryRaycaster.js";
|
|
25
23
|
import ObservedInteger from "../../../../core/model/ObservedInteger.js";
|
|
26
24
|
import { SurfacePoint3 } from "../../../../core/geom/3d/SurfacePoint3.js";
|
|
27
25
|
import Signal from "../../../../core/events/signal/Signal.js";
|
|
26
|
+
import { mat4 } from "gl-matrix";
|
|
27
|
+
import { AABB3 } from "../../../../core/bvh2/aabb3/AABB3.js";
|
|
28
|
+
import { NumericInterval } from "../../../../core/math/interval/NumericInterval.js";
|
|
28
29
|
|
|
29
30
|
function extractFaceIndexFromLeaf(leaf) {
|
|
30
31
|
return leaf;
|
|
@@ -92,11 +93,17 @@ class TerrainTile {
|
|
|
92
93
|
this.isBuildInProgress = false;
|
|
93
94
|
this.referenceCount = 0;
|
|
94
95
|
|
|
96
|
+
/**
|
|
97
|
+
*
|
|
98
|
+
* @type {Signal<TerrainTile>}
|
|
99
|
+
*/
|
|
95
100
|
this.onBuilt = new Signal();
|
|
96
101
|
this.onDestroyed = new Signal();
|
|
97
102
|
|
|
98
|
-
|
|
99
|
-
|
|
103
|
+
/**
|
|
104
|
+
* @private
|
|
105
|
+
* @type {{bottomLeft: boolean, top: boolean, left: boolean, bottom: boolean, bottomRight: boolean, topLeft: boolean, topRight: boolean, right: boolean}}
|
|
106
|
+
*/
|
|
100
107
|
this.stitching = {
|
|
101
108
|
top: false,
|
|
102
109
|
bottom: false,
|
|
@@ -110,27 +117,34 @@ class TerrainTile {
|
|
|
110
117
|
bottomRight: false
|
|
111
118
|
};
|
|
112
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Initial estimate of height bounds for this tile
|
|
122
|
+
* Untransformed by transform matrix
|
|
123
|
+
* @type {NumericInterval}
|
|
124
|
+
* @private
|
|
125
|
+
*/
|
|
126
|
+
this.__initial_height_range = new NumericInterval(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY);
|
|
127
|
+
|
|
113
128
|
this.raycaster = new BVHGeometryRaycaster();
|
|
114
129
|
//Binary BVH form doesn't have distinct leaf objects and stores face indices directly, this requires a special face index extractor that treats leaves as indices directly.
|
|
115
130
|
this.raycaster.extractFaceIndexFromLeaf = extractFaceIndexFromLeaf;
|
|
116
131
|
}
|
|
117
132
|
|
|
118
133
|
/**
|
|
119
|
-
*
|
|
134
|
+
*
|
|
135
|
+
* @return {number[]}
|
|
120
136
|
*/
|
|
121
|
-
|
|
122
|
-
|
|
137
|
+
get transform() {
|
|
138
|
+
return this.mesh.matrixWorld.elements;
|
|
123
139
|
}
|
|
124
140
|
|
|
125
141
|
/**
|
|
126
142
|
*
|
|
127
|
-
* @param {number}
|
|
128
|
-
* @param {number} y
|
|
129
|
-
* @param {function} callback
|
|
130
|
-
* @param {function} missCallback
|
|
143
|
+
* @param {number[]|Float32Array|mat4} m4
|
|
131
144
|
*/
|
|
132
|
-
|
|
133
|
-
|
|
145
|
+
set transform(m4) {
|
|
146
|
+
mat4.copy(this.mesh.matrixWorld.elements, m4);
|
|
147
|
+
this.computeBoundingBox();
|
|
134
148
|
}
|
|
135
149
|
|
|
136
150
|
/**
|
|
@@ -188,7 +202,7 @@ class TerrainTile {
|
|
|
188
202
|
}
|
|
189
203
|
|
|
190
204
|
/**
|
|
191
|
-
*
|
|
205
|
+
* Stitch vertex normals along the edges of the tile set
|
|
192
206
|
* @param {TerrainTile|undefined} top
|
|
193
207
|
* @param {TerrainTile|undefined} bottom
|
|
194
208
|
* @param {TerrainTile|undefined} left
|
|
@@ -254,7 +268,9 @@ class TerrainTile {
|
|
|
254
268
|
bottom.getVertexNormal(i, v0);
|
|
255
269
|
top.getVertexNormal(otherOffset + i, v1);
|
|
256
270
|
|
|
257
|
-
v0.add(v1)
|
|
271
|
+
v0.add(v1);
|
|
272
|
+
v0.normalize();
|
|
273
|
+
|
|
258
274
|
bottom.setVertexNormal(i, v0);
|
|
259
275
|
top.setVertexNormal(otherOffset + i, v0);
|
|
260
276
|
}
|
|
@@ -316,7 +332,9 @@ class TerrainTile {
|
|
|
316
332
|
right.getVertexNormal(index0, v0);
|
|
317
333
|
left.getVertexNormal(index1, v1);
|
|
318
334
|
|
|
319
|
-
v0.add(v1)
|
|
335
|
+
v0.add(v1);
|
|
336
|
+
v0.normalize();
|
|
337
|
+
|
|
320
338
|
right.setVertexNormal(index0, v0);
|
|
321
339
|
left.setVertexNormal(index1, v0);
|
|
322
340
|
}
|
|
@@ -361,7 +379,11 @@ class TerrainTile {
|
|
|
361
379
|
topRight.getVertexNormal(tCornerIndex, v2);
|
|
362
380
|
bottomLeft.getVertexNormal(lCornerIndex, v3);
|
|
363
381
|
|
|
364
|
-
v0.add(v1)
|
|
382
|
+
v0.add(v1);
|
|
383
|
+
v0.add(v2);
|
|
384
|
+
v0.add(v3);
|
|
385
|
+
v0.normalize();
|
|
386
|
+
|
|
365
387
|
topLeft.setVertexNormal(tlCornerIndex, v0);
|
|
366
388
|
bottomRight.setVertexNormal(cornerIndex, v0);
|
|
367
389
|
topRight.setVertexNormal(tCornerIndex, v0);
|
|
@@ -404,118 +426,78 @@ class TerrainTile {
|
|
|
404
426
|
stitchSides();
|
|
405
427
|
}
|
|
406
428
|
|
|
407
|
-
stitchNormals(top, left, topLeft) {
|
|
408
|
-
const v0 = new Vector3(),
|
|
409
|
-
v1 = new Vector3();
|
|
410
|
-
if (top !== null && left !== null && topLeft !== null) {
|
|
411
|
-
|
|
412
|
-
const v2 = new Vector3();
|
|
413
|
-
const v3 = new Vector3();
|
|
414
|
-
//fix corner
|
|
415
|
-
const tlCornerIndex = (topLeft.size.x * topLeft.resolution.getValue()) * (topLeft.size.y * topLeft.resolution.getValue()) - 1;
|
|
416
|
-
const cornerIndex = 0;
|
|
417
|
-
const tCornerIndex = top.size.x * top.resolution.getValue() * (top.size.y * top.resolution.getValue() - 1);
|
|
418
|
-
const lCornerIndex = left.size.x * left.resolution.getValue() - 1;
|
|
419
|
-
|
|
420
|
-
topLeft.getVertexNormal(tlCornerIndex, v0);
|
|
421
|
-
this.getVertexNormal(cornerIndex, v1);
|
|
422
|
-
top.getVertexNormal(tCornerIndex, v2);
|
|
423
|
-
left.getVertexNormal(lCornerIndex, v3);
|
|
424
|
-
|
|
425
|
-
v0.add(v1).add(v2).add(v3).normalize();
|
|
426
|
-
topLeft.setVertexNormal(tlCornerIndex, v0);
|
|
427
|
-
this.setVertexNormal(cornerIndex, v0);
|
|
428
|
-
top.setVertexNormal(tCornerIndex, v0);
|
|
429
|
-
left.setVertexNormal(lCornerIndex, v0);
|
|
430
|
-
}
|
|
431
|
-
let i, l;
|
|
432
|
-
let otherOffset;
|
|
433
|
-
let otherResolution;
|
|
434
|
-
const thisResolution = this.resolution.getValue();
|
|
435
|
-
if (top !== null) {
|
|
436
|
-
otherResolution = top.resolution.getValue();
|
|
437
|
-
otherOffset = top.size.x * otherResolution * (top.size.y * otherResolution - 1);
|
|
438
|
-
for (i = 0, l = this.size.x * thisResolution; i < l; i++) {
|
|
439
|
-
this.getVertexNormal(i, v0);
|
|
440
|
-
top.getVertexNormal(otherOffset + i, v1);
|
|
441
|
-
|
|
442
|
-
v0.add(v1).normalize();
|
|
443
|
-
this.setVertexNormal(i, v0);
|
|
444
|
-
top.setVertexNormal(otherOffset + i, v0);
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
if (left !== null) {
|
|
448
|
-
otherResolution = left.resolution.getValue();
|
|
449
|
-
otherOffset = left.size.x * otherResolution - 1;
|
|
450
|
-
const otherMultiplier = left.size.x * otherResolution;
|
|
451
|
-
const thisMultiplier = this.size.x * thisResolution;
|
|
452
|
-
for (i = 0, l = this.size.y * thisResolution; i < l; i++) {
|
|
453
|
-
|
|
454
|
-
const index0 = i * thisMultiplier;
|
|
455
|
-
const index1 = otherOffset + i * otherMultiplier;
|
|
456
|
-
|
|
457
|
-
this.getVertexNormal(index0, v0);
|
|
458
|
-
left.getVertexNormal(index1, v1);
|
|
459
|
-
|
|
460
|
-
v0.add(v1).normalize();
|
|
461
|
-
this.setVertexNormal(index0, v0);
|
|
462
|
-
left.setVertexNormal(index1, v0);
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
429
|
computeBoundingBox() {
|
|
430
|
+
/**
|
|
431
|
+
* @type {ThreeBox3}
|
|
432
|
+
*/
|
|
433
|
+
let bb;
|
|
434
|
+
|
|
468
435
|
const geometry = this.geometry;
|
|
469
|
-
//check for bvh
|
|
470
|
-
const bvh = this.bvh;
|
|
471
|
-
if (bvh !== null) {
|
|
472
|
-
geometry.boundingBox = new ThreeBox3(new ThreeVector3(bvh.x0, bvh.y0, bvh.z0), new ThreeVector3(bvh.x1, bvh.y1, bvh.z1));
|
|
473
436
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
const dZ = bvh.z1 - bvh.z0;
|
|
437
|
+
if (geometry === null) {
|
|
438
|
+
// no geometry present yet
|
|
477
439
|
|
|
478
|
-
const
|
|
440
|
+
const position = this.position;
|
|
441
|
+
const scale = this.scale;
|
|
442
|
+
const size = this.size;
|
|
479
443
|
|
|
480
|
-
const
|
|
444
|
+
const initial_height_range = this.__initial_height_range;
|
|
481
445
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
//pull bounding box from geometry
|
|
485
|
-
let bb = geometry.boundingBox;
|
|
486
|
-
if (bb === null) {
|
|
487
|
-
geometry.computeBoundingBox();
|
|
488
|
-
bb = geometry.boundingBox;
|
|
489
|
-
}
|
|
490
|
-
this.boundingBox.setBounds(bb.min.x, bb.min.y, bb.min.z, bb.max.x, bb.max.y, bb.max.z);
|
|
491
|
-
}
|
|
446
|
+
const min = new ThreeVector3(position.x * scale.x, initial_height_range.min, position.y * scale.y);
|
|
447
|
+
const max = new ThreeVector3(min.x + size.x * scale.x, initial_height_range.max, min.z + size.y * scale.y);
|
|
492
448
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
// console.profileEnd('build bvh');
|
|
498
|
-
}
|
|
449
|
+
bb = new ThreeBox3(
|
|
450
|
+
min,
|
|
451
|
+
max
|
|
452
|
+
);
|
|
499
453
|
|
|
500
|
-
|
|
501
|
-
this.isBuilt = false;
|
|
454
|
+
} else {
|
|
502
455
|
|
|
503
|
-
|
|
504
|
-
|
|
456
|
+
//check for bvh
|
|
457
|
+
const bvh = this.bvh;
|
|
458
|
+
if (bvh !== null) {
|
|
459
|
+
geometry.boundingBox = new ThreeBox3(new ThreeVector3(bvh.x0, bvh.y0, bvh.z0), new ThreeVector3(bvh.x1, bvh.y1, bvh.z1));
|
|
460
|
+
|
|
461
|
+
const dX = bvh.x1 - bvh.x0;
|
|
462
|
+
const dY = bvh.y1 - bvh.y0;
|
|
463
|
+
const dZ = bvh.z1 - bvh.z0;
|
|
464
|
+
|
|
465
|
+
const radius = Math.sqrt(dX * dX + dY * dY + dZ * dZ) / 2;
|
|
466
|
+
|
|
467
|
+
const center = new ThreeVector3(bvh.x0 + dX / 2, bvh.y0 + dY / 2, bvh.z0 + dZ / 2);
|
|
468
|
+
|
|
469
|
+
geometry.boundingSphere = new ThreeSphere(center, radius);
|
|
470
|
+
}
|
|
471
|
+
//pull bounding box from geometry
|
|
505
472
|
|
|
506
|
-
|
|
473
|
+
bb = geometry.boundingBox;
|
|
474
|
+
if (bb === null) {
|
|
475
|
+
geometry.computeBoundingBox();
|
|
476
|
+
bb = geometry.boundingBox;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
507
479
|
|
|
508
|
-
|
|
509
|
-
|
|
480
|
+
const x0 = bb.min.x;
|
|
481
|
+
const y0 = bb.min.y;
|
|
482
|
+
const z0 = bb.min.z;
|
|
510
483
|
|
|
511
|
-
|
|
512
|
-
|
|
484
|
+
const x1 = bb.max.x;
|
|
485
|
+
const y1 = bb.max.y;
|
|
486
|
+
const z1 = bb.max.z;
|
|
487
|
+
|
|
488
|
+
const geometry_bb = new AABB3(
|
|
489
|
+
x0, y0, z0,
|
|
490
|
+
x1, y1, z1
|
|
491
|
+
);
|
|
513
492
|
|
|
514
|
-
|
|
515
|
-
stitching.topRight = false;
|
|
493
|
+
geometry_bb.applyMatrix4(this.transform);
|
|
516
494
|
|
|
517
|
-
|
|
518
|
-
|
|
495
|
+
this.boundingBox.setBounds(
|
|
496
|
+
geometry_bb.x0, geometry_bb.y0, geometry_bb.z0,
|
|
497
|
+
geometry_bb.x1, geometry_bb.y1, geometry_bb.z1
|
|
498
|
+
);
|
|
499
|
+
// update changes up the tree
|
|
500
|
+
this.boundingBox.bubbleRefit();
|
|
519
501
|
}
|
|
520
502
|
|
|
521
503
|
/**
|
|
@@ -523,23 +505,17 @@ class TerrainTile {
|
|
|
523
505
|
* @param {number} min_height
|
|
524
506
|
* @param {number} max_height
|
|
525
507
|
*/
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
const size = this.size.clone().multiply(this.scale);
|
|
530
|
-
|
|
531
|
-
const max = offset.clone().add(size);
|
|
532
|
-
|
|
533
|
-
this.boundingBox.setBounds(
|
|
534
|
-
offset.x, min_height, offset.y,
|
|
535
|
-
max.x, max_height, max.y
|
|
536
|
-
);
|
|
508
|
+
setInitialHeightBounds(min_height, max_height) {
|
|
509
|
+
this.__initial_height_range.set(min_height, max_height);
|
|
537
510
|
}
|
|
538
511
|
|
|
539
512
|
dispose() {
|
|
540
513
|
if (this.geometry !== null) {
|
|
541
514
|
this.geometry.dispose();
|
|
515
|
+
this.geometry = null;
|
|
542
516
|
}
|
|
517
|
+
|
|
518
|
+
this.isBuilt = false;
|
|
543
519
|
}
|
|
544
520
|
|
|
545
521
|
build(tileData) {
|
|
@@ -549,7 +525,9 @@ class TerrainTile {
|
|
|
549
525
|
const tileDataGeometry = tileData.geometry;
|
|
550
526
|
|
|
551
527
|
const g = new ThreeBufferGeometry();
|
|
528
|
+
|
|
552
529
|
g.setIndex(new ThreeBufferAttribute(tileDataGeometry.indices, 1));
|
|
530
|
+
|
|
553
531
|
g.setAttribute('position', new ThreeBufferAttribute(tileDataGeometry.vertices, 3));
|
|
554
532
|
g.setAttribute('normal', new ThreeBufferAttribute(tileDataGeometry.normals, 3));
|
|
555
533
|
g.setAttribute('uv', new ThreeBufferAttribute(tileDataGeometry.uvs, 2));
|
|
@@ -571,11 +549,6 @@ class TerrainTile {
|
|
|
571
549
|
}
|
|
572
550
|
|
|
573
551
|
|
|
574
|
-
//set bounding box
|
|
575
|
-
// console.time('bb');
|
|
576
|
-
this.computeBoundingBox();
|
|
577
|
-
// console.timeEnd('bb');
|
|
578
|
-
|
|
579
552
|
const mesh = this.mesh;
|
|
580
553
|
|
|
581
554
|
mesh.geometry = g;
|
|
@@ -583,6 +556,11 @@ class TerrainTile {
|
|
|
583
556
|
mesh.receiveShadow = true;
|
|
584
557
|
mesh.castShadow = true;
|
|
585
558
|
|
|
559
|
+
//set bounding box
|
|
560
|
+
// console.time('bb');
|
|
561
|
+
this.computeBoundingBox();
|
|
562
|
+
// console.timeEnd('bb');
|
|
563
|
+
|
|
586
564
|
// console.timeEnd('total');
|
|
587
565
|
// console.groupEnd();
|
|
588
566
|
|
|
@@ -15,7 +15,6 @@ import { MeshPhongMaterial } from 'three';
|
|
|
15
15
|
import { assert } from "../../../../core/assert.js";
|
|
16
16
|
import { Color } from "../../../../core/color/Color.js";
|
|
17
17
|
import { noop } from "../../../../core/function/Functions.js";
|
|
18
|
-
import Vector3 from "../../../../core/geom/Vector3.js";
|
|
19
18
|
import { SurfacePoint3 } from "../../../../core/geom/3d/SurfacePoint3.js";
|
|
20
19
|
import { RaycastBVHVisitor } from "../../../../core/bvh2/traversal/RaycastBVHVisitor.js";
|
|
21
20
|
import { FirstRayIntersectionTerrainBVHVisitor } from "./FirstRayIntersectionTerrainBVHVisitor.js";
|
|
@@ -24,6 +23,8 @@ import { aabb2_overlapExists } from "../../../../core/geom/AABB2.js";
|
|
|
24
23
|
import ObservedInteger from "../../../../core/model/ObservedInteger.js";
|
|
25
24
|
import { NumericInterval } from "../../../../core/math/interval/NumericInterval.js";
|
|
26
25
|
import { randomFloatBetween } from "../../../../core/math/random/randomFloatBetween.js";
|
|
26
|
+
import { mat4, vec3 } from "gl-matrix";
|
|
27
|
+
import { isArrayEqualStrict } from "../../../../core/collection/array/isArrayEqualStrict.js";
|
|
27
28
|
|
|
28
29
|
class TerrainTileManager {
|
|
29
30
|
/**
|
|
@@ -105,7 +106,30 @@ class TerrainTileManager {
|
|
|
105
106
|
this.traverse(this.assignTileMaterial, this);
|
|
106
107
|
});
|
|
107
108
|
|
|
109
|
+
/**
|
|
110
|
+
*
|
|
111
|
+
* @type {Float32Array}
|
|
112
|
+
* @private
|
|
113
|
+
*/
|
|
114
|
+
this.__transform = new Float32Array(16);
|
|
115
|
+
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
set transform(m4) {
|
|
119
|
+
if (isArrayEqualStrict(m4, this.__transform)) {
|
|
120
|
+
// no change
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
mat4.copy(this.__transform, m4);
|
|
125
|
+
|
|
126
|
+
this.traverse(t => {
|
|
127
|
+
t.transform = m4;
|
|
128
|
+
});
|
|
129
|
+
}
|
|
108
130
|
|
|
131
|
+
get transform() {
|
|
132
|
+
return this.__transform;
|
|
109
133
|
}
|
|
110
134
|
|
|
111
135
|
/**
|
|
@@ -156,74 +180,6 @@ class TerrainTileManager {
|
|
|
156
180
|
this.initializeTiles();
|
|
157
181
|
}
|
|
158
182
|
|
|
159
|
-
/**
|
|
160
|
-
*
|
|
161
|
-
* @param {Vector3} origin
|
|
162
|
-
* @param {Vector3} direction
|
|
163
|
-
* @param {function} callback
|
|
164
|
-
* @param {function} missCallback
|
|
165
|
-
*/
|
|
166
|
-
raycast(origin, direction, callback, missCallback) {
|
|
167
|
-
assert.typeOf(callback, 'function', 'callback');
|
|
168
|
-
assert.typeOf(missCallback, 'function', 'missCallback');
|
|
169
|
-
|
|
170
|
-
let bestHit = null;
|
|
171
|
-
let bestNormal = null;
|
|
172
|
-
let bestGeometry = null;
|
|
173
|
-
let bestDistanceSqr = Number.POSITIVE_INFINITY;
|
|
174
|
-
|
|
175
|
-
let firstStageOver = false;
|
|
176
|
-
|
|
177
|
-
let tileCount = 0;
|
|
178
|
-
|
|
179
|
-
function tryReturn() {
|
|
180
|
-
if (tileCount === 0 && firstStageOver) {
|
|
181
|
-
callback(bestHit, bestNormal, bestGeometry);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function registerHit(hit, normal, geo) {
|
|
186
|
-
const d = hit.distanceSqrTo(origin);
|
|
187
|
-
if (d < bestDistanceSqr) {
|
|
188
|
-
bestDistanceSqr = d;
|
|
189
|
-
bestHit = hit;
|
|
190
|
-
bestNormal = normal;
|
|
191
|
-
bestGeometry = geo;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
*
|
|
198
|
-
* @param {TerrainTile} tile
|
|
199
|
-
*/
|
|
200
|
-
function doCast(tile) {
|
|
201
|
-
|
|
202
|
-
tile.raycast(origin, direction, registerHit, missCallback);
|
|
203
|
-
tileCount--;
|
|
204
|
-
tryReturn();
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
this.bvh.traverseRayLeafIntersections(origin.x, origin.y, origin.z, direction.x, direction.y, direction.z, function (leaf) {
|
|
208
|
-
/**
|
|
209
|
-
*
|
|
210
|
-
* @type {TerrainTile}
|
|
211
|
-
*/
|
|
212
|
-
const tile = leaf.object;
|
|
213
|
-
|
|
214
|
-
tileCount++;
|
|
215
|
-
|
|
216
|
-
if (tile.isBuilt) {
|
|
217
|
-
doCast(tile);
|
|
218
|
-
} else {
|
|
219
|
-
tile.onBuilt.addOne(doCast);
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
firstStageOver = true;
|
|
224
|
-
tryReturn();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
183
|
/**
|
|
228
184
|
*
|
|
229
185
|
* @param {TerrainTile} tile
|
|
@@ -378,7 +334,8 @@ class TerrainTileManager {
|
|
|
378
334
|
tile.scale.copy(this.scale);
|
|
379
335
|
tile.resolution.copy(this.resolution);
|
|
380
336
|
|
|
381
|
-
tile.
|
|
337
|
+
tile.setInitialHeightBounds(this.heightRange.min, this.heightRange.max);
|
|
338
|
+
tile.computeBoundingBox();
|
|
382
339
|
|
|
383
340
|
//hook for building
|
|
384
341
|
tile.ensureBuilt = ensureBuilt(x, y);
|
|
@@ -397,11 +354,8 @@ class TerrainTileManager {
|
|
|
397
354
|
* @returns {number}
|
|
398
355
|
*/
|
|
399
356
|
computeTileIndex(x, y) {
|
|
400
|
-
assert.
|
|
401
|
-
assert.
|
|
402
|
-
|
|
403
|
-
assert.ok(x >= 0, `x(=${x}) must be greater or equal to 0`);
|
|
404
|
-
assert.ok(y >= 0, `y(=${y}) must be greater or equal to 0`);
|
|
357
|
+
assert.isNonNegativeInteger(x, 'x');
|
|
358
|
+
assert.isNonNegativeInteger(y, 'y');
|
|
405
359
|
|
|
406
360
|
const w = Math.ceil(this.totalSize.x / this.tileSize.x);
|
|
407
361
|
|
|
@@ -415,9 +369,16 @@ class TerrainTileManager {
|
|
|
415
369
|
*
|
|
416
370
|
* @param {number} x
|
|
417
371
|
* @param {number} y
|
|
418
|
-
* @returns {TerrainTile}
|
|
372
|
+
* @returns {TerrainTile|undefined}
|
|
419
373
|
*/
|
|
420
374
|
getRaw(x, y) {
|
|
375
|
+
if (
|
|
376
|
+
x < 0
|
|
377
|
+
|| x >= Math.ceil(this.totalSize.x / this.tileSize.x)
|
|
378
|
+
|| y < 0
|
|
379
|
+
) {
|
|
380
|
+
return undefined;
|
|
381
|
+
}
|
|
421
382
|
|
|
422
383
|
const tileIndex = this.computeTileIndex(x, y);
|
|
423
384
|
|
|
@@ -442,6 +403,43 @@ class TerrainTileManager {
|
|
|
442
403
|
return this.getRaw(tileX, tileY);
|
|
443
404
|
}
|
|
444
405
|
|
|
406
|
+
/**
|
|
407
|
+
* Given world coordinates in top-down plane, where X runs along X axis and Y runs along Z axis, returns terrain tile that overlaps that 2d region
|
|
408
|
+
* @param {number} x
|
|
409
|
+
* @param {number} y
|
|
410
|
+
* @return {TerrainTile|undefined}
|
|
411
|
+
*/
|
|
412
|
+
getTileByWorldPosition2D(x, y) {
|
|
413
|
+
const v3 = vec3.fromValues(x, 0, y);
|
|
414
|
+
|
|
415
|
+
const world_inverse = mat4.create();
|
|
416
|
+
|
|
417
|
+
mat4.invert(world_inverse, this.transform);
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
vec3.transformMat4(v3, v3, world_inverse);
|
|
421
|
+
|
|
422
|
+
return this.getRawTileByPosition(v3.x, v3.z);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Builds and returns the tile from world coordinates
|
|
427
|
+
* @param {number} x
|
|
428
|
+
* @param {number} y
|
|
429
|
+
* @returns {Promise<TerrainTile>}
|
|
430
|
+
*/
|
|
431
|
+
obtainTileAtWorldPosition2D(x, y) {
|
|
432
|
+
const tile = this.getTileByWorldPosition2D(x, y);
|
|
433
|
+
|
|
434
|
+
return this.obtain(tile.gridPosition.x, tile.gridPosition.y);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* @deprecated use {@link #obtain instead}
|
|
439
|
+
* @param {number} x
|
|
440
|
+
* @param {number} y
|
|
441
|
+
* @param {function(TerrainTile):*} callback
|
|
442
|
+
*/
|
|
445
443
|
processTile(x, y, callback) {
|
|
446
444
|
const tile = this.getRaw(x, y);
|
|
447
445
|
|
|
@@ -454,9 +452,10 @@ class TerrainTileManager {
|
|
|
454
452
|
|
|
455
453
|
/**
|
|
456
454
|
*
|
|
457
|
-
* @param {
|
|
458
|
-
* @param {
|
|
459
|
-
* @returns {Promise}
|
|
455
|
+
* @param {number} x coordinate
|
|
456
|
+
* @param {number} y coordinate
|
|
457
|
+
* @returns {Promise<TerrainTile>}
|
|
458
|
+
* @throws if no tile exists at given coordinates
|
|
460
459
|
*/
|
|
461
460
|
obtain(x, y) {
|
|
462
461
|
const tile = this.getRaw(x, y);
|
|
@@ -490,6 +489,10 @@ class TerrainTileManager {
|
|
|
490
489
|
* @param {TerrainTile} tile
|
|
491
490
|
*/
|
|
492
491
|
release(tile) {
|
|
492
|
+
if (tile.referenceCount <= 0) {
|
|
493
|
+
console.warn('Tile already has no references');
|
|
494
|
+
}
|
|
495
|
+
|
|
493
496
|
tile.referenceCount--;
|
|
494
497
|
|
|
495
498
|
if (tile.referenceCount <= 0) {
|
|
@@ -497,7 +500,7 @@ class TerrainTileManager {
|
|
|
497
500
|
tile.dispose();
|
|
498
501
|
}
|
|
499
502
|
|
|
500
|
-
|
|
503
|
+
// TODO check tile.isBuilt flag
|
|
501
504
|
tile.onDestroyed.send1(tile);
|
|
502
505
|
}
|
|
503
506
|
|
|
@@ -512,9 +515,17 @@ class TerrainTileManager {
|
|
|
512
515
|
}
|
|
513
516
|
}
|
|
514
517
|
|
|
518
|
+
/**
|
|
519
|
+
*
|
|
520
|
+
* @param {number} x
|
|
521
|
+
* @param {number} y
|
|
522
|
+
* @param {TerrainTile} tile
|
|
523
|
+
*/
|
|
515
524
|
stitchTile(x, y, tile) {
|
|
516
525
|
|
|
517
|
-
const gridSize = this.totalSize.clone()
|
|
526
|
+
const gridSize = this.totalSize.clone();
|
|
527
|
+
gridSize.divide(this.tileSize);
|
|
528
|
+
gridSize.floor();
|
|
518
529
|
|
|
519
530
|
const self = this;
|
|
520
531
|
//normal stitching
|
|
@@ -569,6 +580,7 @@ class TerrainTileManager {
|
|
|
569
580
|
directionZ
|
|
570
581
|
) {
|
|
571
582
|
|
|
583
|
+
// console.log('+ raycastFirstSync');
|
|
572
584
|
raycastBVHVisitor.collector = firstRayIntersectionTerrainBVHVisitor;
|
|
573
585
|
raycastBVHVisitor.setOrigin(originX, originY, originZ);
|
|
574
586
|
raycastBVHVisitor.setDirection(directionX, directionY, directionZ);
|
|
@@ -579,6 +591,8 @@ class TerrainTileManager {
|
|
|
579
591
|
|
|
580
592
|
traverseBinaryNodeUsingVisitor(this.bvh, raycastBVHVisitor);
|
|
581
593
|
|
|
594
|
+
// console.log('- raycastFirstSync');
|
|
595
|
+
|
|
582
596
|
if (firstRayIntersectionTerrainBVHVisitor.closestDistance !== Number.POSITIVE_INFINITY) {
|
|
583
597
|
result.copy(firstRayIntersectionTerrainBVHVisitor.closest);
|
|
584
598
|
|
|
@@ -588,41 +602,6 @@ class TerrainTileManager {
|
|
|
588
602
|
return false;
|
|
589
603
|
}
|
|
590
604
|
|
|
591
|
-
raycastVertical(x, y, successCallback, missCallback) {
|
|
592
|
-
assert.typeOf(missCallback, 'function', 'missCallback');
|
|
593
|
-
|
|
594
|
-
/**
|
|
595
|
-
*
|
|
596
|
-
* @param {TerrainTile} tile
|
|
597
|
-
*/
|
|
598
|
-
function doCast(tile) {
|
|
599
|
-
tile.raycastVertical(x, y, successCallback, missCallback);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
let miss = true;
|
|
604
|
-
|
|
605
|
-
this.bvh.traverseRayLeafIntersections(x, -10000, y, 0, 1, 0, function (leaf) {
|
|
606
|
-
/**
|
|
607
|
-
*
|
|
608
|
-
* @type {TerrainTile}
|
|
609
|
-
*/
|
|
610
|
-
const tile = leaf.object;
|
|
611
|
-
|
|
612
|
-
miss = false;
|
|
613
|
-
|
|
614
|
-
if (tile.isBuilt) {
|
|
615
|
-
doCast(tile);
|
|
616
|
-
} else {
|
|
617
|
-
tile.onBuilt.addOne(doCast);
|
|
618
|
-
}
|
|
619
|
-
});
|
|
620
|
-
|
|
621
|
-
if (miss) {
|
|
622
|
-
missCallback();
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
|
|
626
605
|
/**
|
|
627
606
|
* TODO untested
|
|
628
607
|
* @param {SurfacePoint3} contact
|
|
@@ -631,7 +610,10 @@ class TerrainTileManager {
|
|
|
631
610
|
* @return {boolean}
|
|
632
611
|
*/
|
|
633
612
|
raycastVerticalFirstSync(contact, x, y) {
|
|
634
|
-
|
|
613
|
+
// console.log('+ raycastVerticalFirstSync');
|
|
614
|
+
const r = this.raycastFirstSync(contact, x, -10000, y, 0, 1, 0);
|
|
615
|
+
// console.log('- raycastVerticalFirstSync');
|
|
616
|
+
return r;
|
|
635
617
|
}
|
|
636
618
|
|
|
637
619
|
/**
|
|
@@ -697,14 +679,11 @@ class TerrainTileManager {
|
|
|
697
679
|
|
|
698
680
|
// console.timeEnd(processName);
|
|
699
681
|
|
|
700
|
-
self.on.tileBuilt.
|
|
682
|
+
self.on.tileBuilt.send1(tile);
|
|
701
683
|
}, reject);
|
|
702
684
|
}
|
|
703
685
|
}
|
|
704
686
|
|
|
705
|
-
const v3_origin = new Vector3();
|
|
706
|
-
const v3_direction = new Vector3();
|
|
707
|
-
|
|
708
687
|
const raycastBVHVisitor = new RaycastBVHVisitor();
|
|
709
688
|
const firstRayIntersectionTerrainBVHVisitor = new FirstRayIntersectionTerrainBVHVisitor();
|
|
710
689
|
|