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