static void MergeVertsFast()

in shared/ext/mikktspace.cpp [580:688]


static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in)
{
	// make bbox
	int c=0, l=0, channel=0;
	float fvMin[3], fvMax[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]);

	// terminate recursion when the separation/average value
	// is no longer strictly between fMin and fMax values.
	if (fSep>=fvMax[channel] || fSep<=fvMin[channel])
	{
		// complete the weld
		for (l=iL_in; l<=iR_in; l++)
		{
			int i = pTmpVert[l].index;
			const int index = piTriList_in_and_out[i];
			const SVec3 vP = GetPosition(pContext, index);
			const SVec3 vN = GetNormal(pContext, index);
			const SVec3 vT = GetTexCoord(pContext, index);

			tbool bNotFound = TTRUE;
			int l2=iL_in, i2rec=-1;
			while (l2<l && bNotFound)
			{
				const int i2 = pTmpVert[l2].index;
				const int index2 = piTriList_in_and_out[i2];
				const SVec3 vP2 = GetPosition(pContext, index2);
				const SVec3 vN2 = GetNormal(pContext, index2);
				const SVec3 vT2 = GetTexCoord(pContext, index2);
				i2rec=i2;

				//if (vP==vP2 && vN==vN2 && vT==vT2)
				if (vP.x==vP2.x && vP.y==vP2.y && vP.z==vP2.z &&
					vN.x==vN2.x && vN.y==vN2.y && vN.z==vN2.z &&
					vT.x==vT2.x && vT.y==vT2.y && vT.z==vT2.z)
					bNotFound = TFALSE;
				else
					++l2;
			}
			
			// merge if previously found
			if (!bNotFound)
				piTriList_in_and_out[i] = piTriList_in_and_out[i2rec];
		}
	}
	else
	{
		int iL=iL_in, iR=iR_in;
		assert((iR_in-iL_in)>0);	// at least 2 entries

		// separate (by fSep) all points between iL_in and iR_in in pTmpVert[]
		while (iL < iR)
		{
			tbool bReadyLeftSwap = TFALSE, bReadyRightSwap = TFALSE;
			while ((!bReadyLeftSwap) && iL<iR)
			{
				assert(iL>=iL_in && iL<=iR_in);
				bReadyLeftSwap = !(pTmpVert[iL].vert[channel]<fSep);
				if (!bReadyLeftSwap) ++iL;
			}
			while ((!bReadyRightSwap) && iL<iR)
			{
				assert(iR>=iL_in && iR<=iR_in);
				bReadyRightSwap = pTmpVert[iR].vert[channel]<fSep;
				if (!bReadyRightSwap) --iR;
			}
			assert( (iL<iR) || !(bReadyLeftSwap && bReadyRightSwap) );

			if (bReadyLeftSwap && bReadyRightSwap)
			{
				const STmpVert sTmp = pTmpVert[iL];
				assert(iL<iR);
				pTmpVert[iL] = pTmpVert[iR];
				pTmpVert[iR] = sTmp;
				++iL; --iR;
			}
		}

		assert(iL==(iR+1) || (iL==iR));
		if (iL==iR)
		{
			const tbool bReadyRightSwap = pTmpVert[iR].vert[channel]<fSep;
			if (bReadyRightSwap) ++iL;
			else --iR;
		}

		// only need to weld when there is more than 1 instance of the (x,y,z)
		if (iL_in < iR)
			MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL_in, iR);	// weld all left of fSep
		if (iL < iR_in)
			MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL, iR_in);	// weld all right of (or equal to) fSep
	}
}