]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/brush.cpp
propagate from internal tree
[xonotic/netradiant.git] / radiant / brush.cpp
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #include "stdafx.h"
23 #include <assert.h>
24 #include "winding.h"
25 #include <limits.h>
26 #include "filters.h"
27
28 extern MainFrame* g_pParentWnd;
29 extern void MemFile_fprintf(MemStream* pMemFile, const char* pText, ...);
30
31 // globals
32
33 int g_nBrushId = 0;
34
35 #ifdef ENABLE_GROUPS
36 const char* Brush_Name(brush_t *b)
37 {
38   static char cBuff[1024];
39         b->numberId = g_nBrushId++;
40         if (g_qeglobals.m_bBrushPrimitMode)
41   {
42     sprintf(cBuff, "Brush %i", b->numberId);
43     Brush_SetEpair(b, "Name", cBuff);
44   }
45   return cBuff;
46 }
47 #endif
48
49 brush_t *Brush_Alloc()
50 {
51   brush_t *b = (brush_t*)qmalloc(sizeof(brush_t));
52   return b;
53 }
54 /*
55 void Brush_Free(brush_t *b)
56 {
57   free(b);
58 }
59 */
60 void PrintWinding (winding_t *w)
61 {
62   int i;
63
64   Sys_Printf ("-------------\n");
65   for (i=0 ; i<w->numpoints ; i++)
66     Sys_Printf ("(%5.2f, %5.2f, %5.2f)\n", w->points[i][0]
67             , w->points[i][1], w->points[i][2]);
68 }
69
70 void PrintPlane (plane_t *p)
71 {
72   Sys_Printf ("(%5.2f, %5.2f, %5.2f) : %5.2f\n",  p->normal[0],  p->normal[1], 
73   p->normal[2],  p->dist);
74 }
75
76 void PrintVector (vec3_t v)
77 {
78   Sys_Printf ("(%5.2f, %5.2f, %5.2f)\n",  v[0],  v[1], v[2]);
79 }
80
81
82 /*
83 =============================================================================
84
85                         TEXTURE COORDINATES
86
87 =============================================================================
88 */
89
90
91 /*
92 ==================
93 textureAxisFromPlane
94 ==================
95 */
96 vec3_t  baseaxis[18] =
97 {
98 {0,0,1}, {1,0,0}, {0,-1,0},                     // floor
99 {0,0,-1}, {1,0,0}, {0,-1,0},            // ceiling
100 {1,0,0}, {0,1,0}, {0,0,-1},                     // west wall
101 {-1,0,0}, {0,1,0}, {0,0,-1},            // east wall
102 {0,1,0}, {1,0,0}, {0,0,-1},                     // south wall
103 {0,-1,0}, {1,0,0}, {0,0,-1}                     // north wall
104 };
105
106 void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
107 {
108         int             bestaxis;
109         float   dot,best;
110         int             i;
111         
112         best = 0;
113         bestaxis = 0;
114         
115         for (i=0 ; i<6 ; i++)
116         {
117                 dot = DotProduct (pln->normal, baseaxis[i*3]);
118     if (g_PrefsDlg.m_bQ3Map2Texturing && dot > best + 0.0001f || dot > best)
119                 {
120                         best = dot;
121                         bestaxis = i;
122                 }
123         }
124         
125         VectorCopy (baseaxis[bestaxis*3+1], xv);
126         VectorCopy (baseaxis[bestaxis*3+2], yv);
127 }
128
129
130
131 float   lightaxis[3] = {0.6f, 0.8f, 1.0f};
132 /*
133 ================
134 SetShadeForPlane
135
136 Light different planes differently to
137 improve recognition
138 ================
139 */
140 extern float ShadeForNormal(vec3_t normal);
141
142 float SetShadeForPlane (plane_t *p)
143 {
144         //return ShadeForNormal(p->normal);
145
146         
147         int             i;
148         float   f;
149
150         // axial plane
151         for (i=0 ; i<3 ; i++)
152                 if (fabs(p->normal[i]) > 0.9)
153                 {
154                         f = lightaxis[i];
155                         return f;
156                 }
157
158         // between two axial planes
159         for (i=0 ; i<3 ; i++)
160                 if (fabs(p->normal[i]) < 0.1)
161                 {
162                         f = (lightaxis[(i+1)%3] + lightaxis[(i+2)%3])/2;
163                         return f;
164                 }
165
166         // other
167         f= (lightaxis[0] + lightaxis[1] + lightaxis[2]) / 3;
168         return f;
169         
170 }
171
172 vec3_t  vecs[2];
173 float   shift[2];
174
175 /*
176 ================
177 Face_Alloc
178 ================
179 */
180 face_t *Face_Alloc( void )
181 {
182         face_t *f = (face_t*)qmalloc( sizeof( *f ) );
183         return f;
184 }
185
186 /*
187 ================
188 Face_Free
189 ================
190 */
191 void Face_Free( face_t *f )
192 {
193         assert( f != 0 );
194
195         if ( f->face_winding )
196         {
197                 free( f->face_winding );
198                 f->face_winding = 0;
199         }
200         f->texdef.~texdef_t();;
201
202         free( f );
203 }
204
205 /*
206 ================
207 Face_Clone
208 ================
209 */
210 face_t  *Face_Clone (face_t *f)
211 {
212         face_t  *n;
213
214         n = Face_Alloc();
215         n->texdef = f->texdef;
216   n->brushprimit_texdef = f->brushprimit_texdef;
217
218         memcpy (n->planepts, f->planepts, sizeof(n->planepts));
219
220         // all other fields are derived, and will be set by Brush_Build
221   // FIXME: maybe not, for example n->pData!
222         return n;
223 }
224
225 /*
226 ================
227 Face_FullClone
228
229 makes an exact copy of the face
230 ================
231 */
232 face_t  *Face_FullClone (face_t *f)
233 {
234         face_t  *n;
235
236         n = Face_Alloc();
237         n->texdef = f->texdef;
238   n->brushprimit_texdef = f->brushprimit_texdef;
239         memcpy(n->planepts, f->planepts, sizeof(n->planepts));
240         memcpy(&n->plane, &f->plane, sizeof(plane_t));
241         if (f->face_winding)
242                 n->face_winding = Winding_Clone(f->face_winding);
243         else
244                 n->face_winding = NULL;
245         n->pShader = f->pShader;
246         n->pShader->IncRef();
247         n->d_texture = n->pShader->getTexture();
248         return n;
249 }
250
251 void Face_SetShader(face_t *face, const char *name)
252 {
253   if(face->pShader != NULL)
254     face->pShader->DecRef();
255   face->texdef.SetName(name);
256   face->pShader = QERApp_Shader_ForName(name);
257   face->pShader->IncRef();
258   face->d_texture = face->pShader->getTexture();
259   face->texdef.flags = face->pShader->getFlags();
260 }
261
262 void Face_SetShader(face_t *face, IShader *shader)
263 {
264   if(face->pShader != NULL)
265     face->pShader->DecRef();
266   face->texdef.SetName(shader->getName());
267   face->d_texture = shader->getTexture();
268   face->texdef.flags = shader->getFlags();
269   face->pShader = shader;
270   face->pShader->IncRef();
271 }
272
273 /*
274 ================
275 Clamp
276 ================
277 */
278 void Clamp(float& f, int nClamp)
279 {
280   float fFrac = f - static_cast<int>(f);
281   f = static_cast<int>(f) % nClamp;
282   f += fFrac;
283 }
284
285 /*
286 ================
287 Face_MoveTexture
288 ================
289 */
290 void Face_MoveTexture(face_t *f, vec3_t delta)
291 {
292         vec3_t vX, vY;
293
294         if (g_qeglobals.m_bBrushPrimitMode)
295                 ShiftTextureGeometric_BrushPrimit( f, delta );
296         else
297         {
298                 TextureAxisFromPlane(&f->plane, vX, vY);
299
300                 vec3_t vDP, vShift;
301                 vDP[0] = DotProduct(delta, vX);
302                 vDP[1] = DotProduct(delta, vY);
303
304                 double fAngle = f->texdef.rotate  / 180 * Q_PI;
305                 double c = cos(fAngle);
306                 double s = sin(fAngle);
307
308                 vShift[0] = vDP[0] * c - vDP[1] * s;
309                 vShift[1] = vDP[0] * s + vDP[1] * c;
310
311                 if (!f->texdef.scale[0])
312                         f->texdef.scale[0] = g_pGameDescription->mTextureDefaultScale;
313                 if (!f->texdef.scale[1])
314                         f->texdef.scale[1] = g_pGameDescription->mTextureDefaultScale;
315
316                 f->texdef.shift[0] -= vShift[0] / f->texdef.scale[0];
317                 f->texdef.shift[1] -= vShift[1] / f->texdef.scale[1];
318   
319                 // clamp the shifts
320                 Clamp(f->texdef.shift[0], f->d_texture->width);
321                 Clamp(f->texdef.shift[1], f->d_texture->height);
322         }
323 }
324
325 /*
326 ================
327 Face_SetColor
328 ================
329 */
330 /*!\todo Replace all face_t::d_texture access with face_t::pShader::GetTexture.*/
331 void Face_SetColor (brush_t *b, face_t *f, float fCurveColor) 
332 {
333         // set shading for face
334   f->d_shade = SetShadeForPlane (&f->plane);
335         f->d_color[0] = f->pShader->getTexture()->color[0] * f->d_shade;
336   f->d_color[1] = f->pShader->getTexture()->color[1] * f->d_shade;
337         f->d_color[2] = f->pShader->getTexture()->color[2] * f->d_shade;
338 }
339
340 /*
341 ================
342 Face_TextureVectors
343 ================
344 */
345 void Face_TextureVectors (face_t *f, float STfromXYZ[2][4])
346 {
347         vec3_t          pvecs[2];
348         int                     sv, tv;
349         float           ang, sinv, cosv;
350         float           ns, nt;
351         int                     i,j;
352         qtexture_t *q;
353         texdef_t        *td;
354
355 #ifdef _DEBUG
356         // this code is not supposed to be used while in BP mode, warning here can help spot the problem
357         if (g_qeglobals.m_bBrushPrimitMode && !g_qeglobals.bNeedConvert)
358                 Sys_Printf("Warning : illegal call of Face_TextureVectors in brush primitive mode\n");
359 #endif
360
361         td = &f->texdef;
362         q = f->d_texture;
363
364         memset (STfromXYZ, 0, 8*sizeof(float));
365
366         if (!td->scale[0])
367                 td->scale[0] = g_pGameDescription->mTextureDefaultScale;
368         if (!td->scale[1])
369                 td->scale[1] = g_pGameDescription->mTextureDefaultScale;
370
371         // get natural texture axis
372         TextureAxisFromPlane(&f->plane, pvecs[0], pvecs[1]);
373
374         // rotate axis
375         if (td->rotate == 0)
376                 { sinv = 0 ; cosv = 1; }
377         else if (td->rotate == 90)
378                 { sinv = 1 ; cosv = 0; }
379         else if (td->rotate == 180)
380                 { sinv = 0 ; cosv = -1; }
381         else if (td->rotate == 270)
382                 { sinv = -1 ; cosv = 0; }
383         else
384         {       
385                 ang = td->rotate / 180 * Q_PI;
386                 sinv = sin(ang);
387                 cosv = cos(ang);
388         }
389
390         if (pvecs[0][0])
391                 sv = 0;
392         else if (pvecs[0][1])
393                 sv = 1;
394         else
395                 sv = 2;
396                                 
397         if (pvecs[1][0])
398                 tv = 0;
399         else if (pvecs[1][1])
400                 tv = 1;
401         else
402                 tv = 2;
403                                         
404         for (i=0 ; i<2 ; i++) {
405                 ns = cosv * pvecs[i][sv] - sinv * pvecs[i][tv];
406                 nt = sinv * pvecs[i][sv] +  cosv * pvecs[i][tv];
407                 STfromXYZ[i][sv] = ns;
408                 STfromXYZ[i][tv] = nt;
409         }
410
411         // scale
412         for (i=0 ; i<2 ; i++)
413                 for (j=0 ; j<3 ; j++)
414                         STfromXYZ[i][j] = STfromXYZ[i][j] / td->scale[i];
415
416         // shift
417         STfromXYZ[0][3] = td->shift[0];
418         STfromXYZ[1][3] = td->shift[1];
419
420         for (j=0 ; j<4 ; j++) {
421                 STfromXYZ[0][j] /= q->width;
422                 STfromXYZ[1][j] /= q->height;
423         }
424 }
425
426 /*
427 ================
428 Face_MakePlane
429 ================
430 */
431 void Face_MakePlane (face_t *f)
432 {
433         int             j;
434         vec3_t  t1, t2, t3;
435
436         // convert to a vector / dist plane
437         for (j=0 ; j<3 ; j++)
438         {
439                 t1[j] = f->planepts[0][j] - f->planepts[1][j];
440                 t2[j] = f->planepts[2][j] - f->planepts[1][j];
441                 t3[j] = f->planepts[1][j];
442         }
443         
444         CrossProduct(t1,t2, f->plane.normal);
445         if (VectorCompare (f->plane.normal, vec3_origin))
446                 Sys_FPrintf (SYS_WRN, "WARNING: brush plane with no normal\n");
447         VectorNormalize (f->plane.normal, f->plane.normal);
448         f->plane.dist = DotProduct (t3, f->plane.normal);
449 }
450
451 /*
452 ================
453 EmitTextureCoordinates
454 ================
455 */
456 void EmitTextureCoordinates ( float *xyzst, qtexture_t *q, face_t *f)
457 {
458         float   STfromXYZ[2][4];
459
460         Face_TextureVectors (f,  STfromXYZ);
461         xyzst[3] = DotProduct (xyzst, STfromXYZ[0]) + STfromXYZ[0][3];
462         xyzst[4] = DotProduct (xyzst, STfromXYZ[1]) + STfromXYZ[1][3];
463 }
464
465 //==========================================================================
466
467 /*
468 ================
469 Brush_MakeFacePlanes
470 ================
471 */
472 void Brush_MakeFacePlanes (brush_t *b)
473 {
474         face_t  *f;
475
476         for (f=b->brush_faces ; f ; f=f->next)
477         {
478                 Face_MakePlane (f);
479         }
480 }
481
482 /*
483 ================
484 DrawBrushEntityName
485 ================
486 */
487 void DrawBrushEntityName (brush_t *b)
488 {
489   const char  *name;
490   float a, s, c;
491   vec3_t  mid;
492   int   i;
493
494   if (!b->owner)
495     return;   // during contruction
496
497   if (b->owner == world_entity)
498     return;
499
500   if (b != b->owner->brushes.onext)
501     return; // not key brush
502
503   // TTimo: Brush_DrawFacingAngle is for camera view rendering, this function is called for 2D views
504   // FIXME - spog - not sure who put this here.. Brush_DrawFacingAngle() does this job?
505   // Brush_DrawFacingAngle() works when called, but is not being called.
506   if (g_qeglobals.d_savedinfo.show_angles && (b->owner->eclass->nShowFlags & ECLASS_ANGLE))
507   {
508     // draw the angle pointer
509     a = FloatForKey (b->owner, "angle");
510     s = sin (a/180*Q_PI);
511     c = cos (a/180*Q_PI);
512     for (i=0 ; i<3 ; i++)
513       mid[i] = (b->mins[i] + b->maxs[i])*0.5; 
514
515     qglBegin (GL_LINE_STRIP);
516     qglVertex3fv (mid);
517     mid[0] += c*8;
518     mid[1] += s*8;
519     mid[2] += s*8;
520     qglVertex3fv (mid);
521     mid[0] -= c*4;
522     mid[1] -= s*4;
523     mid[2] -= s*4;
524     mid[0] -= s*4;
525     mid[1] += c*4;
526     mid[2] += c*4;
527     qglVertex3fv (mid);
528     mid[0] += c*4;
529     mid[1] += s*4;
530     mid[2] += s*4;
531     mid[0] += s*4;
532     mid[1] -= c*4;
533     mid[2] -= c*4;
534     qglVertex3fv (mid);
535     mid[0] -= c*4;
536     mid[1] -= s*4;
537     mid[2] -= s*4;
538     mid[0] += s*4;
539     mid[1] -= c*4;
540     mid[2] -= c*4;
541     qglVertex3fv (mid);
542     qglEnd ();
543   }
544
545   if (g_qeglobals.d_savedinfo.show_names)
546   {
547     name = ValueForKey (b->owner, "classname");
548     qglRasterPos3f (b->mins[0]+4, b->mins[1]+4, b->mins[2]+4);
549     gtk_glwidget_print_string(name);
550   }
551 }
552
553 /*
554 =================
555 Brush_MakeFaceWinding
556
557 returns the visible polygon on a face
558 =================
559 */
560 winding_t *Brush_MakeFaceWinding (brush_t *b, face_t *face)
561 {
562         winding_t       *w;
563         face_t          *clip;
564         plane_t                 plane;
565         qboolean                past;
566
567   // get a poly that covers an effectively infinite area
568         w = Winding_BaseForPlane (&face->plane);
569
570         // chop the poly by all of the other faces
571         past = false;
572         for (clip = b->brush_faces ; clip && w ; clip=clip->next)
573         {
574                 if (clip == face)
575                 {
576                         past = true;
577                         continue;
578                 }
579                 if (DotProduct (face->plane.normal, clip->plane.normal) > 0.999
580                         && fabs(face->plane.dist - clip->plane.dist) < 0.01 )
581                 {       // identical plane, use the later one
582                         if (past)
583                         {
584                                 free (w);
585                                 return NULL;
586                         }
587                         continue;
588                 }
589
590                 // flip the plane, because we want to keep the back side
591                 VectorSubtract (vec3_origin,clip->plane.normal, plane.normal);
592                 plane.dist = -clip->plane.dist;
593                 
594                 w = Winding_Clip (w, &plane, false);
595                 if (!w)
596                         return w;
597         }
598         
599         if (w->numpoints < 3)
600         {
601                 free(w);
602                 w = NULL;
603         }
604
605         if (!w)
606                 Sys_FPrintf (SYS_WRN, "unused plane\n");
607
608         return w;
609 }
610
611 /*
612 =================
613 Brush_SnapPlanepts
614 =================
615 */
616 void Brush_SnapPlanepts (brush_t *b)
617 {
618         int             i, j;
619         face_t  *f;
620
621   if (g_PrefsDlg.m_bNoClamp)
622     return;
623
624   if (g_qeglobals.d_bSmallGrid)
625   {
626           for (f=b->brush_faces ; f; f=f->next)
627                   for (i=0 ; i<3 ; i++)
628                           for (j=0 ; j<3 ; j++)
629                                 f->planepts[i][j] = floor (f->planepts[i][j]/g_qeglobals.d_gridsize + 0.5)*g_qeglobals.d_gridsize;
630   }
631   else
632   {
633           for (f=b->brush_faces ; f; f=f->next)
634                   for (i=0 ; i<3 ; i++)
635                           for (j=0 ; j<3 ; j++)
636                                   f->planepts[i][j] = floor (f->planepts[i][j] + 0.5);
637   }
638 }
639         
640 /*
641 ** Brush_Build
642 **
643 ** Builds a brush rendering data and also sets the min/max bounds
644 */
645 // TTimo
646 // added a bConvert flag to convert between old and new brush texture formats
647 // TTimo
648 // brush grouping: update the group treeview if necessary
649 void Brush_Build( brush_t *b, bool bSnap, bool bMarkMap, bool bConvert, bool bFilterTest)
650 {
651         bool            bLocalConvert;
652
653         
654 #ifdef _DEBUG
655         if (!g_qeglobals.m_bBrushPrimitMode && bConvert)
656                 Sys_Printf("Warning : conversion from brush primitive to old brush format not implemented\n");
657 #endif
658
659         // if bConvert is set and g_qeglobals.bNeedConvert is not, that just means we need convert for this brush only
660         if (bConvert && !g_qeglobals.bNeedConvert)
661         {
662 #ifdef _DEBUG
663     //++timo FIXME: it's not very clear when this can happen, I guess while dealing with plugins that send brushes
664     // back and forth in one format or the other .. more when mixing BP / noBP in the same maps.
665 #endif
666                 bLocalConvert = true;
667                 g_qeglobals.bNeedConvert = true;
668         }
669         else
670           bLocalConvert = false;
671
672         /*
673         ** build the windings and generate the bounding box
674         */
675         Brush_BuildWindings(b, bSnap);
676
677   if(b->owner->model.pRender)
678   {
679     const aabb_t *aabb = b->owner->model.pRender->GetAABB();
680     VectorAdd(aabb->origin, aabb->extents, b->maxs);
681     VectorSubtract(aabb->origin, aabb->extents, b->mins);
682   } 
683
684         //Patch_BuildPoints (b); // does nothing but set b->patchBrush true if the texdef contains SURF_PATCH !
685
686         /*
687         ** move the points and edges if in select mode
688         */
689         if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge)
690                 SetupVertexSelection ();
691
692         if (b->itemOwner == 0) //NULL)
693           Group_AddToProperGroup(b);
694
695         if (bMarkMap)
696         {
697                 Sys_MarkMapModified();
698         }
699
700         if (bLocalConvert)
701                 g_qeglobals.bNeedConvert = false;
702
703         // spog - applying filters to brush during brush_build instead of during redraw
704         if (bFilterTest)
705                 b->bFiltered = FilterBrush( b );
706 }
707
708 /*
709 ==============
710 Brush_SplitBrushByFace
711
712 The incoming brush is NOT freed.
713 The incoming face is NOT left referenced.
714 ==============
715 */
716 void Brush_SplitBrushByFace (brush_t *in, face_t *f, brush_t **front, brush_t **back, boolean bCaulk)
717 {
718         brush_t *b;
719         face_t  *nf;
720         vec3_t  temp;
721
722         b = Brush_Clone (in);
723         nf = Face_Clone (f);
724
725         nf->texdef = b->brush_faces->texdef;
726   if (bCaulk)
727   {
728     nf->texdef.SetName(g_pGameDescription->mCaulkShader.GetBuffer());
729   }
730         nf->next = b->brush_faces;
731         b->brush_faces = nf;
732
733         Brush_Build( b );
734         Brush_RemoveEmptyFaces ( b );
735         if ( !b->brush_faces )
736         {       // completely clipped away
737                 Brush_Free (b);
738                 *back = NULL;
739         }
740         else
741         {
742                 Entity_LinkBrush (in->owner, b);
743                 *back = b;
744         }
745
746         b = Brush_Clone (in);
747         nf = Face_Clone (f);
748         // swap the plane winding
749         VectorCopy (nf->planepts[0], temp);
750         VectorCopy (nf->planepts[1], nf->planepts[0]);
751         VectorCopy (temp, nf->planepts[1]);
752
753         nf->texdef = b->brush_faces->texdef;
754   if (bCaulk)
755   {
756     nf->texdef.SetName(g_pGameDescription->mCaulkShader.GetBuffer());
757   }
758         nf->next = b->brush_faces;
759         b->brush_faces = nf;
760
761         Brush_Build( b );
762         Brush_RemoveEmptyFaces ( b );
763         if ( !b->brush_faces )
764         {       // completely clipped away
765                 Brush_Free (b);
766                 *front = NULL;
767         }
768         else
769         {
770                 Entity_LinkBrush (in->owner, b);
771                 *front = b;
772         }
773 }
774
775 /*
776 =================
777 Brush_BestSplitFace
778
779 returns the best face to split the brush with.
780 return NULL if the brush is convex
781 =================
782 */
783 face_t *Brush_BestSplitFace(brush_t *b)
784 {
785         face_t *face, *f, *bestface;
786         winding_t *front, *back;
787         int splits, tinywindings, value, bestvalue;
788
789         bestvalue = 999999;
790         bestface = NULL;
791         for (face = b->brush_faces; face; face = face->next)
792         {
793                 splits = 0;
794                 tinywindings = 0;
795                 for (f = b->brush_faces; f; f = f->next)
796                 {
797                         if (f == face) continue;
798                         //
799                         Winding_SplitEpsilon(f->face_winding, face->plane.normal, face->plane.dist, 0.1f, &front, &back);
800
801                         if (!front)
802                         {
803                                 Winding_Free(back);
804                         }
805                         else if (!back)
806                         {
807                                 Winding_Free(front);
808                         }
809                         else
810                         {
811                                 splits++;
812                                 if (Winding_IsTiny(front)) tinywindings++;
813                                 if (Winding_IsTiny(back)) tinywindings++;
814                         }
815                 }
816                 if (splits)
817                 {
818                         value = splits + 50 * tinywindings;
819                         if (value < bestvalue)
820                         {
821                                 bestvalue = value;
822                                 bestface = face;
823                         }
824                 }
825         }
826         return bestface;
827 }
828
829 /*
830 =================
831 Brush_MakeConvexBrushes
832
833 MrE FIXME: this doesn't work because the old
834                    Brush_SplitBrushByFace is used
835 Turns the brush into a minimal number of convex brushes.
836 If the input brush is convex then it will be returned.
837 Otherwise the input brush will be freed.
838 NOTE: the input brush should have windings for the faces.
839 =================
840 */
841 brush_t *Brush_MakeConvexBrushes(brush_t *b)
842 {
843         brush_t *front, *back, *end;
844         face_t *face;
845
846         b->next = NULL;
847         face = Brush_BestSplitFace(b);
848         if (!face) return b;
849         Brush_SplitBrushByFace(b, face, &front, &back);
850         //this should never happen
851         if (!front && !back) return b;
852         Brush_Free(b);
853         if (!front)
854                 return Brush_MakeConvexBrushes(back);
855         b = Brush_MakeConvexBrushes(front);
856         if (back)
857         {
858                 for (end = b; end->next; end = end->next);
859                 end->next = Brush_MakeConvexBrushes(back);
860         }
861         return b;
862 }
863
864 /*
865 =================
866 Brush_Convex
867 =================
868 */
869 int Brush_Convex(brush_t *b)
870 {
871         face_t *face1, *face2;
872
873         for (face1 = b->brush_faces; face1; face1 = face1->next)
874         {
875                 if (!face1->face_winding) continue;
876                 for (face2 = b->brush_faces; face2; face2 = face2->next)
877                 {
878                         if (face1 == face2) continue;
879                         if (!face2->face_winding) continue;
880                         if (Winding_PlanesConcave(face1->face_winding, face2->face_winding,
881                                                                                 face1->plane.normal, face2->plane.normal,
882                                                                                 face1->plane.dist, face2->plane.dist))
883                         {
884                                 return false;
885                         }
886                 }
887         }
888         return true;
889 }
890
891 /*
892 =================
893 Brush_MoveVertexes
894
895 - The input brush must be convex
896 - The input brush must have face windings.
897 - The output brush will be convex.
898 - Returns true if the WHOLE vertex movement is performed.
899 =================
900 */
901
902 // define this to debug the vertex editing mode
903 #ifdef _DEBUG
904 //#define DBG_VERT
905 #endif
906
907 #define MAX_MOVE_FACES          64
908
909 int Brush_MoveVertex(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
910 {
911         face_t *f, *face, *newface, *lastface, *nextface;
912         face_t *movefaces[MAX_MOVE_FACES];
913         int movefacepoints[MAX_MOVE_FACES];
914         winding_t *w, tmpw;
915         vec3_t start, mid;
916         plane_t plane;
917         int i, j, k, nummovefaces, result, done;
918         float dot, front, back, frac, smallestfrac;
919
920 #ifdef DBG_VERT
921   Sys_Printf("Bursh_MoveVertex: %p vertex: %g %g %g delta: %g %g %g end: %g %g %g snap: %s\n", b, vertex[0], vertex[1], vertex[2], delta[0], delta[1], delta[2], end[0], end[1], end[2], bSnap ? "true" : "false" );
922 #endif
923
924         result = true;
925         //
926         tmpw.numpoints = 3;
927         tmpw.maxpoints = 3;
928         VectorCopy(vertex, start);
929         VectorAdd(vertex, delta, end);
930         //snap or not?
931         if (bSnap)
932                 for (i = 0; i < 3; i++)
933                         end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.1) * g_qeglobals.d_gridsize;
934         //
935         VectorCopy(end, mid);
936         //if the start and end are the same
937         if (Point_Equal(start, end, 0.3f)) return false;
938         //the end point may not be the same as another vertex
939         for (face = b->brush_faces; face; face = face->next)
940         {
941                 w = face->face_winding;
942                 if (!w) continue;
943                 for (i = 0; i < w->numpoints; i++)
944                 {
945                         if (Point_Equal(w->points[i], end, 0.3f))
946                         {
947                                 VectorCopy(vertex, end);
948                                 return false;
949                         }
950                 }
951         }
952         //
953         done = false;
954         while(!done)
955         {
956                 //chop off triangles from all brush faces that use the to be moved vertex
957                 //store pointers to these chopped off triangles in movefaces[]
958                 nummovefaces = 0;
959                 for (face = b->brush_faces; face; face = face->next)
960                 {
961                         w = face->face_winding;
962                         if (!w) continue;
963                         for (i = 0; i < w->numpoints; i++)
964                         {
965                                 if (Point_Equal(w->points[i], start, 0.2f))
966                                 {
967                                         if (face->face_winding->numpoints <= 3)
968                                         {
969                                                 movefacepoints[nummovefaces] = i;
970                                                 movefaces[nummovefaces++] = face;
971                                                 break;
972                                         }
973                                         dot = DotProduct(end, face->plane.normal) - face->plane.dist;
974                                         //if the end point is in front of the face plane
975                                         if (dot > 0.1)
976                                         {
977                                           //fanout triangle subdivision
978                                           for (k = i; k < i + w->numpoints-3; k++)
979                                           {
980                                             VectorCopy(w->points[i], tmpw.points[0]);
981                                             VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
982                                             VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
983                                             //
984                                             newface = Face_Clone(face);
985                                             //get the original
986                                             for (f = face; f->original; f = f->original) ;
987                                             newface->original = f;
988                                             //store the new winding
989                                             if (newface->face_winding) Winding_Free(newface->face_winding);
990                                             newface->face_winding = Winding_Clone(&tmpw);
991                                             //get the texture information
992                                             newface->pShader = face->pShader;
993                                             newface->d_texture = face->d_texture;
994
995                                             //add the face to the brush
996                                             newface->next = b->brush_faces;
997                                             b->brush_faces = newface;
998                                             //add this new triangle to the move faces
999                                             movefacepoints[nummovefaces] = 0;
1000                                             movefaces[nummovefaces++] = newface;
1001                                           }
1002                                           //give the original face a new winding
1003                                           VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
1004                                           VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
1005                                           VectorCopy(w->points[i], tmpw.points[2]);
1006                                           Winding_Free(face->face_winding);
1007                                           face->face_winding = Winding_Clone(&tmpw);
1008                                           //add the original face to the move faces
1009                                           movefacepoints[nummovefaces] = 2;
1010                                           movefaces[nummovefaces++] = face;
1011                                         }
1012                                         else
1013                                         {
1014                                                 //chop a triangle off the face
1015                                                 VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
1016                                                 VectorCopy(w->points[i], tmpw.points[1]);
1017                                                 VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
1018                                                 //remove the point from the face winding
1019                                                 Winding_RemovePoint(w, i);
1020                                                 //get texture crap right
1021                                                 Face_SetColor(b, face, 1.0);
1022                                                 for (j = 0; j < w->numpoints; j++)
1023                                                         EmitTextureCoordinates(w->points[j], face->d_texture, face);
1024                                                 //make a triangle face
1025                                                 newface = Face_Clone(face);
1026                                                 //get the original
1027                                                 for (f = face; f->original; f = f->original) ;
1028                                                 newface->original = f;
1029                                                 //store the new winding
1030                                                 if (newface->face_winding) Winding_Free(newface->face_winding);
1031                                                 newface->face_winding = Winding_Clone(&tmpw);
1032                                                 //get the texture
1033                                                 newface->pShader = face->pShader;
1034                                                 newface->d_texture = newface->pShader->getTexture();
1035 //                                              newface->d_texture = QERApp_Texture_ForName2( newface->texdef.name );
1036                                                 //add the face to the brush
1037                                                 newface->next = b->brush_faces;
1038                                                 b->brush_faces = newface;
1039                                                 //
1040                                                 movefacepoints[nummovefaces] = 1;
1041                                                 movefaces[nummovefaces++] = newface;
1042                                         }
1043                                         break;
1044                                 }
1045                         }
1046                 }
1047                 //now movefaces contains pointers to triangle faces that
1048                 //contain the to be moved vertex
1049                 //
1050                 done = true;
1051                 VectorCopy(end, mid);
1052                 smallestfrac = 1;
1053                 for (face = b->brush_faces; face; face = face->next)
1054                 {
1055                         //check if there is a move face that has this face as the original
1056                         for (i = 0; i < nummovefaces; i++)
1057                         {
1058                                 if (movefaces[i]->original == face) break;
1059                         }
1060                         if (i >= nummovefaces) continue;
1061                         //check if the original is not a move face itself
1062                         for (j = 0; j < nummovefaces; j++)
1063                         {
1064                                 if (face == movefaces[j]) break;
1065                         }
1066                         //if the original is not a move face itself
1067                         if (j >= nummovefaces)
1068                         {
1069                                 memcpy(&plane, &movefaces[i]->original->plane, sizeof(plane_t));
1070                         }
1071                         else
1072                         {
1073                                 k = movefacepoints[j];
1074                                 w = movefaces[j]->face_winding;
1075                                 VectorCopy(w->points[(k+1)%w->numpoints], tmpw.points[0]);
1076                                 VectorCopy(w->points[(k+2)%w->numpoints], tmpw.points[1]);
1077                                 //
1078                                 k = movefacepoints[i];
1079                                 w = movefaces[i]->face_winding;
1080                                 VectorCopy(w->points[(k+1)%w->numpoints], tmpw.points[2]);
1081                                 if (!Plane_FromPoints(tmpw.points[0], tmpw.points[1], tmpw.points[2], &plane))
1082                                 {
1083                                         VectorCopy(w->points[(k+2)%w->numpoints], tmpw.points[2]);
1084                                         if (!Plane_FromPoints(tmpw.points[0], tmpw.points[1], tmpw.points[2], &plane))
1085                                                 //this should never happen otherwise the face merge did a crappy job a previous pass
1086                                                 continue;
1087                                 }
1088                         }
1089                         //now we've got the plane to check agains
1090                         front = DotProduct(start, plane.normal) - plane.dist;
1091                         back = DotProduct(end, plane.normal) - plane.dist;
1092                         //if the whole move is at one side of the plane
1093                         if (front < 0.01 && back < 0.01) continue;
1094                         if (front > -0.01 && back > -0.01) continue;
1095                         //if there's no movement orthogonal to this plane at all
1096                         if (fabs(front-back) < 0.001) continue;
1097                         //ok first only move till the plane is hit
1098                         frac = front/(front-back);
1099                         if (frac < smallestfrac)
1100                         {
1101                                 mid[0] = start[0] + (end[0] - start[0]) * frac;
1102                                 mid[1] = start[1] + (end[1] - start[1]) * frac;
1103                                 mid[2] = start[2] + (end[2] - start[2]) * frac;
1104                                 smallestfrac = frac;
1105                         }
1106                         //
1107                         done = false;
1108                 }
1109
1110                 //move the vertex
1111                 for (i = 0; i < nummovefaces; i++)
1112                 {
1113                         //move vertex to end position
1114                         VectorCopy(mid, movefaces[i]->face_winding->points[movefacepoints[i]]);
1115                         //create new face plane
1116                         for (j = 0; j < 3; j++)
1117                         {
1118                                 VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
1119                         }
1120                         Face_MakePlane(movefaces[i]);
1121                         if (VectorLength(movefaces[i]->plane.normal) < 0.1)
1122                                 result = false;
1123                 }
1124                 //if the brush is no longer convex
1125                 if (!result || !Brush_Convex(b))
1126                 {
1127                         for (i = 0; i < nummovefaces; i++)
1128                         {
1129                                 //move the vertex back to the initial position
1130                                 VectorCopy(start, movefaces[i]->face_winding->points[movefacepoints[i]]);
1131                                 //create new face plane
1132                                 for (j = 0; j < 3; j++)
1133                                 {
1134                                         VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
1135                                 }
1136                                 Face_MakePlane(movefaces[i]);
1137                         }
1138                         result = false;
1139                         VectorCopy(start, end);
1140                         done = true;
1141                 }
1142                 else
1143                 {
1144                         VectorCopy(mid, start);
1145                 }
1146                 //get texture crap right
1147                 for (i = 0; i < nummovefaces; i++)
1148                 {
1149                         Face_SetColor(b, movefaces[i], 1.0);
1150                         for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
1151                                 EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
1152                 }
1153
1154                 //now try to merge faces with their original faces
1155                 lastface = NULL;
1156                 for (face = b->brush_faces; face; face = nextface)
1157                 {
1158                         nextface = face->next;
1159                         if (!face->original)
1160                         {
1161                                 lastface = face;
1162                                 continue;
1163                         }
1164                         if (!Plane_Equal(&face->plane, &face->original->plane, false))
1165                         {
1166                                 lastface = face;
1167                                 continue;
1168                         }
1169                         w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
1170                         if (!w)
1171                         {
1172                                 lastface = face;
1173                                 continue;
1174                         }
1175                         Winding_Free(face->original->face_winding);
1176                         face->original->face_winding = w;
1177                         //get texture crap right
1178                         Face_SetColor(b, face->original, 1.0);
1179                         for (j = 0; j < face->original->face_winding->numpoints; j++)
1180                                 EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
1181                         //remove the face that was merged with the original
1182                         if (lastface) lastface->next = face->next;
1183                         else b->brush_faces = face->next;
1184                         Face_Free(face);
1185                 }
1186         }
1187         return result;
1188 }
1189
1190 /*
1191 =================
1192 Brush_InsertVertexBetween
1193 =================
1194 */
1195 int Brush_InsertVertexBetween(brush_t *b, vec3_t p1, vec3_t p2)
1196 {
1197         face_t *face;
1198         winding_t *w, *neww;
1199         vec3_t point;
1200         int i, insert;
1201
1202         if (Point_Equal(p1, p2, 0.4f))
1203                 return false;
1204         VectorAdd(p1, p2, point);
1205         VectorScale(point, 0.5f, point);
1206         insert = false;
1207         //the end point may not be the same as another vertex
1208         for (face = b->brush_faces; face; face = face->next)
1209         {
1210                 w = face->face_winding;
1211                 if (!w) continue;
1212                 neww = NULL;
1213                 for (i = 0; i < w->numpoints; i++)
1214                 {
1215                         if (!Point_Equal(w->points[i], p1, 0.1f))
1216                                 continue;
1217                         if (Point_Equal(w->points[(i+1) % w->numpoints], p2, 0.1f))
1218                         {
1219                                 neww = Winding_InsertPoint(w, point, (i+1) % w->numpoints);
1220                                 break;
1221                         }
1222                         else if (Point_Equal(w->points[(i-1+w->numpoints) % w->numpoints], p2, 0.3f))
1223                         {
1224                                 neww = Winding_InsertPoint(w, point, i);
1225                                 break;
1226                         }
1227                 }
1228                 if (neww)
1229                 {
1230                         Winding_Free(face->face_winding);
1231                         face->face_winding = neww;
1232                         insert = true;
1233                 }
1234         }
1235         return insert;
1236 }
1237
1238
1239 /*
1240 =================
1241 Brush_ResetFaceOriginals
1242 =================
1243 */
1244 void Brush_ResetFaceOriginals(brush_t *b)
1245 {
1246         face_t *face;
1247
1248         for (face = b->brush_faces; face; face = face->next)
1249         {
1250                 face->original = NULL;
1251         }
1252 }
1253
1254 #ifdef ENABLE_GROUPS
1255 /*
1256 ==============
1257 Brush_SetEpair
1258 sets an epair for the given brush
1259 ==============
1260 */
1261 void Brush_SetEpair(brush_t *b, const char *pKey, const char *pValue)
1262 {
1263         if (g_qeglobals.m_bBrushPrimitMode)
1264         {
1265     if (b->patchBrush)
1266     {
1267       Patch_SetEpair(b->pPatch, pKey, pValue);
1268     }
1269     else
1270     {
1271                   SetKeyValue(b->epairs, pKey, pValue);
1272     }
1273         }
1274         else
1275         {
1276                 Sys_Printf("Can only set key/values in Brush primitive mode\n");
1277         }
1278 }
1279
1280 /* 
1281 =================
1282 Brush_GetKeyValue
1283 =================
1284 */
1285 const char* Brush_GetKeyValue(brush_t *b, const char *pKey)
1286 {
1287         if (g_qeglobals.m_bBrushPrimitMode)
1288         {
1289     if (b->patchBrush)
1290     {
1291       return Patch_GetKeyValue(b->pPatch, pKey);
1292     }
1293     else
1294     {
1295                   return ValueForKey(b->epairs, pKey);
1296     }
1297         }
1298         else
1299         {
1300                 Sys_Printf("Can only set brush/patch key/values in Brush primitive mode\n");
1301         }
1302   return "";
1303 }
1304 #endif
1305 /*
1306 =================
1307 CheckName
1308 temporary stuff, detect potential problems when saving the texture name
1309 =================
1310 */
1311 void CheckName( face_t *fa, char *pname )
1312 {
1313   if (!strlen(fa->texdef.GetName()))
1314         {
1315 #ifdef _DEBUG
1316                 Sys_Printf("WARNING: unexpected texdef.name is empty in Brush.cpp CheckName\n");
1317 #endif
1318                 fa->texdef.SetName(SHADER_NOT_FOUND);
1319                 strcpy(pname, SHADER_NOT_FOUND);
1320                 return;
1321         }
1322
1323         // some people manage to get long filename textures (with spaces) in their maps
1324         if (strchr( fa->texdef.GetName(), ' ' ))
1325         {
1326                 char Msg1[1024];
1327     
1328     sprintf( Msg1, "Can't save texture with spaces in name. Rename %s\nNOTE: This message may popup several times .. once for each buggy face detected.", fa->texdef.GetName() );
1329     
1330                 Sys_Printf("%s\n", Msg1 );
1331                 gtk_MessageBox(g_pParentWnd->m_pWidget, Msg1, "Error saving map", MB_OK );
1332                 strcpy( pname, SHADER_NOT_FOUND );
1333                 return;
1334         }
1335
1336   //++timo FIXME: bug #103494 detection attempt
1337   // TODO: clean this detection part when bug will have disappeared
1338         if (fa->texdef.GetName()[0] == '(')
1339   {
1340                 char *text = "Bug #103494 detected, dropping texture. Please report to timo@qeradiant.com if you have a way to reproduce!\nNOTE: this message may popup several times .. once for each buggy face detected.";
1341                 Sys_Printf("%s\n", text);
1342                 gtk_MessageBox(g_pParentWnd->m_pWidget, text, "Error saving map", MB_OK );
1343                 // need to cleanup this dead face name or we may loop endlessly
1344                 fa->texdef.SetName(SHADER_NOT_FOUND);
1345                 strcpy( pname, SHADER_NOT_FOUND );
1346                 return;
1347         }
1348         strcpy( pname, fa->texdef.GetName()+9 ); // remove "textures/"
1349 }
1350
1351 /*
1352 =============
1353 Brush_Create
1354
1355 Create non-textured blocks for entities
1356 The brush is NOT linked to any list
1357 =============
1358 */
1359 brush_t *Brush_Create (vec3_t mins, vec3_t maxs, texdef_t *texdef)
1360 {
1361         int             i, j;
1362         vec3_t  pts[4][2];
1363         face_t  *f;
1364         brush_t *b;
1365
1366 #if DBG_BP
1367         // brush primitive mode : convert texdef to brushprimit_texdef ?
1368         // most of the time texdef is empty
1369         if (g_qeglobals.m_bBrushPrimitMode)
1370         {
1371                 // check texdef is empty .. if there are cases it's not we need to write some conversion code
1372                 if (texdef->shift[0]!=0 || texdef->shift[1]!=0 || texdef->scale[0]!=0 || texdef->scale[1]!=0 || texdef->rotate!=0)
1373                         Sys_Printf("Warning : non-zero texdef detected in Brush_Create .. need brush primitive conversion\n");
1374         }
1375 #endif
1376
1377         for (i=0 ; i<3 ; i++)
1378         {
1379                 if (maxs[i] < mins[i])
1380                         Error ("Brush_InitSolid: backwards");
1381         }
1382
1383         b = Brush_Alloc();
1384         
1385         pts[0][0][0] = mins[0];
1386         pts[0][0][1] = mins[1];
1387         
1388         pts[1][0][0] = mins[0];
1389         pts[1][0][1] = maxs[1];
1390         
1391         pts[2][0][0] = maxs[0];
1392         pts[2][0][1] = maxs[1];
1393         
1394         pts[3][0][0] = maxs[0];
1395         pts[3][0][1] = mins[1];
1396         
1397         for (i=0 ; i<4 ; i++)
1398         {
1399                 pts[i][0][2] = mins[2];
1400                 pts[i][1][0] = pts[i][0][0];
1401                 pts[i][1][1] = pts[i][0][1];
1402                 pts[i][1][2] = maxs[2];
1403         }
1404
1405         for (i=0 ; i<4 ; i++)
1406         {
1407                 f = Face_Alloc();
1408                 f->texdef = *texdef;
1409                 f->texdef.flags &= ~SURF_KEEP;
1410                 f->texdef.contents &= ~CONTENTS_KEEP;
1411                 f->next = b->brush_faces;
1412                 b->brush_faces = f;
1413                 j = (i+1)%4;
1414
1415                 VectorCopy (pts[j][1], f->planepts[0]);
1416                 VectorCopy (pts[i][1], f->planepts[1]);
1417                 VectorCopy (pts[i][0], f->planepts[2]);
1418         }
1419         
1420         f = Face_Alloc();
1421         f->texdef = *texdef;
1422         f->texdef.flags &= ~SURF_KEEP;
1423         f->texdef.contents &= ~CONTENTS_KEEP;
1424         f->next = b->brush_faces;
1425         b->brush_faces = f;
1426
1427         VectorCopy (pts[0][1], f->planepts[0]);
1428         VectorCopy (pts[1][1], f->planepts[1]);
1429         VectorCopy (pts[2][1], f->planepts[2]);
1430
1431         f = Face_Alloc();
1432         f->texdef = *texdef;
1433         f->texdef.flags &= ~SURF_KEEP;
1434         f->texdef.contents &= ~CONTENTS_KEEP;
1435         f->next = b->brush_faces;
1436         b->brush_faces = f;
1437
1438         VectorCopy (pts[2][0], f->planepts[0]);
1439         VectorCopy (pts[1][0], f->planepts[1]);
1440         VectorCopy (pts[0][0], f->planepts[2]);
1441
1442         return b;
1443 }
1444
1445 /*
1446 =============
1447 Brush_CreatePyramid
1448
1449 Create non-textured pyramid for light entities
1450 The brush is NOT linked to any list
1451 =============
1452 */
1453 brush_t *Brush_CreatePyramid (vec3_t mins, vec3_t maxs, texdef_t *texdef)
1454 {
1455   int i;
1456
1457         //++timo handle new brush primitive ? return here ??
1458         return Brush_Create(mins, maxs, texdef);
1459
1460         for (i=0 ; i<3 ; i++)
1461                 if (maxs[i] < mins[i])
1462                         Error ("Brush_InitSolid: backwards");
1463
1464         brush_t* b = Brush_Alloc();
1465
1466         vec3_t corners[4];
1467
1468         float fMid = Rad_rint(mins[2] + (Rad_rint((maxs[2] - mins[2]) / 2)));
1469
1470         corners[0][0] = mins[0];
1471         corners[0][1] = mins[1];
1472         corners[0][2] = fMid;
1473
1474         corners[1][0] = mins[0];
1475         corners[1][1] = maxs[1];
1476         corners[1][2] = fMid;
1477
1478         corners[2][0] = maxs[0];
1479         corners[2][1] = maxs[1];
1480         corners[2][2] = fMid;
1481
1482         corners[3][0] = maxs[0];
1483         corners[3][1] = mins[1];
1484         corners[3][2] = fMid;
1485
1486         vec3_t top, bottom;
1487
1488         top[0] = Rad_rint(mins[0] + ((maxs[0] - mins[0]) / 2));
1489         top[1] = Rad_rint(mins[1] + ((maxs[1] - mins[1]) / 2));
1490         top[2] = Rad_rint(maxs[2]);
1491
1492         VectorCopy(top, bottom);
1493         bottom[2] = mins[2];
1494
1495         // sides
1496         for (i = 0; i < 4; i++)
1497         {
1498                 face_t* f = Face_Alloc();
1499                 f->texdef = *texdef;
1500                 f->texdef.flags &= ~SURF_KEEP;
1501                 f->texdef.contents &= ~CONTENTS_KEEP;
1502                 f->next = b->brush_faces;
1503                 b->brush_faces = f;
1504                 int j = (i+1)%4;
1505
1506                 VectorCopy (top, f->planepts[0]);
1507                 VectorCopy (corners[i], f->planepts[1]);
1508                 VectorCopy(corners[j], f->planepts[2]);
1509
1510                 f = Face_Alloc();
1511                 f->texdef = *texdef;
1512                 f->texdef.flags &= ~SURF_KEEP;
1513                 f->texdef.contents &= ~CONTENTS_KEEP;
1514                 f->next = b->brush_faces;
1515                 b->brush_faces = f;
1516
1517                 VectorCopy (bottom, f->planepts[2]);
1518                 VectorCopy (corners[i], f->planepts[1]);
1519                 VectorCopy(corners[j], f->planepts[0]);
1520         }
1521
1522         return b;
1523 }
1524
1525
1526
1527
1528 /*
1529 =============
1530 Brush_MakeSided
1531
1532 Makes the current brush have the given number of 2d sides
1533 =============
1534 */
1535 void Brush_MakeSided (int sides)
1536 {
1537         int             i, axis;
1538         vec3_t  mins, maxs;
1539         brush_t *b;
1540         texdef_t        *texdef;
1541         face_t  *f;
1542         vec3_t  mid;
1543         float   width;
1544         float   sv, cv;
1545
1546         if (sides < 3)
1547         {
1548                 Sys_Status ("Bad sides number", 0);
1549                 return;
1550         }
1551
1552         if (sides >= MAX_POINTS_ON_WINDING-4)
1553         {
1554                 Sys_Printf("too many sides.\n");
1555                 return;
1556         }
1557
1558         if (!QE_SingleBrush ())
1559         {
1560                 Sys_Status ("Must have a single brush selected", 0 );
1561                 return;
1562         }
1563
1564         b = selected_brushes.next;
1565         VectorCopy (b->mins, mins);
1566         VectorCopy (b->maxs, maxs);
1567         texdef = &g_qeglobals.d_texturewin.texdef;
1568
1569         Brush_Free (b);
1570
1571         if (g_pParentWnd->ActiveXY())
1572         {
1573                 switch(g_pParentWnd->ActiveXY()->GetViewType())
1574                 {
1575                         case XY: axis = 2; break;
1576                         case XZ: axis = 1; break;
1577                         case YZ: axis = 0; break;
1578                 }
1579         }
1580         else
1581         {
1582                 axis = 2;
1583         }
1584
1585         // find center of brush
1586         width = 8;
1587         for (i = 0; i < 3; i++)
1588         {
1589                 mid[i] = (maxs[i] + mins[i]) * 0.5;
1590                 if (i == axis) continue;
1591                 if ((maxs[i] - mins[i]) * 0.5 > width)
1592                         width = (maxs[i] - mins[i]) * 0.5;
1593         }
1594
1595         b = Brush_Alloc();
1596                 
1597         // create top face
1598         f = Face_Alloc();
1599         f->texdef = *texdef;
1600         f->next = b->brush_faces;
1601         b->brush_faces = f;
1602
1603         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];
1604         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];
1605         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];
1606
1607         // create bottom face
1608         f = Face_Alloc();
1609         f->texdef = *texdef;
1610         f->next = b->brush_faces;
1611         b->brush_faces = f;
1612
1613         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];
1614         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];
1615         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];
1616
1617         for (i=0 ; i<sides ; i++)
1618         {
1619                 f = Face_Alloc();
1620                 f->texdef = *texdef;
1621                 f->next = b->brush_faces;
1622                 b->brush_faces = f;
1623
1624                 sv = sin (i*3.14159265*2/sides);
1625                 cv = cos (i*3.14159265*2/sides);
1626
1627                 f->planepts[0][(axis+1)%3] = floor(mid[(axis+1)%3]+width*cv+0.5);
1628                 f->planepts[0][(axis+2)%3] = floor(mid[(axis+2)%3]+width*sv+0.5);
1629                 f->planepts[0][axis] = mins[axis];
1630
1631                 f->planepts[1][(axis+1)%3] = f->planepts[0][(axis+1)%3];
1632                 f->planepts[1][(axis+2)%3] = f->planepts[0][(axis+2)%3];
1633                 f->planepts[1][axis] = maxs[axis];
1634
1635                 f->planepts[2][(axis+1)%3] = floor(f->planepts[0][(axis+1)%3] - width*sv + 0.5);
1636                 f->planepts[2][(axis+2)%3] = floor(f->planepts[0][(axis+2)%3] + width*cv + 0.5);
1637                 f->planepts[2][axis] = maxs[axis];
1638         }
1639
1640         Brush_AddToList (b, &selected_brushes);
1641
1642         Entity_LinkBrush (world_entity, b);
1643
1644         Brush_Build( b );
1645
1646         Sys_UpdateWindows (W_ALL);
1647 }
1648
1649
1650
1651 /*
1652 =============
1653 Brush_Free
1654
1655 Frees the brush with all of its faces and display list.
1656 Unlinks the brush from whichever chain it is in.
1657 Decrements the owner entity's brushcount.
1658 Removes owner entity if this was the last brush
1659 unless owner is the world.
1660 Removes from groups
1661 =============
1662 */
1663 void Brush_Free (brush_t *b, bool bRemoveNode)
1664 {
1665         face_t  *f, *next;
1666         epair_t *ep, *enext;
1667
1668         // remove from group
1669         if (bRemoveNode)
1670                 Group_RemoveBrush(b);
1671
1672         // free the patch if it's there
1673         if (b->patchBrush)
1674         {
1675                 Patch_Delete(b->pPatch);
1676         }
1677
1678         // free faces
1679         for (f=b->brush_faces ; f ; f=next)
1680         {
1681                 next = f->next;
1682                 Face_Free( f );
1683         }
1684
1685         // TTimo : free brush epairs
1686         for (ep = b->epairs ; ep ; ep=enext )
1687         {
1688                 enext = ep->next;
1689                 free (ep->key);
1690                 free (ep->value);
1691                 free (ep);
1692         }
1693
1694         // unlink from active/selected list
1695         if (b->next)
1696                 Brush_RemoveFromList (b);
1697
1698         // unlink from entity list
1699         if (b->onext)
1700                 Entity_UnlinkBrush (b);
1701
1702         free (b);
1703 }
1704
1705 /*
1706 =============
1707 Face_MemorySize
1708 =============
1709 */
1710 int Face_MemorySize(face_t *f )
1711 {
1712   int size = 0;
1713
1714   if (f->face_winding)
1715   {
1716 //    size += _msize(f->face_winding);
1717     size += sizeof(vec3_t)*f->face_winding->numpoints+2*sizeof(int);
1718   }
1719 //  size += _msize(f);
1720   size += sizeof(face_t);
1721   return size;
1722 }
1723
1724 /*
1725 =============
1726 Brush_MemorySize
1727 =============
1728 */
1729 int Brush_MemorySize(brush_t *b)
1730 {
1731         face_t  *f;
1732         epair_t *ep;
1733         int size = 0;
1734
1735         //
1736         if (b->patchBrush)
1737         {
1738                 size += Patch_MemorySize(b->pPatch);
1739         }
1740         //
1741         for (f = b->brush_faces; f; f = f->next)
1742         {
1743                 size += Face_MemorySize(f);
1744         }
1745         //
1746         for (ep = b->epairs; ep; ep = ep->next )
1747         {
1748 //              size += _msize(ep->key);
1749     size += strlen(ep->key);
1750 //              size += _msize(ep->value);
1751     size += strlen(ep->value);
1752 //              size += _msize(ep);
1753     size += sizeof(epair_t);
1754         }
1755 //      size += _msize(b);
1756   size += sizeof(brush_t);
1757         return size;
1758 }
1759
1760
1761 /*
1762 ============
1763 Brush_Clone
1764
1765 Does NOT add the new brush to any lists
1766 ============
1767 */
1768 brush_t *Brush_Clone (brush_t *b)
1769 {
1770         brush_t *n = NULL;
1771         face_t  *f, *nf;
1772
1773         if (b->patchBrush)
1774         {
1775                 patchMesh_t *p = Patch_Duplicate(b->pPatch);
1776                 Brush_RemoveFromList(p->pSymbiot);
1777                 Entity_UnlinkBrush(p->pSymbiot);
1778                 n = p->pSymbiot;
1779         }
1780         else
1781         {
1782         n = Brush_Alloc();
1783           n->numberId = g_nBrushId++;
1784                 n->owner = b->owner;
1785                 for (f=b->brush_faces ; f ; f=f->next)
1786                 {
1787                         nf = Face_Clone( f );
1788                         nf->next = n->brush_faces;
1789                         n->brush_faces = nf;
1790                 }
1791         }
1792
1793         return n;
1794 }
1795
1796 /*
1797 ============
1798 Brush_Clone
1799
1800 Does NOT add the new brush to any lists
1801 ============
1802 */
1803 brush_t *Brush_FullClone(brush_t *b)
1804 {
1805         brush_t *n = NULL;
1806         face_t *f, *nf, *f2, *nf2;
1807         int j;
1808
1809         if (b->patchBrush)
1810         {
1811                 patchMesh_t *p = Patch_Duplicate(b->pPatch);
1812                 Brush_RemoveFromList(p->pSymbiot);
1813                 Entity_UnlinkBrush(p->pSymbiot);
1814                 n = p->pSymbiot;
1815                 n->owner = b->owner;
1816                 Brush_Build(n);
1817         }
1818         else
1819         {
1820         n = Brush_Alloc();
1821         n->numberId = g_nBrushId++;
1822                 n->owner = b->owner;
1823                 VectorCopy(b->mins, n->mins);
1824                 VectorCopy(b->maxs, n->maxs);
1825                 //
1826                 for (f = b->brush_faces; f; f = f->next)
1827                 {
1828                         if (f->original) continue;
1829                         nf = Face_FullClone(f);
1830                         nf->next = n->brush_faces;
1831                         n->brush_faces = nf;
1832                         //copy all faces that have the original set to this face
1833                         for (f2 = b->brush_faces; f2; f2 = f2->next)
1834                         {
1835                                 if (f2->original == f)
1836                                 {
1837                                         nf2 = Face_FullClone(f2);
1838                                         nf2->next = n->brush_faces;
1839                                         n->brush_faces = nf2;
1840                                         //set original
1841                                         nf2->original = nf;
1842                                 }
1843                         }
1844                 }
1845                 for (nf = n->brush_faces; nf; nf = nf->next)
1846                 {
1847                         Face_SetColor(n, nf, 1.0);
1848                         if (nf->face_winding)
1849       {
1850         if (g_qeglobals.m_bBrushPrimitMode)
1851                         EmitBrushPrimitTextureCoordinates(nf,nf->face_winding);
1852         else
1853         {
1854                                   for (j = 0; j < nf->face_winding->numpoints; j++)
1855                                         EmitTextureCoordinates(nf->face_winding->points[j], nf->d_texture, nf);
1856         }
1857       }
1858                 }
1859   }
1860         return n;
1861 }
1862
1863  // FIXME - spog - finish this later..
1864  /*
1865 bool Triangle_Ray(vec3_t origin, vec3_t dir, vec3_t p1, vec3_t p2, vec3_t p3)
1866 {
1867         int i;
1868         vec3_t v1, v2, normal[3];
1869         float d;
1870
1871         //Sys_Printf("p1: %f %f %f\n",p1[0],p1[1],p1[2]);
1872         //Sys_Printf("p2: %f %f %f\n",p2[0],p2[1],p2[2]);
1873         //Sys_Printf("p3: %f %f %f\n",p3[0],p3[1],p3[2]);
1874         //Sys_Printf("origin: %f %f %f\n",origin[0],origin[1],origin[2]);
1875                 
1876         // test ray against triangle
1877         // get triangle plane normal
1878         //VectorSubtract(p1, p2, v1);
1879         //VectorSubtract(p1, p3, v2);
1880         //CrossProduct(v1, v2, v1);
1881         // check normal against direction
1882         //if (DotProduct(dir, v1) >= 0)
1883         //{
1884                 // generate cone normals
1885                 VectorSubtract(origin, p1, v1);
1886                 VectorSubtract(origin, p2, v2);
1887                 CrossProduct(v1, v2, normal[0]);
1888                 VectorSubtract(origin, p2, v1);
1889                 VectorSubtract(origin, p3, v2);
1890                 CrossProduct(v1, v2, normal[1]);
1891                 VectorSubtract(origin, p3, v1);
1892                 VectorSubtract(origin, p1, v2);
1893                 CrossProduct(v1, v2, normal[2]);
1894         //}
1895         //else
1896         //{
1897                 // flip normals if triangle faces away
1898         //      Sys_Printf("flipped\n");
1899         //      VectorSubtract(origin, p1, v1);
1900         //      VectorSubtract(origin, p3, v2);
1901         //      CrossProduct(v1, v2, normal[0]);
1902         //      VectorSubtract(origin, p3, v1);
1903         //      VectorSubtract(origin, p2, v2);
1904         //      CrossProduct(v1, v2, normal[1]);
1905         //      VectorSubtract(origin, p2, v1);
1906         //      VectorSubtract(origin, p1, v2);
1907         //      CrossProduct(v1, v2, normal[2]);
1908         //}
1909         
1910         for (i=0; i<3; i++)
1911         {
1912                 VectorNormalize(normal[i]);
1913                 //Sys_Printf("direction: %f %f %f\n",dir[0],dir[1],dir[2]);
1914                 //Sys_Printf("normal: %f %f %f\n",normal[i][0],normal[i][1],normal[i][2]);
1915                 d = DotProduct(dir, normal[i]);
1916                 //Sys_Printf("dotproduct: %f\n",d);
1917                 if (d < 0)
1918                         return false;
1919         }
1920         return true;
1921 }
1922 */
1923
1924 /*
1925 extern int Triangle_Ray(float orig[3], float dir[3], bool bCullBack,
1926                  float vert0[3], float vert1[3], float vert2[3],
1927                  double *t, double *u, double *v);
1928
1929 bool Model_Ray(brush_t *b, vec3_t origin, vec3_t dir, double *t, double *u, double *v)
1930 {
1931   bool bIntersect = false;
1932   float tBest = FLT_MAX;
1933   int i, j;
1934   vec3_t xyz[3];
1935   vec3_t vRay[2];
1936
1937   float angle = FloatForKey (b->owner, "angle"); // FIXME: should be set when this entity key is set
1938   
1939   VectorSubtract (origin, b->owner->origin, vRay[0]);
1940   VectorCopy (dir, vRay[1]);
1941
1942   if (angle > 0)
1943   {
1944     int i;
1945     float s, c;
1946     float x, y;
1947
1948     s = sin (-angle/180*Q_PI);
1949     c = cos (-angle/180*Q_PI);
1950
1951     for (i=0; i<2; i++)
1952     {
1953       x = vRay[i][0];
1954       y = vRay[i][1];
1955       vRay[i][0] = (x * c) - (y * s);
1956       vRay[i][1] = (x * s) + (y * c);
1957     }
1958   }
1959
1960   entitymodel *model = b->owner->md3Class->model;
1961
1962   while (model != NULL)
1963   {
1964     for (i = 0; i < model->nTriCount; i++)
1965     {
1966       for (j = 0; j < 3; j++)
1967         VectorCopy(model->pVertList[model->pTriList[i].indexes[j]].v, xyz[j]);
1968      
1969       if (Triangle_Ray(vRay[0], vRay[1], true, xyz[0], xyz[2], xyz[1], t, u, v))
1970       {
1971         bIntersect = true;
1972         if (*t < tBest)
1973           tBest = *t;
1974       }
1975     }
1976     model = model->pNext;
1977   }
1978   if (bIntersect)
1979   {
1980     *t = tBest;
1981     return true;
1982   }
1983   else
1984   {
1985     *t = 0;
1986     return false;
1987   }
1988 }
1989 */
1990
1991 /*
1992 ==============
1993 Brush_Ray
1994
1995 Itersects a ray with a brush
1996 Returns the face hit and the distance along the ray the intersection occured at
1997 Returns NULL and 0 if not hit at all
1998
1999 http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=556
2000 ==============
2001 */
2002 extern bool Patch_Ray(patchMesh_t *patch, vec3_t origin, vec3_t dir, double *t, double *u, double *v);
2003 face_t *Brush_Ray (vec3_t origin, vec3_t dir, brush_t *b, float *dist, int nFlags)
2004 {
2005         face_t  *f, *firstface = NULL;
2006         vec3_t  p1, p2;
2007         float   frac, d1, d2;
2008         int             i;
2009
2010         if (b->owner->eclass->fixedsize
2011     && b->owner->model.pSelect
2012     && !(!IsBrushSelected(b) && (g_PrefsDlg.m_nEntityShowState & ENTITY_SELECTED_ONLY))
2013     && g_PrefsDlg.m_nEntityShowState != ENTITY_BOX)
2014         {
2015     ray_t ray_local;
2016     vec_t dist_local = FLT_MAX;
2017     ray_construct_for_vec3(&ray_local, origin, dir);
2018                 if (b->owner->model.pSelect->TestRay(&ray_local, &dist_local))
2019     {
2020       *dist = dist_local;
2021       return b->brush_faces;
2022     }
2023     else
2024     {
2025       *dist = 0.0f;
2026       return NULL;
2027     }
2028         }
2029
2030   VectorCopy (origin, p1);
2031         for (i=0 ; i<3 ; i++)
2032                 p2[i] = p1[i] + dir[i]*2*g_MaxWorldCoord;
2033
2034         for (f=b->brush_faces ; f ; f=f->next)
2035         {
2036                 d1 = DotProduct (p1, f->plane.normal) - f->plane.dist;
2037                 d2 = DotProduct (p2, f->plane.normal) - f->plane.dist;
2038                 if (d1 >= 0 && d2 >= 0)
2039                 {
2040                         *dist = 0;
2041                         return NULL;    // ray is on front side of face
2042                 }
2043                 if (d1 <=0 && d2 <= 0)
2044                         continue;
2045                 // clip the ray to the plane
2046                 frac = d1 / (d1 - d2);
2047                 if (d1 > 0)
2048                 {
2049                         firstface = f;
2050                         for (i=0 ; i<3 ; i++)
2051                                 p1[i] = p1[i] + frac *(p2[i] - p1[i]);
2052                 }
2053                 else
2054                 {
2055                         for (i=0 ; i<3 ; i++)
2056                                 p2[i] = p1[i] + frac *(p2[i] - p1[i]);
2057                 }
2058         }
2059
2060         // find distance p1 is along dir
2061         VectorSubtract (p1, origin, p1);
2062         d1 = DotProduct (p1, dir);
2063
2064         *dist = d1;
2065         
2066         // new test stuff for patches
2067         if (!g_PrefsDlg.m_bPatchBBoxSelect && b->patchBrush)
2068         {
2069     double t, u, v; // t is the distance from origin to point-of-intersection.. er.. i don't know what u and v are
2070                 if (!Patch_Ray(b->pPatch, origin, dir, &t, &u, &v))
2071                 {
2072                         *dist = 0;
2073                         return NULL;
2074                 }
2075     else
2076     {
2077       *dist = (float)t;
2078       //Sys_Printf("t: %f, u: %f, v: %f\n", t, u, v);
2079     }
2080         }
2081
2082   // IMPORTANT NOTE:
2083   // modifications to the discarding code here should be matched in the selection code
2084   // see Brush_Draw  
2085   
2086   // do some last minute filtering
2087   if (firstface && nFlags & SF_CAMERA)
2088   {
2089     if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK)
2090     {
2091       if (strstr(firstface->texdef.GetName(), "caulk"))
2092       {
2093         *dist = 0;
2094         return NULL;
2095       }
2096     }
2097     if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_BOTCLIP)
2098     {
2099       if (strstr(firstface->texdef.GetName(), "botclip") || strstr(firstface->texdef.GetName(), "clipmonster"))
2100       {
2101         *dist = 0;
2102         return NULL;
2103       }
2104     }    
2105     if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP)
2106     {
2107       if (strstr(firstface->texdef.GetName(), "clip"))
2108       {
2109         *dist = 0;
2110         return NULL;
2111       }
2112     }
2113   }
2114
2115         return firstface;
2116 }
2117
2118 //PGM
2119 face_t *Brush_Point (vec3_t origin, brush_t *b)
2120 {
2121         face_t  *f;
2122         float   d1;
2123
2124         for (f=b->brush_faces ; f ; f=f->next)
2125         {
2126                 d1 = DotProduct (origin, f->plane.normal) - f->plane.dist;
2127                 if (d1 > 0)
2128                 {
2129                         return NULL;    // point is on front side of face
2130                 }
2131         }
2132
2133         return b->brush_faces;
2134 }
2135 //PGM
2136
2137
2138 void    Brush_AddToList (brush_t *b, brush_t *blist)
2139 {
2140         if (b->next || b->prev)
2141                 Error ("Brush_AddToList: already linked");
2142         
2143         if (blist == &selected_brushes || blist == &active_brushes)
2144         {
2145                 if (b->patchBrush && blist == &selected_brushes)
2146                 {
2147                         Patch_Select(b->pPatch);
2148                 }
2149         }
2150         b->next = blist->next;
2151         blist->next->prev = b;
2152         blist->next = b;
2153         b->prev = blist;
2154         
2155         // TTimo messaging
2156         DispatchRadiantMsg( RADIANT_SELECTION );        
2157 }
2158
2159 void    Brush_RemoveFromList (brush_t *b)
2160 {
2161         if (!b->next || !b->prev)
2162                 Error ("Brush_RemoveFromList: not linked");
2163         
2164         if (b->patchBrush)
2165         {
2166                 Patch_Deselect(b->pPatch);
2167         }
2168         b->next->prev = b->prev;
2169         b->prev->next = b->next;
2170         b->next = b->prev = NULL;
2171 }
2172
2173 /*
2174 ===============
2175 SetFaceTexdef
2176
2177 Doesn't set the curve flags
2178
2179 NOTE : ( TTimo )
2180         never trust f->d_texture here, f->texdef and f->d_texture are out of sync when called by Brush_SetTexture
2181         use Texture_ForName() to find the right shader
2182         FIXME : send the right shader ( qtexture_t * ) in the parameters ?
2183
2184 TTimo: surface plugin, added an IPluginTexdef* parameter
2185                 if not NULL, get ->Copy() of it into the face ( and remember to hook )
2186                 if NULL, ask for a default
2187
2188  TTimo - shader code cleanup
2189    added IShader* parameter
2190   ===============
2191 */
2192 void SetFaceTexdef2 (brush_t *b, face_t *f, IShader *pShader, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef* pPlugTexdef) {
2193         int             oldFlags;
2194         int             oldContents;
2195         face_t  *tf;
2196
2197         oldFlags = f->texdef.flags;
2198         oldContents = f->texdef.contents;
2199         if (g_qeglobals.m_bBrushPrimitMode)
2200         {
2201                 f->texdef = *texdef;
2202                 ConvertTexMatWithQTexture( brushprimit_texdef, NULL, &f->brushprimit_texdef, QERApp_Shader_ForName( f->texdef.GetName() )->getTexture() );
2203         }
2204         else
2205                 if (bFitScale)
2206                 {
2207                         f->texdef = *texdef;
2208                         // fit the scaling of the texture on the actual plane
2209                         vec3_t p1,p2,p3; // absolute coordinates
2210                         // compute absolute coordinates
2211                         ComputeAbsolute(f,p1,p2,p3);
2212                         // compute the scale
2213                         vec3_t vx,vy;
2214                         VectorSubtract(p2,p1,vx);
2215                         VectorNormalize(vx, vx);
2216                         VectorSubtract(p3,p1,vy);
2217                         VectorNormalize(vy, vy);
2218                         // assign scale
2219                         VectorScale(vx,texdef->scale[0],vx);
2220                         VectorScale(vy,texdef->scale[1],vy);
2221                         VectorAdd(p1,vx,p2);
2222                         VectorAdd(p1,vy,p3);
2223                         // compute back shift scale rot
2224                         AbsoluteToLocal(f->plane,f,p1,p2,p3);
2225                 }
2226                 else
2227                         f->texdef = *texdef;
2228         f->texdef.flags = (f->texdef.flags & ~SURF_KEEP) | (oldFlags & SURF_KEEP);
2229         f->texdef.contents = (f->texdef.contents & ~CONTENTS_KEEP) | (oldContents & CONTENTS_KEEP);
2230
2231         // if this is a curve face, set all other curve faces to the same texdef
2232         if (f->texdef.flags & SURF_CURVE)
2233         {
2234                 for (tf = b->brush_faces ; tf ; tf = tf->next)
2235                 {
2236                         if (tf->texdef.flags & SURF_CURVE)
2237                                 tf->texdef = f->texdef;
2238                 }
2239         }
2240 }
2241
2242 /*
2243 ===============
2244 SetFaceTexdef
2245
2246 Doesn't set the curve flags
2247   
2248 NOTE : ( TTimo )
2249         never trust f->d_texture here, f->texdef and f->d_texture are out of sync when called by Brush_SetTexture
2250         use Texture_ForName() to find the right shader
2251         FIXME : send the right shader ( qtexture_t * ) in the parameters ?
2252  
2253  TTimo: surface plugin, added an IPluginTexdef* parameter
2254                 if not NULL, get ->Copy() of it into the face ( and remember to hook )
2255                 if NULL, ask for a default
2256 ===============
2257 */
2258 void SetFaceTexdef (face_t *f, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef* pPlugTexdef) {
2259         int             oldFlags;
2260         int             oldContents;
2261  
2262         oldFlags = f->texdef.flags;
2263         oldContents = f->texdef.contents;
2264
2265   if(strcmp(f->texdef.GetName(), texdef->GetName()) != 0) // set shader here instead of Brush_Build
2266     Face_SetShader(f, texdef->GetName());
2267
2268         if (g_qeglobals.m_bBrushPrimitMode)
2269         {
2270                 f->texdef = *texdef;
2271                 ConvertTexMatWithQTexture( brushprimit_texdef, NULL, &f->brushprimit_texdef, QERApp_Shader_ForName( f->texdef.GetName() )->getTexture() );
2272         }
2273         else
2274   { 
2275                 if (bFitScale)
2276                 {
2277                         f->texdef = *texdef;
2278                         // fit the scaling of the texture on the actual plane
2279                         vec3_t p1,p2,p3; // absolute coordinates
2280                         // compute absolute coordinates
2281                         ComputeAbsolute(f,p1,p2,p3);
2282                         // compute the scale
2283                         vec3_t vx,vy;
2284                         VectorSubtract(p2,p1,vx);
2285                         VectorNormalize(vx, vx);
2286                         VectorSubtract(p3,p1,vy);
2287                         VectorNormalize(vy, vy);
2288                         // assign scale
2289                         VectorScale(vx,texdef->scale[0],vx);
2290                         VectorScale(vy,texdef->scale[1],vy);
2291                         VectorAdd(p1,vx,p2);
2292                         VectorAdd(p1,vy,p3);
2293                         // compute back shift scale rot
2294                         AbsoluteToLocal(f->plane,f,p1,p2,p3);
2295                 }
2296                 else
2297     {
2298                         f->texdef = *texdef;
2299     }
2300   }
2301         f->texdef.flags = (f->texdef.flags & ~SURF_KEEP) | (oldFlags & SURF_KEEP);
2302         f->texdef.contents = (f->texdef.contents & ~CONTENTS_KEEP) | (oldContents & CONTENTS_KEEP);
2303 }
2304  
2305 #ifdef _DEBUG
2306 void Brush_SetTexture2 (brush_t *b, IShader *pShader, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef* pTexdef)
2307 {
2308         for (face_t* f = b->brush_faces ; f ; f = f->next) 
2309                 SetFaceTexdef2 (b, f, pShader, texdef, brushprimit_texdef, bFitScale, pTexdef);
2310         Brush_Build( b );
2311         if (b->patchBrush)
2312         {
2313                 Patch_SetTexture(b->pPatch, texdef, pTexdef );
2314                 b->bFiltered = FilterBrush( b );
2315         }
2316 }
2317 #endif
2318
2319 void Brush_SetTexture (brush_t *b, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef* pTexdef)
2320 {
2321         for (face_t* f = b->brush_faces ; f ; f = f->next) 
2322                 SetFaceTexdef (f, texdef, brushprimit_texdef, bFitScale, pTexdef);
2323         Brush_Build( b );
2324         if (b->patchBrush)
2325         {
2326                 Patch_SetTexture(b->pPatch, texdef, pTexdef );
2327                 b->bFiltered = FilterBrush( b );
2328         }
2329 }
2330
2331
2332 qboolean ClipLineToFace (vec3_t p1, vec3_t p2, face_t *f)
2333 {
2334         float   d1, d2, fr;
2335         int             i;
2336         float   *v;
2337
2338         d1 = DotProduct (p1, f->plane.normal) - f->plane.dist;
2339         d2 = DotProduct (p2, f->plane.normal) - f->plane.dist;
2340
2341         if (d1 >= 0 && d2 >= 0)
2342                 return false;           // totally outside
2343         if (d1 <= 0 && d2 <= 0)
2344                 return true;            // totally inside
2345
2346         fr = d1 / (d1 - d2);
2347
2348         if (d1 > 0)
2349                 v = p1;
2350         else
2351                 v = p2;
2352
2353         for (i=0 ; i<3 ; i++)
2354                 v[i] = p1[i] + fr*(p2[i] - p1[i]);
2355
2356         return true;
2357 }
2358
2359
2360 int AddPlanept (float *f)
2361 {
2362         int             i;
2363
2364         for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
2365                 if (g_qeglobals.d_move_points[i] == f)
2366                         return 0;
2367         g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = f;
2368         return 1;
2369 }
2370
2371 /*
2372 ==============
2373 Brush_SelectFaceForDragging
2374
2375 Adds the faces planepts to move_points, and
2376 rotates and adds the planepts of adjacent face if shear is set
2377 ==============
2378 */
2379 void Brush_SelectFaceForDragging (brush_t *b, face_t *f, qboolean shear)
2380 {
2381         int             i;
2382         face_t  *f2;
2383         winding_t       *w;
2384         float   d;
2385         brush_t *b2;
2386         int             c;
2387
2388         if (b->owner->eclass->fixedsize)
2389                 return;
2390
2391         c = 0;
2392         for (i=0 ; i<3 ; i++)
2393                 c += AddPlanept (f->planepts[i]);
2394         if (c == 0)
2395                 return;         // already completely added
2396
2397         // select all points on this plane in all brushes the selection
2398         for (b2=selected_brushes.next ; b2 != &selected_brushes ; b2 = b2->next)
2399         {
2400                 if (b2 == b)
2401                         continue;
2402                 for (f2=b2->brush_faces ; f2 ; f2=f2->next)
2403                 {
2404                         for (i=0 ; i<3 ; i++)
2405                                 if (fabs(DotProduct(f2->planepts[i], f->plane.normal)
2406                                 -f->plane.dist) > ON_EPSILON)
2407                                         break;
2408                         if (i==3)
2409                         {       // move this face as well
2410                                 Brush_SelectFaceForDragging (b2, f2, shear);
2411                                 break;
2412                         }
2413                 }
2414         }
2415
2416
2417         // if shearing, take all the planes adjacent to 
2418         // selected faces and rotate their points so the
2419         // edge clipped by a selcted face has two of the points
2420         if (!shear)
2421                 return;
2422
2423         for (f2=b->brush_faces ; f2 ; f2=f2->next)
2424         {
2425                 if (f2 == f)
2426                         continue;
2427                 w = Brush_MakeFaceWinding (b, f2);
2428                 if (!w)
2429                         continue;
2430
2431                 // any points on f will become new control points
2432                 for (i=0 ; i<w->numpoints ; i++)
2433                 {
2434                         d = DotProduct (w->points[i], f->plane.normal) 
2435                                 - f->plane.dist;
2436                         if (d > -ON_EPSILON && d < ON_EPSILON)
2437                                 break;
2438                 }
2439
2440                 //
2441                 // if none of the points were on the plane,
2442                 // leave it alone
2443                 //
2444                 if (i != w->numpoints)
2445                 {
2446                         if (i == 0)
2447                         {       // see if the first clockwise point was the
2448                                 // last point on the winding
2449                                 d = DotProduct (w->points[w->numpoints-1]
2450                                         , f->plane.normal) - f->plane.dist;
2451                                 if (d > -ON_EPSILON && d < ON_EPSILON)
2452                                         i = w->numpoints - 1;
2453                         }
2454
2455                         AddPlanept (f2->planepts[0]);
2456
2457                         VectorCopy (w->points[i], f2->planepts[0]);
2458                         if (++i == w->numpoints)
2459                                 i = 0;
2460                         
2461                         // see if the next point is also on the plane
2462                         d = DotProduct (w->points[i]
2463                                 , f->plane.normal) - f->plane.dist;
2464                         if (d > -ON_EPSILON && d < ON_EPSILON)
2465                                 AddPlanept (f2->planepts[1]);
2466
2467                         VectorCopy (w->points[i], f2->planepts[1]);
2468                         if (++i == w->numpoints)
2469                                 i = 0;
2470
2471                         // the third point is never on the plane
2472
2473                         VectorCopy (w->points[i], f2->planepts[2]);
2474                 }
2475
2476                 free(w);
2477         }
2478 }
2479
2480 /*
2481 ==============
2482 Brush_SideSelect
2483
2484 The mouse click did not hit the brush, so grab one or more side
2485 planes for dragging
2486 ==============
2487 */
2488 void Brush_SideSelect (brush_t *b, vec3_t origin, vec3_t dir
2489                                            , qboolean shear)
2490 {
2491         face_t  *f, *f2;
2492         vec3_t  p1, p2;
2493
2494         for (f=b->brush_faces ; f ; f=f->next)
2495         {
2496                 VectorCopy (origin, p1);
2497                 VectorMA (origin, 2*g_MaxWorldCoord, dir, p2);
2498
2499                 for (f2=b->brush_faces ; f2 ; f2=f2->next)
2500                 {
2501                         if (f2 == f)
2502                                 continue;
2503                         ClipLineToFace (p1, p2, f2);
2504                 }
2505
2506                 if (f2)
2507                         continue;
2508
2509                 if (VectorCompare (p1, origin))
2510                         continue;
2511                 if (ClipLineToFace (p1, p2, f))
2512                         continue;
2513
2514                 Brush_SelectFaceForDragging (b, f, shear);
2515         }       
2516 }
2517
2518 bool g_bBuildWindingsNoTexBuild = false;
2519
2520 void Brush_SetBuildWindingsNoTexBuild(bool bBuild)
2521 {
2522   g_bBuildWindingsNoTexBuild = bBuild;
2523 }
2524
2525 // TTimo: don't rebuild pShader and d_texture if it doesn't seem necessary
2526 //    saves quite a lot of time, but on the other hand we've gotta make sure we clean the d_texture in some cases
2527 //    ie when we want to update a shader
2528 //    default will make Radiant rebuild the texture, but it can be turned off by setting the flag g_bBuildWindingsNoTexBuild
2529 void Brush_BuildWindings( brush_t *b, bool bSnap )
2530 {
2531         winding_t *w;
2532         face_t    *face;
2533         vec_t      v;
2534
2535         if (bSnap)
2536                 Brush_SnapPlanepts( b );
2537
2538         // clear the mins/maxs bounds
2539         b->mins[0] = b->mins[1] = b->mins[2] = 99999;
2540         b->maxs[0] = b->maxs[1] = b->maxs[2] = -99999;
2541
2542         Brush_MakeFacePlanes (b);
2543
2544         face = b->brush_faces;
2545
2546         float fCurveColor = 1.0;
2547
2548         for ( ; face ; face=face->next)
2549         {
2550                 int i, j;
2551                 free(face->face_winding);
2552                 w = face->face_winding = Brush_MakeFaceWinding (b, face);
2553
2554     if (!g_bBuildWindingsNoTexBuild || !face->d_texture)
2555     {
2556 #ifdef _DEBUG
2557       // if there's no d_texture, then we expect pShader to be empty
2558       if (!face->d_texture && face->pShader)
2559         Sys_FPrintf(SYS_ERR, "ERROR: unexpected face->pShader != NULL with face->d_texture == NULL in Brush_BuildWindings\n");
2560 #endif
2561       if ((!face->d_texture && !face->pShader) || !face->pShader)
2562       {
2563         // NOTE TTimo
2564         // patch 84 for bug 253 doesn't dec ref the potential face->pShader
2565         // add a debug check to make sure this is actually not necessary
2566 #ifdef _DEBUG
2567         if (face->pShader)
2568         {
2569           Sys_FPrintf(SYS_ERR, "ERROR: face->pShader != NULL in Brush_BuildWindings\n");
2570         }
2571 #endif
2572         face->pShader = QERApp_Shader_ForName( face->texdef.GetName() );
2573         face->pShader->IncRef();
2574         face->d_texture = face->pShader->getTexture();
2575       }
2576     }
2577
2578                 if (!w)
2579                         continue;
2580         
2581                 for (i=0 ; i<w->numpoints ; i++)
2582                 {
2583                         // add to bounding box
2584                         for (j=0 ; j<3 ; j++)
2585                         {
2586                                 v = w->points[i][j];
2587                                 if (v > b->maxs[j])
2588                                         b->maxs[j] = v;
2589                                 if (v < b->mins[j])
2590                                         b->mins[j] = v;
2591                         }
2592                 }
2593                 Face_SetColor (b, face, fCurveColor);
2594
2595                 fCurveColor -= .10f;
2596                 if (fCurveColor <= 0)
2597                         fCurveColor = 1.0f;
2598
2599                 // computing ST coordinates for the windings
2600                 if (g_qeglobals.m_bBrushPrimitMode)
2601                 {
2602                         if (g_qeglobals.bNeedConvert)
2603                         {
2604                                 // we have parsed old brushes format and need conversion
2605                                 // convert old brush texture representation to new format
2606                                 FaceToBrushPrimitFace(face);
2607 #ifdef _DEBUG
2608                                 // use old texture coordinates code to check against
2609                             for (i=0 ; i<w->numpoints ; i++)
2610                                         EmitTextureCoordinates( w->points[i], face->d_texture, face);
2611 #endif
2612                         }
2613                         // use new texture representation to compute texture coordinates
2614                         // in debug mode we will check against old code and warn if there are differences
2615                         EmitBrushPrimitTextureCoordinates(face,w);
2616                 }
2617                 else
2618                 {
2619       if (g_qeglobals.bNeedConvert)
2620       {
2621         BrushPrimitFaceToFace(face);
2622 /*
2623         // we have parsed brush primitives and need conversion back to standard format
2624         // NOTE: converting back is a quick hack, there's some information lost and we can't do anything about it
2625                                 // FIXME: if we normalize the texture matrix to a standard 2x2 size, we end up with wrong scaling
2626                                 // I tried various tweaks, no luck .. seems shifting is lost
2627         brushprimit_texdef_t aux;
2628         ConvertTexMatWithQTexture( &face->brushprimit_texdef, face->d_texture, &aux, NULL );
2629         TexMatToFakeTexCoords( aux.coords, face->texdef.shift, &face->texdef.rotate, face->texdef.scale );
2630                                 face->texdef.scale[0]/=2.0;
2631                                 face->texdef.scale[1]/=2.0;
2632 */
2633       }
2634                     for (i=0 ; i<w->numpoints ; i++)
2635                                 EmitTextureCoordinates( w->points[i], face->d_texture, face);
2636                 }
2637         }
2638 }
2639
2640 /*
2641 ==================
2642 Brush_RemoveEmptyFaces
2643
2644 Frees any overconstraining faces
2645 ==================
2646 */
2647 void Brush_RemoveEmptyFaces ( brush_t *b )
2648 {
2649         face_t  *f, *next;
2650
2651         f = b->brush_faces;
2652         b->brush_faces = NULL;
2653
2654         for ( ; f ; f=next)
2655         {
2656                 next = f->next;
2657                 if (!f->face_winding)
2658                         Face_Free (f);
2659                 else
2660                 {
2661                         f->next = b->brush_faces;
2662                         b->brush_faces = f;
2663                 }
2664
2665         }
2666 }
2667
2668 void Brush_SnapToGrid(brush_t *pb)
2669 {
2670         face_t *f;
2671         vec3_t temp;
2672         vec3_t diff[2];
2673         int mult[3];
2674         int i, j, n;
2675         // TTimo: some brushes are "special" and should not be snapped
2676         // specially fixed-size entity ones
2677         if (pb->owner->eclass->fixedsize)
2678         {
2679                 // save current origin
2680                 VectorCopy (pb->owner->origin, temp);
2681                 // snap the origin
2682                 VectorFSnap(pb->owner->origin, g_qeglobals.d_gridsize);
2683                 // return if amount is zero
2684                 if (VectorCompare (pb->owner->origin, temp))
2685                         return;
2686                 // transform brush faces same amount
2687                 VectorSubtract (pb->owner->origin, temp, temp);
2688                 for (f = pb->brush_faces; f; f = f->next)
2689                 {
2690                         for (i=0 ; i<3 ; i++)
2691                                 VectorAdd (f->planepts[i], temp, f->planepts[i]);
2692                 }
2693         }
2694         else
2695         {
2696                 for (f = pb->brush_faces ; f; f = f->next)
2697                 {
2698                         for (j=0; j<2; j++)
2699                         {
2700                                 // spog - move planepts apart just far enough to avoid snapping two together
2701                                 VectorSubtract (f->planepts[j+1], f->planepts[j], diff[j]);
2702                                 for (i=0; i<3; i++)
2703                                 {
2704                                         if (diff[j][i] == 0.0f)
2705                                                 mult[i] = 2; // next value up from 1
2706                                         else  // multiplier = gridsize / component difference, rounded up
2707                                                 mult[i] = (int)ceil(fabs(g_qeglobals.d_gridsize / diff[j][i]));
2708                                 }
2709                                 
2710                                 if (mult[0] > 1 && mult[1] > 1 && mult[2] > 1) // if all multipliers are greater than 1
2711                                 {
2712                                         n = (mult[0] >= mult[1] && mult[0] >= mult[2]) ? 0 : (mult[1] >= mult[0] && mult[1] >= mult[2]) ? 1 : 2;
2713                                         for (i=0; i<3; i++)
2714                                                 diff[j][i] *= mult[n]; // multiply difference by multiplier of smallest component
2715                                 }
2716                                 VectorAdd (f->planepts[j], diff[j], f->planepts[j+1]);
2717                         }
2718
2719                         for (i=0; i<3; i++)
2720                                 VectorFSnap(f->planepts[i], g_qeglobals.d_gridsize);
2721
2722                 }
2723         }
2724         Brush_Build(pb,true,true,false,false); // don't filter
2725 }
2726
2727 void Brush_Rotate(brush_t *b, vec3_t vAngle, vec3_t vOrigin, bool bBuild)
2728 {
2729         for (face_t* f=b->brush_faces ; f ; f=f->next)
2730         {
2731                 for (int i=0 ; i<3 ; i++)
2732                 {
2733                         VectorRotateOrigin (f->planepts[i], vAngle, vOrigin, f->planepts[i]);
2734                 }
2735         }
2736         if (bBuild)
2737         {
2738                 Brush_Build(b,false,false,false,false); // don't filter
2739         }
2740 }
2741
2742 void Brush_Center(brush_t *b, vec3_t vNewCenter)
2743 {
2744   vec3_t vMid;
2745   // get center of the brush
2746   for (int j = 0; j < 3; j++)
2747   {
2748     vMid[j] = b->mins[j] + fabs((b->maxs[j] - b->mins[j]) * 0.5);
2749   }
2750   // calc distance between centers
2751   VectorSubtract(vNewCenter, vMid, vMid);
2752   Brush_Move(b, vMid, true);
2753
2754 }
2755
2756 void Brush_Resize(brush_t *b, vec3_t vMin, vec3_t vMax)
2757 {
2758   face_t *f;
2759   texdef_t texdef;
2760   int i;
2761   short box[3][2] = { { 0, 1 }, { 2, 0 }, { 1, 2 } };
2762
2763   for (i=0 ; i<3 ; i++)
2764                 if (vMax[i] < vMin[i])
2765                         Error ("Brush_Resize: invalid input");
2766
2767   if(b->brush_faces != NULL)
2768     texdef = b->brush_faces->texdef;
2769   else
2770     texdef = g_qeglobals.d_texturewin.texdef;
2771
2772   while (b->brush_faces != NULL)
2773   {
2774     f = b->brush_faces->next;
2775     Face_Free(b->brush_faces);
2776     b->brush_faces = f;
2777   }
2778
2779   for(i=0; i<3; i++)
2780   {
2781     f = b->brush_faces;
2782     b->brush_faces = Face_Alloc();
2783     b->brush_faces->next = f;
2784     f = b->brush_faces;
2785     f->texdef = texdef;
2786     VectorCopy(vMax, f->planepts[0]);
2787     VectorCopy(vMax, f->planepts[1]);
2788     VectorCopy(vMax, f->planepts[2]);
2789     f->planepts[2][box[i][0]] = vMin[box[i][0]];
2790     f->planepts[1][box[i][1]] = vMin[box[i][1]];
2791   }
2792   for(i=0; i<3; i++)
2793   {
2794     f = b->brush_faces;
2795     b->brush_faces = Face_Alloc();
2796     b->brush_faces->next = f;
2797     f = b->brush_faces;
2798     f->texdef = texdef;
2799     VectorCopy(vMin, f->planepts[0]);
2800     VectorCopy(vMin, f->planepts[1]);
2801     VectorCopy(vMin, f->planepts[2]);
2802     f->planepts[1][box[i][0]] = vMax[box[i][0]];
2803     f->planepts[2][box[i][1]] = vMax[box[i][1]];
2804   }
2805 }
2806
2807 void FacingVectors (entity_t *e, vec3_t forward, vec3_t right, vec3_t up)
2808 {
2809         int                     angleVal;
2810         vec3_t          angles;
2811
2812         angleVal = IntForKey(e, "angle");
2813         if (angleVal == -1)                             // up
2814         {
2815                 VectorSet(angles, 270, 0, 0);
2816         }
2817         else if(angleVal == -2)         // down
2818         {
2819                 VectorSet(angles, 90, 0, 0);
2820         }
2821         else
2822         {
2823                 VectorSet(angles, 0, angleVal, 0);
2824         }
2825
2826         AngleVectors(angles, forward, right, up);
2827 }
2828
2829 void Brush_DrawFacingAngle (brush_t *b, entity_t *e)
2830 {
2831         vec3_t  forward, right, up;
2832         vec3_t  endpoint, tip1, tip2;
2833         vec3_t  start;
2834         float   dist;
2835
2836         VectorAdd(e->brushes.onext->mins, e->brushes.onext->maxs, start);
2837         VectorScale(start, 0.5, start);
2838         dist = (b->maxs[0] - start[0]) * 2.5;
2839
2840         FacingVectors (e, forward, right, up);
2841         VectorMA (start, dist, forward, endpoint);
2842
2843         dist = (b->maxs[0] - start[0]) * 0.5;
2844         VectorMA (endpoint, -dist, forward, tip1);
2845         VectorMA (tip1, -dist, up, tip1);
2846         VectorMA (tip1, 2*dist, up, tip2);
2847
2848         qglColor4f (1, 1, 1, 1);
2849         qglLineWidth (4);
2850         qglBegin (GL_LINES);
2851         qglVertex3fv (start);
2852         qglVertex3fv (endpoint);
2853         qglVertex3fv (endpoint);
2854         qglVertex3fv (tip1);
2855         qglVertex3fv (endpoint);
2856         qglVertex3fv (tip2);
2857         qglEnd ();
2858         qglLineWidth (1);
2859 }
2860
2861 void Brush_FaceDraw(face_t *face, int nGLState)
2862 {
2863         const winding_t *w = face->face_winding;
2864   if (w == NULL) return;
2865   if (nGLState & DRAW_GL_LIGHTING && g_PrefsDlg.m_bGLLighting)
2866                 qglNormal3fv(face->plane.normal);
2867   /*
2868         if (mode & DRAW_GL_TEXTURE_2D)
2869                 qglTexCoordPointer(2, GL_FLOAT, 5, &w->points[3]);
2870         qglVertexPointer(3, GL_FLOAT, 5, w->points);
2871
2872         if (mode & DRAW_GL_FILL)
2873                 qglDrawArrays(GL_TRIANGLE_FAN, 0, w->numpoints);
2874         else
2875                 qglDrawArrays(GL_POLYGON, 0, w->numpoints);
2876   */
2877
2878   if (nGLState & DRAW_GL_FILL)
2879     qglBegin(GL_TRIANGLE_FAN);
2880   else
2881     qglBegin(GL_POLYGON);
2882         
2883         for (int i=0 ; i<w->numpoints ; i++)
2884         {
2885                 if (nGLState & DRAW_GL_TEXTURE_2D)
2886                         qglTexCoord2fv( &w->points[i][3] );
2887                 qglVertex3fv(w->points[i]);
2888         }
2889         qglEnd();
2890 }
2891
2892 void Brush_Draw(brush_t *b)
2893 {
2894         face_t                  *face;
2895         int                             order;
2896         qtexture_t              *prev = 0;
2897         winding_t *w;
2898
2899         int nDrawMode = g_pParentWnd->GetCamWnd()->Camera()->draw_mode;
2900   int nGLState = g_pParentWnd->GetCamWnd()->Camera()->draw_glstate;
2901
2902         GLfloat material[4], identity[4];
2903         VectorSet(identity, 0.8f, 0.8f, 0.8f);
2904         IShader *pShader;
2905         qglPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
2906         qglDisableClientState(GL_NORMAL_ARRAY);
2907
2908   // guarantee the texture will be set first
2909   bool bTrans;
2910         prev = NULL;
2911         for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++)
2912         {
2913                 w = face->face_winding;
2914                 if (!w)
2915                 {
2916                         continue;               // freed face
2917                 }
2918
2919      bTrans = (face->pShader->getFlags() & QER_TRANS);
2920
2921           if (bTrans && !(nGLState & DRAW_GL_BLEND))
2922       continue;
2923     if (!bTrans && nGLState & DRAW_GL_BLEND)
2924       continue;
2925                 
2926                 // IMPORTANT NOTE:
2927                 // modifications to the discarding code here should be matched in the selection code
2928                 // see Brush_Ray
2929
2930                 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK)
2931                 {
2932                         if (strstr(face->texdef.GetName(), "caulk"))
2933                                 continue;
2934                 }
2935
2936                 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_BOTCLIP)
2937                 {
2938                         if (strstr(face->texdef.GetName(), "botclip") || strstr(face->texdef.GetName(), "clipmonster"))
2939                                 continue;
2940                 }
2941
2942                 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP)
2943                 {
2944                         if (strstr(face->texdef.GetName(), "clip"))
2945                                 continue;
2946     }
2947
2948     if (nGLState & DRAW_GL_TEXTURE_2D && face->d_texture->name[0] == '(')
2949     {
2950       prev = NULL;
2951       qglDisable(GL_TEXTURE_2D);
2952     }
2953     else if (nGLState & DRAW_GL_TEXTURE_2D && (nDrawMode == cd_texture || nDrawMode == cd_light) && face->d_texture != prev)
2954     {
2955       // set the texture for this face
2956       prev = face->d_texture;
2957       qglBindTexture( GL_TEXTURE_2D, face->d_texture->texture_number );
2958     }
2959     
2960     if (nGLState & DRAW_GL_LIGHTING && !g_PrefsDlg.m_bGLLighting)
2961     {
2962       if (!b->owner->eclass->fixedsize)
2963         material[3] = face->pShader->getTrans();
2964       else
2965         material[3] = 1;
2966       VectorCopy(face->d_color, material);
2967
2968                         if (nGLState & DRAW_GL_TEXTURE_2D)
2969         qglColor4f(face->d_shade, face->d_shade, face->d_shade, material[3]);
2970                         else
2971         qglColor4fv(material);
2972     }
2973     else if (!b->owner->eclass->fixedsize)
2974                 {
2975                         pShader = face->pShader;
2976                         VectorCopy(pShader->getTexture()->color, material);
2977                         material[3] = identity[3] = pShader->getTrans();
2978
2979                         if (nGLState & DRAW_GL_TEXTURE_2D)
2980         qglColor4fv(identity);
2981                         else
2982         qglColor4fv(material);
2983                 }
2984     
2985                 // draw the polygon
2986
2987                 Brush_FaceDraw(face, nGLState);
2988         }
2989         qglPopClientAttrib();
2990 }
2991
2992 void Face_Draw( face_t *f )
2993 {
2994         int i;
2995
2996         if ( f->face_winding == 0 )
2997                 return;
2998         qglBegin(GL_POLYGON);
2999         for ( i = 0 ; i < f->face_winding->numpoints; i++)
3000                 qglVertex3fv( f->face_winding->points[i] );
3001         qglEnd();
3002 }
3003
3004 entity_t *FindEntity(const char *pszKey, const char *pszValue)
3005 {
3006         entity_t *pe;
3007         
3008         pe = entities.next;
3009         
3010         for (; pe != NULL && pe != &entities ; pe = pe->next)
3011         {
3012                 if (!strcmp(ValueForKey(pe, pszKey), pszValue))
3013                         return pe;
3014         }
3015
3016         return NULL;
3017 }
3018
3019 void Brush_DrawXY(brush_t *b, int nViewType)
3020 {
3021         face_t *face;
3022         int     order;
3023         winding_t *w;
3024         int        i;
3025
3026   if (b->patchBrush)
3027   {
3028     Patch_DrawXY(b->pPatch);
3029     if (!g_bPatchShowBounds)
3030       return;
3031   }                     
3032
3033   if (b->owner->eclass->fixedsize)
3034   {
3035     if (g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT))
3036     {
3037 #if 1 // requires vertex arrays enabled
3038       DrawLight(b->owner, DRAW_GL_WIRE, (IsBrushSelected(b)) ? g_PrefsDlg.m_nLightRadiuses : 0, nViewType);
3039 #else
3040       vec3_t vCorners[4];
3041       float fMid = b->mins[2] + (b->maxs[2] - b->mins[2]) / 2;
3042
3043       vCorners[0][0] = b->mins[0];
3044       vCorners[0][1] = b->mins[1];
3045       vCorners[0][2] = fMid;
3046
3047       vCorners[1][0] = b->mins[0];
3048       vCorners[1][1] = b->maxs[1];
3049       vCorners[1][2] = fMid;
3050
3051       vCorners[2][0] = b->maxs[0];
3052       vCorners[2][1] = b->maxs[1];
3053       vCorners[2][2] = fMid;
3054
3055       vCorners[3][0] = b->maxs[0];
3056       vCorners[3][1] = b->mins[1];
3057       vCorners[3][2] = fMid;
3058
3059       vec3_t vTop, vBottom;
3060
3061       vTop[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) / 2);
3062       vTop[1] = b->mins[1] + ((b->maxs[1] - b->mins[1]) / 2);
3063       vTop[2] = b->maxs[2];
3064
3065       VectorCopy(vTop, vBottom);
3066       vBottom[2] = b->mins[2];
3067
3068       qglBegin(GL_LINES);
3069       qglVertex3fv(vTop);
3070       qglVertex3fv(vCorners[0]);
3071       qglVertex3fv(vTop);
3072       qglVertex3fv(vCorners[1]);
3073       qglVertex3fv(vTop);
3074       qglVertex3fv(vCorners[2]);
3075       qglVertex3fv(vTop);
3076       qglVertex3fv(vCorners[3]);
3077       qglEnd();
3078
3079       qglBegin(GL_LINES);
3080       qglVertex3fv(vBottom);
3081       qglVertex3fv(vCorners[0]);
3082       qglVertex3fv(vBottom);
3083       qglVertex3fv(vCorners[1]);
3084       qglVertex3fv(vBottom);
3085       qglVertex3fv(vCorners[2]);
3086       qglVertex3fv(vBottom);
3087       qglVertex3fv(vCorners[3]);
3088       qglEnd();
3089
3090       qglBegin(GL_LINE_LOOP);
3091       qglVertex3fv(vCorners[0]);
3092       qglVertex3fv(vCorners[1]);
3093       qglVertex3fv(vCorners[2]);
3094       qglVertex3fv(vCorners[3]);
3095       qglEnd();
3096 #endif
3097       DrawBrushEntityName (b);
3098       return;
3099     }
3100     else if (b->owner->model.pRender && !(!IsBrushSelected(b) && (g_PrefsDlg.m_nEntityShowState & ENTITY_SELECTED_ONLY)))
3101     {
3102       qglPushAttrib(GL_CURRENT_BIT); // save brush colour
3103       qglColor3fv(b->owner->eclass->color);
3104       if( g_PrefsDlg.m_nEntityShowState != ENTITY_BOX )
3105         b->owner->model.pRender->Draw(DRAW_GL_WIRE, DRAW_RF_XY);
3106       aabb_draw(b->owner->model.pRender->GetAABB(), DRAW_GL_WIRE);
3107       qglPopAttrib();
3108       return;
3109     }
3110     //}
3111   }
3112
3113         for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++)
3114         {
3115                 // moved so check occurs earlier
3116                 w = face->face_winding;
3117                 if (!w)
3118                         continue;
3119                 // only draw polygons facing in a direction we care about
3120     if (nViewType == XY)
3121     {
3122                   if (face->plane.normal[2] <= 0)
3123                           continue;
3124     }
3125     else
3126     {
3127       if (nViewType == XZ)
3128       {
3129         if (face->plane.normal[1] >= 0) // stop axes being mirrored
3130           continue;
3131       }
3132       else 
3133       {
3134         if (face->plane.normal[0] <= 0)
3135           continue;
3136       }
3137     }
3138
3139                 // draw the polygon
3140                 qglBegin(GL_LINE_LOOP);
3141     for (i=0 ; i<w->numpoints ; i++)
3142                   qglVertex3fv(w->points[i]);
3143                 qglEnd();
3144         }
3145
3146         DrawBrushEntityName (b);
3147
3148 }
3149
3150 /*
3151 ============
3152 Brush_Move
3153 ============
3154 */
3155 void Brush_Move (brush_t *b, const vec3_t move, bool bSnap)
3156 {
3157   int i;
3158   face_t *f;
3159
3160   for (f=b->brush_faces ; f ; f=f->next)
3161     for (i=0 ; i<3 ; i++)
3162       VectorAdd (f->planepts[i], move, f->planepts[i]);
3163
3164   if (g_PrefsDlg.m_bTextureLock && !b->owner->eclass->fixedsize)
3165   {
3166     for (f=b->brush_faces ; f ; f=f->next)
3167     {
3168       vec3_t vTemp;
3169       VectorCopy(move, vTemp);
3170       Face_MoveTexture(f, vTemp);
3171     }
3172   }
3173
3174   Brush_Build( b, bSnap,true,false,false); // don't filter
3175
3176
3177   if (b->patchBrush)
3178   {
3179     //Patch_Move(b->nPatchID, move);
3180     Patch_Move(b->pPatch, move);
3181   }
3182
3183
3184   // PGM - keep the origin vector up to date on fixed size entities.
3185   if(b->owner->eclass->fixedsize)
3186   {
3187     char text[64];
3188     VectorAdd(b->owner->origin, move, b->owner->origin);
3189     sprintf (text, "%i %i %i",
3190       (int)b->owner->origin[0], (int)b->owner->origin[1], (int)b->owner->origin[2]);
3191     SetKeyValue(b->owner, "origin", text);
3192           //VectorAdd(b->maxs, b->mins, b->owner->origin);
3193           //VectorScale(b->owner->origin, 0.5, b->owner->origin);
3194   }
3195 }
3196
3197
3198
3199 void Brush_Print(brush_t* b)
3200 {
3201   int nFace = 0;
3202   for (face_t* f = b->brush_faces ; f ; f=f->next)
3203   {
3204     Sys_Printf("Face %i\n", nFace++);
3205     Sys_Printf("%f %f %f\n", f->planepts[0][0], f->planepts[0][1], f->planepts[0][2]);
3206     Sys_Printf("%f %f %f\n", f->planepts[1][0], f->planepts[1][1], f->planepts[1][2]);
3207     Sys_Printf("%f %f %f\n", f->planepts[2][0], f->planepts[2][1], f->planepts[2][2]);
3208   }
3209  }
3210
3211
3212
3213 /*
3214 =============
3215 Brush_MakeSided
3216
3217 Makes the current brushhave the given number of 2d sides and turns it into a cone
3218 =============
3219 */
3220 void Brush_MakeSidedCone(int sides)
3221 {
3222         int             i;
3223         vec3_t  mins, maxs;
3224         brush_t *b;
3225         texdef_t        *texdef;
3226         face_t  *f;
3227         vec3_t  mid;
3228         float   width;
3229         float   sv, cv;
3230
3231         if (sides < 3 || sides > 32)
3232         {
3233                 Sys_Status ("Bad sides number", 0);
3234                 return;
3235         }
3236
3237         if (!QE_SingleBrush ())
3238         {
3239                 Sys_Status ("Must have a single brush selected", 0 );
3240                 return;
3241         }
3242
3243         b = selected_brushes.next;
3244         VectorCopy (b->mins, mins);
3245         VectorCopy (b->maxs, maxs);
3246         texdef = &g_qeglobals.d_texturewin.texdef;
3247
3248         Brush_Free (b);
3249
3250         // find center of brush
3251         width = 8;
3252         for (i=0 ; i<2 ; i++)
3253         {
3254                 mid[i] = (maxs[i] + mins[i])*0.5;
3255                 if (maxs[i] - mins[i] > width)
3256                         width = maxs[i] - mins[i];
3257         }
3258         width /= 2;
3259
3260         b = Brush_Alloc();
3261
3262         // create bottom face
3263         f = Face_Alloc();
3264         f->texdef = *texdef;
3265         f->next = b->brush_faces;
3266         b->brush_faces = f;
3267
3268         f->planepts[0][0] = mins[0];f->planepts[0][1] = mins[1];f->planepts[0][2] = mins[2];
3269         f->planepts[1][0] = maxs[0];f->planepts[1][1] = mins[1];f->planepts[1][2] = mins[2];
3270         f->planepts[2][0] = maxs[0];f->planepts[2][1] = maxs[1];f->planepts[2][2] = mins[2];
3271
3272         for (i=0 ; i<sides ; i++)
3273         {
3274                 f = Face_Alloc();
3275                 f->texdef = *texdef;
3276                 f->next = b->brush_faces;
3277                 b->brush_faces = f;
3278
3279                 sv = sin (i*3.14159265*2/sides);
3280                 cv = cos (i*3.14159265*2/sides);
3281
3282
3283                 f->planepts[0][0] = floor(mid[0]+width*cv+0.5);
3284                 f->planepts[0][1] = floor(mid[1]+width*sv+0.5);
3285                 f->planepts[0][2] = mins[2];
3286
3287                 f->planepts[1][0] = mid[0];
3288                 f->planepts[1][1] = mid[1];
3289                 f->planepts[1][2] = maxs[2];
3290
3291                 f->planepts[2][0] = floor(f->planepts[0][0] - width * sv + 0.5);
3292                 f->planepts[2][1] = floor(f->planepts[0][1] + width * cv + 0.5);
3293                 f->planepts[2][2] = maxs[2];
3294
3295         }
3296
3297         Brush_AddToList (b, &selected_brushes);
3298
3299         Entity_LinkBrush (world_entity, b);
3300
3301         Brush_Build( b );
3302
3303         Sys_UpdateWindows (W_ALL);
3304 }
3305
3306 /*
3307 =============
3308 Brush_MakeSided
3309
3310 Makes the current brushhave the given number of 2d sides and turns it into a sphere
3311 =============
3312
3313 */
3314 void Brush_MakeSidedSphere(int sides)
3315 {
3316         int             i,j;
3317         vec3_t  mins, maxs;
3318         brush_t *b;
3319         texdef_t        *texdef;
3320         face_t  *f;
3321         vec3_t  mid;
3322
3323         if (sides < 4 || sides > 32)
3324         {
3325                 Sys_Status ("Bad sides number", 0);
3326                 return;
3327         }
3328
3329         if (!QE_SingleBrush ())
3330         {
3331                 Sys_Status ("Must have a single brush selected", 0 );
3332                 return;
3333         }
3334
3335         b = selected_brushes.next;
3336         VectorCopy (b->mins, mins);
3337         VectorCopy (b->maxs, maxs);
3338         texdef = &g_qeglobals.d_texturewin.texdef;
3339
3340         Brush_Free (b);
3341
3342         // find center of brush
3343         float radius = 8;
3344         for (i=0 ; i<2 ; i++)
3345         {
3346                 mid[i] = (maxs[i] + mins[i])*0.5;
3347                 if (maxs[i] - mins[i] > radius)
3348                         radius = maxs[i] - mins[i];
3349         }
3350         radius /= 2;
3351
3352         b = Brush_Alloc();
3353
3354         float dt = float(2 * Q_PI / sides);
3355         float dp = float(Q_PI / sides);
3356   float t,p;
3357         for(i=0; i <= sides-1; i++)
3358   {
3359                 for(j=0;j <= sides-2; j++)
3360                 {
3361                         t = i * dt;
3362                         p = float(j * dp - Q_PI / 2);
3363
3364       f = Face_Alloc();
3365             f->texdef = *texdef;
3366             f->next = b->brush_faces;
3367             b->brush_faces = f;
3368
3369       VectorPolar(f->planepts[0], radius, t, p);
3370       VectorPolar(f->planepts[1], radius, t, p + dp);
3371       VectorPolar(f->planepts[2], radius, t + dt, p + dp);
3372
3373       for (int k = 0; k < 3; k++)
3374         VectorAdd(f->planepts[k], mid, f->planepts[k]);
3375                 }
3376   }
3377
3378   p = float((sides - 1) * dp - Q_PI / 2);
3379         for(i = 0; i <= sides-1; i++)
3380         {
3381                 t = i * dt;
3382
3383     f = Face_Alloc();
3384           f->texdef = *texdef;
3385           f->next = b->brush_faces;
3386           b->brush_faces = f;
3387
3388     VectorPolar(f->planepts[0], radius, t, p);
3389     VectorPolar(f->planepts[1], radius, t + dt, p + dp);
3390     VectorPolar(f->planepts[2], radius, t + dt, p);
3391
3392     for (int k = 0; k < 3; k++)
3393       VectorAdd(f->planepts[k], mid, f->planepts[k]);
3394         }
3395
3396         Brush_AddToList (b, &selected_brushes);
3397
3398         Entity_LinkBrush (world_entity, b);
3399
3400         Brush_Build( b );
3401
3402         Sys_UpdateWindows (W_ALL);
3403 }
3404
3405 void Face_FitTexture( face_t * face, int nHeight, int nWidth )
3406 {
3407   winding_t *w;
3408   vec3_t   mins,maxs;
3409   int i;
3410   float width, height, temp;
3411   float rot_width, rot_height;
3412   float cosv,sinv,ang;
3413   float min_t, min_s, max_t, max_s;
3414   float s,t;
3415   vec3_t        vecs[2];
3416   vec3_t   coords[4];
3417   texdef_t      *td;
3418   
3419   if (nHeight < 1)
3420     nHeight = 1;
3421   if (nWidth < 1)
3422     nWidth = 1;
3423   
3424   ClearBounds (mins, maxs);
3425   
3426   w = face->face_winding;
3427   if (!w)
3428   {
3429     return;
3430   }
3431   for (i=0 ; i<w->numpoints ; i++)
3432   {
3433     AddPointToBounds( w->points[i], mins, maxs );
3434   }
3435   
3436   if (g_qeglobals.m_bBrushPrimitMode)
3437     Face_FitTexture_BrushPrimit( face, mins, maxs, nHeight, nWidth );
3438   else
3439   {
3440     
3441     td = &face->texdef;
3442     //
3443     // get the current angle
3444     //
3445     ang = td->rotate / 180 * Q_PI;
3446     sinv = sin(ang);
3447     cosv = cos(ang);
3448     
3449     // get natural texture axis
3450     TextureAxisFromPlane(&face->plane, vecs[0], vecs[1]);
3451     
3452     min_s = DotProduct( mins, vecs[0] );
3453     min_t = DotProduct( mins, vecs[1] );
3454     max_s = DotProduct( maxs, vecs[0] );
3455     max_t = DotProduct( maxs, vecs[1] );
3456     width = max_s - min_s;
3457     height = max_t - min_t;
3458     coords[0][0] = min_s;
3459     coords[0][1] = min_t;
3460     coords[1][0] = max_s;
3461     coords[1][1] = min_t;
3462     coords[2][0] = min_s;
3463     coords[2][1] = max_t;
3464     coords[3][0] = max_s;
3465     coords[3][1] = max_t;
3466     min_s = min_t = 99999;
3467     max_s = max_t = -99999;
3468     for (i=0; i<4; i++)
3469     {
3470       s = cosv * coords[i][0] - sinv * coords[i][1];
3471       t = sinv * coords[i][0] + cosv * coords[i][1];
3472       if (i&1)
3473       {
3474         if (s > max_s)
3475         {
3476           max_s = s;
3477         }
3478       }
3479       else
3480       {
3481         if (s < min_s)
3482         {
3483           min_s = s;
3484         }
3485         if (i<2)
3486         {
3487           if (t < min_t)
3488           {
3489             min_t = t;
3490           }
3491         }
3492         else
3493         {
3494           if (t > max_t)
3495           {
3496             max_t = t;
3497           }
3498         }
3499       }
3500     }
3501     rot_width =  (max_s - min_s);
3502     rot_height = (max_t - min_t);
3503     td->scale[0] = -(rot_width/((float)(face->d_texture->width*nWidth)));
3504     td->scale[1] = -(rot_height/((float)(face->d_texture->height*nHeight)));
3505     
3506     td->shift[0] = min_s/td->scale[0];
3507     temp = (int)(td->shift[0] / (face->d_texture->width*nWidth));
3508     temp = (temp+1)*face->d_texture->width*nWidth;
3509     td->shift[0] = (int)(temp - td->shift[0])%(face->d_texture->width*nWidth);
3510     
3511     td->shift[1] = min_t/td->scale[1];
3512     temp = (int)(td->shift[1] / (face->d_texture->height*nHeight));
3513     temp = (temp+1)*(face->d_texture->height*nHeight);
3514     td->shift[1] = (int)(temp - td->shift[1])%(face->d_texture->height*nHeight);
3515     
3516     td->shift[1] = min_t/td->scale[1];
3517     temp = (int)(td->shift[1] / (face->d_texture->height*nHeight));
3518     temp = (temp+1)*(face->d_texture->height*nHeight);
3519     td->shift[1] = (int)(temp - td->shift[1])%(face->d_texture->height*nHeight);
3520     
3521   }
3522 }
3523
3524 void Brush_FitTexture( brush_t *b, int nHeight, int nWidth )
3525 {
3526         face_t *face;
3527
3528         for (face = b->brush_faces ; face ; face=face->next)
3529   {
3530     Face_FitTexture( face, nHeight, nWidth );
3531   }
3532 }
3533
3534 void aabb_draw(const aabb_t *aabb, int mode)
3535 {
3536   vec3_t normals[6] = { { 1, 0, 0}, { 0, 1, 0 }, { 0, 0, 1 }, {-1, 0, 0}, { 0,-1, 0 }, { 0, 0,-1 } };
3537   vec3_t points[8];
3538         vec3_t vMin, vMax;
3539   VectorSubtract(aabb->origin, aabb->extents, vMin);
3540   VectorAdd(aabb->origin, aabb->extents, vMax);
3541   VectorSet(points[0], vMin[0], vMax[1], vMax[2]);
3542   VectorSet(points[1], vMax[0], vMax[1], vMax[2]);
3543   VectorSet(points[2], vMax[0], vMin[1], vMax[2]);
3544   VectorSet(points[3], vMin[0], vMin[1], vMax[2]);
3545   VectorSet(points[4], vMin[0], vMax[1], vMin[2]);
3546   VectorSet(points[5], vMax[0], vMax[1], vMin[2]);
3547   VectorSet(points[6], vMax[0], vMin[1], vMin[2]);
3548   VectorSet(points[7], vMin[0], vMin[1], vMin[2]);
3549
3550   qglBegin(GL_QUADS);
3551
3552   qglNormal3fv(normals[0]);
3553   qglVertex3fv(points[2]);
3554   qglVertex3fv(points[1]);
3555   qglVertex3fv(points[5]);
3556   qglVertex3fv(points[6]);
3557
3558   qglNormal3fv(normals[1]);
3559   qglVertex3fv(points[1]);
3560   qglVertex3fv(points[0]);
3561   qglVertex3fv(points[4]);
3562   qglVertex3fv(points[5]);
3563
3564   qglNormal3fv(normals[2]);
3565   qglVertex3fv(points[0]);
3566   qglVertex3fv(points[1]);
3567   qglVertex3fv(points[2]);
3568   qglVertex3fv(points[3]);
3569
3570   qglNormal3fv(normals[3]);
3571   qglVertex3fv(points[3]);
3572   qglVertex3fv(points[7]);
3573   qglVertex3fv(points[4]);
3574   qglVertex3fv(points[0]);
3575
3576   qglNormal3fv(normals[4]);
3577   qglVertex3fv(points[3]);
3578   qglVertex3fv(points[2]);
3579   qglVertex3fv(points[6]);
3580   qglVertex3fv(points[7]);
3581
3582   qglNormal3fv(normals[5]);
3583   qglVertex3fv(points[7]);
3584   qglVertex3fv(points[6]);
3585   qglVertex3fv(points[5]);
3586   qglVertex3fv(points[4]);
3587
3588   qglEnd();
3589
3590 /*
3591
3592
3593   vec3_t Coords[8];
3594
3595         vec3_t vMin, vMax;
3596   VectorSubtract(aabb->origin, aabb->extents, vMin);
3597   VectorAdd(aabb->origin, aabb->extents, vMax);
3598   VectorSet(Coords[0], vMin[0], vMax[1], vMax[2]);
3599   VectorSet(Coords[1], vMax[0], vMax[1], vMax[2]);
3600   VectorSet(Coords[2], vMax[0], vMin[1], vMax[2]);
3601   VectorSet(Coords[3], vMin[0], vMin[1], vMax[2]);
3602   VectorSet(Coords[4], vMin[0], vMax[1], vMin[2]);
3603   VectorSet(Coords[5], vMax[0], vMax[1], vMin[2]);
3604   VectorSet(Coords[6], vMax[0], vMin[1], vMin[2]);
3605   VectorSet(Coords[7], vMin[0], vMin[1], vMin[2]);
3606
3607         vec3_t Normals[8] = { {-1, 0, 0 },
3608                                                                                         { 0, 0, 0 },
3609                                                                                         { 0, 0, 0 },
3610                                                                                         { 0, 0, 1 },
3611                                                                                         { 0, 0,-1 },
3612                                                                                         { 0, 1, 0 },
3613                                                                                         { 1, 0, 0 },
3614                                                                                         { 0,-1, 0 } };
3615   
3616         unsigned short Indices[24] = { 2, 1, 5, 6,
3617                                                                                                                                  1, 0, 4, 5,
3618                                                                                                                                  0, 1, 2, 3,
3619                                                                                                                                  3, 7, 4, 0,
3620                                                                                                                                  3, 2, 6, 7,
3621                                                                                                                                  7, 6, 5, 4 };
3622
3623   qglVertexPointer(3, GL_FLOAT, 0, Coords);         // filling the arrays
3624   qglNormalPointer(GL_FLOAT, 0, Normals);
3625   
3626   //glLockArraysEXT(0, count);                // extension GL_EXT_compiled_vertex_array
3627   
3628   qglDrawElements(GL_QUADS, 24, GL_UNSIGNED_SHORT, Indices);
3629     
3630   //glUnlockArraysEXT;                        // extension GL_EXT_compiled_vertex_array
3631 */
3632 }
3633
3634 qboolean IsBrushSelected(brush_t* bSel)
3635 {
3636         for (brush_t* b = selected_brushes.next ;b != NULL && b != &selected_brushes; b = b->next)
3637   {
3638     if (b == bSel)
3639       return true;
3640   }
3641   return false;
3642 }
3643
3644