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 lightambient[3],lightbrightness[3];
28 extern float fadestart;
29 extern int environment;
30 extern float texscale;
32 extern float multiplier;
33 extern FRUSTUM frustum;
34 extern float texdetail,terraindetail;
37 extern float blurness;
38 extern float targetblurness;
39 extern Objects objects;
40 extern TGAImageRec texture;
42 extern bool visibleloading;
43 extern bool skyboxtexture;
44 extern int tutoriallevel;
48 int Terrain::lineTerrain(XYZ p1,XYZ p2, XYZ *p)
51 static float distance;
52 static float olddistance;
53 static int intersecting;
54 static int firstintersecting;
56 static int startx,starty;
59 static int numtris=(size-1)*(size-1)*2;
60 static float highest,lowest;
76 if(startx>endx){i=endx;endx=startx;startx=i;}
77 if(starty>endy){i=endy;endy=starty;starty=i;}
81 if(endx>size-1)endx=size-1;
82 if(endy>size-1)endy=size-1;
84 for(i=startx;i<=endx;i++){
85 for(j=starty;j<=endy;j++){
89 if(heightmap[i+k][j]>highest)highest=heightmap[i+k][j];
90 if(heightmap[i+k][j]<lowest)lowest=heightmap[i+k][j];
91 if(heightmap[i+k][j+1]>highest)highest=heightmap[i+k][j+1];
92 if(heightmap[i+k][j+1]<lowest)lowest=heightmap[i+k][j+1];
94 if((p1.y<=highest||p2.y<=highest)&&(p1.y>=lowest||p2.y>=lowest)){
96 triangles[0].y=heightmap[i][j];
100 triangles[1].y=heightmap[i][j+1];
104 triangles[2].y=heightmap[i+1][j];
107 intersecting=LineFacet(p1,p2,triangles[0],triangles[1],triangles[2],&point);
108 distance=findDistancefast(&p1,&point);
109 if((distance<olddistance||firstintersecting==-1)&&intersecting==1){olddistance=distance; firstintersecting=1; *p=point;}
112 triangles[0].y=heightmap[i+1][j];
116 triangles[1].y=heightmap[i][j+1];
120 triangles[2].y=heightmap[i+1][j+1];
123 intersecting=LineFacet(p1,p2,triangles[0],triangles[1],triangles[2],&point);
124 distance=findDistancefast(&p1,&point);
125 if((distance<olddistance||firstintersecting==-1)&&intersecting==1){olddistance=distance; firstintersecting=1; *p=point;}
129 return firstintersecting;
132 void Terrain::UpdateTransparency(int whichx, int whichy){
134 static int i,j,a,b,c,d,patch_size,stepsize;
135 static float distance;
137 static float viewdistsquared;
139 viewdistsquared=viewdistance*viewdistance;
140 patch_size=size/subdivision;
143 c=whichx*patch_elements+whichy*patch_elements*subdivision;
145 for(i=patch_size*whichx;i<patch_size*(whichx+1)+1;i+=stepsize){
146 for(j=patch_size*whichy;j<patch_size*(whichy+1)+1;j+=stepsize){
150 vertex.y=heightmap[i][j]*scale;
151 distance=findDistancefast(&viewer,&vertex);
152 if(distance>viewdistsquared)distance=viewdistsquared;
153 colors[i][j][3]=(viewdistsquared-(distance-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
158 for(i=patch_size*whichx;i<patch_size*(whichx+1);i+=stepsize){
159 for(j=patch_size*whichy;j<patch_size*(whichy+1);j+=stepsize){
160 a=(i-(patch_size*whichx))/stepsize;
161 b=(j-(patch_size*whichy))/stepsize;
162 d=(a*54)+(b*54*patch_size/stepsize);
163 vArray[d+c+6]=colors[i][j][3];
165 vArray[d+c+15]=colors[i][j+stepsize][3];
167 vArray[d+c+24]=colors[i+stepsize][j][3];
169 vArray[d+c+33]=colors[i+stepsize][j][3];
171 vArray[d+c+42]=colors[i][j+stepsize][3];
173 vArray[d+c+51]=colors[i+stepsize][j+stepsize][3];
178 void Terrain::UpdateTransparencyother(int whichx, int whichy){
180 static int i,j,a,b,c,d,patch_size,stepsize;
181 static float distance;
183 patch_size=size/subdivision;
186 c=whichx*patch_elements+whichy*patch_elements*subdivision;
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]*opacityother[i][j];
195 vArray[d+c+15]=colors[i][j+stepsize][3]*opacityother[i][j+stepsize];
197 vArray[d+c+24]=colors[i+stepsize][j][3]*opacityother[i+stepsize][j];
199 vArray[d+c+33]=colors[i+stepsize][j][3]*opacityother[i+stepsize][j];
201 vArray[d+c+42]=colors[i][j+stepsize][3]*opacityother[i][j+stepsize];
203 vArray[d+c+51]=colors[i+stepsize][j+stepsize][3]*opacityother[i+stepsize][j+stepsize];
208 void Terrain::UpdateTransparencyotherother(int whichx, int whichy){
210 static int i,j,a,b,c,d,patch_size,stepsize;
211 static float distance;
213 static float viewdistsquared;
215 viewdistsquared=viewdistance*viewdistance;
216 patch_size=size/subdivision;
219 c=whichx*patch_elements+whichy*patch_elements*subdivision;
221 for(i=patch_size*whichx;i<patch_size*(whichx+1)+1;i+=stepsize){
222 for(j=patch_size*whichy;j<patch_size*(whichy+1)+1;j+=stepsize){
226 vertex.y=heightmap[i][j]*scale;
227 distance=findDistancefast(&viewer,&vertex);
228 if(distance>viewdistsquared)distance=viewdistsquared;
229 colors[i][j][3]=(viewdistsquared-(distance-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
234 for(i=patch_size*whichx;i<patch_size*(whichx+1);i+=stepsize){
235 for(j=patch_size*whichy;j<patch_size*(whichy+1);j+=stepsize){
236 a=(i-(patch_size*whichx))/stepsize;
237 b=(j-(patch_size*whichy))/stepsize;
238 d=(a*54)+(b*54*patch_size/stepsize);
239 vArray[d+c+6]=colors[i][j][3];
241 vArray[d+c+15]=colors[i][j+stepsize][3];
243 vArray[d+c+24]=colors[i+stepsize][j][3];
245 vArray[d+c+33]=colors[i+stepsize][j][3];
247 vArray[d+c+42]=colors[i][j+stepsize][3];
249 vArray[d+c+51]=colors[i+stepsize][j+stepsize][3];
254 void Terrain::UpdateVertexArray(int whichx, int whichy){
255 static int i,j,a,b,c,patch_size,stepsize;
258 numtris[whichx][whichy]=0;
260 patch_size=size/subdivision;
263 c=whichx*patch_elements+whichy*patch_elements*subdivision;
264 for(i=patch_size*whichx;i<patch_size*(whichx+1);i+=stepsize){
265 for(j=patch_size*whichy;j<patch_size*(whichy+1);j+=stepsize){
266 a=(i-((float)size/subdivision*(float)whichx))/stepsize;
267 b=(j-((float)size/subdivision*(float)whichy))/stepsize;
268 vArray[(a*54)+(b*54*patch_size/stepsize)+c+0]=i*scale;
269 vArray[(a*54)+(b*54*patch_size/stepsize)+c+1]=heightmap[i][j]*scale;
270 vArray[(a*54)+(b*54*patch_size/stepsize)+c+2]=j*scale;
271 vArray[(a*54)+(b*54*patch_size/stepsize)+c+3]=colors[i][j][0];
272 vArray[(a*54)+(b*54*patch_size/stepsize)+c+4]=colors[i][j][1];
273 vArray[(a*54)+(b*54*patch_size/stepsize)+c+5]=colors[i][j][2];
274 vArray[(a*54)+(b*54*patch_size/stepsize)+c+6]=colors[i][j][3];
275 vArray[(a*54)+(b*54*patch_size/stepsize)+c+7]=i*scale*texscale+texoffsetx[i][j];
276 vArray[(a*54)+(b*54*patch_size/stepsize)+c+8]=j*scale*texscale+texoffsety[i][j];
278 vArray[(a*54)+(b*54*patch_size/stepsize)+c+9]=i*scale;
279 vArray[(a*54)+(b*54*patch_size/stepsize)+c+10]=heightmap[i][j+stepsize]*scale;
280 vArray[(a*54)+(b*54*patch_size/stepsize)+c+11]=j*scale+stepsize*scale;
281 vArray[(a*54)+(b*54*patch_size/stepsize)+c+12]=colors[i][j+stepsize][0];
282 vArray[(a*54)+(b*54*patch_size/stepsize)+c+13]=colors[i][j+stepsize][1];
283 vArray[(a*54)+(b*54*patch_size/stepsize)+c+14]=colors[i][j+stepsize][2];
284 vArray[(a*54)+(b*54*patch_size/stepsize)+c+15]=colors[i][j+stepsize][3];
285 vArray[(a*54)+(b*54*patch_size/stepsize)+c+16]=i*scale*texscale+texoffsetx[i][j+stepsize];
286 vArray[(a*54)+(b*54*patch_size/stepsize)+c+17]=j*scale*texscale+stepsize*scale*texscale+texoffsety[i][j+stepsize];
288 vArray[(a*54)+(b*54*patch_size/stepsize)+c+18]=i*scale+stepsize*scale;
289 vArray[(a*54)+(b*54*patch_size/stepsize)+c+19]=heightmap[i+stepsize][j]*scale;
290 vArray[(a*54)+(b*54*patch_size/stepsize)+c+20]=j*scale;
291 vArray[(a*54)+(b*54*patch_size/stepsize)+c+21]=colors[i+stepsize][j][0];
292 vArray[(a*54)+(b*54*patch_size/stepsize)+c+22]=colors[i+stepsize][j][1];
293 vArray[(a*54)+(b*54*patch_size/stepsize)+c+23]=colors[i+stepsize][j][2];
294 vArray[(a*54)+(b*54*patch_size/stepsize)+c+24]=colors[i+stepsize][j][3];
295 vArray[(a*54)+(b*54*patch_size/stepsize)+c+25]=i*scale*texscale+stepsize*scale*texscale+texoffsetx[i+stepsize][j];
296 vArray[(a*54)+(b*54*patch_size/stepsize)+c+26]=j*scale*texscale+texoffsety[i+stepsize][j];
298 vArray[(a*54)+(b*54*patch_size/stepsize)+c+27]=i*scale+stepsize*scale;
299 vArray[(a*54)+(b*54*patch_size/stepsize)+c+28]=heightmap[i+stepsize][j]*scale;
300 vArray[(a*54)+(b*54*patch_size/stepsize)+c+29]=j*scale;
301 vArray[(a*54)+(b*54*patch_size/stepsize)+c+30]=colors[i+stepsize][j][0];
302 vArray[(a*54)+(b*54*patch_size/stepsize)+c+31]=colors[i+stepsize][j][1];
303 vArray[(a*54)+(b*54*patch_size/stepsize)+c+32]=colors[i+stepsize][j][2];
304 vArray[(a*54)+(b*54*patch_size/stepsize)+c+33]=colors[i+stepsize][j][3];
305 vArray[(a*54)+(b*54*patch_size/stepsize)+c+34]=i*scale*texscale+stepsize*scale*texscale+texoffsetx[i+stepsize][j];
306 vArray[(a*54)+(b*54*patch_size/stepsize)+c+35]=j*scale*texscale+texoffsety[i+stepsize][j];
308 vArray[(a*54)+(b*54*patch_size/stepsize)+c+36]=i*scale;
309 vArray[(a*54)+(b*54*patch_size/stepsize)+c+37]=heightmap[i][j+stepsize]*scale;
310 vArray[(a*54)+(b*54*patch_size/stepsize)+c+38]=j*scale+stepsize*scale;
311 vArray[(a*54)+(b*54*patch_size/stepsize)+c+39]=colors[i][j+stepsize][0];
312 vArray[(a*54)+(b*54*patch_size/stepsize)+c+40]=colors[i][j+stepsize][1];
313 vArray[(a*54)+(b*54*patch_size/stepsize)+c+41]=colors[i][j+stepsize][2];
314 vArray[(a*54)+(b*54*patch_size/stepsize)+c+42]=colors[i][j+stepsize][3];
315 vArray[(a*54)+(b*54*patch_size/stepsize)+c+43]=i*scale*texscale+texoffsetx[i][j+stepsize];
316 vArray[(a*54)+(b*54*patch_size/stepsize)+c+44]=j*scale*texscale+stepsize*scale*texscale+texoffsety[i][j+stepsize];
318 vArray[(a*54)+(b*54*patch_size/stepsize)+c+45]=i*scale+stepsize*scale;
319 vArray[(a*54)+(b*54*patch_size/stepsize)+c+46]=heightmap[i+stepsize][j+stepsize]*scale;
320 vArray[(a*54)+(b*54*patch_size/stepsize)+c+47]=j*scale+stepsize*scale;
321 vArray[(a*54)+(b*54*patch_size/stepsize)+c+48]=colors[i+stepsize][j+stepsize][0];
322 vArray[(a*54)+(b*54*patch_size/stepsize)+c+49]=colors[i+stepsize][j+stepsize][1];
323 vArray[(a*54)+(b*54*patch_size/stepsize)+c+50]=colors[i+stepsize][j+stepsize][2];
324 vArray[(a*54)+(b*54*patch_size/stepsize)+c+51]=colors[i+stepsize][j+stepsize][3];
325 vArray[(a*54)+(b*54*patch_size/stepsize)+c+52]=i*scale*texscale+stepsize*scale*texscale+texoffsetx[i+stepsize][j+stepsize];
326 vArray[(a*54)+(b*54*patch_size/stepsize)+c+53]=j*scale*texscale+stepsize*scale*texscale+texoffsety[i+stepsize][j+stepsize];
327 numtris[whichx][whichy]+=2;
331 maxypatch[whichx][whichy]=-10000;
332 minypatch[whichx][whichy]=10000;
333 for(a=0;a<size/subdivision;a++){
334 for(b=0;b<size/subdivision;b++){
335 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;
336 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;
339 heightypatch[whichx][whichy]=(maxypatch[whichx][whichy]-minypatch[whichx][whichy]);
340 if(heightypatch[whichx][whichy]<size/subdivision*scale)heightypatch[whichx][whichy]=size/subdivision*scale;
341 avgypatch[whichx][whichy]=(minypatch[whichx][whichy]+maxypatch[whichx][whichy])/2;
343 for(i=whichx*size/subdivision;i<(whichx+1)*size/subdivision-1;i++){
344 for(j=whichy*size/subdivision;j<(whichy+1)*size/subdivision-1;j++){
345 triangles[(i*(size-1)*2)+(j*2)][0].x=i*scale;
346 triangles[(i*(size-1)*2)+(j*2)][0].y=heightmap[i][j]*scale;
347 triangles[(i*(size-1)*2)+(j*2)][0].z=j*scale;
349 triangles[(i*(size-1)*2)+(j*2)][1].x=i*scale;
350 triangles[(i*(size-1)*2)+(j*2)][1].y=heightmap[i][j+1]*scale;
351 triangles[(i*(size-1)*2)+(j*2)][1].z=j*scale+scale;
353 triangles[(i*(size-1)*2)+(j*2)][2].x=i*scale+1*scale;
354 triangles[(i*(size-1)*2)+(j*2)][2].y=heightmap[i+1][j]*scale;
355 triangles[(i*(size-1)*2)+(j*2)][2].z=j*scale;
357 triangles[(i*(size-1)*2)+(j*2)+1][0].x=i*scale+1*scale;
358 triangles[(i*(size-1)*2)+(j*2)+1][0].y=heightmap[i+1][j]*scale;
359 triangles[(i*(size-1)*2)+(j*2)+1][0].z=j*scale;
361 triangles[(i*(size-1)*2)+(j*2)+1][1].x=i*scale;
362 triangles[(i*(size-1)*2)+(j*2)+1][1].y=heightmap[i][j+1]*scale;
363 triangles[(i*(size-1)*2)+(j*2)+1][1].z=j*scale+1*scale;
365 triangles[(i*(size-1)*2)+(j*2)+1][2].x=i*scale+1*scale;
366 triangles[(i*(size-1)*2)+(j*2)+1][2].y=heightmap[i+1][j+1]*scale;
367 triangles[(i*(size-1)*2)+(j*2)+1][2].z=j*scale+1*scale;
374 bool Terrain::load(const char *fileName)
378 static float patch_size;
380 float temptexdetail=texdetail;
381 texdetail=terraindetail;
382 //LoadTGA( fileName );
384 // Fixing filename so that it works with its own os
385 char * FixedFN = ConvertFileName(fileName);
387 unsigned char fileNamep[256];
388 CopyCStringToPascal(FixedFN, fileNamep);
390 upload_image( fileNamep ,0);
394 int bytesPerPixel=texture.bpp/8;
397 for(i=0;i<(long)(texture.sizeY*texture.sizeX*bytesPerPixel);i++){
399 texture.data[tempnum]=texture.data[i];
405 if(visibleloading)pgame->LoadingScreen();
407 texdetail=temptexdetail;
411 /*if ( texture.bpp == 24 )
416 glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
418 if(!terraintexture)glGenTextures( 1, &terraintexture );
419 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
421 glBindTexture( GL_TEXTURE_2D, terraintexture);
422 //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
423 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
425 gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, type, GL_UNSIGNED_BYTE, texture.data );
432 heightmap[size-1-i][j]=(float)((texture.data[(i+(j*size))*texture.bpp/8]))/5/terraindetail;
437 if(visibleloading)pgame->LoadingScreen();
441 for(i=0;i<subdivision;i++){
442 for(j=0;j<subdivision;j++){
443 textureness[i][j]=-1;
446 if(visibleloading)pgame->LoadingScreen();
453 texoffsetx[i][j]=(float)abs(Random()%100)/1200/scale*3;
454 texoffsety[i][j]=(float)abs(Random()%100)/1200/scale*3;
457 if(environment==snowyenvironment){
458 if(j!=0&&heightmap[i][j]-heightmap[i][j-1]>slopeness){ slopeness=heightmap[i][j]-heightmap[i][j-1];}
459 opacityother[i][j]=slopeness*slopeness*2;
460 if(opacityother[i][j]>1)opacityother[i][j]=1;
461 opacityother[i][j]-=(float)abs(Random()%100)/300;
463 if(environment==desertenvironment){
464 if(j!=0&&heightmap[i][j]-heightmap[i][j-1]>slopeness){ slopeness=heightmap[i][j]-heightmap[i][j-1];}
465 opacityother[i][j]=slopeness*slopeness*2;
466 if(opacityother[i][j]>1)opacityother[i][j]=1;
467 opacityother[i][j]-=(float)abs(Random()%100)/300;
469 if(environment==grassyenvironment){
470 if(i!=0&&heightmap[i][j]-heightmap[i-1][j]>slopeness){ slopeness=heightmap[i][j]-heightmap[i-1][j];}
471 if(j!=0&&heightmap[i][j]-heightmap[i][j-1]>slopeness){ slopeness=heightmap[i][j]-heightmap[i][j-1];}
472 if(i<size-1&&heightmap[i][j]-heightmap[i+1][j]>slopeness){ slopeness=heightmap[i][j]-heightmap[i+1][j];}
473 if(j<size-1&&heightmap[i][j]-heightmap[i][j+1]>slopeness){ slopeness=heightmap[i][j]-heightmap[i][j+1];}
474 opacityother[i][j]=slopeness*slopeness*10;
475 if(opacityother[i][j]>1)opacityother[i][j]=1;
476 opacityother[i][j]-=(float)abs(Random()%100)/100;
480 if(visibleloading)pgame->LoadingScreen();
484 if(environment==snowyenvironment){
485 heightmap[i][j]-=opacityother[i][j];
487 if(environment==desertenvironment){
488 heightmap[i][j]-=opacityother[i][j];
492 if(visibleloading)pgame->LoadingScreen();
496 //Smooth opacityother
501 if(i!=0){ total+=opacityother[j][i-1]; todivide++;}
502 if(i!=size-1){ total+=opacityother[j][i+1]; todivide++;}
503 if(j!=0){ total+=opacityother[j-1][i]; todivide++;}
504 if(j!=size-1){ total+=opacityother[j+1][i]; todivide++;}
505 if(i!=0&&j!=0){ total+=opacityother[j-1][i-1]; todivide++;}
506 if(i!=size-1&&j!=0){ total+=opacityother[j-1][i+1]; todivide++;}
507 if(j!=size-1&&i!=size-1){ total+=opacityother[j+1][i+1]; todivide++;}
508 if(j!=size-1&&i!=0){ total+=opacityother[j+1][i-1]; todivide++;}
509 total+=opacityother[j][i]; todivide++;
511 opacityother[j][i]=total/(float)todivide;
518 if(opacityother[i][j]<.1)opacityother[i][j]=0;
519 if(textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==-1){
520 if(!opacityother[i][j])textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=allfirst;
521 if(opacityother[i][j]==1)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=allsecond;
523 if(opacityother[i][j]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
524 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;
530 if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
531 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;
532 if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
533 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;
537 if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
538 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;
539 if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
540 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;
546 if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
547 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;
548 if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
549 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;
557 if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
558 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;
559 if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
560 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;
564 if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
565 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;
566 if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
567 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;
573 if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
574 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;
575 if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
576 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;
584 if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
585 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;
586 if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
587 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(visibleloading)pgame->LoadingScreen();
604 patch_size=size/subdivision;
605 patch_elements=(patch_size)*(patch_size)*54;
609 for(i=0;i<subdivision;i++){
610 for(j=0;j<subdivision;j++){
611 UpdateVertexArray(i,j);
618 void Terrain::CalculateNormals()
621 static XYZ facenormal;
622 static XYZ p,q,a,b,c;
624 for(i=0; i<size; i++){
625 for(j=0; j<size; j++){
632 for(i=0;i<size-1;i++){
633 for(j=0;j<size-1;j++){
638 b.y=heightmap[i][j+1];
641 c.y=heightmap[i+1][j];
651 CrossProduct(&p,&q,&facenormal);
653 facenormals[i][j]=facenormal;
655 normals[i][j]=normals[i][j]+facenormal;
656 normals[i][j+1]=normals[i][j+1]+facenormal;
657 normals[i+1][j]=normals[i+1][j]+facenormal;
661 a.y=heightmap[i+1][j];
664 b.y=heightmap[i][j+1];
667 c.y=heightmap[i+1][j+1];
677 CrossProduct(&p,&q,&facenormal);
679 normals[i+1][j+1]=normals[i+1][j+1]+facenormal;
680 normals[i][j+1]=normals[i][j+1]+facenormal;
681 normals[i+1][j]=normals[i+1][j]+facenormal;
683 Normalise(&facenormals[i][j]);
687 for(i=0; i<size; i++){
688 for(j=0; j<size; j++){
689 Normalise(&normals[i][j]);
690 normals[i][j]=normals[i][j];
695 void Terrain::drawpatch(int whichx, int whichy, float opacity){
696 if(opacity>=1)glDisable(GL_BLEND);
699 UpdateTransparency(whichx,whichy);
702 //Set up vertex array
703 glEnableClientState(GL_VERTEX_ARRAY);
704 glEnableClientState(GL_COLOR_ARRAY);
705 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
706 glVertexPointer(3, GL_FLOAT, 9*sizeof(GLfloat),&vArray[0+whichx*patch_elements+whichy*patch_elements*subdivision]);
707 glColorPointer(4,GL_FLOAT, 9*sizeof(GLfloat),&vArray[3+whichx*patch_elements+whichy*patch_elements*subdivision]);
708 glTexCoordPointer(2, GL_FLOAT, 9*sizeof(GLfloat),&vArray[7+whichx*patch_elements+whichy*patch_elements*subdivision]);
711 glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy]*3);
713 glDisableClientState(GL_VERTEX_ARRAY);
714 glDisableClientState(GL_COLOR_ARRAY);
715 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
718 void Terrain::drawpatchother(int whichx, int whichy, float opacity){
721 UpdateTransparency(whichx,whichy);
723 UpdateTransparencyother(whichx,whichy);
725 //Set up vertex array
726 glEnableClientState(GL_VERTEX_ARRAY);
727 glEnableClientState(GL_COLOR_ARRAY);
728 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
729 glVertexPointer(3, GL_FLOAT, 9*sizeof(GLfloat),&vArray[0+whichx*patch_elements+whichy*patch_elements*subdivision]);
730 glColorPointer(4,GL_FLOAT, 9*sizeof(GLfloat),&vArray[3+whichx*patch_elements+whichy*patch_elements*subdivision]);
731 glTexCoordPointer(2, GL_FLOAT, 9*sizeof(GLfloat),&vArray[7+whichx*patch_elements+whichy*patch_elements*subdivision]);
734 glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy]*3);
736 glDisableClientState(GL_VERTEX_ARRAY);
737 glDisableClientState(GL_COLOR_ARRAY);
738 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
741 void Terrain::drawpatchotherother(int whichx, int whichy, float opacity){
743 UpdateTransparencyotherother(whichx,whichy);
745 glMatrixMode(GL_TEXTURE);
751 //Set up vertex array
752 glEnableClientState(GL_VERTEX_ARRAY);
753 glEnableClientState(GL_COLOR_ARRAY);
754 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
755 glVertexPointer(3, GL_FLOAT, 9*sizeof(GLfloat),&vArray[0+whichx*patch_elements+whichy*patch_elements*subdivision]);
756 glColorPointer(4,GL_FLOAT, 9*sizeof(GLfloat),&vArray[3+whichx*patch_elements+whichy*patch_elements*subdivision]);
757 glTexCoordPointer(2, GL_FLOAT, 9*sizeof(GLfloat),&vArray[7+whichx*patch_elements+whichy*patch_elements*subdivision]);
760 glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy]*3);
762 glDisableClientState(GL_VERTEX_ARRAY);
763 glDisableClientState(GL_COLOR_ARRAY);
764 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
767 glMatrixMode(GL_MODELVIEW);
771 float Terrain::getHeight(float pointx, float pointz)
773 static float height1,height2;
774 static int tilex,tiley;
775 static XYZ startpoint,endpoint,intersect,triangle[3],average;
780 if(pointx>=size-1||pointz>=size-1||pointx<=0||pointz<=0)return 0;
794 triangle[0].y=heightmap[tilex][tiley];
796 triangle[1].x=tilex+1;
798 triangle[1].y=heightmap[tilex+1][tiley];
801 triangle[2].z=tiley+1;
802 triangle[2].y=heightmap[tilex][tiley+1];
804 if(!LineFacetd(&startpoint,&endpoint,&triangle[0],&triangle[1],&triangle[2],&intersect)){
805 triangle[0].x=tilex+1;
807 triangle[0].y=heightmap[tilex+1][tiley];
809 triangle[1].x=tilex+1;
810 triangle[1].z=tiley+1;
811 triangle[1].y=heightmap[tilex+1][tiley+1];
814 triangle[2].z=tiley+1;
815 triangle[2].y=heightmap[tilex][tiley+1];
816 LineFacetd(&startpoint,&endpoint,&triangle[0],&triangle[1],&triangle[2],&intersect);
818 return intersect.y*scale+getOpacity(pointx*scale,pointz*scale)/8;
820 //height1=heightmap[tilex][tiley]*(1-(pointx-tilex))+heightmap[tilex+1][tiley]*(pointx-tilex);
821 //height2=heightmap[tilex][tiley+1]*(1-(pointx-tilex))+heightmap[tilex+1][tiley+1]*(pointx-tilex);
823 //return height1*(1-(pointz-tiley))*scale+height2*(pointz-tiley)*scale;
826 float Terrain::getHeightExtrude(float pointx, float pointz,float point2x, float point2z)
828 static float height1,height2;
829 static int tilex,tiley;
830 static XYZ startpoint,endpoint,intersect,triangle[3],average;
837 if(pointx>=size-1||pointz>=size-1||pointx<=0||pointz<=0)return 0;
838 if(point2x>=size-1||point2z>=size-1||point2x<=0||point2z<=0)return 0;
840 startpoint.x=point2x;
842 startpoint.z=point2z;
852 triangle[0].y=heightmap[tilex][tiley];
854 triangle[1].x=tilex+1;
856 triangle[1].y=heightmap[tilex+1][tiley];
859 triangle[2].z=tiley+1;
860 triangle[2].y=heightmap[tilex][tiley+1];
864 mid=(triangle[0]+triangle[1]+triangle[2])/2;
866 triangle[0]=mid+(triangle[0]-mid)*10;
867 triangle[1]=mid+(triangle[0]-mid)*10;
868 triangle[2]=mid+(triangle[0]-mid)*10;
871 if(!LineFacetd(&startpoint,&endpoint,&triangle[0],&triangle[1],&triangle[2],&intersect)){
872 triangle[0].x=tilex+1;
874 triangle[0].y=heightmap[tilex+1][tiley];
876 triangle[1].x=tilex+1;
877 triangle[1].z=tiley+1;
878 triangle[1].y=heightmap[tilex+1][tiley+1];
881 triangle[2].z=tiley+1;
882 triangle[2].y=heightmap[tilex][tiley+1];
883 LineFacetd(&startpoint,&endpoint,&triangle[0],&triangle[1],&triangle[2],&intersect);
885 return intersect.y*scale+getOpacity(pointx*scale,pointz*scale)/8;
887 //height1=heightmap[tilex][tiley]*(1-(pointx-tilex))+heightmap[tilex+1][tiley]*(pointx-tilex);
888 //height2=heightmap[tilex][tiley+1]*(1-(pointx-tilex))+heightmap[tilex+1][tiley+1]*(pointx-tilex);
890 //return height1*(1-(pointz-tiley))*scale+height2*(pointz-tiley)*scale;
894 float Terrain::getOpacity(float pointx, float pointz)
896 static float height1,height2;
897 static int tilex,tiley;
902 if(pointx>=size-1||pointz>=size-1||pointx<=0||pointz<=0)return 0;
907 height1=opacityother[tilex][tiley]*(1-(pointx-tilex))+opacityother[tilex+1][tiley]*(pointx-tilex);
908 height2=opacityother[tilex][tiley+1]*(1-(pointx-tilex))+opacityother[tilex+1][tiley+1]*(pointx-tilex);
910 return height1*(1-(pointz-tiley))+height2*(pointz-tiley);
913 XYZ Terrain::getNormal(float pointx, float pointz)
915 static XYZ height1,height2,total;
916 static int tilex,tiley;
922 if(pointx>=size-1||pointz>=size-1||pointx<=0||pointz<=0)return height1;
926 height1=normals[tilex][tiley]*(1-(pointx-tilex))+normals[tilex+1][tiley]*(pointx-tilex);
927 height2=normals[tilex][tiley+1]*(1-(pointx-tilex))+normals[tilex+1][tiley+1]*(pointx-tilex);
928 total=height1*(1-(pointz-tiley))+height2*(pointz-tiley);
933 XYZ Terrain::getLighting(float pointx, float pointz)
935 static XYZ height1,height2;
936 static int tilex,tiley;
942 if(pointx>=size-1||pointz>=size-1||pointx<=0||pointz<=0)return height1;
946 height1.x=colors[tilex][tiley][0]*(1-(pointx-tilex))+colors[tilex+1][tiley][0]*(pointx-tilex);
947 height1.y=colors[tilex][tiley][1]*(1-(pointx-tilex))+colors[tilex+1][tiley][1]*(pointx-tilex);
948 height1.z=colors[tilex][tiley][2]*(1-(pointx-tilex))+colors[tilex+1][tiley][2]*(pointx-tilex);
949 height2.x=colors[tilex][tiley+1][0]*(1-(pointx-tilex))+colors[tilex+1][tiley+1][0]*(pointx-tilex);
950 height2.y=colors[tilex][tiley+1][1]*(1-(pointx-tilex))+colors[tilex+1][tiley+1][1]*(pointx-tilex);
951 height2.z=colors[tilex][tiley+1][2]*(1-(pointx-tilex))+colors[tilex+1][tiley+1][2]*(pointx-tilex);
953 return height1*(1-(pointz-tiley))+height2*(pointz-tiley);
956 void Terrain::draw(int layer)
959 static float opacity;
960 static XYZ terrainpoint;
961 static float distance[subdivision][subdivision];
963 static int beginx,endx;
964 static int beginz,endz;
966 static float patch_size=size/subdivision*scale;
967 static float viewdistsquared;
969 viewdistsquared=viewdistance*viewdistance;
972 beginx=(viewer.x-viewdistance)/(patch_size)-1;
973 if(beginx<0)beginx=0;
974 beginz=(viewer.z-viewdistance)/(patch_size)-1;
975 if(beginz<0)beginz=0;
977 endx=(viewer.x+viewdistance)/(patch_size)+1;
978 if(endx>subdivision)endx=subdivision;
979 endz=(viewer.z+viewdistance)/(patch_size)+1;
980 if(endz>subdivision)endz=subdivision;
983 for(i=beginx;i<endx;i++){
984 for(j=beginz;j<endz;j++){
985 terrainpoint.x=i*patch_size+(patch_size)/2;
986 terrainpoint.y=viewer.y;//heightmap[i][j]*scale;
987 terrainpoint.z=j*patch_size+(patch_size)/2;
988 distance[i][j]=findDistancefast(&viewer,&terrainpoint);
992 for(i=beginx;i<endx;i++){
993 for(j=beginz;j<endz;j++){
994 if(distance[i][j]<(viewdistance+patch_size)*(viewdistance+patch_size)){
996 if(distance[i][j]>viewdistsquared*fadestart-viewdistsquared)opacity=0;
997 if(opacity==1&&i!=subdivision)if(distance[i+1][j]>viewdistsquared*fadestart-viewdistsquared)opacity=0;
998 if(opacity==1&&j!=subdivision)if(distance[i][j+1]>viewdistsquared*fadestart-viewdistsquared)opacity=0;
999 if(opacity==1&&j!=subdivision&&i!=subdivision)if(distance[i+1][j+1]>viewdistsquared*fadestart-viewdistsquared)opacity=0;
1000 glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
1002 if(frustum.CubeInFrustum(i*patch_size+patch_size*.5,avgypatch[i][j],j*patch_size+patch_size*.5,heightypatch[i][j]/2))
1004 if(environment==desertenvironment&&distance[i][j]>viewdistsquared/4)glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, blurness);
1005 else if(environment==desertenvironment)glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
1006 if(!layer&&textureness[i][j]!=allsecond)drawpatch(i,j,opacity);
1007 if(layer==1&&textureness[i][j]!=allfirst)drawpatchother(i,j,opacity);
1008 if(layer==2&&textureness[i][j]!=allfirst)drawpatchotherother(i,j,opacity);
1014 if(environment==desertenvironment)glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
1017 void Terrain::drawdecals()
1021 static float distancemult;
1022 static int lasttype;
1024 static float patch_size=size/subdivision*scale;
1025 static float viewdistsquared;
1028 viewdistsquared=viewdistance*viewdistance;
1033 glDisable(GL_LIGHTING);
1034 glDisable(GL_CULL_FACE);
1035 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
1037 for(i=0;i<numdecals;i++){
1038 if(decaltype[i]==blooddecalfast&&decalalivetime[i]<2)decalalivetime[i]=2;
1039 if((decaltype[i]==shadowdecal||decaltype[i]==shadowdecalpermanent)&&decaltype[i]!=lasttype){
1040 glBindTexture( GL_TEXTURE_2D, shadowtexture);
1043 glAlphaFunc(GL_GREATER, 0.0001);
1044 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
1047 if(decaltype[i]==footprintdecal&&decaltype[i]!=lasttype){
1048 glBindTexture( GL_TEXTURE_2D, footprinttexture);
1051 glAlphaFunc(GL_GREATER, 0.0001);
1052 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
1055 if(decaltype[i]==bodyprintdecal&&decaltype[i]!=lasttype){
1056 glBindTexture( GL_TEXTURE_2D, bodyprinttexture);
1059 glAlphaFunc(GL_GREATER, 0.0001);
1060 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
1063 if((decaltype[i]==blooddecal||decaltype[i]==blooddecalslow)&&decaltype[i]!=lasttype){
1064 glBindTexture( GL_TEXTURE_2D, bloodtexture);
1067 glAlphaFunc(GL_GREATER, 0.15);
1068 glBlendFunc(GL_ONE,GL_ZERO);
1071 if((decaltype[i]==blooddecalfast)&&decaltype[i]!=lasttype){
1072 glBindTexture( GL_TEXTURE_2D, bloodtexture2);
1075 glAlphaFunc(GL_GREATER, 0.15);
1076 glBlendFunc(GL_ONE,GL_ZERO);
1079 if(decaltype[i]==shadowdecal||decaltype[i]==shadowdecalpermanent){
1080 distancemult=(viewdistsquared-(findDistancefast(&viewer,&decalposition[i])-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
1081 if(distancemult>=1)glColor4f(1,1,1,decalopacity[i]);
1082 if(distancemult<1)glColor4f(1,1,1,decalopacity[i]*distancemult);
1084 if(decaltype[i]==footprintdecal||decaltype[i]==bodyprintdecal){
1085 distancemult=(viewdistsquared-(findDistancefast(&viewer,&decalposition[i])-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
1086 if(distancemult>=1){
1087 glColor4f(1,1,1,decalopacity[i]);
1088 if(decalalivetime[i]>3)glColor4f(1,1,1,decalopacity[i]*(5-decalalivetime[i])/2);
1091 glColor4f(1,1,1,decalopacity[i]*distancemult);
1092 if(decalalivetime[i]>3)glColor4f(1,1,1,decalopacity[i]*(5-decalalivetime[i])/2*distancemult);
1095 if((decaltype[i]==blooddecal||decaltype[i]==blooddecalfast||decaltype[i]==blooddecalslow)){
1096 distancemult=(viewdistsquared-(findDistancefast(&viewer,&decalposition[i])-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
1097 if(distancemult>=1){
1098 glColor4f(decalbrightness[i],decalbrightness[i],decalbrightness[i],decalopacity[i]);
1099 if(decalalivetime[i]<4)glColor4f(decalbrightness[i],decalbrightness[i],decalbrightness[i],decalopacity[i]*decalalivetime[i]*.25);
1100 if(decalalivetime[i]>58)glColor4f(decalbrightness[i],decalbrightness[i],decalbrightness[i],decalopacity[i]*(60-decalalivetime[i])/2);
1103 glColor4f(decalbrightness[i],decalbrightness[i],decalbrightness[i],decalopacity[i]*distancemult);
1104 if(decalalivetime[i]<4)glColor4f(decalbrightness[i],decalbrightness[i],decalbrightness[i],decalopacity[i]*decalalivetime[i]*distancemult*.25);
1105 if(decalalivetime[i]>58)glColor4f(decalbrightness[i],decalbrightness[i],decalbrightness[i],decalopacity[i]*(60-decalalivetime[i])/2*distancemult);
1108 lasttype=decaltype[i];
1109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1110 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1112 glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
1114 glBegin(GL_TRIANGLES);
1115 for(int j=0;j<3;j++)
1117 glTexCoord2f(decaltexcoords[i][j][0], decaltexcoords[i][j][1]); glVertex3f(decalvertex[i][j].x,decalvertex[i][j].y,decalvertex[i][j].z);
1122 for(i=numdecals-1;i>=0;i--){
1123 decalalivetime[i]+=multiplier;
1124 if(decaltype[i]==blooddecalslow)decalalivetime[i]-=multiplier*2/3;
1125 if(decaltype[i]==blooddecalfast)decalalivetime[i]+=multiplier*4;
1126 if(decaltype[i]==shadowdecal)DeleteDecal(i);
1127 if(decaltype[i]==footprintdecal&&decalalivetime[i]>=5)DeleteDecal(i);
1128 if(decaltype[i]==bodyprintdecal&&decalalivetime[i]>=5)DeleteDecal(i);
1129 if((decaltype[i]==blooddecal||decaltype[i]==blooddecalfast||decaltype[i]==blooddecalslow)&&decalalivetime[i]>=60)DeleteDecal(i);
1131 glAlphaFunc(GL_GREATER, 0.0001);
1135 void Terrain::AddObject(XYZ where, float radius, int id)
1141 for(i=0;i<subdivision;i++){
1142 for(j=0;j<subdivision;j++){
1143 if(patchobjectnum[i][j]<300-1){
1145 points[0].x=(size/subdivision)*i;
1146 points[0].z=(size/subdivision)*j;
1147 points[0].y=heightmap[(int)points[0].x][(int)points[0].z];
1148 points[1].x=(size/subdivision)*(i+1);
1149 points[1].z=(size/subdivision)*j;
1150 points[1].y=heightmap[(int)points[1].x][(int)points[1].z];
1151 points[2].x=(size/subdivision)*(i+1);
1152 points[2].z=(size/subdivision)*(j+1);
1153 points[2].y=heightmap[(int)points[2].x][(int)points[2].z];
1154 points[3].x=(size/subdivision)*i;
1155 points[3].z=(size/subdivision)*(j+1);
1156 points[3].y=heightmap[(int)points[3].x][(int)points[3].z];
1157 points[0]*=scale*terraindetail;
1158 points[1]*=scale*terraindetail;
1159 points[2]*=scale*terraindetail;
1160 points[3]*=scale*terraindetail;
1161 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){
1162 patchobjects[i][j][patchobjectnum[i][j]]=id;
1163 patchobjectnum[i][j]++;
1171 void Terrain::DeleteDecal(int which)
1174 decaltype[which]=decaltype[numdecals-1];
1175 decalposition[which]=decalposition[numdecals-1];
1176 for(int i=0;i<3;i++){
1177 decalvertex[which][i]=decalvertex[numdecals-1][i];
1178 decaltexcoords[which][i][0]=decaltexcoords[numdecals-1][i][0];
1179 decaltexcoords[which][i][1]=decaltexcoords[numdecals-1][i][1];
1181 decalrotation[which]=decalrotation[numdecals-1];
1182 decalalivetime[which]=decalalivetime[numdecals-1];
1183 decalopacity[which]=decalopacity[numdecals-1];
1184 decalbrightness[which]=decalbrightness[numdecals-1];
1189 void Terrain::MakeDecal(int type, XYZ where, float size, float opacity, float rotation){
1191 if(opacity>0&&size>0){
1192 static int patchx[4];
1193 static int patchy[4];
1195 decaltexcoords[numdecals][0][0]=1;
1196 decaltexcoords[numdecals][0][1]=0;
1198 patchx[0]=(where.x+size)/scale;
1199 patchx[1]=(where.x-size)/scale;
1200 patchx[2]=(where.x-size)/scale;
1201 patchx[3]=(where.x+size)/scale;
1203 patchy[0]=(where.z-size)/scale;
1204 patchy[1]=(where.z-size)/scale;
1205 patchy[2]=(where.z+size)/scale;
1206 patchy[3]=(where.z+size)/scale;
1208 /*if(patchx[1]<subdivision-1&&patchy[1]<subdivision-1&&patchx[1]>0&&patchy[1]>0)
1209 if(patchx[2]<subdivision-1&&patchy[2]<subdivision-1&&patchx[2]>0&&patchy[2]>0)
1210 if(patchx[3]<subdivision-1&&patchy[3]<subdivision-1&&patchx[3]>0&&patchy[3]>0)
1211 if(patchx[0]<subdivision-1&&patchy[0]<subdivision-1&&patchx[0]>0&&patchy[0]>0){
1213 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])){
1214 MakeDecalLock(type,where,patchx[0],patchy[0],size,opacity,rotation);
1217 if((patchx[1]!=patchx[2]||patchy[1]!=patchy[2])&&(patchx[1]!=patchx[3]||patchy[1]!=patchy[3])){
1218 MakeDecalLock(type,where,patchx[1],patchy[1],size,opacity,rotation);
1221 if((patchx[2]!=patchx[3]||patchy[2]!=patchy[3])){
1222 MakeDecalLock(type,where,patchx[2],patchy[2],size,opacity,rotation);
1224 MakeDecalLock(type,where,patchx[3],patchy[3],size,opacity,rotation);
1230 void Terrain::MakeDecalLock(int type, XYZ where,int whichx, int whichy, float size, float opacity, float rotation){
1232 static float placex,placez;
1237 rot=getLighting(where.x,where.z);
1238 decalbrightness[numdecals]=(rot.x+rot.y+rot.z)/3;
1239 if(decalbrightness[numdecals]<.4)decalbrightness[numdecals]=.4;
1241 //if(type==blooddecal||type==blooddecalfast||type==blooddecalslow){
1242 if(environment==grassyenvironment){
1243 decalbrightness[numdecals]*=.6;
1247 if(decalbrightness[numdecals]>1)decalbrightness[numdecals]=1;
1248 decalbright=decalbrightness[numdecals];
1250 decalposition[numdecals]=where;
1251 decaltype[numdecals]=type;
1252 decalopacity[numdecals]=opacity;
1253 decalrotation[numdecals]=rotation;
1254 decalalivetime[numdecals]=0;
1256 placex=(float)whichx*scale+scale;
1257 placez=(float)whichy*scale;
1259 decaltexcoords[numdecals][0][0]=(placex-where.x)/size/2+.5;
1260 decaltexcoords[numdecals][0][1]=(placez-where.z)/size/2+.5;
1262 decalvertex[numdecals][0].x=placex;
1263 decalvertex[numdecals][0].z=placez;
1264 decalvertex[numdecals][0].y=heightmap[whichx+1][whichy]*scale+.01;
1267 placex=(float)whichx*scale+scale;
1268 placez=(float)whichy*scale+scale;
1270 decaltexcoords[numdecals][1][0]=(placex-where.x)/size/2+.5;
1271 decaltexcoords[numdecals][1][1]=(placez-where.z)/size/2+.5;
1273 decalvertex[numdecals][1].x=placex;
1274 decalvertex[numdecals][1].z=placez;
1275 decalvertex[numdecals][1].y=heightmap[whichx+1][whichy+1]*scale+.01;
1278 placex=(float)whichx*scale;
1279 placez=(float)whichy*scale+scale;
1281 decaltexcoords[numdecals][2][0]=(placex-where.x)/size/2+.5;
1282 decaltexcoords[numdecals][2][1]=(placez-where.z)/size/2+.5;
1284 decalvertex[numdecals][2].x=placex;
1285 decalvertex[numdecals][2].z=placez;
1286 decalvertex[numdecals][2].y=heightmap[whichx][whichy+1]*scale+.01;
1288 if(decalrotation[numdecals]){
1289 for(int i=0;i<3;i++){
1291 rot.x=decaltexcoords[numdecals][i][0]-.5;
1292 rot.z=decaltexcoords[numdecals][i][1]-.5;
1293 rot=DoRotation(rot,0,-decalrotation[numdecals],0);
1294 decaltexcoords[numdecals][i][0]=rot.x+.5;
1295 decaltexcoords[numdecals][i][1]=rot.z+.5;
1299 if(!(decaltexcoords[numdecals][0][0]<0&&decaltexcoords[numdecals][1][0]<0&&decaltexcoords[numdecals][2][0]<0))
1300 if(!(decaltexcoords[numdecals][0][1]<0&&decaltexcoords[numdecals][1][1]<0&&decaltexcoords[numdecals][2][1]<0))
1301 if(!(decaltexcoords[numdecals][0][0]>1&&decaltexcoords[numdecals][1][0]>1&&decaltexcoords[numdecals][2][0]>1))
1302 if(!(decaltexcoords[numdecals][0][1]>1&&decaltexcoords[numdecals][1][1]>1&&decaltexcoords[numdecals][2][1]>1))
1303 if(numdecals<max_decals-1)numdecals++;
1305 decalbrightness[numdecals]=decalbright;
1307 decalposition[numdecals]=where;
1308 decaltype[numdecals]=type;
1309 decalopacity[numdecals]=opacity;
1310 decalrotation[numdecals]=rotation;
1311 decalalivetime[numdecals]=0;
1313 placex=(float)whichx*scale+scale;
1314 placez=(float)whichy*scale;
1316 decaltexcoords[numdecals][0][0]=(placex-where.x)/size/2+.5;
1317 decaltexcoords[numdecals][0][1]=(placez-where.z)/size/2+.5;
1319 decalvertex[numdecals][0].x=placex;
1320 decalvertex[numdecals][0].z=placez;
1321 decalvertex[numdecals][0].y=heightmap[whichx+1][whichy]*scale+.01;
1324 placex=(float)whichx*scale;
1325 placez=(float)whichy*scale;
1327 decaltexcoords[numdecals][1][0]=(placex-where.x)/size/2+.5;
1328 decaltexcoords[numdecals][1][1]=(placez-where.z)/size/2+.5;
1330 decalvertex[numdecals][1].x=placex;
1331 decalvertex[numdecals][1].z=placez;
1332 decalvertex[numdecals][1].y=heightmap[whichx][whichy]*scale+.01;
1335 placex=(float)whichx*scale;
1336 placez=(float)whichy*scale+scale;
1338 decaltexcoords[numdecals][2][0]=(placex-where.x)/size/2+.5;
1339 decaltexcoords[numdecals][2][1]=(placez-where.z)/size/2+.5;
1341 decalvertex[numdecals][2].x=placex;
1342 decalvertex[numdecals][2].z=placez;
1343 decalvertex[numdecals][2].y=heightmap[whichx][whichy+1]*scale+.01;
1345 if(decalrotation[numdecals]){
1346 for(int i=0;i<3;i++){
1348 rot.x=decaltexcoords[numdecals][i][0]-.5;
1349 rot.z=decaltexcoords[numdecals][i][1]-.5;
1350 rot=DoRotation(rot,0,-decalrotation[numdecals],0);
1351 decaltexcoords[numdecals][i][0]=rot.x+.5;
1352 decaltexcoords[numdecals][i][1]=rot.z+.5;
1356 if(!(decaltexcoords[numdecals][0][0]<0&&decaltexcoords[numdecals][1][0]<0&&decaltexcoords[numdecals][2][0]<0))
1357 if(!(decaltexcoords[numdecals][0][1]<0&&decaltexcoords[numdecals][1][1]<0&&decaltexcoords[numdecals][2][1]<0))
1358 if(!(decaltexcoords[numdecals][0][0]>1&&decaltexcoords[numdecals][1][0]>1&&decaltexcoords[numdecals][2][0]>1))
1359 if(!(decaltexcoords[numdecals][0][1]>1&&decaltexcoords[numdecals][1][1]>1&&decaltexcoords[numdecals][2][1]>1))
1360 if(numdecals<max_decals-1)numdecals++;
1364 void Terrain::DoLighting()
1366 static int i,j,k,todivide;
1367 static float brightness, total;
1368 static XYZ blank, terrainpoint,lightloc;
1369 lightloc=light.location;
1370 Normalise(&lightloc);
1372 for(i=0;i<size;i++){
1373 for(j=0;j<size;j++){
1374 terrainpoint.x=(float)i*scale;
1375 terrainpoint.z=(float)j*scale;
1376 terrainpoint.y=heightmap[i][j]*scale+.1;
1378 if(lineTerrain(lightlocation*10+terrainpoint,terrainpoint,&blank)==-1)
1380 brightness=dotproduct(&lightloc,&normals[i][j]);
1382 if(brightness>1)brightness=1;
1383 if(brightness<0)brightness=0;
1385 colors[i][j][0]=light.color[0]*brightness+light.ambient[0];
1386 colors[i][j][1]=light.color[1]*brightness+light.ambient[1];
1387 colors[i][j][2]=light.color[2]*brightness+light.ambient[2];
1389 if(colors[i][j][0]>1)colors[i][j][0]=1;
1390 if(colors[i][j][1]>1)colors[i][j][1]=1;
1391 if(colors[i][j][2]>1)colors[i][j][2]=1;
1392 if(colors[i][j][0]<0)colors[i][j][0]=0;
1393 if(colors[i][j][1]<0)colors[i][j][1]=0;
1394 if(colors[i][j][2]<0)colors[i][j][2]=0;
1399 for(i=0;i<size;i++){
1400 for(j=0;j<size;j++){
1404 if(i!=0){ total+=colors[j][i-1][k]; todivide++;}
1405 if(i!=size-1){ total+=colors[j][i+1][k]; todivide++;}
1406 if(j!=0){ total+=colors[j-1][i][k]; todivide++;}
1407 if(j!=size-1){ total+=colors[j+1][i][k]; todivide++;}
1408 if(i!=0&&j!=0){ total+=colors[j-1][i-1][k]; todivide++;}
1409 if(i!=size-1&&j!=0){ total+=colors[j-1][i+1][k]; todivide++;}
1410 if(j!=size-1&&i!=size-1){ total+=colors[j+1][i+1][k]; todivide++;}
1411 if(j!=size-1&&i!=0){ total+=colors[j+1][i-1][k]; todivide++;}
1412 total+=colors[j][i][k]; todivide++;
1414 colors[j][i][k]=total/todivide;
1420 void Terrain::DoShadows()
1422 static int i,j,k,l,todivide;
1423 static float brightness, total;
1424 static XYZ testpoint,testpoint2, terrainpoint,lightloc,col;
1425 lightloc=light.location;
1430 if(skyboxtexture&&tutoriallevel){
1436 Normalise(&lightloc);
1438 for(i=0;i<size;i++){
1439 for(j=0;j<size;j++){
1440 terrainpoint.x=(float)(i)*scale;
1441 terrainpoint.z=(float)(j)*scale;
1442 terrainpoint.y=heightmap[i][j]*scale;
1445 patchx=(float)(i)*subdivision/size;
1446 patchz=(float)(j)*subdivision/size;
1447 if(patchobjectnum[patchx][patchz]){
1448 for(k=0;k<patchobjectnum[patchx][patchz];k++){
1449 l=patchobjects[patchx][patchz][k];
1450 if(objects.type[l]!=treetrunktype){
1451 testpoint=terrainpoint;
1452 testpoint2=terrainpoint+lightloc*50*(1-shadowed);
1453 if(objects.model[l].LineCheck(&testpoint,&testpoint2,&col,&objects.position[l],&objects.rotation[l])!=-1){
1454 shadowed=1-(findDistance(&terrainpoint,&col)/50);
1458 if(visibleloading)pgame->LoadingScreen();
1460 brightness=dotproduct(&lightloc,&normals[i][j]);
1461 if(shadowed)brightness*=1-shadowed;
1463 if(brightness>1)brightness=1;
1464 if(brightness<0)brightness=0;
1466 colors[i][j][0]=light.color[0]*brightness+light.ambient[0];
1467 colors[i][j][1]=light.color[1]*brightness+light.ambient[1];
1468 colors[i][j][2]=light.color[2]*brightness+light.ambient[2];
1470 if(colors[i][j][0]>1)colors[i][j][0]=1;
1471 if(colors[i][j][1]>1)colors[i][j][1]=1;
1472 if(colors[i][j][2]>1)colors[i][j][2]=1;
1473 if(colors[i][j][0]<0)colors[i][j][0]=0;
1474 if(colors[i][j][1]<0)colors[i][j][1]=0;
1475 if(colors[i][j][2]<0)colors[i][j][2]=0;
1479 if(visibleloading)pgame->LoadingScreen();
1482 for(i=0;i<size;i++){
1483 for(j=0;j<size;j++){
1487 if(i!=0){ total+=colors[j][i-1][k]; todivide++;}
1488 if(i!=size-1){ total+=colors[j][i+1][k]; todivide++;}
1489 if(j!=0){ total+=colors[j-1][i][k]; todivide++;}
1490 if(j!=size-1){ total+=colors[j+1][i][k]; todivide++;}
1491 if(i!=0&&j!=0){ total+=colors[j-1][i-1][k]; todivide++;}
1492 if(i!=size-1&&j!=0){ total+=colors[j-1][i+1][k]; todivide++;}
1493 if(j!=size-1&&i!=size-1){ total+=colors[j+1][i+1][k]; todivide++;}
1494 if(j!=size-1&&i!=0){ total+=colors[j+1][i-1][k]; todivide++;}
1495 total+=colors[j][i][k]; todivide++;
1497 colors[j][i][k]=total/todivide;
1502 for(i=0;i<subdivision;i++){
1503 for(j=0;j<subdivision;j++){
1504 UpdateVertexArray(i,j);
1514 footprinttexture = 0;
1515 bodyprinttexture = 0;
1520 memset(patchobjectnum, 0, sizeof(patchobjectnum));
1521 memset(patchobjects, 0, sizeof(patchobjects));
1525 memset(heightmap, 0, sizeof(heightmap));
1526 memset(normals, 0, sizeof(normals));
1527 memset(facenormals, 0, sizeof(facenormals));
1528 memset(triangles, 0, sizeof(triangles));
1529 memset(colors, 0, sizeof(colors));
1530 memset(opacityother, 0, sizeof(opacityother));
1531 memset(texoffsetx, 0, sizeof(texoffsetx));
1532 memset(texoffsety, 0, sizeof(texoffsety));
1533 memset(numtris, 0, sizeof(numtris));
1534 memset(textureness, 0, sizeof(textureness));
1536 memset(vArray, 0, sizeof(vArray));
1538 memset(visible, 0, sizeof(visible));
1539 memset(avgypatch, 0, sizeof(avgypatch));
1540 memset(maxypatch, 0, sizeof(maxypatch));
1541 memset(minypatch, 0, sizeof(minypatch));
1542 memset(heightypatch, 0, sizeof(heightypatch));
1546 memset(decaltexcoords, 0, sizeof(decaltexcoords));
1547 memset(decalvertex, 0, sizeof(decalvertex));
1548 memset(decaltype, 0, sizeof(decaltype));
1549 memset(decalopacity, 0, sizeof(decalopacity));
1550 memset(decalrotation, 0, sizeof(decalrotation));
1551 memset(decalalivetime, 0, sizeof(decalalivetime));
1552 memset(decalbrightness, 0, sizeof(decalbrightness));
1553 memset(decalposition, 0, sizeof(decalposition));
1558 if(terraintexture)glDeleteTextures( 1, &terraintexture );
1559 if(shadowtexture) glDeleteTextures( 1, &shadowtexture );
1560 if(bodyprinttexture) glDeleteTextures( 1, &bodyprinttexture );
1561 if(footprinttexture) glDeleteTextures( 1, &footprinttexture );
1562 if(bloodtexture) glDeleteTextures( 1, &bloodtexture );
1563 if(bloodtexture2) glDeleteTextures( 1, &bloodtexture2 );
1564 if(breaktexture) glDeleteTextures( 1, &breaktexture );