home *** CD-ROM | disk | FTP | other *** search
/ Doom I/II Collection / DM12.ISO / edit / doombsp / savebsp.m < prev    next >
Text File  |  1994-04-06  |  12KB  |  618 lines

  1. // savebsp.m
  2.  
  3. #import "doombsp.h"
  4.  
  5. id        secstore_i;
  6. id        mapvertexstore_i;
  7. id        subsecstore_i;
  8. id        maplinestore_i;
  9. id        nodestore_i;
  10. id        mapthingstore_i;
  11. id        ldefstore_i;
  12. id        sdefstore_i;
  13.  
  14. /*
  15. ===============================================================================
  16.  
  17.             the output functions byte swap and write lumps
  18.  
  19. ===============================================================================
  20. */
  21.  
  22.  
  23. /*
  24. ================
  25. =
  26. = WriteStorage
  27. =
  28. ================
  29. */
  30.  
  31. void WriteStorage (char *name, id store, int esize)
  32. {
  33.     int        count, len;
  34.     
  35.     count = [store count];
  36.     len = esize*count;
  37.     [wad_i addName: name data:[store elementAt:0] size:len];
  38.     printf ("%s (%i): %i\n",name,count,len);    
  39. }
  40.  
  41.  
  42. /*
  43. =================
  44. =
  45. = OutputSectors
  46. =
  47. =================
  48. */
  49.  
  50. void OutputSectors (void)
  51. {
  52.     int        i, count;
  53.     mapsector_t        *p;
  54.  
  55.     count = [secstore_i count];
  56.     p = [secstore_i elementAt:0];
  57.     for (i=0 ; i<count ; i++, p++)
  58.     {
  59.         p->floorheight = SHORT(p->floorheight);
  60.         p->ceilingheight = SHORT(p->ceilingheight);
  61.         p->lightlevel = SHORT(p->lightlevel);
  62.         p->special = SHORT(p->special);
  63.         p->tag = SHORT(p->tag);
  64.     }    
  65.     WriteStorage ("sectors", secstore_i, sizeof(mapsector_t));
  66. }
  67.  
  68.  
  69. /*
  70. =================
  71. =
  72. = OutputSegs
  73. =
  74. =================
  75. */
  76.  
  77. void OutputSegs (void)
  78. {
  79.     int        i, count;
  80.     mapseg_t        *p;
  81.  
  82.     count = [maplinestore_i count];
  83.     p = [maplinestore_i elementAt:0];
  84.     for (i=0 ; i<count ; i++, p++)
  85.     {
  86.         p->v1 = SHORT(p->v1);
  87.         p->v2 = SHORT(p->v2);
  88.         p->angle = SHORT(p->angle);
  89.         p->linedef = SHORT(p->linedef);
  90.         p->side = SHORT(p->side);
  91.         p->offset = SHORT(p->offset);
  92.     }    
  93.     WriteStorage ("segs",maplinestore_i, sizeof(mapseg_t));
  94. }
  95.  
  96.  
  97. /*
  98. =================
  99. =
  100. = OutputSubsectors
  101. =
  102. =================
  103. */
  104.  
  105. void OutputSubsectors (void)
  106. {
  107.     int        i, count;
  108.     mapsubsector_t        *p;
  109.  
  110.     count = [subsecstore_i count];
  111.     p = [subsecstore_i elementAt:0];
  112.     for (i=0 ; i<count ; i++, p++)
  113.     {
  114.         p->numsegs = SHORT(p->numsegs);
  115.         p->firstseg = SHORT(p->firstseg);
  116.     }    
  117.     WriteStorage ("ssectors", subsecstore_i, sizeof(mapsubsector_t));
  118. }
  119.  
  120.  
  121. /*
  122. =================
  123. =
  124. = OutputVertexes
  125. =
  126. =================
  127. */
  128.  
  129. void OutputVertexes (void)
  130. {
  131.     int        i, count;
  132.     mapvertex_t        *p;
  133.  
  134.     count = [mapvertexstore_i count];
  135.     p = [mapvertexstore_i elementAt:0];
  136.     for (i=0 ; i<count ; i++, p++)
  137.     {
  138.         p->x = SHORT(p->x);
  139.         p->y = SHORT(p->y);
  140.     }    
  141.     WriteStorage ("vertexes",mapvertexstore_i, sizeof(mapvertex_t));
  142. }
  143.  
  144.  
  145. /*
  146. =================
  147. =
  148. = OutputThings
  149. =
  150. =================
  151. */
  152.  
  153. void OutputThings (void)
  154. {
  155.     int        i, count;
  156.     mapthing_t        *p;
  157.  
  158.     count = [mapthingstore_i count];
  159.     p = [mapthingstore_i elementAt:0];
  160.     for (i=0 ; i<count ; i++, p++)
  161.     {
  162.         p->x = SHORT(p->x);
  163.         p->y = SHORT(p->y);
  164.         p->angle = SHORT(p->angle);
  165.         p->type = SHORT(p->type);
  166.         p->options = SHORT(p->options);
  167.     }    
  168.     WriteStorage ("things", mapthingstore_i, sizeof(mapthing_t));
  169. }
  170.  
  171.  
  172. /*
  173. =================
  174. =
  175. = OutputLineDefs
  176. =
  177. =================
  178. */
  179.  
  180. void OutputLineDefs (void)
  181. {
  182.     int        i, count;
  183.     maplinedef_t        *p;
  184.  
  185.     count = [ldefstore_i count];
  186.     p = [ldefstore_i elementAt:0];
  187.     for (i=0 ; i<count ; i++, p++)
  188.     {
  189.         p->v1 = SHORT(p->v1);
  190.         p->v2 = SHORT(p->v2);
  191. // some ancient version of DoomEd left ML_MAPPED flags in some of the levels
  192.         p->flags = SHORT(p->flags&~ML_MAPPED);
  193.         p->special = SHORT(p->special);
  194.         p->tag = SHORT(p->tag);
  195.         p->sidenum[0] = SHORT(p->sidenum[0]);
  196.         p->sidenum[1] = SHORT(p->sidenum[1]);
  197.     }    
  198.     WriteStorage ("linedefs", ldefstore_i, sizeof(maplinedef_t));
  199. }
  200.  
  201.  
  202. /*
  203. =================
  204. =
  205. = OutputSideDefs
  206. =
  207. =================
  208. */
  209.  
  210. void OutputSideDefs (void)
  211. {
  212.     int        i, count;
  213.     mapsidedef_t        *p;
  214.  
  215.     count = [sdefstore_i count];
  216.     p = [sdefstore_i elementAt:0];
  217.     for (i=0 ; i<count ; i++, p++)
  218.     {
  219.         p->textureoffset = SHORT(p->textureoffset);
  220.         p->rowoffset = SHORT(p->rowoffset);
  221.         p->sector = SHORT(p->sector);
  222.     }    
  223.     WriteStorage ("sidedefs", sdefstore_i, sizeof(mapsidedef_t));
  224. }
  225.  
  226.  
  227. /*
  228. =================
  229. =
  230. = OutputNodes
  231. =
  232. =================
  233. */
  234.  
  235. void OutputNodes (void)
  236. {
  237.     int        i, j, count;
  238.     mapnode_t        *p;
  239.  
  240.     count = [nodestore_i count];
  241.     p = [nodestore_i elementAt:0];
  242.     for (i=0 ; i<count ; i++, p++)
  243.     {
  244.         for (j=0 ; j<sizeof(mapnode_t)/2 ; j++)
  245.             ((short *)p)[j] = SHORT(((short *)p)[j]);
  246.     }    
  247.     WriteStorage ("nodes", nodestore_i, sizeof(mapnode_t));
  248. }
  249.  
  250.  
  251. /*
  252. ===============================================================================
  253.  
  254.                             PROCESSING
  255.  
  256. ===============================================================================
  257. */
  258.  
  259.  
  260. /*
  261. =================
  262. =
  263. = UniqueVertex
  264. =
  265. = Returns the vertex number, adding a new vertex if needed 
  266. =================
  267. */
  268.  
  269. int UniqueVertex (int x, int y)
  270. {
  271.     int                i, count;
  272.     mapvertex_t        mv, *mvp;
  273.     
  274.     mv.x = x;
  275.     mv.y = y;
  276.     
  277. // see if an identical vertex already exists
  278.     count = [mapvertexstore_i count];
  279.     mvp = [mapvertexstore_i elementAt:0];
  280.     for (i=0 ; i<count ; i++, mvp++)
  281.         if (mvp->x == mv.x && mvp->y == mv.y)
  282.             return i;
  283.  
  284.     [mapvertexstore_i addElement: &mv];
  285.     
  286.     return count;    
  287. }
  288.  
  289.  
  290. //=============================================================================
  291.  
  292.  
  293. float    bbox[4];
  294.  
  295. /*
  296. =================
  297. =
  298. = AddPointToBBox
  299. =
  300. =================
  301. */
  302.  
  303. void AddPointToBBox (NXPoint *pt)
  304. {
  305.     if (pt->x < bbox[BOXLEFT])
  306.         bbox[BOXLEFT] = pt->x;
  307.     if (pt->x > bbox[BOXRIGHT])
  308.         bbox[BOXRIGHT] = pt->x;
  309.         
  310.     if (pt->y > bbox[BOXTOP])
  311.         bbox[BOXTOP] = pt->y;
  312.     if (pt->y < bbox[BOXBOTTOM])
  313.         bbox[BOXBOTTOM] = pt->y;
  314. }
  315.  
  316.  
  317. /*
  318. =================
  319. =
  320. = ProcessLines
  321. =
  322. = Adds the lines in a subsector to the mapline storage
  323. =================
  324. */
  325.  
  326. void ProcessLines (id store_i)
  327. {
  328.     int            i,count;
  329.     line_t         *wline;
  330.     mapseg_t    line;
  331.     short        angle;
  332.     float        fangle;
  333.     
  334.     bbox[BOXLEFT] = MAXINT;
  335.     bbox[BOXRIGHT] = MININT;
  336.     bbox[BOXTOP] = MININT;
  337.     bbox[BOXBOTTOM] = MAXINT;
  338.     
  339.     count = [store_i count];
  340.     for (i=0 ; i<count ; i++)
  341.     {
  342.         wline = [store_i elementAt: i];
  343.         if (wline->grouped)
  344.             printf ("ERROR: line regrouped\n");
  345.         wline->grouped = true;
  346.         
  347.         memset (&line, 0, sizeof(line));
  348.         AddPointToBBox (&wline->p1);
  349.         AddPointToBBox (&wline->p2);
  350.         line.v1 = UniqueVertex (wline->p1.x, wline->p1.y);
  351.         line.v2 = UniqueVertex (wline->p2.x, wline->p2.y);
  352.         line.linedef = wline->linedef;
  353.         line.side = wline->side;
  354.         line.offset = wline->offset;
  355.         fangle = atan2 (wline->p2.y - wline->p1.y, wline->p2.x - wline->p1.x);
  356.         angle = (short)(fangle/(PI*2)*0x10000);
  357.         line.angle = angle;
  358.         [maplinestore_i addElement: &line];
  359.     }
  360. }
  361.  
  362.  
  363. /*
  364. =================
  365. =
  366. = ProcessSubsector
  367. =
  368. =================
  369. */
  370.  
  371. int ProcessSubsector (id wmaplinestore_i)
  372. {
  373.     int                count;
  374.     worldline_t        *linedef;
  375.     line_t            *wline;
  376.     mapsubsector_t    sub;
  377.     
  378.     memset (&sub,0,sizeof(sub));
  379.     
  380.     count = [wmaplinestore_i count];
  381.     if (count < 1)
  382.         Error ("ProcessSubsector: count = %i",count);
  383.         
  384.     wline = [wmaplinestore_i elementAt: 0];
  385.     
  386.     linedef = [linestore_i elementAt: wline->linedef];
  387.     sub.numsegs = count;
  388.     sub.firstseg = [maplinestore_i count];
  389.     ProcessLines (wmaplinestore_i);
  390.     
  391. // add the new subsector
  392.     [subsecstore_i addElement: &sub];
  393.     
  394.     return [subsecstore_i count]-1;
  395. }
  396.  
  397. /*
  398. =================
  399. =
  400. = ProcessNode
  401. =
  402. =================
  403. */
  404.  
  405. int ProcessNode (bspnode_t *node, short *totalbox)
  406. {
  407.     short        subbox[2][4];
  408.     int            i, r;
  409.     mapnode_t    mnode;
  410.     
  411.     memset (&mnode,0,sizeof(mnode));
  412.  
  413.     if (node->lines_i)    // NF_SUBSECTOR flags a subsector
  414.     {
  415.         r = ProcessSubsector (node->lines_i);
  416.         for (i=0 ; i<4 ; i++)
  417.             totalbox[i] = bbox[i];
  418.         return r | NF_SUBSECTOR;
  419.     }
  420.     
  421.     mnode.x =node->divline.pt.x;
  422.     mnode.y =node->divline.pt.y;
  423.     mnode.dx =node->divline.dx;
  424.     mnode.dy =node->divline.dy;
  425.     
  426.     r = ProcessNode(node->side[0], subbox[0]);
  427.     mnode.children[0] =r;
  428.     for (i=0 ; i<4 ; i++)
  429.         mnode.bbox[0][i] =subbox[0][i];
  430.     
  431.     r = ProcessNode (node->side[1],subbox[1]);
  432.     mnode.children[1] =r;
  433.     for (i=0 ; i<4 ; i++)
  434.         mnode.bbox[1][i] =subbox[1][i];
  435.  
  436.     totalbox[BOXLEFT] = MIN(subbox[0][BOXLEFT], subbox[1][BOXLEFT]);
  437.     totalbox[BOXTOP] = MAX(subbox[0][BOXTOP], subbox[1][BOXTOP]);
  438.     totalbox[BOXRIGHT] = MAX(subbox[0][BOXRIGHT], subbox[1][BOXRIGHT]);
  439.     totalbox[BOXBOTTOM] = MIN(subbox[0][BOXBOTTOM], subbox[1][BOXBOTTOM]);
  440.     
  441.     [nodestore_i addElement: &mnode];
  442.     return [nodestore_i count] - 1;    
  443. }
  444.  
  445.  
  446. /*
  447. =================
  448. =
  449. = ProcessNodes
  450. =
  451. = Recursively builds the nodes, subsectors, and line lists,
  452. = then writes the lumps
  453. =================
  454. */
  455.  
  456. void ProcessNodes (void)
  457. {
  458.     short    worldbounds[4];
  459.     
  460.     subsecstore_i = [[Storage alloc]
  461.         initCount:        0
  462.         elementSize:    sizeof(mapsubsector_t)
  463.         description:    NULL];
  464.     maplinestore_i = [[Storage alloc]
  465.         initCount:        0
  466.         elementSize:    sizeof(mapseg_t)
  467.         description:    NULL];
  468.     nodestore_i = [[Storage alloc]
  469.         initCount:        0
  470.         elementSize:    sizeof(mapnode_t)
  471.         description:    NULL];
  472.  
  473.     ProcessNode (startnode, worldbounds);
  474.  
  475. }
  476.  
  477.  
  478. /*
  479. =================
  480. =
  481. = ProcessThings
  482. =
  483. =================
  484. */
  485.  
  486. void ProcessThings (void)
  487. {
  488.     worldthing_t    *wt;
  489.     mapthing_t        mt;
  490.     int                count;
  491.     
  492.     mapthingstore_i = [[Storage alloc]
  493.         initCount:        0
  494.         elementSize:    sizeof(mapthing_t)
  495.         description:    NULL];
  496.  
  497.     count = [thingstore_i count];
  498.     wt = [thingstore_i elementAt: 0];
  499.  
  500.     while (count--)
  501.     {     
  502.         memset (&mt,0,sizeof(mt));
  503.         mt.x =wt->origin.x;
  504.         mt.y =wt->origin.y;
  505.         mt.angle =wt->angle;
  506.         mt.type =wt->type;
  507.         mt.options =wt->options;
  508.         [mapthingstore_i addElement: &mt];
  509.         wt++;
  510.     }
  511.     
  512. }
  513.  
  514. //=============================================================================
  515.  
  516.  
  517. /*
  518. ==================
  519. =
  520. = ProcessSidedef
  521. =
  522. ==================
  523. */
  524.  
  525. int ProcessSidedef (worldside_t *ws)
  526. {
  527.     mapsidedef_t    ms;
  528.     
  529.     ms.textureoffset = ws->firstcollumn;
  530.     ms.rowoffset = ws->firstrow;
  531.     memcpy (ms.toptexture, ws->toptexture, 8);
  532.     memcpy (ms.bottomtexture, ws->bottomtexture, 8);
  533.     memcpy (ms.midtexture, ws->midtexture, 8);
  534.     ms.sector = ws->sector;
  535.     
  536.     [sdefstore_i addElement: &ms];
  537.     return [sdefstore_i count]-1;
  538. }
  539.  
  540. /*
  541. ==================
  542. =
  543. = ProcessLineSideDefs
  544. =
  545. = Must be called after BuildSectors
  546. ==================
  547. */
  548.  
  549. void ProcessLineSideDefs (void)
  550. {
  551.     int                i, count;
  552.     maplinedef_t    ld;
  553.     worldline_t        *wl;
  554.     
  555.     mapvertexstore_i = [[Storage alloc]
  556.         initCount:        0
  557.         elementSize:    sizeof(mapvertex_t)
  558.         description:    NULL];
  559.     ldefstore_i = [[Storage alloc]
  560.         initCount:        0
  561.         elementSize:    sizeof(maplinedef_t)
  562.         description:    NULL];
  563.     sdefstore_i = [[Storage alloc]
  564.         initCount:        0
  565.         elementSize:    sizeof(mapsidedef_t)
  566.         description:    NULL];
  567.  
  568.     count = [linestore_i count];
  569.     wl = [linestore_i elementAt:0];
  570.     for (i=0 ; i<count ; i++, wl++)
  571.     {
  572.         ld.v1 = UniqueVertex(wl->p1.x,wl->p1.y);
  573.         ld.v2 =UniqueVertex(wl->p2.x,wl->p2.y);
  574.         ld.flags =wl->flags;
  575.         ld.special =wl->special;
  576.         ld.tag =wl->tag;
  577.         ld.sidenum[0] =ProcessSidedef(&wl->side[0]);
  578.         if (wl->flags & ML_TWOSIDED)
  579.             ld.sidenum[1] =ProcessSidedef(&wl->side[1]);
  580.         else
  581.             ld.sidenum[1] =-1;
  582.         [ldefstore_i addElement: &ld];
  583.     }
  584.     
  585. }
  586.  
  587. //=============================================================================
  588.  
  589. /*
  590. ==================
  591. =
  592. = SaveDoomMap
  593. =
  594. ==================
  595. */
  596.  
  597. void SaveDoomMap (void)
  598. {
  599.     BuildSectordefs ();
  600.     ProcessThings ();
  601.     ProcessLineSideDefs ();
  602.     ProcessNodes ();
  603.     ProcessSectors ();
  604.     ProcessConnections ();
  605.     
  606. // all processing is complete, write everything out
  607.     OutputThings ();
  608.     OutputLineDefs ();
  609.     OutputSideDefs ();
  610.     OutputVertexes ();
  611.     OutputSegs ();
  612.     OutputSubsectors ();
  613.     OutputNodes ();
  614.     OutputSectors ();
  615.     OutputConnections ();
  616. }
  617.  
  618.