home *** CD-ROM | disk | FTP | other *** search
/ Dream 57 / Amiga_Dream_57.iso / Amiga / Programmation / c / QuakeC / qtools0.2-src.lha / src / libqbuild / qbsp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-07-15  |  14.6 KB  |  643 lines

  1. #define    LIBQBUILD_CORE
  2. #include "../include/libqbuild.h"
  3.  
  4. /* command line flags */
  5. int subdivide_size = 240;
  6.  
  7. struct brushset *brushset;
  8.  
  9. int valid;
  10.  
  11. char bspfilename[NAMELEN_PATH];
  12. char pointfilename[NAMELEN_PATH];
  13. char portfilename[NAMELEN_PATH];
  14. char hullfilename[NAMELEN_PATH];
  15.  
  16. char *argv0;                            /* changed after fork(); */
  17.  
  18. bool worldmodel;
  19.  
  20. int hullnum;
  21.  
  22. int c_activefaces, c_peakfaces;
  23. int c_activeleafs, c_peakleafs;
  24. int c_activesurfaces, c_peaksurfaces;
  25. int c_activeportals, c_peakportals;
  26.  
  27. /*=========================================================================== */
  28.  
  29. void PrintMemory(void)
  30. {
  31.   int i, j;
  32.   int a, b;
  33.  
  34.   mprintf(" faces   : %5i, %7i (%5i, %7i)\n", c_activefaces, j = c_activefaces * sizeof(struct visfacet),
  35.       c_peakfaces, i = c_peakfaces * sizeof(struct visfacet));
  36.  
  37.   a = j;
  38.   b = i;
  39.   mprintf(" surfaces: %5i, %7i (%5i, %7i)\n", c_activesurfaces, j = c_activesurfaces * sizeof(struct surface),
  40.       c_peaksurfaces, i = c_peaksurfaces * sizeof(struct surface));
  41.  
  42.   a += j;
  43.   b += i;
  44.   mprintf(" windings: %5i, %7i (%5i, %7i)\n", c_activewindings, j = c_activewindings * sizeof(struct winding),
  45.       c_peakwindings, i = c_peakwindings * sizeof(struct winding));
  46.  
  47.   a += j;
  48.   b += i;
  49.   mprintf(" portals : %5i, %7i (%5i, %7i)\n", c_activeportals, j = c_activeportals * sizeof(struct portal),
  50.       c_peakportals, i = c_peakportals * sizeof(struct portal));
  51.  
  52.   a += j;
  53.   b += i;
  54.   mprintf("-------------------------------------------\n");
  55.   mprintf("                  %7i (       %7i)\n\n", a, b);
  56. }
  57.  
  58. /*
  59.  * ===========
  60.  * AllocLeaf
  61.  * ===========
  62.  */
  63. struct visleaf *AllocLeaf(register int prtals)
  64. {
  65.   struct visleaf *l;
  66.  
  67.   c_activeleafs++;
  68.   if (c_activeleafs > c_peakleafs)
  69.     c_peakleafs = c_activeleafs;
  70.  
  71.   if (!(l = (struct visleaf *)tmalloc(sizeof(struct visleaf))))
  72.       Error(failed_memoryunsize, "leaf");
  73.  
  74. #ifdef DYNAMIC_EDGES
  75.   /* at least one point available */
  76.   if (prtals < 0)
  77.     prtals = 0;
  78.   if (!(l->portals = (struct visportal **)tmalloc((prtals) * sizeof(struct visportal *))))
  79.       Error(failed_memoryunsize, "portals");
  80.  
  81. #endif
  82.   return l;
  83. }
  84.  
  85. void RecalcLeaf(register struct visleaf *l)
  86. {
  87. #ifdef DYNAMIC_EDGES
  88.   /* at least one point available */
  89.   int prtals = l->numportals;
  90.  
  91.   if (prtals < 0)
  92.     prtals = 0;
  93.   if (!(l->portals = (struct visportal **)trealloc(l->portals, (prtals) * sizeof(struct visportal *))))
  94.       Error(failed_memoryunsize, "face");
  95.  
  96. #endif
  97. }
  98.  
  99. void FreeLeaf(register struct visleaf *l)
  100. {
  101.   c_activeleafs--;
  102. #ifdef DYNAMIC_EDGES
  103.   tfree(l->portals);
  104. #endif
  105.   tfree(l);
  106. }
  107.  
  108. /*
  109.  * ===========
  110.  * AllocFace
  111.  * ===========
  112.  */
  113. struct visfacet *AllocFace(register int points)
  114. {
  115.   struct visfacet *f;
  116.  
  117.   c_activefaces++;
  118.   if (c_activefaces > c_peakfaces)
  119.     c_peakfaces = c_activefaces;
  120.  
  121.   if (!(f = (struct visfacet *)tmalloc(sizeof(struct visfacet))))
  122.       Error(failed_memoryunsize, "face");
  123.  
  124.   f->planenum = -1;
  125. #ifdef DYNAMIC_EDGES
  126.   /* at least one point available */
  127.   if (points < 0)
  128.     points = 0;
  129.   if (!(f->pts = (vec3_t *) tmalloc((points) * sizeof(vec3_t))))
  130.     Error(failed_memoryunsize, "points");
  131.   if (!(f->edges = (int *)tmalloc((points) * sizeof(int))))
  132.       Error(failed_memoryunsize, "edges");
  133.  
  134. #endif
  135.   return f;
  136. }
  137.  
  138. void CopyFace(register struct visfacet *out, register struct visfacet *in)
  139. {
  140. #ifdef DYNAMIC_EDGES
  141.   /* at least one point available */
  142.   short int points = in->numpoints;
  143.   vec3_t *pts;
  144.   int *edges;
  145.  
  146.   if (points < 0)
  147.     points = 0;
  148.   tfree(out->pts);
  149.   tfree(out->edges);
  150.   if (!(pts = (vec3_t *) tmalloc((points) * sizeof(vec3_t))))
  151.     Error(failed_memoryunsize, "face");
  152.   if (!(edges = (int *)tmalloc((points) * sizeof(int))))
  153.       Error(failed_memoryunsize, "face");
  154.  
  155.   if (points) {
  156.     memcpy(pts, in->pts, points * sizeof(vec3_t));
  157.     memcpy(edges, in->edges, points * sizeof(int));
  158.   }
  159. #endif
  160.   __memcpy(out, in, sizeof(struct visfacet));
  161.  
  162. #ifdef DYNAMIC_EDGES
  163.   out->pts = pts;
  164.   out->edges = edges;
  165. #endif
  166. }
  167.  
  168. void RecalcFace(register struct visfacet *f)
  169. {
  170. #ifdef DYNAMIC_EDGES
  171.   /* at least one point available */
  172.   short int points = f->numpoints;
  173.  
  174.   if (points < 0)
  175.     points = 0;
  176.   if (!(f->pts = (vec3_t *) trealloc(f->pts, (points) * sizeof(vec3_t))))
  177.     Error(failed_memoryunsize, "face");
  178.   if (!(f->edges = (int *)trealloc(f->edges, (points) * sizeof(int))))
  179.       Error(failed_memoryunsize, "face");
  180.  
  181. #endif
  182. }
  183.  
  184. void FreeFace(register struct visfacet *f)
  185. {
  186.   c_activefaces--;
  187. #ifdef DYNAMIC_EDGES
  188.   tfree(f->pts);
  189.   tfree(f->edges);
  190. #endif
  191.   tfree(f);
  192. }
  193.  
  194. /*
  195.  * ===========
  196.  * AllocSurface
  197.  * ===========
  198.  */
  199. struct surface *AllocSurface(void)
  200. {
  201.   struct surface *s;
  202.  
  203.   if (!(s = (struct surface *)tmalloc(sizeof(struct surface))))
  204.       Error(failed_memoryunsize, "surface");
  205.  
  206.   c_activesurfaces++;
  207.   if (c_activesurfaces > c_peaksurfaces)
  208.     c_peaksurfaces = c_activesurfaces;
  209.  
  210.   return s;
  211. }
  212.  
  213. void FreeSurface(register struct surface *s)
  214. {
  215.   c_activesurfaces--;
  216.   tfree(s);
  217. }
  218.  
  219. /*
  220.  * ===========
  221.  * AllocPortal
  222.  * ===========
  223.  */
  224. struct portal *AllocPortal(void)
  225. {
  226.   struct portal *p;
  227.  
  228.   c_activeportals++;
  229.   if (c_activeportals > c_peakportals)
  230.     c_peakportals = c_activeportals;
  231.  
  232.   if (!(p = (struct portal *)tmalloc(sizeof(struct portal))))
  233.       Error(failed_memoryunsize, "portal");
  234.  
  235.   return p;
  236. }
  237.  
  238. void FreePortal(register struct portal *p)
  239. {
  240.   c_activeportals--;
  241.   tfree(p);
  242. }
  243.  
  244. /*
  245.  * ===========
  246.  * AllocNode
  247.  * ===========
  248.  */
  249. struct node *AllocNode(void)
  250. {
  251.   struct node *n;
  252.  
  253.   if (!(n = (struct node *)tmalloc(sizeof(struct node))))
  254.       Error(failed_memoryunsize, "node");
  255.  
  256.   return n;
  257. }
  258.  
  259. /*
  260.  * ===========
  261.  * AllocBrush
  262.  * ===========
  263.  */
  264. struct brush *AllocBrush(void)
  265. {
  266.   struct brush *b;
  267.  
  268.   if (!(b = (struct brush *)tmalloc(sizeof(struct brush))))
  269.       Error(failed_memoryunsize, "node");
  270.  
  271.   return b;
  272. }
  273.  
  274. /*=========================================================================== */
  275.  
  276. /*
  277.  * ===============
  278.  * ProcessEntity
  279.  * ===============
  280.  */
  281. void ProcessEntity(__memBase, register int entnum)
  282. {
  283.   struct entity *ent;
  284.   char mod[80];
  285.   struct surface *surfs;
  286.   struct node *nodes;
  287.   struct brushset *bs;
  288.  
  289.   ent = &bspMem->mapentities[entnum];
  290.   if (!ent->brushes)
  291.     return;                            /* non-bmodel entity */
  292.  
  293.   if (entnum > 0) {
  294.     worldmodel = FALSE;
  295.     if (entnum == 1)
  296.       mprintf("----- Internal Entities ---\n");
  297.     sprintf(mod, "*%i", bspMem->shared.quake1.nummodels);
  298.  
  299.     if (hullnum == 0)
  300.       mprintf("    - MODEL: %s\n", mod);
  301.     SetKeyValue(ent, "model", mod);
  302.   }
  303.   else
  304.     worldmodel = TRUE;
  305.  
  306.   /*
  307.    * take the brush_ts and clip off all overlapping and contained faces,
  308.    * leaving a perfect skin of the model with no hidden faces
  309.    */
  310.   bs = Brush_LoadEntity(bspMem, ent, hullnum);
  311.  
  312.   if (!bs->brushes) {
  313.     PrintEntity(ent);
  314.     Error("Entity with no valid brushes");
  315.   }
  316.  
  317.   brushset = bs;
  318.   surfs = CSGFaces(bspMem, bs);
  319.  
  320.   if (hullnum != 0) {
  321.     nodes = SolidBSP(bspMem, surfs, TRUE);
  322.     if (entnum == 0 && !(bspMem->bspOptions & QBSP_NOFILL)) {    /* assume non-world bmodels are simple */
  323.       PortalizeWorld(bspMem, nodes);
  324.       if (FillOutside(bspMem, nodes, pointfilename)) {
  325.     surfs = GatherNodeFaces(bspMem, nodes);
  326.     nodes = SolidBSP(bspMem, surfs, FALSE);            /* make a really good tree */
  327.       }
  328.       FreeAllPortals(nodes);
  329.     }
  330.     WriteNodePlanes(bspMem, nodes);
  331.     WriteClipNodes(bspMem, nodes);
  332.     BumpModel(bspMem, hullnum);
  333.   }
  334.   else {
  335.     /*
  336.      * SolidBSP generates a node tree
  337.      *
  338.      * if not the world, make a good tree first
  339.      * the world is just going to make a bad tree
  340.      * because the outside filling will force a regeneration later
  341.      */
  342.     nodes = SolidBSP(bspMem, surfs, entnum == 0);
  343.  
  344.     /*
  345.      * build all the portals in the bsp tree
  346.      * some portals are solid polygons, and some are paths to other leafs
  347.      */
  348.     if (entnum == 0 && !(bspMem->bspOptions & QBSP_NOFILL)) {    /* assume non-world bmodels are simple */
  349.       PortalizeWorld(bspMem, nodes);
  350.  
  351.       if (FillOutside(bspMem, nodes, pointfilename)) {
  352.     FreeAllPortals(nodes);
  353.  
  354.     /* get the remaining faces together into surfaces again */
  355.     surfs = GatherNodeFaces(bspMem, nodes);
  356.  
  357.     /* merge polygons */
  358.     MergeAll(bspMem, surfs);
  359.  
  360.     /* make a really good tree */
  361.     nodes = SolidBSP(bspMem, surfs, FALSE);
  362.  
  363.     /* make the real portals for vis tracing */
  364.     PortalizeWorld(bspMem, nodes);
  365.  
  366.     /* save portal file for vis tracing */
  367.     WritePortalfile(bspMem, nodes, portfilename);
  368.  
  369.     /* fix tjunctions */
  370.     if (!(bspMem->bspOptions & QBSP_NOTJUNC))
  371.       tjunc(nodes);
  372.       }
  373.       FreeAllPortals(nodes);
  374.     }
  375.  
  376.     WriteNodePlanes(bspMem, nodes);
  377.     MakeFaceEdges(bspMem, nodes);
  378.     WriteDrawNodes(bspMem, nodes);
  379.   }
  380. }
  381.  
  382. /*
  383.  * =================
  384.  * UpdateEntLump
  385.  * 
  386.  * =================
  387.  */
  388. void UpdateEntLump(__memBase)
  389. {
  390.   int m, entnum;
  391.   char mod[80];
  392.   HANDLE bspFile;
  393.  
  394.   m = 1;
  395.   for (entnum = 1; entnum < bspMem->nummapentities; entnum++) {
  396.     if (!bspMem->mapentities[entnum].brushes)
  397.       continue;
  398.     sprintf(mod, "*%i", m);
  399.     SetKeyValue(&bspMem->mapentities[entnum], "model", mod);
  400.     m++;
  401.   }
  402.  
  403.   mprintf("    - updating bspMem->mapentities lump...\n");
  404.  
  405.   FreeClusters(bspMem, 0);
  406.   if ((bspFile = __open(bspfilename, H_READWRITE_BINARY_OLD)) > 0) {
  407.     bspMem = LoadBSP(bspFile, ALL_QUAKE1_LUMPS, BSP_VERSION_Q1);
  408.     WriteEntitiesToString(bspMem);
  409.     WriteBSP(bspFile, bspMem, BSP_VERSION_Q1);
  410.     FreeClusters(bspMem, 0);
  411.     tfree(bspMem);
  412.     __close(bspFile);
  413.   }
  414. }
  415.  
  416. /*=========================================================================== */
  417.  
  418. /*
  419.  * =================
  420.  * WriteClipHull
  421.  * 
  422.  * Write the clipping hull out to a text file so the parent process can get it
  423.  * =================
  424.  */
  425. void WriteClipHull(__memBase)
  426. {
  427.   FILE *f;
  428.   int i;
  429.   struct dplane_t *p;
  430.   struct dclipnode_t *d;
  431.  
  432.   hullfilename[strlen(hullfilename) - 1] = '0' + hullnum;
  433.  
  434.   mprintf("----- WriteClipHull -----\n");
  435.   mprintf("    - writing %s\n", hullfilename);
  436.  
  437.   f = __fopen(hullfilename, "w");
  438.   if (!f)
  439.     Error(failed_fileopen, hullfilename);
  440.  
  441.   fprintf(f, "%i\n", bspMem->shared.quake1.nummodels);
  442.  
  443.   for (i = 0; i < bspMem->shared.quake1.nummodels; i++)
  444.     fprintf(f, "%i\n", bspMem->shared.quake1.dmodels[i].headnode[hullnum]);
  445.  
  446.   fprintf(f, "\n%i\n", bspMem->shared.quake1.numclipnodes);
  447.  
  448.   for (i = 0; i < bspMem->shared.quake1.numclipnodes; i++) {
  449.     d = &bspMem->shared.quake1.dclipnodes[i];
  450.     p = &bspMem->shared.quake1.dplanes[d->planenum];
  451.     /* the node number is only written out for human readability */
  452.     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]);
  453.   }
  454.  
  455.   __fclose(f);
  456. }
  457.  
  458. /*
  459.  * =================
  460.  * ReadClipHull
  461.  * 
  462.  * Read the files written out by the child processes
  463.  * =================
  464.  */
  465. void ReadClipHull(__memBase, register int hullnum)
  466. {
  467.   FILE *f;
  468.   int i, j, n;
  469.   int firstclipnode;
  470.   struct dplane_t p;
  471.   struct dclipnode_t *d;
  472.   int c1, c2;
  473.   float f1, f2, f3, f4;
  474.   int junk;
  475.   vec3_t norm;
  476.  
  477.   hullfilename[strlen(hullfilename) - 1] = '0' + hullnum;
  478.  
  479.   f = __fopen(hullfilename, "r");
  480.   if (!f)
  481.     Error(failed_fileopen, hullfilename);
  482.  
  483.   if (fscanf(f, "%i\n", &n) != 1)
  484.     Error("Error parsing %s", hullfilename);
  485.  
  486.   if (n != bspMem->shared.quake1.nummodels)
  487.     Error("ReadClipHull: hull had %i models, base had %i", n, bspMem->shared.quake1.nummodels);
  488.  
  489.   for (i = 0; i < n; i++) {
  490.     fscanf(f, "%i\n", &j);
  491.     bspMem->shared.quake1.dmodels[i].headnode[hullnum] = bspMem->shared.quake1.numclipnodes + j;
  492.   }
  493.  
  494.   fscanf(f, "\n%i\n", &n);
  495.   firstclipnode = bspMem->shared.quake1.numclipnodes;
  496.  
  497.   for (i = 0; i < n; i++) {
  498.     if (bspMem->shared.quake1.numclipnodes == bspMem->shared.quake1.max_numclipnodes)
  499.       ExpandClusters(bspMem, LUMP_CLIPNODES);
  500.     d = &bspMem->shared.quake1.dclipnodes[bspMem->shared.quake1.numclipnodes];
  501.     bspMem->shared.quake1.numclipnodes++;
  502.     if (fscanf(f, "%i : %g %g %g %g : %i %i\n", &junk, &f1, &f2, &f3, &f4, &c1, &c2) != 7)
  503.       Error("Error parsing %s", hullfilename);
  504.  
  505.     p.normal[0] = f1;
  506.     p.normal[1] = f2;
  507.     p.normal[2] = f3;
  508.     p.dist = f4;
  509.  
  510.     norm[0] = f1;
  511.     norm[1] = f2;
  512.     norm[2] = f3;                        /* vec_t precision */
  513.  
  514.     p.type = PlaneTypeForNormal(norm);
  515.  
  516.     d->children[0] = c1 >= 0 ? c1 + firstclipnode : c1;
  517.     d->children[1] = c2 >= 0 ? c2 + firstclipnode : c2;
  518.     d->planenum = FindFinalPlane(bspMem, &p);
  519.   }
  520.  
  521. }
  522.  
  523. /*
  524.  * =================
  525.  * CreateSingleHull
  526.  * 
  527.  * =================
  528.  */
  529. void CreateSingleHull(__memBase)
  530. {
  531.   int entnum;
  532.  
  533.   /* for each entity in the map file that has geometry */
  534.   for (entnum = 0; entnum < bspMem->nummapentities; entnum++)
  535.     ProcessEntity(bspMem, entnum);
  536.  
  537.   if (hullnum)
  538.     WriteClipHull(bspMem);
  539. }
  540.  
  541. /*
  542.  * =================
  543.  * CreateHulls
  544.  * 
  545.  * =================
  546.  */
  547. void CreateHulls(__memBase)
  548. {
  549.   /* commanded to create a single hull only */
  550.   if (hullnum) {
  551.     CreateSingleHull(bspMem);
  552.     exit(0);
  553.   }
  554.  
  555.   /* commanded to use the allready existing hulls 1 and 2 */
  556.   if (bspMem->bspOptions & QBSP_USEHULLS) {
  557.     CreateSingleHull(bspMem);
  558.     return;
  559.   }
  560.  
  561.   /* commanded to ignore the hulls altogether */
  562.   if (bspMem->bspOptions & QBSP_NOCLIP) {
  563.     CreateSingleHull(bspMem);
  564.     return;
  565.   }
  566.  
  567.   /* create all the hulls */
  568.  
  569.   /* create the hulls sequentially */
  570.   mprintf("    - building hulls sequentially...\n");
  571.  
  572.   hullnum = 1;
  573.   CreateSingleHull(bspMem);
  574.  
  575.   bspMem->shared.quake1.nummodels = 0;
  576.   bspMem->shared.quake1.numplanes = 0;
  577.   bspMem->shared.quake1.numclipnodes = 0;
  578.   hullnum = 2;
  579.   CreateSingleHull(bspMem);
  580.  
  581.   bspMem->shared.quake1.nummodels = 0;
  582.   bspMem->shared.quake1.numplanes = 0;
  583.   bspMem->shared.quake1.numclipnodes = 0;
  584.   hullnum = 0;
  585.   CreateSingleHull(bspMem);
  586. }
  587.  
  588. /*
  589.  * =================
  590.  * ProcessMem
  591.  * =================
  592.  */
  593. void ProcessMem(__memBase, register char *filebase)
  594. {
  595.   /* create filenames */
  596.   strcpy(bspfilename, filebase);
  597.   ReplaceExt(bspfilename, "bsp");
  598.   strcpy(hullfilename, filebase);
  599.   ReplaceExt(hullfilename, "h0");
  600.   strcpy(portfilename, filebase);
  601.   ReplaceExt(portfilename, "prt");
  602.   strcpy(pointfilename, filebase);
  603.   ReplaceExt(pointfilename, "pts");
  604.  
  605.   if (bspMem->bspOptions & QBSP_ONLYENTS)
  606.     UpdateEntLump(bspMem);
  607.   else {
  608.     if (!(bspMem->bspOptions & QBSP_USEHULLS)) {
  609.       hullfilename[strlen(hullfilename) - 1] = '1';
  610.       remove(hullfilename);
  611.       hullfilename[strlen(hullfilename) - 1] = '2';
  612.       remove(hullfilename);
  613.     }
  614.     remove(portfilename);
  615.     remove(pointfilename);
  616.  
  617.     /* the clipping hulls will be written out to text files by forked processes */
  618.     CreateHulls(bspMem);
  619.  
  620.     ReadClipHull(bspMem, 1);
  621.     ReadClipHull(bspMem, 2);
  622.  
  623.     WriteEntitiesToString(bspMem);
  624.   }
  625. }
  626.  
  627. bool qbsp(__memBase, int hullNum, int subDivide, char *filebase)
  628. {
  629.   if (hullNum) {
  630.     hullnum = hullNum;
  631.     mprintf("use hull %d\n", hullNum);
  632.   }
  633.   if (subDivide) {
  634.     subdivide_size = subDivide;
  635.     mprintf("subdivide %d\n", subDivide);
  636.   }
  637.  
  638.   ProcessMem(bspMem, filebase);
  639.   PrintMemory();
  640.  
  641.   return TRUE;
  642. }
  643.