@woosh/meep-engine 2.43.16 → 2.43.18
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/assert.js +3 -1
- package/core/bvh2/aabb3/aabb3_intersects_ray.js +14 -9
- package/core/bvh2/aabb3/aabb3_intersects_ray_branchless.js +52 -0
- package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.d.ts +2 -0
- package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +214 -5
- package/core/bvh2/bvh3/bvh_query_leaves_ray.js +32 -29
- package/core/collection/array/typed/typed_array_copy.js +2 -2
- package/core/geom/3d/aabb/compute_aabb_from_points.js +4 -3
- package/core/geom/3d/compute_triangle_normal.js +76 -0
- package/core/geom/3d/topology/samples/sampleFloodFill.js +1 -1
- package/core/geom/3d/topology/simplify/compute_face_normal_change_dot_product.js +1 -1
- package/core/geom/3d/topology/simplify/quadratic/Quadratic3.js +1 -1
- package/core/geom/3d/topology/struct/TopoTriangle.js +1 -57
- package/core/geom/3d/topology/tm_face_normal.js +1 -1
- package/core/geom/3d/topology/tm_vertex_compute_normal.js +1 -1
- package/core/geom/3d/triangle/computeTriangleRayIntersection.js +195 -27
- package/core/geom/Vector3.js +12 -12
- package/core/math/physics/brdf/D_GGX.js +13 -0
- package/editor/tools/v2/prototypeTransformControls.js +14 -2
- package/engine/ecs/parent/EntityNode.js +80 -7
- package/engine/ecs/parent/EntityNodeFlags.js +8 -0
- package/engine/ecs/terrain/tiles/TerrainTile.js +7 -9
- package/engine/graphics/ecs/path/PathDisplaySystem.d.ts +3 -0
- package/engine/graphics/ecs/path/PathDisplaySystem.js +10 -0
- package/engine/graphics/geometry/AttributeSpec.js +18 -3
- package/engine/graphics/geometry/VertexDataSpec.js +53 -3
- package/engine/graphics/micron/format/VirtualGeometry.js +7 -0
- package/engine/graphics/micron/render/VirtualGeometryBuilder.js +1 -1
- package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +5 -2
- package/engine/graphics/particles/particular/engine/parameter/sample/RGBA_LUT_HEATMAP_IR.js +11 -0
- package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +2 -9
- package/engine/graphics/sh3/README.md +1 -0
- package/engine/graphics/sh3/path_tracer/GeometryBVHBatched.js +324 -0
- package/engine/graphics/sh3/path_tracer/PathTracedMesh.js +85 -0
- package/engine/graphics/sh3/path_tracer/PathTracer.js +469 -0
- package/engine/graphics/sh3/path_tracer/apply_texture_clamping_to_coordinate.js +22 -0
- package/engine/graphics/sh3/path_tracer/compute_triangle_group_aabb3.js +36 -0
- package/engine/graphics/sh3/path_tracer/getBiasedNormalSample.js +55 -0
- package/engine/graphics/sh3/path_tracer/make_sky_hosek.js +44 -0
- package/engine/graphics/sh3/path_tracer/make_sky_rtiw.js +15 -0
- package/engine/graphics/sh3/path_tracer/prototypePathTracer.js +619 -0
- package/engine/graphics/sh3/path_tracer/random_in_hemisphere.js +39 -0
- package/engine/graphics/sh3/path_tracer/ray_hit_apply_transform.js +42 -0
- package/engine/graphics/sh3/path_tracer/ray_reflect.js +27 -0
- package/engine/graphics/sh3/path_tracer/sample_triangle_attribute.js +35 -0
- package/engine/graphics/sh3/path_tracer/vec3_uint8_to_float.js +12 -0
- package/engine/graphics/sh3/sky/hosek/README.md +4 -0
- package/engine/graphics/sh3/sky/hosek/prototype_hosek.js +71 -0
- package/engine/graphics/sh3/sky/hosek/sky_hosek_compute_irradiance_by_direction.js +4171 -0
- package/engine/graphics/texture/sampler/convertTexture2Sampler2D.js +2 -0
- package/package.json +1 -1
- package/view/elements/progress/SmoothProgressBar.js +1 -1
- package/view/task/TaskProgressView.js +6 -8
|
@@ -3,63 +3,7 @@ import { array_push_if_unique } from "../../../../collection/array/array_push_if
|
|
|
3
3
|
import { assert } from "../../../../assert.js";
|
|
4
4
|
import { array_remove_first } from "../../../../collection/array/array_remove_first.js";
|
|
5
5
|
import { vec3 } from "gl-matrix";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
* @param {number[]|vec3} result
|
|
11
|
-
* @param {Vector3|Vector3Like|TopoVertex|{x:number,y:number,z:number}} vA
|
|
12
|
-
* @param {Vector3|Vector3Like|TopoVertex|{x:number,y:number,z:number}} vB
|
|
13
|
-
* @param {Vector3|Vector3Like|TopoVertex|{x:number,y:number,z:number}} vC
|
|
14
|
-
*/
|
|
15
|
-
export function compute_triangle_normal(result, vA, vB, vC) {
|
|
16
|
-
|
|
17
|
-
const vAx = vA.x
|
|
18
|
-
const vAy = vA.y
|
|
19
|
-
const vAz = vA.z
|
|
20
|
-
|
|
21
|
-
const vBx = vB.x
|
|
22
|
-
const vBy = vB.y
|
|
23
|
-
const vBz = vB.z
|
|
24
|
-
|
|
25
|
-
const vCx = vC.x
|
|
26
|
-
const vCy = vC.y
|
|
27
|
-
const vCz = vC.z
|
|
28
|
-
|
|
29
|
-
//compute CB and AB vectors
|
|
30
|
-
const vCBx = vCx - vBx;
|
|
31
|
-
const vCBy = vCy - vBy;
|
|
32
|
-
const vCBz = vCz - vBz;
|
|
33
|
-
|
|
34
|
-
const vABx = vAx - vBx;
|
|
35
|
-
const vABy = vAy - vBy;
|
|
36
|
-
const vABz = vAz - vBz;
|
|
37
|
-
|
|
38
|
-
//compute triangle normal
|
|
39
|
-
const crossX = vCBy * vABz - vCBz * vABy;
|
|
40
|
-
const crossY = vCBz * vABx - vCBx * vABz;
|
|
41
|
-
const crossZ = vCBx * vABy - vCBy * vABx;
|
|
42
|
-
|
|
43
|
-
const l_sqr = v3_length_sqr(crossX, crossY, crossZ);
|
|
44
|
-
|
|
45
|
-
if (l_sqr === 0) {
|
|
46
|
-
// degenerate triangle, provide arbitrary invalid result
|
|
47
|
-
vec3.set(result, 0, 0, 0);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const l_inv = 1 / Math.sqrt(l_sqr);
|
|
52
|
-
|
|
53
|
-
const x = crossX * l_inv;
|
|
54
|
-
const y = crossY * l_inv;
|
|
55
|
-
const z = crossZ * l_inv;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
vec3.set(
|
|
59
|
-
result,
|
|
60
|
-
x, y, z
|
|
61
|
-
);
|
|
62
|
-
}
|
|
6
|
+
import { compute_triangle_normal } from "../../compute_triangle_normal.js";
|
|
63
7
|
|
|
64
8
|
let index_counter = 0;
|
|
65
9
|
|
|
@@ -30,43 +30,43 @@ export function computeTriangleRayIntersection(
|
|
|
30
30
|
bx, by, bz,
|
|
31
31
|
cx, cy, cz
|
|
32
32
|
) {
|
|
33
|
-
assert.isNumber(ax,'ax');
|
|
34
|
-
assert.isNumber(ay,'ay');
|
|
35
|
-
assert.isNumber(az,'az');
|
|
33
|
+
assert.isNumber(ax, 'ax');
|
|
34
|
+
assert.isNumber(ay, 'ay');
|
|
35
|
+
assert.isNumber(az, 'az');
|
|
36
36
|
|
|
37
|
-
assert.isNumber(bx,'bx');
|
|
38
|
-
assert.isNumber(by,'by');
|
|
39
|
-
assert.isNumber(bz,'bz');
|
|
37
|
+
assert.isNumber(bx, 'bx');
|
|
38
|
+
assert.isNumber(by, 'by');
|
|
39
|
+
assert.isNumber(bz, 'bz');
|
|
40
40
|
|
|
41
|
-
assert.isNumber(cx,'cx');
|
|
42
|
-
assert.isNumber(cy,'cy');
|
|
43
|
-
assert.isNumber(cz,'cz');
|
|
41
|
+
assert.isNumber(cx, 'cx');
|
|
42
|
+
assert.isNumber(cy, 'cy');
|
|
43
|
+
assert.isNumber(cz, 'cz');
|
|
44
44
|
|
|
45
45
|
// nan checks
|
|
46
|
-
assert.notNaN(ax,'ax');
|
|
47
|
-
assert.notNaN(ay,'ay');
|
|
48
|
-
assert.notNaN(az,'az');
|
|
46
|
+
assert.notNaN(ax, 'ax');
|
|
47
|
+
assert.notNaN(ay, 'ay');
|
|
48
|
+
assert.notNaN(az, 'az');
|
|
49
49
|
|
|
50
|
-
assert.notNaN(bx,'bx');
|
|
51
|
-
assert.notNaN(by,'by');
|
|
52
|
-
assert.notNaN(bz,'bz');
|
|
50
|
+
assert.notNaN(bx, 'bx');
|
|
51
|
+
assert.notNaN(by, 'by');
|
|
52
|
+
assert.notNaN(bz, 'bz');
|
|
53
53
|
|
|
54
|
-
assert.notNaN(cx,'cx');
|
|
55
|
-
assert.notNaN(cy,'cy');
|
|
56
|
-
assert.notNaN(cz,'cz');
|
|
54
|
+
assert.notNaN(cx, 'cx');
|
|
55
|
+
assert.notNaN(cy, 'cy');
|
|
56
|
+
assert.notNaN(cz, 'cz');
|
|
57
57
|
|
|
58
58
|
// finate number check
|
|
59
|
-
assert.isFiniteNumber(ax,'ax');
|
|
60
|
-
assert.isFiniteNumber(ay,'ay');
|
|
61
|
-
assert.isFiniteNumber(az,'az');
|
|
59
|
+
assert.isFiniteNumber(ax, 'ax');
|
|
60
|
+
assert.isFiniteNumber(ay, 'ay');
|
|
61
|
+
assert.isFiniteNumber(az, 'az');
|
|
62
62
|
|
|
63
|
-
assert.isFiniteNumber(bx,'bx');
|
|
64
|
-
assert.isFiniteNumber(by,'by');
|
|
65
|
-
assert.isFiniteNumber(bz,'bz');
|
|
63
|
+
assert.isFiniteNumber(bx, 'bx');
|
|
64
|
+
assert.isFiniteNumber(by, 'by');
|
|
65
|
+
assert.isFiniteNumber(bz, 'bz');
|
|
66
66
|
|
|
67
|
-
assert.isFiniteNumber(cx,'cx');
|
|
68
|
-
assert.isFiniteNumber(cy,'cy');
|
|
69
|
-
assert.isFiniteNumber(cz,'cz');
|
|
67
|
+
assert.isFiniteNumber(cx, 'cx');
|
|
68
|
+
assert.isFiniteNumber(cy, 'cy');
|
|
69
|
+
assert.isFiniteNumber(cz, 'cz');
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
// edge1 = a - b
|
|
@@ -157,3 +157,171 @@ export function computeTriangleRayIntersection(
|
|
|
157
157
|
|
|
158
158
|
return true;
|
|
159
159
|
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Compute barycentric coordinates for triangle intersection
|
|
163
|
+
* Operates on edges, this is optimized for raytracing, as same edges are required to reconstruct various attributes later on
|
|
164
|
+
* NOTE: most of the code is inlined for speed to avoid allocation and function calls
|
|
165
|
+
* @see https://github.com/erich666/jgt-code/blob/master/Volume_02/Number_1/Moller1997a/raytri.c
|
|
166
|
+
* @source https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm (Möller and Trumbore, « Fast, Minimum Storage Ray-Triangle Intersection », Journal of Graphics Tools, vol. 2, 1997, p. 21–28)
|
|
167
|
+
* @param {number[]} result
|
|
168
|
+
* @param {number} origin_x
|
|
169
|
+
* @param {number} origin_y
|
|
170
|
+
* @param {number} origin_z
|
|
171
|
+
* @param {number} direction_x
|
|
172
|
+
* @param {number} direction_y
|
|
173
|
+
* @param {number} direction_z
|
|
174
|
+
* @param {number} ax
|
|
175
|
+
* @param {number} ay
|
|
176
|
+
* @param {number} az
|
|
177
|
+
* @param {number} edge1_x
|
|
178
|
+
* @param {number} edge1_y
|
|
179
|
+
* @param {number} edge1_z
|
|
180
|
+
* @param {number} edge2_x
|
|
181
|
+
* @param {number} edge2_y
|
|
182
|
+
* @param {number} edge2_z
|
|
183
|
+
* @return {boolean}
|
|
184
|
+
*/
|
|
185
|
+
export function computeTriangleRayIntersectionBarycentricEdge(result, origin_x, origin_y, origin_z, direction_x, direction_y, direction_z, ax, ay, az, edge1_x, edge1_y, edge1_z, edge2_x, edge2_y, edge2_z) {
|
|
186
|
+
// begin calculating determinant - also used to calculate U parameter
|
|
187
|
+
|
|
188
|
+
// CROSS(pvec, dir, edge2)
|
|
189
|
+
const pvec_x = direction_y * edge2_z - direction_z * edge2_y;
|
|
190
|
+
const pvec_y = direction_z * edge2_x - direction_x * edge2_z;
|
|
191
|
+
const pvec_z = direction_x * edge2_y - direction_y * edge2_x;
|
|
192
|
+
|
|
193
|
+
//if determinant is near zero, ray lies in plane of triangle
|
|
194
|
+
const det = v3_dot(edge1_x, edge1_y, edge1_z, pvec_x, pvec_y, pvec_z);
|
|
195
|
+
|
|
196
|
+
if (det <= 0) {
|
|
197
|
+
// back-face culling
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// calculate distance from vert0 to ray origin (not really, but okay)
|
|
202
|
+
const tvec_x = origin_x - ax;
|
|
203
|
+
const tvec_y = origin_y - ay;
|
|
204
|
+
const tvec_z = origin_z - az;
|
|
205
|
+
|
|
206
|
+
// calculate u
|
|
207
|
+
let u = v3_dot(tvec_x, tvec_y, tvec_z, pvec_x, pvec_y, pvec_z);
|
|
208
|
+
|
|
209
|
+
if (u < 0 || u > det) {
|
|
210
|
+
// outside of bounds of the triangle
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// prepare to test V parameter
|
|
215
|
+
// CROSS(qvec, tvec, edge1)
|
|
216
|
+
const qvec_x = tvec_y * edge1_z - tvec_z * edge1_y;
|
|
217
|
+
const qvec_y = tvec_z * edge1_x - tvec_x * edge1_z;
|
|
218
|
+
const qvec_z = tvec_x * edge1_y - tvec_y * edge1_x;
|
|
219
|
+
|
|
220
|
+
// calculate V parameter
|
|
221
|
+
let v = v3_dot(direction_x, direction_y, direction_z, qvec_x, qvec_y, qvec_z);
|
|
222
|
+
|
|
223
|
+
if (v < 0 || u + v > det) {
|
|
224
|
+
// out of bounds
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
const inv_det = 1 / det;
|
|
230
|
+
|
|
231
|
+
// calculate t, scale parameter, ray intersects triangle
|
|
232
|
+
const t = v3_dot(edge2_x, edge2_y, edge2_z, qvec_x, qvec_y, qvec_z) * inv_det;
|
|
233
|
+
|
|
234
|
+
u *= inv_det;
|
|
235
|
+
v *= inv_det;
|
|
236
|
+
|
|
237
|
+
result[0] = t;
|
|
238
|
+
result[1] = u;
|
|
239
|
+
result[2] = v;
|
|
240
|
+
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Compute barycentric coordinates for triangle intersection
|
|
246
|
+
* NOTE: most of the code is inlined for speed to avoid allocation and function calls
|
|
247
|
+
* @see https://github.com/erich666/jgt-code/blob/master/Volume_02/Number_1/Moller1997a/raytri.c
|
|
248
|
+
* @source https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm (Möller and Trumbore, « Fast, Minimum Storage Ray-Triangle Intersection », Journal of Graphics Tools, vol. 2, 1997, p. 21–28)
|
|
249
|
+
* @param {number[]} result [t,u,v, normal_x, normal_y, normal_z] will be written here
|
|
250
|
+
* @param {number} origin_x
|
|
251
|
+
* @param {number} origin_y
|
|
252
|
+
* @param {number} origin_z
|
|
253
|
+
* @param {number} direction_x
|
|
254
|
+
* @param {number} direction_y
|
|
255
|
+
* @param {number} direction_z
|
|
256
|
+
* @param {number} ax
|
|
257
|
+
* @param {number} ay
|
|
258
|
+
* @param {number} az
|
|
259
|
+
* @param {number} bx
|
|
260
|
+
* @param {number} by
|
|
261
|
+
* @param {number} bz
|
|
262
|
+
* @param {number} cx
|
|
263
|
+
* @param {number} cy
|
|
264
|
+
* @param {number} cz
|
|
265
|
+
* @returns {boolean}
|
|
266
|
+
*/
|
|
267
|
+
export function computeTriangleRayIntersectionBarycentric(
|
|
268
|
+
result,
|
|
269
|
+
origin_x, origin_y, origin_z,
|
|
270
|
+
direction_x, direction_y, direction_z,
|
|
271
|
+
ax, ay, az,
|
|
272
|
+
bx, by, bz,
|
|
273
|
+
cx, cy, cz
|
|
274
|
+
) {
|
|
275
|
+
assert.isNumber(ax, 'ax');
|
|
276
|
+
assert.isNumber(ay, 'ay');
|
|
277
|
+
assert.isNumber(az, 'az');
|
|
278
|
+
|
|
279
|
+
assert.isNumber(bx, 'bx');
|
|
280
|
+
assert.isNumber(by, 'by');
|
|
281
|
+
assert.isNumber(bz, 'bz');
|
|
282
|
+
|
|
283
|
+
assert.isNumber(cx, 'cx');
|
|
284
|
+
assert.isNumber(cy, 'cy');
|
|
285
|
+
assert.isNumber(cz, 'cz');
|
|
286
|
+
|
|
287
|
+
// nan checks
|
|
288
|
+
assert.notNaN(ax, 'ax');
|
|
289
|
+
assert.notNaN(ay, 'ay');
|
|
290
|
+
assert.notNaN(az, 'az');
|
|
291
|
+
|
|
292
|
+
assert.notNaN(bx, 'bx');
|
|
293
|
+
assert.notNaN(by, 'by');
|
|
294
|
+
assert.notNaN(bz, 'bz');
|
|
295
|
+
|
|
296
|
+
assert.notNaN(cx, 'cx');
|
|
297
|
+
assert.notNaN(cy, 'cy');
|
|
298
|
+
assert.notNaN(cz, 'cz');
|
|
299
|
+
|
|
300
|
+
// finate number check
|
|
301
|
+
assert.isFiniteNumber(ax, 'ax');
|
|
302
|
+
assert.isFiniteNumber(ay, 'ay');
|
|
303
|
+
assert.isFiniteNumber(az, 'az');
|
|
304
|
+
|
|
305
|
+
assert.isFiniteNumber(bx, 'bx');
|
|
306
|
+
assert.isFiniteNumber(by, 'by');
|
|
307
|
+
assert.isFiniteNumber(bz, 'bz');
|
|
308
|
+
|
|
309
|
+
assert.isFiniteNumber(cx, 'cx');
|
|
310
|
+
assert.isFiniteNumber(cy, 'cy');
|
|
311
|
+
assert.isFiniteNumber(cz, 'cz');
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
// find vectors for two edges sharing vert
|
|
315
|
+
|
|
316
|
+
// edge1 = a - b
|
|
317
|
+
const edge1_x = bx - ax;
|
|
318
|
+
const edge1_y = by - ay;
|
|
319
|
+
const edge1_z = bz - az;
|
|
320
|
+
|
|
321
|
+
// edge2 = c - a
|
|
322
|
+
const edge2_x = cx - ax;
|
|
323
|
+
const edge2_y = cy - ay;
|
|
324
|
+
const edge2_z = cz - az;
|
|
325
|
+
|
|
326
|
+
return computeTriangleRayIntersectionBarycentricEdge(result, origin_x, origin_y, origin_z, direction_x, direction_y, direction_z, ax, ay, az, edge1_x, edge1_y, edge1_z, edge2_x, edge2_y, edge2_z);
|
|
327
|
+
}
|
package/core/geom/Vector3.js
CHANGED
|
@@ -305,6 +305,18 @@ class Vector3 {
|
|
|
305
305
|
return this;
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
+
/**
|
|
309
|
+
*
|
|
310
|
+
* @param {Vector3} first
|
|
311
|
+
* @param {Vector3} second
|
|
312
|
+
*/
|
|
313
|
+
crossVectors(first, second) {
|
|
314
|
+
const ax = first.x, ay = first.y, az = first.z;
|
|
315
|
+
const bx = second.x, by = second.y, bz = second.z;
|
|
316
|
+
|
|
317
|
+
this._crossVectors(ax, ay, az, bx, by, bz);
|
|
318
|
+
}
|
|
319
|
+
|
|
308
320
|
/**
|
|
309
321
|
*
|
|
310
322
|
* @param {number} ax
|
|
@@ -322,18 +334,6 @@ class Vector3 {
|
|
|
322
334
|
this.set(x, y, z);
|
|
323
335
|
}
|
|
324
336
|
|
|
325
|
-
/**
|
|
326
|
-
*
|
|
327
|
-
* @param {Vector3} first
|
|
328
|
-
* @param {Vector3} second
|
|
329
|
-
*/
|
|
330
|
-
crossVectors(first, second) {
|
|
331
|
-
const ax = first.x, ay = first.y, az = first.z;
|
|
332
|
-
const bx = second.x, by = second.y, bz = second.z;
|
|
333
|
-
|
|
334
|
-
this._crossVectors(ax, ay, az, bx, by, bz);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
337
|
/**
|
|
338
338
|
* Sets all components of the vector to absolute value (positive)
|
|
339
339
|
* @returns {Vector3}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GGX diffuse distribution function
|
|
3
|
+
* @see https://google.github.io/filament/Filament.md.html#listing_diffusebrdf
|
|
4
|
+
* @param {number} NoH dot(n,h) where n is surface normal and h is half unit vector between incident light and outgoing light (view vector)
|
|
5
|
+
* @param {number} roughness
|
|
6
|
+
* @returns {number}
|
|
7
|
+
*/
|
|
8
|
+
export function D_GGX(NoH, roughness) {
|
|
9
|
+
const a = NoH * roughness;
|
|
10
|
+
const k = roughness / (1 - NoH * NoH + a * a);
|
|
11
|
+
|
|
12
|
+
return k * k * (1 / Math.PI);
|
|
13
|
+
}
|
|
@@ -9,6 +9,10 @@ import { Camera } from "../../../engine/graphics/ecs/camera/Camera.js";
|
|
|
9
9
|
import { TransformAttachmentSystem } from "../../../engine/ecs/transform-attachment/TransformAttachmentSystem.js";
|
|
10
10
|
import InputController from "../../../engine/input/ecs/components/InputController.js";
|
|
11
11
|
import InputControllerSystem from "../../../engine/input/ecs/systems/InputControllerSystem.js";
|
|
12
|
+
import { GLTFAssetLoader } from "../../../engine/asset/loaders/GLTFAssetLoader.js";
|
|
13
|
+
import {
|
|
14
|
+
three_object_to_entity_composition
|
|
15
|
+
} from "../../../engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js";
|
|
12
16
|
|
|
13
17
|
const harness = new EngineHarness();
|
|
14
18
|
|
|
@@ -17,11 +21,13 @@ const harness = new EngineHarness();
|
|
|
17
21
|
* @param {Engine} engine
|
|
18
22
|
*/
|
|
19
23
|
async function main(engine) {
|
|
20
|
-
EngineHarness.buildBasics({
|
|
24
|
+
await EngineHarness.buildBasics({
|
|
21
25
|
engine,
|
|
22
26
|
cameraController: false
|
|
23
27
|
});
|
|
24
28
|
|
|
29
|
+
const gltf_asset = await engine.assetManager.promise('data/models/sponza-pbr/gltf/sponza.glb', 'gltf');
|
|
30
|
+
|
|
25
31
|
|
|
26
32
|
const ecd = engine.entityManager.dataset;
|
|
27
33
|
|
|
@@ -46,9 +52,13 @@ async function main(engine) {
|
|
|
46
52
|
|
|
47
53
|
const controls = new TransformControls(camera.component.object, engine.gameView.el);
|
|
48
54
|
|
|
55
|
+
const entityNode = three_object_to_entity_composition(gltf_asset.create());
|
|
56
|
+
entityNode.build(ecd);
|
|
57
|
+
entityNode.transform.scale.multiplyScalar(0.1);
|
|
49
58
|
|
|
50
59
|
controls.build(ecd); // add controls to the scene
|
|
51
|
-
controls.attach(cube_entity); // make controls target the cube
|
|
60
|
+
// controls.attach(cube_entity); // make controls target the cube
|
|
61
|
+
controls.attach(entityNode.entity.entity); // make controls target the cube
|
|
52
62
|
|
|
53
63
|
new EntityBuilder()
|
|
54
64
|
.add(new InputController([{
|
|
@@ -76,5 +86,7 @@ harness.initialize({
|
|
|
76
86
|
config.addSystem(new ShadedGeometrySystem(engine));
|
|
77
87
|
config.addSystem(new TransformAttachmentSystem(engine));
|
|
78
88
|
config.addSystem(new InputControllerSystem(engine.devices));
|
|
89
|
+
|
|
90
|
+
config.addLoader('gltf', new GLTFAssetLoader());
|
|
79
91
|
}
|
|
80
92
|
}).then(main);
|
|
@@ -6,6 +6,9 @@ import { array_push_if_unique } from "../../../core/collection/array/array_push_
|
|
|
6
6
|
import { Transform } from "../transform/Transform.js";
|
|
7
7
|
import { TransformAttachment, TransformAttachmentFlags } from "../transform-attachment/TransformAttachment.js";
|
|
8
8
|
import Signal from "../../../core/events/signal/Signal.js";
|
|
9
|
+
import { EntityNodeFlags } from "./EntityNodeFlags.js";
|
|
10
|
+
|
|
11
|
+
const DEFAULT_FLAGS = EntityNodeFlags.LiveManagement;
|
|
9
12
|
|
|
10
13
|
export class EntityNode {
|
|
11
14
|
/**
|
|
@@ -45,6 +48,52 @@ export class EntityNode {
|
|
|
45
48
|
built: new Signal(),
|
|
46
49
|
destroyed: new Signal()
|
|
47
50
|
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
* @type {number}
|
|
55
|
+
*/
|
|
56
|
+
this.flags = DEFAULT_FLAGS;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
*
|
|
61
|
+
* @param {number|EntityNodeFlags} flag
|
|
62
|
+
* @returns {void}
|
|
63
|
+
*/
|
|
64
|
+
setFlag(flag) {
|
|
65
|
+
this.flags |= flag;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
*
|
|
70
|
+
* @param {number|EntityNodeFlags} flag
|
|
71
|
+
* @returns {void}
|
|
72
|
+
*/
|
|
73
|
+
clearFlag(flag) {
|
|
74
|
+
this.flags &= ~flag;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
*
|
|
79
|
+
* @param {number|EntityNodeFlags} flag
|
|
80
|
+
* @param {boolean} value
|
|
81
|
+
*/
|
|
82
|
+
writeFlag(flag, value) {
|
|
83
|
+
if (value) {
|
|
84
|
+
this.setFlag(flag);
|
|
85
|
+
} else {
|
|
86
|
+
this.clearFlag(flag);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
*
|
|
92
|
+
* @param {number|EntityNodeFlags} flag
|
|
93
|
+
* @returns {boolean}
|
|
94
|
+
*/
|
|
95
|
+
getFlag(flag) {
|
|
96
|
+
return (this.flags & flag) === flag;
|
|
48
97
|
}
|
|
49
98
|
|
|
50
99
|
/**
|
|
@@ -263,6 +312,28 @@ export class EntityNode {
|
|
|
263
312
|
return this.__entity.isBuilt;
|
|
264
313
|
}
|
|
265
314
|
|
|
315
|
+
attachListeners() {
|
|
316
|
+
if (this.getFlag(EntityNodeFlags.TransformObserved)) {
|
|
317
|
+
// already observed
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
this.__transform.position.onChanged.add(this.__transform_sync_down, this);
|
|
322
|
+
this.__transform.scale.onChanged.add(this.__transform_sync_down, this);
|
|
323
|
+
this.__transform.rotation.onChanged.add(this.__transform_sync_down, this);
|
|
324
|
+
|
|
325
|
+
this.setFlag(EntityNodeFlags.TransformObserved);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
detachListeners() {
|
|
329
|
+
|
|
330
|
+
this.__transform.position.onChanged.remove(this.__transform_sync_down, this);
|
|
331
|
+
this.__transform.scale.onChanged.remove(this.__transform_sync_down, this);
|
|
332
|
+
this.__transform.rotation.onChanged.remove(this.__transform_sync_down, this);
|
|
333
|
+
|
|
334
|
+
this.clearFlag(EntityNodeFlags.TransformObserved);
|
|
335
|
+
}
|
|
336
|
+
|
|
266
337
|
/**
|
|
267
338
|
*
|
|
268
339
|
* @param {EntityComponentDataset} ecd
|
|
@@ -303,9 +374,9 @@ export class EntityNode {
|
|
|
303
374
|
this.__transform_sync_down();
|
|
304
375
|
|
|
305
376
|
// attach listeners
|
|
306
|
-
this.
|
|
307
|
-
|
|
308
|
-
|
|
377
|
+
if (this.getFlag(EntityNodeFlags.LiveManagement)) {
|
|
378
|
+
this.attachListeners();
|
|
379
|
+
}
|
|
309
380
|
|
|
310
381
|
this.__entity.build(ecd);
|
|
311
382
|
|
|
@@ -321,6 +392,7 @@ export class EntityNode {
|
|
|
321
392
|
this.on.built.send0();
|
|
322
393
|
}
|
|
323
394
|
|
|
395
|
+
|
|
324
396
|
destroy() {
|
|
325
397
|
if (!this.__entity.isBuilt) {
|
|
326
398
|
// not built
|
|
@@ -329,10 +401,11 @@ export class EntityNode {
|
|
|
329
401
|
return;
|
|
330
402
|
}
|
|
331
403
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
404
|
+
if (this.getFlag(EntityNodeFlags.TransformObserved)) {
|
|
405
|
+
|
|
406
|
+
// remove listeners
|
|
407
|
+
this.detachListeners();
|
|
408
|
+
}
|
|
336
409
|
|
|
337
410
|
// destroy children first
|
|
338
411
|
const children = this.__children;
|
|
@@ -27,16 +27,12 @@ import { mat4 } from "gl-matrix";
|
|
|
27
27
|
import { AABB3 } from "../../../../core/bvh2/aabb3/AABB3.js";
|
|
28
28
|
import { NumericInterval } from "../../../../core/math/interval/NumericInterval.js";
|
|
29
29
|
import { array_copy } from "../../../../core/collection/array/copyArray.js";
|
|
30
|
+
import { passThrough } from "../../../../core/function/Functions.js";
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
/**
|
|
33
|
+
* terrain tile is a part of a 2d array
|
|
34
|
+
*/
|
|
36
35
|
class TerrainTile {
|
|
37
|
-
/**
|
|
38
|
-
* terrain tile is a part of a 2d array
|
|
39
|
-
*/
|
|
40
36
|
constructor() {
|
|
41
37
|
this.gridPosition = new Vector2();
|
|
42
38
|
this.scale = new Vector2(1, 1);
|
|
@@ -103,6 +99,7 @@ class TerrainTile {
|
|
|
103
99
|
this.onDestroyed = new Signal();
|
|
104
100
|
|
|
105
101
|
/**
|
|
102
|
+
* Encodes whether stitching has been performed on per-neighbour basis
|
|
106
103
|
* @private
|
|
107
104
|
* @type {{bottomLeft: boolean, top: boolean, left: boolean, bottom: boolean, bottomRight: boolean, topLeft: boolean, topRight: boolean, right: boolean}}
|
|
108
105
|
*/
|
|
@@ -129,7 +126,7 @@ class TerrainTile {
|
|
|
129
126
|
|
|
130
127
|
this.raycaster = new BVHGeometryRaycaster();
|
|
131
128
|
//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.
|
|
132
|
-
this.raycaster.extractFaceIndexFromLeaf =
|
|
129
|
+
this.raycaster.extractFaceIndexFromLeaf = passThrough;
|
|
133
130
|
}
|
|
134
131
|
|
|
135
132
|
/**
|
|
@@ -148,6 +145,7 @@ class TerrainTile {
|
|
|
148
145
|
array_copy(m4, 0, this.mesh.matrixWorld.elements, 0, 16);
|
|
149
146
|
this.computeBoundingBox();
|
|
150
147
|
|
|
148
|
+
// raycaster needs to store transform as well
|
|
151
149
|
array_copy(m4, 0, this.raycaster.transform, 0, 16);
|
|
152
150
|
}
|
|
153
151
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import Engine from "../../../Engine";
|
|
2
2
|
import {System} from "../../../ecs/System";
|
|
3
3
|
import {PathDisplay} from "./PathDisplay";
|
|
4
|
+
import Signal from "../../../../core/events/signal/Signal";
|
|
4
5
|
|
|
5
6
|
export class PathDisplaySystem extends System<PathDisplay> {
|
|
6
7
|
constructor(engine: Engine)
|
|
8
|
+
|
|
9
|
+
readonly onWorkDone: Signal<void>
|
|
7
10
|
}
|
|
@@ -12,6 +12,7 @@ import { PathEvents } from "../../../navigation/ecs/components/PathEvents.js";
|
|
|
12
12
|
import { assert } from "../../../../core/assert.js";
|
|
13
13
|
import { TubePathBuilder } from "./tube/build/TubePathBuilder.js";
|
|
14
14
|
import { Deque } from "../../../../core/collection/queue/Deque.js";
|
|
15
|
+
import Signal from "../../../../core/events/signal/Signal.js";
|
|
15
16
|
|
|
16
17
|
const builders = {
|
|
17
18
|
[PathDisplayType.None]: function (style, path, result) {
|
|
@@ -274,6 +275,12 @@ export class PathDisplaySystem extends AbstractContextSystem {
|
|
|
274
275
|
* @private
|
|
275
276
|
*/
|
|
276
277
|
this.__rebuild_queue = new Deque();
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
*
|
|
281
|
+
* @type {Signal}
|
|
282
|
+
*/
|
|
283
|
+
this.onWorkDone = new Signal();
|
|
277
284
|
}
|
|
278
285
|
|
|
279
286
|
/**
|
|
@@ -340,5 +347,8 @@ export class PathDisplaySystem extends AbstractContextSystem {
|
|
|
340
347
|
ctx.rebuild();
|
|
341
348
|
|
|
342
349
|
} while ((performance.now() - t0) < UPDATE_PROCESSING_BUDGET_MS && !queue.isEmpty());
|
|
350
|
+
|
|
351
|
+
// notify that some work was done
|
|
352
|
+
this.onWorkDone.send0();
|
|
343
353
|
}
|
|
344
354
|
}
|