@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.
- 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/geom/3d/apply_mat4_transform_to_v3_array.js +2 -4
- package/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.js +28 -0
- package/core/geom/Quaternion.js +14 -0
- 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 +13 -3
- 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/ecs/transform/Transform.js +23 -3
- package/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +17 -1
- package/engine/graphics/ecs/decal/v2/Decal.d.ts +11 -0
- package/engine/graphics/ecs/decal/v2/Decal.js +50 -0
- package/engine/graphics/ecs/decal/v2/FPDecalSystem.d.ts +8 -0
- package/engine/graphics/ecs/decal/v2/FPDecalSystem.js +201 -0
- package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +278 -0
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +8 -1
- package/engine/graphics/ecs/mesh-v2/allocate_v3.js +37 -0
- package/engine/graphics/ecs/mesh-v2/build_three_object.js +4 -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 +197 -2068
- 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/geometry/buffered/computeGeometryEquality.js +1 -1
- package/engine/graphics/geometry/buffered/computeGeometryHash.js +1 -1
- package/engine/graphics/impostors/octahedral/ImpostorBaker.js +28 -14
- package/engine/graphics/impostors/octahedral/ImpostorDescription.js +6 -0
- package/engine/graphics/impostors/octahedral/README.md +1 -0
- package/engine/graphics/impostors/octahedral/bake/compute_bounding_sphere.js +25 -22
- package/engine/graphics/impostors/octahedral/bake/compute_bounding_sphere_radius_only.js +37 -0
- package/engine/graphics/impostors/octahedral/bake/prepare_bake_material.js +30 -1
- package/engine/graphics/impostors/octahedral/grid/HemiOctahedralUvEncoder.js +1 -1
- package/engine/graphics/impostors/octahedral/prototypeBaker.js +121 -22
- package/engine/graphics/impostors/octahedral/shader/BakeShaderStandard.js +46 -7
- package/engine/graphics/impostors/octahedral/shader/ImpostorShaderV0.js +349 -0
- package/engine/graphics/impostors/octahedral/shader/ImpostorShaderV1.js +74 -0
- package/engine/graphics/impostors/octahedral/shader/glsl/v1/common.glsl +209 -0
- package/engine/graphics/impostors/octahedral/shader/glsl/v1/flagment.glsl +80 -0
- package/engine/graphics/impostors/octahedral/shader/glsl/v1/vertex.glsl +350 -0
- package/engine/graphics/micron/render/v1/getTransformedPositionsCached.js +1 -1
- package/engine/graphics/render/forward_plus/LightManager.js +17 -7
- package/engine/graphics/render/forward_plus/data/TextureBackedMemoryRegion.js +7 -1
- package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +13 -5
- package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_PREAMBLE.js +3 -1
- package/engine/graphics/render/forward_plus/model/Decal.js +19 -2
- 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/graphics/texture/sampler/Sampler2D.js +10 -10
- package/engine/graphics/texture/sampler/prototypeSamplerFiltering.js +117 -11
- package/engine/graphics/texture/sampler/resize/sampler2d_downsample_mipmap.js +66 -0
- package/engine/graphics/texture/sampler/sampler2_d_scale_down_lanczos.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,38 @@
|
|
|
1
|
+
import { vec3 } from "gl-matrix";
|
|
2
|
+
import { NormalizeSafe } from "./NormalizeSafe.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {STSpace} ts_res
|
|
7
|
+
* @param {STSpace} pTS0
|
|
8
|
+
* @param {STSpace} pTS1
|
|
9
|
+
* @returns {void}
|
|
10
|
+
*/
|
|
11
|
+
export function AvgTSpace(ts_res, pTS0, pTS1) {
|
|
12
|
+
|
|
13
|
+
// this if is important. Due to floating point precision
|
|
14
|
+
// averaging when ts0==ts1 will cause a slight difference
|
|
15
|
+
// which results in tangent space splits later on
|
|
16
|
+
if (
|
|
17
|
+
pTS0.fMagS === pTS1.fMagS && pTS0.fMagT === pTS1.fMagT &&
|
|
18
|
+
vec3.exactEquals(pTS0.vOs, pTS1.vOs) && vec3.exactEquals(pTS0.vOt, pTS1.vOt)
|
|
19
|
+
) {
|
|
20
|
+
|
|
21
|
+
ts_res.fMagS = pTS0.fMagS;
|
|
22
|
+
ts_res.fMagT = pTS0.fMagT;
|
|
23
|
+
|
|
24
|
+
vec3.copy(ts_res.vOs, pTS0.vOs);
|
|
25
|
+
vec3.copy(ts_res.vOt, pTS0.vOt);
|
|
26
|
+
|
|
27
|
+
} else {
|
|
28
|
+
ts_res.fMagS = 0.5 * (pTS0.fMagS + pTS1.fMagS);
|
|
29
|
+
ts_res.fMagT = 0.5 * (pTS0.fMagT + pTS1.fMagT);
|
|
30
|
+
|
|
31
|
+
vec3.add(ts_res.vOs, pTS0.vOs, pTS1.vOs);
|
|
32
|
+
vec3.add(ts_res.vOt, pTS0.vOt, pTS1.vOt);
|
|
33
|
+
|
|
34
|
+
NormalizeSafe(ts_res.vOs, ts_res.vOs);
|
|
35
|
+
NormalizeSafe(ts_res.vOt, ts_res.vOt);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { GROUP_WITH_ANY } from "./constants/GROUP_WITH_ANY.js";
|
|
2
|
+
import { assert } from "../../../../core/assert.js";
|
|
3
|
+
import { ORIENT_PRESERVING } from "./constants/ORIENT_PRESERVING.js";
|
|
4
|
+
import { AddTriToGroup } from "./AddTriToGroup.js";
|
|
5
|
+
import { AssignRecur } from "./AssignRecur.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @param {STriInfo[]} pTriInfos
|
|
10
|
+
* @param {SGroup[]} pGroups
|
|
11
|
+
* @param {number[]|Int32Array} piGroupTrianglesBuffer
|
|
12
|
+
* @param {number[]|Int32Array} piTriListIn
|
|
13
|
+
* @param {number} iNrTrianglesIn
|
|
14
|
+
* @return {number}
|
|
15
|
+
*/
|
|
16
|
+
export function Build4RuleGroups(
|
|
17
|
+
pTriInfos,
|
|
18
|
+
pGroups,
|
|
19
|
+
piGroupTrianglesBuffer,
|
|
20
|
+
piTriListIn,
|
|
21
|
+
iNrTrianglesIn
|
|
22
|
+
) {
|
|
23
|
+
|
|
24
|
+
const iNrMaxGroups = iNrTrianglesIn * 3;
|
|
25
|
+
let iNrActiveGroups = 0;
|
|
26
|
+
let iOffset = 0;
|
|
27
|
+
|
|
28
|
+
for (let f=0; f < iNrTrianglesIn; f++) {
|
|
29
|
+
const tri_info_f = pTriInfos[f];
|
|
30
|
+
|
|
31
|
+
for (let i = 0; i < 3; i++) {
|
|
32
|
+
|
|
33
|
+
// if not assigned to a group
|
|
34
|
+
if ((tri_info_f.iFlag & GROUP_WITH_ANY) === 0 && tri_info_f.AssignedGroup[i] === null) {
|
|
35
|
+
|
|
36
|
+
const vert_index = piTriListIn[f * 3 + i];
|
|
37
|
+
|
|
38
|
+
assert.lessThan(iNrActiveGroups, iNrMaxGroups);
|
|
39
|
+
|
|
40
|
+
const assigned_group = pGroups[iNrActiveGroups];
|
|
41
|
+
tri_info_f.AssignedGroup[i] = assigned_group;
|
|
42
|
+
|
|
43
|
+
assigned_group.iVertexRepresentitive = vert_index;
|
|
44
|
+
|
|
45
|
+
const bOrPre = (tri_info_f.iFlag & ORIENT_PRESERVING) !== 0;
|
|
46
|
+
|
|
47
|
+
assigned_group.bOrientPreservering = bOrPre;
|
|
48
|
+
assigned_group.iNrFaces = 0;
|
|
49
|
+
assigned_group.pFaceIndices = new Int32Array(piGroupTrianglesBuffer.buffer, iOffset * 4);
|
|
50
|
+
++iNrActiveGroups;
|
|
51
|
+
|
|
52
|
+
AddTriToGroup(assigned_group, f);
|
|
53
|
+
|
|
54
|
+
const neigh_indexL = tri_info_f.FaceNeighbors[i];
|
|
55
|
+
const neigh_indexR = tri_info_f.FaceNeighbors[i > 0 ? (i - 1) : 2];
|
|
56
|
+
|
|
57
|
+
if (neigh_indexL >= 0) {
|
|
58
|
+
|
|
59
|
+
// neighbor
|
|
60
|
+
const bAnswer = AssignRecur(
|
|
61
|
+
piTriListIn,
|
|
62
|
+
pTriInfos,
|
|
63
|
+
neigh_indexL,
|
|
64
|
+
assigned_group
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
assert(bAnswer || (bOrPre !== ((pTriInfos[neigh_indexL].iFlag & ORIENT_PRESERVING) !== 0)) );
|
|
68
|
+
|
|
69
|
+
}
|
|
70
|
+
if (neigh_indexR >= 0) {
|
|
71
|
+
|
|
72
|
+
// neighbor
|
|
73
|
+
const bAnswer = AssignRecur(
|
|
74
|
+
piTriListIn,
|
|
75
|
+
pTriInfos,
|
|
76
|
+
neigh_indexR,
|
|
77
|
+
assigned_group
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
assert(bAnswer || bOrPre !== ((pTriInfos[neigh_indexR].iFlag & ORIENT_PRESERVING) !== 0));
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// update offset
|
|
85
|
+
iOffset += assigned_group.iNrFaces;
|
|
86
|
+
|
|
87
|
+
// since the groups are disjoint a triangle can never
|
|
88
|
+
// belong to more than 3 groups. Subsequently, something
|
|
89
|
+
// is completely screwed if this assertion ever hits.
|
|
90
|
+
assert.lessThanOrEqual(iOffset, iNrMaxGroups);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return iNrActiveGroups;
|
|
96
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { INTERNAL_RND_SORT_SEED } from "./constants/INTERNAL_RND_SORT_SEED.js";
|
|
2
|
+
import { QuickSortEdges } from "./QuickSortEdges.js";
|
|
3
|
+
import { vec3 } from "gl-matrix";
|
|
4
|
+
import { GetEdge } from "./GetEdge.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param {STriInfo[]} pTriInfos
|
|
9
|
+
* @param {number[]|Float32Array} pEdges
|
|
10
|
+
* @param {number[]} piTriListIn
|
|
11
|
+
* @param {number} iNrTrianglesIn
|
|
12
|
+
* @returns {void}
|
|
13
|
+
*/
|
|
14
|
+
export function BuildNeighborsFast(pTriInfos, pEdges, piTriListIn, iNrTrianglesIn) {
|
|
15
|
+
// build array of edges
|
|
16
|
+
const uSeed = INTERNAL_RND_SORT_SEED; // could replace with a random seed?
|
|
17
|
+
|
|
18
|
+
for (let f = 0; f < iNrTrianglesIn; f++) {
|
|
19
|
+
for (let i = 0; i < 3; i++) {
|
|
20
|
+
|
|
21
|
+
const edge_index = f * 3 + i;
|
|
22
|
+
|
|
23
|
+
const i0 = piTriListIn[edge_index];
|
|
24
|
+
const i1 = piTriListIn[f * 3 + (i < 2 ? (i + 1) : 0)];
|
|
25
|
+
|
|
26
|
+
pEdges[edge_index * 3] = i0 < i1 ? i0 : i1; // put minimum index in i0
|
|
27
|
+
pEdges[edge_index * 3 + 1] = !(i0 < i1) ? i0 : i1; // put maximum index in i1
|
|
28
|
+
pEdges[edge_index * 3 + 2] = f; // record face number
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// sort over all edges by i0, this is a pricey one.
|
|
33
|
+
QuickSortEdges(pEdges, 0, iNrTrianglesIn * 3 - 1, 0, uSeed); // sort channel 0 which is i0
|
|
34
|
+
|
|
35
|
+
// sub sort over i1, should be fast.
|
|
36
|
+
// could replace this with a 64 bit int sort over (i0,i1)
|
|
37
|
+
// with i0 as msb in the quicksort call above.
|
|
38
|
+
const iEntries = iNrTrianglesIn * 3;
|
|
39
|
+
let iCurStartIndex = 0;
|
|
40
|
+
|
|
41
|
+
for (let i = 1; i < iEntries; i++) {
|
|
42
|
+
if (pEdges[iCurStartIndex * 3] !== pEdges[i * 3]) {
|
|
43
|
+
|
|
44
|
+
const iL = iCurStartIndex;
|
|
45
|
+
const iR = i - 1;
|
|
46
|
+
//const int iElems = i-iL;
|
|
47
|
+
iCurStartIndex = i;
|
|
48
|
+
|
|
49
|
+
QuickSortEdges(pEdges, iL, iR, 1, uSeed); // sort channel 1 which is i1
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// sub sort over f, which should be fast.
|
|
55
|
+
// this step is to remain compliant with BuildNeighborsSlow() when
|
|
56
|
+
// more than 2 triangles use the same edge (such as a butterfly topology).
|
|
57
|
+
iCurStartIndex = 0;
|
|
58
|
+
|
|
59
|
+
for (let i = 1; i < iEntries; i++) {
|
|
60
|
+
|
|
61
|
+
if (
|
|
62
|
+
pEdges[iCurStartIndex * 3] !== pEdges[i * 3]
|
|
63
|
+
|| pEdges[iCurStartIndex * 3 + 1] !== pEdges[i * 3 + 1]
|
|
64
|
+
) {
|
|
65
|
+
const iL = iCurStartIndex;
|
|
66
|
+
const iR = i - 1;
|
|
67
|
+
//const int iElems = i-iL;
|
|
68
|
+
iCurStartIndex = i;
|
|
69
|
+
QuickSortEdges(pEdges, iL, iR, 2, uSeed); // sort channel 2 which is f
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const temp_edge_A = vec3.create();
|
|
75
|
+
const temp_edge_B = vec3.create();
|
|
76
|
+
|
|
77
|
+
// pair up, adjacent triangles
|
|
78
|
+
for (let i = 0; i < iEntries; i++) {
|
|
79
|
+
|
|
80
|
+
const i0 = pEdges[i * 3];
|
|
81
|
+
const i1 = pEdges[i * 3 + 1];
|
|
82
|
+
const f = pEdges[i * 3 + 2];
|
|
83
|
+
|
|
84
|
+
GetEdge(temp_edge_A, 0, piTriListIn, f * 3, i0, i1); // resolve index ordering and edge_num
|
|
85
|
+
|
|
86
|
+
const i0_A = temp_edge_A[0];
|
|
87
|
+
const i1_A = temp_edge_A[1];
|
|
88
|
+
const edgenum_A = temp_edge_A[2];
|
|
89
|
+
|
|
90
|
+
const bUnassigned_A = pTriInfos[f].FaceNeighbors[edgenum_A] === -1;
|
|
91
|
+
|
|
92
|
+
if (!bUnassigned_A) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let j = i + 1;
|
|
97
|
+
|
|
98
|
+
while (
|
|
99
|
+
j < iEntries
|
|
100
|
+
&& i0 === pEdges[j * 3]
|
|
101
|
+
&& i1 === pEdges[j * 3 + 1]
|
|
102
|
+
) {
|
|
103
|
+
|
|
104
|
+
const t = pEdges[j * 3 + 2];
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
GetEdge(
|
|
108
|
+
temp_edge_B,
|
|
109
|
+
0,
|
|
110
|
+
piTriListIn,
|
|
111
|
+
t * 3,
|
|
112
|
+
pEdges[j * 3],
|
|
113
|
+
pEdges[j * 3 + 1]
|
|
114
|
+
); // resolve index ordering and edge_num
|
|
115
|
+
|
|
116
|
+
// flip i0_B and i1_B
|
|
117
|
+
const i0_B = temp_edge_B[1];
|
|
118
|
+
const i1_B = temp_edge_B[2];
|
|
119
|
+
const edgenum_B = temp_edge_B[2];
|
|
120
|
+
|
|
121
|
+
//assert(!(i0_A==i1_B && i1_A==i0_B));
|
|
122
|
+
const bUnassigned_B = pTriInfos[t].FaceNeighbors[edgenum_B] === -1;
|
|
123
|
+
|
|
124
|
+
if (i0_A === i0_B && i1_A === i1_B && bUnassigned_B) {
|
|
125
|
+
|
|
126
|
+
const t = pEdges[j * 3 + 2];
|
|
127
|
+
pTriInfos[f].FaceNeighbors[edgenum_A] = t;
|
|
128
|
+
//assert(pTriInfos[t].FaceNeighbors[edgenum_B]==-1);
|
|
129
|
+
pTriInfos[t].FaceNeighbors[edgenum_B] = f;
|
|
130
|
+
break;
|
|
131
|
+
|
|
132
|
+
} else {
|
|
133
|
+
++j;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { vec3 } from "gl-matrix";
|
|
2
|
+
import { GetTexCoord } from "./GetTexCoord.js";
|
|
3
|
+
import { fabsf } from "../../../../core/math/fabsf.js";
|
|
4
|
+
|
|
5
|
+
const t1 = vec3.create();
|
|
6
|
+
const t2 = vec3.create();
|
|
7
|
+
const t3 = vec3.create();
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* returns the texture area times 2
|
|
11
|
+
* @param {SMikkTSpaceContext } pContext
|
|
12
|
+
* @param {number[]} indices
|
|
13
|
+
* @param {number} indices_offset
|
|
14
|
+
* @returns {number}
|
|
15
|
+
*/
|
|
16
|
+
export function CalcTexArea(pContext, indices, indices_offset) {
|
|
17
|
+
|
|
18
|
+
GetTexCoord(t1, pContext, indices[indices_offset ]);
|
|
19
|
+
GetTexCoord(t2, pContext, indices[indices_offset + 1]);
|
|
20
|
+
GetTexCoord(t3, pContext, indices[indices_offset + 2]);
|
|
21
|
+
|
|
22
|
+
const t21x = t2[0] - t1[0];
|
|
23
|
+
const t21y = t2[1] - t1[1];
|
|
24
|
+
|
|
25
|
+
const t31x = t3[0] - t1[0];
|
|
26
|
+
const t31y = t3[1] - t1[1];
|
|
27
|
+
|
|
28
|
+
const fSignedAreaSTx2 = t21x * t31y - t21y * t31x;
|
|
29
|
+
|
|
30
|
+
return fabsf(fSignedAreaSTx2);
|
|
31
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {SSubGroup} pg1
|
|
4
|
+
* @param {SSubGroup } pg2
|
|
5
|
+
* @returns {boolean}
|
|
6
|
+
*/
|
|
7
|
+
export function CompareSubGroups(pg1, pg2) {
|
|
8
|
+
const n = pg1.iNrFaces;
|
|
9
|
+
|
|
10
|
+
if (n !== pg2.iNrFaces) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const tris_1 = pg1.pTriMembers;
|
|
15
|
+
const tris_2 = pg2.pTriMembers;
|
|
16
|
+
|
|
17
|
+
for (let i = 0; i < n; i++) {
|
|
18
|
+
|
|
19
|
+
if (tris_1[i] !== tris_2[i]) {
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { QUAD_ONE_DEGEN_TRI } from "./constants/QUAD_ONE_DEGEN_TRI.js";
|
|
2
|
+
import { vec3 } from "gl-matrix";
|
|
3
|
+
import { GetPosition } from "./GetPosition.js";
|
|
4
|
+
import { MakeIndex } from "./MakeIndex.js";
|
|
5
|
+
import { assert } from "../../../../core/assert.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @type {vec3}
|
|
9
|
+
*/
|
|
10
|
+
const vDstP = vec3.create();
|
|
11
|
+
const vSrcP = vec3.create();
|
|
12
|
+
|
|
13
|
+
class VertReverseLookupContext {
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @type {boolean}
|
|
17
|
+
*/
|
|
18
|
+
bIsInitialized = false;
|
|
19
|
+
/**
|
|
20
|
+
* int*
|
|
21
|
+
* @type {Int32Array|null}
|
|
22
|
+
*/
|
|
23
|
+
pLookup = null;
|
|
24
|
+
/**
|
|
25
|
+
* int
|
|
26
|
+
* @type {number}
|
|
27
|
+
*/
|
|
28
|
+
iMaxVertIndex = 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @param {number[]} piTriListIn
|
|
34
|
+
* @param {number} iNrTrianglesIn
|
|
35
|
+
* @param {VertReverseLookupContext} pLookupCtx
|
|
36
|
+
*/
|
|
37
|
+
function GenerateReverseLookup(
|
|
38
|
+
piTriListIn,
|
|
39
|
+
iNrTrianglesIn,
|
|
40
|
+
pLookupCtx
|
|
41
|
+
) {
|
|
42
|
+
let t;
|
|
43
|
+
|
|
44
|
+
// Figure out what size of lookup array we need.
|
|
45
|
+
pLookupCtx.iMaxVertIndex = -1;
|
|
46
|
+
|
|
47
|
+
for (t = 0; t < 3 * iNrTrianglesIn; t++) {
|
|
48
|
+
const iVertIndex = piTriListIn[t];
|
|
49
|
+
|
|
50
|
+
if (iVertIndex > pLookupCtx.iMaxVertIndex) {
|
|
51
|
+
pLookupCtx.iMaxVertIndex = iVertIndex;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
// Allocate memory.
|
|
56
|
+
if (pLookupCtx.iMaxVertIndex < 1) {
|
|
57
|
+
// Nothing to allocate, all triangles are degenerate.
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
pLookupCtx.pLookup = new Int32Array(pLookupCtx.iMaxVertIndex + 1);
|
|
61
|
+
|
|
62
|
+
// Fill in lookup.
|
|
63
|
+
for (t = 0; t <= pLookupCtx.iMaxVertIndex; t++) {
|
|
64
|
+
pLookupCtx.pLookup[t] = -1;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
for (t = 0; t < 3 * iNrTrianglesIn; t++) {
|
|
68
|
+
const iVertIndex = piTriListIn[t];
|
|
69
|
+
|
|
70
|
+
if (pLookupCtx.pLookup[iVertIndex] !== -1) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
pLookupCtx.pLookup[iVertIndex] = t;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
*
|
|
80
|
+
* @param {VertReverseLookupContext} pLookupCtx
|
|
81
|
+
* @param {number[]} piTriListIn
|
|
82
|
+
* @param {number} iNrTrianglesIn
|
|
83
|
+
* @param {number} iVertexIndex
|
|
84
|
+
* @returns {number}
|
|
85
|
+
*/
|
|
86
|
+
function LookupVertexIndexFromGoodTriangle(
|
|
87
|
+
pLookupCtx,
|
|
88
|
+
piTriListIn,
|
|
89
|
+
iNrTrianglesIn,
|
|
90
|
+
iVertexIndex
|
|
91
|
+
) {
|
|
92
|
+
// Allocate lookup on demand.
|
|
93
|
+
if (!pLookupCtx.bIsInitialized) {
|
|
94
|
+
GenerateReverseLookup(piTriListIn, iNrTrianglesIn, pLookupCtx);
|
|
95
|
+
pLookupCtx.bIsInitialized = true;
|
|
96
|
+
}
|
|
97
|
+
// Make sure vertex index is in the mapping.
|
|
98
|
+
if (iVertexIndex > pLookupCtx.iMaxVertIndex) {
|
|
99
|
+
return -1;
|
|
100
|
+
}
|
|
101
|
+
if (pLookupCtx.pLookup === null) {
|
|
102
|
+
return -1;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Perform actual lookup.
|
|
106
|
+
return pLookupCtx.pLookup[iVertexIndex];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
*
|
|
111
|
+
* @param {STSpace[]} psTspace
|
|
112
|
+
* @param {STriInfo[]} pTriInfos
|
|
113
|
+
* @param {number[]|Int32Array} piTriListIn
|
|
114
|
+
* @param {SMikkTSpaceContext} pContext
|
|
115
|
+
* @param {number} iNrTrianglesIn
|
|
116
|
+
* @param {number} iTotTris
|
|
117
|
+
* @returns {void}
|
|
118
|
+
*/
|
|
119
|
+
export function DegenEpilogue(psTspace, pTriInfos, piTriListIn, pContext, iNrTrianglesIn, iTotTris) {
|
|
120
|
+
|
|
121
|
+
// deal with degenerate triangles
|
|
122
|
+
// punishment for degenerate triangles is O(N^2)
|
|
123
|
+
const lookupCtx = new VertReverseLookupContext();
|
|
124
|
+
|
|
125
|
+
for (let t = iNrTrianglesIn; t < iTotTris; t++) {
|
|
126
|
+
const tri0 = pTriInfos[t];
|
|
127
|
+
|
|
128
|
+
// degenerate triangles on a quad with one good triangle are skipped
|
|
129
|
+
// here but processed in the next loop
|
|
130
|
+
const bSkip = (tri0.iFlag & QUAD_ONE_DEGEN_TRI) !== 0;
|
|
131
|
+
|
|
132
|
+
if (bSkip) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
for (let i = 0; i < 3; i++) {
|
|
137
|
+
|
|
138
|
+
const index1 = piTriListIn[t * 3 + i];
|
|
139
|
+
const j = LookupVertexIndexFromGoodTriangle(lookupCtx, piTriListIn, iNrTrianglesIn, index1);
|
|
140
|
+
|
|
141
|
+
if (j < 0) {
|
|
142
|
+
// Matching vertex from good triangle is not found.
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const iTri = Math.floor(j / 3);
|
|
147
|
+
const iVert = j % 3;
|
|
148
|
+
|
|
149
|
+
const tri1 = pTriInfos[iTri];
|
|
150
|
+
|
|
151
|
+
const iSrcVert = tri1.vert_num[iVert];
|
|
152
|
+
const iSrcOffs = tri1.iTSpacesOffs;
|
|
153
|
+
|
|
154
|
+
const iDstVert = tri0.vert_num[i];
|
|
155
|
+
const iDstOffs = tri0.iTSpacesOffs;
|
|
156
|
+
|
|
157
|
+
// copy tspace
|
|
158
|
+
const dst_tspace = psTspace[iDstOffs + iDstVert];
|
|
159
|
+
const src_tspace = psTspace[iSrcOffs + iSrcVert];
|
|
160
|
+
|
|
161
|
+
dst_tspace.copy(src_tspace);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
// deal with degenerate quads with one good triangle
|
|
167
|
+
for (let t = 0; t < iNrTrianglesIn; t++) {
|
|
168
|
+
// this triangle belongs to a quad where the
|
|
169
|
+
// other triangle is degenerate
|
|
170
|
+
const tri = pTriInfos[t];
|
|
171
|
+
|
|
172
|
+
if ((tri.iFlag & QUAD_ONE_DEGEN_TRI) === 0) {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const pV = tri.vert_num;
|
|
177
|
+
|
|
178
|
+
const iFlag = (1 << pV[0]) | (1 << pV[1]) | (1 << pV[2]);
|
|
179
|
+
|
|
180
|
+
let iMissingIndex = 0;
|
|
181
|
+
|
|
182
|
+
if ((iFlag & 2) === 0) {
|
|
183
|
+
iMissingIndex = 1;
|
|
184
|
+
} else if ((iFlag & 4) === 0) {
|
|
185
|
+
iMissingIndex = 2;
|
|
186
|
+
} else if ((iFlag & 8) === 0) {
|
|
187
|
+
iMissingIndex = 3;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const iOrgF = tri.iOrgFaceNumber;
|
|
191
|
+
|
|
192
|
+
GetPosition(vDstP, 0, pContext, MakeIndex(iOrgF, iMissingIndex));
|
|
193
|
+
|
|
194
|
+
let bNotFound = true;
|
|
195
|
+
let i = 0;
|
|
196
|
+
|
|
197
|
+
while (i < 3) {
|
|
198
|
+
|
|
199
|
+
const iVert = pV[i];
|
|
200
|
+
GetPosition(vSrcP, 0, pContext, MakeIndex(iOrgF, iVert));
|
|
201
|
+
|
|
202
|
+
if (vec3.exactEquals(vSrcP, vDstP)) {
|
|
203
|
+
|
|
204
|
+
const iOffs = tri.iTSpacesOffs;
|
|
205
|
+
|
|
206
|
+
psTspace[iOffs + iMissingIndex].copy(psTspace[iOffs + iVert]);
|
|
207
|
+
|
|
208
|
+
bNotFound = false;
|
|
209
|
+
|
|
210
|
+
break;
|
|
211
|
+
|
|
212
|
+
} else {
|
|
213
|
+
++i;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
assert(!bNotFound);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { MARK_DEGENERATE } from "./constants/MARK_DEGENERATE.js";
|
|
2
|
+
import { QUAD_ONE_DEGEN_TRI } from "./constants/QUAD_ONE_DEGEN_TRI.js";
|
|
3
|
+
import { assert } from "../../../../core/assert.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {STriInfo[]} pTriInfos
|
|
8
|
+
* @param {number[]|Int32Array} piTriList_out
|
|
9
|
+
* @param {number} iNrTrianglesIn
|
|
10
|
+
* @param {number} iTotTris
|
|
11
|
+
* @returns {void}
|
|
12
|
+
*/
|
|
13
|
+
export function DegenPrologue(
|
|
14
|
+
pTriInfos,
|
|
15
|
+
piTriList_out,
|
|
16
|
+
iNrTrianglesIn,
|
|
17
|
+
iTotTris
|
|
18
|
+
) {
|
|
19
|
+
// locate quads with only one good triangle
|
|
20
|
+
let t = 0;
|
|
21
|
+
|
|
22
|
+
while (t < (iTotTris - 1)) {
|
|
23
|
+
|
|
24
|
+
const tri_0 = pTriInfos[t];
|
|
25
|
+
const tri_1 = pTriInfos[t + 1];
|
|
26
|
+
|
|
27
|
+
const iFO_a = tri_0.iOrgFaceNumber;
|
|
28
|
+
const iFO_b = tri_1.iOrgFaceNumber;
|
|
29
|
+
|
|
30
|
+
if (iFO_a === iFO_b) {
|
|
31
|
+
|
|
32
|
+
// this is a quad
|
|
33
|
+
const bIsDeg_a = (tri_0.iFlag & MARK_DEGENERATE) !== 0;
|
|
34
|
+
const bIsDeg_b = (tri_1.iFlag & MARK_DEGENERATE) !== 0;
|
|
35
|
+
|
|
36
|
+
if (bIsDeg_a !== bIsDeg_b) {
|
|
37
|
+
tri_0.iFlag |= QUAD_ONE_DEGEN_TRI;
|
|
38
|
+
tri_1.iFlag |= QUAD_ONE_DEGEN_TRI;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
t += 2;
|
|
42
|
+
|
|
43
|
+
} else {
|
|
44
|
+
++t;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// reorder list so all degen triangles are moved to the back
|
|
49
|
+
// without reordering the good triangles
|
|
50
|
+
let iNextGoodTriangleSearchIndex = 1;
|
|
51
|
+
let bStillFindingGoodOnes = true;
|
|
52
|
+
|
|
53
|
+
t = 0;
|
|
54
|
+
|
|
55
|
+
while (t < iNrTrianglesIn && bStillFindingGoodOnes) {
|
|
56
|
+
|
|
57
|
+
const bIsGood = (pTriInfos[t].iFlag & MARK_DEGENERATE) === 0;
|
|
58
|
+
|
|
59
|
+
if (bIsGood) {
|
|
60
|
+
if (iNextGoodTriangleSearchIndex < (t + 2)) {
|
|
61
|
+
iNextGoodTriangleSearchIndex = t + 2;
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
// search for the first good triangle.
|
|
65
|
+
let bJustADegenerate = true;
|
|
66
|
+
|
|
67
|
+
while (bJustADegenerate && iNextGoodTriangleSearchIndex < iTotTris) {
|
|
68
|
+
|
|
69
|
+
const bIsGood = (pTriInfos[iNextGoodTriangleSearchIndex].iFlag & MARK_DEGENERATE) === 0;
|
|
70
|
+
|
|
71
|
+
if (bIsGood) {
|
|
72
|
+
bJustADegenerate = false;
|
|
73
|
+
} else {
|
|
74
|
+
++iNextGoodTriangleSearchIndex;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const t0 = t;
|
|
80
|
+
const t1 = iNextGoodTriangleSearchIndex;
|
|
81
|
+
|
|
82
|
+
++iNextGoodTriangleSearchIndex;
|
|
83
|
+
assert.greaterThan(iNextGoodTriangleSearchIndex, (t + 1));
|
|
84
|
+
|
|
85
|
+
// swap triangle t0 and t1
|
|
86
|
+
if (!bJustADegenerate) {
|
|
87
|
+
|
|
88
|
+
for (let i = 0; i < 3; i++) {
|
|
89
|
+
const i0 = t0 * 3 + i;
|
|
90
|
+
const i1 = t1 * 3 + i;
|
|
91
|
+
|
|
92
|
+
const index = piTriList_out[i0];
|
|
93
|
+
|
|
94
|
+
piTriList_out[i0] = piTriList_out[i1];
|
|
95
|
+
piTriList_out[i1] = index;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const tri_info = pTriInfos[t0];
|
|
99
|
+
pTriInfos[t0] = pTriInfos[t1];
|
|
100
|
+
pTriInfos[t1] = tri_info;
|
|
101
|
+
|
|
102
|
+
} else {
|
|
103
|
+
// this is not supposed to happen
|
|
104
|
+
bStillFindingGoodOnes = false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (bStillFindingGoodOnes) {
|
|
109
|
+
++t;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
assert(bStillFindingGoodOnes); // code will still work.
|
|
114
|
+
assert.equal(iNrTrianglesIn, t);
|
|
115
|
+
}
|