]> git.jsancho.org Git - lugaru.git/blob - Source/Environment/Terrain.cpp
164dce38fd6a02739d221c4e5282204584d6283a
[lugaru.git] / Source / Environment / Terrain.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
4
5 This file is part of Lugaru.
6
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "Environment/Terrain.hpp"
22
23 #include "Game.hpp"
24 #include "Objects/Objects.hpp"
25 #include "Utils/Folders.hpp"
26
27 extern XYZ viewer;
28 extern float viewdistance;
29 extern float fadestart;
30 extern int environment;
31 extern float texscale;
32 extern Light light;
33 extern float multiplier;
34 extern FRUSTUM frustum;
35 extern float texdetail;
36 extern int detail;
37 extern bool decals;
38 extern float blurness;
39 extern float targetblurness;
40 extern Objects objects;
41 extern bool visibleloading;
42 extern bool skyboxtexture;
43 extern int tutoriallevel;
44
45 //Functions
46
47 int Terrain::lineTerrain(XYZ p1, XYZ p2, XYZ *p)
48 {
49     static int i, j, k;
50     static float distance;
51     static float olddistance;
52     static int intersecting;
53     static int firstintersecting;
54     static XYZ point;
55     static int startx, starty;
56     static int endx, endy;
57     static float highest, lowest;
58
59     firstintersecting = -1;
60     olddistance = 10000;
61     distance = 1;
62
63     XYZ triangles[3];
64
65     p1 /= scale;
66     p2 /= scale;
67
68     startx = p1.x;
69     starty = p1.z;
70     endx = p2.x;
71     endy = p2.z;
72
73     if (startx > endx) {
74         i = endx;
75         endx = startx;
76         startx = i;
77     }
78     if (starty > endy) {
79         i = endy;
80         endy = starty;
81         starty = i;
82     }
83
84     if (startx < 0)
85         startx = 0;
86     if (starty < 0)
87         starty = 0;
88     if (endx > size - 1)
89         endx = size - 1;
90     if (endy > size - 1)
91         endy = size - 1;
92
93     for (i = startx; i <= endx; i++) {
94         for (j = starty; j <= endy; j++) {
95             highest = -1000;
96             lowest = 1000;
97             for (k = 0; k < 2; k++) {
98                 if (heightmap[i + k][j] > highest)
99                     highest = heightmap[i + k][j];
100                 if (heightmap[i + k][j] < lowest)
101                     lowest = heightmap[i + k][j];
102                 if (heightmap[i + k][j + 1] > highest)
103                     highest = heightmap[i + k][j + 1];
104                 if (heightmap[i + k][j + 1] < lowest)
105                     lowest = heightmap[i + k][j + 1];
106             }
107             if ((p1.y <= highest || p2.y <= highest) && (p1.y >= lowest || p2.y >= lowest)) {
108                 triangles[0].x = i;
109                 triangles[0].y = heightmap[i][j];
110                 triangles[0].z = j;
111
112                 triangles[1].x = i;
113                 triangles[1].y = heightmap[i][j + 1];
114                 triangles[1].z = j + 1;
115
116                 triangles[2].x = i + 1;
117                 triangles[2].y = heightmap[i + 1][j];
118                 triangles[2].z = j;
119
120                 intersecting = LineFacet(p1, p2, triangles[0], triangles[1], triangles[2], &point);
121                 distance = distsq(&p1, &point);
122                 if ((distance < olddistance || firstintersecting == -1) && intersecting == 1) {
123                     olddistance = distance;
124                     firstintersecting = 1;
125                     *p = point;
126                 }
127
128                 triangles[0].x = i + 1;
129                 triangles[0].y = heightmap[i + 1][j];
130                 triangles[0].z = j;
131
132                 triangles[1].x = i;
133                 triangles[1].y = heightmap[i][j + 1];
134                 triangles[1].z = j + 1;
135
136                 triangles[2].x = i + 1;
137                 triangles[2].y = heightmap[i + 1][j + 1];
138                 triangles[2].z = j + 1;
139
140                 intersecting = LineFacet(p1, p2, triangles[0], triangles[1], triangles[2], &point);
141                 distance = distsq(&p1, &point);
142                 if ((distance < olddistance || firstintersecting == -1) && intersecting == 1) {
143                     olddistance = distance;
144                     firstintersecting = 1;
145                     *p = point;
146                 }
147             }
148         }
149     }
150     return firstintersecting;
151 }
152
153 void Terrain::UpdateTransparency(int whichx, int whichy)
154 {
155     static XYZ vertex;
156     static int i, j, a, b, c, d, patch_size, stepsize;
157     static float distance;
158
159     static float viewdistsquared;
160
161     viewdistsquared = viewdistance * viewdistance;
162     patch_size = size / subdivision;
163
164     stepsize = 1;
165     c = whichx * patch_elements + whichy * patch_elements * subdivision;
166
167     for (i = patch_size * whichx; i < patch_size * (whichx + 1) + 1; i += stepsize) {
168         for (j = patch_size * whichy; j < patch_size * (whichy + 1) + 1; j += stepsize) {
169             if (i < size && j < size) {
170                 vertex.x = i * scale;
171                 vertex.z = j * scale;
172                 vertex.y = heightmap[i][j] * scale;
173                 distance = distsq(&viewer, &vertex);
174                 if (distance > viewdistsquared)
175                     distance = viewdistsquared;
176                 colors[i][j][3] = (viewdistsquared - (distance - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
177             }
178         }
179     }
180
181     for (i = patch_size * whichx; i < patch_size * (whichx + 1); i += stepsize) {
182         for (j = patch_size * whichy; j < patch_size * (whichy + 1); j += stepsize) {
183             a = (i - (patch_size * whichx)) / stepsize;
184             b = (j - (patch_size * whichy)) / stepsize;
185             d = (a * 54) + (b * 54 * patch_size / stepsize);
186             vArray[d + c + 6] = colors[i][j][3];
187
188             vArray[d + c + 15] = colors[i][j + stepsize][3];
189
190             vArray[d + c + 24] = colors[i + stepsize][j][3];
191
192             vArray[d + c + 33] = colors[i + stepsize][j][3];
193
194             vArray[d + c + 42] = colors[i][j + stepsize][3];
195
196             vArray[d + c + 51] = colors[i + stepsize][j + stepsize][3];
197         }
198     }
199 }
200
201 void Terrain::UpdateTransparencyother(int whichx, int whichy)
202 {
203     static int i, j, a, b, c, d, patch_size, stepsize;
204
205     patch_size = size / subdivision;
206
207     stepsize = 1;
208     c = whichx * patch_elements + whichy * patch_elements * subdivision;
209
210     for (i = patch_size * whichx; i < patch_size * (whichx + 1); i += stepsize) {
211         for (j = patch_size * whichy; j < patch_size * (whichy + 1); j += stepsize) {
212             a = (i - (patch_size * whichx)) / stepsize;
213             b = (j - (patch_size * whichy)) / stepsize;
214             d = (a * 54) + (b * 54 * patch_size / stepsize);
215             vArray[d + c + 6] = colors[i][j][3] * opacityother[i][j];
216
217             vArray[d + c + 15] = colors[i][j + stepsize][3] * opacityother[i][j + stepsize];
218
219             vArray[d + c + 24] = colors[i + stepsize][j][3] * opacityother[i + stepsize][j];
220
221             vArray[d + c + 33] = colors[i + stepsize][j][3] * opacityother[i + stepsize][j];
222
223             vArray[d + c + 42] = colors[i][j + stepsize][3] * opacityother[i][j + stepsize];
224
225             vArray[d + c + 51] = colors[i + stepsize][j + stepsize][3] * opacityother[i + stepsize][j + stepsize];
226         }
227     }
228 }
229
230 void Terrain::UpdateTransparencyotherother(int whichx, int whichy)
231 {
232     static XYZ vertex;
233     static int i, j, a, b, c, d, patch_size, stepsize;
234     static float distance;
235
236     static float viewdistsquared;
237
238     viewdistsquared = viewdistance * viewdistance;
239     patch_size = size / subdivision;
240
241     stepsize = 1;
242     c = whichx * patch_elements + whichy * patch_elements * subdivision;
243
244     for (i = patch_size * whichx; i < patch_size * (whichx + 1) + 1; i += stepsize) {
245         for (j = patch_size * whichy; j < patch_size * (whichy + 1) + 1; j += stepsize) {
246             if (i < size && j < size) {
247                 vertex.x = i * scale;
248                 vertex.z = j * scale;
249                 vertex.y = heightmap[i][j] * scale;
250                 distance = distsq(&viewer, &vertex);
251                 if (distance > viewdistsquared)
252                     distance = viewdistsquared;
253                 colors[i][j][3] = (viewdistsquared - (distance - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
254             }
255         }
256     }
257
258     for (i = patch_size * whichx; i < patch_size * (whichx + 1); i += stepsize) {
259         for (j = patch_size * whichy; j < patch_size * (whichy + 1); j += stepsize) {
260             a = (i - (patch_size * whichx)) / stepsize;
261             b = (j - (patch_size * whichy)) / stepsize;
262             d = (a * 54) + (b * 54 * patch_size / stepsize);
263             vArray[d + c + 6] = colors[i][j][3];
264
265             vArray[d + c + 15] = colors[i][j + stepsize][3];
266
267             vArray[d + c + 24] = colors[i + stepsize][j][3];
268
269             vArray[d + c + 33] = colors[i + stepsize][j][3];
270
271             vArray[d + c + 42] = colors[i][j + stepsize][3];
272
273             vArray[d + c + 51] = colors[i + stepsize][j + stepsize][3];
274         }
275     }
276 }
277
278 void Terrain::UpdateVertexArray(int whichx, int whichy)
279 {
280     static int i, j, a, b, c, patch_size, stepsize;
281
282
283     numtris[whichx][whichy] = 0;
284
285     patch_size = size / subdivision;
286
287     stepsize = 1;
288     c = whichx * patch_elements + whichy * patch_elements * subdivision;
289     for (i = patch_size * whichx; i < patch_size * (whichx + 1); i += stepsize) {
290         for (j = patch_size * whichy; j < patch_size * (whichy + 1); j += stepsize) {
291             a = (i - ((float)size / subdivision * (float)whichx)) / stepsize;
292             b = (j - ((float)size / subdivision * (float)whichy)) / stepsize;
293             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 0] = i * scale;
294             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 1] = heightmap[i][j] * scale;
295             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 2] = j * scale;
296             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 3] = colors[i][j][0];
297             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 4] = colors[i][j][1];
298             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 5] = colors[i][j][2];
299             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 6] = colors[i][j][3];
300             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 7] = i * scale * texscale + texoffsetx[i][j];
301             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 8] = j * scale * texscale + texoffsety[i][j];
302
303             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 9] = i * scale;
304             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 10] = heightmap[i][j + stepsize] * scale;
305             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 11] = j * scale + stepsize * scale;
306             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 12] = colors[i][j + stepsize][0];
307             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 13] = colors[i][j + stepsize][1];
308             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 14] = colors[i][j + stepsize][2];
309             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 15] = colors[i][j + stepsize][3];
310             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 16] = i * scale * texscale + texoffsetx[i][j + stepsize];
311             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 17] = j * scale * texscale + stepsize * scale * texscale + texoffsety[i][j + stepsize];
312
313             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 18] = i * scale + stepsize * scale;
314             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 19] = heightmap[i + stepsize][j] * scale;
315             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 20] = j * scale;
316             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 21] = colors[i + stepsize][j][0];
317             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 22] = colors[i + stepsize][j][1];
318             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 23] = colors[i + stepsize][j][2];
319             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 24] = colors[i + stepsize][j][3];
320             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 25] = i * scale * texscale + stepsize * scale * texscale + texoffsetx[i + stepsize][j];
321             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 26] = j * scale * texscale + texoffsety[i + stepsize][j];
322
323             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 27] = i * scale + stepsize * scale;
324             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 28] = heightmap[i + stepsize][j] * scale;
325             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 29] = j * scale;
326             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 30] = colors[i + stepsize][j][0];
327             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 31] = colors[i + stepsize][j][1];
328             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 32] = colors[i + stepsize][j][2];
329             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 33] = colors[i + stepsize][j][3];
330             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 34] = i * scale * texscale + stepsize * scale * texscale + texoffsetx[i + stepsize][j];
331             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 35] = j * scale * texscale + texoffsety[i + stepsize][j];
332
333             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 36] = i * scale;
334             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 37] = heightmap[i][j + stepsize] * scale;
335             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 38] = j * scale + stepsize * scale;
336             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 39] = colors[i][j + stepsize][0];
337             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 40] = colors[i][j + stepsize][1];
338             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 41] = colors[i][j + stepsize][2];
339             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 42] = colors[i][j + stepsize][3];
340             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 43] = i * scale * texscale + texoffsetx[i][j + stepsize];
341             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 44] = j * scale * texscale + stepsize * scale * texscale + texoffsety[i][j + stepsize];
342
343             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 45] = i * scale + stepsize * scale;
344             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 46] = heightmap[i + stepsize][j + stepsize] * scale;
345             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 47] = j * scale + stepsize * scale;
346             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 48] = colors[i + stepsize][j + stepsize][0];
347             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 49] = colors[i + stepsize][j + stepsize][1];
348             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 50] = colors[i + stepsize][j + stepsize][2];
349             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 51] = colors[i + stepsize][j + stepsize][3];
350             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 52] = i * scale * texscale + stepsize * scale * texscale + texoffsetx[i + stepsize][j + stepsize];
351             vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 53] = j * scale * texscale + stepsize * scale * texscale + texoffsety[i + stepsize][j + stepsize];
352             numtris[whichx][whichy] += 2;
353         }
354     }
355
356     maxypatch[whichx][whichy] = -10000;
357     minypatch[whichx][whichy] = 10000;
358     for (a = 0; a < size / subdivision; a++) {
359         for (b = 0; b < size / subdivision; b++) {
360             if (heightmap[(size / subdivision)*whichx + a][(size / subdivision)*whichy + b]*scale > maxypatch[whichx][whichy])
361                 maxypatch[whichx][whichy] = heightmap[(size / subdivision) * whichx + a][(size / subdivision) * whichy + b] * scale;
362             if (heightmap[(size / subdivision)*whichx + a][(size / subdivision)*whichy + b]*scale < minypatch[whichx][whichy])
363                 minypatch[whichx][whichy] = heightmap[(size / subdivision) * whichx + a][(size / subdivision) * whichy + b] * scale;
364         }
365     }
366     heightypatch[whichx][whichy] = (maxypatch[whichx][whichy] - minypatch[whichx][whichy]);
367     if (heightypatch[whichx][whichy] < size / subdivision * scale)
368         heightypatch[whichx][whichy] = size / subdivision * scale;
369     avgypatch[whichx][whichy] = (minypatch[whichx][whichy] + maxypatch[whichx][whichy]) / 2;
370
371     for (i = whichx * size / subdivision; i < (whichx + 1)*size / subdivision - 1; i++) {
372         for (j = whichy * size / subdivision; j < (whichy + 1)*size / subdivision - 1; j++) {
373             triangles[(i * (size - 1) * 2) + (j * 2)][0].x = i * scale;
374             triangles[(i * (size - 1) * 2) + (j * 2)][0].y = heightmap[i][j] * scale;
375             triangles[(i * (size - 1) * 2) + (j * 2)][0].z = j * scale;
376
377             triangles[(i * (size - 1) * 2) + (j * 2)][1].x = i * scale;
378             triangles[(i * (size - 1) * 2) + (j * 2)][1].y = heightmap[i][j + 1] * scale;
379             triangles[(i * (size - 1) * 2) + (j * 2)][1].z = j * scale + scale;
380
381             triangles[(i * (size - 1) * 2) + (j * 2)][2].x = i * scale + 1 * scale;
382             triangles[(i * (size - 1) * 2) + (j * 2)][2].y = heightmap[i + 1][j] * scale;
383             triangles[(i * (size - 1) * 2) + (j * 2)][2].z = j * scale;
384
385             triangles[(i * (size - 1) * 2) + (j * 2) + 1][0].x = i * scale + 1 * scale;
386             triangles[(i * (size - 1) * 2) + (j * 2) + 1][0].y = heightmap[i + 1][j] * scale;
387             triangles[(i * (size - 1) * 2) + (j * 2) + 1][0].z = j * scale;
388
389             triangles[(i * (size - 1) * 2) + (j * 2) + 1][1].x = i * scale;
390             triangles[(i * (size - 1) * 2) + (j * 2) + 1][1].y = heightmap[i][j + 1] * scale;
391             triangles[(i * (size - 1) * 2) + (j * 2) + 1][1].z = j * scale + 1 * scale;
392
393             triangles[(i * (size - 1) * 2) + (j * 2) + 1][2].x = i * scale + 1 * scale;
394             triangles[(i * (size - 1) * 2) + (j * 2) + 1][2].y = heightmap[i + 1][j + 1] * scale;
395             triangles[(i * (size - 1) * 2) + (j * 2) + 1][2].z = j * scale + 1 * scale;
396         }
397     }
398
399 }
400
401
402 bool Terrain::load(const std::string& fileName)
403 {
404     static long i, j;
405     static long x, y;
406     static float patch_size;
407
408     float temptexdetail = texdetail;
409
410     ImageRec texture;
411
412     //Load Image
413     if (!load_image(Folders::getResourcePath(fileName).c_str(), texture)) {
414         return false;
415     }
416
417     //Is it valid?
418     if (texture.bpp > 24) {
419         int bytesPerPixel = texture.bpp / 8;
420
421         int tempnum = 0;
422         for (i = 0; i < (long)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
423             if ((i + 1) % 4) {
424                 texture.data[tempnum] = texture.data[i];
425                 tempnum++;
426             }
427         }
428     }
429     texture.bpp = 24;
430     if (visibleloading)
431         Game::LoadingScreen();
432
433     texdetail = temptexdetail;
434
435     size = texture.sizeX;
436
437     for (i = 0; i < size; i++) {
438         for (j = 0; j < size; j++) {
439             heightmap[size - 1 - i][j] = (float)((texture.data[(i + (j * size)) * texture.bpp / 8])) / 5;
440         }
441     }
442
443     if (visibleloading)
444         Game::LoadingScreen();
445
446     float slopeness;
447
448     for (i = 0; i < subdivision; i++) {
449         for (j = 0; j < subdivision; j++) {
450             textureness[i][j] = -1;
451         }
452     }
453     if (visibleloading)
454         Game::LoadingScreen();
455
456
457     for (i = 0; i < size; i++) {
458         for (j = 0; j < size; j++) {
459             heightmap[i][j] *= .5;
460
461             texoffsetx[i][j] = (float)abs(Random() % 100) / 1200 / scale * 3;
462             texoffsety[i][j] = (float)abs(Random() % 100) / 1200 / scale * 3;
463
464             slopeness = 0;
465             if (environment == snowyenvironment) {
466                 if (j != 0 && heightmap[i][j] - heightmap[i][j - 1] > slopeness) {
467                     slopeness = heightmap[i][j] - heightmap[i][j - 1];
468                 }
469                 opacityother[i][j] = slopeness * slopeness * 2;
470                 if (opacityother[i][j] > 1)
471                     opacityother[i][j] = 1;
472                 opacityother[i][j] -= (float)abs(Random() % 100) / 300;
473             }
474             if (environment == desertenvironment) {
475                 if (j != 0 && heightmap[i][j] - heightmap[i][j - 1] > slopeness) {
476                     slopeness = heightmap[i][j] - heightmap[i][j - 1];
477                 }
478                 opacityother[i][j] = slopeness * slopeness * 2;
479                 if (opacityother[i][j] > 1)
480                     opacityother[i][j] = 1;
481                 opacityother[i][j] -= (float)abs(Random() % 100) / 300;
482             }
483             if (environment == grassyenvironment) {
484                 if (i != 0 && heightmap[i][j] - heightmap[i - 1][j] > slopeness) {
485                     slopeness = heightmap[i][j] - heightmap[i - 1][j];
486                 }
487                 if (j != 0 && heightmap[i][j] - heightmap[i][j - 1] > slopeness) {
488                     slopeness = heightmap[i][j] - heightmap[i][j - 1];
489                 }
490                 if (i < size - 1 && heightmap[i][j] - heightmap[i + 1][j] > slopeness) {
491                     slopeness = heightmap[i][j] - heightmap[i + 1][j];
492                 }
493                 if (j < size - 1 && heightmap[i][j] - heightmap[i][j + 1] > slopeness) {
494                     slopeness = heightmap[i][j] - heightmap[i][j + 1];
495                 }
496                 opacityother[i][j] = slopeness * slopeness * 10;
497                 if (opacityother[i][j] > 1)
498                     opacityother[i][j] = 1;
499                 opacityother[i][j] -= (float)abs(Random() % 100) / 100;
500             }
501         }
502     }
503     if (visibleloading)
504         Game::LoadingScreen();
505
506     for (i = 0; i < size; i++) {
507         for (j = 0; j < size; j++) {
508             if (environment == snowyenvironment) {
509                 heightmap[i][j] -= opacityother[i][j];
510             }
511             if (environment == desertenvironment) {
512                 heightmap[i][j] -= opacityother[i][j];
513             }
514         }
515     }
516     if (visibleloading)
517         Game::LoadingScreen();
518
519     for (i = 0; i < size; i++) {
520         for (j = 0; j < size; j++) {
521             if (opacityother[i][j] < .1)
522                 opacityother[i][j] = 0;
523             if (textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == -1) {
524                 if (!opacityother[i][j])
525                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = allfirst;
526                 if (opacityother[i][j] == 1)
527                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = allsecond;
528             }
529             if (opacityother[i][j] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
530                 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
531             if (opacityother[i][j] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
532                 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
533
534             x = i;
535             y = j;
536             if (i > 0) {
537                 i--;
538                 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
539                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
540                 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
541                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
542                 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
543                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
544                 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
545                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
546
547                 if (j > 0) {
548                     j--;
549                     if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
550                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
551                     if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
552                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
553                     if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
554                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
555                     if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
556                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
557                     j++;
558                 }
559
560                 if (j < size - 1) {
561                     j++;
562                     if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
563                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
564                     if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
565                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
566                     if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
567                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
568                     if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
569                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
570                     j--;
571                 }
572                 i++;
573             }
574
575             if (i < size - 1) {
576                 i++;
577                 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
578                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
579                 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
580                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
581                 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
582                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
583                 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
584                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
585
586                 if (j > 0) {
587                     j--;
588                     if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
589                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
590                     if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
591                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
592                     if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
593                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
594                     if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
595                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
596                     j++;
597                 }
598
599                 if (j < size - 1) {
600                     j++;
601                     if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
602                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
603                     if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
604                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
605                     if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
606                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
607                     if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
608                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
609                     j--;
610                 }
611                 i--;
612             }
613
614             if (j > 0) {
615                 j--;
616                 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
617                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
618                 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
619                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
620                 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
621                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
622                 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
623                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
624                 j++;
625             }
626
627             if (j < size - 1) {
628                 j++;
629                 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
630                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
631                 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
632                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
633                 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
634                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
635                 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
636                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
637                 j--;
638
639             }
640         }
641     }
642     if (visibleloading)
643         Game::LoadingScreen();
644
645     patch_size = size / subdivision;
646     patch_elements = (patch_size) * (patch_size) * 54;
647     CalculateNormals();
648
649     return true;
650 }
651
652 void Terrain::CalculateNormals()
653 {
654     static int i, j;
655     static XYZ facenormal;
656     static XYZ p, q, a, b, c;
657
658     for (i = 0; i < size; i++) {
659         for (j = 0; j < size; j++) {
660             normals[i][j].x = 0;
661             normals[i][j].y = 0;
662             normals[i][j].z = 0;
663         }
664     }
665
666     for (i = 0; i < size - 1; i++) {
667         for (j = 0; j < size - 1; j++) {
668             a.x = i;
669             a.y = heightmap[i][j];
670             a.z = j;
671             b.x = i;
672             b.y = heightmap[i][j + 1];
673             b.z = j + 1;
674             c.x = i + 1;
675             c.y = heightmap[i + 1][j];
676             c.z = j;
677
678             p.x = b.x - a.x;
679             p.y = b.y - a.y;
680             p.z = b.z - a.z;
681             q.x = c.x - a.x;
682             q.y = c.y - a.y;
683             q.z = c.z - a.z;
684
685             CrossProduct(&p, &q, &facenormal);
686
687             facenormals[i][j] = facenormal;
688
689             normals[i][j] = normals[i][j] + facenormal;
690             normals[i][j + 1] = normals[i][j + 1] + facenormal;
691             normals[i + 1][j] = normals[i + 1][j] + facenormal;
692
693
694             a.x = i + 1;
695             a.y = heightmap[i + 1][j];
696             a.z = j;
697             b.x = i;
698             b.y = heightmap[i][j + 1];
699             b.z = j + 1;
700             c.x = i + 1;
701             c.y = heightmap[i + 1][j + 1];
702             c.z = j + 1;
703
704             p.x = b.x - a.x;
705             p.y = b.y - a.y;
706             p.z = b.z - a.z;
707             q.x = c.x - a.x;
708             q.y = c.y - a.y;
709             q.z = c.z - a.z;
710
711             CrossProduct(&p, &q, &facenormal);
712
713             normals[i + 1][j + 1] = normals[i + 1][j + 1] + facenormal;
714             normals[i][j + 1] = normals[i][j + 1] + facenormal;
715             normals[i + 1][j] = normals[i + 1][j] + facenormal;
716
717             Normalise(&facenormals[i][j]);
718         }
719     }
720
721     for (i = 0; i < size; i++) {
722         for (j = 0; j < size; j++) {
723             Normalise(&normals[i][j]);
724         }
725     }
726 }
727
728 void Terrain::drawpatch(int whichx, int whichy, float opacity)
729 {
730     if (opacity >= 1)
731         glDisable(GL_BLEND);
732     if (opacity < 1) {
733         glEnable(GL_BLEND);
734         UpdateTransparency(whichx, whichy);
735     }
736     glColor4f(1, 1, 1, 1);
737     //Set up vertex array
738     glEnableClientState(GL_VERTEX_ARRAY);
739     glEnableClientState(GL_COLOR_ARRAY);
740     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
741     glVertexPointer(3, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[0 + whichx * patch_elements + whichy * patch_elements * subdivision]);
742     glColorPointer(4, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[3 + whichx * patch_elements + whichy * patch_elements * subdivision]);
743     glTexCoordPointer(2, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[7 + whichx * patch_elements + whichy * patch_elements * subdivision]);
744
745     //Draw
746     glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy] * 3);
747
748     glDisableClientState(GL_VERTEX_ARRAY);
749     glDisableClientState(GL_COLOR_ARRAY);
750     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
751 }
752
753 void Terrain::drawpatchother(int whichx, int whichy, float opacity)
754 {
755     glEnable(GL_BLEND);
756     if (opacity < 1) {
757         UpdateTransparency(whichx, whichy);
758     }
759     UpdateTransparencyother(whichx, whichy);
760     glColor4f(1, 1, 1, 1);
761     //Set up vertex array
762     glEnableClientState(GL_VERTEX_ARRAY);
763     glEnableClientState(GL_COLOR_ARRAY);
764     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
765     glVertexPointer(3, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[0 + whichx * patch_elements + whichy * patch_elements * subdivision]);
766     glColorPointer(4, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[3 + whichx * patch_elements + whichy * patch_elements * subdivision]);
767     glTexCoordPointer(2, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[7 + whichx * patch_elements + whichy * patch_elements * subdivision]);
768
769     //Draw
770     glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy] * 3);
771
772     glDisableClientState(GL_VERTEX_ARRAY);
773     glDisableClientState(GL_COLOR_ARRAY);
774     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
775 }
776
777 void Terrain::drawpatchotherother(int whichx, int whichy, float opacity)
778 {
779     glEnable(GL_BLEND);
780     UpdateTransparencyotherother(whichx, whichy);
781
782     glMatrixMode(GL_TEXTURE);
783     glPushMatrix();
784     glScalef(6, 6, 6);
785
786     glColor4f(1, 1, 1, 1);
787
788     //Set up vertex array
789     glEnableClientState(GL_VERTEX_ARRAY);
790     glEnableClientState(GL_COLOR_ARRAY);
791     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
792     glVertexPointer(3, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[0 + whichx * patch_elements + whichy * patch_elements * subdivision]);
793     glColorPointer(4, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[3 + whichx * patch_elements + whichy * patch_elements * subdivision]);
794     glTexCoordPointer(2, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[7 + whichx * patch_elements + whichy * patch_elements * subdivision]);
795
796     //Draw
797     glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy] * 3);
798
799     glDisableClientState(GL_VERTEX_ARRAY);
800     glDisableClientState(GL_COLOR_ARRAY);
801     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
802
803     glPopMatrix();
804     glMatrixMode(GL_MODELVIEW);
805 }
806
807
808 float Terrain::getHeight(float pointx, float pointz)
809 {
810     static int tilex, tiley;
811     static XYZ startpoint, endpoint, intersect, triangle[3];
812
813     pointx /= scale;
814     pointz /= scale;
815
816     if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0)
817         return 0;
818
819     startpoint.x = pointx;
820     startpoint.y = -1000;
821     startpoint.z = pointz;
822
823     endpoint = startpoint;
824     endpoint.y = 1000;
825
826     tilex = pointx;
827     tiley = pointz;
828
829     triangle[0].x = tilex;
830     triangle[0].z = tiley;
831     triangle[0].y = heightmap[tilex][tiley];
832
833     triangle[1].x = tilex + 1;
834     triangle[1].z = tiley;
835     triangle[1].y = heightmap[tilex + 1][tiley];
836
837     triangle[2].x = tilex;
838     triangle[2].z = tiley + 1;
839     triangle[2].y = heightmap[tilex][tiley + 1];
840
841     if (!LineFacetd(&startpoint, &endpoint, &triangle[0], &triangle[1], &triangle[2], &intersect)) {
842         triangle[0].x = tilex + 1;
843         triangle[0].z = tiley;
844         triangle[0].y = heightmap[tilex + 1][tiley];
845
846         triangle[1].x = tilex + 1;
847         triangle[1].z = tiley + 1;
848         triangle[1].y = heightmap[tilex + 1][tiley + 1];
849
850         triangle[2].x = tilex;
851         triangle[2].z = tiley + 1;
852         triangle[2].y = heightmap[tilex][tiley + 1];
853         LineFacetd(&startpoint, &endpoint, &triangle[0], &triangle[1], &triangle[2], &intersect);
854     }
855     return intersect.y * scale + getOpacity(pointx * scale, pointz * scale) / 8;
856 }
857
858 float Terrain::getOpacity(float pointx, float pointz)
859 {
860     static float height1, height2;
861     static int tilex, tiley;
862
863     pointx /= scale;
864     pointz /= scale;
865
866     if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0)
867         return 0;
868
869     tilex = pointx;
870     tiley = pointz;
871
872     height1 = opacityother[tilex][tiley] * (1 - (pointx - tilex)) + opacityother[tilex + 1][tiley] * (pointx - tilex);
873     height2 = opacityother[tilex][tiley + 1] * (1 - (pointx - tilex)) + opacityother[tilex + 1][tiley + 1] * (pointx - tilex);
874
875     return height1 * (1 - (pointz - tiley)) + height2 * (pointz - tiley);
876 }
877
878 XYZ Terrain::getNormal(float pointx, float pointz)
879 {
880     static XYZ height1, height2, total;
881     static int tilex, tiley;
882
883     pointx /= scale;
884     pointz /= scale;
885
886     height1 = 0;
887     if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0)
888         return height1;
889     tilex = pointx;
890     tiley = pointz;
891
892     height1 = normals[tilex][tiley] * (1 - (pointx - tilex)) + normals[tilex + 1][tiley] * (pointx - tilex);
893     height2 = normals[tilex][tiley + 1] * (1 - (pointx - tilex)) + normals[tilex + 1][tiley + 1] * (pointx - tilex);
894     total = height1 * (1 - (pointz - tiley)) + height2 * (pointz - tiley);
895     Normalise(&total);
896     return total;
897 }
898
899 XYZ Terrain::getLighting(float pointx, float pointz)
900 {
901     static XYZ height1, height2;
902     static int tilex, tiley;
903
904     pointx /= scale;
905     pointz /= scale;
906
907     height1 = 0;
908     if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0)
909         return height1;
910     tilex = pointx;
911     tiley = pointz;
912
913     height1.x = colors[tilex][tiley][0] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley][0] * (pointx - tilex);
914     height1.y = colors[tilex][tiley][1] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley][1] * (pointx - tilex);
915     height1.z = colors[tilex][tiley][2] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley][2] * (pointx - tilex);
916     height2.x = colors[tilex][tiley + 1][0] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley + 1][0] * (pointx - tilex);
917     height2.y = colors[tilex][tiley + 1][1] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley + 1][1] * (pointx - tilex);
918     height2.z = colors[tilex][tiley + 1][2] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley + 1][2] * (pointx - tilex);
919
920     return height1 * (1 - (pointz - tiley)) + height2 * (pointz - tiley);
921 }
922
923 void Terrain::draw(int layer)
924 {
925     static int i, j;
926     static float opacity;
927     static XYZ terrainpoint;
928     static float distance[subdivision][subdivision];
929
930     static int beginx, endx;
931     static int beginz, endz;
932
933     static float patch_size = size / subdivision * scale;
934     static float viewdistsquared;
935
936     viewdistsquared = viewdistance * viewdistance;
937
938     //Only nearby blocks
939     beginx = (viewer.x - viewdistance) / (patch_size) - 1;
940     if (beginx < 0)
941         beginx = 0;
942     beginz = (viewer.z - viewdistance) / (patch_size) - 1;
943     if (beginz < 0)
944         beginz = 0;
945
946     endx = (viewer.x + viewdistance) / (patch_size) + 1;
947     if (endx > subdivision)
948         endx = subdivision;
949     endz = (viewer.z + viewdistance) / (patch_size) + 1;
950     if (endz > subdivision)
951         endz = subdivision;
952
953     if (!layer) {
954         for (i = beginx; i < endx; i++) {
955             for (j = beginz; j < endz; j++) {
956                 terrainpoint.x = i * patch_size + (patch_size) / 2;
957                 terrainpoint.y = viewer.y; //heightmap[i][j]*scale;
958                 terrainpoint.z = j * patch_size + (patch_size) / 2;
959                 distance[i][j] = distsq(&viewer, &terrainpoint);
960             }
961         }
962     }
963     for (i = beginx; i < endx; i++) {
964         for (j = beginz; j < endz; j++) {
965             if (distance[i][j] < (viewdistance + patch_size) * (viewdistance + patch_size)) {
966                 opacity = 1;
967                 if (distance[i][j] > viewdistsquared * fadestart - viewdistsquared)
968                     opacity = 0;
969                 if (opacity == 1 && i != subdivision)
970                     if (distance[i + 1][j] > viewdistsquared * fadestart - viewdistsquared)
971                         opacity = 0;
972                 if (opacity == 1 && j != subdivision)
973                     if (distance[i][j + 1] > viewdistsquared * fadestart - viewdistsquared)
974                         opacity = 0;
975                 if (opacity == 1 && j != subdivision && i != subdivision)
976                     if (distance[i + 1][j + 1] > viewdistsquared * fadestart - viewdistsquared)
977                         opacity = 0;
978                 glMatrixMode(GL_MODELVIEW);
979                 glPushMatrix();
980                 if (frustum.CubeInFrustum(i * patch_size + patch_size * .5, avgypatch[i][j], j * patch_size + patch_size * .5, heightypatch[i][j] / 2)) {
981                     if (environment == desertenvironment && distance[i][j] > viewdistsquared / 4)
982                         glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, blurness);
983                     else if (environment == desertenvironment)
984                         glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
985                     if (!layer && textureness[i][j] != allsecond)
986                         drawpatch(i, j, opacity);
987                     if (layer == 1 && textureness[i][j] != allfirst)
988                         drawpatchother(i, j, opacity);
989                     if (layer == 2 && textureness[i][j] != allfirst)
990                         drawpatchotherother(i, j, opacity);
991                 }
992                 glPopMatrix();
993             }
994         }
995     }
996     if (environment == desertenvironment)
997         glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
998 }
999
1000 void Terrain::drawdecals()
1001 {
1002     if (decals) {
1003         static int i;
1004         static float distancemult;
1005         static int lasttype;
1006
1007         static float viewdistsquared;
1008         static bool blend;
1009
1010         viewdistsquared = viewdistance * viewdistance;
1011         blend = 1;
1012
1013         lasttype = -1;
1014         glEnable(GL_BLEND);
1015         glDisable(GL_LIGHTING);
1016         glDisable(GL_CULL_FACE);
1017         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1018         glDepthMask(0);
1019         for (i = 0; i < numdecals; i++) {
1020             if (decaltype[i] == blooddecalfast && decalalivetime[i] < 2)
1021                 decalalivetime[i] = 2;
1022             if ((decaltype[i] == shadowdecal || decaltype[i] == shadowdecalpermanent) && decaltype[i] != lasttype) {
1023                 shadowtexture.bind();
1024                 if (!blend) {
1025                     blend = 1;
1026                     glAlphaFunc(GL_GREATER, 0.0001);
1027                     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1028                 }
1029             }
1030             if (decaltype[i] == footprintdecal && decaltype[i] != lasttype) {
1031                 footprinttexture.bind();
1032                 if (!blend) {
1033                     blend = 1;
1034                     glAlphaFunc(GL_GREATER, 0.0001);
1035                     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1036                 }
1037             }
1038             if (decaltype[i] == bodyprintdecal && decaltype[i] != lasttype) {
1039                 bodyprinttexture.bind();
1040                 if (!blend) {
1041                     blend = 1;
1042                     glAlphaFunc(GL_GREATER, 0.0001);
1043                     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1044                 }
1045             }
1046             if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalslow) && decaltype[i] != lasttype) {
1047                 bloodtexture.bind();
1048                 if (blend) {
1049                     blend = 0;
1050                     glAlphaFunc(GL_GREATER, 0.15);
1051                     glBlendFunc(GL_ONE, GL_ZERO);
1052                 }
1053             }
1054             if ((decaltype[i] == blooddecalfast) && decaltype[i] != lasttype) {
1055                 bloodtexture2.bind();
1056                 if (blend) {
1057                     blend = 0;
1058                     glAlphaFunc(GL_GREATER, 0.15);
1059                     glBlendFunc(GL_ONE, GL_ZERO);
1060                 }
1061             }
1062             if (decaltype[i] == shadowdecal || decaltype[i] == shadowdecalpermanent) {
1063                 distancemult = (viewdistsquared - (distsq(&viewer, &decalposition[i]) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
1064                 if (distancemult >= 1)
1065                     glColor4f(1, 1, 1, decalopacity[i]);
1066                 if (distancemult < 1)
1067                     glColor4f(1, 1, 1, decalopacity[i]*distancemult);
1068             }
1069             if (decaltype[i] == footprintdecal || decaltype[i] == bodyprintdecal) {
1070                 distancemult = (viewdistsquared - (distsq(&viewer, &decalposition[i]) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
1071                 if (distancemult >= 1) {
1072                     glColor4f(1, 1, 1, decalopacity[i]);
1073                     if (decalalivetime[i] > 3)
1074                         glColor4f(1, 1, 1, decalopacity[i] * (5 - decalalivetime[i]) / 2);
1075                 }
1076                 if (distancemult < 1) {
1077                     glColor4f(1, 1, 1, decalopacity[i]*distancemult);
1078                     if (decalalivetime[i] > 3)
1079                         glColor4f(1, 1, 1, decalopacity[i] * (5 - decalalivetime[i]) / 2 * distancemult);
1080                 }
1081             }
1082             if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow)) {
1083                 distancemult = (viewdistsquared - (distsq(&viewer, &decalposition[i]) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
1084                 if (distancemult >= 1) {
1085                     glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i]);
1086                     if (decalalivetime[i] < 4)
1087                         glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i]*decalalivetime[i]*.25);
1088                     if (decalalivetime[i] > 58)
1089                         glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i] * (60 - decalalivetime[i]) / 2);
1090                 }
1091                 if (distancemult < 1) {
1092                     glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i]*distancemult);
1093                     if (decalalivetime[i] < 4)
1094                         glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i]*decalalivetime[i]*distancemult * .25);
1095                     if (decalalivetime[i] > 58)
1096                         glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i] * (60 - decalalivetime[i]) / 2 * distancemult);
1097                 }
1098             }
1099             lasttype = decaltype[i];
1100             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1101             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1102
1103             glMatrixMode(GL_MODELVIEW);
1104             glPushMatrix();
1105             glBegin(GL_TRIANGLES);
1106             for (int j = 0; j < 3; j++) {
1107                 glTexCoord2f(decaltexcoords[i][j][0], decaltexcoords[i][j][1]);
1108                 glVertex3f(decalvertex[i][j].x, decalvertex[i][j].y, decalvertex[i][j].z);
1109             }
1110             glEnd();
1111             glPopMatrix();
1112         }
1113         for (i = numdecals - 1; i >= 0; i--) {
1114             decalalivetime[i] += multiplier;
1115             if (decaltype[i] == blooddecalslow)
1116                 decalalivetime[i] -= multiplier * 2 / 3;
1117             if (decaltype[i] == blooddecalfast)
1118                 decalalivetime[i] += multiplier * 4;
1119             if (decaltype[i] == shadowdecal)
1120                 DeleteDecal(i);
1121             if (decaltype[i] == footprintdecal && decalalivetime[i] >= 5)
1122                 DeleteDecal(i);
1123             if (decaltype[i] == bodyprintdecal && decalalivetime[i] >= 5)
1124                 DeleteDecal(i);
1125             if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow) && decalalivetime[i] >= 60)
1126                 DeleteDecal(i);
1127         }
1128         glAlphaFunc(GL_GREATER, 0.0001);
1129     }
1130 }
1131
1132 void Terrain::AddObject(XYZ where, float radius, int id)
1133 {
1134     bool done;
1135     int i, j;
1136     XYZ points[4];
1137     if (id >= 0 && id < 10000)
1138         for (i = 0; i < subdivision; i++) {
1139             for (j = 0; j < subdivision; j++) {
1140                 if (patchobjectnum[i][j] < 300 - 1) {
1141                     done = 0;
1142                     points[0].x = (size / subdivision) * i;
1143                     points[0].z = (size / subdivision) * j;
1144                     points[0].y = heightmap[(int)points[0].x][(int)points[0].z];
1145                     points[1].x = (size / subdivision) * (i + 1);
1146                     points[1].z = (size / subdivision) * j;
1147                     points[1].y = heightmap[(int)points[1].x][(int)points[1].z];
1148                     points[2].x = (size / subdivision) * (i + 1);
1149                     points[2].z = (size / subdivision) * (j + 1);
1150                     points[2].y = heightmap[(int)points[2].x][(int)points[2].z];
1151                     points[3].x = (size / subdivision) * i;
1152                     points[3].z = (size / subdivision) * (j + 1);
1153                     points[3].y = heightmap[(int)points[3].x][(int)points[3].z];
1154                     points[0] *= scale;
1155                     points[1] *= scale;
1156                     points[2] *= scale;
1157                     points[3] *= scale;
1158                     if (!done && where.x + radius > points[0].x && where.x - radius < points[2].x && where.z + radius > points[0].z && where.z - radius < points[2].z) {
1159                         patchobjects[i][j][patchobjectnum[i][j]] = id;
1160                         patchobjectnum[i][j]++;
1161                         done = 1;
1162                     }
1163                 }
1164             }
1165         }
1166 }
1167
1168 void Terrain::DeleteDecal(int which)
1169 {
1170     if (decals) {
1171         decaltype[which] = decaltype[numdecals - 1];
1172         decalposition[which] = decalposition[numdecals - 1];
1173         for (int i = 0; i < 3; i++) {
1174             decalvertex[which][i] = decalvertex[numdecals - 1][i];
1175             decaltexcoords[which][i][0] = decaltexcoords[numdecals - 1][i][0];
1176             decaltexcoords[which][i][1] = decaltexcoords[numdecals - 1][i][1];
1177         }
1178         decalrotation[which] = decalrotation[numdecals - 1];
1179         decalalivetime[which] = decalalivetime[numdecals - 1];
1180         decalopacity[which] = decalopacity[numdecals - 1];
1181         decalbrightness[which] = decalbrightness[numdecals - 1];
1182         numdecals--;
1183     }
1184 }
1185
1186 void Terrain::MakeDecal(int type, XYZ where, float size, float opacity, float rotation)
1187 {
1188     if (decals) {
1189         if (opacity > 0 && size > 0) {
1190             static int patchx[4];
1191             static int patchy[4];
1192
1193             decaltexcoords[numdecals][0][0] = 1;
1194             decaltexcoords[numdecals][0][1] = 0;
1195
1196             patchx[0] = (where.x + size) / scale;
1197             patchx[1] = (where.x - size) / scale;
1198             patchx[2] = (where.x - size) / scale;
1199             patchx[3] = (where.x + size) / scale;
1200
1201             patchy[0] = (where.z - size) / scale;
1202             patchy[1] = (where.z - size) / scale;
1203             patchy[2] = (where.z + size) / scale;
1204             patchy[3] = (where.z + size) / scale;
1205
1206             if ((patchx[0] != patchx[1] || patchy[0] != patchy[1]) && (patchx[0] != patchx[2] || patchy[0] != patchy[2]) && (patchx[0] != patchx[3] || patchy[0] != patchy[3])) {
1207                 MakeDecalLock(type, where, patchx[0], patchy[0], size, opacity, rotation);
1208             }
1209
1210             if ((patchx[1] != patchx[2] || patchy[1] != patchy[2]) && (patchx[1] != patchx[3] || patchy[1] != patchy[3])) {
1211                 MakeDecalLock(type, where, patchx[1], patchy[1], size, opacity, rotation);
1212             }
1213
1214             if ((patchx[2] != patchx[3] || patchy[2] != patchy[3])) {
1215                 MakeDecalLock(type, where, patchx[2], patchy[2], size, opacity, rotation);
1216             }
1217             MakeDecalLock(type, where, patchx[3], patchy[3], size, opacity, rotation);
1218         }
1219     }
1220     //}
1221 }
1222
1223 void Terrain::MakeDecalLock(int type, XYZ where, int whichx, int whichy, float size, float opacity, float rotation)
1224 {
1225     if (decals) {
1226         static float placex, placez;
1227         static XYZ rot;
1228
1229         float decalbright;
1230
1231         rot = getLighting(where.x, where.z);
1232         decalbrightness[numdecals] = (rot.x + rot.y + rot.z) / 3;
1233         if (decalbrightness[numdecals] < .4)
1234             decalbrightness[numdecals] = .4;
1235
1236         if (environment == grassyenvironment) {
1237             decalbrightness[numdecals] *= .6;
1238         }
1239
1240         if (decalbrightness[numdecals] > 1)
1241             decalbrightness[numdecals] = 1;
1242         decalbright = decalbrightness[numdecals];
1243
1244         decalposition[numdecals] = where;
1245         decaltype[numdecals] = type;
1246         decalopacity[numdecals] = opacity;
1247         decalrotation[numdecals] = rotation;
1248         decalalivetime[numdecals] = 0;
1249
1250         placex = (float)whichx * scale + scale;
1251         placez = (float)whichy * scale;
1252
1253         decaltexcoords[numdecals][0][0] = (placex - where.x) / size / 2 + .5;
1254         decaltexcoords[numdecals][0][1] = (placez - where.z) / size / 2 + .5;
1255
1256         decalvertex[numdecals][0].x = placex;
1257         decalvertex[numdecals][0].z = placez;
1258         decalvertex[numdecals][0].y = heightmap[whichx + 1][whichy] * scale + .01;
1259
1260
1261         placex = (float)whichx * scale + scale;
1262         placez = (float)whichy * scale + scale;
1263
1264         decaltexcoords[numdecals][1][0] = (placex - where.x) / size / 2 + .5;
1265         decaltexcoords[numdecals][1][1] = (placez - where.z) / size / 2 + .5;
1266
1267         decalvertex[numdecals][1].x = placex;
1268         decalvertex[numdecals][1].z = placez;
1269         decalvertex[numdecals][1].y = heightmap[whichx + 1][whichy + 1] * scale + .01;
1270
1271
1272         placex = (float)whichx * scale;
1273         placez = (float)whichy * scale + scale;
1274
1275         decaltexcoords[numdecals][2][0] = (placex - where.x) / size / 2 + .5;
1276         decaltexcoords[numdecals][2][1] = (placez - where.z) / size / 2 + .5;
1277
1278         decalvertex[numdecals][2].x = placex;
1279         decalvertex[numdecals][2].z = placez;
1280         decalvertex[numdecals][2].y = heightmap[whichx][whichy + 1] * scale + .01;
1281
1282         if (decalrotation[numdecals]) {
1283             for (int i = 0; i < 3; i++) {
1284                 rot.y = 0;
1285                 rot.x = decaltexcoords[numdecals][i][0] - .5;
1286                 rot.z = decaltexcoords[numdecals][i][1] - .5;
1287                 rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1288                 decaltexcoords[numdecals][i][0] = rot.x + .5;
1289                 decaltexcoords[numdecals][i][1] = rot.z + .5;
1290             }
1291         }
1292
1293         if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1294             if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1295                 if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1296                     if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1))
1297                         if (numdecals < max_decals - 1)
1298                             numdecals++;
1299
1300         decalbrightness[numdecals] = decalbright;
1301
1302         decalposition[numdecals] = where;
1303         decaltype[numdecals] = type;
1304         decalopacity[numdecals] = opacity;
1305         decalrotation[numdecals] = rotation;
1306         decalalivetime[numdecals] = 0;
1307
1308         placex = (float)whichx * scale + scale;
1309         placez = (float)whichy * scale;
1310
1311         decaltexcoords[numdecals][0][0] = (placex - where.x) / size / 2 + .5;
1312         decaltexcoords[numdecals][0][1] = (placez - where.z) / size / 2 + .5;
1313
1314         decalvertex[numdecals][0].x = placex;
1315         decalvertex[numdecals][0].z = placez;
1316         decalvertex[numdecals][0].y = heightmap[whichx + 1][whichy] * scale + .01;
1317
1318
1319         placex = (float)whichx * scale;
1320         placez = (float)whichy * scale;
1321
1322         decaltexcoords[numdecals][1][0] = (placex - where.x) / size / 2 + .5;
1323         decaltexcoords[numdecals][1][1] = (placez - where.z) / size / 2 + .5;
1324
1325         decalvertex[numdecals][1].x = placex;
1326         decalvertex[numdecals][1].z = placez;
1327         decalvertex[numdecals][1].y = heightmap[whichx][whichy] * scale + .01;
1328
1329
1330         placex = (float)whichx * scale;
1331         placez = (float)whichy * scale + scale;
1332
1333         decaltexcoords[numdecals][2][0] = (placex - where.x) / size / 2 + .5;
1334         decaltexcoords[numdecals][2][1] = (placez - where.z) / size / 2 + .5;
1335
1336         decalvertex[numdecals][2].x = placex;
1337         decalvertex[numdecals][2].z = placez;
1338         decalvertex[numdecals][2].y = heightmap[whichx][whichy + 1] * scale + .01;
1339
1340         if (decalrotation[numdecals]) {
1341             for (int i = 0; i < 3; i++) {
1342                 rot.y = 0;
1343                 rot.x = decaltexcoords[numdecals][i][0] - .5;
1344                 rot.z = decaltexcoords[numdecals][i][1] - .5;
1345                 rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1346                 decaltexcoords[numdecals][i][0] = rot.x + .5;
1347                 decaltexcoords[numdecals][i][1] = rot.z + .5;
1348             }
1349         }
1350
1351         if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1352             if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1353                 if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1354                     if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1))
1355                         if (numdecals < max_decals - 1)
1356                             numdecals++;
1357     }
1358 }
1359
1360 void Terrain::DoShadows()
1361 {
1362     static int i, j, k, l, todivide;
1363     static float brightness, total;
1364     static XYZ testpoint, testpoint2, terrainpoint, lightloc, col;
1365     lightloc = light.location;
1366     if (!skyboxtexture) {
1367         lightloc.x = 0;
1368         lightloc.z = 0;
1369     }
1370     if (skyboxtexture && tutoriallevel) {
1371         lightloc.x *= .4;
1372         lightloc.z *= .4;
1373     }
1374     int patchx, patchz;
1375     float shadowed;
1376     Normalise(&lightloc);
1377     //Calculate shadows
1378     for (i = 0; i < size; i++) {
1379         for (j = 0; j < size; j++) {
1380             terrainpoint.x = (float)(i) * scale;
1381             terrainpoint.z = (float)(j) * scale;
1382             terrainpoint.y = heightmap[i][j] * scale;
1383
1384             shadowed = 0;
1385             patchx = (float)(i) * subdivision / size;
1386             patchz = (float)(j) * subdivision / size;
1387             if (patchobjectnum[patchx][patchz]) {
1388                 for (k = 0; k < patchobjectnum[patchx][patchz]; k++) {
1389                     l = patchobjects[patchx][patchz][k];
1390                     if (objects.type[l] != treetrunktype) {
1391                         testpoint = terrainpoint;
1392                         testpoint2 = terrainpoint + lightloc * 50 * (1 - shadowed);
1393                         if (objects.model[l].LineCheck(&testpoint, &testpoint2, &col, &objects.position[l], &objects.yaw[l]) != -1) {
1394                             shadowed = 1 - (findDistance(&terrainpoint, &col) / 50);
1395                         }
1396                     }
1397                 }
1398                 if (visibleloading)
1399                     Game::LoadingScreen();
1400             }
1401             brightness = dotproduct(&lightloc, &normals[i][j]);
1402             if (shadowed)
1403                 brightness *= 1 - shadowed;
1404
1405             if (brightness > 1)
1406                 brightness = 1;
1407             if (brightness < 0)
1408                 brightness = 0;
1409
1410             colors[i][j][0] = light.color[0] * brightness + light.ambient[0];
1411             colors[i][j][1] = light.color[1] * brightness + light.ambient[1];
1412             colors[i][j][2] = light.color[2] * brightness + light.ambient[2];
1413
1414             if (colors[i][j][0] > 1) colors[i][j][0] = 1;
1415             if (colors[i][j][1] > 1) colors[i][j][1] = 1;
1416             if (colors[i][j][2] > 1) colors[i][j][2] = 1;
1417             if (colors[i][j][0] < 0) colors[i][j][0] = 0;
1418             if (colors[i][j][1] < 0) colors[i][j][1] = 0;
1419             if (colors[i][j][2] < 0) colors[i][j][2] = 0;
1420         }
1421     }
1422
1423     if (visibleloading)
1424         Game::LoadingScreen();
1425
1426     //Smooth shadows
1427     for (i = 0; i < size; i++) {
1428         for (j = 0; j < size; j++) {
1429             for (k = 0; k < 3; k++) {
1430                 total = 0;
1431                 todivide = 0;
1432                 if (i != 0) {
1433                     total += colors[j][i - 1][k];
1434                     todivide++;
1435                 }
1436                 if (i != size - 1) {
1437                     total += colors[j][i + 1][k];
1438                     todivide++;
1439                 }
1440                 if (j != 0) {
1441                     total += colors[j - 1][i][k];
1442                     todivide++;
1443                 }
1444                 if (j != size - 1) {
1445                     total += colors[j + 1][i][k];
1446                     todivide++;
1447                 }
1448                 if (i != 0 && j != 0) {
1449                     total += colors[j - 1][i - 1][k];
1450                     todivide++;
1451                 }
1452                 if (i != size - 1 && j != 0) {
1453                     total += colors[j - 1][i + 1][k];
1454                     todivide++;
1455                 }
1456                 if (j != size - 1 && i != size - 1) {
1457                     total += colors[j + 1][i + 1][k];
1458                     todivide++;
1459                 }
1460                 if (j != size - 1 && i != 0) {
1461                     total += colors[j + 1][i - 1][k];
1462                     todivide++;
1463                 }
1464                 total += colors[j][i][k];
1465                 todivide++;
1466
1467                 colors[j][i][k] = total / todivide;
1468             }
1469         }
1470     }
1471
1472     for (i = 0; i < subdivision; i++) {
1473         for (j = 0; j < subdivision; j++) {
1474             UpdateVertexArray(i, j);
1475         }
1476     }
1477 }
1478
1479 Terrain::Terrain()
1480 {
1481     size = 0;
1482
1483     memset(patchobjectnum, 0, sizeof(patchobjectnum));
1484     memset(patchobjects, 0, sizeof(patchobjects));
1485
1486     scale = 1.0f;
1487     type = 0;
1488     memset(heightmap, 0, sizeof(heightmap));
1489     memset(normals, 0, sizeof(normals));
1490     memset(facenormals, 0, sizeof(facenormals));
1491     memset(triangles, 0, sizeof(triangles));
1492     memset(colors, 0, sizeof(colors));
1493     memset(opacityother, 0, sizeof(opacityother));
1494     memset(texoffsetx, 0, sizeof(texoffsetx));
1495     memset(texoffsety, 0, sizeof(texoffsety));
1496     memset(numtris, 0, sizeof(numtris));
1497     memset(textureness, 0, sizeof(textureness));
1498
1499     memset(vArray, 0, sizeof(vArray));
1500
1501     memset(visible, 0, sizeof(visible));
1502     memset(avgypatch, 0, sizeof(avgypatch));
1503     memset(maxypatch, 0, sizeof(maxypatch));
1504     memset(minypatch, 0, sizeof(minypatch));
1505     memset(heightypatch, 0, sizeof(heightypatch));
1506
1507     patch_elements = 0;
1508
1509     memset(decaltexcoords, 0, sizeof(decaltexcoords));
1510     memset(decalvertex, 0, sizeof(decalvertex));
1511     memset(decaltype, 0, sizeof(decaltype));
1512     memset(decalopacity, 0, sizeof(decalopacity));
1513     memset(decalrotation, 0, sizeof(decalrotation));
1514     memset(decalalivetime, 0, sizeof(decalalivetime));
1515     memset(decalbrightness, 0, sizeof(decalbrightness));
1516     memset(decalposition, 0, sizeof(decalposition));
1517     numdecals = 0;
1518 }
1519 Terrain::~Terrain()
1520 {
1521     terraintexture.destroy();
1522     shadowtexture.destroy();
1523     bodyprinttexture.destroy();
1524     footprinttexture.destroy();
1525     bloodtexture.destroy();
1526     bloodtexture2.destroy();
1527     breaktexture.destroy();
1528 }
1529