@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,128 @@
|
|
|
1
|
+
import { STSpace } from "./STSpace.js";
|
|
2
|
+
import { vec3 } from "gl-matrix";
|
|
3
|
+
import { GROUP_WITH_ANY } from "./constants/GROUP_WITH_ANY.js";
|
|
4
|
+
import { assert } from "../../../../core/assert.js";
|
|
5
|
+
import { GetNormal } from "./GetNormal.js";
|
|
6
|
+
import { NormalizeSafe } from "./NormalizeSafe.js";
|
|
7
|
+
import { GetPosition } from "./GetPosition.js";
|
|
8
|
+
import { clamp01 } from "../../../../core/math/clamp01.js";
|
|
9
|
+
import { v3_scale_dot_sub_normalize } from "./v3_scale_dot_sub_normalize.js";
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
let offset = 0;
|
|
13
|
+
const _buffer = new ArrayBuffer(3 * 4 * 6);
|
|
14
|
+
|
|
15
|
+
const vOs = new Float32Array(_buffer, offset, 3);
|
|
16
|
+
offset += 12;
|
|
17
|
+
const vOt = new Float32Array(_buffer, offset, 3);
|
|
18
|
+
offset += 12;
|
|
19
|
+
const n = new Float32Array(_buffer, offset, 3);
|
|
20
|
+
offset += 12;
|
|
21
|
+
|
|
22
|
+
const p0 = new Float32Array(_buffer, offset, 3);
|
|
23
|
+
offset += 12;
|
|
24
|
+
const p1 = new Float32Array(_buffer, offset, 3);
|
|
25
|
+
offset += 12;
|
|
26
|
+
const p2 = new Float32Array(_buffer, offset, 3);
|
|
27
|
+
offset += 12;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @param {STSpace} res
|
|
32
|
+
* @param {number[]|Uint32Array|Int32Array} face_indices
|
|
33
|
+
* @param {number} iFaces
|
|
34
|
+
* @param {number[]} piTriListIn
|
|
35
|
+
* @param {STriInfo[]} pTriInfos
|
|
36
|
+
* @param {SMikkTSpaceContext} pContext
|
|
37
|
+
* @param {number} iVertexRepresentitive
|
|
38
|
+
*/
|
|
39
|
+
export function EvalTspace(res, face_indices, iFaces, piTriListIn, pTriInfos, pContext, iVertexRepresentitive) {
|
|
40
|
+
|
|
41
|
+
let fAngleSum = 0;
|
|
42
|
+
|
|
43
|
+
res.vOs[0] = 0.0;
|
|
44
|
+
res.vOs[1] = 0.0;
|
|
45
|
+
res.vOs[2] = 0.0;
|
|
46
|
+
|
|
47
|
+
res.vOt[0] = 0.0;
|
|
48
|
+
res.vOt[1] = 0.0;
|
|
49
|
+
res.vOt[2] = 0.0;
|
|
50
|
+
|
|
51
|
+
res.fMagS = 0;
|
|
52
|
+
res.fMagT = 0;
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
for (let face = 0; face < iFaces; face++) {
|
|
56
|
+
const f = face_indices[face];
|
|
57
|
+
const tri_info = pTriInfos[f];
|
|
58
|
+
|
|
59
|
+
// only valid triangles get to add their contribution
|
|
60
|
+
if ((tri_info.iFlag & GROUP_WITH_ANY) === 0) {
|
|
61
|
+
let i = -1;
|
|
62
|
+
|
|
63
|
+
const f3 = 3 * f;
|
|
64
|
+
|
|
65
|
+
if (piTriListIn[f3] === iVertexRepresentitive) {
|
|
66
|
+
i = 0;
|
|
67
|
+
} else if (piTriListIn[f3 + 1] === iVertexRepresentitive) {
|
|
68
|
+
i = 1;
|
|
69
|
+
} else if (piTriListIn[f3 + 2] === iVertexRepresentitive) {
|
|
70
|
+
i = 2;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
assert(i >= 0 && i < 3);
|
|
74
|
+
|
|
75
|
+
// project
|
|
76
|
+
const index = piTriListIn[f3 + i];
|
|
77
|
+
|
|
78
|
+
GetNormal(n, pContext, index);
|
|
79
|
+
|
|
80
|
+
v3_scale_dot_sub_normalize(vOs, n, tri_info.vOs);
|
|
81
|
+
v3_scale_dot_sub_normalize(vOt, n, tri_info.vOt);
|
|
82
|
+
|
|
83
|
+
const i0 = piTriListIn[f3 + (i > 0 ? (i - 1) : 2)];
|
|
84
|
+
const i1 = piTriListIn[f3 + i];
|
|
85
|
+
const i2 = piTriListIn[f3 + (i < 2 ? (i + 1) : 0)];
|
|
86
|
+
|
|
87
|
+
GetPosition(p0, 0, pContext, i0);
|
|
88
|
+
GetPosition(p1, 0, pContext, i1);
|
|
89
|
+
GetPosition(p2, 0, pContext, i2);
|
|
90
|
+
|
|
91
|
+
vec3.sub(p0, p0, p1);
|
|
92
|
+
vec3.sub(p1, p2, p1);
|
|
93
|
+
|
|
94
|
+
// project
|
|
95
|
+
v3_scale_dot_sub_normalize(p0, n, p0);
|
|
96
|
+
v3_scale_dot_sub_normalize(p1, n, p1);
|
|
97
|
+
|
|
98
|
+
// weight contribution by the angle
|
|
99
|
+
// between the two edge vectors
|
|
100
|
+
|
|
101
|
+
const fCos = clamp01(vec3.dot(p0, p1));
|
|
102
|
+
const fAngle = Math.acos(fCos);
|
|
103
|
+
const fMagS = tri_info.fMagS;
|
|
104
|
+
const fMagT = tri_info.fMagT;
|
|
105
|
+
|
|
106
|
+
vec3.scale(p2, vOs, fAngle);
|
|
107
|
+
vec3.add(res.vOs, res.vOs, p2);
|
|
108
|
+
|
|
109
|
+
vec3.scale(p2, vOt, fAngle);
|
|
110
|
+
vec3.add(res.vOt, res.vOt, p2);
|
|
111
|
+
|
|
112
|
+
res.fMagS += (fAngle * fMagS);
|
|
113
|
+
res.fMagT += (fAngle * fMagT);
|
|
114
|
+
|
|
115
|
+
fAngleSum += fAngle;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// normalize
|
|
120
|
+
NormalizeSafe(res.vOs, res.vOs);
|
|
121
|
+
NormalizeSafe(res.vOt, res.vOt);
|
|
122
|
+
|
|
123
|
+
if (fAngleSum > 0) {
|
|
124
|
+
res.fMagS /= fAngleSum;
|
|
125
|
+
res.fMagT /= fAngleSum;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { m_getNumFaces } from "./m_getNumFaces.js";
|
|
2
|
+
import { MakeIndex } from "./MakeIndex.js";
|
|
3
|
+
import { assert } from "../../../../core/assert.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {STriInfo[]} pTriInfos
|
|
8
|
+
* @param {number[]|Int32Array} piTriList_out
|
|
9
|
+
* @param {SMikkTSpaceContext } pContext
|
|
10
|
+
* @param {number} iNrTrianglesIn
|
|
11
|
+
* @return {number}
|
|
12
|
+
*/
|
|
13
|
+
export function GenerateInitialVerticesIndexList(pTriInfos, piTriList_out, pContext, iNrTrianglesIn) {
|
|
14
|
+
let iTSpacesOffs = 0;
|
|
15
|
+
let iDstTriIndex = 0;
|
|
16
|
+
|
|
17
|
+
const face_count = m_getNumFaces(pContext);
|
|
18
|
+
|
|
19
|
+
for (let f = 0; f < face_count; f++) {
|
|
20
|
+
|
|
21
|
+
const tri_info = pTriInfos[iDstTriIndex];
|
|
22
|
+
|
|
23
|
+
tri_info.iOrgFaceNumber = f;
|
|
24
|
+
tri_info.iTSpacesOffs = iTSpacesOffs;
|
|
25
|
+
|
|
26
|
+
const pVerts = tri_info.vert_num;
|
|
27
|
+
|
|
28
|
+
pVerts[0] = 0;
|
|
29
|
+
pVerts[1] = 1;
|
|
30
|
+
pVerts[2] = 2;
|
|
31
|
+
|
|
32
|
+
piTriList_out[iDstTriIndex * 3 ] = MakeIndex(f, 0);
|
|
33
|
+
piTriList_out[iDstTriIndex * 3 + 1] = MakeIndex(f, 1);
|
|
34
|
+
piTriList_out[iDstTriIndex * 3 + 2] = MakeIndex(f, 2);
|
|
35
|
+
|
|
36
|
+
++iDstTriIndex; // next
|
|
37
|
+
|
|
38
|
+
iTSpacesOffs += 3;
|
|
39
|
+
assert.lessThanOrEqual(iDstTriIndex, iNrTrianglesIn);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (let t = 0; t < iNrTrianglesIn; t++) {
|
|
43
|
+
pTriInfos[t].iFlag = 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// return total amount of tspaces
|
|
47
|
+
return iTSpacesOffs;
|
|
48
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { vec3 } from "gl-matrix";
|
|
2
|
+
import { GetPosition } from "./GetPosition.js";
|
|
3
|
+
import { computeHashFloat } from "../../../../core/math/hash/computeHashFloat.js";
|
|
4
|
+
import { GetNormal } from "./GetNormal.js";
|
|
5
|
+
import { GetTexCoord } from "./GetTexCoord.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @param {number} x
|
|
10
|
+
* @param {number} y
|
|
11
|
+
* @param {number} z
|
|
12
|
+
* @returns {number}
|
|
13
|
+
*/
|
|
14
|
+
function HASH(x, y, z) {
|
|
15
|
+
return ((x) * 73856093) ^ ((y) * 19349663) ^ ((z) * 83492791);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
* @param {number} x
|
|
21
|
+
* @param {number} y
|
|
22
|
+
* @param {number} z
|
|
23
|
+
* @returns {number}
|
|
24
|
+
*/
|
|
25
|
+
function HASH_F(x, y, z) {
|
|
26
|
+
return (computeHashFloat(x) * 73856093) ^ (computeHashFloat(y) * 19349663) ^ (computeHashFloat(z) * 83492791);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Sort comp and data based on comp.
|
|
31
|
+
* comp2 and data2 are used as temporary storage.
|
|
32
|
+
*
|
|
33
|
+
* @param {Uint32Array} comp
|
|
34
|
+
* @param {Int32Array} data
|
|
35
|
+
* @param {Uint32Array} comp2
|
|
36
|
+
* @param {Int32Array} data2
|
|
37
|
+
* @param {number} n
|
|
38
|
+
*/
|
|
39
|
+
function radixsort_pair(comp, data, comp2, data2, n) {
|
|
40
|
+
let shift = 0;
|
|
41
|
+
|
|
42
|
+
let _data_0 = data;
|
|
43
|
+
let _data_1 = data2;
|
|
44
|
+
|
|
45
|
+
let _comp_0 = comp;
|
|
46
|
+
let _comp_1 = comp2;
|
|
47
|
+
|
|
48
|
+
for (let pass = 0; pass < 4; pass++, shift += 8) {
|
|
49
|
+
const bins = new Int32Array(257);
|
|
50
|
+
/* Count number of elements per bin. */
|
|
51
|
+
for (let i = 0; i < n; i++) {
|
|
52
|
+
bins[((_comp_0[i] >> shift) & 0xff) + 1]++;
|
|
53
|
+
}
|
|
54
|
+
/* Compute prefix sum to find position of each bin in the sorted array. */
|
|
55
|
+
for (let i = 2; i < 256; i++) {
|
|
56
|
+
bins[i] += bins[i - 1];
|
|
57
|
+
}
|
|
58
|
+
/* Insert the elements in their correct location based on their bin. */
|
|
59
|
+
for (let i = 0; i < n; i++) {
|
|
60
|
+
const pos = bins[(_comp_0[i] >> shift) & 0xff]++;
|
|
61
|
+
_comp_1[pos] = _comp_0[i];
|
|
62
|
+
_data_1[pos] = _data_0[i];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Swap arrays. */
|
|
66
|
+
let tmpdata = _data_0;
|
|
67
|
+
_data_0 = _data_1;
|
|
68
|
+
_data_1 = tmpdata;
|
|
69
|
+
|
|
70
|
+
let tmpcomp = _comp_0;
|
|
71
|
+
_comp_0 = _comp_1;
|
|
72
|
+
_comp_1 = tmpcomp;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
*
|
|
78
|
+
* @param {number[]|Int32Array} piTriList_in_and_out
|
|
79
|
+
* @param {SMikkTSpaceContext} pContext
|
|
80
|
+
* @param {number} iNrTrianglesIn
|
|
81
|
+
* @returns {void}
|
|
82
|
+
*/
|
|
83
|
+
export function GenerateSharedVerticesIndexList(
|
|
84
|
+
piTriList_in_and_out,
|
|
85
|
+
pContext,
|
|
86
|
+
iNrTrianglesIn
|
|
87
|
+
) {
|
|
88
|
+
const numVertices = iNrTrianglesIn * 3;
|
|
89
|
+
|
|
90
|
+
const _buffer = new ArrayBuffer(numVertices * 4 * 4);
|
|
91
|
+
|
|
92
|
+
const hashes = new Uint32Array(_buffer, 0, numVertices);
|
|
93
|
+
const indices = new Int32Array(_buffer, numVertices * 4, numVertices);
|
|
94
|
+
const temp_hashes = new Uint32Array(_buffer, numVertices * 2 * 4, numVertices);
|
|
95
|
+
const temp_indices = new Int32Array(_buffer, numVertices * 3 * 4, numVertices);
|
|
96
|
+
|
|
97
|
+
const v = vec3.create();
|
|
98
|
+
|
|
99
|
+
for (let i = 0; i < numVertices; i++) {
|
|
100
|
+
const index = piTriList_in_and_out[i];
|
|
101
|
+
|
|
102
|
+
GetPosition(v, 0, pContext, index);
|
|
103
|
+
const hashP = HASH_F(v[0], v[1], v[2]);
|
|
104
|
+
|
|
105
|
+
GetNormal(v, pContext, index);
|
|
106
|
+
const hashN = HASH_F(v[0], v[1], v[2]);
|
|
107
|
+
|
|
108
|
+
GetTexCoord(v, pContext, index);
|
|
109
|
+
const hashT = HASH_F(v[0], v[1], v[2]);
|
|
110
|
+
|
|
111
|
+
hashes[i] = HASH(hashP, hashN, hashT);
|
|
112
|
+
indices[i] = i;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
radixsort_pair(hashes, indices, temp_hashes, temp_indices, numVertices);
|
|
116
|
+
|
|
117
|
+
// free(temp_hashes);
|
|
118
|
+
// free(temp_indices);
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
const vT = vec3.create();
|
|
122
|
+
const vP = vec3.create();
|
|
123
|
+
|
|
124
|
+
const vT2 = vec3.create();
|
|
125
|
+
const vP2 = vec3.create();
|
|
126
|
+
|
|
127
|
+
const vN = vec3.create();
|
|
128
|
+
const vN2 = vec3.create();
|
|
129
|
+
|
|
130
|
+
/*
|
|
131
|
+
* Process blocks of vertices with the same hash.
|
|
132
|
+
* Vertices in the block might still be separate, but we know for sure that
|
|
133
|
+
* vertices in different blocks will never be identical.
|
|
134
|
+
*/
|
|
135
|
+
let blockstart = 0;
|
|
136
|
+
while (blockstart < numVertices) {
|
|
137
|
+
/* Find end of this block (exclusive). */
|
|
138
|
+
const hash = hashes[blockstart];
|
|
139
|
+
let blockend = blockstart + 1;
|
|
140
|
+
for (; blockend < numVertices; blockend++) {
|
|
141
|
+
if (hashes[blockend] !== hash)
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
for (let i = blockstart; i < blockend; i++) {
|
|
146
|
+
|
|
147
|
+
const index1 = piTriList_in_and_out[indices[i]];
|
|
148
|
+
|
|
149
|
+
GetPosition(vP, 0, pContext, index1);
|
|
150
|
+
GetNormal(vN, pContext, index1);
|
|
151
|
+
GetTexCoord(vT, pContext, index1);
|
|
152
|
+
|
|
153
|
+
for (let i2 = i + 1; i2 < blockend; i2++) {
|
|
154
|
+
const index2 = piTriList_in_and_out[indices[i2]];
|
|
155
|
+
|
|
156
|
+
if (index1 === index2) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
GetPosition(vP2, 0, pContext, index2);
|
|
161
|
+
GetNormal(vN2, pContext, index2);
|
|
162
|
+
GetTexCoord(vT2, pContext, index2);
|
|
163
|
+
|
|
164
|
+
if (
|
|
165
|
+
vP[0] === vP2[0] && vP[1] === vP2[1] && vP[2] === vP2[2] &&
|
|
166
|
+
vN[0] === vN2[0] && vN[1] === vN2[1] && vN[2] === vN2[2] &&
|
|
167
|
+
vT[0] === vT2[0] && vT[1] === vT2[1] && vT[2] === vT2[2]
|
|
168
|
+
) {
|
|
169
|
+
piTriList_in_and_out[indices[i2]] = index1;
|
|
170
|
+
/* Once i2>i has been identified as a duplicate, we can stop since any
|
|
171
|
+
* i3>i2>i that is a duplicate of i (and therefore also i2) will also be
|
|
172
|
+
* compared to i2 and therefore be identified there anyways. */
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* Advance to next block. */
|
|
179
|
+
blockstart = blockend;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// free(hashes);
|
|
183
|
+
// free(indices);
|
|
184
|
+
}
|
|
@@ -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
|
+
}
|