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