#include "bsp.hpp" #include "polygon.hpp" void BSPCreateExtent(BSP* bsp) { Vector lo, hi; if (bsp && bsp->faces) { BSPCreateExtent(bsp->sides[1]); for (int i = 0; i < NumberOf(bsp->faces); i++) { Face* face = &bsp->faces[i]; PolygonExtent(lo, hi, face->vertices, NumberOf(face->vertices)); if (i == 0) { v3dcpy(bsp->lo, lo); v3dcpy(bsp->hi, hi); } else { VectorMinimize(bsp->lo, bsp->lo, lo); VectorMaximize(bsp->hi, bsp->hi, hi); } } /* if (bsp->sides[1] && bsp->sides[1]->faces) { VectorMinimize(bsp->lo, bsp->lo, bsp->sides[1]->lo); VectorMaximize(bsp->hi, bsp->hi, bsp->sides[1]->hi); } */ BSPCreateExtent(bsp->sides[0]); } } /******************************************************************************* ** BSPRead *******************************************************************************/ BSP* BSPRead(FILE* file) { BSP* bsp = (BSP*) calloc(1, sizeof(BSP)); assert(bsp && file); fread(bsp->plane, sizeof(Plane), 1, file); bsp->faces = FaceArrayRead(file); if (bsp->faces) { bsp->sides[0] = BSPRead(file); bsp->sides[1] = BSPRead(file); } return bsp; } /******************************************************************************* ** BSPFaceIntersect *******************************************************************************/ Face* BSPFaceIntersect(BSP* bsp, Vector A, Vector B) { Vector intersect; Face* facehit = NULL; if (bsp->sides[0] && bsp->sides[1]) { float dist1 = PlaneDistanceTo(bsp->plane, A); float dist2 = PlaneDistanceTo(bsp->plane, B); /* ** Does the light ray intersect the bsp plane? */ if (dist1 < 0.0f ^ dist2 < 0.0f) { /* ** Calculate the intersect point. */ VectorInterpolate(intersect, A, B, dist1 / (dist1 - dist2)); Face* facearray = bsp->faces; /* ** Does the light ray hit any face? */ for (int i = 0; i < NumberOf(facearray); i++) { Face* face = &facearray[i]; if (face->colour > 3) { /* ** Is the intersection point within the hull planes of this face? */ int n = 0; for (int j = 0; j < NumberOf(face->hull); j++) { if (PlaneDistanceTo(face->hull[j], intersect) < 2.0f) n++; } /* ** If the intersection point is within the hull planes, then the ray ** is blocked by the face. Ie. we have a shadow! */ if (n == NumberOf(face->hull)) { facehit = face; break; } } } if (!facehit) { facehit = BSPFaceIntersect(bsp->sides[dist1 < 0.0f], A, intersect); if (!facehit) { facehit = BSPFaceIntersect(bsp->sides[dist2 < 0.0f], intersect, B); } } } else { facehit = BSPFaceIntersect(bsp->sides[dist1 < 0.0f], A, B); } } return facehit; }