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