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