2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 #include "Environment/Terrain.hpp"
24 #include "Objects/Object.hpp"
25 #include "Tutorial.hpp"
26 #include "Utils/Folders.hpp"
29 extern float viewdistance;
30 extern float fadestart;
31 extern int environment;
32 extern float texscale;
34 extern float multiplier;
35 extern FRUSTUM frustum;
36 extern float texdetail;
38 extern bool decalstoggle;
39 extern float blurness;
40 extern float targetblurness;
41 extern bool skyboxtexture;
45 int Terrain::lineTerrain(XYZ p1, XYZ p2, XYZ* p)
48 static float distance;
49 static float olddistance;
50 static int intersecting;
51 static int firstintersecting;
53 static int startx, starty;
54 static int endx, endy;
55 static float highest, lowest;
57 firstintersecting = -1;
88 if (endx > size - 1) {
91 if (endy > size - 1) {
95 for (i = startx; i <= endx; i++) {
96 for (j = starty; j <= endy; j++) {
99 for (k = 0; k < 2; k++) {
100 if (heightmap[i + k][j] > highest) {
101 highest = heightmap[i + k][j];
103 if (heightmap[i + k][j] < lowest) {
104 lowest = heightmap[i + k][j];
106 if (heightmap[i + k][j + 1] > highest) {
107 highest = heightmap[i + k][j + 1];
109 if (heightmap[i + k][j + 1] < lowest) {
110 lowest = heightmap[i + k][j + 1];
113 if ((p1.y <= highest || p2.y <= highest) && (p1.y >= lowest || p2.y >= lowest)) {
115 triangles[0].y = heightmap[i][j];
119 triangles[1].y = heightmap[i][j + 1];
120 triangles[1].z = j + 1;
122 triangles[2].x = i + 1;
123 triangles[2].y = heightmap[i + 1][j];
126 intersecting = LineFacet(p1, p2, triangles[0], triangles[1], triangles[2], &point);
127 distance = distsq(&p1, &point);
128 if ((distance < olddistance || firstintersecting == -1) && intersecting == 1) {
129 olddistance = distance;
130 firstintersecting = 1;
134 triangles[0].x = i + 1;
135 triangles[0].y = heightmap[i + 1][j];
139 triangles[1].y = heightmap[i][j + 1];
140 triangles[1].z = j + 1;
142 triangles[2].x = i + 1;
143 triangles[2].y = heightmap[i + 1][j + 1];
144 triangles[2].z = j + 1;
146 intersecting = LineFacet(p1, p2, triangles[0], triangles[1], triangles[2], &point);
147 distance = distsq(&p1, &point);
148 if ((distance < olddistance || firstintersecting == -1) && intersecting == 1) {
149 olddistance = distance;
150 firstintersecting = 1;
156 return firstintersecting;
159 void Terrain::UpdateTransparency(int whichx, int whichy)
162 static int i, j, a, b, c, d, patch_size, stepsize;
163 static float distance;
165 static float viewdistsquared;
167 viewdistsquared = viewdistance * viewdistance;
168 patch_size = size / subdivision;
171 c = whichx * patch_elements + whichy * patch_elements * subdivision;
173 for (i = patch_size * whichx; i < patch_size * (whichx + 1) + 1; i += stepsize) {
174 for (j = patch_size * whichy; j < patch_size * (whichy + 1) + 1; j += stepsize) {
175 if (i < size && j < size) {
176 vertex.x = i * scale;
177 vertex.z = j * scale;
178 vertex.y = heightmap[i][j] * scale;
179 distance = distsq(&viewer, &vertex);
180 if (distance > viewdistsquared) {
181 distance = viewdistsquared;
183 colors[i][j][3] = (viewdistsquared - (distance - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
188 for (i = patch_size * whichx; i < patch_size * (whichx + 1); i += stepsize) {
189 for (j = patch_size * whichy; j < patch_size * (whichy + 1); j += stepsize) {
190 a = (i - (patch_size * whichx)) / stepsize;
191 b = (j - (patch_size * whichy)) / stepsize;
192 d = (a * 54) + (b * 54 * patch_size / stepsize);
193 vArray[d + c + 6] = colors[i][j][3];
195 vArray[d + c + 15] = colors[i][j + stepsize][3];
197 vArray[d + c + 24] = colors[i + stepsize][j][3];
199 vArray[d + c + 33] = colors[i + stepsize][j][3];
201 vArray[d + c + 42] = colors[i][j + stepsize][3];
203 vArray[d + c + 51] = colors[i + stepsize][j + stepsize][3];
208 void Terrain::UpdateTransparencyother(int whichx, int whichy)
210 static int i, j, a, b, c, d, patch_size, stepsize;
212 patch_size = size / subdivision;
215 c = whichx * patch_elements + whichy * patch_elements * subdivision;
217 for (i = patch_size * whichx; i < patch_size * (whichx + 1); i += stepsize) {
218 for (j = patch_size * whichy; j < patch_size * (whichy + 1); j += stepsize) {
219 a = (i - (patch_size * whichx)) / stepsize;
220 b = (j - (patch_size * whichy)) / stepsize;
221 d = (a * 54) + (b * 54 * patch_size / stepsize);
222 vArray[d + c + 6] = colors[i][j][3] * opacityother[i][j];
224 vArray[d + c + 15] = colors[i][j + stepsize][3] * opacityother[i][j + stepsize];
226 vArray[d + c + 24] = colors[i + stepsize][j][3] * opacityother[i + stepsize][j];
228 vArray[d + c + 33] = colors[i + stepsize][j][3] * opacityother[i + stepsize][j];
230 vArray[d + c + 42] = colors[i][j + stepsize][3] * opacityother[i][j + stepsize];
232 vArray[d + c + 51] = colors[i + stepsize][j + stepsize][3] * opacityother[i + stepsize][j + stepsize];
237 void Terrain::UpdateTransparencyotherother(int whichx, int whichy)
240 static int i, j, a, b, c, d, patch_size, stepsize;
241 static float distance;
243 static float viewdistsquared;
245 viewdistsquared = viewdistance * viewdistance;
246 patch_size = size / subdivision;
249 c = whichx * patch_elements + whichy * patch_elements * subdivision;
251 for (i = patch_size * whichx; i < patch_size * (whichx + 1) + 1; i += stepsize) {
252 for (j = patch_size * whichy; j < patch_size * (whichy + 1) + 1; j += stepsize) {
253 if (i < size && j < size) {
254 vertex.x = i * scale;
255 vertex.z = j * scale;
256 vertex.y = heightmap[i][j] * scale;
257 distance = distsq(&viewer, &vertex);
258 if (distance > viewdistsquared) {
259 distance = viewdistsquared;
261 colors[i][j][3] = (viewdistsquared - (distance - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
266 for (i = patch_size * whichx; i < patch_size * (whichx + 1); i += stepsize) {
267 for (j = patch_size * whichy; j < patch_size * (whichy + 1); j += stepsize) {
268 a = (i - (patch_size * whichx)) / stepsize;
269 b = (j - (patch_size * whichy)) / stepsize;
270 d = (a * 54) + (b * 54 * patch_size / stepsize);
271 vArray[d + c + 6] = colors[i][j][3];
273 vArray[d + c + 15] = colors[i][j + stepsize][3];
275 vArray[d + c + 24] = colors[i + stepsize][j][3];
277 vArray[d + c + 33] = colors[i + stepsize][j][3];
279 vArray[d + c + 42] = colors[i][j + stepsize][3];
281 vArray[d + c + 51] = colors[i + stepsize][j + stepsize][3];
286 void Terrain::UpdateVertexArray(int whichx, int whichy)
288 static int i, j, a, b, c, patch_size, stepsize;
290 numtris[whichx][whichy] = 0;
292 patch_size = size / subdivision;
295 c = whichx * patch_elements + whichy * patch_elements * subdivision;
296 for (i = patch_size * whichx; i < patch_size * (whichx + 1); i += stepsize) {
297 for (j = patch_size * whichy; j < patch_size * (whichy + 1); j += stepsize) {
298 a = (i - ((float)size / subdivision * (float)whichx)) / stepsize;
299 b = (j - ((float)size / subdivision * (float)whichy)) / stepsize;
300 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 0] = i * scale;
301 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 1] = heightmap[i][j] * scale;
302 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 2] = j * scale;
303 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 3] = colors[i][j][0];
304 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 4] = colors[i][j][1];
305 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 5] = colors[i][j][2];
306 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 6] = colors[i][j][3];
307 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 7] = i * scale * texscale + texoffsetx[i][j];
308 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 8] = j * scale * texscale + texoffsety[i][j];
310 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 9] = i * scale;
311 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 10] = heightmap[i][j + stepsize] * scale;
312 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 11] = j * scale + stepsize * scale;
313 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 12] = colors[i][j + stepsize][0];
314 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 13] = colors[i][j + stepsize][1];
315 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 14] = colors[i][j + stepsize][2];
316 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 15] = colors[i][j + stepsize][3];
317 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 16] = i * scale * texscale + texoffsetx[i][j + stepsize];
318 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 17] = j * scale * texscale + stepsize * scale * texscale + texoffsety[i][j + stepsize];
320 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 18] = i * scale + stepsize * scale;
321 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 19] = heightmap[i + stepsize][j] * scale;
322 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 20] = j * scale;
323 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 21] = colors[i + stepsize][j][0];
324 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 22] = colors[i + stepsize][j][1];
325 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 23] = colors[i + stepsize][j][2];
326 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 24] = colors[i + stepsize][j][3];
327 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 25] = i * scale * texscale + stepsize * scale * texscale + texoffsetx[i + stepsize][j];
328 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 26] = j * scale * texscale + texoffsety[i + stepsize][j];
330 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 27] = i * scale + stepsize * scale;
331 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 28] = heightmap[i + stepsize][j] * scale;
332 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 29] = j * scale;
333 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 30] = colors[i + stepsize][j][0];
334 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 31] = colors[i + stepsize][j][1];
335 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 32] = colors[i + stepsize][j][2];
336 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 33] = colors[i + stepsize][j][3];
337 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 34] = i * scale * texscale + stepsize * scale * texscale + texoffsetx[i + stepsize][j];
338 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 35] = j * scale * texscale + texoffsety[i + stepsize][j];
340 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 36] = i * scale;
341 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 37] = heightmap[i][j + stepsize] * scale;
342 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 38] = j * scale + stepsize * scale;
343 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 39] = colors[i][j + stepsize][0];
344 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 40] = colors[i][j + stepsize][1];
345 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 41] = colors[i][j + stepsize][2];
346 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 42] = colors[i][j + stepsize][3];
347 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 43] = i * scale * texscale + texoffsetx[i][j + stepsize];
348 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 44] = j * scale * texscale + stepsize * scale * texscale + texoffsety[i][j + stepsize];
350 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 45] = i * scale + stepsize * scale;
351 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 46] = heightmap[i + stepsize][j + stepsize] * scale;
352 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 47] = j * scale + stepsize * scale;
353 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 48] = colors[i + stepsize][j + stepsize][0];
354 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 49] = colors[i + stepsize][j + stepsize][1];
355 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 50] = colors[i + stepsize][j + stepsize][2];
356 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 51] = colors[i + stepsize][j + stepsize][3];
357 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 52] = i * scale * texscale + stepsize * scale * texscale + texoffsetx[i + stepsize][j + stepsize];
358 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 53] = j * scale * texscale + stepsize * scale * texscale + texoffsety[i + stepsize][j + stepsize];
359 numtris[whichx][whichy] += 2;
363 maxypatch[whichx][whichy] = -10000;
364 minypatch[whichx][whichy] = 10000;
365 for (a = 0; a < size / subdivision; a++) {
366 for (b = 0; b < size / subdivision; b++) {
367 if (heightmap[(size / subdivision) * whichx + a][(size / subdivision) * whichy + b] * scale > maxypatch[whichx][whichy]) {
368 maxypatch[whichx][whichy] = heightmap[(size / subdivision) * whichx + a][(size / subdivision) * whichy + b] * scale;
370 if (heightmap[(size / subdivision) * whichx + a][(size / subdivision) * whichy + b] * scale < minypatch[whichx][whichy]) {
371 minypatch[whichx][whichy] = heightmap[(size / subdivision) * whichx + a][(size / subdivision) * whichy + b] * scale;
375 heightypatch[whichx][whichy] = (maxypatch[whichx][whichy] - minypatch[whichx][whichy]);
376 if (heightypatch[whichx][whichy] < size / subdivision * scale) {
377 heightypatch[whichx][whichy] = size / subdivision * scale;
379 avgypatch[whichx][whichy] = (minypatch[whichx][whichy] + maxypatch[whichx][whichy]) / 2;
381 for (i = whichx * size / subdivision; i < (whichx + 1) * size / subdivision - 1; i++) {
382 for (j = whichy * size / subdivision; j < (whichy + 1) * size / subdivision - 1; j++) {
383 triangles[(i * (size - 1) * 2) + (j * 2)][0].x = i * scale;
384 triangles[(i * (size - 1) * 2) + (j * 2)][0].y = heightmap[i][j] * scale;
385 triangles[(i * (size - 1) * 2) + (j * 2)][0].z = j * scale;
387 triangles[(i * (size - 1) * 2) + (j * 2)][1].x = i * scale;
388 triangles[(i * (size - 1) * 2) + (j * 2)][1].y = heightmap[i][j + 1] * scale;
389 triangles[(i * (size - 1) * 2) + (j * 2)][1].z = j * scale + scale;
391 triangles[(i * (size - 1) * 2) + (j * 2)][2].x = i * scale + 1 * scale;
392 triangles[(i * (size - 1) * 2) + (j * 2)][2].y = heightmap[i + 1][j] * scale;
393 triangles[(i * (size - 1) * 2) + (j * 2)][2].z = j * scale;
395 triangles[(i * (size - 1) * 2) + (j * 2) + 1][0].x = i * scale + 1 * scale;
396 triangles[(i * (size - 1) * 2) + (j * 2) + 1][0].y = heightmap[i + 1][j] * scale;
397 triangles[(i * (size - 1) * 2) + (j * 2) + 1][0].z = j * scale;
399 triangles[(i * (size - 1) * 2) + (j * 2) + 1][1].x = i * scale;
400 triangles[(i * (size - 1) * 2) + (j * 2) + 1][1].y = heightmap[i][j + 1] * scale;
401 triangles[(i * (size - 1) * 2) + (j * 2) + 1][1].z = j * scale + 1 * scale;
403 triangles[(i * (size - 1) * 2) + (j * 2) + 1][2].x = i * scale + 1 * scale;
404 triangles[(i * (size - 1) * 2) + (j * 2) + 1][2].y = heightmap[i + 1][j + 1] * scale;
405 triangles[(i * (size - 1) * 2) + (j * 2) + 1][2].z = j * scale + 1 * scale;
410 bool Terrain::load(const std::string& fileName)
414 static float patch_size;
416 float temptexdetail = texdetail;
421 if (!load_image(Folders::getResourcePath(fileName).c_str(), texture)) {
426 if (texture.bpp > 24) {
427 int bytesPerPixel = texture.bpp / 8;
430 for (i = 0; i < (long)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
432 texture.data[tempnum] = texture.data[i];
438 Game::LoadingScreen();
440 texdetail = temptexdetail;
442 size = texture.sizeX;
444 for (i = 0; i < size; i++) {
445 for (j = 0; j < size; j++) {
446 heightmap[size - 1 - i][j] = (float)((texture.data[(i + (j * size)) * texture.bpp / 8])) / 5;
450 Game::LoadingScreen();
454 for (i = 0; i < subdivision; i++) {
455 for (j = 0; j < subdivision; j++) {
456 textureness[i][j] = -1;
459 Game::LoadingScreen();
461 for (i = 0; i < size; i++) {
462 for (j = 0; j < size; j++) {
463 heightmap[i][j] *= .5;
465 texoffsetx[i][j] = (float)abs(Random() % 100) / 1200 / scale * 3;
466 texoffsety[i][j] = (float)abs(Random() % 100) / 1200 / scale * 3;
469 if (environment == snowyenvironment) {
470 if (j != 0 && heightmap[i][j] - heightmap[i][j - 1] > slopeness) {
471 slopeness = heightmap[i][j] - heightmap[i][j - 1];
473 opacityother[i][j] = slopeness * slopeness * 2;
474 if (opacityother[i][j] > 1) {
475 opacityother[i][j] = 1;
477 opacityother[i][j] -= (float)abs(Random() % 100) / 300;
479 if (environment == desertenvironment) {
480 if (j != 0 && heightmap[i][j] - heightmap[i][j - 1] > slopeness) {
481 slopeness = heightmap[i][j] - heightmap[i][j - 1];
483 opacityother[i][j] = slopeness * slopeness * 2;
484 if (opacityother[i][j] > 1) {
485 opacityother[i][j] = 1;
487 opacityother[i][j] -= (float)abs(Random() % 100) / 300;
489 if (environment == grassyenvironment) {
490 if (i != 0 && heightmap[i][j] - heightmap[i - 1][j] > slopeness) {
491 slopeness = heightmap[i][j] - heightmap[i - 1][j];
493 if (j != 0 && heightmap[i][j] - heightmap[i][j - 1] > slopeness) {
494 slopeness = heightmap[i][j] - heightmap[i][j - 1];
496 if (i < size - 1 && heightmap[i][j] - heightmap[i + 1][j] > slopeness) {
497 slopeness = heightmap[i][j] - heightmap[i + 1][j];
499 if (j < size - 1 && heightmap[i][j] - heightmap[i][j + 1] > slopeness) {
500 slopeness = heightmap[i][j] - heightmap[i][j + 1];
502 opacityother[i][j] = slopeness * slopeness * 10;
503 if (opacityother[i][j] > 1) {
504 opacityother[i][j] = 1;
506 opacityother[i][j] -= (float)abs(Random() % 100) / 100;
510 Game::LoadingScreen();
512 for (i = 0; i < size; i++) {
513 for (j = 0; j < size; j++) {
514 if (environment == snowyenvironment) {
515 heightmap[i][j] -= opacityother[i][j];
517 if (environment == desertenvironment) {
518 heightmap[i][j] -= opacityother[i][j];
522 Game::LoadingScreen();
524 for (i = 0; i < size; i++) {
525 for (j = 0; j < size; j++) {
526 if (opacityother[i][j] < .1) {
527 opacityother[i][j] = 0;
529 if (textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == -1) {
530 if (!opacityother[i][j]) {
531 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = allfirst;
533 if (opacityother[i][j] == 1) {
534 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = allsecond;
537 if (opacityother[i][j] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst) {
538 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
540 if (opacityother[i][j] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond) {
541 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
548 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst) {
549 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
551 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond) {
552 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
554 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst) {
555 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
557 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond) {
558 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
563 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst) {
564 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
566 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond) {
567 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
569 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst) {
570 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
572 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond) {
573 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
580 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst) {
581 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
583 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond) {
584 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
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;
589 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond) {
590 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
599 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst) {
600 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
602 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond) {
603 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
605 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst) {
606 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
608 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond) {
609 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
614 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst) {
615 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
617 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond) {
618 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
620 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst) {
621 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
623 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond) {
624 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
631 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst) {
632 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
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;
637 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst) {
638 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
640 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond) {
641 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
650 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst) {
651 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
653 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond) {
654 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
656 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst) {
657 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
659 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond) {
660 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
667 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst) {
668 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
670 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond) {
671 textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
673 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst) {
674 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
676 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond) {
677 textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
683 Game::LoadingScreen();
685 patch_size = size / subdivision;
686 patch_elements = patch_size * patch_size * 54;
692 void Terrain::CalculateNormals()
695 static XYZ facenormal;
696 static XYZ p, q, a, b, c;
698 for (i = 0; i < size; i++) {
699 for (j = 0; j < size; j++) {
706 for (i = 0; i < size - 1; i++) {
707 for (j = 0; j < size - 1; j++) {
709 a.y = heightmap[i][j];
712 b.y = heightmap[i][j + 1];
715 c.y = heightmap[i + 1][j];
725 CrossProduct(&p, &q, &facenormal);
727 facenormals[i][j] = facenormal;
729 normals[i][j] = normals[i][j] + facenormal;
730 normals[i][j + 1] = normals[i][j + 1] + facenormal;
731 normals[i + 1][j] = normals[i + 1][j] + facenormal;
734 a.y = heightmap[i + 1][j];
737 b.y = heightmap[i][j + 1];
740 c.y = heightmap[i + 1][j + 1];
750 CrossProduct(&p, &q, &facenormal);
752 normals[i + 1][j + 1] = normals[i + 1][j + 1] + facenormal;
753 normals[i][j + 1] = normals[i][j + 1] + facenormal;
754 normals[i + 1][j] = normals[i + 1][j] + facenormal;
756 Normalise(&facenormals[i][j]);
760 for (i = 0; i < size; i++) {
761 for (j = 0; j < size; j++) {
762 Normalise(&normals[i][j]);
767 void Terrain::drawpatch(int whichx, int whichy, float opacity)
774 UpdateTransparency(whichx, whichy);
777 glColor4f(1, 1, 1, 1);
779 //Set up vertex array
780 glEnableClientState(GL_VERTEX_ARRAY);
781 glEnableClientState(GL_COLOR_ARRAY);
782 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
783 glVertexPointer(3, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[0 + whichx * patch_elements + whichy * patch_elements * subdivision]);
784 glColorPointer(4, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[3 + whichx * patch_elements + whichy * patch_elements * subdivision]);
785 glTexCoordPointer(2, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[7 + whichx * patch_elements + whichy * patch_elements * subdivision]);
788 glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy] * 3);
790 glDisableClientState(GL_VERTEX_ARRAY);
791 glDisableClientState(GL_COLOR_ARRAY);
792 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
795 void Terrain::drawpatchother(int whichx, int whichy, float opacity)
799 UpdateTransparency(whichx, whichy);
801 UpdateTransparencyother(whichx, whichy);
803 glColor4f(1, 1, 1, 1);
805 //Set up vertex array
806 glEnableClientState(GL_VERTEX_ARRAY);
807 glEnableClientState(GL_COLOR_ARRAY);
808 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
809 glVertexPointer(3, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[0 + whichx * patch_elements + whichy * patch_elements * subdivision]);
810 glColorPointer(4, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[3 + whichx * patch_elements + whichy * patch_elements * subdivision]);
811 glTexCoordPointer(2, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[7 + whichx * patch_elements + whichy * patch_elements * subdivision]);
814 glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy] * 3);
816 glDisableClientState(GL_VERTEX_ARRAY);
817 glDisableClientState(GL_COLOR_ARRAY);
818 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
821 void Terrain::drawpatchotherother(int whichx, int whichy)
824 UpdateTransparencyotherother(whichx, whichy);
826 glMatrixMode(GL_TEXTURE);
830 glColor4f(1, 1, 1, 1);
832 //Set up vertex array
833 glEnableClientState(GL_VERTEX_ARRAY);
834 glEnableClientState(GL_COLOR_ARRAY);
835 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
836 glVertexPointer(3, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[0 + whichx * patch_elements + whichy * patch_elements * subdivision]);
837 glColorPointer(4, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[3 + whichx * patch_elements + whichy * patch_elements * subdivision]);
838 glTexCoordPointer(2, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[7 + whichx * patch_elements + whichy * patch_elements * subdivision]);
841 glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy] * 3);
843 glDisableClientState(GL_VERTEX_ARRAY);
844 glDisableClientState(GL_COLOR_ARRAY);
845 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
848 glMatrixMode(GL_MODELVIEW);
851 float Terrain::getHeight(float pointx, float pointz)
853 static int tilex, tiley;
854 static XYZ startpoint, endpoint, intersect, triangle[3];
859 if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0) {
863 startpoint.x = pointx;
864 startpoint.y = -1000;
865 startpoint.z = pointz;
867 endpoint = startpoint;
873 triangle[0].x = tilex;
874 triangle[0].z = tiley;
875 triangle[0].y = heightmap[tilex][tiley];
877 triangle[1].x = tilex + 1;
878 triangle[1].z = tiley;
879 triangle[1].y = heightmap[tilex + 1][tiley];
881 triangle[2].x = tilex;
882 triangle[2].z = tiley + 1;
883 triangle[2].y = heightmap[tilex][tiley + 1];
885 if (!LineFacetd(&startpoint, &endpoint, &triangle[0], &triangle[1], &triangle[2], &intersect)) {
886 triangle[0].x = tilex + 1;
887 triangle[0].z = tiley;
888 triangle[0].y = heightmap[tilex + 1][tiley];
890 triangle[1].x = tilex + 1;
891 triangle[1].z = tiley + 1;
892 triangle[1].y = heightmap[tilex + 1][tiley + 1];
894 triangle[2].x = tilex;
895 triangle[2].z = tiley + 1;
896 triangle[2].y = heightmap[tilex][tiley + 1];
897 LineFacetd(&startpoint, &endpoint, &triangle[0], &triangle[1], &triangle[2], &intersect);
899 return intersect.y * scale + getOpacity(pointx * scale, pointz * scale) / 8;
902 float Terrain::getOpacity(float pointx, float pointz)
904 static float height1, height2;
905 static int tilex, tiley;
910 if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0) {
917 height1 = opacityother[tilex][tiley] * (1 - (pointx - tilex)) + opacityother[tilex + 1][tiley] * (pointx - tilex);
918 height2 = opacityother[tilex][tiley + 1] * (1 - (pointx - tilex)) + opacityother[tilex + 1][tiley + 1] * (pointx - tilex);
920 return height1 * (1 - (pointz - tiley)) + height2 * (pointz - tiley);
923 XYZ Terrain::getNormal(float pointx, float pointz)
925 static XYZ height1, height2, total;
926 static int tilex, tiley;
932 if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0) {
938 height1 = normals[tilex][tiley] * (1 - (pointx - tilex)) + normals[tilex + 1][tiley] * (pointx - tilex);
939 height2 = normals[tilex][tiley + 1] * (1 - (pointx - tilex)) + normals[tilex + 1][tiley + 1] * (pointx - tilex);
940 total = height1 * (1 - (pointz - tiley)) + height2 * (pointz - tiley);
945 XYZ Terrain::getLighting(float pointx, float pointz)
947 static XYZ height1, height2;
948 static int tilex, tiley;
954 if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0) {
960 height1.x = colors[tilex][tiley][0] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley][0] * (pointx - tilex);
961 height1.y = colors[tilex][tiley][1] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley][1] * (pointx - tilex);
962 height1.z = colors[tilex][tiley][2] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley][2] * (pointx - tilex);
963 height2.x = colors[tilex][tiley + 1][0] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley + 1][0] * (pointx - tilex);
964 height2.y = colors[tilex][tiley + 1][1] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley + 1][1] * (pointx - tilex);
965 height2.z = colors[tilex][tiley + 1][2] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley + 1][2] * (pointx - tilex);
967 return height1 * (1 - (pointz - tiley)) + height2 * (pointz - tiley);
970 void Terrain::draw(int layer)
973 static float opacity;
974 static XYZ terrainpoint;
975 static float distance[subdivision][subdivision];
977 static int beginx, endx;
978 static int beginz, endz;
980 static float patch_size = size / subdivision * scale;
981 static float viewdistsquared;
983 viewdistsquared = viewdistance * viewdistance;
986 beginx = ((viewer.x - viewdistance) / patch_size) - 1;
990 beginz = ((viewer.z - viewdistance) / patch_size) - 1;
995 endx = ((viewer.x + viewdistance) / patch_size) + 1;
996 if (endx > subdivision) {
999 endz = ((viewer.z + viewdistance) / patch_size) + 1;
1000 if (endz > subdivision) {
1005 for (i = beginx; i < endx; i++) {
1006 for (j = beginz; j < endz; j++) {
1007 terrainpoint.x = i * patch_size + (patch_size) / 2;
1008 terrainpoint.y = viewer.y; //heightmap[i][j]*scale;
1009 terrainpoint.z = j * patch_size + (patch_size) / 2;
1010 distance[i][j] = distsq(&viewer, &terrainpoint);
1014 for (i = beginx; i < endx; i++) {
1015 for (j = beginz; j < endz; j++) {
1016 if (distance[i][j] < (viewdistance + patch_size) * (viewdistance + patch_size)) {
1018 if (distance[i][j] > viewdistsquared * fadestart - viewdistsquared) {
1021 if (opacity == 1 && i != subdivision) {
1022 if (distance[i + 1][j] > viewdistsquared * fadestart - viewdistsquared) {
1026 if (opacity == 1 && j != subdivision) {
1027 if (distance[i][j + 1] > viewdistsquared * fadestart - viewdistsquared) {
1031 if (opacity == 1 && j != subdivision && i != subdivision) {
1032 if (distance[i + 1][j + 1] > viewdistsquared * fadestart - viewdistsquared) {
1036 glMatrixMode(GL_MODELVIEW);
1038 if (frustum.CubeInFrustum(i * patch_size + patch_size * .5, avgypatch[i][j], j * patch_size + patch_size * .5, heightypatch[i][j] / 2)) {
1039 if (environment == desertenvironment && distance[i][j] > viewdistsquared / 4) {
1040 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, blurness);
1041 } else if (environment == desertenvironment) {
1042 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0);
1044 if (!layer && textureness[i][j] != allsecond) {
1045 drawpatch(i, j, opacity);
1047 if (layer == 1 && textureness[i][j] != allfirst) {
1048 drawpatchother(i, j, opacity);
1050 if (layer == 2 && textureness[i][j] != allfirst) {
1051 drawpatchotherother(i, j);
1058 if (environment == desertenvironment) {
1059 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0);
1063 void Terrain::drawdecals()
1066 static float distancemult;
1067 static int lasttype;
1069 static float viewdistsquared;
1072 viewdistsquared = viewdistance * viewdistance;
1077 glDisable(GL_LIGHTING);
1078 glDisable(GL_CULL_FACE);
1079 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1081 for (unsigned int i = 0; i < decals.size(); i++) {
1082 if (decals[i].type == blooddecalfast && decals[i].alivetime < 2) {
1083 decals[i].alivetime = 2;
1085 if (decals[i].type != lasttype) {
1086 if (decals[i].type == shadowdecal || decals[i].type == shadowdecalpermanent) {
1087 shadowtexture.bind();
1090 glAlphaFunc(GL_GREATER, 0.0001);
1091 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1094 if (decals[i].type == footprintdecal) {
1095 footprinttexture.bind();
1098 glAlphaFunc(GL_GREATER, 0.0001);
1099 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1102 if (decals[i].type == bodyprintdecal) {
1103 bodyprinttexture.bind();
1106 glAlphaFunc(GL_GREATER, 0.0001);
1107 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1110 if (decals[i].type == blooddecal || decals[i].type == blooddecalslow) {
1111 bloodtexture.bind();
1114 glAlphaFunc(GL_GREATER, 0.15);
1115 glBlendFunc(GL_ONE, GL_ZERO);
1118 if (decals[i].type == blooddecalfast) {
1119 bloodtexture2.bind();
1122 glAlphaFunc(GL_GREATER, 0.15);
1123 glBlendFunc(GL_ONE, GL_ZERO);
1127 if (decals[i].type == shadowdecal || decals[i].type == shadowdecalpermanent) {
1128 distancemult = (viewdistsquared - (distsq(&viewer, &decals[i].position) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
1129 if (distancemult >= 1) {
1130 glColor4f(1, 1, 1, decals[i].opacity);
1132 if (distancemult < 1) {
1133 glColor4f(1, 1, 1, decals[i].opacity * distancemult);
1136 if (decals[i].type == footprintdecal || decals[i].type == bodyprintdecal) {
1137 distancemult = (viewdistsquared - (distsq(&viewer, &decals[i].position) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
1138 if (distancemult >= 1) {
1139 glColor4f(1, 1, 1, decals[i].opacity);
1140 if (decals[i].alivetime > 3) {
1141 glColor4f(1, 1, 1, decals[i].opacity * (5 - decals[i].alivetime) / 2);
1144 if (distancemult < 1) {
1145 glColor4f(1, 1, 1, decals[i].opacity * distancemult);
1146 if (decals[i].alivetime > 3) {
1147 glColor4f(1, 1, 1, decals[i].opacity * (5 - decals[i].alivetime) / 2 * distancemult);
1151 if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow)) {
1152 distancemult = (viewdistsquared - (distsq(&viewer, &decals[i].position) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
1153 if (distancemult >= 1) {
1154 glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity);
1155 if (decals[i].alivetime < 4) {
1156 glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity * decals[i].alivetime * .25);
1158 if (decals[i].alivetime > 58) {
1159 glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity * (60 - decals[i].alivetime) / 2);
1162 if (distancemult < 1) {
1163 glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity * distancemult);
1164 if (decals[i].alivetime < 4) {
1165 glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity * decals[i].alivetime * distancemult * .25);
1167 if (decals[i].alivetime > 58) {
1168 glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity * (60 - decals[i].alivetime) / 2 * distancemult);
1172 lasttype = decals[i].type;
1173 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1176 glMatrixMode(GL_MODELVIEW);
1178 glBegin(GL_TRIANGLES);
1179 for (int j = 0; j < 3; j++) {
1180 glTexCoord2f(decals[i].texcoords[j][0], decals[i].texcoords[j][1]);
1181 glVertex3f(decals[i].vertex[j].x, decals[i].vertex[j].y, decals[i].vertex[j].z);
1186 for (int i = decals.size() - 1; i >= 0; i--) {
1187 decals[i].alivetime += multiplier;
1188 if (decals[i].type == blooddecalslow) {
1189 decals[i].alivetime -= multiplier * 2 / 3;
1191 if (decals[i].type == blooddecalfast) {
1192 decals[i].alivetime += multiplier * 4;
1194 if (decals[i].type == shadowdecal) {
1197 if (decals[i].type == footprintdecal && decals[i].alivetime >= 5) {
1200 if (decals[i].type == bodyprintdecal && decals[i].alivetime >= 5) {
1203 if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow) && decals[i].alivetime >= 60) {
1207 glAlphaFunc(GL_GREATER, 0.0001);
1211 void Terrain::deleteDeadDecals()
1213 for (int i = decals.size() - 1; i >= 0; i--) {
1214 if ((decals[i].type == blooddecal || decals[i].type == blooddecalslow) && decals[i].alivetime < 2) {
1220 void Terrain::AddObject(XYZ where, float radius, int id)
1223 if (id >= 0 && id < 10000) {
1224 for (int i = 0; i < subdivision; i++) {
1225 for (int j = 0; j < subdivision; j++) {
1226 if (patchobjects[i][j].size() < 300 - 1) {
1227 points[0].x = (size / subdivision) * i;
1228 points[0].z = (size / subdivision) * j;
1229 points[0].y = heightmap[(int)points[0].x][(int)points[0].z];
1230 points[1].x = (size / subdivision) * (i + 1);
1231 points[1].z = (size / subdivision) * (j + 1);
1232 points[1].y = heightmap[(int)points[1].x][(int)points[1].z];
1235 if (where.x + radius > points[0].x && where.x - radius < points[1].x && where.z + radius > points[0].z && where.z - radius < points[1].z) {
1236 patchobjects[i][j].push_back(id);
1244 void Terrain::DeleteDecal(int which)
1247 decals.erase(decals.begin() + which);
1251 void Terrain::MakeDecal(decal_type type, XYZ where, float size, float opacity, float rotation)
1254 if (opacity > 0 && size > 0) {
1255 static int patchx[4];
1256 static int patchy[4];
1258 patchx[0] = (where.x + size) / scale;
1259 patchx[1] = (where.x - size) / scale;
1260 patchx[2] = (where.x - size) / scale;
1261 patchx[3] = (where.x + size) / scale;
1263 patchy[0] = (where.z - size) / scale;
1264 patchy[1] = (where.z - size) / scale;
1265 patchy[2] = (where.z + size) / scale;
1266 patchy[3] = (where.z + size) / scale;
1268 if ((patchx[0] != patchx[1] || patchy[0] != patchy[1]) && (patchx[0] != patchx[2] || patchy[0] != patchy[2]) && (patchx[0] != patchx[3] || patchy[0] != patchy[3])) {
1269 MakeDecalLock(type, where, patchx[0], patchy[0], size, opacity, rotation);
1272 if ((patchx[1] != patchx[2] || patchy[1] != patchy[2]) && (patchx[1] != patchx[3] || patchy[1] != patchy[3])) {
1273 MakeDecalLock(type, where, patchx[1], patchy[1], size, opacity, rotation);
1276 if ((patchx[2] != patchx[3] || patchy[2] != patchy[3])) {
1277 MakeDecalLock(type, where, patchx[2], patchy[2], size, opacity, rotation);
1280 MakeDecalLock(type, where, patchx[3], patchy[3], size, opacity, rotation);
1285 void Terrain::MakeDecalLock(decal_type type, XYZ where, int whichx, int whichy, float size, float opacity, float rotation)
1288 XYZ rot = getLighting(where.x, where.z);
1289 float decalbright = (rot.x + rot.y + rot.z) / 3;
1291 if (decalbright < .4) {
1295 if (environment == grassyenvironment) {
1299 if (decalbright > 1) {
1303 Decal decal(where, type, opacity, rotation, decalbright, whichx, whichy, size, *this, true);
1305 if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0)) {
1306 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0)) {
1307 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1)) {
1308 if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1309 if (decals.size() < max_decals - 1) {
1310 decals.push_back(decal);
1317 Decal decal2(where, type, opacity, rotation, decalbright, whichx, whichy, size, *this, false);
1319 if (!(decal2.texcoords[0][0] < 0 && decal2.texcoords[1][0] < 0 && decal2.texcoords[2][0] < 0)) {
1320 if (!(decal2.texcoords[0][1] < 0 && decal2.texcoords[1][1] < 0 && decal2.texcoords[2][1] < 0)) {
1321 if (!(decal2.texcoords[0][0] > 1 && decal2.texcoords[1][0] > 1 && decal2.texcoords[2][0] > 1)) {
1322 if (!(decal2.texcoords[0][1] > 1 && decal2.texcoords[1][1] > 1 && decal2.texcoords[2][1] > 1)) {
1323 if (decals.size() < max_decals - 1) {
1324 decals.push_back(decal2);
1333 void Terrain::DoShadows()
1335 static XYZ testpoint, testpoint2, terrainpoint, lightloc, col;
1336 lightloc = light.location;
1337 if (!skyboxtexture) {
1341 if (skyboxtexture && Tutorial::active) {
1347 Normalise(&lightloc);
1349 for (short int i = 0; i < size; i++) {
1350 for (short int j = 0; j < size; j++) {
1351 terrainpoint.x = (float)i * scale;
1352 terrainpoint.z = (float)j * scale;
1353 terrainpoint.y = heightmap[i][j] * scale;
1356 patchx = (float)i * subdivision / size;
1357 patchz = (float)j * subdivision / size;
1358 if (patchobjects[patchx][patchz].size()) {
1359 for (unsigned int k = 0; k < patchobjects[patchx][patchz].size(); k++) {
1360 unsigned int l = patchobjects[patchx][patchz][k];
1361 if (Object::objects[l]->type != treetrunktype) {
1362 testpoint = terrainpoint;
1363 testpoint2 = terrainpoint + lightloc * 50 * (1 - shadowed);
1364 if (Object::objects[l]->model.LineCheck(&testpoint, &testpoint2, &col, &Object::objects[l]->position, &Object::objects[l]->yaw) != -1) {
1365 shadowed = 1 - (findDistance(&terrainpoint, &col) / 50);
1369 Game::LoadingScreen();
1371 float brightness = dotproduct(&lightloc, &normals[i][j]);
1373 brightness *= 1 - shadowed;
1376 if (brightness > 1) {
1379 if (brightness < 0) {
1383 colors[i][j][0] = light.color[0] * brightness + light.ambient[0];
1384 colors[i][j][1] = light.color[1] * brightness + light.ambient[1];
1385 colors[i][j][2] = light.color[2] * brightness + light.ambient[2];
1387 if (colors[i][j][0] > 1) {
1388 colors[i][j][0] = 1;
1390 if (colors[i][j][1] > 1) {
1391 colors[i][j][1] = 1;
1393 if (colors[i][j][2] > 1) {
1394 colors[i][j][2] = 1;
1396 if (colors[i][j][0] < 0) {
1397 colors[i][j][0] = 0;
1399 if (colors[i][j][1] < 0) {
1400 colors[i][j][1] = 0;
1402 if (colors[i][j][2] < 0) {
1403 colors[i][j][2] = 0;
1408 Game::LoadingScreen();
1411 for (short int i = 0; i < size; i++) {
1412 for (short int j = 0; j < size; j++) {
1413 for (short int k = 0; k < 3; k++) {
1415 unsigned int todivide = 0;
1417 total += colors[j][i - 1][k];
1420 if (i != size - 1) {
1421 total += colors[j][i + 1][k];
1425 total += colors[j - 1][i][k];
1428 if (j != size - 1) {
1429 total += colors[j + 1][i][k];
1432 if (i != 0 && j != 0) {
1433 total += colors[j - 1][i - 1][k];
1436 if (i != size - 1 && j != 0) {
1437 total += colors[j - 1][i + 1][k];
1440 if (j != size - 1 && i != size - 1) {
1441 total += colors[j + 1][i + 1][k];
1444 if (j != size - 1 && i != 0) {
1445 total += colors[j + 1][i - 1][k];
1448 total += colors[j][i][k];
1451 colors[j][i][k] = total / todivide;
1456 for (unsigned int i = 0; i < subdivision; i++) {
1457 for (unsigned int j = 0; j < subdivision; j++) {
1458 UpdateVertexArray(i, j);
1469 memset(heightmap, 0, sizeof(heightmap));
1470 memset(normals, 0, sizeof(normals));
1471 memset(facenormals, 0, sizeof(facenormals));
1472 memset(triangles, 0, sizeof(triangles));
1473 memset(colors, 0, sizeof(colors));
1474 memset(opacityother, 0, sizeof(opacityother));
1475 memset(texoffsetx, 0, sizeof(texoffsetx));
1476 memset(texoffsety, 0, sizeof(texoffsety));
1477 memset(numtris, 0, sizeof(numtris));
1478 memset(textureness, 0, sizeof(textureness));
1480 memset(vArray, 0, sizeof(vArray));
1482 memset(visible, 0, sizeof(visible));
1483 memset(avgypatch, 0, sizeof(avgypatch));
1484 memset(maxypatch, 0, sizeof(maxypatch));
1485 memset(minypatch, 0, sizeof(minypatch));
1486 memset(heightypatch, 0, sizeof(heightypatch));