⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 terrain.c

📁 quake3工具源码。包括生成bsp文件
💻 C
📖 第 1 页 / 共 2 页
字号:
#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

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();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -