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