@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.
- package/core/assert.js +2 -2
- package/core/collection/RingBuffer.js +15 -0
- 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 +3 -1
- package/engine/development/performance/RingBufferMetric.js +39 -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
|
@@ -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
|
-
|
|
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
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
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,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
|
+
}
|