D3DXVECTOR3 CollisionSolver::GetMinkowskiSumEdgePoint(const D3DXVECTOR3& direction,
                                                         const CollisionMesh& particle, 
                                                         const CollisionMesh& hull)
{
    return FindFurthestPoint(particle.GetVertices(), direction) - 
        FindFurthestPoint(hull.GetVertices(), -direction);
}
BOOL CConvexHullGenerator::Generate(void)
{
	int							iMaxXIndex;
	int							iMinXIndex;
	CHalfSpaceHelper			cHalfSpace;
	int							iFarIndex;
	SFloat3*					psPosition;
	CArrayExtremeTrianglePtr	apcTriangles;
	CExtremeTriangle*			pcTriangle;
	CExtremeTriangle*			pcDeleted;
	SFreeListIterator			sIter;
	CArrayExtremeTrianglePtr	cDeleted;
	CArrayExtremeTrianglePtr	cFixedDeleted;
	int							j;
	SConvexHullHoleEdge			sEdges;
	int							k;
	int							aiIndex[3];
	int							iIndex;
	CExtremeTriangle*			pcSelected;
	CTextFile					cTextFile;
	int							iTriangle;
	float						fMinX;
	float						fMaxX;

	iMaxXIndex = FindMaxX(&fMinX);
	iMinXIndex = FindMinX(&fMaxX);
	iFarIndex = FindFurthestPoint(iMaxXIndex, iMinXIndex);

	if (iFarIndex == -1)
	{
		gcUserError.Set("Could not find a third point generating Convex Hull.");
		return FALSE;
	}

	apcTriangles.Init(2048);

	if (!FindFirstPairTriangles(&apcTriangles, iMaxXIndex, iMinXIndex, iFarIndex))
	{
		gcUserError.Set("Could not find the first triangle pair generating Convex Hull.");
		return FALSE;
	}

	cDeleted.Init(512);
	cFixedDeleted.Init(512);

	for (iTriangle = 0; iTriangle < apcTriangles.NumElements(); iTriangle++)
	{
		pcSelected = *apcTriangles.Get(iTriangle);

		if ((pcSelected == NULL) || (pcSelected->maiVisible.NumElements() == 0))
		{
			continue;
		}

		aiIndex[0] = GetIndex(mpsPoints, iStride, pcSelected->mpsPosition);
		aiIndex[1] = GetIndex(mpsPoints, iStride, pcSelected->mpsPosition1);
		aiIndex[2] = GetIndex(mpsPoints, iStride, pcSelected->mpsPosition2);

		iFarIndex = pcSelected->FindFurthestPoint(mpsPoints, iStride);
		if (iFarIndex == -1)
		{
			gcUserError.Set("Could not find furthest point!");
			return FALSE;
		}

		cDeleted.FakeSetUsedElements(0);  //It's sort of safe to do this.

		psPosition = GetPosition(mpsPoints, iStride, iFarIndex);
		pcTriangle = (CExtremeTriangle*)mcTriangles.StartIteration(&sIter);
		while (pcTriangle)
		{
			if (pcTriangle->maiVisible.NumElements() > 0)
			{
				if (pcTriangle->NotContains(psPosition))
				{
					cDeleted.Add(&pcTriangle);
				}
			}
			pcTriangle = (CExtremeTriangle*)mcTriangles.Iterate(&sIter);
		}
		
		RemoveDiscontiguousTriangles(pcSelected, &cDeleted, &cFixedDeleted);

		for (j = 0; j < cDeleted.NumElements(); j++)
		{
			pcDeleted = *cDeleted.Get(j);
			FindEdges(&sEdges, pcDeleted, &cDeleted);

			for (k = 0; k < sEdges.iNumEdges; k++)
			{
				pcTriangle = AddTriangle(GetPosition(mpsPoints, iStride, sEdges.aaiEdgeIndices[k][0]),
					GetPosition(mpsPoints, iStride, sEdges.aaiEdgeIndices[k][1]),
					GetPosition(mpsPoints, iStride, iFarIndex));

				apcTriangles.Add(&pcTriangle);
				AddPointsFromTriangles(pcTriangle, &cDeleted, iFarIndex);
			}
		}

		for (j = 0; j < cDeleted.NumElements(); j++)
		{
			pcDeleted = *cDeleted.Get(j);
			pcDeleted->Kill();
			mcTriangles.Remove(pcDeleted);

			iIndex = apcTriangles.FindWithIntKey((int)(size_t)pcDeleted, 0);
			*(apcTriangles.Get(iIndex)) = NULL;
		}
	}
	cDeleted.Kill();
	cFixedDeleted.Kill();

	apcTriangles.Kill();

	RemoveSlivers();

	if (mszHullName)
	{
		CChars szTemp;
		szTemp.Init("Writing Hull file [");
		szTemp.Append(mszHullName);
		szTemp.Append("]\n");
		szTemp.Kill();
		cTextFile.Init();
		DumpTriangleObj(&cTextFile.mcText, iTriangle);
		cTextFile.Write(mszHullName);
		cTextFile.Kill();
	}

	return TRUE;
}