@woosh/meep-engine 2.58.0 → 2.59.1

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 (66) hide show
  1. package/build/bundle-worker-image-decoder.js +1 -1
  2. package/build/bundle-worker-terrain.js +1 -1
  3. package/build/meep.cjs +15297 -20126
  4. package/build/meep.min.js +1 -1
  5. package/build/meep.module.js +15298 -20126
  6. package/editor/process/symbolic/SymbolicDisplayInternalAPI.js +3 -3
  7. package/editor/process/symbolic/makeParticleEmitterSymbolicDisplay.js +1 -1
  8. package/editor/process/symbolic/makePathSymbolicDisplay.js +1 -1
  9. package/editor/process/symbolic/makeSoundEmitterSymbolicDisplay.js +1 -1
  10. package/editor/tools/TopDownCameraControlTool.js +2 -2
  11. package/editor/tools/v2/TransformControls.js +1 -1
  12. package/editor/tools/v2/prototypeTransformControls.js +1 -1
  13. package/package.json +2 -2
  14. package/samples/generation/main.js +1 -1
  15. package/samples/terrain/editor.js +1 -1
  16. package/src/core/collection/array/arraySetDiff.js +11 -7
  17. package/src/core/geom/3d/aabb/aabb3_array_intersects_point.spec.js +48 -0
  18. package/src/core/geom/3d/aabb/aabb3_array_intersects_ray.js +5 -1
  19. package/src/core/geom/3d/aabb/aabb3_expand_array.spec.js +16 -0
  20. package/src/core/geom/3d/aabb/aabb3_raycast.spec.js +37 -0
  21. package/src/core/geom/3d/aabb/aabb3_score_boxes_SAH.js +11 -12
  22. package/src/core/geom/3d/aabb/aabb3_score_boxes_SAH.spec.js +14 -0
  23. package/src/core/geom/3d/aabb/aabb3_transformed_compute_plane_side.js +6 -4
  24. package/src/core/geom/3d/aabb/compute_aabb_from_points.js +6 -3
  25. package/src/core/geom/3d/matrix/m4_multiply.spec.js +24 -0
  26. package/src/core/geom/3d/matrix/m4_multiply_alphatensor.js +56 -40
  27. package/src/core/geom/3d/matrix/m4_multiply_alphatensor.spec.js +24 -0
  28. package/src/core/geom/3d/shape/util/shape_to_visual_entity.js +2 -2
  29. package/src/core/geom/Vector3.spec.js +24 -14
  30. package/src/engine/EngineHarness.js +1 -1
  31. package/src/engine/control/ControlContext.js +1 -1
  32. package/src/engine/ecs/Entity.d.ts +2 -0
  33. package/src/engine/ecs/Entity.js +40 -37
  34. package/src/engine/ecs/Entity.spec.js +2 -2
  35. package/src/engine/ecs/EntityBuilderUtils.js +2 -2
  36. package/src/engine/ecs/EntityComponentDataset.js +91 -89
  37. package/src/engine/ecs/EntityFlags.js +4 -4
  38. package/src/engine/ecs/attachment/Attachment.js +5 -2
  39. package/src/engine/ecs/binding/ComponentPropertyBinding.js +13 -13
  40. package/src/engine/ecs/dynamic_actions/RuleExecution.js +1 -1
  41. package/src/engine/ecs/parent/EntityNode.js +2 -2
  42. package/src/engine/ecs/parent/EntityNode.spec.js +2 -2
  43. package/src/engine/ecs/tooltip/testTooltipComponentSystem.js +1 -1
  44. package/src/engine/ecs/util/hideEntityGracefully.js +6 -6
  45. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +1 -0
  46. package/src/engine/graphics/ecs/mesh-v2/render/SGThreeObjectCache.js +30 -7
  47. package/src/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +1 -1
  48. package/src/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +71 -34
  49. package/src/engine/graphics/ecs/mesh-v2/sample/prototype_sg_raycast.js +1 -1
  50. package/src/engine/graphics/ecs/path/PathDisplaySystem.js +4 -4
  51. package/src/engine/graphics/ecs/path/entity/EntityPathMarker.js +1 -1
  52. package/src/engine/graphics/ecs/path/highlight/PathDisplayHighlightSystem.js +3 -3
  53. package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +5 -5
  54. package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +2 -2
  55. package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +1 -1
  56. package/src/engine/graphics/sh3/prototypeSH3Probe.js +2 -2
  57. package/src/engine/intelligence/behavior/ecs/EntityBehavior.js +14 -17
  58. package/src/engine/intelligence/behavior/util/DelayBehavior.js +6 -6
  59. package/src/engine/ui/GUIEngine.js +368 -371
  60. package/src/engine/ui/notification/NotificationManager.js +1 -1
  61. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessor.js +1 -1
  62. package/src/view/tooltip/gml/TooltipParser.js +21 -28
  63. package/src/view/tooltip/gml/compiler/GMLReferenceCompiler.js +3 -2
  64. package/src/core/geom/3d/aabb/aabb3_intersects_ray_branchless.js +0 -52
  65. package/src/core/geom/3d/aabb/aabb3_intersects_ray_fast.js +0 -176
  66. package/src/core/geom/3d/aabb/aabb3_intersects_ray_slab.js +0 -91
@@ -27,7 +27,7 @@ export class SymbolicDisplayInternalAPI {
27
27
 
28
28
  /**
29
29
  *
30
- * @type {List<EntityBuilder>}
30
+ * @type {List<Entity>}
31
31
  * @private
32
32
  */
33
33
  this.__managed_entities = new List();
@@ -56,11 +56,11 @@ export class SymbolicDisplayInternalAPI {
56
56
 
57
57
  /**
58
58
  *
59
- * @param {EntityBuilder} entity
59
+ * @param {Entity} entity
60
60
  */
61
61
  emit(entity) {
62
62
  assert.defined(entity, 'entity');
63
- assert.equal(entity.isEntityBuilder, true, 'entity.isEntityBuilder !== true');
63
+ assert.equal(entity.isEntity, true, 'entity.isEntity !== true');
64
64
 
65
65
  if (entity.getComponent(EditorEntity) === null) {
66
66
  entity.add(new EditorEntity({ referenceEntity: this.__source_entity }));
@@ -40,7 +40,7 @@ export function makeParticleEmitterSymbolicDisplay(engine) {
40
40
  * @param {Transform} transform
41
41
  * @param {number} entity
42
42
  * @param {SymbolicDisplayInternalAPI} api
43
- * @returns {EntityBuilder}
43
+ * @returns {Entity}
44
44
  */
45
45
  function factory([emitter, transform, entity], api) {
46
46
 
@@ -52,7 +52,7 @@ export function makePathSymbolicDisplay(engine) {
52
52
  * @param {Path} path
53
53
  * @param entity
54
54
  * @param {SymbolicDisplayInternalAPI} api
55
- * @return {EntityBuilder}
55
+ * @return {Entity}
56
56
  */
57
57
  function factory([path, entity], api) {
58
58
  const pathObjectMaterial = new LineBasicMaterial({ color: 0xFF0000, opacity: 0.4 });
@@ -38,7 +38,7 @@ export function makeSoundEmitterSymbolicDisplay(engine) {
38
38
  * @param {Transform} transform
39
39
  * @param {number} entity
40
40
  * @param {SymbolicDisplayInternalAPI} api
41
- * @returns {EntityBuilder}
41
+ * @returns {Entity}
42
42
  */
43
43
  function factory([emitter, transform, entity], api) {
44
44
 
@@ -16,7 +16,7 @@ class TopDownCameraControlTool extends Tool {
16
16
 
17
17
  /**
18
18
  *
19
- * @type {EntityBuilder}
19
+ * @type {Entity}
20
20
  * @private
21
21
  */
22
22
  this.__controller = null;
@@ -39,7 +39,7 @@ class TopDownCameraControlTool extends Tool {
39
39
 
40
40
  this.__controller = makeOrbitalCameraController({
41
41
  ecd: ecd,
42
- camera_entity: editor.cameraEntity.entity,
42
+ camera_entity: editor.cameraEntity.id,
43
43
  dom_element: engine.graphics.domElement
44
44
  });
45
45
 
@@ -879,7 +879,7 @@ function intersectObjectWithRay(object, raycaster, includeInvisible = false) {
879
879
 
880
880
  contacts.push({
881
881
  contact,
882
- entity: node.entity.entity,
882
+ entity: node.entity.id,
883
883
  node
884
884
  });
885
885
  }
@@ -58,7 +58,7 @@ async function main(engine) {
58
58
 
59
59
  controls.build(ecd); // add controls to the scene
60
60
  // controls.attach(cube_entity); // make controls target the cube
61
- controls.attach(entityNode.entity.entity); // make controls target the cube
61
+ controls.attach(entityNode.entity.id); // make controls target the cube
62
62
 
63
63
  new Entity()
64
64
  .add(new InputController([{
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "description": "Fully featured ECS game engine written in JavaScript",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.58.0",
8
+ "version": "2.59.1",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -42,7 +42,7 @@
42
42
  "simplex-noise": "2.4.0"
43
43
  },
44
44
  "peerDependencies": {
45
- "three": ">=0.135.0"
45
+ "three": ">=0.135.0 & <0.137.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@babel/core": "7.20.12",
@@ -166,7 +166,7 @@ function prepare_gen_task({
166
166
  // prepare gameplay-specific things on top of the generated level
167
167
 
168
168
  //build minimap
169
- const terrainPreview = generateTerrainPreview(terrainBuilder.entity, ecd);
169
+ const terrainPreview = generateTerrainPreview(terrainBuilder.id, ecd);
170
170
  terrain.preview.copy(terrainPreview);
171
171
  });
172
172
 
@@ -307,7 +307,7 @@ async function main(engine) {
307
307
 
308
308
  EngineHarness.buildLights({ engine });
309
309
  const camera = EngineHarness.buildCamera({ engine });
310
- EngineHarness.buildOrbitalCameraController({ engine, cameraEntity: camera.entity })
310
+ EngineHarness.buildOrbitalCameraController({ engine, cameraEntity: camera.id })
311
311
 
312
312
  await EngineHarness.buildTerrain({ engine });
313
313
 
@@ -1,35 +1,39 @@
1
- import { strictEquals } from "../../function/Functions.js";
2
- import { arrayIndexByEquality } from "./arrayIndexByEquality.js";
1
+ import {strictEquals} from "../../function/Functions.js";
2
+ import {arrayIndexByEquality} from "./arrayIndexByEquality.js";
3
3
 
4
4
  /**
5
+ * Compute a diff between two arrays, result is a 3 way split between common items, unique items in `a` array and unique items in `b` array
5
6
  * @template T
6
7
  * @param {T[]} a
7
8
  * @param {T[]} b
8
- * @param {function(a:T,b:T):boolean} [equals]
9
+ * @param {function(a:T,b:T):boolean} [equals] method to determine equality between two elements
9
10
  * @returns {{uniqueA:T[], uniqueB:T[], common:T[]}}
10
11
  */
11
12
  export function arraySetDiff(a, b, equals = strictEquals) {
13
+ // TODO we can do this faster if we use a comparator instead of equality and pre-sort the data
12
14
  const uniqueA = a.slice();
13
15
  const uniqueB = b.slice();
14
16
 
15
17
  const common = [];
16
18
 
17
- let lA = uniqueA.length;
19
+ let a_length = uniqueA.length;
18
20
 
19
- let i;
20
- for (i = 0; i < lA; i++) {
21
+ for (let i = 0; i < a_length; i++) {
21
22
  const elA = uniqueA[i];
22
23
 
23
24
  const j = arrayIndexByEquality(uniqueB, elA, equals);
24
25
 
25
26
  if (j !== -1) {
27
+ // common element found
28
+
26
29
  common.push(elA);
27
30
 
31
+ // remove from respective unique sets
28
32
  uniqueA.splice(i, 1);
29
33
  uniqueB.splice(j, 1);
30
34
 
31
35
  i--;
32
- lA--;
36
+ a_length--;
33
37
  }
34
38
  }
35
39
 
@@ -0,0 +1,48 @@
1
+ import {aabb3_array_intersects_point} from "./aabb3_array_intersects_point.js";
2
+
3
+ test("", () => {
4
+ expect(aabb3_array_intersects_point([
5
+ 0, 0, 0,
6
+ 0, 0, 0
7
+ ], 0, 0, 0)).toBe(true);
8
+
9
+ expect(aabb3_array_intersects_point([
10
+ 1, 1, 1,
11
+ 2, 2, 2
12
+ ], 0, 0, 0)).toBe(false);
13
+
14
+ expect(aabb3_array_intersects_point([
15
+ 1, 1, 1,
16
+ 2, 2, 2
17
+ ], 1, 0, 0)).toBe(false);
18
+
19
+ expect(aabb3_array_intersects_point([
20
+ 1, 1, 1,
21
+ 2, 2, 2
22
+ ], 0, 1, 0)).toBe(false);
23
+
24
+ expect(aabb3_array_intersects_point([
25
+ 1, 1, 1,
26
+ 2, 2, 2
27
+ ], 0, 0, 1)).toBe(false);
28
+
29
+ expect(aabb3_array_intersects_point([
30
+ 1, 1, 1,
31
+ 2, 2, 2
32
+ ], 2, 0, 0)).toBe(false);
33
+
34
+ expect(aabb3_array_intersects_point([
35
+ 1, 1, 1,
36
+ 2, 2, 2
37
+ ], 0, 2, 0)).toBe(false);
38
+
39
+ expect(aabb3_array_intersects_point([
40
+ 1, 1, 1,
41
+ 2, 2, 2
42
+ ], 0, 0, 2)).toBe(false);
43
+
44
+ expect(aabb3_array_intersects_point([
45
+ 1, 1, 1,
46
+ 2, 2, 2
47
+ ], 1.5, 1.5, 1.5)).toBe(true);
48
+ });
@@ -12,7 +12,11 @@ import { aabb3_intersects_ray } from "./aabb3_intersects_ray.js";
12
12
  * @param {number} direction_y
13
13
  * @param {number} direction_z
14
14
  */
15
- export function aabb3_array_intersects_ray(aabb, origin_x, origin_y, origin_z, direction_x, direction_y, direction_z) {
15
+ export function aabb3_array_intersects_ray(
16
+ aabb,
17
+ origin_x, origin_y, origin_z,
18
+ direction_x, direction_y, direction_z
19
+ ) {
16
20
  return aabb3_intersects_ray(aabb[0], aabb[1], aabb[2], aabb[3], aabb[4], aabb[5],
17
21
  origin_x, origin_y, origin_z,
18
22
  direction_x, direction_y, direction_z
@@ -0,0 +1,16 @@
1
+ import {aabb3_expand_array} from "./aabb3_expand_array.js";
2
+
3
+ test("", () => {
4
+
5
+ const output = [];
6
+
7
+ aabb3_expand_array([
8
+ 1, 3, 5,
9
+ 7, 11, 17
10
+ ], output, 3);
11
+
12
+ expect(output).toEqual([
13
+ -2, 0, 2,
14
+ 10, 14, 20
15
+ ]);
16
+ });
@@ -0,0 +1,37 @@
1
+ import {aabb3_raycast} from "./aabb3_raycast.js";
2
+
3
+ test("basics", () => {
4
+
5
+ const result = [];
6
+
7
+ let hit_found;
8
+
9
+ hit_found = aabb3_raycast(
10
+ result, 0,
11
+ 1, 3, 5,
12
+ 7, 11, 13,
13
+ -1, 4, 6,
14
+ 1, 0, 0
15
+ );
16
+
17
+ expect(hit_found).toBe(true);
18
+ expect(result).toEqual([
19
+ 1, 4, 6,
20
+ -1, 0, 0
21
+ ]);
22
+
23
+ hit_found = aabb3_raycast(
24
+ result, 0,
25
+ 1, 3, 5,
26
+ 7, 11, 13,
27
+ 8, 4, 6,
28
+ -1, 0, 0
29
+ );
30
+
31
+ expect(hit_found).toBe(true);
32
+ expect(result).toEqual([
33
+ 7, 4, 6,
34
+ 1, 0, 0
35
+ ]);
36
+
37
+ });
@@ -1,4 +1,4 @@
1
- import { aabb3_compute_half_surface_area } from "./aabb3_compute_half_surface_area.js";
1
+ import {aabb3_compute_half_surface_area} from "./aabb3_compute_half_surface_area.js";
2
2
 
3
3
  /**
4
4
  * Compute surface area for a box contain both inputs
@@ -7,9 +7,8 @@ import { aabb3_compute_half_surface_area } from "./aabb3_compute_half_surface_ar
7
7
  * @returns {number}
8
8
  */
9
9
  function aabb3_score_boxes_SAH(a, b) {
10
- let x0, y0, z0, x1, y1, z1;
11
-
12
- //
10
+
11
+ // read out bounds
13
12
 
14
13
  const ax0 = a.x0;
15
14
  const ay0 = a.y0;
@@ -25,19 +24,19 @@ function aabb3_score_boxes_SAH(a, b) {
25
24
  const by1 = b.y1;
26
25
  const bz1 = b.z1;
27
26
 
28
- //
27
+ // compute combined bounds
29
28
 
30
- x0 = ax0 < bx0 ? ax0 : bx0;
31
- y0 = ay0 < by0 ? ay0 : by0;
32
- z0 = az0 < bz0 ? az0 : bz0;
29
+ const x0 = ax0 < bx0 ? ax0 : bx0;
30
+ const y0 = ay0 < by0 ? ay0 : by0;
31
+ const z0 = az0 < bz0 ? az0 : bz0;
33
32
 
34
- x1 = ax1 > bx1 ? ax1 : bx1;
35
- y1 = ay1 > by1 ? ay1 : by1;
36
- z1 = az1 > bz1 ? az1 : bz1;
33
+ const x1 = ax1 > bx1 ? ax1 : bx1;
34
+ const y1 = ay1 > by1 ? ay1 : by1;
35
+ const z1 = az1 > bz1 ? az1 : bz1;
37
36
 
38
37
  //
39
38
 
40
39
  return aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1);
41
40
  }
42
41
 
43
- export { aabb3_score_boxes_SAH };
42
+ export {aabb3_score_boxes_SAH};
@@ -0,0 +1,14 @@
1
+ import {AABB3} from "./AABB3.js";
2
+ import {aabb3_score_boxes_SAH} from "./aabb3_score_boxes_SAH.js";
3
+
4
+ test("basics", () => {
5
+
6
+ const value = aabb3_score_boxes_SAH(
7
+ new AABB3(0, 0, 0, 0, 0, 0),
8
+ new AABB3(0, 0, 0, 0, 0, 0)
9
+ );
10
+
11
+ expect(typeof value).toEqual("number");
12
+ expect(value).not.toBeNaN();
13
+
14
+ });
@@ -1,11 +1,11 @@
1
- import { aabb3_build_corners } from "./aabb3_build_corners.js";
2
- import { aabb3_matrix4_project_by_corners } from "./aabb3_matrix4_project_by_corners.js";
3
- import { v3_distance_above_plane } from "../../vec3/v3_distance_above_plane.js";
1
+ import {v3_distance_above_plane} from "../../vec3/v3_distance_above_plane.js";
2
+ import {aabb3_build_corners} from "./aabb3_build_corners.js";
3
+ import {aabb3_matrix4_project_by_corners} from "./aabb3_matrix4_project_by_corners.js";
4
4
 
5
5
  const scratch_corners = new Float32Array(24);
6
6
 
7
7
  /**
8
- *
8
+ * Figure out which side of a plane an Axis-Aligned Bounding Box lies, after applying transform matrix to it
9
9
  * 2,0,or -2; 2: above, -2 : below, 0 : intersects plane
10
10
  * @param {number} x0
11
11
  * @param {number} y0
@@ -25,6 +25,8 @@ export function aabb3_transformed_compute_plane_side(
25
25
  plane_normal_x, plane_normal_y, plane_normal_z, plane_offset,
26
26
  transform_matrix
27
27
  ) {
28
+ // TODO consider transforming the plane instead?
29
+
28
30
 
29
31
  aabb3_build_corners(
30
32
  scratch_corners, 0,
@@ -1,5 +1,5 @@
1
- import { min2 } from "../../../math/min2.js";
2
- import { max2 } from "../../../math/max2.js";
1
+ import {min2} from "../../../math/min2.js";
2
+ import {max2} from "../../../math/max2.js";
3
3
 
4
4
  /**
5
5
  * Multidimensional axis-aligned bounding box calculation
@@ -26,8 +26,11 @@ export function compute_aabb_from_points(
26
26
  }
27
27
 
28
28
  for (i = 0; i < input_count; i++) {
29
+
30
+ const offset_0 = input_count + i * d;
31
+
29
32
  for (j = 0; j < d; j++) {
30
- const v = input[input_count + i * d + j];
33
+ const v = input[offset_0 + j];
31
34
 
32
35
  result[j] = min2(result[j], v);
33
36
  result[j + d] = max2(result[j + d], v);
@@ -1,5 +1,7 @@
1
1
  import {MATRIX_4_IDENTITY} from "./MATRIX_4_IDENTITY.js";
2
2
  import {m4_multiply} from "./m4_multiply.js";
3
+ import {m4_multiply_alphatensor} from "./m4_multiply_alphatensor.js";
4
+ import {number_pretty_print} from "../../../primitives/numbers/number_pretty_print.js";
3
5
 
4
6
  test("identity multiplication", () => {
5
7
 
@@ -8,4 +10,26 @@ test("identity multiplication", () => {
8
10
  m4_multiply(result, MATRIX_4_IDENTITY, MATRIX_4_IDENTITY);
9
11
 
10
12
  expect(result).toEqual(MATRIX_4_IDENTITY);
13
+ });
14
+ test.skip("benchmark 1,000,000", () => {
15
+
16
+ const COUNT = 1000000;
17
+
18
+
19
+ const memory = new ArrayBuffer(16 * 3 * 4);
20
+
21
+ const m0 = new Float32Array(memory, 16 * 4 * 0, 16);
22
+ const m1 = new Float32Array(memory, 16 * 4 * 1, 16);
23
+ const m2 = new Float32Array(memory, 16 * 4 * 2, 16);
24
+
25
+ const t0 = performance.now();
26
+
27
+ for (let i = 0; i < COUNT; i++) {
28
+ m4_multiply(m0, m1, m2);
29
+ }
30
+
31
+ const t1 = performance.now();
32
+
33
+ const span_ms = t1 - t0;
34
+ console.log(`total time ${span_ms}ms, ${ number_pretty_print(COUNT / (span_ms * 1e-3))} Operations/s`)
11
35
  });
@@ -1,45 +1,23 @@
1
1
  /**
2
2
  * Performs 4x4 matrix multiplication using algorithm discovered by AlphaTensor
3
+ * NOTE: currently ~2.5 times slower than {@link m4_multiply}
3
4
  * @see AlphaTensor2022 by Fawzi etAl
4
- * @param {number[]} out
5
- * @param {number[]} a
6
- * @param {number[]} b
5
+ * @param {number[]|Float32Array} out
6
+ * @param {number[]|Float32Array} a
7
+ * @param {number[]|Float32Array} b
7
8
  */
8
9
  export function m4_multiply_alphatensor(out, a, b) {
9
10
  // read out matricies
10
11
  const a11 = a[0];
11
- const a12 = a[1];
12
12
  const a13 = a[2];
13
- const a14 = a[3];
14
- const a21 = a[4];
15
- const a22 = a[5];
16
- const a23 = a[6];
17
- const a24 = a[7];
18
13
  const a31 = a[8];
19
- const a32 = a[9];
20
14
  const a33 = a[10];
21
- const a34 = a[11];
22
- const a41 = a[12];
23
- const a42 = a[13];
24
- const a43 = a[14];
25
- const a44 = a[15];
26
15
 
27
16
  const b11 = b[0];
28
- const b12 = b[1];
29
17
  const b13 = b[2];
30
- const b14 = b[3];
31
- const b21 = b[4];
32
- const b22 = b[5];
33
- const b23 = b[6];
34
- const b24 = b[7];
35
18
  const b31 = b[8];
36
- const b32 = b[9];
37
19
  const b33 = b[10];
38
- const b34 = b[11];
39
- const b41 = b[12];
40
- const b42 = b[13];
41
- const b43 = b[14];
42
- const b44 = b[15];
20
+
43
21
 
44
22
  // apply multiplication algorithm
45
23
  const h1 = (a11 + a31) * (b11 + b31)
@@ -48,6 +26,26 @@ export function m4_multiply_alphatensor(out, a, b) {
48
26
  const h4 = -a33 * -b33
49
27
  const h5 = -a31 * -b13
50
28
  const h6 = (a11 - a13 + a31 - a33) * -b31
29
+
30
+ const b21 = b[4];
31
+ const b22 = b[5];
32
+ const b23 = b[6];
33
+ const b24 = b[7];
34
+ const b41 = b[12];
35
+ const b42 = b[13];
36
+ const b43 = b[14];
37
+ const b44 = b[15];
38
+
39
+ const a21 = a[4];
40
+ const a22 = a[5];
41
+ const a23 = a[6];
42
+ const a24 = a[7];
43
+ const a41 = a[12];
44
+ const a42 = a[13];
45
+ const a43 = a[14];
46
+ const a44 = a[15];
47
+
48
+
51
49
  const h7 = (-a21 + a22 - a23 - a24) * (-b21 + b22 - b23 - b24)
52
50
  const h8 = (-a21 + a22 - a23 - a24 - a41 + a42) * (-b21 + b22 - b23 - b24 - b41 + b42)
53
51
  const h9 = (a11 - a13) * (b11 - b13)
@@ -55,9 +53,24 @@ export function m4_multiply_alphatensor(out, a, b) {
55
53
  const h11 = (a41 - a42) * (-b23 - b24)
56
54
  const h12 = (-a21 + a22 - a23 - a24 - a41 + a42 - a43 - a44) * (b41 - b42)
57
55
  const h13 = (-a23 - a24) * (-b21 + b22 - b23 - b24 - b41 + b42 - b43 - b44)
56
+
57
+ const a12 = a[1];
58
+
59
+ const b12 = b[1];
60
+ const b14 = b[3];
61
+
58
62
  const h14 = (a11 - a12 + a21 - a22) * (-b12 - b14)
63
+
64
+ const a14 = a[3];
65
+
59
66
  const h15 = (-a12 - a14) * -b21
60
67
  const h16 = (a12 + a14 - a21 + a22 + a23 + a24) * (b12 + b14 - b21 + b22 + b23 + b24)
68
+
69
+ const b32 = b[9];
70
+ const b34 = b[11];
71
+ const a32 = a[9];
72
+ const a34 = a[11];
73
+
61
74
  const h17 = (a12 + a14 - a21 + a22 + a23 + a24 + a32 + a41 - a42) * (b12 + b14 - b21 + b22 + b23 + b24 + b32 + b41 - b42)
62
75
  const h18 = (a12 - a21 + a22 + a32 + a41 - a42) * (b12 - b21 + b22 + b32 + b41 - b42)
63
76
  const h19 = (a14 + a23 + a24) * (b12 + b14 - b21 + b22 + b23 + b24 + b32 + b34 + b41 - b42 - b43 - b44)
@@ -91,39 +104,42 @@ export function m4_multiply_alphatensor(out, a, b) {
91
104
  const h47 = (a41 - a43) * (-b13 - b14 - b23 - b24)
92
105
  const h48 = (-a43 - a44) * (-b43 - b44)
93
106
  const h49 = -a23 * (-b31 + b32 + b41 - b42)
107
+
94
108
  const c11 = h1 - h2 - h5 + h9 + h15 + h33
95
109
  const c12 = -h15 - h16 + h17 - h18 - h21 + h22 - h23 + h26 - h33 - h41 + h44 + h49
96
110
  const c13 = h2 + h5 + h6 - h9 - h29 - h33 + h34 + h38
97
111
  const c14 = -h16 + h17 - h20 - h21 + h22 - h23 + h25 + h26 - h29 - h32 - h33 + h34 + h38 - h41 + h42 + h43
98
- const c21 = -h7 + h8 - h10 + h11 - h14 + h15 + h16 - h17 + h18 + h21 - h31 + h33 - h35 - h36
99
- const c22 = h7 - h8 + h10 - h11 - h15 - h16 + h17 - h18 - h21 + h22 - h23 + h26 - h33 + h44
100
- const c23 = -h7 + h8 + h11 + h12 - h16 + h17 - h20 - h21 - h29 - h33 + h34 + h36 + h38 + h46
101
- const c24 = -h7 + h8 + h11 + h12 - h16 + h17 - h20 - h21 + h22 - h23 + h25 + h26 - h29 - h33 + h34 + h38
102
- const c31 = h1 - h2 + h3 - h5 + h33 - h34 + h37 - h40
103
- const c32 = h17 - h18 - h19 - h21 - h23 + h24 + h26 - h33 + h34 - h37 + h40 - h43 + h44 + h45 - h47 + h49
104
- const c33 = h4 + h5 - h29 - h33 + h34 + h40
105
- const c34 = -h21 + h26 - h27 + h28 - h29 - h32 - h33 + h34 + h40 - h47
106
- const c41 = h8 - h10 + h11 - h13 + h17 - h18 - h19 - h21 + h31 - h33 + h34 + h35 + h36 - h37 - h39 + h40
107
- const c42 = -h8 + h10 - h11 + h13 - h17 + h18 + h19 + h21 + h23 - h24 - h26 + h33 - h34 + h37 - h40 - h44
108
- const c43 = h11 + h21 - h28 + h29 + h30 + h33 - h34 - h35 - h36 + h39 - h40 + h48
109
- const c44 = h11 + h21 - h26 + h27 - h28 + h29 + h33 - h34 - h40 + h48
110
112
 
111
- // write out results
112
113
  out[0] = c11;
113
114
  out[1] = c12;
114
115
  out[2] = c13;
115
116
  out[3] = c14;
116
117
 
118
+ const c21 = -h7 + h8 - h10 + h11 - h14 + h15 + h16 - h17 + h18 + h21 - h31 + h33 - h35 - h36
119
+ const c22 = h7 - h8 + h10 - h11 - h15 - h16 + h17 - h18 - h21 + h22 - h23 + h26 - h33 + h44
120
+ const c23 = -h7 + h8 + h11 + h12 - h16 + h17 - h20 - h21 - h29 - h33 + h34 + h36 + h38 + h46
121
+ const c24 = -h7 + h8 + h11 + h12 - h16 + h17 - h20 - h21 + h22 - h23 + h25 + h26 - h29 - h33 + h34 + h38
122
+
117
123
  out[4] = c21;
118
124
  out[5] = c22;
119
125
  out[6] = c23;
120
126
  out[7] = c24;
121
127
 
128
+ const c31 = h1 - h2 + h3 - h5 + h33 - h34 + h37 - h40
129
+ const c32 = h17 - h18 - h19 - h21 - h23 + h24 + h26 - h33 + h34 - h37 + h40 - h43 + h44 + h45 - h47 + h49
130
+ const c33 = h4 + h5 - h29 - h33 + h34 + h40
131
+ const c34 = -h21 + h26 - h27 + h28 - h29 - h32 - h33 + h34 + h40 - h47
132
+
122
133
  out[8] = c31;
123
134
  out[9] = c32;
124
135
  out[10] = c33;
125
136
  out[11] = c34;
126
137
 
138
+ const c41 = h8 - h10 + h11 - h13 + h17 - h18 - h19 - h21 + h31 - h33 + h34 + h35 + h36 - h37 - h39 + h40
139
+ const c42 = -h8 + h10 - h11 + h13 - h17 + h18 + h19 + h21 + h23 - h24 - h26 + h33 - h34 + h37 - h40 - h44
140
+ const c43 = h11 + h21 - h28 + h29 + h30 + h33 - h34 - h35 - h36 + h39 - h40 + h48
141
+ const c44 = h11 + h21 - h26 + h27 - h28 + h29 + h33 - h34 - h40 + h48
142
+
127
143
  out[12] = c41;
128
144
  out[13] = c42;
129
145
  out[14] = c43;
@@ -1,5 +1,6 @@
1
1
  import {m4_multiply_alphatensor} from "./m4_multiply_alphatensor.js";
2
2
  import {MATRIX_4_IDENTITY} from "./MATRIX_4_IDENTITY.js";
3
+ import {number_pretty_print} from "../../../primitives/numbers/number_pretty_print.js";
3
4
 
4
5
  test("identity multiplication", () => {
5
6
 
@@ -8,4 +9,27 @@ test("identity multiplication", () => {
8
9
  m4_multiply_alphatensor(result, MATRIX_4_IDENTITY, MATRIX_4_IDENTITY);
9
10
 
10
11
  expect(result).toEqual(MATRIX_4_IDENTITY);
12
+ });
13
+
14
+ test.skip("benchmark 1,000,000", () => {
15
+
16
+ const COUNT = 1000000;
17
+
18
+
19
+ const memory = new ArrayBuffer(16 * 3 * 4);
20
+
21
+ const m0 = new Float32Array(memory, 16 * 4 * 0, 16);
22
+ const m1 = new Float32Array(memory, 16 * 4 * 1, 16);
23
+ const m2 = new Float32Array(memory, 16 * 4 * 2, 16);
24
+
25
+ const t0 = performance.now();
26
+
27
+ for (let i = 0; i < COUNT; i++) {
28
+ m4_multiply_alphatensor(m0, m1, m2);
29
+ }
30
+
31
+ const t1 = performance.now();
32
+
33
+ const span_ms = t1 - t0;
34
+ console.log(`total time ${span_ms}ms, ${ number_pretty_print(COUNT / (span_ms * 1e-3))} Operations/s`)
11
35
  });
@@ -55,7 +55,7 @@ function composite_shape_to_entity(shape, ecd) {
55
55
 
56
56
  child_entity.add(Attachment.fromJSON({
57
57
  socket: 0,
58
- parent: parent.entity,
58
+ parent: parent.id,
59
59
  immediate: true
60
60
  }));
61
61
 
@@ -127,7 +127,7 @@ function transformed_shape_to_entity(shape, ecd) {
127
127
 
128
128
  const attachment = Attachment.fromJSON({
129
129
  socket: 0,
130
- parent: parent.entity,
130
+ parent: parent.id,
131
131
  immediate: true
132
132
  });
133
133