@woosh/meep-engine 2.75.8 → 2.75.9

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 (77) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/build/meep.cjs +784 -982
  3. package/build/meep.min.js +1 -1
  4. package/build/meep.module.js +784 -982
  5. package/editor/actions/concrete/ModifyPatchSampler2DAction.js +6 -3
  6. package/editor/actions/concrete/PatchTerrainTextureAction.js +6 -3
  7. package/editor/process/EditorProcess.js +12 -16
  8. package/editor/process/ProcessEngine.js +9 -10
  9. package/package.json +1 -1
  10. package/src/core/binary/dec2hex.js +1 -1
  11. package/src/{engine/ecs/ik/IKMath.js → core/geom/vec3/v3_computeOffsetVector.js} +1 -1
  12. package/src/core/math/newton_solver_1d.js +13 -4
  13. package/src/core/math/solveQuadratic.js +5 -3
  14. package/src/core/math/spline/catmull_rom_compute_T.js +19 -0
  15. package/src/{engine/navigation/ecs/components → core/math/spline}/computeCatmullRomSpline.js +3 -3
  16. package/src/{engine/navigation/ecs/components → core/math/spline}/computeCatmullRomSplineUniformDistance.js +3 -3
  17. package/src/core/math/spline/computeNonuniformCatmullRomSplineSample.js +109 -0
  18. package/src/core/math/spline/interpolate_bicubic.js +12 -0
  19. package/src/core/math/spline/spline_catmullrom_1d.js +120 -0
  20. package/src/engine/control/ControlContext.js +25 -27
  21. package/src/engine/ecs/EntityManager.js +12 -9
  22. package/src/engine/ecs/EntityObserver.js +26 -22
  23. package/src/engine/ecs/binding/ComponentPropertyPath.js +12 -12
  24. package/src/engine/ecs/components/Motion.js +5 -7
  25. package/src/engine/ecs/components/SerializationMetadata.js +5 -3
  26. package/src/engine/ecs/dynamic_actions/actions/definition/AbstractActionDescription.js +0 -2
  27. package/src/engine/ecs/dynamic_actions/actions/definition/ActionSequenceDescription.js +7 -9
  28. package/src/engine/ecs/dynamic_actions/actions/definition/DelayActionDescription.js +3 -5
  29. package/src/engine/ecs/dynamic_actions/actions/definition/SendRequestActionDescription.js +6 -8
  30. package/src/engine/ecs/dynamic_actions/actions/definition/SpeakLineActionDescription.js +14 -17
  31. package/src/engine/ecs/dynamic_actions/actions/definition/WeightedRandomActionDescription.js +8 -11
  32. package/src/engine/ecs/dynamic_actions/actions/definition/WriteToBlackboardActionDescription.js +15 -18
  33. package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +7 -7
  34. package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +6 -6
  35. package/src/engine/ecs/parent/EntityNode.js +39 -37
  36. package/src/engine/ecs/speaker/VoiceSystem.js +36 -39
  37. package/src/engine/ecs/system/SystemEntityContext.js +25 -23
  38. package/src/engine/ecs/tag/find_entities_with_tag.js +18 -0
  39. package/src/engine/ecs/terrain/TerrainClouds.js +23 -24
  40. package/src/engine/ecs/terrain/ecs/splat/SplatMapMaterialPatch.js +5 -2
  41. package/src/engine/ecs/terrain/overlay/TerrainOverlay.js +15 -14
  42. package/src/engine/ecs/tooltip/TooltipComponent.js +6 -7
  43. package/src/engine/graphics/camera/testClippingPlaneComputation.js +0 -4
  44. package/src/engine/graphics/ecs/path/testPathDisplaySystem.js +1 -5
  45. package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +2 -6
  46. package/src/engine/graphics/ecs/water2/shader/testWaterShader.js +12 -14
  47. package/src/engine/graphics/material/optimization/MaterialOptimizationContext.js +22 -20
  48. package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +3 -4
  49. package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +0 -4
  50. package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +0 -4
  51. package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +0 -4
  52. package/src/engine/graphics/shadows/testShadowMapRendering.js +0 -2
  53. package/src/engine/graphics/texture/atlas/TextureAtlas.js +13 -11
  54. package/src/engine/graphics/texture/sampler/Sampler2D.js +15 -366
  55. package/src/engine/graphics/texture/sampler/Sampler2D.spec.js +0 -31
  56. package/src/engine/graphics/texture/sampler/sampler2d_copy_with_margins.js +166 -0
  57. package/src/engine/graphics/texture/sampler/sampler2d_copy_with_margins.spec.js +31 -0
  58. package/src/engine/graphics/texture/sampler/sampler2d_paint.js +81 -0
  59. package/src/engine/graphics/texture/sampler/sampler2d_sub_copy_same_item_size.js +50 -0
  60. package/src/engine/navigation/ecs/components/Path.js +10 -9
  61. package/src/engine/physics/computeInterceptPoint.js +44 -0
  62. package/src/engine/plugin/EnginePlugin.js +1 -2
  63. package/src/engine/ecs/components/AlignToVelocity.js +0 -9
  64. package/src/engine/ecs/components/CharacterController.js +0 -31
  65. package/src/engine/ecs/components/PhysicalBody.js +0 -51
  66. package/src/engine/ecs/components/Steering.js +0 -111
  67. package/src/engine/ecs/components/SteeringSerializationAdapter.js +0 -34
  68. package/src/engine/ecs/systems/AlignToVelocitySystem.js +0 -51
  69. package/src/engine/ecs/systems/CharacterControlSystem.js +0 -134
  70. package/src/engine/ecs/systems/PhysicsSystem.js +0 -89
  71. package/src/engine/ecs/systems/PropertySetSystem.js +0 -18
  72. package/src/engine/ecs/systems/SteeringSystem.js +0 -171
  73. package/src/engine/ecs/systems/TagSystem.d.ts +0 -5
  74. package/src/engine/ecs/systems/TagSystem.js +0 -31
  75. package/src/engine/graphics/texture/sampler/bicubic.js +0 -59
  76. package/src/engine/graphics/texture/sampler/bicubic.spec.js +0 -13
  77. package/src/engine/navigation/ecs/components/computeNonuniformCatmullRomSplineSample.js +0 -242
@@ -3,20 +3,20 @@
3
3
  */
4
4
 
5
5
 
6
- import { clamp } from "../../../../core/math/clamp.js";
7
- import { max2 } from "../../../../core/math/max2.js";
8
- import { min2 } from "../../../../core/math/min2.js";
9
- import { mix } from "../../../../core/math/mix.js";
10
- import { BlendingType } from "./BlendingType.js";
11
6
  import { assert } from "../../../../core/assert.js";
12
- import { typedArrayConstructorByInstance } from "./typedArrayConstructorByInstance.js";
13
- import { typedArrayToDataType } from "../../../../core/collection/array/typed/typedArrayToDataType.js";
7
+ import { Base64 } from "../../../../core/binary/Base64.js";
14
8
  import {
15
9
  compute_typed_array_constructor_from_data_type
16
10
  } from "../../../../core/binary/type/DataType2TypedArrayConstructorMapping.js";
17
- import { Base64 } from "../../../../core/binary/Base64.js";
18
- import { computeStridedIntegerArrayHash } from "../../../../core/primitives/array/computeStridedIntegerArrayHash.js";
19
11
  import { is_typed_array_equals } from "../../../../core/collection/array/typed/is_typed_array_equals.js";
12
+ import { typedArrayToDataType } from "../../../../core/collection/array/typed/typedArrayToDataType.js";
13
+ import { clamp } from "../../../../core/math/clamp.js";
14
+ import { max2 } from "../../../../core/math/max2.js";
15
+ import { min2 } from "../../../../core/math/min2.js";
16
+ import { mix } from "../../../../core/math/mix.js";
17
+ import { interpolate_bicubic } from "../../../../core/math/spline/interpolate_bicubic.js";
18
+ import { computeStridedIntegerArrayHash } from "../../../../core/primitives/array/computeStridedIntegerArrayHash.js";
19
+ import { typedArrayConstructorByInstance } from "./typedArrayConstructorByInstance.js";
20
20
 
21
21
  /**
22
22
  * Data Texture class, providing an abstraction around 2d numerical arrays, mostly for sampling purposes
@@ -82,35 +82,6 @@ export class Sampler2D {
82
82
  this.version = 0;
83
83
  }
84
84
 
85
- /**
86
- * @deprecated
87
- * @param {number} [channel=0]
88
- * @returns {{x: number, index: number, y: number, value: number}}
89
- */
90
- computeMax(channel = 0) {
91
- throw new Error("deprecated, use sampler2d_channel_compute_max");
92
- }
93
-
94
- /**
95
- * @deprecated
96
- * @param {number[]} result
97
- * @param {number} result_offset
98
- * @param {number} [channel=0]
99
- * @returns {number} number of matches written to result array
100
- */
101
- computeMinIndices(result, result_offset = 0, channel = 0) {
102
- throw new Error("deprecated, use sampler2d_channel_compute_min_indices")
103
- }
104
-
105
- /**
106
- * @deprecated
107
- * @param {number} [channel=0]
108
- * @returns {{x: number, index: number, y: number, value: number}}
109
- */
110
- computeMin(channel = 0) {
111
- throw new Error("deprecated, use sampler2d_channel_compute_min");
112
- }
113
-
114
85
  /**
115
86
  *
116
87
  * @deprecated
@@ -120,18 +91,7 @@ export class Sampler2D {
120
91
  * @returns {number}
121
92
  */
122
93
  get(x, y, result) {
123
- console.warn("Deprecated method, use sampleBilinear instead");
124
-
125
- const t = [];
126
-
127
- this.sampleBilinear(x, y, t, 0);
128
-
129
- if (result !== undefined) {
130
- result.readFromArray(t, 0);
131
- return result;
132
- } else {
133
- return t[0];
134
- }
94
+ throw new Error("Deprecated method, use sampleBilinear instead");
135
95
  }
136
96
 
137
97
  /**
@@ -334,23 +294,14 @@ export class Sampler2D {
334
294
  const vl2 = data[row3_address + col2_offset];
335
295
  const vl3 = data[row3_address + col3_offset];
336
296
 
337
-
338
- // return bicubic(xd, yd,
339
- // vi0, vi1, vi2, vi3,
340
- // vj0, vj1, vj2, vj3,
341
- // vk0, vk1, vk2, vk3,
342
- // vl0, vl1, vl2, vl3,
343
- // );
344
-
345
-
346
297
  // perform filtering in X (rows)
347
- const s0 = bicubic_terp(xd, vi0, vi1, vi2, vi3);
348
- const s1 = bicubic_terp(xd, vj0, vj1, vj2, vj3);
349
- const s2 = bicubic_terp(xd, vk0, vk1, vk2, vk3);
350
- const s3 = bicubic_terp(xd, vl0, vl1, vl2, vl3);
298
+ const s0 = interpolate_bicubic(xd, vi0, vi1, vi2, vi3);
299
+ const s1 = interpolate_bicubic(xd, vj0, vj1, vj2, vj3);
300
+ const s2 = interpolate_bicubic(xd, vk0, vk1, vk2, vk3);
301
+ const s3 = interpolate_bicubic(xd, vl0, vl1, vl2, vl3);
351
302
 
352
303
  // filter in Y (columns)
353
- return bicubic_terp(yd, s0, s1, s2, s3);
304
+ return interpolate_bicubic(yd, s0, s1, s2, s3);
354
305
  }
355
306
 
356
307
  /**
@@ -589,162 +540,6 @@ export class Sampler2D {
589
540
  result.set(x, y);
590
541
  }
591
542
 
592
- /**
593
- * Copy a patch from another sampler with a margin.
594
- * This is useful for texture rendering where filtering can cause bleeding along the edges of the patch.
595
- * @param {Sampler2D} source where to copy from
596
- * @param {Number} sourceX where to start reading from, X coordinate
597
- * @param {Number} sourceY where to start reading from, X coordinate
598
- * @param {Number} destinationX where to start writing to, X coordinate
599
- * @param {Number} destinationY where to start writing to, X coordinate
600
- * @param {Number} width size of the patch that is to be copied
601
- * @param {Number} height size of the patch that is to be copied
602
- * @param {Number} marginLeft
603
- * @param {Number} marginRight
604
- * @param {Number} marginTop
605
- * @param {Number} marginBottom
606
- */
607
- copyWithMargin(source, sourceX, sourceY, destinationX, destinationY, width, height, marginLeft, marginRight, marginTop, marginBottom) {
608
- const dItemSize = this.itemSize;
609
- const sItemSize = source.itemSize;
610
- const _itemSize = Math.min(dItemSize, sItemSize);
611
-
612
-
613
- const dRowSize = dItemSize * this.width;
614
- const sRowSize = sItemSize * source.width;
615
-
616
- const sData = source.data;
617
- const dData = this.data;
618
-
619
- let x, y, i, j;
620
-
621
- let xMax, yMax;
622
-
623
- let dA, sA, dOffset, sOffset;
624
- //Write top-left corner
625
- sOffset = sourceY * sRowSize + sourceX * dItemSize;
626
- for (y = Math.max(0, destinationY - marginTop), yMax = destinationY; y < yMax; y++) {
627
- dA = y * dRowSize;
628
-
629
- for (x = Math.max(0, destinationX - marginLeft), xMax = destinationX; x < xMax; x++) {
630
-
631
- dOffset = dA + x * dItemSize;
632
-
633
- for (i = 0; i < _itemSize; i++) {
634
- dData[dOffset + i] = sData[sOffset + i];
635
- }
636
- }
637
- }
638
- //Write top margin
639
- sA = sourceY * sRowSize;
640
- for (y = Math.max(0, destinationY - marginTop), yMax = destinationY; y < yMax; y++) {
641
- dA = y * dRowSize;
642
-
643
- for (x = 0; x < width; x++) {
644
-
645
- dOffset = dA + (x + destinationX) * dItemSize;
646
- sOffset = sA + (x + sourceX) * dItemSize;
647
- for (i = 0; i < _itemSize; i++) {
648
- dData[dOffset + i] = sData[sOffset + i];
649
- }
650
- }
651
- }
652
- //Write top-right corner
653
- sOffset = sourceY * sRowSize + (sourceX + width - 1) * dItemSize;
654
- for (y = Math.max(0, destinationY - marginTop), yMax = destinationY; y < yMax; y++) {
655
- dA = y * dRowSize;
656
-
657
- for (x = destinationX + width, xMax = Math.min(this.width, x + marginRight); x < xMax; x++) {
658
-
659
- dOffset = dA + x * dItemSize;
660
-
661
- for (i = 0; i < _itemSize; i++) {
662
- dData[dOffset + i] = sData[sOffset + i];
663
- }
664
- }
665
- }
666
- //Write left margin
667
- for (y = 0; y < height; y++) {
668
- dA = (y + destinationY) * dRowSize;
669
- sA = (y + sourceY) * sRowSize;
670
-
671
- sOffset = sA + (sourceX) * dItemSize;
672
-
673
- for (x = Math.max(0, destinationX - marginLeft), xMax = destinationX; x < xMax; x++) {
674
-
675
- dOffset = dA + x * dItemSize;
676
-
677
- for (i = 0; i < _itemSize; i++) {
678
- dData[dOffset + i] = sData[sOffset + i];
679
- }
680
- }
681
- }
682
- //write actual patch
683
- this.copy(source, sourceX, sourceY, destinationX, destinationY, width, height);
684
-
685
- //Write right margin
686
- for (y = 0; y < height; y++) {
687
- dA = (y + destinationY) * dRowSize;
688
- sA = (y + sourceY) * sRowSize;
689
-
690
- sOffset = sA + (sourceX + width - 1) * dItemSize;
691
-
692
- for (x = destinationX + width, xMax = Math.min(this.width, x + marginRight); x < xMax; x++) {
693
-
694
- dOffset = dA + x * dItemSize;
695
-
696
- for (i = 0; i < _itemSize; i++) {
697
- dData[dOffset + i] = sData[sOffset + i];
698
- }
699
- }
700
- }
701
-
702
- //Write Bottom-left margin
703
- sOffset = (sourceY + height - 1) * sRowSize + sourceX * dItemSize;
704
- for (y = destinationY + width, yMax = Math.min(this.height, y + marginBottom); y < yMax; y++) {
705
- dA = y * dRowSize;
706
-
707
- for (x = Math.max(0, destinationX - marginLeft), xMax = destinationX; x < xMax; x++) {
708
-
709
- dOffset = dA + x * dItemSize;
710
-
711
- for (i = 0; i < _itemSize; i++) {
712
- dData[dOffset + i] = sData[sOffset + i];
713
- }
714
- }
715
- }
716
- //Write Bottom margin
717
- sA = (sourceY + height - 1) * sRowSize;
718
- for (y = destinationY + width, yMax = Math.min(this.height, y + marginBottom); y < yMax; y++) {
719
- dA = y * dRowSize;
720
-
721
- for (x = 0; x < width; x++) {
722
-
723
- dOffset = dA + (x + destinationX) * dItemSize;
724
- sOffset = sA + (x + sourceX) * dItemSize;
725
- for (i = 0; i < _itemSize; i++) {
726
- dData[dOffset + i] = sData[sOffset + i];
727
- }
728
- }
729
- }
730
- //Write Bottom-right margin
731
- sOffset = (sourceY + height - 1) * sRowSize + (sourceX + width - 1) * dItemSize;
732
- for (y = destinationY + width, yMax = Math.min(this.height, y + marginBottom); y < yMax; y++) {
733
- dA = y * dRowSize;
734
-
735
- for (x = destinationX + width, xMax = Math.min(this.width, x + marginRight); x < xMax; x++) {
736
-
737
- dOffset = dA + x * dItemSize;
738
-
739
- for (i = 0; i < _itemSize; i++) {
740
- dData[dOffset + i] = sData[sOffset + i];
741
- }
742
- }
743
- }
744
-
745
- this.version++;
746
- }
747
-
748
543
  /**
749
544
  * Copy a patch from another sampler
750
545
  * @param {Sampler2D} source where to copy from
@@ -801,106 +596,6 @@ export class Sampler2D {
801
596
  this.version++;
802
597
  }
803
598
 
804
- /**
805
- * Copy a patch from another sampler with the same itemSize
806
- * @param {Sampler2D} source where to copy from
807
- * @param {Number} sourceX where to start reading from, X coordinate
808
- * @param {Number} sourceY where to start reading from, X coordinate
809
- * @param {Number} destinationX where to start writing to, X coordinate
810
- * @param {Number} destinationY where to start writing to, X coordinate
811
- * @param {Number} width size of the patch that is to be copied
812
- * @param {Number} height size of the patch that is to be copied
813
- */
814
- copy_sameItemSize(source, sourceX, sourceY, destinationX, destinationY, width, height) {
815
- const itemSize = this.itemSize;
816
- const sItemSize = source.itemSize;
817
-
818
- assert.equal(sItemSize, sItemSize, `source.itemSize(=${sItemSize}) != this.itemSize(=${itemSize})`);
819
-
820
- const _w = Math.min(width, source.width - sourceX, this.width - destinationX);
821
- const _h = Math.min(height, source.height - sourceY, this.height - destinationY);
822
-
823
-
824
- const dRowSize = itemSize * this.width;
825
- const sRowSize = itemSize * source.width;
826
-
827
- const sData = source.data;
828
- const dData = this.data;
829
-
830
- const patchRowSize = _w * itemSize;
831
-
832
- let y, i;
833
-
834
- for (y = 0; y < _h; y++) {
835
- const dA = (y + destinationY) * dRowSize;
836
- const sA = (y + sourceY) * sRowSize;
837
-
838
- const dOffset = dA + destinationX * itemSize;
839
- const sOffset = sA + sourceX * itemSize;
840
-
841
- for (i = 0; i < patchRowSize; i++) {
842
-
843
- dData[dOffset + i] = sData[sOffset + i];
844
-
845
- }
846
- }
847
-
848
- this.version++;
849
- }
850
-
851
- /**
852
- * Assumes both samplers are uint8 with values 0-255
853
- * @param {Sampler2D} source
854
- * @param sourceX
855
- * @param sourceY
856
- * @param destinationX
857
- * @param destinationY
858
- * @param width
859
- * @param height
860
- * @param {BlendingType} [blendMode]
861
- */
862
- paint(source, sourceX, sourceY, destinationX, destinationY, width, height, blendMode = BlendingType.Normal) {
863
- let blendFunction;
864
- if (blendMode === BlendingType.Normal) {
865
- blendFunction = blendFunctionNormal;
866
- } else {
867
- throw new Error(`Unsupported blendType(=${blendMode})`);
868
- }
869
-
870
- const _w = Math.min(width, source.width - sourceX, this.width - destinationX);
871
- const _h = Math.min(height, source.height - sourceY, this.height - destinationY);
872
-
873
- const _x0 = Math.max(0, -destinationX);
874
- const _y0 = Math.max(0, -destinationY);
875
-
876
- const c0 = [0, 0, 0, 255];
877
- const c1 = [0, 0, 0, 255];
878
-
879
- const c3 = [];
880
-
881
- let x, y;
882
-
883
- for (y = _y0; y < _h; y++) {
884
- for (x = _x0; x < _w; x++) {
885
- const d_x = Math.round(x + destinationX);
886
- const d_y = Math.round(y + destinationY);
887
-
888
- this.read(d_x, d_y, c0);
889
-
890
- const s_x = Math.round(x + sourceY);
891
- const s_y = Math.round(y + sourceY);
892
-
893
- source.read(s_x, s_y, c1);
894
-
895
- blendFunction(c1, c0, c3);
896
-
897
- this.set(d_x, d_y, c3);
898
-
899
- }
900
- }
901
-
902
-
903
- }
904
599
 
905
600
  /**
906
601
  * Fill data values with zeros for a given area
@@ -1161,22 +856,6 @@ export class Sampler2D {
1161
856
  return dataSize + 280;
1162
857
  }
1163
858
 
1164
- /**
1165
- * @deprecated Use {@link Sampler2DSerializationAdapter} adapter instead
1166
- * @param {BinaryBuffer} buffer
1167
- */
1168
- toBinaryBuffer(buffer) {
1169
- throw new Error('Deprecated, use Sampler2DSerializationAdapter instead');
1170
- }
1171
-
1172
- /**
1173
- * @deprecated Use {@link Sampler2DSerializationAdapter} adapter instead
1174
- * @param {BinaryBuffer} buffer
1175
- */
1176
- fromBinaryBuffer(buffer) {
1177
- throw new Error('Deprecated, use Sampler2DSerializationAdapter instead');
1178
- }
1179
-
1180
859
  /**
1181
860
  *
1182
861
  * @param {Sampler2D} other
@@ -1389,35 +1068,5 @@ Sampler2D.prototype.isSampler2D = true;
1389
1068
  */
1390
1069
  Sampler2D.typeName = "Sampler2D";
1391
1070
 
1392
- /**
1393
- * Based on code from reddit https://www.reddit.com/r/javascript/comments/jxa8x/bicubic_interpolation/
1394
- * @param {number} t
1395
- * @param {number} a
1396
- * @param {number} b
1397
- * @param {number} c
1398
- * @param {number} d
1399
- * @returns {number}
1400
- */
1401
- function bicubic_terp(t, a, b, c, d) {
1402
- return 0.5 * (c - a + (2.0 * a - 5.0 * b + 4.0 * c - d + (3.0 * (b - c) + d - a) * t) * t) * t + b;
1403
- }
1404
-
1405
-
1406
- /**
1407
- *
1408
- * @param {number[]} source
1409
- * @param {number[]} destination
1410
- * @param {Array} result
1411
- */
1412
- function blendFunctionNormal(source, destination, result) {
1413
-
1414
- const a1 = source[3] / 255;
1415
- const a0 = destination[3] / 255;
1416
-
1417
- result[0] = source[0] * a1 + destination[0] * (1 - a1);
1418
- result[1] = source[1] * a1 + destination[1] * (1 - a1);
1419
- result[2] = source[2] * a1 + destination[2] * (1 - a1);
1420
- result[3] = (a1 + a0 * (1 - a1)) * 255;
1421
- }
1422
1071
 
1423
1072
 
@@ -222,34 +222,3 @@ describe("copy method", () => {
222
222
  expect(target.readChannel(1, 1, 0)).toBe(2);
223
223
  });
224
224
  });
225
-
226
- describe("copyWithMargin method", () => {
227
- test("one texel patch with 1 texel margin all around", () => {
228
- const target = Sampler2D.uint8(1, 3, 3);
229
- target.data[0] = 1;
230
-
231
- const source = Sampler2D.uint8(1, 1, 1);
232
- source.data[0] = 2;
233
-
234
- target.copyWithMargin(source, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1);
235
-
236
- //top left
237
- expect(target.readChannel(0, 0, 0)).toEqual(2);
238
- //top
239
- expect(target.readChannel(1, 0, 0)).toEqual(2);
240
- //top right
241
- expect(target.readChannel(2, 0, 0)).toEqual(2);
242
- //left
243
- expect(target.readChannel(0, 1, 0)).toEqual(2);
244
- //copied region
245
- expect(target.readChannel(1, 1, 0)).toEqual(2);
246
- //right
247
- expect(target.readChannel(2, 1, 0)).toEqual(2);
248
- //bottom left
249
- expect(target.readChannel(0, 2, 0)).toEqual(2);
250
- //bottom
251
- expect(target.readChannel(1, 2, 0)).toEqual(2);
252
- //bottom right
253
- expect(target.readChannel(2, 2, 0)).toEqual(2);
254
- });
255
- });
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Copy a patch from another sampler with a margin.
3
+ * This is useful for texture rendering where filtering can cause bleeding along the edges of the patch.
4
+ * @param {Sampler2D} destination
5
+ * @param {Sampler2D} source where to copy from
6
+ * @param {Number} sourceX where to start reading from, X coordinate
7
+ * @param {Number} sourceY where to start reading from, X coordinate
8
+ * @param {Number} destinationX where to start writing to, X coordinate
9
+ * @param {Number} destinationY where to start writing to, X coordinate
10
+ * @param {Number} width size of the patch that is to be copied
11
+ * @param {Number} height size of the patch that is to be copied
12
+ * @param {Number} marginLeft
13
+ * @param {Number} marginRight
14
+ * @param {Number} marginTop
15
+ * @param {Number} marginBottom
16
+ */
17
+ export function sampler2d_copy_with_margins(
18
+ destination,
19
+ source,
20
+ sourceX, sourceY,
21
+ destinationX, destinationY,
22
+ width, height,
23
+ marginLeft,
24
+ marginRight,
25
+ marginTop,
26
+ marginBottom
27
+ ) {
28
+ const dItemSize = destination.itemSize;
29
+ const sItemSize = source.itemSize;
30
+ const _itemSize = Math.min(dItemSize, sItemSize);
31
+
32
+
33
+ const dRowSize = dItemSize * destination.width;
34
+ const sRowSize = sItemSize * source.width;
35
+
36
+ const sData = source.data;
37
+ const dData = destination.data;
38
+
39
+ let x, y, i;
40
+
41
+ let xMax, yMax;
42
+
43
+ let dA, sA, dOffset, sOffset;
44
+ //Write top-left corner
45
+ sOffset = sourceY * sRowSize + sourceX * dItemSize;
46
+ for (y = Math.max(0, destinationY - marginTop), yMax = destinationY; y < yMax; y++) {
47
+ dA = y * dRowSize;
48
+
49
+ for (x = Math.max(0, destinationX - marginLeft), xMax = destinationX; x < xMax; x++) {
50
+
51
+ dOffset = dA + x * dItemSize;
52
+
53
+ for (i = 0; i < _itemSize; i++) {
54
+ dData[dOffset + i] = sData[sOffset + i];
55
+ }
56
+ }
57
+ }
58
+ //Write top margin
59
+ sA = sourceY * sRowSize;
60
+ for (y = Math.max(0, destinationY - marginTop), yMax = destinationY; y < yMax; y++) {
61
+ dA = y * dRowSize;
62
+
63
+ for (x = 0; x < width; x++) {
64
+
65
+ dOffset = dA + (x + destinationX) * dItemSize;
66
+ sOffset = sA + (x + sourceX) * dItemSize;
67
+ for (i = 0; i < _itemSize; i++) {
68
+ dData[dOffset + i] = sData[sOffset + i];
69
+ }
70
+ }
71
+ }
72
+ //Write top-right corner
73
+ sOffset = sourceY * sRowSize + (sourceX + width - 1) * dItemSize;
74
+ for (y = Math.max(0, destinationY - marginTop), yMax = destinationY; y < yMax; y++) {
75
+ dA = y * dRowSize;
76
+
77
+ for (x = destinationX + width, xMax = Math.min(destination.width, x + marginRight); x < xMax; x++) {
78
+
79
+ dOffset = dA + x * dItemSize;
80
+
81
+ for (i = 0; i < _itemSize; i++) {
82
+ dData[dOffset + i] = sData[sOffset + i];
83
+ }
84
+ }
85
+ }
86
+ //Write left margin
87
+ for (y = 0; y < height; y++) {
88
+ dA = (y + destinationY) * dRowSize;
89
+ sA = (y + sourceY) * sRowSize;
90
+
91
+ sOffset = sA + (sourceX) * dItemSize;
92
+
93
+ for (x = Math.max(0, destinationX - marginLeft), xMax = destinationX; x < xMax; x++) {
94
+
95
+ dOffset = dA + x * dItemSize;
96
+
97
+ for (i = 0; i < _itemSize; i++) {
98
+ dData[dOffset + i] = sData[sOffset + i];
99
+ }
100
+ }
101
+ }
102
+ //write actual patch
103
+ destination.copy(source, sourceX, sourceY, destinationX, destinationY, width, height);
104
+
105
+ //Write right margin
106
+ for (y = 0; y < height; y++) {
107
+ dA = (y + destinationY) * dRowSize;
108
+ sA = (y + sourceY) * sRowSize;
109
+
110
+ sOffset = sA + (sourceX + width - 1) * dItemSize;
111
+
112
+ for (x = destinationX + width, xMax = Math.min(destination.width, x + marginRight); x < xMax; x++) {
113
+
114
+ dOffset = dA + x * dItemSize;
115
+
116
+ for (i = 0; i < _itemSize; i++) {
117
+ dData[dOffset + i] = sData[sOffset + i];
118
+ }
119
+ }
120
+ }
121
+
122
+ //Write Bottom-left margin
123
+ sOffset = (sourceY + height - 1) * sRowSize + sourceX * dItemSize;
124
+ for (y = destinationY + width, yMax = Math.min(destination.height, y + marginBottom); y < yMax; y++) {
125
+ dA = y * dRowSize;
126
+
127
+ for (x = Math.max(0, destinationX - marginLeft), xMax = destinationX; x < xMax; x++) {
128
+
129
+ dOffset = dA + x * dItemSize;
130
+
131
+ for (i = 0; i < _itemSize; i++) {
132
+ dData[dOffset + i] = sData[sOffset + i];
133
+ }
134
+ }
135
+ }
136
+ //Write Bottom margin
137
+ sA = (sourceY + height - 1) * sRowSize;
138
+ for (y = destinationY + width, yMax = Math.min(destination.height, y + marginBottom); y < yMax; y++) {
139
+ dA = y * dRowSize;
140
+
141
+ for (x = 0; x < width; x++) {
142
+
143
+ dOffset = dA + (x + destinationX) * dItemSize;
144
+ sOffset = sA + (x + sourceX) * dItemSize;
145
+ for (i = 0; i < _itemSize; i++) {
146
+ dData[dOffset + i] = sData[sOffset + i];
147
+ }
148
+ }
149
+ }
150
+ //Write Bottom-right margin
151
+ sOffset = (sourceY + height - 1) * sRowSize + (sourceX + width - 1) * dItemSize;
152
+ for (y = destinationY + width, yMax = Math.min(destination.height, y + marginBottom); y < yMax; y++) {
153
+ dA = y * dRowSize;
154
+
155
+ for (x = destinationX + width, xMax = Math.min(destination.width, x + marginRight); x < xMax; x++) {
156
+
157
+ dOffset = dA + x * dItemSize;
158
+
159
+ for (i = 0; i < _itemSize; i++) {
160
+ dData[dOffset + i] = sData[sOffset + i];
161
+ }
162
+ }
163
+ }
164
+
165
+ destination.version++;
166
+ }
@@ -0,0 +1,31 @@
1
+ import { Sampler2D } from "./Sampler2D.js";
2
+ import { sampler2d_copy_with_margins } from "./sampler2d_copy_with_margins.js";
3
+
4
+ test("one texel patch with 1 texel margin all around", () => {
5
+ const target = Sampler2D.uint8(1, 3, 3);
6
+ target.data[0] = 1;
7
+
8
+ const source = Sampler2D.uint8(1, 1, 1);
9
+ source.data[0] = 2;
10
+
11
+ sampler2d_copy_with_margins(target, source, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1);
12
+
13
+ //top left
14
+ expect(target.readChannel(0, 0, 0)).toEqual(2);
15
+ //top
16
+ expect(target.readChannel(1, 0, 0)).toEqual(2);
17
+ //top right
18
+ expect(target.readChannel(2, 0, 0)).toEqual(2);
19
+ //left
20
+ expect(target.readChannel(0, 1, 0)).toEqual(2);
21
+ //copied region
22
+ expect(target.readChannel(1, 1, 0)).toEqual(2);
23
+ //right
24
+ expect(target.readChannel(2, 1, 0)).toEqual(2);
25
+ //bottom left
26
+ expect(target.readChannel(0, 2, 0)).toEqual(2);
27
+ //bottom
28
+ expect(target.readChannel(1, 2, 0)).toEqual(2);
29
+ //bottom right
30
+ expect(target.readChannel(2, 2, 0)).toEqual(2);
31
+ });