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