Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

terrain.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 #include "qbsp.h"
00023 #include <assert.h>
00024 
00025 #define SURF_WIDTH  2048
00026 #define SURF_HEIGHT 2048
00027 
00028 #define GROW_VERTS      512
00029 #define GROW_INDICES    512
00030 #define GROW_SURFACES   128
00031 
00032 #define VectorSet(v, x, y, z)       v[0] = x;v[1] = y;v[2] = z;
00033 
00034 void QuakeTextureVecs(  plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2], vec_t mappingVecs[2][4] );
00035 
00036 typedef struct {
00037     shaderInfo_t    *shader;
00038     int             x, y;
00039 
00040     int             maxVerts;
00041     int             numVerts;
00042     drawVert_t      *verts;
00043 
00044     int             maxIndexes;
00045     int             numIndexes;
00046     int             *indexes;
00047 } terrainSurf_t;
00048 
00049 static terrainSurf_t    *surfaces = NULL;
00050 static terrainSurf_t    *lastSurface = NULL;
00051 static int              numsurfaces = 0;
00052 static int              maxsurfaces = 0;
00053 
00054 /*
00055 ================
00056 ShaderForLayer
00057 ================
00058 */
00059 shaderInfo_t *ShaderForLayer( int minlayer, int maxlayer, const char *shadername ) {
00060     char    shader[ MAX_QPATH ];
00061 
00062     if ( minlayer == maxlayer ) {
00063         sprintf( shader, "textures/%s_%d", shadername, maxlayer );
00064     } else {
00065         sprintf( shader, "textures/%s_%dto%d", shadername, minlayer, maxlayer );
00066     }
00067 
00068     return ShaderInfoForShader( shader );
00069 }
00070 
00071 /*
00072 ================
00073 CompareVert
00074 ================
00075 */
00076 qboolean CompareVert( drawVert_t *v1, drawVert_t *v2, qboolean checkst ) {
00077     int i;
00078 
00079     for( i = 0; i < 3; i++ ) {
00080         if ( floor( v1->xyz[ i ] + 0.1 ) != floor( v2->xyz[ i ] + 0.1 ) ) {
00081             return qfalse;
00082         }
00083         if ( checkst && ( ( v1->st[ 0 ] != v2->st[ 0 ] ) || ( v1->st[ 1 ] != v2->st[ 1 ] ) ) ) {
00084             return qfalse;
00085         }
00086     }
00087 
00088     return qtrue;
00089 }
00090 
00091 /*
00092 ================
00093 LoadAlphaMap
00094 ================
00095 */
00096 byte *LoadAlphaMap( int *num_layers, int *alphawidth, int *alphaheight ) {
00097     int         *alphamap32;
00098     byte        *alphamap;
00099     const char  *alphamapname;
00100     char        ext[ 128 ];
00101     int         width;
00102     int         height;
00103     int         layers;
00104     int         size;
00105     int         i;
00106 
00107     assert( alphawidth );
00108     assert( alphaheight );
00109     assert( num_layers );
00110 
00111     layers = atoi( ValueForKey( mapent, "layers" ) );
00112     if ( layers < 1 ) {
00113         Error ("SetTerrainTextures: invalid value for 'layers' (%d)", layers );
00114     }
00115 
00116     alphamapname = ValueForKey( mapent, "alphamap" );
00117     if ( !alphamapname[ 0 ] ) {
00118         Error ("LoadAlphaMap: No alphamap specified on terrain" );
00119     }
00120 
00121     ExtractFileExtension( alphamapname, ext);
00122     if ( !Q_stricmp( ext, "tga" ) ) {
00123         Load32BitImage( ExpandGamePath( alphamapname ), &alphamap32, &width, &height );
00124 
00125         size = width * height;
00126         alphamap = malloc( size );
00127         for( i = 0; i < size; i++ ) {
00128             alphamap[ i ] = ( ( alphamap32[ i ] & 0xff ) * layers ) / 256;
00129             if ( alphamap[ i ] >= layers ) {
00130                 alphamap[ i ] = layers - 1;
00131             }
00132         }
00133     } else {
00134         Load256Image( ExpandGamePath( alphamapname ), &alphamap, NULL, &width, &height );
00135         size = width * height;
00136         for( i = 0; i < size; i++ ) {
00137             if ( alphamap[ i ] >= layers ) {
00138                 alphamap[ i ] = layers - 1;
00139             }
00140         }
00141     }
00142 
00143     if ( ( width < 2 ) || ( height < 2 ) ) {
00144         Error ("LoadAlphaMap: alphamap width/height must be at least 2x2." );
00145     }
00146 
00147     *num_layers     = layers;
00148     *alphawidth     = width;
00149     *alphaheight    = height;
00150 
00151     return alphamap;
00152 }
00153 
00154 /*
00155 ================
00156 CalcTerrainSize
00157 ================
00158 */
00159 void CalcTerrainSize( vec3_t mins, vec3_t maxs, vec3_t size ) {
00160     bspbrush_t  *brush;
00161     int         i;
00162     const char  *key;
00163 
00164     // calculate the size of the terrain
00165     ClearBounds( mins, maxs );
00166     for( brush = mapent->brushes; brush != NULL; brush = brush->next ) {
00167         AddPointToBounds( brush->mins, mins, maxs );
00168         AddPointToBounds( brush->maxs, mins, maxs );
00169     }
00170 
00171     key = ValueForKey( mapent, "min" ); 
00172     if ( key[ 0 ] ) {
00173         GetVectorForKey( mapent, "min", mins );
00174     }
00175 
00176     key = ValueForKey( mapent, "max" ); 
00177     if ( key[ 0 ] ) {
00178         GetVectorForKey( mapent, "max", maxs );
00179     }
00180 
00181     for( i = 0; i < 3; i++ ) {
00182         mins[ i ] =  floor( mins[ i ] + 0.1 );
00183         maxs[ i ] =  floor( maxs[ i ] + 0.1 );
00184     }
00185 
00186     VectorSubtract( maxs, mins, size );
00187 
00188     if ( ( size[ 0 ] <= 0 ) || ( size[ 1 ] <= 0 ) ) {
00189         Error ("CalcTerrainSize: Invalid terrain size: %fx%f", size[ 0 ], size[ 1 ] );
00190     }
00191 }
00192 
00193 /*
00194 ==================
00195 IsTriangleDegenerate
00196 
00197 Returns qtrue if all three points are collinear or backwards
00198 ===================
00199 */
00200 #define COLINEAR_AREA   10
00201 static qboolean IsTriangleDegenerate( drawVert_t *points, int a, int b, int c ) {
00202     vec3_t      v1, v2, v3;
00203     float       d;
00204 
00205     VectorSubtract( points[b].xyz, points[a].xyz, v1 );
00206     VectorSubtract( points[c].xyz, points[a].xyz, v2 );
00207     CrossProduct( v1, v2, v3 );
00208     d = VectorLength( v3 );
00209 
00210     // assume all very small or backwards triangles will cause problems
00211     if ( d < COLINEAR_AREA ) {
00212         return qtrue;
00213     }
00214 
00215     return qfalse;
00216 }
00217 
00218 /*
00219 ===============
00220 SideAsTriFan
00221 
00222 The surface can't be represented as a single tristrip without
00223 leaving a degenerate triangle (and therefore a crack), so add
00224 a point in the middle and create (points-1) triangles in fan order
00225 ===============
00226 */
00227 static void SideAsTriFan( terrainSurf_t *surf, int *index, int num ) {
00228     int                 i;
00229     int                 colorSum[4];
00230     drawVert_t          *mid, *v;
00231 
00232     // make sure we have enough space for a new vert
00233     if ( surf->numVerts >= surf->maxVerts ) {
00234         surf->maxVerts += GROW_VERTS;
00235         surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) );
00236     }
00237 
00238     // create a new point in the center of the face
00239     mid = &surf->verts[ surf->numVerts ];
00240     surf->numVerts++;
00241 
00242     colorSum[0] = colorSum[1] = colorSum[2] = colorSum[3] = 0;
00243 
00244     for (i = 0 ; i < num; i++ ) {
00245         v = &surf->verts[ index[ i ] ];
00246         VectorAdd( mid->xyz, v->xyz, mid->xyz );
00247         mid->st[0] += v->st[0];
00248         mid->st[1] += v->st[1];
00249         mid->lightmap[0] += v->lightmap[0];
00250         mid->lightmap[1] += v->lightmap[1];
00251 
00252         colorSum[0] += v->color[0];
00253         colorSum[1] += v->color[1];
00254         colorSum[2] += v->color[2];
00255         colorSum[3] += v->color[3];
00256     }
00257 
00258     mid->xyz[0] /= num;
00259     mid->xyz[1] /= num;
00260     mid->xyz[2] /= num;
00261 
00262     mid->st[0] /= num;
00263     mid->st[1] /= num;
00264 
00265     mid->lightmap[0] /= num;
00266     mid->lightmap[1] /= num;
00267 
00268     mid->color[0] = colorSum[0] / num;
00269     mid->color[1] = colorSum[1] / num;
00270     mid->color[2] = colorSum[2] / num;
00271     mid->color[3] = colorSum[3] / num;
00272 
00273     // fill in indices in trifan order
00274     if ( surf->numIndexes + num * 3 > surf->maxIndexes ) {
00275         surf->maxIndexes = surf->numIndexes + num * 3;
00276         surf->indexes = realloc( surf->indexes, surf->maxIndexes * sizeof( *surf->indexes ) );
00277     }
00278 
00279 
00280     for ( i = 0 ; i < num; i++ ) {
00281         surf->indexes[ surf->numIndexes++ ] = surf->numVerts - 1;
00282         surf->indexes[ surf->numIndexes++ ] = index[ i ];
00283         surf->indexes[ surf->numIndexes++ ] = index[ (i+1) % ( surf->numVerts - 1 ) ];
00284     }
00285 }
00286 /*
00287 ================
00288 SideAsTristrip
00289 
00290 Try to create indices that make (points-2) triangles in tristrip order
00291 ================
00292 */
00293 #define MAX_INDICES 1024
00294 static void SideAsTristrip( terrainSurf_t *surf, int *index, int num ) {
00295     int                 i;
00296     int                 rotate;
00297     int                 numIndices;
00298     int                 ni;
00299     int                 a, b, c;
00300     int                 indices[ MAX_INDICES ];
00301 
00302     // determine the triangle strip order
00303     numIndices = ( num - 2 ) * 3;
00304     if ( numIndices > MAX_INDICES ) {
00305         Error( "MAX_INDICES exceeded for surface" );
00306     }
00307 
00308     // try all possible orderings of the points looking
00309     // for a strip order that isn't degenerate
00310     for ( rotate = 0 ; rotate < num; rotate++ ) {
00311         for ( ni = 0, i = 0 ; i < num - 2 - i ; i++ ) {
00312             a = index[ ( num - 1 - i + rotate ) % num ];
00313             b = index[ ( i + rotate ) % num ];
00314             c = index[ ( num - 2 - i + rotate ) % num ];
00315 
00316             if ( IsTriangleDegenerate( surf->verts, a, b, c ) ) {
00317                 break;
00318             }
00319             indices[ni++] = a;
00320             indices[ni++] = b;
00321             indices[ni++] = c;
00322 
00323             if ( i + 1 != num - 1 - i ) {
00324                 a = index[ ( num - 2 - i + rotate ) % num ];
00325                 b = index[ ( i + rotate ) % num ];
00326                 c = index[ ( i + 1 + rotate ) % num ];
00327 
00328                 if ( IsTriangleDegenerate( surf->verts, a, b, c ) ) {
00329                     break;
00330                 }
00331                 indices[ni++] = a;
00332                 indices[ni++] = b;
00333                 indices[ni++] = c;
00334             }
00335         }
00336         if ( ni == numIndices ) {
00337             break;      // got it done without degenerate triangles
00338         }
00339     }
00340 
00341     // if any triangle in the strip is degenerate,
00342     // render from a centered fan point instead
00343     if ( ni < numIndices ) {
00344         SideAsTriFan( surf, index, num );
00345         return;
00346     }
00347 
00348     // a normal tristrip
00349     if ( surf->numIndexes + ni > surf->maxIndexes ) {
00350         surf->maxIndexes = surf->numIndexes + ni;
00351         surf->indexes = realloc( surf->indexes, surf->maxIndexes * sizeof( *surf->indexes ) );
00352     }
00353 
00354     memcpy( surf->indexes + surf->numIndexes, indices, ni * sizeof( *surf->indexes ) );
00355     surf->numIndexes += ni;
00356 }
00357 
00358 /*
00359 ================
00360 CreateTerrainSurface
00361 ================
00362 */
00363 void CreateTerrainSurface( terrainSurf_t *surf, shaderInfo_t *shader ) {
00364     int                 i, j, k;
00365     drawVert_t          *out;
00366     drawVert_t          *in;
00367     mapDrawSurface_t    *newsurf;
00368 
00369     newsurf = AllocDrawSurf();
00370 
00371     newsurf->miscModel      = qtrue;
00372     newsurf->shaderInfo     = shader;
00373     newsurf->lightmapNum    = -1;
00374     newsurf->fogNum         = -1;
00375     newsurf->numIndexes     = surf->numIndexes;
00376     newsurf->numVerts       = surf->numVerts;
00377 
00378     // copy the indices
00379     newsurf->indexes = malloc( surf->numIndexes * sizeof( *newsurf->indexes ) );
00380     memcpy( newsurf->indexes, surf->indexes, surf->numIndexes * sizeof( *newsurf->indexes ) );
00381 
00382     // allocate the vertices
00383     newsurf->verts = malloc( surf->numVerts * sizeof( *newsurf->verts ) );
00384     memset( newsurf->verts, 0, surf->numVerts * sizeof( *newsurf->verts ) );
00385 
00386     // calculate the surface verts
00387     out = newsurf->verts;
00388     for( i = 0; i < newsurf->numVerts; i++, out++ ) {
00389         VectorCopy( surf->verts[ i ].xyz, out->xyz );
00390 
00391         // set the texture coordinates
00392         out->st[ 0 ] = surf->verts[ i ].st[ 0 ];
00393         out->st[ 1 ] = surf->verts[ i ].st[ 1 ];
00394 
00395         // the colors will be set by the lighting pass
00396         out->color[0] = 255;
00397         out->color[1] = 255;
00398         out->color[2] = 255;
00399         out->color[3] = surf->verts[ i ].color[ 3 ];
00400 
00401         // calculate the vertex normal
00402         VectorClear( out->normal );
00403         for( j = 0; j < numsurfaces; j++ ) {
00404             in = surfaces[ j ].verts;
00405             for( k = 0; k < surfaces[ j ].numVerts; k++, in++ ) {
00406                 if ( CompareVert( out, in, qfalse ) ) {
00407                     VectorAdd( out->normal, in->normal, out->normal );
00408                 }
00409             }
00410         }
00411 
00412         VectorNormalize( out->normal, out->normal );
00413     }
00414 }
00415 
00416 /*
00417 ================
00418 EmitTerrainVerts
00419 ================
00420 */
00421 void EmitTerrainVerts( side_t *side, terrainSurf_t *surf, int maxlayer, int alpha[ MAX_POINTS_ON_WINDING ], qboolean projecttexture ) {
00422     int         i;
00423     int         j;
00424     drawVert_t  *vert;
00425     int         *indices;
00426     int         numindices;
00427     int         maxindices;
00428     int         xyplane;
00429     vec3_t      xynorm = { 0, 0, 1 };
00430     vec_t       shift[ 2 ] = { 0, 0 };
00431     vec_t       scale[ 2 ] = { 0.5, 0.5 };
00432     float       vecs[ 2 ][ 4 ];
00433     static int numtimes = 0;
00434 
00435     numtimes++;
00436 
00437     if ( !surf->verts ) {
00438         surf->numVerts      = 0;
00439         surf->maxVerts      = GROW_VERTS;
00440         surf->verts         = malloc( surf->maxVerts * sizeof( *surf->verts ) );
00441 
00442         surf->numIndexes    = 0;
00443         surf->maxIndexes    = GROW_INDICES;
00444         surf->indexes       = malloc( surf->maxIndexes * sizeof( *surf->indexes ) );
00445     }
00446 
00447     // calculate the texture coordinate vectors
00448     xyplane = FindFloatPlane( xynorm, 0 );
00449     QuakeTextureVecs( &mapplanes[ xyplane ], shift, 0, scale, vecs );
00450 
00451     // emit the vertexes
00452     numindices = 0;
00453     maxindices = surf->maxIndexes;
00454     indices = malloc ( maxindices * sizeof( *indices ) );
00455 
00456     for ( i = 0; i < side->winding->numpoints; i++ ) {
00457         vert = &surf->verts[ surf->numVerts ];
00458 
00459         // set the final alpha value--0 for texture 1, 255 for texture 2
00460         if ( alpha[ i ] < maxlayer ) {
00461             vert->color[3] = 0;
00462         } else {
00463             vert->color[3] = 255;
00464         }
00465 
00466         vert->xyz[ 0 ] = floor( side->winding->p[ i ][ 0 ] + 0.1f );
00467         vert->xyz[ 1 ] = floor( side->winding->p[ i ][ 1 ] + 0.1f );
00468         vert->xyz[ 2 ] = floor( side->winding->p[ i ][ 2 ] + 0.1f );
00469 
00470         // set the texture coordinates
00471         if ( projecttexture ) {
00472             vert->st[0] = ( vecs[0][3] + DotProduct( vecs[ 0 ], vert->xyz ) ) / surf->shader->width;
00473             vert->st[1] = ( vecs[1][3] + DotProduct( vecs[ 1 ], vert->xyz ) ) / surf->shader->height;
00474         } else {
00475             vert->st[0] = ( side->vecs[0][3] + DotProduct( side->vecs[ 0 ], vert->xyz ) ) / surf->shader->width;
00476             vert->st[1] = ( side->vecs[1][3] + DotProduct( side->vecs[ 1 ], vert->xyz ) ) / surf->shader->height;
00477         }
00478 
00479         VectorCopy( mapplanes[ side->planenum ].normal, vert->normal );
00480 
00481         for( j = 0; j < surf->numVerts; j++ ) {
00482             if ( CompareVert( vert, &surf->verts[ j ], qtrue ) ) {
00483                 break;
00484             }
00485         }
00486         
00487         if ( numindices >= maxindices ) {
00488             maxindices += GROW_INDICES;
00489             indices = realloc( indices, maxindices * sizeof( *indices ) );
00490         }
00491 
00492         if ( j != surf->numVerts ) {
00493             indices[ numindices++ ] = j;
00494         } else {
00495             indices[ numindices++ ] = surf->numVerts;
00496             surf->numVerts++;
00497             if ( surf->numVerts >= surf->maxVerts ) {
00498                 surf->maxVerts += GROW_VERTS;
00499                 surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) );
00500             }
00501         }
00502     }
00503 
00504     SideAsTristrip( surf, indices, numindices );
00505 
00506     free( indices );
00507 }
00508 
00509 /*
00510 ================
00511 SurfaceForShader
00512 ================
00513 */
00514 terrainSurf_t *SurfaceForShader( shaderInfo_t *shader, int x, int y ) {
00515     int i;
00516 
00517     if ( lastSurface && ( lastSurface->shader == shader ) && ( lastSurface->x == x ) && ( lastSurface->y == y ) ) {
00518         return lastSurface;
00519     }
00520 
00521     lastSurface = surfaces;
00522     for( i = 0; i < numsurfaces; i++, lastSurface++ ) {
00523         if ( ( lastSurface->shader == shader ) && ( lastSurface->x == x ) && ( lastSurface->y == y ) ) {
00524             return lastSurface;
00525         }
00526     }
00527 
00528     if ( numsurfaces >= maxsurfaces ) {
00529         maxsurfaces += GROW_SURFACES;
00530         surfaces = realloc( surfaces, maxsurfaces * sizeof( *surfaces ) );
00531         memset( surfaces + numsurfaces + 1, 0, ( maxsurfaces - numsurfaces - 1 ) * sizeof( *surfaces ) );
00532     }
00533 
00534     lastSurface= &surfaces[ numsurfaces++ ];
00535     lastSurface->shader = shader;
00536     lastSurface->x = x;
00537     lastSurface->y = y;
00538 
00539     return lastSurface;
00540 }
00541 
00542 /*
00543 ================
00544 SetTerrainTextures
00545 ================
00546 */
00547 void SetTerrainTextures( void ) {
00548     int             i;
00549     int             x, y;
00550     int             layer;
00551     int             minlayer, maxlayer;
00552     float           s, t;
00553     float           min_s, min_t;
00554     int             alpha[ MAX_POINTS_ON_WINDING ];
00555     shaderInfo_t    *si, *terrainShader;
00556     bspbrush_t      *brush;
00557     side_t          *side;
00558     const char      *shadername;
00559     vec3_t          mins, maxs;
00560     vec3_t          size;
00561     int             surfwidth, surfheight, surfsize;
00562     terrainSurf_t   *surf;
00563     byte            *alphamap;
00564     int             alphawidth, alphaheight;
00565     int             num_layers;
00566     extern qboolean onlyents;
00567 
00568     if ( onlyents ) {
00569         return;
00570     }
00571 
00572     shadername = ValueForKey( mapent, "shader" );
00573     if ( !shadername[ 0 ] ) {
00574         Error ("SetTerrainTextures: shader not specified" );
00575     }
00576 
00577     alphamap = LoadAlphaMap( &num_layers, &alphawidth, &alphaheight );
00578 
00579     mapent->firstDrawSurf = numMapDrawSurfs;
00580 
00581     // calculate the size of the terrain
00582     CalcTerrainSize( mins, maxs, size );
00583 
00584     surfwidth   = ( size[ 0 ] + SURF_WIDTH - 1 ) / SURF_WIDTH;
00585     surfheight  = ( size[ 1 ] + SURF_HEIGHT - 1 ) / SURF_HEIGHT;
00586     surfsize = surfwidth * surfheight;
00587 
00588     lastSurface = NULL;
00589     numsurfaces = 0;
00590     maxsurfaces = 0;
00591     for( i = num_layers; i > 0; i-- ) {
00592         maxsurfaces += i * surfsize;
00593     }
00594     surfaces = malloc( maxsurfaces * sizeof( *surfaces ) );
00595     memset( surfaces, 0, maxsurfaces * sizeof( *surfaces ) );
00596 
00597     terrainShader = ShaderInfoForShader( "textures/common/terrain" );
00598 
00599     for( brush = mapent->brushes; brush != NULL; brush = brush->next ) {
00600         // only create surfaces for sides marked as terrain
00601         for( side = brush->sides; side < &brush->sides[ brush->numsides ]; side++ ) {
00602             if ( !side->shaderInfo ) {
00603                 continue;
00604             }
00605 
00606             if ( ( ( side->surfaceFlags | side->shaderInfo->surfaceFlags ) & SURF_NODRAW ) && !strstr( side->shaderInfo->shader, "terrain" ) ) {
00607                 continue;
00608             }
00609 
00610             minlayer = num_layers;
00611             maxlayer = 0;
00612 
00613             // project each point of the winding onto the alphamap to determine which
00614             // textures to blend
00615             min_s = 1.0;
00616             min_t = 1.0;
00617             for( i = 0; i < side->winding->numpoints; i++ ) {
00618                 s = floor( side->winding->p[ i ][ 0 ] + 0.1f - mins[ 0 ] ) / size[ 0 ];
00619                 t = floor( side->winding->p[ i ][ 1 ] + 0.1f - mins[ 0 ] ) / size[ 1 ];
00620 
00621                 if ( s < 0 ) {
00622                     s = 0;
00623                 }
00624                 
00625                 if ( t < 0 ) {
00626                     t = 0;
00627                 }
00628 
00629                 if ( s >= 1.0 ) {
00630                     s = 1.0;
00631                 }
00632 
00633                 if ( t >= 1.0 ) {
00634                     t = 1.0;
00635                 }
00636 
00637                 if ( s < min_s ) {
00638                     min_s = s;
00639                 }
00640 
00641                 if ( t < min_t ) {
00642                     min_t = t;
00643                 }
00644 
00645                 x = ( alphawidth - 1 ) * s;
00646                 y = ( alphaheight - 1 ) * t;
00647 
00648                 layer = alphamap[ x + y * alphawidth ];
00649                 if ( layer < minlayer ) {
00650                     minlayer = layer;
00651                 }
00652 
00653                 if ( layer > maxlayer ) {
00654                     maxlayer = layer;
00655                 }
00656 
00657                 alpha[ i ] = layer;
00658             }
00659 
00660             x = min_s * surfwidth;
00661             if ( x >= surfwidth ) {
00662                 x = surfwidth - 1;
00663             }
00664 
00665             y = min_t * surfheight;
00666             if ( y >= surfheight ) {
00667                 y = surfheight - 1;
00668             }
00669 
00670             if ( strstr( side->shaderInfo->shader, "terrain" ) ) {
00671                 si = ShaderForLayer( minlayer, maxlayer, shadername );
00672                 if ( showseams ) {
00673                     for( i = 0; i < side->winding->numpoints; i++ ) {
00674                         if ( ( alpha[ i ] != minlayer ) && ( alpha[ i ] != maxlayer ) ) {
00675                             si = ShaderInfoForShader( "textures/common/white" );
00676                             break;
00677                         }
00678                     }
00679                 }
00680                 surf = SurfaceForShader( si, x, y );
00681                 EmitTerrainVerts( side, surf, maxlayer, alpha, qtrue );
00682             } else {
00683                 si = side->shaderInfo;
00684                 side->shaderInfo = terrainShader;
00685                 surf = SurfaceForShader( si, x, y );
00686                 EmitTerrainVerts( side, surf, maxlayer, alpha, qfalse );
00687             }
00688         }
00689     }
00690 
00691     // create the final surfaces
00692     for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) {
00693         if ( surf->numVerts ) {
00694             CreateTerrainSurface( surf, surf->shader );
00695         }
00696     }
00697 
00698     //
00699     // clean up any allocated memory
00700     //
00701     for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) {
00702         if ( surf->verts ) {
00703             free( surf->verts );
00704             free( surf->indexes );
00705         }
00706     }
00707     free( alphamap );
00708     free( surfaces );
00709 
00710     surfaces = NULL;
00711     lastSurface = NULL;
00712     numsurfaces = 0;
00713     maxsurfaces = 0;
00714 }
00715 
00716 /*****************************************************************************
00717 
00718     New terrain code
00719 
00720 ******************************************************************************/
00721 
00722 typedef struct terrainFace_s {
00723     shaderInfo_t            *shaderInfo;
00724     //texdef_t              texdef;
00725 
00726     float                   vecs[ 2 ][ 4 ]; // texture coordinate mapping
00727 } terrainFace_t;
00728 
00729 typedef struct terrainVert_s {
00730     vec3_t                  xyz;
00731     terrainFace_t           tri;
00732 } terrainVert_t;
00733 
00734 typedef struct terrainMesh_s {
00735     float                   scale_x;
00736     float                   scale_y;
00737     vec3_t                  origin;
00738 
00739     int                     width, height;
00740     terrainVert_t           *map;
00741 } terrainMesh_t;
00742 
00743 terrainVert_t *Terrain_GetVert( terrainMesh_t *pm, int x, int y ) {
00744     return &pm->map[ x + y * pm->width ];
00745 }
00746 
00747 void Terrain_GetTriangles( terrainMesh_t *pm, int x, int y, terrainVert_t **verts ) {
00748     if ( ( x + y ) & 1 ) {
00749         // first tri
00750         verts[ 0 ] = Terrain_GetVert( pm, x, y );
00751         verts[ 1 ] = Terrain_GetVert( pm, x, y + 1 );
00752         verts[ 2 ] = Terrain_GetVert( pm, x + 1, y + 1 );
00753 
00754         // second tri
00755         verts[ 3 ] = verts[ 2 ];
00756         verts[ 4 ] = Terrain_GetVert( pm, x + 1, y );
00757         verts[ 5 ] = verts[ 0 ];
00758     } else {
00759         // first tri
00760         verts[ 0 ] = Terrain_GetVert( pm, x, y );
00761         verts[ 1 ] = Terrain_GetVert( pm, x, y + 1 );
00762         verts[ 2 ] = Terrain_GetVert( pm, x + 1, y );
00763 
00764         // second tri
00765         verts[ 3 ] = verts[ 2 ];
00766         verts[ 4 ] = verts[ 1 ];
00767         verts[ 5 ] = Terrain_GetVert( pm, x + 1, y + 1 );
00768     }
00769 }
00770 
00771 /*
00772 ================
00773 EmitTerrainVerts2
00774 ================
00775 */
00776 void EmitTerrainVerts2( terrainSurf_t *surf, terrainVert_t **verts, int alpha[ 3 ] ) {
00777     int         i;
00778     int         j;
00779     drawVert_t  *vert;
00780     int         *indices;
00781     int         numindices;
00782     int         maxindices;
00783     int         xyplane;
00784     vec3_t      xynorm = { 0, 0, 1 };
00785     vec_t       shift[ 2 ] = { 0, 0 };
00786     vec_t       scale[ 2 ] = { 0.5, 0.5 };
00787     float       vecs[ 2 ][ 4 ];
00788     vec4_t      plane;
00789 
00790     if ( !surf->verts ) {
00791         surf->numVerts      = 0;
00792         surf->maxVerts      = GROW_VERTS;
00793         surf->verts         = malloc( surf->maxVerts * sizeof( *surf->verts ) );
00794 
00795         surf->numIndexes    = 0;
00796         surf->maxIndexes    = GROW_INDICES;
00797         surf->indexes       = malloc( surf->maxIndexes * sizeof( *surf->indexes ) );
00798     }
00799 
00800     // calculate the texture coordinate vectors
00801     xyplane = FindFloatPlane( xynorm, 0 );
00802     QuakeTextureVecs( &mapplanes[ xyplane ], shift, 0, scale, vecs );
00803 
00804     // emit the vertexes
00805     numindices = 0;
00806     maxindices = surf->maxIndexes;
00807     assert( maxindices >= 0 );
00808     indices = malloc ( maxindices * sizeof( *indices ) );
00809 
00810     PlaneFromPoints( plane, verts[ 0 ]->xyz, verts[ 1 ]->xyz, verts[ 2 ]->xyz );
00811 
00812     for ( i = 0; i < 3; i++ ) {
00813         vert = &surf->verts[ surf->numVerts ];
00814 
00815         if ( alpha[ i ] ) {
00816             vert->color[3] = 255;
00817         } else {
00818             vert->color[3] = 0;
00819         }
00820 
00821         vert->xyz[ 0 ] = floor( verts[ i ]->xyz[ 0 ] + 0.1f );
00822         vert->xyz[ 1 ] = floor( verts[ i ]->xyz[ 1 ] + 0.1f );
00823         vert->xyz[ 2 ] = floor( verts[ i ]->xyz[ 2 ] + 0.1f );
00824 
00825         // set the texture coordinates
00826         vert->st[0] = ( vecs[0][3] + DotProduct( vecs[ 0 ], vert->xyz ) ) / surf->shader->width;
00827         vert->st[1] = ( vecs[1][3] + DotProduct( vecs[ 1 ], vert->xyz ) ) / surf->shader->height;
00828 
00829         VectorCopy( plane, vert->normal );
00830 
00831         for( j = 0; j < surf->numVerts; j++ ) {
00832             if ( CompareVert( vert, &surf->verts[ j ], qtrue ) ) {
00833                 break;
00834             }
00835         }
00836         
00837         if ( numindices >= maxindices ) {
00838             maxindices += GROW_INDICES;
00839             indices = realloc( indices, maxindices * sizeof( *indices ) );
00840         }
00841 
00842         if ( j != surf->numVerts ) {
00843             indices[ numindices++ ] = j;
00844         } else {
00845             indices[ numindices++ ] = surf->numVerts;
00846             surf->numVerts++;
00847             if ( surf->numVerts >= surf->maxVerts ) {
00848                 surf->maxVerts += GROW_VERTS;
00849                 surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) );
00850             }
00851         }
00852     }
00853 
00854     SideAsTristrip( surf, indices, numindices );
00855 
00856     free( indices );
00857 }
00858 
00859 int      MapPlaneFromPoints( vec3_t p0, vec3_t p1, vec3_t p2 );
00860 void     QuakeTextureVecs( plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2], vec_t mappingVecs[2][4] );
00861 qboolean RemoveDuplicateBrushPlanes( bspbrush_t *b );
00862 void     SetBrushContents( bspbrush_t *b );
00863 
00864 void AddBrushSide( vec3_t v1, vec3_t v2, vec3_t v3, shaderInfo_t *terrainShader ) {
00865     side_t  *side;
00866     int     planenum;
00867 
00868     side = &buildBrush->sides[ buildBrush->numsides ];
00869     memset( side, 0, sizeof( *side ) );
00870     buildBrush->numsides++;
00871 
00872     side->shaderInfo = terrainShader;
00873 
00874     // find the plane number
00875     planenum = MapPlaneFromPoints( v1, v2, v3 );
00876     side->planenum = planenum;
00877 }
00878 
00879 void MakeBrushFromTriangle( vec3_t v1, vec3_t v2, vec3_t v3, shaderInfo_t *terrainShader ) {
00880     bspbrush_t  *b;
00881     vec3_t      d1;
00882     vec3_t      d2;
00883     vec3_t      d3;
00884 
00885     VectorSet( d1, v1[ 0 ], v1[ 1 ], MIN_WORLD_COORD + 10 );    //FIXME
00886     VectorSet( d2, v2[ 0 ], v2[ 1 ], MIN_WORLD_COORD + 10 );
00887     VectorSet( d3, v3[ 0 ], v3[ 1 ], MIN_WORLD_COORD + 10 );
00888 
00889     buildBrush->numsides = 0;
00890     buildBrush->detail = qfalse;
00891 
00892     AddBrushSide( v1, v2, v3, terrainShader );
00893     AddBrushSide( v1, d1, v2, terrainShader );
00894     AddBrushSide( v2, d2, v3, terrainShader );
00895     AddBrushSide( v3, d3, v1, terrainShader );
00896     AddBrushSide( d3, d2, d1, terrainShader );
00897 
00898     buildBrush->portalareas[0] = -1;
00899     buildBrush->portalareas[1] = -1;
00900     buildBrush->entitynum = num_entities-1;
00901     buildBrush->brushnum = entitySourceBrushes;
00902 
00903     // if there are mirrored planes, the entire brush is invalid
00904     if ( !RemoveDuplicateBrushPlanes( buildBrush ) ) {
00905         return;
00906     }
00907 
00908     // get the content for the entire brush
00909     SetBrushContents( buildBrush );
00910     buildBrush->contents |= CONTENTS_DETAIL;
00911 
00912     b = FinishBrush();
00913     if ( !b ) {
00914         return;
00915     }
00916 }
00917 
00918 void MakeTerrainIntoBrushes( terrainMesh_t *tm ) {
00919     int             index[ 6 ];
00920     int             y;
00921     int             x;
00922     terrainVert_t   *verts;
00923     shaderInfo_t    *terrainShader;
00924 
00925     terrainShader = ShaderInfoForShader( "textures/common/terrain" );
00926 
00927     verts = tm->map;
00928     for( y = 0; y < tm->height - 1; y++ ) {
00929         for( x = 0; x < tm->width - 1; x++ ) {
00930             if ( ( x + y ) & 1 ) {
00931                 // first tri
00932                 index[ 0 ] = x + y * tm->width;
00933                 index[ 1 ] = x + ( y + 1 ) * tm->width;
00934                 index[ 2 ] = ( x + 1 ) + ( y + 1 ) * tm->width;
00935                 index[ 3 ] = ( x + 1 ) + ( y + 1 ) * tm->width;
00936                 index[ 4 ] = ( x + 1 ) + y * tm->width;
00937                 index[ 5 ] = x + y * tm->width;
00938             } else {
00939                 // first tri
00940                 index[ 0 ] = x + y * tm->width;
00941                 index[ 1 ] = x + ( y + 1 ) * tm->width;
00942                 index[ 2 ] = ( x + 1 ) + y * tm->width;
00943                 index[ 3 ] = ( x + 1 ) + y * tm->width;
00944                 index[ 4 ] = x + ( y + 1 ) * tm->width;
00945                 index[ 5 ] = ( x + 1 ) + ( y + 1 ) * tm->width;
00946             }
00947 
00948             MakeBrushFromTriangle( verts[ index[ 0 ] ].xyz, verts[ index[ 1 ] ].xyz, verts[ index[ 2 ] ].xyz, terrainShader );
00949             MakeBrushFromTriangle( verts[ index[ 3 ] ].xyz, verts[ index[ 4 ] ].xyz, verts[ index[ 5 ] ].xyz, terrainShader );
00950         }
00951     }
00952 }
00953 
00954 void Terrain_ParseFace( terrainFace_t *face ) {
00955     shaderInfo_t    *si;
00956     vec_t           shift[ 2 ];
00957     vec_t           rotate;
00958     vec_t           scale[ 2 ];
00959     char            name[ MAX_QPATH ];
00960     char            shader[ MAX_QPATH ];
00961     plane_t         p;
00962 
00963     // read the texturedef
00964     GetToken( qfalse );
00965     strcpy( name, token );
00966 
00967     GetToken( qfalse );
00968     shift[ 0 ] = atof(token);
00969     GetToken( qfalse );
00970     shift[ 1 ] = atof( token ); 
00971     GetToken( qfalse );
00972     rotate = atof( token );
00973     GetToken( qfalse );
00974     scale[ 0 ] = atof( token );
00975     GetToken( qfalse );
00976     scale[ 1 ] = atof( token );
00977 
00978     // find default flags and values
00979     sprintf( shader, "textures/%s", name );
00980     si = ShaderInfoForShader( shader );
00981     face->shaderInfo = si;
00982     //face->texdef = si->texdef;
00983 
00984     // skip over old contents
00985     GetToken( qfalse );
00986 
00987     // skip over old flags
00988     GetToken( qfalse );
00989 
00990     // skip over old value
00991     GetToken( qfalse );
00992 
00993     //Surface_Parse( &face->texdef );
00994     //Surface_BuildTexdef( &face->texdef );
00995 
00996     // make a fake horizontal plane
00997     VectorSet( p.normal, 0, 0, 1 );
00998     p.dist = 0;
00999     p.type = PlaneTypeForNormal( p.normal );
01000 
01001     QuakeTextureVecs( &p, shift, rotate, scale, face->vecs );
01002 }
01003 
01004 #define MAX_TERRAIN_TEXTURES 128
01005 static int          numtextures = 0;;
01006 static shaderInfo_t *textures[ MAX_TERRAIN_TEXTURES ];
01007 
01008 void Terrain_AddTexture( shaderInfo_t *texture ) {
01009     int i;
01010 
01011     if ( !texture ) {
01012         return;
01013     }
01014 
01015     for( i = 0; i < numtextures; i++ ) {
01016         if ( textures[ i ] == texture ) {
01017             return;
01018         }
01019     }
01020 
01021     if ( numtextures >= MAX_TERRAIN_TEXTURES ) {
01022         Error( "Too many textures on terrain" );
01023         return;
01024     }
01025 
01026     textures[ numtextures++ ] = texture;
01027 }
01028 
01029 int LayerForShader( shaderInfo_t *shader ) {
01030     int i;
01031     int l;
01032 
01033     l = strlen( shader->shader );
01034     for( i = l - 1; i >= 0; i-- ) {
01035         if ( shader->shader[ i ] == '_' ) {
01036             return atoi( &shader->shader[ i + 1 ] );
01037             break;
01038         }
01039     }
01040 
01041     return 0;
01042 }
01043 
01044 /*
01045 =================
01046 ParseTerrain
01047 
01048 Creates a mapDrawSurface_t from the terrain text
01049 =================
01050 */
01051 
01052 void ParseTerrain( void ) {
01053     int             i, j;
01054     int             x, y;
01055     int             x1, y1;
01056     terrainMesh_t   t;
01057     int             index;
01058     terrainVert_t   *verts[ 6 ];
01059     int             num_layers;
01060     int             layer, minlayer, maxlayer;
01061     int             alpha[ 6 ];
01062     shaderInfo_t    *si, *terrainShader;
01063     int             surfwidth, surfheight, surfsize;
01064     terrainSurf_t   *surf;
01065     char            shadername[ MAX_QPATH ];
01066 
01067     mapent->firstDrawSurf = numMapDrawSurfs;
01068 
01069     memset( &t, 0, sizeof( t ) );
01070 
01071     MatchToken( "{" );
01072 
01073     // get width
01074     GetToken( qtrue );
01075     t.width = atoi( token );
01076 
01077     // get height
01078     GetToken( qfalse );
01079     t.height = atoi( token );
01080 
01081     // get scale_x
01082     GetToken( qfalse );
01083     t.scale_x = atof( token );
01084 
01085     // get scale_y
01086     GetToken( qfalse );
01087     t.scale_y = atof( token );
01088 
01089     // get origin
01090     GetToken( qtrue );
01091     t.origin[ 0 ] = atof( token );
01092     GetToken( qfalse );
01093     t.origin[ 1 ] = atof( token );
01094     GetToken( qfalse );
01095     t.origin[ 2 ] = atof( token );
01096 
01097     t.map = malloc( t.width * t.height * sizeof( t.map[ 0 ] ) );
01098 
01099     if ( t.width <= 0 || t.height <= 0 ) {
01100         Error( "ParseTerrain: bad size" );
01101     }
01102 
01103     numtextures = 0;
01104     index = 0;
01105     for ( i = 0; i < t.height; i++ ) {
01106         for( j = 0; j < t.width; j++, index++ ) {
01107             // get height
01108             GetToken( qtrue );
01109             t.map[ index ].xyz[ 0 ] = t.origin[ 0 ] + t.scale_x * ( float )j;
01110             t.map[ index ].xyz[ 1 ] = t.origin[ 1 ] + t.scale_y * ( float )i;
01111             t.map[ index ].xyz[ 2 ] = t.origin[ 2 ] + atof( token );
01112 
01113             Terrain_ParseFace( &t.map[ index ].tri );
01114             Terrain_AddTexture( t.map[ index ].tri.shaderInfo );
01115         }
01116     }
01117 
01118     MatchToken( "}" );
01119     MatchToken( "}" );
01120 
01121     MakeTerrainIntoBrushes( &t );
01122 
01123     surfwidth   = ( ( t.scale_x * t.width ) + SURF_WIDTH - 1 ) / SURF_WIDTH;
01124     surfheight  = ( ( t.scale_y * t.height ) + SURF_HEIGHT - 1 ) / SURF_HEIGHT;
01125     surfsize = surfwidth * surfheight;
01126 
01127     //FIXME
01128     num_layers = 0;
01129     for( i = 0; i < numtextures; i++ ) {
01130         layer = LayerForShader( textures[ i ] ) + 1;
01131         if ( layer > num_layers ) {
01132             num_layers = layer;
01133         }
01134     }
01135     num_layers = 4;
01136 
01137     memset( alpha, 0, sizeof( alpha ) );
01138 
01139     lastSurface = NULL;
01140     numsurfaces = 0;
01141     maxsurfaces = 0;
01142     for( i = num_layers; i > 0; i-- ) {
01143         maxsurfaces += i * surfsize;
01144     }
01145 
01146     surfaces = malloc( maxsurfaces * sizeof( *surfaces ) );
01147     memset( surfaces, 0, maxsurfaces * sizeof( *surfaces ) );
01148 
01149     terrainShader = ShaderInfoForShader( "textures/common/terrain" );
01150 
01151     // get the shadername
01152     if ( Q_strncasecmp( textures[ 0 ]->shader, "textures/", 9 ) == 0 ) {
01153         strcpy( shadername, &textures[ 0 ]->shader[ 9 ] );
01154     } else {
01155         strcpy( shadername, textures[ 0 ]->shader );
01156     }
01157     j = strlen( shadername );
01158     for( i = j - 1; i >= 0; i-- ) {
01159         if ( shadername[ i ] == '_' ) {
01160             shadername[ i ] = 0;
01161             break;
01162         }
01163     }
01164     
01165     for( y = 0; y < t.height - 1; y++ ) {
01166         for( x = 0; x < t.width - 1; x++ ) {
01167             Terrain_GetTriangles( &t, x, y, verts );
01168 
01169             x1 = ( ( float )x / ( float )( t.width - 1 ) ) * surfwidth;
01170             if ( x1 >= surfwidth ) {
01171                 x1 = surfwidth - 1;
01172             }
01173 
01174             y1 = ( ( float )y / ( float )( t.height - 1 ) ) * surfheight;
01175             if ( y1 >= surfheight ) {
01176                 y1 = surfheight - 1;
01177             }
01178 
01179             maxlayer = minlayer = LayerForShader( verts[ 0 ]->tri.shaderInfo );
01180             for( i = 0; i < 3; i++ ) {
01181                 layer = LayerForShader( verts[ i ]->tri.shaderInfo );
01182                 if ( layer < minlayer ) {
01183                     minlayer = layer;
01184                 }
01185                 if ( layer > maxlayer ) {
01186                     maxlayer = layer;
01187                 }
01188             }
01189 
01190             for( i = 0; i < 3; i++ ) {
01191                 layer = LayerForShader( verts[ i ]->tri.shaderInfo );
01192                 if ( layer > minlayer ) {
01193                     alpha[ i ] = 1.0f;
01194                 } else {
01195                     alpha[ i ] = 0.0f;
01196                 }
01197             }
01198 
01199             si = ShaderForLayer( minlayer, maxlayer, shadername );
01200             surf = SurfaceForShader( si, x1, y1 );
01201             EmitTerrainVerts2( surf, &verts[ 0 ], &alpha[ 0 ] );
01202 
01203             // second triangle
01204             maxlayer = minlayer = LayerForShader( verts[ 3 ]->tri.shaderInfo );
01205             for( i = 3; i < 6; i++ ) {
01206                 layer = LayerForShader( verts[ i ]->tri.shaderInfo );
01207                 if ( layer < minlayer ) {
01208                     minlayer = layer;
01209                 }
01210                 if ( layer > maxlayer ) {
01211                     maxlayer = layer;
01212                 }
01213             }
01214 
01215             for( i = 3; i < 6; i++ ) {
01216                 layer = LayerForShader( verts[ i ]->tri.shaderInfo );
01217                 if ( layer > minlayer ) {
01218                     alpha[ i ] = 1.0f;
01219                 } else {
01220                     alpha[ i ] = 0.0f;
01221                 }
01222             }
01223 
01224             si = ShaderForLayer( minlayer, maxlayer, shadername );
01225             surf = SurfaceFo