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