diff options
author | tma <tma@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-09-28 18:55:31 +0000 |
---|---|---|
committer | tma <tma@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-09-28 18:55:31 +0000 |
commit | ec912002d3f75729c627cf467903c4607a529495 (patch) | |
tree | b944aa3ec6a159d4607b3bb25cb09640bca02ddb /q3map/terrain.c | |
parent | ea1ca0473a510a02fff82788a2a6c8d95a6bf2d3 (diff) | |
download | ioquake3-aero-ec912002d3f75729c627cf467903c4607a529495.tar.gz ioquake3-aero-ec912002d3f75729c627cf467903c4607a529495.zip |
* Removed q3map and associated common and libs directories
git-svn-id: svn://svn.icculus.org/quake3/trunk@123 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'q3map/terrain.c')
-rw-r--r-- | q3map/terrain.c | 1255 |
1 files changed, 0 insertions, 1255 deletions
diff --git a/q3map/terrain.c b/q3map/terrain.c deleted file mode 100644 index 129ac08..0000000 --- a/q3map/terrain.c +++ /dev/null @@ -1,1255 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "qbsp.h" -#include <assert.h> - -#define SURF_WIDTH 2048 -#define SURF_HEIGHT 2048 - -#define GROW_VERTS 512 -#define GROW_INDICES 512 -#define GROW_SURFACES 128 - -#define VectorSet(v, x, y, z) v[0] = x;v[1] = y;v[2] = z; - -void QuakeTextureVecs( plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2], vec_t mappingVecs[2][4] ); - -typedef struct { - shaderInfo_t *shader; - int x, y; - - int maxVerts; - int numVerts; - drawVert_t *verts; - - int maxIndexes; - int numIndexes; - int *indexes; -} terrainSurf_t; - -static terrainSurf_t *surfaces = NULL; -static terrainSurf_t *lastSurface = NULL; -static int numsurfaces = 0; -static int maxsurfaces = 0; - -/* -================ -ShaderForLayer -================ -*/ -shaderInfo_t *ShaderForLayer( int minlayer, int maxlayer, const char *shadername ) { - char shader[ MAX_QPATH ]; - - if ( minlayer == maxlayer ) { - sprintf( shader, "textures/%s_%d", shadername, maxlayer ); - } else { - sprintf( shader, "textures/%s_%dto%d", shadername, minlayer, maxlayer ); - } - - return ShaderInfoForShader( shader ); -} - -/* -================ -CompareVert -================ -*/ -qboolean CompareVert( drawVert_t *v1, drawVert_t *v2, qboolean checkst ) { - int i; - - for( i = 0; i < 3; i++ ) { - if ( floor( v1->xyz[ i ] + 0.1 ) != floor( v2->xyz[ i ] + 0.1 ) ) { - return qfalse; - } - if ( checkst && ( ( v1->st[ 0 ] != v2->st[ 0 ] ) || ( v1->st[ 1 ] != v2->st[ 1 ] ) ) ) { - return qfalse; - } - } - - return qtrue; -} - -/* -================ -LoadAlphaMap -================ -*/ -byte *LoadAlphaMap( int *num_layers, int *alphawidth, int *alphaheight ) { - int *alphamap32; - byte *alphamap; - const char *alphamapname; - char ext[ 128 ]; - int width; - int height; - int layers; - int size; - int i; - - assert( alphawidth ); - assert( alphaheight ); - assert( num_layers ); - - layers = atoi( ValueForKey( mapent, "layers" ) ); - if ( layers < 1 ) { - Error ("SetTerrainTextures: invalid value for 'layers' (%d)", layers ); - } - - alphamapname = ValueForKey( mapent, "alphamap" ); - if ( !alphamapname[ 0 ] ) { - Error ("LoadAlphaMap: No alphamap specified on terrain" ); - } - - ExtractFileExtension( alphamapname, ext); - if ( !Q_stricmp( ext, "tga" ) ) { - Load32BitImage( ExpandGamePath( alphamapname ), &alphamap32, &width, &height ); - - size = width * height; - alphamap = malloc( size ); - for( i = 0; i < size; i++ ) { - alphamap[ i ] = ( ( alphamap32[ i ] & 0xff ) * layers ) / 256; - if ( alphamap[ i ] >= layers ) { - alphamap[ i ] = layers - 1; - } - } - } else { - Load256Image( ExpandGamePath( alphamapname ), &alphamap, NULL, &width, &height ); - size = width * height; - for( i = 0; i < size; i++ ) { - if ( alphamap[ i ] >= layers ) { - alphamap[ i ] = layers - 1; - } - } - } - - if ( ( width < 2 ) || ( height < 2 ) ) { - Error ("LoadAlphaMap: alphamap width/height must be at least 2x2." ); - } - - *num_layers = layers; - *alphawidth = width; - *alphaheight = height; - - return alphamap; -} - -/* -================ -CalcTerrainSize -================ -*/ -void CalcTerrainSize( vec3_t mins, vec3_t maxs, vec3_t size ) { - bspbrush_t *brush; - int i; - const char *key; - - // calculate the size of the terrain - ClearBounds( mins, maxs ); - for( brush = mapent->brushes; brush != NULL; brush = brush->next ) { - AddPointToBounds( brush->mins, mins, maxs ); - AddPointToBounds( brush->maxs, mins, maxs ); - } - - key = ValueForKey( mapent, "min" ); - if ( key[ 0 ] ) { - GetVectorForKey( mapent, "min", mins ); - } - - key = ValueForKey( mapent, "max" ); - if ( key[ 0 ] ) { - GetVectorForKey( mapent, "max", maxs ); - } - - for( i = 0; i < 3; i++ ) { - mins[ i ] = floor( mins[ i ] + 0.1 ); - maxs[ i ] = floor( maxs[ i ] + 0.1 ); - } - - VectorSubtract( maxs, mins, size ); - - if ( ( size[ 0 ] <= 0 ) || ( size[ 1 ] <= 0 ) ) { - Error ("CalcTerrainSize: Invalid terrain size: %fx%f", size[ 0 ], size[ 1 ] ); - } -} - -/* -================== -IsTriangleDegenerate - -Returns qtrue if all three points are collinear or backwards -=================== -*/ -#define COLINEAR_AREA 10 -static qboolean IsTriangleDegenerate( drawVert_t *points, int a, int b, int c ) { - vec3_t v1, v2, v3; - float d; - - VectorSubtract( points[b].xyz, points[a].xyz, v1 ); - VectorSubtract( points[c].xyz, points[a].xyz, v2 ); - CrossProduct( v1, v2, v3 ); - d = VectorLength( v3 ); - - // assume all very small or backwards triangles will cause problems - if ( d < COLINEAR_AREA ) { - return qtrue; - } - - return qfalse; -} - -/* -=============== -SideAsTriFan - -The surface can't be represented as a single tristrip without -leaving a degenerate triangle (and therefore a crack), so add -a point in the middle and create (points-1) triangles in fan order -=============== -*/ -static void SideAsTriFan( terrainSurf_t *surf, int *index, int num ) { - int i; - int colorSum[4]; - drawVert_t *mid, *v; - - // make sure we have enough space for a new vert - if ( surf->numVerts >= surf->maxVerts ) { - surf->maxVerts += GROW_VERTS; - surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) ); - } - - // create a new point in the center of the face - mid = &surf->verts[ surf->numVerts ]; - surf->numVerts++; - - colorSum[0] = colorSum[1] = colorSum[2] = colorSum[3] = 0; - - for (i = 0 ; i < num; i++ ) { - v = &surf->verts[ index[ i ] ]; - VectorAdd( mid->xyz, v->xyz, mid->xyz ); - mid->st[0] += v->st[0]; - mid->st[1] += v->st[1]; - mid->lightmap[0] += v->lightmap[0]; - mid->lightmap[1] += v->lightmap[1]; - - colorSum[0] += v->color[0]; - colorSum[1] += v->color[1]; - colorSum[2] += v->color[2]; - colorSum[3] += v->color[3]; - } - - mid->xyz[0] /= num; - mid->xyz[1] /= num; - mid->xyz[2] /= num; - - mid->st[0] /= num; - mid->st[1] /= num; - - mid->lightmap[0] /= num; - mid->lightmap[1] /= num; - - mid->color[0] = colorSum[0] / num; - mid->color[1] = colorSum[1] / num; - mid->color[2] = colorSum[2] / num; - mid->color[3] = colorSum[3] / num; - - // fill in indices in trifan order - if ( surf->numIndexes + num * 3 > surf->maxIndexes ) { - surf->maxIndexes = surf->numIndexes + num * 3; - surf->indexes = realloc( surf->indexes, surf->maxIndexes * sizeof( *surf->indexes ) ); - } - - - for ( i = 0 ; i < num; i++ ) { - surf->indexes[ surf->numIndexes++ ] = surf->numVerts - 1; - surf->indexes[ surf->numIndexes++ ] = index[ i ]; - surf->indexes[ surf->numIndexes++ ] = index[ (i+1) % ( surf->numVerts - 1 ) ]; - } -} -/* -================ -SideAsTristrip - -Try to create indices that make (points-2) triangles in tristrip order -================ -*/ -#define MAX_INDICES 1024 -static void SideAsTristrip( terrainSurf_t *surf, int *index, int num ) { - int i; - int rotate; - int numIndices; - int ni; - int a, b, c; - int indices[ MAX_INDICES ]; - - // determine the triangle strip order - numIndices = ( num - 2 ) * 3; - if ( numIndices > MAX_INDICES ) { - Error( "MAX_INDICES exceeded for surface" ); - } - - // try all possible orderings of the points looking - // for a strip order that isn't degenerate - for ( rotate = 0 ; rotate < num; rotate++ ) { - for ( ni = 0, i = 0 ; i < num - 2 - i ; i++ ) { - a = index[ ( num - 1 - i + rotate ) % num ]; - b = index[ ( i + rotate ) % num ]; - c = index[ ( num - 2 - i + rotate ) % num ]; - - if ( IsTriangleDegenerate( surf->verts, a, b, c ) ) { - break; - } - indices[ni++] = a; - indices[ni++] = b; - indices[ni++] = c; - - if ( i + 1 != num - 1 - i ) { - a = index[ ( num - 2 - i + rotate ) % num ]; - b = index[ ( i + rotate ) % num ]; - c = index[ ( i + 1 + rotate ) % num ]; - - if ( IsTriangleDegenerate( surf->verts, a, b, c ) ) { - break; - } - indices[ni++] = a; - indices[ni++] = b; - indices[ni++] = c; - } - } - if ( ni == numIndices ) { - break; // got it done without degenerate triangles - } - } - - // if any triangle in the strip is degenerate, - // render from a centered fan point instead - if ( ni < numIndices ) { - SideAsTriFan( surf, index, num ); - return; - } - - // a normal tristrip - if ( surf->numIndexes + ni > surf->maxIndexes ) { - surf->maxIndexes = surf->numIndexes + ni; - surf->indexes = realloc( surf->indexes, surf->maxIndexes * sizeof( *surf->indexes ) ); - } - - memcpy( surf->indexes + surf->numIndexes, indices, ni * sizeof( *surf->indexes ) ); - surf->numIndexes += ni; -} - -/* -================ -CreateTerrainSurface -================ -*/ -void CreateTerrainSurface( terrainSurf_t *surf, shaderInfo_t *shader ) { - int i, j, k; - drawVert_t *out; - drawVert_t *in; - mapDrawSurface_t *newsurf; - - newsurf = AllocDrawSurf(); - - newsurf->miscModel = qtrue; - newsurf->shaderInfo = shader; - newsurf->lightmapNum = -1; - newsurf->fogNum = -1; - newsurf->numIndexes = surf->numIndexes; - newsurf->numVerts = surf->numVerts; - - // copy the indices - newsurf->indexes = malloc( surf->numIndexes * sizeof( *newsurf->indexes ) ); - memcpy( newsurf->indexes, surf->indexes, surf->numIndexes * sizeof( *newsurf->indexes ) ); - - // allocate the vertices - newsurf->verts = malloc( surf->numVerts * sizeof( *newsurf->verts ) ); - memset( newsurf->verts, 0, surf->numVerts * sizeof( *newsurf->verts ) ); - - // calculate the surface verts - out = newsurf->verts; - for( i = 0; i < newsurf->numVerts; i++, out++ ) { - VectorCopy( surf->verts[ i ].xyz, out->xyz ); - - // set the texture coordinates - out->st[ 0 ] = surf->verts[ i ].st[ 0 ]; - out->st[ 1 ] = surf->verts[ i ].st[ 1 ]; - - // the colors will be set by the lighting pass - out->color[0] = 255; - out->color[1] = 255; - out->color[2] = 255; - out->color[3] = surf->verts[ i ].color[ 3 ]; - - // calculate the vertex normal - VectorClear( out->normal ); - for( j = 0; j < numsurfaces; j++ ) { - in = surfaces[ j ].verts; - for( k = 0; k < surfaces[ j ].numVerts; k++, in++ ) { - if ( CompareVert( out, in, qfalse ) ) { - VectorAdd( out->normal, in->normal, out->normal ); - } - } - } - - VectorNormalize( out->normal, out->normal ); - } -} - -/* -================ -EmitTerrainVerts -================ -*/ -void EmitTerrainVerts( side_t *side, terrainSurf_t *surf, int maxlayer, int alpha[ MAX_POINTS_ON_WINDING ], qboolean projecttexture ) { - int i; - int j; - drawVert_t *vert; - int *indices; - int numindices; - int maxindices; - int xyplane; - vec3_t xynorm = { 0, 0, 1 }; - vec_t shift[ 2 ] = { 0, 0 }; - vec_t scale[ 2 ] = { 0.5, 0.5 }; - float vecs[ 2 ][ 4 ]; - static int numtimes = 0; - - numtimes++; - - if ( !surf->verts ) { - surf->numVerts = 0; - surf->maxVerts = GROW_VERTS; - surf->verts = malloc( surf->maxVerts * sizeof( *surf->verts ) ); - - surf->numIndexes = 0; - surf->maxIndexes = GROW_INDICES; - surf->indexes = malloc( surf->maxIndexes * sizeof( *surf->indexes ) ); - } - - // calculate the texture coordinate vectors - xyplane = FindFloatPlane( xynorm, 0 ); - QuakeTextureVecs( &mapplanes[ xyplane ], shift, 0, scale, vecs ); - - // emit the vertexes - numindices = 0; - maxindices = surf->maxIndexes; - indices = malloc ( maxindices * sizeof( *indices ) ); - - for ( i = 0; i < side->winding->numpoints; i++ ) { - vert = &surf->verts[ surf->numVerts ]; - - // set the final alpha value--0 for texture 1, 255 for texture 2 - if ( alpha[ i ] < maxlayer ) { - vert->color[3] = 0; - } else { - vert->color[3] = 255; - } - - vert->xyz[ 0 ] = floor( side->winding->p[ i ][ 0 ] + 0.1f ); - vert->xyz[ 1 ] = floor( side->winding->p[ i ][ 1 ] + 0.1f ); - vert->xyz[ 2 ] = floor( side->winding->p[ i ][ 2 ] + 0.1f ); - - // set the texture coordinates - if ( projecttexture ) { - vert->st[0] = ( vecs[0][3] + DotProduct( vecs[ 0 ], vert->xyz ) ) / surf->shader->width; - vert->st[1] = ( vecs[1][3] + DotProduct( vecs[ 1 ], vert->xyz ) ) / surf->shader->height; - } else { - vert->st[0] = ( side->vecs[0][3] + DotProduct( side->vecs[ 0 ], vert->xyz ) ) / surf->shader->width; - vert->st[1] = ( side->vecs[1][3] + DotProduct( side->vecs[ 1 ], vert->xyz ) ) / surf->shader->height; - } - - VectorCopy( mapplanes[ side->planenum ].normal, vert->normal ); - - for( j = 0; j < surf->numVerts; j++ ) { - if ( CompareVert( vert, &surf->verts[ j ], qtrue ) ) { - break; - } - } - - if ( numindices >= maxindices ) { - maxindices += GROW_INDICES; - indices = realloc( indices, maxindices * sizeof( *indices ) ); - } - - if ( j != surf->numVerts ) { - indices[ numindices++ ] = j; - } else { - indices[ numindices++ ] = surf->numVerts; - surf->numVerts++; - if ( surf->numVerts >= surf->maxVerts ) { - surf->maxVerts += GROW_VERTS; - surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) ); - } - } - } - - SideAsTristrip( surf, indices, numindices ); - - free( indices ); -} - -/* -================ -SurfaceForShader -================ -*/ -terrainSurf_t *SurfaceForShader( shaderInfo_t *shader, int x, int y ) { - int i; - - if ( lastSurface && ( lastSurface->shader == shader ) && ( lastSurface->x == x ) && ( lastSurface->y == y ) ) { - return lastSurface; - } - - lastSurface = surfaces; - for( i = 0; i < numsurfaces; i++, lastSurface++ ) { - if ( ( lastSurface->shader == shader ) && ( lastSurface->x == x ) && ( lastSurface->y == y ) ) { - return lastSurface; - } - } - - if ( numsurfaces >= maxsurfaces ) { - maxsurfaces += GROW_SURFACES; - surfaces = realloc( surfaces, maxsurfaces * sizeof( *surfaces ) ); - memset( surfaces + numsurfaces + 1, 0, ( maxsurfaces - numsurfaces - 1 ) * sizeof( *surfaces ) ); - } - - lastSurface= &surfaces[ numsurfaces++ ]; - lastSurface->shader = shader; - lastSurface->x = x; - lastSurface->y = y; - - return lastSurface; -} - -/* -================ -SetTerrainTextures -================ -*/ -void SetTerrainTextures( void ) { - int i; - int x, y; - int layer; - int minlayer, maxlayer; - float s, t; - float min_s, min_t; - int alpha[ MAX_POINTS_ON_WINDING ]; - shaderInfo_t *si, *terrainShader; - bspbrush_t *brush; - side_t *side; - const char *shadername; - vec3_t mins, maxs; - vec3_t size; - int surfwidth, surfheight, surfsize; - terrainSurf_t *surf; - byte *alphamap; - int alphawidth, alphaheight; - int num_layers; - extern qboolean onlyents; - - if ( onlyents ) { - return; - } - - shadername = ValueForKey( mapent, "shader" ); - if ( !shadername[ 0 ] ) { - Error ("SetTerrainTextures: shader not specified" ); - } - - alphamap = LoadAlphaMap( &num_layers, &alphawidth, &alphaheight ); - - mapent->firstDrawSurf = numMapDrawSurfs; - - // calculate the size of the terrain - CalcTerrainSize( mins, maxs, size ); - - surfwidth = ( size[ 0 ] + SURF_WIDTH - 1 ) / SURF_WIDTH; - surfheight = ( size[ 1 ] + SURF_HEIGHT - 1 ) / SURF_HEIGHT; - surfsize = surfwidth * surfheight; - - lastSurface = NULL; - numsurfaces = 0; - maxsurfaces = 0; - for( i = num_layers; i > 0; i-- ) { - maxsurfaces += i * surfsize; - } - surfaces = malloc( maxsurfaces * sizeof( *surfaces ) ); - memset( surfaces, 0, maxsurfaces * sizeof( *surfaces ) ); - - terrainShader = ShaderInfoForShader( "textures/common/terrain" ); - - for( brush = mapent->brushes; brush != NULL; brush = brush->next ) { - // only create surfaces for sides marked as terrain - for( side = brush->sides; side < &brush->sides[ brush->numsides ]; side++ ) { - if ( !side->shaderInfo ) { - continue; - } - - if ( ( ( side->surfaceFlags | side->shaderInfo->surfaceFlags ) & SURF_NODRAW ) && !strstr( side->shaderInfo->shader, "terrain" ) ) { - continue; - } - - minlayer = num_layers; - maxlayer = 0; - - // project each point of the winding onto the alphamap to determine which - // textures to blend - min_s = 1.0; - min_t = 1.0; - for( i = 0; i < side->winding->numpoints; i++ ) { - s = floor( side->winding->p[ i ][ 0 ] + 0.1f - mins[ 0 ] ) / size[ 0 ]; - t = floor( side->winding->p[ i ][ 1 ] + 0.1f - mins[ 0 ] ) / size[ 1 ]; - - if ( s < 0 ) { - s = 0; - } - - if ( t < 0 ) { - t = 0; - } - - if ( s >= 1.0 ) { - s = 1.0; - } - - if ( t >= 1.0 ) { - t = 1.0; - } - - if ( s < min_s ) { - min_s = s; - } - - if ( t < min_t ) { - min_t = t; - } - - x = ( alphawidth - 1 ) * s; - y = ( alphaheight - 1 ) * t; - - layer = alphamap[ x + y * alphawidth ]; - if ( layer < minlayer ) { - minlayer = layer; - } - - if ( layer > maxlayer ) { - maxlayer = layer; - } - - alpha[ i ] = layer; - } - - x = min_s * surfwidth; - if ( x >= surfwidth ) { - x = surfwidth - 1; - } - - y = min_t * surfheight; - if ( y >= surfheight ) { - y = surfheight - 1; - } - - if ( strstr( side->shaderInfo->shader, "terrain" ) ) { - si = ShaderForLayer( minlayer, maxlayer, shadername ); - if ( showseams ) { - for( i = 0; i < side->winding->numpoints; i++ ) { - if ( ( alpha[ i ] != minlayer ) && ( alpha[ i ] != maxlayer ) ) { - si = ShaderInfoForShader( "textures/common/white" ); - break; - } - } - } - surf = SurfaceForShader( si, x, y ); - EmitTerrainVerts( side, surf, maxlayer, alpha, qtrue ); - } else { - si = side->shaderInfo; - side->shaderInfo = terrainShader; - surf = SurfaceForShader( si, x, y ); - EmitTerrainVerts( side, surf, maxlayer, alpha, qfalse ); - } - } - } - - // create the final surfaces - for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { - if ( surf->numVerts ) { - CreateTerrainSurface( surf, surf->shader ); - } - } - - // - // clean up any allocated memory - // - for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { - if ( surf->verts ) { - free( surf->verts ); - free( surf->indexes ); - } - } - free( alphamap ); - free( surfaces ); - - surfaces = NULL; - lastSurface = NULL; - numsurfaces = 0; - maxsurfaces = 0; -} - -/***************************************************************************** - - New terrain code - -******************************************************************************/ - -typedef struct terrainFace_s { - shaderInfo_t *shaderInfo; - //texdef_t texdef; - - float vecs[ 2 ][ 4 ]; // texture coordinate mapping -} terrainFace_t; - -typedef struct terrainVert_s { - vec3_t xyz; - terrainFace_t tri; -} terrainVert_t; - -typedef struct terrainMesh_s { - float scale_x; - float scale_y; - vec3_t origin; - - int width, height; - terrainVert_t *map; -} terrainMesh_t; - -terrainVert_t *Terrain_GetVert( terrainMesh_t *pm, int x, int y ) { - return &pm->map[ x + y * pm->width ]; -} - -void Terrain_GetTriangles( terrainMesh_t *pm, int x, int y, terrainVert_t **verts ) { - if ( ( x + y ) & 1 ) { - // first tri - verts[ 0 ] = Terrain_GetVert( pm, x, y ); - verts[ 1 ] = Terrain_GetVert( pm, x, y + 1 ); - verts[ 2 ] = Terrain_GetVert( pm, x + 1, y + 1 ); - - // second tri - verts[ 3 ] = verts[ 2 ]; - verts[ 4 ] = Terrain_GetVert( pm, x + 1, y ); - verts[ 5 ] = verts[ 0 ]; - } else { - // first tri - verts[ 0 ] = Terrain_GetVert( pm, x, y ); - verts[ 1 ] = Terrain_GetVert( pm, x, y + 1 ); - verts[ 2 ] = Terrain_GetVert( pm, x + 1, y ); - - // second tri - verts[ 3 ] = verts[ 2 ]; - verts[ 4 ] = verts[ 1 ]; - verts[ 5 ] = Terrain_GetVert( pm, x + 1, y + 1 ); - } -} - -/* -================ -EmitTerrainVerts2 -================ -*/ -void EmitTerrainVerts2( terrainSurf_t *surf, terrainVert_t **verts, int alpha[ 3 ] ) { - int i; - int j; - drawVert_t *vert; - int *indices; - int numindices; - int maxindices; - int xyplane; - vec3_t xynorm = { 0, 0, 1 }; - vec_t shift[ 2 ] = { 0, 0 }; - vec_t scale[ 2 ] = { 0.5, 0.5 }; - float vecs[ 2 ][ 4 ]; - vec4_t plane; - - if ( !surf->verts ) { - surf->numVerts = 0; - surf->maxVerts = GROW_VERTS; - surf->verts = malloc( surf->maxVerts * sizeof( *surf->verts ) ); - - surf->numIndexes = 0; - surf->maxIndexes = GROW_INDICES; - surf->indexes = malloc( surf->maxIndexes * sizeof( *surf->indexes ) ); - } - - // calculate the texture coordinate vectors - xyplane = FindFloatPlane( xynorm, 0 ); - QuakeTextureVecs( &mapplanes[ xyplane ], shift, 0, scale, vecs ); - - // emit the vertexes - numindices = 0; - maxindices = surf->maxIndexes; - assert( maxindices >= 0 ); - indices = malloc ( maxindices * sizeof( *indices ) ); - - PlaneFromPoints( plane, verts[ 0 ]->xyz, verts[ 1 ]->xyz, verts[ 2 ]->xyz ); - - for ( i = 0; i < 3; i++ ) { - vert = &surf->verts[ surf->numVerts ]; - - if ( alpha[ i ] ) { - vert->color[3] = 255; - } else { - vert->color[3] = 0; - } - - vert->xyz[ 0 ] = floor( verts[ i ]->xyz[ 0 ] + 0.1f ); - vert->xyz[ 1 ] = floor( verts[ i ]->xyz[ 1 ] + 0.1f ); - vert->xyz[ 2 ] = floor( verts[ i ]->xyz[ 2 ] + 0.1f ); - - // set the texture coordinates - vert->st[0] = ( vecs[0][3] + DotProduct( vecs[ 0 ], vert->xyz ) ) / surf->shader->width; - vert->st[1] = ( vecs[1][3] + DotProduct( vecs[ 1 ], vert->xyz ) ) / surf->shader->height; - - VectorCopy( plane, vert->normal ); - - for( j = 0; j < surf->numVerts; j++ ) { - if ( CompareVert( vert, &surf->verts[ j ], qtrue ) ) { - break; - } - } - - if ( numindices >= maxindices ) { - maxindices += GROW_INDICES; - indices = realloc( indices, maxindices * sizeof( *indices ) ); - } - - if ( j != surf->numVerts ) { - indices[ numindices++ ] = j; - } else { - indices[ numindices++ ] = surf->numVerts; - surf->numVerts++; - if ( surf->numVerts >= surf->maxVerts ) { - surf->maxVerts += GROW_VERTS; - surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) ); - } - } - } - - SideAsTristrip( surf, indices, numindices ); - - free( indices ); -} - -int MapPlaneFromPoints( vec3_t p0, vec3_t p1, vec3_t p2 ); -void QuakeTextureVecs( plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2], vec_t mappingVecs[2][4] ); -qboolean RemoveDuplicateBrushPlanes( bspbrush_t *b ); -void SetBrushContents( bspbrush_t *b ); - -void AddBrushSide( vec3_t v1, vec3_t v2, vec3_t v3, shaderInfo_t *terrainShader ) { - side_t *side; - int planenum; - - side = &buildBrush->sides[ buildBrush->numsides ]; - memset( side, 0, sizeof( *side ) ); - buildBrush->numsides++; - - side->shaderInfo = terrainShader; - - // find the plane number - planenum = MapPlaneFromPoints( v1, v2, v3 ); - side->planenum = planenum; -} - -void MakeBrushFromTriangle( vec3_t v1, vec3_t v2, vec3_t v3, shaderInfo_t *terrainShader ) { - bspbrush_t *b; - vec3_t d1; - vec3_t d2; - vec3_t d3; - - VectorSet( d1, v1[ 0 ], v1[ 1 ], MIN_WORLD_COORD + 10 ); //FIXME - VectorSet( d2, v2[ 0 ], v2[ 1 ], MIN_WORLD_COORD + 10 ); - VectorSet( d3, v3[ 0 ], v3[ 1 ], MIN_WORLD_COORD + 10 ); - - buildBrush->numsides = 0; - buildBrush->detail = qfalse; - - AddBrushSide( v1, v2, v3, terrainShader ); - AddBrushSide( v1, d1, v2, terrainShader ); - AddBrushSide( v2, d2, v3, terrainShader ); - AddBrushSide( v3, d3, v1, terrainShader ); - AddBrushSide( d3, d2, d1, terrainShader ); - - buildBrush->portalareas[0] = -1; - buildBrush->portalareas[1] = -1; - buildBrush->entitynum = num_entities-1; - buildBrush->brushnum = entitySourceBrushes; - - // if there are mirrored planes, the entire brush is invalid - if ( !RemoveDuplicateBrushPlanes( buildBrush ) ) { - return; - } - - // get the content for the entire brush - SetBrushContents( buildBrush ); - buildBrush->contents |= CONTENTS_DETAIL; - - b = FinishBrush(); - if ( !b ) { - return; - } -} - -void MakeTerrainIntoBrushes( terrainMesh_t *tm ) { - int index[ 6 ]; - int y; - int x; - terrainVert_t *verts; - shaderInfo_t *terrainShader; - - terrainShader = ShaderInfoForShader( "textures/common/terrain" ); - - verts = tm->map; - for( y = 0; y < tm->height - 1; y++ ) { - for( x = 0; x < tm->width - 1; x++ ) { - if ( ( x + y ) & 1 ) { - // first tri - index[ 0 ] = x + y * tm->width; - index[ 1 ] = x + ( y + 1 ) * tm->width; - index[ 2 ] = ( x + 1 ) + ( y + 1 ) * tm->width; - index[ 3 ] = ( x + 1 ) + ( y + 1 ) * tm->width; - index[ 4 ] = ( x + 1 ) + y * tm->width; - index[ 5 ] = x + y * tm->width; - } else { - // first tri - index[ 0 ] = x + y * tm->width; - index[ 1 ] = x + ( y + 1 ) * tm->width; - index[ 2 ] = ( x + 1 ) + y * tm->width; - index[ 3 ] = ( x + 1 ) + y * tm->width; - index[ 4 ] = x + ( y + 1 ) * tm->width; - index[ 5 ] = ( x + 1 ) + ( y + 1 ) * tm->width; - } - - MakeBrushFromTriangle( verts[ index[ 0 ] ].xyz, verts[ index[ 1 ] ].xyz, verts[ index[ 2 ] ].xyz, terrainShader ); - MakeBrushFromTriangle( verts[ index[ 3 ] ].xyz, verts[ index[ 4 ] ].xyz, verts[ index[ 5 ] ].xyz, terrainShader ); - } - } -} - -void Terrain_ParseFace( terrainFace_t *face ) { - shaderInfo_t *si; - vec_t shift[ 2 ]; - vec_t rotate; - vec_t scale[ 2 ]; - char name[ MAX_QPATH ]; - char shader[ MAX_QPATH ]; - plane_t p; - - // read the texturedef - GetToken( qfalse ); - strcpy( name, token ); - - GetToken( qfalse ); - shift[ 0 ] = atof(token); - GetToken( qfalse ); - shift[ 1 ] = atof( token ); - GetToken( qfalse ); - rotate = atof( token ); - GetToken( qfalse ); - scale[ 0 ] = atof( token ); - GetToken( qfalse ); - scale[ 1 ] = atof( token ); - - // find default flags and values - sprintf( shader, "textures/%s", name ); - si = ShaderInfoForShader( shader ); - face->shaderInfo = si; - //face->texdef = si->texdef; - - // skip over old contents - GetToken( qfalse ); - - // skip over old flags - GetToken( qfalse ); - - // skip over old value - GetToken( qfalse ); - - //Surface_Parse( &face->texdef ); - //Surface_BuildTexdef( &face->texdef ); - - // make a fake horizontal plane - VectorSet( p.normal, 0, 0, 1 ); - p.dist = 0; - p.type = PlaneTypeForNormal( p.normal ); - - QuakeTextureVecs( &p, shift, rotate, scale, face->vecs ); -} - -#define MAX_TERRAIN_TEXTURES 128 -static int numtextures = 0;; -static shaderInfo_t *textures[ MAX_TERRAIN_TEXTURES ]; - -void Terrain_AddTexture( shaderInfo_t *texture ) { - int i; - - if ( !texture ) { - return; - } - - for( i = 0; i < numtextures; i++ ) { - if ( textures[ i ] == texture ) { - return; - } - } - - if ( numtextures >= MAX_TERRAIN_TEXTURES ) { - Error( "Too many textures on terrain" ); - return; - } - - textures[ numtextures++ ] = texture; -} - -int LayerForShader( shaderInfo_t *shader ) { - int i; - int l; - - l = strlen( shader->shader ); - for( i = l - 1; i >= 0; i-- ) { - if ( shader->shader[ i ] == '_' ) { - return atoi( &shader->shader[ i + 1 ] ); - break; - } - } - - return 0; -} - -/* -================= -ParseTerrain - -Creates a mapDrawSurface_t from the terrain text -================= -*/ - -void ParseTerrain( void ) { - int i, j; - int x, y; - int x1, y1; - terrainMesh_t t; - int index; - terrainVert_t *verts[ 6 ]; - int num_layers; - int layer, minlayer, maxlayer; - int alpha[ 6 ]; - shaderInfo_t *si, *terrainShader; - int surfwidth, surfheight, surfsize; - terrainSurf_t *surf; - char shadername[ MAX_QPATH ]; - - mapent->firstDrawSurf = numMapDrawSurfs; - - memset( &t, 0, sizeof( t ) ); - - MatchToken( "{" ); - - // get width - GetToken( qtrue ); - t.width = atoi( token ); - - // get height - GetToken( qfalse ); - t.height = atoi( token ); - - // get scale_x - GetToken( qfalse ); - t.scale_x = atof( token ); - - // get scale_y - GetToken( qfalse ); - t.scale_y = atof( token ); - - // get origin - GetToken( qtrue ); - t.origin[ 0 ] = atof( token ); - GetToken( qfalse ); - t.origin[ 1 ] = atof( token ); - GetToken( qfalse ); - t.origin[ 2 ] = atof( token ); - - t.map = malloc( t.width * t.height * sizeof( t.map[ 0 ] ) ); - - if ( t.width <= 0 || t.height <= 0 ) { - Error( "ParseTerrain: bad size" ); - } - - numtextures = 0; - index = 0; - for ( i = 0; i < t.height; i++ ) { - for( j = 0; j < t.width; j++, index++ ) { - // get height - GetToken( qtrue ); - t.map[ index ].xyz[ 0 ] = t.origin[ 0 ] + t.scale_x * ( float )j; - t.map[ index ].xyz[ 1 ] = t.origin[ 1 ] + t.scale_y * ( float )i; - t.map[ index ].xyz[ 2 ] = t.origin[ 2 ] + atof( token ); - - Terrain_ParseFace( &t.map[ index ].tri ); - Terrain_AddTexture( t.map[ index ].tri.shaderInfo ); - } - } - - MatchToken( "}" ); - MatchToken( "}" ); - - MakeTerrainIntoBrushes( &t ); - - surfwidth = ( ( t.scale_x * t.width ) + SURF_WIDTH - 1 ) / SURF_WIDTH; - surfheight = ( ( t.scale_y * t.height ) + SURF_HEIGHT - 1 ) / SURF_HEIGHT; - surfsize = surfwidth * surfheight; - - //FIXME - num_layers = 0; - for( i = 0; i < numtextures; i++ ) { - layer = LayerForShader( textures[ i ] ) + 1; - if ( layer > num_layers ) { - num_layers = layer; - } - } - num_layers = 4; - - memset( alpha, 0, sizeof( alpha ) ); - - lastSurface = NULL; - numsurfaces = 0; - maxsurfaces = 0; - for( i = num_layers; i > 0; i-- ) { - maxsurfaces += i * surfsize; - } - - surfaces = malloc( maxsurfaces * sizeof( *surfaces ) ); - memset( surfaces, 0, maxsurfaces * sizeof( *surfaces ) ); - - terrainShader = ShaderInfoForShader( "textures/common/terrain" ); - - // get the shadername - if ( Q_strncasecmp( textures[ 0 ]->shader, "textures/", 9 ) == 0 ) { - strcpy( shadername, &textures[ 0 ]->shader[ 9 ] ); - } else { - strcpy( shadername, textures[ 0 ]->shader ); - } - j = strlen( shadername ); - for( i = j - 1; i >= 0; i-- ) { - if ( shadername[ i ] == '_' ) { - shadername[ i ] = 0; - break; - } - } - - for( y = 0; y < t.height - 1; y++ ) { - for( x = 0; x < t.width - 1; x++ ) { - Terrain_GetTriangles( &t, x, y, verts ); - - x1 = ( ( float )x / ( float )( t.width - 1 ) ) * surfwidth; - if ( x1 >= surfwidth ) { - x1 = surfwidth - 1; - } - - y1 = ( ( float )y / ( float )( t.height - 1 ) ) * surfheight; - if ( y1 >= surfheight ) { - y1 = surfheight - 1; - } - - maxlayer = minlayer = LayerForShader( verts[ 0 ]->tri.shaderInfo ); - for( i = 0; i < 3; i++ ) { - layer = LayerForShader( verts[ i ]->tri.shaderInfo ); - if ( layer < minlayer ) { - minlayer = layer; - } - if ( layer > maxlayer ) { - maxlayer = layer; - } - } - - for( i = 0; i < 3; i++ ) { - layer = LayerForShader( verts[ i ]->tri.shaderInfo ); - if ( layer > minlayer ) { - alpha[ i ] = 1.0f; - } else { - alpha[ i ] = 0.0f; - } - } - - si = ShaderForLayer( minlayer, maxlayer, shadername ); - surf = SurfaceForShader( si, x1, y1 ); - EmitTerrainVerts2( surf, &verts[ 0 ], &alpha[ 0 ] ); - - // second triangle - maxlayer = minlayer = LayerForShader( verts[ 3 ]->tri.shaderInfo ); - for( i = 3; i < 6; i++ ) { - layer = LayerForShader( verts[ i ]->tri.shaderInfo ); - if ( layer < minlayer ) { - minlayer = layer; - } - if ( layer > maxlayer ) { - maxlayer = layer; - } - } - - for( i = 3; i < 6; i++ ) { - layer = LayerForShader( verts[ i ]->tri.shaderInfo ); - if ( layer > minlayer ) { - alpha[ i ] = 1.0f; - } else { - alpha[ i ] = 0.0f; - } - } - - si = ShaderForLayer( minlayer, maxlayer, shadername ); - surf = SurfaceForShader( si, x1, y1 ); - EmitTerrainVerts2( surf, &verts[ 3 ], &alpha[ 3 ] ); - } - } - - // create the final surfaces - for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { - if ( surf->numVerts ) { - CreateTerrainSurface( surf, surf->shader ); - } - } - - // - // clean up any allocated memory - // - for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { - if ( surf->verts ) { - free( surf->verts ); - free( surf->indexes ); - } - } - free( surfaces ); - - surfaces = NULL; - lastSurface = NULL; - numsurfaces = 0; - maxsurfaces = 0; - - free( t.map ); -} - |