]> git.jsancho.org Git - lugaru.git/blob - Source/Environment/Terrain.cpp
Replaced patchobjects arrays by vectors, cleaned code a bit
[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 #include "Tutorial.hpp"
27
28 extern XYZ viewer;
29 extern float viewdistance;
30 extern float fadestart;
31 extern int environment;
32 extern float texscale;
33 extern Light light;
34 extern float multiplier;
35 extern FRUSTUM frustum;
36 extern float texdetail;
37 extern int detail;
38 extern bool decalstoggle;
39 extern float blurness;
40 extern float targetblurness;
41 extern bool skyboxtexture;
42
43 //Functions
44
45 int Terrain::lineTerrain(XYZ p1, XYZ p2, XYZ *p)
46 {
47     static int i, j, k;
48     static float distance;
49     static float olddistance;
50     static int intersecting;
51     static int firstintersecting;
52     static XYZ point;
53     static int startx, starty;
54     static int endx, endy;
55     static float highest, lowest;
56
57     firstintersecting = -1;
58     olddistance = 10000;
59     distance = 1;
60
61     XYZ triangles[3];
62
63     p1 /= scale;
64     p2 /= scale;
65
66     startx = p1.x;
67     starty = p1.z;
68     endx = p2.x;
69     endy = p2.z;
70
71     if (startx > endx) {
72         i = endx;
73         endx = startx;
74         startx = i;
75     }
76     if (starty > endy) {
77         i = endy;
78         endy = starty;
79         starty = i;
80     }
81
82     if (startx < 0)
83         startx = 0;
84     if (starty < 0)
85         starty = 0;
86     if (endx > size - 1)
87         endx = size - 1;
88     if (endy > size - 1)
89         endy = size - 1;
90
91     for (i = startx; i <= endx; i++) {
92         for (j = starty; j <= endy; j++) {
93             highest = -1000;
94             lowest = 1000;
95             for (k = 0; k < 2; k++) {
96                 if (heightmap[i + k][j] > highest)
97                     highest = heightmap[i + k][j];
98                 if (heightmap[i + k][j] < lowest)
99                     lowest = heightmap[i + k][j];
100                 if (heightmap[i + k][j + 1] > highest)
101                     highest = heightmap[i + k][j + 1];
102                 if (heightmap[i + k][j + 1] < lowest)
103                     lowest = heightmap[i + k][j + 1];
104             }
105             if ((p1.y <= highest || p2.y <= highest) && (p1.y >= lowest || p2.y >= lowest)) {
106                 triangles[0].x = i;
107                 triangles[0].y = heightmap[i][j];
108                 triangles[0].z = j;
109
110                 triangles[1].x = i;
111                 triangles[1].y = heightmap[i][j + 1];
112                 triangles[1].z = j + 1;
113
114                 triangles[2].x = i + 1;
115                 triangles[2].y = heightmap[i + 1][j];
116                 triangles[2].z = j;
117
118                 intersecting = LineFacet(p1, p2, triangles[0], triangles[1], triangles[2], &point);
119                 distance = distsq(&p1, &point);
120                 if ((distance < olddistance || firstintersecting == -1) && intersecting == 1) {
121                     olddistance = distance;
122                     firstintersecting = 1;
123                     *p = point;
124                 }
125
126                 triangles[0].x = i + 1;
127                 triangles[0].y = heightmap[i + 1][j];
128                 triangles[0].z = j;
129
130                 triangles[1].x = i;
131                 triangles[1].y = heightmap[i][j + 1];
132                 triangles[1].z = j + 1;
133
134                 triangles[2].x = i + 1;
135                 triangles[2].y = heightmap[i + 1][j + 1];
136                 triangles[2].z = j + 1;
137
138                 intersecting = LineFacet(p1, p2, triangles[0], triangles[1], triangles[2], &point);
139                 distance = distsq(&p1, &point);
140                 if ((distance < olddistance || firstintersecting == -1) && intersecting == 1) {
141                     olddistance = distance;
142                     firstintersecting = 1;
143                     *p = point;
144                 }
145             }
146         }
147     }
148     return firstintersecting;
149 }
150
151 void Terrain::UpdateTransparency(int whichx, int whichy)
152 {
153     static XYZ vertex;
154     static int i, j, a, b, c, d, patch_size, stepsize;
155     static float distance;
156
157     static float viewdistsquared;
158
159     viewdistsquared = viewdistance * viewdistance;
160     patch_size = size / subdivision;
161
162     stepsize = 1;
163     c = whichx * patch_elements + whichy * patch_elements * subdivision;
164
165     for (i = patch_size * whichx; i < patch_size * (whichx + 1) + 1; i += stepsize) {
166         for (j = patch_size * whichy; j < patch_size * (whichy + 1) + 1; j += stepsize) {
167             if (i < size && j < size) {
168                 vertex.x = i * scale;
169                 vertex.z = j * scale;
170                 vertex.y = heightmap[i][j] * scale;
171                 distance = distsq(&viewer, &vertex);
172                 if (distance > viewdistsquared)
173                     distance = viewdistsquared;
174                 colors[i][j][3] = (viewdistsquared - (distance - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
175             }
176         }
177     }
178
179     for (i = patch_size * whichx; i < patch_size * (whichx + 1); i += stepsize) {
180         for (j = patch_size * whichy; j < patch_size * (whichy + 1); j += stepsize) {
181             a = (i - (patch_size * whichx)) / stepsize;
182             b = (j - (patch_size * whichy)) / stepsize;
183             d = (a * 54) + (b * 54 * patch_size / stepsize);
184             vArray[d + c + 6] = colors[i][j][3];
185
186             vArray[d + c + 15] = colors[i][j + stepsize][3];
187
188             vArray[d + c + 24] = colors[i + stepsize][j][3];
189
190             vArray[d + c + 33] = colors[i + stepsize][j][3];
191
192             vArray[d + c + 42] = colors[i][j + stepsize][3];
193
194             vArray[d + c + 51] = colors[i + stepsize][j + stepsize][3];
195         }
196     }
197 }
198
199 void Terrain::UpdateTransparencyother(int whichx, int whichy)
200 {
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 std::string& fileName)
401 {
402     static long i, j;
403     static long x, y;
404     static float patch_size;
405
406     float temptexdetail = texdetail;
407
408     ImageRec texture;
409
410     //Load Image
411     if (!load_image(Folders::getResourcePath(fileName).c_str(), texture)) {
412         return false;
413     }
414
415     //Is it valid?
416     if (texture.bpp > 24) {
417         int bytesPerPixel = texture.bpp / 8;
418
419         int tempnum = 0;
420         for (i = 0; i < (long)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
421             if ((i + 1) % 4) {
422                 texture.data[tempnum] = texture.data[i];
423                 tempnum++;
424             }
425         }
426     }
427     texture.bpp = 24;
428     Game::LoadingScreen();
429
430     texdetail = temptexdetail;
431
432     size = texture.sizeX;
433
434     for (i = 0; i < size; i++) {
435         for (j = 0; j < size; j++) {
436             heightmap[size - 1 - i][j] = (float)((texture.data[(i + (j * size)) * texture.bpp / 8])) / 5;
437         }
438     }
439
440     Game::LoadingScreen();
441
442     float slopeness;
443
444     for (i = 0; i < subdivision; i++) {
445         for (j = 0; j < subdivision; j++) {
446             textureness[i][j] = -1;
447         }
448     }
449     Game::LoadingScreen();
450
451
452     for (i = 0; i < size; i++) {
453         for (j = 0; j < size; j++) {
454             heightmap[i][j] *= .5;
455
456             texoffsetx[i][j] = (float)abs(Random() % 100) / 1200 / scale * 3;
457             texoffsety[i][j] = (float)abs(Random() % 100) / 1200 / scale * 3;
458
459             slopeness = 0;
460             if (environment == snowyenvironment) {
461                 if (j != 0 && heightmap[i][j] - heightmap[i][j - 1] > slopeness) {
462                     slopeness = heightmap[i][j] - heightmap[i][j - 1];
463                 }
464                 opacityother[i][j] = slopeness * slopeness * 2;
465                 if (opacityother[i][j] > 1)
466                     opacityother[i][j] = 1;
467                 opacityother[i][j] -= (float)abs(Random() % 100) / 300;
468             }
469             if (environment == desertenvironment) {
470                 if (j != 0 && heightmap[i][j] - heightmap[i][j - 1] > slopeness) {
471                     slopeness = heightmap[i][j] - heightmap[i][j - 1];
472                 }
473                 opacityother[i][j] = slopeness * slopeness * 2;
474                 if (opacityother[i][j] > 1)
475                     opacityother[i][j] = 1;
476                 opacityother[i][j] -= (float)abs(Random() % 100) / 300;
477             }
478             if (environment == grassyenvironment) {
479                 if (i != 0 && heightmap[i][j] - heightmap[i - 1][j] > slopeness) {
480                     slopeness = heightmap[i][j] - heightmap[i - 1][j];
481                 }
482                 if (j != 0 && heightmap[i][j] - heightmap[i][j - 1] > slopeness) {
483                     slopeness = heightmap[i][j] - heightmap[i][j - 1];
484                 }
485                 if (i < size - 1 && heightmap[i][j] - heightmap[i + 1][j] > slopeness) {
486                     slopeness = heightmap[i][j] - heightmap[i + 1][j];
487                 }
488                 if (j < size - 1 && heightmap[i][j] - heightmap[i][j + 1] > slopeness) {
489                     slopeness = heightmap[i][j] - heightmap[i][j + 1];
490                 }
491                 opacityother[i][j] = slopeness * slopeness * 10;
492                 if (opacityother[i][j] > 1)
493                     opacityother[i][j] = 1;
494                 opacityother[i][j] -= (float)abs(Random() % 100) / 100;
495             }
496         }
497     }
498     Game::LoadingScreen();
499
500     for (i = 0; i < size; i++) {
501         for (j = 0; j < size; j++) {
502             if (environment == snowyenvironment) {
503                 heightmap[i][j] -= opacityother[i][j];
504             }
505             if (environment == desertenvironment) {
506                 heightmap[i][j] -= opacityother[i][j];
507             }
508         }
509     }
510     Game::LoadingScreen();
511
512     for (i = 0; i < size; i++) {
513         for (j = 0; j < size; j++) {
514             if (opacityother[i][j] < .1)
515                 opacityother[i][j] = 0;
516             if (textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == -1) {
517                 if (!opacityother[i][j])
518                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = allfirst;
519                 if (opacityother[i][j] == 1)
520                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = allsecond;
521             }
522             if (opacityother[i][j] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
523                 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
524             if (opacityother[i][j] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
525                 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
526
527             x = i;
528             y = j;
529             if (i > 0) {
530                 i--;
531                 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
532                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
533                 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
534                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
535                 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
536                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
537                 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
538                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
539
540                 if (j > 0) {
541                     j--;
542                     if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
543                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
544                     if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
545                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
546                     if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
547                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
548                     if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
549                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
550                     j++;
551                 }
552
553                 if (j < size - 1) {
554                     j++;
555                     if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
556                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
557                     if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
558                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
559                     if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
560                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
561                     if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
562                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
563                     j--;
564                 }
565                 i++;
566             }
567
568             if (i < size - 1) {
569                 i++;
570                 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
571                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
572                 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
573                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
574                 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
575                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
576                 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
577                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
578
579                 if (j > 0) {
580                     j--;
581                     if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
582                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
583                     if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
584                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
585                     if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
586                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
587                     if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
588                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
589                     j++;
590                 }
591
592                 if (j < size - 1) {
593                     j++;
594                     if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
595                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
596                     if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
597                         textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
598                     if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
599                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
600                     if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
601                         textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
602                     j--;
603                 }
604                 i--;
605             }
606
607             if (j > 0) {
608                 j--;
609                 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
610                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
611                 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
612                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
613                 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
614                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
615                 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
616                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
617                 j++;
618             }
619
620             if (j < size - 1) {
621                 j++;
622                 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)
623                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
624                 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)
625                     textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
626                 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)
627                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
628                 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)
629                     textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
630                 j--;
631
632             }
633         }
634     }
635     Game::LoadingScreen();
636
637     patch_size = size / subdivision;
638     patch_elements = (patch_size) * (patch_size) * 54;
639     CalculateNormals();
640
641     return true;
642 }
643
644 void Terrain::CalculateNormals()
645 {
646     static int i, j;
647     static XYZ facenormal;
648     static XYZ p, q, a, b, c;
649
650     for (i = 0; i < size; i++) {
651         for (j = 0; j < size; j++) {
652             normals[i][j].x = 0;
653             normals[i][j].y = 0;
654             normals[i][j].z = 0;
655         }
656     }
657
658     for (i = 0; i < size - 1; i++) {
659         for (j = 0; j < size - 1; j++) {
660             a.x = i;
661             a.y = heightmap[i][j];
662             a.z = j;
663             b.x = i;
664             b.y = heightmap[i][j + 1];
665             b.z = j + 1;
666             c.x = i + 1;
667             c.y = heightmap[i + 1][j];
668             c.z = j;
669
670             p.x = b.x - a.x;
671             p.y = b.y - a.y;
672             p.z = b.z - a.z;
673             q.x = c.x - a.x;
674             q.y = c.y - a.y;
675             q.z = c.z - a.z;
676
677             CrossProduct(&p, &q, &facenormal);
678
679             facenormals[i][j] = facenormal;
680
681             normals[i][j] = normals[i][j] + facenormal;
682             normals[i][j + 1] = normals[i][j + 1] + facenormal;
683             normals[i + 1][j] = normals[i + 1][j] + facenormal;
684
685
686             a.x = i + 1;
687             a.y = heightmap[i + 1][j];
688             a.z = j;
689             b.x = i;
690             b.y = heightmap[i][j + 1];
691             b.z = j + 1;
692             c.x = i + 1;
693             c.y = heightmap[i + 1][j + 1];
694             c.z = j + 1;
695
696             p.x = b.x - a.x;
697             p.y = b.y - a.y;
698             p.z = b.z - a.z;
699             q.x = c.x - a.x;
700             q.y = c.y - a.y;
701             q.z = c.z - a.z;
702
703             CrossProduct(&p, &q, &facenormal);
704
705             normals[i + 1][j + 1] = normals[i + 1][j + 1] + facenormal;
706             normals[i][j + 1] = normals[i][j + 1] + facenormal;
707             normals[i + 1][j] = normals[i + 1][j] + facenormal;
708
709             Normalise(&facenormals[i][j]);
710         }
711     }
712
713     for (i = 0; i < size; i++) {
714         for (j = 0; j < size; j++) {
715             Normalise(&normals[i][j]);
716         }
717     }
718 }
719
720 void Terrain::drawpatch(int whichx, int whichy, float opacity)
721 {
722     if (opacity >= 1)
723         glDisable(GL_BLEND);
724     if (opacity < 1) {
725         glEnable(GL_BLEND);
726         UpdateTransparency(whichx, whichy);
727     }
728
729     glColor4f(1, 1, 1, 1);
730
731     //Set up vertex array
732     glEnableClientState(GL_VERTEX_ARRAY);
733     glEnableClientState(GL_COLOR_ARRAY);
734     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
735     glVertexPointer(3, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[0 + whichx * patch_elements + whichy * patch_elements * subdivision]);
736     glColorPointer(4, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[3 + whichx * patch_elements + whichy * patch_elements * subdivision]);
737     glTexCoordPointer(2, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[7 + whichx * patch_elements + whichy * patch_elements * subdivision]);
738
739     //Draw
740     glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy] * 3);
741
742     glDisableClientState(GL_VERTEX_ARRAY);
743     glDisableClientState(GL_COLOR_ARRAY);
744     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
745 }
746
747 void Terrain::drawpatchother(int whichx, int whichy, float opacity)
748 {
749     glEnable(GL_BLEND);
750     if (opacity < 1) {
751         UpdateTransparency(whichx, whichy);
752     }
753     UpdateTransparencyother(whichx, whichy);
754
755     glColor4f(1, 1, 1, 1);
756
757     //Set up vertex array
758     glEnableClientState(GL_VERTEX_ARRAY);
759     glEnableClientState(GL_COLOR_ARRAY);
760     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
761     glVertexPointer(3, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[0 + whichx * patch_elements + whichy * patch_elements * subdivision]);
762     glColorPointer(4, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[3 + whichx * patch_elements + whichy * patch_elements * subdivision]);
763     glTexCoordPointer(2, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[7 + whichx * patch_elements + whichy * patch_elements * subdivision]);
764
765     //Draw
766     glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy] * 3);
767
768     glDisableClientState(GL_VERTEX_ARRAY);
769     glDisableClientState(GL_COLOR_ARRAY);
770     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
771 }
772
773 void Terrain::drawpatchotherother(int whichx, int whichy)
774 {
775     glEnable(GL_BLEND);
776     UpdateTransparencyotherother(whichx, whichy);
777
778     glMatrixMode(GL_TEXTURE);
779     glPushMatrix();
780     glScalef(6, 6, 6);
781
782     glColor4f(1, 1, 1, 1);
783
784     //Set up vertex array
785     glEnableClientState(GL_VERTEX_ARRAY);
786     glEnableClientState(GL_COLOR_ARRAY);
787     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
788     glVertexPointer(3, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[0 + whichx * patch_elements + whichy * patch_elements * subdivision]);
789     glColorPointer(4, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[3 + whichx * patch_elements + whichy * patch_elements * subdivision]);
790     glTexCoordPointer(2, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[7 + whichx * patch_elements + whichy * patch_elements * subdivision]);
791
792     //Draw
793     glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy] * 3);
794
795     glDisableClientState(GL_VERTEX_ARRAY);
796     glDisableClientState(GL_COLOR_ARRAY);
797     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
798
799     glPopMatrix();
800     glMatrixMode(GL_MODELVIEW);
801 }
802
803
804 float Terrain::getHeight(float pointx, float pointz)
805 {
806     static int tilex, tiley;
807     static XYZ startpoint, endpoint, intersect, triangle[3];
808
809     pointx /= scale;
810     pointz /= scale;
811
812     if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0)
813         return 0;
814
815     startpoint.x = pointx;
816     startpoint.y = -1000;
817     startpoint.z = pointz;
818
819     endpoint = startpoint;
820     endpoint.y = 1000;
821
822     tilex = pointx;
823     tiley = pointz;
824
825     triangle[0].x = tilex;
826     triangle[0].z = tiley;
827     triangle[0].y = heightmap[tilex][tiley];
828
829     triangle[1].x = tilex + 1;
830     triangle[1].z = tiley;
831     triangle[1].y = heightmap[tilex + 1][tiley];
832
833     triangle[2].x = tilex;
834     triangle[2].z = tiley + 1;
835     triangle[2].y = heightmap[tilex][tiley + 1];
836
837     if (!LineFacetd(&startpoint, &endpoint, &triangle[0], &triangle[1], &triangle[2], &intersect)) {
838         triangle[0].x = tilex + 1;
839         triangle[0].z = tiley;
840         triangle[0].y = heightmap[tilex + 1][tiley];
841
842         triangle[1].x = tilex + 1;
843         triangle[1].z = tiley + 1;
844         triangle[1].y = heightmap[tilex + 1][tiley + 1];
845
846         triangle[2].x = tilex;
847         triangle[2].z = tiley + 1;
848         triangle[2].y = heightmap[tilex][tiley + 1];
849         LineFacetd(&startpoint, &endpoint, &triangle[0], &triangle[1], &triangle[2], &intersect);
850     }
851     return intersect.y * scale + getOpacity(pointx * scale, pointz * scale) / 8;
852 }
853
854 float Terrain::getOpacity(float pointx, float pointz)
855 {
856     static float height1, height2;
857     static int tilex, tiley;
858
859     pointx /= scale;
860     pointz /= scale;
861
862     if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0)
863         return 0;
864
865     tilex = pointx;
866     tiley = pointz;
867
868     height1 = opacityother[tilex][tiley] * (1 - (pointx - tilex)) + opacityother[tilex + 1][tiley] * (pointx - tilex);
869     height2 = opacityother[tilex][tiley + 1] * (1 - (pointx - tilex)) + opacityother[tilex + 1][tiley + 1] * (pointx - tilex);
870
871     return height1 * (1 - (pointz - tiley)) + height2 * (pointz - tiley);
872 }
873
874 XYZ Terrain::getNormal(float pointx, float pointz)
875 {
876     static XYZ height1, height2, total;
877     static int tilex, tiley;
878
879     pointx /= scale;
880     pointz /= scale;
881
882     height1 = 0;
883     if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0)
884         return height1;
885     tilex = pointx;
886     tiley = pointz;
887
888     height1 = normals[tilex][tiley] * (1 - (pointx - tilex)) + normals[tilex + 1][tiley] * (pointx - tilex);
889     height2 = normals[tilex][tiley + 1] * (1 - (pointx - tilex)) + normals[tilex + 1][tiley + 1] * (pointx - tilex);
890     total = height1 * (1 - (pointz - tiley)) + height2 * (pointz - tiley);
891     Normalise(&total);
892     return total;
893 }
894
895 XYZ Terrain::getLighting(float pointx, float pointz)
896 {
897     static XYZ height1, height2;
898     static int tilex, tiley;
899
900     pointx /= scale;
901     pointz /= scale;
902
903     height1 = 0;
904     if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0)
905         return height1;
906     tilex = pointx;
907     tiley = pointz;
908
909     height1.x = colors[tilex][tiley][0] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley][0] * (pointx - tilex);
910     height1.y = colors[tilex][tiley][1] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley][1] * (pointx - tilex);
911     height1.z = colors[tilex][tiley][2] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley][2] * (pointx - tilex);
912     height2.x = colors[tilex][tiley + 1][0] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley + 1][0] * (pointx - tilex);
913     height2.y = colors[tilex][tiley + 1][1] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley + 1][1] * (pointx - tilex);
914     height2.z = colors[tilex][tiley + 1][2] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley + 1][2] * (pointx - tilex);
915
916     return height1 * (1 - (pointz - tiley)) + height2 * (pointz - tiley);
917 }
918
919 void Terrain::draw(int layer)
920 {
921     static int i, j;
922     static float opacity;
923     static XYZ terrainpoint;
924     static float distance[subdivision][subdivision];
925
926     static int beginx, endx;
927     static int beginz, endz;
928
929     static float patch_size = size / subdivision * scale;
930     static float viewdistsquared;
931
932     viewdistsquared = viewdistance * viewdistance;
933
934     //Only nearby blocks
935     beginx = (viewer.x - viewdistance) / (patch_size) - 1;
936     if (beginx < 0)
937         beginx = 0;
938     beginz = (viewer.z - viewdistance) / (patch_size) - 1;
939     if (beginz < 0)
940         beginz = 0;
941
942     endx = (viewer.x + viewdistance) / (patch_size) + 1;
943     if (endx > subdivision)
944         endx = subdivision;
945     endz = (viewer.z + viewdistance) / (patch_size) + 1;
946     if (endz > subdivision)
947         endz = subdivision;
948
949     if (!layer) {
950         for (i = beginx; i < endx; i++) {
951             for (j = beginz; j < endz; j++) {
952                 terrainpoint.x = i * patch_size + (patch_size) / 2;
953                 terrainpoint.y = viewer.y; //heightmap[i][j]*scale;
954                 terrainpoint.z = j * patch_size + (patch_size) / 2;
955                 distance[i][j] = distsq(&viewer, &terrainpoint);
956             }
957         }
958     }
959     for (i = beginx; i < endx; i++) {
960         for (j = beginz; j < endz; j++) {
961             if (distance[i][j] < (viewdistance + patch_size) * (viewdistance + patch_size)) {
962                 opacity = 1;
963                 if (distance[i][j] > viewdistsquared * fadestart - viewdistsquared)
964                     opacity = 0;
965                 if (opacity == 1 && i != subdivision)
966                     if (distance[i + 1][j] > viewdistsquared * fadestart - viewdistsquared)
967                         opacity = 0;
968                 if (opacity == 1 && j != subdivision)
969                     if (distance[i][j + 1] > viewdistsquared * fadestart - viewdistsquared)
970                         opacity = 0;
971                 if (opacity == 1 && j != subdivision && i != subdivision)
972                     if (distance[i + 1][j + 1] > viewdistsquared * fadestart - viewdistsquared)
973                         opacity = 0;
974                 glMatrixMode(GL_MODELVIEW);
975                 glPushMatrix();
976                 if (frustum.CubeInFrustum(i * patch_size + patch_size * .5, avgypatch[i][j], j * patch_size + patch_size * .5, heightypatch[i][j] / 2)) {
977                     if (environment == desertenvironment && distance[i][j] > viewdistsquared / 4)
978                         glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, blurness);
979                     else if (environment == desertenvironment)
980                         glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
981                     if (!layer && textureness[i][j] != allsecond)
982                         drawpatch(i, j, opacity);
983                     if (layer == 1 && textureness[i][j] != allfirst)
984                         drawpatchother(i, j, opacity);
985                     if (layer == 2 && textureness[i][j] != allfirst)
986                         drawpatchotherother(i, j);
987                 }
988                 glPopMatrix();
989             }
990         }
991     }
992     if (environment == desertenvironment)
993         glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
994 }
995
996 void Terrain::drawdecals()
997 {
998     if (decalstoggle) {
999         static float distancemult;
1000         static int lasttype;
1001
1002         static float viewdistsquared;
1003         static bool blend;
1004
1005         viewdistsquared = viewdistance * viewdistance;
1006         blend = 1;
1007
1008         lasttype = -1;
1009         glEnable(GL_BLEND);
1010         glDisable(GL_LIGHTING);
1011         glDisable(GL_CULL_FACE);
1012         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1013         glDepthMask(0);
1014         for (unsigned int i = 0; i < decals.size(); i++) {
1015             if (decals[i].type == blooddecalfast && decals[i].alivetime < 2)
1016                 decals[i].alivetime = 2;
1017             if (decals[i].type != lasttype) {
1018                 if (decals[i].type == shadowdecal || decals[i].type == shadowdecalpermanent) {
1019                     shadowtexture.bind();
1020                     if (!blend) {
1021                         blend = 1;
1022                         glAlphaFunc(GL_GREATER, 0.0001);
1023                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1024                     }
1025                 }
1026                 if (decals[i].type == footprintdecal) {
1027                     footprinttexture.bind();
1028                     if (!blend) {
1029                         blend = 1;
1030                         glAlphaFunc(GL_GREATER, 0.0001);
1031                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1032                     }
1033                 }
1034                 if (decals[i].type == bodyprintdecal) {
1035                     bodyprinttexture.bind();
1036                     if (!blend) {
1037                         blend = 1;
1038                         glAlphaFunc(GL_GREATER, 0.0001);
1039                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1040                     }
1041                 }
1042                 if (decals[i].type == blooddecal || decals[i].type == blooddecalslow) {
1043                     bloodtexture.bind();
1044                     if (blend) {
1045                         blend = 0;
1046                         glAlphaFunc(GL_GREATER, 0.15);
1047                         glBlendFunc(GL_ONE, GL_ZERO);
1048                     }
1049                 }
1050                 if (decals[i].type == blooddecalfast) {
1051                     bloodtexture2.bind();
1052                     if (blend) {
1053                         blend = 0;
1054                         glAlphaFunc(GL_GREATER, 0.15);
1055                         glBlendFunc(GL_ONE, GL_ZERO);
1056                     }
1057                 }
1058             }
1059             if (decals[i].type == shadowdecal || decals[i].type == shadowdecalpermanent) {
1060                 distancemult = (viewdistsquared - (distsq(&viewer, &decals[i].position) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
1061                 if (distancemult >= 1)
1062                     glColor4f(1, 1, 1, decals[i].opacity);
1063                 if (distancemult < 1)
1064                     glColor4f(1, 1, 1, decals[i].opacity*distancemult);
1065             }
1066             if (decals[i].type == footprintdecal || decals[i].type == bodyprintdecal) {
1067                 distancemult = (viewdistsquared - (distsq(&viewer, &decals[i].position) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
1068                 if (distancemult >= 1) {
1069                     glColor4f(1, 1, 1, decals[i].opacity);
1070                     if (decals[i].alivetime > 3)
1071                         glColor4f(1, 1, 1, decals[i].opacity * (5 - decals[i].alivetime) / 2);
1072                 }
1073                 if (distancemult < 1) {
1074                     glColor4f(1, 1, 1, decals[i].opacity*distancemult);
1075                     if (decals[i].alivetime > 3)
1076                         glColor4f(1, 1, 1, decals[i].opacity * (5 - decals[i].alivetime) / 2 * distancemult);
1077                 }
1078             }
1079             if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow)) {
1080                 distancemult = (viewdistsquared - (distsq(&viewer, &decals[i].position) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
1081                 if (distancemult >= 1) {
1082                     glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity);
1083                     if (decals[i].alivetime < 4)
1084                         glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity*decals[i].alivetime*.25);
1085                     if (decals[i].alivetime > 58)
1086                         glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity * (60 - decals[i].alivetime) / 2);
1087                 }
1088                 if (distancemult < 1) {
1089                     glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity*distancemult);
1090                     if (decals[i].alivetime < 4)
1091                         glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity*decals[i].alivetime*distancemult * .25);
1092                     if (decals[i].alivetime > 58)
1093                         glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity * (60 - decals[i].alivetime) / 2 * distancemult);
1094                 }
1095             }
1096             lasttype = decals[i].type;
1097             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1098             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1099
1100             glMatrixMode(GL_MODELVIEW);
1101             glPushMatrix();
1102             glBegin(GL_TRIANGLES);
1103             for (int j = 0; j < 3; j++) {
1104                 glTexCoord2f(decals[i].texcoords[j][0], decals[i].texcoords[j][1]);
1105                 glVertex3f(decals[i].vertex[j].x, decals[i].vertex[j].y, decals[i].vertex[j].z);
1106             }
1107             glEnd();
1108             glPopMatrix();
1109         }
1110         for (int i = decals.size() - 1; i >= 0; i--) {
1111             decals[i].alivetime += multiplier;
1112             if (decals[i].type == blooddecalslow)
1113                 decals[i].alivetime -= multiplier * 2 / 3;
1114             if (decals[i].type == blooddecalfast)
1115                 decals[i].alivetime += multiplier * 4;
1116             if (decals[i].type == shadowdecal)
1117                 DeleteDecal(i);
1118             if (decals[i].type == footprintdecal && decals[i].alivetime >= 5)
1119                 DeleteDecal(i);
1120             if (decals[i].type == bodyprintdecal && decals[i].alivetime >= 5)
1121                 DeleteDecal(i);
1122             if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow) && decals[i].alivetime >= 60)
1123                 DeleteDecal(i);
1124         }
1125         glAlphaFunc(GL_GREATER, 0.0001);
1126     }
1127 }
1128
1129 void Terrain::deleteDeadDecals()
1130 {
1131     for (int i = decals.size() - 1; i >= 0; i--) {
1132         if ((decals[i].type == blooddecal || decals[i].type == blooddecalslow) && decals[i].alivetime < 2) {
1133             DeleteDecal(i);
1134         }
1135     }
1136 }
1137
1138 void Terrain::AddObject(XYZ where, float radius, int id)
1139 {
1140     XYZ points[2];
1141     if (id >= 0 && id < 10000) {
1142         for (int i = 0; i < subdivision; i++) {
1143             for (int j = 0; j < subdivision; j++) {
1144                 if (patchobjects[i][j].size() < 300 - 1) {
1145                     points[0].x = (size / subdivision) * i;
1146                     points[0].z = (size / subdivision) * j;
1147                     points[0].y = heightmap[(int)points[0].x][(int)points[0].z];
1148                     points[1].x = (size / subdivision) * (i + 1);
1149                     points[1].z = (size / subdivision) * (j + 1);
1150                     points[1].y = heightmap[(int)points[1].x][(int)points[1].z];
1151                     points[0] *= scale;
1152                     points[1] *= scale;
1153                     if (where.x + radius > points[0].x && where.x - radius < points[1].x && where.z + radius > points[0].z && where.z - radius < points[1].z) {
1154                         patchobjects[i][j].push_back(id);
1155                     }
1156                 }
1157             }
1158         }
1159     }
1160 }
1161
1162 void Terrain::DeleteDecal(int which)
1163 {
1164     if (decalstoggle) {
1165         decals.erase(decals.begin() + which);
1166     }
1167 }
1168
1169 void Terrain::MakeDecal(decal_type type, XYZ where, float size, float opacity, float rotation)
1170 {
1171     if (decalstoggle) {
1172         if (opacity > 0 && size > 0) {
1173             static int patchx[4];
1174             static int patchy[4];
1175
1176             patchx[0] = (where.x + size) / scale;
1177             patchx[1] = (where.x - size) / scale;
1178             patchx[2] = (where.x - size) / scale;
1179             patchx[3] = (where.x + size) / scale;
1180
1181             patchy[0] = (where.z - size) / scale;
1182             patchy[1] = (where.z - size) / scale;
1183             patchy[2] = (where.z + size) / scale;
1184             patchy[3] = (where.z + size) / scale;
1185
1186             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])) {
1187                 MakeDecalLock(type, where, patchx[0], patchy[0], size, opacity, rotation);
1188             }
1189
1190             if ((patchx[1] != patchx[2] || patchy[1] != patchy[2]) && (patchx[1] != patchx[3] || patchy[1] != patchy[3])) {
1191                 MakeDecalLock(type, where, patchx[1], patchy[1], size, opacity, rotation);
1192             }
1193
1194             if ((patchx[2] != patchx[3] || patchy[2] != patchy[3])) {
1195                 MakeDecalLock(type, where, patchx[2], patchy[2], size, opacity, rotation);
1196             }
1197
1198             MakeDecalLock(type, where, patchx[3], patchy[3], size, opacity, rotation);
1199         }
1200     }
1201 }
1202
1203 void Terrain::MakeDecalLock(decal_type type, XYZ where, int whichx, int whichy, float size, float opacity, float rotation)
1204 {
1205     if (decalstoggle) {
1206         XYZ rot = getLighting(where.x, where.z);
1207         float decalbright = (rot.x + rot.y + rot.z) / 3;
1208
1209         if (decalbright < .4)
1210             decalbright = .4;
1211
1212         if (environment == grassyenvironment) {
1213             decalbright *= .6;
1214         }
1215
1216         if (decalbright > 1) {
1217             decalbright = 1;
1218         }
1219
1220         Decal decal(where, type, opacity, rotation, decalbright, whichx, whichy, size, *this, true);
1221
1222         if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0))
1223             if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0))
1224                 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1))
1225                     if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1))
1226                         if (decals.size() < max_decals - 1)
1227                             decals.push_back(decal);
1228
1229         Decal decal2(where, type, opacity, rotation, decalbright, whichx, whichy, size, *this, false);
1230
1231         if (!(decal2.texcoords[0][0] < 0 && decal2.texcoords[1][0] < 0 && decal2.texcoords[2][0] < 0))
1232             if (!(decal2.texcoords[0][1] < 0 && decal2.texcoords[1][1] < 0 && decal2.texcoords[2][1] < 0))
1233                 if (!(decal2.texcoords[0][0] > 1 && decal2.texcoords[1][0] > 1 && decal2.texcoords[2][0] > 1))
1234                     if (!(decal2.texcoords[0][1] > 1 && decal2.texcoords[1][1] > 1 && decal2.texcoords[2][1] > 1))
1235                         if (decals.size() < max_decals - 1)
1236                             decals.push_back(decal2);
1237     }
1238 }
1239
1240 void Terrain::DoShadows()
1241 {
1242     static XYZ testpoint, testpoint2, terrainpoint, lightloc, col;
1243     lightloc = light.location;
1244     if (!skyboxtexture) {
1245         lightloc.x = 0;
1246         lightloc.z = 0;
1247     }
1248     if (skyboxtexture && Tutorial::active) {
1249         lightloc.x *= .4;
1250         lightloc.z *= .4;
1251     }
1252     int patchx, patchz;
1253     float shadowed;
1254     Normalise(&lightloc);
1255     //Calculate shadows
1256     for (short int i = 0; i < size; i++) {
1257         for (short int j = 0; j < size; j++) {
1258             terrainpoint.x = (float)(i) * scale;
1259             terrainpoint.z = (float)(j) * scale;
1260             terrainpoint.y = heightmap[i][j] * scale;
1261
1262             shadowed = 0;
1263             patchx = (float)(i) * subdivision / size;
1264             patchz = (float)(j) * subdivision / size;
1265             if (patchobjects[patchx][patchz].size()) {
1266                 for (unsigned int k = 0; k < patchobjects[patchx][patchz].size(); k++) {
1267                     unsigned int l = patchobjects[patchx][patchz][k];
1268                     if (Object::objects[l]->type != treetrunktype) {
1269                         testpoint = terrainpoint;
1270                         testpoint2 = terrainpoint + lightloc * 50 * (1 - shadowed);
1271                         if (Object::objects[l]->model.LineCheck(&testpoint, &testpoint2, &col, &Object::objects[l]->position, &Object::objects[l]->yaw) != -1) {
1272                             shadowed = 1 - (findDistance(&terrainpoint, &col) / 50);
1273                         }
1274                     }
1275                 }
1276                 Game::LoadingScreen();
1277             }
1278             float brightness = dotproduct(&lightloc, &normals[i][j]);
1279             if (shadowed)
1280                 brightness *= 1 - shadowed;
1281
1282             if (brightness > 1)
1283                 brightness = 1;
1284             if (brightness < 0)
1285                 brightness = 0;
1286
1287             colors[i][j][0] = light.color[0] * brightness + light.ambient[0];
1288             colors[i][j][1] = light.color[1] * brightness + light.ambient[1];
1289             colors[i][j][2] = light.color[2] * brightness + light.ambient[2];
1290
1291             if (colors[i][j][0] > 1) colors[i][j][0] = 1;
1292             if (colors[i][j][1] > 1) colors[i][j][1] = 1;
1293             if (colors[i][j][2] > 1) colors[i][j][2] = 1;
1294             if (colors[i][j][0] < 0) colors[i][j][0] = 0;
1295             if (colors[i][j][1] < 0) colors[i][j][1] = 0;
1296             if (colors[i][j][2] < 0) colors[i][j][2] = 0;
1297         }
1298     }
1299
1300     Game::LoadingScreen();
1301
1302     //Smooth shadows
1303     for (short int i = 0; i < size; i++) {
1304         for (short int j = 0; j < size; j++) {
1305             for (short int k = 0; k < 3; k++) {
1306                 float total = 0;
1307                 unsigned int todivide = 0;
1308                 if (i != 0) {
1309                     total += colors[j][i - 1][k];
1310                     todivide++;
1311                 }
1312                 if (i != size - 1) {
1313                     total += colors[j][i + 1][k];
1314                     todivide++;
1315                 }
1316                 if (j != 0) {
1317                     total += colors[j - 1][i][k];
1318                     todivide++;
1319                 }
1320                 if (j != size - 1) {
1321                     total += colors[j + 1][i][k];
1322                     todivide++;
1323                 }
1324                 if (i != 0 && j != 0) {
1325                     total += colors[j - 1][i - 1][k];
1326                     todivide++;
1327                 }
1328                 if (i != size - 1 && j != 0) {
1329                     total += colors[j - 1][i + 1][k];
1330                     todivide++;
1331                 }
1332                 if (j != size - 1 && i != size - 1) {
1333                     total += colors[j + 1][i + 1][k];
1334                     todivide++;
1335                 }
1336                 if (j != size - 1 && i != 0) {
1337                     total += colors[j + 1][i - 1][k];
1338                     todivide++;
1339                 }
1340                 total += colors[j][i][k];
1341                 todivide++;
1342
1343                 colors[j][i][k] = total / todivide;
1344             }
1345         }
1346     }
1347
1348     for (unsigned int i = 0; i < subdivision; i++) {
1349         for (unsigned int j = 0; j < subdivision; j++) {
1350             UpdateVertexArray(i, j);
1351         }
1352     }
1353 }
1354
1355 Terrain::Terrain()
1356 {
1357     size = 0;
1358
1359     scale = 1.0f;
1360     type = 0;
1361     memset(heightmap, 0, sizeof(heightmap));
1362     memset(normals, 0, sizeof(normals));
1363     memset(facenormals, 0, sizeof(facenormals));
1364     memset(triangles, 0, sizeof(triangles));
1365     memset(colors, 0, sizeof(colors));
1366     memset(opacityother, 0, sizeof(opacityother));
1367     memset(texoffsetx, 0, sizeof(texoffsetx));
1368     memset(texoffsety, 0, sizeof(texoffsety));
1369     memset(numtris, 0, sizeof(numtris));
1370     memset(textureness, 0, sizeof(textureness));
1371
1372     memset(vArray, 0, sizeof(vArray));
1373
1374     memset(visible, 0, sizeof(visible));
1375     memset(avgypatch, 0, sizeof(avgypatch));
1376     memset(maxypatch, 0, sizeof(maxypatch));
1377     memset(minypatch, 0, sizeof(minypatch));
1378     memset(heightypatch, 0, sizeof(heightypatch));
1379
1380     patch_elements = 0;
1381 }