128 lines
4.2 KiB
C++
Executable File
128 lines
4.2 KiB
C++
Executable File
//-----------------------------------------------------------------------------
|
|
// Torque Game Engine
|
|
// Copyright (C) GarageGames.com, Inc.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "sceneGraph/windingClipper.h"
|
|
|
|
void sgUtil_clipToPlane(Point3F* points, U32& rNumPoints, const PlaneF& rPlane)
|
|
{
|
|
S32 start = -1;
|
|
for (U32 i = 0; i < rNumPoints; i++) {
|
|
if (rPlane.whichSide(points[i]) == PlaneF::Front) {
|
|
start = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Nothing was in front of the plane...
|
|
if (start == -1) {
|
|
rNumPoints = 0;
|
|
return;
|
|
}
|
|
|
|
Point3F finalPoints[128];
|
|
U32 numFinalPoints = 0;
|
|
|
|
U32 baseStart = start;
|
|
U32 end = (start + 1) % rNumPoints;
|
|
|
|
while (end != baseStart) {
|
|
const Point3F& rStartPoint = points[start];
|
|
const Point3F& rEndPoint = points[end];
|
|
|
|
PlaneF::Side fSide = rPlane.whichSide(rStartPoint);
|
|
PlaneF::Side eSide = rPlane.whichSide(rEndPoint);
|
|
|
|
S32 code = fSide * 3 + eSide;
|
|
switch (code) {
|
|
case 4: // f f
|
|
case 3: // f o
|
|
case 1: // o f
|
|
case 0: // o o
|
|
// No Clipping required
|
|
finalPoints[numFinalPoints++] = points[start];
|
|
start = end;
|
|
end = (end + 1) % rNumPoints;
|
|
break;
|
|
|
|
|
|
case 2: { // f b
|
|
// In this case, we emit the front point, Insert the intersection,
|
|
// and advancing to point to first point that is in front or on...
|
|
//
|
|
finalPoints[numFinalPoints++] = points[start];
|
|
|
|
Point3F vector = rEndPoint - rStartPoint;
|
|
F32 t = -(rPlane.distToPlane(rStartPoint) / mDot(rPlane, vector));
|
|
|
|
Point3F intersection = rStartPoint + (vector * t);
|
|
finalPoints[numFinalPoints++] = intersection;
|
|
|
|
U32 endSeek = (end + 1) % rNumPoints;
|
|
while (rPlane.whichSide(points[endSeek]) == PlaneF::Back)
|
|
endSeek = (endSeek + 1) % rNumPoints;
|
|
|
|
end = endSeek;
|
|
start = (end + (rNumPoints - 1)) % rNumPoints;
|
|
|
|
const Point3F& rNewStartPoint = points[start];
|
|
const Point3F& rNewEndPoint = points[end];
|
|
|
|
vector = rNewEndPoint - rNewStartPoint;
|
|
t = -(rPlane.distToPlane(rNewStartPoint) / mDot(rPlane, vector));
|
|
|
|
intersection = rNewStartPoint + (vector * t);
|
|
points[start] = intersection;
|
|
}
|
|
break;
|
|
|
|
case -1: {// o b
|
|
// In this case, we emit the front point, and advance to point to first
|
|
// point that is in front or on...
|
|
//
|
|
finalPoints[numFinalPoints++] = points[start];
|
|
|
|
U32 endSeek = (end + 1) % rNumPoints;
|
|
while (rPlane.whichSide(points[endSeek]) == PlaneF::Back)
|
|
endSeek = (endSeek + 1) % rNumPoints;
|
|
|
|
end = endSeek;
|
|
start = (end + (rNumPoints - 1)) % rNumPoints;
|
|
|
|
const Point3F& rNewStartPoint = points[start];
|
|
const Point3F& rNewEndPoint = points[end];
|
|
|
|
Point3F vector = rNewEndPoint - rNewStartPoint;
|
|
F32 t = -(rPlane.distToPlane(rNewStartPoint) / mDot(rPlane, vector));
|
|
|
|
Point3F intersection = rNewStartPoint + (vector * t);
|
|
points[start] = intersection;
|
|
}
|
|
break;
|
|
|
|
case -2: // b f
|
|
case -3: // b o
|
|
case -4: // b b
|
|
// In the algorithm used here, this should never happen...
|
|
AssertISV(false, "SGUtil::clipToPlane: error in polygon clipper");
|
|
break;
|
|
|
|
default:
|
|
AssertFatal(false, "SGUtil::clipToPlane: bad outcode");
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
// Emit the last point.
|
|
finalPoints[numFinalPoints++] = points[start];
|
|
AssertFatal(numFinalPoints >= 3, avar("Error, this shouldn't happen! Invalid winding in clipToPlane: %d", numFinalPoints));
|
|
|
|
// Copy the new rWinding, and we're set!
|
|
//
|
|
dMemcpy(points, finalPoints, numFinalPoints * sizeof(Point3F));
|
|
rNumPoints = numFinalPoints;
|
|
AssertISV(rNumPoints <= 128, "MaxWindingPoints exceeded in scenegraph. Fatal error.");
|
|
}
|