more eol-style
[xonotic/netradiant.git] / contrib / gtkgensurf / genmap.cpp
1 /*
2 GenSurf plugin for GtkRadiant
3 Copyright (C) 2001 David Hyde, Loki software and qeradiant.com
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20 #include <math.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include "gensurf.h"
24
25 double  xmin,xmax,ymin,ymax,zmin,zmax;
26 double  backface;
27 extern double dh, dv;
28 FILE  *fmap;
29 XYZ     xyz[MAX_ROWS+1][MAX_ROWS+1];
30 int     contents;
31 int     surface[3];
32 LPVOID  h_func_group;
33 LPVOID  terrainkey; // ^Fishman - Add terrain key to func_group.
34
35 //=============================================================
36 // Hydra : snap-to-grid begin
37 double CalculateSnapValue(double value)
38 {
39         long                snapvalue;
40
41   // simple uncomplicated snapping, rounding both UP and DOWN to the nearest
42         // grid unit.
43         if (SnapToGrid >0)
44         {
45                 snapvalue = (int)value / SnapToGrid;
46                 if ((long)value % SnapToGrid < (SnapToGrid / 2)) // Snap Downwards if less than halfway between to grid units
47                         value = snapvalue * SnapToGrid; 
48                 else // Snap Upwards if more than halfway between to grid units
49                         value = (snapvalue+1) * SnapToGrid;
50         }
51   return value;
52 }
53 // Hydra : snap-to-grid end
54
55 //=============================================================
56 bool ValidSurface()
57 {
58   if(WaveType == WAVE_BITMAP && !gbmp.colors) return FALSE;
59   if(NH  < 1)        return FALSE;
60   if(NH  > MAX_ROWS) return FALSE;
61   if(NV  < 1)        return FALSE;
62   if(NV  > MAX_ROWS) return FALSE;
63   if(Hll >= Hur)     return FALSE;
64   if(Vll >= Vur)     return FALSE;
65   return TRUE;
66 }
67
68 //=============================================================
69 int MapPatches()
70 {
71   int     NH_remain;
72   int     NV_remain;
73   int     NH_patch;
74   int     NV_patch;
75   int     BrushNum = 0;
76   int     i, j, k1, k2, k3;
77   int     i0, j0, ii;
78   char    szOops[128];
79   patchMesh_t p;
80
81   dh = (Hur-Hll)/NH;
82   dv = (Vur-Vll)/NV;
83   memset(&p,0,sizeof(patchMesh_t));
84
85   // Generate control points in pp array to give desired values currently
86   // in p array.
87   switch(Plane)
88   {
89   case PLANE_XY0:
90   case PLANE_XY1:
91     k1 = 0;
92     k2 = 1;
93     k3 = 2;
94     break;
95   case PLANE_XZ0:
96   case PLANE_XZ1:
97     k1 = 0;
98     k2 = 2;
99     k3 = 1;
100     break;
101   case PLANE_YZ0:
102   case PLANE_YZ1:
103     k1 = 1;
104     k2 = 2;
105     k3 = 0;
106     break;
107   }
108   for(i=0; i<=NH; i++)
109   {
110     for(j=0; j<=NV; j++)
111     {
112       xyz[i][j].pp[k1] = xyz[i][j].p[k1];
113       xyz[i][j].pp[k2] = xyz[i][j].p[k2];
114     }
115   }
116   for(i=0; i<=NH; i+=2)
117   {
118     for(j=0; j<=NV; j+=2)
119       xyz[i][j].pp[k3] = xyz[i][j].p[k3];
120   }
121   for(i=1; i<NH; i+=2)
122   {
123     for(j=0; j<=NV; j+=2)
124     {
125       xyz[i][j].pp[k3] = (4*xyz[i][j].p[k3] - xyz[i-1][j].p[k3] - xyz[i+1][j].p[k3])/2;
126     }
127   }
128   for(j=1; j<NV; j+=2)
129   {
130     for(i=0; i<=NH; i+=2)
131     {
132       xyz[i][j].pp[k3] = (4*xyz[i][j].p[k3] - xyz[i][j-1].p[k3] - xyz[i][j+1].p[k3])/2;
133     }
134   }
135   for(i=1; i<NH; i+=2)
136   {
137     for(j=1; j<NV; j+=2)
138     {
139       xyz[i][j].pp[k3] = (16*xyz[i][j].p[k3] - xyz[i-1][j-1].p[k3] - 2*xyz[i][j-1].p[k3]
140         - xyz[i+1][j-1].p[k3] - 2*xyz[i-1][j].p[k3] - 2*xyz[i+1][j].p[k3]
141         - xyz[i-1][j+1].p[k3] - 2*xyz[i][j+1].p[k3] - xyz[i+1][j+1].p[k3])/4;
142     }
143   }
144
145   NH_remain = NH+1;
146   i0 = 0;
147   while(NH_remain > 1)
148   {
149     if(( (NH_remain-1) % 14) == 0)
150       NH_patch = 15;
151     else if(( (NH_remain-1) % 12) == 0)
152       NH_patch = 13;
153     else if(( (NH_remain-1) % 10) == 0)
154       NH_patch = 11;
155     else if(( (NH_remain-1) % 8) == 0)
156       NH_patch = 9;
157     else if(( (NH_remain-1) % 6) == 0)
158       NH_patch = 7;
159     else if(( (NH_remain-1) % 4) == 0)
160       NH_patch = 5;
161     else if(( (NH_remain-1) % 2) == 0)
162       NH_patch = 3;
163     else if(NH_remain > 16)
164       NH_patch = 7;
165     else if(NH_remain > 4)
166       NH_patch = 5;
167     else
168       NH_patch = 3;
169     while( NH_patch > 3 && (NH_patch-1)*dh > 512 )
170       NH_patch -= 2;
171     NH_remain -= (NH_patch-1);
172     if(NH_remain < 0)
173     {
174       sprintf(szOops,"Oops... screwed up with NH=%d",NH);
175       g_FuncTable.m_pfnMessageBox(NULL,szOops,"Uh oh");
176     }
177     NV_remain = NV+1;
178     j0 = 0;
179     while(NV_remain > 1)
180     {
181       if(( (NV_remain-1) % 14) == 0)
182         NV_patch = 15;
183       else if(( (NV_remain-1) % 12) == 0)
184         NV_patch = 13;
185       else if(( (NV_remain-1) % 10) == 0)
186         NV_patch = 11;
187       else if(( (NV_remain-1) % 8) == 0)
188         NV_patch = 9;
189       else if(( (NV_remain-1) % 6) == 0)
190         NV_patch = 7;
191       else if(( (NV_remain-1) % 4) == 0)
192         NV_patch = 5;
193       else if(( (NV_remain-1) % 2) == 0)
194         NV_patch = 3;
195       else if(NV_remain > 16)
196         NV_patch = 7;
197       else if(NV_remain > 4)
198         NV_patch = 5;
199       else
200         NV_patch = 3;
201       while( NV_patch > 3 && (NV_patch-1)*dh > 512 )
202         NV_patch -= 2;
203       NV_remain -= (NV_patch-1);
204       if(NV_remain < 0)
205       {
206         sprintf(szOops,"Oops... screwed up with NV=%d",NV);
207         g_FuncTable.m_pfnMessageBox(NULL,szOops,"Uh oh");
208       }
209
210       p.width  = NH_patch;
211       p.height = NV_patch;
212       p.type   = PATCH_GENERIC;
213       for(i=0; i<NH_patch; i++)
214       {
215         switch(Plane)
216         {
217         case PLANE_XY1:
218         case PLANE_XZ0:
219         case PLANE_YZ1:
220           ii = i0 + NH_patch - 1 - i;
221           break;
222         default:
223           ii = i0+i;
224         }
225         for(j=0; j<NV_patch; j++)
226         {
227           p.ctrl[i][j].xyz[0] = (float)xyz[ii][j0+j].pp[0];
228           p.ctrl[i][j].xyz[1] = (float)xyz[ii][j0+j].pp[1];
229           p.ctrl[i][j].xyz[2] = (float)xyz[ii][j0+j].pp[2];
230           p.ctrl[i][j].st[0]  = (float)i;
231           p.ctrl[i][j].st[1]  = (float)j;
232         }
233       }
234       MakePatch(&p);
235       BrushNum++;
236       j0 += NV_patch-1;
237     }
238     i0 += NH_patch-1;
239   }
240   return BrushNum;
241 }
242
243 //=============================================================
244 void MapBrushes()
245 {
246   char  hint[128];
247   char  skip[128];
248   char  sidetext[64];
249   char  surftext[64];
250   char  surftext2[64];
251   char  surft[64];
252   float Steep;
253   vec3_t  PlaneNormal,SurfNormal;
254   vec3_t  t[2];
255   int   i, j, k;
256   int   surf;
257   bool  CheckAngle;
258   BRUSH brush;
259   XYZ   v[8];
260
261   strcpy(surftext,Texture[Game][0]);
262   strcpy(sidetext,(strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
263   strcpy(surftext2,(strlen(Texture[Game][2]) ? Texture[Game][2] : Texture[Game][0]));
264
265   // if surftext2 is identical to surftext, there's no need to
266   // check surface angle
267   if(!g_strcasecmp(surftext,surftext2))
268     CheckAngle = FALSE;
269   else
270   {
271     CheckAngle = TRUE;
272     Steep = (float)cos((double)SlantAngle/57.2957795);
273     switch(Plane)
274     {
275     case PLANE_XY0: PlaneNormal[0]= 0.;PlaneNormal[1]= 0.;PlaneNormal[2]= 1.;break;
276     case PLANE_XY1: PlaneNormal[0]= 0.;PlaneNormal[1]= 0.;PlaneNormal[2]=-1.;break;
277     case PLANE_XZ0: PlaneNormal[0]= 0.;PlaneNormal[1]= 1.;PlaneNormal[2]= 1.;break;
278     case PLANE_XZ1: PlaneNormal[0]= 0.;PlaneNormal[1]=-1.;PlaneNormal[2]= 1.;break;
279     case PLANE_YZ0: PlaneNormal[0]= 1.;PlaneNormal[1]= 0.;PlaneNormal[2]= 1.;break;
280     case PLANE_YZ1: PlaneNormal[0]=-1.;PlaneNormal[1]= 0.;PlaneNormal[2]= 1.;break;
281     }
282   }
283   
284   OpenFuncGroup();
285
286   for(i=0; i<NH; i++)
287   {
288     for(j=0; j<NV; j++)
289     {
290       if( (i+j) % 2 )
291       {
292         VectorCopy(xyz[i  ][j  ].p, v[0].p);
293         switch(Plane)
294         {
295         case PLANE_XY1:
296         case PLANE_XZ1:
297         case PLANE_YZ1:
298           VectorCopy(xyz[i+1][j  ].p, v[1].p);
299           VectorCopy(xyz[i+1][j+1].p, v[2].p);
300           break;
301         default:
302           VectorCopy(xyz[i+1][j+1].p, v[1].p);
303           VectorCopy(xyz[i+1][j  ].p, v[2].p);
304         }
305       }
306       else
307       {
308         VectorCopy(xyz[i  ][j  ].p, v[0].p);
309         switch(Plane)
310         {
311         case PLANE_XY1:
312         case PLANE_XZ1:
313         case PLANE_YZ1:
314           VectorCopy(xyz[i+1][j  ].p, v[1].p);
315           VectorCopy(xyz[i  ][j+1].p, v[2].p);
316           break;
317         default:
318           VectorCopy(xyz[i  ][j+1].p, v[1].p);
319           VectorCopy(xyz[i+1][j  ].p, v[2].p);
320         }
321       }
322       VectorCopy(v[0].p,v[3].p);
323       VectorCopy(v[1].p,v[4].p);
324       VectorCopy(v[2].p,v[5].p);
325       switch(Plane)
326       {
327       case PLANE_XZ0:
328       case PLANE_XZ1:
329         v[0].p[1] = backface;
330         v[1].p[1] = backface;
331         v[2].p[1] = backface;
332         break;
333       case PLANE_YZ0:
334       case PLANE_YZ1:
335         v[3].p[0] = backface;
336         v[4].p[0] = backface;
337         v[5].p[0] = backface;
338         break;
339       default:
340         v[3].p[2] = backface;
341         v[4].p[2] = backface;
342         v[5].p[2] = backface;
343       }
344
345       brush.Number   = i*NV*2+j*2;
346       brush.NumFaces = 5;
347       XYZtoV(&v[0],&brush.face[0].v[0]);
348       XYZtoV(&v[3],&brush.face[0].v[1]);
349       XYZtoV(&v[4],&brush.face[0].v[2]);
350       strcpy(brush.face[0].texture,
351         (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
352       brush.face[0].Shift[0] = (float)TexOffset[0];
353       brush.face[0].Shift[1] = (float)TexOffset[1];
354       brush.face[0].Rotate   = 0.;
355       brush.face[0].Scale[0] = (float)TexScale[0];
356       brush.face[0].Scale[1] = (float)TexScale[1];
357       brush.face[0].Contents = contents;
358       brush.face[0].Surface  = surface[1];
359       brush.face[0].Value    = 0;
360
361       XYZtoV(&v[1],&brush.face[1].v[0]);
362       XYZtoV(&v[4],&brush.face[1].v[1]);
363       XYZtoV(&v[5],&brush.face[1].v[2]);
364       strcpy(brush.face[1].texture,
365         (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
366       brush.face[1].Shift[0] = (float)TexOffset[0];
367       brush.face[1].Shift[1] = (float)TexOffset[1];
368       brush.face[1].Rotate   = 0.;
369       brush.face[1].Scale[0] = (float)TexScale[0];
370       brush.face[1].Scale[1] = (float)TexScale[1];
371       brush.face[1].Contents = contents;
372       brush.face[1].Surface  = surface[1];
373       brush.face[1].Value    = 0;
374
375       XYZtoV(&v[2],&brush.face[2].v[0]);
376       XYZtoV(&v[5],&brush.face[2].v[1]);
377       XYZtoV(&v[3],&brush.face[2].v[2]);
378       strcpy(brush.face[2].texture,
379         (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
380       brush.face[2].Shift[0] = (float)TexOffset[0];
381       brush.face[2].Shift[1] = (float)TexOffset[1];
382       brush.face[2].Rotate   = 0.;
383       brush.face[2].Scale[0] = (float)TexScale[0];
384       brush.face[2].Scale[1] = (float)TexScale[1];
385       brush.face[2].Contents = contents;
386       brush.face[2].Surface  = surface[1];
387       brush.face[2].Value    = 0;
388
389       if(CheckAngle && (Plane==PLANE_XZ0 || Plane==PLANE_XZ1))
390       {
391         XYZVectorSubtract(v[4].p,v[3].p,t[0]);
392         XYZVectorSubtract(v[5].p,v[4].p,t[1]);
393         CrossProduct(t[0],t[1],SurfNormal);
394         VectorNormalize(SurfNormal,SurfNormal);
395         if(DotProduct(SurfNormal,PlaneNormal) < Steep)
396         {
397           strcpy(surft,surftext2);
398           surf = surface[2];
399         }
400         else
401         {
402           strcpy(surft,surftext);
403           surf = surface[0];
404         }
405       }
406       else
407       {
408         strcpy(surft,surftext);
409         surf = surface[0];
410       }
411
412       XYZtoV(&v[3],&brush.face[3].v[0]);
413       XYZtoV(&v[5],&brush.face[3].v[1]);
414       XYZtoV(&v[4],&brush.face[3].v[2]);
415       strcpy(brush.face[3].texture,
416         (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? surft : sidetext));
417       brush.face[3].Shift[0] = (float)TexOffset[0];
418       brush.face[3].Shift[1] = (float)TexOffset[1];
419       brush.face[3].Rotate   = 0.;
420       brush.face[3].Scale[0] = (float)TexScale[0];
421       brush.face[3].Scale[1] = (float)TexScale[1];
422       brush.face[3].Contents = contents;
423       brush.face[3].Surface  = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? surf : surface[1]);
424       brush.face[3].Value    = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? ArghRad2 : 0);
425
426       if(CheckAngle && Plane!=PLANE_XZ0 && Plane!=PLANE_XZ1)
427       {
428         XYZVectorSubtract(v[2].p,v[0].p,t[0]);
429         XYZVectorSubtract(v[1].p,v[2].p,t[1]);
430         CrossProduct(t[0],t[1],SurfNormal);
431         VectorNormalize(SurfNormal,SurfNormal);
432         if(DotProduct(SurfNormal,PlaneNormal) < Steep)
433         {
434           strcpy(surft,surftext2);
435           surf = surface[2];
436         }
437         else
438         {
439           strcpy(surft,surftext);
440           surf = surface[0];
441         }
442       }
443       else
444       {
445         strcpy(surft,surftext);
446         surf = surface[0];
447       }
448
449       XYZtoV(&v[0],&brush.face[4].v[0]);
450       XYZtoV(&v[1],&brush.face[4].v[1]);
451       XYZtoV(&v[2],&brush.face[4].v[2]);
452       strcpy(brush.face[4].texture,
453         (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? sidetext : surft));
454       brush.face[4].Shift[0] = (float)TexOffset[0];
455       brush.face[4].Shift[1] = (float)TexOffset[1];
456       brush.face[4].Rotate   = 0.;
457       brush.face[4].Scale[0] = (float)TexScale[0];
458       brush.face[4].Scale[1] = (float)TexScale[1];
459       brush.face[4].Contents = contents;
460       brush.face[4].Surface  = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? surface[1] : surf);
461       brush.face[4].Value    = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? 0 : ArghRad2);
462
463       MakeBrush(&brush);
464       if( (i+j) %2 )
465       {
466         VectorCopy(xyz[i  ][j+1].p,v[0].p);
467         switch(Plane)
468         {
469         case PLANE_XY1:
470         case PLANE_XZ1:
471         case PLANE_YZ1:
472           VectorCopy(xyz[i  ][j  ].p,v[1].p);
473           VectorCopy(xyz[i+1][j+1].p,v[2].p);
474           break;
475         default:
476           VectorCopy(xyz[i+1][j+1].p,v[1].p);
477           VectorCopy(xyz[i  ][j  ].p,v[2].p);
478         }
479       }
480       else
481       {
482         VectorCopy(xyz[i  ][j+1].p,v[0].p);
483         switch(Plane)
484         {
485         case PLANE_XY1:
486         case PLANE_XZ1:
487         case PLANE_YZ1:
488           VectorCopy(xyz[i+1][j  ].p,v[1].p);
489           VectorCopy(xyz[i+1][j+1].p,v[2].p);
490           break;
491         default:
492           VectorCopy(xyz[i+1][j+1].p,v[1].p);
493           VectorCopy(xyz[i+1][j  ].p,v[2].p);
494         }
495       }
496       VectorCopy(v[0].p,v[3].p);
497       VectorCopy(v[1].p,v[4].p);
498       VectorCopy(v[2].p,v[5].p);
499       switch(Plane)
500       {
501       case PLANE_XZ0:
502       case PLANE_XZ1:
503         v[0].p[1] = backface;
504         v[1].p[1] = backface;
505         v[2].p[1] = backface;
506         break;
507       case PLANE_YZ0:
508       case PLANE_YZ1:
509         v[3].p[0] = backface;
510         v[4].p[0] = backface;
511         v[5].p[0] = backface;
512         break;
513       default:
514         v[3].p[2] = backface;
515         v[4].p[2] = backface;
516         v[5].p[2] = backface;
517       }
518       brush.Number   = i*NV*2+j*2+1;
519       brush.NumFaces = 5;
520       XYZtoV(&v[0],&brush.face[0].v[0]);
521       XYZtoV(&v[3],&brush.face[0].v[1]);
522       XYZtoV(&v[4],&brush.face[0].v[2]);
523       strcpy(brush.face[0].texture,
524         (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
525       brush.face[0].Shift[0] = (float)TexOffset[0];
526       brush.face[0].Shift[1] = (float)TexOffset[1];
527       brush.face[0].Rotate   = 0.;
528       brush.face[0].Scale[0] = (float)TexScale[0];
529       brush.face[0].Scale[1] = (float)TexScale[1];
530       brush.face[0].Contents = contents;
531       brush.face[0].Surface  = surface[1];
532       brush.face[0].Value    = 0;
533
534       XYZtoV(&v[1],&brush.face[1].v[0]);
535       XYZtoV(&v[4],&brush.face[1].v[1]);
536       XYZtoV(&v[5],&brush.face[1].v[2]);
537       strcpy(brush.face[1].texture,
538         (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
539       brush.face[1].Shift[0] = (float)TexOffset[0];
540       brush.face[1].Shift[1] = (float)TexOffset[1];
541       brush.face[1].Rotate   = 0.;
542       brush.face[1].Scale[0] = (float)TexScale[0];
543       brush.face[1].Scale[1] = (float)TexScale[1];
544       brush.face[1].Contents = contents;
545       brush.face[1].Surface  = surface[1];
546       brush.face[1].Value    = 0;
547
548       XYZtoV(&v[2],&brush.face[2].v[0]);
549       XYZtoV(&v[5],&brush.face[2].v[1]);
550       XYZtoV(&v[3],&brush.face[2].v[2]);
551       strcpy(brush.face[2].texture,
552         (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
553       brush.face[2].Shift[0] = (float)TexOffset[0];
554       brush.face[2].Shift[1] = (float)TexOffset[1];
555       brush.face[2].Rotate   = 0.;
556       brush.face[2].Scale[0] = (float)TexScale[0];
557       brush.face[2].Scale[1] = (float)TexScale[1];
558       brush.face[2].Contents = contents;
559       brush.face[2].Surface  = surface[1];
560       brush.face[2].Value    = 0;
561
562       if(CheckAngle && (Plane==PLANE_XZ0 || Plane==PLANE_XZ1))
563       {
564         XYZVectorSubtract(v[4].p,v[3].p,t[0]);
565         XYZVectorSubtract(v[5].p,v[4].p,t[1]);
566         CrossProduct(t[0],t[1],SurfNormal);
567         VectorNormalize(SurfNormal,SurfNormal);
568         if(DotProduct(SurfNormal,PlaneNormal) < Steep)
569         {
570           strcpy(surft,surftext2);
571           surf = surface[2];
572         }
573         else
574         {
575           strcpy(surft,surftext);
576           surf = surface[0];
577         }
578       }
579       else
580       {
581         strcpy(surft,surftext);
582         surf = surface[0];
583       }
584       XYZtoV(&v[3],&brush.face[3].v[0]);
585       XYZtoV(&v[5],&brush.face[3].v[1]);
586       XYZtoV(&v[4],&brush.face[3].v[2]);
587       strcpy(brush.face[3].texture,
588         (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? surft : sidetext));
589       brush.face[3].Shift[0] = (float)TexOffset[0];
590       brush.face[3].Shift[1] = (float)TexOffset[1];
591       brush.face[3].Rotate   = 0.;
592       brush.face[3].Scale[0] = (float)TexScale[0];
593       brush.face[3].Scale[1] = (float)TexScale[1];
594       brush.face[3].Contents = contents;
595       brush.face[3].Surface  = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? surf : surface[1]);
596       brush.face[3].Value    = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? ArghRad2 : 0);
597
598       if(CheckAngle && Plane!=PLANE_XZ0 && Plane!=PLANE_XZ1)
599       {
600         XYZVectorSubtract(v[2].p,v[0].p,t[0]);
601         XYZVectorSubtract(v[1].p,v[2].p,t[1]);
602         CrossProduct(t[0],t[1],SurfNormal);
603         VectorNormalize(SurfNormal,SurfNormal);
604         if(DotProduct(SurfNormal,PlaneNormal) < Steep)
605         {
606           strcpy(surft,surftext2);
607           surf = surface[2];
608         }
609         else
610         {
611           strcpy(surft,surftext);
612           surf = surface[0];
613         }
614       }
615       else
616       {
617         strcpy(surft,surftext);
618         surf = surface[0];
619       }
620       XYZtoV(&v[0],&brush.face[4].v[0]);
621       XYZtoV(&v[1],&brush.face[4].v[1]);
622       XYZtoV(&v[2],&brush.face[4].v[2]);
623       strcpy(brush.face[4].texture,
624         (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? sidetext : surft));
625       brush.face[4].Shift[0] = (float)TexOffset[0];
626       brush.face[4].Shift[1] = (float)TexOffset[1];
627       brush.face[4].Rotate   = 0.;
628       brush.face[4].Scale[0] = (float)TexScale[0];
629       brush.face[4].Scale[1] = (float)TexScale[1];
630       brush.face[4].Contents = contents;
631       brush.face[4].Surface  = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? surface[1] : surf);
632       brush.face[4].Value    = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? 0 : ArghRad2);
633
634       MakeBrush(&brush);
635     }
636   }
637   CloseFuncGroup();
638
639   if( AddHints || GimpHints )
640   {
641     int detail, i1, j1, N;
642     double front;
643
644     switch(Game)
645     {
646     case HALFLIFE:
647       strcpy(hint,"HINT");
648       strcpy(skip,"HINT");
649       break;
650     case SIN:
651       strcpy(hint,"generic/misc/hint");
652       strcpy(skip,"generic/misc/skip");
653       break;
654     case HERETIC2:
655       strcpy(hint,"general/hint");
656       strcpy(skip,"general/hint");   // Heretic2 doesn't have a skip texture
657       break;
658     case KINGPIN:
659       strcpy(hint,"common/0_hint");
660       strcpy(skip,"common/0_skip");
661       break;
662     case GENESIS3D:
663       strcpy(hint,"hint");
664       strcpy(skip,"hint");
665       break;
666     case QUAKE3:
667       strcpy(hint,"textures/common/hint");
668       strcpy(skip,"textures/common/skip");
669       break;
670     default:
671       strcpy(hint,"e1u1/hint");
672       strcpy(skip,"e1u1/skip");
673     }
674
675     OpenFuncGroup();
676
677     if(AddHints==1)
678     {
679       detail = CONTENTS_DETAIL;
680       N = 0;
681       for(i=0; i<NH; i++)
682       {
683         i1 = i+1;
684         
685         for(j=0; j<NV; j++)
686         {
687           
688           // For detail hint brushes, no need to use a hint brush over
689           // EVERY grid square... it would be redundant. Instead use
690           // a checkerboard pattern
691           if((i+j)%2) continue;
692           
693           j1 = j+1;
694           
695           VectorCopy(xyz[i  ][j  ].p, v[0].p);
696           switch(Plane)
697           {
698           case PLANE_XY1:
699           case PLANE_XZ1:
700           case PLANE_YZ1:
701             VectorCopy(xyz[i1][j ].p, v[1].p);
702             VectorCopy(xyz[i1][j1].p, v[2].p);
703             VectorCopy(xyz[i ][j1].p, v[3].p);
704             break;
705           default:
706             VectorCopy(xyz[i ][j1].p, v[1].p);
707             VectorCopy(xyz[i1][j1].p, v[2].p);
708             VectorCopy(xyz[i1][j ].p, v[3].p);
709           }
710           
711           VectorCopy(v[0].p,v[4].p);
712           VectorCopy(v[1].p,v[5].p);
713           VectorCopy(v[2].p,v[6].p);
714           VectorCopy(v[3].p,v[7].p);
715           
716           switch(Plane)
717           {
718           case PLANE_XY1:
719             front  = LessThan(zmin,32.);
720             v[4].p[2] = backface;
721             v[5].p[2] = backface;
722             v[6].p[2] = backface;
723             v[7].p[2] = backface;
724             break;
725           case PLANE_XZ0:
726             front  = MoreThan(ymax,32.);
727             v[0].p[1] = backface;
728             v[1].p[1] = backface;
729             v[2].p[1] = backface;
730             v[3].p[1] = backface;
731             break;
732           case PLANE_XZ1:
733             front  = LessThan(ymin,32.);
734             v[0].p[1] = backface;
735             v[1].p[1] = backface;
736             v[2].p[1] = backface;
737             v[3].p[1] = backface;
738             break;
739           case PLANE_YZ0:
740             front  = MoreThan(xmax,32.);
741             v[4].p[0] = backface;
742             v[5].p[0] = backface;
743             v[6].p[0] = backface;
744             v[7].p[0] = backface;
745             break;
746           case PLANE_YZ1:
747             front  = LessThan(xmin,32.);
748             v[4].p[0] = backface;
749             v[5].p[0] = backface;
750             v[6].p[0] = backface;
751             v[7].p[0] = backface;
752             break;
753           default:
754             front  = MoreThan(zmax,32.);
755             v[4].p[2] = backface;
756             v[5].p[2] = backface;
757             v[6].p[2] = backface;
758             v[7].p[2] = backface;
759           }
760           
761           switch(Plane)
762           {
763           case PLANE_XZ0:
764           case PLANE_XZ1:
765             v[4].p[1] = front;
766             v[5].p[1] = v[4].p[1];
767             v[6].p[1] = v[4].p[1];
768             v[7].p[1] = v[4].p[1];
769             break;
770           case PLANE_YZ0:
771           case PLANE_YZ1:
772             v[0].p[0] = front;
773             v[1].p[0] = v[0].p[0];
774             v[2].p[0] = v[0].p[0];
775             v[3].p[0] = v[0].p[0];
776             break;
777           default:
778             v[0].p[2] = front;
779             v[1].p[2] = v[0].p[2];
780             v[2].p[2] = v[0].p[2];
781             v[3].p[2] = v[0].p[2];
782           }
783           
784           brush.NumFaces = 6;
785           brush.Number   = N;
786           XYZtoV(&v[0],&brush.face[0].v[0]);
787           XYZtoV(&v[1],&brush.face[0].v[1]);
788           XYZtoV(&v[2],&brush.face[0].v[2]);
789           strcpy(brush.face[0].texture,skip);
790           brush.face[0].Shift[0] = 0.;
791           brush.face[0].Shift[1] = 0.;
792           brush.face[0].Rotate   = 0.;
793           brush.face[0].Scale[0] = 1.;
794           brush.face[0].Scale[1] = 1.;
795           brush.face[0].Contents = detail;
796           brush.face[0].Surface  = SURF_SKIP;
797           brush.face[0].Value    = 0;
798           
799           XYZtoV(&v[4],&brush.face[1].v[0]);
800           XYZtoV(&v[7],&brush.face[1].v[1]);
801           XYZtoV(&v[6],&brush.face[1].v[2]);
802           strcpy(brush.face[1].texture,skip);
803           brush.face[1].Shift[0] = 0.;
804           brush.face[1].Shift[1] = 0.;
805           brush.face[1].Rotate   = 0.;
806           brush.face[1].Scale[0] = 1.;
807           brush.face[1].Scale[1] = 1.;
808           brush.face[1].Contents = detail;
809           brush.face[1].Surface  = SURF_SKIP;
810           brush.face[1].Value    = 0;
811           
812           XYZtoV(&v[0],&brush.face[2].v[0]);
813           XYZtoV(&v[4],&brush.face[2].v[1]);
814           XYZtoV(&v[5],&brush.face[2].v[2]);
815           strcpy(brush.face[2].texture,hint);
816           brush.face[2].Shift[0] = 0.;
817           brush.face[2].Shift[1] = 0.;
818           brush.face[2].Rotate   = 0.;
819           brush.face[2].Scale[0] = 1.;
820           brush.face[2].Scale[1] = 1.;
821           brush.face[2].Contents = detail;
822           brush.face[2].Surface  = SURF_HINT;
823           brush.face[2].Value    = 0;
824           
825           XYZtoV(&v[1],&brush.face[3].v[0]);
826           XYZtoV(&v[5],&brush.face[3].v[1]);
827           XYZtoV(&v[6],&brush.face[3].v[2]);
828           strcpy(brush.face[3].texture,hint);
829           brush.face[3].Shift[0] = 0.;
830           brush.face[3].Shift[1] = 0.;
831           brush.face[3].Rotate   = 0.;
832           brush.face[3].Scale[0] = 1.;
833           brush.face[3].Scale[1] = 1.;
834           brush.face[3].Contents = detail;
835           brush.face[3].Surface  = SURF_HINT;
836           brush.face[3].Value    = 0;
837           
838           XYZtoV(&v[2],&brush.face[4].v[0]);
839           XYZtoV(&v[6],&brush.face[4].v[1]);
840           XYZtoV(&v[7],&brush.face[4].v[2]);
841           strcpy(brush.face[4].texture,hint);
842           brush.face[4].Shift[0] = 0.;
843           brush.face[4].Shift[1] = 0.;
844           brush.face[4].Rotate   = 0.;
845           brush.face[4].Scale[0] = 1.;
846           brush.face[4].Scale[1] = 1.;
847           brush.face[4].Contents = detail;
848           brush.face[4].Surface  = SURF_HINT;
849           brush.face[4].Value    = 0;
850           
851           XYZtoV(&v[3],&brush.face[5].v[0]);
852           XYZtoV(&v[7],&brush.face[5].v[1]);
853           XYZtoV(&v[4],&brush.face[5].v[2]);
854           strcpy(brush.face[5].texture,hint);
855           brush.face[5].Shift[0] = 0.;
856           brush.face[5].Shift[1] = 0.;
857           brush.face[5].Rotate   = 0.;
858           brush.face[5].Scale[0] = 1.;
859           brush.face[5].Scale[1] = 1.;
860           brush.face[5].Contents = detail;
861           brush.face[5].Surface  = SURF_HINT;
862           brush.face[5].Value    = 0;
863           
864           MakeBrush(&brush);
865           N++;
866         }
867       }
868     }
869     if(GimpHints)
870     {
871       N = 0;
872       // these brush parameters never change
873       brush.NumFaces = 5;
874       for(i=0; i<6; i++)
875       {
876         strcpy(brush.face[i].texture,hint);
877         brush.face[i].Shift[0] = 0.;
878         brush.face[i].Shift[1] = 0.;
879         brush.face[i].Rotate   = 0.;
880         brush.face[i].Scale[0] = 1.;
881         brush.face[i].Scale[1] = 1.;
882         brush.face[i].Contents = 0;
883         brush.face[i].Surface  = SURF_HINT;
884         brush.face[i].Value    = 0;
885       }
886       for(i=0; i<NH; i++)
887       {
888         for(j=0; j<NV; j++)
889         {
890           for(k=0; k<2; k++)
891           {
892             if(k==0)
893             {
894               if( (i+j) % 2 )
895               {
896                 VectorCopy(xyz[i  ][j  ].p, v[0].p);
897                 switch(Plane)
898                 {
899                 case PLANE_XY1:
900                 case PLANE_XZ1:
901                 case PLANE_YZ1:
902                   VectorCopy(xyz[i+1][j  ].p, v[1].p);
903                   VectorCopy(xyz[i+1][j+1].p, v[2].p);
904                   break;
905                 default:
906                   VectorCopy(xyz[i+1][j+1].p, v[1].p);
907                   VectorCopy(xyz[i+1][j  ].p, v[2].p);
908                 }
909               }
910               else
911               {
912                 VectorCopy(xyz[i  ][j  ].p, v[0].p);
913                 switch(Plane)
914                 {
915                 case PLANE_XY1:
916                 case PLANE_XZ1:
917                 case PLANE_YZ1:
918                   VectorCopy(xyz[i+1][j  ].p, v[1].p);
919                   VectorCopy(xyz[i  ][j+1].p, v[2].p);
920                   break;
921                 default:
922                   VectorCopy(xyz[i  ][j+1].p, v[1].p);
923                   VectorCopy(xyz[i+1][j  ].p, v[2].p);
924                 }
925               }
926             }
927             else
928             {
929               if( (i+j) %2 )
930               {
931                 VectorCopy(xyz[i  ][j+1].p,v[0].p);
932                 switch(Plane)
933                 {
934                 case PLANE_XY1:
935                 case PLANE_XZ1:
936                 case PLANE_YZ1:
937                   VectorCopy(xyz[i  ][j  ].p,v[1].p);
938                   VectorCopy(xyz[i+1][j+1].p,v[2].p);
939                   break;
940                 default:
941                   VectorCopy(xyz[i+1][j+1].p,v[1].p);
942                   VectorCopy(xyz[i  ][j  ].p,v[2].p);
943                 }
944               }
945               else
946               {
947                 VectorCopy(xyz[i  ][j+1].p,v[0].p);
948                 switch(Plane)
949                 {
950                 case PLANE_XY1:
951                 case PLANE_XZ1:
952                 case PLANE_YZ1:
953                   VectorCopy(xyz[i+1][j  ].p,v[1].p);
954                   VectorCopy(xyz[i+1][j+1].p,v[2].p);
955                   break;
956                 default:
957                   VectorCopy(xyz[i+1][j+1].p,v[1].p);
958                   VectorCopy(xyz[i+1][j  ].p,v[2].p);
959                 }
960               }
961             }
962             VectorCopy(v[0].p,v[3].p);
963             VectorCopy(v[1].p,v[4].p);
964             VectorCopy(v[2].p,v[5].p);
965             switch(Plane)
966             {
967             case PLANE_XY0:
968               v[0].p[2] += HINT_OFFSET;
969               v[1].p[2] += HINT_OFFSET;
970               v[2].p[2] += HINT_OFFSET;
971 //              v[3].p[2] = backface;
972 //              v[4].p[2] = backface;
973 //              v[5].p[2] = backface;
974               break;
975             case PLANE_XY1:
976               v[0].p[2] -= HINT_OFFSET;
977               v[1].p[2] -= HINT_OFFSET;
978               v[2].p[2] -= HINT_OFFSET;
979 //              v[3].p[2] = backface;
980 //              v[4].p[2] = backface;
981 //              v[5].p[2] = backface;
982               break;
983             case PLANE_XZ0:
984 //              v[0].p[1] = backface;
985 //              v[1].p[1] = backface;
986 //              v[2].p[1] = backface;
987               v[3].p[1] += HINT_OFFSET;
988               v[4].p[1] += HINT_OFFSET;
989               v[5].p[1] += HINT_OFFSET;
990               break;            
991             case PLANE_XZ1:
992 //              v[0].p[1] = backface;
993 //              v[1].p[1] = backface;
994 //              v[2].p[1] = backface;
995               v[3].p[1] -= HINT_OFFSET;
996               v[4].p[1] -= HINT_OFFSET;
997               v[5].p[1] -= HINT_OFFSET;
998               break;
999             case PLANE_YZ0:
1000               v[0].p[0] += HINT_OFFSET;
1001               v[1].p[0] += HINT_OFFSET;
1002               v[2].p[0] += HINT_OFFSET;
1003 //              v[3].p[0] = backface;
1004 //              v[4].p[0] = backface;
1005 //              v[5].p[0] = backface;
1006               break;
1007             case PLANE_YZ1:
1008               v[0].p[0] -= HINT_OFFSET;
1009               v[1].p[0] -= HINT_OFFSET;
1010               v[2].p[0] -= HINT_OFFSET;
1011 //              v[3].p[0] = backface;
1012 //              v[4].p[0] = backface;
1013 //              v[5].p[0] = backface;
1014               break;
1015             }
1016             brush.Number   = N;
1017             XYZtoV(&v[0],&brush.face[0].v[0]);
1018             XYZtoV(&v[3],&brush.face[0].v[1]);
1019             XYZtoV(&v[4],&brush.face[0].v[2]);
1020   
1021             XYZtoV(&v[1],&brush.face[1].v[0]);
1022             XYZtoV(&v[4],&brush.face[1].v[1]);
1023             XYZtoV(&v[5],&brush.face[1].v[2]);
1024
1025             XYZtoV(&v[2],&brush.face[2].v[0]);
1026             XYZtoV(&v[5],&brush.face[2].v[1]);
1027             XYZtoV(&v[3],&brush.face[2].v[2]);
1028   
1029             XYZtoV(&v[3],&brush.face[3].v[0]);
1030             XYZtoV(&v[5],&brush.face[3].v[1]);
1031             XYZtoV(&v[4],&brush.face[3].v[2]);
1032
1033             XYZtoV(&v[0],&brush.face[4].v[0]);
1034             XYZtoV(&v[1],&brush.face[4].v[1]);
1035             XYZtoV(&v[2],&brush.face[4].v[2]);
1036
1037             MakeBrush(&brush);
1038             N++;
1039           }
1040         }
1041       }
1042     } // endif AddHints==1
1043     CloseFuncGroup();
1044   }
1045
1046 } // end MapBrushes
1047
1048 //=============================================================
1049 void GenerateMap()
1050 {
1051   extern void MapOut(int,int,NODE *,TRI *);
1052   extern bool SingleBrushSelected;
1053   int  ntri;
1054
1055   if(!ValidSurface()) return;
1056         /*
1057   ghCursorCurrent = LoadCursor(NULL,IDC_WAIT);
1058   SetCursor(ghCursorCurrent);
1059         */
1060     if(SingleBrushSelected) g_FuncTable.m_pfnDeleteSelection();
1061
1062   GenerateXYZ();
1063   ntri = NH*NV*2;
1064
1065   if(Game==QUAKE3 && UsePatches != 0)
1066     MapPatches();
1067
1068   if(Decimate > 0 && (Game != QUAKE3 || UsePatches==0) )
1069   {
1070     MapOut(gNumNodes,gNumTris,gNode,gTri);
1071                 /*
1072     ghCursorCurrent = ghCursorDefault;
1073     SetCursor(ghCursorCurrent);
1074                 */
1075     return;
1076   }
1077
1078   contents = 0;
1079   // HL doesn't have detail property
1080   if((Game != HALFLIFE) && UseDetail) contents += CONTENTS_DETAIL;
1081   // HL and Q3 don't have ladder property
1082   if((Game != HALFLIFE && Game != QUAKE3) && UseLadder) contents += CONTENTS_LADDER;
1083   // Genesis requires solid property to be set explicitly
1084   if(Game == GENESIS3D) contents |= CONTENTS_SOLID;
1085   // Heretic 2 uses different sounds (in surface props) for different texture types
1086   if(Game == HERETIC2)
1087   {
1088     surface[0] = GetDefSurfaceProps(Texture[Game][0]);
1089     surface[1] = GetDefSurfaceProps(Texture[Game][1]);
1090     surface[2] = GetDefSurfaceProps(Texture[Game][2]);
1091   }
1092   else
1093   {
1094     surface[0] = 0;
1095     surface[1] = 0;
1096     surface[2] = 0;
1097   }
1098   if(Game!=QUAKE3 || UsePatches == 0)
1099     MapBrushes();
1100
1101         /*
1102   ghCursorCurrent = ghCursorDefault;
1103   SetCursor(ghCursorCurrent);
1104         */
1105 }
1106
1107 //=============================================================
1108 void GenerateXYZ()
1109 {
1110   extern void MakeDecimatedMap(int *, int *, NODE **, TRI **);
1111   double zl, zu;
1112   double wh, wv;
1113   int NHalfcycles;
1114   double a,v,h,ha,va;
1115   double delta, dr, rate;
1116   double range, maxrange;
1117   double r;
1118   int i, j, k, N;
1119   int i0, i1, j0, j1;
1120   int ii, jj;
1121
1122 //  FILE *f;
1123 //  char CSV[64];
1124
1125   if(!ValidSurface()) return;
1126
1127   srand(1);
1128   srand(RandomSeed);
1129
1130   dh = (Hur-Hll)/NH;
1131   dv = (Vur-Vll)/NV;
1132   
1133   // H & V
1134   for(i=0; i<=NH; i++)
1135   {
1136     for(j=0;j<=NV;j++)
1137     {
1138       switch(Plane)
1139       {
1140       case PLANE_XZ0:
1141       case PLANE_XZ1:
1142         xyz[i][j].p[0] = Hll + i*dh;
1143         xyz[i][j].p[2] = Vll + j*dv;
1144         break;
1145       case PLANE_YZ0:
1146       case PLANE_YZ1:
1147         xyz[i][j].p[1] = Hll + i*dh;
1148         xyz[i][j].p[2] = Vll + j*dv;
1149         break;
1150       default:
1151         xyz[i][j].p[0] = Hll + i*dh;
1152         xyz[i][j].p[1] = Vll + j*dv;
1153       }
1154     }
1155   }
1156
1157   if(WaveType == WAVE_BITMAP)
1158     GenerateBitmapMapping();
1159         /*
1160   else if(WaveType == WAVE_FORMULA)
1161     DoFormula();
1162         */
1163   else
1164   {
1165     // Initialize Z values using bilinear interpolation
1166     for(i=0; i<=NH; i++)
1167     {
1168       zl = Z00 + i*(Z10 - Z00)/NH;
1169       zu = Z01 + i*(Z11 - Z01)/NH;
1170       switch(Plane)
1171       {
1172       case PLANE_XZ0:
1173       case PLANE_XZ1:
1174         for(j=0; j<=NV; j++)
1175           xyz[i][j].p[1] = zl + j*(zu-zl)/NV;
1176         break;
1177       case PLANE_YZ0:
1178       case PLANE_YZ1:
1179         for(j=0; j<=NV; j++)
1180           xyz[i][j].p[0] = zl + j*(zu-zl)/NV;
1181         break;
1182       default:
1183         for(j=0; j<=NV; j++)
1184           xyz[i][j].p[2] = zl + j*(zu-zl)/NV;
1185       }
1186     }
1187   }
1188   
1189   switch(WaveType)
1190   {
1191   case WAVE_COS_SIN:
1192     if(FixBorders)
1193     {
1194       NHalfcycles = (int)((Hur-Hll)/(WaveLength/2.));
1195       NHalfcycles = max(NHalfcycles,1);
1196       wh = 2.*(Hur-Hll)/NHalfcycles;
1197       NHalfcycles = (int)((Vur-Vll)/(WaveLength/2.));
1198       wv = 2.*(Vur-Vll)/NHalfcycles;
1199       NHalfcycles = max(NHalfcycles,1);
1200       i0 = 1;
1201       i1 = NH-1;
1202       j0 = 1;
1203       j1 = NV-1;
1204     }
1205     else
1206     {
1207       wh = WaveLength;
1208       wv = WaveLength;
1209       i0 = 0;
1210       i1 = NH;
1211       j0 = 0;
1212       j1 = NV;
1213     }
1214     
1215     for(i=i0; i<=i1; i++)
1216     {
1217       h  = Hll + i*dh;
1218       ha = ((h-Hll)/wh)*2.*PI - PI/2.;
1219       for(j=j0; j<=j1; j++)
1220       {
1221         v  = Vll + j*dv;
1222         va = ((v-Vll)/wv)*2.*PI;
1223         a = Amplitude * cos( ha ) * sin( va );
1224         switch(Plane)
1225         {
1226         case PLANE_XY1:
1227           xyz[i][j].p[2] -= a;
1228           break;
1229         case PLANE_XZ0:
1230           xyz[i][j].p[1] += a;
1231           break;
1232         case PLANE_XZ1:
1233           xyz[i][j].p[1] -= a;
1234           break;
1235         case PLANE_YZ0:
1236           xyz[i][j].p[0] += a;
1237           break;
1238         case PLANE_YZ1:
1239           xyz[i][j].p[0] -= a;
1240           break;
1241         default:
1242           xyz[i][j].p[2] += a;
1243         }
1244       }
1245     }
1246     break;
1247   case WAVE_HCYLINDER:
1248     for(i=0; i<=NH; i++)
1249     {
1250       h  = Hll + i*dh;
1251       ha = ((h-Hll)/WaveLength)*2.*PI - PI/2.;
1252       for(j=0; j<=NV; j++)
1253       {
1254         a = Amplitude * cos( ha );
1255         switch(Plane)
1256         {
1257         case PLANE_XY1:
1258           xyz[i][j].p[2] -= a;
1259           break;
1260         case PLANE_XZ0:
1261           xyz[i][j].p[1] += a;
1262           break;
1263         case PLANE_XZ1:
1264           xyz[i][j].p[1] -= a;
1265           break;
1266         case PLANE_YZ0:
1267           xyz[i][j].p[0] += a;
1268           break;
1269         case PLANE_YZ1:
1270           xyz[i][j].p[0] -= a;
1271           break;
1272         default:
1273           xyz[i][j].p[2] += a;
1274         }
1275       }
1276     }
1277     break;
1278   case WAVE_VCYLINDER:
1279     for(i=0; i<=NH; i++)
1280     {
1281       h  = Hll + i*dh;
1282       for(j=0; j<=NV; j++)
1283       {
1284         v  = Vll + j*dv;
1285         va = ((v-Vll)/WaveLength)*2.*PI;
1286         a = Amplitude * sin( va );
1287         switch(Plane)
1288         {
1289         case PLANE_XY1:
1290           xyz[i][j].p[2] -= a;
1291           break;
1292         case PLANE_XZ0:
1293           xyz[i][j].p[1] += a;
1294           break;
1295         case PLANE_XZ1:
1296           xyz[i][j].p[1] -= a;
1297           break;
1298         case PLANE_YZ0:
1299           xyz[i][j].p[0] += a;
1300           break;
1301         case PLANE_YZ1:
1302           xyz[i][j].p[0] -= a;
1303           break;
1304         default:
1305           xyz[i][j].p[2] += a;
1306         }
1307       }
1308     }
1309     break;
1310   case WAVE_ROUGH_ONLY:
1311     PlasmaCloud();
1312     break;
1313   }
1314   
1315   if(WaveType != WAVE_ROUGH_ONLY)
1316   {
1317     // Fixed values
1318     for(i=0; i<=NH; i++)
1319     {
1320       for(j=0; j<=NV; j++)
1321       {
1322         if(xyz[i][j].fixed)
1323         {
1324           switch(Plane)
1325           {
1326           case PLANE_XZ0:
1327           case PLANE_XZ1:
1328             xyz[i][j].p[1] = xyz[i][j].fixed_value;
1329             break;
1330           case PLANE_YZ0:
1331           case PLANE_YZ1:
1332             xyz[i][j].p[0] = xyz[i][j].fixed_value;
1333             break;
1334           default:
1335             xyz[i][j].p[2] = xyz[i][j].fixed_value;
1336           }
1337           
1338           if(xyz[i][j].range > 0)
1339           {
1340             maxrange = pow(xyz[i][j].range,2); // so we don't have to do sqrt's
1341             i0 = i - (int)( floor(xyz[i][j].range/dh - 0.5) + 1 );
1342             i1 = i + i - i0;
1343             j0 = j - (int)( floor(xyz[i][j].range/dv - 0.5) + 1 );
1344             j1 = j + j - j0;
1345             if(FixBorders)
1346             {
1347               i0 = max(i0,1);
1348               i1 = min(i1,NH-1);
1349               j0 = max(j0,1);
1350               j1 = min(j1,NV-1);
1351             }
1352             else
1353             {
1354               i0 = max(i0,0);
1355               i1 = min(i1,NH);
1356               j0 = max(j0,0);
1357               j1 = min(j1,NV);
1358             }
1359             for(ii=i0; ii<=i1; ii++)
1360             {
1361               for(jj=j0; jj<=j1; jj++)
1362               {
1363                 if(ii==i && jj==j) continue;
1364                 range = pow( dh*(i-ii), 2) + pow( dv*(j-jj), 2);
1365                 if(range > maxrange) continue;
1366                 dr = sqrt(range/maxrange);
1367                 rate = max(-30.,min(xyz[i][j].rate,30.));
1368                 if(rate < -1.)
1369                 {
1370                   delta = pow((1.-dr),-rate+1.);
1371                 }
1372                 else if(rate < 0.)
1373                 {
1374                   delta = (1+rate)*0.5*(cos(dr*PI)+1.0) -
1375                     rate*pow((1.-dr),2);
1376                 }
1377                 else if(rate == 0.)
1378                 {
1379                   delta = 0.5*(cos(dr*PI)+1.0);
1380                 }
1381                 else if(rate <= 1.)
1382                 {
1383                   delta = (1.-rate)*0.5*(cos(dr*PI)+1.0) +
1384                     rate*(1.-pow(dr,2));
1385                 }
1386                 else
1387                 {
1388                   delta = 1.-pow(dr,rate+1);
1389                 }
1390                 switch(Plane)
1391                 {
1392                 case PLANE_XZ0:
1393                 case PLANE_XZ1:
1394                   xyz[ii][jj].p[1] += (xyz[i][j].p[1] - xyz[ii][jj].p[1])*delta;
1395                   break;
1396                 case PLANE_YZ0:
1397                 case PLANE_YZ1:
1398                   xyz[ii][jj].p[0] += (xyz[i][j].p[0] - xyz[ii][jj].p[0])*delta;
1399                   break;
1400                 default:
1401                   xyz[ii][jj].p[2] += (xyz[i][j].p[2] - xyz[ii][jj].p[2])*delta;
1402                 }
1403               }
1404             }
1405           }
1406         }
1407       }
1408     }
1409   }
1410
1411   if((Roughness > 0.) && (WaveType != WAVE_ROUGH_ONLY) )
1412   {
1413     for(i=0; i<=NH; i++)
1414     {
1415       for(j=0; j<=NV; j++)
1416       {
1417         if(CanEdit(i,j) && !xyz[i][j].fixed)
1418         {
1419           switch(Plane)
1420           {
1421           case PLANE_XZ0:
1422           case PLANE_XZ1:
1423             xyz[i][j].p[1] += -Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX);
1424             break;
1425           case PLANE_YZ0:
1426           case PLANE_YZ1:
1427             xyz[i][j].p[0] += -Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX);
1428             break;
1429           default:
1430             xyz[i][j].p[2] += -Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX);
1431           }
1432         }
1433         else
1434           r = rand();    // We still get a random number, so that fixing points
1435                            // doesn't change the sequence.
1436
1437       }
1438     }
1439   }
1440
1441   for(i=0; i<=NH; i++)
1442   {
1443     for(j=0; j<=NV; j++)
1444     {
1445       for(k=0; k<3; k++)
1446       {
1447         xyz[i][j].p[k] = Nearest(xyz[i][j].p[k],2.0);
1448       }
1449     }
1450   }
1451
1452   // Find minima and maxima
1453   switch(Plane)
1454   {
1455   case PLANE_XZ0:
1456   case PLANE_XZ1:
1457     xmin = Hll;
1458     xmax = Hur;
1459     zmin = Vll;
1460     zmax = Vur;
1461     ymin = xyz[0][0].p[1];
1462     ymax = ymin;
1463     for(i=0; i<=NH; i++)
1464     {
1465       for(j=0; j<=NV; j++)
1466       {
1467         ymin = min(ymin,xyz[i][j].p[1]);
1468         ymax = max(ymax,xyz[i][j].p[1]);
1469       }
1470     }
1471     break;
1472   case PLANE_YZ0:
1473   case PLANE_YZ1:
1474     ymin = Hll;
1475     ymax = Hur;
1476     zmin = Vll;
1477     zmax = Vur;
1478     xmin = xyz[0][0].p[0];
1479     xmax = ymin;
1480     for(i=0; i<=NH; i++)
1481     {
1482       for(j=0; j<=NV; j++)
1483       {
1484         xmin = min(xmin,xyz[i][j].p[0]);
1485         xmax = max(xmax,xyz[i][j].p[0]);
1486       }
1487     }
1488     break;
1489     break;
1490   default:
1491     xmin = Hll;
1492     xmax = Hur;
1493     ymin = Vll;
1494     ymax = Vur;
1495     zmin = xyz[0][0].p[2];
1496     zmax = zmin;
1497     for(i=0; i<=NH; i++)
1498     {
1499       for(j=0; j<=NV; j++)
1500       {
1501         zmin = min(zmin,xyz[i][j].p[2]);
1502         zmax = max(zmax,xyz[i][j].p[2]);
1503       }
1504     }
1505   }
1506   
1507   xmin = Nearest(xmin,2.);
1508   xmax = Nearest(xmax,2.);
1509   ymin = Nearest(ymin,2.);
1510   ymax = Nearest(ymax,2.);
1511   zmin = Nearest(zmin,2.);
1512   zmax = Nearest(zmax,2.);
1513   
1514   switch(Plane)
1515   {
1516   case PLANE_XY1:
1517     backface = AtLeast(zmax+32.,32.);
1518     break;
1519   case PLANE_XZ0:
1520     backface = NoMoreThan(ymin-32.,32.);
1521     break;
1522   case PLANE_XZ1:
1523     backface = AtLeast(ymax+32.,32.);
1524     break;
1525   case PLANE_YZ0:
1526     backface = NoMoreThan(xmin-32.,32.);
1527     break;
1528   case PLANE_YZ1:
1529     backface = AtLeast(xmax+32.,32.);
1530     break;
1531   default:
1532     backface = NoMoreThan(zmin-32.,32.);
1533   }
1534
1535   if(gNode)
1536   {
1537     free(gNode);
1538     free(gTri);
1539     gNode = (NODE *)NULL;
1540     gTri  = (TRI *)NULL;
1541   }
1542   if(Decimate > 0 && (Game != QUAKE3 || UsePatches==0) )
1543   {
1544     MakeDecimatedMap(&gNumNodes,&gNumTris,&gNode,&gTri);
1545   }
1546   else
1547   {
1548     gNumNodes = (NH+1)*(NV+1);
1549     gNumTris  = NH*NV*2;
1550     gNode = (NODE *) malloc(gNumNodes * sizeof(NODE));
1551     gTri = (TRI *) malloc(gNumTris * sizeof(TRI));
1552
1553     for(i=0,N=0; i<=NH; i++)
1554     {
1555       for(j=0; j<=NV; j++, N++)
1556       {
1557         gNode[N].used = 1;
1558         gNode[N].p[0] = (float)xyz[i][j].p[0];
1559         gNode[N].p[1] = (float)xyz[i][j].p[1];
1560         gNode[N].p[2] = (float)xyz[i][j].p[2];
1561       }
1562     }
1563     
1564     for(i=0; i<NH; i++)
1565     {
1566       for(j=0; j<NV; j++)
1567       {
1568         k = i*NV*2 + j*2;
1569         if( (i+j) % 2 )
1570         {
1571           switch(Plane)
1572           {
1573           case PLANE_XY1:
1574           case PLANE_XZ1:
1575           case PLANE_YZ1:
1576             gTri[k  ].v[0] = i*(NV+1)+j;
1577             gTri[k  ].v[1] = (i+1)*(NV+1)+j+1;
1578             gTri[k  ].v[2] = (i+1)*(NV+1)+j;
1579             gTri[k+1].v[0] = i*(NV+1)+j;
1580             gTri[k+1].v[1] = i*(NV+1)+j+1;
1581             gTri[k+1].v[2] = (i+1)*(NV+1)+j+1;
1582             break;
1583           default:
1584             gTri[k  ].v[0] = i*(NV+1)+j;
1585             gTri[k  ].v[1] = (i+1)*(NV+1)+j;
1586             gTri[k  ].v[2] = (i+1)*(NV+1)+j+1;
1587             gTri[k+1].v[0] = i*(NV+1)+j;
1588             gTri[k+1].v[1] = (i+1)*(NV+1)+j+1;
1589             gTri[k+1].v[2] = i*(NV+1)+j+1;
1590           }
1591         }
1592         else
1593         {
1594           switch(Plane)
1595           {
1596           case PLANE_XY1:
1597           case PLANE_XZ1:
1598           case PLANE_YZ1:
1599             gTri[k  ].v[0] = i*(NV+1)+j;
1600             gTri[k  ].v[1] = i*(NV+1)+j+1;
1601             gTri[k  ].v[2] = (i+1)*(NV+1)+j;
1602             gTri[k+1].v[0] = (i+1)*(NV+1)+j;
1603             gTri[k+1].v[1] = i*(NV+1)+j+1;
1604             gTri[k+1].v[2] = (i+1)*(NV+1)+j+1;
1605             break;
1606           default:
1607             gTri[k  ].v[0] = i*(NV+1)+j;
1608             gTri[k  ].v[1] = (i+1)*(NV+1)+j;
1609             gTri[k  ].v[2] = i*(NV+1)+j+1;
1610             gTri[k+1].v[0] = (i+1)*(NV+1)+j;
1611             gTri[k+1].v[1] = (i+1)*(NV+1)+j+1;
1612             gTri[k+1].v[2] = i*(NV+1)+j+1;
1613           }
1614         }
1615       }
1616     }
1617   }
1618 /*
1619   sprintf(CSV,"csv%03d.csv",Decimate);
1620   f = fopen(CSV,"w");
1621   for(i=0; i<gNumNodes; i++)
1622   {
1623     if(gNode[i].used)
1624       fprintf(f,"%g,%g,%g\n",gNode[i].p[0],gNode[i].p[1],gNode[i].p[2]);
1625   }
1626   fclose(f);
1627 */
1628   for(i=0; i<gNumTris; i++)
1629     PlaneFromPoints(gNode[gTri[i].v[0]].p,
1630                     gNode[gTri[i].v[1]].p,
1631                     gNode[gTri[i].v[2]].p,
1632                     &gTri[i].plane);
1633
1634   // Hydra: snap-to-grid begin
1635   if (SnapToGrid > 0)
1636   {
1637     for(i=0; i<NH; i++)
1638     {
1639       for(j=0; j<NV; j++)
1640       {
1641         switch(Plane)
1642         {
1643         case PLANE_XZ0:
1644         case PLANE_XZ1:
1645           xyz[i][j].p[1] = CalculateSnapValue(xyz[i][j].p[1]);
1646           break;
1647         case PLANE_YZ0:
1648         case PLANE_YZ1:
1649           xyz[i][j].p[0] = CalculateSnapValue(xyz[i][j].p[0]);
1650           break;
1651         default:
1652           xyz[i][j].p[2] = CalculateSnapValue(xyz[i][j].p[2]);
1653         }
1654       }
1655     }
1656   }
1657   // Hydra: snap-to-grid end
1658 }
1659 //=============================================================
1660 double Nearest(double x, double dx)
1661 {
1662   double xx;
1663
1664   xx = (double)(floor(x/dx - 0.5)+1.)*dx;
1665   if(fabs(xx) < dx/2) xx = 0.;
1666   return xx;
1667 }
1668 //=============================================================
1669 double NoMoreThan(double x, double dx)
1670 {
1671   double xx;
1672
1673   xx = (double)(floor(x/dx - 0.5)+1.)*dx;
1674   if(xx > x) xx -= dx;
1675   return xx;
1676 }
1677 //=============================================================
1678 double AtLeast(double x, double dx)
1679 {
1680   double xx;
1681
1682   xx = (double)(floor(x/dx - 0.5)+1.)*dx;
1683   if(xx < x) xx += dx;
1684   return xx;
1685 }
1686 //=============================================================
1687 double LessThan(double x,double dx)
1688 {
1689   double xx;
1690
1691   xx = (double)(floor(x/dx - 0.5)+1.)*dx;
1692   if(xx >= x) xx -= dx;
1693   return xx;
1694 }
1695 //=============================================================
1696 double MoreThan(double x,double dx)
1697 {
1698   double xx;
1699
1700   xx = (double)(floor(x/dx - 0.5)+1.)*dx;
1701   while(xx <= x)
1702     xx += dx;
1703   return xx;
1704 }
1705 //=============================================================
1706 void SubdividePlasma(int i0,int j0,int i1,int j1)
1707 {
1708   int i, j;
1709   double z1, z2;
1710   double r;      // NOTE: This is used to keep the random number sequence the same
1711                  //       when we fix a point. If we did NOT do this, then simply
1712                  //       fixing a point at its current value would change the entire
1713                  //       surface.
1714
1715   i = (i0+i1)/2;
1716   j = (j0+j1)/2;
1717   if(i1 > i0+1)
1718   {
1719     if(!xyz[i][j0].done)
1720     {
1721       xyz[i][j0].pp[2] = xyz[i0][j0].pp[2] + 
1722         (xyz[i1][j0].pp[2] - xyz[i0][j0].pp[2])*(double)(i-i0)/(double)(i1-i0) +
1723         ((double)(i-i0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX));
1724       xyz[i][j0].done = 1;
1725     }
1726     else
1727       r = rand();
1728     if((j1 > j0) && (!xyz[i][j1].done) )
1729     {
1730       xyz[i][j1].pp[2] = xyz[i0][j1].pp[2] + 
1731         (xyz[i1][j1].pp[2] - xyz[i0][j1].pp[2])*(double)(i-i0)/(double)(i1-i0) +
1732         ((double)(i-i0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX));
1733       xyz[i][j1].done = 1;
1734     }
1735     else
1736       r = rand();
1737   }
1738   if(j1 > j0 + 1)
1739   {
1740     if(!xyz[i0][j].done)
1741     {
1742       xyz[i0][j].pp[2] = xyz[i0][j0].pp[2] + 
1743         (xyz[i0][j1].pp[2] - xyz[i0][j0].pp[2])*(double)(j-j0)/(double)(j1-j0) +
1744         ((double)(j-j0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX));
1745       xyz[i0][j].done = 1;
1746     }
1747     else
1748       r = rand();
1749     if((i1 > i0) && (!xyz[i1][j].done))
1750     {
1751       xyz[i1][j].pp[2] = xyz[i1][j0].pp[2] + 
1752         (xyz[i1][j1].pp[2] - xyz[i1][j0].pp[2])*(double)(j-j0)/(double)(j1-j0) +
1753         ((double)(j-j0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX));
1754       xyz[i1][j].done = 1;
1755     }
1756     else
1757       r = rand();
1758   }
1759   if((i1 > i0+1) && (j1 > j0+1))
1760   {
1761     if(!xyz[i][j].done)
1762     {
1763       z1 = xyz[i0][j].pp[2] +
1764         (xyz[i1][j].pp[2] - xyz[i0][j].pp[2])*(double)(i-i0)/(double)(i1-i0);
1765       z2 = xyz[i][j0].pp[2] +
1766         (xyz[i][j1].pp[2] - xyz[i][j0].pp[2])*(double)(j-j0)/(double)(j1-j0);
1767       xyz[i][j].pp[2] = (z1+z2)/2. +
1768         ((double)(i-i0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX));
1769       xyz[i][j].done = 1;
1770     }
1771     else
1772       r = rand();
1773   }
1774   if(i > i0+1 || j > j0+1)
1775     SubdividePlasma(i0,j0,i,j);
1776   if(i1 > i+1 || j > j0+1)
1777     SubdividePlasma(i,j0,i1,j);
1778   if(i > i0+1 || j1 > j0+1)
1779     SubdividePlasma(i0,j,i,j1);
1780   if(i1 > i+1 || j1 > j0+1)
1781     SubdividePlasma(i,j,i1,j1);
1782 }
1783 //==================================================================================
1784 void PlasmaCloud()
1785 {
1786   int i, j;
1787   /* use pp[2] values until done to avoid messing with a bunch of 
1788      switch statements */
1789
1790   for(i=0; i<=NH; i++)
1791   {
1792     for(j=0; j<=NV; j++)
1793     {
1794       if(FixedPoint(i,j))
1795         xyz[i][j].done = 1;
1796       else
1797         xyz[i][j].done = 0;
1798     }
1799   }
1800
1801   switch(Plane)
1802   {
1803   case PLANE_XZ0:
1804   case PLANE_XZ1:
1805     for(i=0; i<=NH; i++)
1806     {
1807       for(j=0; j<=NV; j++)
1808       {
1809         if(xyz[i][j].fixed)
1810           xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1811         else
1812           xyz[i][j].pp[2] = xyz[i][j].p[1];
1813       }
1814     }
1815     break;
1816   case PLANE_YZ0:
1817   case PLANE_YZ1:
1818     for(i=0; i<=NH; i++)
1819     {
1820       for(j=0; j<=NV; j++)
1821       {
1822         if(xyz[i][j].fixed)
1823           xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1824         else
1825           xyz[i][j].pp[2] = xyz[i][j].p[0];
1826       }
1827     }
1828     break;
1829   default:
1830     for(i=0; i<=NH; i++)
1831     {
1832       for(j=0; j<=NV; j++)
1833       {
1834         if(xyz[i][j].fixed)
1835           xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1836         else
1837           xyz[i][j].pp[2] = xyz[i][j].p[2];
1838       }
1839     }
1840     break;
1841   }
1842   SubdividePlasma(0,0,NH,NV);
1843   switch(Plane)
1844   {
1845   case PLANE_XZ0:
1846   case PLANE_XZ1:
1847     for(i=0; i<=NH; i++)
1848     {
1849       for(j=0; j<=NV; j++)
1850       {
1851         xyz[i][j].p[1] = xyz[i][j].pp[2];
1852       }
1853     }
1854     break;
1855   case PLANE_YZ0:
1856   case PLANE_YZ1:
1857     for(i=0; i<=NH; i++)
1858     {
1859       for(j=0; j<=NV; j++)
1860       {
1861         xyz[i][j].p[0] = xyz[i][j].pp[2];
1862       }
1863     }
1864     break;
1865   default:
1866     for(i=0; i<=NH; i++)
1867     {
1868       for(j=0; j<=NV; j++)
1869       {
1870         xyz[i][j].p[2] = xyz[i][j].pp[2];
1871       }
1872     }
1873     break;
1874   }
1875 }
1876 //===========================================================================
1877 bool FixedPoint(int i, int j)
1878 {
1879   if(xyz[i][j].fixed) return TRUE;
1880   return !CanEdit(i,j);
1881 }
1882 //===========================================================================
1883 bool CanEdit(int i, int j)
1884 {
1885   if(FixBorders && ( (WaveType==WAVE_COS_SIN) || (WaveType==WAVE_ROUGH_ONLY) ) )
1886   {
1887     if(i== 0) return FALSE;
1888     if(i==NH) return FALSE;
1889     if(j== 0) return FALSE;
1890     if(j==NV) return FALSE;
1891   }
1892   if(i== 0 && j== 0) return FALSE;
1893   if(i==NH && j== 0) return FALSE;
1894   if(i== 0 && j==NV) return FALSE;
1895   if(i==NH && j==NV) return FALSE;
1896   return TRUE;
1897 }
1898 /*============================================================================
1899   TriangleFromPoint
1900   Determines which triangle in the gTri array bounds the input point. Doesn't
1901   do anything special with border points.
1902 */
1903 int TriangleFromPoint(double x, double y)
1904 {
1905   int j, tri;
1906
1907   if(!gTri) return -1;
1908
1909   for(j=0, tri=-1; j<gNumTris && tri==-1; j++)
1910   {
1911     if( side(x,y,
1912       gNode[gTri[j].v[0]].p[0],gNode[gTri[j].v[0]].p[1],
1913       gNode[gTri[j].v[1]].p[0],gNode[gTri[j].v[1]].p[1]) < 0. ) continue;
1914     if( side(x,y,
1915       gNode[gTri[j].v[1]].p[0],gNode[gTri[j].v[1]].p[1],
1916       gNode[gTri[j].v[2]].p[0],gNode[gTri[j].v[2]].p[1]) < 0. ) continue;
1917     if( side(x,y,
1918       gNode[gTri[j].v[2]].p[0],gNode[gTri[j].v[2]].p[1],
1919       gNode[gTri[j].v[0]].p[0],gNode[gTri[j].v[0]].p[1]) < 0. ) continue;
1920     tri = j;
1921   }
1922
1923   return tri;
1924 }
1925 /*============================================================================
1926   PlayerStartZ
1927   Determines minimum height to place the player start such that he doesn't
1928   intersect any surface brushes.
1929 */
1930 int PlayerStartZ(double x, double y)
1931 {
1932   int k,t[5];
1933   double z, zt;
1934
1935   if(!gTri) return (int)zmax;
1936
1937   t[0] = TriangleFromPoint(x,y);
1938   t[1] = TriangleFromPoint(x+PlayerBox[Game].x[0],y+PlayerBox[Game].y[0]);
1939   t[2] = TriangleFromPoint(x+PlayerBox[Game].x[0],y+PlayerBox[Game].y[1]);
1940   t[3] = TriangleFromPoint(x+PlayerBox[Game].x[1],y+PlayerBox[Game].y[0]);
1941   t[4] = TriangleFromPoint(x+PlayerBox[Game].x[1],y+PlayerBox[Game].y[1]);
1942   z = zmin;
1943   for(k=0; k<5; k++)
1944   {
1945     zt = (gTri[t[k]].plane.dist -
1946           gTri[t[k]].plane.normal[0]*x -
1947           gTri[t[k]].plane.normal[1]*y   )/
1948           gTri[t[k]].plane.normal[2];
1949     z = max(z,zt);
1950   }
1951   return (int)(AtLeast(z,2.) - PlayerBox[Game].z[0]);
1952 }
1953 //=============================================================
1954 void XYZtoV(XYZ *xyz, vec3 *v)
1955 {
1956   v[0][0] = (vec)Nearest(xyz->p[0],2.);
1957   v[0][1] = (vec)Nearest(xyz->p[1],2.);
1958   v[0][2] = (vec)Nearest(xyz->p[2],2.);
1959 }
1960
1961 //=============================================================
1962 void MakePatch(patchMesh_t *p)
1963 {
1964   int ret;
1965   char shadername[64+9];
1966
1967   ret = g_FuncTable.m_pfnCreatePatchHandle();
1968   // strcpy(shadername, "textures/");
1969   // strcpy(shadername+9, Texture[Game][0]);
1970   strcpy(shadername, Texture[Game][0]);
1971   g_FuncTable.m_pfnCommitPatchHandleToMap(ret,p,shadername);
1972   g_FuncTable.m_pfnReleasePatchHandles();
1973 }
1974
1975 //=============================================================
1976 void MakeBrush(BRUSH *brush)
1977 {
1978   LPVOID vp;
1979   int i;
1980   _QERFaceData QERFaceData;
1981
1982   if(g_FuncTable.m_pfnCreateBrushHandle==NULL)
1983   {
1984     g_FuncTable.m_pfnMessageBox(g_pRadiantWnd,"m_pfnCreateBrushHandle==NULL","Aw damn",0);
1985     return;
1986   }
1987   vp=(g_FuncTable.m_pfnCreateBrushHandle)();
1988   if(!vp) return;
1989   for(i=0; i<brush->NumFaces; i++)
1990   {
1991     if(!strncmp(brush->face[i].texture, "textures/", 9))
1992       strcpy(QERFaceData.m_TextureName,brush->face[i].texture);
1993     else 
1994     {
1995       strcpy(QERFaceData.m_TextureName,"textures/");
1996       strcpy(QERFaceData.m_TextureName+9,brush->face[i].texture);  
1997     }
1998     QERFaceData.m_nContents = brush->face[i].Contents;
1999     QERFaceData.m_nFlags    = brush->face[i].Surface;
2000     QERFaceData.m_nValue    = brush->face[i].Value;
2001     QERFaceData.m_fShift[0] = brush->face[i].Shift[0];
2002     QERFaceData.m_fShift[1] = brush->face[i].Shift[1];
2003     QERFaceData.m_fRotate   = brush->face[i].Rotate;
2004     QERFaceData.m_fScale[0] = brush->face[i].Scale[0];
2005     QERFaceData.m_fScale[1] = brush->face[i].Scale[1];
2006     QERFaceData.m_v1[0]     = brush->face[i].v[0][0];
2007     QERFaceData.m_v1[1]     = brush->face[i].v[0][1];
2008     QERFaceData.m_v1[2]     = brush->face[i].v[0][2];
2009     QERFaceData.m_v2[0]     = brush->face[i].v[1][0];
2010     QERFaceData.m_v2[1]     = brush->face[i].v[1][1];
2011     QERFaceData.m_v2[2]     = brush->face[i].v[1][2];
2012     QERFaceData.m_v3[0]     = brush->face[i].v[2][0];
2013     QERFaceData.m_v3[1]     = brush->face[i].v[2][1];
2014     QERFaceData.m_v3[2]     = brush->face[i].v[2][2];
2015     QERFaceData.m_bBPrimit  = false;
2016     (g_FuncTable.m_pfnAddFaceData)(vp,&QERFaceData);
2017   }
2018   if(g_FuncTable.m_pfnCommitBrushHandle!=NULL)
2019   {
2020     if(h_func_group)
2021       g_FuncTable.m_pfnCommitBrushHandleToEntity(vp,h_func_group);
2022     else
2023       g_FuncTable.m_pfnCommitBrushHandle(vp);
2024   }
2025 }
2026 //=============================================================
2027 void OpenFuncGroup()
2028 {
2029   if (g_FuncTable.m_pfnAllocateEpair!=NULL)
2030   {
2031     epair_t *ep;
2032
2033     h_func_group = g_FuncTable.m_pfnCreateEntityHandle();
2034     ep = g_EntityTable.m_pfnAllocateEpair("classname","func_group");
2035     g_EntityTable.m_pfnSetEntityKeyValList((entity_t *)h_func_group,ep);
2036                 
2037                 if (AddTerrainKey) // ^Fishman - Add terrain key to func_group.
2038                 {
2039                         epair_t *ep2;
2040                         terrainkey = g_FuncTable.m_pfnCreateEntityHandle();
2041                         ep2 = g_EntityTable.m_pfnAllocateEpair("terrain","1");
2042                         ep->next = ep2;
2043                         g_EntityTable.m_pfnSetEntityKeyValList((entity_t *)h_func_group,ep);
2044                 }
2045         }
2046         else
2047     h_func_group = NULL;
2048 }
2049 //=============================================================
2050 void CloseFuncGroup()
2051 {
2052   if (h_func_group)
2053     g_FuncTable.m_pfnCommitEntityHandleToMap (h_func_group);
2054   if (g_FuncTable.m_pfnSysUpdateWindows != NULL)
2055     g_FuncTable.m_pfnSysUpdateWindows (W_ALL);
2056 }