715 lines
20 KiB
C++
715 lines
20 KiB
C++
|
#include "../main.hpp"
|
||
|
#include "../string.hpp"
|
||
|
#include "../light.hpp"
|
||
|
#include "../triangle.hpp"
|
||
|
#include "../surface.hpp"
|
||
|
#include "../bsp.hpp"
|
||
|
#include "../file.hpp"
|
||
|
#include "../polygon.hpp"
|
||
|
|
||
|
#define MAX_SURFACES 10000
|
||
|
#define MAX_POINTS 5000
|
||
|
#define MAX_LIGHTS 1000
|
||
|
#define MAX_FACES 10000
|
||
|
#define MAX_BSP 10000
|
||
|
|
||
|
struct
|
||
|
{
|
||
|
int lighting;
|
||
|
int shadows;
|
||
|
} switches;
|
||
|
|
||
|
int nlights;
|
||
|
Light lights[MAX_LIGHTS];
|
||
|
|
||
|
int nsurfaces;
|
||
|
int nportals;
|
||
|
Surface surfaces[MAX_SURFACES];
|
||
|
Picture lightmaps[MAX_SURFACES];
|
||
|
|
||
|
BSP bsps[MAX_BSP];
|
||
|
int nbsps;
|
||
|
int nleafs;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
Plane plane;
|
||
|
int nfaces;
|
||
|
int points_infront;
|
||
|
int points_behind;
|
||
|
int point_balance;
|
||
|
int faces_split;
|
||
|
int nportals;
|
||
|
float balance;
|
||
|
} PlaneInfo;
|
||
|
|
||
|
PlaneInfo planeinfo[MAX_FACES];
|
||
|
/*******************************************************************************
|
||
|
** FaceCreate
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
FaceCreate(Face* face, Polygon src, int n, int colour, int surfaceid)
|
||
|
{
|
||
|
Polygon tt1;
|
||
|
Polygon tt2;
|
||
|
|
||
|
ThrowIf(n >= POLYGON_MAX, "Polygon has too many vertices");
|
||
|
|
||
|
memset(face, 0, sizeof(Face));
|
||
|
|
||
|
if (n < 3) return;
|
||
|
|
||
|
n = PolygonMergePoints(tt2, src, n);
|
||
|
|
||
|
if (n < 3) return;
|
||
|
|
||
|
n = PolygonCollinear(tt1, tt2, n);
|
||
|
|
||
|
if (n < 3) return;
|
||
|
|
||
|
face->vertices = (Vector*) MemoryAlloc(n, sizeof(Vector));
|
||
|
|
||
|
PolygonCopy(face->vertices, tt1, n);
|
||
|
|
||
|
if (surfaceid >= 0)
|
||
|
{
|
||
|
PlaneCopy(face->plane, surfaces[surfaceid].plane);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TrianglePlane(tt1, face->plane);
|
||
|
}
|
||
|
face->surfaceid = surfaceid;
|
||
|
face->colour = colour;
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** PlaneHullCreate
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
PlaneHullCreate(Plane plane, int i, Polygon poly, int n, Plane faceplane)
|
||
|
{
|
||
|
Vector normal, edge;
|
||
|
|
||
|
VectorSubtract(edge, poly[i], poly[(i + 1) % n]);
|
||
|
|
||
|
VectorCrossProduct(normal, faceplane, edge);
|
||
|
|
||
|
PlaneInit(plane, normal, poly[i]);
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** FaceCreateHullPlanes
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
FaceCreateHullPlanes(Face* face)
|
||
|
{
|
||
|
assert(face);
|
||
|
assert(NumberOf(face->hull) == 0);
|
||
|
assert(NumberOf(face->vertices) > 2);
|
||
|
|
||
|
face->hull = (Plane*) MemoryAlloc(NumberOf(face->vertices), sizeof(Plane));
|
||
|
|
||
|
for (int i = 0; i < NumberOf(face->vertices); i++)
|
||
|
{
|
||
|
PlaneHullCreate(face->hull[i], i, face->vertices, NumberOf(face->vertices), face->plane);
|
||
|
}
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** FaceSlice
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
FaceSlice(Face* dst, Face* src, Plane plane)
|
||
|
{
|
||
|
Polygon tmp;
|
||
|
|
||
|
assert(dst && src && plane && NumberOf(src->vertices) < 20);
|
||
|
|
||
|
FaceCreate(dst, tmp,
|
||
|
PolygonClipToPlane(tmp, src->vertices, NumberOf(src->vertices), plane),
|
||
|
src->colour,
|
||
|
src->surfaceid);
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** FaceArrayPush
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
FaceArrayPush(Face** facearray, Face* face)
|
||
|
{
|
||
|
assert(facearray && face);
|
||
|
|
||
|
*facearray = (Face*) MemoryRealloc(*facearray, NumberOf(*facearray) + 1, sizeof(Face));
|
||
|
|
||
|
(*facearray)[NumberOf(*facearray) - 1] = *face;
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** FaceArrayPull
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
FaceArrayPull(Face** facearray, Face* face)
|
||
|
{
|
||
|
assert(facearray && *facearray && face);
|
||
|
|
||
|
*face = (*facearray)[NumberOf(*facearray) - 1];
|
||
|
|
||
|
*facearray = (Face*) MemoryRealloc(*facearray, NumberOf(*facearray) - 1, sizeof(Face));
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** FaceArrayReadMDL
|
||
|
*******************************************************************************/
|
||
|
Face*
|
||
|
FaceArrayReadMDL(FILE* file_raw, FILE* file_lights, FILE* file_data)
|
||
|
{
|
||
|
String s, name;
|
||
|
int colour, groupid;
|
||
|
Triangle triangle;
|
||
|
Face face;
|
||
|
Face* array = NULL;
|
||
|
|
||
|
fscanf(file_raw, "%s", s);
|
||
|
|
||
|
int nfaces = 0;
|
||
|
|
||
|
while (TriangleScan(triangle, file_raw))
|
||
|
{
|
||
|
nfaces++;
|
||
|
|
||
|
fscanf(file_data, "%s %d %d", name, &colour, &groupid);
|
||
|
|
||
|
if (colour == 0) nportals++;
|
||
|
|
||
|
if (colour != 0)
|
||
|
{
|
||
|
FaceCreate(&face, triangle, 3, colour, -1);
|
||
|
|
||
|
if (face.vertices) FaceArrayPush(&array, &face);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
while (
|
||
|
fscanf(file_lights, "%s %f %f %f %f %f %f",
|
||
|
lights[nlights].name,
|
||
|
&lights[nlights].pos[0],
|
||
|
&lights[nlights].pos[1],
|
||
|
&lights[nlights].pos[2],
|
||
|
&lights[nlights].rgb[0],
|
||
|
&lights[nlights].rgb[1],
|
||
|
&lights[nlights].rgb[2]) == 7)
|
||
|
{
|
||
|
nlights++;
|
||
|
ThrowIf(nlights >= MAX_LIGHTS, "Too many lights");
|
||
|
}
|
||
|
|
||
|
|
||
|
fprintf(stderr, "Number of faces: %d\n", nfaces);
|
||
|
fprintf(stderr, "Number of portals: %d\n", nportals);
|
||
|
fprintf(stderr, "Number of lights: %d\n", nlights);
|
||
|
|
||
|
return array;
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** FaceArrayWrite
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
FaceArrayWrite(Face* array, FILE* file)
|
||
|
{
|
||
|
assert(file);
|
||
|
|
||
|
IntWrite(NumberOf(array), file);
|
||
|
|
||
|
for (int i = 0; i < NumberOf(array); i++)
|
||
|
{
|
||
|
FaceWrite(&array[i], file);
|
||
|
}
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** FaceArrayDelete
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
FaceArrayDelete(Face* array)
|
||
|
{
|
||
|
Face face;
|
||
|
|
||
|
while (array)
|
||
|
{
|
||
|
FaceArrayPull(&array, &face);
|
||
|
|
||
|
FaceDelete(&face);
|
||
|
}
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** FaceArraySlice
|
||
|
*******************************************************************************/
|
||
|
Face*
|
||
|
FaceArraySlice(Face* src, Plane plane)
|
||
|
{
|
||
|
Face face;
|
||
|
Face* facearray = NULL;
|
||
|
|
||
|
for (int i = 0; i < NumberOf(src); i++)
|
||
|
{
|
||
|
FaceSlice(&face, &src[i], plane);
|
||
|
|
||
|
if (face.vertices)
|
||
|
{
|
||
|
FaceArrayPush(&facearray, &face);
|
||
|
}
|
||
|
}
|
||
|
return facearray;
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** PlaneInfoCollect
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
PlaneInfoCollect(Face* faces)
|
||
|
{
|
||
|
assert(faces && NumberOf(faces) < MAX_FACES);
|
||
|
|
||
|
for (int infoid = 0; infoid < NumberOf(faces); infoid++)
|
||
|
{
|
||
|
PlaneInfo* info = &planeinfo[infoid];
|
||
|
|
||
|
memset(info, 0, sizeof(PlaneInfo));
|
||
|
|
||
|
memcpy(info->plane, faces[infoid].plane, sizeof(Plane));
|
||
|
|
||
|
for (int faceid = 0; faceid < NumberOf(faces); faceid++)
|
||
|
{
|
||
|
Face* face = &faces[faceid];
|
||
|
|
||
|
if (PlanesAreCollinear(face->plane, info->plane))
|
||
|
{
|
||
|
info->nfaces++;
|
||
|
|
||
|
if (face->colour == 0) info->nportals++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int behind = 0;
|
||
|
int infront = 0;
|
||
|
/*
|
||
|
** Count how many points are on each side of the plane.
|
||
|
*/
|
||
|
for (int i = 0; i < NumberOf(face->vertices); i++)
|
||
|
{
|
||
|
info->balance += PlaneDistanceTo(info->plane, face->vertices[i]);
|
||
|
|
||
|
if (PlaneDistanceTo(info->plane, face->vertices[i]) < 0.0f)
|
||
|
{
|
||
|
behind++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
infront++;
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
** Update totals.
|
||
|
*/
|
||
|
info->points_behind += behind;
|
||
|
info->points_infront += infront;
|
||
|
|
||
|
if (behind && infront) info->faces_split++;
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
** Calculate the point balance for this plane.
|
||
|
*/
|
||
|
info->point_balance = abs(info->points_behind - info->points_infront);
|
||
|
info->balance = (float) fabs(info->balance);
|
||
|
}
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** SelectPlane
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
SelectPlane(Plane plane, Face* faces)
|
||
|
{
|
||
|
int i, j;
|
||
|
|
||
|
assert(faces && NumberOf(faces));
|
||
|
|
||
|
PlaneInfoCollect(faces);
|
||
|
|
||
|
for (j = i = 0; i < NumberOf(faces); i++)
|
||
|
{
|
||
|
//if (planeinfo[i].balance < planeinfo[j].balance ) j = i; else
|
||
|
//if (planeinfo[i].balance == planeinfo[j].balance )
|
||
|
|
||
|
//if (planeinfo[i].nportals > planeinfo[j].nportals) j = i; else
|
||
|
//if (planeinfo[i].nportals == planeinfo[j].nportals)
|
||
|
|
||
|
if (planeinfo[i].faces_split < planeinfo[j].faces_split ) j = i; else
|
||
|
if (planeinfo[i].faces_split == planeinfo[j].faces_split )
|
||
|
|
||
|
//if (planeinfo[i].points_infront > planeinfo[j].points_infront) j = i; else
|
||
|
//if (planeinfo[i].points_infront == planeinfo[j].points_infront)
|
||
|
|
||
|
|
||
|
|
||
|
//if (planeinfo[i].nfaces > planeinfo[j].nfaces ) j = i; else
|
||
|
//if (planeinfo[i].nfaces == planeinfo[j].nfaces )
|
||
|
|
||
|
//if (planeinfo[i].point_balance < planeinfo[j].point_balance) j = i; else
|
||
|
//if (planeinfo[i].point_balance == planeinfo[j].point_balance)
|
||
|
|
||
|
{}
|
||
|
|
||
|
}
|
||
|
|
||
|
memcpy(plane, planeinfo[j].plane, sizeof(Plane));
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** BSPCompile
|
||
|
*******************************************************************************/
|
||
|
BSP*
|
||
|
BSPCompile(Face** facearray)
|
||
|
{
|
||
|
Face* both = NULL;
|
||
|
Face* front = NULL;
|
||
|
Face* back = NULL;
|
||
|
Face face;
|
||
|
Plane plane;
|
||
|
BSP* bsp = &bsps[nbsps++];;
|
||
|
|
||
|
assert(facearray);
|
||
|
|
||
|
ThrowIf(nbsps >= MAX_BSP, "Too many BSP's");
|
||
|
|
||
|
if (*facearray)
|
||
|
{
|
||
|
SelectPlane(bsp->plane, *facearray);
|
||
|
|
||
|
while (*facearray)
|
||
|
{
|
||
|
FaceArrayPull(facearray, &face);
|
||
|
|
||
|
if (PlanesAreCollinear(face.plane, bsp->plane))
|
||
|
{
|
||
|
FaceArrayPush(&bsp->faces, &face);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FaceArrayPush(&both, &face);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
memcpy(plane, bsp->plane, sizeof(Plane));
|
||
|
|
||
|
front = FaceArraySlice(both, plane);
|
||
|
|
||
|
PlaneNegate(plane);
|
||
|
|
||
|
back = FaceArraySlice(both, plane);
|
||
|
|
||
|
FaceArrayDelete(*facearray);
|
||
|
FaceArrayDelete(both);
|
||
|
|
||
|
bsp->sides[0] = BSPCompile(&front);
|
||
|
bsp->sides[1] = BSPCompile(&back);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nleafs++;
|
||
|
}
|
||
|
|
||
|
return bsp;
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** FaceLightMapCreate
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
FaceLightMapCreate(Picture* dst, Surface* surface, BSP* bsproot)
|
||
|
{
|
||
|
Vector rgb, sample, vector, L;
|
||
|
Matrix matrix;
|
||
|
|
||
|
assert(dst && surface && bsproot);
|
||
|
|
||
|
if (surface->colour < 3)
|
||
|
{
|
||
|
PictureCreate(dst, 1, 1, 0, 0);
|
||
|
return;
|
||
|
}
|
||
|
/*
|
||
|
** Create lightmap channel. The lightmap contains sample points every 16th pixel
|
||
|
** plus one extra point along the right and bottom edges.
|
||
|
*/
|
||
|
PictureCreate(dst, surface->width / 16 + 1, surface->height / 16 + 1, NULL, 0);
|
||
|
|
||
|
|
||
|
if (!switches.lighting || nlights == 0)
|
||
|
{
|
||
|
PictureBlitRect(dst, dst->rect, PixelCreate(31, 31, 31));
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
MatrixTranspose(matrix, surface->matrix);
|
||
|
/*
|
||
|
** Iterate over lightmap surface.
|
||
|
*/
|
||
|
for (int x = 0; x < dst->width; x++)
|
||
|
{
|
||
|
for (int y = 0; y < dst->height; y++)
|
||
|
{
|
||
|
/*
|
||
|
** Create and transform the sample point into world space.
|
||
|
*/
|
||
|
vector[0] = surface->lo[0] + x * 16.0f;
|
||
|
vector[1] = surface->lo[1] + y * 16.0f;
|
||
|
vector[2] = surface->lo[2] + 16.0f;
|
||
|
|
||
|
VectorRotate(sample, vector, matrix);
|
||
|
|
||
|
VectorCreate(rgb, 0.0f, 0.0f, 0.0f);
|
||
|
/*
|
||
|
** Iterate through each light.
|
||
|
*/
|
||
|
for (int z = 0; z < nlights; z++)
|
||
|
{
|
||
|
if (PlaneDistanceTo(surface->plane, lights[z].pos) > 0.0f)
|
||
|
{
|
||
|
Face* face = BSPFaceIntersect(bsproot, lights[z].pos, sample);
|
||
|
|
||
|
if (!face)
|
||
|
{
|
||
|
VectorSubtract(L, lights[z].pos, sample);
|
||
|
float brightness = 1.0f / VectorMagnitude(L);
|
||
|
VectorScale(L, L, brightness);
|
||
|
brightness *= VectorDotProduct(L, surface->plane);
|
||
|
rgb[0] += lights[z].rgb[0] * brightness;
|
||
|
rgb[1] += lights[z].rgb[1] * brightness;
|
||
|
rgb[2] += lights[z].rgb[2] * brightness;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
int r = Clamp((int)(rgb[0] * 31.0f + 0.5f), 7, 31);
|
||
|
int g = Clamp((int)(rgb[1] * 31.0f + 0.5f), 7, 31);
|
||
|
int b = Clamp((int)(rgb[2] * 31.0f + 0.5f), 7, 31);
|
||
|
|
||
|
dst->pixels[y][x] = PixelCreate(r, g, b);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** BSPCreateHullPlanes
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
BSPCreateHullPlanes(BSP* bsp)
|
||
|
{
|
||
|
if (bsp)
|
||
|
{
|
||
|
for (int i = 0; i < NumberOf(bsp->faces); i++)
|
||
|
{
|
||
|
FaceCreateHullPlanes(&bsp->faces[i]);
|
||
|
}
|
||
|
|
||
|
BSPCreateHullPlanes(bsp->sides[0]);
|
||
|
BSPCreateHullPlanes(bsp->sides[1]);
|
||
|
}
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** FaceSurfacesCreate
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
FaceSurfacesCreate(Face* faces)
|
||
|
{
|
||
|
static Vector temp[MAX_POINTS];
|
||
|
Surface surface1, surface2, surface3;
|
||
|
int i, j, newfaces;
|
||
|
|
||
|
assert(faces);
|
||
|
/*
|
||
|
** Reset all the face surfaces.
|
||
|
*/
|
||
|
for (i = 0; i < NumberOf(faces); i++)
|
||
|
{
|
||
|
faces[i].surfaceid = -1;
|
||
|
}
|
||
|
|
||
|
nsurfaces = 0;
|
||
|
|
||
|
for (i = 0; i < NumberOf(faces); i++)
|
||
|
{
|
||
|
Face* face1 = &faces[i];
|
||
|
|
||
|
float angle = 0.0;
|
||
|
float sz = 0.0;
|
||
|
|
||
|
if (face1->colour == 2)
|
||
|
{
|
||
|
angle = 22.0;
|
||
|
sz = -8000.0;
|
||
|
}
|
||
|
if (face1->surfaceid == -1)
|
||
|
{
|
||
|
face1->surfaceid = nsurfaces++;
|
||
|
|
||
|
ThrowIf(nsurfaces >= MAX_SURFACES, "Too many Surfaces");
|
||
|
|
||
|
int npoints = 0;
|
||
|
|
||
|
memcpy(temp[npoints], face1->vertices, sizeof(Vector) * NumberOf(face1->vertices));
|
||
|
|
||
|
npoints += NumberOf(face1->vertices);
|
||
|
|
||
|
assert(npoints < MAX_POINTS);
|
||
|
|
||
|
SurfaceCreate(&surface1,
|
||
|
temp,
|
||
|
npoints,
|
||
|
face1->colour,
|
||
|
angle, sz);
|
||
|
|
||
|
do
|
||
|
{
|
||
|
newfaces = 0;
|
||
|
|
||
|
for (j = 0; j < NumberOf(faces); j++)
|
||
|
{
|
||
|
Face* face2 = &faces[j];
|
||
|
|
||
|
if (
|
||
|
face2->surfaceid == -1 &&
|
||
|
face2->colour == face1->colour &&
|
||
|
PlanesAreEqual(face2->plane, face1->plane)
|
||
|
)
|
||
|
{
|
||
|
memcpy(temp[npoints], face2->vertices, sizeof(Vector) * NumberOf(face2->vertices));
|
||
|
|
||
|
npoints += NumberOf(face2->vertices);
|
||
|
|
||
|
assert(npoints < MAX_POINTS);
|
||
|
|
||
|
SurfaceCreate(&surface2,
|
||
|
face2->vertices,
|
||
|
NumberOf(face2->vertices),
|
||
|
face1->colour,
|
||
|
angle, sz);
|
||
|
|
||
|
SurfaceCreate(&surface3,
|
||
|
temp,
|
||
|
npoints,
|
||
|
face1->colour,
|
||
|
angle, sz);
|
||
|
|
||
|
int size1 = surface1.width * surface1.height + surface2.width * surface2.height;
|
||
|
int size2 = surface3.width * surface3.height;
|
||
|
|
||
|
if (face1->colour < 3 || size1 > size2)
|
||
|
{
|
||
|
surface1 = surface3;
|
||
|
face2->surfaceid = face1->surfaceid;
|
||
|
newfaces++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
npoints -= NumberOf(face2->vertices);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
while (newfaces > 0);
|
||
|
|
||
|
surfaces[face1->surfaceid] = surface1;
|
||
|
}
|
||
|
}
|
||
|
for (i = 0; i < NumberOf(faces); i++)
|
||
|
{
|
||
|
memcpy(faces[i].plane, surfaces[faces[i].surfaceid].plane, sizeof(Plane));
|
||
|
}
|
||
|
fprintf(stderr, "Number of surfaces: %d\n", nsurfaces);
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** BSPNodeWrite
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
BSPNodeWrite(BSP* bsp, FILE* file)
|
||
|
{
|
||
|
if (bsp)
|
||
|
{
|
||
|
fwrite(bsp->plane, sizeof(Plane), 1, file);
|
||
|
|
||
|
FaceArrayWrite(bsp->faces, file);
|
||
|
|
||
|
BSPNodeWrite(bsp->sides[0], file);
|
||
|
BSPNodeWrite(bsp->sides[1], file);
|
||
|
}
|
||
|
}
|
||
|
/*******************************************************************************
|
||
|
** BSPWrite
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
BSPWrite(BSP* bsp, FILE* file)
|
||
|
{
|
||
|
BSPNodeWrite(bsp, file);
|
||
|
|
||
|
MemoryWrite(surfaces, nsurfaces, sizeof(Surface), file);
|
||
|
|
||
|
IntWrite(nsurfaces, file);
|
||
|
|
||
|
for (int i = 0; i < nsurfaces; i++)
|
||
|
{
|
||
|
PictureWrite(&lightmaps[i], file);
|
||
|
}
|
||
|
MemoryWrite(lights, nlights, sizeof(Light), file);
|
||
|
}
|
||
|
|
||
|
char* title =
|
||
|
"\nDEBSP Compiler - (c) 1999-2000 by Derek J. Evans\n\n"
|
||
|
"Usage:\n\n"
|
||
|
" debsp INPUT <input filename>\n\n"
|
||
|
"Options:\n\n"
|
||
|
" -v Verbose\n"
|
||
|
" -s Shadows\n"
|
||
|
" -l Calculate lightmaps\n\n";
|
||
|
|
||
|
void
|
||
|
Main(void)
|
||
|
{
|
||
|
String filename;
|
||
|
|
||
|
strcpy(filename, FindArg("INPUT", title, NULL));
|
||
|
|
||
|
FILE* file_raw = FileOpen(FileNameExtChange(filename, "raw"), "r");
|
||
|
FILE* file_lights = FileOpen(FileNameExtChange(filename, "lit"), "r");
|
||
|
FILE* file_colours = FileOpen(FileNameExtChange(filename, "dat"), "r");
|
||
|
FILE* file_bsp = FileOpen(FileNameExtChange(filename, "bsp"), "wb");
|
||
|
|
||
|
switches.lighting = FindSwitch('l');
|
||
|
switches.shadows = FindSwitch('s');
|
||
|
|
||
|
Verbose("Reading world file");
|
||
|
|
||
|
Face* faces = FaceArrayReadMDL(file_raw, file_lights, file_colours);
|
||
|
|
||
|
Verbose("Creating surfaces");
|
||
|
|
||
|
FaceSurfacesCreate(faces);
|
||
|
|
||
|
Verbose("Compiling BSP tree");
|
||
|
|
||
|
BSP* bsp = BSPCompile(&faces);
|
||
|
|
||
|
Verbose("Creating hull planes");
|
||
|
|
||
|
BSPCreateHullPlanes(bsp);
|
||
|
|
||
|
Verbose("Calculating lightmaps");
|
||
|
|
||
|
for (int i = 0; i < nsurfaces; i++)
|
||
|
{
|
||
|
FaceLightMapCreate(&lightmaps[i], &surfaces[i], bsp);
|
||
|
}
|
||
|
|
||
|
Verbose("Writing BSP file");
|
||
|
|
||
|
BSPWrite(bsp, file_bsp);
|
||
|
|
||
|
fprintf(stderr, "Number of BSPs: %d\n", nbsps);
|
||
|
fprintf(stderr, "Number of nodes: %d\n", nbsps - nleafs);
|
||
|
fprintf(stderr, "Number of leafs: %d\n", nleafs);
|
||
|
|
||
|
Verbose("Done");
|
||
|
}
|
||
|
|
||
|
|