@woosh/meep-engine 2.133.3 → 2.133.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.
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "description": "Pure JavaScript game engine. Fully featured and production ready.",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.133.3",
8
+ "version": "2.133.5",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -89,6 +89,6 @@
89
89
  "typescript"
90
90
  ],
91
91
  "engines": {
92
- "node": ">=14"
92
+ "node": ">=24"
93
93
  }
94
94
  }
@@ -183,6 +183,12 @@ export class BitSet {
183
183
  * Sets all the bits in this BitSet to false.
184
184
  */
185
185
  reset(): void;
186
+ /**
187
+ * Number of set bits in this BitSet.
188
+ * Also known as "Hamming weight" or "population count".
189
+ * @returns {number}
190
+ */
191
+ cardinality(): number;
186
192
  /**
187
193
  * Copy contents of another bit set into this one
188
194
  * @param {BitSet} other
@@ -1 +1 @@
1
- {"version":3,"file":"BitSet.d.ts","sourceRoot":"","sources":["../../../../src/core/binary/BitSet.js"],"names":[],"mappings":"AAgCA;;;;;;;;;;;;;;GAcG;AACH;IAkjBI;;;;OAIG;IACH,oBAHW,MAAM,GACJ,MAAM,CAQlB;IA3jBD;;;OAGG;IACH,+BAFW,MAAM,EAgChB;IA3BG;;;;OAIG;IACH,iBAAiB;IAEjB;;;;;OAKG;IACH,mBAA4C;IAE5C;;;;OAIG;IACH,sBAA0D;IAE1D;;;OAGG;IACH,gBAFU,MAAM,CAE2B;IAG/C;;;;OAIG;IACH,iBAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,mBAFW,MAAM,QAOhB;IACD;;;;;;OAMG;IACH,uBAJW,MAAM,GAEJ,IAAI,CAUhB;IAED;;;;OAIG;IACH,QAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,YAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,iBAsBC;IAED;;;OAGG;IACH,uBAMC;IAED;;;;;OAKG;IACH,oBAyBC;IAED;;;;OAIG;IACH,2BAHW,MAAM,GACJ,MAAM,CAuClB;IAED;;;;OAIG;IACH,uBAHW,MAAM,GACJ,MAAM,CAuDlB;IAED;;;;OAIG;IACH,yBAHW,MAAM,GACJ,MAAM,CAkDlB;IAED;;;;;OAKG;IACH,eAJW,MAAM,SACN,OAAO,GACL,IAAI,CAmChB;IAED;;;OAGG;IACH,iBAFW,MAAM,QAIhB;IAED;;;;OAIG;IACH,sBAHW,MAAM,aACN,MAAM,QAWhB;IAED;;;;OAIG;IACH,wBAHW,MAAM,aACN,MAAM,QAShB;IAED;;;;OAIG;IACH,qBAFa,OAAO,CAkBnB;IAED;;;;OAIG;IACH,iBAHW,MAAM,GACJ,OAAO,CAUnB;IAED;;;;OAIG;IACH,mBAHW,MAAM,GACJ,OAAO,CAUnB;IAED;;;;;OAKG;IACH,sBAJW,MAAM,eACN,MAAM,aACN,MAAM,QAShB;IAED;;;;;OAKG;IACH,qBAJW,MAAM,eACN,MAAM,aACN,MAAM,QAShB;IAED;;;;;OAKG;IACH,gBAJW,MAAM,eACN,MAAM,aACN,MAAM,QAQhB;IAED;;OAEG;IACH,cAgBC;IAED;;;OAGG;IACH,YAFW,MAAM,QAoChB;CAcJ"}
1
+ {"version":3,"file":"BitSet.d.ts","sourceRoot":"","sources":["../../../../src/core/binary/BitSet.js"],"names":[],"mappings":"AAiCA;;;;;;;;;;;;;;GAcG;AACH;IAslBI;;;;OAIG;IACH,oBAHW,MAAM,GACJ,MAAM,CAQlB;IA/lBD;;;OAGG;IACH,+BAFW,MAAM,EAgChB;IA3BG;;;;OAIG;IACH,iBAAiB;IAEjB;;;;;OAKG;IACH,mBAA4C;IAE5C;;;;OAIG;IACH,sBAA0D;IAE1D;;;OAGG;IACH,gBAFU,MAAM,CAE2B;IAG/C;;;;OAIG;IACH,iBAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,mBAFW,MAAM,QAOhB;IACD;;;;;;OAMG;IACH,uBAJW,MAAM,GAEJ,IAAI,CAUhB;IAED;;;;OAIG;IACH,QAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,YAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,iBAsBC;IAED;;;OAGG;IACH,uBAMC;IAED;;;;;OAKG;IACH,oBAyBC;IAED;;;;OAIG;IACH,2BAHW,MAAM,GACJ,MAAM,CAuClB;IAED;;;;OAIG;IACH,uBAHW,MAAM,GACJ,MAAM,CAuDlB;IAED;;;;OAIG;IACH,yBAHW,MAAM,GACJ,MAAM,CAkDlB;IAED;;;;;OAKG;IACH,eAJW,MAAM,SACN,OAAO,GACL,IAAI,CAmChB;IAED;;;OAGG;IACH,iBAFW,MAAM,QAIhB;IAED;;;;OAIG;IACH,sBAHW,MAAM,aACN,MAAM,QAWhB;IAED;;;;OAIG;IACH,wBAHW,MAAM,aACN,MAAM,QAShB;IAED;;;;OAIG;IACH,qBAFa,OAAO,CAkBnB;IAED;;;;OAIG;IACH,iBAHW,MAAM,GACJ,OAAO,CAUnB;IAED;;;;OAIG;IACH,mBAHW,MAAM,GACJ,OAAO,CAUnB;IAED;;;;;OAKG;IACH,sBAJW,MAAM,eACN,MAAM,aACN,MAAM,QAShB;IAED;;;;;OAKG;IACH,qBAJW,MAAM,eACN,MAAM,aACN,MAAM,QAShB;IAED;;;;;OAKG;IACH,gBAJW,MAAM,eACN,MAAM,aACN,MAAM,QAQhB;IAED;;OAEG;IACH,cAgBC;IAED;;;;OAIG;IACH,eAFa,MAAM,CA+BlB;IAED;;;OAGG;IACH,YAFW,MAAM,QAoChB;CAcJ"}
@@ -3,6 +3,7 @@ import { max3 } from "../math/max3.js";
3
3
  import { min2 } from "../math/min2.js";
4
4
  import { align_32 } from "./align_32.js";
5
5
  import { lsb_32 } from "./lsb_32.js";
6
+ import { bitCount } from "./operations/bitCount.js";
6
7
 
7
8
  /**
8
9
  * Used for overallocating space when bit set needs to grow
@@ -567,6 +568,42 @@ export class BitSet {
567
568
  this.__length = 0;
568
569
  }
569
570
 
571
+ /**
572
+ * Number of set bits in this BitSet.
573
+ * Also known as "Hamming weight" or "population count".
574
+ * @returns {number}
575
+ */
576
+ cardinality(){
577
+ const length = this.__length;
578
+
579
+ if (length === 0) {
580
+ return 0;
581
+ }
582
+
583
+ const data = this.__data_uint32;
584
+ let count = 0;
585
+
586
+ // Number of fully utilized 32-bit words
587
+ const full_words = length >> 5;
588
+
589
+ // Count bits in all complete words
590
+ for (let i = 0; i < full_words; i++) {
591
+ count += bitCount(data[i]);
592
+ }
593
+
594
+ // Handle any remaining bits in the partial last word
595
+ const remainder_bits = length & 31;
596
+
597
+ if (remainder_bits > 0) {
598
+ // Create a mask to ignore any bits beyond __length
599
+ // e.g., if remainder is 3, mask is (1<<3)-1 = 7 (0b111)
600
+ const mask = (1 << remainder_bits) - 1;
601
+ count += bitCount(data[full_words] & mask);
602
+ }
603
+
604
+ return count;
605
+ }
606
+
570
607
  /**
571
608
  * Copy contents of another bit set into this one
572
609
  * @param {BitSet} other
@@ -619,4 +656,4 @@ export class BitSet {
619
656
 
620
657
  return r;
621
658
  }
622
- }
659
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"bitCount.d.ts","sourceRoot":"","sources":["../../../../../src/core/binary/operations/bitCount.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,4BAHW,MAAM,GACJ,MAAM,CAalB"}
1
+ {"version":3,"file":"bitCount.d.ts","sourceRoot":"","sources":["../../../../../src/core/binary/operations/bitCount.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,4BAHW,MAAM,GACJ,MAAM,CAkBlB"}
@@ -7,11 +7,16 @@ export function bitCount(v) {
7
7
  // see https://stackoverflow.com/a/109025/3973586
8
8
  // see https://graphics.stanford.edu/%7Eseander/bithacks.html#CountBitsSetParallel
9
9
 
10
- let i = v|0;
11
10
 
12
- i = i - ((i >> 1) & 0x55555555); // add pairs of bits
13
- i = (i & 0x33333333) + ((i >> 2) & 0x33333333); // quads
14
- i = (i + (i >> 4)) & 0x0F0F0F0F; // groups of 8
15
- i *= 0x01010101; // horizontal sum of bytes
16
- return i >> 24; // return just that top byte (after truncating to 32-bit even when int is wider than uint32_t)
11
+ // Force to a 32-bit unsigned integer
12
+ let i = v >>> 0;
13
+
14
+ i = i - ((i >>> 1) & 0x55555555); // Add pairs of bits
15
+ i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); // Quads
16
+ i = (i + (i >>> 4)) & 0x0F0F0F0F; // Groups of 8
17
+
18
+ // horizontal sum of bytes
19
+ // return just that top byte (after truncating to 32-bit even when int is wider than uint32_t)
20
+ // Math.imul perfectly simulates C's 32-bit integer multiplication overflow
21
+ return (Math.imul(i, 0x01010101) >>> 24);
17
22
  }
@@ -215,10 +215,16 @@ export class AABB3 {
215
215
  * @returns {boolean}
216
216
  */
217
217
  _expandToFitPoint(x: number, y: number, z: number): boolean;
218
+ /**
219
+ *
220
+ * @param {AABB3} other
221
+ */
222
+ union(other: AABB3): void;
218
223
  /**
219
224
  *
220
225
  * @param {AABB3} box
221
226
  * @returns {boolean}
227
+ * @deprecated use {@link AABB3#union} instead
222
228
  */
223
229
  expandToFit(box: AABB3): boolean;
224
230
  /**
@@ -323,7 +329,7 @@ export class AABB3 {
323
329
  intersectRay(oX: any, oY: any, oZ: any, dX: any, dY: any, dZ: any): boolean;
324
330
  intersectSegment(startX: any, startY: any, startZ: any, endX: any, endY: any, endZ: any): boolean;
325
331
  /**
326
- *
332
+ * @deprecated use {@link AABB3#_containsBox} instead
327
333
  * @param {THREE.Box} box
328
334
  * @returns {boolean}
329
335
  */
@@ -1 +1 @@
1
- {"version":3,"file":"AABB3.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/aabb/AABB3.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AABB3.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/aabb/AABB3.js"],"names":[],"mappings":"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"}
@@ -491,10 +491,19 @@ export class AABB3 {
491
491
  return expanded;
492
492
  }
493
493
 
494
+ /**
495
+ *
496
+ * @param {AABB3} other
497
+ */
498
+ union(other) {
499
+ this._expandToFit(other.x0, other.y0, other.z0, other.x1, other.y1, other.z1);
500
+ }
501
+
494
502
  /**
495
503
  *
496
504
  * @param {AABB3} box
497
505
  * @returns {boolean}
506
+ * @deprecated use {@link AABB3#union} instead
498
507
  */
499
508
  expandToFit(box) {
500
509
  return this._expandToFit(box.x0, box.y0, box.z0, box.x1, box.y1, box.z1);
@@ -710,7 +719,7 @@ export class AABB3 {
710
719
  }
711
720
 
712
721
  /**
713
- *
722
+ * @deprecated use {@link AABB3#_containsBox} instead
714
723
  * @param {THREE.Box} box
715
724
  * @returns {boolean}
716
725
  */
@@ -961,6 +970,10 @@ export class AABB3 {
961
970
  * @param {number} extra
962
971
  */
963
972
  grow(extra) {
973
+ assert.isNumber(extra, 'extra');
974
+ assert.notNaN(extra, 'extra');
975
+ assert.isFinite(extra, 'extra');
976
+
964
977
  this.x0 -= extra;
965
978
  this.y0 -= extra;
966
979
  this.z0 -= extra;
@@ -1 +1 @@
1
- {"version":3,"file":"Terrain.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/terrain/ecs/Terrain.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Terrain.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/terrain/ecs/Terrain.js"],"names":[],"mappings":"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"}
@@ -586,7 +586,12 @@ class Terrain {
586
586
 
587
587
  uniforms.splatWeightMap.value = this.splat.weightTexture;
588
588
 
589
- uniforms.splatLayerCount.value = this.layers.count();
589
+ // Update layer count as a compile-time define (AMD GLSL 300 ES requires constant loop bounds)
590
+ const layerCount = this.layers.count();
591
+ if (m.defines.SPLAT_LAYER_COUNT !== layerCount) {
592
+ m.defines.SPLAT_LAYER_COUNT = layerCount;
593
+ m.needsUpdate = true;
594
+ }
590
595
 
591
596
  uniforms.materialScalesMap.value = this.layers.scalesTexture;
592
597
 
@@ -1 +1 @@
1
- {"version":3,"file":"TerrainLayer.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/ecs/terrain/ecs/layers/TerrainLayer.js"],"names":[],"mappings":"AA2BA;IA+CI;;;;;OAKG;IACH,iBAJW,MAAM,SACN,MAAM,UACN,MAAM,gBAShB;IAED;;;;OAIG;IACH,oDAFa,YAAY,CAQxB;IAvED;;;OAGG;IACH,0BAAuB;IAEvB;;;OAGG;IACH,SAFU,SAAS,CAEgB;IAEnC;;;OAGG;IACH,MAFU,OAAO,CAEQ;IAEzB;;;OAGG;IACH,WAAW;IAEX;;;OAGG;IACH,WAFU,MAAM,CAES;IAGzB;;;;;;;MAMC;IAED;;;;aAIC;IA8BD;;;;OAIG;IACH,0DAwDC;IAGL;;;OAGG;IACH,yBAFU,OAAO,CAEoB;CANpC;0BA9JyB,mDAAmD;oBAJzD,qCAAqC;mBADtC,6CAA6C"}
1
+ {"version":3,"file":"TerrainLayer.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/ecs/terrain/ecs/layers/TerrainLayer.js"],"names":[],"mappings":"AA2BA;IA+CI;;;;;OAKG;IACH,iBAJW,MAAM,SACN,MAAM,UACN,MAAM,gBAShB;IAED;;;;OAIG;IACH,oDAFa,YAAY,CAQxB;IAvED;;;OAGG;IACH,0BAAuB;IAEvB;;;OAGG;IACH,SAFU,SAAS,CAEgB;IAEnC;;;OAGG;IACH,MAFU,OAAO,CAEQ;IAEzB;;;OAGG;IACH,WAAW;IAEX;;;OAGG;IACH,WAFU,MAAM,CAES;IAGzB;;;;;;;MAMC;IAED;;;;aAIC;IA8BD;;;;OAIG;IACH,0DAyDC;IAGL;;;OAGG;IACH,yBAFU,OAAO,CAEoB;CANpC;0BA/JyB,mDAAmD;oBAJzD,qCAAqC;mBADtC,6CAA6C"}
@@ -5,7 +5,7 @@ import { computeStringHash } from "../../../../../core/primitives/strings/comput
5
5
  import { string_compute_byte_size } from "../../../../../core/primitives/strings/string_compute_byte_size.js";
6
6
  import { GameAssetType } from "../../../../asset/GameAssetType.js";
7
7
  import { Sampler2D } from "../../../../graphics/texture/sampler/Sampler2D.js";
8
- import { sampler2d_transfer_data } from "../../../../graphics/texture/sampler/sampler2d_transfer_data.js";
8
+ import { sampler2d_ensure_uint8_RGBA } from "../../../../graphics/texture/sampler/sampler2d_ensure_uint8_RGBA.js";
9
9
 
10
10
  /**
11
11
  *
@@ -37,7 +37,7 @@ export class TerrainLayer {
37
37
  *
38
38
  * @type {Sampler2D}
39
39
  */
40
- diffuse = Sampler2D.uint8(3, 1, 1);
40
+ diffuse = Sampler2D.uint8(4, 1, 1);
41
41
 
42
42
  /**
43
43
  *
@@ -135,21 +135,22 @@ export class TerrainLayer {
135
135
  .then(assert => {
136
136
  const image = assert.create();
137
137
 
138
+ const source_data = image.data;
138
139
  const source_item_size = image.itemSize;
139
140
 
140
- const source_data = image.data;
141
+ // RGBA (4 channels) for AMD GPU compatibility
142
+ const destination_item_size = 4;
143
+
144
+ const source = new Sampler2D(source_data, source_item_size, image.width, image.height);
141
145
 
142
- // RGB
143
- const destination_item_size = 3;
146
+ // Convert to uint8 RGBA, handling any source format
147
+ const rgba = sampler2d_ensure_uint8_RGBA(source);
144
148
 
145
149
  if (this.diffuse === null || this.diffuse.width !== image.width || this.diffuse.height !== image.height) {
146
- // loaded image does not match the side of the layer
147
150
  this.diffuse = Sampler2D.uint8(destination_item_size, image.width, image.height);
148
151
  }
149
152
 
150
- const source = new Sampler2D(source_data, source_item_size, image.width, image.height);
151
-
152
- sampler2d_transfer_data(source, this.diffuse);
153
+ this.diffuse.data.set(rgba.data);
153
154
 
154
155
  this.onChanged.send0();
155
156
 
@@ -1 +1 @@
1
- {"version":3,"file":"TerrainLayers.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/ecs/terrain/ecs/layers/TerrainLayers.js"],"names":[],"mappings":"AA6EA;IAGQ;;;OAGG;IACH,QAFU,KAAK,YAAY,CAAC,CAEJ;IAExB;;;OAGG;IACH,YAFU,OAAO,CAEoD;IAMrE;;;OAGG;IACH,SAFU,kBAAkB,CAE8B;IAiB1D,2BAAsF;IAc1F;;;;;;MAKC;IAED;;;aAGC;IAED;;;;OAIG;IACH,gCAHW,MAAM,iBACN,MAAM,QAuChB;IAED;;;;OAIG;IACH,0DAyBC;IAED,sCAIC;IAED;;;;OAIG;IACH,WAHW,MAAM,GACL,YAAY,CAIvB;IAED;;;;OAIG;IACH,8DAFa,MAAM,CAqBlB;IAED;;;;OAIG;IACH,kCAHW,MAAM,GACJ,MAAM,CAMlB;IAED;;;OAGG;IACH,SAFY,MAAM,CAIjB;IAED;;;;OAIG;IACH,gBAHW,YAAY,GACV,MAAM,CAWlB;IAED;;;;OAIG;IACH,mBAHW,YAAY,GACX,OAAO,CAIlB;IAED;;;;;;OAMG;IACH,0CA8BC;IAED;;;OAGG;IACH,iCAFW,MAAM,QAgChB;IAED,gBAGC;IAED,cAEC;IAGD,qBAsCC;CACJ;iBA5ZgB,6CAA6C;6BAQjC,mBAAmB;oBAP5B,qCAAqC;mCALlD,OAAO;4BAAP,OAAO"}
1
+ {"version":3,"file":"TerrainLayers.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/ecs/terrain/ecs/layers/TerrainLayers.js"],"names":[],"mappings":"AA8EA;IAGQ;;;OAGG;IACH,QAFU,KAAK,YAAY,CAAC,CAEJ;IAExB;;;OAGG;IACH,YAFU,OAAO,CAEoD;IAMrE;;;OAGG;IACH,SAFU,kBAAkB,CAE8B;IAiB1D,2BAAsF;IAc1F;;;;;;MAKC;IAED;;;aAGC;IAED;;;;OAIG;IACH,gCAHW,MAAM,iBACN,MAAM,QAuChB;IAED;;;;OAIG;IACH,0DAyBC;IAED,sCAIC;IAED;;;;OAIG;IACH,WAHW,MAAM,GACL,YAAY,CAIvB;IAED;;;;OAIG;IACH,8DAFa,MAAM,CAqBlB;IAED;;;;OAIG;IACH,kCAHW,MAAM,GACJ,MAAM,CAMlB;IAED;;;OAGG;IACH,SAFY,MAAM,CAIjB;IAED;;;;OAIG;IACH,gBAHW,YAAY,GACV,MAAM,CAWlB;IAED;;;;OAIG;IACH,mBAHW,YAAY,GACX,OAAO,CAIlB;IAED;;;;;;OAMG;IACH,0CAgCC;IAED;;;OAGG;IACH,iCAFW,MAAM,QAgChB;IAED,gBAGC;IAED,cAEC;IAGD,qBAsCC;CACJ;iBA9ZgB,6CAA6C;6BAQjC,mBAAmB;oBAP5B,qCAAqC;mCALlD,OAAO;4BAAP,OAAO"}
@@ -8,6 +8,7 @@ import {
8
8
  LinearMipMapLinearFilter,
9
9
  NearestFilter,
10
10
  RepeatWrapping,
11
+ RGBAFormat,
11
12
  RGFormat,
12
13
  UnsignedByteType
13
14
  } from "three";
@@ -19,9 +20,9 @@ import Vector2 from "../../../../../core/geom/Vector2.js";
19
20
  import { invokeObjectEquals } from "../../../../../core/model/object/invokeObjectEquals.js";
20
21
  import { invokeObjectHash } from "../../../../../core/model/object/invokeObjectHash.js";
21
22
  import { computeStringHash } from "../../../../../core/primitives/strings/computeStringHash.js";
22
- import { GL_RGBFormat } from "../../../../graphics/texture/GL_RGBFormat.js";
23
23
  import { sampler2d_scale } from "../../../../graphics/texture/sampler/resize/sampler2d_scale.js";
24
24
  import { Sampler2D } from "../../../../graphics/texture/sampler/Sampler2D.js";
25
+ import { sampler2d_ensure_uint8_RGBA } from "../../../../graphics/texture/sampler/sampler2d_ensure_uint8_RGBA.js";
25
26
  import { TerrainLayer } from "./TerrainLayer.js";
26
27
 
27
28
  class ScaledTextureKey {
@@ -91,7 +92,7 @@ export class TerrainLayers {
91
92
  this.resolution = new Vector2(DEFAULT_RESOLUTION, DEFAULT_RESOLUTION);
92
93
 
93
94
 
94
- const layer_data = new Uint8Array(3);
95
+ const layer_data = new Uint8Array(4);
95
96
  layer_data.fill(255); //pre-fill with white
96
97
 
97
98
  /**
@@ -99,7 +100,7 @@ export class TerrainLayers {
99
100
  * @type {DataTexture2DArray}
100
101
  */
101
102
  this.texture = new DataTexture2DArray(layer_data, 1, 1, 1);
102
- this.texture.format = GL_RGBFormat;
103
+ this.texture.format = RGBAFormat;
103
104
  this.texture.type = UnsignedByteType;
104
105
 
105
106
  this.texture.wrapS = RepeatWrapping;
@@ -112,7 +113,7 @@ export class TerrainLayers {
112
113
 
113
114
  this.texture.generateMipmaps = true;
114
115
  this.texture.encoding = LinearEncoding;
115
- this.texture.internalFormat = 'RGB8';
116
+ this.texture.internalFormat = 'RGBA8';
116
117
  this.texture.needsUpdate = true;
117
118
 
118
119
  this.scalesTexture = new DataTexture(new Float32Array(64), 32, 1, RGFormat, FloatType);
@@ -312,7 +313,7 @@ export class TerrainLayers {
312
313
  __obtain_layer_data_at_resolution(layer, resolution) {
313
314
  const layerSampler = layer.diffuse;
314
315
 
315
- assert.equal(layerSampler.itemSize, 3, 'layer sampler must have 3 channels');
316
+ assert.equal(layerSampler.itemSize, 4, 'layer sampler must have 4 channels');
316
317
 
317
318
  const resolution_x = resolution.x;
318
319
  const resolution_y = resolution.y;
@@ -330,14 +331,16 @@ export class TerrainLayers {
330
331
  return existing;
331
332
  }
332
333
 
333
- const scaledLayerSampler = Sampler2D.uint8(3, resolution_x, resolution_y);
334
+ const scaledLayerSampler = Sampler2D.uint8(4, resolution_x, resolution_y);
334
335
 
335
336
  sampler2d_scale(layerSampler, scaledLayerSampler);
336
337
 
337
- // write scaled texture into the cache
338
- scaled_texture_cache.put(key, scaledLayerSampler);
338
+ // Ensure result is uint8 RGBA
339
+ const rgba = sampler2d_ensure_uint8_RGBA(scaledLayerSampler);
339
340
 
340
- return scaledLayerSampler;
341
+ scaled_texture_cache.put(key, rgba);
342
+
343
+ return rgba;
341
344
  }
342
345
  }
343
346
 
@@ -359,7 +362,7 @@ export class TerrainLayers {
359
362
 
360
363
  const resolution = this.resolution;
361
364
 
362
- const single_layer_byte_size = resolution.x * resolution.y * 3;
365
+ const single_layer_byte_size = resolution.x * resolution.y * 4;
363
366
 
364
367
  if (arrayData.length < single_layer_byte_size * index) {
365
368
  throw new Error('Texture data is too small, make sure you rebuild texture data before attempting to write');
@@ -411,7 +414,7 @@ export class TerrainLayers {
411
414
  texture.dispose();
412
415
 
413
416
  //build an array to hold texture array
414
- const arrayData = new Uint8Array(size_x * size_y * 3 * layerCount);
417
+ const arrayData = new Uint8Array(size_x * size_y * 4 * layerCount);
415
418
  arrayData.fill(255); // fill with white
416
419
 
417
420
  if (image.width === size_x && image.height === size_y) {
@@ -1 +1 @@
1
- {"version":3,"file":"WaterSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/water/WaterSystem.js"],"names":[],"mappings":";AAWA;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,2CA0DC;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;;;;uBA7QsB,wBAAwB;kBAM7B,YAAY;oBAPV,mCAAmC"}
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,4 +1,5 @@
1
1
  import { BackSide, PlaneBufferGeometry } from 'three';
2
+ import { assert } from "../../../../core/assert.js";
2
3
  import { BVH } from "../../../../core/bvh2/bvh3/BVH.js";
3
4
  import { System } from '../../../ecs/System.js';
4
5
  import { obtainTerrain } from "../../../ecs/terrain/util/obtainTerrain.js";
@@ -76,6 +77,8 @@ class WaterSystem extends System {
76
77
  (destination, offset, entity, ecd) => {
77
78
  const component = ecd.getComponent(entity, Water);
78
79
 
80
+ assert.defined(component, 'component');
81
+
79
82
  const mesh = component.__threeObject;
80
83
 
81
84
  if (mesh === null) {
@@ -1 +1 @@
1
- {"version":3,"file":"SplatMaterial.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics/material/SplatMaterial.js"],"names":[],"mappings":"AAgBA;;;;;;;;GAQG;AACH,oFAPW,OAAO,GAIN,cAAc,CAkIzB;;IAxID;;;;;;;;OAQG;IACH,kEAPW,OAAO,EAsIjB;;wBA5IM,OAAO;+BAAP,OAAO"}
1
+ {"version":3,"file":"SplatMaterial.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics/material/SplatMaterial.js"],"names":[],"mappings":"AAgBA;;;;;;;;GAQG;AACH,oFAPW,OAAO,GAIN,cAAc,CAgIzB;;IAtID;;;;;;;;OAQG;IACH,kEAPW,OAAO,EAoIjB;;wBA1IM,OAAO;+BAAP,OAAO"}
@@ -47,10 +47,7 @@ export function SplatMaterial(
47
47
  type: "t",
48
48
  value: null
49
49
  },
50
- "splatLayerCount": {
51
- type: "f",
52
- value: 4
53
- },
50
+
54
51
  "splatResolution": {
55
52
  type: 'v2',
56
53
  value: new Vector2(1, 1)
@@ -115,6 +112,7 @@ export function SplatMaterial(
115
112
  transparent: false,
116
113
  lights: true,
117
114
  defines: {
115
+ SPLAT_LAYER_COUNT: 4,
118
116
  SHADOWMAP_CLOUDS: false,
119
117
  DIFFUSE_GRAIN: false
120
118
  },
@@ -95,7 +95,7 @@ function fragment() {
95
95
  precision highp sampler2DArray;
96
96
 
97
97
  uniform sampler2DArray splatWeightMap;
98
- uniform int splatLayerCount;
98
+ // SPLAT_LAYER_COUNT is injected as a #define from the material defines
99
99
 
100
100
  uniform vec2 splatResolution;
101
101
 
@@ -240,14 +240,7 @@ function fragment() {
240
240
  return hsv2rgb(hsv);
241
241
  }
242
242
 
243
- vec3 brighten2(const in vec3 color, in float factor, float p){
244
- vec3 yiq = rgb2yiq*color;
245
-
246
- yiq.x *= p;
247
- yiq.x = pow(yiq.x,factor);
248
-
249
- return yiq2rgb * yiq;
250
- }
243
+
251
244
 
252
245
  vec4 computeGridOverlayTexel(const in vec2 grid_uv, const in vec2 grid_resolution){
253
246
  vec2 grid_texel = vGridPosition + 0.5;
@@ -276,7 +269,7 @@ function fragment() {
276
269
  float weightSum = 0.0;
277
270
  vec4 colorSum = vec4(0.0);
278
271
 
279
- for( int i = 0; i < splatLayerCount; i++){
272
+ for( int i = 0; i < SPLAT_LAYER_COUNT; i++){
280
273
 
281
274
  vec2 scale = texelFetch(materialScalesMap, ivec2(i, 0), 0 ).xy;
282
275
 
@@ -290,7 +283,7 @@ function fragment() {
290
283
  colorSum += diffuseData*weight;
291
284
  }
292
285
 
293
- return colorSum / weightSum;
286
+ return weightSum > 0.0 ? colorSum / weightSum : vec4(0.0);
294
287
  }
295
288
 
296
289
  ${ShaderChunks.clouds_pars_fragment}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * GJK intersection test for two convex shapes.
3
+ *
4
+ * Determines whether two convex shapes overlap by iteratively building a simplex
5
+ * in the Minkowski difference space. If the origin is enclosed by the simplex,
6
+ * the shapes intersect.
7
+ *
8
+ * Adapted from https://github.com/kevinmoran/GJK/blob/master/GJK.h
9
+ *
10
+ * @param {number[]|Float32Array} simplex Working buffer for simplex vertices (4 vec3s). Must have length >= 12.
11
+ * @param {AbstractShape3D} shape_a
12
+ * @param {AbstractShape3D} shape_b
13
+ * @returns {boolean} true if the shapes intersect
14
+ */
15
+ export function gjk(simplex: number[] | Float32Array, shape_a: AbstractShape3D, shape_b: AbstractShape3D): boolean;
16
+ //# sourceMappingURL=gjk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gjk.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/gjk/gjk.js"],"names":[],"mappings":"AAmDA;;;;;;;;;;;;;GAaG;AACH,6BALW,MAAM,EAAE,GAAC,YAAY,uDAGnB,OAAO,CAkGnB"}
@@ -0,0 +1,378 @@
1
+ import { v3_dot } from "../../../core/geom/vec3/v3_dot.js";
2
+ import { v3_length } from "../../../core/geom/vec3/v3_length.js";
3
+
4
+ const GJK_MAX_ITERATIONS = 64;
5
+
6
+ /**
7
+ * Module-level scratch buffers to avoid per-call allocations.
8
+ */
9
+ const scratch_support_a = new Float32Array(3);
10
+ const scratch_support_b = new Float32Array(3);
11
+ const scratch_dir = new Float32Array(3);
12
+
13
+ /**
14
+ * Compute the Minkowski difference support point for two shapes.
15
+ * support(A-B, d) = support(A, d) - support(B, -d)
16
+ *
17
+ * The direction is normalized before being passed to the shape support
18
+ * functions, since {@link AbstractShape3D#support} assumes a unit vector.
19
+ *
20
+ * @param {number[]|Float32Array} result
21
+ * @param {number} result_offset
22
+ * @param {AbstractShape3D} shape_a
23
+ * @param {AbstractShape3D} shape_b
24
+ * @param {number} dir_x
25
+ * @param {number} dir_y
26
+ * @param {number} dir_z
27
+ */
28
+ function minkowski_support(
29
+ result, result_offset,
30
+ shape_a,
31
+ shape_b,
32
+ dir_x, dir_y, dir_z
33
+ ) {
34
+ // Normalize direction — support() contract requires a unit vector
35
+ const len = v3_length(dir_x, dir_y, dir_z);
36
+
37
+ if (len > 0) {
38
+ const inv = 1 / len;
39
+ dir_x *= inv;
40
+ dir_y *= inv;
41
+ dir_z *= inv;
42
+ }
43
+
44
+ shape_a.support(scratch_support_a, 0, dir_x, dir_y, dir_z);
45
+ shape_b.support(scratch_support_b, 0, -dir_x, -dir_y, -dir_z);
46
+
47
+ result[result_offset] = scratch_support_a[0] - scratch_support_b[0];
48
+ result[result_offset + 1] = scratch_support_a[1] - scratch_support_b[1];
49
+ result[result_offset + 2] = scratch_support_a[2] - scratch_support_b[2];
50
+ }
51
+
52
+ /**
53
+ * GJK intersection test for two convex shapes.
54
+ *
55
+ * Determines whether two convex shapes overlap by iteratively building a simplex
56
+ * in the Minkowski difference space. If the origin is enclosed by the simplex,
57
+ * the shapes intersect.
58
+ *
59
+ * Adapted from https://github.com/kevinmoran/GJK/blob/master/GJK.h
60
+ *
61
+ * @param {number[]|Float32Array} simplex Working buffer for simplex vertices (4 vec3s). Must have length >= 12.
62
+ * @param {AbstractShape3D} shape_a
63
+ * @param {AbstractShape3D} shape_b
64
+ * @returns {boolean} true if the shapes intersect
65
+ */
66
+ export function gjk(simplex, shape_a, shape_b) {
67
+
68
+ const dir = scratch_dir;
69
+
70
+ // Initial search direction — arbitrary, (1,0,0)
71
+
72
+ // Get initial support point (simplex point C)
73
+ minkowski_support(
74
+ simplex, 6,
75
+ shape_a, shape_b,
76
+ 1, 0, 0
77
+ );
78
+
79
+ // Search toward the origin from C
80
+ dir[0] = -simplex[6];
81
+ dir[1] = -simplex[7];
82
+ dir[2] = -simplex[8];
83
+
84
+ if (dir[0] === 0 && dir[1] === 0 && dir[2] === 0) {
85
+ // Origin is exactly on the first support point — intersection
86
+ return true;
87
+ }
88
+
89
+ // Get second support point (simplex point B)
90
+ minkowski_support(simplex, 3, shape_a, shape_b, dir[0], dir[1], dir[2]);
91
+
92
+ // B didn't pass the origin — no intersection possible
93
+ if (v3_dot(simplex[3], simplex[4], simplex[5], dir[0], dir[1], dir[2]) < 0) {
94
+ return false;
95
+ }
96
+
97
+ // Line case: compute direction perpendicular to line segment BC toward origin
98
+ // CB = C - B
99
+ const cb_x = simplex[6] - simplex[3];
100
+ const cb_y = simplex[7] - simplex[4];
101
+ const cb_z = simplex[8] - simplex[5];
102
+
103
+ // BO = -B (origin - B)
104
+ const bo_x = -simplex[3];
105
+ const bo_y = -simplex[4];
106
+ const bo_z = -simplex[5];
107
+
108
+ // dir = CB × BO × CB (triple cross product)
109
+ triple_cross_product(dir, cb_x, cb_y, cb_z, bo_x, bo_y, bo_z);
110
+
111
+ // Handle degenerate case where origin is on the line segment
112
+ if (dir[0] === 0 && dir[1] === 0 && dir[2] === 0) {
113
+ // Origin is on the line segment — pick any perpendicular direction
114
+ // Use the cross product of CB with an arbitrary axis
115
+ // CB × (1,0,0)
116
+ dir[0] = cb_y;
117
+ dir[1] = -cb_x;
118
+ dir[2] = 0;
119
+
120
+ if (dir[0] === 0 && dir[1] === 0 && dir[2] === 0) {
121
+ // CB is parallel to (1,0,0), use (0,1,0)
122
+ dir[0] = -cb_z;
123
+ dir[1] = 0;
124
+ dir[2] = cb_x;
125
+ }
126
+ }
127
+
128
+ let simplex_size = 2; // we have B and C
129
+
130
+ for (let iterations = 0; iterations < GJK_MAX_ITERATIONS; iterations++) {
131
+ // Get new support point A
132
+ minkowski_support(simplex, 0, shape_a, shape_b, dir[0], dir[1], dir[2]);
133
+
134
+ const a_x = simplex[0];
135
+ const a_y = simplex[1];
136
+ const a_z = simplex[2];
137
+
138
+ // Check if A passed the origin
139
+ if (v3_dot(a_x, a_y, a_z, dir[0], dir[1], dir[2]) < 0) {
140
+ return false; // no intersection
141
+ }
142
+
143
+ simplex_size++;
144
+
145
+ if (simplex_size === 3) {
146
+ // Triangle case
147
+ update_simplex_triangle(dir, simplex);
148
+ } else {
149
+ // Tetrahedron case
150
+ if (update_simplex_tetrahedron(dir, simplex)) {
151
+ // Origin is inside the tetrahedron — intersection!
152
+ return true;
153
+ }
154
+
155
+ // The simplex was reduced to a triangle, so keep size at 3
156
+ simplex_size = 3;
157
+ }
158
+ }
159
+
160
+ // Did not converge — assume no intersection
161
+ return false;
162
+ }
163
+
164
+ /**
165
+ * Compute the triple cross product: (a × b) × a
166
+ *
167
+ * @param {number[]|Float32Array} result output vec3
168
+ * @param {number} ax
169
+ * @param {number} ay
170
+ * @param {number} az
171
+ * @param {number} bx
172
+ * @param {number} by
173
+ * @param {number} bz
174
+ */
175
+ function triple_cross_product(result, ax, ay, az, bx, by, bz) {
176
+ // First: t = a × b
177
+ const tx = ay * bz - az * by;
178
+ const ty = az * bx - ax * bz;
179
+ const tz = ax * by - ay * bx;
180
+
181
+ // Then: t × a
182
+ result[0] = ty * az - tz * ay;
183
+ result[1] = tz * ax - tx * az;
184
+ result[2] = tx * ay - ty * ax;
185
+ }
186
+
187
+ /**
188
+ * Update simplex for the triangle case (3 points: A, B, C).
189
+ *
190
+ * Determines the Voronoi region of the origin relative to triangle ABC
191
+ * and updates the search direction accordingly.
192
+ *
193
+ * simplex layout: [A(0-2), B(3-5), C(6-8)]
194
+ *
195
+ * @param {number[]|Float32Array} search_dir output: next search direction
196
+ * @param {Float32Array} simplex
197
+ */
198
+ function update_simplex_triangle(search_dir, simplex) {
199
+ const a_x = simplex[0], a_y = simplex[1], a_z = simplex[2];
200
+ const b_x = simplex[3], b_y = simplex[4], b_z = simplex[5];
201
+ const c_x = simplex[6], c_y = simplex[7], c_z = simplex[8];
202
+
203
+ // AB = B - A
204
+ const ab_x = b_x - a_x;
205
+ const ab_y = b_y - a_y;
206
+ const ab_z = b_z - a_z;
207
+
208
+ // AC = C - A
209
+ const ac_x = c_x - a_x;
210
+ const ac_y = c_y - a_y;
211
+ const ac_z = c_z - a_z;
212
+
213
+ // AO = -A (origin - A)
214
+ const ao_x = -a_x;
215
+ const ao_y = -a_y;
216
+ const ao_z = -a_z;
217
+
218
+ // Normal of triangle ABC
219
+ const abc_x = ab_y * ac_z - ab_z * ac_y;
220
+ const abc_y = ab_z * ac_x - ab_x * ac_z;
221
+ const abc_z = ab_x * ac_y - ab_y * ac_x;
222
+
223
+ // Test edge AC
224
+ // ABC × AC
225
+ const abc_cross_ac_x = abc_y * ac_z - abc_z * ac_y;
226
+ const abc_cross_ac_y = abc_z * ac_x - abc_x * ac_z;
227
+ const abc_cross_ac_z = abc_x * ac_y - abc_y * ac_x;
228
+
229
+ if (v3_dot(abc_cross_ac_x, abc_cross_ac_y, abc_cross_ac_z, ao_x, ao_y, ao_z) > 0) {
230
+ // Origin is on the AC side
231
+ // Reduce simplex to line AC (A stays as A, C moves to B position)
232
+ simplex[3] = c_x;
233
+ simplex[4] = c_y;
234
+ simplex[5] = c_z;
235
+
236
+ // New direction: AC × AO × AC
237
+ triple_cross_product(search_dir, ac_x, ac_y, ac_z, ao_x, ao_y, ao_z);
238
+ return;
239
+ }
240
+
241
+ // Test edge AB
242
+ // AB × ABC
243
+ const ab_cross_abc_x = ab_y * abc_z - ab_z * abc_y;
244
+ const ab_cross_abc_y = ab_z * abc_x - ab_x * abc_z;
245
+ const ab_cross_abc_z = ab_x * abc_y - ab_y * abc_x;
246
+
247
+ if (v3_dot(ab_cross_abc_x, ab_cross_abc_y, ab_cross_abc_z, ao_x, ao_y, ao_z) > 0) {
248
+ // Origin is on the AB side
249
+ // Keep simplex as line AB (C slot is cleared by not using it)
250
+ simplex[6] = simplex[3];
251
+ simplex[7] = simplex[4];
252
+ simplex[8] = simplex[5];
253
+
254
+ // New direction: AB × AO × AB
255
+ triple_cross_product(search_dir, ab_x, ab_y, ab_z, ao_x, ao_y, ao_z);
256
+ return;
257
+ }
258
+
259
+ // Origin is above or below the triangle
260
+ if (v3_dot(abc_x, abc_y, abc_z, ao_x, ao_y, ao_z) > 0) {
261
+ // Origin is above — search in normal direction
262
+ // Simplex stays as A, B, C
263
+ search_dir[0] = abc_x;
264
+ search_dir[1] = abc_y;
265
+ search_dir[2] = abc_z;
266
+ } else {
267
+ // Origin is below — swap B and C, search in -normal
268
+ const tmp_x = simplex[3], tmp_y = simplex[4], tmp_z = simplex[5];
269
+ simplex[3] = simplex[6];
270
+ simplex[4] = simplex[7];
271
+ simplex[5] = simplex[8];
272
+ simplex[6] = tmp_x;
273
+ simplex[7] = tmp_y;
274
+ simplex[8] = tmp_z;
275
+
276
+ search_dir[0] = -abc_x;
277
+ search_dir[1] = -abc_y;
278
+ search_dir[2] = -abc_z;
279
+ }
280
+ }
281
+
282
+ /**
283
+ * Update simplex for the tetrahedron case (4 points: A, B, C, D).
284
+ *
285
+ * Tests which face of the tetrahedron is closest to the origin and
286
+ * reduces the simplex accordingly. Returns true if the origin is
287
+ * inside the tetrahedron.
288
+ *
289
+ * simplex layout: [A(0-2), B(3-5), C(6-8), D(9-11)]
290
+ *
291
+ * @param {number[]|Float32Array} search_dir output: next search direction (only written when returning false)
292
+ * @param {Float32Array} simplex
293
+ * @returns {boolean} true if origin is inside the tetrahedron
294
+ */
295
+ function update_simplex_tetrahedron(search_dir, simplex) {
296
+ const a_x = simplex[0], a_y = simplex[1], a_z = simplex[2];
297
+ const b_x = simplex[3], b_y = simplex[4], b_z = simplex[5];
298
+ const c_x = simplex[6], c_y = simplex[7], c_z = simplex[8];
299
+ const d_x = simplex[9], d_y = simplex[10], d_z = simplex[11];
300
+
301
+ // AB, AC, AD vectors
302
+ const ab_x = b_x - a_x, ab_y = b_y - a_y, ab_z = b_z - a_z;
303
+ const ac_x = c_x - a_x, ac_y = c_y - a_y, ac_z = c_z - a_z;
304
+ const ad_x = d_x - a_x, ad_y = d_y - a_y, ad_z = d_z - a_z;
305
+
306
+ // AO = origin - A = -A
307
+ const ao_x = -a_x, ao_y = -a_y, ao_z = -a_z;
308
+
309
+ // Face normals (outward-facing from A's perspective)
310
+ // ABC normal
311
+ const abc_x = ab_y * ac_z - ab_z * ac_y;
312
+ const abc_y = ab_z * ac_x - ab_x * ac_z;
313
+ const abc_z = ab_x * ac_y - ab_y * ac_x;
314
+
315
+ // ACD normal
316
+ const acd_x = ac_y * ad_z - ac_z * ad_y;
317
+ const acd_y = ac_z * ad_x - ac_x * ad_z;
318
+ const acd_z = ac_x * ad_y - ac_y * ad_x;
319
+
320
+ // ADB normal
321
+ const adb_x = ad_y * ab_z - ad_z * ab_y;
322
+ const adb_y = ad_z * ab_x - ad_x * ab_z;
323
+ const adb_z = ad_x * ab_y - ad_y * ab_x;
324
+
325
+ // Test each face to see if the origin is on the outside
326
+
327
+ // Check face ABC (opposite to D)
328
+ const abc_test = v3_dot(abc_x, abc_y, abc_z, ao_x, ao_y, ao_z);
329
+ // Make sure normal points away from D
330
+ const abc_d_side = v3_dot(abc_x, abc_y, abc_z, ad_x, ad_y, ad_z);
331
+
332
+ if (abc_test * abc_d_side < 0) {
333
+ // Origin is on the opposite side of ABC from D
334
+ // Reduce to triangle ABC: D is dropped
335
+ // simplex = [A, B, C] — A(0), B(3), C(6) already in place
336
+ update_simplex_triangle(search_dir, simplex);
337
+ return false;
338
+ }
339
+
340
+ // Check face ACD (opposite to B)
341
+ const acd_test = v3_dot(acd_x, acd_y, acd_z, ao_x, ao_y, ao_z);
342
+ const acd_b_side = v3_dot(acd_x, acd_y, acd_z, ab_x, ab_y, ab_z);
343
+
344
+ if (acd_test * acd_b_side < 0) {
345
+ // Origin is outside face ACD
346
+ // Reduce to triangle ACD: replace B with D
347
+ simplex[3] = c_x;
348
+ simplex[4] = c_y;
349
+ simplex[5] = c_z;
350
+ simplex[6] = d_x;
351
+ simplex[7] = d_y;
352
+ simplex[8] = d_z;
353
+
354
+ update_simplex_triangle(search_dir, simplex);
355
+ return false;
356
+ }
357
+
358
+ // Check face ADB (opposite to C)
359
+ const adb_test = v3_dot(adb_x, adb_y, adb_z, ao_x, ao_y, ao_z);
360
+ const adb_c_side = v3_dot(adb_x, adb_y, adb_z, ac_x, ac_y, ac_z);
361
+
362
+ if (adb_test * adb_c_side < 0) {
363
+ // Origin is outside face ADB
364
+ // Reduce to triangle ADB: replace C with B, B with D
365
+ simplex[6] = b_x;
366
+ simplex[7] = b_y;
367
+ simplex[8] = b_z;
368
+ simplex[3] = d_x;
369
+ simplex[4] = d_y;
370
+ simplex[5] = d_z;
371
+
372
+ update_simplex_triangle(search_dir, simplex);
373
+ return false;
374
+ }
375
+
376
+ // Origin is inside the tetrahedron
377
+ return true;
378
+ }