@woosh/meep-engine 2.42.0 → 2.42.2

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 (70) hide show
  1. package/core/assert.js +2 -2
  2. package/core/collection/RingBuffer.js +15 -0
  3. package/core/collection/array/array_swap.js +3 -3
  4. package/core/collection/map/AsyncLoadingCache.js +47 -0
  5. package/core/geom/3d/aabb/aabb3_compute_distance_above_plane_max.js +1 -1
  6. package/core/math/statistics/computeSampleSize_Cochran.js +3 -3
  7. package/editor/ecs/component/editors/geom/QuaternionEditor.js +12 -5
  8. package/engine/Engine.js +6 -1
  9. package/engine/EngineBootstrapper.js +2 -1
  10. package/engine/EngineHarness.js +5 -1
  11. package/engine/asset/AssetManager.js +97 -7
  12. package/engine/development/performance/AbstractMetric.js +3 -1
  13. package/engine/development/performance/RingBufferMetric.js +39 -4
  14. package/engine/ecs/EntityBuilder.js +29 -4
  15. package/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +17 -1
  16. package/engine/graphics/ecs/decal/v2/FPDecalSystem.js +18 -30
  17. package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +57 -16
  18. package/engine/graphics/ecs/mesh-v2/allocate_v3.js +37 -0
  19. package/engine/graphics/geometry/MikkT/AddTriToGroup.js +10 -0
  20. package/engine/graphics/geometry/MikkT/AssignRecur.js +84 -0
  21. package/engine/graphics/geometry/MikkT/AvgTSpace.js +38 -0
  22. package/engine/graphics/geometry/MikkT/Build4RuleGroups.js +96 -0
  23. package/engine/graphics/geometry/MikkT/BuildNeighborsFast.js +137 -0
  24. package/engine/graphics/geometry/MikkT/CalcTexArea.js +31 -0
  25. package/engine/graphics/geometry/MikkT/CompareSubGroups.js +26 -0
  26. package/engine/graphics/geometry/MikkT/DegenEpilogue.js +220 -0
  27. package/engine/graphics/geometry/MikkT/DegenPrologue.js +115 -0
  28. package/engine/graphics/geometry/MikkT/EvalTspace.js +128 -0
  29. package/engine/graphics/geometry/MikkT/GenerateInitialVerticesIndexList.js +48 -0
  30. package/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.js +184 -0
  31. package/engine/graphics/geometry/MikkT/GenerateTSpaces.js +226 -0
  32. package/engine/graphics/geometry/MikkT/GetEdge.js +45 -0
  33. package/engine/graphics/geometry/MikkT/GetNormal.js +16 -0
  34. package/engine/graphics/geometry/MikkT/GetPosition.js +25 -0
  35. package/engine/graphics/geometry/MikkT/GetTexCoord.js +18 -0
  36. package/engine/graphics/geometry/MikkT/InitTriInfo.js +180 -0
  37. package/engine/graphics/geometry/MikkT/Length.js +10 -0
  38. package/engine/graphics/geometry/MikkT/MakeIndex.js +18 -0
  39. package/engine/graphics/geometry/MikkT/MikkTSpace.js +165 -2197
  40. package/engine/graphics/geometry/MikkT/NormalizeSafe.js +21 -0
  41. package/engine/graphics/geometry/MikkT/NotZero.js +10 -0
  42. package/engine/graphics/geometry/MikkT/QuickSort.js +54 -0
  43. package/engine/graphics/geometry/MikkT/QuickSortEdges.js +71 -0
  44. package/engine/graphics/geometry/MikkT/SSubGroup.js +15 -0
  45. package/engine/graphics/geometry/MikkT/STSpace.js +36 -0
  46. package/engine/graphics/geometry/MikkT/constants/GROUP_WITH_ANY.js +1 -0
  47. package/engine/graphics/geometry/MikkT/constants/INTERNAL_RND_SORT_SEED.js +1 -0
  48. package/engine/graphics/geometry/MikkT/constants/MARK_DEGENERATE.js +1 -0
  49. package/engine/graphics/geometry/MikkT/constants/ORIENT_PRESERVING.js +1 -0
  50. package/engine/graphics/geometry/MikkT/constants/QUAD_ONE_DEGEN_TRI.js +1 -0
  51. package/engine/graphics/geometry/MikkT/m_getNormal.js +16 -0
  52. package/engine/graphics/geometry/MikkT/m_getNumFaces.js +8 -0
  53. package/engine/graphics/geometry/MikkT/m_getNumVerticesOfFace.js +11 -0
  54. package/engine/graphics/geometry/MikkT/m_getPosition.js +20 -0
  55. package/engine/graphics/geometry/MikkT/m_getTexCoord.js +16 -0
  56. package/engine/graphics/geometry/MikkT/m_setTSpace.js +35 -0
  57. package/engine/graphics/geometry/MikkT/m_setTSpaceBasic.js +22 -0
  58. package/engine/graphics/geometry/MikkT/malloc.js +16 -0
  59. package/engine/graphics/geometry/MikkT/v3_scale_dot_sub_normalize.js +52 -0
  60. package/engine/graphics/impostors/octahedral/ImpostorBaker.js +3 -2
  61. package/engine/graphics/impostors/octahedral/prototypeBaker.js +5 -5
  62. package/engine/graphics/render/forward_plus/LightManager.js +16 -6
  63. package/engine/graphics/render/forward_plus/data/TextureBackedMemoryRegion.js +7 -1
  64. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +13 -3
  65. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_PREAMBLE.js +2 -1
  66. package/engine/graphics/render/forward_plus/plugin/MaterialTransformer.js +14 -2
  67. package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +2 -2
  68. package/engine/intelligence/behavior/util/RotationBehavior.js +69 -0
  69. package/generation/example/filters/SampleGroundMoistureFilter.js +5 -5
  70. package/package.json +1 -1
@@ -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
+ }
@@ -0,0 +1,180 @@
1
+ import { GROUP_WITH_ANY } from "./constants/GROUP_WITH_ANY.js";
2
+ import { vec3 } from "gl-matrix";
3
+ import { GetPosition } from "./GetPosition.js";
4
+ import { GetTexCoord } from "./GetTexCoord.js";
5
+ import { ORIENT_PRESERVING } from "./constants/ORIENT_PRESERVING.js";
6
+ import { NotZero } from "./NotZero.js";
7
+ import { fabsf } from "../../../../core/math/fabsf.js";
8
+ import { Length } from "./Length.js";
9
+ import { MARK_DEGENERATE } from "./constants/MARK_DEGENERATE.js";
10
+ import { CalcTexArea } from "./CalcTexArea.js";
11
+ import { BuildNeighborsFast } from "./BuildNeighborsFast.js";
12
+
13
+ const t1 = vec3.create();
14
+ const t2 = vec3.create();
15
+ const t3 = vec3.create();
16
+
17
+ const d1 = vec3.create();
18
+ const d2 = vec3.create();
19
+
20
+ const vOs = vec3.create();
21
+ const vOt = vec3.create();
22
+
23
+ const v1 = vec3.create();
24
+ const v2 = vec3.create();
25
+ const v3 = vec3.create();
26
+
27
+ const v_temp_0 = vec3.create();
28
+ const v_temp_1 = vec3.create();
29
+
30
+ /**
31
+ *
32
+ * @param {STriInfo[]} pTriInfos
33
+ * @param {number[]|Int32Array} piTriListIn
34
+ * @param {SMikkTSpaceContext} pContext
35
+ * @param {number} iNrTrianglesIn
36
+ * @returns {void}
37
+ */
38
+ export function InitTriInfo(pTriInfos, piTriListIn, pContext, iNrTrianglesIn) {
39
+ let f = 0, i = 0, t = 0;
40
+ // pTriInfos[f].iFlag is cleared in GenerateInitialVerticesIndexList() which is called before this function.
41
+
42
+ // generate neighbor info list
43
+ for (f = 0; f < iNrTrianglesIn; f++) {
44
+ const tri = pTriInfos[f];
45
+
46
+ for (i = 0; i < 3; i++) {
47
+
48
+ tri.FaceNeighbors[i] = -1;
49
+ tri.AssignedGroup[i] = null;
50
+ }
51
+
52
+ tri.vOs[0] = 0.0;
53
+ tri.vOs[1] = 0.0;
54
+ tri.vOs[2] = 0.0;
55
+
56
+ tri.vOt[0] = 0.0;
57
+ tri.vOt[1] = 0.0;
58
+ tri.vOt[2] = 0.0;
59
+
60
+ tri.fMagS = 0;
61
+ tri.fMagT = 0;
62
+
63
+ // assumed bad
64
+ tri.iFlag |= GROUP_WITH_ANY;
65
+ }
66
+
67
+
68
+ // evaluate first order derivatives
69
+ for (f = 0; f < iNrTrianglesIn; f++) {
70
+ // initial values
71
+ const f3 = f * 3;
72
+
73
+ GetPosition(v1,0, pContext, piTriListIn[f3 + 0]);
74
+ GetPosition(v2,0, pContext, piTriListIn[f3 + 1]);
75
+ GetPosition(v3,0, pContext, piTriListIn[f3 + 2]);
76
+
77
+ GetTexCoord(t1, pContext, piTriListIn[f3 + 0]);
78
+ GetTexCoord(t2, pContext, piTriListIn[f3 + 1]);
79
+ GetTexCoord(t3, pContext, piTriListIn[f3 + 2]);
80
+
81
+ const t21x = t2[0] - t1[0];
82
+ const t21y = t2[1] - t1[1];
83
+
84
+ const t31x = t3[0] - t1[0];
85
+ const t31y = t3[1] - t1[1];
86
+
87
+ vec3.sub(d1, v2, v1);
88
+ vec3.sub(d2, v3, v1);
89
+
90
+ const fSignedAreaSTx2 = t21x * t31y - t21y * t31x;
91
+ //assert(fSignedAreaSTx2!=0);
92
+
93
+ vec3.scale(v_temp_0, d1, t31y);
94
+ vec3.scale(v_temp_1, d2, t21y);
95
+ vec3.sub(vOs, v_temp_0, v_temp_1); // eq 18
96
+
97
+
98
+ vec3.scale(v_temp_0, d1, -t31x);
99
+ vec3.scale(v_temp_1, d2, t21x);
100
+ vec3.add(vOt, v_temp_0, v_temp_1); // eq 19
101
+
102
+ const tri_info = pTriInfos[f];
103
+ tri_info.iFlag |= (fSignedAreaSTx2 > 0 ? ORIENT_PRESERVING : 0);
104
+
105
+ if (NotZero(fSignedAreaSTx2)) {
106
+ const fAbsArea = fabsf(fSignedAreaSTx2);
107
+
108
+ const fLenOs = Length(vOs);
109
+ const fLenOt = Length(vOt);
110
+
111
+ const fS = (tri_info.iFlag & ORIENT_PRESERVING) === 0 ? (-1.0) : 1.0;
112
+
113
+ if (NotZero(fLenOs)) {
114
+ vec3.scale(tri_info.vOs, vOs, fS / fLenOs);
115
+ }
116
+
117
+ if (NotZero(fLenOt)) {
118
+ vec3.scale(tri_info.vOt, vOt, fS / fLenOt);
119
+ }
120
+
121
+ // evaluate magnitudes prior to normalization of vOs and vOt
122
+ tri_info.fMagS = fLenOs / fAbsArea;
123
+ tri_info.fMagT = fLenOt / fAbsArea;
124
+
125
+ // if this is a good triangle
126
+ if (NotZero(tri_info.fMagS) && NotZero(tri_info.fMagT)) {
127
+ tri_info.iFlag &= (~GROUP_WITH_ANY);
128
+ }
129
+ }
130
+ }
131
+
132
+ // force otherwise healthy quads to a fixed orientation
133
+ while (t < (iNrTrianglesIn - 1)) {
134
+ const tri_0 = pTriInfos[t];
135
+ const tri_1 = pTriInfos[t + 1];
136
+
137
+ const iFO_a = tri_0.iOrgFaceNumber;
138
+ const iFO_b = tri_1.iOrgFaceNumber;
139
+
140
+ if (iFO_a === iFO_b) {
141
+ // this is a quad
142
+ const bIsDeg_a = (tri_0.iFlag & MARK_DEGENERATE) !== 0;
143
+ const bIsDeg_b = (tri_1.iFlag & MARK_DEGENERATE) !== 0;
144
+
145
+ // bad triangles should already have been removed by
146
+ // DegenPrologue(), but just in case check bIsDeg_a and bIsDeg_a are false
147
+ if ((bIsDeg_a || bIsDeg_b) === false) {
148
+ const bOrientA = (tri_0.iFlag & ORIENT_PRESERVING) !== 0;
149
+ const bOrientB = (tri_1.iFlag & ORIENT_PRESERVING) !== 0;
150
+
151
+ // if this happens the quad has extremely bad mapping!!
152
+ if (bOrientA !== bOrientB) {
153
+ //printf("found quad with bad mapping\n");
154
+ let bChooseOrientFirstTri = false;
155
+
156
+ if ((tri_1.iFlag & GROUP_WITH_ANY) !== 0) {
157
+ bChooseOrientFirstTri = true;
158
+ } else if (CalcTexArea(pContext, piTriListIn, t * 3) >= CalcTexArea(pContext, piTriListIn, (t + 1) * 3 + 0)) {
159
+ bChooseOrientFirstTri = true;
160
+ }
161
+
162
+ // force match
163
+ const t0 = bChooseOrientFirstTri ? tri_0 : tri_1;
164
+ const t1 = bChooseOrientFirstTri ? tri_1 : tri_0;
165
+ t1.iFlag &= (~ORIENT_PRESERVING); // clear first
166
+ t1.iFlag |= (t0.iFlag & ORIENT_PRESERVING); // copy bit
167
+ }
168
+ }
169
+ t += 2;
170
+ } else {
171
+ ++t;
172
+ }
173
+ }
174
+
175
+ // match up edge pairs
176
+
177
+ const pEdges = new Float32Array(iNrTrianglesIn * 3 * 3);
178
+ BuildNeighborsFast(pTriInfos, pEdges, piTriListIn, iNrTrianglesIn);
179
+
180
+ }
@@ -0,0 +1,10 @@
1
+ import { vec3 } from "gl-matrix";
2
+
3
+ /**
4
+ *
5
+ * @param {vec3} v
6
+ * @returns {number}
7
+ */
8
+ export function Length(v) {
9
+ return Math.sqrt(vec3.squaredLength(v));
10
+ }
@@ -0,0 +1,18 @@
1
+ import { assert } from "../../../../core/assert.js";
2
+
3
+ /**
4
+ *
5
+ * @param {number} iFace
6
+ * @param {number} iVert
7
+ * @returns {number}
8
+ */
9
+ export function MakeIndex(iFace, iVert) {
10
+ assert.greaterThanOrEqual(iVert, 0);
11
+ assert.lessThan(iVert, 4);
12
+ assert.greaterThanOrEqual(iFace, 0);
13
+
14
+ assert.isNonNegativeInteger(iFace,'iFace');
15
+ assert.isNonNegativeInteger(iVert,'iVert');
16
+
17
+ return (iFace << 2) | (iVert & 0x3);
18
+ }