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