136 lines
3.5 KiB
C++
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;
|
|
}
|
|
|
|
|