static void MergeVertsFast(int[] piTriList_in_and_out, ref STmpVert[] pTmpVert, ref SMikkTSpaceContext context, int iL_in, int iR_in) { int c = 0, l = 0, channel = 0; float[] fvMin = new float[3], fvMax = new float[3]; float dx = 0, dy = 0, dz = 0, fSep = 0; for (c = 0; c < 3; c++) { fvMin[c] = pTmpVert[iL_in].vert[c]; fvMax[c] = fvMin[c]; } for (l = (iL_in + 1); l <= iR_in; l++) { for (c = 0; c < 3; c++) { if (fvMin[c] > pTmpVert[l].vert[c]) { fvMin[c] = pTmpVert[l].vert[c]; } else if (fvMax[c] < pTmpVert[l].vert[c]) { fvMax[c] = pTmpVert[l].vert[c]; } } } dx = fvMax[0] - fvMin[0]; dy = fvMax[1] - fvMin[1]; dz = fvMax[2] - fvMin[2]; channel = 0; if (dy > dx && dy > dz) { channel = 1; } else if (dz > dx) { channel = 2; } fSep = 0.5f * (fvMax[channel] + fvMin[channel]); if (fSep >= fvMax[channel] || fSep <= fvMin[channel]) { for (l = iL_in; l <= iR_in; l++) { int i = pTmpVert[l].index; int index = piTriList_in_and_out[i]; Vector3 vP = GetPosition(ref context, index); Vector3 vN = GetNormal(ref context, index); Vector2 vT = GetTexCoord(ref context, index); bool bNotFound = true; int l2 = iL_in, i2rec = -1; while (l2 < l && bNotFound) { int i2 = pTmpVert[l2].index; int index2 = piTriList_in_and_out[i2]; Vector3 vP2 = GetPosition(ref context, index2); Vector3 vN2 = GetNormal(ref context, index2); Vector2 vT2 = GetTexCoord(ref context, index2); i2rec = i2; if (vP.Equals(vP2) && vN.Equals(vN2) && vT.Equals(vT2)) { bNotFound = false; } else { l2++; } } if (!bNotFound) { piTriList_in_and_out[i] = piTriList_in_and_out[i2rec]; } } } else { int iL = iL_in, iR = iR = iR_in; while (iL < iR) { bool bReadyLeftSwap = false, bReadyRightSwap = false; while ((!bReadyLeftSwap) && iL < iR) { bReadyLeftSwap = !(pTmpVert[iL].vert[channel] < fSep); if (!bReadyLeftSwap) { ++iL; } } while ((!bReadyRightSwap) && iL < iR) { bReadyRightSwap = pTmpVert[iR].vert[channel] < fSep; if (!bReadyRightSwap) { --iR; } } if (bReadyLeftSwap && bReadyRightSwap) { STmpVert sTmp = pTmpVert[iL]; pTmpVert[iL] = pTmpVert[iR]; pTmpVert[iR] = sTmp; ++iL; --iR; } } if (iL == iR) { bool bReadyRightSwap = pTmpVert[iR].vert[channel] < fSep; if (bReadyRightSwap) { ++iL; } else { --iR; } } if (iL_in < iR) { MergeVertsFast(piTriList_in_and_out, ref pTmpVert, ref context, iL_in, iR); } if (iL < iR_in) { MergeVertsFast(piTriList_in_and_out, ref pTmpVert, ref context, iL, iR_in); } } }
static void GenerateSharedVerticesIndexList(int[] piTriList_in_and_out, ref SMikkTSpaceContext pContext, int iNrTrianglesIn) { int[] piHashTable = null, piHashCount = null, piHashOffsets = null, piHashCount2 = null; STmpVert[] pTmpVer = null; int i = 0, iChannel = 0, k = 0, e = 0; int iMaxCount = 0; Vector3 vMin = GetPosition(ref pContext, 0), vMax = vMin, vDim = new Vector3(); float fMin, fMax; for (i = 1; i < (iNrTrianglesIn * 3); ++i) { int index = piTriList_in_and_out[i]; Vector3 vP = GetPosition(ref pContext, index); if (vMin.X > vP.X) { vMin.X = vP.X; } else if (vMax.X < vP.X) { vMax.X = vP.X; } if (vMin.Y > vP.Y) { vMin.Y = vP.Y; } else if (vMax.Y < vP.Y) { vMax.Y = vP.Y; } if (vMin.Z > vP.Z) { vMin.Z = vP.Z; } else if (vMax.Z < vP.Z) { vMax.Z = vP.Z; } } vDim = vMax - vMin; iChannel = 0; fMin = vMin.X; fMax = vMax.X; if (vDim.Y > vDim.X && vDim.Y > vDim.Z) { iChannel = 1; fMin = vMin.Y; fMax = vMax.Y; } else if (vDim.Z > vDim.X) { iChannel = 2; fMin = vMin.Z; fMax = vMax.Z; } piHashTable = new int[iNrTrianglesIn * 3]; piHashCount = new int[g_iCells]; piHashOffsets = new int[g_iCells]; piHashCount2 = new int[g_iCells]; try { for (i = 0; i < iNrTrianglesIn * 3; ++i) { int index = piTriList_in_and_out[i]; Vector3 vP = GetPosition(ref pContext, index); float fVal = iChannel == 0 ? vP.X : (iChannel == 1) ? vP.Y : vP.Z; int iCell = FindGridCell(fMin, fMax, fVal); piHashCount[iCell]++; } } catch (Exception ex) { Console.WriteLine(ex.StackTrace); } piHashOffsets[0] = 0; for (k = 1; k < g_iCells; ++k) { piHashOffsets[k] = piHashOffsets[k - 1] + piHashCount[k - 1]; } try { for (i = 0; i < iNrTrianglesIn * 3; ++i) { int index = piTriList_in_and_out[i]; Vector3 vP = GetPosition(ref pContext, index); float fVal = iChannel == 0 ? vP.X : (iChannel == 1) ? vP.Y : vP.Z; int iCell = FindGridCell(fMin, fMax, fVal); piHashTable[piHashOffsets[iCell] + piHashCount2[iCell]] = i; piHashCount2[iCell]++; } } catch (Exception ex) { Console.WriteLine(ex.StackTrace); } piHashCount2 = null; iMaxCount = piHashCount[0]; for (k = 1; k < g_iCells; ++k) { if (iMaxCount < piHashCount[k]) { iMaxCount = piHashCount[k]; } } pTmpVer = new STmpVert[iMaxCount]; try { for (k = 0; k < g_iCells; ++k) { int entries = piHashCount[k]; if (entries < 2) { continue; } for (e = 0; e < entries; e++) { pTmpVer[e].vert = new float[3]; int iv = piHashTable[piHashOffsets[k] + e]; Vector3 vP = GetPosition(ref pContext, piTriList_in_and_out[iv]); pTmpVer[e].vert[0] = vP.X; pTmpVer[e].vert[1] = vP.Y; pTmpVer[e].vert[2] = vP.Z; pTmpVer[e].index = iv; } //merge verts fast here MergeVertsFast(piTriList_in_and_out, ref pTmpVer, ref pContext, 0, entries - 1); } } catch (Exception ex) { Console.WriteLine(ex.StackTrace); } pTmpVer = null; }