@woosh/meep-engine 2.41.0 → 2.42.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 (98) hide show
  1. package/core/assert.js +2 -2
  2. package/core/collection/array/array_swap.js +3 -3
  3. package/core/collection/map/AsyncLoadingCache.js +47 -0
  4. package/core/geom/3d/aabb/aabb3_compute_distance_above_plane_max.js +1 -1
  5. package/core/geom/3d/apply_mat4_transform_to_v3_array.js +2 -4
  6. package/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.js +28 -0
  7. package/core/geom/Quaternion.js +14 -0
  8. package/core/math/statistics/computeSampleSize_Cochran.js +3 -3
  9. package/editor/ecs/component/editors/geom/QuaternionEditor.js +12 -5
  10. package/engine/Engine.js +6 -1
  11. package/engine/EngineBootstrapper.js +2 -1
  12. package/engine/EngineHarness.js +13 -3
  13. package/engine/asset/AssetManager.js +97 -7
  14. package/engine/development/performance/AbstractMetric.js +1 -0
  15. package/engine/development/performance/RingBufferMetric.js +25 -4
  16. package/engine/ecs/EntityBuilder.js +29 -4
  17. package/engine/ecs/transform/Transform.js +23 -3
  18. package/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +17 -1
  19. package/engine/graphics/ecs/decal/v2/Decal.d.ts +11 -0
  20. package/engine/graphics/ecs/decal/v2/Decal.js +50 -0
  21. package/engine/graphics/ecs/decal/v2/FPDecalSystem.d.ts +8 -0
  22. package/engine/graphics/ecs/decal/v2/FPDecalSystem.js +201 -0
  23. package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +278 -0
  24. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +8 -1
  25. package/engine/graphics/ecs/mesh-v2/allocate_v3.js +37 -0
  26. package/engine/graphics/ecs/mesh-v2/build_three_object.js +4 -0
  27. package/engine/graphics/geometry/MikkT/AddTriToGroup.js +10 -0
  28. package/engine/graphics/geometry/MikkT/AssignRecur.js +84 -0
  29. package/engine/graphics/geometry/MikkT/AvgTSpace.js +38 -0
  30. package/engine/graphics/geometry/MikkT/Build4RuleGroups.js +96 -0
  31. package/engine/graphics/geometry/MikkT/BuildNeighborsFast.js +137 -0
  32. package/engine/graphics/geometry/MikkT/CalcTexArea.js +31 -0
  33. package/engine/graphics/geometry/MikkT/CompareSubGroups.js +26 -0
  34. package/engine/graphics/geometry/MikkT/DegenEpilogue.js +220 -0
  35. package/engine/graphics/geometry/MikkT/DegenPrologue.js +115 -0
  36. package/engine/graphics/geometry/MikkT/EvalTspace.js +128 -0
  37. package/engine/graphics/geometry/MikkT/GenerateInitialVerticesIndexList.js +48 -0
  38. package/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.js +184 -0
  39. package/engine/graphics/geometry/MikkT/GenerateTSpaces.js +226 -0
  40. package/engine/graphics/geometry/MikkT/GetEdge.js +45 -0
  41. package/engine/graphics/geometry/MikkT/GetNormal.js +16 -0
  42. package/engine/graphics/geometry/MikkT/GetPosition.js +25 -0
  43. package/engine/graphics/geometry/MikkT/GetTexCoord.js +18 -0
  44. package/engine/graphics/geometry/MikkT/InitTriInfo.js +180 -0
  45. package/engine/graphics/geometry/MikkT/Length.js +10 -0
  46. package/engine/graphics/geometry/MikkT/MakeIndex.js +18 -0
  47. package/engine/graphics/geometry/MikkT/MikkTSpace.js +197 -2068
  48. package/engine/graphics/geometry/MikkT/NormalizeSafe.js +21 -0
  49. package/engine/graphics/geometry/MikkT/NotZero.js +10 -0
  50. package/engine/graphics/geometry/MikkT/QuickSort.js +54 -0
  51. package/engine/graphics/geometry/MikkT/QuickSortEdges.js +71 -0
  52. package/engine/graphics/geometry/MikkT/SSubGroup.js +15 -0
  53. package/engine/graphics/geometry/MikkT/STSpace.js +36 -0
  54. package/engine/graphics/geometry/MikkT/constants/GROUP_WITH_ANY.js +1 -0
  55. package/engine/graphics/geometry/MikkT/constants/INTERNAL_RND_SORT_SEED.js +1 -0
  56. package/engine/graphics/geometry/MikkT/constants/MARK_DEGENERATE.js +1 -0
  57. package/engine/graphics/geometry/MikkT/constants/ORIENT_PRESERVING.js +1 -0
  58. package/engine/graphics/geometry/MikkT/constants/QUAD_ONE_DEGEN_TRI.js +1 -0
  59. package/engine/graphics/geometry/MikkT/m_getNormal.js +16 -0
  60. package/engine/graphics/geometry/MikkT/m_getNumFaces.js +8 -0
  61. package/engine/graphics/geometry/MikkT/m_getNumVerticesOfFace.js +11 -0
  62. package/engine/graphics/geometry/MikkT/m_getPosition.js +20 -0
  63. package/engine/graphics/geometry/MikkT/m_getTexCoord.js +16 -0
  64. package/engine/graphics/geometry/MikkT/m_setTSpace.js +35 -0
  65. package/engine/graphics/geometry/MikkT/m_setTSpaceBasic.js +22 -0
  66. package/engine/graphics/geometry/MikkT/malloc.js +16 -0
  67. package/engine/graphics/geometry/MikkT/v3_scale_dot_sub_normalize.js +52 -0
  68. package/engine/graphics/geometry/buffered/computeGeometryEquality.js +1 -1
  69. package/engine/graphics/geometry/buffered/computeGeometryHash.js +1 -1
  70. package/engine/graphics/impostors/octahedral/ImpostorBaker.js +28 -14
  71. package/engine/graphics/impostors/octahedral/ImpostorDescription.js +6 -0
  72. package/engine/graphics/impostors/octahedral/README.md +1 -0
  73. package/engine/graphics/impostors/octahedral/bake/compute_bounding_sphere.js +25 -22
  74. package/engine/graphics/impostors/octahedral/bake/compute_bounding_sphere_radius_only.js +37 -0
  75. package/engine/graphics/impostors/octahedral/bake/prepare_bake_material.js +30 -1
  76. package/engine/graphics/impostors/octahedral/grid/HemiOctahedralUvEncoder.js +1 -1
  77. package/engine/graphics/impostors/octahedral/prototypeBaker.js +121 -22
  78. package/engine/graphics/impostors/octahedral/shader/BakeShaderStandard.js +46 -7
  79. package/engine/graphics/impostors/octahedral/shader/ImpostorShaderV0.js +349 -0
  80. package/engine/graphics/impostors/octahedral/shader/ImpostorShaderV1.js +74 -0
  81. package/engine/graphics/impostors/octahedral/shader/glsl/v1/common.glsl +209 -0
  82. package/engine/graphics/impostors/octahedral/shader/glsl/v1/flagment.glsl +80 -0
  83. package/engine/graphics/impostors/octahedral/shader/glsl/v1/vertex.glsl +350 -0
  84. package/engine/graphics/micron/render/v1/getTransformedPositionsCached.js +1 -1
  85. package/engine/graphics/render/forward_plus/LightManager.js +17 -7
  86. package/engine/graphics/render/forward_plus/data/TextureBackedMemoryRegion.js +7 -1
  87. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +13 -5
  88. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_PREAMBLE.js +3 -1
  89. package/engine/graphics/render/forward_plus/model/Decal.js +19 -2
  90. package/engine/graphics/render/forward_plus/plugin/MaterialTransformer.js +14 -2
  91. package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +2 -2
  92. package/engine/graphics/texture/sampler/Sampler2D.js +10 -10
  93. package/engine/graphics/texture/sampler/prototypeSamplerFiltering.js +117 -11
  94. package/engine/graphics/texture/sampler/resize/sampler2d_downsample_mipmap.js +66 -0
  95. package/engine/graphics/texture/sampler/sampler2_d_scale_down_lanczos.js +2 -2
  96. package/engine/intelligence/behavior/util/RotationBehavior.js +69 -0
  97. package/generation/example/filters/SampleGroundMoistureFilter.js +5 -5
  98. package/package.json +1 -1
@@ -0,0 +1,128 @@
1
+ import { STSpace } from "./STSpace.js";
2
+ import { vec3 } from "gl-matrix";
3
+ import { GROUP_WITH_ANY } from "./constants/GROUP_WITH_ANY.js";
4
+ import { assert } from "../../../../core/assert.js";
5
+ import { GetNormal } from "./GetNormal.js";
6
+ import { NormalizeSafe } from "./NormalizeSafe.js";
7
+ import { GetPosition } from "./GetPosition.js";
8
+ import { clamp01 } from "../../../../core/math/clamp01.js";
9
+ import { v3_scale_dot_sub_normalize } from "./v3_scale_dot_sub_normalize.js";
10
+
11
+
12
+ let offset = 0;
13
+ const _buffer = new ArrayBuffer(3 * 4 * 6);
14
+
15
+ const vOs = new Float32Array(_buffer, offset, 3);
16
+ offset += 12;
17
+ const vOt = new Float32Array(_buffer, offset, 3);
18
+ offset += 12;
19
+ const n = new Float32Array(_buffer, offset, 3);
20
+ offset += 12;
21
+
22
+ const p0 = new Float32Array(_buffer, offset, 3);
23
+ offset += 12;
24
+ const p1 = new Float32Array(_buffer, offset, 3);
25
+ offset += 12;
26
+ const p2 = new Float32Array(_buffer, offset, 3);
27
+ offset += 12;
28
+
29
+ /**
30
+ *
31
+ * @param {STSpace} res
32
+ * @param {number[]|Uint32Array|Int32Array} face_indices
33
+ * @param {number} iFaces
34
+ * @param {number[]} piTriListIn
35
+ * @param {STriInfo[]} pTriInfos
36
+ * @param {SMikkTSpaceContext} pContext
37
+ * @param {number} iVertexRepresentitive
38
+ */
39
+ export function EvalTspace(res, face_indices, iFaces, piTriListIn, pTriInfos, pContext, iVertexRepresentitive) {
40
+
41
+ let fAngleSum = 0;
42
+
43
+ res.vOs[0] = 0.0;
44
+ res.vOs[1] = 0.0;
45
+ res.vOs[2] = 0.0;
46
+
47
+ res.vOt[0] = 0.0;
48
+ res.vOt[1] = 0.0;
49
+ res.vOt[2] = 0.0;
50
+
51
+ res.fMagS = 0;
52
+ res.fMagT = 0;
53
+
54
+
55
+ for (let face = 0; face < iFaces; face++) {
56
+ const f = face_indices[face];
57
+ const tri_info = pTriInfos[f];
58
+
59
+ // only valid triangles get to add their contribution
60
+ if ((tri_info.iFlag & GROUP_WITH_ANY) === 0) {
61
+ let i = -1;
62
+
63
+ const f3 = 3 * f;
64
+
65
+ if (piTriListIn[f3] === iVertexRepresentitive) {
66
+ i = 0;
67
+ } else if (piTriListIn[f3 + 1] === iVertexRepresentitive) {
68
+ i = 1;
69
+ } else if (piTriListIn[f3 + 2] === iVertexRepresentitive) {
70
+ i = 2;
71
+ }
72
+
73
+ assert(i >= 0 && i < 3);
74
+
75
+ // project
76
+ const index = piTriListIn[f3 + i];
77
+
78
+ GetNormal(n, pContext, index);
79
+
80
+ v3_scale_dot_sub_normalize(vOs, n, tri_info.vOs);
81
+ v3_scale_dot_sub_normalize(vOt, n, tri_info.vOt);
82
+
83
+ const i0 = piTriListIn[f3 + (i > 0 ? (i - 1) : 2)];
84
+ const i1 = piTriListIn[f3 + i];
85
+ const i2 = piTriListIn[f3 + (i < 2 ? (i + 1) : 0)];
86
+
87
+ GetPosition(p0, 0, pContext, i0);
88
+ GetPosition(p1, 0, pContext, i1);
89
+ GetPosition(p2, 0, pContext, i2);
90
+
91
+ vec3.sub(p0, p0, p1);
92
+ vec3.sub(p1, p2, p1);
93
+
94
+ // project
95
+ v3_scale_dot_sub_normalize(p0, n, p0);
96
+ v3_scale_dot_sub_normalize(p1, n, p1);
97
+
98
+ // weight contribution by the angle
99
+ // between the two edge vectors
100
+
101
+ const fCos = clamp01(vec3.dot(p0, p1));
102
+ const fAngle = Math.acos(fCos);
103
+ const fMagS = tri_info.fMagS;
104
+ const fMagT = tri_info.fMagT;
105
+
106
+ vec3.scale(p2, vOs, fAngle);
107
+ vec3.add(res.vOs, res.vOs, p2);
108
+
109
+ vec3.scale(p2, vOt, fAngle);
110
+ vec3.add(res.vOt, res.vOt, p2);
111
+
112
+ res.fMagS += (fAngle * fMagS);
113
+ res.fMagT += (fAngle * fMagT);
114
+
115
+ fAngleSum += fAngle;
116
+ }
117
+ }
118
+
119
+ // normalize
120
+ NormalizeSafe(res.vOs, res.vOs);
121
+ NormalizeSafe(res.vOt, res.vOt);
122
+
123
+ if (fAngleSum > 0) {
124
+ res.fMagS /= fAngleSum;
125
+ res.fMagT /= fAngleSum;
126
+ }
127
+
128
+ }
@@ -0,0 +1,48 @@
1
+ import { m_getNumFaces } from "./m_getNumFaces.js";
2
+ import { MakeIndex } from "./MakeIndex.js";
3
+ import { assert } from "../../../../core/assert.js";
4
+
5
+ /**
6
+ *
7
+ * @param {STriInfo[]} pTriInfos
8
+ * @param {number[]|Int32Array} piTriList_out
9
+ * @param {SMikkTSpaceContext } pContext
10
+ * @param {number} iNrTrianglesIn
11
+ * @return {number}
12
+ */
13
+ export function GenerateInitialVerticesIndexList(pTriInfos, piTriList_out, pContext, iNrTrianglesIn) {
14
+ let iTSpacesOffs = 0;
15
+ let iDstTriIndex = 0;
16
+
17
+ const face_count = m_getNumFaces(pContext);
18
+
19
+ for (let f = 0; f < face_count; f++) {
20
+
21
+ const tri_info = pTriInfos[iDstTriIndex];
22
+
23
+ tri_info.iOrgFaceNumber = f;
24
+ tri_info.iTSpacesOffs = iTSpacesOffs;
25
+
26
+ const pVerts = tri_info.vert_num;
27
+
28
+ pVerts[0] = 0;
29
+ pVerts[1] = 1;
30
+ pVerts[2] = 2;
31
+
32
+ piTriList_out[iDstTriIndex * 3 ] = MakeIndex(f, 0);
33
+ piTriList_out[iDstTriIndex * 3 + 1] = MakeIndex(f, 1);
34
+ piTriList_out[iDstTriIndex * 3 + 2] = MakeIndex(f, 2);
35
+
36
+ ++iDstTriIndex; // next
37
+
38
+ iTSpacesOffs += 3;
39
+ assert.lessThanOrEqual(iDstTriIndex, iNrTrianglesIn);
40
+ }
41
+
42
+ for (let t = 0; t < iNrTrianglesIn; t++) {
43
+ pTriInfos[t].iFlag = 0;
44
+ }
45
+
46
+ // return total amount of tspaces
47
+ return iTSpacesOffs;
48
+ }
@@ -0,0 +1,184 @@
1
+ import { vec3 } from "gl-matrix";
2
+ import { GetPosition } from "./GetPosition.js";
3
+ import { computeHashFloat } from "../../../../core/math/hash/computeHashFloat.js";
4
+ import { GetNormal } from "./GetNormal.js";
5
+ import { GetTexCoord } from "./GetTexCoord.js";
6
+
7
+ /**
8
+ *
9
+ * @param {number} x
10
+ * @param {number} y
11
+ * @param {number} z
12
+ * @returns {number}
13
+ */
14
+ function HASH(x, y, z) {
15
+ return ((x) * 73856093) ^ ((y) * 19349663) ^ ((z) * 83492791);
16
+ }
17
+
18
+ /**
19
+ *
20
+ * @param {number} x
21
+ * @param {number} y
22
+ * @param {number} z
23
+ * @returns {number}
24
+ */
25
+ function HASH_F(x, y, z) {
26
+ return (computeHashFloat(x) * 73856093) ^ (computeHashFloat(y) * 19349663) ^ (computeHashFloat(z) * 83492791);
27
+ }
28
+
29
+ /**
30
+ * Sort comp and data based on comp.
31
+ * comp2 and data2 are used as temporary storage.
32
+ *
33
+ * @param {Uint32Array} comp
34
+ * @param {Int32Array} data
35
+ * @param {Uint32Array} comp2
36
+ * @param {Int32Array} data2
37
+ * @param {number} n
38
+ */
39
+ function radixsort_pair(comp, data, comp2, data2, n) {
40
+ let shift = 0;
41
+
42
+ let _data_0 = data;
43
+ let _data_1 = data2;
44
+
45
+ let _comp_0 = comp;
46
+ let _comp_1 = comp2;
47
+
48
+ for (let pass = 0; pass < 4; pass++, shift += 8) {
49
+ const bins = new Int32Array(257);
50
+ /* Count number of elements per bin. */
51
+ for (let i = 0; i < n; i++) {
52
+ bins[((_comp_0[i] >> shift) & 0xff) + 1]++;
53
+ }
54
+ /* Compute prefix sum to find position of each bin in the sorted array. */
55
+ for (let i = 2; i < 256; i++) {
56
+ bins[i] += bins[i - 1];
57
+ }
58
+ /* Insert the elements in their correct location based on their bin. */
59
+ for (let i = 0; i < n; i++) {
60
+ const pos = bins[(_comp_0[i] >> shift) & 0xff]++;
61
+ _comp_1[pos] = _comp_0[i];
62
+ _data_1[pos] = _data_0[i];
63
+ }
64
+
65
+ /* Swap arrays. */
66
+ let tmpdata = _data_0;
67
+ _data_0 = _data_1;
68
+ _data_1 = tmpdata;
69
+
70
+ let tmpcomp = _comp_0;
71
+ _comp_0 = _comp_1;
72
+ _comp_1 = tmpcomp;
73
+ }
74
+ }
75
+
76
+ /**
77
+ *
78
+ * @param {number[]|Int32Array} piTriList_in_and_out
79
+ * @param {SMikkTSpaceContext} pContext
80
+ * @param {number} iNrTrianglesIn
81
+ * @returns {void}
82
+ */
83
+ export function GenerateSharedVerticesIndexList(
84
+ piTriList_in_and_out,
85
+ pContext,
86
+ iNrTrianglesIn
87
+ ) {
88
+ const numVertices = iNrTrianglesIn * 3;
89
+
90
+ const _buffer = new ArrayBuffer(numVertices * 4 * 4);
91
+
92
+ const hashes = new Uint32Array(_buffer, 0, numVertices);
93
+ const indices = new Int32Array(_buffer, numVertices * 4, numVertices);
94
+ const temp_hashes = new Uint32Array(_buffer, numVertices * 2 * 4, numVertices);
95
+ const temp_indices = new Int32Array(_buffer, numVertices * 3 * 4, numVertices);
96
+
97
+ const v = vec3.create();
98
+
99
+ for (let i = 0; i < numVertices; i++) {
100
+ const index = piTriList_in_and_out[i];
101
+
102
+ GetPosition(v, 0, pContext, index);
103
+ const hashP = HASH_F(v[0], v[1], v[2]);
104
+
105
+ GetNormal(v, pContext, index);
106
+ const hashN = HASH_F(v[0], v[1], v[2]);
107
+
108
+ GetTexCoord(v, pContext, index);
109
+ const hashT = HASH_F(v[0], v[1], v[2]);
110
+
111
+ hashes[i] = HASH(hashP, hashN, hashT);
112
+ indices[i] = i;
113
+ }
114
+
115
+ radixsort_pair(hashes, indices, temp_hashes, temp_indices, numVertices);
116
+
117
+ // free(temp_hashes);
118
+ // free(temp_indices);
119
+
120
+
121
+ const vT = vec3.create();
122
+ const vP = vec3.create();
123
+
124
+ const vT2 = vec3.create();
125
+ const vP2 = vec3.create();
126
+
127
+ const vN = vec3.create();
128
+ const vN2 = vec3.create();
129
+
130
+ /*
131
+ * Process blocks of vertices with the same hash.
132
+ * Vertices in the block might still be separate, but we know for sure that
133
+ * vertices in different blocks will never be identical.
134
+ */
135
+ let blockstart = 0;
136
+ while (blockstart < numVertices) {
137
+ /* Find end of this block (exclusive). */
138
+ const hash = hashes[blockstart];
139
+ let blockend = blockstart + 1;
140
+ for (; blockend < numVertices; blockend++) {
141
+ if (hashes[blockend] !== hash)
142
+ break;
143
+ }
144
+
145
+ for (let i = blockstart; i < blockend; i++) {
146
+
147
+ const index1 = piTriList_in_and_out[indices[i]];
148
+
149
+ GetPosition(vP, 0, pContext, index1);
150
+ GetNormal(vN, pContext, index1);
151
+ GetTexCoord(vT, pContext, index1);
152
+
153
+ for (let i2 = i + 1; i2 < blockend; i2++) {
154
+ const index2 = piTriList_in_and_out[indices[i2]];
155
+
156
+ if (index1 === index2) {
157
+ continue;
158
+ }
159
+
160
+ GetPosition(vP2, 0, pContext, index2);
161
+ GetNormal(vN2, pContext, index2);
162
+ GetTexCoord(vT2, pContext, index2);
163
+
164
+ if (
165
+ vP[0] === vP2[0] && vP[1] === vP2[1] && vP[2] === vP2[2] &&
166
+ vN[0] === vN2[0] && vN[1] === vN2[1] && vN[2] === vN2[2] &&
167
+ vT[0] === vT2[0] && vT[1] === vT2[1] && vT[2] === vT2[2]
168
+ ) {
169
+ piTriList_in_and_out[indices[i2]] = index1;
170
+ /* Once i2>i has been identified as a duplicate, we can stop since any
171
+ * i3>i2>i that is a duplicate of i (and therefore also i2) will also be
172
+ * compared to i2 and therefore be identified there anyways. */
173
+ break;
174
+ }
175
+ }
176
+ }
177
+
178
+ /* Advance to next block. */
179
+ blockstart = blockend;
180
+ }
181
+
182
+ // free(hashes);
183
+ // free(indices);
184
+ }
@@ -0,0 +1,226 @@
1
+ import { malloc } from "./malloc.js";
2
+ import { STSpace } from "./STSpace.js";
3
+ import { SSubGroup } from "./SSubGroup.js";
4
+ import { vec3 } from "gl-matrix";
5
+ import { assert } from "../../../../core/assert.js";
6
+ import { GetNormal } from "./GetNormal.js";
7
+ import { GROUP_WITH_ANY } from "./constants/GROUP_WITH_ANY.js";
8
+ import { INTERNAL_RND_SORT_SEED } from "./constants/INTERNAL_RND_SORT_SEED.js";
9
+ import { QuickSort } from "./QuickSort.js";
10
+ import { CompareSubGroups } from "./CompareSubGroups.js";
11
+ import { array_copy } from "../../../../core/collection/array/copyArray.js";
12
+ import { EvalTspace } from "./EvalTspace.js";
13
+ import { ORIENT_PRESERVING } from "./constants/ORIENT_PRESERVING.js";
14
+ import { AvgTSpace } from "./AvgTSpace.js";
15
+ import { v3_scale_dot_sub_normalize } from "./v3_scale_dot_sub_normalize.js";
16
+
17
+ const vOs = vec3.create();
18
+ const vOt = vec3.create();
19
+
20
+ const vOs2 = vec3.create();
21
+ const vOt2 = vec3.create();
22
+ /**
23
+ * @type {vec3}
24
+ */
25
+ const n = vec3.create();
26
+
27
+ /**
28
+ * @type {SSubGroup}
29
+ */
30
+ const tmp_group = new SSubGroup();
31
+
32
+ /**
33
+ *
34
+ * @param {STSpace[]} psTspace
35
+ * @param {STriInfo[]} pTriInfos
36
+ * @param {SGroup[]} pGroups
37
+ * @param {number} iNrActiveGroups
38
+ * @param {number[]|Int32Array} piTriListIn
39
+ * @param {number} fThresCos
40
+ * @param {SMikkTSpaceContext} pContext
41
+ */
42
+ export function GenerateTSpaces(psTspace, pTriInfos, pGroups, iNrActiveGroups, piTriListIn, fThresCos, pContext) {
43
+
44
+ let iMaxNrFaces = 0, iUniqueTspaces = 0;
45
+
46
+ for (let g = 0; g < iNrActiveGroups; g++) {
47
+ const sGroup = pGroups[g];
48
+
49
+ if (iMaxNrFaces < sGroup.iNrFaces) {
50
+ iMaxNrFaces = sGroup.iNrFaces;
51
+ }
52
+
53
+ }
54
+
55
+ if (iMaxNrFaces === 0) {
56
+ // no faces, nothing to do
57
+ return;
58
+ }
59
+
60
+
61
+ // make initial allocations
62
+ /**
63
+ * @type {STSpace[]}
64
+ */
65
+ const pSubGroupTspace = malloc(STSpace, iMaxNrFaces);
66
+
67
+ /**
68
+ *
69
+ * @type {SSubGroup[]}
70
+ */
71
+ const pUniSubGroups = malloc(SSubGroup, iMaxNrFaces);
72
+
73
+ /**
74
+ *
75
+ * @type {Int32Array|null}
76
+ */
77
+ const pTmpMembers = new Int32Array(iMaxNrFaces);
78
+
79
+ iUniqueTspaces = 0;
80
+
81
+
82
+ for (let g = 0; g < iNrActiveGroups; g++) {
83
+ const pGroup = pGroups[g];
84
+ let iUniqueSubGroups = 0;
85
+
86
+ for (let i = 0; i < pGroup.iNrFaces; i++) {
87
+ // triangles
88
+ const f = pGroup.pFaceIndices[i]; // triangle number
89
+
90
+ let bFound = false;
91
+
92
+ const tri_info = pTriInfos[f];
93
+
94
+ let index = -1;
95
+ if (tri_info.AssignedGroup[0] === pGroup) {
96
+ index = 0;
97
+ } else if (tri_info.AssignedGroup[1] === pGroup) {
98
+ index = 1;
99
+ } else if (tri_info.AssignedGroup[2] === pGroup) {
100
+ index = 2;
101
+ }
102
+
103
+ assert(index >= 0 && index < 3);
104
+
105
+ const iVertIndex = piTriListIn[f * 3 + index];
106
+ assert.equal(iVertIndex, pGroup.iVertexRepresentitive);
107
+
108
+ // is normalized already
109
+ GetNormal(n, pContext, iVertIndex);
110
+
111
+ // project
112
+ v3_scale_dot_sub_normalize(vOs, n, tri_info.vOs);
113
+ v3_scale_dot_sub_normalize(vOt, n, tri_info.vOt);
114
+
115
+ // original face number
116
+ const iOF_1 = tri_info.iOrgFaceNumber;
117
+
118
+ let iMembers = 0;
119
+ for (let j = 0; j < pGroup.iNrFaces; j++) {
120
+ const t = pGroup.pFaceIndices[j]; // triangle number
121
+ const iOF_2 = pTriInfos[t].iOrgFaceNumber;
122
+
123
+ // project
124
+ v3_scale_dot_sub_normalize(vOs2, n, pTriInfos[t].vOs);
125
+ v3_scale_dot_sub_normalize(vOt2, n, pTriInfos[t].vOt);
126
+
127
+ const bAny = ((tri_info.iFlag | pTriInfos[t].iFlag) & GROUP_WITH_ANY) !== 0;
128
+
129
+ // make sure triangles which belong to the same quad are joined.
130
+ const bSameOrgFace = iOF_1 === iOF_2;
131
+
132
+ const fCosS = vec3.dot(vOs, vOs2);
133
+ const fCosT = vec3.dot(vOt, vOt2);
134
+
135
+ assert(f !== t || bSameOrgFace); // sanity check
136
+
137
+ if (bAny || bSameOrgFace || (fCosS > fThresCos && fCosT > fThresCos)) {
138
+ pTmpMembers[iMembers++] = t;
139
+ }
140
+
141
+ }
142
+
143
+ // sort pTmpMembers
144
+ tmp_group.iNrFaces = iMembers;
145
+ tmp_group.pTriMembers = pTmpMembers;
146
+
147
+ if (iMembers > 1) {
148
+ // could replace with a random seed?
149
+ QuickSort(pTmpMembers, 0, iMembers - 1, INTERNAL_RND_SORT_SEED);
150
+ }
151
+
152
+ // look for an existing match
153
+ bFound = false;
154
+ let l = 0;
155
+ while (l < iUniqueSubGroups && !bFound) {
156
+
157
+ bFound = CompareSubGroups(tmp_group, pUniSubGroups[l]);
158
+
159
+ if (!bFound) {
160
+ ++l;
161
+ }
162
+ }
163
+
164
+ // assign tangent space index
165
+ assert(bFound || l === iUniqueSubGroups);
166
+ //piTempTangIndices[f*3+index] = iUniqueTspaces+l;
167
+
168
+ // if no match was found we allocate a new subgroup
169
+ if (!bFound) {
170
+ // insert new subgroup
171
+ const pIndices = new Int32Array(iMembers);
172
+
173
+ pUniSubGroups[iUniqueSubGroups].iNrFaces = iMembers;
174
+ pUniSubGroups[iUniqueSubGroups].pTriMembers = pIndices;
175
+
176
+ array_copy(tmp_group.pTriMembers, 0, pIndices, 0, iMembers);
177
+
178
+ EvalTspace(
179
+ pSubGroupTspace[iUniqueSubGroups],
180
+ tmp_group.pTriMembers,
181
+ iMembers,
182
+ piTriListIn,
183
+ pTriInfos,
184
+ pContext,
185
+ pGroup.iVertexRepresentitive
186
+ );
187
+
188
+ ++iUniqueSubGroups;
189
+ }
190
+
191
+ // output tspace
192
+
193
+ const iOffs = tri_info.iTSpacesOffs;
194
+ const iVert = tri_info.vert_num[index];
195
+
196
+ /**
197
+ * @type {STSpace}
198
+ */
199
+ const pTS_out = psTspace[iOffs + iVert];
200
+
201
+ assert.lessThan(pTS_out.iCounter, 2);
202
+ assert.equal(((tri_info.iFlag & ORIENT_PRESERVING) !== 0), pGroup.bOrientPreservering);
203
+
204
+ if (pTS_out.iCounter === 1) {
205
+
206
+ AvgTSpace(pTS_out, pTS_out, pSubGroupTspace[l]);
207
+ pTS_out.iCounter = 2; // update counter
208
+ pTS_out.bOrient = pGroup.bOrientPreservering;
209
+
210
+ } else {
211
+
212
+ assert.equal(pTS_out.iCounter, 0);
213
+
214
+ pTS_out.copy(pSubGroupTspace[l]);
215
+ pTS_out.iCounter = 1; // update counter
216
+ pTS_out.bOrient = pGroup.bOrientPreservering;
217
+
218
+ }
219
+
220
+ }
221
+
222
+ // clean up and offset iUniqueTspaces
223
+
224
+ iUniqueTspaces += iUniqueSubGroups;
225
+ }
226
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * resolve ordering and edge number
3
+ * @param {number[]} out
4
+ * @param {number} out_offset
5
+ * @param {number[]} indices
6
+ * @param {number} indices_offset
7
+ * @param {number} i0_in
8
+ * @param {number} i1_in
9
+ * @returns {void}
10
+ */
11
+ export function GetEdge(out, out_offset, indices, indices_offset, i0_in, i1_in) {
12
+
13
+ // test if first index is on the edge
14
+ const index_0 = indices[indices_offset];
15
+ const index_1 = indices[indices_offset + 1];
16
+
17
+ if (index_0 === i0_in || index_0 === i1_in) {
18
+
19
+ // test if second index is on the edge
20
+ if (index_1 === i0_in || index_1 === i1_in) {
21
+
22
+ out[out_offset + 2] = 0; // first edge
23
+
24
+ out[out_offset] = index_0; //i0
25
+ out[out_offset + 1] = index_1; //i1
26
+
27
+ } else {
28
+
29
+ out[out_offset + 2] = 2; // third edge
30
+
31
+ out[out_offset] = indices[indices_offset + 2]; //i0
32
+ out[out_offset + 1] = index_0; //i1
33
+
34
+ }
35
+
36
+ } else {
37
+
38
+ // only second and third index is on the edge
39
+ out[out_offset + 2] = 1; // second edge
40
+
41
+ out[out_offset] = index_1; //i0
42
+ out[out_offset + 1] = indices[indices_offset + 2]; //i1
43
+
44
+ }
45
+ }
@@ -0,0 +1,16 @@
1
+ import { m_getNormal } from "./m_getNormal.js";
2
+
3
+ /**
4
+ *
5
+ * @param {vec3|number[]|Float32Array} res
6
+ * @param {SMikkTSpaceContext} pContext
7
+ * @param {number} index
8
+ */
9
+ export function GetNormal(res, pContext, index) {
10
+
11
+ // inlined : IndexToData(&iF, &iI, index);
12
+ const iI = index & 0x3;
13
+ const iF = index >> 2;
14
+
15
+ m_getNormal(pContext, res, iF, iI);
16
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ *
3
+ * @param {vec3|Float32Array|number[]} out
4
+ * @param {number} out_offset
5
+ * @param {SMikkTSpaceContext} pContext
6
+ * @param {number} index
7
+ */
8
+ export function GetPosition(out, out_offset, pContext, index) {
9
+
10
+ // inlined : IndexToData(&iF, &iI, index);
11
+ const iI = index & 0x3;
12
+ const iF = index >> 2;
13
+
14
+ // figure out which vertex it is
15
+ const vertex_index = pContext.geometry_buffer_index[iF * 3 + iI];
16
+
17
+ const position = pContext.geometry_buffer_vertex_position;
18
+
19
+ const position_offset = vertex_index * 3;
20
+
21
+ out[out_offset] = position[position_offset];
22
+ out[out_offset + 1] = position[position_offset + 1];
23
+ out[out_offset + 2] = position[position_offset + 2];
24
+
25
+ }
@@ -0,0 +1,18 @@
1
+ import { m_getTexCoord } from "./m_getTexCoord.js";
2
+
3
+ /**
4
+ * TODO doesn't need to be V3, can save memory
5
+ * @param {vec3} res
6
+ * @param {SMikkTSpaceContext} pContext
7
+ * @param {number} index
8
+ */
9
+ export function GetTexCoord(res, pContext, index) {
10
+
11
+ // inlined : IndexToData(&iF, &iI, index);
12
+ const iI = index & 0x3;
13
+ const iF = index >> 2;
14
+
15
+ m_getTexCoord(pContext, res, iF, iI);
16
+
17
+ res[2] = 1;
18
+ }