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