@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
@@ -1,15 +1,18 @@
1
1
  import { EngineHarness } from "../../../../EngineHarness.js";
2
2
  import { FPDecalSystem } from "./FPDecalSystem.js";
3
- import EntityBuilder from "../../../../ecs/EntityBuilder.js";
3
+ import EntityBuilder, { EntityBuilderFlags } from "../../../../ecs/EntityBuilder.js";
4
4
  import { Decal } from "./Decal.js";
5
5
  import { Transform } from "../../../../ecs/transform/Transform.js";
6
6
  import { randomFloatBetween } from "../../../../../core/math/random/randomFloatBetween.js";
7
7
  import { seededRandom } from "../../../../../core/math/random/seededRandom.js";
8
- import Quaternion from "../../../../../core/geom/Quaternion.js";
9
8
  import { randomFromArray } from "../../../../../core/math/random/randomFromArray.js";
10
- import { BehaviorComponent } from "../../../../intelligence/behavior/ecs/BehaviorComponent.js";
11
- import { RotationBehavior } from "../../../../../../model/game/util/behavior/RotationBehavior.js";
12
9
  import { BehaviorSystem } from "../../../../intelligence/behavior/ecs/BehaviorSystem.js";
10
+ import { SGMeshSystem } from "../../mesh-v2/aggregate/SGMeshSystem.js";
11
+ import { ShadedGeometrySystem } from "../../mesh-v2/ShadedGeometrySystem.js";
12
+ import { TransformAttachmentSystem } from "../../../../ecs/transform-attachment/TransformAttachmentSystem.js";
13
+ import { SGMesh } from "../../mesh-v2/aggregate/SGMesh.js";
14
+ import { GameAssetType } from "../../../../asset/GameAssetType.js";
15
+ import { GLTFAssetLoader } from "../../../../asset/loaders/GLTFAssetLoader.js";
13
16
 
14
17
  const decal_urls = `data/textures/icons/FantasyIconsMegaPack/MagicItems/MagicItems_png/transparent/x64/staff_13_t.png
15
18
  data/textures/icons/FantasyIconsMegaPack/MagicItems/MagicItems_png/transparent/x64/artifact_01_t.png
@@ -195,6 +198,12 @@ data/textures/utility/sampling-test.png`
195
198
  .split('\n')
196
199
  .map(a => a.trim());
197
200
 
201
+ function promise_time_out(t) {
202
+ return new Promise(resolve => {
203
+ setTimeout(resolve, t);
204
+ });
205
+ }
206
+
198
207
  /**
199
208
  *
200
209
  * @param {Engine} engine
@@ -202,36 +211,68 @@ data/textures/utility/sampling-test.png`
202
211
  async function main(engine) {
203
212
 
204
213
  await EngineHarness.buildBasics({
205
- engine
214
+ engine,
215
+ enableWater: false,
216
+ cameraFarDistance: 300
206
217
  });
207
218
 
219
+ new EntityBuilder()
220
+ .add(SGMesh.fromURL("moicon/gnutti_not_optimized/model.gltf"))
221
+ .add(Transform.fromJSON({
222
+ position: { x: 10, y: 3, z: 10 },
223
+ scale: 1.5
224
+ }))
225
+ // .build(engine.entityManager.dataset);
226
+
227
+
208
228
  const random = seededRandom();
209
229
 
210
- for (let i = 0; i < 100; i++) {
230
+ const ENTITY_COUNT = 10000;
231
+
232
+ for (let i = 0; i < ENTITY_COUNT; i++) {
211
233
  const decal = new Decal();
212
234
 
213
235
  decal.uri = randomFromArray(random, decal_urls);
214
236
 
215
- new EntityBuilder()
216
- .add(Transform.fromJSON({
217
- position: { x: randomFloatBetween(random, 0, 10), y: 0, z: randomFloatBetween(random, 0, 10) },
218
- rotation: Quaternion.random(random)
219
- }))
237
+ const entity = new EntityBuilder();
238
+
239
+ entity.clearFlag(EntityBuilderFlags.WatchDestruction);
240
+
241
+ const transform = new Transform();
242
+ transform.position.set(
243
+ randomFloatBetween(random, -400, 400),
244
+ randomFloatBetween(random, 0, 0),
245
+ randomFloatBetween(random, -400, 400)
246
+ );
247
+ transform.rotation.random(random);
248
+ transform.scale.setScalar(0.5);
249
+
250
+ entity
251
+ .add(transform)
220
252
  .add(decal)
221
- .add(BehaviorComponent.fromOne(RotationBehavior.fromJSON({
222
- speed: 1
223
- })))
224
- .build(engine.entityManager.dataset);
253
+ // .add(BehaviorComponent.fromOne(RotationBehavior.fromJSON({ speed: 1 })))
254
+
255
+ entity.build(engine.entityManager.dataset);
256
+
225
257
  }
226
258
 
259
+ await promise_time_out(10);
260
+
261
+
227
262
  }
228
263
 
229
264
  new EngineHarness()
230
265
  .initialize({
231
266
  configuration(config, engine) {
267
+ const gltfAssetLoader = new GLTFAssetLoader();
268
+
269
+ config.addLoader(GameAssetType.ModelGLTF_JSON, gltfAssetLoader);
270
+ config.addLoader(GameAssetType.ModelGLTF, gltfAssetLoader);
232
271
 
233
272
  config.addSystem(new FPDecalSystem(engine));
234
273
  config.addSystem(new BehaviorSystem(engine))
235
-
274
+ config.addSystem(new SGMeshSystem(engine));
275
+ config.addSystem(new ShadedGeometrySystem(engine));
276
+ config.addSystem(new TransformAttachmentSystem(engine));
236
277
  }
237
278
  }).then(main);
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Larger bucket sizes provide better cache locality
3
+ * Larger bucket sizes also cause more hanging GC references, as if one matrix element is still held - ENTIRE bucket is still referenced
4
+ * @type {number}
5
+ */
6
+ const ALLOCATOR_BUCKET_CAPACITY = 42;
7
+
8
+ /**
9
+ *
10
+ * @type {ArrayBuffer|null}
11
+ */
12
+ let bucket = null;
13
+
14
+ /**
15
+ *
16
+ * @type {number}
17
+ */
18
+ let bucket_cursor = ALLOCATOR_BUCKET_CAPACITY;
19
+
20
+ const ELEMENT_BYTE_SIZE = 4 * 3;
21
+
22
+ /**
23
+ * custom Float32Array allocator, allocated memory in continuous chunks
24
+ * @returns {Float32Array}
25
+ */
26
+ export function allocate_v3() {
27
+ if (bucket_cursor >= ALLOCATOR_BUCKET_CAPACITY) {
28
+ bucket = new ArrayBuffer(ALLOCATOR_BUCKET_CAPACITY * ELEMENT_BYTE_SIZE);
29
+ bucket_cursor = 0;
30
+ }
31
+
32
+ const result = new Float32Array(bucket, bucket_cursor * ELEMENT_BYTE_SIZE, 3);
33
+
34
+ bucket_cursor++;
35
+
36
+ return result;
37
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ *
3
+ * @param {SGroup} pGroup
4
+ * @param {number} iTriIndex
5
+ * @returns {void}
6
+ */
7
+ export function AddTriToGroup(pGroup, iTriIndex) {
8
+ pGroup.pFaceIndices[pGroup.iNrFaces] = iTriIndex;
9
+ pGroup.iNrFaces++;
10
+ }
@@ -0,0 +1,84 @@
1
+ import { assert } from "../../../../core/assert.js";
2
+ import { GROUP_WITH_ANY } from "./constants/GROUP_WITH_ANY.js";
3
+ import { ORIENT_PRESERVING } from "./constants/ORIENT_PRESERVING.js";
4
+ import { AddTriToGroup } from "./AddTriToGroup.js";
5
+
6
+ /**
7
+ *
8
+ * @param {number[]} piTriListIn
9
+ * @param {STriInfo[]} psTriInfos
10
+ * @param {number} iMyTriIndex
11
+ * @param {SGroup} pGroup
12
+ * @return {boolean}
13
+ */
14
+ export function AssignRecur(
15
+ piTriListIn,
16
+ psTriInfos,
17
+ iMyTriIndex,
18
+ pGroup
19
+ ) {
20
+
21
+ // track down vertex
22
+ const iVertRep = pGroup.iVertexRepresentitive;
23
+ const triangle_address = iMyTriIndex * 3;
24
+
25
+ let i = -1;
26
+
27
+ if (piTriListIn[triangle_address] === iVertRep) {
28
+ i = 0;
29
+ } else if (piTriListIn[triangle_address + 1] === iVertRep) {
30
+ i = 1;
31
+ } else if (piTriListIn[triangle_address + 2] === iVertRep) {
32
+ i = 2;
33
+ }
34
+
35
+ assert.greaterThanOrEqual(i, 0);
36
+ assert.lessThan(i, 3);
37
+
38
+ const pMyTriInfo = psTriInfos[iMyTriIndex];
39
+
40
+ // early out
41
+ const sGroups = pMyTriInfo.AssignedGroup;
42
+
43
+ if (sGroups[i] === pGroup) {
44
+ return true;
45
+ } else if (sGroups[i] !== null) {
46
+ return false;
47
+ }
48
+
49
+ if ((pMyTriInfo.iFlag & GROUP_WITH_ANY) !== 0) {
50
+ // first to group with a group-with-anything triangle
51
+ // determines its orientation.
52
+ // This is the only existing order dependency in the code!!
53
+ if (
54
+ sGroups[0] === null &&
55
+ sGroups[1] === null &&
56
+ sGroups[2] === null
57
+ ) {
58
+ pMyTriInfo.iFlag &= (~ORIENT_PRESERVING);
59
+ pMyTriInfo.iFlag |= (pGroup.bOrientPreservering ? ORIENT_PRESERVING : 0);
60
+ }
61
+ }
62
+
63
+ const bOrient = (pMyTriInfo.iFlag & ORIENT_PRESERVING) !== 0;
64
+
65
+ if (bOrient !== pGroup.bOrientPreservering) {
66
+ return false;
67
+ }
68
+
69
+ AddTriToGroup(pGroup, iMyTriIndex);
70
+ sGroups[i] = pGroup;
71
+
72
+ const neigh_indexL = pMyTriInfo.FaceNeighbors[i];
73
+ const neigh_indexR = pMyTriInfo.FaceNeighbors[i > 0 ? (i - 1) : 2];
74
+
75
+ if (neigh_indexL >= 0) {
76
+ AssignRecur(piTriListIn, psTriInfos, neigh_indexL, pGroup);
77
+ }
78
+ if (neigh_indexR >= 0) {
79
+ AssignRecur(piTriListIn, psTriInfos, neigh_indexR, pGroup);
80
+ }
81
+
82
+
83
+ return true;
84
+ }
@@ -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
+ }