POLYGON* CSGClipPolygon (POLYGON* poly, POLYGON* planepoly, int clip)
{
// Temporary polygon lists.
POLYGON* retfrags = NULL;
POLYGON* frontfrag = NULL;
POLYGON* backfrag = NULL;
// Classify the polygon against the plane.
int result = ClassifyPolygon(poly, *planepoly);
switch (result)
{
case Front:
// If the polygon is in front of the plane then return it whole.
return poly;
break;
case Back:
// If the polygon is behind the plane and there are more planes
// in the plane list then clip it against the next plane.
if (planepoly->GetNext())
{
retfrags = CSGClipPolygon(poly, planepoly->GetNext(), clip);
return retfrags;
}
// Otherwise return NULL.
else
return NULL;
break;
case PolygonWasSplit:
// If the polygon intersects the plane then it needs splitting.
frontfrag = new POLYGON;
backfrag = new POLYGON;
SplitPolygon(poly, *planepoly, frontfrag, backfrag);
// If there are more planes in the list then continue to clip the back fragment.
if (planepoly->GetNext())
{
retfrags = CSGClipPolygon(backfrag, planepoly->GetNext(), clip);
// If the returned fragment is not the same as the original back
// fragment then delete the back fragment and add the returned
// fragment to the front fragment before returning all.
if (!(retfrags == backfrag))
{
delete backfrag;
frontfrag->AddPolygon(retfrags);
return frontfrag;
}
// If the returned fragment is the same as the original back
// fragment then it survived further clipping and we can just
// return the original polygon.
else
{
delete frontfrag;
delete backfrag;
return poly;
}
}
// There were no more planes to check the back fragment against so
// we only keep the front fragment.
else
{
delete backfrag;
return frontfrag;
}
break;
case OnPartition:
// The polygon was coplanar with the plane so we check the polygons
// normal to see if it is in front of the plane, if it is we know
// that the polygon is facing the same way as the plane. If so, and
// the clip flag hasn't been set, then we can return the polygon.
if (ClassifyPoint(poly->Vertex[0].normal, planepoly->Vertex[0].coords,
planepoly->Vertex[0].normal) == 1)
if (!clip)
return poly;
// If the program gets to here then either the polygon faced the
// opposite way to the plane or the clip flag was set, in which case
// we continue to clip it with any other planes in the list or return
// NULL if there are no more planes.
if (planepoly->GetNext())
retfrags = CSGClipPolygon(poly, planepoly->GetNext(), clip);
else
return NULL;
break;
}
// If a coplanar polygon gets split by other planes then we return the
// fragments here.
return retfrags;
}
Hopefully this source code combined with the tutorials mentioned will make it easier for you to perform CSG, it is a difficult subject so give yourself a lot of time to let the ideas become clear. This has been my first experiment with CSG and I will keep working on it in future demos. I hope it helps you to construct your own worlds. If you have any suggestions, problems or error reports then send me an email.
Al.
References:
Stefan Hajnoczi
http://folk.uio.no/stefanha/mapfiles.pdf
Gerald Filimonov
http://www.3dtechdev/tutorials/illegalgeometry/illegalgeometrytut.html
Dan Royer
http://www.cfxweb.net/~aggrav8d/tutorials/csg.html