home *** CD-ROM | disk | FTP | other *** search
- #define LIBQBUILD_CORE
- #include "../include/libqbuild.h"
-
- /* command line flags */
- int subdivide_size = 240;
-
- struct brushset *brushset;
-
- int valid;
-
- char bspfilename[NAMELEN_PATH];
- char pointfilename[NAMELEN_PATH];
- char portfilename[NAMELEN_PATH];
- char hullfilename[NAMELEN_PATH];
-
- char *argv0; /* changed after fork(); */
-
- bool worldmodel;
-
- int hullnum;
-
- int c_activefaces, c_peakfaces;
- int c_activeleafs, c_peakleafs;
- int c_activesurfaces, c_peaksurfaces;
- int c_activeportals, c_peakportals;
-
- /*=========================================================================== */
-
- void PrintMemory(void)
- {
- int i, j;
- int a, b;
-
- mprintf(" faces : %5i, %7i (%5i, %7i)\n", c_activefaces, j = c_activefaces * sizeof(struct visfacet),
- c_peakfaces, i = c_peakfaces * sizeof(struct visfacet));
-
- a = j;
- b = i;
- mprintf(" surfaces: %5i, %7i (%5i, %7i)\n", c_activesurfaces, j = c_activesurfaces * sizeof(struct surface),
- c_peaksurfaces, i = c_peaksurfaces * sizeof(struct surface));
-
- a += j;
- b += i;
- mprintf(" windings: %5i, %7i (%5i, %7i)\n", c_activewindings, j = c_activewindings * sizeof(struct winding),
- c_peakwindings, i = c_peakwindings * sizeof(struct winding));
-
- a += j;
- b += i;
- mprintf(" portals : %5i, %7i (%5i, %7i)\n", c_activeportals, j = c_activeportals * sizeof(struct portal),
- c_peakportals, i = c_peakportals * sizeof(struct portal));
-
- a += j;
- b += i;
- mprintf("-------------------------------------------\n");
- mprintf(" %7i ( %7i)\n\n", a, b);
- }
-
- /*
- * ===========
- * AllocLeaf
- * ===========
- */
- struct visleaf *AllocLeaf(register int prtals)
- {
- struct visleaf *l;
-
- c_activeleafs++;
- if (c_activeleafs > c_peakleafs)
- c_peakleafs = c_activeleafs;
-
- if (!(l = (struct visleaf *)tmalloc(sizeof(struct visleaf))))
- Error(failed_memoryunsize, "leaf");
-
- #ifdef DYNAMIC_EDGES
- /* at least one point available */
- if (prtals < 0)
- prtals = 0;
- if (!(l->portals = (struct visportal **)tmalloc((prtals) * sizeof(struct visportal *))))
- Error(failed_memoryunsize, "portals");
-
- #endif
- return l;
- }
-
- void RecalcLeaf(register struct visleaf *l)
- {
- #ifdef DYNAMIC_EDGES
- /* at least one point available */
- int prtals = l->numportals;
-
- if (prtals < 0)
- prtals = 0;
- if (!(l->portals = (struct visportal **)trealloc(l->portals, (prtals) * sizeof(struct visportal *))))
- Error(failed_memoryunsize, "face");
-
- #endif
- }
-
- void FreeLeaf(register struct visleaf *l)
- {
- c_activeleafs--;
- #ifdef DYNAMIC_EDGES
- tfree(l->portals);
- #endif
- tfree(l);
- }
-
- /*
- * ===========
- * AllocFace
- * ===========
- */
- struct visfacet *AllocFace(register int points)
- {
- struct visfacet *f;
-
- c_activefaces++;
- if (c_activefaces > c_peakfaces)
- c_peakfaces = c_activefaces;
-
- if (!(f = (struct visfacet *)tmalloc(sizeof(struct visfacet))))
- Error(failed_memoryunsize, "face");
-
- f->planenum = -1;
- #ifdef DYNAMIC_EDGES
- /* at least one point available */
- if (points < 0)
- points = 0;
- if (!(f->pts = (vec3_t *) tmalloc((points) * sizeof(vec3_t))))
- Error(failed_memoryunsize, "points");
- if (!(f->edges = (int *)tmalloc((points) * sizeof(int))))
- Error(failed_memoryunsize, "edges");
-
- #endif
- return f;
- }
-
- void CopyFace(register struct visfacet *out, register struct visfacet *in)
- {
- #ifdef DYNAMIC_EDGES
- /* at least one point available */
- short int points = in->numpoints;
- vec3_t *pts;
- int *edges;
-
- if (points < 0)
- points = 0;
- tfree(out->pts);
- tfree(out->edges);
- if (!(pts = (vec3_t *) tmalloc((points) * sizeof(vec3_t))))
- Error(failed_memoryunsize, "face");
- if (!(edges = (int *)tmalloc((points) * sizeof(int))))
- Error(failed_memoryunsize, "face");
-
- if (points) {
- memcpy(pts, in->pts, points * sizeof(vec3_t));
- memcpy(edges, in->edges, points * sizeof(int));
- }
- #endif
- __memcpy(out, in, sizeof(struct visfacet));
-
- #ifdef DYNAMIC_EDGES
- out->pts = pts;
- out->edges = edges;
- #endif
- }
-
- void RecalcFace(register struct visfacet *f)
- {
- #ifdef DYNAMIC_EDGES
- /* at least one point available */
- short int points = f->numpoints;
-
- if (points < 0)
- points = 0;
- if (!(f->pts = (vec3_t *) trealloc(f->pts, (points) * sizeof(vec3_t))))
- Error(failed_memoryunsize, "face");
- if (!(f->edges = (int *)trealloc(f->edges, (points) * sizeof(int))))
- Error(failed_memoryunsize, "face");
-
- #endif
- }
-
- void FreeFace(register struct visfacet *f)
- {
- c_activefaces--;
- #ifdef DYNAMIC_EDGES
- tfree(f->pts);
- tfree(f->edges);
- #endif
- tfree(f);
- }
-
- /*
- * ===========
- * AllocSurface
- * ===========
- */
- struct surface *AllocSurface(void)
- {
- struct surface *s;
-
- if (!(s = (struct surface *)tmalloc(sizeof(struct surface))))
- Error(failed_memoryunsize, "surface");
-
- c_activesurfaces++;
- if (c_activesurfaces > c_peaksurfaces)
- c_peaksurfaces = c_activesurfaces;
-
- return s;
- }
-
- void FreeSurface(register struct surface *s)
- {
- c_activesurfaces--;
- tfree(s);
- }
-
- /*
- * ===========
- * AllocPortal
- * ===========
- */
- struct portal *AllocPortal(void)
- {
- struct portal *p;
-
- c_activeportals++;
- if (c_activeportals > c_peakportals)
- c_peakportals = c_activeportals;
-
- if (!(p = (struct portal *)tmalloc(sizeof(struct portal))))
- Error(failed_memoryunsize, "portal");
-
- return p;
- }
-
- void FreePortal(register struct portal *p)
- {
- c_activeportals--;
- tfree(p);
- }
-
- /*
- * ===========
- * AllocNode
- * ===========
- */
- struct node *AllocNode(void)
- {
- struct node *n;
-
- if (!(n = (struct node *)tmalloc(sizeof(struct node))))
- Error(failed_memoryunsize, "node");
-
- return n;
- }
-
- /*
- * ===========
- * AllocBrush
- * ===========
- */
- struct brush *AllocBrush(void)
- {
- struct brush *b;
-
- if (!(b = (struct brush *)tmalloc(sizeof(struct brush))))
- Error(failed_memoryunsize, "node");
-
- return b;
- }
-
- /*=========================================================================== */
-
- /*
- * ===============
- * ProcessEntity
- * ===============
- */
- void ProcessEntity(__memBase, register int entnum)
- {
- struct entity *ent;
- char mod[80];
- struct surface *surfs;
- struct node *nodes;
- struct brushset *bs;
-
- ent = &bspMem->mapentities[entnum];
- if (!ent->brushes)
- return; /* non-bmodel entity */
-
- if (entnum > 0) {
- worldmodel = FALSE;
- if (entnum == 1)
- mprintf("----- Internal Entities ---\n");
- sprintf(mod, "*%i", bspMem->shared.quake1.nummodels);
-
- if (hullnum == 0)
- mprintf(" - MODEL: %s\n", mod);
- SetKeyValue(ent, "model", mod);
- }
- else
- worldmodel = TRUE;
-
- /*
- * take the brush_ts and clip off all overlapping and contained faces,
- * leaving a perfect skin of the model with no hidden faces
- */
- bs = Brush_LoadEntity(bspMem, ent, hullnum);
-
- if (!bs->brushes) {
- PrintEntity(ent);
- Error("Entity with no valid brushes");
- }
-
- brushset = bs;
- surfs = CSGFaces(bspMem, bs);
-
- if (hullnum != 0) {
- nodes = SolidBSP(bspMem, surfs, TRUE);
- if (entnum == 0 && !(bspMem->bspOptions & QBSP_NOFILL)) { /* assume non-world bmodels are simple */
- PortalizeWorld(bspMem, nodes);
- if (FillOutside(bspMem, nodes, pointfilename)) {
- surfs = GatherNodeFaces(bspMem, nodes);
- nodes = SolidBSP(bspMem, surfs, FALSE); /* make a really good tree */
- }
- FreeAllPortals(nodes);
- }
- WriteNodePlanes(bspMem, nodes);
- WriteClipNodes(bspMem, nodes);
- BumpModel(bspMem, hullnum);
- }
- else {
- /*
- * SolidBSP generates a node tree
- *
- * if not the world, make a good tree first
- * the world is just going to make a bad tree
- * because the outside filling will force a regeneration later
- */
- nodes = SolidBSP(bspMem, surfs, entnum == 0);
-
- /*
- * build all the portals in the bsp tree
- * some portals are solid polygons, and some are paths to other leafs
- */
- if (entnum == 0 && !(bspMem->bspOptions & QBSP_NOFILL)) { /* assume non-world bmodels are simple */
- PortalizeWorld(bspMem, nodes);
-
- if (FillOutside(bspMem, nodes, pointfilename)) {
- FreeAllPortals(nodes);
-
- /* get the remaining faces together into surfaces again */
- surfs = GatherNodeFaces(bspMem, nodes);
-
- /* merge polygons */
- MergeAll(bspMem, surfs);
-
- /* make a really good tree */
- nodes = SolidBSP(bspMem, surfs, FALSE);
-
- /* make the real portals for vis tracing */
- PortalizeWorld(bspMem, nodes);
-
- /* save portal file for vis tracing */
- WritePortalfile(bspMem, nodes, portfilename);
-
- /* fix tjunctions */
- if (!(bspMem->bspOptions & QBSP_NOTJUNC))
- tjunc(nodes);
- }
- FreeAllPortals(nodes);
- }
-
- WriteNodePlanes(bspMem, nodes);
- MakeFaceEdges(bspMem, nodes);
- WriteDrawNodes(bspMem, nodes);
- }
- }
-
- /*
- * =================
- * UpdateEntLump
- *
- * =================
- */
- void UpdateEntLump(__memBase)
- {
- int m, entnum;
- char mod[80];
- HANDLE bspFile;
-
- m = 1;
- for (entnum = 1; entnum < bspMem->nummapentities; entnum++) {
- if (!bspMem->mapentities[entnum].brushes)
- continue;
- sprintf(mod, "*%i", m);
- SetKeyValue(&bspMem->mapentities[entnum], "model", mod);
- m++;
- }
-
- mprintf(" - updating bspMem->mapentities lump...\n");
-
- FreeClusters(bspMem, 0);
- if ((bspFile = __open(bspfilename, H_READWRITE_BINARY_OLD)) > 0) {
- bspMem = LoadBSP(bspFile, ALL_QUAKE1_LUMPS, BSP_VERSION_Q1);
- WriteEntitiesToString(bspMem);
- WriteBSP(bspFile, bspMem, BSP_VERSION_Q1);
- FreeClusters(bspMem, 0);
- tfree(bspMem);
- __close(bspFile);
- }
- }
-
- /*=========================================================================== */
-
- /*
- * =================
- * WriteClipHull
- *
- * Write the clipping hull out to a text file so the parent process can get it
- * =================
- */
- void WriteClipHull(__memBase)
- {
- FILE *f;
- int i;
- struct dplane_t *p;
- struct dclipnode_t *d;
-
- hullfilename[strlen(hullfilename) - 1] = '0' + hullnum;
-
- mprintf("----- WriteClipHull -----\n");
- mprintf(" - writing %s\n", hullfilename);
-
- f = __fopen(hullfilename, "w");
- if (!f)
- Error(failed_fileopen, hullfilename);
-
- fprintf(f, "%i\n", bspMem->shared.quake1.nummodels);
-
- for (i = 0; i < bspMem->shared.quake1.nummodels; i++)
- fprintf(f, "%i\n", bspMem->shared.quake1.dmodels[i].headnode[hullnum]);
-
- fprintf(f, "\n%i\n", bspMem->shared.quake1.numclipnodes);
-
- for (i = 0; i < bspMem->shared.quake1.numclipnodes; i++) {
- d = &bspMem->shared.quake1.dclipnodes[i];
- p = &bspMem->shared.quake1.dplanes[d->planenum];
- /* the node number is only written out for human readability */
- fprintf(f, "%5i : %g %g %g %g : %5i %5i\n", i, p->normal[0], p->normal[1], p->normal[2], p->dist, d->children[0], d->children[1]);
- }
-
- __fclose(f);
- }
-
- /*
- * =================
- * ReadClipHull
- *
- * Read the files written out by the child processes
- * =================
- */
- void ReadClipHull(__memBase, register int hullnum)
- {
- FILE *f;
- int i, j, n;
- int firstclipnode;
- struct dplane_t p;
- struct dclipnode_t *d;
- int c1, c2;
- float f1, f2, f3, f4;
- int junk;
- vec3_t norm;
-
- hullfilename[strlen(hullfilename) - 1] = '0' + hullnum;
-
- f = __fopen(hullfilename, "r");
- if (!f)
- Error(failed_fileopen, hullfilename);
-
- if (fscanf(f, "%i\n", &n) != 1)
- Error("Error parsing %s", hullfilename);
-
- if (n != bspMem->shared.quake1.nummodels)
- Error("ReadClipHull: hull had %i models, base had %i", n, bspMem->shared.quake1.nummodels);
-
- for (i = 0; i < n; i++) {
- fscanf(f, "%i\n", &j);
- bspMem->shared.quake1.dmodels[i].headnode[hullnum] = bspMem->shared.quake1.numclipnodes + j;
- }
-
- fscanf(f, "\n%i\n", &n);
- firstclipnode = bspMem->shared.quake1.numclipnodes;
-
- for (i = 0; i < n; i++) {
- if (bspMem->shared.quake1.numclipnodes == bspMem->shared.quake1.max_numclipnodes)
- ExpandClusters(bspMem, LUMP_CLIPNODES);
- d = &bspMem->shared.quake1.dclipnodes[bspMem->shared.quake1.numclipnodes];
- bspMem->shared.quake1.numclipnodes++;
- if (fscanf(f, "%i : %g %g %g %g : %i %i\n", &junk, &f1, &f2, &f3, &f4, &c1, &c2) != 7)
- Error("Error parsing %s", hullfilename);
-
- p.normal[0] = f1;
- p.normal[1] = f2;
- p.normal[2] = f3;
- p.dist = f4;
-
- norm[0] = f1;
- norm[1] = f2;
- norm[2] = f3; /* vec_t precision */
-
- p.type = PlaneTypeForNormal(norm);
-
- d->children[0] = c1 >= 0 ? c1 + firstclipnode : c1;
- d->children[1] = c2 >= 0 ? c2 + firstclipnode : c2;
- d->planenum = FindFinalPlane(bspMem, &p);
- }
-
- }
-
- /*
- * =================
- * CreateSingleHull
- *
- * =================
- */
- void CreateSingleHull(__memBase)
- {
- int entnum;
-
- /* for each entity in the map file that has geometry */
- for (entnum = 0; entnum < bspMem->nummapentities; entnum++)
- ProcessEntity(bspMem, entnum);
-
- if (hullnum)
- WriteClipHull(bspMem);
- }
-
- /*
- * =================
- * CreateHulls
- *
- * =================
- */
- void CreateHulls(__memBase)
- {
- /* commanded to create a single hull only */
- if (hullnum) {
- CreateSingleHull(bspMem);
- exit(0);
- }
-
- /* commanded to use the allready existing hulls 1 and 2 */
- if (bspMem->bspOptions & QBSP_USEHULLS) {
- CreateSingleHull(bspMem);
- return;
- }
-
- /* commanded to ignore the hulls altogether */
- if (bspMem->bspOptions & QBSP_NOCLIP) {
- CreateSingleHull(bspMem);
- return;
- }
-
- /* create all the hulls */
-
- /* create the hulls sequentially */
- mprintf(" - building hulls sequentially...\n");
-
- hullnum = 1;
- CreateSingleHull(bspMem);
-
- bspMem->shared.quake1.nummodels = 0;
- bspMem->shared.quake1.numplanes = 0;
- bspMem->shared.quake1.numclipnodes = 0;
- hullnum = 2;
- CreateSingleHull(bspMem);
-
- bspMem->shared.quake1.nummodels = 0;
- bspMem->shared.quake1.numplanes = 0;
- bspMem->shared.quake1.numclipnodes = 0;
- hullnum = 0;
- CreateSingleHull(bspMem);
- }
-
- /*
- * =================
- * ProcessMem
- * =================
- */
- void ProcessMem(__memBase, register char *filebase)
- {
- /* create filenames */
- strcpy(bspfilename, filebase);
- ReplaceExt(bspfilename, "bsp");
- strcpy(hullfilename, filebase);
- ReplaceExt(hullfilename, "h0");
- strcpy(portfilename, filebase);
- ReplaceExt(portfilename, "prt");
- strcpy(pointfilename, filebase);
- ReplaceExt(pointfilename, "pts");
-
- if (bspMem->bspOptions & QBSP_ONLYENTS)
- UpdateEntLump(bspMem);
- else {
- if (!(bspMem->bspOptions & QBSP_USEHULLS)) {
- hullfilename[strlen(hullfilename) - 1] = '1';
- remove(hullfilename);
- hullfilename[strlen(hullfilename) - 1] = '2';
- remove(hullfilename);
- }
- remove(portfilename);
- remove(pointfilename);
-
- /* the clipping hulls will be written out to text files by forked processes */
- CreateHulls(bspMem);
-
- ReadClipHull(bspMem, 1);
- ReadClipHull(bspMem, 2);
-
- WriteEntitiesToString(bspMem);
- }
- }
-
- bool qbsp(__memBase, int hullNum, int subDivide, char *filebase)
- {
- if (hullNum) {
- hullnum = hullNum;
- mprintf("use hull %d\n", hullNum);
- }
- if (subDivide) {
- subdivide_size = subDivide;
- mprintf("subdivide %d\n", subDivide);
- }
-
- ProcessMem(bspMem, filebase);
- PrintMemory();
-
- return TRUE;
- }
-