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

  1. // map.c
  2.  
  3. #include "bsp5.h"
  4.  
  5. int            nummapbrushes;
  6. mbrush_t    mapbrushes[MAX_MAP_BRUSHES];
  7.  
  8. int            num_entities;
  9. entity_t    entities[MAX_MAP_ENTITIES];
  10.  
  11. int            nummiptex;
  12. char        miptex[MAX_MAP_TEXINFO][16];
  13.  
  14. //============================================================================
  15.  
  16. /*
  17. ===============
  18. FindMiptex
  19.  
  20. ===============
  21. */
  22. int FindMiptex (char *name)
  23. {
  24.     int        i;
  25.     
  26.     for (i=0 ; i<nummiptex ; i++)
  27.     {
  28.         if (!strcmp (name, miptex[i]))
  29.             return i;
  30.     }
  31.     if (nummiptex == MAX_MAP_TEXINFO)
  32.         Error ("nummiptex == MAX_MAP_TEXINFO");
  33.     strcpy (miptex[i], name);
  34.     nummiptex++;
  35.     return i;
  36. }
  37.  
  38. /*
  39. ===============
  40. FindTexinfo
  41.  
  42. Returns a global texinfo number
  43. ===============
  44. */
  45. int    FindTexinfo (texinfo_t *t)
  46. {
  47.     int            i, j;
  48.     texinfo_t    *tex;
  49.         
  50. // set the special flag
  51.     if (miptex[t->miptex][0] == '*' 
  52.     || !Q_strncasecmp (miptex[t->miptex], "sky",3) )
  53.         t->flags |= TEX_SPECIAL;
  54.  
  55.  
  56.     tex = texinfo;    
  57.     for (i=0 ; i<numtexinfo;i++, tex++)
  58.     {
  59.         if (t->miptex != tex->miptex)
  60.             continue;
  61.         if (t->flags != tex->flags)
  62.             continue;
  63.         
  64.         for (j=0 ; j<8 ; j++)
  65.             if (t->vecs[0][j] != tex->vecs[0][j])
  66.                 break;
  67.         if (j != 8)
  68.             continue;
  69.             
  70.         return i;
  71.     }
  72.     
  73. // allocate a new texture
  74.     if (numtexinfo == MAX_MAP_TEXINFO)
  75.         Error ("numtexinfo == MAX_MAP_TEXINFO");
  76.     texinfo[i] = *t;
  77.     numtexinfo++;
  78.  
  79.     return i;
  80. }
  81.  
  82.  
  83. //============================================================================
  84.  
  85. #define    MAXTOKEN    128
  86.  
  87. char    token[MAXTOKEN];
  88. qboolean    unget;
  89. char    *script_p;
  90. int        scriptline;
  91.  
  92. void    StartTokenParsing (char *data)
  93. {
  94.     scriptline = 1;
  95.     script_p = data;
  96.     unget = false;
  97. }
  98.  
  99. qboolean GetToken (qboolean crossline)
  100. {
  101.     char    *token_p;
  102.  
  103.     if (unget)                         // is a token allready waiting?
  104.         return true;
  105.  
  106. //
  107. // skip space
  108. //
  109. skipspace:
  110.     while (*script_p <= 32)
  111.     {
  112.         if (!*script_p)
  113.         {
  114.             if (!crossline)
  115.                 Error ("Line %i is incomplete",scriptline);
  116.             return false;
  117.         }
  118.         if (*script_p++ == '\n')
  119.         {
  120.             if (!crossline)
  121.                 Error ("Line %i is incomplete",scriptline);
  122.             scriptline++;
  123.         }
  124.     }
  125.  
  126.     if (script_p[0] == '/' && script_p[1] == '/')    // comment field
  127.     {
  128.         if (!crossline)
  129.             Error ("Line %i is incomplete\n",scriptline);
  130.         while (*script_p++ != '\n')
  131.             if (!*script_p)
  132.             {
  133.                 if (!crossline)
  134.                     Error ("Line %i is incomplete",scriptline);
  135.                 return false;
  136.             }
  137.         goto skipspace;
  138.     }
  139.  
  140. //
  141. // copy token
  142. //
  143.     token_p = token;
  144.  
  145.     if (*script_p == '"')
  146.     {
  147.         script_p++;
  148.         while ( *script_p != '"' )
  149.         {
  150.             if (!*script_p)
  151.                 Error ("EOF inside quoted token");
  152.             *token_p++ = *script_p++;
  153.             if (token_p > &token[MAXTOKEN-1])
  154.                 Error ("Token too large on line %i",scriptline);
  155.         }
  156.         script_p++;
  157.     }
  158.     else while ( *script_p > 32 )
  159.     {
  160.         *token_p++ = *script_p++;
  161.         if (token_p > &token[MAXTOKEN-1])
  162.             Error ("Token too large on line %i",scriptline);
  163.     }
  164.  
  165.     *token_p = 0;
  166.     
  167.     return true;
  168. }
  169.  
  170. void UngetToken ()
  171. {
  172.     unget = true;
  173. }
  174.  
  175.  
  176. //============================================================================
  177.  
  178. entity_t    *mapent;
  179.  
  180. /*
  181. =================
  182. ParseEpair
  183. =================
  184. */
  185. void ParseEpair (void)
  186. {
  187.     epair_t    *e;
  188.     
  189.     e = malloc (sizeof(epair_t));
  190.     memset (e, 0, sizeof(epair_t));
  191.     e->next = mapent->epairs;
  192.     mapent->epairs = e;
  193.     
  194.     if (strlen(token) >= MAX_KEY-1)
  195.         Error ("ParseEpar: token too long");
  196.     e->key = copystring(token);
  197.     GetToken (false);
  198.     if (strlen(token) >= MAX_VALUE-1)
  199.         Error ("ParseEpar: token too long");
  200.     e->value = copystring(token);
  201. }
  202.  
  203. //============================================================================
  204.  
  205.  
  206. /*
  207. ==================
  208. textureAxisFromPlane
  209. ==================
  210. */
  211. vec3_t    baseaxis[18] =
  212. {
  213. {0,0,1}, {1,0,0}, {0,-1,0},            // floor
  214. {0,0,-1}, {1,0,0}, {0,-1,0},        // ceiling
  215. {1,0,0}, {0,1,0}, {0,0,-1},            // west wall
  216. {-1,0,0}, {0,1,0}, {0,0,-1},        // east wall
  217. {0,1,0}, {1,0,0}, {0,0,-1},            // south wall
  218. {0,-1,0}, {1,0,0}, {0,0,-1}            // north wall
  219. };
  220.  
  221. void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
  222. {
  223.     int        bestaxis;
  224.     float    dot,best;
  225.     int        i;
  226.     
  227.     best = 0;
  228.     bestaxis = 0;
  229.     
  230.     for (i=0 ; i<6 ; i++)
  231.     {
  232.         dot = DotProduct (pln->normal, baseaxis[i*3]);
  233.         if (dot > best)
  234.         {
  235.             best = dot;
  236.             bestaxis = i;
  237.         }
  238.     }
  239.     
  240.     VectorCopy (baseaxis[bestaxis*3+1], xv);
  241.     VectorCopy (baseaxis[bestaxis*3+2], yv);
  242. }
  243.  
  244.  
  245. //=============================================================================
  246.  
  247.  
  248. /*
  249. =================
  250. ParseBrush
  251. =================
  252. */
  253. void ParseBrush (void)
  254. {
  255.     mbrush_t        *b;
  256.     mface_t        *f, *f2;
  257.     vec3_t        planepts[3];
  258.     vec3_t            t1, t2, t3;
  259.     int            i,j;
  260.     texinfo_t    tx;
  261.     vec_t        d;
  262.     float        shift[2], rotate, scale[2];
  263.  
  264.     b = &mapbrushes[nummapbrushes];
  265.     nummapbrushes++;
  266.     b->next = mapent->brushes;
  267.     mapent->brushes = b;
  268.         
  269.     do
  270.     {
  271.         if (!GetToken (true))
  272.             break;
  273.         if (!strcmp (token, "}") )
  274.             break;
  275.         
  276.     // read the three point plane definition
  277.         for (i=0 ; i<3 ; i++)
  278.         {
  279.             if (i != 0)
  280.                 GetToken (true);
  281.             if (strcmp (token, "(") )
  282.                 Error ("parsing brush");
  283.             
  284.             for (j=0 ; j<3 ; j++)
  285.             {
  286.                 GetToken (false);
  287.                 planepts[i][j] = atoi(token);
  288.             }
  289.             
  290.             GetToken (false);
  291.             if (strcmp (token, ")") )
  292.                 Error ("parsing brush");
  293.                 
  294.         }
  295.  
  296.     // read the texturedef
  297.         memset (&tx, 0, sizeof(tx));
  298.         GetToken (false);
  299.         tx.miptex = FindMiptex (token);
  300.         GetToken (false);
  301.         shift[0] = atoi(token);
  302.         GetToken (false);
  303.         shift[1] = atoi(token);
  304.         GetToken (false);
  305.         rotate = atoi(token);    
  306.         GetToken (false);
  307.         scale[0] = atof(token);
  308.         GetToken (false);
  309.         scale[1] = atof(token);
  310.  
  311.         // if the three points are all on a previous plane, it is a
  312.         // duplicate plane
  313.         for (f2 = b->faces ; f2 ; f2=f2->next)
  314.         {
  315.             for (i=0 ; i<3 ; i++)
  316.             {
  317.                 d = DotProduct(planepts[i],f2->plane.normal) - f2->plane.dist;
  318.                 if (d < -ON_EPSILON || d > ON_EPSILON)
  319.                     break;
  320.             }
  321.             if (i==3)
  322.                 break;
  323.         }
  324.         if (f2)        
  325.         {
  326.             printf ("WARNING: brush with duplicate plane\n");
  327.             continue;
  328.         }
  329.  
  330.         f = malloc(sizeof(mface_t));
  331.         f->next = b->faces;
  332.         b->faces = f;
  333.         
  334.     // convert to a vector / dist plane
  335.         for (j=0 ; j<3 ; j++)
  336.         {
  337.             t1[j] = planepts[0][j] - planepts[1][j];
  338.             t2[j] = planepts[2][j] - planepts[1][j];
  339.             t3[j] = planepts[1][j];
  340.         }
  341.         
  342.         CrossProduct(t1,t2, f->plane.normal);
  343.         if (VectorCompare (f->plane.normal, vec3_origin))
  344.         {
  345.             printf ("WARNING: brush plane with no normal\n");
  346.             b->faces = f->next;
  347.             free (f);
  348.             break;
  349.         }
  350.         VectorNormalize (f->plane.normal);
  351.         f->plane.dist = DotProduct (t3, f->plane.normal);
  352.  
  353.     //
  354.     // fake proper texture vectors from QuakeEd style
  355.     //
  356.         {
  357.             vec3_t    vecs[2];
  358.             int        sv, tv;
  359.             float    ang, sinv, cosv;
  360.             float    ns, nt;
  361.             
  362.             TextureAxisFromPlane(&f->plane, vecs[0], vecs[1]);
  363.         
  364.             if (!scale[0])
  365.                 scale[0] = 1;
  366.             if (!scale[1])
  367.                 scale[1] = 1;
  368.         
  369.         
  370.         // rotate axis
  371.             if (rotate == 0)
  372.                 { sinv = 0 ; cosv = 1; }
  373.             else if (rotate == 90)
  374.                 { sinv = 1 ; cosv = 0; }
  375.             else if (rotate == 180)
  376.                 { sinv = 0 ; cosv = -1; }
  377.             else if (rotate == 270)
  378.                 { sinv = -1 ; cosv = 0; }
  379.             else
  380.             {    
  381.                 ang = rotate / 180 * Q_PI;
  382.                 sinv = sin(ang);
  383.                 cosv = cos(ang);
  384.             }
  385.         
  386.             if (vecs[0][0])
  387.                 sv = 0;
  388.             else if (vecs[0][1])
  389.                 sv = 1;
  390.             else
  391.                 sv = 2;
  392.                         
  393.             if (vecs[1][0])
  394.                 tv = 0;
  395.             else if (vecs[1][1])
  396.                 tv = 1;
  397.             else
  398.                 tv = 2;
  399.                             
  400.             for (i=0 ; i<2 ; i++)
  401.             {
  402.                 ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
  403.                 nt = sinv * vecs[i][sv] +  cosv * vecs[i][tv];
  404.                 vecs[i][sv] = ns;
  405.                 vecs[i][tv] = nt;
  406.             }
  407.         
  408.             for (i=0 ; i<2 ; i++)
  409.                 for (j=0 ; j<3 ; j++)
  410.                     tx.vecs[i][j] = vecs[i][j] / scale[i];
  411.         
  412.             tx.vecs[0][3] = shift[0];
  413.             tx.vecs[1][3] = shift[1];
  414.         }
  415.     
  416.     // unique the texinfo
  417.         f->texinfo = FindTexinfo (&tx);        
  418.     } while (1);
  419. }
  420.  
  421. /*
  422. ================
  423. ParseEntity
  424. ================
  425. */
  426. qboolean    ParseEntity (void)
  427. {
  428.     if (!GetToken (true))
  429.         return false;
  430.  
  431.     if (strcmp (token, "{") )
  432.         Error ("ParseEntity: { not found");
  433.     
  434.     if (num_entities == MAX_MAP_ENTITIES)
  435.         Error ("num_entities == MAX_MAP_ENTITIES");
  436.  
  437.     mapent = &entities[num_entities];
  438.     num_entities++;
  439.     
  440.     do
  441.     {
  442.         if (!GetToken (true))
  443.             Error ("ParseEntity: EOF without closing brace");
  444.         if (!strcmp (token, "}") )
  445.             break;
  446.         if (!strcmp (token, "{") )
  447.             ParseBrush ();
  448.         else
  449.             ParseEpair ();
  450.     } while (1);
  451.     
  452.     GetVectorForKey (mapent, "origin", mapent->origin);
  453.     return true;
  454. }
  455.  
  456. /*
  457. ================
  458. LoadMapFile
  459. ================
  460. */
  461. void LoadMapFile (char *filename)
  462. {
  463.     char    *buf;
  464.         
  465.     LoadFile (filename, (void **)&buf);
  466.  
  467.     StartTokenParsing (buf);
  468.     
  469.     num_entities = 0;
  470.     
  471.     while (ParseEntity ())
  472.     {
  473.     }
  474.     
  475.     free (buf);
  476.     
  477.     qprintf ("--- LoadMapFile ---\n");
  478.     qprintf ("%s\n", filename);
  479.     qprintf ("%5i brushes\n", nummapbrushes);
  480.     qprintf ("%5i entities\n", num_entities);
  481.     qprintf ("%5i miptex\n", nummiptex);
  482.     qprintf ("%5i texinfo\n", numtexinfo);
  483. }
  484.  
  485. void PrintEntity (entity_t *ent)
  486. {
  487.     epair_t    *ep;
  488.     
  489.     for (ep=ent->epairs ; ep ; ep=ep->next)
  490.         printf ("%20s : %s\n", ep->key, ep->value);
  491. }
  492.  
  493.  
  494. char     *ValueForKey (entity_t *ent, char *key)
  495. {
  496.     epair_t    *ep;
  497.     
  498.     for (ep=ent->epairs ; ep ; ep=ep->next)
  499.         if (!strcmp (ep->key, key) )
  500.             return ep->value;
  501.     return "";
  502. }
  503.  
  504. void     SetKeyValue (entity_t *ent, char *key, char *value)
  505. {
  506.     epair_t    *ep;
  507.     
  508.     for (ep=ent->epairs ; ep ; ep=ep->next)
  509.         if (!strcmp (ep->key, key) )
  510.         {
  511.             free (ep->value);
  512.             ep->value = copystring(value);
  513.             return;
  514.         }
  515.     ep = malloc (sizeof(*ep));
  516.     ep->next = ent->epairs;
  517.     ent->epairs = ep;
  518.     ep->key = copystring(key);
  519.     ep->value = copystring(value);
  520. }
  521.  
  522. float    FloatForKey (entity_t *ent, char *key)
  523. {
  524.     char    *k;
  525.     
  526.     k = ValueForKey (ent, key);
  527.     return atof(k);
  528. }
  529.  
  530. void     GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
  531. {
  532.     char    *k;
  533.     double    v1, v2, v3;
  534.  
  535.     k = ValueForKey (ent, key);
  536.     v1 = v2 = v3 = 0;
  537. // scanf into doubles, then assign, so it is vec_t size independent
  538.     sscanf (k, "%lf %lf %lf", &v1, &v2, &v3);
  539.     vec[0] = v1;
  540.     vec[1] = v2;
  541.     vec[2] = v3;
  542. }
  543.  
  544.  
  545. void WriteEntitiesToString (void)
  546. {
  547.     char    *buf, *end;
  548.     epair_t    *ep;
  549.     char    line[128];
  550.     int        i;
  551.     
  552.     buf = dentdata;
  553.     end = buf;
  554.     *end = 0;
  555.     
  556.     for (i=0 ; i<num_entities ; i++)
  557.     {
  558.         ep = entities[i].epairs;
  559.         if (!ep)
  560.             continue;    // ent got removed
  561.         
  562.         strcat (end,"{\n");
  563.         end += 2;
  564.                 
  565.         for (ep = entities[i].epairs ; ep ; ep=ep->next)
  566.         {
  567.             sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value);
  568.             strcat (end, line);
  569.             end += strlen(line);
  570.         }
  571.         strcat (end,"}\n");
  572.         end += 2;
  573.  
  574.         if (end > buf + MAX_MAP_ENTSTRING)
  575.             Error ("Entity text too long");
  576.     }
  577.     entdatasize = end - buf + 1;
  578. }
  579.  
  580.