@woosh/meep-engine 2.35.16 → 2.36.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 (101) hide show
  1. package/core/binary/BinaryBuffer.js +42 -17
  2. package/core/bvh2/BinaryNode.js +1 -1
  3. package/core/bvh2/aabb3/AABB3.js +2 -2
  4. package/core/bvh2/aabb3/aabb3_array_combine.js +20 -0
  5. package/core/bvh2/aabb3/aabb3_array_intersects_frustum_array.js +20 -0
  6. package/core/bvh2/aabb3/aabb3_array_intersects_ray.js +1 -0
  7. package/core/bvh2/aabb3/aabb3_array_intersects_ray_array.js +14 -0
  8. package/core/bvh2/{aabb3_combined_surface_area.js → aabb3/aabb3_combined_surface_area.js} +3 -3
  9. package/core/bvh2/aabb3/aabb3_intersects_frustum_array.js +1 -19
  10. package/core/bvh2/bvh3/BVHNodeProxy.js +53 -0
  11. package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +848 -0
  12. package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.spec.js +142 -0
  13. package/core/bvh2/bvh3/bvh_query_leaves_generic.js +79 -0
  14. package/core/bvh2/bvh3/bvh_query_leaves_ray.js +95 -0
  15. package/core/bvh2/bvh3/query/BVHQuery.js +11 -0
  16. package/core/bvh2/bvh3/query/BVHQueryIntersectsFrustum.js +36 -0
  17. package/core/bvh2/bvh3/query/BVHQueryIntersectsRay.js +36 -0
  18. package/core/collection/array/copyArray.js +2 -2
  19. package/core/collection/table/RowFirstTable.js +25 -7
  20. package/core/collection/table/RowFirstTableSpec.js +4 -4
  21. package/core/geom/3d/aabb/aabb3_matrix4_project.spec.js +1 -1
  22. package/{engine/graphics/util → core/geom/3d/aabb}/computeBoundingBoxFromVertexData.js +1 -1
  23. package/core/geom/3d/compose_matrix4_array.js +53 -0
  24. package/{engine/graphics/util → core/geom/3d}/decompose_matrix_4_array.js +0 -0
  25. package/core/geom/AABB2.d.ts +2 -0
  26. package/core/geom/Vector1.js +2 -3
  27. package/core/geom/Vector3.js +5 -1
  28. package/core/process/undo/ActionProcessor.js +31 -3
  29. package/core/process/undo/ActionProcessor.spec.js +1 -1
  30. package/engine/animation/curve/AnimationCurve.js +40 -1
  31. package/engine/animation/curve/Keyframe.js +19 -0
  32. package/engine/animation/curve/compression/animation_curve_to_float_array.js +35 -0
  33. package/engine/animation/curve/compression/downsample_float_array.js +50 -0
  34. package/engine/animation/curve/compression/downsample_float_array_curve_by_error.js +147 -0
  35. package/engine/animation/curve/compression/downsample_float_array_curve_by_error.spec.js +47 -0
  36. package/engine/animation/curve/compression/prototypeCurveCompression.js +154 -0
  37. package/engine/animation/curve/draw/build_curve_editor.js +316 -0
  38. package/engine/animation/curve/draw/build_plot_entity_from_array.js +47 -0
  39. package/engine/animation/curve/draw/build_tangent_editor.js +115 -0
  40. package/engine/animation/curve/draw/draw_grid.js +27 -0
  41. package/engine/animation/curve/draw/draw_label.js +17 -0
  42. package/engine/animation/curve/draw/plot_array.js +76 -0
  43. package/engine/animation/curve/draw/plot_data.js +49 -0
  44. package/engine/asset/loaders/GLTFAssetLoader.js +3 -0
  45. package/engine/asset/loaders/gltf/GLTFAssetTransformMikkTSpaceTangents.js +27 -0
  46. package/engine/ecs/EntityComponentDataset.js +7 -4
  47. package/engine/ecs/foliage/InstancedFoliage.js +1 -1
  48. package/engine/ecs/foliage/ViewState.js +1 -1
  49. package/engine/ecs/parent/EntityNode.d.ts +7 -3
  50. package/engine/ecs/parent/EntityNode.js +21 -0
  51. package/engine/ecs/parent/entity_node_compute_bounding_box.js +41 -0
  52. package/engine/ecs/transform/Transform.js +2 -2
  53. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts +5 -0
  54. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +46 -12
  55. package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +81 -95
  56. package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +16 -5
  57. package/engine/graphics/ecs/mesh-v2/render/adapters/InstancedRendererAdapter.js +2 -0
  58. package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +1 -0
  59. package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +3 -4
  60. package/engine/graphics/ecs/path/PathDisplaySystem.js +2 -1
  61. package/engine/graphics/ecs/path/testPathDisplaySystem.js +8 -8
  62. package/engine/graphics/ecs/path/tube/CapType.d.ts +5 -0
  63. package/engine/graphics/ecs/path/tube/CapType.js +9 -0
  64. package/engine/graphics/ecs/path/tube/TubePathStyle.d.ts +2 -0
  65. package/engine/graphics/ecs/path/tube/TubePathStyle.js +10 -1
  66. package/engine/graphics/ecs/path/tube/build/GeometryOutput.js +90 -0
  67. package/engine/graphics/ecs/path/tube/build/build_geometry_catmullrom.js +3 -2
  68. package/engine/graphics/ecs/path/tube/build/build_geometry_linear.js +1 -1
  69. package/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +1 -2
  70. package/engine/graphics/ecs/path/tube/build/makeTubeGeometry.js +353 -91
  71. package/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +390 -0
  72. package/engine/graphics/geometry/MikkT/MikkTSpace.js +2210 -0
  73. package/engine/graphics/geometry/MikkT/MikkTSpace.spec.js +22 -0
  74. package/engine/graphics/geometry/MikkT/buffer_geometry_ensure_tangents.js +34 -0
  75. package/engine/graphics/geometry/MikkT/buffer_geometry_generate_tangents.js +28 -0
  76. package/engine/graphics/{compute_geometry_polycount.js → geometry/compute_geometry_polycount.js} +0 -0
  77. package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +34 -3
  78. package/engine/graphics/geometry/skining/computeSkinnedMeshBoundingVolumes.js +1 -1
  79. package/engine/graphics/micron/format/serialization/collection/geometry_collection_serialization.js +83 -0
  80. package/engine/graphics/micron/format/serialization/collection/geometry_collection_serialization.spec.js +24 -0
  81. package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +42 -19
  82. package/engine/graphics/micron/plugin/GLTF_MICRON_ID_FIELD.js +5 -0
  83. package/engine/graphics/micron/plugin/MicronRenderPlugin.js +0 -4
  84. package/engine/graphics/micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js +10 -0
  85. package/engine/graphics/micron/prototypeVirtualGeometry.js +5 -3
  86. package/engine/graphics/micron/render/refinement/ActivePatchList.js +2 -2
  87. package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +2 -2
  88. package/engine/graphics/micron/render/v1/MicronRenderContext.js +0 -6
  89. package/engine/graphics/render/forward_plus/LightManager.js +3 -1
  90. package/engine/graphics/util/composeMatrix4.js +1 -53
  91. package/engine/graphics/util/composeMatrix4RotationScale.js +1 -1
  92. package/engine/intelligence/behavior/ecs/BehaviorComponent.js +1 -1
  93. package/engine/intelligence/blackboard/AbstractBlackboard.js +9 -0
  94. package/engine/notify/Notification.js +1 -1
  95. package/engine/ui/DraggableAspect.js +4 -1
  96. package/engine/ui/notification/ViewEmitter.js +7 -1
  97. package/engine/ui/notification/notificationGenerator.js +1 -1
  98. package/engine/ui/scene/SceneGUIContext.js +11 -130
  99. package/engine/ui/scene/initializeNotifications.js +141 -0
  100. package/package.json +1 -1
  101. package/view/elements/notify/NotificationView.js +1 -2
@@ -213,6 +213,28 @@ export class ActionProcessor {
213
213
 
214
214
  }
215
215
 
216
+ /**
217
+ *
218
+ * @param {M} descriptor
219
+ * @returns {number[]}
220
+ * @private
221
+ */
222
+ __find_mark_indices_by_description(descriptor) {
223
+ const result = [];
224
+
225
+ const marks = this.marks;
226
+ const mark_count = marks.length;
227
+ for (let i = 0; i < mark_count; i++) {
228
+ const mark = marks[i];
229
+
230
+ if (mark.description === descriptor) {
231
+ result.push(i);
232
+ }
233
+ }
234
+
235
+ return result;
236
+ }
237
+
216
238
  /**
217
239
  * Navigate to a specific mark back or forward
218
240
  * @param {M} mark_descriptor specific mark description
@@ -221,7 +243,7 @@ export class ActionProcessor {
221
243
  */
222
244
  navigateTo(mark_descriptor) {
223
245
  // find all matching marks
224
- const matching_marks = this.marks.filter(m => m.description === mark_descriptor);
246
+ const matching_marks = this.__find_mark_indices_by_description(mark_descriptor);
225
247
 
226
248
  if (matching_marks.length === 0) {
227
249
  // not found
@@ -232,9 +254,15 @@ export class ActionProcessor {
232
254
  throw new Error(`Attempting to navigate to a non-unique mark descriptor '${mark_descriptor}'. Mark descriptor must be unique, instead ${matching_marks.length} matches were found`);
233
255
  }
234
256
 
235
- const match = matching_marks[0];
257
+ const match_index = matching_marks[0];
236
258
 
237
- const target = match.index;
259
+ let target;
260
+ if (match_index + 1 >= this.marks.length) {
261
+ // mark is already at the end, go to the end of the history
262
+ target = this.history.length;
263
+ } else {
264
+ target = this.marks[match_index + 1].index;
265
+ }
238
266
 
239
267
  let temp_cursor = this.cursor;
240
268
 
@@ -29,7 +29,7 @@ test('navigateTo backwards', () => {
29
29
 
30
30
  expect(ap.navigateTo('a')).toBe(true);
31
31
 
32
- expect(ctx.value).toBe(0);
32
+ expect(ctx.value).toBe(1);
33
33
  });
34
34
 
35
35
  test('navigateTo forward', () => {
@@ -1,4 +1,5 @@
1
1
  import { inverseLerp } from "../../../core/math/inverseLerp.js";
2
+ import { lerp } from "../../../core/math/lerp.js";
2
3
 
3
4
  /**
4
5
  *
@@ -32,12 +33,18 @@ function evaluate(t, keyframe0, keyframe1) {
32
33
  export class AnimationCurve {
33
34
  constructor() {
34
35
  /**
35
- *
36
+ * @readonly
36
37
  * @type {Keyframe[]}
37
38
  */
38
39
  this.keys = [];
39
40
  }
40
41
 
42
+
43
+ /**
44
+ *
45
+ * @param {number} t
46
+ * @return {number}
47
+ */
41
48
  evaluate(t) {
42
49
  const keys = this.keys;
43
50
  const key_count = keys.length;
@@ -69,4 +76,36 @@ export class AnimationCurve {
69
76
  return keys[key_count - 1].value;
70
77
  }
71
78
 
79
+
80
+ /**
81
+ *
82
+ * @param {number} index
83
+ * @param {number} weight
84
+ */
85
+ smoothTangents(index, weight) {
86
+ const keys = this.keys;
87
+
88
+ const key_main = keys[index];
89
+
90
+ const has_previous = index > 0;
91
+ if (has_previous) {
92
+ const key_previous = keys[index - 1];
93
+
94
+ key_main.inTangent = key_main.value - key_previous.value;
95
+ }
96
+
97
+ const has_next = index < keys.length - 1;
98
+ if (has_next) {
99
+ const key_next = keys[index + 1];
100
+
101
+ key_main.outTangent = key_next.value - key_main.value;
102
+ }
103
+
104
+ if (has_previous && has_next) {
105
+ const average = lerp(key_main.inTangent, key_main.outTangent, 0.5);
106
+ key_main.inTangent = average;
107
+ key_main.outTangent = average;
108
+ }
109
+
110
+ }
72
111
  }
@@ -24,4 +24,23 @@ export class Keyframe {
24
24
  */
25
25
  this.outTangent = 0;
26
26
  }
27
+
28
+ /**
29
+ *
30
+ * @param {number} time
31
+ * @param {number} value
32
+ * @param {number} inTangent
33
+ * @param {number} outTangent
34
+ * @return {Keyframe}
35
+ */
36
+ static from(time, value, inTangent = 0, outTangent = 0) {
37
+ const r = new Keyframe();
38
+
39
+ r.time = time;
40
+ r.value = value;
41
+ r.inTangent = inTangent;
42
+ r.outTangent = outTangent;
43
+
44
+ return r;
45
+ }
27
46
  }
@@ -0,0 +1,35 @@
1
+ //
2
+
3
+
4
+ /**
5
+ * Sample entire animation curve into a flat array with discrete equal intervals
6
+ * @param {number[]|Float32Array} out
7
+ * @param {number} out_offset
8
+ * @param {number} sample_count
9
+ * @param {AnimationCurve} curve
10
+ */
11
+ export function animation_curve_to_float_array(out, curve, out_offset = 0, sample_count = out.length) {
12
+ const keyframes = curve.keys;
13
+ const keyframe_count = keyframes.length;
14
+
15
+ if (keyframe_count === 0) {
16
+ // not data
17
+ out.fill(0, out_offset, out_offset + sample_count);
18
+ return;
19
+ }
20
+
21
+ const key_first = keyframes[0];
22
+ const key_last = keyframes[keyframe_count - 1];
23
+
24
+ const time_start = key_first.time;
25
+ const time_end = key_last.time;
26
+ const time_span = time_end - time_start;
27
+
28
+ for (let i = 0; i < sample_count; i++) {
29
+ const f = i / (sample_count - 1);
30
+
31
+ const t = time_start + (f * time_span);
32
+
33
+ out[i + out_offset] = curve.evaluate(t);
34
+ }
35
+ }
@@ -0,0 +1,50 @@
1
+ //
2
+
3
+ import { assert } from "../../../../core/assert.js";
4
+ import { lerp } from "../../../../core/math/lerp.js";
5
+
6
+ /**
7
+ *
8
+ * @param {number[]|Float32Array} output
9
+ * @param {number} output_offset
10
+ * @param {number[]|Float32Array} input
11
+ * @param {number} input_offset
12
+ * @param {number} input_size
13
+ */
14
+ export function downsample_float_array(output, output_offset, input, input_offset, input_size) {
15
+ assert.isNonNegativeInteger(output_offset, 'output_offset');
16
+ assert.isNonNegativeInteger(input_offset, 'input_offset');
17
+ assert.isNonNegativeInteger(input_size, 'input_size');
18
+
19
+ const target_samples = input_size / 2;
20
+
21
+ if (!Number.isInteger(target_samples)) {
22
+ throw new Error(`input_size(=${input_size}) is not divisible by 2`);
23
+ }
24
+
25
+ if (target_samples === 1) {
26
+ // special case, take average
27
+ output[output_offset] = (
28
+ input[input_offset] + input[input_offset + 1]
29
+ ) / 2;
30
+
31
+ return;
32
+ }
33
+
34
+ let i = 0;
35
+ for (; i < target_samples; i++) {
36
+
37
+ const f = i / (target_samples - 1);
38
+
39
+ const input_sample_offset = input_offset + i * 2;
40
+
41
+ const s0 = input[input_sample_offset];
42
+ const s1 = input[input_sample_offset + 1];
43
+
44
+ const sample_value = lerp(s0, s1, f);
45
+
46
+ // TODO implement decision scheme that would pick between min/max/average
47
+
48
+ output[output_offset + i] = sample_value;
49
+ }
50
+ }
@@ -0,0 +1,147 @@
1
+ //
2
+
3
+
4
+ import { max2 } from "../../../../core/math/max2.js";
5
+ import { lerp } from "../../../../core/math/lerp.js";
6
+ import { min3 } from "../../../../core/math/min3.js";
7
+ import { max3 } from "../../../../core/math/max3.js";
8
+ import { downsample_float_array } from "./downsample_float_array.js";
9
+ import { array_copy } from "../../../../core/collection/array/copyArray.js";
10
+ import { isPowerOfTwo } from "../../../../core/math/isPowerOrTwo.js";
11
+
12
+ /**
13
+ *
14
+ * @param {number[]} input
15
+ * @param {number} input_offset
16
+ * @param {number} input_size
17
+ * @param {number} f
18
+ * @return {number}
19
+ */
20
+ function array_sampler_linear(input, input_offset, input_size, f) {
21
+ const t = f * (input_size - 1);
22
+
23
+ const fraction = t % 1;
24
+
25
+ if (fraction === 0) {
26
+ return input[input_offset + t];
27
+ }
28
+
29
+ const i0 = Math.floor(t);
30
+ const i1 = i0 + 1;
31
+
32
+ const s0 = input[input_offset + i0];
33
+ const s1 = input[input_offset + i1];
34
+
35
+ return lerp(s0, s1, fraction);
36
+ }
37
+
38
+ /**
39
+ *
40
+ * @param {number[]|Float32Array} input0
41
+ * @param {number} input0_offset
42
+ * @param {number} input0_size
43
+ * @param {number[]|Float32Array} input1
44
+ * @param {number} input1_offset
45
+ * @param {number} input1_size
46
+ */
47
+ function compute_float_array_curve_linear_sampling_relative_error(
48
+ input0, input0_offset, input0_size,
49
+ input1, input1_offset, input1_size
50
+ ) {
51
+
52
+ const largest_size = max2(input0_size, input1_size);
53
+
54
+ let max_error = 0;
55
+
56
+ let min = Number.POSITIVE_INFINITY;
57
+ let max = Number.NEGATIVE_INFINITY;
58
+
59
+ for (let i = 0; i < largest_size; i++) {
60
+ const f = i / (largest_size - 1);
61
+
62
+ const s0 = array_sampler_linear(input0, input0_offset, input0_size, f);
63
+ const s1 = array_sampler_linear(input1, input1_offset, input1_size, f);
64
+
65
+ const error = Math.abs(s0 - s1);
66
+
67
+ if (error > max_error) {
68
+ max_error = error;
69
+ }
70
+
71
+ min = min3(min, s0, s1);
72
+ max = max3(max, s0, s1);
73
+ }
74
+
75
+ const span = max - min;
76
+
77
+ if (span === 0) {
78
+ // avoid division by 0
79
+ return 0;
80
+ }
81
+
82
+ return max_error / span;
83
+ }
84
+
85
+ /**
86
+ *
87
+ * @param {number[]} output
88
+ * @param {number} output_offset
89
+ * @param {number[]} input
90
+ * @param {number} input_offset
91
+ * @param {number} input_size
92
+ * @param {number} [error]
93
+ * @return {number}
94
+ */
95
+ export function downsample_float_array_curve_by_error(output, output_offset, input, input_offset, input_size, error = 0.03) {
96
+ if (!isPowerOfTwo(input_size)) {
97
+ throw new Error(`Input size must be a power of two, instead was '${input_size}'`);
98
+ }
99
+
100
+ const buffer_0 = new Float32Array(input_size >>> 1); // first step needs half the size of the original buffer
101
+ const buffer_1 = new Float32Array(input_size >>> 2); // next step needs quarter
102
+
103
+ let current = input;
104
+ let current_offset = input_offset;
105
+ let current_size = input_size;
106
+
107
+ let next = buffer_0;
108
+ let next_offset = 0;
109
+ let next_size = buffer_0.length;
110
+
111
+ let current_error = 0;
112
+
113
+ while (current_error <= error && current_size > 1) {
114
+ downsample_float_array(next, next_offset, current, current_offset, current_size);
115
+
116
+ current_error = compute_float_array_curve_linear_sampling_relative_error(
117
+ input, input_offset, input_size,
118
+ next, next_offset, next_size
119
+ );
120
+
121
+ if (current_error > error) {
122
+ // reached best possible reduction
123
+ break;
124
+ }
125
+
126
+ current = next;
127
+ current_offset = next_offset;
128
+ current_size = next_size;
129
+
130
+ // perform swap
131
+ if (next === buffer_0) {
132
+ next = buffer_1;
133
+ } else {
134
+ next = buffer_0;
135
+ }
136
+
137
+ next_offset = 0;
138
+ // next will be half the current size
139
+ next_size = current_size >>> 1;
140
+ }
141
+
142
+
143
+ // copy current buffer to output
144
+ array_copy(current, current_offset, output, output_offset, current_size);
145
+
146
+ return current_size;
147
+ }
@@ -0,0 +1,47 @@
1
+ import { downsample_float_array_curve_by_error } from "./downsample_float_array_curve_by_error.js";
2
+
3
+ test('1 constant to 1', () => {
4
+ const output = [];
5
+
6
+ const sample_count = downsample_float_array_curve_by_error(output, 0, [1], 0, 1, 0.1);
7
+
8
+ expect(sample_count).toBe(1);
9
+ expect(output[0]).toBe(1);
10
+ });
11
+
12
+ test('4 constants to 1', () => {
13
+ const output = [];
14
+
15
+ const sample_count = downsample_float_array_curve_by_error(output, 0, [1, 1, 1, 1], 0, 4, 0.1);
16
+
17
+ expect(sample_count).toBe(1);
18
+ expect(output[0]).toBe(1);
19
+ });
20
+
21
+ test('2 constants to 1 with error = 0', () => {
22
+ const output = [];
23
+
24
+ const sample_count = downsample_float_array_curve_by_error(output, 0, [1, 1], 0, 2, 0);
25
+
26
+ expect(sample_count).toBe(1);
27
+ expect(output[0]).toBe(1);
28
+ });
29
+
30
+ test('2 different constants to 2', () => {
31
+ const output = [];
32
+
33
+ const sample_count = downsample_float_array_curve_by_error(output, 0, [1, 2], 0, 2, 0.1);
34
+
35
+ expect(sample_count).toBe(2);
36
+ expect(output).toEqual([1, 2]);
37
+ });
38
+
39
+ test('4 to 2, linear scale compression', () => {
40
+ const output = [];
41
+
42
+ const sample_count = downsample_float_array_curve_by_error(output, 0, [1, 2, 3, 4], 0, 4, 0.1);
43
+
44
+ expect(sample_count).toBe(2);
45
+ expect(output[0]).toBeCloseTo(1);
46
+ expect(output[1]).toBeCloseTo(4);
47
+ });
@@ -0,0 +1,154 @@
1
+ import { EngineHarness } from "../../../EngineHarness.js";
2
+ import { AnimationCurve } from "../AnimationCurve.js";
3
+ import { Keyframe } from "../Keyframe.js";
4
+ import { EngineConfiguration } from "../../../EngineConfiguration.js";
5
+ import GUIElementSystem from "../../../ecs/gui/GUIElementSystem.js";
6
+ import ViewportPositionSystem from "../../../ecs/gui/position/ViewportPositionSystem.js";
7
+ import { animation_curve_to_float_array } from "./animation_curve_to_float_array.js";
8
+ import { downsample_float_array_curve_by_error } from "./downsample_float_array_curve_by_error.js";
9
+ import { build_plot_entity_from_array } from "../draw/build_plot_entity_from_array.js";
10
+
11
+ const eh = new EngineHarness();
12
+
13
+ async function init() {
14
+
15
+ const config = new EngineConfiguration();
16
+
17
+ const engine = eh.engine;
18
+
19
+ config.addSystem(new GUIElementSystem(engine.gameView, engine));
20
+ config.addSystem(new ViewportPositionSystem(engine.gameView.size));
21
+
22
+ await config.apply(engine);
23
+
24
+ await eh.initialize();
25
+
26
+ main(engine);
27
+ }
28
+
29
+ function build_error_scale(ecd, curve) {
30
+ const curve_data = [];
31
+ animation_curve_to_float_array(curve_data, curve, 0, 256);
32
+
33
+
34
+ build_plot_entity_from_array({
35
+ data: curve_data,
36
+ x: 10, y: 0
37
+ }).build(ecd);
38
+
39
+ const compressed_01 = [];
40
+ downsample_float_array_curve_by_error(compressed_01, 0, curve_data, 0, curve_data.length, 0.01);
41
+
42
+ build_plot_entity_from_array({
43
+ data: compressed_01,
44
+ x: 10, y: 202,
45
+ label: '1%'
46
+ }).build(ecd);
47
+
48
+ const compressed_03 = [];
49
+ downsample_float_array_curve_by_error(compressed_03, 0, curve_data, 0, curve_data.length, 0.03);
50
+
51
+ build_plot_entity_from_array({
52
+ data: compressed_03,
53
+ x: 10, y: 404,
54
+ label: '3%'
55
+ }).build(ecd);
56
+
57
+ const compressed_05 = [];
58
+ downsample_float_array_curve_by_error(compressed_05, 0, curve_data, 0, curve_data.length, 0.05);
59
+
60
+ build_plot_entity_from_array({
61
+ data: compressed_05,
62
+ x: 10, y: 606,
63
+ label: '5%'
64
+ }).build(ecd);
65
+
66
+ const compressed_10 = [];
67
+ downsample_float_array_curve_by_error(compressed_10, 0, curve_data, 0, curve_data.length, 0.10);
68
+
69
+ build_plot_entity_from_array({
70
+ data: compressed_10,
71
+ x: 10, y: 808,
72
+ label: '10%'
73
+ }).build(ecd);
74
+ }
75
+
76
+ async function main(engine) {
77
+
78
+ // EngineHarness.buildBasics({ engine });
79
+ function sample_curve_0() {
80
+
81
+ const curve = new AnimationCurve();
82
+
83
+ curve.keys.push(Keyframe.from(0, 0));
84
+ curve.keys.push(Keyframe.from(1, 1));
85
+ curve.keys.push(Keyframe.from(2, 0.5));
86
+
87
+ return curve;
88
+ }
89
+
90
+ function sample_curve_1() {
91
+
92
+ const curve = new AnimationCurve();
93
+
94
+ curve.keys.push(Keyframe.from(0, 0));
95
+ curve.keys.push(Keyframe.from(0.1, 1));
96
+ curve.keys.push(Keyframe.from(2, 0.5));
97
+
98
+ return curve;
99
+ }
100
+
101
+ function sample_curve_2() {
102
+
103
+ const curve = new AnimationCurve();
104
+
105
+ curve.keys.push(Keyframe.from(0, 1));
106
+ curve.keys.push(Keyframe.from(1, 2));
107
+ curve.keys.push(Keyframe.from(2, 3));
108
+ curve.keys.push(Keyframe.from(3, 4));
109
+
110
+ return curve;
111
+ }
112
+
113
+ function sample_curve_3() {
114
+
115
+ const curve = new AnimationCurve();
116
+
117
+ curve.keys.push(Keyframe.from(0, 1));
118
+ curve.keys.push(Keyframe.from(1, 1));
119
+ curve.keys.push(Keyframe.from(2, 1));
120
+ curve.keys.push(Keyframe.from(3, 1));
121
+
122
+ return curve;
123
+ }
124
+
125
+ function sample_curve_4() {
126
+
127
+ const curve = new AnimationCurve();
128
+
129
+ curve.keys.push(Keyframe.from(0, 1, 0, 1));
130
+ // curve.keys.push(Keyframe.from(1, 2, 1, -1));
131
+ curve.keys.push(Keyframe.from(1, 2, -1, 1));
132
+ curve.keys.push(Keyframe.from(2, 1));
133
+
134
+ return curve;
135
+ }
136
+
137
+ const curve = sample_curve_2();
138
+
139
+ const ecd = engine.entityManager.dataset;
140
+
141
+ build_error_scale(ecd, curve);
142
+
143
+ // const editor_view = build_curve_editor({ curve });
144
+ //
145
+ // new EntityBuilder()
146
+ // .add(ViewportPosition.fromJSON({
147
+ // offset: { x: 0, y: 0 }
148
+ // }))
149
+ // .add(GUIElement.fromView(editor_view))
150
+ // .build(ecd);
151
+
152
+ }
153
+
154
+ init();