@woosh/meep-engine 2.53.0 → 2.54.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/package.json +1 -1
- package/src/engine/EngineConfiguration.js +24 -25
- package/src/engine/ecs/EntityBlueprint.js +2 -4
- package/src/engine/ecs/EntityComponentDataset.spec.js +77 -0
- package/src/engine/ecs/terrain/overlay/TerrainOverlay.spec.js +6 -0
- package/src/engine/ecs/terrain/tiles/TerrainTile.js +79 -76
- package/src/engine/ecs/terrain/tiles/TerrainTile.spec.js +25 -0
- package/src/engine/platform/EnginePlatform.js +0 -4
- package/src/engine/InputEngine.js +0 -94
- package/src/engine/PointerLock.js +0 -60
- package/src/engine/ecs/terrain/ecs/layers/loadLegacyTerrainLayers.js +0 -99
- package/src/engine/ecs/terrain/ecs/splat/loadLegacyTerrainSplats.js +0 -73
package/package.json
CHANGED
|
@@ -2,31 +2,30 @@ import { assert } from "../core/assert.js";
|
|
|
2
2
|
import { computeSystemName } from "./ecs/System.js";
|
|
3
3
|
|
|
4
4
|
export class EngineConfiguration {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @private
|
|
8
|
+
* @type {System[]}
|
|
9
|
+
*/
|
|
10
|
+
systems = [];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @private
|
|
14
|
+
* @type {Class<EnginePlugin>[]}
|
|
15
|
+
*/
|
|
16
|
+
plugins = [];
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @private
|
|
20
|
+
* @type {StaticKnowledgeDataTableDescriptor[]}
|
|
21
|
+
*/
|
|
22
|
+
knowledge = [];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @type {Map<string,AssetLoader<any>>}
|
|
27
|
+
*/
|
|
28
|
+
loaders = new Map();
|
|
30
29
|
|
|
31
30
|
/**
|
|
32
31
|
*
|
|
@@ -3,7 +3,7 @@ import EntityBuilder from "./EntityBuilder.js";
|
|
|
3
3
|
/**
|
|
4
4
|
*
|
|
5
5
|
* @param {Object} template
|
|
6
|
-
* @param {Object} seed
|
|
6
|
+
* @param {Object} [seed]
|
|
7
7
|
*/
|
|
8
8
|
function populateJsonTemplate(template, seed) {
|
|
9
9
|
if (seed === undefined) {
|
|
@@ -41,9 +41,7 @@ function populateJsonTemplate(template, seed) {
|
|
|
41
41
|
for (const propertyName in template) {
|
|
42
42
|
const templateValue = template[propertyName];
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
result[propertyName] = seededValue;
|
|
44
|
+
result[propertyName] = populateJsonTemplate(templateValue, seed);
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
return result;
|
|
@@ -442,6 +442,30 @@ test('getComponent with 1 entity and 1 component', () => {
|
|
|
442
442
|
expect(visitor_1).not.toHaveBeenCalled();
|
|
443
443
|
});
|
|
444
444
|
|
|
445
|
+
test("getComponent on unregistered component class", () => {
|
|
446
|
+
|
|
447
|
+
const ecd = new EntityComponentDataset();
|
|
448
|
+
|
|
449
|
+
const entity = ecd.createEntity();
|
|
450
|
+
|
|
451
|
+
expect(ecd.getComponent(entity, DummyComponentA)).toBe(undefined);
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
test("getComponentSafe", () => {
|
|
455
|
+
|
|
456
|
+
const ecd = new EntityComponentDataset();
|
|
457
|
+
ecd.registerComponentType(DummyComponentA);
|
|
458
|
+
|
|
459
|
+
const entity = ecd.createEntity();
|
|
460
|
+
|
|
461
|
+
expect(() => ecd.getComponentSafe(entity, DummyComponentA)).toThrow();
|
|
462
|
+
|
|
463
|
+
const component = new DummyComponentA();
|
|
464
|
+
|
|
465
|
+
ecd.addComponentToEntity(entity, component);
|
|
466
|
+
|
|
467
|
+
expect(ecd.getComponentSafe(entity, DummyComponentA)).toBe(component);
|
|
468
|
+
});
|
|
445
469
|
|
|
446
470
|
test('isComponentTypeRegistered', () => {
|
|
447
471
|
const ecd = new EntityComponentDataset();
|
|
@@ -594,6 +618,59 @@ test('entityHasComponents', () => {
|
|
|
594
618
|
expect(ecd.entityHasComponents(a)).toBe(true);
|
|
595
619
|
});
|
|
596
620
|
|
|
621
|
+
test("getAnyComponent", () => {
|
|
622
|
+
|
|
623
|
+
const ecd = new EntityComponentDataset();
|
|
624
|
+
|
|
625
|
+
ecd.registerManyComponentTypes([
|
|
626
|
+
DummyComponentA,
|
|
627
|
+
DummyComponentB
|
|
628
|
+
]);
|
|
629
|
+
|
|
630
|
+
const a = ecd.createEntity();
|
|
631
|
+
|
|
632
|
+
expect(ecd.getAnyComponent(DummyComponentA)).toEqual({
|
|
633
|
+
entity: -1,
|
|
634
|
+
component: null
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
const component_a = new DummyComponentA();
|
|
638
|
+
ecd.addComponentToEntity(a, component_a);
|
|
639
|
+
ecd.addComponentToEntity(a, new DummyComponentB());
|
|
640
|
+
|
|
641
|
+
expect(ecd.getAnyComponent(DummyComponentA)).toEqual({
|
|
642
|
+
entity: a,
|
|
643
|
+
component: component_a
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
test("hasComponent", () => {
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
const ecd = new EntityComponentDataset();
|
|
652
|
+
|
|
653
|
+
ecd.registerManyComponentTypes([
|
|
654
|
+
DummyComponentA,
|
|
655
|
+
DummyComponentB
|
|
656
|
+
]);
|
|
657
|
+
|
|
658
|
+
const a = ecd.createEntity();
|
|
659
|
+
|
|
660
|
+
expect(ecd.hasComponent(a, DummyComponentA)).toBe(false);
|
|
661
|
+
expect(ecd.hasComponent(a, DummyComponentB)).toBe(false);
|
|
662
|
+
|
|
663
|
+
ecd.addComponentToEntity(a, new DummyComponentA());
|
|
664
|
+
|
|
665
|
+
expect(ecd.hasComponent(a, DummyComponentA)).toBe(true);
|
|
666
|
+
expect(ecd.hasComponent(a, DummyComponentB)).toBe(false);
|
|
667
|
+
|
|
668
|
+
ecd.addComponentToEntity(a, new DummyComponentB());
|
|
669
|
+
|
|
670
|
+
expect(ecd.hasComponent(a, DummyComponentA)).toBe(true);
|
|
671
|
+
expect(ecd.hasComponent(a, DummyComponentB)).toBe(true);
|
|
672
|
+
});
|
|
673
|
+
|
|
597
674
|
describe('event management', () => {
|
|
598
675
|
|
|
599
676
|
test("shouldn't be able to add event listener to non-existent entity", () => {
|
|
@@ -33,98 +33,101 @@ import { passThrough } from "../../../../core/function/Functions.js";
|
|
|
33
33
|
* terrain tile is a part of a 2d array
|
|
34
34
|
*/
|
|
35
35
|
class TerrainTile {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this.resolution = new ObservedInteger(1);
|
|
36
|
+
gridPosition = new Vector2();
|
|
37
|
+
scale = new Vector2(1, 1);
|
|
38
|
+
size = new Vector2();
|
|
39
|
+
position = new Vector2();
|
|
40
|
+
resolution = new ObservedInteger(1);
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
* @type {Material}
|
|
45
|
+
*/
|
|
46
|
+
material = null;
|
|
47
|
+
mesh = ThreeFactory.createMesh();
|
|
49
48
|
|
|
50
|
-
this.mesh.name = "TerrainTile";
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
/**
|
|
51
|
+
*
|
|
52
|
+
* @type {THREE.BufferGeometry}
|
|
53
|
+
*/
|
|
54
|
+
geometry = null;
|
|
57
55
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @type {boolean}
|
|
59
|
+
*/
|
|
60
|
+
enableBVH = true;
|
|
63
61
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
/**
|
|
63
|
+
*
|
|
64
|
+
* @type {LeafNode}
|
|
65
|
+
*/
|
|
66
|
+
boundingBox = new LeafNode(this);
|
|
69
67
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
/**
|
|
69
|
+
*
|
|
70
|
+
* @type {BinaryNode}
|
|
71
|
+
*/
|
|
72
|
+
bvh = null;
|
|
75
73
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
/**
|
|
75
|
+
*
|
|
76
|
+
* @type {boolean}
|
|
77
|
+
*/
|
|
78
|
+
isBuilt = false;
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* @type {boolean}
|
|
82
|
+
*/
|
|
83
|
+
isBuildInProgress = false;
|
|
84
|
+
referenceCount = 0;
|
|
81
85
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
*
|
|
89
|
-
* @type {boolean}
|
|
90
|
-
*/
|
|
91
|
-
this.isBuildInProgress = false;
|
|
92
|
-
this.referenceCount = 0;
|
|
86
|
+
/**
|
|
87
|
+
*
|
|
88
|
+
* @type {Signal<TerrainTile>}
|
|
89
|
+
*/
|
|
90
|
+
onBuilt = new Signal();
|
|
91
|
+
onDestroyed = new Signal();
|
|
93
92
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Encodes whether stitching has been performed on per-neighbour basis
|
|
95
|
+
* @private
|
|
96
|
+
* @type {{bottomLeft: boolean, top: boolean, left: boolean, bottom: boolean, bottomRight: boolean, topLeft: boolean, topRight: boolean, right: boolean}}
|
|
97
|
+
*/
|
|
98
|
+
stitching = {
|
|
99
|
+
top: false,
|
|
100
|
+
bottom: false,
|
|
101
|
+
left: false,
|
|
102
|
+
right: false,
|
|
100
103
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
top: false,
|
|
108
|
-
bottom: false,
|
|
109
|
-
left: false,
|
|
110
|
-
right: false,
|
|
104
|
+
topLeft: false,
|
|
105
|
+
topRight: false,
|
|
106
|
+
|
|
107
|
+
bottomLeft: false,
|
|
108
|
+
bottomRight: false
|
|
109
|
+
};
|
|
111
110
|
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
/**
|
|
112
|
+
* Initial estimate of height bounds for this tile
|
|
113
|
+
* Untransformed by transform matrix
|
|
114
|
+
* @type {NumericInterval}
|
|
115
|
+
* @private
|
|
116
|
+
*/
|
|
117
|
+
__initial_height_range = new NumericInterval(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY);
|
|
114
118
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
119
|
+
raycaster = new BVHGeometryRaycaster();
|
|
120
|
+
|
|
121
|
+
constructor() {
|
|
122
|
+
|
|
123
|
+
this.mesh.name = "TerrainTile";
|
|
118
124
|
|
|
119
125
|
/**
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* @type {NumericInterval}
|
|
123
|
-
* @private
|
|
126
|
+
* Terrain mesh is static, it never changes its transform. Updates are wasteful.
|
|
127
|
+
* @type {boolean}
|
|
124
128
|
*/
|
|
125
|
-
this.
|
|
129
|
+
this.mesh.matrixWorldNeedsUpdate = false;
|
|
126
130
|
|
|
127
|
-
this.raycaster = new BVHGeometryRaycaster();
|
|
128
131
|
//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.
|
|
129
132
|
this.raycaster.extractFaceIndexFromLeaf = passThrough;
|
|
130
133
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import TerrainTile from "./TerrainTile.js";
|
|
2
|
+
import { MATRIX_4_IDENTITY } from "../../../../core/geom/3d/matrix/MATRIX_4_IDENTITY.js";
|
|
3
|
+
|
|
4
|
+
test("constructor does not throw", () => {
|
|
5
|
+
new TerrainTile();
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
test("get/set transform", () => {
|
|
9
|
+
|
|
10
|
+
const tile = new TerrainTile();
|
|
11
|
+
tile.setInitialHeightBounds(1, 7);
|
|
12
|
+
|
|
13
|
+
tile.transform = MATRIX_4_IDENTITY;
|
|
14
|
+
|
|
15
|
+
expect(Array.from(tile.transform)).toEqual(Array.from(MATRIX_4_IDENTITY));
|
|
16
|
+
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("using 'dispose' method on newly created tile", () => {
|
|
20
|
+
|
|
21
|
+
const tile = new TerrainTile();
|
|
22
|
+
|
|
23
|
+
expect(() => tile.dispose()).not.toThrow();
|
|
24
|
+
|
|
25
|
+
});
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User: Alex Goldring
|
|
3
|
-
* Date: 22/6/2014
|
|
4
|
-
* Time: 20:15
|
|
5
|
-
*/
|
|
6
|
-
import { KeyCodes } from './input/devices/KeyCodes.js';
|
|
7
|
-
import { assert } from "../core/assert.js";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @deprecated use PointerDevice and KeyboardDevice respectively
|
|
11
|
-
* @param pointerContext
|
|
12
|
-
* @param keyContext
|
|
13
|
-
* @constructor
|
|
14
|
-
*/
|
|
15
|
-
const InputEngine = function (pointerContext, keyContext) {
|
|
16
|
-
assert.defined(pointerContext, 'pointerContext');
|
|
17
|
-
assert.defined(keyContext, 'keyContext');
|
|
18
|
-
|
|
19
|
-
console.warn('deprecated, use PointerDevice and KeyboardDevice instead');
|
|
20
|
-
|
|
21
|
-
const keyMap = [];
|
|
22
|
-
const mouseMap = {};
|
|
23
|
-
|
|
24
|
-
function obtainBindingByCode(code) {
|
|
25
|
-
let binding;
|
|
26
|
-
if (typeof (code) === "number") {
|
|
27
|
-
if (keyMap[code] === void 0) {
|
|
28
|
-
keyMap[code] = {};
|
|
29
|
-
}
|
|
30
|
-
binding = keyMap[code];
|
|
31
|
-
} else {
|
|
32
|
-
if (mouseMap[code] === void 0) {
|
|
33
|
-
mouseMap[code] = {};
|
|
34
|
-
}
|
|
35
|
-
binding = mouseMap[code];
|
|
36
|
-
}
|
|
37
|
-
return binding;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
this.mapKey = function (keyCode, config) {
|
|
41
|
-
const binding = obtainBindingByCode(keyCode);
|
|
42
|
-
if (config.on) {
|
|
43
|
-
binding.on = config.on;
|
|
44
|
-
}
|
|
45
|
-
if (config.off) {
|
|
46
|
-
binding.off = config.off;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
this.mapKeyBoolean = function (keyName, context, property) {
|
|
50
|
-
const keyCode = KeyCodes[keyName];
|
|
51
|
-
const binding = obtainBindingByCode(keyCode);
|
|
52
|
-
binding.on = function () {
|
|
53
|
-
context[property] = true;
|
|
54
|
-
};
|
|
55
|
-
binding.off = function () {
|
|
56
|
-
context[property] = false;
|
|
57
|
-
};
|
|
58
|
-
return this;
|
|
59
|
-
};
|
|
60
|
-
const keyDownHandler = function (event) {
|
|
61
|
-
const keyCode = event.keyCode;
|
|
62
|
-
//console.log("down", keyCode);
|
|
63
|
-
const binding = keyMap[keyCode];
|
|
64
|
-
if (binding && binding.on) {
|
|
65
|
-
binding.on(event);
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
const keyUpHandler = function (event) {
|
|
69
|
-
const keyCode = event.keyCode;
|
|
70
|
-
const binding = keyMap[keyCode];
|
|
71
|
-
if (binding && binding.off) {
|
|
72
|
-
binding.off(event);
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
const mouseUpHandler = function (event) {
|
|
76
|
-
const mouse1 = mouseMap.mouse1;
|
|
77
|
-
if (mouse1) {
|
|
78
|
-
mouse1.off(event);
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
const mouseDownHandler = function (event) {
|
|
82
|
-
const mouse1 = mouseMap.mouse1;
|
|
83
|
-
if (mouse1) {
|
|
84
|
-
mouse1.on(event);
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
keyContext.addEventListener("keydown", keyDownHandler);
|
|
88
|
-
keyContext.addEventListener("keyup", keyUpHandler);
|
|
89
|
-
pointerContext.addEventListener("mousedown", mouseDownHandler);
|
|
90
|
-
pointerContext.addEventListener("mouseup", mouseUpHandler);
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
};
|
|
94
|
-
export default InputEngine;
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Created by Alex on 27/02/14.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
function getPointerLockElement() {
|
|
8
|
-
const pointerLockElement = document.pointerLockElement ||
|
|
9
|
-
document.mozPointerLockElement ||
|
|
10
|
-
document.webkitPointerLockElement;
|
|
11
|
-
return pointerLockElement;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function PointerLock(element) {
|
|
15
|
-
this.element = element;
|
|
16
|
-
element.requestPointerLock = element.requestPointerLock ||
|
|
17
|
-
element.mozRequestPointerLock ||
|
|
18
|
-
element.webkitRequestPointerLock;
|
|
19
|
-
element.exitPointerLock = element.exitPointerLock ||
|
|
20
|
-
element.mozExitPointerLock ||
|
|
21
|
-
element.webkitExitPointerLock;
|
|
22
|
-
this.pointerLockError = (function (evt) {
|
|
23
|
-
console.error("failed to lock pointer", evt);
|
|
24
|
-
}).bind(this);
|
|
25
|
-
this.pointerLockChange = (function (evt) {
|
|
26
|
-
if (this.isBound()) {
|
|
27
|
-
this.emit("locked");
|
|
28
|
-
} else {
|
|
29
|
-
this.unlock();
|
|
30
|
-
}
|
|
31
|
-
}).bind(this);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
PointerLock.prototype = new EventEmitter();
|
|
35
|
-
PointerLock.prototype.isBound = function () {
|
|
36
|
-
return this.element === getPointerLockElement();
|
|
37
|
-
};
|
|
38
|
-
PointerLock.prototype.lock = function () {
|
|
39
|
-
if (this.isBound()) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
document.addEventListener('pointerlockerror', this.pointerLockError, false);
|
|
43
|
-
document.addEventListener('mozpointerlockerror', this.pointerLockError, false);
|
|
44
|
-
document.addEventListener('webkitpointerlockerror', this.pointerLockError, false);
|
|
45
|
-
|
|
46
|
-
document.addEventListener('pointerlockchange', this.pointerLockChange, false);
|
|
47
|
-
document.addEventListener('mozpointerlockchange', this.pointerLockChange, false);
|
|
48
|
-
document.addEventListener('webkitpointerlockchange', this.pointerLockChange, false);
|
|
49
|
-
this.element.requestPointerLock();
|
|
50
|
-
};
|
|
51
|
-
PointerLock.prototype.unlock = function () {
|
|
52
|
-
document.removeEventListener('pointerlockchange', this.pointerLockChange, false);
|
|
53
|
-
document.removeEventListener('mozpointerlockchange', this.pointerLockChange, false);
|
|
54
|
-
document.removeEventListener('webkitpointerlockchange', this.pointerLockChange, false);
|
|
55
|
-
if (this.isBound()) {
|
|
56
|
-
this.element.exitPointerLock();
|
|
57
|
-
}
|
|
58
|
-
this.emit("unlocked");
|
|
59
|
-
};
|
|
60
|
-
export default PointerLock;
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { max2 } from "../../../../../core/math/max2.js";
|
|
2
|
-
import { TerrainLayer } from "./TerrainLayer.js";
|
|
3
|
-
import { Sampler2D } from "../../../../graphics/texture/sampler/Sampler2D.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
* @param {{repeat:Vector2,textures:{diffuse:string[]}}} description
|
|
8
|
-
* @param {TerrainLayers} layers
|
|
9
|
-
* @param {AssetManager} am
|
|
10
|
-
* @param {Vector2} size
|
|
11
|
-
* @param {number} gridScale
|
|
12
|
-
* @returns {Promise}
|
|
13
|
-
*/
|
|
14
|
-
export function loadLegacyTerrainLayers(description, layers, am, size, gridScale) {
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
* @type {string[]}
|
|
19
|
-
*/
|
|
20
|
-
const textures = description.textures.diffuse;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
*
|
|
24
|
-
* @param {string} url
|
|
25
|
-
* @param {number} layerIndex
|
|
26
|
-
* @return {Promise<Asset>}
|
|
27
|
-
*/
|
|
28
|
-
function loadLayer(url, layerIndex) {
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
*
|
|
32
|
-
* @type {TerrainLayer}
|
|
33
|
-
*/
|
|
34
|
-
const layer = layers.layers.get(layerIndex);
|
|
35
|
-
|
|
36
|
-
layer.textureDiffuseURL = url;
|
|
37
|
-
|
|
38
|
-
return layer.loadTextureData(am);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const layerCount = textures.length;
|
|
42
|
-
|
|
43
|
-
for (let i = 0; i < layerCount; i++) {
|
|
44
|
-
|
|
45
|
-
const layer = new TerrainLayer();
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const nX = gridScale * (size.x / size.y);
|
|
49
|
-
const nY = gridScale;
|
|
50
|
-
|
|
51
|
-
layer.size.set(nX / description.repeat.x, nY / description.repeat.y);
|
|
52
|
-
|
|
53
|
-
layer.diffuse = Sampler2D.uint8(3, layers.resolution.x, layers.resolution.y);
|
|
54
|
-
|
|
55
|
-
layers.addLayer(layer);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
layers.buildTexture();
|
|
59
|
-
|
|
60
|
-
const promises = [];
|
|
61
|
-
|
|
62
|
-
for (let i = 0; i < layerCount; i++) {
|
|
63
|
-
const url = textures[i];
|
|
64
|
-
|
|
65
|
-
const promise = loadLayer(url, i);
|
|
66
|
-
|
|
67
|
-
promises.push(promise);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function updateResolution() {
|
|
71
|
-
|
|
72
|
-
let size_x = 0;
|
|
73
|
-
let size_y = 0;
|
|
74
|
-
|
|
75
|
-
for (let i = 0; i < layerCount; i++) {
|
|
76
|
-
const layer = layers.get(i);
|
|
77
|
-
|
|
78
|
-
size_x = max2(layer.diffuse.width, size_x);
|
|
79
|
-
size_y = max2(layer.diffuse.height, size_y);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
layers.resolution.set(size_x, size_y);
|
|
83
|
-
|
|
84
|
-
layers.buildTexture();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function writeLayers() {
|
|
88
|
-
|
|
89
|
-
layers.writeAllLayersDataIntoTexture();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return Promise.all(promises)
|
|
94
|
-
.then(() => {
|
|
95
|
-
updateResolution();
|
|
96
|
-
|
|
97
|
-
writeLayers();
|
|
98
|
-
});
|
|
99
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { GameAssetType } from "../../../../asset/GameAssetType.js";
|
|
2
|
-
import { max2 } from "../../../../../core/math/max2.js";
|
|
3
|
-
import { Sampler2D } from "../../../../graphics/texture/sampler/Sampler2D.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
* @param {{textures:{splat:string[]}}} description
|
|
8
|
-
* @param {SplatMapping} mapping
|
|
9
|
-
* @param {AssetManager} am
|
|
10
|
-
* @returns {Promise}
|
|
11
|
-
*/
|
|
12
|
-
export function loadLegacyTerrainSplats(description, mapping, am) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const textures = description.textures.splat;
|
|
16
|
-
|
|
17
|
-
const n = textures.length;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
*
|
|
21
|
-
* @param {string} url
|
|
22
|
-
* @param {number} index
|
|
23
|
-
* @return {Promise<Asset>}
|
|
24
|
-
*/
|
|
25
|
-
function loadSplat(url, index) {
|
|
26
|
-
|
|
27
|
-
return am.promise(url, GameAssetType.Image)
|
|
28
|
-
.then(asset => {
|
|
29
|
-
|
|
30
|
-
const image = asset.create();
|
|
31
|
-
|
|
32
|
-
// FIXME texture array in three.js doesn't work when texture size is less than 4x4
|
|
33
|
-
const width = max2(image.width, 4);
|
|
34
|
-
const height = max2(image.height, 4);
|
|
35
|
-
|
|
36
|
-
//create a sampler
|
|
37
|
-
const source = new Sampler2D(image.data, 4, image.width, image.height);
|
|
38
|
-
|
|
39
|
-
mapping.resize(width, height, 4);
|
|
40
|
-
|
|
41
|
-
mapping.writeLayerFromSampler(source, index, 0);
|
|
42
|
-
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const weightPromises = [];
|
|
47
|
-
|
|
48
|
-
for (let i = 0; i < n; i++) {
|
|
49
|
-
const url = textures[i];
|
|
50
|
-
|
|
51
|
-
const promise = loadSplat(url, i);
|
|
52
|
-
|
|
53
|
-
weightPromises.push(promise);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return Promise.all(weightPromises)
|
|
57
|
-
.then(() => {
|
|
58
|
-
const materialData = mapping.materialData;
|
|
59
|
-
|
|
60
|
-
const n = materialData.length;
|
|
61
|
-
|
|
62
|
-
for (let i = 0; i < n; i += 4) {
|
|
63
|
-
materialData[i] = 0;
|
|
64
|
-
materialData[i + 1] = 1;
|
|
65
|
-
materialData[i + 2] = 2;
|
|
66
|
-
materialData[i + 3] = 3;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
mapping.materialTexture.needsUpdate = true;
|
|
70
|
-
mapping.weightTexture.needsUpdate = true;
|
|
71
|
-
|
|
72
|
-
});
|
|
73
|
-
}
|