@woosh/meep-engine 2.42.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.
- package/core/assert.js +2 -2
- package/core/collection/array/array_swap.js +3 -3
- package/core/collection/map/AsyncLoadingCache.js +47 -0
- package/core/geom/3d/aabb/aabb3_compute_distance_above_plane_max.js +1 -1
- package/core/math/statistics/computeSampleSize_Cochran.js +3 -3
- package/editor/ecs/component/editors/geom/QuaternionEditor.js +12 -5
- package/engine/Engine.js +6 -1
- package/engine/EngineBootstrapper.js +2 -1
- package/engine/EngineHarness.js +5 -1
- package/engine/asset/AssetManager.js +97 -7
- package/engine/development/performance/AbstractMetric.js +1 -0
- package/engine/development/performance/RingBufferMetric.js +25 -4
- package/engine/ecs/EntityBuilder.js +29 -4
- package/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +17 -1
- package/engine/graphics/ecs/decal/v2/FPDecalSystem.js +18 -30
- package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +57 -16
- package/engine/graphics/ecs/mesh-v2/allocate_v3.js +37 -0
- package/engine/graphics/geometry/MikkT/AddTriToGroup.js +10 -0
- package/engine/graphics/geometry/MikkT/AssignRecur.js +84 -0
- package/engine/graphics/geometry/MikkT/AvgTSpace.js +38 -0
- package/engine/graphics/geometry/MikkT/Build4RuleGroups.js +96 -0
- package/engine/graphics/geometry/MikkT/BuildNeighborsFast.js +137 -0
- package/engine/graphics/geometry/MikkT/CalcTexArea.js +31 -0
- package/engine/graphics/geometry/MikkT/CompareSubGroups.js +26 -0
- package/engine/graphics/geometry/MikkT/DegenEpilogue.js +220 -0
- package/engine/graphics/geometry/MikkT/DegenPrologue.js +115 -0
- package/engine/graphics/geometry/MikkT/EvalTspace.js +128 -0
- package/engine/graphics/geometry/MikkT/GenerateInitialVerticesIndexList.js +48 -0
- package/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.js +184 -0
- package/engine/graphics/geometry/MikkT/GenerateTSpaces.js +226 -0
- package/engine/graphics/geometry/MikkT/GetEdge.js +45 -0
- package/engine/graphics/geometry/MikkT/GetNormal.js +16 -0
- package/engine/graphics/geometry/MikkT/GetPosition.js +25 -0
- package/engine/graphics/geometry/MikkT/GetTexCoord.js +18 -0
- package/engine/graphics/geometry/MikkT/InitTriInfo.js +180 -0
- package/engine/graphics/geometry/MikkT/Length.js +10 -0
- package/engine/graphics/geometry/MikkT/MakeIndex.js +18 -0
- package/engine/graphics/geometry/MikkT/MikkTSpace.js +165 -2197
- package/engine/graphics/geometry/MikkT/NormalizeSafe.js +21 -0
- package/engine/graphics/geometry/MikkT/NotZero.js +10 -0
- package/engine/graphics/geometry/MikkT/QuickSort.js +54 -0
- package/engine/graphics/geometry/MikkT/QuickSortEdges.js +71 -0
- package/engine/graphics/geometry/MikkT/SSubGroup.js +15 -0
- package/engine/graphics/geometry/MikkT/STSpace.js +36 -0
- package/engine/graphics/geometry/MikkT/constants/GROUP_WITH_ANY.js +1 -0
- package/engine/graphics/geometry/MikkT/constants/INTERNAL_RND_SORT_SEED.js +1 -0
- package/engine/graphics/geometry/MikkT/constants/MARK_DEGENERATE.js +1 -0
- package/engine/graphics/geometry/MikkT/constants/ORIENT_PRESERVING.js +1 -0
- package/engine/graphics/geometry/MikkT/constants/QUAD_ONE_DEGEN_TRI.js +1 -0
- package/engine/graphics/geometry/MikkT/m_getNormal.js +16 -0
- package/engine/graphics/geometry/MikkT/m_getNumFaces.js +8 -0
- package/engine/graphics/geometry/MikkT/m_getNumVerticesOfFace.js +11 -0
- package/engine/graphics/geometry/MikkT/m_getPosition.js +20 -0
- package/engine/graphics/geometry/MikkT/m_getTexCoord.js +16 -0
- package/engine/graphics/geometry/MikkT/m_setTSpace.js +35 -0
- package/engine/graphics/geometry/MikkT/m_setTSpaceBasic.js +22 -0
- package/engine/graphics/geometry/MikkT/malloc.js +16 -0
- package/engine/graphics/geometry/MikkT/v3_scale_dot_sub_normalize.js +52 -0
- package/engine/graphics/impostors/octahedral/ImpostorBaker.js +3 -2
- package/engine/graphics/impostors/octahedral/prototypeBaker.js +5 -5
- package/engine/graphics/render/forward_plus/LightManager.js +16 -6
- package/engine/graphics/render/forward_plus/data/TextureBackedMemoryRegion.js +7 -1
- package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +13 -3
- package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_PREAMBLE.js +2 -1
- package/engine/graphics/render/forward_plus/plugin/MaterialTransformer.js +14 -2
- package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +2 -2
- package/engine/intelligence/behavior/util/RotationBehavior.js +69 -0
- package/generation/example/filters/SampleGroundMoistureFilter.js +5 -5
- 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,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
|
+
}
|