]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/brush.cpp
2e5780350ac66cc4b7f7d46266c21d71fc301c90
[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 = 0;
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 #define Q2_SURF_TRANS33   0x00000010
2893 #define Q2_SURF_TRANS66   0x00000020
2894
2895 void Brush_Draw(brush_t *b)
2896 {
2897         face_t                  *face;
2898         int                             order;
2899         qtexture_t              *prev = 0;
2900         winding_t *w;
2901
2902         int nDrawMode = g_pParentWnd->GetCamWnd()->Camera()->draw_mode;
2903   int nGLState = g_pParentWnd->GetCamWnd()->Camera()->draw_glstate;
2904
2905         GLfloat material[4], identity[4];
2906         VectorSet(identity, 0.8f, 0.8f, 0.8f);
2907         IShader *pShader;
2908         qglPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
2909         qglDisableClientState(GL_NORMAL_ARRAY);
2910
2911   // guarantee the texture will be set first
2912   bool bTrans;
2913         float transVal;
2914         prev = NULL;
2915         for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++)
2916         {
2917                 w = face->face_winding;
2918                 if (!w)
2919                 {
2920                         continue;               // freed face
2921                 }
2922
2923                 bTrans = (face->pShader->getFlags() & QER_TRANS);
2924                 transVal = face->pShader->getTrans();
2925                 // try to read the texture def surface flags to get trans
2926                 if (!bTrans) {
2927                         if (face->texdef.flags & Q2_SURF_TRANS33) {
2928                                 bTrans = true;
2929                                 transVal = 0.33;
2930                         } else if (face->texdef.flags & Q2_SURF_TRANS66) {
2931                                 bTrans = true;
2932                                 transVal = 0.66;
2933                         }
2934                 }
2935
2936           if (bTrans && !(nGLState & DRAW_GL_BLEND))
2937       continue;
2938     if (!bTrans && nGLState & DRAW_GL_BLEND)
2939       continue;
2940                 
2941                 // IMPORTANT NOTE:
2942                 // modifications to the discarding code here should be matched in the selection code
2943                 // see Brush_Ray
2944
2945                 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK)
2946                 {
2947                         if (strstr(face->texdef.GetName(), "caulk"))
2948                                 continue;
2949                 }
2950
2951                 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_BOTCLIP)
2952                 {
2953                         if (strstr(face->texdef.GetName(), "botclip") || strstr(face->texdef.GetName(), "clipmonster"))
2954                                 continue;
2955                 }
2956
2957                 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP)
2958                 {
2959                         if (strstr(face->texdef.GetName(), "clip"))
2960                                 continue;
2961     }
2962
2963     if (nGLState & DRAW_GL_TEXTURE_2D && face->d_texture->name[0] == '(')
2964     {
2965       prev = NULL;
2966       qglDisable(GL_TEXTURE_2D);
2967     }
2968     else if (nGLState & DRAW_GL_TEXTURE_2D && (nDrawMode == cd_texture || nDrawMode == cd_light) && face->d_texture != prev)
2969     {
2970       // set the texture for this face
2971       prev = face->d_texture;
2972       qglBindTexture( GL_TEXTURE_2D, face->d_texture->texture_number );
2973     }
2974     
2975     if (nGLState & DRAW_GL_LIGHTING && !g_PrefsDlg.m_bGLLighting)
2976     {
2977       if (!b->owner->eclass->fixedsize)
2978         material[3] = transVal;
2979       else
2980         material[3] = 1;
2981       VectorCopy(face->d_color, material);
2982
2983                         if (nGLState & DRAW_GL_TEXTURE_2D)
2984         qglColor4f(face->d_shade, face->d_shade, face->d_shade, material[3]);
2985                         else
2986         qglColor4fv(material);
2987     }
2988     else if (!b->owner->eclass->fixedsize)
2989                 {
2990                         pShader = face->pShader;
2991                         VectorCopy(pShader->getTexture()->color, material);
2992                         material[3] = identity[3] = transVal;
2993
2994                         if (nGLState & DRAW_GL_TEXTURE_2D)
2995         qglColor4fv(identity);
2996                         else
2997         qglColor4fv(material);
2998                 }
2999     
3000                 // draw the polygon
3001
3002                 Brush_FaceDraw(face, nGLState);
3003         }
3004         qglPopClientAttrib();
3005 }
3006
3007 void Face_Draw( face_t *f )
3008 {
3009         int i;
3010
3011         if ( f->face_winding == 0 )
3012                 return;
3013         qglBegin(GL_POLYGON);
3014         for ( i = 0 ; i < f->face_winding->numpoints; i++)
3015                 qglVertex3fv( f->face_winding->points[i] );
3016         qglEnd();
3017 }
3018
3019 entity_t *FindEntity(const char *pszKey, const char *pszValue)
3020 {
3021         entity_t *pe;
3022         
3023         pe = entities.next;
3024         
3025         for (; pe != NULL && pe != &entities ; pe = pe->next)
3026         {
3027                 if (!strcmp(ValueForKey(pe, pszKey), pszValue))
3028                         return pe;
3029         }
3030
3031         return NULL;
3032 }
3033
3034 void Brush_DrawXY(brush_t *b, int nViewType)
3035 {
3036         face_t *face;
3037         int     order;
3038         winding_t *w;
3039         int        i;
3040
3041   if (b->patchBrush)
3042   {
3043     Patch_DrawXY(b->pPatch);
3044     if (!g_bPatchShowBounds)
3045       return;
3046   }                     
3047
3048   if (b->owner->eclass->fixedsize)
3049   {
3050     if (g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT))
3051     {
3052 #if 1 // requires vertex arrays enabled
3053       DrawLight(b->owner, DRAW_GL_WIRE, (IsBrushSelected(b)) ? g_PrefsDlg.m_nLightRadiuses : 0, nViewType);
3054 #else
3055       vec3_t vCorners[4];
3056       float fMid = b->mins[2] + (b->maxs[2] - b->mins[2]) / 2;
3057
3058       vCorners[0][0] = b->mins[0];
3059       vCorners[0][1] = b->mins[1];
3060       vCorners[0][2] = fMid;
3061
3062       vCorners[1][0] = b->mins[0];
3063       vCorners[1][1] = b->maxs[1];
3064       vCorners[1][2] = fMid;
3065
3066       vCorners[2][0] = b->maxs[0];
3067       vCorners[2][1] = b->maxs[1];
3068       vCorners[2][2] = fMid;
3069
3070       vCorners[3][0] = b->maxs[0];
3071       vCorners[3][1] = b->mins[1];
3072       vCorners[3][2] = fMid;
3073
3074       vec3_t vTop, vBottom;
3075
3076       vTop[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) / 2);
3077       vTop[1] = b->mins[1] + ((b->maxs[1] - b->mins[1]) / 2);
3078       vTop[2] = b->maxs[2];
3079
3080       VectorCopy(vTop, vBottom);
3081       vBottom[2] = b->mins[2];
3082
3083       qglBegin(GL_LINES);
3084       qglVertex3fv(vTop);
3085       qglVertex3fv(vCorners[0]);
3086       qglVertex3fv(vTop);
3087       qglVertex3fv(vCorners[1]);
3088       qglVertex3fv(vTop);
3089       qglVertex3fv(vCorners[2]);
3090       qglVertex3fv(vTop);
3091       qglVertex3fv(vCorners[3]);
3092       qglEnd();
3093
3094       qglBegin(GL_LINES);
3095       qglVertex3fv(vBottom);
3096       qglVertex3fv(vCorners[0]);
3097       qglVertex3fv(vBottom);
3098       qglVertex3fv(vCorners[1]);
3099       qglVertex3fv(vBottom);
3100       qglVertex3fv(vCorners[2]);
3101       qglVertex3fv(vBottom);
3102       qglVertex3fv(vCorners[3]);
3103       qglEnd();
3104
3105       qglBegin(GL_LINE_LOOP);
3106       qglVertex3fv(vCorners[0]);
3107       qglVertex3fv(vCorners[1]);
3108       qglVertex3fv(vCorners[2]);
3109       qglVertex3fv(vCorners[3]);
3110       qglEnd();
3111 #endif
3112       DrawBrushEntityName (b);
3113       return;
3114     }
3115     else if (b->owner->model.pRender && !(!IsBrushSelected(b) && (g_PrefsDlg.m_nEntityShowState & ENTITY_SELECTED_ONLY)))
3116     {
3117       qglPushAttrib(GL_CURRENT_BIT); // save brush colour
3118       qglColor3fv(b->owner->eclass->color);
3119       if( g_PrefsDlg.m_nEntityShowState != ENTITY_BOX )
3120         b->owner->model.pRender->Draw(DRAW_GL_WIRE, DRAW_RF_XY);
3121       aabb_draw(b->owner->model.pRender->GetAABB(), DRAW_GL_WIRE);
3122       qglPopAttrib();
3123       return;
3124     }
3125     //}
3126   }
3127
3128         for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++)
3129         {
3130                 // moved so check occurs earlier
3131                 w = face->face_winding;
3132                 if (!w)
3133                         continue;
3134                 // only draw polygons facing in a direction we care about
3135     if (nViewType == XY)
3136     {
3137                   if (face->plane.normal[2] <= 0)
3138                           continue;
3139     }
3140     else
3141     {
3142       if (nViewType == XZ)
3143       {
3144         if (face->plane.normal[1] >= 0) // stop axes being mirrored
3145           continue;
3146       }
3147       else 
3148       {
3149         if (face->plane.normal[0] <= 0)
3150           continue;
3151       }
3152     }
3153
3154                 // draw the polygon
3155                 qglBegin(GL_LINE_LOOP);
3156     for (i=0 ; i<w->numpoints ; i++)
3157                   qglVertex3fv(w->points[i]);
3158                 qglEnd();
3159         }
3160
3161         DrawBrushEntityName (b);
3162
3163 }
3164
3165 /*
3166 ============
3167 Brush_Move
3168 ============
3169 */
3170 void Brush_Move (brush_t *b, const vec3_t move, bool bSnap)
3171 {
3172   int i;
3173   face_t *f;
3174
3175   for (f=b->brush_faces ; f ; f=f->next)
3176     for (i=0 ; i<3 ; i++)
3177       VectorAdd (f->planepts[i], move, f->planepts[i]);
3178
3179   if (g_PrefsDlg.m_bTextureLock && !b->owner->eclass->fixedsize)
3180   {
3181     for (f=b->brush_faces ; f ; f=f->next)
3182     {
3183       vec3_t vTemp;
3184       VectorCopy(move, vTemp);
3185       Face_MoveTexture(f, vTemp);
3186     }
3187   }
3188
3189   Brush_Build( b, bSnap,true,false,false); // don't filter
3190
3191
3192   if (b->patchBrush)
3193   {
3194     //Patch_Move(b->nPatchID, move);
3195     Patch_Move(b->pPatch, move);
3196   }
3197
3198
3199   // PGM - keep the origin vector up to date on fixed size entities.
3200   if(b->owner->eclass->fixedsize)
3201   {
3202     char text[64];
3203     VectorAdd(b->owner->origin, move, b->owner->origin);
3204     sprintf (text, "%i %i %i",
3205       (int)b->owner->origin[0], (int)b->owner->origin[1], (int)b->owner->origin[2]);
3206     SetKeyValue(b->owner, "origin", text);
3207           //VectorAdd(b->maxs, b->mins, b->owner->origin);
3208           //VectorScale(b->owner->origin, 0.5, b->owner->origin);
3209   }
3210 }
3211
3212
3213
3214 void Brush_Print(brush_t* b)
3215 {
3216   int nFace = 0;
3217   for (face_t* f = b->brush_faces ; f ; f=f->next)
3218   {
3219     Sys_Printf("Face %i\n", nFace++);
3220     Sys_Printf("%f %f %f\n", f->planepts[0][0], f->planepts[0][1], f->planepts[0][2]);
3221     Sys_Printf("%f %f %f\n", f->planepts[1][0], f->planepts[1][1], f->planepts[1][2]);
3222     Sys_Printf("%f %f %f\n", f->planepts[2][0], f->planepts[2][1], f->planepts[2][2]);
3223   }
3224  }
3225
3226
3227
3228 /*
3229 =============
3230 Brush_MakeSided
3231
3232 Makes the current brushhave the given number of 2d sides and turns it into a cone
3233 =============
3234 */
3235 void Brush_MakeSidedCone(int sides)
3236 {
3237         int             i;
3238         vec3_t  mins, maxs;
3239         brush_t *b;
3240         texdef_t        *texdef;
3241         face_t  *f;
3242         vec3_t  mid;
3243         float   width;
3244         float   sv, cv;
3245
3246         if (sides < 3 || sides > 32)
3247         {
3248                 Sys_Status ("Bad sides number", 0);
3249                 return;
3250         }
3251
3252         if (!QE_SingleBrush ())
3253         {
3254                 Sys_Status ("Must have a single brush selected", 0 );
3255                 return;
3256         }
3257
3258         b = selected_brushes.next;
3259         VectorCopy (b->mins, mins);
3260         VectorCopy (b->maxs, maxs);
3261         texdef = &g_qeglobals.d_texturewin.texdef;
3262
3263         Brush_Free (b);
3264
3265         // find center of brush
3266         width = 8;
3267         for (i=0 ; i<2 ; i++)
3268         {
3269                 mid[i] = (maxs[i] + mins[i])*0.5;
3270                 if (maxs[i] - mins[i] > width)
3271                         width = maxs[i] - mins[i];
3272         }
3273         width /= 2;
3274
3275         b = Brush_Alloc();
3276
3277         // create bottom face
3278         f = Face_Alloc();
3279         f->texdef = *texdef;
3280         f->next = b->brush_faces;
3281         b->brush_faces = f;
3282
3283         f->planepts[0][0] = mins[0];f->planepts[0][1] = mins[1];f->planepts[0][2] = mins[2];
3284         f->planepts[1][0] = maxs[0];f->planepts[1][1] = mins[1];f->planepts[1][2] = mins[2];
3285         f->planepts[2][0] = maxs[0];f->planepts[2][1] = maxs[1];f->planepts[2][2] = mins[2];
3286
3287         for (i=0 ; i<sides ; i++)
3288         {
3289                 f = Face_Alloc();
3290                 f->texdef = *texdef;
3291                 f->next = b->brush_faces;
3292                 b->brush_faces = f;
3293
3294                 sv = sin (i*3.14159265*2/sides);
3295                 cv = cos (i*3.14159265*2/sides);
3296
3297
3298                 f->planepts[0][0] = floor(mid[0]+width*cv+0.5);
3299                 f->planepts[0][1] = floor(mid[1]+width*sv+0.5);
3300                 f->planepts[0][2] = mins[2];
3301
3302                 f->planepts[1][0] = mid[0];
3303                 f->planepts[1][1] = mid[1];
3304                 f->planepts[1][2] = maxs[2];
3305
3306                 f->planepts[2][0] = floor(f->planepts[0][0] - width * sv + 0.5);
3307                 f->planepts[2][1] = floor(f->planepts[0][1] + width * cv + 0.5);
3308                 f->planepts[2][2] = maxs[2];
3309
3310         }
3311
3312         Brush_AddToList (b, &selected_brushes);
3313
3314         Entity_LinkBrush (world_entity, b);
3315
3316         Brush_Build( b );
3317
3318         Sys_UpdateWindows (W_ALL);
3319 }
3320
3321 /*
3322 =============
3323 Brush_MakeSided
3324
3325 Makes the current brushhave the given number of 2d sides and turns it into a sphere
3326 =============
3327
3328 */
3329 void Brush_MakeSidedSphere(int sides)
3330 {
3331         int             i,j;
3332         vec3_t  mins, maxs;
3333         brush_t *b;
3334         texdef_t        *texdef;
3335         face_t  *f;
3336         vec3_t  mid;
3337
3338         if (sides < 4 || sides > 32)
3339         {
3340                 Sys_Status ("Bad sides number", 0);
3341                 return;
3342         }
3343
3344         if (!QE_SingleBrush ())
3345         {
3346                 Sys_Status ("Must have a single brush selected", 0 );
3347                 return;
3348         }
3349
3350         b = selected_brushes.next;
3351         VectorCopy (b->mins, mins);
3352         VectorCopy (b->maxs, maxs);
3353         texdef = &g_qeglobals.d_texturewin.texdef;
3354
3355         Brush_Free (b);
3356
3357         // find center of brush
3358         float radius = 8;
3359         for (i=0 ; i<2 ; i++)
3360         {
3361                 mid[i] = (maxs[i] + mins[i])*0.5;
3362                 if (maxs[i] - mins[i] > radius)
3363                         radius = maxs[i] - mins[i];
3364         }
3365         radius /= 2;
3366
3367         b = Brush_Alloc();
3368
3369         float dt = float(2 * Q_PI / sides);
3370         float dp = float(Q_PI / sides);
3371   float t,p;
3372         for(i=0; i <= sides-1; i++)
3373   {
3374                 for(j=0;j <= sides-2; j++)
3375                 {
3376                         t = i * dt;
3377                         p = float(j * dp - Q_PI / 2);
3378
3379       f = Face_Alloc();
3380             f->texdef = *texdef;
3381             f->next = b->brush_faces;
3382             b->brush_faces = f;
3383
3384       VectorPolar(f->planepts[0], radius, t, p);
3385       VectorPolar(f->planepts[1], radius, t, p + dp);
3386       VectorPolar(f->planepts[2], radius, t + dt, p + dp);
3387
3388       for (int k = 0; k < 3; k++)
3389         VectorAdd(f->planepts[k], mid, f->planepts[k]);
3390                 }
3391   }
3392
3393   p = float((sides - 1) * dp - Q_PI / 2);
3394         for(i = 0; i <= sides-1; i++)
3395         {
3396                 t = i * dt;
3397
3398     f = Face_Alloc();
3399           f->texdef = *texdef;
3400           f->next = b->brush_faces;
3401           b->brush_faces = f;
3402
3403     VectorPolar(f->planepts[0], radius, t, p);
3404     VectorPolar(f->planepts[1], radius, t + dt, p + dp);
3405     VectorPolar(f->planepts[2], radius, t + dt, p);
3406
3407     for (int k = 0; k < 3; k++)
3408       VectorAdd(f->planepts[k], mid, f->planepts[k]);
3409         }
3410
3411         Brush_AddToList (b, &selected_brushes);
3412
3413         Entity_LinkBrush (world_entity, b);
3414
3415         Brush_Build( b );
3416
3417         Sys_UpdateWindows (W_ALL);
3418 }
3419
3420 void Face_FitTexture( face_t * face, int nHeight, int nWidth )
3421 {
3422   winding_t *w;
3423   vec3_t   mins,maxs;
3424   int i;
3425   float width, height, temp;
3426   float rot_width, rot_height;
3427   float cosv,sinv,ang;
3428   float min_t, min_s, max_t, max_s;
3429   float s,t;
3430   vec3_t        vecs[2];
3431   vec3_t   coords[4];
3432   texdef_t      *td;
3433   
3434   if (nHeight < 1)
3435     nHeight = 1;
3436   if (nWidth < 1)
3437     nWidth = 1;
3438   
3439   ClearBounds (mins, maxs);
3440   
3441   w = face->face_winding;
3442   if (!w)
3443   {
3444     return;
3445   }
3446   for (i=0 ; i<w->numpoints ; i++)
3447   {
3448     AddPointToBounds( w->points[i], mins, maxs );
3449   }
3450   
3451   if (g_qeglobals.m_bBrushPrimitMode)
3452     Face_FitTexture_BrushPrimit( face, mins, maxs, nHeight, nWidth );
3453   else
3454   {
3455     
3456     td = &face->texdef;
3457     //
3458     // get the current angle
3459     //
3460     ang = td->rotate / 180 * Q_PI;
3461     sinv = sin(ang);
3462     cosv = cos(ang);
3463     
3464     // get natural texture axis
3465     TextureAxisFromPlane(&face->plane, vecs[0], vecs[1]);
3466     
3467     min_s = DotProduct( mins, vecs[0] );
3468     min_t = DotProduct( mins, vecs[1] );
3469     max_s = DotProduct( maxs, vecs[0] );
3470     max_t = DotProduct( maxs, vecs[1] );
3471     width = max_s - min_s;
3472     height = max_t - min_t;
3473     coords[0][0] = min_s;
3474     coords[0][1] = min_t;
3475     coords[1][0] = max_s;
3476     coords[1][1] = min_t;
3477     coords[2][0] = min_s;
3478     coords[2][1] = max_t;
3479     coords[3][0] = max_s;
3480     coords[3][1] = max_t;
3481     min_s = min_t = 99999;
3482     max_s = max_t = -99999;
3483     for (i=0; i<4; i++)
3484     {
3485       s = cosv * coords[i][0] - sinv * coords[i][1];
3486       t = sinv * coords[i][0] + cosv * coords[i][1];
3487       if (i&1)
3488       {
3489         if (s > max_s)
3490         {
3491           max_s = s;
3492         }
3493       }
3494       else
3495       {
3496         if (s < min_s)
3497         {
3498           min_s = s;
3499         }
3500         if (i<2)
3501         {
3502           if (t < min_t)
3503           {
3504             min_t = t;
3505           }
3506         }
3507         else
3508         {
3509           if (t > max_t)
3510           {
3511             max_t = t;
3512           }
3513         }
3514       }
3515     }
3516     rot_width =  (max_s - min_s);
3517     rot_height = (max_t - min_t);
3518     td->scale[0] = -(rot_width/((float)(face->d_texture->width*nWidth)));
3519     td->scale[1] = -(rot_height/((float)(face->d_texture->height*nHeight)));
3520     
3521     td->shift[0] = min_s/td->scale[0];
3522     temp = (int)(td->shift[0] / (face->d_texture->width*nWidth));
3523     temp = (temp+1)*face->d_texture->width*nWidth;
3524     td->shift[0] = (int)(temp - td->shift[0])%(face->d_texture->width*nWidth);
3525     
3526     td->shift[1] = min_t/td->scale[1];
3527     temp = (int)(td->shift[1] / (face->d_texture->height*nHeight));
3528     temp = (temp+1)*(face->d_texture->height*nHeight);
3529     td->shift[1] = (int)(temp - td->shift[1])%(face->d_texture->height*nHeight);
3530     
3531     td->shift[1] = min_t/td->scale[1];
3532     temp = (int)(td->shift[1] / (face->d_texture->height*nHeight));
3533     temp = (temp+1)*(face->d_texture->height*nHeight);
3534     td->shift[1] = (int)(temp - td->shift[1])%(face->d_texture->height*nHeight);
3535     
3536   }
3537 }
3538
3539 void Brush_FitTexture( brush_t *b, int nHeight, int nWidth )
3540 {
3541         face_t *face;
3542
3543         for (face = b->brush_faces ; face ; face=face->next)
3544   {
3545     Face_FitTexture( face, nHeight, nWidth );
3546   }
3547 }
3548
3549 void aabb_draw(const aabb_t *aabb, int mode)
3550 {
3551   vec3_t normals[6] = { { 1, 0, 0}, { 0, 1, 0 }, { 0, 0, 1 }, {-1, 0, 0}, { 0,-1, 0 }, { 0, 0,-1 } };
3552   vec3_t points[8];
3553         vec3_t vMin, vMax;
3554   VectorSubtract(aabb->origin, aabb->extents, vMin);
3555   VectorAdd(aabb->origin, aabb->extents, vMax);
3556   VectorSet(points[0], vMin[0], vMax[1], vMax[2]);
3557   VectorSet(points[1], vMax[0], vMax[1], vMax[2]);
3558   VectorSet(points[2], vMax[0], vMin[1], vMax[2]);
3559   VectorSet(points[3], vMin[0], vMin[1], vMax[2]);
3560   VectorSet(points[4], vMin[0], vMax[1], vMin[2]);
3561   VectorSet(points[5], vMax[0], vMax[1], vMin[2]);
3562   VectorSet(points[6], vMax[0], vMin[1], vMin[2]);
3563   VectorSet(points[7], vMin[0], vMin[1], vMin[2]);
3564
3565   qglBegin(GL_QUADS);
3566
3567   qglNormal3fv(normals[0]);
3568   qglVertex3fv(points[2]);
3569   qglVertex3fv(points[1]);
3570   qglVertex3fv(points[5]);
3571   qglVertex3fv(points[6]);
3572
3573   qglNormal3fv(normals[1]);
3574   qglVertex3fv(points[1]);
3575   qglVertex3fv(points[0]);
3576   qglVertex3fv(points[4]);
3577   qglVertex3fv(points[5]);
3578
3579   qglNormal3fv(normals[2]);
3580   qglVertex3fv(points[0]);
3581   qglVertex3fv(points[1]);
3582   qglVertex3fv(points[2]);
3583   qglVertex3fv(points[3]);
3584
3585   qglNormal3fv(normals[3]);
3586   qglVertex3fv(points[3]);
3587   qglVertex3fv(points[7]);
3588   qglVertex3fv(points[4]);
3589   qglVertex3fv(points[0]);
3590
3591   qglNormal3fv(normals[4]);
3592   qglVertex3fv(points[3]);
3593   qglVertex3fv(points[2]);
3594   qglVertex3fv(points[6]);
3595   qglVertex3fv(points[7]);
3596
3597   qglNormal3fv(normals[5]);
3598   qglVertex3fv(points[7]);
3599   qglVertex3fv(points[6]);
3600   qglVertex3fv(points[5]);
3601   qglVertex3fv(points[4]);
3602
3603   qglEnd();
3604
3605 /*
3606
3607
3608   vec3_t Coords[8];
3609
3610         vec3_t vMin, vMax;
3611   VectorSubtract(aabb->origin, aabb->extents, vMin);
3612   VectorAdd(aabb->origin, aabb->extents, vMax);
3613   VectorSet(Coords[0], vMin[0], vMax[1], vMax[2]);
3614   VectorSet(Coords[1], vMax[0], vMax[1], vMax[2]);
3615   VectorSet(Coords[2], vMax[0], vMin[1], vMax[2]);
3616   VectorSet(Coords[3], vMin[0], vMin[1], vMax[2]);
3617   VectorSet(Coords[4], vMin[0], vMax[1], vMin[2]);
3618   VectorSet(Coords[5], vMax[0], vMax[1], vMin[2]);
3619   VectorSet(Coords[6], vMax[0], vMin[1], vMin[2]);
3620   VectorSet(Coords[7], vMin[0], vMin[1], vMin[2]);
3621
3622         vec3_t Normals[8] = { {-1, 0, 0 },
3623                                                                                         { 0, 0, 0 },
3624                                                                                         { 0, 0, 0 },
3625                                                                                         { 0, 0, 1 },
3626                                                                                         { 0, 0,-1 },
3627                                                                                         { 0, 1, 0 },
3628                                                                                         { 1, 0, 0 },
3629                                                                                         { 0,-1, 0 } };
3630   
3631         unsigned short Indices[24] = { 2, 1, 5, 6,
3632                                                                                                                                  1, 0, 4, 5,
3633                                                                                                                                  0, 1, 2, 3,
3634                                                                                                                                  3, 7, 4, 0,
3635                                                                                                                                  3, 2, 6, 7,
3636                                                                                                                                  7, 6, 5, 4 };
3637
3638   qglVertexPointer(3, GL_FLOAT, 0, Coords);         // filling the arrays
3639   qglNormalPointer(GL_FLOAT, 0, Normals);
3640   
3641   //glLockArraysEXT(0, count);                // extension GL_EXT_compiled_vertex_array
3642   
3643   qglDrawElements(GL_QUADS, 24, GL_UNSIGNED_SHORT, Indices);
3644     
3645   //glUnlockArraysEXT;                        // extension GL_EXT_compiled_vertex_array
3646 */
3647 }
3648
3649 qboolean IsBrushSelected(brush_t* bSel)
3650 {
3651         for (brush_t* b = selected_brushes.next ;b != NULL && b != &selected_brushes; b = b->next)
3652   {
3653     if (b == bSel)
3654       return true;
3655   }
3656   return false;
3657 }
3658
3659