@woosh/meep-engine 2.33.67 → 2.33.71
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/geom/3d/eulerAnglesFromMatrix.js +115 -0
- package/core/geom/3d/topology/TopoMesh.js +1 -1
- package/core/geom/3d/triangle/computeTriangleRayIntersection.js +3 -9
- package/core/geom/normalize_angle_rad.js +18 -0
- package/core/geom/normalize_angle_rad.spec.js +45 -0
- package/engine/asset/loaders/GLTFAssetLoader.js +0 -4
- package/engine/ecs/fow/FogOfWarRevealerSystem.js +8 -0
- package/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +27 -23
- package/engine/graphics/ecs/camera/topdown/TopDownCameraController.spec.js +9 -0
- package/engine/graphics/geometry/buffered/deinterleaveBufferAttribute.js +3 -2
- package/engine/graphics/geometry/buffered/query/ClippingPlaneContainmentComputingVisitor.js +28 -27
- package/engine/graphics/geometry/buffered/query/GeometryVisitor.js +29 -2
- package/engine/graphics/geometry/buffered/query/RaycastNearestHitComputingVisitor.js +28 -27
- package/generation/example/SampleGenerator0.js +7 -11
- package/generation/example/main.js +215 -0
- package/generation/example/themes/SampleTheme0.js +22 -9
- package/generation/placement/GridCellPlacementRule.js +3 -5
- package/package.json +1 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
//
|
|
2
|
+
|
|
3
|
+
import { v2_magnitude } from "../Vector2.js";
|
|
4
|
+
|
|
5
|
+
function atan2(a, b) {
|
|
6
|
+
return Math.atan2(a, b);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param {number[]} mat4
|
|
12
|
+
* @param {number} row_index
|
|
13
|
+
* @param {number} column_index
|
|
14
|
+
* @return {number}
|
|
15
|
+
*/
|
|
16
|
+
function coeff(mat4, row_index, column_index) {
|
|
17
|
+
return mat4[row_index + column_index * 4];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function sin(a) {
|
|
21
|
+
return Math.sin(a);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function cos(a) {
|
|
25
|
+
return Math.cos(a);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const EIGEN_PI = Math.PI;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* \returns the Euler-angles of the rotation matrix \c *this using the convention defined by the triplet (\a a0,\a a1,\a a2)
|
|
33
|
+
*
|
|
34
|
+
* Each of the three parameters \a a0,\a a1,\a a2 represents the respective rotation axis as an integer in {0,1,2}.
|
|
35
|
+
* For instance, in:
|
|
36
|
+
* \code Vector3f ea = mat.eulerAngles(2, 0, 2); \endcode
|
|
37
|
+
* "2" represents the z axis and "0" the x axis, etc. The returned angles are such that
|
|
38
|
+
* we have the following equality:
|
|
39
|
+
* \code
|
|
40
|
+
* mat == AngleAxisf(ea[0], Vector3f::UnitZ())
|
|
41
|
+
* * AngleAxisf(ea[1], Vector3f::UnitX())
|
|
42
|
+
* * AngleAxisf(ea[2], Vector3f::UnitZ()); \endcode
|
|
43
|
+
* This corresponds to the right-multiply conventions (with right hand side frames).
|
|
44
|
+
*
|
|
45
|
+
* The returned angles are in the ranges [0:pi]x[-pi:pi]x[-pi:pi].
|
|
46
|
+
|
|
47
|
+
* NOTE: ported from Eigen C++ library
|
|
48
|
+
* @see https://gitlab.com/libeigen/eigen/-/blob/master/Eigen/src/Geometry/EulerAngles.h
|
|
49
|
+
* @see https://stackoverflow.com/questions/11514063/extract-yaw-pitch-and-roll-from-a-rotationmatrix
|
|
50
|
+
* @param {number[]} res
|
|
51
|
+
* @param {number[]|Float32Array|mat4} m4
|
|
52
|
+
* @param {number} a0 axis index
|
|
53
|
+
* @param {number} a1
|
|
54
|
+
* @param {number} a2
|
|
55
|
+
*/
|
|
56
|
+
export function eulerAnglesFromMatrix(res, m4, a0, a1, a2) {
|
|
57
|
+
const odd = ((a0 + 1) % 3 === a1) ? 0 : 1;
|
|
58
|
+
|
|
59
|
+
const i = a0;
|
|
60
|
+
const j = (a0 + 1 + odd) % 3;
|
|
61
|
+
const k = (a0 + 2 - odd) % 3;
|
|
62
|
+
|
|
63
|
+
if (a0 === a2) {
|
|
64
|
+
res[0] = atan2(coeff(m4, j, i), coeff(m4, k, i));
|
|
65
|
+
if ((odd && res[0] < 0) || ((!odd) && res[0] > 0)) {
|
|
66
|
+
if (res[0] > 0) {
|
|
67
|
+
res[0] -= EIGEN_PI;
|
|
68
|
+
} else {
|
|
69
|
+
res[0] += EIGEN_PI;
|
|
70
|
+
}
|
|
71
|
+
const s2 = v2_magnitude(coeff(m4, j, i), coeff(m4, k, i));
|
|
72
|
+
res[1] = -atan2(s2, coeff(m4, i, i));
|
|
73
|
+
} else {
|
|
74
|
+
const s2 = v2_magnitude(coeff(m4, j, i), coeff(m4, k, i));
|
|
75
|
+
res[1] = atan2(s2, coeff(m4, i, i));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// With a=(0,1,0), we have i=0; j=1; k=2, and after computing the first two angles,
|
|
79
|
+
// we can compute their respective rotation, and apply its inverse to M. Since the result must
|
|
80
|
+
// be a rotation around x, we have:
|
|
81
|
+
//
|
|
82
|
+
// c2 s1.s2 c1.s2 1 0 0
|
|
83
|
+
// 0 c1 -s1 * M = 0 c3 s3
|
|
84
|
+
// -s2 s1.c2 c1.c2 0 -s3 c3
|
|
85
|
+
//
|
|
86
|
+
// Thus: m11.c1 - m21.s1 = c3 & m12.c1 - m22.s1 = s3
|
|
87
|
+
|
|
88
|
+
const s1 = sin(res[0]);
|
|
89
|
+
const c1 = cos(res[0]);
|
|
90
|
+
res[2] = atan2(c1 * coeff(m4, j, k) - s1 * coeff(m4, k, k), c1 * coeff(m4, j, j) - s1 * coeff(m4, k, j));
|
|
91
|
+
} else {
|
|
92
|
+
res[0] = atan2(coeff(m4, j, k), coeff(m4, k, k));
|
|
93
|
+
const c2 = v2_magnitude(coeff(m4, i, i), coeff(m4, i, j));
|
|
94
|
+
if ((odd && res[0] < 0) || ((!odd) && res[0] > 0)) {
|
|
95
|
+
if (res[0] > 0) {
|
|
96
|
+
res[0] -= EIGEN_PI;
|
|
97
|
+
} else {
|
|
98
|
+
res[0] += EIGEN_PI;
|
|
99
|
+
}
|
|
100
|
+
res[1] = atan2(-coeff(m4, i, k), -c2);
|
|
101
|
+
} else
|
|
102
|
+
res[1] = atan2(-coeff(m4, i, k), c2);
|
|
103
|
+
const s1 = sin(res[0]);
|
|
104
|
+
const c1 = cos(res[0]);
|
|
105
|
+
res[2] = atan2(s1 * coeff(m4, k, i) - c1 * coeff(m4, j, i), c1 * coeff(m4, j, j) - s1 * coeff(m4, k, j));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (!odd) {
|
|
109
|
+
// invert result
|
|
110
|
+
res[0] = -res[0];
|
|
111
|
+
res[1] = -res[1];
|
|
112
|
+
res[2] = -res[2];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
}
|
|
@@ -482,7 +482,7 @@ export class TopoMesh {
|
|
|
482
482
|
assert.equal(a.isTopoVertex, true, 'a.isTopoVertex !== true');
|
|
483
483
|
assert.equal(b.isTopoVertex, true, 'b.isTopoVertex !== true');
|
|
484
484
|
|
|
485
|
-
assert.notEqual(a, b, 'a === b, attempting to create an edge from vertex to itself')
|
|
485
|
+
assert.notEqual(a, b, 'a === b, attempting to create an edge from vertex to itself');
|
|
486
486
|
|
|
487
487
|
const aEdges = a.edges;
|
|
488
488
|
const n = aEdges.length;
|
|
@@ -25,15 +25,9 @@ export function computeTriangleRayIntersection(
|
|
|
25
25
|
result,
|
|
26
26
|
origin_x, origin_y, origin_z,
|
|
27
27
|
direction_x, direction_y, direction_z,
|
|
28
|
-
ax,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
bx,
|
|
32
|
-
by,
|
|
33
|
-
bz,
|
|
34
|
-
cx,
|
|
35
|
-
cy,
|
|
36
|
-
cz
|
|
28
|
+
ax, ay, az,
|
|
29
|
+
bx, by, bz,
|
|
30
|
+
cx, cy, cz
|
|
37
31
|
) {
|
|
38
32
|
|
|
39
33
|
// edge1 = a - b
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PI2 } from "../math/MathUtils.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Force angle to [-PI, +PI] range
|
|
5
|
+
* based on answer https://stackoverflow.com/a/2323034/3973586
|
|
6
|
+
* @param {number} angle in radians
|
|
7
|
+
* @return {number} in radians
|
|
8
|
+
*/
|
|
9
|
+
export function normalize_angle_rad(angle) {
|
|
10
|
+
let r = angle % PI2;
|
|
11
|
+
r = (r + PI2) % PI2;
|
|
12
|
+
|
|
13
|
+
if (r > Math.PI) {
|
|
14
|
+
r -= PI2;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return r;
|
|
18
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { normalize_angle_rad } from "./normalize_angle_rad.js";
|
|
2
|
+
|
|
3
|
+
test('0', () => {
|
|
4
|
+
expect(normalize_angle_rad(0)).toBe(0);
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
test('PI', () => {
|
|
8
|
+
expect(normalize_angle_rad(Math.PI)).toBe(Math.PI);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('-PI', () => {
|
|
12
|
+
expect(normalize_angle_rad(-Math.PI)).toBeCloseTo(Math.PI);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('2*PI', () => {
|
|
16
|
+
expect(normalize_angle_rad(Math.PI * 2)).toBeCloseTo(0);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('-2*PI', () => {
|
|
20
|
+
expect(normalize_angle_rad(-Math.PI * 2)).toBeCloseTo(0);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('-1', () => {
|
|
24
|
+
expect(normalize_angle_rad(-1)).toBeCloseTo(-1);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('-3', () => {
|
|
28
|
+
expect(normalize_angle_rad(-3)).toBeCloseTo(-3);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('1', () => {
|
|
32
|
+
expect(normalize_angle_rad(1)).toBeCloseTo(1);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('3', () => {
|
|
36
|
+
expect(normalize_angle_rad(3)).toBeCloseTo(3);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('2*PI + 1', () => {
|
|
40
|
+
expect(normalize_angle_rad(Math.PI * 2 + 1)).toBeCloseTo(1);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('- ( 2*PI + 1)', () => {
|
|
44
|
+
expect(normalize_angle_rad(-(Math.PI * 2 + 1))).toBeCloseTo(-1);
|
|
45
|
+
});
|
|
@@ -26,7 +26,6 @@ import { traverseThreeObject } from "../../graphics/ecs/highlight/renderer/trave
|
|
|
26
26
|
import { computeTextureHash } from "./material/computeTextureHash.js";
|
|
27
27
|
import { computeTextureEquality } from "./material/computeTextureEquality.js";
|
|
28
28
|
import { async_traverse_three_object } from "./async_traverse_three_object.js";
|
|
29
|
-
import { deinterleaveBufferGeometry } from "../../graphics/geometry/buffered/deinterleaveBufferGeometry.js";
|
|
30
29
|
|
|
31
30
|
const animationOptimizer = new AnimationOptimizer();
|
|
32
31
|
const materialCache = StaticMaterialCache.Global;
|
|
@@ -294,9 +293,6 @@ export class GLTFAssetLoader extends AssetLoader {
|
|
|
294
293
|
mesh.geometry = geometry;
|
|
295
294
|
}
|
|
296
295
|
|
|
297
|
-
mesh.geometry = deinterleaveBufferGeometry(geometry);
|
|
298
|
-
|
|
299
|
-
|
|
300
296
|
if (this.__enable_texture_cache) {
|
|
301
297
|
// replace textures from cache
|
|
302
298
|
replace_material_textures_from_cache(mesh.material, texture_cache);
|
|
@@ -10,6 +10,10 @@ import { obtainTerrain } from "../terrain/util/obtainTerrain.js";
|
|
|
10
10
|
const v2 = new Vector2();
|
|
11
11
|
|
|
12
12
|
export class FogOfWarRevealerSystem extends System {
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @param {number} team
|
|
16
|
+
*/
|
|
13
17
|
constructor(team) {
|
|
14
18
|
super();
|
|
15
19
|
|
|
@@ -19,6 +23,10 @@ export class FogOfWarRevealerSystem extends System {
|
|
|
19
23
|
|
|
20
24
|
this.data = [];
|
|
21
25
|
|
|
26
|
+
/**
|
|
27
|
+
*
|
|
28
|
+
* @type {number}
|
|
29
|
+
*/
|
|
22
30
|
this.team = team;
|
|
23
31
|
}
|
|
24
32
|
|
|
@@ -7,30 +7,14 @@ import Vector3 from '../../../../../core/geom/Vector3.js';
|
|
|
7
7
|
import { assert } from "../../../../../core/assert.js";
|
|
8
8
|
import { lerp } from "../../../../../core/math/lerp.js";
|
|
9
9
|
import { Euler, Matrix4 } from "three";
|
|
10
|
-
import {
|
|
10
|
+
import { normalize_angle_rad } from "../../../../../core/geom/normalize_angle_rad.js";
|
|
11
|
+
import { eulerAnglesFromMatrix } from "../../../../../core/geom/3d/eulerAnglesFromMatrix.js";
|
|
11
12
|
|
|
12
13
|
const m4 = new Matrix4();
|
|
13
14
|
const euler = new Euler();
|
|
14
15
|
|
|
15
16
|
const panOffset = new Vector3();
|
|
16
17
|
|
|
17
|
-
/**
|
|
18
|
-
* Force angle to [-PI, +PI] range
|
|
19
|
-
* based on answer https://stackoverflow.com/a/2323034/3973586
|
|
20
|
-
* @param {number} angle in radians
|
|
21
|
-
* @return {number} in radians
|
|
22
|
-
*/
|
|
23
|
-
function normalize_angle(angle) {
|
|
24
|
-
let r = angle % PI2;
|
|
25
|
-
r = (r + PI2) % PI2;
|
|
26
|
-
|
|
27
|
-
if (r > Math.PI) {
|
|
28
|
-
r -= PI2;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return r;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
18
|
/**
|
|
35
19
|
*
|
|
36
20
|
* @param {number} displacement_x
|
|
@@ -40,8 +24,8 @@ function normalize_angle(angle) {
|
|
|
40
24
|
*/
|
|
41
25
|
export function rotate_from_view(displacement_x, displacement_y, input, output) {
|
|
42
26
|
// crop yaw and pitch to safe range of -PI to PI
|
|
43
|
-
const i_pitch =
|
|
44
|
-
const i_yaw =
|
|
27
|
+
const i_pitch = normalize_angle_rad(input.pitch);
|
|
28
|
+
const i_yaw = normalize_angle_rad(input.yaw);
|
|
45
29
|
|
|
46
30
|
// flip rotation axis when pitch is over 90deg in either direction, that is UP vector is pointing down
|
|
47
31
|
const d_yaw = ((i_pitch > Math.PI || i_pitch < -Math.PI) ? -1 : 1) * displacement_x;
|
|
@@ -146,9 +130,29 @@ class TopDownCameraController {
|
|
|
146
130
|
|
|
147
131
|
euler.setFromRotationMatrix(m4, 'ZYX');
|
|
148
132
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
133
|
+
const angles = [];
|
|
134
|
+
eulerAnglesFromMatrix(angles, m4.elements, 2, 1, 0);
|
|
135
|
+
|
|
136
|
+
const _p0 = normalize_angle_rad(euler.x);
|
|
137
|
+
const _y0 = normalize_angle_rad(euler.y);
|
|
138
|
+
const _r0 = normalize_angle_rad(euler.z);
|
|
139
|
+
|
|
140
|
+
this.pitch = _p0;
|
|
141
|
+
this.yaw = _y0;
|
|
142
|
+
this.roll = _r0;
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
const _p1 = angles[2];
|
|
146
|
+
const _y1 = angles[1];
|
|
147
|
+
const _r1 = angles[0];
|
|
148
|
+
|
|
149
|
+
if (_p0 !== _p0 || _y0 !== _y1 || _r0 !== _r1) {
|
|
150
|
+
console.warn('Angular discrepancy');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
this.pitch = _p1;
|
|
154
|
+
this.yaw = _y1;
|
|
155
|
+
this.roll = _r1;
|
|
152
156
|
|
|
153
157
|
this.distance = eye.distanceTo(target);
|
|
154
158
|
|
|
@@ -11,6 +11,15 @@ test('setFromEyeAndTarget does not introduce roll when UP is aligned with +Y', (
|
|
|
11
11
|
expect(ut.roll).toBe(0);
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
+
test('setFromEyeAndTarget, with different directional axial combinations', () => {
|
|
15
|
+
const ut = new TopDownCameraController();
|
|
16
|
+
|
|
17
|
+
ut.setFromEyeAndTarget(new Vector3(0, 1, -1), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
|
|
18
|
+
ut.setFromEyeAndTarget(new Vector3(0, 1, -1), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
|
|
19
|
+
|
|
20
|
+
expect(ut.roll).toBe(0);
|
|
21
|
+
});
|
|
22
|
+
|
|
14
23
|
test('setFromEyeAndTarget results in roll respecting UP vector', () => {
|
|
15
24
|
const eye = new Vector3();
|
|
16
25
|
const target = new Vector3();
|
|
@@ -28,9 +28,10 @@ export function deinterleaveBufferAttribute(source_attribute) {
|
|
|
28
28
|
attribute.normalized = source_attribute.normalized;
|
|
29
29
|
attribute.name = source_attribute.name;
|
|
30
30
|
|
|
31
|
+
let i = 0, j = 0;
|
|
31
32
|
// copy data
|
|
32
|
-
for (
|
|
33
|
-
for (
|
|
33
|
+
for (; i < item_count; i++) {
|
|
34
|
+
for (j = 0; j < itemSize; j++) {
|
|
34
35
|
destination_array[i * itemSize + j] = source_data_array[i * stride + offset + j];
|
|
35
36
|
}
|
|
36
37
|
}
|
|
@@ -79,21 +79,32 @@ export class ClippingPlaneContainmentComputingVisitor extends GeometrySpatialAcc
|
|
|
79
79
|
|
|
80
80
|
const index3 = index * 3;
|
|
81
81
|
|
|
82
|
-
const
|
|
83
|
-
const b = this.__buffer_indices[index3 + 1] * 3;
|
|
84
|
-
const c = this.__buffer_indices[index3 + 2] * 3;
|
|
82
|
+
const indices = this.__buffer_indices;
|
|
85
83
|
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
const
|
|
84
|
+
const a = indices[index3];
|
|
85
|
+
const b = indices[index3 + 1];
|
|
86
|
+
const c = indices[index3 + 2];
|
|
89
87
|
|
|
90
|
-
const
|
|
91
|
-
const by = this.__buffer_vertices[b + 1];
|
|
92
|
-
const bz = this.__buffer_vertices[b + 2];
|
|
88
|
+
const vertices = this.__buffer_vertices;
|
|
93
89
|
|
|
94
|
-
const
|
|
95
|
-
const
|
|
96
|
-
|
|
90
|
+
const stride = this.__buffer_vertex_stride;
|
|
91
|
+
const offset = this.__buffer_position_offset;
|
|
92
|
+
|
|
93
|
+
const a_address = a * stride + offset;
|
|
94
|
+
const b_address = b * stride + offset;
|
|
95
|
+
const c_address = c * stride + offset;
|
|
96
|
+
|
|
97
|
+
const ax = vertices[a_address];
|
|
98
|
+
const ay = vertices[a_address + 1];
|
|
99
|
+
const az = vertices[a_address + 2];
|
|
100
|
+
|
|
101
|
+
const bx = vertices[b_address];
|
|
102
|
+
const by = vertices[b_address + 1];
|
|
103
|
+
const bz = vertices[b_address + 2];
|
|
104
|
+
|
|
105
|
+
const cx = vertices[c_address];
|
|
106
|
+
const cy = vertices[c_address + 1];
|
|
107
|
+
const cz = vertices[c_address + 2];
|
|
97
108
|
|
|
98
109
|
for (let i = 0; i < plane_count; i++) {
|
|
99
110
|
const plane = planes[i];
|
|
@@ -108,15 +119,9 @@ export class ClippingPlaneContainmentComputingVisitor extends GeometrySpatialAcc
|
|
|
108
119
|
plane_normal_y,
|
|
109
120
|
plane_normal_z,
|
|
110
121
|
plane_constant,
|
|
111
|
-
ax,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
bx,
|
|
115
|
-
by,
|
|
116
|
-
bz,
|
|
117
|
-
cx,
|
|
118
|
-
cy,
|
|
119
|
-
cz
|
|
122
|
+
ax, ay, az,
|
|
123
|
+
bx, by, bz,
|
|
124
|
+
cx, cy, cz
|
|
120
125
|
);
|
|
121
126
|
|
|
122
127
|
if (side === -3) {
|
|
@@ -163,12 +168,8 @@ export class ClippingPlaneContainmentComputingVisitor extends GeometrySpatialAcc
|
|
|
163
168
|
plane_normal_z,
|
|
164
169
|
plane_constant,
|
|
165
170
|
|
|
166
|
-
x0,
|
|
167
|
-
|
|
168
|
-
z0,
|
|
169
|
-
x1,
|
|
170
|
-
y1,
|
|
171
|
-
z1
|
|
171
|
+
x0, y0, z0,
|
|
172
|
+
x1, y1, z1
|
|
172
173
|
);
|
|
173
174
|
|
|
174
175
|
if (side === -2) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IndexedBinaryBVHVisitor } from "../../../../../core/bvh2/binary/IndexedBinaryBVHVisitor.js";
|
|
2
2
|
|
|
3
|
-
export class GeometrySpatialAcceleratorVisitor extends IndexedBinaryBVHVisitor{
|
|
3
|
+
export class GeometrySpatialAcceleratorVisitor extends IndexedBinaryBVHVisitor {
|
|
4
4
|
constructor() {
|
|
5
5
|
super();
|
|
6
6
|
|
|
@@ -25,6 +25,20 @@ export class GeometrySpatialAcceleratorVisitor extends IndexedBinaryBVHVisitor{
|
|
|
25
25
|
*/
|
|
26
26
|
this.__buffer_vertices = null;
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @type {number}
|
|
31
|
+
* @protected
|
|
32
|
+
*/
|
|
33
|
+
this.__buffer_vertex_stride = 3;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
*
|
|
37
|
+
* @type {number}
|
|
38
|
+
* @protected
|
|
39
|
+
*/
|
|
40
|
+
this.__buffer_position_offset = 0;
|
|
41
|
+
|
|
28
42
|
/**
|
|
29
43
|
* @protected
|
|
30
44
|
* @type {IndexedBinaryBVH}
|
|
@@ -47,7 +61,20 @@ export class GeometrySpatialAcceleratorVisitor extends IndexedBinaryBVHVisitor{
|
|
|
47
61
|
this.geometry = geometry;
|
|
48
62
|
|
|
49
63
|
this.__buffer_indices = geometry.getIndex().array;
|
|
50
|
-
|
|
64
|
+
|
|
65
|
+
const position_attribute = geometry.getAttribute('position');
|
|
66
|
+
|
|
67
|
+
if (position_attribute.isInterleavedBufferAttribute) {
|
|
68
|
+
const data = position_attribute.data;
|
|
69
|
+
|
|
70
|
+
this.__buffer_vertices = data.array;
|
|
71
|
+
this.__buffer_vertex_stride = data.stride;
|
|
72
|
+
this.__buffer_position_offset = position_attribute.offset;
|
|
73
|
+
} else {
|
|
74
|
+
this.__buffer_vertices = position_attribute.array;
|
|
75
|
+
this.__buffer_vertex_stride = 3;
|
|
76
|
+
this.__buffer_position_offset = 0;
|
|
77
|
+
}
|
|
51
78
|
}
|
|
52
79
|
|
|
53
80
|
}
|
|
@@ -96,21 +96,32 @@ export class RaycastNearestHitComputingVisitor extends GeometrySpatialAccelerato
|
|
|
96
96
|
|
|
97
97
|
const index3 = index * 3;
|
|
98
98
|
|
|
99
|
-
const
|
|
100
|
-
const b = this.__buffer_indices[index3 + 1] * 3;
|
|
101
|
-
const c = this.__buffer_indices[index3 + 2] * 3;
|
|
99
|
+
const indices = this.__buffer_indices;
|
|
102
100
|
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
const
|
|
101
|
+
const a = indices[index3];
|
|
102
|
+
const b = indices[index3 + 1];
|
|
103
|
+
const c = indices[index3 + 2];
|
|
106
104
|
|
|
107
|
-
const
|
|
108
|
-
const by = this.__buffer_vertices[b + 1];
|
|
109
|
-
const bz = this.__buffer_vertices[b + 2];
|
|
105
|
+
const vertices = this.__buffer_vertices;
|
|
110
106
|
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
|
|
107
|
+
const stride = this.__buffer_vertex_stride;
|
|
108
|
+
const offset = this.__buffer_position_offset;
|
|
109
|
+
|
|
110
|
+
const a_address = a * stride + offset;
|
|
111
|
+
const b_address = b * stride + offset;
|
|
112
|
+
const c_address = c * stride + offset;
|
|
113
|
+
|
|
114
|
+
const ax = vertices[a_address];
|
|
115
|
+
const ay = vertices[a_address + 1];
|
|
116
|
+
const az = vertices[a_address + 2];
|
|
117
|
+
|
|
118
|
+
const bx = vertices[b_address];
|
|
119
|
+
const by = vertices[b_address + 1];
|
|
120
|
+
const bz = vertices[b_address + 2];
|
|
121
|
+
|
|
122
|
+
const cx = vertices[c_address];
|
|
123
|
+
const cy = vertices[c_address + 1];
|
|
124
|
+
const cz = vertices[c_address + 2];
|
|
114
125
|
|
|
115
126
|
if (computeTriangleRayIntersection(
|
|
116
127
|
this.__temp_hit,
|
|
@@ -120,15 +131,9 @@ export class RaycastNearestHitComputingVisitor extends GeometrySpatialAccelerato
|
|
|
120
131
|
rayDirection.x,
|
|
121
132
|
rayDirection.y,
|
|
122
133
|
rayDirection.z,
|
|
123
|
-
ax,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
bx,
|
|
127
|
-
by,
|
|
128
|
-
bz,
|
|
129
|
-
cx,
|
|
130
|
-
cy,
|
|
131
|
-
cz
|
|
134
|
+
ax, ay, az,
|
|
135
|
+
bx, by, bz,
|
|
136
|
+
cx, cy, cz
|
|
132
137
|
)) {
|
|
133
138
|
const d = this.__temp_hit.position.distanceSqrTo(rayOrigin);
|
|
134
139
|
|
|
@@ -154,12 +159,8 @@ export class RaycastNearestHitComputingVisitor extends GeometrySpatialAccelerato
|
|
|
154
159
|
const z1 = data[address + 5];
|
|
155
160
|
|
|
156
161
|
return intersectRay(
|
|
157
|
-
x0,
|
|
158
|
-
|
|
159
|
-
z0,
|
|
160
|
-
x1,
|
|
161
|
-
y1,
|
|
162
|
-
z1,
|
|
162
|
+
x0, y0, z0,
|
|
163
|
+
x1, y1, z1,
|
|
163
164
|
|
|
164
165
|
rayOrigin.x,
|
|
165
166
|
rayOrigin.y,
|
|
@@ -21,7 +21,6 @@ import { matcher_tag_traversable } from "./rules/matcher_tag_traversable.js";
|
|
|
21
21
|
import { GridTaskGenerateRoads } from "../grid/generation/road/GridTaskGenerateRoads.js";
|
|
22
22
|
import { mir_generator_place_road_decorators } from "./generators/mir_generator_place_road_decorators.js";
|
|
23
23
|
import { MarkerNodeMatcherByType } from "../markers/matcher/MarkerNodeMatcherByType.js";
|
|
24
|
-
import { mir_generator_place_buff_objects } from "./generators/interactive/mir_generator_place_buff_objects.js";
|
|
25
24
|
import { GridTaskDensityMarkerDistribution } from "../grid/generation/GridTaskDensityMarkerDistribution.js";
|
|
26
25
|
import { CellFilterSimplexNoise } from "../filtering/numeric/complex/CellFilterSimplexNoise.js";
|
|
27
26
|
import { NumericInterval } from "../../core/math/interval/NumericInterval.js";
|
|
@@ -211,12 +210,11 @@ const prEnemyCorridorGuard = GridCellPlacementRule.from(
|
|
|
211
210
|
), actions: [
|
|
212
211
|
ACTION_PLACE_ENEMY_MARKER,
|
|
213
212
|
ACTION_PLACE_ENEMY_TAG
|
|
214
|
-
]
|
|
213
|
+
],
|
|
214
|
+
probability: CellFilterLiteralFloat.from(0.5)
|
|
215
215
|
}
|
|
216
216
|
);
|
|
217
217
|
|
|
218
|
-
prEnemyCorridorGuard.probability = 0.5;
|
|
219
|
-
|
|
220
218
|
const gRuleSet2 = GridTaskActionRuleSet.from({ rules: GridActionRuleSet.from({ rules: [prEnemyTreasureGuard, prEnemyCorridorGuard] }) });
|
|
221
219
|
|
|
222
220
|
gRuleSet2.addDependency(gRuleSetTreasureGuards);
|
|
@@ -226,7 +224,11 @@ const gPlaceStartingPoint = mir_generator_place_starting_point();
|
|
|
226
224
|
|
|
227
225
|
gPlaceStartingPoint.addDependency(gConnectRooms);
|
|
228
226
|
|
|
229
|
-
const gBuildDistanceMap = GridTaskBuildSourceDistanceMap.from({
|
|
227
|
+
const gBuildDistanceMap = GridTaskBuildSourceDistanceMap.from({
|
|
228
|
+
source: MATCH_STARTING_POINT,
|
|
229
|
+
pass: MATCH_EMPTY,
|
|
230
|
+
layer: MirGridLayers.DistanceFromStart
|
|
231
|
+
});
|
|
230
232
|
|
|
231
233
|
gBuildDistanceMap.addDependency(gPlaceStartingPoint);
|
|
232
234
|
|
|
@@ -235,11 +237,8 @@ gRuleSet1.addDependency(gBuildDistanceMap);
|
|
|
235
237
|
const gBases = mir_generator_place_bases();
|
|
236
238
|
gBases.addDependency(gMakeEmpty);
|
|
237
239
|
|
|
238
|
-
const gBuffObjects = mir_generator_place_buff_objects();
|
|
239
|
-
gBuffObjects.addDependency(gBases);
|
|
240
240
|
|
|
241
241
|
gConnectRooms.addDependency(gBases);
|
|
242
|
-
gConnectRooms.addDependency(gBuffObjects);
|
|
243
242
|
|
|
244
243
|
gPlaceStartingPoint.addDependency(gBases);
|
|
245
244
|
|
|
@@ -250,7 +249,6 @@ const gRoads = new GridTaskGenerateRoads();
|
|
|
250
249
|
|
|
251
250
|
gRoads.addDependency(gConnectRooms);
|
|
252
251
|
gRoads.addDependency(gBases);
|
|
253
|
-
gRoads.addDependency(gBuffObjects);
|
|
254
252
|
|
|
255
253
|
const gRoadDecorators = mir_generator_place_road_decorators();
|
|
256
254
|
|
|
@@ -540,7 +538,6 @@ gFoliageLarge.addDependencies([
|
|
|
540
538
|
gRuleSet1,
|
|
541
539
|
gRuleSet2,
|
|
542
540
|
gRuleSetTreasureGuards,
|
|
543
|
-
gBuffObjects,
|
|
544
541
|
gBases
|
|
545
542
|
]);
|
|
546
543
|
|
|
@@ -555,7 +552,6 @@ SampleGenerator0.addGenerator(gConnectRooms);
|
|
|
555
552
|
SampleGenerator0.addGenerator(gRoads);
|
|
556
553
|
SampleGenerator0.addGenerator(gRoadDecorators);
|
|
557
554
|
SampleGenerator0.addGenerator(gBases);
|
|
558
|
-
SampleGenerator0.addGenerator(gBuffObjects);
|
|
559
555
|
SampleGenerator0.addGenerator(gPlaceStartingPoint);
|
|
560
556
|
SampleGenerator0.addGenerator(gBuildDistanceMap);
|
|
561
557
|
SampleGenerator0.addGenerator(gRuleSet1);
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { EngineHarness } from "../../engine/EngineHarness.js";
|
|
2
|
+
import RenderSystem from "../../engine/ecs/systems/RenderSystem.js";
|
|
3
|
+
import { Camera } from "../../engine/graphics/ecs/camera/Camera.js";
|
|
4
|
+
import TopDownCameraController from "../../engine/graphics/ecs/camera/topdown/TopDownCameraController.js";
|
|
5
|
+
import Vector3 from "../../core/geom/Vector3.js";
|
|
6
|
+
import { TopDownCameraLander } from "../../engine/graphics/ecs/camera/topdown/TopDownCameraLander.js";
|
|
7
|
+
import Terrain from "../../engine/ecs/terrain/ecs/Terrain.js";
|
|
8
|
+
import { TerrainFlags } from "../../engine/ecs/terrain/ecs/TerrainFlags.js";
|
|
9
|
+
import Water from "../../engine/graphics/ecs/water/Water.js";
|
|
10
|
+
import GridObstacle from "../../engine/grid/components/GridObstacle.js";
|
|
11
|
+
import EntityBuilder from "../../engine/ecs/EntityBuilder.js";
|
|
12
|
+
import GridPosition from "../../engine/grid/components/GridPosition.js";
|
|
13
|
+
import { Transform } from "../../engine/ecs/transform/Transform.js";
|
|
14
|
+
import { GridData } from "../grid/GridData.js";
|
|
15
|
+
import { computeStringHash } from "../../core/primitives/strings/computeStringHash.js";
|
|
16
|
+
import { ThemeEngine } from "../theme/ThemeEngine.js";
|
|
17
|
+
import { AreaTheme } from "../theme/AreaTheme.js";
|
|
18
|
+
import TaskGroup from "../../core/process/task/TaskGroup.js";
|
|
19
|
+
import { actionTask } from "../../core/process/task/TaskUtils.js";
|
|
20
|
+
import { generateTerrainPreview } from "../../../../generator/generator/generateTerrainPreview.js";
|
|
21
|
+
import { SampleTheme0 } from "./themes/SampleTheme0.js";
|
|
22
|
+
import { SampleGenerator0 } from "./SampleGenerator0.js";
|
|
23
|
+
import { configureMirGrid } from "./grid/configureMirGrid.js";
|
|
24
|
+
import { EngineConfiguration } from "../../engine/EngineConfiguration.js";
|
|
25
|
+
import TerrainSystem from "../../engine/ecs/terrain/ecs/TerrainSystem.js";
|
|
26
|
+
import WaterSystem from "../../engine/graphics/ecs/water/WaterSystem.js";
|
|
27
|
+
import { MeshSystem } from "../../engine/graphics/ecs/mesh/MeshSystem.js";
|
|
28
|
+
import TopDownCameraControllerSystem from "../../engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js";
|
|
29
|
+
import { TopDownCameraLanderSystem } from "../../engine/graphics/ecs/camera/topdown/TopDownCameraLanderSystem.js";
|
|
30
|
+
import LightSystem from "../../engine/graphics/ecs/light/LightSystem.js";
|
|
31
|
+
|
|
32
|
+
function makeEngineConfig(engine) {
|
|
33
|
+
const config = new EngineConfiguration();
|
|
34
|
+
|
|
35
|
+
const graphics = engine.graphics;
|
|
36
|
+
|
|
37
|
+
config.addSystem(new RenderSystem(graphics));
|
|
38
|
+
config.addSystem(new TerrainSystem(graphics, engine.assetManager));
|
|
39
|
+
config.addSystem(new WaterSystem(graphics));
|
|
40
|
+
config.addSystem(new MeshSystem(engine));
|
|
41
|
+
config.addSystem(new TopDownCameraControllerSystem());
|
|
42
|
+
config.addSystem(new TopDownCameraLanderSystem());
|
|
43
|
+
config.addSystem(new LightSystem(engine))
|
|
44
|
+
|
|
45
|
+
return config;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
*
|
|
51
|
+
* @param {EngineHarness} harness
|
|
52
|
+
* @return {Promise<void>}
|
|
53
|
+
*/
|
|
54
|
+
async function init(harness) {
|
|
55
|
+
const engine = harness.engine;
|
|
56
|
+
|
|
57
|
+
await makeEngineConfig(engine).apply(engine);
|
|
58
|
+
|
|
59
|
+
await harness.initialize();
|
|
60
|
+
|
|
61
|
+
main(engine);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function prepare_gen_task({
|
|
65
|
+
SIZE_X = 64,
|
|
66
|
+
SIZE_Y = 64,
|
|
67
|
+
ecd
|
|
68
|
+
}) {
|
|
69
|
+
|
|
70
|
+
const camera = EngineHarness.buildCamera({
|
|
71
|
+
engine,
|
|
72
|
+
target: new Vector3(15, 0, 16),
|
|
73
|
+
// pitch: -PI_HALF,
|
|
74
|
+
pitch: 1.1,
|
|
75
|
+
yaw: 3.14,
|
|
76
|
+
distance: 13,
|
|
77
|
+
ecd,
|
|
78
|
+
distanceMin: 5,
|
|
79
|
+
distanceMax: 30
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
camera.add(new TopDownCameraLander());
|
|
83
|
+
|
|
84
|
+
// build lights
|
|
85
|
+
EngineHarness.buildLights({ engine })
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
// build terrain
|
|
89
|
+
const terrain = new Terrain();
|
|
90
|
+
|
|
91
|
+
terrain.resolution = 4;
|
|
92
|
+
|
|
93
|
+
terrain.size.set(SIZE_X, SIZE_Y);
|
|
94
|
+
terrain.samplerHeight.resize(SIZE_X, SIZE_Y);
|
|
95
|
+
terrain.splat.resize(SIZE_X * 4, SIZE_Y * 4, 0);
|
|
96
|
+
|
|
97
|
+
terrain.layers.resolution.set(512, 512);
|
|
98
|
+
|
|
99
|
+
terrain.clearFlag(TerrainFlags.Built);
|
|
100
|
+
terrain.build(engine.assetManager);
|
|
101
|
+
|
|
102
|
+
const water = new Water();
|
|
103
|
+
|
|
104
|
+
water.color.setRGB(0.2, 0.0, 0.5);
|
|
105
|
+
water.shoreColor.setRGB(0.3, 0.3, 1);
|
|
106
|
+
water.shoreDepthTransition.set(0.16, 0.5);
|
|
107
|
+
water.waveFrequency.set(1.3);
|
|
108
|
+
water.waveAmplitude.set(0.15);
|
|
109
|
+
water.waveSpeed.set(1.2);
|
|
110
|
+
water.scattering.set(1.2);
|
|
111
|
+
water.level.set(-0.3);
|
|
112
|
+
|
|
113
|
+
const obstacle = new GridObstacle();
|
|
114
|
+
obstacle.resize(terrain.size.x, terrain.size.y);
|
|
115
|
+
|
|
116
|
+
const terrainBuilder = new EntityBuilder();
|
|
117
|
+
|
|
118
|
+
terrainBuilder
|
|
119
|
+
.add(terrain)
|
|
120
|
+
.add(water)
|
|
121
|
+
.add(obstacle)
|
|
122
|
+
.add(new GridPosition())
|
|
123
|
+
.add(new Transform())
|
|
124
|
+
.build(ecd);
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
const gridData = new GridData();
|
|
128
|
+
|
|
129
|
+
configureMirGrid(gridData);
|
|
130
|
+
|
|
131
|
+
gridData.resize(terrain.size.x, terrain.size.y);
|
|
132
|
+
gridData.computeScale(1);
|
|
133
|
+
|
|
134
|
+
const generator = SampleGenerator0;
|
|
135
|
+
|
|
136
|
+
const tGenerationTask = generator.generate(ecd, gridData, computeStringHash('alexx855'));
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
const themeEngine = new ThemeEngine();
|
|
140
|
+
themeEngine.assetManager = engine.assetManager;
|
|
141
|
+
|
|
142
|
+
const theme0 = new AreaTheme();
|
|
143
|
+
|
|
144
|
+
const width = gridData.width;
|
|
145
|
+
const height = gridData.height;
|
|
146
|
+
|
|
147
|
+
theme0.mask.resize(width, height);
|
|
148
|
+
theme0.mask.mask.fill(0, 0, width, height, [1]);
|
|
149
|
+
theme0.theme = SampleTheme0;
|
|
150
|
+
|
|
151
|
+
themeEngine.add(theme0);
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
themeEngine.random.setCurrentSeed(1);
|
|
155
|
+
const tTheme = themeEngine.apply(gridData, ecd);
|
|
156
|
+
|
|
157
|
+
tTheme.addDependency(tGenerationTask);
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
const tBuildLevel = new TaskGroup([tGenerationTask, tTheme]);
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
const tAddGameplayElements = actionTask(() => {
|
|
164
|
+
// prepare gameplay-specific things on top of the generated level
|
|
165
|
+
|
|
166
|
+
//build minimap
|
|
167
|
+
const terrainPreview = generateTerrainPreview(terrainBuilder.entity, ecd);
|
|
168
|
+
terrain.preview.copy(terrainPreview);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
tAddGameplayElements.addDependency(tBuildLevel);
|
|
172
|
+
|
|
173
|
+
return new TaskGroup([tBuildLevel, tAddGameplayElements]);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
*
|
|
178
|
+
* @param {Engine} engine
|
|
179
|
+
*/
|
|
180
|
+
function main(engine) {
|
|
181
|
+
const ecd = engine.entityManager.dataset;
|
|
182
|
+
|
|
183
|
+
const tBuildLevel = prepare_gen_task({ ecd });
|
|
184
|
+
|
|
185
|
+
engine.loadSlowTask(tBuildLevel);
|
|
186
|
+
|
|
187
|
+
engine.executor.runGroup(tBuildLevel);
|
|
188
|
+
|
|
189
|
+
tBuildLevel.promise().then(() => {
|
|
190
|
+
console.log('Generation took ', tBuildLevel.getExecutedCpuTime(), 'ms');
|
|
191
|
+
|
|
192
|
+
const camera = ecd.getAnyComponent(Camera);
|
|
193
|
+
|
|
194
|
+
EngineHarness.buildOrbitalCameraController({
|
|
195
|
+
cameraEntity: camera.entity,
|
|
196
|
+
engine
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// tweak camera for prototyping
|
|
200
|
+
const ctrl = ecd.getComponent(camera.entity, TopDownCameraController);
|
|
201
|
+
if (ctrl !== undefined) {
|
|
202
|
+
ctrl.distanceMax = 200;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Resume audio context
|
|
208
|
+
engine.devices.pointer.on.down.addOne(engine.sound.resumeContext, engine.sound);
|
|
209
|
+
engine.devices.pointer.on.wheel.addOne(engine.sound.resumeContext, engine.sound);
|
|
210
|
+
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const engineHarness = new EngineHarness();
|
|
214
|
+
|
|
215
|
+
init(engineHarness);
|
|
@@ -46,6 +46,8 @@ import { SoundEmitter } from "../../../engine/sound/ecs/emitter/SoundEmitter.js"
|
|
|
46
46
|
import { SampleGroundMoistureFilter } from "../filters/SampleGroundMoistureFilter.js";
|
|
47
47
|
import GeneratedArmy from "../../../../model/game/ecs/component/generator/army/GeneratedArmy.js";
|
|
48
48
|
import { MirMarkerTypes } from "../../../../generator/MirMarkerTypes.js";
|
|
49
|
+
import { TerrainLayerDescription } from "../../theme/TerrainLayerDescription.js";
|
|
50
|
+
import Vector2 from "../../../core/geom/Vector2.js";
|
|
49
51
|
|
|
50
52
|
export const SampleTheme0 = new Theme();
|
|
51
53
|
|
|
@@ -123,10 +125,6 @@ const filterSand = CellFilterMultiply.from(
|
|
|
123
125
|
filterNotRockAndNotRoad
|
|
124
126
|
);
|
|
125
127
|
|
|
126
|
-
const TERRAIN_LAYER_GRASS = 0;
|
|
127
|
-
const TERRAIN_LAYER_ROCK = 1;
|
|
128
|
-
const TERRAIN_LAYER_SAND = 3;
|
|
129
|
-
|
|
130
128
|
terrainTheme.rules.push(TerrainLayerRule.from(
|
|
131
129
|
CellFilterMultiply.from(
|
|
132
130
|
CellFilterMultiply.from(
|
|
@@ -135,22 +133,34 @@ terrainTheme.rules.push(TerrainLayerRule.from(
|
|
|
135
133
|
),
|
|
136
134
|
filterNotRockAndNotRoad
|
|
137
135
|
),
|
|
138
|
-
|
|
136
|
+
TerrainLayerDescription.from({
|
|
137
|
+
diffuse:'data/textures/materials/Sci-Fi Planet/Grass_02.png',
|
|
138
|
+
size:new Vector2(7,7)
|
|
139
|
+
})
|
|
139
140
|
));
|
|
140
141
|
|
|
141
142
|
terrainTheme.rules.push(TerrainLayerRule.from(
|
|
142
143
|
filterRock,
|
|
143
|
-
|
|
144
|
+
TerrainLayerDescription.from({
|
|
145
|
+
diffuse:'data/textures/Materials_Stylized/4k JPEG/Stylized_04_Rocks/Stylized_04_Rocks_basecolor.jpg',
|
|
146
|
+
size:new Vector2(7,7)
|
|
147
|
+
})
|
|
144
148
|
));
|
|
145
149
|
|
|
146
150
|
terrainTheme.rules.push(TerrainLayerRule.from(
|
|
147
151
|
filterSand,
|
|
148
|
-
|
|
152
|
+
TerrainLayerDescription.from({
|
|
153
|
+
diffuse:'data/textures/Materials_Stylized/4k JPEG/Stylized_06_Sand/Stylized_06_Sand_basecolor.jpg',
|
|
154
|
+
size:new Vector2(7,7)
|
|
155
|
+
})
|
|
149
156
|
));
|
|
150
157
|
|
|
151
158
|
terrainTheme.rules.push(TerrainLayerRule.from(
|
|
152
159
|
filterRoad,
|
|
153
|
-
|
|
160
|
+
TerrainLayerDescription.from({
|
|
161
|
+
diffuse:'data/textures/Materials_Stylized/4k JPEG/Stylized_02_Stone_Ground/Stylized_02_Stone_Ground_basecolor.jpg',
|
|
162
|
+
size:new Vector2(7,7)
|
|
163
|
+
})
|
|
154
164
|
));
|
|
155
165
|
|
|
156
166
|
terrainTheme.rules.push(TerrainLayerRule.from(
|
|
@@ -158,7 +168,10 @@ terrainTheme.rules.push(TerrainLayerRule.from(
|
|
|
158
168
|
ROAD_FILTER,
|
|
159
169
|
CellFilterLerp.from(CellFilterLiteralFloat.from(1), CellFilterLiteralFloat.from(0.3), NOISE_10_a)
|
|
160
170
|
),
|
|
161
|
-
|
|
171
|
+
TerrainLayerDescription.from({
|
|
172
|
+
diffuse:'data/textures/materials/Sci-Fi Planet/Grass_02.png',
|
|
173
|
+
size:new Vector2(7,7)
|
|
174
|
+
}),
|
|
162
175
|
));
|
|
163
176
|
|
|
164
177
|
SampleTheme0.terrain = terrainTheme;
|
|
@@ -44,7 +44,7 @@ export class GridCellPlacementRule {
|
|
|
44
44
|
* @param {Vector2} [offset]
|
|
45
45
|
* @returns {GridCellPlacementRule}
|
|
46
46
|
*/
|
|
47
|
-
static from({ matcher, actions, probability, offset = Vector2.zero }) {
|
|
47
|
+
static from({ matcher, actions, probability = CellFilterLiteralFloat.from(1), offset = Vector2.zero }) {
|
|
48
48
|
|
|
49
49
|
assert.defined(matcher);
|
|
50
50
|
assert.defined(actions);
|
|
@@ -56,10 +56,8 @@ export class GridCellPlacementRule {
|
|
|
56
56
|
r.pattern = matcher;
|
|
57
57
|
r.actions = actions;
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
r.probability = probability;
|
|
62
|
-
}
|
|
59
|
+
assert.equal(probability.isCellFilter, true, 'probability.isCellFilter !== true');
|
|
60
|
+
r.probability = probability;
|
|
63
61
|
|
|
64
62
|
r.positionOffset.copy(offset);
|
|
65
63
|
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"productName": "Meep",
|
|
6
6
|
"description": "production-ready JavaScript game engine based on Entity Component System Architecture",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.33.
|
|
8
|
+
"version": "2.33.71",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|