@woosh/meep-engine 2.33.38 → 2.33.42

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.
Files changed (40) hide show
  1. package/core/bvh2/binary/2/BinaryUint32BVH.js +3 -3
  2. package/core/collection/array/typed/typed_array_copy.js +2 -2
  3. package/core/geom/3d/aabb/aabb3_matrix4_project_by_corners.js +1 -1
  4. package/core/geom/3d/morton/mortonEncode_magicbits.js +7 -6
  5. package/core/geom/3d/morton/v3_morton_encode_transformed.js +15 -11
  6. package/core/geom/3d/tetrahedra/tetrahedra_collection.js +193 -18
  7. package/core/geom/3d/tetrahedra/tetrahedron_contains_point.js +2 -1
  8. package/engine/asset/loaders/GLTFAssetLoader.js +4 -8
  9. package/engine/ecs/System.d.ts +24 -1
  10. package/engine/graphics/ecs/light/binding/fp/FPLightBinding.js +1 -1
  11. package/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +20 -24
  12. package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +1 -1
  13. package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +2 -2
  14. package/engine/graphics/render/buffer/simple-fx/DepthLimitedBlur.js +9 -4
  15. package/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +7 -1
  16. package/engine/graphics/render/forward_plus/LightManager.js +295 -51
  17. package/engine/graphics/render/forward_plus/LightManager.spec.js +1 -1
  18. package/engine/graphics/render/forward_plus/PointLightData.js +9 -13
  19. package/engine/graphics/render/forward_plus/data/TextureBackedMemoryRegion.js +10 -1
  20. package/engine/graphics/render/forward_plus/debug/LightClusterVolumeMaterial.js +1 -1
  21. package/engine/graphics/render/forward_plus/debug/buildLightClusterWidget.js +3 -1
  22. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +31 -18
  23. package/engine/graphics/render/forward_plus/materials/fp_build_fragment_shader.js +1 -0
  24. package/engine/graphics/render/forward_plus/model/AbstractLight.js +50 -0
  25. package/engine/graphics/render/forward_plus/model/Decal.js +68 -0
  26. package/engine/graphics/render/forward_plus/{PointLight.js → model/PointLight.js} +19 -11
  27. package/engine/graphics/render/forward_plus/{SpotLight.js → model/SpotLight.js} +20 -12
  28. package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +6 -5
  29. package/engine/graphics/render/forward_plus/{prototypeLightManager.js → prototype/prototypeLightManager.js} +100 -25
  30. package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +29 -20
  31. package/engine/graphics/render/visibility/IncrementalDeltaSet.d.ts +2 -0
  32. package/engine/graphics/render/visibility/IncrementalDeltaSet.js +1 -0
  33. package/engine/graphics/texture/atlas/AbstractTextureAtlas.js +19 -0
  34. package/engine/graphics/texture/atlas/CachingTextureAtlas.js +99 -0
  35. package/engine/graphics/texture/atlas/ManagedTextureAtlas.js +19 -39
  36. package/engine/graphics/texture/atlas/ReferencedTextureAtlas.js +75 -0
  37. package/engine/graphics/texture/atlas/TextureAtlas.js +22 -2
  38. package/engine/reference/v2/Reference.d.ts +4 -0
  39. package/engine/reference/v2/Reference.js +3 -1
  40. package/package.json +1 -1
@@ -55,7 +55,9 @@ export function buildLightClusterWidget(lm, camera) {
55
55
  domElement: renderer.domElement,
56
56
  update() {
57
57
  render_cam.updateProjectionMatrix();
58
- m.uniforms.map.value = lm.getTextureClusters().clone();
58
+ const t = lm.getTextureClusters().clone();
59
+ t.needsUpdate = true;
60
+ m.uniforms.map.value = t;
59
61
  m.uniforms.cameraPos.value.copy(render_cam.position)
60
62
 
61
63
  renderer.render(group, render_cam);
@@ -8,25 +8,38 @@ export const FP_SHADER_CHUNK_ACCUMULATION = `
8
8
  for(uint i=0u; i < cluster_metadata.y; i++){
9
9
  uint lookup_index = cluster_metadata.x + i;
10
10
 
11
- uint light_address = texelFetch(fp_t_light_lookup, address_to_data_texture_coordinates(lookup_index), 0 ).r;
11
+ uint light_descriptor = texelFetch(fp_t_light_lookup, address_to_data_texture_coordinates(lookup_index), 0 ).r;
12
12
 
13
- vec4 light_data_0 = texelFetch(fp_t_light_data, address_to_data_texture_coordinates(light_address), 0);
14
- vec4 light_data_1 = texelFetch(fp_t_light_data, address_to_data_texture_coordinates(light_address+1u), 0);
13
+ uint type = (light_descriptor) & 0x3u;
14
+ uint light_address = light_descriptor >> 2;
15
+
15
16
 
16
- vec3 light_position = light_data_0.xyz;
17
- float light_radius = light_data_0.w;
18
-
19
- vec3 light_color = light_data_1.xyz;
20
- float light_intensity = light_data_1.w;
21
-
22
- PointLight pointlight;
23
-
24
- pointlight.position = light_position;
25
- pointlight.distance = light_radius;
26
- pointlight.color = light_color*light_intensity;
27
- pointlight.decay = 1.0;
28
-
29
- fp_getPointDirectLightIrradiance( pointlight, directLight, vViewPosition );
30
- RE_Direct( directLight, geometry, material, reflectedLight );
17
+ if(type == 0u){
18
+ // point light
19
+
20
+ vec4 light_data_0 = texelFetch(fp_t_light_data, address_to_data_texture_coordinates(light_address), 0);
21
+ vec4 light_data_1 = texelFetch(fp_t_light_data, address_to_data_texture_coordinates(light_address+1u), 0);
22
+
23
+ vec3 light_position = light_data_0.xyz;
24
+ float light_radius = light_data_0.w;
25
+
26
+ vec3 light_color = light_data_1.xyz;
27
+ float light_intensity = light_data_1.w;
28
+
29
+ PointLight pointlight;
30
+
31
+ pointlight.position = light_position;
32
+ pointlight.distance = light_radius;
33
+ pointlight.color = light_color*light_intensity;
34
+ pointlight.decay = 1.0;
35
+
36
+ fp_getPointDirectLightIrradiance( pointlight, directLight, vViewPosition );
37
+ RE_Direct( directLight, geometry, material, reflectedLight );
38
+
39
+ }else if(type == 3u){
40
+ // decal
41
+
42
+
43
+ }
31
44
  }
32
45
  `;
@@ -9,6 +9,7 @@ const three_chunk_accummulation_mark = '#include <lights_fragment_end>';
9
9
 
10
10
  const accumulation_pars = `
11
11
  vec3 clip_v = vec3( vec2(gl_FragCoord.x, gl_FragCoord.y) / fp_resolution, convert_depth_to_linear(gl_FragCoord.z));
12
+ clip_v.x = 1.0 - clip_v.x;
12
13
  ${FP_SHADER_CHUNK_ACCUMULATION}
13
14
  `;
14
15
 
@@ -0,0 +1,50 @@
1
+ export class AbstractLight {
2
+
3
+ /**
4
+ *
5
+ * @param {function} f
6
+ * @param {*} [thisArg]
7
+ * @returns {void}
8
+ */
9
+ onDimensionChanged(f, thisArg) {
10
+ throw new Error('Not Implemented');
11
+ }
12
+
13
+ /**
14
+ *
15
+ * @param {function} f
16
+ * @param {*} [thisArg]
17
+ * @returns {void}
18
+ */
19
+ offDimensionChanged(f, thisArg) {
20
+ throw new Error('Not Implemented');
21
+ }
22
+
23
+ /**
24
+ *
25
+ * @param {number[]} result
26
+ * @returns {void}
27
+ */
28
+ getCenter(result) {
29
+ throw new Error('Not Implemented');
30
+ }
31
+
32
+ /**
33
+ *
34
+ * @param {AABB3} result
35
+ * @returns {void}
36
+ */
37
+ getAABB(result) {
38
+ throw new Error('Not Implemented');
39
+ }
40
+
41
+ /**
42
+ *
43
+ * @param {number[]|Float32Array|Float64Array} destination
44
+ * @param {number} address
45
+ * @returns {number} number of records written, measured in destination array slots
46
+ */
47
+ toArray(destination, address) {
48
+ throw new Error('Not Implemented');
49
+ }
50
+ }
@@ -0,0 +1,68 @@
1
+ import { AbstractLight } from "./AbstractLight.js";
2
+ import { aabb3_matrix4_project_by_corners } from "../../../../../core/geom/3d/aabb/aabb3_matrix4_project_by_corners.js";
3
+ import { aabb3_build_corners } from "../../../../../core/geom/3d/aabb/aabb3_build_corners.js";
4
+ import { array_copy } from "../../../../../core/collection/array/copyArray.js";
5
+
6
+ export class Decal extends AbstractLight {
7
+ constructor() {
8
+ super();
9
+
10
+ /**
11
+ * Transform matrix, initial volume is a unit cube
12
+ * @type {number[]|Float32Array|mat4[]}
13
+ */
14
+ this.transform = new Float32Array(16);
15
+
16
+ /**
17
+ *
18
+ * @type {Sampler2D}
19
+ */
20
+ this.texture_diffuse = null;
21
+
22
+ /**
23
+ * Order in which decal should be applied, higher priority decals will be drawn first
24
+ * NOTE: not implemented yet
25
+ * @type {number}
26
+ */
27
+ this.draw_priority = 0;
28
+ }
29
+
30
+ onDimensionChanged(f, thisArg) {
31
+ // TODO implement
32
+ }
33
+
34
+ offDimensionChanged(f, thisArg) {
35
+ // TODO implement
36
+ }
37
+
38
+ getCenter(result) {
39
+ // extract translation portion of the matrix
40
+ result[0] = this.transform[12];
41
+ result[1] = this.transform[13];
42
+ result[2] = this.transform[14];
43
+ }
44
+
45
+ getAABB(result) {
46
+ const corners = [];
47
+ aabb3_build_corners(corners, 0, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5);
48
+
49
+ const aabb_array = new Float32Array(6);
50
+ aabb3_matrix4_project_by_corners(aabb_array, corners, this.transform);
51
+
52
+ result.readFromArray(aabb_array, 0);
53
+ }
54
+
55
+ toArray(destination, address) {
56
+ array_copy(this.transform, 0, destination, address, 16);
57
+
58
+ return 16;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * @readonly
64
+ * @type {boolean}
65
+ */
66
+ Decal.prototype.isDecal = true;
67
+
68
+ Decal.prototype.ENCODED_SLOT_COUNT = 16;
@@ -1,10 +1,16 @@
1
- import Vector3 from "../../../../core/geom/Vector3.js";
2
- import { Color } from "../../../../core/color/Color.js";
3
- import Vector1 from "../../../../core/geom/Vector1.js";
4
- import { mortonEncode_magicbits } from "../../../../core/geom/3d/morton/mortonEncode_magicbits.js";
1
+ import Vector3 from "../../../../../core/geom/Vector3.js";
2
+ import { Color } from "../../../../../core/color/Color.js";
3
+ import Vector1 from "../../../../../core/geom/Vector1.js";
4
+ import { AbstractLight } from "./AbstractLight.js";
5
5
 
6
- export class PointLight {
6
+ export class PointLight extends AbstractLight {
7
7
  constructor() {
8
+ super();
9
+
10
+ /**
11
+ * @readonly
12
+ * @type {Vector3}
13
+ */
8
14
  this.position = new Vector3();
9
15
 
10
16
  /**
@@ -13,6 +19,10 @@ export class PointLight {
13
19
  */
14
20
  this.radius = new Vector1(1);
15
21
 
22
+ /**
23
+ * @readonly
24
+ * @type {Color}
25
+ */
16
26
  this.color = new Color(1, 1, 1);
17
27
 
18
28
  /**
@@ -22,12 +32,8 @@ export class PointLight {
22
32
  this.intensity = new Vector1(1);
23
33
  }
24
34
 
25
- /**
26
- *
27
- * @returns {number}
28
- */
29
- computeMortonCode() {
30
- return mortonEncode_magicbits(this.position.x, this.position.y, this.position.z);
35
+ getCenter(result) {
36
+ this.position.writeToArray(result, 0);
31
37
  }
32
38
 
33
39
  /**
@@ -95,3 +101,5 @@ export class PointLight {
95
101
  * @type {boolean}
96
102
  */
97
103
  PointLight.prototype.isPointLight = true;
104
+
105
+ PointLight.prototype.ENCODED_SLOT_COUNT = 16;
@@ -1,11 +1,13 @@
1
- import Vector3 from "../../../../core/geom/Vector3.js";
2
- import Vector1 from "../../../../core/geom/Vector1.js";
3
- import { Color } from "../../../../core/color/Color.js";
4
- import { computeConeBoundingBox } from "../../../../core/geom/3d/cone/computeConeBoundingBox.js";
5
- import { mortonEncode_magicbits } from "../../../../core/geom/3d/morton/mortonEncode_magicbits.js";
1
+ import Vector3 from "../../../../../core/geom/Vector3.js";
2
+ import Vector1 from "../../../../../core/geom/Vector1.js";
3
+ import { Color } from "../../../../../core/color/Color.js";
4
+ import { computeConeBoundingBox } from "../../../../../core/geom/3d/cone/computeConeBoundingBox.js";
5
+ import { AbstractLight } from "./AbstractLight.js";
6
6
 
7
- export class SpotLight {
7
+ export class SpotLight extends AbstractLight {
8
8
  constructor() {
9
+ super();
10
+
9
11
  /**
10
12
  *
11
13
  * @type {Vector3}
@@ -49,12 +51,18 @@ export class SpotLight {
49
51
  this.penumbra = new Vector1(0.4);
50
52
  }
51
53
 
52
- /**
53
- *
54
- * @returns {number}
55
- */
56
- computeMortonCode() {
57
- return mortonEncode_magicbits(this.position.x, this.position.y, this.position.z);
54
+ getCenter(result) {
55
+ // find center of the cone (mid point along the cone length)
56
+
57
+ const d = this.direction;
58
+
59
+ const m = this.distance.getValue() * 0.5;
60
+
61
+ const p = this.position;
62
+
63
+ result[0] = p.x + d.x * m;
64
+ result[1] = p.y + d.y * m;
65
+ result[2] = p.z + d.z * m;
58
66
  }
59
67
 
60
68
  /**
@@ -223,7 +223,8 @@ function makeLight(position, radius, color, intensity = 1) {
223
223
  const mesh_center_1 = new ThreeMesh(sphere_geometry, new MeshBasicMaterial({
224
224
  color: color_uint,
225
225
  transparent: true,
226
- opacity: 0.06
226
+ opacity: 0.06,
227
+ writeDepth: false
227
228
  }));
228
229
  mesh_center_1.scale.setScalar(0.3);
229
230
  mesh_center_1.matrixAutoUpdate = false;
@@ -737,7 +738,7 @@ function setup_scene_3(engine, ecd) {
737
738
  1,
738
739
  1,
739
740
  1,
740
- 0.1,
741
+ 0.0,
741
742
 
742
743
  1,
743
744
  1,
@@ -937,7 +938,7 @@ function setup_scene_2(engine, ecd) {
937
938
 
938
939
  const random = seededRandom(0);
939
940
 
940
- for (let i = 0; i < 10; i++) {
941
+ for (let i = 0; i < 100; i++) {
941
942
 
942
943
  const builder = makeLight([
943
944
  randomFloatBetween(random, -20, 20) + offset.x,
@@ -968,7 +969,7 @@ function setup_scene_2(engine, ecd) {
968
969
  .build(ecd);
969
970
  }
970
971
 
971
- for (let i = 0; i < 200; i++) {
972
+ for (let i = 0; i < 0; i++) {
972
973
 
973
974
  const builder = makeLight([
974
975
  randomFloatBetween(random, -10, 10) + offset.x,
@@ -1130,7 +1131,7 @@ function main(engine) {
1130
1131
  engine.graphics.renderer.setClearColor('rgba(99,99,99,1)');
1131
1132
 
1132
1133
  setup_scene_3(engine, ecd);
1133
- // setup_scene_1(engine, ecd);
1134
+ // setup_scene_2(engine, ecd);
1134
1135
 
1135
1136
  // engine.graphics.loadEnvironmentMap(buildCubeURLs('data/textures/cubemaps/hip_miramar/32/', '.png'));
1136
1137
 
@@ -3,6 +3,7 @@ import {
3
3
  HemisphereLight,
4
4
  Line,
5
5
  LineBasicMaterial,
6
+ LineSegments,
6
7
  Mesh,
7
8
  MeshBasicMaterial,
8
9
  OctahedronBufferGeometry,
@@ -13,35 +14,40 @@ import {
13
14
  Vector2,
14
15
  WebGLRenderer
15
16
  } from "three";
16
- import { min2 } from "../../../../core/math/min2.js";
17
- import { seededRandom } from "../../../../core/math/random/seededRandom.js";
18
- import { PointLight } from "./PointLight.js";
19
- import { makeHelperSphereGeometry } from "../../../../editor/process/symbolic/makeHelperSphereGeometry.js";
17
+ import { min2 } from "../../../../../core/math/min2.js";
18
+ import { seededRandom } from "../../../../../core/math/random/seededRandom.js";
19
+ import { PointLight } from "../model/PointLight.js";
20
+ import { makeHelperSphereGeometry } from "../../../../../editor/process/symbolic/makeHelperSphereGeometry.js";
20
21
  import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
21
- import { MouseEvents } from "../../../input/devices/events/MouseEvents.js";
22
- import { RingBuffer } from "../../../../core/collection/RingBuffer.js";
23
- import { query_bvh_frustum_from_objects } from "./query/query_bvh_frustum_from_objects.js";
24
- import { prettyPrint } from "../../../../core/NumberFormat.js";
25
- import { FPlusDebugMaterial } from "./materials/FPlusDebugMaterial.js";
26
- import { parseColor } from "../../../../core/color/ColorUtils.js";
27
- import { buildLightClusterWidget } from "./debug/buildLightClusterWidget.js";
28
- import domify from "../../../../view/DOM.js";
29
- import { createScreenGrid } from "./debug/createScreenGrid.js";
30
- import { createLayerSwitcher } from "./debug/createLayerSwitcher.js";
31
- import { FPlusStandardMaterial } from "./materials/FPlusStandardMaterial.js";
32
- import { LightManager } from "./LightManager.js";
33
- import ButtonView from "../../../../view/elements/button/ButtonView.js";
22
+ import { MouseEvents } from "../../../../input/devices/events/MouseEvents.js";
23
+ import { RingBuffer } from "../../../../../core/collection/RingBuffer.js";
24
+ import { query_bvh_frustum_from_objects } from "../query/query_bvh_frustum_from_objects.js";
25
+ import { prettyPrint } from "../../../../../core/NumberFormat.js";
26
+ import { FPlusDebugMaterial } from "../materials/FPlusDebugMaterial.js";
27
+ import { parseColor } from "../../../../../core/color/ColorUtils.js";
28
+ import { buildLightClusterWidget } from "../debug/buildLightClusterWidget.js";
29
+ import domify from "../../../../../view/DOM.js";
30
+ import { createScreenGrid } from "../debug/createScreenGrid.js";
31
+ import { createLayerSwitcher } from "../debug/createLayerSwitcher.js";
32
+ import { FPlusStandardMaterial } from "../materials/FPlusStandardMaterial.js";
33
+ import { LightManager } from "../LightManager.js";
34
+ import ButtonView from "../../../../../view/elements/button/ButtonView.js";
34
35
  import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
35
- import { traverseMaterialTextures } from "../../../asset/loaders/material/traverseMaterialTextures.js";
36
- import Vector3 from "../../../../core/geom/Vector3.js";
37
- import { MetricCollection } from "../../../development/performance/MetricCollection.js";
38
- import { MetricStatistics } from "../../../development/performance/MetricStatistics.js";
39
- import { SpotLight } from "./SpotLight.js";
40
- import { randomFloatBetween } from "../../../../core/math/random/randomFloatBetween.js";
41
- import Signal from "../../../../core/events/signal/Signal.js";
36
+ import { traverseMaterialTextures } from "../../../../asset/loaders/material/traverseMaterialTextures.js";
37
+ import Vector3 from "../../../../../core/geom/Vector3.js";
38
+ import { MetricCollection } from "../../../../development/performance/MetricCollection.js";
39
+ import { MetricStatistics } from "../../../../development/performance/MetricStatistics.js";
40
+ import { SpotLight } from "../model/SpotLight.js";
41
+ import { randomFloatBetween } from "../../../../../core/math/random/randomFloatBetween.js";
42
+ import Signal from "../../../../../core/events/signal/Signal.js";
42
43
  import SimplexNoise from "simplex-noise";
43
44
  import Stats from "three/examples/jsm/libs/stats.module.js";
44
- import { threeUpdateTransform } from "../../util/threeUpdateTransform.js";
45
+ import { threeUpdateTransform } from "../../../util/threeUpdateTransform.js";
46
+ import { Decal } from "../model/Decal.js";
47
+ import { mat4 } from "gl-matrix";
48
+ import { Sampler2D } from "../../../texture/sampler/Sampler2D.js";
49
+ import { makeHelperBoxGeometry } from "../../../../../editor/process/symbolic/makeHelperBoxGeometry.js";
50
+ import { array_copy } from "../../../../../core/collection/array/copyArray.js";
45
51
 
46
52
  const on_render = new Signal();
47
53
 
@@ -50,6 +56,7 @@ const lm = new LightManager();
50
56
  const camera = new PerspectiveCamera(30);
51
57
  camera.position.z = 1;
52
58
 
59
+ camera.layers.enable(1);
53
60
  camera.layers.enable(3);
54
61
  camera.layers.enable(4);
55
62
  // camera.layers.enable(1);
@@ -62,6 +69,7 @@ camera.updateProjectionMatrix();
62
69
  camera.updateMatrixWorld(true);
63
70
 
64
71
  // lm.setTileMapResolution(32,32,32);
72
+ // lm.setTileMapResolution(2, 2, 2);
65
73
  lm.setTileMapResolution(24, 14, 8);
66
74
  // lm.setTileMapResolution(16, 8, 10);
67
75
 
@@ -300,6 +308,41 @@ function addPointLight({
300
308
  }
301
309
  }
302
310
 
311
+ /**
312
+ *
313
+ * @param {number[]} position
314
+ * @param {number[]} scale
315
+ * @param {number[]} [rotation] Quaternion
316
+ * @param {Sampler2D} sampler
317
+ * @param {THREE.Scene} scene
318
+ * @param {LightManager} light_manager
319
+ */
320
+ function addDecal({
321
+ position,
322
+ scale,
323
+ rotation = [0, 0, 0, 1],
324
+ sampler,
325
+ scene,
326
+ light_manager
327
+ }) {
328
+ const decal = new Decal();
329
+
330
+ mat4.fromRotationTranslationScale(decal.transform, rotation, position, scale);
331
+ decal.texture_diffuse = sampler;
332
+
333
+ const vis = new LineSegments(makeHelperBoxGeometry(), new LineBasicMaterial({ color: 0xFFFFFF }));
334
+
335
+ vis.layers.set(1);
336
+
337
+ vis.matrixAutoUpdate = false;
338
+ vis.matrixWorldNeedsUpdate = false;
339
+ array_copy(decal.transform, 0, vis.matrixWorld.elements, 0, 16);
340
+
341
+ scene.add(vis);
342
+
343
+ light_manager.addLight(decal);
344
+ }
345
+
303
346
  const box_geometry = new TorusKnotBufferGeometry(1, 0.3, 128, 128);
304
347
  const debug_material = new FPlusDebugMaterial();
305
348
 
@@ -406,6 +449,35 @@ function prepare_scene_2() {
406
449
  camera.lookAt(0, 0, -5);
407
450
  }
408
451
 
452
+ function prepare_scene_decal_0() {
453
+ addPointLight({
454
+ position: [
455
+ 1.5, 0, -4
456
+ ], radius: 1.5, color: 0xFF0000, intensity: 1
457
+ }
458
+ );
459
+
460
+ const sampler = new Sampler2D(new Uint8Array([255, 255, 255, 255]), 4, 1, 1);
461
+ addDecal({
462
+ position: [
463
+ -1.5, 0, -4
464
+ ],
465
+ scale: [
466
+ 1.5, 1.5, 1.5
467
+ ],
468
+ sampler: sampler,
469
+ scene,
470
+ light_manager: lm
471
+ });
472
+
473
+ addKnot([0, 0, -5], 1, [0, 0, 0]);
474
+
475
+ camera.near = 1;
476
+ camera.far = 7;
477
+
478
+ camera.lookAt(0, 0, -5);
479
+ }
480
+
409
481
 
410
482
  function prepare_scene_5() {
411
483
 
@@ -760,6 +832,9 @@ function draw_camera_view_planes() {
760
832
  });
761
833
  }
762
834
 
835
+ // prepare_scene_2();
836
+ // prepare_scene_decal_0();
837
+ // prepare_scene_2();
763
838
  prepare_scene_0();
764
839
  animate();
765
840
 
@@ -28,6 +28,7 @@ export function query_bvh_frustum_from_texture(
28
28
 
29
29
  let stackPointer = 1;
30
30
  let result = 0;
31
+ let plane_address;
31
32
 
32
33
  /**
33
34
  * After performing empirical tests, stack-based depth-first traversal turns out faster than using a queue
@@ -55,9 +56,7 @@ export function query_bvh_frustum_from_texture(
55
56
  const n_y1 = data_view.getFloat32(node_address + 16);
56
57
  const n_z1 = data_view.getFloat32(node_address + 20);
57
58
 
58
- for (let j = 0; j < 6; j++) {
59
-
60
- const plane_address = j * 4;
59
+ for (plane_address = 0; plane_address < 24; plane_address += 4) {
61
60
 
62
61
  const plane_normal_x = planes[plane_address];
63
62
  const plane_normal_y = planes[plane_address + 1];
@@ -84,41 +83,51 @@ export function query_bvh_frustum_from_texture(
84
83
  const left_index = (node_index << 1) + 1;
85
84
  const right_index = left_index + 1;
86
85
 
87
- if (left_index < last_valid_index) {
88
- stack[stackPointer] = left_index;
89
- stackPointer++;
90
- }
91
-
86
+ // left node ends up on top of the stack, which aligns with the desired access sequence
92
87
  if (right_index < last_valid_index) {
93
- stack[stackPointer] = right_index;
94
- stackPointer++;
88
+ stack[stackPointer++] = right_index;
89
+ // micro-optimization, since we know that right node is valid and left appears before that, left is valid too
90
+ stack[stackPointer++] = left_index;
91
+ } else if (left_index < last_valid_index) {
92
+ stack[stackPointer++] = left_index;
95
93
  }
96
94
 
97
95
 
98
96
  } else {
99
97
  // leaf node
100
98
  const leaf_index = node_index - binary_node_count;
99
+
101
100
  const node_address = leaf_index * BVH_LEAF_NODE_SIZE + binary_node_count * BVH_BINARY_NODE_SIZE;
102
101
 
103
- const light_index = data_view.getUint32(node_address + 24);
102
+ const light_descriptor = data_view.getUint32(node_address + 24);
103
+
104
+ const light_type = light_descriptor & 3;
105
+ const light_texel_index = light_descriptor >> 2;
104
106
 
105
- const light_address = light_index * 8;
107
+ const light_address = light_texel_index * 4;
106
108
 
107
- // TODO figure out light type from address
109
+ if (light_type === 0) {
110
+ // Point light
108
111
 
112
+ const light_x = source_data[light_address];
113
+ const light_y = source_data[light_address + 1];
114
+ const light_z = source_data[light_address + 2];
109
115
 
110
- const light_x = source_data[light_address];
111
- const light_y = source_data[light_address + 1];
112
- const light_z = source_data[light_address + 2];
116
+ const radius = source_data[light_address + 3];
113
117
 
114
- const radius = source_data[light_address + 3];
118
+ if (!point_light_inside_volume(light_x, light_y, light_z, radius, points, planes)) {
119
+ continue;
120
+ }
121
+ } else if (light_type === 3) {
122
+ // decal
123
+ debugger;
115
124
 
116
- if (!point_light_inside_volume(light_x, light_y, light_z, radius, points, planes)) {
117
- continue;
125
+ } else {
126
+ throw new Error('Unsupported light type');
118
127
  }
119
128
 
120
129
  // write to output
121
- destination[destination_offset + result] = light_index;
130
+ destination[destination_offset + result] = light_descriptor;
122
131
 
123
132
  result++;
124
133
  }
@@ -14,4 +14,6 @@ export class IncrementalDeltaSet<T> {
14
14
  initializeUpdate(): void
15
15
 
16
16
  finalizeUpdate(): void
17
+
18
+ sort(f: (T) => number, ctx?: any): void
17
19
  }
@@ -74,6 +74,7 @@ export class IncrementalDeltaSet {
74
74
  *
75
75
  * @param {function(T):number} score_function
76
76
  * @param {*} [score_context]
77
+ * @returns {void}
77
78
  */
78
79
  sort(score_function, score_context) {
79
80
  arrayQuickSort(this.elements, score_function, score_context, 0, this.size - 1);
@@ -0,0 +1,19 @@
1
+ export class AbstractTextureAtlas {
2
+ /**
3
+ *
4
+ * @param {Sampler2D} sampler
5
+ * @returns {AtlasPatch}
6
+ */
7
+ add(sampler) {
8
+ throw new Error('Not Implemented');
9
+ }
10
+
11
+ /**
12
+ *
13
+ * @param {AtlasPatch} patch
14
+ * @returns {boolean}
15
+ */
16
+ remove(patch) {
17
+ throw new Error('Not Implemented')
18
+ }
19
+ }