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