2 Copyright (C) 2003, 2010 - Wolfire Games
4 This file is part of Lugaru.
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.
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.
15 See the GNU General Public License for more details.
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.
26 extern float viewdistance;
27 extern float fadestart;
28 extern int environment;
29 extern float texscale;
31 extern float multiplier;
32 extern FRUSTUM frustum;
33 extern float texdetail;
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;
46 int Terrain::lineTerrain(XYZ p1, XYZ p2, XYZ *p)
49 static float distance;
50 static float olddistance;
51 static int intersecting;
52 static int firstintersecting;
54 static int startx, starty;
56 static int endx, endy;
57 static int numtris = (size - 1) * (size - 1) * 2;
58 static float highest, lowest;
60 firstintersecting = -1;
85 if (startx < 0)startx = 0;
86 if (starty < 0)starty = 0;
87 if (endx > size - 1)endx = size - 1;
88 if (endy > size - 1)endy = size - 1;
90 for (i = startx; i <= endx; i++) {
91 for (j = starty; j <= endy; j++) {
94 for (k = 0; k < 2; k++) {
95 if (heightmap[i + k][j] > highest)highest = heightmap[i + k][j];
96 if (heightmap[i + k][j] < lowest)lowest = heightmap[i + k][j];
97 if (heightmap[i + k][j + 1] > highest)highest = heightmap[i + k][j + 1];
98 if (heightmap[i + k][j + 1] < lowest)lowest = heightmap[i + k][j + 1];
100 if ((p1.y <= highest || p2.y <= highest) && (p1.y >= lowest || p2.y >= lowest)) {
102 triangles[0].y = heightmap[i][j];
106 triangles[1].y = heightmap[i][j + 1];
107 triangles[1].z = j + 1;
109 triangles[2].x = i + 1;
110 triangles[2].y = heightmap[i + 1][j];
113 intersecting = LineFacet(p1, p2, triangles[0], triangles[1], triangles[2], &point);
114 distance = distsq(&p1, &point);
115 if ((distance < olddistance || firstintersecting == -1) && intersecting == 1) {
116 olddistance = distance;
117 firstintersecting = 1;
121 triangles[0].x = i + 1;
122 triangles[0].y = heightmap[i + 1][j];
126 triangles[1].y = heightmap[i][j + 1];
127 triangles[1].z = j + 1;
129 triangles[2].x = i + 1;
130 triangles[2].y = heightmap[i + 1][j + 1];
131 triangles[2].z = j + 1;
133 intersecting = LineFacet(p1, p2, triangles[0], triangles[1], triangles[2], &point);
134 distance = distsq(&p1, &point);
135 if ((distance < olddistance || firstintersecting == -1) && intersecting == 1) {
136 olddistance = distance;
137 firstintersecting = 1;
143 return firstintersecting;
146 void Terrain::UpdateTransparency(int whichx, int whichy)
149 static int i, j, a, b, c, d, patch_size, stepsize;
150 static float distance;
152 static float viewdistsquared;
154 viewdistsquared = viewdistance * viewdistance;
155 patch_size = size / subdivision;
158 c = whichx * patch_elements + whichy * patch_elements * subdivision;
160 for (i = patch_size * whichx; i < patch_size * (whichx + 1) + 1; i += stepsize) {
161 for (j = patch_size * whichy; j < patch_size * (whichy + 1) + 1; j += stepsize) {
162 if (i < size && j < size) {
163 vertex.x = i * scale;
164 vertex.z = j * scale;
165 vertex.y = heightmap[i][j] * scale;
166 distance = distsq(&viewer, &vertex);
167 if (distance > viewdistsquared)distance = viewdistsquared;
168 colors[i][j][3] = (viewdistsquared - (distance - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
173 for (i = patch_size * whichx; i < patch_size * (whichx + 1); i += stepsize) {
174 for (j = patch_size * whichy; j < patch_size * (whichy + 1); j += stepsize) {
175 a = (i - (patch_size * whichx)) / stepsize;
176 b = (j - (patch_size * whichy)) / stepsize;
177 d = (a * 54) + (b * 54 * patch_size / stepsize);
178 vArray[d + c + 6] = colors[i][j][3];
180 vArray[d + c + 15] = colors[i][j + stepsize][3];
182 vArray[d + c + 24] = colors[i + stepsize][j][3];
184 vArray[d + c + 33] = colors[i + stepsize][j][3];
186 vArray[d + c + 42] = colors[i][j + stepsize][3];
188 vArray[d + c + 51] = colors[i + stepsize][j + stepsize][3];
193 void Terrain::UpdateTransparencyother(int whichx, int whichy)
196 static int i, j, a, b, c, d, patch_size, stepsize;
197 static float distance;
199 patch_size = size / subdivision;
202 c = whichx * patch_elements + whichy * patch_elements * subdivision;
204 for (i = patch_size * whichx; i < patch_size * (whichx + 1); i += stepsize) {
205 for (j = patch_size * whichy; j < patch_size * (whichy + 1); j += stepsize) {
206 a = (i - (patch_size * whichx)) / stepsize;
207 b = (j - (patch_size * whichy)) / stepsize;
208 d = (a * 54) + (b * 54 * patch_size / stepsize);
209 vArray[d + c + 6] = colors[i][j][3] * opacityother[i][j];
211 vArray[d + c + 15] = colors[i][j + stepsize][3] * opacityother[i][j + stepsize];
213 vArray[d + c + 24] = colors[i + stepsize][j][3] * opacityother[i + stepsize][j];
215 vArray[d + c + 33] = colors[i + stepsize][j][3] * opacityother[i + stepsize][j];
217 vArray[d + c + 42] = colors[i][j + stepsize][3] * opacityother[i][j + stepsize];
219 vArray[d + c + 51] = colors[i + stepsize][j + stepsize][3] * opacityother[i + stepsize][j + stepsize];
224 void Terrain::UpdateTransparencyotherother(int whichx, int whichy)
227 static int i, j, a, b, c, d, patch_size, stepsize;
228 static float distance;
230 static float viewdistsquared;
232 viewdistsquared = viewdistance * viewdistance;
233 patch_size = size / subdivision;
236 c = whichx * patch_elements + whichy * patch_elements * subdivision;
238 for (i = patch_size * whichx; i < patch_size * (whichx + 1) + 1; i += stepsize) {
239 for (j = patch_size * whichy; j < patch_size * (whichy + 1) + 1; j += stepsize) {
240 if (i < size && j < size) {
241 vertex.x = i * scale;
242 vertex.z = j * scale;
243 vertex.y = heightmap[i][j] * scale;
244 distance = distsq(&viewer, &vertex);
245 if (distance > viewdistsquared)distance = viewdistsquared;
246 colors[i][j][3] = (viewdistsquared - (distance - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
251 for (i = patch_size * whichx; i < patch_size * (whichx + 1); i += stepsize) {
252 for (j = patch_size * whichy; j < patch_size * (whichy + 1); j += stepsize) {
253 a = (i - (patch_size * whichx)) / stepsize;
254 b = (j - (patch_size * whichy)) / stepsize;
255 d = (a * 54) + (b * 54 * patch_size / stepsize);
256 vArray[d + c + 6] = colors[i][j][3];
258 vArray[d + c + 15] = colors[i][j + stepsize][3];
260 vArray[d + c + 24] = colors[i + stepsize][j][3];
262 vArray[d + c + 33] = colors[i + stepsize][j][3];
264 vArray[d + c + 42] = colors[i][j + stepsize][3];
266 vArray[d + c + 51] = colors[i + stepsize][j + stepsize][3];
271 void Terrain::UpdateVertexArray(int whichx, int whichy)
273 static int i, j, a, b, c, patch_size, stepsize;
276 numtris[whichx][whichy] = 0;
278 patch_size = size / subdivision;
281 c = whichx * patch_elements + whichy * patch_elements * subdivision;
282 for (i = patch_size * whichx; i < patch_size * (whichx + 1); i += stepsize) {
283 for (j = patch_size * whichy; j < patch_size * (whichy + 1); j += stepsize) {
284 a = (i - ((float)size / subdivision * (float)whichx)) / stepsize;
285 b = (j - ((float)size / subdivision * (float)whichy)) / stepsize;
286 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 0] = i * scale;
287 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 1] = heightmap[i][j] * scale;
288 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 2] = j * scale;
289 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 3] = colors[i][j][0];
290 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 4] = colors[i][j][1];
291 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 5] = colors[i][j][2];
292 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 6] = colors[i][j][3];
293 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 7] = i * scale * texscale + texoffsetx[i][j];
294 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 8] = j * scale * texscale + texoffsety[i][j];
296 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 9] = i * scale;
297 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 10] = heightmap[i][j + stepsize] * scale;
298 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 11] = j * scale + stepsize * scale;
299 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 12] = colors[i][j + stepsize][0];
300 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 13] = colors[i][j + stepsize][1];
301 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 14] = colors[i][j + stepsize][2];
302 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 15] = colors[i][j + stepsize][3];
303 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 16] = i * scale * texscale + texoffsetx[i][j + stepsize];
304 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 17] = j * scale * texscale + stepsize * scale * texscale + texoffsety[i][j + stepsize];
306 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 18] = i * scale + stepsize * scale;
307 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 19] = heightmap[i + stepsize][j] * scale;
308 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 20] = j * scale;
309 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 21] = colors[i + stepsize][j][0];
310 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 22] = colors[i + stepsize][j][1];
311 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 23] = colors[i + stepsize][j][2];
312 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 24] = colors[i + stepsize][j][3];
313 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 25] = i * scale * texscale + stepsize * scale * texscale + texoffsetx[i + stepsize][j];
314 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 26] = j * scale * texscale + texoffsety[i + stepsize][j];
316 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 27] = i * scale + stepsize * scale;
317 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 28] = heightmap[i + stepsize][j] * scale;
318 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 29] = j * scale;
319 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 30] = colors[i + stepsize][j][0];
320 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 31] = colors[i + stepsize][j][1];
321 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 32] = colors[i + stepsize][j][2];
322 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 33] = colors[i + stepsize][j][3];
323 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 34] = i * scale * texscale + stepsize * scale * texscale + texoffsetx[i + stepsize][j];
324 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 35] = j * scale * texscale + texoffsety[i + stepsize][j];
326 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 36] = i * scale;
327 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 37] = heightmap[i][j + stepsize] * scale;
328 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 38] = j * scale + stepsize * scale;
329 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 39] = colors[i][j + stepsize][0];
330 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 40] = colors[i][j + stepsize][1];
331 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 41] = colors[i][j + stepsize][2];
332 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 42] = colors[i][j + stepsize][3];
333 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 43] = i * scale * texscale + texoffsetx[i][j + stepsize];
334 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 44] = j * scale * texscale + stepsize * scale * texscale + texoffsety[i][j + stepsize];
336 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 45] = i * scale + stepsize * scale;
337 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 46] = heightmap[i + stepsize][j + stepsize] * scale;
338 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 47] = j * scale + stepsize * scale;
339 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 48] = colors[i + stepsize][j + stepsize][0];
340 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 49] = colors[i + stepsize][j + stepsize][1];
341 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 50] = colors[i + stepsize][j + stepsize][2];
342 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 51] = colors[i + stepsize][j + stepsize][3];
343 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 52] = i * scale * texscale + stepsize * scale * texscale + texoffsetx[i + stepsize][j + stepsize];
344 vArray[(a * 54) + (b * 54 * patch_size / stepsize) + c + 53] = j * scale * texscale + stepsize * scale * texscale + texoffsety[i + stepsize][j + stepsize];
345 numtris[whichx][whichy] += 2;
349 maxypatch[whichx][whichy] = -10000;
350 minypatch[whichx][whichy] = 10000;
351 for (a = 0; a < size / subdivision; a++) {
352 for (b = 0; b < size / subdivision; b++) {
353 if (heightmap[(size / subdivision)*whichx + a][(size / subdivision)*whichy + b]*scale > maxypatch[whichx][whichy]) maxypatch[whichx][whichy] = heightmap[(size / subdivision) * whichx + a][(size / subdivision) * whichy + b] * scale;
354 if (heightmap[(size / subdivision)*whichx + a][(size / subdivision)*whichy + b]*scale < minypatch[whichx][whichy]) minypatch[whichx][whichy] = heightmap[(size / subdivision) * whichx + a][(size / subdivision) * whichy + b] * scale;
357 heightypatch[whichx][whichy] = (maxypatch[whichx][whichy] - minypatch[whichx][whichy]);
358 if (heightypatch[whichx][whichy] < size / subdivision * scale)heightypatch[whichx][whichy] = size / subdivision * scale;
359 avgypatch[whichx][whichy] = (minypatch[whichx][whichy] + maxypatch[whichx][whichy]) / 2;
361 for (i = whichx * size / subdivision; i < (whichx + 1)*size / subdivision - 1; i++) {
362 for (j = whichy * size / subdivision; j < (whichy + 1)*size / subdivision - 1; j++) {
363 triangles[(i * (size - 1) * 2) + (j * 2)][0].x = i * scale;
364 triangles[(i * (size - 1) * 2) + (j * 2)][0].y = heightmap[i][j] * scale;
365 triangles[(i * (size - 1) * 2) + (j * 2)][0].z = j * scale;
367 triangles[(i * (size - 1) * 2) + (j * 2)][1].x = i * scale;
368 triangles[(i * (size - 1) * 2) + (j * 2)][1].y = heightmap[i][j + 1] * scale;
369 triangles[(i * (size - 1) * 2) + (j * 2)][1].z = j * scale + scale;
371 triangles[(i * (size - 1) * 2) + (j * 2)][2].x = i * scale + 1 * scale;
372 triangles[(i * (size - 1) * 2) + (j * 2)][2].y = heightmap[i + 1][j] * scale;
373 triangles[(i * (size - 1) * 2) + (j * 2)][2].z = j * scale;
375 triangles[(i * (size - 1) * 2) + (j * 2) + 1][0].x = i * scale + 1 * scale;
376 triangles[(i * (size - 1) * 2) + (j * 2) + 1][0].y = heightmap[i + 1][j] * scale;
377 triangles[(i * (size - 1) * 2) + (j * 2) + 1][0].z = j * scale;
379 triangles[(i * (size - 1) * 2) + (j * 2) + 1][1].x = i * scale;
380 triangles[(i * (size - 1) * 2) + (j * 2) + 1][1].y = heightmap[i][j + 1] * scale;
381 triangles[(i * (size - 1) * 2) + (j * 2) + 1][1].z = j * scale + 1 * scale;
383 triangles[(i * (size - 1) * 2) + (j * 2) + 1][2].x = i * scale + 1 * scale;
384 triangles[(i * (size - 1) * 2) + (j * 2) + 1][2].y = heightmap[i + 1][j + 1] * scale;
385 triangles[(i * (size - 1) * 2) + (j * 2) + 1][2].z = j * scale + 1 * scale;
392 bool Terrain::load(const char *fileName)
396 static float patch_size;
398 float temptexdetail = texdetail;
399 //LoadTGA( fileName );
401 // Fixing filename so that it works with its own os
402 char * FixedFN = ConvertFileName(fileName);
404 unsigned char fileNamep[256];
405 CopyCStringToPascal(FixedFN, fileNamep);
407 upload_image( fileNamep , 0);
410 if (texture.bpp > 24) {
411 int bytesPerPixel = texture.bpp / 8;
414 for (i = 0; i < (long)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
416 texture.data[tempnum] = texture.data[i];
422 if (visibleloading) Game::LoadingScreen();
424 texdetail = temptexdetail;
428 /*if ( texture.bpp == 24 )
433 glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
435 if(!terraintexture)glGenTextures( 1, &terraintexture );
436 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
438 glBindTexture( GL_TEXTURE_2D, terraintexture);
439 //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
440 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
442 gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, type, GL_UNSIGNED_BYTE, texture.data );
445 size = texture.sizeX;
447 for (i = 0; i < size; i++) {
448 for (j = 0; j < size; j++) {
449 heightmap[size - 1 - i][j] = (float)((texture.data[(i + (j * size)) * texture.bpp / 8])) / 5;
454 if (visibleloading) Game::LoadingScreen();
458 for (i = 0; i < subdivision; i++) {
459 for (j = 0; j < subdivision; j++) {
460 textureness[i][j] = -1;
463 if (visibleloading) Game::LoadingScreen();
466 for (i = 0; i < size; i++) {
467 for (j = 0; j < size; j++) {
468 heightmap[i][j] *= .5;
470 texoffsetx[i][j] = (float)abs(Random() % 100) / 1200 / scale * 3;
471 texoffsety[i][j] = (float)abs(Random() % 100) / 1200 / scale * 3;
474 if (environment == snowyenvironment) {
475 if (j != 0 && heightmap[i][j] - heightmap[i][j - 1] > slopeness) {
476 slopeness = heightmap[i][j] - heightmap[i][j - 1];
478 opacityother[i][j] = slopeness * slopeness * 2;
479 if (opacityother[i][j] > 1)opacityother[i][j] = 1;
480 opacityother[i][j] -= (float)abs(Random() % 100) / 300;
482 if (environment == desertenvironment) {
483 if (j != 0 && heightmap[i][j] - heightmap[i][j - 1] > slopeness) {
484 slopeness = heightmap[i][j] - heightmap[i][j - 1];
486 opacityother[i][j] = slopeness * slopeness * 2;
487 if (opacityother[i][j] > 1)opacityother[i][j] = 1;
488 opacityother[i][j] -= (float)abs(Random() % 100) / 300;
490 if (environment == grassyenvironment) {
491 if (i != 0 && heightmap[i][j] - heightmap[i - 1][j] > slopeness) {
492 slopeness = heightmap[i][j] - heightmap[i - 1][j];
494 if (j != 0 && heightmap[i][j] - heightmap[i][j - 1] > slopeness) {
495 slopeness = heightmap[i][j] - heightmap[i][j - 1];
497 if (i < size - 1 && heightmap[i][j] - heightmap[i + 1][j] > slopeness) {
498 slopeness = heightmap[i][j] - heightmap[i + 1][j];
500 if (j < size - 1 && heightmap[i][j] - heightmap[i][j + 1] > slopeness) {
501 slopeness = heightmap[i][j] - heightmap[i][j + 1];
503 opacityother[i][j] = slopeness * slopeness * 10;
504 if (opacityother[i][j] > 1)opacityother[i][j] = 1;
505 opacityother[i][j] -= (float)abs(Random() % 100) / 100;
509 if (visibleloading) Game::LoadingScreen();
511 for (i = 0; i < size; i++) {
512 for (j = 0; j < size; j++) {
513 if (environment == snowyenvironment) {
514 heightmap[i][j] -= opacityother[i][j];
516 if (environment == desertenvironment) {
517 heightmap[i][j] -= opacityother[i][j];
521 if (visibleloading) Game::LoadingScreen();
525 //Smooth opacityother
530 if(i!=0){ total+=opacityother[j][i-1]; todivide++;}
531 if(i!=size-1){ total+=opacityother[j][i+1]; todivide++;}
532 if(j!=0){ total+=opacityother[j-1][i]; todivide++;}
533 if(j!=size-1){ total+=opacityother[j+1][i]; todivide++;}
534 if(i!=0&&j!=0){ total+=opacityother[j-1][i-1]; todivide++;}
535 if(i!=size-1&&j!=0){ total+=opacityother[j-1][i+1]; todivide++;}
536 if(j!=size-1&&i!=size-1){ total+=opacityother[j+1][i+1]; todivide++;}
537 if(j!=size-1&&i!=0){ total+=opacityother[j+1][i-1]; todivide++;}
538 total+=opacityother[j][i]; todivide++;
540 opacityother[j][i]=total/(float)todivide;
545 for (i = 0; i < size; i++) {
546 for (j = 0; j < size; j++) {
547 if (opacityother[i][j] < .1)opacityother[i][j] = 0;
548 if (textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == -1) {
549 if (!opacityother[i][j])textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = allfirst;
550 if (opacityother[i][j] == 1)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = allsecond;
552 if (opacityother[i][j] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
553 if (opacityother[i][j] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
559 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
560 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
561 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
562 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
566 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
567 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
568 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
569 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
575 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
576 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
577 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
578 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
586 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
587 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
588 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
589 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
593 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
594 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
595 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
596 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
602 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
603 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
604 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
605 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
613 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
614 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
615 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
616 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
622 if (opacityother[x][y] && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allfirst)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
623 if (opacityother[x][y] != 1 && textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] == allsecond)textureness[(int)(i * subdivision / size)][(int)(j * subdivision / size)] = mixed;
624 if (opacityother[i][j] && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allfirst)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
625 if (opacityother[i][j] != 1 && textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] == allsecond)textureness[(int)(x * subdivision / size)][(int)(y * subdivision / size)] = mixed;
631 if (visibleloading) Game::LoadingScreen();
633 patch_size = size / subdivision;
634 patch_elements = (patch_size) * (patch_size) * 54;
638 for(i=0;i<subdivision;i++){
639 for(j=0;j<subdivision;j++){
640 UpdateVertexArray(i,j);
647 void Terrain::CalculateNormals()
650 static XYZ facenormal;
651 static XYZ p, q, a, b, c;
653 for (i = 0; i < size; i++) {
654 for (j = 0; j < size; j++) {
661 for (i = 0; i < size - 1; i++) {
662 for (j = 0; j < size - 1; j++) {
664 a.y = heightmap[i][j];
667 b.y = heightmap[i][j + 1];
670 c.y = heightmap[i + 1][j];
680 CrossProduct(&p, &q, &facenormal);
682 facenormals[i][j] = facenormal;
684 normals[i][j] = normals[i][j] + facenormal;
685 normals[i][j + 1] = normals[i][j + 1] + facenormal;
686 normals[i + 1][j] = normals[i + 1][j] + facenormal;
690 a.y = heightmap[i + 1][j];
693 b.y = heightmap[i][j + 1];
696 c.y = heightmap[i + 1][j + 1];
706 CrossProduct(&p, &q, &facenormal);
708 normals[i + 1][j + 1] = normals[i + 1][j + 1] + facenormal;
709 normals[i][j + 1] = normals[i][j + 1] + facenormal;
710 normals[i + 1][j] = normals[i + 1][j] + facenormal;
712 Normalise(&facenormals[i][j]);
716 for (i = 0; i < size; i++) {
717 for (j = 0; j < size; j++) {
718 Normalise(&normals[i][j]);
719 normals[i][j] = normals[i][j];
724 void Terrain::drawpatch(int whichx, int whichy, float opacity)
726 if (opacity >= 1)glDisable(GL_BLEND);
729 UpdateTransparency(whichx, whichy);
731 glColor4f(1, 1, 1, 1);
732 //Set up vertex array
733 glEnableClientState(GL_VERTEX_ARRAY);
734 glEnableClientState(GL_COLOR_ARRAY);
735 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
736 glVertexPointer(3, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[0 + whichx * patch_elements + whichy * patch_elements * subdivision]);
737 glColorPointer(4, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[3 + whichx * patch_elements + whichy * patch_elements * subdivision]);
738 glTexCoordPointer(2, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[7 + whichx * patch_elements + whichy * patch_elements * subdivision]);
741 glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy] * 3);
743 glDisableClientState(GL_VERTEX_ARRAY);
744 glDisableClientState(GL_COLOR_ARRAY);
745 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
748 void Terrain::drawpatchother(int whichx, int whichy, float opacity)
752 UpdateTransparency(whichx, whichy);
754 UpdateTransparencyother(whichx, whichy);
755 glColor4f(1, 1, 1, 1);
756 //Set up vertex array
757 glEnableClientState(GL_VERTEX_ARRAY);
758 glEnableClientState(GL_COLOR_ARRAY);
759 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
760 glVertexPointer(3, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[0 + whichx * patch_elements + whichy * patch_elements * subdivision]);
761 glColorPointer(4, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[3 + whichx * patch_elements + whichy * patch_elements * subdivision]);
762 glTexCoordPointer(2, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[7 + whichx * patch_elements + whichy * patch_elements * subdivision]);
765 glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy] * 3);
767 glDisableClientState(GL_VERTEX_ARRAY);
768 glDisableClientState(GL_COLOR_ARRAY);
769 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
772 void Terrain::drawpatchotherother(int whichx, int whichy, float opacity)
775 UpdateTransparencyotherother(whichx, whichy);
777 glMatrixMode(GL_TEXTURE);
781 glColor4f(1, 1, 1, 1);
783 //Set up vertex array
784 glEnableClientState(GL_VERTEX_ARRAY);
785 glEnableClientState(GL_COLOR_ARRAY);
786 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
787 glVertexPointer(3, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[0 + whichx * patch_elements + whichy * patch_elements * subdivision]);
788 glColorPointer(4, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[3 + whichx * patch_elements + whichy * patch_elements * subdivision]);
789 glTexCoordPointer(2, GL_FLOAT, 9 * sizeof(GLfloat), &vArray[7 + whichx * patch_elements + whichy * patch_elements * subdivision]);
792 glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy] * 3);
794 glDisableClientState(GL_VERTEX_ARRAY);
795 glDisableClientState(GL_COLOR_ARRAY);
796 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
799 glMatrixMode(GL_MODELVIEW);
803 float Terrain::getHeight(float pointx, float pointz)
805 static float height1, height2;
806 static int tilex, tiley;
807 static XYZ startpoint, endpoint, intersect, triangle[3], average;
812 if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0)return 0;
814 startpoint.x = pointx;
815 startpoint.y = -1000;
816 startpoint.z = pointz;
818 endpoint = startpoint;
824 triangle[0].x = tilex;
825 triangle[0].z = tiley;
826 triangle[0].y = heightmap[tilex][tiley];
828 triangle[1].x = tilex + 1;
829 triangle[1].z = tiley;
830 triangle[1].y = heightmap[tilex + 1][tiley];
832 triangle[2].x = tilex;
833 triangle[2].z = tiley + 1;
834 triangle[2].y = heightmap[tilex][tiley + 1];
836 if (!LineFacetd(&startpoint, &endpoint, &triangle[0], &triangle[1], &triangle[2], &intersect)) {
837 triangle[0].x = tilex + 1;
838 triangle[0].z = tiley;
839 triangle[0].y = heightmap[tilex + 1][tiley];
841 triangle[1].x = tilex + 1;
842 triangle[1].z = tiley + 1;
843 triangle[1].y = heightmap[tilex + 1][tiley + 1];
845 triangle[2].x = tilex;
846 triangle[2].z = tiley + 1;
847 triangle[2].y = heightmap[tilex][tiley + 1];
848 LineFacetd(&startpoint, &endpoint, &triangle[0], &triangle[1], &triangle[2], &intersect);
850 return intersect.y * scale + getOpacity(pointx * scale, pointz * scale) / 8;
852 //height1=heightmap[tilex][tiley]*(1-(pointx-tilex))+heightmap[tilex+1][tiley]*(pointx-tilex);
853 //height2=heightmap[tilex][tiley+1]*(1-(pointx-tilex))+heightmap[tilex+1][tiley+1]*(pointx-tilex);
855 //return height1*(1-(pointz-tiley))*scale+height2*(pointz-tiley)*scale;
858 float Terrain::getHeightExtrude(float pointx, float pointz, float point2x, float point2z)
860 static float height1, height2;
861 static int tilex, tiley;
862 static XYZ startpoint, endpoint, intersect, triangle[3], average;
869 if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0)return 0;
870 if (point2x >= size - 1 || point2z >= size - 1 || point2x <= 0 || point2z <= 0)return 0;
872 startpoint.x = point2x;
873 startpoint.y = -1000;
874 startpoint.z = point2z;
876 endpoint = startpoint;
882 triangle[0].x = tilex;
883 triangle[0].z = tiley;
884 triangle[0].y = heightmap[tilex][tiley];
886 triangle[1].x = tilex + 1;
887 triangle[1].z = tiley;
888 triangle[1].y = heightmap[tilex + 1][tiley];
890 triangle[2].x = tilex;
891 triangle[2].z = tiley + 1;
892 triangle[2].y = heightmap[tilex][tiley + 1];
896 mid = (triangle[0] + triangle[1] + triangle[2]) / 2;
898 triangle[0] = mid + (triangle[0] - mid) * 10;
899 triangle[1] = mid + (triangle[0] - mid) * 10;
900 triangle[2] = mid + (triangle[0] - mid) * 10;
903 if(!LineFacetd(&startpoint,&endpoint,&triangle[0],&triangle[1],&triangle[2],&intersect)){
904 triangle[0].x=tilex+1;
906 triangle[0].y=heightmap[tilex+1][tiley];
908 triangle[1].x=tilex+1;
909 triangle[1].z=tiley+1;
910 triangle[1].y=heightmap[tilex+1][tiley+1];
913 triangle[2].z=tiley+1;
914 triangle[2].y=heightmap[tilex][tiley+1];
915 LineFacetd(&startpoint,&endpoint,&triangle[0],&triangle[1],&triangle[2],&intersect);
917 return intersect.y * scale + getOpacity(pointx * scale, pointz * scale) / 8;
919 //height1=heightmap[tilex][tiley]*(1-(pointx-tilex))+heightmap[tilex+1][tiley]*(pointx-tilex);
920 //height2=heightmap[tilex][tiley+1]*(1-(pointx-tilex))+heightmap[tilex+1][tiley+1]*(pointx-tilex);
922 //return height1*(1-(pointz-tiley))*scale+height2*(pointz-tiley)*scale;
926 float Terrain::getOpacity(float pointx, float pointz)
928 static float height1, height2;
929 static int tilex, tiley;
934 if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0)return 0;
939 height1 = opacityother[tilex][tiley] * (1 - (pointx - tilex)) + opacityother[tilex + 1][tiley] * (pointx - tilex);
940 height2 = opacityother[tilex][tiley + 1] * (1 - (pointx - tilex)) + opacityother[tilex + 1][tiley + 1] * (pointx - tilex);
942 return height1 * (1 - (pointz - tiley)) + height2 * (pointz - tiley);
945 XYZ Terrain::getNormal(float pointx, float pointz)
947 static XYZ height1, height2, total;
948 static int tilex, tiley;
954 if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0)return height1;
958 height1 = normals[tilex][tiley] * (1 - (pointx - tilex)) + normals[tilex + 1][tiley] * (pointx - tilex);
959 height2 = normals[tilex][tiley + 1] * (1 - (pointx - tilex)) + normals[tilex + 1][tiley + 1] * (pointx - tilex);
960 total = height1 * (1 - (pointz - tiley)) + height2 * (pointz - tiley);
965 XYZ Terrain::getLighting(float pointx, float pointz)
967 static XYZ height1, height2;
968 static int tilex, tiley;
974 if (pointx >= size - 1 || pointz >= size - 1 || pointx <= 0 || pointz <= 0)return height1;
978 height1.x = colors[tilex][tiley][0] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley][0] * (pointx - tilex);
979 height1.y = colors[tilex][tiley][1] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley][1] * (pointx - tilex);
980 height1.z = colors[tilex][tiley][2] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley][2] * (pointx - tilex);
981 height2.x = colors[tilex][tiley + 1][0] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley + 1][0] * (pointx - tilex);
982 height2.y = colors[tilex][tiley + 1][1] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley + 1][1] * (pointx - tilex);
983 height2.z = colors[tilex][tiley + 1][2] * (1 - (pointx - tilex)) + colors[tilex + 1][tiley + 1][2] * (pointx - tilex);
985 return height1 * (1 - (pointz - tiley)) + height2 * (pointz - tiley);
988 void Terrain::draw(int layer)
991 static float opacity;
992 static XYZ terrainpoint;
993 static float distance[subdivision][subdivision];
995 static int beginx, endx;
996 static int beginz, endz;
998 static float patch_size = size / subdivision * scale;
999 static float viewdistsquared;
1001 viewdistsquared = viewdistance * viewdistance;
1003 //Only nearby blocks
1004 beginx = (viewer.x - viewdistance) / (patch_size) - 1;
1005 if (beginx < 0)beginx = 0;
1006 beginz = (viewer.z - viewdistance) / (patch_size) - 1;
1007 if (beginz < 0)beginz = 0;
1009 endx = (viewer.x + viewdistance) / (patch_size) + 1;
1010 if (endx > subdivision)endx = subdivision;
1011 endz = (viewer.z + viewdistance) / (patch_size) + 1;
1012 if (endz > subdivision)endz = subdivision;
1015 for (i = beginx; i < endx; i++) {
1016 for (j = beginz; j < endz; j++) {
1017 terrainpoint.x = i * patch_size + (patch_size) / 2;
1018 terrainpoint.y = viewer.y; //heightmap[i][j]*scale;
1019 terrainpoint.z = j * patch_size + (patch_size) / 2;
1020 distance[i][j] = distsq(&viewer, &terrainpoint);
1024 for (i = beginx; i < endx; i++) {
1025 for (j = beginz; j < endz; j++) {
1026 if (distance[i][j] < (viewdistance + patch_size) * (viewdistance + patch_size)) {
1028 if (distance[i][j] > viewdistsquared * fadestart - viewdistsquared)
1030 if (opacity == 1 && i != subdivision)
1031 if (distance[i + 1][j] > viewdistsquared * fadestart - viewdistsquared)
1033 if (opacity == 1 && j != subdivision)
1034 if (distance[i][j + 1] > viewdistsquared * fadestart - viewdistsquared)
1036 if (opacity == 1 && j != subdivision && i != subdivision)
1037 if (distance[i + 1][j + 1] > viewdistsquared * fadestart - viewdistsquared)
1039 glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
1041 if (frustum.CubeInFrustum(i * patch_size + patch_size * .5, avgypatch[i][j], j * patch_size + patch_size * .5, heightypatch[i][j] / 2)) {
1042 if (environment == desertenvironment && distance[i][j] > viewdistsquared / 4)
1043 glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, blurness);
1044 else if (environment == desertenvironment)
1045 glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
1046 if (!layer && textureness[i][j] != allsecond)
1047 drawpatch(i, j, opacity);
1048 if (layer == 1 && textureness[i][j] != allfirst)
1049 drawpatchother(i, j, opacity);
1050 if (layer == 2 && textureness[i][j] != allfirst)
1051 drawpatchotherother(i, j, opacity);
1057 if (environment == desertenvironment)
1058 glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
1061 void Terrain::drawdecals()
1065 static float distancemult;
1066 static int lasttype;
1068 static float patch_size = size / subdivision * scale;
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 (i = 0; i < numdecals; i++) {
1082 if (decaltype[i] == blooddecalfast && decalalivetime[i] < 2)decalalivetime[i] = 2;
1083 if ((decaltype[i] == shadowdecal || decaltype[i] == shadowdecalpermanent) && decaltype[i] != lasttype) {
1084 shadowtexture.bind();
1087 glAlphaFunc(GL_GREATER, 0.0001);
1088 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1091 if (decaltype[i] == footprintdecal && decaltype[i] != lasttype) {
1092 footprinttexture.bind();
1095 glAlphaFunc(GL_GREATER, 0.0001);
1096 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1099 if (decaltype[i] == bodyprintdecal && decaltype[i] != lasttype) {
1100 bodyprinttexture.bind();
1103 glAlphaFunc(GL_GREATER, 0.0001);
1104 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1107 if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalslow) && decaltype[i] != lasttype) {
1108 bloodtexture.bind();
1111 glAlphaFunc(GL_GREATER, 0.15);
1112 glBlendFunc(GL_ONE, GL_ZERO);
1115 if ((decaltype[i] == blooddecalfast) && decaltype[i] != lasttype) {
1116 bloodtexture2.bind();
1119 glAlphaFunc(GL_GREATER, 0.15);
1120 glBlendFunc(GL_ONE, GL_ZERO);
1123 if (decaltype[i] == shadowdecal || decaltype[i] == shadowdecalpermanent) {
1124 distancemult = (viewdistsquared - (distsq(&viewer, &decalposition[i]) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
1125 if (distancemult >= 1)glColor4f(1, 1, 1, decalopacity[i]);
1126 if (distancemult < 1)glColor4f(1, 1, 1, decalopacity[i]*distancemult);
1128 if (decaltype[i] == footprintdecal || decaltype[i] == bodyprintdecal) {
1129 distancemult = (viewdistsquared - (distsq(&viewer, &decalposition[i]) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
1130 if (distancemult >= 1) {
1131 glColor4f(1, 1, 1, decalopacity[i]);
1132 if (decalalivetime[i] > 3)glColor4f(1, 1, 1, decalopacity[i] * (5 - decalalivetime[i]) / 2);
1134 if (distancemult < 1) {
1135 glColor4f(1, 1, 1, decalopacity[i]*distancemult);
1136 if (decalalivetime[i] > 3)glColor4f(1, 1, 1, decalopacity[i] * (5 - decalalivetime[i]) / 2 * distancemult);
1139 if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow)) {
1140 distancemult = (viewdistsquared - (distsq(&viewer, &decalposition[i]) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
1141 if (distancemult >= 1) {
1142 glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i]);
1143 if (decalalivetime[i] < 4)glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i]*decalalivetime[i]*.25);
1144 if (decalalivetime[i] > 58)glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i] * (60 - decalalivetime[i]) / 2);
1146 if (distancemult < 1) {
1147 glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i]*distancemult);
1148 if (decalalivetime[i] < 4)glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i]*decalalivetime[i]*distancemult * .25);
1149 if (decalalivetime[i] > 58)glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i] * (60 - decalalivetime[i]) / 2 * distancemult);
1152 lasttype = decaltype[i];
1153 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1154 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1156 glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
1158 glBegin(GL_TRIANGLES);
1159 for (int j = 0; j < 3; j++) {
1160 glTexCoord2f(decaltexcoords[i][j][0], decaltexcoords[i][j][1]);
1161 glVertex3f(decalvertex[i][j].x, decalvertex[i][j].y, decalvertex[i][j].z);
1166 for (i = numdecals - 1; i >= 0; i--) {
1167 decalalivetime[i] += multiplier;
1168 if (decaltype[i] == blooddecalslow)decalalivetime[i] -= multiplier * 2 / 3;
1169 if (decaltype[i] == blooddecalfast)decalalivetime[i] += multiplier * 4;
1170 if (decaltype[i] == shadowdecal)DeleteDecal(i);
1171 if (decaltype[i] == footprintdecal && decalalivetime[i] >= 5)DeleteDecal(i);
1172 if (decaltype[i] == bodyprintdecal && decalalivetime[i] >= 5)DeleteDecal(i);
1173 if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow) && decalalivetime[i] >= 60)DeleteDecal(i);
1175 glAlphaFunc(GL_GREATER, 0.0001);
1179 void Terrain::AddObject(XYZ where, float radius, int id)
1184 if (id >= 0 && id < 10000)
1185 for (i = 0; i < subdivision; i++) {
1186 for (j = 0; j < subdivision; j++) {
1187 if (patchobjectnum[i][j] < 300 - 1) {
1189 points[0].x = (size / subdivision) * i;
1190 points[0].z = (size / subdivision) * j;
1191 points[0].y = heightmap[(int)points[0].x][(int)points[0].z];
1192 points[1].x = (size / subdivision) * (i + 1);
1193 points[1].z = (size / subdivision) * j;
1194 points[1].y = heightmap[(int)points[1].x][(int)points[1].z];
1195 points[2].x = (size / subdivision) * (i + 1);
1196 points[2].z = (size / subdivision) * (j + 1);
1197 points[2].y = heightmap[(int)points[2].x][(int)points[2].z];
1198 points[3].x = (size / subdivision) * i;
1199 points[3].z = (size / subdivision) * (j + 1);
1200 points[3].y = heightmap[(int)points[3].x][(int)points[3].z];
1205 if (!done && where.x + radius > points[0].x && where.x - radius < points[2].x && where.z + radius > points[0].z && where.z - radius < points[2].z) {
1206 patchobjects[i][j][patchobjectnum[i][j]] = id;
1207 patchobjectnum[i][j]++;
1215 void Terrain::DeleteDecal(int which)
1218 decaltype[which] = decaltype[numdecals - 1];
1219 decalposition[which] = decalposition[numdecals - 1];
1220 for (int i = 0; i < 3; i++) {
1221 decalvertex[which][i] = decalvertex[numdecals - 1][i];
1222 decaltexcoords[which][i][0] = decaltexcoords[numdecals - 1][i][0];
1223 decaltexcoords[which][i][1] = decaltexcoords[numdecals - 1][i][1];
1225 decalrotation[which] = decalrotation[numdecals - 1];
1226 decalalivetime[which] = decalalivetime[numdecals - 1];
1227 decalopacity[which] = decalopacity[numdecals - 1];
1228 decalbrightness[which] = decalbrightness[numdecals - 1];
1233 void Terrain::MakeDecal(int type, XYZ where, float size, float opacity, float rotation)
1236 if (opacity > 0 && size > 0) {
1237 static int patchx[4];
1238 static int patchy[4];
1240 decaltexcoords[numdecals][0][0] = 1;
1241 decaltexcoords[numdecals][0][1] = 0;
1243 patchx[0] = (where.x + size) / scale;
1244 patchx[1] = (where.x - size) / scale;
1245 patchx[2] = (where.x - size) / scale;
1246 patchx[3] = (where.x + size) / scale;
1248 patchy[0] = (where.z - size) / scale;
1249 patchy[1] = (where.z - size) / scale;
1250 patchy[2] = (where.z + size) / scale;
1251 patchy[3] = (where.z + size) / scale;
1253 /*if(patchx[1]<subdivision-1&&patchy[1]<subdivision-1&&patchx[1]>0&&patchy[1]>0)
1254 if(patchx[2]<subdivision-1&&patchy[2]<subdivision-1&&patchx[2]>0&&patchy[2]>0)
1255 if(patchx[3]<subdivision-1&&patchy[3]<subdivision-1&&patchx[3]>0&&patchy[3]>0)
1256 if(patchx[0]<subdivision-1&&patchy[0]<subdivision-1&&patchx[0]>0&&patchy[0]>0){
1258 if ((patchx[0] != patchx[1] || patchy[0] != patchy[1]) && (patchx[0] != patchx[2] || patchy[0] != patchy[2]) && (patchx[0] != patchx[3] || patchy[0] != patchy[3])) {
1259 MakeDecalLock(type, where, patchx[0], patchy[0], size, opacity, rotation);
1262 if ((patchx[1] != patchx[2] || patchy[1] != patchy[2]) && (patchx[1] != patchx[3] || patchy[1] != patchy[3])) {
1263 MakeDecalLock(type, where, patchx[1], patchy[1], size, opacity, rotation);
1266 if ((patchx[2] != patchx[3] || patchy[2] != patchy[3])) {
1267 MakeDecalLock(type, where, patchx[2], patchy[2], size, opacity, rotation);
1269 MakeDecalLock(type, where, patchx[3], patchy[3], size, opacity, rotation);
1275 void Terrain::MakeDecalLock(int type, XYZ where, int whichx, int whichy, float size, float opacity, float rotation)
1278 static float placex, placez;
1283 rot = getLighting(where.x, where.z);
1284 decalbrightness[numdecals] = (rot.x + rot.y + rot.z) / 3;
1285 if (decalbrightness[numdecals] < .4)decalbrightness[numdecals] = .4;
1287 if (environment == grassyenvironment) {
1288 decalbrightness[numdecals] *= .6;
1291 if (decalbrightness[numdecals] > 1)decalbrightness[numdecals] = 1;
1292 decalbright = decalbrightness[numdecals];
1294 decalposition[numdecals] = where;
1295 decaltype[numdecals] = type;
1296 decalopacity[numdecals] = opacity;
1297 decalrotation[numdecals] = rotation;
1298 decalalivetime[numdecals] = 0;
1300 placex = (float)whichx * scale + scale;
1301 placez = (float)whichy * scale;
1303 decaltexcoords[numdecals][0][0] = (placex - where.x) / size / 2 + .5;
1304 decaltexcoords[numdecals][0][1] = (placez - where.z) / size / 2 + .5;
1306 decalvertex[numdecals][0].x = placex;
1307 decalvertex[numdecals][0].z = placez;
1308 decalvertex[numdecals][0].y = heightmap[whichx + 1][whichy] * scale + .01;
1311 placex = (float)whichx * scale + scale;
1312 placez = (float)whichy * scale + scale;
1314 decaltexcoords[numdecals][1][0] = (placex - where.x) / size / 2 + .5;
1315 decaltexcoords[numdecals][1][1] = (placez - where.z) / size / 2 + .5;
1317 decalvertex[numdecals][1].x = placex;
1318 decalvertex[numdecals][1].z = placez;
1319 decalvertex[numdecals][1].y = heightmap[whichx + 1][whichy + 1] * scale + .01;
1322 placex = (float)whichx * scale;
1323 placez = (float)whichy * scale + scale;
1325 decaltexcoords[numdecals][2][0] = (placex - where.x) / size / 2 + .5;
1326 decaltexcoords[numdecals][2][1] = (placez - where.z) / size / 2 + .5;
1328 decalvertex[numdecals][2].x = placex;
1329 decalvertex[numdecals][2].z = placez;
1330 decalvertex[numdecals][2].y = heightmap[whichx][whichy + 1] * scale + .01;
1332 if (decalrotation[numdecals]) {
1333 for (int i = 0; i < 3; i++) {
1335 rot.x = decaltexcoords[numdecals][i][0] - .5;
1336 rot.z = decaltexcoords[numdecals][i][1] - .5;
1337 rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1338 decaltexcoords[numdecals][i][0] = rot.x + .5;
1339 decaltexcoords[numdecals][i][1] = rot.z + .5;
1343 if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1344 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1345 if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1346 if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1))
1347 if (numdecals < max_decals - 1)numdecals++;
1349 decalbrightness[numdecals] = decalbright;
1351 decalposition[numdecals] = where;
1352 decaltype[numdecals] = type;
1353 decalopacity[numdecals] = opacity;
1354 decalrotation[numdecals] = rotation;
1355 decalalivetime[numdecals] = 0;
1357 placex = (float)whichx * scale + scale;
1358 placez = (float)whichy * scale;
1360 decaltexcoords[numdecals][0][0] = (placex - where.x) / size / 2 + .5;
1361 decaltexcoords[numdecals][0][1] = (placez - where.z) / size / 2 + .5;
1363 decalvertex[numdecals][0].x = placex;
1364 decalvertex[numdecals][0].z = placez;
1365 decalvertex[numdecals][0].y = heightmap[whichx + 1][whichy] * scale + .01;
1368 placex = (float)whichx * scale;
1369 placez = (float)whichy * scale;
1371 decaltexcoords[numdecals][1][0] = (placex - where.x) / size / 2 + .5;
1372 decaltexcoords[numdecals][1][1] = (placez - where.z) / size / 2 + .5;
1374 decalvertex[numdecals][1].x = placex;
1375 decalvertex[numdecals][1].z = placez;
1376 decalvertex[numdecals][1].y = heightmap[whichx][whichy] * scale + .01;
1379 placex = (float)whichx * scale;
1380 placez = (float)whichy * scale + scale;
1382 decaltexcoords[numdecals][2][0] = (placex - where.x) / size / 2 + .5;
1383 decaltexcoords[numdecals][2][1] = (placez - where.z) / size / 2 + .5;
1385 decalvertex[numdecals][2].x = placex;
1386 decalvertex[numdecals][2].z = placez;
1387 decalvertex[numdecals][2].y = heightmap[whichx][whichy + 1] * scale + .01;
1389 if (decalrotation[numdecals]) {
1390 for (int i = 0; i < 3; i++) {
1392 rot.x = decaltexcoords[numdecals][i][0] - .5;
1393 rot.z = decaltexcoords[numdecals][i][1] - .5;
1394 rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1395 decaltexcoords[numdecals][i][0] = rot.x + .5;
1396 decaltexcoords[numdecals][i][1] = rot.z + .5;
1400 if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1401 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1402 if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1403 if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1))
1404 if (numdecals < max_decals - 1)numdecals++;
1408 void Terrain::DoLighting()
1410 static int i, j, k, todivide;
1411 static float brightness, total;
1412 static XYZ blank, terrainpoint, lightloc;
1413 lightloc = light.location;
1414 Normalise(&lightloc);
1416 for (i = 0; i < size; i++) {
1417 for (j = 0; j < size; j++) {
1418 terrainpoint.x = (float)i * scale;
1419 terrainpoint.z = (float)j * scale;
1420 terrainpoint.y = heightmap[i][j] * scale + .1;
1422 if(lineTerrain(lightlocation*10+terrainpoint,terrainpoint,&blank)==-1)
1424 brightness = dotproduct(&lightloc, &normals[i][j]);
1426 if (brightness > 1)brightness = 1;
1427 if (brightness < 0)brightness = 0;
1429 colors[i][j][0] = light.color[0] * brightness + light.ambient[0];
1430 colors[i][j][1] = light.color[1] * brightness + light.ambient[1];
1431 colors[i][j][2] = light.color[2] * brightness + light.ambient[2];
1433 if (colors[i][j][0] > 1)colors[i][j][0] = 1;
1434 if (colors[i][j][1] > 1)colors[i][j][1] = 1;
1435 if (colors[i][j][2] > 1)colors[i][j][2] = 1;
1436 if (colors[i][j][0] < 0)colors[i][j][0] = 0;
1437 if (colors[i][j][1] < 0)colors[i][j][1] = 0;
1438 if (colors[i][j][2] < 0)colors[i][j][2] = 0;
1443 for (i = 0; i < size; i++) {
1444 for (j = 0; j < size; j++) {
1445 for (k = 0; k < 3; k++) {
1449 total += colors[j][i - 1][k];
1452 if (i != size - 1) {
1453 total += colors[j][i + 1][k];
1457 total += colors[j - 1][i][k];
1460 if (j != size - 1) {
1461 total += colors[j + 1][i][k];
1464 if (i != 0 && j != 0) {
1465 total += colors[j - 1][i - 1][k];
1468 if (i != size - 1 && j != 0) {
1469 total += colors[j - 1][i + 1][k];
1472 if (j != size - 1 && i != size - 1) {
1473 total += colors[j + 1][i + 1][k];
1476 if (j != size - 1 && i != 0) {
1477 total += colors[j + 1][i - 1][k];
1480 total += colors[j][i][k];
1483 colors[j][i][k] = total / todivide;
1489 void Terrain::DoShadows()
1491 static int i, j, k, l, todivide;
1492 static float brightness, total;
1493 static XYZ testpoint, testpoint2, terrainpoint, lightloc, col;
1494 lightloc = light.location;
1495 if (!skyboxtexture) {
1499 if (skyboxtexture && tutoriallevel) {
1505 Normalise(&lightloc);
1507 for (i = 0; i < size; i++) {
1508 for (j = 0; j < size; j++) {
1509 terrainpoint.x = (float)(i) * scale;
1510 terrainpoint.z = (float)(j) * scale;
1511 terrainpoint.y = heightmap[i][j] * scale;
1514 patchx = (float)(i) * subdivision / size;
1515 patchz = (float)(j) * subdivision / size;
1516 if (patchobjectnum[patchx][patchz]) {
1517 for (k = 0; k < patchobjectnum[patchx][patchz]; k++) {
1518 l = patchobjects[patchx][patchz][k];
1519 if (objects.type[l] != treetrunktype) {
1520 testpoint = terrainpoint;
1521 testpoint2 = terrainpoint + lightloc * 50 * (1 - shadowed);
1522 if (objects.model[l].LineCheck(&testpoint, &testpoint2, &col, &objects.position[l], &objects.yaw[l]) != -1) {
1523 shadowed = 1 - (findDistance(&terrainpoint, &col) / 50);
1527 if (visibleloading) Game::LoadingScreen();
1529 brightness = dotproduct(&lightloc, &normals[i][j]);
1530 if (shadowed)brightness *= 1 - shadowed;
1532 if (brightness > 1)brightness = 1;
1533 if (brightness < 0)brightness = 0;
1535 colors[i][j][0] = light.color[0] * brightness + light.ambient[0];
1536 colors[i][j][1] = light.color[1] * brightness + light.ambient[1];
1537 colors[i][j][2] = light.color[2] * brightness + light.ambient[2];
1539 if (colors[i][j][0] > 1)colors[i][j][0] = 1;
1540 if (colors[i][j][1] > 1)colors[i][j][1] = 1;
1541 if (colors[i][j][2] > 1)colors[i][j][2] = 1;
1542 if (colors[i][j][0] < 0)colors[i][j][0] = 0;
1543 if (colors[i][j][1] < 0)colors[i][j][1] = 0;
1544 if (colors[i][j][2] < 0)colors[i][j][2] = 0;
1548 if (visibleloading) Game::LoadingScreen();
1551 for (i = 0; i < size; i++) {
1552 for (j = 0; j < size; j++) {
1553 for (k = 0; k < 3; k++) {
1557 total += colors[j][i - 1][k];
1560 if (i != size - 1) {
1561 total += colors[j][i + 1][k];
1565 total += colors[j - 1][i][k];
1568 if (j != size - 1) {
1569 total += colors[j + 1][i][k];
1572 if (i != 0 && j != 0) {
1573 total += colors[j - 1][i - 1][k];
1576 if (i != size - 1 && j != 0) {
1577 total += colors[j - 1][i + 1][k];
1580 if (j != size - 1 && i != size - 1) {
1581 total += colors[j + 1][i + 1][k];
1584 if (j != size - 1 && i != 0) {
1585 total += colors[j + 1][i - 1][k];
1588 total += colors[j][i][k];
1591 colors[j][i][k] = total / todivide;
1596 for (i = 0; i < subdivision; i++) {
1597 for (j = 0; j < subdivision; j++) {
1598 UpdateVertexArray(i, j);
1607 memset(patchobjectnum, 0, sizeof(patchobjectnum));
1608 memset(patchobjects, 0, sizeof(patchobjects));
1612 memset(heightmap, 0, sizeof(heightmap));
1613 memset(normals, 0, sizeof(normals));
1614 memset(facenormals, 0, sizeof(facenormals));
1615 memset(triangles, 0, sizeof(triangles));
1616 memset(colors, 0, sizeof(colors));
1617 memset(opacityother, 0, sizeof(opacityother));
1618 memset(texoffsetx, 0, sizeof(texoffsetx));
1619 memset(texoffsety, 0, sizeof(texoffsety));
1620 memset(numtris, 0, sizeof(numtris));
1621 memset(textureness, 0, sizeof(textureness));
1623 memset(vArray, 0, sizeof(vArray));
1625 memset(visible, 0, sizeof(visible));
1626 memset(avgypatch, 0, sizeof(avgypatch));
1627 memset(maxypatch, 0, sizeof(maxypatch));
1628 memset(minypatch, 0, sizeof(minypatch));
1629 memset(heightypatch, 0, sizeof(heightypatch));
1633 memset(decaltexcoords, 0, sizeof(decaltexcoords));
1634 memset(decalvertex, 0, sizeof(decalvertex));
1635 memset(decaltype, 0, sizeof(decaltype));
1636 memset(decalopacity, 0, sizeof(decalopacity));
1637 memset(decalrotation, 0, sizeof(decalrotation));
1638 memset(decalalivetime, 0, sizeof(decalalivetime));
1639 memset(decalbrightness, 0, sizeof(decalbrightness));
1640 memset(decalposition, 0, sizeof(decalposition));
1645 terraintexture.destroy();
1646 shadowtexture.destroy();
1647 bodyprinttexture.destroy();
1648 footprinttexture.destroy();
1649 bloodtexture.destroy();
1650 bloodtexture2.destroy();
1651 breaktexture.destroy();