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