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