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