📄 terrain.c
字号:
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 ];
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 {
if ( surf->numVerts >= surf->maxVerts ) {
surf->maxVerts += GROW_VERTS;
surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) );
}
indices[ numindices++ ] = surf->numVerts;
surf->numVerts++;
}
}
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 );
num_layers = 3;
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( maxs[ 1 ] - side->winding->p[ i ][ 1 ] + 0.1f ) / 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -