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