home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 December / PCWKCD1296.iso / sharewar / quake106 / utils / qbsp / writebsp.c < prev   
C/C++ Source or Header  |  1996-09-12  |  10KB  |  524 lines

  1.  
  2. #include "bsp5.h"
  3.  
  4.  
  5. int        headclipnode;
  6. int        firstface;
  7.  
  8. //===========================================================================
  9.  
  10. /*
  11. ==================
  12. FindFinalPlane
  13.  
  14. Used to find plane index numbers for clip nodes read from child processes
  15. ==================
  16. */
  17. int FindFinalPlane (dplane_t *p)
  18. {
  19.     int        i;
  20.     dplane_t    *dplane;
  21.     
  22.     for (i=0, dplane = dplanes ; i<numplanes ; i++, dplane++)
  23.     {
  24.         if (p->type != dplane->type)
  25.             continue;
  26.         if (p->dist != dplane->dist)
  27.             continue;
  28.         if (p->normal[0] != dplane->normal[0])
  29.             continue;
  30.         if (p->normal[1] != dplane->normal[1])
  31.             continue;
  32.         if (p->normal[2] != dplane->normal[2])
  33.             continue;
  34.         return i;
  35.     }
  36.     
  37. //
  38. // new plane
  39. //
  40.     if (numplanes == MAX_MAP_PLANES)
  41.         Error ("numplanes == MAX_MAP_PLANES");
  42.     dplane = &dplanes[numplanes];
  43.     *dplane = *p;
  44.     numplanes++;
  45.     
  46.     return numplanes - 1;
  47. }
  48.  
  49.  
  50.  
  51. int        planemapping[MAX_MAP_PLANES];
  52.  
  53. void WriteNodePlanes_r (node_t *node)
  54. {
  55.     plane_t        *plane;
  56.     dplane_t    *dplane;
  57.  
  58.     if (node->planenum == -1)
  59.         return;
  60.     if (planemapping[node->planenum] == -1)
  61.     {    // a new plane
  62.         planemapping[node->planenum] = numplanes;
  63.         
  64.         if (numplanes == MAX_MAP_PLANES)
  65.             Error ("numplanes == MAX_MAP_PLANES");
  66.         plane = &planes[node->planenum];
  67.         dplane = &dplanes[numplanes];
  68.         dplane->normal[0] = plane->normal[0];
  69.         dplane->normal[1] = plane->normal[1];
  70.         dplane->normal[2] = plane->normal[2];
  71.         dplane->dist = plane->dist;
  72.         dplane->type = plane->type;
  73.  
  74.         numplanes++;
  75.     }
  76.  
  77.     node->outputplanenum = planemapping[node->planenum];
  78.     
  79.     WriteNodePlanes_r (node->children[0]);
  80.     WriteNodePlanes_r (node->children[1]);
  81. }
  82.  
  83. /*
  84. ==================
  85. WriteNodePlanes
  86.  
  87. ==================
  88. */
  89. void WriteNodePlanes (node_t *nodes)
  90. {
  91.     memset (planemapping,-1, sizeof(planemapping));
  92.     WriteNodePlanes_r (nodes);
  93. }
  94.  
  95. //===========================================================================
  96.  
  97. /*
  98. ==================
  99. WriteClipNodes_r
  100.  
  101. ==================
  102. */
  103. int WriteClipNodes_r (node_t *node)
  104. {
  105.     int            i, c;
  106.     dclipnode_t    *cn;
  107.     int            num;
  108.     
  109. // FIXME: free more stuff?    
  110.     if (node->planenum == -1)
  111.     {
  112.         num = node->contents;
  113.         free (node);
  114.         return num;
  115.     }
  116.     
  117. // emit a clipnode
  118.     c = numclipnodes;
  119.     cn = &dclipnodes[numclipnodes];
  120.     numclipnodes++;
  121.     cn->planenum = node->outputplanenum;
  122.     for (i=0 ; i<2 ; i++)
  123.         cn->children[i] = WriteClipNodes_r(node->children[i]);
  124.     
  125.     free (node);
  126.     return c;
  127. }
  128.  
  129. /*
  130. ==================
  131. WriteClipNodes
  132.  
  133. Called after the clipping hull is completed.  Generates a disk format
  134. representation and frees the original memory.
  135. ==================
  136. */
  137. void WriteClipNodes (node_t *nodes)
  138. {
  139.     headclipnode = numclipnodes;
  140.     WriteClipNodes_r (nodes);
  141. }
  142.  
  143. //===========================================================================
  144.  
  145. /*
  146. ==================
  147. WriteLeaf
  148. ==================
  149. */
  150. void WriteLeaf (node_t *node)
  151. {
  152.     face_t        **fp, *f;
  153.     dleaf_t        *leaf_p;
  154.         
  155. // emit a leaf
  156.     leaf_p = &dleafs[numleafs];
  157.     numleafs++;
  158.  
  159.     leaf_p->contents = node->contents;
  160.  
  161. //
  162. // write bounding box info
  163. //    
  164.     VectorCopy (node->mins, leaf_p->mins);
  165.     VectorCopy (node->maxs, leaf_p->maxs);
  166.     
  167.     leaf_p->visofs = -1;    // no vis info yet
  168.     
  169. //
  170. // write the marksurfaces
  171. //
  172.     leaf_p->firstmarksurface = nummarksurfaces;
  173.     
  174.     for (fp=node->markfaces ; *fp ; fp++)
  175.     {
  176.     // emit a marksurface
  177.         if (nummarksurfaces == MAX_MAP_MARKSURFACES)
  178.             Error ("nummarksurfaces == MAX_MAP_MARKSURFACES");
  179.         f = *fp;
  180.         do
  181.         {
  182.             dmarksurfaces[nummarksurfaces] =  f->outputnumber;
  183.             nummarksurfaces++;
  184.             f=f->original;        // grab tjunction split faces
  185.         } while (f);
  186.     }
  187.     
  188.     leaf_p->nummarksurfaces = nummarksurfaces - leaf_p->firstmarksurface;
  189. }
  190.  
  191.  
  192. /*
  193. ==================
  194. WriteDrawNodes_r
  195. ==================
  196. */
  197. void WriteDrawNodes_r (node_t *node)
  198. {
  199.     dnode_t    *n;
  200.     int        i;
  201.  
  202. // emit a node    
  203.     if (numnodes == MAX_MAP_NODES)
  204.         Error ("numnodes == MAX_MAP_NODES");
  205.     n = &dnodes[numnodes];
  206.     numnodes++;
  207.  
  208.     VectorCopy (node->mins, n->mins);
  209.     VectorCopy (node->maxs, n->maxs);
  210.  
  211.     n->planenum = node->outputplanenum;
  212.     n->firstface = node->firstface;
  213.     n->numfaces = node->numfaces;
  214.  
  215. //
  216. // recursively output the other nodes
  217. //    
  218.     
  219.     for (i=0 ; i<2 ; i++)
  220.     {
  221.         if (node->children[i]->planenum == -1)
  222.         {
  223.             if (node->children[i]->contents == CONTENTS_SOLID)
  224.                 n->children[i] = -1;
  225.             else
  226.             {
  227.                 n->children[i] = -(numleafs + 1);
  228.                 WriteLeaf (node->children[i]);
  229.             }
  230.         }
  231.         else
  232.         {
  233.             n->children[i] = numnodes;    
  234.             WriteDrawNodes_r (node->children[i]);
  235.         }
  236.     }
  237. }
  238.  
  239. /*
  240. ==================
  241. WriteDrawNodes
  242. ==================
  243. */
  244. void WriteDrawNodes (node_t *headnode)
  245. {
  246.     int        i;
  247.     int        start;
  248.     dmodel_t    *bm;
  249.  
  250. #if 0
  251.     if (headnode->contents < 0)
  252.         Error ("FinishBSPModel: empty model");
  253. #endif
  254.  
  255. // emit a model
  256.     if (nummodels == MAX_MAP_MODELS)
  257.         Error ("nummodels == MAX_MAP_MODELS");
  258.     bm = &dmodels[nummodels];
  259.     nummodels++;
  260.     
  261.     bm->headnode[0] = numnodes;
  262.     bm->firstface = firstface;
  263.     bm->numfaces = numfaces - firstface;    
  264.     firstface = numfaces;
  265.     
  266.     start = numleafs;
  267.  
  268.     if (headnode->contents < 0)    
  269.         WriteLeaf (headnode);
  270.     else
  271.         WriteDrawNodes_r (headnode);
  272.     bm->visleafs = numleafs - start;
  273.     
  274.     for (i=0 ; i<3 ; i++)
  275.     {
  276.         bm->mins[i] = headnode->mins[i] + SIDESPACE + 1;    // remove the padding
  277.         bm->maxs[i] = headnode->maxs[i] - SIDESPACE - 1;
  278.     }
  279. // FIXME: are all the children decendant of padded nodes?
  280. }
  281.  
  282.  
  283. /*
  284. ==================
  285. BumpModel
  286.  
  287. Used by the clipping hull processes that only need to store headclipnode
  288. ==================
  289. */
  290. void BumpModel (int hullnum)
  291. {
  292.     dmodel_t    *bm;
  293.  
  294. // emit a model
  295.     if (nummodels == MAX_MAP_MODELS)
  296.         Error ("nummodels == MAX_MAP_MODELS");
  297.     bm = &dmodels[nummodels];
  298.     nummodels++;
  299.     
  300.     bm->headnode[hullnum] = headclipnode;
  301. }
  302.  
  303. //=============================================================================
  304.  
  305. typedef struct
  306. {
  307.     char        identification[4];        // should be WAD2
  308.     int            numlumps;
  309.     int            infotableofs;
  310. } wadinfo_t;
  311.  
  312.  
  313. typedef struct
  314. {
  315.     int            filepos;
  316.     int            disksize;
  317.     int            size;                    // uncompressed
  318.     char        type;
  319.     char        compression;
  320.     char        pad1, pad2;
  321.     char        name[16];                // must be null terminated
  322. } lumpinfo_t;
  323.  
  324. FILE        *texfile;
  325. wadinfo_t    wadinfo;
  326. lumpinfo_t    *lumpinfo;
  327.  
  328. void CleanupName (char *in, char *out)
  329. {
  330.     int        i;
  331.     
  332.     for (i=0 ; i< 16 ; i++ )
  333.     {
  334.         if (!in[i])
  335.             break;
  336.             
  337.         out[i] = toupper(in[i]);
  338.     }
  339.     
  340.     for ( ; i< 16 ; i++ )
  341.         out[i] = 0;
  342. }
  343.  
  344.  
  345. /*
  346. =================
  347. TEX_InitFromWad
  348. =================
  349. */
  350. void    TEX_InitFromWad (char *path)
  351. {
  352.     int            i;
  353.     
  354.     texfile = SafeOpenRead (path);
  355.     SafeRead (texfile, &wadinfo, sizeof(wadinfo));
  356.     if (strncmp (wadinfo.identification, "WAD2", 4))
  357.         Error ("TEX_InitFromWad: %s isn't a wadfile",path);
  358.     wadinfo.numlumps = LittleLong(wadinfo.numlumps);
  359.     wadinfo.infotableofs = LittleLong(wadinfo.infotableofs);
  360.     fseek (texfile, wadinfo.infotableofs, SEEK_SET);
  361.     lumpinfo = malloc(wadinfo.numlumps*sizeof(lumpinfo_t));
  362.     SafeRead (texfile, lumpinfo, wadinfo.numlumps*sizeof(lumpinfo_t));
  363.     
  364.     for (i=0 ; i<wadinfo.numlumps ; i++)
  365.     {
  366.         CleanupName (lumpinfo[i].name, lumpinfo[i].name);
  367.         lumpinfo[i].filepos = LittleLong(lumpinfo[i].filepos);
  368.         lumpinfo[i].disksize = LittleLong(lumpinfo[i].disksize);
  369.     }
  370. }
  371.  
  372. /*
  373. ==================
  374. LoadLump
  375. ==================
  376. */
  377. int LoadLump (char *name, byte *dest)
  378. {
  379.     int        i;
  380.     char    cname[16];
  381.     
  382.     CleanupName (name, cname);
  383.     
  384.     for (i=0 ; i<wadinfo.numlumps ; i++)
  385.     {
  386.         if (!strcmp(cname, lumpinfo[i].name))
  387.         {
  388.             fseek (texfile, lumpinfo[i].filepos, SEEK_SET);
  389.             SafeRead (texfile, dest, lumpinfo[i].disksize);
  390.             return lumpinfo[i].disksize;
  391.         }
  392.     }
  393.     
  394.     printf ("WARNING: texture %s not found\n", name);
  395.     return 0;
  396. }
  397.  
  398.  
  399. /*
  400. ==================
  401. AddAnimatingTextures
  402. ==================
  403. */
  404. void AddAnimatingTextures (void)
  405. {
  406.     int        base;
  407.     int        i, j, k;
  408.     char    name[32];
  409.  
  410.     base = nummiptex;
  411.     
  412.     for (i=0 ; i<base ; i++)
  413.     {
  414.         if (miptex[i][0] != '+')
  415.             continue;
  416.         strcpy (name, miptex[i]);
  417.  
  418.         for (j=0 ; j<20 ; j++)
  419.         {
  420.             if (j < 10)
  421.                 name[1] = '0'+j;
  422.             else
  423.                 name[1] = 'A'+j-10;        // alternate animation
  424.             
  425.  
  426.         // see if this name exists in the wadfile
  427.             for (k=0 ; k<wadinfo.numlumps ; k++)
  428.                 if (!strcmp(name, lumpinfo[k].name))
  429.                 {
  430.                     FindMiptex (name);    // add to the miptex list
  431.                     break;
  432.                 }
  433.         }
  434.     }
  435.     
  436.     printf ("added %i texture frames\n", nummiptex - base);
  437. }
  438.  
  439. /*
  440. ==================
  441. WriteMiptex
  442. ==================
  443. */
  444. void WriteMiptex (void)
  445. {
  446.     int        i, len;
  447.     byte    *data;
  448.     dmiptexlump_t    *l;
  449.     char    *path;
  450.     char    fullpath[1024];
  451.  
  452.     path = ValueForKey (&entities[0], "_wad");
  453.     if (!path || !path[0])
  454.     {
  455.         path = ValueForKey (&entities[0], "wad");
  456.         if (!path || !path[0])
  457.         {
  458.             printf ("WARNING: no wadfile specified\n");
  459.             texdatasize = 0;
  460.             return;
  461.         }
  462.     }
  463.     
  464.     sprintf (fullpath, "%s/%s", gamedir, path);
  465.  
  466.     TEX_InitFromWad (fullpath);
  467.     
  468.     AddAnimatingTextures ();
  469.  
  470.     l = (dmiptexlump_t *)dtexdata;
  471.     data = (byte *)&l->dataofs[nummiptex];
  472.     l->nummiptex = nummiptex;
  473.     for (i=0 ; i<nummiptex ; i++)
  474.     {
  475.         l->dataofs[i] = data - (byte *)l;
  476.         len = LoadLump (miptex[i], data);
  477.         if (data + len - dtexdata >= MAX_MAP_MIPTEX)
  478.             Error ("Textures exceeded MAX_MAP_MIPTEX");
  479.         if (!len)
  480.             l->dataofs[i] = -1;    // didn't find the texture
  481.         data += len;
  482.     }
  483.  
  484.     texdatasize = data - dtexdata;
  485. }
  486.  
  487. //===========================================================================
  488.  
  489.  
  490. /*
  491. ==================
  492. BeginBSPFile
  493. ==================
  494. */
  495. void BeginBSPFile (void)
  496. {
  497. // edge 0 is not used, because 0 can't be negated
  498.     numedges = 1;
  499.  
  500. // leaf 0 is common solid with no faces
  501.     numleafs = 1;
  502.     dleafs[0].contents = CONTENTS_SOLID;
  503.  
  504.     firstface = 0;    
  505. }
  506.  
  507.  
  508. /*
  509. ==================
  510. FinishBSPFile
  511. ==================
  512. */
  513. void FinishBSPFile (void)
  514. {
  515.     printf ("--- FinishBSPFile ---\n");
  516.     printf ("WriteBSPFile: %s\n", bspfilename);
  517.     
  518.     WriteMiptex ();
  519.  
  520.     PrintBSPFileSizes ();
  521.     WriteBSPFile (bspfilename);
  522. }
  523.  
  524.