home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 58 / pcpp58a.iso / extras / quake 3 source / Q3A_ToolSource.exe / Main / Brush.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-02  |  107.3 KB  |  4,489 lines

  1.  
  2.  
  3. #include "stdafx.h"
  4. #include <assert.h>
  5. #include "qe3.h"
  6. #include "winding.h"
  7.  
  8.  
  9. // globals
  10.  
  11. int g_nBrushId = 0;
  12.  
  13. const char* Brush_Name(brush_t *b)
  14. {
  15.   static char cBuff[1024];
  16.     b->numberId = g_nBrushId++;
  17.     if (g_qeglobals.m_bBrushPrimitMode)
  18.   {
  19.     sprintf(cBuff, "Brush %i", b->numberId);
  20.     Brush_SetEpair(b, "Name", cBuff);
  21.   }
  22.   return cBuff;
  23. }
  24.  
  25. brush_t *Brush_Alloc()
  26. {
  27.   brush_t *b = (brush_t*)qmalloc(sizeof(brush_t));
  28.   return b;
  29. }
  30.  
  31.  
  32.  
  33.  
  34. void PrintWinding (winding_t *w)
  35. {
  36.     int        i;
  37.     
  38.     printf ("-------------\n");
  39.     for (i=0 ; i<w->numpoints ; i++)
  40.         printf ("(%5.2f, %5.2f, %5.2f)\n", w->points[i][0]
  41.         , w->points[i][1], w->points[i][2]);
  42. }
  43.  
  44. void PrintPlane (plane_t *p)
  45. {
  46.   printf ("(%5.2f, %5.2f, %5.2f) : %5.2f\n",  p->normal[0],  p->normal[1], 
  47.   p->normal[2],  p->dist);
  48. }
  49.  
  50. void PrintVector (vec3_t v)
  51. {
  52.   printf ("(%5.2f, %5.2f, %5.2f)\n",  v[0],  v[1], v[2]);
  53. }
  54.  
  55.  
  56. /*
  57. =============================================================================
  58.  
  59.             TEXTURE COORDINATES
  60.  
  61. =============================================================================
  62. */
  63.  
  64.  
  65. /*
  66. ==================
  67. textureAxisFromPlane
  68. ==================
  69. */
  70. vec3_t    baseaxis[18] =
  71. {
  72. {0,0,1}, {1,0,0}, {0,-1,0},            // floor
  73. {0,0,-1}, {1,0,0}, {0,-1,0},        // ceiling
  74. {1,0,0}, {0,1,0}, {0,0,-1},            // west wall
  75. {-1,0,0}, {0,1,0}, {0,0,-1},        // east wall
  76. {0,1,0}, {1,0,0}, {0,0,-1},            // south wall
  77. {0,-1,0}, {1,0,0}, {0,0,-1}            // north wall
  78. };
  79.  
  80. void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
  81. {
  82.     int        bestaxis;
  83.     float    dot,best;
  84.     int        i;
  85.     
  86.     best = 0;
  87.     bestaxis = 0;
  88.     
  89.     for (i=0 ; i<6 ; i++)
  90.     {
  91.         dot = DotProduct (pln->normal, baseaxis[i*3]);
  92.         if (dot > best)
  93.         {
  94.             best = dot;
  95.             bestaxis = i;
  96.         }
  97.     }
  98.     
  99.     VectorCopy (baseaxis[bestaxis*3+1], xv);
  100.     VectorCopy (baseaxis[bestaxis*3+2], yv);
  101. }
  102.  
  103.  
  104.  
  105. float    lightaxis[3] = {0.6, 0.8, 1.0};
  106. /*
  107. ================
  108. SetShadeForPlane
  109.  
  110. Light different planes differently to
  111. improve recognition
  112. ================
  113. */
  114. float SetShadeForPlane (plane_t *p)
  115. {
  116.     int        i;
  117.     float    f;
  118.  
  119.     // axial plane
  120.     for (i=0 ; i<3 ; i++)
  121.         if (fabs(p->normal[i]) > 0.9)
  122.         {
  123.             f = lightaxis[i];
  124.             return f;
  125.         }
  126.  
  127.     // between two axial planes
  128.     for (i=0 ; i<3 ; i++)
  129.         if (fabs(p->normal[i]) < 0.1)
  130.         {
  131.             f = (lightaxis[(i+1)%3] + lightaxis[(i+2)%3])/2;
  132.             return f;
  133.         }
  134.  
  135.     // other
  136.     f= (lightaxis[0] + lightaxis[1] + lightaxis[2]) / 3;
  137.     return f;
  138. }
  139.  
  140. vec3_t  vecs[2];
  141. float    shift[2];
  142.  
  143. /*
  144. ================
  145. Face_Alloc
  146. ================
  147. */
  148. face_t *Face_Alloc( void )
  149. {
  150.     face_t *f = (face_t*)qmalloc( sizeof( *f ) );
  151.     
  152.     if (g_qeglobals.bSurfacePropertiesPlugin)
  153.         f->pData = static_cast<void *>( g_SurfaceTable.m_pfnTexdefAlloc( f ) );
  154.  
  155.     return f;
  156. }
  157.  
  158. /*
  159. ================
  160. Face_Free
  161. ================
  162. */
  163. void Face_Free( face_t *f )
  164. {
  165.     assert( f != 0 );
  166.  
  167.     if ( f->face_winding )
  168.     {
  169.         free( f->face_winding );
  170.         f->face_winding = 0;
  171.     }
  172.  
  173.     if (g_qeglobals.bSurfacePropertiesPlugin)
  174.     {
  175. #ifdef _DEBUG
  176.         if ( !f->pData )
  177.         {
  178.             Sys_Printf("WARNING: unexpected IPluginTexdef is NULL in Face_Free\n");
  179.         }
  180.         else
  181. #endif
  182.         GETPLUGINTEXDEF(f)->DecRef();
  183.     }
  184.  
  185.     f->texdef.~texdef_t();;
  186.  
  187.     free( f );
  188. }
  189.  
  190. /*
  191. ================
  192. Face_Clone
  193. ================
  194. */
  195. face_t    *Face_Clone (face_t *f)
  196. {
  197.     face_t    *n;
  198.  
  199.     n = Face_Alloc();
  200.     n->texdef = f->texdef;
  201.  
  202.     memcpy (n->planepts, f->planepts, sizeof(n->planepts));
  203.  
  204.     // all other fields are derived, and will be set by Brush_Build
  205.     return n;
  206. }
  207.  
  208. /*
  209. ================
  210. Face_FullClone
  211.  
  212. makes an exact copy of the face
  213. ================
  214. */
  215. face_t    *Face_FullClone (face_t *f)
  216. {
  217.     face_t    *n;
  218.  
  219.     n = Face_Alloc();
  220.     n->texdef = f->texdef;
  221.     memcpy(n->planepts, f->planepts, sizeof(n->planepts));
  222.     memcpy(&n->plane, &f->plane, sizeof(plane_t));
  223.     if (f->face_winding)
  224.         n->face_winding = Winding_Clone(f->face_winding);
  225.     else
  226.         n->face_winding = NULL;
  227.     n->d_texture = Texture_ForName( n->texdef.name );
  228.     return n;
  229. }
  230.  
  231. /*
  232. ================
  233. Clamp
  234. ================
  235. */
  236. void Clamp(float& f, int nClamp)
  237. {
  238.   float fFrac = f - static_cast<int>(f);
  239.   f = static_cast<int>(f) % nClamp;
  240.   f += fFrac;
  241. }
  242.  
  243. /*
  244. ================
  245. Face_MoveTexture
  246. ================
  247. */
  248. void Face_MoveTexture(face_t *f, vec3_t delta)
  249. {
  250.     vec3_t vX, vY;
  251. /*
  252. #ifdef _DEBUG
  253.     if (g_PrefsDlg.m_bBrushPrimitMode)
  254.         Sys_Printf("Warning : Face_MoveTexture not done in brush primitive mode\n");
  255. #endif
  256. */
  257.     if (g_qeglobals.m_bBrushPrimitMode)
  258.         Face_MoveTexture_BrushPrimit( f, delta );
  259.     else
  260.     {
  261.         TextureAxisFromPlane(&f->plane, vX, vY);
  262.  
  263.         vec3_t vDP, vShift;
  264.         vDP[0] = DotProduct(delta, vX);
  265.         vDP[1] = DotProduct(delta, vY);
  266.  
  267.         double fAngle = f->texdef.rotate  / 180 * Q_PI;
  268.         double c = cos(fAngle);
  269.         double s = sin(fAngle);
  270.  
  271.         vShift[0] = vDP[0] * c - vDP[1] * s;
  272.         vShift[1] = vDP[0] * s + vDP[1] * c;
  273.  
  274.         if (!f->texdef.scale[0])
  275.             f->texdef.scale[0] = 1;
  276.         if (!f->texdef.scale[1])
  277.             f->texdef.scale[1] = 1;
  278.  
  279.         f->texdef.shift[0] -= vShift[0] / f->texdef.scale[0];
  280.         f->texdef.shift[1] -= vShift[1] / f->texdef.scale[1];
  281.   
  282.         // clamp the shifts
  283.         Clamp(f->texdef.shift[0], f->d_texture->width);
  284.         Clamp(f->texdef.shift[1], f->d_texture->height);
  285.     }
  286. }
  287.  
  288. /*
  289. ================
  290. Face_SetColor
  291. ================
  292. */
  293. void Face_SetColor (brush_t *b, face_t *f, float fCurveColor) 
  294. {
  295.     float    shade;
  296.     qtexture_t *q;
  297.  
  298.     q = f->d_texture;
  299.  
  300.     // set shading for face
  301.     shade = SetShadeForPlane (&f->plane);
  302.     if (g_pParentWnd->GetCamera()->Camera().draw_mode == cd_texture && !b->owner->eclass->fixedsize)
  303.     {
  304.         //if (b->curveBrush)
  305.         //  shade = fCurveColor;
  306.         f->d_color[0] = 
  307.         f->d_color[1] = 
  308.         f->d_color[2] = shade;
  309.     }
  310.     else
  311.     {
  312.         f->d_color[0] = shade*q->color[0];
  313.         f->d_color[1] = shade*q->color[1];
  314.         f->d_color[2] = shade*q->color[2];
  315.     }
  316. }
  317.  
  318. /*
  319. ================
  320. Face_TextureVectors
  321. TTimo: NOTE: this is never to get called while in brush primitives mode
  322. ================
  323. */
  324. void Face_TextureVectors (face_t *f, float STfromXYZ[2][4])
  325. {
  326.     vec3_t        pvecs[2];
  327.     int            sv, tv;
  328.     float        ang, sinv, cosv;
  329.     float        ns, nt;
  330.     int            i,j;
  331.     qtexture_t *q;
  332.     texdef_t    *td;
  333.  
  334. #ifdef _DEBUG
  335.     //++timo when playing with patches, this sometimes get called and the Warning is displayed
  336.     // find some way out ..
  337.     if (g_qeglobals.m_bBrushPrimitMode && !g_qeglobals.bNeedConvert)
  338.         Sys_Printf("Warning : illegal call of Face_TextureVectors in brush primitive mode\n");
  339. #endif
  340.  
  341.     td = &f->texdef;
  342.     q = f->d_texture;
  343.  
  344.     memset (STfromXYZ, 0, 8*sizeof(float));
  345.  
  346.     if (!td->scale[0])
  347.         td->scale[0] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
  348.     if (!td->scale[1])
  349.         td->scale[1] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
  350.  
  351.     // get natural texture axis
  352.     TextureAxisFromPlane(&f->plane, pvecs[0], pvecs[1]);
  353.  
  354.     // rotate axis
  355.     if (td->rotate == 0)
  356.         { sinv = 0 ; cosv = 1; }
  357.     else if (td->rotate == 90)
  358.         { sinv = 1 ; cosv = 0; }
  359.     else if (td->rotate == 180)
  360.         { sinv = 0 ; cosv = -1; }
  361.     else if (td->rotate == 270)
  362.         { sinv = -1 ; cosv = 0; }
  363.     else
  364.     {    
  365.         ang = td->rotate / 180 * Q_PI;
  366.         sinv = sin(ang);
  367.         cosv = cos(ang);
  368.     }
  369.  
  370.     if (pvecs[0][0])
  371.         sv = 0;
  372.     else if (pvecs[0][1])
  373.         sv = 1;
  374.     else
  375.         sv = 2;
  376.                 
  377.     if (pvecs[1][0])
  378.         tv = 0;
  379.     else if (pvecs[1][1])
  380.         tv = 1;
  381.     else
  382.         tv = 2;
  383.                     
  384.     for (i=0 ; i<2 ; i++) {
  385.         ns = cosv * pvecs[i][sv] - sinv * pvecs[i][tv];
  386.         nt = sinv * pvecs[i][sv] +  cosv * pvecs[i][tv];
  387.         STfromXYZ[i][sv] = ns;
  388.         STfromXYZ[i][tv] = nt;
  389.     }
  390.  
  391.     // scale
  392.     for (i=0 ; i<2 ; i++)
  393.         for (j=0 ; j<3 ; j++)
  394.             STfromXYZ[i][j] = STfromXYZ[i][j] / td->scale[i];
  395.  
  396.     // shift
  397.     STfromXYZ[0][3] = td->shift[0];
  398.     STfromXYZ[1][3] = td->shift[1];
  399.  
  400.     for (j=0 ; j<4 ; j++) {
  401.         STfromXYZ[0][j] /= q->width;
  402.         STfromXYZ[1][j] /= q->height;
  403.     }
  404. }
  405.  
  406. /*
  407. ================
  408. Face_MakePlane
  409. ================
  410. */
  411. void Face_MakePlane (face_t *f)
  412. {
  413.     int        j;
  414.     vec3_t    t1, t2, t3;
  415.  
  416.     // convert to a vector / dist plane
  417.     for (j=0 ; j<3 ; j++)
  418.     {
  419.         t1[j] = f->planepts[0][j] - f->planepts[1][j];
  420.         t2[j] = f->planepts[2][j] - f->planepts[1][j];
  421.         t3[j] = f->planepts[1][j];
  422.     }
  423.     
  424.     CrossProduct(t1,t2, f->plane.normal);
  425.     if (VectorCompare (f->plane.normal, vec3_origin))
  426.         printf ("WARNING: brush plane with no normal\n");
  427.     VectorNormalize (f->plane.normal);
  428.     f->plane.dist = DotProduct (t3, f->plane.normal);
  429. }
  430.  
  431. /*
  432. ================
  433. EmitTextureCoordinates
  434. ================
  435. */
  436. void EmitTextureCoordinates ( float *xyzst, qtexture_t *q, face_t *f)
  437. {
  438.     float    STfromXYZ[2][4];
  439.  
  440.     Face_TextureVectors (f,  STfromXYZ);
  441.     xyzst[3] = DotProduct (xyzst, STfromXYZ[0]) + STfromXYZ[0][3];
  442.     xyzst[4] = DotProduct (xyzst, STfromXYZ[1]) + STfromXYZ[1][3];
  443. }
  444.  
  445. //==========================================================================
  446.  
  447. /*
  448. ================
  449. Brush_MakeFacePlanes
  450. ================
  451. */
  452. void Brush_MakeFacePlanes (brush_t *b)
  453. {
  454.     face_t    *f;
  455.  
  456.     for (f=b->brush_faces ; f ; f=f->next)
  457.     {
  458.         Face_MakePlane (f);
  459.     }
  460. }
  461.  
  462. /*
  463. ================
  464. DrawBrushEntityName
  465. ================
  466. */
  467. void DrawBrushEntityName (brush_t *b)
  468. {
  469.     char    *name;
  470.     //float    a, s, c;
  471.     //vec3_t    mid;
  472.     //int        i;
  473.  
  474.     if (!b->owner)
  475.         return;        // during contruction
  476.  
  477.     if (b->owner == world_entity)
  478.         return;
  479.  
  480.     if (b != b->owner->brushes.onext)
  481.         return;    // not key brush
  482.  
  483. // MERGEME
  484. #if 0
  485.     if (!(g_qeglobals.d_savedinfo.exclude & EXCLUDE_ANGLES))
  486.     {
  487.         // draw the angle pointer
  488.         a = FloatForKey (b->owner, "angle");
  489.         if (a)
  490.         {
  491.             s = sin (a/180*Q_PI);
  492.             c = cos (a/180*Q_PI);
  493.             for (i=0 ; i<3 ; i++)
  494.                 mid[i] = (b->mins[i] + b->maxs[i])*0.5; 
  495.  
  496.             qglBegin (GL_LINE_STRIP);
  497.             qglVertex3fv (mid);
  498.             mid[0] += c*8;
  499.             mid[1] += s*8;
  500.             mid[2] += s*8;
  501.             qglVertex3fv (mid);
  502.             mid[0] -= c*4;
  503.             mid[1] -= s*4;
  504.             mid[2] -= s*4;
  505.             mid[0] -= s*4;
  506.             mid[1] += c*4;
  507.             mid[2] += c*4;
  508.             qglVertex3fv (mid);
  509.             mid[0] += c*4;
  510.             mid[1] += s*4;
  511.             mid[2] += s*4;
  512.             mid[0] += s*4;
  513.             mid[1] -= c*4;
  514.             mid[2] -= c*4;
  515.             qglVertex3fv (mid);
  516.             mid[0] -= c*4;
  517.             mid[1] -= s*4;
  518.             mid[2] -= s*4;
  519.             mid[0] += s*4;
  520.             mid[1] -= c*4;
  521.             mid[2] -= c*4;
  522.             qglVertex3fv (mid);
  523.             qglEnd ();
  524.         }
  525.     }
  526. #endif
  527.  
  528.     if (g_qeglobals.d_savedinfo.show_names)
  529.     {
  530.         name = ValueForKey (b->owner, "classname");
  531.         qglRasterPos3f (b->mins[0]+4, b->mins[1]+4, b->mins[2]+4);
  532.         qglCallLists (strlen(name), GL_UNSIGNED_BYTE, name);
  533.     }
  534. }
  535.  
  536. /*
  537. =================
  538. Brush_MakeFaceWinding
  539.  
  540. returns the visible polygon on a face
  541. =================
  542. */
  543. winding_t *Brush_MakeFaceWinding (brush_t *b, face_t *face)
  544. {
  545.     winding_t    *w;
  546.     face_t        *clip;
  547.     plane_t            plane;
  548.     qboolean        past;
  549.  
  550.     // get a poly that covers an effectively infinite area
  551.     w = Winding_BaseForPlane (&face->plane);
  552.  
  553.     // chop the poly by all of the other faces
  554.     past = false;
  555.     for (clip = b->brush_faces ; clip && w ; clip=clip->next)
  556.     {
  557.         if (clip == face)
  558.         {
  559.             past = true;
  560.             continue;
  561.         }
  562.         if (DotProduct (face->plane.normal, clip->plane.normal) > 0.999
  563.             && fabs(face->plane.dist - clip->plane.dist) < 0.01 )
  564.         {    // identical plane, use the later one
  565.             if (past)
  566.             {
  567.                 free (w);
  568.                 return NULL;
  569.             }
  570.             continue;
  571.         }
  572.  
  573.         // flip the plane, because we want to keep the back side
  574.         VectorSubtract (vec3_origin,clip->plane.normal, plane.normal);
  575.         plane.dist = -clip->plane.dist;
  576.         
  577.         w = Winding_Clip (w, &plane, false);
  578.         if (!w)
  579.             return w;
  580.     }
  581.     
  582.     if (w->numpoints < 3)
  583.     {
  584.         free(w);
  585.         w = NULL;
  586.     }
  587.  
  588.     if (!w)
  589.         printf ("unused plane\n");
  590.  
  591.     return w;
  592. }
  593.  
  594. /*
  595. =================
  596. Brush_SnapPlanepts
  597. =================
  598. */
  599. void Brush_SnapPlanepts (brush_t *b)
  600. {
  601.     int        i, j;
  602.     face_t    *f;
  603.  
  604.   if (g_PrefsDlg.m_bNoClamp)
  605.     return;
  606.  
  607.     for (f=b->brush_faces ; f; f=f->next)
  608.         for (i=0 ; i<3 ; i++)
  609.             for (j=0 ; j<3 ; j++)
  610.                 f->planepts[i][j] = floor (f->planepts[i][j] + 0.5);
  611. }
  612.     
  613. /*
  614. ** Brush_Build
  615. **
  616. ** Builds a brush rendering data and also sets the min/max bounds
  617. */
  618. // TTimo
  619. // added a bConvert flag to convert between old and new brush texture formats
  620. // TTimo
  621. // brush grouping: update the group treeview if necessary
  622. void Brush_Build( brush_t *b, bool bSnap, bool bMarkMap, bool bConvert )
  623. {
  624.     bool        bLocalConvert;
  625.  
  626. #ifdef _DEBUG
  627.     if (!g_qeglobals.m_bBrushPrimitMode && bConvert)
  628.         Sys_Printf("Warning : conversion from brush primitive to old brush format not implemented\n");
  629. #endif
  630.  
  631.     // if bConvert is set and g_qeglobals.bNeedConvert is not, that just means we need convert for this brush only
  632.     if (bConvert && !g_qeglobals.bNeedConvert)
  633.     {
  634.         bLocalConvert = true;
  635.         g_qeglobals.bNeedConvert = true;
  636.     }
  637.  
  638.     /*
  639.     ** build the windings and generate the bounding box
  640.     */
  641.     Brush_BuildWindings(b, bSnap);
  642.  
  643.     Patch_BuildPoints (b);
  644.  
  645.     /*
  646.     ** move the points and edges if in select mode
  647.     */
  648.     if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge)
  649.         SetupVertexSelection ();
  650.  
  651.     if (b->itemOwner == NULL)
  652.       Group_AddToProperGroup(b);
  653.  
  654.     if (bMarkMap)
  655.     {
  656.         Sys_MarkMapModified();
  657.     }
  658.  
  659.     if (bLocalConvert)
  660.         g_qeglobals.bNeedConvert = false;
  661. }
  662.  
  663. /*
  664. ==============
  665. Brush_SplitBrushByFace
  666.  
  667. The incoming brush is NOT freed.
  668. The incoming face is NOT left referenced.
  669. ==============
  670. */
  671. void Brush_SplitBrushByFace (brush_t *in, face_t *f, brush_t **front, brush_t **back)
  672. {
  673.     brush_t    *b;
  674.     face_t    *nf;
  675.     vec3_t    temp;
  676.  
  677.     b = Brush_Clone (in);
  678.     nf = Face_Clone (f);
  679.  
  680.     nf->texdef = b->brush_faces->texdef;
  681.     nf->next = b->brush_faces;
  682.     b->brush_faces = nf;
  683.  
  684.     Brush_Build( b );
  685.     Brush_RemoveEmptyFaces ( b );
  686.     if ( !b->brush_faces )
  687.     {    // completely clipped away
  688.         Brush_Free (b);
  689.         *back = NULL;
  690.     }
  691.     else
  692.     {
  693.         Entity_LinkBrush (in->owner, b);
  694.         *back = b;
  695.     }
  696.  
  697.     b = Brush_Clone (in);
  698.     nf = Face_Clone (f);
  699.     // swap the plane winding
  700.     VectorCopy (nf->planepts[0], temp);
  701.     VectorCopy (nf->planepts[1], nf->planepts[0]);
  702.     VectorCopy (temp, nf->planepts[1]);
  703.  
  704.     nf->texdef = b->brush_faces->texdef;
  705.     nf->next = b->brush_faces;
  706.     b->brush_faces = nf;
  707.  
  708.     Brush_Build( b );
  709.     Brush_RemoveEmptyFaces ( b );
  710.     if ( !b->brush_faces )
  711.     {    // completely clipped away
  712.         Brush_Free (b);
  713.         *front = NULL;
  714.     }
  715.     else
  716.     {
  717.         Entity_LinkBrush (in->owner, b);
  718.         *front = b;
  719.     }
  720. }
  721.  
  722. /*
  723. =================
  724. Brush_BestSplitFace
  725.  
  726. returns the best face to split the brush with.
  727. return NULL if the brush is convex
  728. =================
  729. */
  730. face_t *Brush_BestSplitFace(brush_t *b)
  731. {
  732.     face_t *face, *f, *bestface;
  733.     winding_t *front, *back;
  734.     int splits, tinywindings, value, bestvalue;
  735.  
  736.     bestvalue = 999999;
  737.     bestface = NULL;
  738.     for (face = b->brush_faces; face; face = face->next)
  739.     {
  740.         splits = 0;
  741.         tinywindings = 0;
  742.         for (f = b->brush_faces; f; f = f->next)
  743.         {
  744.             if (f == face) continue;
  745.             //
  746.             Winding_SplitEpsilon(f->face_winding, face->plane.normal, face->plane.dist, 0.1, &front, &back);
  747.  
  748.             if (!front)
  749.             {
  750.                 Winding_Free(back);
  751.             }
  752.             else if (!back)
  753.             {
  754.                 Winding_Free(front);
  755.             }
  756.             else
  757.             {
  758.                 splits++;
  759.                 if (Winding_IsTiny(front)) tinywindings++;
  760.                 if (Winding_IsTiny(back)) tinywindings++;
  761.             }
  762.         }
  763.         if (splits)
  764.         {
  765.             value = splits + 50 * tinywindings;
  766.             if (value < bestvalue)
  767.             {
  768.                 bestvalue = value;
  769.                 bestface = face;
  770.             }
  771.         }
  772.     }
  773.     return bestface;
  774. }
  775.  
  776. /*
  777. =================
  778. Brush_MakeConvexBrushes
  779.  
  780. MrE FIXME: this doesn't work because the old
  781.            Brush_SplitBrushByFace is used
  782. Turns the brush into a minimal number of convex brushes.
  783. If the input brush is convex then it will be returned.
  784. Otherwise the input brush will be freed.
  785. NOTE: the input brush should have windings for the faces.
  786. =================
  787. */
  788. brush_t *Brush_MakeConvexBrushes(brush_t *b)
  789. {
  790.     brush_t *front, *back, *end;
  791.     face_t *face;
  792.  
  793.     b->next = NULL;
  794.     face = Brush_BestSplitFace(b);
  795.     if (!face) return b;
  796.     Brush_SplitBrushByFace(b, face, &front, &back);
  797.     //this should never happen
  798.     if (!front && !back) return b;
  799.     Brush_Free(b);
  800.     if (!front)
  801.         return Brush_MakeConvexBrushes(back);
  802.     b = Brush_MakeConvexBrushes(front);
  803.     if (back)
  804.     {
  805.         for (end = b; end->next; end = end->next);
  806.         end->next = Brush_MakeConvexBrushes(back);
  807.     }
  808.     return b;
  809. }
  810.  
  811. /*
  812. =================
  813. Brush_Convex
  814. =================
  815. */
  816. int Brush_Convex(brush_t *b)
  817. {
  818.     face_t *face1, *face2;
  819.  
  820.     for (face1 = b->brush_faces; face1; face1 = face1->next)
  821.     {
  822.         if (!face1->face_winding) continue;
  823.         for (face2 = b->brush_faces; face2; face2 = face2->next)
  824.         {
  825.             if (face1 == face2) continue;
  826.             if (!face2->face_winding) continue;
  827.             if (Winding_PlanesConcave(face1->face_winding, face2->face_winding,
  828.                                         face1->plane.normal, face2->plane.normal,
  829.                                         face1->plane.dist, face2->plane.dist))
  830.             {
  831.                 return false;
  832.             }
  833.         }
  834.     }
  835.     return true;
  836. }
  837.  
  838. /*
  839. =================
  840. Brush_MoveVertexes_old1
  841.  
  842. - The input brush must have face windings.
  843. - The input brush must be a brush with faces that do not intersect.
  844. - The input brush does not have to be convex.
  845. - The vertex will not be moved if the movement either causes the
  846.   brush to have faces that intersect or causes the brush to be
  847.   flipped inside out.
  848.   (For instance a tetrahedron can easily be flipped inside out
  849.   without having faces that intersect.)
  850. - The created brush does not have to be convex.
  851. - Returns true if the vertex movement is performed.
  852. =================
  853. */
  854.  
  855. #define MAX_MOVE_FACES        64
  856. #define INTERSECT_EPSILON    0.1
  857. #define POINT_EPSILON        0.3
  858.  
  859. int Brush_MoveVertex_old1(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
  860. {
  861.     face_t *f, *face, *newface, *lastface, *nextface;
  862.     face_t *movefaces[MAX_MOVE_FACES];
  863.     int movefacepoints[MAX_MOVE_FACES];
  864.     winding_t *w, tmpw;
  865.     int i, j, k, nummovefaces, result;
  866.     float dot;
  867.  
  868.     result = false;
  869.     //
  870.     tmpw.numpoints = 3;
  871.     tmpw.maxpoints = 3;
  872.     VectorAdd(vertex, delta, end);
  873.     //snap or not?
  874.     if (bSnap)
  875.         for (i = 0; i < 3; i++)
  876.             end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
  877.     //chop off triangles from all brush faces that use the to be moved vertex
  878.     //store pointers to these chopped off triangles in movefaces[]
  879.     nummovefaces = 0;
  880.     for (face = b->brush_faces; face; face = face->next)
  881.     {
  882.         w = face->face_winding;
  883.         if (!w) continue;
  884.         for (i = 0; i < w->numpoints; i++)
  885.         {
  886.             if (Point_Equal(w->points[i], vertex, POINT_EPSILON))
  887.             {
  888.                 if (face->face_winding->numpoints <= 3)
  889.                 {
  890.                     movefacepoints[nummovefaces] = i;
  891.                     movefaces[nummovefaces++] = face;
  892.                     break;
  893.                 }
  894.                 dot = DotProduct(end, face->plane.normal) - face->plane.dist;
  895.                 //if the end point is in front of the face plane
  896.                 if (dot > 0.1)
  897.                 {
  898.                     //fanout triangle subdivision
  899.                     for (k = i; k < i + w->numpoints-3; k++)
  900.                     {
  901.                         VectorCopy(w->points[i], tmpw.points[0]);
  902.                         VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
  903.                         VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
  904.                         //
  905.                         newface = Face_Clone(face);
  906.                         //get the original
  907.                         for (f = face; f->original; f = f->original) ;
  908.                         newface->original = f;
  909.                         //store the new winding
  910.                         if (newface->face_winding) Winding_Free(newface->face_winding);
  911.                         newface->face_winding = Winding_Clone(&tmpw);
  912.                         //get the texture
  913.                         newface->d_texture = Texture_ForName( newface->texdef.name );
  914.                         //add the face to the brush
  915.                         newface->next = b->brush_faces;
  916.                         b->brush_faces = newface;
  917.                         //add this new triangle to the move faces
  918.                         movefacepoints[nummovefaces] = 0;
  919.                         movefaces[nummovefaces++] = newface;
  920.                     }
  921.                     //give the original face a new winding
  922.                     VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
  923.                     VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
  924.                     VectorCopy(w->points[i], tmpw.points[2]);
  925.                     Winding_Free(face->face_winding);
  926.                     face->face_winding = Winding_Clone(&tmpw);
  927.                     //add the original face to the move faces
  928.                     movefacepoints[nummovefaces] = 2;
  929.                     movefaces[nummovefaces++] = face;
  930.                 }
  931.                 else
  932.                 {
  933.                     //chop a triangle off the face
  934.                     VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
  935.                     VectorCopy(w->points[i], tmpw.points[1]);
  936.                     VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
  937.                     //remove the point from the face winding
  938.                     Winding_RemovePoint(w, i);
  939.                     //get texture crap right
  940.                     Face_SetColor(b, face, 1.0);
  941.                     for (j = 0; j < w->numpoints; j++)
  942.                         EmitTextureCoordinates(w->points[j], face->d_texture, face);
  943.                     //make a triangle face
  944.                     newface = Face_Clone(face);
  945.                     //get the original
  946.                     for (f = face; f->original; f = f->original) ;
  947.                     newface->original = f;
  948.                     //store the new winding
  949.                     if (newface->face_winding) Winding_Free(newface->face_winding);
  950.                     newface->face_winding = Winding_Clone(&tmpw);
  951.                     //get the texture
  952.                     newface->d_texture = Texture_ForName( newface->texdef.name );
  953.                     //add the face to the brush
  954.                     newface->next = b->brush_faces;
  955.                     b->brush_faces = newface;
  956.                     //
  957.                     movefacepoints[nummovefaces] = 1;
  958.                     movefaces[nummovefaces++] = newface;
  959.                 }
  960.                 break;
  961.             }
  962.         }
  963.     }
  964.     //now movefaces contains pointers to triangle faces that
  965.     //contain the to be moved vertex
  966.  
  967.     //check if the move is valid
  968.     int l;
  969.     vec3_t p1, p2;
  970.     winding_t *w2;
  971.     plane_t plane;
  972.  
  973.     face = NULL;
  974.     VectorCopy(vertex, tmpw.points[1]);
  975.     VectorCopy(end, tmpw.points[2]);
  976.     for (face = b->brush_faces; face; face = face->next)
  977.     {
  978.         for (i = 0; i < nummovefaces; i++)
  979.         {
  980.             if (face == movefaces[i])
  981.                 break;
  982.         }
  983.         if (i < nummovefaces)
  984.             continue;
  985.         //the delta vector may not intersect with any of the not move faces
  986.         if (Winding_VectorIntersect(face->face_winding, &face->plane, vertex, end, INTERSECT_EPSILON))
  987.             break;
  988.         //if the end point of the to be moved vertex is near this not move face
  989.         if (abs(DotProduct(face->plane.normal, end) - face->plane.dist) < 0.5)
  990.         {
  991.             //the end point may not be inside or very close to the not move face winding
  992.             if (Winding_PointInside(face->face_winding, &face->plane, end, 0.5))
  993.                 break;
  994.         }
  995.         for (i = 0; i < nummovefaces; i++)
  996.         {
  997.             w = movefaces[i]->face_winding;
  998.             j = movefacepoints[i];
  999.             for (k = -1; k <= 1; k += 2)
  1000.             {
  1001.                 //check if the new edge will not intersect with the not move face
  1002.                 VectorCopy(w->points[(j + k + w->numpoints) % w->numpoints], tmpw.points[0]);
  1003.                 if (Winding_VectorIntersect(face->face_winding, &face->plane, tmpw.points[0], end, INTERSECT_EPSILON))
  1004.                 {
  1005.                     //ok the new edge instersects with the not move face
  1006.                     //we can't perform the vertex movement
  1007.                     //break;
  1008.                 }
  1009.                 //check if the not move face intersects the "movement winding"
  1010.                 Winding_Plane(&tmpw, plane.normal, &plane.dist);
  1011.                 w2 = face->face_winding;
  1012.                 for (l = 0; l < w2->numpoints; l++)
  1013.                 {
  1014.                     VectorCopy(w2->points[l], p1);
  1015.                     if (Point_Equal(p1, tmpw.points[0], POINT_EPSILON)) continue;
  1016.                     VectorCopy(w2->points[(l+1) % w2->numpoints], p2);
  1017.                     if (Point_Equal(p2, tmpw.points[0], POINT_EPSILON)) continue;
  1018.                     if (Winding_VectorIntersect(&tmpw, &plane, p1, p2, INTERSECT_EPSILON))
  1019.                         break;
  1020.                 }
  1021.                 if (l < w2->numpoints)
  1022.                 {
  1023.                     //ok this not move face intersects the "movement winding"
  1024.                     //we can't perform the vertex movement
  1025.                     break;
  1026.                 }
  1027.             }
  1028.             if (k <= 1) break;
  1029.         }
  1030.         if (i < nummovefaces)
  1031.             break;
  1032.     }
  1033.     if (!face)
  1034.     {
  1035.         //ok the move was valid
  1036.         //now move all the vertexes of the movefaces
  1037.         for (i = 0; i < nummovefaces; i++)
  1038.         {
  1039.             VectorCopy(end, movefaces[i]->face_winding->points[movefacepoints[i]]);
  1040.             //create new face plane
  1041.             for (j = 0; j < 3; j++)
  1042.             {
  1043.                 VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
  1044.             }
  1045.             Face_MakePlane(movefaces[i]);
  1046.         }
  1047.         result = true;
  1048.     }
  1049.     //get texture crap right
  1050.     for (i = 0; i < nummovefaces; i++)
  1051.     {
  1052.         Face_SetColor(b, movefaces[i], 1.0);
  1053.         for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
  1054.             EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
  1055.     }
  1056.  
  1057.     //now try to merge faces with their original faces
  1058.     lastface = NULL;
  1059.     for (face = b->brush_faces; face; face = nextface)
  1060.     {
  1061.         nextface = face->next;
  1062.         if (!face->original)
  1063.         {
  1064.             lastface = face;
  1065.             continue;
  1066.         }
  1067.         if (!Plane_Equal(&face->plane, &face->original->plane, false))
  1068.         {
  1069.             lastface = face;
  1070.             continue;
  1071.         }
  1072.         w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
  1073.         if (!w)
  1074.         {
  1075.             lastface = face;
  1076.             continue;
  1077.         }
  1078.         Winding_Free(face->original->face_winding);
  1079.         face->original->face_winding = w;
  1080.         //get texture crap right
  1081.         Face_SetColor(b, face->original, 1.0);
  1082.         for (j = 0; j < face->original->face_winding->numpoints; j++)
  1083.             EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
  1084.         //remove the face that was merged with the original
  1085.         if (lastface) lastface->next = face->next;
  1086.         else b->brush_faces = face->next;
  1087.         Face_Free(face);
  1088.     }
  1089.     return result;
  1090. }
  1091.  
  1092. /*
  1093. =================
  1094. Brush_MoveVertexes_old2
  1095.  
  1096. - The input brush must be convex
  1097. - The input brush must have face windings.
  1098. - The output brush will be convex.
  1099. - Returns true if the vertex movement is performed.
  1100. =================
  1101. */
  1102.  
  1103. #define MAX_MOVE_FACES        64
  1104. #define INTERSECT_EPSILON    0.1
  1105. #define POINT_EPSILON        0.3
  1106.  
  1107. int Brush_MoveVertex_old2(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
  1108. {
  1109.     face_t *f, *face, *newface, *lastface, *nextface;
  1110.     face_t *movefaces[MAX_MOVE_FACES];
  1111.     int movefacepoints[MAX_MOVE_FACES];
  1112.     winding_t *w, tmpw;
  1113.     int i, j, k, nummovefaces, result;
  1114.     float dot;
  1115.  
  1116.     result = true;
  1117.     //
  1118.     tmpw.numpoints = 3;
  1119.     tmpw.maxpoints = 3;
  1120.     VectorAdd(vertex, delta, end);
  1121.     //snap or not?
  1122.     if (bSnap)
  1123.         for (i = 0; i < 3; i++)
  1124.             end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
  1125.     //chop off triangles from all brush faces that use the to be moved vertex
  1126.     //store pointers to these chopped off triangles in movefaces[]
  1127.     nummovefaces = 0;
  1128.     for (face = b->brush_faces; face; face = face->next)
  1129.     {
  1130.         w = face->face_winding;
  1131.         if (!w) continue;
  1132.         for (i = 0; i < w->numpoints; i++)
  1133.         {
  1134.             if (Point_Equal(w->points[i], vertex, POINT_EPSILON))
  1135.             {
  1136.                 if (face->face_winding->numpoints <= 3)
  1137.                 {
  1138.                     movefacepoints[nummovefaces] = i;
  1139.                     movefaces[nummovefaces++] = face;
  1140.                     break;
  1141.                 }
  1142.                 dot = DotProduct(end, face->plane.normal) - face->plane.dist;
  1143.                 //if the end point is in front of the face plane
  1144.                 if (dot > 0.1)
  1145.                 {
  1146.                     //fanout triangle subdivision
  1147.                     for (k = i; k < i + w->numpoints-3; k++)
  1148.                     {
  1149.                         VectorCopy(w->points[i], tmpw.points[0]);
  1150.                         VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
  1151.                         VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
  1152.                         //
  1153.                         newface = Face_Clone(face);
  1154.                         //get the original
  1155.                         for (f = face; f->original; f = f->original) ;
  1156.                         newface->original = f;
  1157.                         //store the new winding
  1158.                         if (newface->face_winding) Winding_Free(newface->face_winding);
  1159.                         newface->face_winding = Winding_Clone(&tmpw);
  1160.                         //get the texture
  1161.                         newface->d_texture = Texture_ForName( newface->texdef.name );
  1162.                         //add the face to the brush
  1163.                         newface->next = b->brush_faces;
  1164.                         b->brush_faces = newface;
  1165.                         //add this new triangle to the move faces
  1166.                         movefacepoints[nummovefaces] = 0;
  1167.                         movefaces[nummovefaces++] = newface;
  1168.                     }
  1169.                     //give the original face a new winding
  1170.                     VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
  1171.                     VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
  1172.                     VectorCopy(w->points[i], tmpw.points[2]);
  1173.                     Winding_Free(face->face_winding);
  1174.                     face->face_winding = Winding_Clone(&tmpw);
  1175.                     //add the original face to the move faces
  1176.                     movefacepoints[nummovefaces] = 2;
  1177.                     movefaces[nummovefaces++] = face;
  1178.                 }
  1179.                 else
  1180.                 {
  1181.                     //chop a triangle off the face
  1182.                     VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
  1183.                     VectorCopy(w->points[i], tmpw.points[1]);
  1184.                     VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
  1185.                     //remove the point from the face winding
  1186.                     Winding_RemovePoint(w, i);
  1187.                     //get texture crap right
  1188.                     Face_SetColor(b, face, 1.0);
  1189.                     for (j = 0; j < w->numpoints; j++)
  1190.                         EmitTextureCoordinates(w->points[j], face->d_texture, face);
  1191.                     //make a triangle face
  1192.                     newface = Face_Clone(face);
  1193.                     //get the original
  1194.                     for (f = face; f->original; f = f->original) ;
  1195.                     newface->original = f;
  1196.                     //store the new winding
  1197.                     if (newface->face_winding) Winding_Free(newface->face_winding);
  1198.                     newface->face_winding = Winding_Clone(&tmpw);
  1199.                     //get the texture
  1200.                     newface->d_texture = Texture_ForName( newface->texdef.name );
  1201.                     //add the face to the brush
  1202.                     newface->next = b->brush_faces;
  1203.                     b->brush_faces = newface;
  1204.                     //
  1205.                     movefacepoints[nummovefaces] = 1;
  1206.                     movefaces[nummovefaces++] = newface;
  1207.                 }
  1208.                 break;
  1209.             }
  1210.         }
  1211.     }
  1212.     //now movefaces contains pointers to triangle faces that
  1213.     //contain the to be moved vertex
  1214.  
  1215.     //move the vertex
  1216.     for (i = 0; i < nummovefaces; i++)
  1217.     {
  1218.         //move vertex to end position
  1219.         VectorCopy(end, movefaces[i]->face_winding->points[movefacepoints[i]]);
  1220.         //create new face plane
  1221.         for (j = 0; j < 3; j++)
  1222.         {
  1223.             VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
  1224.         }
  1225.         Face_MakePlane(movefaces[i]);
  1226.     }
  1227.     //if the brush is no longer convex
  1228.     if (!Brush_Convex(b))
  1229.     {
  1230.         for (i = 0; i < nummovefaces; i++)
  1231.         {
  1232.             //move the vertex back to the initial position
  1233.             VectorCopy(vertex, movefaces[i]->face_winding->points[movefacepoints[i]]);
  1234.             //create new face plane
  1235.             for (j = 0; j < 3; j++)
  1236.             {
  1237.                 VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
  1238.             }
  1239.             Face_MakePlane(movefaces[i]);
  1240.         }
  1241.         result = false;
  1242.     }
  1243.     //get texture crap right
  1244.     for (i = 0; i < nummovefaces; i++)
  1245.     {
  1246.         Face_SetColor(b, movefaces[i], 1.0);
  1247.         for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
  1248.             EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
  1249.     }
  1250.  
  1251.     //now try to merge faces with their original faces
  1252.     lastface = NULL;
  1253.     for (face = b->brush_faces; face; face = nextface)
  1254.     {
  1255.         nextface = face->next;
  1256.         if (!face->original)
  1257.         {
  1258.             lastface = face;
  1259.             continue;
  1260.         }
  1261.         if (!Plane_Equal(&face->plane, &face->original->plane, false))
  1262.         {
  1263.             lastface = face;
  1264.             continue;
  1265.         }
  1266.         w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
  1267.         if (!w)
  1268.         {
  1269.             lastface = face;
  1270.             continue;
  1271.         }
  1272.         Winding_Free(face->original->face_winding);
  1273.         face->original->face_winding = w;
  1274.         //get texture crap right
  1275.         Face_SetColor(b, face->original, 1.0);
  1276.         for (j = 0; j < face->original->face_winding->numpoints; j++)
  1277.             EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
  1278.         //remove the face that was merged with the original
  1279.         if (lastface) lastface->next = face->next;
  1280.         else b->brush_faces = face->next;
  1281.         Face_Free(face);
  1282.     }
  1283.     return result;
  1284. }
  1285.  
  1286. /*
  1287. =================
  1288. Brush_MoveVertexes
  1289.  
  1290. - The input brush must be convex
  1291. - The input brush must have face windings.
  1292. - The output brush will be convex.
  1293. - Returns true if the WHOLE vertex movement is performed.
  1294. =================
  1295. */
  1296.  
  1297. #define MAX_MOVE_FACES        64
  1298.  
  1299. int Brush_MoveVertex(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
  1300. {
  1301.     face_t *f, *face, *newface, *lastface, *nextface;
  1302.     face_t *movefaces[MAX_MOVE_FACES];
  1303.     int movefacepoints[MAX_MOVE_FACES];
  1304.     winding_t *w, tmpw;
  1305.     vec3_t start, mid;
  1306.     plane_t plane;
  1307.     int i, j, k, nummovefaces, result, done;
  1308.     float dot, front, back, frac, smallestfrac;
  1309.  
  1310.     result = true;
  1311.     //
  1312.     tmpw.numpoints = 3;
  1313.     tmpw.maxpoints = 3;
  1314.     VectorCopy(vertex, start);
  1315.     VectorAdd(vertex, delta, end);
  1316.     //snap or not?
  1317.     if (bSnap)
  1318.         for (i = 0; i < 3; i++)
  1319.             end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
  1320.     //
  1321.     VectorCopy(end, mid);
  1322.     //if the start and end are the same
  1323.     if (Point_Equal(start, end, 0.3)) return false;
  1324.     //the end point may not be the same as another vertex
  1325.     for (face = b->brush_faces; face; face = face->next)
  1326.     {
  1327.         w = face->face_winding;
  1328.         if (!w) continue;
  1329.         for (i = 0; i < w->numpoints; i++)
  1330.         {
  1331.             if (Point_Equal(w->points[i], end, 0.3))
  1332.             {
  1333.                 VectorCopy(vertex, end);
  1334.                 return false;
  1335.             }
  1336.         }
  1337.     }
  1338.     //
  1339.     done = false;
  1340.     while(!done)
  1341.     {
  1342.         //chop off triangles from all brush faces that use the to be moved vertex
  1343.         //store pointers to these chopped off triangles in movefaces[]
  1344.         nummovefaces = 0;
  1345.         for (face = b->brush_faces; face; face = face->next)
  1346.         {
  1347.             w = face->face_winding;
  1348.             if (!w) continue;
  1349.             for (i = 0; i < w->numpoints; i++)
  1350.             {
  1351.                 if (Point_Equal(w->points[i], start, 0.2))
  1352.                 {
  1353.                     if (face->face_winding->numpoints <= 3)
  1354.                     {
  1355.                         movefacepoints[nummovefaces] = i;
  1356.                         movefaces[nummovefaces++] = face;
  1357.                         break;
  1358.                     }
  1359.                     dot = DotProduct(end, face->plane.normal) - face->plane.dist;
  1360.                     //if the end point is in front of the face plane
  1361.                     if (dot > 0.1)
  1362.                     {
  1363.                         //fanout triangle subdivision
  1364.                         for (k = i; k < i + w->numpoints-3; k++)
  1365.                         {
  1366.                             VectorCopy(w->points[i], tmpw.points[0]);
  1367.                             VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
  1368.                             VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
  1369.                             //
  1370.                             newface = Face_Clone(face);
  1371.                             //get the original
  1372.                             for (f = face; f->original; f = f->original) ;
  1373.                             newface->original = f;
  1374.                             //store the new winding
  1375.                             if (newface->face_winding) Winding_Free(newface->face_winding);
  1376.                             newface->face_winding = Winding_Clone(&tmpw);
  1377.                             //get the texture
  1378.                             newface->d_texture = Texture_ForName( newface->texdef.name );
  1379.                             //add the face to the brush
  1380.                             newface->next = b->brush_faces;
  1381.                             b->brush_faces = newface;
  1382.                             //add this new triangle to the move faces
  1383.                             movefacepoints[nummovefaces] = 0;
  1384.                             movefaces[nummovefaces++] = newface;
  1385.                         }
  1386.                         //give the original face a new winding
  1387.                         VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
  1388.                         VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
  1389.                         VectorCopy(w->points[i], tmpw.points[2]);
  1390.                         Winding_Free(face->face_winding);
  1391.                         face->face_winding = Winding_Clone(&tmpw);
  1392.                         //add the original face to the move faces
  1393.                         movefacepoints[nummovefaces] = 2;
  1394.                         movefaces[nummovefaces++] = face;
  1395.                     }
  1396.                     else
  1397.                     {
  1398.                         //chop a triangle off the face
  1399.                         VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
  1400.                         VectorCopy(w->points[i], tmpw.points[1]);
  1401.                         VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
  1402.                         //remove the point from the face winding
  1403.                         Winding_RemovePoint(w, i);
  1404.                         //get texture crap right
  1405.                         Face_SetColor(b, face, 1.0);
  1406.                         for (j = 0; j < w->numpoints; j++)
  1407.                             EmitTextureCoordinates(w->points[j], face->d_texture, face);
  1408.                         //make a triangle face
  1409.                         newface = Face_Clone(face);
  1410.                         //get the original
  1411.                         for (f = face; f->original; f = f->original) ;
  1412.                         newface->original = f;
  1413.                         //store the new winding
  1414.                         if (newface->face_winding) Winding_Free(newface->face_winding);
  1415.                         newface->face_winding = Winding_Clone(&tmpw);
  1416.                         //get the texture
  1417.                         newface->d_texture = Texture_ForName( newface->texdef.name );
  1418.                         //add the face to the brush
  1419.                         newface->next = b->brush_faces;
  1420.                         b->brush_faces = newface;
  1421.                         //
  1422.                         movefacepoints[nummovefaces] = 1;
  1423.                         movefaces[nummovefaces++] = newface;
  1424.                     }
  1425.                     break;
  1426.                 }
  1427.             }
  1428.         }
  1429.         //now movefaces contains pointers to triangle faces that
  1430.         //contain the to be moved vertex
  1431.         //
  1432.         done = true;
  1433.         VectorCopy(end, mid);
  1434.         smallestfrac = 1;
  1435.         for (face = b->brush_faces; face; face = face->next)
  1436.         {
  1437.             //check if there is a move face that has this face as the original
  1438.             for (i = 0; i < nummovefaces; i++)
  1439.             {
  1440.                 if (movefaces[i]->original == face) break;
  1441.             }
  1442.             if (i >= nummovefaces) continue;
  1443.             //check if the original is not a move face itself
  1444.             for (j = 0; j < nummovefaces; j++)
  1445.             {
  1446.                 if (face == movefaces[j]) break;
  1447.             }
  1448.             //if the original is not a move face itself
  1449.             if (j >= nummovefaces)
  1450.             {
  1451.                 memcpy(&plane, &movefaces[i]->original->plane, sizeof(plane_t));
  1452.             }
  1453.             else
  1454.             {
  1455.                 k = movefacepoints[j];
  1456.                 w = movefaces[j]->face_winding;
  1457.                 VectorCopy(w->points[(k+1)%w->numpoints], tmpw.points[0]);
  1458.                 VectorCopy(w->points[(k+2)%w->numpoints], tmpw.points[1]);
  1459.                 //
  1460.                 k = movefacepoints[i];
  1461.                 w = movefaces[i]->face_winding;
  1462.                 VectorCopy(w->points[(k+1)%w->numpoints], tmpw.points[2]);
  1463.                 if (!Plane_FromPoints(tmpw.points[0], tmpw.points[1], tmpw.points[2], &plane))
  1464.                 {
  1465.                     VectorCopy(w->points[(k+2)%w->numpoints], tmpw.points[2]);
  1466.                     if (!Plane_FromPoints(tmpw.points[0], tmpw.points[1], tmpw.points[2], &plane))
  1467.                         //this should never happen otherwise the face merge did a crappy job a previous pass
  1468.                         continue;
  1469.                 }
  1470.             }
  1471.             //now we've got the plane to check agains
  1472.             front = DotProduct(start, plane.normal) - plane.dist;
  1473.             back = DotProduct(end, plane.normal) - plane.dist;
  1474.             //if the whole move is at one side of the plane
  1475.             if (front < 0.01 && back < 0.01) continue;
  1476.             if (front > -0.01 && back > -0.01) continue;
  1477.             //if there's no movement orthogonal to this plane at all
  1478.             if (fabs(front-back) < 0.001) continue;
  1479.             //ok first only move till the plane is hit
  1480.             frac = front/(front-back);
  1481.             if (frac < smallestfrac)
  1482.             {
  1483.                 mid[0] = start[0] + (end[0] - start[0]) * frac;
  1484.                 mid[1] = start[1] + (end[1] - start[1]) * frac;
  1485.                 mid[2] = start[2] + (end[2] - start[2]) * frac;
  1486.                 smallestfrac = frac;
  1487.             }
  1488.             //
  1489.             done = false;
  1490.         }
  1491.  
  1492.         //move the vertex
  1493.         for (i = 0; i < nummovefaces; i++)
  1494.         {
  1495.             //move vertex to end position
  1496.             VectorCopy(mid, movefaces[i]->face_winding->points[movefacepoints[i]]);
  1497.             //create new face plane
  1498.             for (j = 0; j < 3; j++)
  1499.             {
  1500.                 VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
  1501.             }
  1502.             Face_MakePlane(movefaces[i]);
  1503.             if (VectorLength(movefaces[i]->plane.normal) < 0.1)
  1504.                 result = false;
  1505.         }
  1506.         //if the brush is no longer convex
  1507.         if (!result || !Brush_Convex(b))
  1508.         {
  1509.             for (i = 0; i < nummovefaces; i++)
  1510.             {
  1511.                 //move the vertex back to the initial position
  1512.                 VectorCopy(start, movefaces[i]->face_winding->points[movefacepoints[i]]);
  1513.                 //create new face plane
  1514.                 for (j = 0; j < 3; j++)
  1515.                 {
  1516.                     VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
  1517.                 }
  1518.                 Face_MakePlane(movefaces[i]);
  1519.             }
  1520.             result = false;
  1521.             VectorCopy(start, end);
  1522.             done = true;
  1523.         }
  1524.         else
  1525.         {
  1526.             VectorCopy(mid, start);
  1527.         }
  1528.         //get texture crap right
  1529.         for (i = 0; i < nummovefaces; i++)
  1530.         {
  1531.             Face_SetColor(b, movefaces[i], 1.0);
  1532.             for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
  1533.                 EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
  1534.         }
  1535.  
  1536.         //now try to merge faces with their original faces
  1537.         lastface = NULL;
  1538.         for (face = b->brush_faces; face; face = nextface)
  1539.         {
  1540.             nextface = face->next;
  1541.             if (!face->original)
  1542.             {
  1543.                 lastface = face;
  1544.                 continue;
  1545.             }
  1546.             if (!Plane_Equal(&face->plane, &face->original->plane, false))
  1547.             {
  1548.                 lastface = face;
  1549.                 continue;
  1550.             }
  1551.             w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
  1552.             if (!w)
  1553.             {
  1554.                 lastface = face;
  1555.                 continue;
  1556.             }
  1557.             Winding_Free(face->original->face_winding);
  1558.             face->original->face_winding = w;
  1559.             //get texture crap right
  1560.             Face_SetColor(b, face->original, 1.0);
  1561.             for (j = 0; j < face->original->face_winding->numpoints; j++)
  1562.                 EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
  1563.             //remove the face that was merged with the original
  1564.             if (lastface) lastface->next = face->next;
  1565.             else b->brush_faces = face->next;
  1566.             Face_Free(face);
  1567.         }
  1568.     }
  1569.     return result;
  1570. }
  1571.  
  1572. /*
  1573. =================
  1574. Brush_InsertVertexBetween
  1575. =================
  1576. */
  1577. int Brush_InsertVertexBetween(brush_t *b, vec3_t p1, vec3_t p2)
  1578. {
  1579.     face_t *face;
  1580.     winding_t *w, *neww;
  1581.     vec3_t point;
  1582.     int i, insert;
  1583.  
  1584.     if (Point_Equal(p1, p2, 0.4))
  1585.         return false;
  1586.     VectorAdd(p1, p2, point);
  1587.     VectorScale(point, 0.5, point);
  1588.     insert = false;
  1589.     //the end point may not be the same as another vertex
  1590.     for (face = b->brush_faces; face; face = face->next)
  1591.     {
  1592.         w = face->face_winding;
  1593.         if (!w) continue;
  1594.         neww = NULL;
  1595.         for (i = 0; i < w->numpoints; i++)
  1596.         {
  1597.             if (!Point_Equal(w->points[i], p1, 0.1))
  1598.                 continue;
  1599.             if (Point_Equal(w->points[(i+1) % w->numpoints], p2, 0.1))
  1600.             {
  1601.                 neww = Winding_InsertPoint(w, point, (i+1) % w->numpoints);
  1602.                 break;
  1603.             }
  1604.             else if (Point_Equal(w->points[(i-1+w->numpoints) % w->numpoints], p2, 0.3))
  1605.             {
  1606.                 neww = Winding_InsertPoint(w, point, i);
  1607.                 break;
  1608.             }
  1609.         }
  1610.         if (neww)
  1611.         {
  1612.             Winding_Free(face->face_winding);
  1613.             face->face_winding = neww;
  1614.             insert = true;
  1615.         }
  1616.     }
  1617.     return insert;
  1618. }
  1619.  
  1620.  
  1621. /*
  1622. =================
  1623. Brush_ResetFaceOriginals
  1624. =================
  1625. */
  1626. void Brush_ResetFaceOriginals(brush_t *b)
  1627. {
  1628.     face_t *face;
  1629.  
  1630.     for (face = b->brush_faces; face; face = face->next)
  1631.     {
  1632.         face->original = NULL;
  1633.     }
  1634. }
  1635.  
  1636. /*
  1637. =================
  1638. Brush_Parse
  1639.  
  1640. The brush is NOT linked to any list
  1641. =================
  1642. */
  1643. //++timo FIXME: when using old brush primitives, the test loop for "Brush" and "patchDef2" "patchDef3" is ran
  1644. // before each face parsing. It works, but it's a performance hit
  1645. brush_t *Brush_Parse (void)
  1646. {
  1647.     brush_t        *b;
  1648.     face_t        *f;
  1649.     int            i,j;
  1650.     
  1651.     g_qeglobals.d_parsed_brushes++;
  1652.   b = Brush_Alloc();
  1653.  
  1654.   do
  1655.     {
  1656.         if (!GetToken (true))
  1657.             break;
  1658.         if (!strcmp (token, "}") )
  1659.             break;
  1660.         
  1661.         // handle "Brush" primitive
  1662.         if (strcmpi(token, "brushDef") == 0)
  1663.         {
  1664.             // Timo parsing new brush format
  1665.             g_qeglobals.bPrimitBrushes=true;
  1666.             // check the map is not mixing the two kinds of brushes
  1667.             if (g_qeglobals.m_bBrushPrimitMode)
  1668.             {
  1669.                 if (g_qeglobals.bOldBrushes)
  1670.                     Sys_Printf("Warning : old brushes and brush primitive in the same file are not allowed ( Brush_Parse )\n");
  1671.             }
  1672.             //++Timo write new brush primitive -> old conversion code for Q3->Q2 conversions ?
  1673.             else
  1674.                 Sys_Printf("Warning : conversion code from brush primitive not done ( Brush_Parse )\n");
  1675.             
  1676.             BrushPrimit_Parse(b);
  1677.             if (b == NULL)
  1678.             {
  1679.                 Warning ("parsing brush primitive");
  1680.                 return NULL;
  1681.             }
  1682.             else
  1683.       {
  1684.         
  1685.                 continue;
  1686.       }
  1687.         }
  1688.         if (strcmpi(token, "patchDef2") == 0 || strcmpi(token, "patchDef3") == 0)
  1689.         {
  1690.             free (b);
  1691.             
  1692.             // double string compare but will go away soon
  1693.             b = Patch_Parse(strcmpi(token, "patchDef2") == 0);
  1694.             if (b == NULL)
  1695.             {
  1696.                 Warning ("parsing patch/brush");
  1697.                 return NULL;
  1698.             }
  1699.             else
  1700.             {
  1701.                 continue;
  1702.             }
  1703.             // handle inline patch
  1704.         }
  1705.         else
  1706.         {
  1707.             // Timo parsing old brush format
  1708.             g_qeglobals.bOldBrushes=true;
  1709.             if (g_qeglobals.m_bBrushPrimitMode)
  1710.             {
  1711.                 // check the map is not mixing the two kinds of brushes
  1712.                 if (g_qeglobals.bPrimitBrushes)
  1713.                     Sys_Printf("Warning : old brushes and brush primitive in the same file are not allowed ( Brush_Parse )\n");
  1714.                 // set the "need" conversion flag
  1715.                 g_qeglobals.bNeedConvert=true;
  1716.             }
  1717.             
  1718.             f = Face_Alloc();
  1719.             
  1720.             // add the brush to the end of the chain, so
  1721.             // loading and saving a map doesn't reverse the order
  1722.             
  1723.             f->next = NULL;
  1724.             if (!b->brush_faces)
  1725.             {
  1726.                 b->brush_faces = f;
  1727.             }
  1728.             else
  1729.             {
  1730.                 face_t *scan;
  1731.                 for (scan=b->brush_faces ; scan->next ; scan=scan->next)
  1732.                     ;
  1733.                 scan->next = f;
  1734.             }
  1735.             
  1736.             // read the three point plane definition
  1737.             for (i=0 ; i<3 ; i++)
  1738.             {
  1739.                 if (i != 0)
  1740.                     GetToken (true);
  1741.                 if (strcmp (token, "(") )
  1742.                 {
  1743.                     Warning ("parsing brush");
  1744.                     return NULL;
  1745.                 }
  1746.                 
  1747.                 for (j=0 ; j<3 ; j++)
  1748.                 {
  1749.                     GetToken (false);
  1750.                     f->planepts[i][j] = atof(token);
  1751.                 }
  1752.                 
  1753.                 GetToken (false);
  1754.                 if (strcmp (token, ")") )
  1755.                 {
  1756.                     Warning ("parsing brush");
  1757.                     return NULL;
  1758.                 }
  1759.             }
  1760.         }
  1761.  
  1762.         // Timo
  1763.         // if we have a surface plugin, we'll call the plugin parsing
  1764.         if (g_qeglobals.bSurfacePropertiesPlugin)
  1765.         {
  1766.             GETPLUGINTEXDEF(f)->ParseTexdef();
  1767.         }
  1768.         else
  1769.         {
  1770.             
  1771.             // read the texturedef
  1772.             GetToken (false);
  1773.             f->texdef.SetName(token);
  1774.             if (token[0] == '(')
  1775.             {
  1776.                 int i = 32;
  1777.             }
  1778.             GetToken (false);
  1779.             f->texdef.shift[0] = atoi(token);
  1780.             GetToken (false);
  1781.             f->texdef.shift[1] = atoi(token);
  1782.             GetToken (false);
  1783.             f->texdef.rotate = atoi(token);    
  1784.             GetToken (false);
  1785.             f->texdef.scale[0] = atof(token);
  1786.             GetToken (false);
  1787.             f->texdef.scale[1] = atof(token);
  1788.                         
  1789.             // the flags and value field aren't necessarily present
  1790.             f->d_texture = Texture_ForName( f->texdef.name );
  1791.             f->texdef.flags = f->d_texture->flags;
  1792.             f->texdef.value = f->d_texture->value;
  1793.             f->texdef.contents = f->d_texture->contents;
  1794.             
  1795.             if (TokenAvailable ())
  1796.             {
  1797.                 GetToken (false);
  1798.                 f->texdef.contents = atoi(token);
  1799.                 GetToken (false);
  1800.                 f->texdef.flags = atoi(token);
  1801.                 GetToken (false);
  1802.                 f->texdef.value = atoi(token);
  1803.             }
  1804.             
  1805.         }
  1806.     } while (1);
  1807.     
  1808.     return b;
  1809. }
  1810.  
  1811. /*
  1812. =================
  1813. QERApp_MapPrintf_FILE
  1814. callback for surface properties plugin
  1815. must fit a PFN_QERAPP_MAPPRINTF ( see isurfaceplugin.h )
  1816. =================
  1817. */
  1818. // carefully initialize !
  1819. FILE * g_File;
  1820. void WINAPI QERApp_MapPrintf_FILE( char *text, ... )
  1821. {
  1822.     va_list argptr;
  1823.     char    buf[32768];
  1824.  
  1825.     va_start (argptr,text);
  1826.     vsprintf (buf, text,argptr);
  1827.     va_end (argptr);
  1828.  
  1829.     fprintf( g_File, buf );
  1830. }
  1831.  
  1832.  
  1833. /*
  1834. ==============
  1835. Brush_SetEpair
  1836. sets an epair for the given brush
  1837. ==============
  1838. */
  1839. void Brush_SetEpair(brush_t *b, const char *pKey, const char *pValue)
  1840. {
  1841.     if (g_qeglobals.m_bBrushPrimitMode)
  1842.     {
  1843.     if (b->patchBrush)
  1844.     {
  1845.       Patch_SetEpair(b->pPatch, pKey, pValue);
  1846.     }
  1847.     else
  1848.     {
  1849.           SetKeyValue(b->epairs, pKey, pValue);
  1850.     }
  1851.     }
  1852.     else
  1853.     {
  1854.         Sys_Printf("Can only set key/values in Brush primitive mode\n");
  1855.     }
  1856. }
  1857.  
  1858. /* 
  1859. =================
  1860. Brush_GetKeyValue
  1861. =================
  1862. */
  1863. const char* Brush_GetKeyValue(brush_t *b, const char *pKey)
  1864. {
  1865.     if (g_qeglobals.m_bBrushPrimitMode)
  1866.     {
  1867.     if (b->patchBrush)
  1868.     {
  1869.       return Patch_GetKeyValue(b->pPatch, pKey);
  1870.     }
  1871.     else
  1872.     {
  1873.           return ValueForKey(b->epairs, pKey);
  1874.     }
  1875.     }
  1876.     else
  1877.     {
  1878.         Sys_Printf("Can only set brush/patch key/values in Brush primitive mode\n");
  1879.     }
  1880.   return "";
  1881. }
  1882.  
  1883. /*
  1884. =================
  1885. Brush_Write
  1886. save all brushes as Brush primitive format
  1887. =================
  1888. */
  1889. void Brush_Write (brush_t *b, FILE *f)
  1890. {
  1891.     epair_t    *ep;
  1892.     face_t    *fa;
  1893.     char    *pname;
  1894.     int        i;
  1895.     
  1896.     if (b->patchBrush)
  1897.     {
  1898.         Patch_Write(b->pPatch, f);
  1899.         return;
  1900.     }
  1901.     if (g_qeglobals.m_bBrushPrimitMode)
  1902.     {
  1903.         // save brush primitive format
  1904.         fprintf (f, "{\nbrushDef\n{\n");
  1905.         // brush epairs
  1906.         if (b->epairs)
  1907.             for (ep = b->epairs ; ep ; ep=ep->next)
  1908.                 fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value);
  1909.         for (fa=b->brush_faces ; fa ; fa=fa->next)
  1910.         {
  1911.             // save planepts
  1912.             for (i=0 ; i<3 ; i++)
  1913.             {
  1914.                 fprintf(f, "( ");
  1915.                 for (int j = 0; j < 3; j++)
  1916.                     if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
  1917.                         fprintf(f, "%i ", static_cast<int>(fa->planepts[i][j]));
  1918.                     else
  1919.                         fprintf(f, "%f ", fa->planepts[i][j]);
  1920.                 fprintf(f, ") ");
  1921.             }
  1922.             // save texture coordinates
  1923.             fprintf(f,"( ( ");
  1924.             for (i=0 ; i<3 ; i++)
  1925.                 if (fa->brushprimit_texdef.coords[0][i] == static_cast<int>(fa->brushprimit_texdef.coords[0][i]))
  1926.                     fprintf(f,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[0][i]));
  1927.                 else
  1928.                     fprintf(f,"%f ",fa->brushprimit_texdef.coords[0][i]);
  1929.             fprintf(f,") ( ");
  1930.             for (i=0 ; i<3 ; i++)
  1931.                 if (fa->brushprimit_texdef.coords[1][i] == static_cast<int>(fa->brushprimit_texdef.coords[1][i]))
  1932.                     fprintf(f,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[1][i]));
  1933.                 else
  1934.                     fprintf(f,"%f ",fa->brushprimit_texdef.coords[1][i]);
  1935.             fprintf(f,") ) ");
  1936.             // save texture attribs
  1937.             //++timo surface properties plugin not implemented for brush primitives
  1938.             if (g_qeglobals.bSurfacePropertiesPlugin)
  1939.                 Sys_Printf("WARNING: surface properties plugin not supported with brush primitives (yet)\n");
  1940.  
  1941.       char *pName = strlen(fa->texdef.name) > 0 ? fa->texdef.name : "unnamed";
  1942.             fprintf(f, "%s ", pName );
  1943.             fprintf(f, "%i %i %i\n", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
  1944.         }
  1945.         fprintf (f, "}\n}\n");
  1946.     }
  1947.     else
  1948.     {
  1949.         fprintf (f, "{\n");
  1950.         for (fa=b->brush_faces ; fa ; fa=fa->next)
  1951.         {
  1952.             for (i=0 ; i<3 ; i++)
  1953.             {
  1954.                 fprintf(f, "( ");
  1955.                 for (int j = 0; j < 3; j++)
  1956.                 {
  1957.                     if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
  1958.                         fprintf(f, "%i ", static_cast<int>(fa->planepts[i][j]));
  1959.                     else
  1960.                         fprintf(f, "%f ", fa->planepts[i][j]);
  1961.                 }
  1962.                 fprintf(f, ") ");
  1963.             }
  1964.             
  1965.             if (g_qeglobals.bSurfacePropertiesPlugin)
  1966.             {
  1967.                 g_File = f;
  1968. #ifdef _DEBUG
  1969.                 if (!fa->pData)
  1970.                     Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in Brush_Write\n");
  1971.                 else
  1972. #endif
  1973.                 GETPLUGINTEXDEF(fa)->WriteTexdef( QERApp_MapPrintf_FILE );
  1974.             }
  1975.             else
  1976.             {
  1977.                 pname = fa->texdef.name;
  1978.                 if (pname[0] == 0)
  1979.                     pname = "unnamed";
  1980.                 
  1981.                 fprintf (f, "%s %i %i %i ", pname,
  1982.                     (int)fa->texdef.shift[0], (int)fa->texdef.shift[1],
  1983.                     (int)fa->texdef.rotate);
  1984.                 
  1985.                 if (fa->texdef.scale[0] == (int)fa->texdef.scale[0])
  1986.                     fprintf (f, "%i ", (int)fa->texdef.scale[0]);
  1987.                 else
  1988.                     fprintf (f, "%f ", (float)fa->texdef.scale[0]);
  1989.                 if (fa->texdef.scale[1] == (int)fa->texdef.scale[1])
  1990.                     fprintf (f, "%i", (int)fa->texdef.scale[1]);
  1991.                 else
  1992.                     fprintf (f, "%f", (float)fa->texdef.scale[1]);
  1993.                 
  1994.                 fprintf (f, " %i %i %i", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
  1995.             }
  1996.             fprintf (f, "\n");
  1997.         }
  1998.         fprintf (f, "}\n");
  1999.     }
  2000. }
  2001.  
  2002. /*
  2003. =================
  2004. QERApp_MapPrintf_MEMFILE
  2005. callback for surface properties plugin
  2006. must fit a PFN_QERAPP_MAPPRINTF ( see isurfaceplugin.h )
  2007. =================
  2008. */
  2009. // carefully initialize !
  2010. CMemFile * g_pMemFile;
  2011. void WINAPI QERApp_MapPrintf_MEMFILE( char *text, ... )
  2012. {
  2013.     va_list argptr;
  2014.     char    buf[32768];
  2015.  
  2016.     va_start (argptr,text);
  2017.     vsprintf (buf, text,argptr);
  2018.     va_end (argptr);
  2019.  
  2020.     MemFile_fprintf( g_pMemFile, buf );
  2021. }
  2022.  
  2023. /*
  2024. =================
  2025. Brush_Write to a CMemFile*
  2026. save all brushes as Brush primitive format
  2027. =================
  2028. */
  2029. void Brush_Write (brush_t *b, CMemFile *pMemFile)
  2030. {
  2031.     epair_t *ep;
  2032.     face_t    *fa;
  2033.     char *pname;
  2034.     int        i;
  2035.     
  2036.     if (b->patchBrush)
  2037.     {
  2038.         Patch_Write(b->pPatch, pMemFile);
  2039.         return;
  2040.     }
  2041.     //++timo NOTE: it's not very difficult to add since the surface properties plugin
  2042.     // writes throught a printf-style function prototype
  2043.     if (g_qeglobals.bSurfacePropertiesPlugin)
  2044.     {
  2045.         Sys_Printf("WARNING: Brush_Write to a CMemFile and Surface Properties plugin not done\n");
  2046.     }
  2047.     if (g_qeglobals.m_bBrushPrimitMode)
  2048.     {
  2049.         // brush primitive format
  2050.         MemFile_fprintf (pMemFile, "{\nBrushDef\n{\n");
  2051.         // brush epairs
  2052.         if (b->epairs)
  2053.             for( ep = b->epairs ; ep ; ep=ep->next )
  2054.                 MemFile_fprintf (pMemFile, "\"%s\" \"%s\"\n", ep->key, ep->value );
  2055.         for (fa=b->brush_faces ; fa ; fa=fa->next)
  2056.         {
  2057.             // save planepts
  2058.             for (i=0 ; i<3 ; i++)
  2059.             {
  2060.                 MemFile_fprintf(pMemFile, "( ");
  2061.                 for (int j = 0; j < 3; j++)
  2062.                     if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
  2063.                         MemFile_fprintf(pMemFile, "%i ", static_cast<int>(fa->planepts[i][j]));
  2064.                     else
  2065.                         MemFile_fprintf(pMemFile, "%f ", fa->planepts[i][j]);
  2066.                 MemFile_fprintf(pMemFile, ") ");
  2067.             }
  2068.             // save texture coordinates
  2069.             MemFile_fprintf(pMemFile,"( ( ");
  2070.             for (i=0 ; i<3 ; i++)
  2071.                 if (fa->brushprimit_texdef.coords[0][i] == static_cast<int>(fa->brushprimit_texdef.coords[0][i]))
  2072.                     MemFile_fprintf(pMemFile,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[0][i]));
  2073.                 else
  2074.                     MemFile_fprintf(pMemFile,"%f ",fa->brushprimit_texdef.coords[0][i]);
  2075.             MemFile_fprintf(pMemFile,") ( ");
  2076.             for (i=0 ; i<3 ; i++)
  2077.                 if (fa->brushprimit_texdef.coords[1][i] == static_cast<int>(fa->brushprimit_texdef.coords[1][i]))
  2078.                     MemFile_fprintf(pMemFile,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[1][i]));
  2079.                 else
  2080.                     MemFile_fprintf(pMemFile,"%f ",fa->brushprimit_texdef.coords[1][i]);
  2081.             MemFile_fprintf(pMemFile,") ) ");
  2082.             // save texture attribs
  2083.       char *pName = strlen(fa->texdef.name) > 0 ? fa->texdef.name : "unnamed";
  2084.             MemFile_fprintf(pMemFile, "%s ", pName);
  2085.             MemFile_fprintf(pMemFile, "%i %i %i\n", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
  2086.         }
  2087.         MemFile_fprintf (pMemFile, "}\n}\n");
  2088.     }
  2089.     else
  2090.     {
  2091.         // old brushes format
  2092.         // also handle surface properties plugin
  2093.         MemFile_fprintf (pMemFile, "{\n");
  2094.         for (fa=b->brush_faces ; fa ; fa=fa->next)
  2095.         {
  2096.             for (i=0 ; i<3 ; i++)
  2097.             {
  2098.                 MemFile_fprintf(pMemFile, "( ");
  2099.                 for (int j = 0; j < 3; j++)
  2100.                 {
  2101.                     if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
  2102.                         MemFile_fprintf(pMemFile, "%i ", static_cast<int>(fa->planepts[i][j]));
  2103.                     else
  2104.                         MemFile_fprintf(pMemFile, "%f ", fa->planepts[i][j]);
  2105.                 }
  2106.                 MemFile_fprintf(pMemFile, ") ");
  2107.             }
  2108.             
  2109.             if (g_qeglobals.bSurfacePropertiesPlugin)
  2110.             {
  2111.                 g_pMemFile = pMemFile;
  2112. #ifdef _DEBUG
  2113.                 if (!fa->pData)
  2114.                     Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in Brush_Write\n");
  2115.                 else
  2116. #endif
  2117.                 GETPLUGINTEXDEF(fa)->WriteTexdef( QERApp_MapPrintf_MEMFILE );
  2118.             }
  2119.             else
  2120.             {
  2121.                 pname = fa->texdef.name;
  2122.                 if (pname[0] == 0)
  2123.                     pname = "unnamed";
  2124.                 
  2125.                 MemFile_fprintf (pMemFile, "%s %i %i %i ", pname,
  2126.                     (int)fa->texdef.shift[0], (int)fa->texdef.shift[1],
  2127.                     (int)fa->texdef.rotate);
  2128.                 
  2129.                 if (fa->texdef.scale[0] == (int)fa->texdef.scale[0])
  2130.                     MemFile_fprintf (pMemFile, "%i ", (int)fa->texdef.scale[0]);
  2131.                 else
  2132.                     MemFile_fprintf (pMemFile, "%f ", (float)fa->texdef.scale[0]);
  2133.                 if (fa->texdef.scale[1] == (int)fa->texdef.scale[1])
  2134.                     MemFile_fprintf (pMemFile, "%i", (int)fa->texdef.scale[1]);
  2135.                 else
  2136.                     MemFile_fprintf (pMemFile, "%f", (float)fa->texdef.scale[1]);
  2137.                 
  2138.                 MemFile_fprintf (pMemFile, " %i %i %i", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
  2139.             }
  2140.             MemFile_fprintf (pMemFile, "\n");
  2141.         }
  2142.         MemFile_fprintf (pMemFile, "}\n");
  2143.     }
  2144.     
  2145.     
  2146. }
  2147.  
  2148.  
  2149. /*
  2150. =============
  2151. Brush_Create
  2152.  
  2153. Create non-textured blocks for entities
  2154. The brush is NOT linked to any list
  2155. =============
  2156. */
  2157. brush_t    *Brush_Create (vec3_t mins, vec3_t maxs, texdef_t *texdef)
  2158. {
  2159.     int        i, j;
  2160.     vec3_t    pts[4][2];
  2161.     face_t    *f;
  2162.     brush_t    *b;
  2163.  
  2164.     // brush primitive mode : convert texdef to brushprimit_texdef ?
  2165.     // most of the time texdef is empty
  2166.     if (g_qeglobals.m_bBrushPrimitMode)
  2167.     {
  2168.         // check texdef is empty .. if there are cases it's not we need to write some conversion code
  2169.         if (texdef->shift[0]!=0 || texdef->shift[1]!=0 || texdef->scale[0]!=0 || texdef->scale[1]!=0 || texdef->rotate!=0)
  2170.             Sys_Printf("Warning : non-zero texdef detected in Brush_Create .. need brush primitive conversion\n");
  2171.     }
  2172.  
  2173.     for (i=0 ; i<3 ; i++)
  2174.     {
  2175.         if (maxs[i] < mins[i])
  2176.             Error ("Brush_InitSolid: backwards");
  2177.     }
  2178.  
  2179.     b = Brush_Alloc();
  2180.     
  2181.     pts[0][0][0] = mins[0];
  2182.     pts[0][0][1] = mins[1];
  2183.     
  2184.     pts[1][0][0] = mins[0];
  2185.     pts[1][0][1] = maxs[1];
  2186.     
  2187.     pts[2][0][0] = maxs[0];
  2188.     pts[2][0][1] = maxs[1];
  2189.     
  2190.     pts[3][0][0] = maxs[0];
  2191.     pts[3][0][1] = mins[1];
  2192.     
  2193.     for (i=0 ; i<4 ; i++)
  2194.     {
  2195.         pts[i][0][2] = mins[2];
  2196.         pts[i][1][0] = pts[i][0][0];
  2197.         pts[i][1][1] = pts[i][0][1];
  2198.         pts[i][1][2] = maxs[2];
  2199.     }
  2200.  
  2201.     for (i=0 ; i<4 ; i++)
  2202.     {
  2203.         f = Face_Alloc();
  2204.         f->texdef = *texdef;
  2205.         f->texdef.flags &= ~SURF_KEEP;
  2206.         f->texdef.contents &= ~CONTENTS_KEEP;
  2207.         f->next = b->brush_faces;
  2208.         b->brush_faces = f;
  2209.         j = (i+1)%4;
  2210.  
  2211.         VectorCopy (pts[j][1], f->planepts[0]);
  2212.         VectorCopy (pts[i][1], f->planepts[1]);
  2213.         VectorCopy (pts[i][0], f->planepts[2]);
  2214.     }
  2215.     
  2216.     f = Face_Alloc();
  2217.     f->texdef = *texdef;
  2218.     f->texdef.flags &= ~SURF_KEEP;
  2219.     f->texdef.contents &= ~CONTENTS_KEEP;
  2220.     f->next = b->brush_faces;
  2221.     b->brush_faces = f;
  2222.  
  2223.     VectorCopy (pts[0][1], f->planepts[0]);
  2224.     VectorCopy (pts[1][1], f->planepts[1]);
  2225.     VectorCopy (pts[2][1], f->planepts[2]);
  2226.  
  2227.     f = Face_Alloc();
  2228.     f->texdef = *texdef;
  2229.     f->texdef.flags &= ~SURF_KEEP;
  2230.     f->texdef.contents &= ~CONTENTS_KEEP;
  2231.     f->next = b->brush_faces;
  2232.     b->brush_faces = f;
  2233.  
  2234.     VectorCopy (pts[2][0], f->planepts[0]);
  2235.     VectorCopy (pts[1][0], f->planepts[1]);
  2236.     VectorCopy (pts[0][0], f->planepts[2]);
  2237.  
  2238.     return b;
  2239. }
  2240.  
  2241. /*
  2242. =============
  2243. Brush_CreatePyramid
  2244.  
  2245. Create non-textured pyramid for light entities
  2246. The brush is NOT linked to any list
  2247. =============
  2248. */
  2249. brush_t    *Brush_CreatePyramid (vec3_t mins, vec3_t maxs, texdef_t *texdef)
  2250. {
  2251.     //++timo handle new brush primitive ? return here ??
  2252.     return Brush_Create(mins, maxs, texdef);
  2253.  
  2254.     for (int i=0 ; i<3 ; i++)
  2255.         if (maxs[i] < mins[i])
  2256.             Error ("Brush_InitSolid: backwards");
  2257.  
  2258.     brush_t* b = Brush_Alloc();
  2259.  
  2260.     vec3_t corners[4];
  2261.  
  2262.     float fMid = Q_rint(mins[2] + (Q_rint((maxs[2] - mins[2]) / 2)));
  2263.  
  2264.     corners[0][0] = mins[0];
  2265.     corners[0][1] = mins[1];
  2266.     corners[0][2] = fMid;
  2267.  
  2268.     corners[1][0] = mins[0];
  2269.     corners[1][1] = maxs[1];
  2270.     corners[1][2] = fMid;
  2271.  
  2272.     corners[2][0] = maxs[0];
  2273.     corners[2][1] = maxs[1];
  2274.     corners[2][2] = fMid;
  2275.  
  2276.     corners[3][0] = maxs[0];
  2277.     corners[3][1] = mins[1];
  2278.     corners[3][2] = fMid;
  2279.  
  2280.     vec3_t top, bottom;
  2281.  
  2282.     top[0] = Q_rint(mins[0] + ((maxs[0] - mins[0]) / 2));
  2283.     top[1] = Q_rint(mins[1] + ((maxs[1] - mins[1]) / 2));
  2284.     top[2] = Q_rint(maxs[2]);
  2285.  
  2286.     VectorCopy(top, bottom);
  2287.     bottom[2] = mins[2];
  2288.  
  2289.     // sides
  2290.     for (i = 0; i < 4; i++)
  2291.     {
  2292.         face_t* f = Face_Alloc();
  2293.         f->texdef = *texdef;
  2294.         f->texdef.flags &= ~SURF_KEEP;
  2295.         f->texdef.contents &= ~CONTENTS_KEEP;
  2296.         f->next = b->brush_faces;
  2297.         b->brush_faces = f;
  2298.         int j = (i+1)%4;
  2299.  
  2300.         VectorCopy (top, f->planepts[0]);
  2301.         VectorCopy (corners[i], f->planepts[1]);
  2302.         VectorCopy(corners[j], f->planepts[2]);
  2303.  
  2304.         f = Face_Alloc();
  2305.         f->texdef = *texdef;
  2306.         f->texdef.flags &= ~SURF_KEEP;
  2307.         f->texdef.contents &= ~CONTENTS_KEEP;
  2308.         f->next = b->brush_faces;
  2309.         b->brush_faces = f;
  2310.  
  2311.         VectorCopy (bottom, f->planepts[2]);
  2312.         VectorCopy (corners[i], f->planepts[1]);
  2313.         VectorCopy(corners[j], f->planepts[0]);
  2314.     }
  2315.  
  2316.     return b;
  2317. }
  2318.  
  2319.  
  2320.  
  2321.  
  2322. /*
  2323. =============
  2324. Brush_MakeSided
  2325.  
  2326. Makes the current brush have the given number of 2d sides
  2327. =============
  2328. */
  2329. void Brush_MakeSided (int sides)
  2330. {
  2331.     int        i, axis;
  2332.     vec3_t    mins, maxs;
  2333.     brush_t    *b;
  2334.     texdef_t    *texdef;
  2335.     face_t    *f;
  2336.     vec3_t    mid;
  2337.     float    width;
  2338.     float    sv, cv;
  2339.  
  2340.     if (sides < 3)
  2341.     {
  2342.         Sys_Status ("Bad sides number", 0);
  2343.         return;
  2344.     }
  2345.  
  2346.     if (sides >= MAX_POINTS_ON_WINDING-4)
  2347.     {
  2348.         Sys_Printf("too many sides.\n");
  2349.         return;
  2350.     }
  2351.  
  2352.     if (!QE_SingleBrush ())
  2353.     {
  2354.         Sys_Status ("Must have a single brush selected", 0 );
  2355.         return;
  2356.     }
  2357.  
  2358.     b = selected_brushes.next;
  2359.     VectorCopy (b->mins, mins);
  2360.     VectorCopy (b->maxs, maxs);
  2361.     texdef = &g_qeglobals.d_texturewin.texdef;
  2362.  
  2363.     Brush_Free (b);
  2364.  
  2365.     if (g_pParentWnd->ActiveXY())
  2366.     {
  2367.         switch(g_pParentWnd->ActiveXY()->GetViewType())
  2368.         {
  2369.             case XY: axis = 2; break;
  2370.             case XZ: axis = 1; break;
  2371.             case YZ: axis = 0; break;
  2372.         }
  2373.     }
  2374.     else
  2375.     {
  2376.         axis = 2;
  2377.     }
  2378.  
  2379.     // find center of brush
  2380.     width = 8;
  2381.     for (i = 0; i < 3; i++)
  2382.     {
  2383.         mid[i] = (maxs[i] + mins[i]) * 0.5;
  2384.         if (i == axis) continue;
  2385.         if ((maxs[i] - mins[i]) * 0.5 > width)
  2386.             width = (maxs[i] - mins[i]) * 0.5;
  2387.     }
  2388.  
  2389.     b = Brush_Alloc();
  2390.         
  2391.     // create top face
  2392.     f = Face_Alloc();
  2393.     f->texdef = *texdef;
  2394.     f->next = b->brush_faces;
  2395.     b->brush_faces = f;
  2396.  
  2397.     f->planepts[2][(axis+1)%3] = mins[(axis+1)%3]; f->planepts[2][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[2][axis] = maxs[axis];
  2398.     f->planepts[1][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[1][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[1][axis] = maxs[axis];
  2399.     f->planepts[0][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[0][(axis+2)%3] = maxs[(axis+2)%3]; f->planepts[0][axis] = maxs[axis];
  2400.  
  2401.     // create bottom face
  2402.     f = Face_Alloc();
  2403.     f->texdef = *texdef;
  2404.     f->next = b->brush_faces;
  2405.     b->brush_faces = f;
  2406.  
  2407.     f->planepts[0][(axis+1)%3] = mins[(axis+1)%3]; f->planepts[0][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[0][axis] = mins[axis];
  2408.     f->planepts[1][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[1][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[1][axis] = mins[axis];
  2409.     f->planepts[2][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[2][(axis+2)%3] = maxs[(axis+2)%3]; f->planepts[2][axis] = mins[axis];
  2410.  
  2411.     for (i=0 ; i<sides ; i++)
  2412.     {
  2413.         f = Face_Alloc();
  2414.         f->texdef = *texdef;
  2415.         f->next = b->brush_faces;
  2416.         b->brush_faces = f;
  2417.  
  2418.         sv = sin (i*3.14159265*2/sides);
  2419.         cv = cos (i*3.14159265*2/sides);
  2420.  
  2421.         f->planepts[0][(axis+1)%3] = floor(mid[(axis+1)%3]+width*cv+0.5);
  2422.         f->planepts[0][(axis+2)%3] = floor(mid[(axis+2)%3]+width*sv+0.5);
  2423.         f->planepts[0][axis] = mins[axis];
  2424.  
  2425.         f->planepts[1][(axis+1)%3] = f->planepts[0][(axis+1)%3];
  2426.         f->planepts[1][(axis+2)%3] = f->planepts[0][(axis+2)%3];
  2427.         f->planepts[1][axis] = maxs[axis];
  2428.  
  2429.         f->planepts[2][(axis+1)%3] = floor(f->planepts[0][(axis+1)%3] - width*sv + 0.5);
  2430.         f->planepts[2][(axis+2)%3] = floor(f->planepts[0][(axis+2)%3] + width*cv + 0.5);
  2431.         f->planepts[2][axis] = maxs[axis];
  2432.     }
  2433.  
  2434.     Brush_AddToList (b, &selected_brushes);
  2435.  
  2436.     Entity_LinkBrush (world_entity, b);
  2437.  
  2438.     Brush_Build( b );
  2439.  
  2440.     Sys_UpdateWindows (W_ALL);
  2441. }
  2442.  
  2443.  
  2444.  
  2445. /*
  2446. =============
  2447. Brush_Free
  2448.  
  2449. Frees the brush with all of its faces and display list.
  2450. Unlinks the brush from whichever chain it is in.
  2451. Decrements the owner entity's brushcount.
  2452. Removes owner entity if this was the last brush
  2453. unless owner is the world.
  2454. Removes from groups
  2455. =============
  2456. */
  2457. void Brush_Free (brush_t *b, bool bRemoveNode)
  2458. {
  2459.     face_t    *f, *next;
  2460.     epair_t    *ep, *enext;
  2461.  
  2462.     // remove from group
  2463.     if (bRemoveNode)
  2464.         Group_RemoveBrush(b);
  2465.  
  2466.     // free the patch if it's there
  2467.     if (b->patchBrush)
  2468.     {
  2469.         Patch_Delete(b->pPatch);
  2470.     }
  2471.  
  2472.     // free faces
  2473.     for (f=b->brush_faces ; f ; f=next)
  2474.     {
  2475.         next = f->next;
  2476.         Face_Free( f );
  2477.     }
  2478.  
  2479.     //Timo : free brush epairs
  2480.     for (ep = b->epairs ; ep ; ep=enext )
  2481.     {
  2482.         enext = ep->next;
  2483.         free (ep->key);
  2484.         free (ep->value);
  2485.         free (ep);
  2486.     }
  2487.  
  2488.     // unlink from active/selected list
  2489.     if (b->next)
  2490.         Brush_RemoveFromList (b);
  2491.  
  2492.     // unlink from entity list
  2493.     if (b->onext)
  2494.         Entity_UnlinkBrush (b);
  2495.  
  2496.     free (b);
  2497. }
  2498.  
  2499. /*
  2500. =============
  2501. Face_MemorySize
  2502. =============
  2503. */
  2504. int Face_MemorySize(face_t *f )
  2505. {
  2506.     int size = 0;
  2507.  
  2508.     if (f->face_winding)
  2509.     {
  2510.         size += _msize(f->face_winding);
  2511.     }
  2512.     //f->texdef.~texdef_t();;
  2513.     size += _msize(f);
  2514.     return size;
  2515. }
  2516.  
  2517. /*
  2518. =============
  2519. Brush_MemorySize
  2520. =============
  2521. */
  2522. int Brush_MemorySize(brush_t *b)
  2523. {
  2524.     face_t    *f;
  2525.     epair_t    *ep;
  2526.     int size = 0;
  2527.  
  2528.     //
  2529.     if (b->patchBrush)
  2530.     {
  2531.         size += Patch_MemorySize(b->pPatch);
  2532.     }
  2533.     //
  2534.     for (f = b->brush_faces; f; f = f->next)
  2535.     {
  2536.         size += Face_MemorySize(f);
  2537.     }
  2538.     //
  2539.     for (ep = b->epairs; ep; ep = ep->next )
  2540.     {
  2541.         size += _msize(ep->key);
  2542.         size += _msize(ep->value);
  2543.         size += _msize(ep);
  2544.     }
  2545.     size += _msize(b);
  2546.     return size;
  2547. }
  2548.  
  2549.  
  2550. /*
  2551. ============
  2552. Brush_Clone
  2553.  
  2554. Does NOT add the new brush to any lists
  2555. ============
  2556. */
  2557. brush_t *Brush_Clone (brush_t *b)
  2558. {
  2559.     brush_t    *n = NULL;
  2560.     face_t    *f, *nf;
  2561.  
  2562.     if (b->patchBrush)
  2563.     {
  2564.         patchMesh_t *p = Patch_Duplicate(b->pPatch);
  2565.         Brush_RemoveFromList(p->pSymbiot);
  2566.         Entity_UnlinkBrush(p->pSymbiot);
  2567.         n = p->pSymbiot;
  2568.     }
  2569.     else
  2570.     {
  2571.       n = Brush_Alloc();
  2572.       n->numberId = g_nBrushId++;
  2573.         n->owner = b->owner;
  2574.         for (f=b->brush_faces ; f ; f=f->next)
  2575.         {
  2576.             nf = Face_Clone( f );
  2577.             nf->next = n->brush_faces;
  2578.             n->brush_faces = nf;
  2579.         }
  2580.     }
  2581.  
  2582.     return n;
  2583. }
  2584.  
  2585.  
  2586.  
  2587. /*
  2588. ============
  2589. Brush_Clone
  2590.  
  2591. Does NOT add the new brush to any lists
  2592. ============
  2593. */
  2594. brush_t *Brush_FullClone(brush_t *b)
  2595. {
  2596.     brush_t    *n = NULL;
  2597.     face_t *f, *nf, *f2, *nf2;
  2598.     int j;
  2599.  
  2600.     if (b->patchBrush)
  2601.     {
  2602.         patchMesh_t *p = Patch_Duplicate(b->pPatch);
  2603.         Brush_RemoveFromList(p->pSymbiot);
  2604.         Entity_UnlinkBrush(p->pSymbiot);
  2605.         n = p->pSymbiot;
  2606.         n->owner = b->owner;
  2607.         Brush_Build(n);
  2608.     }
  2609.     else
  2610.     {
  2611.       n = Brush_Alloc();
  2612.        n->numberId = g_nBrushId++;
  2613.         n->owner = b->owner;
  2614.         VectorCopy(b->mins, n->mins);
  2615.         VectorCopy(b->maxs, n->maxs);
  2616.         //
  2617.         for (f = b->brush_faces; f; f = f->next)
  2618.         {
  2619.             if (f->original) continue;
  2620.             nf = Face_FullClone(f);
  2621.             nf->next = n->brush_faces;
  2622.             n->brush_faces = nf;
  2623.             //copy all faces that have the original set to this face
  2624.             for (f2 = b->brush_faces; f2; f2 = f2->next)
  2625.             {
  2626.                 if (f2->original == f)
  2627.                 {
  2628.                     nf2 = Face_FullClone(f2);
  2629.                     nf2->next = n->brush_faces;
  2630.                     n->brush_faces = nf2;
  2631.                     //set original
  2632.                     nf2->original = nf;
  2633.                 }
  2634.             }
  2635.         }
  2636.         for (nf = n->brush_faces; nf; nf = nf->next)
  2637.         {
  2638.             Face_SetColor(n, nf, 1.0);
  2639.             if (nf->face_winding)
  2640.       {
  2641.         if (g_qeglobals.m_bBrushPrimitMode)
  2642.                 EmitBrushPrimitTextureCoordinates(nf,nf->face_winding);
  2643.         else
  2644.         {
  2645.                   for (j = 0; j < nf->face_winding->numpoints; j++)
  2646.                       EmitTextureCoordinates(nf->face_winding->points[j], nf->d_texture, nf);
  2647.         }
  2648.       }
  2649.         }
  2650.   }
  2651.     return n;
  2652. }
  2653.  
  2654. /*
  2655. ==============
  2656. Brush_Ray
  2657.  
  2658. Itersects a ray with a brush
  2659. Returns the face hit and the distance along the ray the intersection occured at
  2660. Returns NULL and 0 if not hit at all
  2661. ==============
  2662. */
  2663. face_t *Brush_Ray (vec3_t origin, vec3_t dir, brush_t *b, float *dist)
  2664. {
  2665.     face_t    *f, *firstface;
  2666.     vec3_t    p1, p2;
  2667.     float    frac, d1, d2;
  2668.     int        i;
  2669.  
  2670.     VectorCopy (origin, p1);
  2671.     for (i=0 ; i<3 ; i++)
  2672.         p2[i] = p1[i] + dir[i]*16384;
  2673.  
  2674.     for (f=b->brush_faces ; f ; f=f->next)
  2675.     {
  2676.         d1 = DotProduct (p1, f->plane.normal) - f->plane.dist;
  2677.         d2 = DotProduct (p2, f->plane.normal) - f->plane.dist;
  2678.         if (d1 >= 0 && d2 >= 0)
  2679.         {
  2680.             *dist = 0;
  2681.             return NULL;    // ray is on front side of face
  2682.         }
  2683.         if (d1 <=0 && d2 <= 0)
  2684.             continue;
  2685.     // clip the ray to the plane
  2686.         frac = d1 / (d1 - d2);
  2687.         if (d1 > 0)
  2688.         {
  2689.             firstface = f;
  2690.             for (i=0 ; i<3 ; i++)
  2691.                 p1[i] = p1[i] + frac *(p2[i] - p1[i]);
  2692.         }
  2693.         else
  2694.         {
  2695.             for (i=0 ; i<3 ; i++)
  2696.                 p2[i] = p1[i] + frac *(p2[i] - p1[i]);
  2697.         }
  2698.     }
  2699.  
  2700.     // find distance p1 is along dir
  2701.     VectorSubtract (p1, origin, p1);
  2702.     d1 = DotProduct (p1, dir);
  2703.  
  2704.     *dist = d1;
  2705.  
  2706.     return firstface;
  2707. }
  2708.  
  2709. //PGM
  2710. face_t *Brush_Point (vec3_t origin, brush_t *b)
  2711. {
  2712.     face_t    *f;
  2713.     float    d1;
  2714.  
  2715.     for (f=b->brush_faces ; f ; f=f->next)
  2716.     {
  2717.         d1 = DotProduct (origin, f->plane.normal) - f->plane.dist;
  2718.         if (d1 > 0)
  2719.         {
  2720.             return NULL;    // point is on front side of face
  2721.         }
  2722.     }
  2723.  
  2724.     return b->brush_faces;
  2725. }
  2726. //PGM
  2727.  
  2728.  
  2729. void    Brush_AddToList (brush_t *b, brush_t *list)
  2730. {
  2731.     if (b->next || b->prev)
  2732.         Error ("Brush_AddToList: allready linked");
  2733.     
  2734.     if (list == &selected_brushes || list == &active_brushes)
  2735.     {
  2736.         if (b->patchBrush && list == &selected_brushes)
  2737.         {
  2738.             Patch_Select(b->pPatch);
  2739.         }
  2740.     }
  2741.     b->next = list->next;
  2742.     list->next->prev = b;
  2743.     list->next = b;
  2744.     b->prev = list;
  2745.     
  2746.     // TTimo messaging
  2747.     DispatchRadiantMsg( RADIANT_SELECTION );    
  2748. }
  2749.  
  2750. void    Brush_RemoveFromList (brush_t *b)
  2751. {
  2752.     if (!b->next || !b->prev)
  2753.         Error ("Brush_RemoveFromList: not linked");
  2754.     
  2755.     if (b->patchBrush)
  2756.     {
  2757.         Patch_Deselect(b->pPatch);
  2758.         //Patch_Deselect(b->nPatchID);
  2759.     }
  2760.     b->next->prev = b->prev;
  2761.     b->prev->next = b->next;
  2762.     b->next = b->prev = NULL;
  2763. }
  2764.  
  2765. /*
  2766. ===============
  2767. SetFaceTexdef
  2768.  
  2769. Doesn't set the curve flags
  2770.  
  2771. NOTE : ( TTimo )
  2772.     never trust f->d_texture here, f->texdef and f->d_texture are out of sync when called by Brush_SetTexture
  2773.     use Texture_ForName() to find the right shader
  2774.     FIXME : send the right shader ( qtexture_t * ) in the parameters ?
  2775.  
  2776. TTimo: surface plugin, added an IPluginTexdef* parameter
  2777.         if not NULL, get ->Copy() of it into the face ( and remember to hook )
  2778.         if NULL, ask for a default
  2779. ===============
  2780. */
  2781. void SetFaceTexdef (brush_t *b, face_t *f, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef* pPlugTexdef) {
  2782.     int        oldFlags;
  2783.     int        oldContents;
  2784.     face_t    *tf;
  2785.  
  2786.     oldFlags = f->texdef.flags;
  2787.     oldContents = f->texdef.contents;
  2788.     if (g_qeglobals.m_bBrushPrimitMode)
  2789.     {
  2790.         f->texdef = *texdef;
  2791.         ConvertTexMatWithQTexture( brushprimit_texdef, NULL, &f->brushprimit_texdef, Texture_ForName( f->texdef.name ) );
  2792.     }
  2793.     else
  2794.         if (bFitScale)
  2795.         {
  2796.             f->texdef = *texdef;
  2797.             // fit the scaling of the texture on the actual plane
  2798.             vec3_t p1,p2,p3; // absolute coordinates
  2799.             // compute absolute coordinates
  2800.             ComputeAbsolute(f,p1,p2,p3);
  2801.             // compute the scale
  2802.             vec3_t vx,vy;
  2803.             VectorSubtract(p2,p1,vx);
  2804.             VectorNormalize(vx);
  2805.             VectorSubtract(p3,p1,vy);
  2806.             VectorNormalize(vy);
  2807.             // assign scale
  2808.             VectorScale(vx,texdef->scale[0],vx);
  2809.             VectorScale(vy,texdef->scale[1],vy);
  2810.             VectorAdd(p1,vx,p2);
  2811.             VectorAdd(p1,vy,p3);
  2812.             // compute back shift scale rot
  2813.             AbsoluteToLocal(f->plane,f,p1,p2,p3);
  2814.         }
  2815.         else
  2816.             f->texdef = *texdef;
  2817.     f->texdef.flags = (f->texdef.flags & ~SURF_KEEP) | (oldFlags & SURF_KEEP);
  2818.     f->texdef.contents = (f->texdef.contents & ~CONTENTS_KEEP) | (oldContents & CONTENTS_KEEP);
  2819.  
  2820.     // surface plugin
  2821.     if (g_qeglobals.bSurfacePropertiesPlugin)
  2822.     {
  2823. #ifdef _DEBUG
  2824.         if (!f->pData)
  2825.             Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in SetFaceTexdef\n");
  2826.         else
  2827. #endif
  2828.             GETPLUGINTEXDEF(f)->DecRef();
  2829.         IPluginTexdef *pTexdef = NULL;
  2830.         if ( pPlugTexdef )
  2831.         {
  2832.             pTexdef = pPlugTexdef->Copy();
  2833.             pTexdef->Hook( f );
  2834.         }
  2835.         else
  2836.             pTexdef = g_SurfaceTable.m_pfnTexdefAlloc( f );
  2837.         f->pData = pTexdef;
  2838.     }
  2839.  
  2840.     // if this is a curve face, set all other curve faces to the same texdef
  2841.     if (f->texdef.flags & SURF_CURVE) 
  2842.     {
  2843.         for (tf = b->brush_faces ; tf ; tf = tf->next) 
  2844.         {
  2845.             if (tf->texdef.flags & SURF_CURVE) 
  2846.                 tf->texdef = f->texdef;
  2847.         }
  2848.     }
  2849. }
  2850.  
  2851.  
  2852. void Brush_SetTexture (brush_t *b, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef* pTexdef)
  2853. {
  2854.     for (face_t* f = b->brush_faces ; f ; f = f->next) 
  2855.     {
  2856.         SetFaceTexdef (b, f, texdef, brushprimit_texdef, bFitScale, pTexdef);
  2857.     }
  2858.     Brush_Build( b );
  2859.     if (b->patchBrush)
  2860.     {
  2861.         //++timo clean
  2862. //        Sys_Printf("WARNING: Brush_SetTexture needs surface plugin code for patches\n");
  2863.         Patch_SetTexture(b->pPatch, texdef, pTexdef );
  2864.     }
  2865. }
  2866.  
  2867.  
  2868. qboolean ClipLineToFace (vec3_t p1, vec3_t p2, face_t *f)
  2869. {
  2870.     float    d1, d2, fr;
  2871.     int        i;
  2872.     float    *v;
  2873.  
  2874.     d1 = DotProduct (p1, f->plane.normal) - f->plane.dist;
  2875.     d2 = DotProduct (p2, f->plane.normal) - f->plane.dist;
  2876.  
  2877.     if (d1 >= 0 && d2 >= 0)
  2878.         return false;        // totally outside
  2879.     if (d1 <= 0 && d2 <= 0)
  2880.         return true;        // totally inside
  2881.  
  2882.     fr = d1 / (d1 - d2);
  2883.  
  2884.     if (d1 > 0)
  2885.         v = p1;
  2886.     else
  2887.         v = p2;
  2888.  
  2889.     for (i=0 ; i<3 ; i++)
  2890.         v[i] = p1[i] + fr*(p2[i] - p1[i]);
  2891.  
  2892.     return true;
  2893. }
  2894.  
  2895.  
  2896. int AddPlanept (float *f)
  2897. {
  2898.     int        i;
  2899.  
  2900.     for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
  2901.         if (g_qeglobals.d_move_points[i] == f)
  2902.             return 0;
  2903.     g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = f;
  2904.     return 1;
  2905. }
  2906.  
  2907. /*
  2908. ==============
  2909. Brush_SelectFaceForDragging
  2910.  
  2911. Adds the faces planepts to move_points, and
  2912. rotates and adds the planepts of adjacent face if shear is set
  2913. ==============
  2914. */
  2915. void Brush_SelectFaceForDragging (brush_t *b, face_t *f, qboolean shear)
  2916. {
  2917.     int        i;
  2918.     face_t    *f2;
  2919.     winding_t    *w;
  2920.     float    d;
  2921.     brush_t    *b2;
  2922.     int        c;
  2923.  
  2924.     if (b->owner->eclass->fixedsize)
  2925.         return;
  2926.  
  2927.     c = 0;
  2928.     for (i=0 ; i<3 ; i++)
  2929.         c += AddPlanept (f->planepts[i]);
  2930.     if (c == 0)
  2931.         return;        // allready completely added
  2932.  
  2933.     // select all points on this plane in all brushes the selection
  2934.     for (b2=selected_brushes.next ; b2 != &selected_brushes ; b2 = b2->next)
  2935.     {
  2936.         if (b2 == b)
  2937.             continue;
  2938.         for (f2=b2->brush_faces ; f2 ; f2=f2->next)
  2939.         {
  2940.             for (i=0 ; i<3 ; i++)
  2941.                 if (fabs(DotProduct(f2->planepts[i], f->plane.normal)
  2942.                 -f->plane.dist) > ON_EPSILON)
  2943.                     break;
  2944.             if (i==3)
  2945.             {    // move this face as well
  2946.                 Brush_SelectFaceForDragging (b2, f2, shear);
  2947.                 break;
  2948.             }
  2949.         }
  2950.     }
  2951.  
  2952.  
  2953.     // if shearing, take all the planes adjacent to 
  2954.     // selected faces and rotate their points so the
  2955.     // edge clipped by a selcted face has two of the points
  2956.     if (!shear)
  2957.         return;
  2958.  
  2959.     for (f2=b->brush_faces ; f2 ; f2=f2->next)
  2960.     {
  2961.         if (f2 == f)
  2962.             continue;
  2963.         w = Brush_MakeFaceWinding (b, f2);
  2964.         if (!w)
  2965.             continue;
  2966.  
  2967.         // any points on f will become new control points
  2968.         for (i=0 ; i<w->numpoints ; i++)
  2969.         {
  2970.             d = DotProduct (w->points[i], f->plane.normal) 
  2971.                 - f->plane.dist;
  2972.             if (d > -ON_EPSILON && d < ON_EPSILON)
  2973.                 break;
  2974.         }
  2975.  
  2976.         //
  2977.         // if none of the points were on the plane,
  2978.         // leave it alone
  2979.         //
  2980.         if (i != w->numpoints)
  2981.         {
  2982.             if (i == 0)
  2983.             {    // see if the first clockwise point was the
  2984.                 // last point on the winding
  2985.                 d = DotProduct (w->points[w->numpoints-1]
  2986.                     , f->plane.normal) - f->plane.dist;
  2987.                 if (d > -ON_EPSILON && d < ON_EPSILON)
  2988.                     i = w->numpoints - 1;
  2989.             }
  2990.  
  2991.             AddPlanept (f2->planepts[0]);
  2992.  
  2993.             VectorCopy (w->points[i], f2->planepts[0]);
  2994.             if (++i == w->numpoints)
  2995.                 i = 0;
  2996.             
  2997.             // see if the next point is also on the plane
  2998.             d = DotProduct (w->points[i]
  2999.                 , f->plane.normal) - f->plane.dist;
  3000.             if (d > -ON_EPSILON && d < ON_EPSILON)
  3001.                 AddPlanept (f2->planepts[1]);
  3002.  
  3003.             VectorCopy (w->points[i], f2->planepts[1]);
  3004.             if (++i == w->numpoints)
  3005.                 i = 0;
  3006.  
  3007.             // the third point is never on the plane
  3008.  
  3009.             VectorCopy (w->points[i], f2->planepts[2]);
  3010.         }
  3011.  
  3012.         free(w);
  3013.     }
  3014. }
  3015.  
  3016. /*
  3017. ==============
  3018. Brush_SideSelect
  3019.  
  3020. The mouse click did not hit the brush, so grab one or more side
  3021. planes for dragging
  3022. ==============
  3023. */
  3024. void Brush_SideSelect (brush_t *b, vec3_t origin, vec3_t dir
  3025.                        , qboolean shear)
  3026. {
  3027.     face_t    *f, *f2;
  3028.     vec3_t    p1, p2;
  3029.  
  3030.   //if (b->patchBrush)
  3031.   //  return;
  3032.     //Patch_SideSelect(b->nPatchID, origin, dir);
  3033.     for (f=b->brush_faces ; f ; f=f->next)
  3034.     {
  3035.         VectorCopy (origin, p1);
  3036.         VectorMA (origin, 16384, dir, p2);
  3037.  
  3038.         for (f2=b->brush_faces ; f2 ; f2=f2->next)
  3039.         {
  3040.             if (f2 == f)
  3041.                 continue;
  3042.             ClipLineToFace (p1, p2, f2);
  3043.         }
  3044.  
  3045.         if (f2)
  3046.             continue;
  3047.  
  3048.         if (VectorCompare (p1, origin))
  3049.             continue;
  3050.         if (ClipLineToFace (p1, p2, f))
  3051.             continue;
  3052.  
  3053.         Brush_SelectFaceForDragging (b, f, shear);
  3054.     }
  3055.  
  3056.     
  3057. }
  3058.  
  3059. void Brush_BuildWindings( brush_t *b, bool bSnap )
  3060. {
  3061.     winding_t *w;
  3062.     face_t    *face;
  3063.     vec_t      v;
  3064.  
  3065.     if (bSnap)
  3066.         Brush_SnapPlanepts( b );
  3067.  
  3068.     // clear the mins/maxs bounds
  3069.     b->mins[0] = b->mins[1] = b->mins[2] = 99999;
  3070.     b->maxs[0] = b->maxs[1] = b->maxs[2] = -99999;
  3071.  
  3072.     Brush_MakeFacePlanes (b);
  3073.  
  3074.     face = b->brush_faces;
  3075.  
  3076.     float fCurveColor = 1.0;
  3077.  
  3078.     for ( ; face ; face=face->next)
  3079.     {
  3080.         int i, j;
  3081.         free(face->face_winding);
  3082.         w = face->face_winding = Brush_MakeFaceWinding (b, face);
  3083.         face->d_texture = Texture_ForName( face->texdef.name );
  3084.  
  3085.         if (!w)
  3086.             continue;
  3087.     
  3088.         for (i=0 ; i<w->numpoints ; i++)
  3089.         {
  3090.             // add to bounding box
  3091.             for (j=0 ; j<3 ; j++)
  3092.             {
  3093.                 v = w->points[i][j];
  3094.                 if (v > b->maxs[j])
  3095.                     b->maxs[j] = v;
  3096.                 if (v < b->mins[j])
  3097.                     b->mins[j] = v;
  3098.             }
  3099.         }
  3100.         // setup s and t vectors, and set color
  3101.         //if (!g_PrefsDlg.m_bGLLighting)
  3102.     //{
  3103.           Face_SetColor (b, face, fCurveColor);
  3104.     //}
  3105.  
  3106.         fCurveColor -= .10;
  3107.         if (fCurveColor <= 0)
  3108.             fCurveColor = 1.0;
  3109.  
  3110.         // computing ST coordinates for the windings
  3111.         if (g_qeglobals.m_bBrushPrimitMode)
  3112.         {
  3113.             if (g_qeglobals.bNeedConvert)
  3114.             {
  3115.                 // we have parsed old brushes format and need conversion
  3116.                 // convert old brush texture representation to new format
  3117.                 FaceToBrushPrimitFace(face);
  3118. #ifdef _DEBUG
  3119.                 // use old texture coordinates code to check against
  3120.                 for (i=0 ; i<w->numpoints ; i++)
  3121.                     EmitTextureCoordinates( w->points[i], face->d_texture, face);
  3122. #endif
  3123.             }
  3124.             // use new texture representation to compute texture coordinates
  3125.             // in debug mode we will check against old code and warn if there are differences
  3126.             EmitBrushPrimitTextureCoordinates(face,w);
  3127.         }
  3128.         else
  3129.         {
  3130.             for (i=0 ; i<w->numpoints ; i++)
  3131.                 EmitTextureCoordinates( w->points[i], face->d_texture, face);
  3132.         }
  3133.     }
  3134. }
  3135.  
  3136. /*
  3137. ==================
  3138. Brush_RemoveEmptyFaces
  3139.  
  3140. Frees any overconstraining faces
  3141. ==================
  3142. */
  3143. void Brush_RemoveEmptyFaces ( brush_t *b )
  3144. {
  3145.     face_t    *f, *next;
  3146.  
  3147.     f = b->brush_faces;
  3148.     b->brush_faces = NULL;
  3149.  
  3150.     for ( ; f ; f=next)
  3151.     {
  3152.         next = f->next;
  3153.         if (!f->face_winding)
  3154.             Face_Free (f);
  3155.         else
  3156.         {
  3157.             f->next = b->brush_faces;
  3158.             b->brush_faces = f;
  3159.         }
  3160.  
  3161.     }
  3162. }
  3163.  
  3164. void Brush_SnapToGrid(brush_t *pb)
  3165. {
  3166.     for (face_t *f = pb->brush_faces ; f; f = f->next)
  3167.     {
  3168.         for (int i = 0 ;i < 3 ;i++)
  3169.         {
  3170.             for (int j = 0 ;j < 3 ; j++)
  3171.             {
  3172.                 f->planepts[i][j] = floor (f->planepts[i][j] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
  3173.             }
  3174.         }
  3175.     }
  3176.     Brush_Build(pb);
  3177. }
  3178.  
  3179. void Brush_Rotate(brush_t *b, vec3_t vAngle, vec3_t vOrigin, bool bBuild)
  3180. {
  3181.     for (face_t* f=b->brush_faces ; f ; f=f->next)
  3182.     {
  3183.         for (int i=0 ; i<3 ; i++)
  3184.         {
  3185.             VectorRotate(f->planepts[i], vAngle, vOrigin, f->planepts[i]);
  3186.         }
  3187.     }
  3188.     if (bBuild)
  3189.     {
  3190.         Brush_Build(b, false, false);
  3191.     }
  3192. }
  3193.  
  3194. void Brush_Center(brush_t *b, vec3_t vNewCenter)
  3195. {
  3196.   vec3_t vMid;
  3197.   // get center of the brush
  3198.   for (int j = 0; j < 3; j++)
  3199.   {
  3200.     vMid[j] = b->mins[j] + abs((b->maxs[j] - b->mins[j]) * 0.5);
  3201.   }
  3202.   // calc distance between centers
  3203.   VectorSubtract(vNewCenter, vMid, vMid);
  3204.   Brush_Move(b, vMid, true);
  3205.  
  3206. }
  3207.  
  3208. // only designed for fixed size entity brushes
  3209. void Brush_Resize(brush_t *b, vec3_t vMin, vec3_t vMax)
  3210. {
  3211.   brush_t *b2 = Brush_Create(vMin, vMax, &b->brush_faces->texdef);
  3212.  
  3213.   face_t *next;
  3214.     for (face_t *f=b->brush_faces ; f ; f=next)
  3215.     {
  3216.         next = f->next;
  3217.         Face_Free( f );
  3218.     }
  3219.  
  3220.   b->brush_faces = b2->brush_faces;
  3221.  
  3222.     // unlink from active/selected list
  3223.     if (b2->next)
  3224.   Brush_RemoveFromList (b2);
  3225.   free(b2);
  3226.   Brush_Build(b, true);
  3227. }
  3228.  
  3229.  
  3230. eclass_t* HasModel(brush_t *b)
  3231. {
  3232.   vec3_t vMin, vMax;
  3233.   vMin[0] = vMin[1] = vMin[2] = 9999;
  3234.   vMax[0] = vMax[1] = vMax[2] = -9999;
  3235.  
  3236.   if (b->owner->md3Class != NULL)
  3237.   {
  3238.     return b->owner->md3Class;
  3239.   }
  3240.  
  3241.   if (Eclass_hasModel(b->owner->eclass, vMin, vMax))
  3242.   {
  3243.     return b->owner->eclass;
  3244.   }
  3245.  
  3246.   eclass_t *e = NULL;
  3247.   // FIXME: entity needs to track whether a cache hit failed and not ask again
  3248.   if (b->owner->eclass->nShowFlags & ECLASS_MISCMODEL)
  3249.   {
  3250.     char *pModel = ValueForKey(b->owner, "model");
  3251.     if (pModel != NULL && strlen(pModel) > 0)
  3252.     {
  3253.       e = GetCachedModel(b->owner, pModel, vMin, vMax);
  3254.       if (e != NULL)
  3255.       {
  3256.         // we need to scale the brush to the proper size based on the model load
  3257.         // recreate brush just like in load/save
  3258.  
  3259.             VectorAdd (vMin, b->owner->origin, vMin);
  3260.             VectorAdd (vMax, b->owner->origin, vMax);
  3261.  
  3262.         Brush_Resize(b, vMin, vMax);
  3263.  
  3264. /*
  3265.         //
  3266.         vec3_t vTemp, vTemp2;
  3267.         VectorSubtract(b->maxs, b->mins, vTemp);
  3268.         VectorSubtract(vMax, vMin, vTemp2);
  3269.         for (int i = 0; i < 3; i++)
  3270.         {
  3271.           if (vTemp[i] != 0)
  3272.           {
  3273.             vTemp2[i] /= vTemp[i];
  3274.           }
  3275.         }
  3276.         vec3_t vMid, vMid2;
  3277.         vMid[0] = vMid[1] = vMid[2] = 0.0;
  3278.         vMid2[0] = vMid2[1] = vMid2[2] = 0.0;
  3279.  
  3280.         for (int j = 0; j < 3; j++)
  3281.         {
  3282.           vMid2[j] = b->mins[j] + abs((b->maxs[j] - b->mins[j]) * 0.5);
  3283.         }
  3284.  
  3285.         //VectorSubtract(vMid2, vMid, vMid2);
  3286.  
  3287.             for (face_t* f=b->brush_faces ; f ; f=f->next)
  3288.             {
  3289.                 for (int i=0 ; i<3 ; i++)
  3290.                 {
  3291.  
  3292.             // scale
  3293.             VectorSubtract(f->planepts[i], vMid2, f->planepts[i]);
  3294.             f->planepts[i][0] *= vTemp2[0];
  3295.             f->planepts[i][1] *= vTemp2[1];
  3296.             f->planepts[i][2] *= vTemp2[2];
  3297.             VectorAdd(f->planepts[i], vMid2, f->planepts[i]);
  3298.           }
  3299.         }
  3300.  
  3301.         //Brush_Center(b, b->owner->origin);
  3302.  
  3303.         //Brush_SnapToGrid(b);
  3304. /*
  3305.         float a = FloatForKey (b->owner, "angle");
  3306.         if (a)
  3307.         {
  3308.           vec3_t vAngle;
  3309.           vAngle[0] = vAngle[1] = 0;
  3310.           vAngle[2] = a;
  3311.           Brush_Rotate(b, vAngle, b->owner->origin);
  3312.         }
  3313.         else
  3314.         {
  3315.           Brush_Build(b, true);
  3316. */
  3317. //        }
  3318.  
  3319.         b->bModelFailed = false;
  3320.       }
  3321.       else
  3322.       {
  3323.         b->bModelFailed = true;
  3324.       }
  3325.     } 
  3326.   }
  3327.   return e;
  3328. }
  3329.  
  3330. static bool g_bInPaintedModel = false;
  3331. static bool g_bDoIt = false;
  3332. bool PaintedModel(brush_t *b, bool bOkToTexture)
  3333. {
  3334.     if (g_bInPaintedModel)
  3335.     { 
  3336.       return true;
  3337.     }
  3338.     
  3339.     if (g_PrefsDlg.m_nEntityShowState == ENTITY_BOX || b->bModelFailed)
  3340.     {
  3341.       return false;
  3342.     }
  3343.     else if (!IsBrushSelected(b) && (g_PrefsDlg.m_nEntityShowState & ENTITY_SELECTED_ONLY))
  3344.     {
  3345.         return false;
  3346.     }
  3347.  
  3348.     g_bInPaintedModel = true;
  3349.     bool bReturn = false;
  3350.  
  3351.     eclass_t *pEclass = HasModel(b);
  3352.  
  3353.     if (pEclass)
  3354.     {
  3355.       qglPushAttrib(GL_ALL_ATTRIB_BITS);
  3356.       entitymodel *model = pEclass->model;
  3357.  
  3358.  
  3359.       float a = FloatForKey (b->owner, "angle");
  3360.       while (model != NULL)
  3361.       {
  3362.         if (bOkToTexture == false || g_PrefsDlg.m_nEntityShowState & ENTITY_WIREFRAME || model->nTextureBind == -1)    // skinned
  3363.         {
  3364.             qglDisable( GL_CULL_FACE );
  3365.             qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
  3366.             qglDisable(GL_TEXTURE_2D);
  3367.           qglColor3fv(pEclass->color);
  3368.         }
  3369.         else
  3370.         {
  3371.           qglColor3f(1, 1, 1);
  3372.           qglEnable(GL_TEXTURE_2D);
  3373.             qglBindTexture( GL_TEXTURE_2D, model->nTextureBind );
  3374.         }
  3375.         vec3_t v;
  3376.         
  3377.         int i,j;
  3378.         VectorAdd(b->maxs, b->mins, v);
  3379.         VectorScale(v, 0.5, v);
  3380.         VectorCopy(b->owner->origin, v);
  3381.  
  3382.           
  3383.         //for (i = 0; i < 3; i++)
  3384.         //{
  3385.         //  v[i] -= (pEclass->mins[i] - b->mins[i]);
  3386.         //}
  3387.  
  3388.         //if (model->nModelPosition)
  3389.         //{
  3390.               //v[2] = b->mins[2] - (pEclass->mins[2]);
  3391.         //}
  3392.  
  3393.         float s, c;
  3394.           if (a)
  3395.         {
  3396.               s = sin (a/180*Q_PI);
  3397.               c = cos (a/180*Q_PI);
  3398.         }
  3399.  
  3400.         vec3_t vSin;
  3401.         vec3_t vCos;
  3402.         VectorClear(vSin);
  3403.         VectorClear(vCos);
  3404.         for ( j = 0; j < 3; j++)
  3405.         {
  3406.           if (b->owner->vRotation[j])
  3407.           {
  3408.             vSin[j] = sin(b->owner->vRotation[j]/180*Q_PI);
  3409.             vCos[j] = cos(b->owner->vRotation[j]/180*Q_PI);
  3410.           }
  3411.         }
  3412.  
  3413.  
  3414.           qglBegin (GL_TRIANGLES);
  3415.  
  3416.         vec5_t vTest[3];
  3417.         for (i = 0; i < model->nTriCount; i++)
  3418.         {
  3419.           for (j = 0; j < 3; j++)
  3420.           {
  3421. #if 1
  3422.             float x = model->pTriList[i].v[j][0] + v[0];
  3423.             float y = model->pTriList[i].v[j][1] + v[1];
  3424.             if (a)
  3425.             {
  3426.               float x2 = (((x - v[0]) * c) - ((y - v[1]) * s)) + v[0];
  3427.               float y2 = (((x - v[0]) * s) + ((y - v[1]) * c)) + v[1];
  3428.               x = x2;
  3429.               y = y2;
  3430.             }
  3431.             //qglTexCoord2f (pEclass->pTriList[i].st[j][0] / pEclass->nSkinWidth, pEclass->pTriList[i].st[j][1] / pEclass->nSkinHeight);
  3432.             qglTexCoord2f (model->pTriList[i].st[j][0], model->pTriList[i].st[j][1]);
  3433.             qglVertex3f(x, y, model->pTriList[i].v[j][2] + v[2]);
  3434. #else
  3435.             float x = model->pTriList[i].v[j][0] + v[0];
  3436.             float y = model->pTriList[i].v[j][1] + v[1];
  3437.             float z = model->pTriList[i].v[j][2] + v[2];
  3438.  
  3439.             if (b->owner->vRotation[0])
  3440.             {
  3441.               float y2 = (((y - v[1]) * vCos[0]) - ((z - v[2]) * vSin[0])) + v[1];
  3442.               float z2 = (((y - v[1]) * vSin[0]) + ((z - v[2]) * vCos[0])) + v[2];
  3443.               y = y2;
  3444.               z = z2;
  3445.             }
  3446.             if (b->owner->vRotation[1])
  3447.             {
  3448.               float z2 = (((z - v[2]) * vCos[1]) - ((x - v[0]) * vSin[1])) + v[2];
  3449.               float x2 = (((z - v[2]) * vSin[1]) + ((x - v[0]) * vCos[1])) + v[0];
  3450.               x = x2;
  3451.               z = z2;
  3452.             }
  3453.             if (b->owner->vRotation[2])
  3454.             {
  3455.               float x2 = (((x - v[0]) * vCos[2]) - ((y - v[1]) * vSin[2])) + v[0];
  3456.               float y2 = (((x - v[0]) * vSin[2]) + ((y - v[1]) * vCos[2])) + v[1];
  3457.               x = x2;
  3458.               y = y2;
  3459.             }
  3460.             qglTexCoord2f (model->pTriList[i].st[j][0], model->pTriList[i].st[j][1]);
  3461.             qglVertex3f(x, y, z);
  3462. #endif
  3463.             if (g_bDoIt)
  3464.             {
  3465.               vTest[j][0] = x;
  3466.               vTest[j][1] = y;
  3467.               vTest[j][2] = model->pTriList[i].v[j][2] + v[2];
  3468.               vTest[j][3] = model->pTriList[i].st[j][0];
  3469.               vTest[j][4] = model->pTriList[i].st[j][1];
  3470.             }
  3471.  
  3472.           }
  3473.           if (g_bDoIt)
  3474.           {
  3475.             Patch_FromTriangle(vTest[0], vTest[1], vTest[2]);
  3476.           }
  3477.         }
  3478.         qglEnd();
  3479.         if (g_PrefsDlg.m_nEntityShowState & ENTITY_WIREFRAME)    // skinned
  3480.         {
  3481.           qglEnable(GL_CULL_FACE );
  3482.           qglEnable(GL_TEXTURE_2D);
  3483.             qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
  3484.         }
  3485.         else
  3486.         {
  3487.             qglDisable(GL_TEXTURE_2D);
  3488.         }
  3489.         model = model->pNext;
  3490.       }
  3491.  
  3492.       if (g_bDoIt)
  3493.       {
  3494.         g_bDoIt = false;
  3495.       }
  3496.  
  3497.       vec3_t vColor;
  3498.       VectorScale(pEclass->color, 0.50, vColor);
  3499.  
  3500.       vec3_t vCenter, vMin, vMax;
  3501.       VectorCopy(b->owner->origin, vCenter);
  3502.  
  3503.           qglColor3fv(vColor);
  3504.       qglPointSize(4);
  3505.  
  3506.       qglBegin(GL_POINTS);
  3507.       qglVertex3fv(b->owner->origin);
  3508.       qglEnd();
  3509.  
  3510.       qglBegin(GL_LINES);
  3511.       vCenter[0] -= 8;
  3512.       qglVertex3fv(vCenter);
  3513.       vCenter[0] += 16;
  3514.       qglVertex3fv(vCenter);
  3515.       vCenter[0] -= 8;
  3516.       vCenter[1] -= 8;
  3517.       qglVertex3fv(vCenter);
  3518.       vCenter[1] += 16;
  3519.       qglVertex3fv(vCenter);
  3520.       vCenter[1] -= 8;
  3521.       vCenter[2] -= 8;
  3522.       qglVertex3fv(vCenter);
  3523.       vCenter[2] += 16;
  3524.       qglVertex3fv(vCenter);
  3525.       vCenter[2] -= 8;
  3526.       qglEnd();
  3527.  
  3528.       VectorCopy(vCenter, vMin);
  3529.       VectorCopy(vCenter, vMax);
  3530.       vMin[0] -= 4;
  3531.       vMin[1] -= 4;
  3532.       vMin[2] -= 4;
  3533.       vMax[0] += 4;
  3534.       vMax[1] += 4;
  3535.       vMax[2] += 4;
  3536.  
  3537.             qglBegin(GL_LINE_LOOP);
  3538.           qglVertex3f(vMin[0],vMin[1],vMin[2]);
  3539.           qglVertex3f(vMax[0],vMin[1],vMin[2]);
  3540.           qglVertex3f(vMax[0],vMax[1],vMin[2]);
  3541.           qglVertex3f(vMin[0],vMax[1],vMin[2]);
  3542.             qglEnd();
  3543.             
  3544.             qglBegin(GL_LINE_LOOP);
  3545.             qglVertex3f(vMin[0],vMin[1],vMax[2]);
  3546.               qglVertex3f(vMax[0],vMin[1],vMax[2]);
  3547.               qglVertex3f(vMax[0],vMax[1],vMax[2]);
  3548.               qglVertex3f(vMin[0],vMax[1],vMax[2]);
  3549.             qglEnd();
  3550.  
  3551.             qglBegin(GL_LINES);
  3552.               qglVertex3f(vMin[0],vMin[1],vMin[2]);
  3553.               qglVertex3f(vMin[0],vMin[1],vMax[2]);
  3554.               qglVertex3f(vMin[0],vMax[1],vMax[2]);
  3555.               qglVertex3f(vMin[0],vMax[1],vMin[2]);
  3556.               qglVertex3f(vMax[0],vMin[1],vMin[2]);
  3557.               qglVertex3f(vMax[0],vMin[1],vMax[2]);
  3558.               qglVertex3f(vMax[0],vMax[1],vMax[2]);
  3559.               qglVertex3f(vMax[0],vMax[1],vMin[2]);
  3560.             qglEnd();
  3561.  
  3562.  
  3563.         if (g_PrefsDlg.m_nEntityShowState & ENTITY_BOXED)
  3564.         {
  3565.             qglColor3fv(pEclass->color);
  3566.  
  3567.         vec3_t mins, maxs;
  3568.         VectorCopy(b->mins, mins);
  3569.         VectorCopy(b->maxs, maxs);
  3570. /*
  3571.         if (a)
  3572.         {
  3573.           vec3_t vAngle;
  3574.           vAngle[0] = vAngle[1] = 0;
  3575.           vAngle[2] = a;
  3576.           VectorRotate(mins, vAngle, b->owner->origin, mins);
  3577.           VectorRotate(maxs, vAngle, b->owner->origin, maxs);
  3578.         }
  3579. */
  3580.             qglBegin(GL_LINE_LOOP);
  3581.           qglVertex3f(mins[0],mins[1],mins[2]);
  3582.           qglVertex3f(maxs[0],mins[1],mins[2]);
  3583.           qglVertex3f(maxs[0],maxs[1],mins[2]);
  3584.           qglVertex3f(mins[0],maxs[1],mins[2]);
  3585.             qglEnd();
  3586.             
  3587.             qglBegin(GL_LINE_LOOP);
  3588.             qglVertex3f(mins[0],mins[1],maxs[2]);
  3589.               qglVertex3f(maxs[0],mins[1],maxs[2]);
  3590.               qglVertex3f(maxs[0],maxs[1],maxs[2]);
  3591.               qglVertex3f(mins[0],maxs[1],maxs[2]);
  3592.             qglEnd();
  3593.  
  3594.             qglBegin(GL_LINES);
  3595.               qglVertex3f(mins[0],mins[1],mins[2]);
  3596.               qglVertex3f(mins[0],mins[1],maxs[2]);
  3597.               qglVertex3f(mins[0],maxs[1],maxs[2]);
  3598.               qglVertex3f(mins[0],maxs[1],mins[2]);
  3599.               qglVertex3f(maxs[0],mins[1],mins[2]);
  3600.               qglVertex3f(maxs[0],mins[1],maxs[2]);
  3601.               qglVertex3f(maxs[0],maxs[1],maxs[2]);
  3602.               qglVertex3f(maxs[0],maxs[1],mins[2]);
  3603.             qglEnd();
  3604.       }
  3605.         qglPopAttrib();
  3606.       bReturn = true;
  3607.     }
  3608.     else
  3609.     {
  3610.       b->bModelFailed = true;
  3611.     }
  3612.  
  3613.   g_bInPaintedModel = false;
  3614.   return bReturn;
  3615. }
  3616. /*
  3617. //++timo moved out to mahlib.h
  3618. //++timo remove
  3619. void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
  3620. {
  3621.     float        angle;
  3622.     static float        sr, sp, sy, cr, cp, cy;
  3623.     // static to help MS compiler fp bugs
  3624.  
  3625.     angle = angles[YAW] * Q_PI / 180;
  3626.     sy = sin(angle);
  3627.     cy = cos(angle);
  3628.     angle = angles[PITCH] * Q_PI / 180;
  3629.     sp = sin(angle);
  3630.     cp = cos(angle);
  3631.     angle = angles[ROLL] * Q_PI / 180;
  3632.     sr = sin(angle);
  3633.     cr = cos(angle);
  3634.  
  3635.     if (forward)
  3636.     {
  3637.         forward[0] = cp*cy;
  3638.         forward[1] = cp*sy;
  3639.         forward[2] = -sp;
  3640.     }
  3641.     if (right)
  3642.     {
  3643.         right[0] = (-1*sr*sp*cy+-1*cr*-sy);
  3644.         right[1] = (-1*sr*sp*sy+-1*cr*cy);
  3645.         right[2] = -1*sr*cp;
  3646.     }
  3647.     if (up)
  3648.     {
  3649.         up[0] = (cr*sp*cy+-sr*-sy);
  3650.         up[1] = (cr*sp*sy+-sr*cy);
  3651.         up[2] = cr*cp;
  3652.     }
  3653. }
  3654. */
  3655. void FacingVectors (entity_t *e, vec3_t forward, vec3_t right, vec3_t up)
  3656. {
  3657.     int            angleVal;
  3658.     vec3_t        angles;
  3659.  
  3660.     angleVal = IntForKey(e, "angle");
  3661.     if (angleVal == -1)                // up
  3662.     {
  3663.         VectorSet(angles, 270, 0, 0);
  3664.     }
  3665.     else if(angleVal == -2)        // down
  3666.     {
  3667.         VectorSet(angles, 90, 0, 0);
  3668.     }
  3669.     else
  3670.     {
  3671.         VectorSet(angles, 0, angleVal, 0);
  3672.     }
  3673.  
  3674.     AngleVectors(angles, forward, right, up);
  3675. }
  3676.  
  3677. void Brush_DrawFacingAngle (brush_t *b, entity_t *e)
  3678. {
  3679.     vec3_t    forward, right, up;
  3680.     vec3_t    endpoint, tip1, tip2;
  3681.     vec3_t    start;
  3682.     float    dist;
  3683.  
  3684.     VectorAdd(e->brushes.onext->mins, e->brushes.onext->maxs, start);
  3685.     VectorScale(start, 0.5, start);
  3686.     dist = (b->maxs[0] - start[0]) * 2.5;
  3687.  
  3688.     FacingVectors (e, forward, right, up);
  3689.     VectorMA (start, dist, forward, endpoint);
  3690.  
  3691.     dist = (b->maxs[0] - start[0]) * 0.5;
  3692.     VectorMA (endpoint, -dist, forward, tip1);
  3693.     VectorMA (tip1, -dist, up, tip1);
  3694.     VectorMA (tip1, 2*dist, up, tip2);
  3695.  
  3696.     qglColor4f (1, 1, 1, 1);
  3697.     qglLineWidth (4);
  3698.     qglBegin (GL_LINES);
  3699.     qglVertex3fv (start);
  3700.     qglVertex3fv (endpoint);
  3701.     qglVertex3fv (endpoint);
  3702.     qglVertex3fv (tip1);
  3703.     qglVertex3fv (endpoint);
  3704.     qglVertex3fv (tip2);
  3705.     qglEnd ();
  3706.     qglLineWidth (1);
  3707. }
  3708.  
  3709. void DrawLight(brush_t *b)
  3710. {
  3711.     vec3_t vTriColor;
  3712.     bool bTriPaint = false;
  3713.  
  3714.   vTriColor[0] = vTriColor[2] = 1.0;
  3715.   vTriColor[1]  = 1.0;
  3716.   bTriPaint = true;
  3717.   CString strColor = ValueForKey(b->owner, "_color");
  3718.   if (strColor.GetLength() > 0)
  3719.   {
  3720.     float fR, fG, fB;
  3721.       int n = sscanf(strColor,"%f %f %f", &fR, &fG, &fB);
  3722.     if (n == 3)
  3723.     {
  3724.       vTriColor[0] = fR;
  3725.       vTriColor[1] = fG;
  3726.       vTriColor[2] = fB;
  3727.     }
  3728.   }
  3729.   qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
  3730.  
  3731.   vec3_t vCorners[4];
  3732.   float fMid = b->mins[2] + (b->maxs[2] - b->mins[2]) / 2;
  3733.  
  3734.   vCorners[0][0] = b->mins[0];
  3735.   vCorners[0][1] = b->mins[1];
  3736.   vCorners[0][2] = fMid;
  3737.  
  3738.   vCorners[1][0] = b->mins[0];
  3739.   vCorners[1][1] = b->maxs[1];
  3740.   vCorners[1][2] = fMid;
  3741.  
  3742.   vCorners[2][0] = b->maxs[0];
  3743.   vCorners[2][1] = b->maxs[1];
  3744.   vCorners[2][2] = fMid;
  3745.  
  3746.   vCorners[3][0] = b->maxs[0];
  3747.   vCorners[3][1] = b->mins[1];
  3748.   vCorners[3][2] = fMid;
  3749.  
  3750.   vec3_t vTop, vBottom;
  3751.  
  3752.   vTop[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) / 2);
  3753.   vTop[1] = b->mins[1] + ((b->maxs[1] - b->mins[1]) / 2);
  3754.   vTop[2] = b->maxs[2];
  3755.  
  3756.   VectorCopy(vTop, vBottom);
  3757.   vBottom[2] = b->mins[2];
  3758.  
  3759.   vec3_t vSave;
  3760.   VectorCopy(vTriColor, vSave);
  3761.  
  3762.   qglBegin(GL_TRIANGLE_FAN);
  3763.   qglVertex3fv(vTop);
  3764.   for (int i = 0; i <= 3; i++)
  3765.   {
  3766.     vTriColor[0] *= 0.95;
  3767.     vTriColor[1] *= 0.95;
  3768.     vTriColor[2] *= 0.95;
  3769.     qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
  3770.     qglVertex3fv(vCorners[i]);
  3771.   }
  3772.   qglVertex3fv(vCorners[0]);
  3773.   qglEnd();
  3774.   
  3775.   VectorCopy(vSave, vTriColor);
  3776.   vTriColor[0] *= 0.95;
  3777.   vTriColor[1] *= 0.95;
  3778.   vTriColor[2] *= 0.95;
  3779.  
  3780.   qglBegin(GL_TRIANGLE_FAN);
  3781.   qglVertex3fv(vBottom);
  3782.   qglVertex3fv(vCorners[0]);
  3783.   for (i = 3; i >= 0; i--)
  3784.   {
  3785.     vTriColor[0] *= 0.95;
  3786.     vTriColor[1] *= 0.95;
  3787.     vTriColor[2] *= 0.95;
  3788.     qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
  3789.     qglVertex3fv(vCorners[i]);
  3790.   }
  3791.   qglEnd();
  3792.  
  3793.   // check for DOOM lights
  3794.   CString str = ValueForKey(b->owner, "light_right");
  3795.   if (str.GetLength() > 0) {
  3796.     vec3_t vRight, vUp, vTarget, vTemp;
  3797.     GetVectorForKey (b->owner, "light_right", vRight);
  3798.     GetVectorForKey (b->owner, "light_up", vUp);
  3799.     GetVectorForKey (b->owner, "light_target", vTarget);
  3800.  
  3801.     qglColor3f(0, 1, 0);
  3802.         qglBegin(GL_LINE_LOOP);
  3803.     VectorAdd(vTarget, b->owner->origin, vTemp);
  3804.     VectorAdd(vTemp, vRight, vTemp);
  3805.     VectorAdd(vTemp, vUp, vTemp);
  3806.     qglVertex3fv(b->owner->origin);
  3807.     qglVertex3fv(vTemp);
  3808.     VectorAdd(vTarget, b->owner->origin, vTemp);
  3809.     VectorAdd(vTemp, vUp, vTemp);
  3810.     VectorSubtract(vTemp, vRight, vTemp);
  3811.     qglVertex3fv(b->owner->origin);
  3812.     qglVertex3fv(vTemp);
  3813.     VectorAdd(vTarget, b->owner->origin, vTemp);
  3814.     VectorAdd(vTemp, vRight, vTemp);
  3815.     VectorSubtract(vTemp, vUp, vTemp);
  3816.     qglVertex3fv(b->owner->origin);
  3817.     qglVertex3fv(vTemp);
  3818.     VectorAdd(vTarget, b->owner->origin, vTemp);
  3819.     VectorSubtract(vTemp, vUp, vTemp);
  3820.     VectorSubtract(vTemp, vRight, vTemp);
  3821.     qglVertex3fv(b->owner->origin);
  3822.     qglVertex3fv(vTemp);
  3823.     qglEnd();
  3824.  
  3825.   }
  3826.  
  3827. }
  3828.  
  3829. void Brush_Draw( brush_t *b )
  3830. {
  3831.     face_t            *face;
  3832.     int                i, order;
  3833.     qtexture_t        *prev = 0;
  3834.     winding_t *w;
  3835.  
  3836.     if ( b->owner && ( b->owner->eclass->nShowFlags & ECLASS_PLUGINENTITY ) )
  3837.     {
  3838.         b->owner->pPlugEnt->CamRender();
  3839.         return;
  3840.     }
  3841.     
  3842.     // (TTimo) NOTE: added by build 173, I check after pPlugEnt so it doesn't interfere ?
  3843.   if (b->hiddenBrush)
  3844.   {
  3845.     return;
  3846.   }
  3847.  
  3848.     if (b->patchBrush)
  3849.     {
  3850.         //Patch_DrawCam(b->nPatchID);
  3851.         Patch_DrawCam(b->pPatch);
  3852.         //if (!g_bPatchShowBounds)
  3853.         return;
  3854.     }
  3855.     
  3856.     int nDrawMode = g_pParentWnd->GetCamera()->Camera().draw_mode;
  3857.     
  3858.     if (b->owner->eclass->fixedsize)
  3859.     {
  3860.         
  3861.         if (!(g_qeglobals.d_savedinfo.exclude & EXCLUDE_ANGLES) && (b->owner->eclass->nShowFlags & ECLASS_ANGLE))
  3862.         {
  3863.             Brush_DrawFacingAngle(b, b->owner);
  3864.         }
  3865.         
  3866.         if (g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT))
  3867.         {
  3868.             DrawLight(b);
  3869.             return;
  3870.         }
  3871.         if (nDrawMode == cd_texture || nDrawMode == cd_light)
  3872.             qglDisable (GL_TEXTURE_2D);
  3873.         
  3874.         // if we are wireframing models
  3875.         bool bp = (b->bModelFailed) ? false : PaintedModel(b, true);
  3876.         
  3877.         if (nDrawMode == cd_texture || nDrawMode == cd_light)
  3878.             qglEnable (GL_TEXTURE_2D);
  3879.         
  3880.         if (bp)
  3881.             return;
  3882.     }
  3883.     
  3884.     // guarantee the texture will be set first
  3885.     prev = NULL;
  3886.     for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++)
  3887.     {
  3888.         w = face->face_winding;
  3889.         if (!w)
  3890.         {
  3891.             continue;        // freed face
  3892.         }
  3893.         
  3894.         if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK)
  3895.         {
  3896.             if (strstr(face->texdef.name, "caulk"))
  3897.             {
  3898.                 continue;
  3899.             }
  3900.         }
  3901.         
  3902. #if 0
  3903.         if (b->alphaBrush)
  3904.         {
  3905.             if (!(face->texdef.flags & SURF_ALPHA))
  3906.                 continue;
  3907.             //--qglPushAttrib(GL_ALL_ATTRIB_BITS);
  3908.             qglDisable(GL_CULL_FACE);
  3909.             //--qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  3910.             //--qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  3911.             //--qglDisable(GL_DEPTH_TEST);
  3912.             //--qglBlendFunc (GL_SRC_ALPHA, GL_DST_ALPHA);
  3913.             //--qglEnable (GL_BLEND);
  3914.         }
  3915. #endif
  3916.         
  3917.         if ((nDrawMode == cd_texture || nDrawMode == cd_light) && face->d_texture != prev)
  3918.         {
  3919.             // set the texture for this face
  3920.             prev = face->d_texture;
  3921.             qglBindTexture( GL_TEXTURE_2D, face->d_texture->texture_number );
  3922.         }
  3923.         
  3924.         
  3925.         
  3926.         if (!b->patchBrush)
  3927.         {
  3928.             if (face->texdef.flags & SURF_TRANS33) 
  3929.                 qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], 0.33 );
  3930.             else if ( face->texdef.flags & SURF_TRANS66) 
  3931.                 qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], 0.66 );
  3932.             else
  3933.                 qglColor3fv( face->d_color );
  3934.         }
  3935.         else
  3936.         {
  3937.             qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], 0.13 );
  3938.         }
  3939.         
  3940.         // shader drawing stuff
  3941.         if (face->d_texture->bFromShader)
  3942.         {
  3943.             // setup shader drawing
  3944.             qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], face->d_texture->fTrans );
  3945.             
  3946.         }
  3947.         
  3948.         // draw the polygon
  3949.         
  3950.         //if (nDrawMode == cd_light)
  3951.         //{
  3952.         if (g_PrefsDlg.m_bGLLighting)
  3953.         {
  3954.             qglNormal3fv(face->plane.normal);
  3955.         }
  3956.         //}
  3957.         
  3958.         qglBegin(GL_POLYGON);
  3959.         //if (nDrawMode == cd_light)
  3960.         
  3961.         for (i=0 ; i<w->numpoints ; i++)
  3962.         {
  3963.             if (nDrawMode == cd_texture || nDrawMode == cd_light)
  3964.                 qglTexCoord2fv( &w->points[i][3] );
  3965.             qglVertex3fv(w->points[i]);
  3966.         }
  3967.         qglEnd();
  3968.     }
  3969.     
  3970. #if 0
  3971.     if (b->alphaBrush)
  3972.     {
  3973.         //--qglPopAttrib();
  3974.         qglEnable(GL_CULL_FACE);
  3975.         //--qglDisable (GL_BLEND);
  3976.         //--qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  3977.     }
  3978. #endif
  3979.     
  3980.     if (b->owner->eclass->fixedsize && (nDrawMode == cd_texture || nDrawMode == cd_light))
  3981.         qglEnable (GL_TEXTURE_2D);
  3982.     
  3983.     qglBindTexture( GL_TEXTURE_2D, 0 );
  3984. }
  3985.  
  3986.  
  3987.  
  3988. void Face_Draw( face_t *f )
  3989. {
  3990.     int i;
  3991.  
  3992.     if ( f->face_winding == 0 )
  3993.         return;
  3994.     qglBegin( GL_POLYGON );
  3995.     for ( i = 0 ; i < f->face_winding->numpoints; i++)
  3996.         qglVertex3fv( f->face_winding->points[i] );
  3997.     qglEnd();
  3998. }
  3999.  
  4000. void Brush_DrawXY(brush_t *b, int nViewType)
  4001. {
  4002.     face_t *face;
  4003.     int     order;
  4004.     winding_t *w;
  4005.     int        i;
  4006.  
  4007.   if (b->hiddenBrush)
  4008.   {
  4009.     return;
  4010.   }
  4011.  
  4012.   if (b->patchBrush)
  4013.   {
  4014.     //Patch_DrawXY(b->nPatchID);
  4015.     Patch_DrawXY(b->pPatch);
  4016.     if (!g_bPatchShowBounds)
  4017.       return;
  4018.   }
  4019.                      
  4020.  
  4021.   if (b->owner->eclass->fixedsize)
  4022.   {
  4023.     if (g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT))
  4024.     {
  4025.       vec3_t vCorners[4];
  4026.       float fMid = b->mins[2] + (b->maxs[2] - b->mins[2]) / 2;
  4027.  
  4028.       vCorners[0][0] = b->mins[0];
  4029.       vCorners[0][1] = b->mins[1];
  4030.       vCorners[0][2] = fMid;
  4031.  
  4032.       vCorners[1][0] = b->mins[0];
  4033.       vCorners[1][1] = b->maxs[1];
  4034.       vCorners[1][2] = fMid;
  4035.  
  4036.       vCorners[2][0] = b->maxs[0];
  4037.       vCorners[2][1] = b->maxs[1];
  4038.       vCorners[2][2] = fMid;
  4039.  
  4040.       vCorners[3][0] = b->maxs[0];
  4041.       vCorners[3][1] = b->mins[1];
  4042.       vCorners[3][2] = fMid;
  4043.  
  4044.       vec3_t vTop, vBottom;
  4045.  
  4046.       vTop[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) / 2);
  4047.       vTop[1] = b->mins[1] + ((b->maxs[1] - b->mins[1]) / 2);
  4048.       vTop[2] = b->maxs[2];
  4049.  
  4050.       VectorCopy(vTop, vBottom);
  4051.       vBottom[2] = b->mins[2];
  4052.         
  4053.       qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
  4054.       qglBegin(GL_TRIANGLE_FAN);
  4055.       qglVertex3fv(vTop);
  4056.       qglVertex3fv(vCorners[0]);
  4057.       qglVertex3fv(vCorners[1]);
  4058.       qglVertex3fv(vCorners[2]);
  4059.       qglVertex3fv(vCorners[3]);
  4060.       qglVertex3fv(vCorners[0]);
  4061.       qglEnd();
  4062.       qglBegin(GL_TRIANGLE_FAN);
  4063.       qglVertex3fv(vBottom);
  4064.       qglVertex3fv(vCorners[0]);
  4065.       qglVertex3fv(vCorners[3]);
  4066.       qglVertex3fv(vCorners[2]);
  4067.       qglVertex3fv(vCorners[1]);
  4068.       qglVertex3fv(vCorners[0]);
  4069.       qglEnd();
  4070.           DrawBrushEntityName (b);
  4071.       return;
  4072.     }
  4073.     else if (b->owner->eclass->nShowFlags & ECLASS_MISCMODEL)
  4074.     {
  4075.       if (PaintedModel(b, false))
  4076.         return;
  4077.     }
  4078.   }
  4079.  
  4080.     for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++)
  4081.     {
  4082.         // only draw polygons facing in a direction we care about
  4083.     if (nViewType == XY)
  4084.     {
  4085.           if (face->plane.normal[2] <= 0)
  4086.               continue;
  4087.     }
  4088.     else
  4089.     {
  4090.       if (nViewType == XZ)
  4091.       {
  4092.         if (face->plane.normal[1] <= 0)
  4093.           continue;
  4094.       }
  4095.       else 
  4096.       {
  4097.         if (face->plane.normal[0] <= 0)
  4098.           continue;
  4099.       }
  4100.     }
  4101.  
  4102.         w = face->face_winding;
  4103.         if (!w)
  4104.             continue;
  4105.  
  4106.     //if (b->alphaBrush && !(face->texdef.flags & SURF_ALPHA))
  4107.     //  continue;
  4108.  
  4109.         // draw the polygon
  4110.         qglBegin(GL_LINE_LOOP);
  4111.     for (i=0 ; i<w->numpoints ; i++)
  4112.           qglVertex3fv(w->points[i]);
  4113.         qglEnd();
  4114.     }
  4115.  
  4116.     DrawBrushEntityName (b);
  4117.  
  4118. }
  4119.  
  4120. /*
  4121. ============
  4122. Brush_Move
  4123. ============
  4124. */
  4125. void Brush_Move (brush_t *b, const vec3_t move, bool bSnap)
  4126. {
  4127.   int i;
  4128.   face_t *f;
  4129.  
  4130.   for (f=b->brush_faces ; f ; f=f->next)
  4131.   {
  4132.     vec3_t vTemp;
  4133.     VectorCopy(move, vTemp);
  4134.  
  4135.     if (g_PrefsDlg.m_bTextureLock)
  4136.       Face_MoveTexture(f, vTemp);
  4137.     
  4138.     for (i=0 ; i<3 ; i++)
  4139.       VectorAdd (f->planepts[i], move, f->planepts[i]);
  4140.   }
  4141.   Brush_Build( b, bSnap );
  4142.  
  4143.  
  4144.   if (b->patchBrush)
  4145.   {
  4146.     //Patch_Move(b->nPatchID, move);
  4147.     Patch_Move(b->pPatch, move);
  4148.   }
  4149.  
  4150.  
  4151.   // PGM - keep the origin vector up to date on fixed size entities.
  4152.   if(b->owner->eclass->fixedsize)
  4153.   {
  4154.     VectorAdd(b->owner->origin, move, b->owner->origin);
  4155.       //VectorAdd(b->maxs, b->mins, b->owner->origin);
  4156.       //VectorScale(b->owner->origin, 0.5, b->owner->origin);
  4157.   }
  4158. }
  4159.  
  4160.  
  4161.  
  4162. void Brush_Print(brush_t* b)
  4163. {
  4164.   int nFace = 0;
  4165.   for (face_t* f = b->brush_faces ; f ; f=f->next)
  4166.   {
  4167.     Sys_Printf("Face %i\n", nFace++);
  4168.     Sys_Printf("%f %f %f\n", f->planepts[0][0], f->planepts[0][1], f->planepts[0][2]);
  4169.     Sys_Printf("%f %f %f\n", f->planepts[1][0], f->planepts[1][1], f->planepts[1][2]);
  4170.     Sys_Printf("%f %f %f\n", f->planepts[2][0], f->planepts[2][1], f->planepts[2][2]);
  4171.   }
  4172.  }
  4173.  
  4174.  
  4175.  
  4176. /*
  4177. =============
  4178. Brush_MakeSided
  4179.  
  4180. Makes the current brushhave the given number of 2d sides and turns it into a cone
  4181. =============
  4182. */
  4183. void Brush_MakeSidedCone(int sides)
  4184. {
  4185.     int        i;
  4186.     vec3_t    mins, maxs;
  4187.     brush_t    *b;
  4188.     texdef_t    *texdef;
  4189.     face_t    *f;
  4190.     vec3_t    mid;
  4191.     float    width;
  4192.     float    sv, cv;
  4193.  
  4194.     if (sides < 3)
  4195.     {
  4196.         Sys_Status ("Bad sides number", 0);
  4197.         return;
  4198.     }
  4199.  
  4200.     if (!QE_SingleBrush ())
  4201.     {
  4202.         Sys_Status ("Must have a single brush selected", 0 );
  4203.         return;
  4204.     }
  4205.  
  4206.     b = selected_brushes.next;
  4207.     VectorCopy (b->mins, mins);
  4208.     VectorCopy (b->maxs, maxs);
  4209.     texdef = &g_qeglobals.d_texturewin.texdef;
  4210.  
  4211.     Brush_Free (b);
  4212.  
  4213.     // find center of brush
  4214.     width = 8;
  4215.     for (i=0 ; i<2 ; i++)
  4216.     {
  4217.         mid[i] = (maxs[i] + mins[i])*0.5;
  4218.         if (maxs[i] - mins[i] > width)
  4219.             width = maxs[i] - mins[i];
  4220.     }
  4221.     width /= 2;
  4222.  
  4223.     b = Brush_Alloc();
  4224.  
  4225.     // create bottom face
  4226.     f = Face_Alloc();
  4227.     f->texdef = *texdef;
  4228.     f->next = b->brush_faces;
  4229.     b->brush_faces = f;
  4230.  
  4231.     f->planepts[0][0] = mins[0];f->planepts[0][1] = mins[1];f->planepts[0][2] = mins[2];
  4232.     f->planepts[1][0] = maxs[0];f->planepts[1][1] = mins[1];f->planepts[1][2] = mins[2];
  4233.     f->planepts[2][0] = maxs[0];f->planepts[2][1] = maxs[1];f->planepts[2][2] = mins[2];
  4234.  
  4235.     for (i=0 ; i<sides ; i++)
  4236.     {
  4237.         f = Face_Alloc();
  4238.         f->texdef = *texdef;
  4239.         f->next = b->brush_faces;
  4240.         b->brush_faces = f;
  4241.  
  4242.         sv = sin (i*3.14159265*2/sides);
  4243.         cv = cos (i*3.14159265*2/sides);
  4244.  
  4245.  
  4246.         f->planepts[0][0] = floor(mid[0]+width*cv+0.5);
  4247.         f->planepts[0][1] = floor(mid[1]+width*sv+0.5);
  4248.         f->planepts[0][2] = mins[2];
  4249.  
  4250.         f->planepts[1][0] = mid[0];
  4251.         f->planepts[1][1] = mid[1];
  4252.         f->planepts[1][2] = maxs[2];
  4253.  
  4254.         f->planepts[2][0] = floor(f->planepts[0][0] - width * sv + 0.5);
  4255.         f->planepts[2][1] = floor(f->planepts[0][1] + width * cv + 0.5);
  4256.         f->planepts[2][2] = maxs[2];
  4257.  
  4258.     }
  4259.  
  4260.     Brush_AddToList (b, &selected_brushes);
  4261.  
  4262.     Entity_LinkBrush (world_entity, b);
  4263.  
  4264.     Brush_Build( b );
  4265.  
  4266.     Sys_UpdateWindows (W_ALL);
  4267. }
  4268.  
  4269. /*
  4270. =============
  4271. Brush_MakeSided
  4272.  
  4273. Makes the current brushhave the given number of 2d sides and turns it into a sphere
  4274. =============
  4275.  
  4276. */
  4277. void Brush_MakeSidedSphere(int sides)
  4278. {
  4279.     int        i,j;
  4280.     vec3_t    mins, maxs;
  4281.     brush_t    *b;
  4282.     texdef_t    *texdef;
  4283.     face_t    *f;
  4284.     vec3_t    mid;
  4285.  
  4286.     if (sides < 4)
  4287.     {
  4288.         Sys_Status ("Bad sides number", 0);
  4289.         return;
  4290.     }
  4291.  
  4292.     if (!QE_SingleBrush ())
  4293.     {
  4294.         Sys_Status ("Must have a single brush selected", 0 );
  4295.         return;
  4296.     }
  4297.  
  4298.     b = selected_brushes.next;
  4299.     VectorCopy (b->mins, mins);
  4300.     VectorCopy (b->maxs, maxs);
  4301.     texdef = &g_qeglobals.d_texturewin.texdef;
  4302.  
  4303.     Brush_Free (b);
  4304.  
  4305.     // find center of brush
  4306.     float radius = 8;
  4307.     for (i=0 ; i<2 ; i++)
  4308.     {
  4309.         mid[i] = (maxs[i] + mins[i])*0.5;
  4310.         if (maxs[i] - mins[i] > radius)
  4311.             radius = maxs[i] - mins[i];
  4312.     }
  4313.     radius /= 2;
  4314.  
  4315.     b = Brush_Alloc();
  4316.  
  4317.     float dt = float(2 * Q_PI / sides);
  4318.     float dp = float(Q_PI / sides);
  4319.   float t,p;
  4320.     for(i=0; i <= sides-1; i++)
  4321.   {
  4322.         for(j=0;j <= sides-2; j++)
  4323.         {
  4324.             t = i * dt;
  4325.             p = float(j * dp - Q_PI / 2);
  4326.  
  4327.       f = Face_Alloc();
  4328.         f->texdef = *texdef;
  4329.         f->next = b->brush_faces;
  4330.         b->brush_faces = f;
  4331.  
  4332.       VectorPolar(f->planepts[0], radius, t, p);
  4333.       VectorPolar(f->planepts[1], radius, t, p + dp);
  4334.       VectorPolar(f->planepts[2], radius, t + dt, p + dp);
  4335.  
  4336.       for (int k = 0; k < 3; k++)
  4337.         VectorAdd(f->planepts[k], mid, f->planepts[k]);
  4338.         }
  4339.   }
  4340.  
  4341.   p = float((sides - 1) * dp - Q_PI / 2);
  4342.     for(i = 0; i <= sides-1; i++)
  4343.     {
  4344.         t = i * dt;
  4345.  
  4346.     f = Face_Alloc();
  4347.       f->texdef = *texdef;
  4348.       f->next = b->brush_faces;
  4349.       b->brush_faces = f;
  4350.  
  4351.     VectorPolar(f->planepts[0], radius, t, p);
  4352.     VectorPolar(f->planepts[1], radius, t + dt, p + dp);
  4353.     VectorPolar(f->planepts[2], radius, t + dt, p);
  4354.  
  4355.     for (int k = 0; k < 3; k++)
  4356.       VectorAdd(f->planepts[k], mid, f->planepts[k]);
  4357.     }
  4358.  
  4359.     Brush_AddToList (b, &selected_brushes);
  4360.  
  4361.     Entity_LinkBrush (world_entity, b);
  4362.  
  4363.     Brush_Build( b );
  4364.  
  4365.     Sys_UpdateWindows (W_ALL);
  4366. }
  4367.  
  4368. void Face_FitTexture( face_t * face, int nHeight, int nWidth )
  4369. {
  4370.   winding_t *w;
  4371.   vec3_t   mins,maxs;
  4372.   int i;
  4373.   float width, height, temp;
  4374.   float rot_width, rot_height;
  4375.   float cosv,sinv,ang;
  4376.   float min_t, min_s, max_t, max_s;
  4377.   float s,t;
  4378.     vec3_t    vecs[2];
  4379.   vec3_t   coords[4];
  4380.     texdef_t    *td;
  4381.  
  4382.   if (nHeight < 1)
  4383.   {
  4384.     nHeight = 1;
  4385.   }
  4386.   if (nWidth < 1)
  4387.   {
  4388.     nWidth = 1;
  4389.   }
  4390.  
  4391.   ClearBounds (mins, maxs);
  4392.  
  4393.     td = &face->texdef;
  4394.     w = face->face_winding;
  4395.     if (!w)
  4396.     {
  4397.     return;
  4398.     }
  4399.   for (i=0 ; i<w->numpoints ; i++)
  4400.   {
  4401.     AddPointToBounds( w->points[i], mins, maxs );
  4402.   }
  4403.    // 
  4404.    // get the current angle
  4405.    //
  4406.     ang = td->rotate / 180 * Q_PI;
  4407.     sinv = sin(ang);
  4408.     cosv = cos(ang);
  4409.  
  4410.     // get natural texture axis
  4411.     TextureAxisFromPlane(&face->plane, vecs[0], vecs[1]);
  4412.  
  4413.   min_s = DotProduct( mins, vecs[0] );
  4414.   min_t = DotProduct( mins, vecs[1] );
  4415.   max_s = DotProduct( maxs, vecs[0] );
  4416.   max_t = DotProduct( maxs, vecs[1] );
  4417.   width = max_s - min_s;
  4418.   height = max_t - min_t;
  4419.   coords[0][0] = min_s;
  4420.   coords[0][1] = min_t;
  4421.   coords[1][0] = max_s;
  4422.   coords[1][1] = min_t;
  4423.   coords[2][0] = min_s;
  4424.   coords[2][1] = max_t;
  4425.   coords[3][0] = max_s;
  4426.   coords[3][1] = max_t;
  4427.   min_s = min_t = 99999;
  4428.   max_s = max_t = -99999;
  4429.   for (i=0; i<4; i++)
  4430.   {
  4431.     s = cosv * coords[i][0] - sinv * coords[i][1];
  4432.       t = sinv * coords[i][0] + cosv * coords[i][1];
  4433.     if (i&1)
  4434.     {
  4435.       if (s > max_s) 
  4436.       {
  4437.         max_s = s;
  4438.       }
  4439.     }
  4440.     else
  4441.     {
  4442.       if (s < min_s) 
  4443.       {
  4444.         min_s = s;
  4445.       }
  4446.       if (i<2)
  4447.       {
  4448.         if (t < min_t) 
  4449.         {
  4450.           min_t = t;
  4451.         }
  4452.       }
  4453.       else
  4454.       {
  4455.         if (t > max_t) 
  4456.         {
  4457.           max_t = t;
  4458.         }
  4459.       }
  4460.     }
  4461.   }
  4462.   rot_width =  (max_s - min_s);
  4463.   rot_height = (max_t - min_t);
  4464.   td->scale[0] = -(rot_width/((float)(face->d_texture->width*nWidth)));
  4465.   td->scale[1] = -(rot_height/((float)(face->d_texture->height*nHeight)));
  4466.  
  4467.   td->shift[0] = min_s/td->scale[0];
  4468.   temp = (int)(td->shift[0] / (face->d_texture->width*nWidth));
  4469.   temp = (temp+1)*face->d_texture->width*nWidth;
  4470.   td->shift[0] = (int)(temp - td->shift[0])%(face->d_texture->width*nWidth);
  4471.  
  4472.   td->shift[1] = min_t/td->scale[1];
  4473.   temp = (int)(td->shift[1] / (face->d_texture->height*nHeight));
  4474.   temp = (temp+1)*(face->d_texture->height*nHeight);
  4475.   td->shift[1] = (int)(temp - td->shift[1])%(face->d_texture->height*nHeight);
  4476. }
  4477.  
  4478. void Brush_FitTexture( brush_t *b, int nHeight, int nWidth )
  4479. {
  4480.     face_t *face;
  4481.  
  4482.     for (face = b->brush_faces ; face ; face=face->next)
  4483.   {
  4484.     Face_FitTexture( face, nHeight, nWidth );
  4485.   }
  4486. }
  4487.  
  4488.  
  4489.