room101/BSP.CPP

136 lines
3.5 KiB
C++

#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;
}