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