@woosh/meep-engine 2.43.17 → 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/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;
|
|
@@ -3,22 +3,28 @@ import { computeStringHash } from "../../../core/primitives/strings/computeStrin
|
|
|
3
3
|
import { DataTypeByteSizes } from "../../../core/collection/table/DataTypeByteSizes.js";
|
|
4
4
|
import { assert } from "../../../core/assert.js";
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Describes data structure of a single data attribute, such as a scalar, or a vector
|
|
8
|
+
* This structure is designed to map well to GPU shader formats and is intended for larger datasets, such as meshes or particle clouds
|
|
9
|
+
*/
|
|
6
10
|
export class AttributeSpec {
|
|
7
11
|
constructor() {
|
|
8
12
|
/**
|
|
9
|
-
*
|
|
13
|
+
* Typically unique within a given set, used to identify the attribute
|
|
10
14
|
* @type {string}
|
|
11
15
|
*/
|
|
12
16
|
this.name = "";
|
|
13
17
|
|
|
14
18
|
/**
|
|
15
|
-
*
|
|
19
|
+
* How the attribute is stored in memory and interpreted
|
|
16
20
|
* @type {DataType}
|
|
17
21
|
*/
|
|
18
22
|
this.type = DataType.Float32;
|
|
19
23
|
|
|
20
24
|
/**
|
|
21
|
-
*
|
|
25
|
+
* How many elements the attribute uses. This is cardinality of a vector.
|
|
26
|
+
* 1 means the attribute is a scalar
|
|
27
|
+
* must be greater or equal to 1
|
|
22
28
|
* @type {number}
|
|
23
29
|
*/
|
|
24
30
|
this.itemSize = 1;
|
|
@@ -62,6 +68,15 @@ export class AttributeSpec {
|
|
|
62
68
|
this.normalized = normalized;
|
|
63
69
|
}
|
|
64
70
|
|
|
71
|
+
toJSON() {
|
|
72
|
+
return {
|
|
73
|
+
name: this.name,
|
|
74
|
+
type: this.type,
|
|
75
|
+
itemSize: this.itemSize,
|
|
76
|
+
normalized: this.normalized
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
65
80
|
hash() {
|
|
66
81
|
return computeStringHash(this.name);
|
|
67
82
|
}
|