#include "polygon.hpp" #include "plane.hpp" #define POLYGON_VALIDATE() assert(n >= POLYGON_MIN && n < POLYGON_MAX); /******************************************************************************* ** PolygonMerge *******************************************************************************/ int PolygonMerge(Polygon dst, Vector* p1, int n1, Vector* p2, int n2) { int k = 0; for (int i = 0; i < n1; i++) { v3dcpy(dst[k++], p1[i]); for (int j = 0; j < n2; j++) { if (VectorsAreEqual(p1[i], p2[j])) { i = j; int n3 = n1; n1 = n2; n2 = n3; Vector* p3 = p1; p1 = p2; p2 = p3; break; } } } return k; } /******************************************************************************* ** PolygonCopy *******************************************************************************/ void PolygonCopy(Polygon dst, Polygon src, int n) { memcpy(dst, src, sizeof(Vector) * n); } /******************************************************************************* ** PolygonRotate *******************************************************************************/ void PolygonRotate(Polygon dst, Polygon src, int n, Matrix matrix) { while (n--) VectorRotate(dst[n], src[n], matrix); } /******************************************************************************* ** PolygonTranslate *******************************************************************************/ void PolygonTranslate(Polygon dst, Polygon src, int n, Matrix matrix) { while (n--) VectorTranslate(dst[n], src[n], matrix); } /******************************************************************************* ** PolygonTransform *******************************************************************************/ void PolygonTransform(Polygon dst, Polygon src, int n, Matrix matrix) { while (n--) VectorTransform(dst[n], src[n], matrix); } /******************************************************************************* ** PolygonScale *******************************************************************************/ void PolygonScale(Polygon dst, Polygon src, int n, float scale) { while (n--) VectorScale(dst[n], src[n], scale); } /******************************************************************************* ** PolygonInterpolate *******************************************************************************/ void PolygonInterpolate(Polygon dst, Polygon A, Polygon B, int n, float scale) { while (n--) VectorInterpolate(dst[n], A[n], B[n], scale); } /******************************************************************************* ** PolygonAddition *******************************************************************************/ void PolygonAddition(Polygon dst, Polygon src, int n, Vector vector) { while (n--) { dst[n][0] = src[n][0] + vector[0]; dst[n][1] = src[n][1] + vector[1]; dst[n][2] = src[n][2] + vector[2]; } } /******************************************************************************* ** PolygonSubtract *******************************************************************************/ void PolygonSubtract(Polygon dst, Polygon src, int n, Vector vector) { while (n--) { dst[n][0] = src[n][0] - vector[0]; dst[n][1] = src[n][1] - vector[1]; dst[n][2] = src[n][2] - vector[2]; } } /******************************************************************************* ** PolygonMultiply *******************************************************************************/ void PolygonMultiply(Polygon dst, Polygon src, int n, Vector vector) { while (n--) { dst[n][0] = src[n][0] * vector[0]; dst[n][1] = src[n][1] * vector[1]; dst[n][2] = src[n][2] * vector[2]; } } /******************************************************************************* ** PolygonDivide *******************************************************************************/ void PolygonDivide(Polygon dst, Polygon src, int n, Vector vector) { while (n--) { dst[n][0] = src[n][0] / vector[0]; dst[n][1] = src[n][1] / vector[1]; dst[n][2] = src[n][2] / vector[2]; } } /******************************************************************************* ** PolygonSize *******************************************************************************/ void PolygonSize(Vector size, Polygon src, int n) { Vector lo, hi; PolygonExtent(lo, hi, src, n); VectorSubtract(size, hi, lo); } /******************************************************************************* ** PolygonMagnitude *******************************************************************************/ float PolygonMagnitude(Polygon src, int n) { float dst = 0.0; while (n--) { dst = Max(dst, (float)fabs(src[n][0])); dst = Max(dst, (float)fabs(src[n][1])); dst = Max(dst, (float)fabs(src[n][2])); } return dst; } /******************************************************************************* ** PolygonNormalize *******************************************************************************/ void PolygonNormalize(Polygon dst, Polygon src, int n, float size) { PolygonScale(dst, src, n, size / PolygonMagnitude(src, n)); } /******************************************************************************* ** PolygonCentrePoint *******************************************************************************/ void PolygonCentrePoint(Vector dst, Polygon src, int n) { Vector lo, hi; PolygonExtent(lo, hi, src, n); VectorSubtract(hi, hi, lo); VectorScale(hi, hi, 0.5f); VectorAddition(dst, lo, hi); } /******************************************************************************* ** PolygonSum *******************************************************************************/ void PolygonSum(Vector dst, Polygon src, int n) { VectorCreate(dst, 0.0f, 0.0f, 0.0f); while (n--) VectorAddition(dst, dst, src[n]); } /******************************************************************************* ** PolygonMean *******************************************************************************/ void PolygonMean(Vector dst, Polygon src, int n) { assert(n); PolygonSum(dst, src, n); VectorScale(dst, dst, 1.0f / n); } /******************************************************************************* ** VectorMidPoint *******************************************************************************/ void VectorMidPoint(Vector A, Vector B, Vector C) { VectorInterpolate(A, B, C, 0.5f); } /******************************************************************************* ** PolygonCentre *******************************************************************************/ void PolygonCentre(Polygon dst, Polygon src, int n) { Vector lo, hi, shift; PolygonExtent(lo, hi, src, n); VectorSubtract(shift, hi, lo); VectorScale(shift, shift, 0.5f); VectorAddition(shift, shift, lo); PolygonSubtract(dst, src, n, shift); } /******************************************************************************* ** PolygonExtent *******************************************************************************/ void PolygonExtent(Vector lo, Vector hi, Polygon src, int n) { assert(n); v3dcpy(lo, src[0]); v3dcpy(hi, src[0]); while (n--) { VectorMinimize(lo, lo, src[n]); VectorMaximize(hi, hi, src[n]); } } /******************************************************************************* ** PolygonMergePoints *******************************************************************************/ int PolygonMergePoints(Polygon dst, Polygon src, int n) { int i, j, k = 0; assert(n >= POLYGON_MIN && n < POLYGON_MAX); for (j = n - 1, i = 0; i < n; j = i++) { if (!VectorsAreEqual(src[i], src[j])) { v3dcpy(dst[k++], src[i]); } } return k; } /******************************************************************************* ** PolygonEdges *******************************************************************************/ void PolygonEdges(Polygon dst, Polygon src, int n) { int i, j; for (j = n - 1, i = 0; i < n; j = i++) { VectorSubtract(dst[j], src[i], src[j]); } } /******************************************************************************* ** PolygonNormals *******************************************************************************/ void PolygonNormals(Polygon dst, Polygon src, int n) { int i, j; Polygon edges; PolygonEdges(edges, src, n); for (j = n - 1, i = 0; i < n; j = i++) { VectorCrossProduct(dst[i], edges[j], edges[i]); VectorNormalize(dst[i], dst[i]); } } /******************************************************************************* ** PolygonIsConvex *******************************************************************************/ int PolygonIsConvex(Polygon src, int n) { Polygon normals; PolygonNormals(normals, src, n); while (n--) if (!VectorsAreEqual(src[0], src[n])) return 0; return 1; } /******************************************************************************* ** PolygonCollinear *******************************************************************************/ int PolygonCollinear(Polygon dst, Polygon src, int n) { int i, j, k = 0; Vector A, B; assert(n >= POLYGON_MIN && n < POLYGON_MAX); VectorSubtract(A, src[n - 1], src[n - 2]); for (j = n - 1, i = 0; i < n; j = i++) { VectorSubtract(B, src[i], src[j]); if (!VectorsAreCollinear(A, B)) { v3dcpy(dst[k++], src[j]); } v3dcpy(A, B); } return k; } /******************************************************************************* ** PolygonsAreJoined *******************************************************************************/ int PolygonsAreJoined(Polygon p1, int n1, Polygon p2, int n2) { int a1, b1, a2, b2; for (a1 = n1 - 1, b1 = 0; b1 < n1; a1 = b1++) { for (a2 = n2 - 1, b2 = 0; b2 < n2; a2 = b2++) { if ( (VectorsAreEqual(p1[a1], p2[a2]) && VectorsAreEqual(p1[b1], p2[b2])) || (VectorsAreEqual(p1[a1], p2[b2]) && VectorsAreEqual(p1[b1], p2[a2])) ) return 1; } } return 0; } /******************************************************************************* ** PolygonClipToPlane *******************************************************************************/ int PolygonClipToPlane(Polygon dst, Polygon src, int n, Plane plane) { int i, j, k = 0; float dist1, dist2; if (n >= POLYGON_MIN && n < POLYGON_MAX) { dist1 = PlaneDistanceTo(plane, src[n - 1]); for (j = n - 1, i = 0; i < n; j = i++) { if (dist1 >= 0.0f) v3dcpy(dst[k++], src[j]); dist2 = PlaneDistanceTo(plane, src[i]); if (dist1 < 0.0f ^ dist2 < 0.0f) { VectorInterpolate(dst[k++], src[j], src[i], dist1 / (dist1 - dist2)); } dist1 = dist2; } } return k; } void PolygonDistPlane(float out[], Vector in[], int n, Plane plane) { assert(n >= POLYGON_MIN && n < POLYGON_MAX); while (n--) out[n] = PlaneDistanceTo(plane, in[n]); } void PolygonDistLeftViewPlane(float out[], Vector in[], int n) { assert(n >= POLYGON_MIN && n < POLYGON_MAX); while (n--) out[n] = in[n][0] + in[n][2]; } void PolygonDistRightViewPlane(float out[], Vector in[], int n) { assert(n >= POLYGON_MIN && n < POLYGON_MAX); while (n--) out[n] = in[n][2] - in[n][0]; } void PolygonDistTopViewPlane(float out[], Vector in[], int n) { assert(n >= POLYGON_MIN && n < POLYGON_MAX); while (n--) out[n] = in[n][1] + in[n][2]; } void PolygonDistBotViewPlane(float out[], Vector in[], int n) { assert(n >= POLYGON_MIN && n < POLYGON_MAX); while (n--) out[n] = in[n][2] - in[n][1]; } /******************************************************************************* ** PolygonProject *******************************************************************************/ void PolygonProject(Polygon src, int n, Camera* camera) { while (n--) { src[n][0] = camera->origin[0] * src[n][0] / src[n][2] + camera->origin[0]; src[n][1] = - camera->origin[1] * src[n][1] / src[n][2] + camera->origin[1]; } }