@woosh/meep-engine 2.41.0 → 2.42.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/core/geom/3d/apply_mat4_transform_to_v3_array.js +2 -4
- package/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.js +28 -0
- package/core/geom/Quaternion.js +14 -0
- package/engine/EngineHarness.js +9 -3
- package/engine/ecs/transform/Transform.js +23 -3
- package/engine/graphics/ecs/decal/v2/Decal.d.ts +11 -0
- package/engine/graphics/ecs/decal/v2/Decal.js +50 -0
- package/engine/graphics/ecs/decal/v2/FPDecalSystem.d.ts +8 -0
- package/engine/graphics/ecs/decal/v2/FPDecalSystem.js +213 -0
- package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +237 -0
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +8 -1
- package/engine/graphics/ecs/mesh-v2/build_three_object.js +4 -0
- package/engine/graphics/geometry/MikkT/MikkTSpace.js +466 -305
- package/engine/graphics/geometry/buffered/computeGeometryEquality.js +1 -1
- package/engine/graphics/geometry/buffered/computeGeometryHash.js +1 -1
- package/engine/graphics/impostors/octahedral/ImpostorBaker.js +27 -14
- package/engine/graphics/impostors/octahedral/ImpostorDescription.js +6 -0
- package/engine/graphics/impostors/octahedral/README.md +1 -0
- package/engine/graphics/impostors/octahedral/bake/compute_bounding_sphere.js +25 -22
- package/engine/graphics/impostors/octahedral/bake/compute_bounding_sphere_radius_only.js +37 -0
- package/engine/graphics/impostors/octahedral/bake/prepare_bake_material.js +30 -1
- package/engine/graphics/impostors/octahedral/grid/HemiOctahedralUvEncoder.js +1 -1
- package/engine/graphics/impostors/octahedral/prototypeBaker.js +121 -22
- package/engine/graphics/impostors/octahedral/shader/BakeShaderStandard.js +46 -7
- package/engine/graphics/impostors/octahedral/shader/ImpostorShaderV0.js +349 -0
- package/engine/graphics/impostors/octahedral/shader/ImpostorShaderV1.js +74 -0
- package/engine/graphics/impostors/octahedral/shader/glsl/v1/common.glsl +209 -0
- package/engine/graphics/impostors/octahedral/shader/glsl/v1/flagment.glsl +80 -0
- package/engine/graphics/impostors/octahedral/shader/glsl/v1/vertex.glsl +350 -0
- package/engine/graphics/micron/render/v1/getTransformedPositionsCached.js +1 -1
- package/engine/graphics/render/forward_plus/LightManager.js +1 -1
- package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +1 -3
- package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_PREAMBLE.js +2 -1
- package/engine/graphics/render/forward_plus/model/Decal.js +19 -2
- package/engine/graphics/texture/sampler/Sampler2D.js +10 -10
- package/engine/graphics/texture/sampler/prototypeSamplerFiltering.js +117 -11
- package/engine/graphics/texture/sampler/resize/sampler2d_downsample_mipmap.js +66 -0
- package/engine/graphics/texture/sampler/sampler2_d_scale_down_lanczos.js +2 -2
- package/package.json +1 -1
|
@@ -6,11 +6,9 @@
|
|
|
6
6
|
* @param {number[]|Float32Array|Float64Array} destination
|
|
7
7
|
* @param {number} destination_offset
|
|
8
8
|
* @param {number} count
|
|
9
|
-
* @param {
|
|
9
|
+
* @param {mat4|number[]|Float32Array} mat4
|
|
10
10
|
*/
|
|
11
|
-
export function apply_mat4_transform_to_v3_array(source, source_offset, destination, destination_offset, count,
|
|
12
|
-
|
|
13
|
-
const mat4 = matrix.elements;
|
|
11
|
+
export function apply_mat4_transform_to_v3_array(source, source_offset, destination, destination_offset, count, mat4) {
|
|
14
12
|
|
|
15
13
|
const a0 = mat4[0];
|
|
16
14
|
const a1 = mat4[1];
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {number[]|ArrayLike<number>} input
|
|
4
|
+
* @param {number} input_length
|
|
5
|
+
* @param {ArrayLike<number>|number[]|Float32Array} e 4x4 transformation matrix
|
|
6
|
+
* @returns {number}
|
|
7
|
+
*/
|
|
8
|
+
export function sphere_radius_sqr_from_v3_array_transformed(input, input_length, e) {
|
|
9
|
+
let result = 0;
|
|
10
|
+
|
|
11
|
+
for (let i = 0; i < input_length; i += 3) {
|
|
12
|
+
const x = input[i];
|
|
13
|
+
const y = input[i + 1];
|
|
14
|
+
const z = input[i + 2];
|
|
15
|
+
|
|
16
|
+
const _x = e[0] * x + e[4] * y + e[8] * z + e[12];
|
|
17
|
+
const _y = e[1] * x + e[5] * y + e[9] * z + e[13];
|
|
18
|
+
const _z = e[2] * x + e[6] * y + e[10] * z + e[14];
|
|
19
|
+
|
|
20
|
+
const l2 = _x * _x + _y * _y + _z * _z;
|
|
21
|
+
|
|
22
|
+
if (l2 > result) {
|
|
23
|
+
result = l2;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return result;
|
|
28
|
+
}
|
package/core/geom/Quaternion.js
CHANGED
|
@@ -1705,6 +1705,20 @@ class Quaternion {
|
|
|
1705
1705
|
return result;
|
|
1706
1706
|
}
|
|
1707
1707
|
|
|
1708
|
+
/**
|
|
1709
|
+
*
|
|
1710
|
+
* @param {number} x
|
|
1711
|
+
* @param {number} y
|
|
1712
|
+
* @param {number} z
|
|
1713
|
+
* @returns {Quaternion}
|
|
1714
|
+
*/
|
|
1715
|
+
static fromEulerAngles(x, y, z) {
|
|
1716
|
+
const r = new Quaternion();
|
|
1717
|
+
|
|
1718
|
+
r.fromEulerAnglesXYZ(x, y, z);
|
|
1719
|
+
|
|
1720
|
+
return r;
|
|
1721
|
+
}
|
|
1708
1722
|
|
|
1709
1723
|
/**
|
|
1710
1724
|
* Behaves similarly to Unity's Quaternion `RotateToward` method
|
package/engine/EngineHarness.js
CHANGED
|
@@ -153,6 +153,7 @@ export class EngineHarness {
|
|
|
153
153
|
* @param {boolean} [autoClip]
|
|
154
154
|
* @param {number} [distanceMin]
|
|
155
155
|
* @param {number} [distanceMax]
|
|
156
|
+
* @param {number} [fieldOfView] in degrees
|
|
156
157
|
* @returns {EntityBuilder}
|
|
157
158
|
*/
|
|
158
159
|
static buildCamera(
|
|
@@ -163,9 +164,10 @@ export class EngineHarness {
|
|
|
163
164
|
distance = 10,
|
|
164
165
|
pitch = 1.4,
|
|
165
166
|
yaw = 0,
|
|
166
|
-
autoClip =
|
|
167
|
+
autoClip = false,
|
|
167
168
|
distanceMin = 0,
|
|
168
|
-
distanceMax = 1000
|
|
169
|
+
distanceMax = 1000,
|
|
170
|
+
fieldOfView = 45
|
|
169
171
|
}
|
|
170
172
|
) {
|
|
171
173
|
const em = engine.entityManager;
|
|
@@ -199,6 +201,7 @@ export class EngineHarness {
|
|
|
199
201
|
|
|
200
202
|
camera.active.set(true);
|
|
201
203
|
camera.autoClip = autoClip;
|
|
204
|
+
camera.fov.set(fieldOfView);
|
|
202
205
|
|
|
203
206
|
const entityBuilder = new EntityBuilder();
|
|
204
207
|
|
|
@@ -229,6 +232,7 @@ export class EngineHarness {
|
|
|
229
232
|
* @param {boolean} [enableWater]
|
|
230
233
|
* @param {boolean} [enableTerrain]
|
|
231
234
|
* @param {boolean} [enableLights=true]
|
|
235
|
+
* @param {number} [cameraFieldOfView]
|
|
232
236
|
* @param {boolean} [cameraController=true]
|
|
233
237
|
*/
|
|
234
238
|
static async buildBasics({
|
|
@@ -244,6 +248,7 @@ export class EngineHarness {
|
|
|
244
248
|
enableWater = true,
|
|
245
249
|
enableTerrain = true,
|
|
246
250
|
enableLights = true,
|
|
251
|
+
cameraFieldOfView,
|
|
247
252
|
cameraController = true
|
|
248
253
|
}) {
|
|
249
254
|
|
|
@@ -256,7 +261,8 @@ export class EngineHarness {
|
|
|
256
261
|
target: focus,
|
|
257
262
|
pitch,
|
|
258
263
|
yaw,
|
|
259
|
-
distance
|
|
264
|
+
distance,
|
|
265
|
+
fieldOfView: cameraFieldOfView
|
|
260
266
|
});
|
|
261
267
|
|
|
262
268
|
const cameraEntity = camera.entity;
|
|
@@ -63,9 +63,29 @@ export class Transform {
|
|
|
63
63
|
this.flags = FLAGS_DEFAULT;
|
|
64
64
|
|
|
65
65
|
// watch changes
|
|
66
|
-
this.
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
this.subscribeAllChanges(this.__handle_component_change, this);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
*
|
|
71
|
+
* @param {function} handler
|
|
72
|
+
* @param {*} [thisArg]
|
|
73
|
+
*/
|
|
74
|
+
subscribeAllChanges(handler, thisArg) {
|
|
75
|
+
this.position.onChanged.add(handler, thisArg);
|
|
76
|
+
this.rotation.onChanged.add(handler, thisArg);
|
|
77
|
+
this.scale.onChanged.add(handler, thisArg);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
*
|
|
82
|
+
* @param {function} handler
|
|
83
|
+
* @param {*} [thisArg]
|
|
84
|
+
*/
|
|
85
|
+
unsubscribeAllChanges(handler, thisArg) {
|
|
86
|
+
this.position.onChanged.remove(handler, thisArg);
|
|
87
|
+
this.rotation.onChanged.remove(handler, thisArg);
|
|
88
|
+
this.scale.onChanged.scale(handler, thisArg);
|
|
69
89
|
}
|
|
70
90
|
|
|
71
91
|
/**
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export class Decal {
|
|
2
|
+
constructor() {
|
|
3
|
+
/**
|
|
4
|
+
* Asset URL
|
|
5
|
+
* @type {string}
|
|
6
|
+
*/
|
|
7
|
+
this.uri = "";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Controls draw order
|
|
11
|
+
* @type {number}
|
|
12
|
+
*/
|
|
13
|
+
this.priority = 0;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Internal transient reference to loaded asset
|
|
17
|
+
* @type {Sampler2D|null}
|
|
18
|
+
* @private
|
|
19
|
+
*/
|
|
20
|
+
this.__cached_sampler = null;
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
* @type {String|null}
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
this.__cached_uri = null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
toJSON() {
|
|
30
|
+
return {
|
|
31
|
+
uri: this.uri,
|
|
32
|
+
priority: this.priority
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
fromJSON({
|
|
37
|
+
uri, priority = 0
|
|
38
|
+
}) {
|
|
39
|
+
this.uri = uri;
|
|
40
|
+
this.priority = priority;
|
|
41
|
+
|
|
42
|
+
if (uri !== this.__cached_uri) {
|
|
43
|
+
// reset sampler
|
|
44
|
+
this.__cached_sampler = null;
|
|
45
|
+
this.__cached_uri = null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
Decal.typeName = 'Decal';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import {System} from "../../../../ecs/System";
|
|
2
|
+
import {Decal} from "./Decal";
|
|
3
|
+
import {Transform} from "../../../../ecs/transform/Transform";
|
|
4
|
+
import Engine from "../../../../Engine";
|
|
5
|
+
|
|
6
|
+
export class FPDecalSystem extends System<Decal, Transform> {
|
|
7
|
+
constructor(engine: Engine)
|
|
8
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { AbstractContextSystem } from "../../../../ecs/system/AbstractContextSystem.js";
|
|
2
|
+
import { SystemEntityContext } from "../../../../ecs/system/SystemEntityContext.js";
|
|
3
|
+
import { Decal } from "./Decal.js";
|
|
4
|
+
import { Transform } from "../../../../ecs/transform/Transform.js";
|
|
5
|
+
import { ForwardPlusRenderingPlugin } from "../../../render/forward_plus/plugin/ForwardPlusRenderingPlugin.js";
|
|
6
|
+
import { Reference } from "../../../../reference/v2/Reference.js";
|
|
7
|
+
import { Decal as FPDecal } from '../../../render/forward_plus/model/Decal.js';
|
|
8
|
+
import { AssetManager } from "../../../../asset/AssetManager.js";
|
|
9
|
+
import { Sampler2D } from "../../../texture/sampler/Sampler2D.js";
|
|
10
|
+
import { GameAssetType } from "../../../../asset/GameAssetType.js";
|
|
11
|
+
|
|
12
|
+
const placeholder_texture = Sampler2D.uint8(4, 1, 1);
|
|
13
|
+
placeholder_texture.data.fill(255);
|
|
14
|
+
|
|
15
|
+
class Context extends SystemEntityContext {
|
|
16
|
+
constructor() {
|
|
17
|
+
super();
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @type {FPDecal|null}
|
|
22
|
+
* @private
|
|
23
|
+
*/
|
|
24
|
+
this.__fp_decal = null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @return {ForwardPlusRenderingPlugin}
|
|
29
|
+
* @private
|
|
30
|
+
*/
|
|
31
|
+
getPlugin() {
|
|
32
|
+
return this.system.__fp_plugin.getValue();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
*
|
|
37
|
+
* @returns {Transform}
|
|
38
|
+
*/
|
|
39
|
+
getTransform() {
|
|
40
|
+
return this.components[1];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
__update_transform() {
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* @type {Transform}
|
|
47
|
+
*/
|
|
48
|
+
const transform = this.getTransform();
|
|
49
|
+
|
|
50
|
+
this.__fp_decal.setTransform(transform.matrix);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async __load_texture() {
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
*
|
|
57
|
+
* @type {Decal}
|
|
58
|
+
*/
|
|
59
|
+
const decal_spec = this.components[0];
|
|
60
|
+
|
|
61
|
+
const _uri = decal_spec.uri;
|
|
62
|
+
|
|
63
|
+
if (decal_spec.__cached_sampler !== null && decal_spec.__cached_uri === _uri) {
|
|
64
|
+
// cached asset is still relevant
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
const loaded_texture = await this.system.internal_loadTexture(_uri);
|
|
70
|
+
|
|
71
|
+
decal_spec.__cached_sampler = loaded_texture;
|
|
72
|
+
decal_spec.__cached_uri = _uri;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
link() {
|
|
76
|
+
const plugin = this.getPlugin();
|
|
77
|
+
|
|
78
|
+
const lm = plugin.getLightManager();
|
|
79
|
+
|
|
80
|
+
const fpDecal = new FPDecal();
|
|
81
|
+
|
|
82
|
+
this.__fp_decal = fpDecal;
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
this.__update_transform();
|
|
86
|
+
|
|
87
|
+
const transform = this.getTransform();
|
|
88
|
+
transform.subscribeAllChanges(this.__update_transform, this);
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
*
|
|
92
|
+
* @type {Decal}
|
|
93
|
+
*/
|
|
94
|
+
const decal_spec = this.components[0];
|
|
95
|
+
|
|
96
|
+
this.__load_texture().then(() => {
|
|
97
|
+
|
|
98
|
+
if (!this.__is_linked) {
|
|
99
|
+
// not linked anymore
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const sampler = decal_spec.__cached_sampler;
|
|
104
|
+
|
|
105
|
+
if (sampler === null) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
fpDecal.texture_diffuse = sampler;
|
|
110
|
+
|
|
111
|
+
if (this.__fp_decal === fpDecal) {
|
|
112
|
+
lm.addLight(fpDecal);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
super.link();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
unlink() {
|
|
121
|
+
|
|
122
|
+
this.getPlugin()
|
|
123
|
+
.getLightManager()
|
|
124
|
+
.removeLight(this.__fp_decal);
|
|
125
|
+
|
|
126
|
+
this.__fp_decal = null;
|
|
127
|
+
|
|
128
|
+
const transform = this.getTransform();
|
|
129
|
+
transform.subscribeAllChanges(this.__update_transform, this);
|
|
130
|
+
|
|
131
|
+
super.unlink();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export class FPDecalSystem extends AbstractContextSystem {
|
|
136
|
+
/**
|
|
137
|
+
*
|
|
138
|
+
* @param {Engine} engine
|
|
139
|
+
*/
|
|
140
|
+
constructor(engine) {
|
|
141
|
+
super(Context);
|
|
142
|
+
|
|
143
|
+
this.dependencies = [Decal, Transform];
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
*
|
|
147
|
+
* @type {Map<string, Sampler2D>}
|
|
148
|
+
* @private
|
|
149
|
+
*/
|
|
150
|
+
this.__texture_cache = new Map();
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
*
|
|
154
|
+
* @type {AssetManager}
|
|
155
|
+
* @private
|
|
156
|
+
*/
|
|
157
|
+
this.__assets = engine.assetManager;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
*
|
|
161
|
+
* @type {Engine}
|
|
162
|
+
* @private
|
|
163
|
+
*/
|
|
164
|
+
this.__engine = engine;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
*
|
|
168
|
+
* @type {Reference<ForwardPlusRenderingPlugin>|null}
|
|
169
|
+
* @private
|
|
170
|
+
*/
|
|
171
|
+
this.__fp_plugin = Reference.NULL;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
*
|
|
176
|
+
* @param {string} uri
|
|
177
|
+
* @returns {Promise<void>}
|
|
178
|
+
*/
|
|
179
|
+
async internal_loadTexture(uri) {
|
|
180
|
+
const cached = this.__texture_cache.get(uri);
|
|
181
|
+
|
|
182
|
+
if (cached !== undefined) {
|
|
183
|
+
return cached;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const asset = await this.__assets.promise(uri, GameAssetType.Image);
|
|
187
|
+
|
|
188
|
+
// check cache again, in case another request has succeeded
|
|
189
|
+
const cached_v2 = this.__texture_cache.get(uri);
|
|
190
|
+
|
|
191
|
+
if (cached_v2 !== undefined) {
|
|
192
|
+
return cached_v2;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const sampler = asset.create();
|
|
196
|
+
|
|
197
|
+
this.__texture_cache.set(uri, sampler);
|
|
198
|
+
|
|
199
|
+
return sampler;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async startup(em, ready_callback, error_callback) {
|
|
203
|
+
this.__fp_plugin = await this.__engine.plugins.acquire(ForwardPlusRenderingPlugin);
|
|
204
|
+
|
|
205
|
+
super.startup(em, ready_callback, error_callback);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
shutdown(em, ready_callback, error_callback) {
|
|
209
|
+
this.__fp_plugin.release();
|
|
210
|
+
|
|
211
|
+
super.shutdown(em, ready_callback, error_callback);
|
|
212
|
+
}
|
|
213
|
+
}
|