static void GenerateSharedVerticesIndexList()

in shared/ext/mikktspace.cpp [454:578]


static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
{

	// Generate bounding box
	int * piHashTable=NULL, * piHashCount=NULL, * piHashOffsets=NULL, * piHashCount2=NULL;
	STmpVert * pTmpVert = NULL;
	int iChannel=0, k=0, e=0;
	int iMaxCount=0;
	SVec3 vMin = GetPosition(pContext, 0), vMax = vMin, vDim;
	float fMin, fMax;
	for (int i=1; i<(iNrTrianglesIn*3); i++)
	{
		const int index = piTriList_in_and_out[i];

		const SVec3 vP = GetPosition(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 = vsub(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;
	}

	// make allocations
	piHashTable = (int *) malloc(sizeof(int)*iNrTrianglesIn*3);
	piHashCount = (int *) malloc(sizeof(int)*g_iCells);
	piHashOffsets = (int *) malloc(sizeof(int)*g_iCells);
	piHashCount2 = (int *) malloc(sizeof(int)*g_iCells);

	if (piHashTable==NULL || piHashCount==NULL || piHashOffsets==NULL || piHashCount2==NULL)
	{
		if (piHashTable!=NULL) free(piHashTable);
		if (piHashCount!=NULL) free(piHashCount);
		if (piHashOffsets!=NULL) free(piHashOffsets);
		if (piHashCount2!=NULL) free(piHashCount2);
		GenerateSharedVerticesIndexListSlow(piTriList_in_and_out, pContext, iNrTrianglesIn);
		return;
	}
	memset(piHashCount, 0, sizeof(int)*g_iCells);
	memset(piHashCount2, 0, sizeof(int)*g_iCells);

	// count amount of elements in each cell unit
	for (int i=0; i<(iNrTrianglesIn*3); i++)
	{
		const int index = piTriList_in_and_out[i];
		const SVec3 vP = GetPosition(pContext, index);
		const float fVal = iChannel==0 ? vP.x : (iChannel==1 ? vP.y : vP.z);
		const int iCell = FindGridCell(fMin, fMax, fVal);
		++piHashCount[iCell];
	}

	// evaluate start index of each cell.
	piHashOffsets[0]=0;
	for (k=1; k<g_iCells; k++)
		piHashOffsets[k]=piHashOffsets[k-1]+piHashCount[k-1];

	// insert vertices
	for (int i=0; i<(iNrTrianglesIn*3); i++)
	{
		const int index = piTriList_in_and_out[i];
		const SVec3 vP = GetPosition(pContext, index);
		const float fVal = iChannel==0 ? vP.x : (iChannel==1 ? vP.y : vP.z);
		const int iCell = FindGridCell(fMin, fMax, fVal);
		int * pTable = NULL;

		assert(piHashCount2[iCell]<piHashCount[iCell]);
		pTable = &piHashTable[piHashOffsets[iCell]];
		pTable[piHashCount2[iCell]] = i;	// vertex i has been inserted.
		++piHashCount2[iCell];
	}
	for (k=0; k<g_iCells; k++)
		assert(piHashCount2[k] == piHashCount[k]);	// verify the count
	free(piHashCount2);

	// find maximum amount of entries in any hash entry
	iMaxCount = piHashCount[0];
	for (k=1; k<g_iCells; k++)
		if (iMaxCount<piHashCount[k])
			iMaxCount=piHashCount[k];
	pTmpVert = (STmpVert *) malloc(sizeof(STmpVert)*iMaxCount);
	

	// complete the merge
	for (k=0; k<g_iCells; k++)
	{
		// extract table of cell k and amount of entries in it
		int * pTable = &piHashTable[piHashOffsets[k]];
		const int iEntries = piHashCount[k];
		if (iEntries < 2) continue;

		if (pTmpVert!=NULL)
		{
			for (e=0; e<iEntries; e++)
			{
				int i = pTable[e];
				const SVec3 vP = GetPosition(pContext, piTriList_in_and_out[i]);
				_Analysis_assume_(e < iMaxCount);
				pTmpVert[e].vert[0] = vP.x; pTmpVert[e].vert[1] = vP.y;
				pTmpVert[e].vert[2] = vP.z; pTmpVert[e].index = i;
			}
			MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, 0, iEntries-1);
		}
		else
			MergeVertsSlow(piTriList_in_and_out, pContext, pTable, iEntries);
	}

	if (pTmpVert!=NULL) { free(pTmpVert); }
	free(piHashTable);
	free(piHashCount);
	free(piHashOffsets);
}