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