@woosh/meep-engine 2.138.3 → 2.138.5

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 (52) hide show
  1. package/package.json +1 -1
  2. package/src/core/bvh2/bvh3/ebvh_build_hierarchy_radix.d.ts +13 -5
  3. package/src/core/bvh2/bvh3/ebvh_build_hierarchy_radix.d.ts.map +1 -1
  4. package/src/core/bvh2/bvh3/ebvh_build_hierarchy_radix.js +253 -280
  5. package/src/core/bvh2/bvh3/ebvh_update_hierarchy_bounds.js +1 -1
  6. package/src/core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.d.ts +31 -0
  7. package/src/core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.d.ts.map +1 -0
  8. package/src/core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js +101 -0
  9. package/src/core/cache/CacheV2.d.ts +6 -2
  10. package/src/core/cache/CacheV2.d.ts.map +1 -1
  11. package/src/core/cache/CacheV2.js +6 -2
  12. package/src/engine/EngineHarness.js +2 -2
  13. package/src/engine/ecs/renderable/RenderSystem.d.ts.map +1 -1
  14. package/src/engine/ecs/renderable/RenderSystem.js +6 -0
  15. package/src/engine/ecs/terrain/ecs/TerrainSystem.d.ts.map +1 -1
  16. package/src/engine/ecs/terrain/ecs/TerrainSystem.js +19 -0
  17. package/src/engine/graphics/ecs/camera/auto_set_camera_clipping_planes.d.ts +4 -1
  18. package/src/engine/graphics/ecs/camera/auto_set_camera_clipping_planes.d.ts.map +1 -1
  19. package/src/engine/graphics/ecs/camera/auto_set_camera_clipping_planes.js +121 -12
  20. package/src/engine/graphics/ecs/light/LightSystem.d.ts.map +1 -1
  21. package/src/engine/graphics/ecs/light/LightSystem.js +80 -18
  22. package/src/engine/graphics/ecs/light/shadow/compute_view_frustum_aabb_in_space.d.ts +14 -0
  23. package/src/engine/graphics/ecs/light/shadow/compute_view_frustum_aabb_in_space.d.ts.map +1 -0
  24. package/src/engine/graphics/ecs/light/shadow/compute_view_frustum_aabb_in_space.js +62 -0
  25. package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.d.ts +30 -0
  26. package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.d.ts.map +1 -0
  27. package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.js +97 -0
  28. package/src/engine/graphics/ecs/mesh/MeshSystem.d.ts.map +1 -1
  29. package/src/engine/graphics/ecs/mesh/MeshSystem.js +6 -0
  30. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts.map +1 -1
  31. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +6 -0
  32. package/src/engine/graphics/ecs/trail2d/Trail2DSystem.d.ts.map +1 -1
  33. package/src/engine/graphics/ecs/trail2d/Trail2DSystem.js +6 -0
  34. package/src/engine/graphics/ecs/water/WaterSystem.d.ts.map +1 -1
  35. package/src/engine/graphics/ecs/water/WaterSystem.js +6 -0
  36. package/src/engine/graphics/impostors/octahedral/prototypeBaker.js +7 -10
  37. package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderV0.d.ts.map +1 -1
  38. package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderV0.js +139 -57
  39. package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderWireframeV0.d.ts.map +1 -1
  40. package/src/engine/graphics/impostors/octahedral/shader/ImpostorShaderWireframeV0.js +123 -38
  41. package/src/engine/graphics/impostors/octahedral/util/makeImpostorAtlasPreview.d.ts +1 -1
  42. package/src/engine/graphics/impostors/octahedral/util/makeImpostorAtlasPreview.d.ts.map +1 -1
  43. package/src/engine/graphics/impostors/octahedral/util/makeImpostorAtlasPreview.js +7 -3
  44. package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.d.ts.map +1 -1
  45. package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.js +6 -0
  46. package/src/engine/graphics/render/layers/RenderLayer.d.ts +2 -0
  47. package/src/engine/graphics/render/layers/RenderLayer.d.ts.map +1 -1
  48. package/src/engine/graphics/render/layers/RenderLayer.js +14 -0
  49. package/src/engine/intelligence/mcts/MonteCarlo.js +1 -1
  50. package/src/engine/graphics/ecs/camera/FrustumProjector.d.ts +0 -14
  51. package/src/engine/graphics/ecs/camera/FrustumProjector.d.ts.map +0 -1
  52. package/src/engine/graphics/ecs/camera/FrustumProjector.js +0 -86
@@ -0,0 +1,97 @@
1
+ import {
2
+ clipping_volume_matrix4_project
3
+ } from "../../../../../core/geom/3d/frustum/clipping_volume_matrix4_project.js";
4
+ import { hexahedron_from_aabb } from "../../../../../core/geom/3d/frustum/hexahedron_from_aabb.js";
5
+
6
+ const scratch_local_planes = new Float32Array(24);
7
+ const scratch_world_planes = new Float32Array(24);
8
+ const scratch_range = { near: 0, far: 0 };
9
+
10
+ // Half-extent of the z range used for the caster query. We want any object in
11
+ // the column above the receivers regardless of how far it sits along the light
12
+ // direction, so the query volume is effectively unbounded in z; the BVH walk's
13
+ // AABB-vs-frustum test is happy with a wide-but-finite range and avoids
14
+ // infinities propagating through plane math.
15
+ const CASTER_QUERY_HALF_RANGE = 1e7;
16
+
17
+ /**
18
+ * Push the shadow camera's near plane back toward the light to include any
19
+ * occluder whose shadow would fall within the camera's x/y bounds, even when
20
+ * the occluder itself sits outside the main view frustum.
21
+ *
22
+ * Without this step the textbook "fit shadow camera to view frustum" leaves
23
+ * the near plane at the closest receiver — a brick floating just above the
24
+ * view frustum gets clipped out of the shadow map and casts no shadow on the
25
+ * ground below.
26
+ *
27
+ * Algorithm:
28
+ * 1. Take the shadow camera's existing left/right/top/bottom (already fit
29
+ * to receivers) as the x/y extents of a light-local query box. Extend z
30
+ * to a wide range so any caster along the light direction is captured.
31
+ * 2. Transform the 6 box planes to world space via the shadow camera's
32
+ * matrixWorld.
33
+ * 3. Walk every render layer's BVH through `compute_depth_range` against
34
+ * this world-space volume, measured along the shadow camera's view
35
+ * direction.
36
+ * 4. If the closest depth found is smaller than the camera's current near,
37
+ * replace near with it.
38
+ *
39
+ * Far is intentionally left alone: casters behind the farthest receiver (in
40
+ * light direction) can't shadow anything in the view.
41
+ *
42
+ * @param {THREE.OrthographicCamera} shadow_camera
43
+ * @param {RenderLayerManager} layers
44
+ */
45
+ export function extend_shadow_camera_near_for_casters(shadow_camera, layers) {
46
+ if (layers === null) {
47
+ return;
48
+ }
49
+
50
+ const x0 = shadow_camera.left;
51
+ const x1 = shadow_camera.right;
52
+ const y0 = shadow_camera.bottom;
53
+ const y1 = shadow_camera.top;
54
+
55
+ hexahedron_from_aabb(
56
+ scratch_local_planes, 0,
57
+ x0, y0, -CASTER_QUERY_HALF_RANGE,
58
+ x1, y1, CASTER_QUERY_HALF_RANGE
59
+ );
60
+
61
+ clipping_volume_matrix4_project(
62
+ scratch_world_planes, 0,
63
+ scratch_local_planes, 0,
64
+ 6,
65
+ shadow_camera.matrixWorld.elements
66
+ );
67
+
68
+ // Depth plane: world-space, normal along the shadow camera's view direction
69
+ // (-Z column of matrixWorld), passing through the camera position. A point's
70
+ // distance to this plane equals its depth in front of the camera.
71
+ const m = shadow_camera.matrixWorld.elements;
72
+ const nx = -m[8];
73
+ const ny = -m[9];
74
+ const nz = -m[10];
75
+ const plane_constant = -(nx * m[12] + ny * m[13] + nz * m[14]);
76
+
77
+ scratch_range.near = Number.POSITIVE_INFINITY;
78
+ scratch_range.far = Number.NEGATIVE_INFINITY;
79
+
80
+ layers.traverse((layer) => {
81
+ if (!layer.state.visible) {
82
+ return;
83
+ }
84
+
85
+ const compute = layer.compute_depth_range;
86
+
87
+ if (compute === null) {
88
+ return;
89
+ }
90
+
91
+ compute(scratch_range, scratch_world_planes, nx, ny, nz, plane_constant);
92
+ });
93
+
94
+ if (isFinite(scratch_range.near) && scratch_range.near < shadow_camera.near) {
95
+ shadow_camera.near = scratch_range.near;
96
+ }
97
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"MeshSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/mesh/MeshSystem.js"],"names":[],"mappings":"AA6BA;IAiZI;;;;;;;OAOG;IACH,kCANW,IAAI,uCAEJ,OAAO,GACL,OAAO,CAQnB;IA7ZD;;;;;OAKG;IACH,4BAwDC;IAjDG;;;;OAIG;IACH,iBAAsB;IAEtB,iDAAqC;IAErC,4DAEC;IAGD;;;OAGG;IACH,2BAAgC;IAEhC,sBAAwB;IAExB;;;OAGG;IACH,YAFU,MAAO,MAAO,aAAa,CAAC,CAAC,CAEnB;IAEpB,cAAwB;IAExB;;;OAGG;IACH,aAFU,cAAY,IAAI,CAEH;IAEvB;;;;OAIG;IACH,+BAAmC;IAEnC;;;;OAIG;IACH,qBAA6B;IAGjC;;;;;;OAMG;IACH,8BALW,MAAM,4DAGN,IAAI,QA+Bd;IAED,2CAuDC;IAED;;;;OAIG;IACH,gCAHoB,IAAI,QAAE,MAAM,+BA8C/B;IAED,4CAEC;IAED;;;;;OAKG;IACH,YAHW,IAAI,aADJ,SAAS,UAET,MAAM,QAkChB;IAED;;;;;OAKG;IACH,cAHW,IAAI,aADJ,SAAS,YAET,MAAM,QAmChB;IAED;;;;OAIG;IACH,gCAFW,IAAI,QA+Ed;IAED,6BAoBC;CAgBJ;uBAnbsB,wBAAwB;0BACrB,qCAAqC;iBAO/B,WAAW;4CAVC,uDAAuD;8BAJrE,iDAAiD;oBAE3D,kCAAkC"}
1
+ {"version":3,"file":"MeshSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/mesh/MeshSystem.js"],"names":[],"mappings":"AA8BA;IAsZI;;;;;;;OAOG;IACH,kCANW,IAAI,uCAEJ,OAAO,GACL,OAAO,CAQnB;IAlaD;;;;;OAKG;IACH,4BAwDC;IAjDG;;;;OAIG;IACH,iBAAsB;IAEtB,iDAAqC;IAErC,4DAEC;IAGD;;;OAGG;IACH,2BAAgC;IAEhC,sBAAwB;IAExB;;;OAGG;IACH,YAFU,MAAO,MAAO,aAAa,CAAC,CAAC,CAEnB;IAEpB,cAAwB;IAExB;;;OAGG;IACH,aAFU,cAAY,IAAI,CAEH;IAEvB;;;;OAIG;IACH,+BAAmC;IAEnC;;;;OAIG;IACH,qBAA6B;IAGjC;;;;;;OAMG;IACH,8BALW,MAAM,4DAGN,IAAI,QA+Bd;IAED,2CA4DC;IAED;;;;OAIG;IACH,gCAHoB,IAAI,QAAE,MAAM,+BA8C/B;IAED,4CAEC;IAED;;;;;OAKG;IACH,YAHW,IAAI,aADJ,SAAS,UAET,MAAM,QAkChB;IAED;;;;;OAKG;IACH,cAHW,IAAI,aADJ,SAAS,YAET,MAAM,QAmChB;IAED;;;;OAIG;IACH,gCAFW,IAAI,QA+Ed;IAED,6BAoBC;CAgBJ;uBAxbsB,wBAAwB;0BACrB,qCAAqC;iBAO/B,WAAW;4CAVC,uDAAuD;8BAJrE,iDAAiD;oBAE3D,kCAAkC"}
@@ -1,6 +1,7 @@
1
1
  import { BoxBufferGeometry, MeshLambertMaterial } from "three";
2
2
  import { assert } from "../../../../core/assert.js";
3
3
  import { BVH } from "../../../../core/bvh2/bvh3/BVH.js";
4
+ import { bvh_query_depth_range_in_frustum } from "../../../../core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js";
4
5
  import { SignalBinding } from "../../../../core/events/signal/SignalBinding.js";
5
6
 
6
7
  import Vector3 from "../../../../core/geom/Vector3.js";
@@ -157,6 +158,11 @@ export class MeshSystem extends System {
157
158
  }
158
159
  )
159
160
 
161
+ const bvh = this.__bvh_binary;
162
+ this.renderLayer.compute_depth_range = (result, frustum, nx, ny, nz, c) => {
163
+ bvh_query_depth_range_in_frustum(result, bvh, frustum, nx, ny, nz, c);
164
+ };
165
+
160
166
  const visibleSet = this.renderLayer.visibleSet;
161
167
 
162
168
  visibleSet.onAdded.add(m => {
@@ -1 +1 @@
1
- {"version":3,"file":"ShadedGeometrySystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js"],"names":[],"mappings":"AA6DA;IACI;;;OAGG;IACH,4BAmEC;IAjEG,2DAA+C;IAE/C;;;;OAIG;IACH,iBAAsB;IAEtB;;;;OAIG;IACH,uBAA0B;IAE1B;;;;OAIG;IACH,wBAAgC;IAEhC;;;;OAIG;IACH,4BAAoC;IAEpC;;;;OAIG;IACH,kCAA0C;IAE1C;;;;OAIG;IACH,qBAA6B;IAI7B,0BAYE;IAEF,yBAIC;IAIL;;;OAGG;IACH,eAEC;IAED;;;OAGG;IACH,4BAFa,IAAI,MAAM,EAAC,MAAM,CAAC,CAI9B;IAED;;;;OAIG;IACH,+BAHW,MAAM,+CAsBhB;IAED;;;;OAIG;IACH,iCAHW,MAAM,GACL,OAAO,CAmBlB;IAED;;;;OAIG;IACH,4BASC;IAED;;;;OAIG;IACH,8BAMC;IAED,2CAgCC;IAED,4CAcC;IAED;;;;;OAKG;IACH,SAJW,cAAc,KACd,SAAS,UACT,MAAM,QAqBhB;IAED;;;;;OAKG;IACH,WAJW,cAAc,KACd,SAAS,UACT,MAAM,QAsBhB;IAED;;;;;;OAMG;IACH,4BALW,MAAM,EAAE,iBACR,MAAM,UACN,MAAM,EAAE,GAAC,UAAU,MAAM,CAAC,GACxB,MAAM,CAQlB;IAED;;;;;;;;;;;OAWG;IACH,kBAVW,MAAM,YACN,MAAM,YACN,MAAM,eACN,MAAM,eACN,MAAM,eACN,MAAM,uEAGJ;QAAC,MAAM,EAAC,MAAM,CAAC;QAAC,IAAI,EAAC,cAAc,CAAC;QAAC,OAAO,EAAE,aAAa,CAAA;KAAC,EAAE,CA8D1E;IAGD;;;;;;;;;;;;OAYG;IACH,wBAXW,aAAa,YACb,MAAM,YACN,MAAM,YACN,MAAM,eACN,MAAM,eACN,MAAM,eACN,MAAM,uEAGJ;QAAC,MAAM,EAAC,MAAM,CAAC;QAAC,IAAI,EAAC,cAAc,CAAA;KAAC,GAAC,SAAS,CAmF1D;CACJ;uBAxfsB,wBAAwB;0BACrB,qCAAqC;+BAGhC,qBAAqB;iBARnC,uCAAuC;oBAXpC,mCAAmC;2BAO5B,yCAAyC;8BAEtC,2CAA2C"}
1
+ {"version":3,"file":"ShadedGeometrySystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js"],"names":[],"mappings":"AA8DA;IACI;;;OAGG;IACH,4BAmEC;IAjEG,2DAA+C;IAE/C;;;;OAIG;IACH,iBAAsB;IAEtB;;;;OAIG;IACH,uBAA0B;IAE1B;;;;OAIG;IACH,wBAAgC;IAEhC;;;;OAIG;IACH,4BAAoC;IAEpC;;;;OAIG;IACH,kCAA0C;IAE1C;;;;OAIG;IACH,qBAA6B;IAI7B,0BAYE;IAEF,yBAIC;IAIL;;;OAGG;IACH,eAEC;IAED;;;OAGG;IACH,4BAFa,IAAI,MAAM,EAAC,MAAM,CAAC,CAI9B;IAED;;;;OAIG;IACH,+BAHW,MAAM,+CAsBhB;IAED;;;;OAIG;IACH,iCAHW,MAAM,GACL,OAAO,CAmBlB;IAED;;;;OAIG;IACH,4BASC;IAED;;;;OAIG;IACH,8BAMC;IAED,2CAqCC;IAED,4CAcC;IAED;;;;;OAKG;IACH,SAJW,cAAc,KACd,SAAS,UACT,MAAM,QAqBhB;IAED;;;;;OAKG;IACH,WAJW,cAAc,KACd,SAAS,UACT,MAAM,QAsBhB;IAED;;;;;;OAMG;IACH,4BALW,MAAM,EAAE,iBACR,MAAM,UACN,MAAM,EAAE,GAAC,UAAU,MAAM,CAAC,GACxB,MAAM,CAQlB;IAED;;;;;;;;;;;OAWG;IACH,kBAVW,MAAM,YACN,MAAM,YACN,MAAM,eACN,MAAM,eACN,MAAM,eACN,MAAM,uEAGJ;QAAC,MAAM,EAAC,MAAM,CAAC;QAAC,IAAI,EAAC,cAAc,CAAC;QAAC,OAAO,EAAE,aAAa,CAAA;KAAC,EAAE,CA8D1E;IAGD;;;;;;;;;;;;OAYG;IACH,wBAXW,aAAa,YACb,MAAM,YACN,MAAM,YACN,MAAM,eACN,MAAM,eACN,MAAM,eACN,MAAM,uEAGJ;QAAC,MAAM,EAAC,MAAM,CAAC;QAAC,IAAI,EAAC,cAAc,CAAA;KAAC,GAAC,SAAS,CAmF1D;CACJ;uBA7fsB,wBAAwB;0BACrB,qCAAqC;+BAGhC,qBAAqB;iBARnC,uCAAuC;oBAZpC,mCAAmC;2BAQ5B,yCAAyC;8BAEtC,2CAA2C"}
@@ -1,6 +1,7 @@
1
1
  import { mat4 } from "gl-matrix";
2
2
  import { assert } from "../../../../core/assert.js";
3
3
  import { BVH } from "../../../../core/bvh2/bvh3/BVH.js";
4
+ import { bvh_query_depth_range_in_frustum } from "../../../../core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js";
4
5
  import { bvh_query_leaves_generic } from "../../../../core/bvh2/bvh3/query/bvh_query_leaves_generic.js";
5
6
  import {
6
7
  bvh_query_user_data_overlaps_frustum
@@ -256,6 +257,11 @@ export class ShadedGeometrySystem extends System {
256
257
  return ctx.collect(destination, destination_offset, graphics.renderer, view, this.__bvh_binary, ecd);
257
258
  });
258
259
 
260
+ const bvh = this.__bvh_binary;
261
+ this.__render_layer.compute_depth_range = (result, frustum, nx, ny, nz, c) => {
262
+ bvh_query_depth_range_in_frustum(result, bvh, frustum, nx, ny, nz, c);
263
+ };
264
+
259
265
  this.__optimization_task.state.set(TaskState.INITIAL);
260
266
  engine.executor.run(this.__optimization_task);
261
267
 
@@ -1 +1 @@
1
- {"version":3,"file":"Trail2DSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/trail2d/Trail2DSystem.js"],"names":[],"mappings":";AAyBA;IAkCI;;;OAGG;IACH,4BA4BC;IAjED,oDAAoC;IAEpC,+DAEE;IAEF;;;OAGG;IACH,WAFU,4BAA4B,CAES;IAE/C;;;;OAIG;IACH,wBAAiC;IAGjC;;;;OAIG;IACH,oBAAgB;IAEhB;;;OAGG;IACH,YAAgB;IAcZ;;;;OAIG;IACH,iBAAsB;IAEtB;;;OAGG;IACH,UAFU,cAAc,CAEO;IAE/B;;;OAGG;IACH,aAFU,cAAY,IAAI,CAEH;IAK3B,2CAcC;IAED,4CAIC;IAED;;;;;OAKG;IACH,sBAoDC;IAED;;;;;OAKG;IACH,YAHW,OAAO,aADP,SAAS,YAET,MAAM,QAahB;IAED;;;;;OAKG;IACH,kBAJW,OAAO,aACP,SAAS,UACT,MAAM,QAShB;IAED;;;;OAIG;IACH,yBAHW,OAAO,aACP,SAAS,QAoCnB;IAED,6BAWC;CACJ;uBA/PsB,wBAAwB;0BACrB,qCAAqC;oBAY3C,cAAc;4CAdU,uDAAuD;6CAYtD,yDAAyD;+BARvE,yBAAyB"}
1
+ {"version":3,"file":"Trail2DSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/trail2d/Trail2DSystem.js"],"names":[],"mappings":";AA0BA;IAkCI;;;OAGG;IACH,4BA4BC;IAjED,oDAAoC;IAEpC,+DAEE;IAEF;;;OAGG;IACH,WAFU,4BAA4B,CAES;IAE/C;;;;OAIG;IACH,wBAAiC;IAGjC;;;;OAIG;IACH,oBAAgB;IAEhB;;;OAGG;IACH,YAAgB;IAcZ;;;;OAIG;IACH,iBAAsB;IAEtB;;;OAGG;IACH,UAFU,cAAc,CAEO;IAE/B;;;OAGG;IACH,aAFU,cAAY,IAAI,CAEH;IAK3B,2CAmBC;IAED,4CAIC;IAED;;;;;OAKG;IACH,sBAoDC;IAED;;;;;OAKG;IACH,YAHW,OAAO,aADP,SAAS,YAET,MAAM,QAahB;IAED;;;;;OAKG;IACH,kBAJW,OAAO,aACP,SAAS,UACT,MAAM,QAShB;IAED;;;;OAIG;IACH,yBAHW,OAAO,aACP,SAAS,QAoCnB;IAED,6BAWC;CACJ;uBApQsB,wBAAwB;0BACrB,qCAAqC;oBAY3C,cAAc;4CAdU,uDAAuD;6CAYtD,yDAAyD;+BARvE,yBAAyB"}
@@ -1,5 +1,6 @@
1
1
  import { assert } from "../../../../core/assert.js";
2
2
  import { BVH } from "../../../../core/bvh2/bvh3/BVH.js";
3
+ import { bvh_query_depth_range_in_frustum } from "../../../../core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js";
3
4
  import Vector3 from '../../../../core/geom/Vector3.js';
4
5
  import { clamp } from "../../../../core/math/clamp.js";
5
6
  import { max2 } from "../../../../core/math/max2.js";
@@ -104,6 +105,11 @@ class Trail2DSystem extends System {
104
105
  }
105
106
  );
106
107
 
108
+ const bvh = this.bvh;
109
+ this.renderLayer.compute_depth_range = (result, frustum, nx, ny, nz, c) => {
110
+ bvh_query_depth_range_in_frustum(result, bvh, frustum, nx, ny, nz, c);
111
+ };
112
+
107
113
  this.__ribbon_plugin = await this.__engine.plugins.acquire(RibbonXPlugin);
108
114
  }
109
115
 
@@ -1 +1 @@
1
- {"version":3,"file":"WaterSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/water/WaterSystem.js"],"names":[],"mappings":";AAYA;IAyBI;;;;OAIG;IACH,sCAYC;IAzCD,+BAAuB;IAEvB;;;OAGG;IACH,cAFU,GAAG,CAEG;IAGhB,cAAY;IAEZ;;;OAGG;IACH,aAFU,KAAK,EAAE,CAEA;IAEjB;;;;OAIG;IACH,qBAAiB;IAWb,+BAA8B;IAE9B;;;OAGG;IACH,aAFU,cAAY,IAAI,CAEH;IAK3B,4CAMC;IAED,2CA4DC;IAED;;;;OAIG;IACH,gBAHW,KAAK,UACL,MAAM,QAsDhB;IAED;;;;OAIG;IACH,kBAHW,KAAK,UACL,MAAM,QAgBhB;IAED,2BAgCC;IAED;;;;;OAKG;IACH,0BAUC;IAED,6BAcC;CACJ;;;;uBA/QsB,wBAAwB;kBAM7B,YAAY;oBAPV,mCAAmC"}
1
+ {"version":3,"file":"WaterSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/water/WaterSystem.js"],"names":[],"mappings":";AAaA;IAyBI;;;;OAIG;IACH,sCAYC;IAzCD,+BAAuB;IAEvB;;;OAGG;IACH,cAFU,GAAG,CAEG;IAGhB,cAAY;IAEZ;;;OAGG;IACH,aAFU,KAAK,EAAE,CAEA;IAEjB;;;;OAIG;IACH,qBAAiB;IAWb,+BAA8B;IAE9B;;;OAGG;IACH,aAFU,cAAY,IAAI,CAEH;IAK3B,4CAMC;IAED,2CAiEC;IAED;;;;OAIG;IACH,gBAHW,KAAK,UACL,MAAM,QAsDhB;IAED;;;;OAIG;IACH,kBAHW,KAAK,UACL,MAAM,QAgBhB;IAED,2BAgCC;IAED;;;;;OAKG;IACH,0BAUC;IAED,6BAcC;CACJ;;;;uBApRsB,wBAAwB;kBAM7B,YAAY;oBARV,mCAAmC"}
@@ -1,6 +1,7 @@
1
1
  import { BackSide, PlaneBufferGeometry } from 'three';
2
2
  import { assert } from "../../../../core/assert.js";
3
3
  import { BVH } from "../../../../core/bvh2/bvh3/BVH.js";
4
+ import { bvh_query_depth_range_in_frustum } from "../../../../core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js";
4
5
  import { System } from '../../../ecs/System.js';
5
6
  import { obtainTerrain } from "../../../ecs/terrain/util/obtainTerrain.js";
6
7
  import { make_bvh_visibility_builder } from "../../render/make_bvh_visibility_builder.js";
@@ -90,6 +91,11 @@ class WaterSystem extends System {
90
91
  }
91
92
  )
92
93
 
94
+ const bvh = this.bvh;
95
+ this.renderLayer.compute_depth_range = (result, frustum, nx, ny, nz, c) => {
96
+ bvh_query_depth_range_in_frustum(result, bvh, frustum, nx, ny, nz, c);
97
+ };
98
+
93
99
 
94
100
  const self = this;
95
101
 
@@ -39,14 +39,11 @@ async function main(engine) {
39
39
  enableWater: false,
40
40
  cameraFieldOfView: 45,
41
41
  showFps: false,
42
- enableLights: false
42
+ enableLights: true,
43
+ enableShadows: true,
44
+ cameraAutoClip: true,
43
45
  });
44
46
 
45
- await EngineHarness.buildLights({
46
- engine,
47
- sunIntensity: 0,
48
- ambientIntensity: 1
49
- });
50
47
 
51
48
  const ecd = engine.entityManager.dataset;
52
49
 
@@ -75,7 +72,7 @@ async function main(engine) {
75
72
  // console.profile('bake');
76
73
  const id = baker.bake({
77
74
  objects,
78
- frames: 8,
75
+ frames: 32,
79
76
  resolution: 1024,
80
77
  type: ImpostorCaptureType.FullSphere
81
78
  });
@@ -86,7 +83,7 @@ async function main(engine) {
86
83
  const ctrl = makeImpostorAtlasPreview({
87
84
  impostor: id,
88
85
  renderer,
89
- mode: 'diffuse'
86
+ mode: 'albedo'
90
87
  });
91
88
 
92
89
  ctrl.scale.setScalar(1);
@@ -119,8 +116,8 @@ async function main(engine) {
119
116
 
120
117
  const sg_mesh = SGMesh.fromURL(path);
121
118
 
122
- sg_mesh.castShadow = false;
123
- sg_mesh.receiveShadow = false;
119
+ sg_mesh.castShadow = true;
120
+ sg_mesh.receiveShadow = true;
124
121
 
125
122
  const entity_true_mesh = new Entity();
126
123
  entity_true_mesh
@@ -1 +1 @@
1
- {"version":3,"file":"ImpostorShaderV0.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/graphics/impostors/octahedral/shader/ImpostorShaderV0.js"],"names":[],"mappings":"AA+TA;IACI,cAmEC;IAHG,4CAAyB;CAIhC;kCA5XM,OAAO"}
1
+ {"version":3,"file":"ImpostorShaderV0.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/graphics/impostors/octahedral/shader/ImpostorShaderV0.js"],"names":[],"mappings":"AAiZA;IACI,cAmEC;IAHG,4CAAyB;CAIhC;kCA9cM,OAAO"}
@@ -22,25 +22,42 @@ const shader_vx = `
22
22
  // tangent-space parallax computation in the fragment shader.
23
23
  out vec3 vViewPos;
24
24
 
25
- // Octahedral atlas frame indices and triangle interpolation weights are
26
- // chosen once per-impostor and forwarded as flat varyings so every
27
- // fragment samples the same 3 atlas frames (without this, a perspective
28
- // camera could flip the chosen frame across the card and produce
29
- // visible seams).
25
+ // The 4 atlas frames at the corners of the current grid cell are chosen
26
+ // once per-impostor and forwarded as flat varyings so every fragment
27
+ // samples the same set (without this, a perspective camera could flip
28
+ // the chosen frames across the card and produce visible seams).
29
+ //
30
+ // We use bilinear interpolation over a full 2x2 cell, not a triangle
31
+ // interpolation over 3 corners. Triangle interpolation has a
32
+ // C1-discontinuous "diagonal switch" where one of the three contributing
33
+ // frames swaps between (gridFloor+(1,0)) and (gridFloor+(0,1)); even
34
+ // though the swap happens at zero weight (so the result is C0), the
35
+ // weight DERIVATIVE jumps, which the eye perceives as a snap inside the
36
+ // cell. Bilinear has no such switch — all 4 corners always contribute
37
+ // with weights that are smooth products of fract(grid).
30
38
  flat out vec2 vGridFloor;
31
- flat out vec4 vWeights;
39
+ flat out vec4 vWeights; // (w00, w10, w01, w11)
32
40
 
33
41
  // Card's TBN basis in view space. The card is oriented so its NORMAL
34
- // points along the weighted blend of the 3 nearest baked view
35
- // directions, and TANGENT/BINORMAL line up with the bake camera's
36
- // right/up at bake time — i.e. with the texture's X/Y axes. This is
37
- // what makes the depth field (which is perpendicular to the bake
38
- // direction) usable as a tangent-space height map. flat because the
39
- // basis is the same for every vertex of the card.
42
+ // points along the weighted blend of the 4 nearest baked view
43
+ // directions, and TANGENT/BINORMAL line up with the *blended* bake
44
+ // camera's right/up. Used by the fragment shader to transform the
45
+ // view-space view-dir into the card's tangent frame.
40
46
  flat out vec3 vTangent;
41
47
  flat out vec3 vBinormal;
42
48
  flat out vec3 vNormal;
43
49
 
50
+ // Per-frame card-UV -> texture-UV rotation matrices, one per cell
51
+ // corner. Each frame was baked with its own camera right/up (from
52
+ // three.js Camera.lookAt with up=(0,1,0)); near the octahedral pole
53
+ // those right-axes can swing 90° or more between adjacent frames.
54
+ // These matrices rotate the sample-UV into each frame's bake-camera
55
+ // basis so the four corners line up consistently when blended.
56
+ flat out vec4 vFrameXform00;
57
+ flat out vec4 vFrameXform10;
58
+ flat out vec4 vFrameXform01;
59
+ flat out vec4 vFrameXform11;
60
+
44
61
  uniform mat4 modelViewMatrix;
45
62
  uniform mat4 projectionMatrix;
46
63
 
@@ -130,19 +147,41 @@ const shader_vx = `
130
147
  return normalize(GridToVector(f));
131
148
  }
132
149
 
133
- vec4 TriangleInterpolate(vec2 frac_uv)
150
+ // Build the 2x2 matrix that maps card-centred UV (vUv - 0.5) into the
151
+ // texture-centred UV of a single baked frame. The matrix is just the
152
+ // (tangent_OS, binormal_OS) basis expressed in the frame's own
153
+ // (bake_right, bake_up) basis — i.e. how a step along the card's local
154
+ // axes shows up in the texture the frame was rendered into.
155
+ //
156
+ // bake_right/bake_up follow three.js Camera.lookAt with up=(0,1,0).
157
+ // We mirror its polar nudge so our shader basis matches what the
158
+ // baker actually used when D_frame is parallel to up.
159
+ vec4 ComputeFrameXform(vec3 D_frame, vec3 tangent_OS, vec3 binormal_OS)
160
+ {
161
+ vec3 D = abs(D_frame.y) > 0.99999
162
+ ? normalize(D_frame + vec3(0.0, 0.0, 0.0001))
163
+ : D_frame;
164
+ vec3 bake_right = normalize(cross(vec3(0.0, 1.0, 0.0), D));
165
+ vec3 bake_up = cross(D, bake_right);
166
+ return vec4(
167
+ dot(tangent_OS, bake_right),
168
+ dot(binormal_OS, bake_right),
169
+ dot(tangent_OS, bake_up),
170
+ dot(binormal_OS, bake_up)
171
+ );
172
+ }
173
+
174
+ // Bilinear weights over the 4 corners of the current cell, in the
175
+ // order (w00, w10, w01, w11) matching gridFloor + (0,0)/(1,0)/(0,1)/(1,1).
176
+ vec4 BilinearWeights(vec2 frac_uv)
134
177
  {
135
178
  vec2 omuv = vec2(1.0) - frac_uv;
136
- vec4 res;
137
- // frame 0 weight (corner (0,0) of the quad)
138
- res.x = min(omuv.x, omuv.y);
139
- // frame 1 weight (off-diagonal corner — picked by res.w)
140
- res.y = abs(frac_uv.x - frac_uv.y);
141
- // frame 2 weight (corner (1,1) of the quad)
142
- res.z = min(frac_uv.x, frac_uv.y);
143
- // triangle-half mask: 1 in the lower-right half, 0 in the upper-left
144
- res.w = clamp(ceil(frac_uv.x - frac_uv.y), 0.0, 1.0);
145
- return res;
179
+ return vec4(
180
+ omuv.x * omuv.y, // w00
181
+ frac_uv.x * omuv.y, // w10
182
+ omuv.x * frac_uv.y, // w01
183
+ frac_uv.x * frac_uv.y // w11
184
+ );
146
185
  }
147
186
 
148
187
  void main() {
@@ -159,25 +198,28 @@ const shader_vx = `
159
198
  vec2 framesMinusOne = vec2(uFrames - 1.0);
160
199
  vec2 octahedral_uv = clamp(VectorToGrid(pivotToCameraRay) * 0.5 + 0.5, 0.0, 1.0);
161
200
  vec2 grid = octahedral_uv * framesMinusOne;
162
- vec2 gridFloor = floor(grid);
163
- vec4 weights = TriangleInterpolate(fract(grid));
201
+ // Clamp gridFloor so the +1 corners never reference past the last
202
+ // valid frame index when grid is at the upper edge.
203
+ vec2 gridFloor = min(floor(grid), framesMinusOne - 1.0);
204
+ vec4 weights = BilinearWeights(grid - gridFloor);
164
205
 
165
206
  vGridFloor = gridFloor;
166
207
  vWeights = weights;
167
208
 
168
- // 2. Decode each of the 3 chosen frame indices back into the
169
- // bake-time view direction, then blend with the triangle weights.
209
+ // 2. Decode each of the 4 cell-corner frame indices back into its
210
+ // bake-time view direction, then blend with the bilinear weights.
170
211
  // projectedRay is the "effective" baked view direction the card
171
212
  // is showing — the direction the depth and colour textures we're
172
213
  // blending were captured along.
173
- vec2 frame0 = gridFloor;
174
- vec2 frame1 = gridFloor + mix(vec2(0.0, 1.0), vec2(1.0, 0.0), weights.w);
175
- vec2 frame2 = gridFloor + vec2(1.0, 1.0);
176
- vec3 ray0 = FrameToRay(frame0, framesMinusOne);
177
- vec3 ray1 = FrameToRay(frame1, framesMinusOne);
178
- vec3 ray2 = FrameToRay(frame2, framesMinusOne);
214
+ vec3 ray00 = FrameToRay(gridFloor + vec2(0.0, 0.0), framesMinusOne);
215
+ vec3 ray10 = FrameToRay(gridFloor + vec2(1.0, 0.0), framesMinusOne);
216
+ vec3 ray01 = FrameToRay(gridFloor + vec2(0.0, 1.0), framesMinusOne);
217
+ vec3 ray11 = FrameToRay(gridFloor + vec2(1.0, 1.0), framesMinusOne);
179
218
  vec3 projectedRay = normalize(
180
- ray0 * weights.x + ray1 * weights.y + ray2 * weights.z
219
+ ray00 * weights.x +
220
+ ray10 * weights.y +
221
+ ray01 * weights.z +
222
+ ray11 * weights.w
181
223
  );
182
224
 
183
225
  // 3. Build the card's TBN in object-local space.
@@ -224,6 +266,13 @@ const shader_vx = `
224
266
  vTangent = normalize(m3 * tangent_OS);
225
267
  vBinormal = normalize(m3 * binormal_OS);
226
268
  vNormal = normalize(m3 * normal_OS);
269
+
270
+ // 6. Per-frame UV rotation matrices. ComputeFrameXform handles the
271
+ // polar-singularity nudge in three.js's lookAt internally.
272
+ vFrameXform00 = ComputeFrameXform(ray00, tangent_OS, binormal_OS);
273
+ vFrameXform10 = ComputeFrameXform(ray10, tangent_OS, binormal_OS);
274
+ vFrameXform01 = ComputeFrameXform(ray01, tangent_OS, binormal_OS);
275
+ vFrameXform11 = ComputeFrameXform(ray11, tangent_OS, binormal_OS);
227
276
  }
228
277
  `;
229
278
  const shader_fg = `
@@ -233,20 +282,25 @@ const shader_fg = `
233
282
  in vec2 vUv;
234
283
  in vec3 vViewPos;
235
284
 
236
- // Frame indices + triangle weights are computed per-impostor in the
237
- // vertex shader. flat = no interpolation; every fragment sees the same
238
- // values and samples the same 3 atlas frames.
285
+ // Cell base + bilinear weights for the 4 corners (w00, w10, w01, w11),
286
+ // computed per-impostor in the vertex shader. flat = no interpolation.
239
287
  flat in vec2 vGridFloor;
240
288
  flat in vec4 vWeights;
241
289
 
242
- // Card's TBN in view space. The card is no longer view-aligned — it's
243
- // oriented perpendicular to the effective bake direction so we have
244
- // to convert the view-space view direction into this tangent frame
245
- // before doing parallax.
290
+ // Card's TBN in view space (perpendicular to the effective bake
291
+ // direction). Used to express the view direction in the card's tangent
292
+ // frame for parallax.
246
293
  flat in vec3 vTangent;
247
294
  flat in vec3 vBinormal;
248
295
  flat in vec3 vNormal;
249
296
 
297
+ // Per-frame 2x2 rotation matrices (a, b, c, d) that map card-centred
298
+ // UV into each frame's bake-camera basis. Each cell corner has its own.
299
+ flat in vec4 vFrameXform00;
300
+ flat in vec4 vFrameXform10;
301
+ flat in vec4 vFrameXform01;
302
+ flat in vec4 vFrameXform11;
303
+
250
304
  out vec4 color_out;
251
305
 
252
306
  uniform sampler2D tBase;
@@ -254,25 +308,45 @@ const shader_fg = `
254
308
  uniform float uFrames;
255
309
  uniform float uDepthScale;
256
310
 
257
- // Sample the same within-frame UV from the three chosen atlas frames and
258
- // blend with the triangle weights from the vertex shader. Used for both
259
- // depth and colour.
260
- vec4 blend_3_frames(sampler2D tex, vec2 frame_uv, vec2 f0, vec2 f1, vec2 f2, vec4 w)
311
+ // Apply a per-frame 2x2 rotation matrix to a card UV, rotating around
312
+ // the texture centre (0.5, 0.5). xform = (a, b, c, d) packs row-major
313
+ // [a b ; c d].
314
+ vec2 apply_frame_xform(vec2 card_uv, vec4 xform)
261
315
  {
316
+ vec2 c = card_uv - 0.5;
317
+ return vec2(
318
+ xform.x * c.x + xform.y * c.y,
319
+ xform.z * c.x + xform.w * c.y
320
+ ) + 0.5;
321
+ }
322
+
323
+ // Sample the same card-UV from the 4 cell-corner atlas frames, applying
324
+ // each frame's own UV rotation so the textures land in a consistent
325
+ // orientation, then blend with the bilinear weights. Used for both
326
+ // depth and colour.
327
+ vec4 blend_4_frames(
328
+ sampler2D tex, vec2 card_uv,
329
+ vec2 gridFloor, vec4 w,
330
+ vec4 x00, vec4 x10, vec4 x01, vec4 x11
331
+ ) {
262
332
  vec2 frame_size = vec2(1.0 / uFrames);
263
- vec4 s0 = texture(tex, (f0 + frame_uv) * frame_size);
264
- vec4 s1 = texture(tex, (f1 + frame_uv) * frame_size);
265
- vec4 s2 = texture(tex, (f2 + frame_uv) * frame_size);
266
- return s0 * w.x + s1 * w.y + s2 * w.z;
333
+ // Clamp inside the unit square AFTER the per-frame rotation: at
334
+ // sharp angles the rotation can push a corner UV outside [0,1] and
335
+ // bleed into the neighbouring atlas tile (which is a completely
336
+ // different bake direction). Clamping keeps the sample inside the
337
+ // frame it's supposed to belong to.
338
+ vec2 uv00 = clamp(apply_frame_xform(card_uv, x00), 0.0, 1.0);
339
+ vec2 uv10 = clamp(apply_frame_xform(card_uv, x10), 0.0, 1.0);
340
+ vec2 uv01 = clamp(apply_frame_xform(card_uv, x01), 0.0, 1.0);
341
+ vec2 uv11 = clamp(apply_frame_xform(card_uv, x11), 0.0, 1.0);
342
+ vec4 s00 = texture(tex, (gridFloor + vec2(0.0, 0.0) + uv00) * frame_size);
343
+ vec4 s10 = texture(tex, (gridFloor + vec2(1.0, 0.0) + uv10) * frame_size);
344
+ vec4 s01 = texture(tex, (gridFloor + vec2(0.0, 1.0) + uv01) * frame_size);
345
+ vec4 s11 = texture(tex, (gridFloor + vec2(1.0, 1.0) + uv11) * frame_size);
346
+ return s00 * w.x + s10 * w.y + s01 * w.z + s11 * w.w;
267
347
  }
268
348
 
269
349
  void main() {
270
- // 3 nearest frames — flat from vertex shader, identical for every
271
- // fragment of this impostor card.
272
- vec2 frame0 = vGridFloor;
273
- vec2 frame1 = vGridFloor + mix(vec2(0.0, 1.0), vec2(1.0, 0.0), vWeights.w);
274
- vec2 frame2 = vGridFloor + vec2(1.0, 1.0);
275
-
276
350
  // View direction in the card's tangent space. The card is oriented
277
351
  // perpendicular to the effective bake direction, not view-aligned,
278
352
  // so we project the view-space view-dir onto the (T, B, N) basis we
@@ -299,7 +373,11 @@ const shader_fg = `
299
373
  // where V is the view direction in tangent space and h is the
300
374
  // surface height above the card plane.
301
375
  vec2 base_uv = vUv;
302
- float depth = blend_3_frames(tGeometry, base_uv, frame0, frame1, frame2, vWeights).a;
376
+ float depth = blend_4_frames(
377
+ tGeometry, base_uv,
378
+ vGridFloor, vWeights,
379
+ vFrameXform00, vFrameXform10, vFrameXform01, vFrameXform11
380
+ ).a;
303
381
  base_uv += (view_dir.xy / view_dir.z) * (depth - 0.5) * uDepthScale;
304
382
 
305
383
  // Keep the parallax-shifted sample inside the current frame's tile.
@@ -307,7 +385,11 @@ const shader_fg = `
307
385
  // neighbouring atlas frame (a completely different bake direction).
308
386
  base_uv = clamp(base_uv, 0.0, 1.0);
309
387
 
310
- vec4 texel_color = blend_3_frames(tBase, base_uv, frame0, frame1, frame2, vWeights);
388
+ vec4 texel_color = blend_4_frames(
389
+ tBase, base_uv,
390
+ vGridFloor, vWeights,
391
+ vFrameXform00, vFrameXform10, vFrameXform01, vFrameXform11
392
+ );
311
393
 
312
394
  if (texel_color.a <= 0.5) {
313
395
  discard;
@@ -1 +1 @@
1
- {"version":3,"file":"ImpostorShaderWireframeV0.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/graphics/impostors/octahedral/shader/ImpostorShaderWireframeV0.js"],"names":[],"mappings":"AAwEA;IACI,cA2DC;IAHG,4CAAyB;CAIhC;kCA7HM,OAAO"}
1
+ {"version":3,"file":"ImpostorShaderWireframeV0.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/graphics/impostors/octahedral/shader/ImpostorShaderWireframeV0.js"],"names":[],"mappings":"AA6JA;IACI,cA2DC;IAHG,4CAAyB;CAIhC;kCAlNM,OAAO"}