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