@woosh/meep-engine 2.43.19 → 2.43.21
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/bvh2/bvh3/query/bvh_collect_user_data.js +1 -1
- package/engine/graphics/ecs/mesh-v2/aggregate/SGMeshHighlightSystem.js +12 -3
- package/engine/graphics/micron/format/MicronGeometryPatch.d.ts +1 -1
- package/engine/graphics/micron/format/MicronGeometryPatch.js +2 -1
- package/engine/graphics/sh3/path_tracer/PathTracedMesh.js +4 -0
- package/engine/graphics/sh3/path_tracer/PathTracer.js +89 -34
- package/engine/graphics/sh3/path_tracer/prototypePathTracer.js +41 -8
- package/engine/graphics/sh3/path_tracer/ray_hit_apply_transform.js +28 -13
- package/package.json +1 -1
|
@@ -16,12 +16,21 @@ export class SGMeshHighlightSystem extends System {
|
|
|
16
16
|
* @param {number} entity
|
|
17
17
|
* @private
|
|
18
18
|
*/
|
|
19
|
-
__apply_highlight(
|
|
19
|
+
__apply_highlight(event, entity) {
|
|
20
20
|
const ecd = this.entityManager.dataset;
|
|
21
21
|
|
|
22
22
|
const sg_mesh = ecd.getComponent(entity, SGMesh);
|
|
23
|
+
|
|
24
|
+
if (sg_mesh === undefined) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
23
28
|
const highlight = ecd.getComponent(entity, Highlight);
|
|
24
29
|
|
|
30
|
+
if (highlight === undefined) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
25
34
|
const node = sg_mesh.__node;
|
|
26
35
|
|
|
27
36
|
node.traverse(t => {
|
|
@@ -35,7 +44,7 @@ export class SGMeshHighlightSystem extends System {
|
|
|
35
44
|
* @param {number} entity
|
|
36
45
|
* @private
|
|
37
46
|
*/
|
|
38
|
-
__remove_highlight(
|
|
47
|
+
__remove_highlight(event, entity) {
|
|
39
48
|
|
|
40
49
|
const ecd = this.entityManager.dataset;
|
|
41
50
|
|
|
@@ -56,7 +65,7 @@ export class SGMeshHighlightSystem extends System {
|
|
|
56
65
|
*/
|
|
57
66
|
link(highlight, mesh, entity) {
|
|
58
67
|
if (mesh.__node !== null) {
|
|
59
|
-
this.__apply_highlight(undefined,
|
|
68
|
+
this.__apply_highlight(undefined, entity);
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
const ecd = this.entityManager.dataset;
|
|
@@ -35,7 +35,7 @@ export class MicronGeometryPatch {
|
|
|
35
35
|
this.group_bounding_box = null;
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
38
|
+
* TODO get rid of this, use bounding box instead for smaller memory footprint
|
|
39
39
|
* @type {number[]|Float32Array}
|
|
40
40
|
*/
|
|
41
41
|
this.group_bounding_box_corners = null;
|
|
@@ -124,6 +124,7 @@ export class MicronGeometryPatch {
|
|
|
124
124
|
* @returns {number}
|
|
125
125
|
*/
|
|
126
126
|
allocate_metadata(buffer, offset) {
|
|
127
|
+
assert.isNonNegativeInteger(offset, 'offset');
|
|
127
128
|
assert.greaterThanOrEqual(buffer.byteLength, offset + 144, 'buffer underflow');
|
|
128
129
|
|
|
129
130
|
this.bounding_box = new Float32Array(buffer, offset, 6);
|
|
@@ -23,14 +23,12 @@ import { linear_to_sRGB } from "../../../../core/color/linear_to_sRGB.js";
|
|
|
23
23
|
import { random_in_hemisphere } from "./random_in_hemisphere.js";
|
|
24
24
|
import { sample_triangle_attribute } from "./sample_triangle_attribute.js";
|
|
25
25
|
import { vec3_uint8_to_float } from "./vec3_uint8_to_float.js";
|
|
26
|
-
import { make_sky_rtiw } from "./make_sky_rtiw.js";
|
|
27
26
|
import { apply_texture_clamping_to_coordinate } from "./apply_texture_clamping_to_coordinate.js";
|
|
28
27
|
import { ebvh_sort_for_traversal_depth_first } from "../../../../core/bvh2/bvh3/ebvh_sort_for_traversal_depth_first.js";
|
|
29
|
-
import { clamp01 } from "../../../../core/math/clamp01.js";
|
|
30
28
|
import { v3_dot } from "../../../../core/geom/v3_dot.js";
|
|
31
|
-
import { LightType } from "../../ecs/light/LightType.js";
|
|
32
|
-
import { make_zero_vector3 } from "./make_zero_vector3.js";
|
|
33
29
|
import { make_one_vector3 } from "./make_one_vector3.js";
|
|
30
|
+
import { transform_normal_m4 } from "./ray_hit_apply_transform.js";
|
|
31
|
+
import { ray3_array_compose } from "../../../../core/geom/3d/ray/ray3_array_compose.js";
|
|
34
32
|
|
|
35
33
|
/*
|
|
36
34
|
Ray hit data layout:
|
|
@@ -49,13 +47,22 @@ const texture_uv = [0, 0];
|
|
|
49
47
|
const color = [];
|
|
50
48
|
|
|
51
49
|
const irradiance = [0, 0, 0];
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @type {number[]|vec3}
|
|
54
|
+
*/
|
|
55
|
+
const throughputColor = [1, 1, 1];
|
|
52
56
|
const trace_result = [];
|
|
53
57
|
|
|
54
|
-
const
|
|
58
|
+
const _ray_0 = [];
|
|
59
|
+
const _ray_1 = [];
|
|
55
60
|
|
|
56
61
|
const tmp_0 = [];
|
|
57
62
|
const tmp_1 = [];
|
|
58
63
|
|
|
64
|
+
const null_output = [];
|
|
65
|
+
|
|
59
66
|
|
|
60
67
|
export class PathTracer {
|
|
61
68
|
constructor() {
|
|
@@ -320,6 +327,9 @@ export class PathTracer {
|
|
|
320
327
|
const normal_array = normal_attribute.array;
|
|
321
328
|
|
|
322
329
|
sample_triangle_attribute(out, 3, index_0, index_1, index_2, normal_array, 3, u, v);
|
|
330
|
+
|
|
331
|
+
// apply transform
|
|
332
|
+
transform_normal_m4(out, 3, out, 3, mesh.transform);
|
|
323
333
|
} else {
|
|
324
334
|
// copy hit normal
|
|
325
335
|
array_copy(hit, 3, out, 3, 3);
|
|
@@ -417,16 +427,17 @@ export class PathTracer {
|
|
|
417
427
|
*
|
|
418
428
|
* @param {number[]} out
|
|
419
429
|
* @param {number} out_offset
|
|
420
|
-
* @param {number[]}
|
|
421
|
-
* @param {number}
|
|
430
|
+
* @param {number[]} ray
|
|
431
|
+
* @param {number} ray_address
|
|
422
432
|
*/
|
|
423
|
-
sample_lights(out, out_offset,
|
|
433
|
+
sample_lights(out, out_offset, ray, ray_address) {
|
|
424
434
|
let lights_sampled = false;
|
|
425
435
|
|
|
426
436
|
const lights = this.__lights;
|
|
427
437
|
const light_count = lights.length;
|
|
428
438
|
|
|
429
439
|
for (let i = 0; i < 3; i++) {
|
|
440
|
+
// initialize contribution to 0
|
|
430
441
|
out[out_offset + i] = 0;
|
|
431
442
|
}
|
|
432
443
|
|
|
@@ -436,23 +447,47 @@ export class PathTracer {
|
|
|
436
447
|
if (light.isDirectionalLight === true) {
|
|
437
448
|
const dir = light.direction;
|
|
438
449
|
|
|
450
|
+
// see https://github.com/mrdoob/three.js/blob/f0a9e0cf90a2f1ba5017fcb7fd46f02748b920cf/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js#L172
|
|
451
|
+
|
|
452
|
+
const ray_direction_x = ray[ray_address + 3];
|
|
453
|
+
const ray_direction_y = ray[ray_address + 4];
|
|
454
|
+
const ray_direction_z = ray[ray_address + 5];
|
|
455
|
+
|
|
456
|
+
const light_dir_inv_x = -dir.x;
|
|
457
|
+
const light_dir_inv_y = -dir.y;
|
|
458
|
+
const light_dir_inv_z = -dir.z;
|
|
459
|
+
|
|
460
|
+
const dotNL = v3_dot(ray_direction_x, ray_direction_y, ray_direction_z, light_dir_inv_x, light_dir_inv_y, light_dir_inv_z);
|
|
461
|
+
|
|
462
|
+
if (dotNL <= 0) {
|
|
463
|
+
// no contribution, facing away from the light
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
const ray_origin_x = ray[ray_address + 0];
|
|
468
|
+
const ray_origin_y = ray[ray_address + 1];
|
|
469
|
+
const ray_origin_z = ray[ray_address + 2];
|
|
470
|
+
|
|
471
|
+
ray3_array_compose(_ray_1,
|
|
472
|
+
ray_origin_x, ray_origin_y, ray_origin_z,
|
|
473
|
+
light_dir_inv_x, light_dir_inv_y, light_dir_inv_z
|
|
474
|
+
);
|
|
475
|
+
|
|
439
476
|
// check if there are any obstacles in the direction of the light
|
|
440
|
-
if (this.trace(
|
|
441
|
-
hit_info[hit_info_address + 0],
|
|
442
|
-
hit_info[hit_info_address + 1],
|
|
443
|
-
hit_info[hit_info_address + 2],
|
|
444
|
-
-dir.x, -dir.y, -dir.z
|
|
445
|
-
], 0.0001, Infinity) > 0) {
|
|
477
|
+
if (this.trace(null_output, _ray_1, 0.0001, Infinity) > 0) {
|
|
446
478
|
// light is occluded
|
|
447
|
-
|
|
479
|
+
continue;
|
|
448
480
|
}
|
|
449
481
|
|
|
450
|
-
|
|
482
|
+
|
|
483
|
+
const intensity = dotNL * light.intensity.getValue();
|
|
451
484
|
|
|
452
485
|
for (let j = 0; j < 3; j++) {
|
|
453
486
|
// irradiance
|
|
454
|
-
out[out_offset + j] +=
|
|
487
|
+
out[out_offset + j] += light.color[j] * intensity;
|
|
455
488
|
}
|
|
489
|
+
|
|
490
|
+
lights_sampled = true;
|
|
456
491
|
}
|
|
457
492
|
}
|
|
458
493
|
|
|
@@ -462,28 +497,30 @@ export class PathTracer {
|
|
|
462
497
|
path_trace(out, ray, max_distance, max_bounce, random = Math.random) {
|
|
463
498
|
//TODO add importance sampling, see https://raytracing.github.io/books/RayTracingTheRestOfYourLife.html#lightscattering/thescatteringpdf
|
|
464
499
|
|
|
465
|
-
array_copy(ray, 0,
|
|
500
|
+
array_copy(ray, 0, _ray_0, 0, 6);
|
|
466
501
|
|
|
467
|
-
irradiance[0] =
|
|
468
|
-
irradiance[1] =
|
|
469
|
-
irradiance[2] =
|
|
502
|
+
irradiance[0] = 1;
|
|
503
|
+
irradiance[1] = 1;
|
|
504
|
+
irradiance[2] = 1;
|
|
470
505
|
|
|
471
506
|
let got_emission = false;
|
|
472
507
|
|
|
473
508
|
let i;
|
|
474
509
|
for (i = 0; i < max_bounce; i++) {
|
|
475
510
|
|
|
476
|
-
const hit_distance = this.trace(trace_result,
|
|
511
|
+
const hit_distance = this.trace(trace_result, _ray_0, 0.0001, max_distance);
|
|
512
|
+
|
|
477
513
|
|
|
478
514
|
if (hit_distance < 0) {
|
|
479
515
|
// ray didn't hit anything
|
|
480
516
|
|
|
481
517
|
// sample "environment" and terminate path as there is nothing to reflect off of
|
|
482
518
|
|
|
483
|
-
this.sample_background(tmp_0, 0,
|
|
519
|
+
this.sample_background(tmp_0, 0, _ray_0, 3);
|
|
484
520
|
|
|
485
521
|
vec3.multiply(irradiance, irradiance, tmp_0);
|
|
486
522
|
|
|
523
|
+
|
|
487
524
|
got_emission = true;
|
|
488
525
|
|
|
489
526
|
break;
|
|
@@ -496,28 +533,36 @@ export class PathTracer {
|
|
|
496
533
|
this.sample_material(tmp_0, trace_result);
|
|
497
534
|
|
|
498
535
|
// adjust normal on the hit
|
|
499
|
-
|
|
536
|
+
array_copy(tmp_0, 3, trace_result, 3, 3);
|
|
500
537
|
|
|
501
|
-
// sample light
|
|
502
|
-
this.sample_lights(tmp_1, 0, trace_result, 0);
|
|
503
|
-
vec3.add(irradiance, irradiance, tmp_1);
|
|
504
538
|
|
|
505
539
|
// reflect ray
|
|
506
|
-
array_copy(trace_result, 0,
|
|
540
|
+
array_copy(trace_result, 0, _ray_0, 0, 3);
|
|
507
541
|
|
|
508
542
|
// getBiasedNormalSample(_ray, 3, tmp, 3, 1, random);
|
|
509
|
-
random_in_hemisphere(random,
|
|
543
|
+
random_in_hemisphere(random, _ray_0, 3, tmp_0, 3);
|
|
510
544
|
|
|
545
|
+
// accumulate
|
|
511
546
|
vec3.multiply(irradiance, irradiance, tmp_0);
|
|
512
547
|
}
|
|
513
548
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
549
|
+
|
|
550
|
+
if (i > 0) {
|
|
551
|
+
|
|
552
|
+
// directly sample light at the end of the path
|
|
553
|
+
this.sample_lights(tmp_1, 0, trace_result, 0);
|
|
554
|
+
|
|
555
|
+
vec3.multiply(irradiance, irradiance, tmp_1);
|
|
519
556
|
}
|
|
520
557
|
|
|
558
|
+
//
|
|
559
|
+
// if (got_emission === false) {
|
|
560
|
+
// // no light source was hit, propagate shadow(darkness) along the ray
|
|
561
|
+
// irradiance[0] = 0;
|
|
562
|
+
// irradiance[1] = 0;
|
|
563
|
+
// irradiance[2] = 0;
|
|
564
|
+
// }
|
|
565
|
+
|
|
521
566
|
array_copy(irradiance, 0, out, 0, 3);
|
|
522
567
|
}
|
|
523
568
|
}
|
|
@@ -532,3 +577,13 @@ function compute_hit_reaction_standard_material(material, hit) {
|
|
|
532
577
|
}
|
|
533
578
|
|
|
534
579
|
|
|
580
|
+
/**
|
|
581
|
+
*
|
|
582
|
+
* @param {number[]|vec3} out
|
|
583
|
+
* @param {number} value
|
|
584
|
+
*/
|
|
585
|
+
function vec3_set_scalar(out, value) {
|
|
586
|
+
out[0] = value;
|
|
587
|
+
out[1] = value;
|
|
588
|
+
out[2] = value;
|
|
589
|
+
}
|
|
@@ -21,7 +21,7 @@ import { Camera } from "../../ecs/camera/Camera.js";
|
|
|
21
21
|
import Vector3 from "../../../../core/geom/Vector3.js";
|
|
22
22
|
import { scaleSampler2D } from "../../texture/sampler/scaleSampler2D.js";
|
|
23
23
|
import { seededRandom } from "../../../../core/math/random/seededRandom.js";
|
|
24
|
-
import { mat4 } from "gl-matrix";
|
|
24
|
+
import { mat4, vec3 } from "gl-matrix";
|
|
25
25
|
import { v3_distance } from "../../../../core/geom/v3_distance.js";
|
|
26
26
|
import ConcurrentExecutor from "../../../../core/process/executor/ConcurrentExecutor.js";
|
|
27
27
|
import Task from "../../../../core/process/task/Task.js";
|
|
@@ -38,6 +38,7 @@ import { Color } from "../../../../core/color/Color.js";
|
|
|
38
38
|
import { min2 } from "../../../../core/math/min2.js";
|
|
39
39
|
import { makeGeometryIndexed } from "../../geometry/buffered/makeGeometryIndexed.js";
|
|
40
40
|
import { DirectionalLight } from "../../render/forward_plus/model/DirectionalLight.js";
|
|
41
|
+
import { kelvin_to_rgb } from "../../../../core/color/kelvin_to_rgb.js";
|
|
41
42
|
|
|
42
43
|
document.body.style.margin = 0;
|
|
43
44
|
document.body.style.overflow = "hidden";
|
|
@@ -103,6 +104,32 @@ const gltfLoader = new GLTFLoader();
|
|
|
103
104
|
// );
|
|
104
105
|
//
|
|
105
106
|
|
|
107
|
+
function make_sun({
|
|
108
|
+
temperature = 5000, // around clear-sky day
|
|
109
|
+
color = '#FFFFFF',
|
|
110
|
+
intensity = 1,
|
|
111
|
+
direction = new Vector3(-0.5, -1, -0.05)
|
|
112
|
+
} = {}) {
|
|
113
|
+
|
|
114
|
+
const temp_c = new Color();
|
|
115
|
+
|
|
116
|
+
kelvin_to_rgb(temp_c, 0, temperature);
|
|
117
|
+
|
|
118
|
+
const light = new DirectionalLight();
|
|
119
|
+
|
|
120
|
+
light.color.parse(color);
|
|
121
|
+
vec3.multiply(light.color, light.color, temp_c);
|
|
122
|
+
|
|
123
|
+
const n = vec3.length(light.color);
|
|
124
|
+
vec3.scale(light.color, light.color, 1 / n); // normalize color vector
|
|
125
|
+
|
|
126
|
+
light.intensity.set(intensity * n);
|
|
127
|
+
light.direction.copy(direction);
|
|
128
|
+
light.direction.normalize();
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
return light;
|
|
132
|
+
}
|
|
106
133
|
|
|
107
134
|
function prepare_scene_sphere_01(pt, camera) {
|
|
108
135
|
camera.position.set(0, 0, -2.1);
|
|
@@ -132,7 +159,7 @@ function prepare_scene_sphere_01(pt, camera) {
|
|
|
132
159
|
light.direction.set(-1, -1, 0);
|
|
133
160
|
light.direction.normalize();
|
|
134
161
|
|
|
135
|
-
pt.addLight(
|
|
162
|
+
pt.addLight(make_sun());
|
|
136
163
|
}
|
|
137
164
|
|
|
138
165
|
function promise_ply(url) {
|
|
@@ -189,6 +216,8 @@ async function prepare_scene_gltf(pt, camera, url) {
|
|
|
189
216
|
|
|
190
217
|
box3.getBoundingSphere(sphere);
|
|
191
218
|
|
|
219
|
+
pt.addLight(make_sun());
|
|
220
|
+
|
|
192
221
|
camera.position.set(1, 1.3, 1)
|
|
193
222
|
.normalize()
|
|
194
223
|
.multiplyScalar(sphere.radius * 2.6);
|
|
@@ -226,6 +255,8 @@ async function prepare_scene_lucy(pt, camera) {
|
|
|
226
255
|
}).matrix);
|
|
227
256
|
|
|
228
257
|
|
|
258
|
+
pt.addLight(make_sun());
|
|
259
|
+
|
|
229
260
|
camera.position.set(0, 0, -2300);
|
|
230
261
|
camera.lookAt(0, 0, 0);
|
|
231
262
|
}
|
|
@@ -336,6 +367,8 @@ async function prepare_scene_rtiow(pt, camera) {
|
|
|
336
367
|
}
|
|
337
368
|
|
|
338
369
|
|
|
370
|
+
pt.addLight(make_sun());
|
|
371
|
+
|
|
339
372
|
camera.position.set(13, 2, 3);
|
|
340
373
|
camera.lookAt(0, 0, 0);
|
|
341
374
|
|
|
@@ -376,7 +409,7 @@ function* render(target, pt, camera, progress = { current: 0, total: 0 }) {
|
|
|
376
409
|
const pixel_scale_x = 1 / (width - 1);
|
|
377
410
|
const pixel_scale_y = 1 / (height - 1);
|
|
378
411
|
|
|
379
|
-
const pixel_sample_count =
|
|
412
|
+
const pixel_sample_count = 500;
|
|
380
413
|
|
|
381
414
|
progress.total = width * height;
|
|
382
415
|
|
|
@@ -426,7 +459,7 @@ function* render(target, pt, camera, progress = { current: 0, total: 0 }) {
|
|
|
426
459
|
ray_direction.x, ray_direction.y, ray_direction.z
|
|
427
460
|
);
|
|
428
461
|
|
|
429
|
-
pt.path_trace(out, ray, Infinity,
|
|
462
|
+
pt.path_trace(out, ray, Infinity, 16, random);
|
|
430
463
|
|
|
431
464
|
out2[0] += out[0];
|
|
432
465
|
out2[1] += out[1];
|
|
@@ -476,12 +509,12 @@ const camera = new PerspectiveCamera();
|
|
|
476
509
|
async function start_renderer(camera) {
|
|
477
510
|
camera.aspect = vCanvas.size.x / vCanvas.size.y;
|
|
478
511
|
|
|
479
|
-
|
|
480
|
-
const path = 'data/models/road_bike/road_bike.gltf'; //large CAD-type model
|
|
512
|
+
const path = 'data/models/LowPolyTownshipSet/Small_house/Small_house.gltf';
|
|
513
|
+
// const path = 'data/models/road_bike/road_bike.gltf'; //large CAD-type model
|
|
481
514
|
|
|
482
515
|
// await prepare_scene_lucy(pt, camera);
|
|
483
|
-
|
|
484
|
-
await prepare_scene_sphere_01(pt, camera);
|
|
516
|
+
await prepare_scene_rtiow(pt, camera);
|
|
517
|
+
// await prepare_scene_sphere_01(pt, camera);
|
|
485
518
|
// await prepare_scene_gltf(pt, camera, path);
|
|
486
519
|
|
|
487
520
|
pt.build();
|
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
import { v3_length } from "../../../../core/geom/v3_length.js";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {number[]} output
|
|
6
|
+
* @param {number} output_offset
|
|
7
|
+
* @param {number[]} normal
|
|
8
|
+
* @param {number} normal_offset
|
|
9
|
+
* @param {number[]} m 4x4 matrix
|
|
10
|
+
*/
|
|
11
|
+
export function transform_normal_m4(output, output_offset, normal, normal_offset, m) {
|
|
12
|
+
|
|
13
|
+
const n_x = normal[normal_offset];
|
|
14
|
+
const n_y = normal[normal_offset + 1];
|
|
15
|
+
const n_z = normal[normal_offset + 2];
|
|
16
|
+
|
|
17
|
+
const result_n_x = m[0] * n_x + m[4] * n_y + m[8] * n_z;
|
|
18
|
+
const result_n_y = m[1] * n_x + m[5] * n_y + m[9] * n_z;
|
|
19
|
+
const result_n_z = m[2] * n_x + m[6] * n_y + m[10] * n_z;
|
|
20
|
+
|
|
21
|
+
const vec_length = v3_length(result_n_x, result_n_y, result_n_z);
|
|
22
|
+
|
|
23
|
+
const normal_multiplier = vec_length === 0 ? 0 : 1 / vec_length;
|
|
24
|
+
|
|
25
|
+
output[output_offset] = result_n_x * normal_multiplier;
|
|
26
|
+
output[output_offset + 1] = result_n_y * normal_multiplier;
|
|
27
|
+
output[output_offset + 2] = result_n_z * normal_multiplier;
|
|
28
|
+
}
|
|
29
|
+
|
|
3
30
|
/**
|
|
4
31
|
*
|
|
5
32
|
* @param {number[]} output
|
|
@@ -25,18 +52,6 @@ export function ray_hit_apply_transform(output, hit, m) {
|
|
|
25
52
|
output[2] = result_p_z;
|
|
26
53
|
|
|
27
54
|
// transform normal
|
|
28
|
-
|
|
29
|
-
const n_y = hit[4];
|
|
30
|
-
const n_z = hit[5];
|
|
31
|
-
|
|
32
|
-
const result_n_x = m[0] * n_x + m[4] * n_y + m[8] * n_z;
|
|
33
|
-
const result_n_y = m[1] * n_x + m[5] * n_y + m[9] * n_z;
|
|
34
|
-
const result_n_z = m[2] * n_x + m[6] * n_y + m[10] * n_z;
|
|
35
|
-
|
|
36
|
-
const normal_multiplier = 1 / v3_length(result_n_x, result_n_y, result_n_z);
|
|
37
|
-
|
|
38
|
-
output[3] = result_n_x * normal_multiplier;
|
|
39
|
-
output[4] = result_n_y * normal_multiplier;
|
|
40
|
-
output[5] = result_n_z * normal_multiplier;
|
|
55
|
+
transform_normal_m4(output, 3, hit, 3, m);
|
|
41
56
|
|
|
42
57
|
}
|
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.43.
|
|
8
|
+
"version": "2.43.21",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|