UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

221 lines (173 loc) • 5.66 kB
import { QUAD_ONE_DEGEN_TRI } from "./constants/QUAD_ONE_DEGEN_TRI.js"; import { vec3 } from "gl-matrix"; import { GetPosition } from "./GetPosition.js"; import { MakeIndex } from "./MakeIndex.js"; import { assert } from "../../../../core/assert.js"; /** * @type {vec3} */ const vDstP = vec3.create(); const vSrcP = vec3.create(); class VertReverseLookupContext { /** * * @type {boolean} */ bIsInitialized = false; /** * int* * @type {Int32Array|null} */ pLookup = null; /** * int * @type {number} */ iMaxVertIndex = 0; } /** * * @param {number[]} piTriListIn * @param {number} iNrTrianglesIn * @param {VertReverseLookupContext} pLookupCtx */ function GenerateReverseLookup( piTriListIn, iNrTrianglesIn, pLookupCtx ) { let t; // Figure out what size of lookup array we need. pLookupCtx.iMaxVertIndex = -1; for (t = 0; t < 3 * iNrTrianglesIn; t++) { const iVertIndex = piTriListIn[t]; if (iVertIndex > pLookupCtx.iMaxVertIndex) { pLookupCtx.iMaxVertIndex = iVertIndex; } } // Allocate memory. if (pLookupCtx.iMaxVertIndex < 1) { // Nothing to allocate, all triangles are degenerate. return; } pLookupCtx.pLookup = new Int32Array(pLookupCtx.iMaxVertIndex + 1); // Fill in lookup. for (t = 0; t <= pLookupCtx.iMaxVertIndex; t++) { pLookupCtx.pLookup[t] = -1; } for (t = 0; t < 3 * iNrTrianglesIn; t++) { const iVertIndex = piTriListIn[t]; if (pLookupCtx.pLookup[iVertIndex] !== -1) { continue; } pLookupCtx.pLookup[iVertIndex] = t; } } /** * * @param {VertReverseLookupContext} pLookupCtx * @param {number[]} piTriListIn * @param {number} iNrTrianglesIn * @param {number} iVertexIndex * @returns {number} */ function LookupVertexIndexFromGoodTriangle( pLookupCtx, piTriListIn, iNrTrianglesIn, iVertexIndex ) { // Allocate lookup on demand. if (!pLookupCtx.bIsInitialized) { GenerateReverseLookup(piTriListIn, iNrTrianglesIn, pLookupCtx); pLookupCtx.bIsInitialized = true; } // Make sure vertex index is in the mapping. if (iVertexIndex > pLookupCtx.iMaxVertIndex) { return -1; } if (pLookupCtx.pLookup === null) { return -1; } // Perform actual lookup. return pLookupCtx.pLookup[iVertexIndex]; } /** * * @param {STSpace[]} psTspace * @param {STriInfo[]} pTriInfos * @param {number[]|Int32Array} piTriListIn * @param {SMikkTSpaceContext} pContext * @param {number} iNrTrianglesIn * @param {number} iTotTris * @returns {void} */ export function DegenEpilogue(psTspace, pTriInfos, piTriListIn, pContext, iNrTrianglesIn, iTotTris) { // deal with degenerate triangles // punishment for degenerate triangles is O(N^2) const lookupCtx = new VertReverseLookupContext(); for (let t = iNrTrianglesIn; t < iTotTris; t++) { const tri0 = pTriInfos[t]; // degenerate triangles on a quad with one good triangle are skipped // here but processed in the next loop const bSkip = (tri0.iFlag & QUAD_ONE_DEGEN_TRI) !== 0; if (bSkip) { continue; } for (let i = 0; i < 3; i++) { const index1 = piTriListIn[t * 3 + i]; const j = LookupVertexIndexFromGoodTriangle(lookupCtx, piTriListIn, iNrTrianglesIn, index1); if (j < 0) { // Matching vertex from good triangle is not found. continue; } const iTri = Math.floor(j / 3); const iVert = j % 3; const tri1 = pTriInfos[iTri]; const iSrcVert = tri1.vert_num[iVert]; const iSrcOffs = tri1.iTSpacesOffs; const iDstVert = tri0.vert_num[i]; const iDstOffs = tri0.iTSpacesOffs; // copy tspace const dst_tspace = psTspace[iDstOffs + iDstVert]; const src_tspace = psTspace[iSrcOffs + iSrcVert]; dst_tspace.copy(src_tspace); } } // deal with degenerate quads with one good triangle for (let t = 0; t < iNrTrianglesIn; t++) { // this triangle belongs to a quad where the // other triangle is degenerate const tri = pTriInfos[t]; if ((tri.iFlag & QUAD_ONE_DEGEN_TRI) === 0) { continue; } const pV = tri.vert_num; const iFlag = (1 << pV[0]) | (1 << pV[1]) | (1 << pV[2]); let iMissingIndex = 0; if ((iFlag & 2) === 0) { iMissingIndex = 1; } else if ((iFlag & 4) === 0) { iMissingIndex = 2; } else if ((iFlag & 8) === 0) { iMissingIndex = 3; } const iOrgF = tri.iOrgFaceNumber; GetPosition(vDstP, 0, pContext, MakeIndex(iOrgF, iMissingIndex)); let bNotFound = true; let i = 0; while (i < 3) { const iVert = pV[i]; GetPosition(vSrcP, 0, pContext, MakeIndex(iOrgF, iVert)); if (vec3.exactEquals(vSrcP, vDstP)) { const iOffs = tri.iTSpacesOffs; psTspace[iOffs + iMissingIndex].copy(psTspace[iOffs + iVert]); bNotFound = false; break; } else { ++i; } } assert(!bNotFound); } }