@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
138 lines (105 loc) • 4.36 kB
JavaScript
import { INTERNAL_RND_SORT_SEED } from "./constants/INTERNAL_RND_SORT_SEED.js";
import { QuickSortEdges } from "./QuickSortEdges.js";
import { vec3 } from "gl-matrix";
import { GetEdge } from "./GetEdge.js";
/**
*
* @param {STriInfo[]} pTriInfos
* @param {number[]|Float32Array} pEdges
* @param {number[]} piTriListIn
* @param {number} iNrTrianglesIn
* @returns {void}
*/
export function BuildNeighborsFast(pTriInfos, pEdges, piTriListIn, iNrTrianglesIn) {
// build array of edges
const uSeed = INTERNAL_RND_SORT_SEED; // could replace with a random seed?
for (let f = 0; f < iNrTrianglesIn; f++) {
for (let i = 0; i < 3; i++) {
const edge_index = f * 3 + i;
const i0 = piTriListIn[edge_index];
const i1 = piTriListIn[f * 3 + (i < 2 ? (i + 1) : 0)];
pEdges[edge_index * 3] = i0 < i1 ? i0 : i1; // put minimum index in i0
pEdges[edge_index * 3 + 1] = !(i0 < i1) ? i0 : i1; // put maximum index in i1
pEdges[edge_index * 3 + 2] = f; // record face number
}
}
// sort over all edges by i0, this is a pricey one.
QuickSortEdges(pEdges, 0, iNrTrianglesIn * 3 - 1, 0, uSeed); // sort channel 0 which is i0
// sub sort over i1, should be fast.
// could replace this with a 64 bit int sort over (i0,i1)
// with i0 as msb in the quicksort call above.
const iEntries = iNrTrianglesIn * 3;
let iCurStartIndex = 0;
for (let i = 1; i < iEntries; i++) {
if (pEdges[iCurStartIndex * 3] !== pEdges[i * 3]) {
const iL = iCurStartIndex;
const iR = i - 1;
//const int iElems = i-iL;
iCurStartIndex = i;
QuickSortEdges(pEdges, iL, iR, 1, uSeed); // sort channel 1 which is i1
}
}
// sub sort over f, which should be fast.
// this step is to remain compliant with BuildNeighborsSlow() when
// more than 2 triangles use the same edge (such as a butterfly topology).
iCurStartIndex = 0;
for (let i = 1; i < iEntries; i++) {
if (
pEdges[iCurStartIndex * 3] !== pEdges[i * 3]
|| pEdges[iCurStartIndex * 3 + 1] !== pEdges[i * 3 + 1]
) {
const iL = iCurStartIndex;
const iR = i - 1;
//const int iElems = i-iL;
iCurStartIndex = i;
QuickSortEdges(pEdges, iL, iR, 2, uSeed); // sort channel 2 which is f
}
}
const temp_edge_A = vec3.create();
const temp_edge_B = vec3.create();
// pair up, adjacent triangles
for (let i = 0; i < iEntries; i++) {
const i0 = pEdges[i * 3];
const i1 = pEdges[i * 3 + 1];
const f = pEdges[i * 3 + 2];
GetEdge(temp_edge_A, 0, piTriListIn, f * 3, i0, i1); // resolve index ordering and edge_num
const i0_A = temp_edge_A[0];
const i1_A = temp_edge_A[1];
const edgenum_A = temp_edge_A[2];
const bUnassigned_A = pTriInfos[f].FaceNeighbors[edgenum_A] === -1;
if (!bUnassigned_A) {
continue;
}
let j = i + 1;
while (
j < iEntries
&& i0 === pEdges[j * 3]
&& i1 === pEdges[j * 3 + 1]
) {
const t = pEdges[j * 3 + 2];
GetEdge(
temp_edge_B,
0,
piTriListIn,
t * 3,
pEdges[j * 3],
pEdges[j * 3 + 1]
); // resolve index ordering and edge_num
// flip i0_B and i1_B
const i0_B = temp_edge_B[1];
const i1_B = temp_edge_B[2];
const edgenum_B = temp_edge_B[2];
//assert(!(i0_A==i1_B && i1_A==i0_B));
const bUnassigned_B = pTriInfos[t].FaceNeighbors[edgenum_B] === -1;
if (i0_A === i0_B && i1_A === i1_B && bUnassigned_B) {
const t = pEdges[j * 3 + 2];
pTriInfos[f].FaceNeighbors[edgenum_A] = t;
//assert(pTriInfos[t].FaceNeighbors[edgenum_B]==-1);
pTriInfos[t].FaceNeighbors[edgenum_B] = f;
break;
} else {
++j;
}
}
}
}