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