Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

patch.c (6874B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 #include "qbsp.h"
     23 
     24 
     25 void PrintCtrl( vec3_t ctrl[9] ) {
     26 	int		i, j;
     27 
     28 	for ( i = 0 ; i < 3 ; i++ ) {
     29 		for ( j = 0 ; j < 3 ; j++ ) {
     30 			_printf("(%5.2f %5.2f %5.2f) ", ctrl[i*3+j][0], ctrl[i*3+j][1], ctrl[i*3+j][2] );
     31 		}
     32 		_printf("\n");
     33 	}
     34 }
     35 
     36 /*
     37 ================
     38 DrawSurfaceForMesh
     39 ================
     40 */
     41 mapDrawSurface_t	*DrawSurfaceForMesh( mesh_t *m ) {
     42 	mapDrawSurface_t	*ds;
     43 	int				i, j;
     44 	mesh_t			*copy;
     45 
     46 	// to make valid normals for patches with degenerate edges,
     47 	// we need to make a copy of the mesh and put the aproximating
     48 	// points onto the curve
     49 	copy = CopyMesh( m );
     50 	PutMeshOnCurve( *copy );
     51 	MakeMeshNormals( *copy );
     52 	for ( j = 0 ; j < m->width ; j++ ) {
     53 		for ( i = 0 ; i < m->height ; i++ ) {
     54 			VectorCopy( copy->verts[i*m->width+j].normal, m->verts[i*m->width+j].normal );
     55 		}
     56 	}
     57 	FreeMesh( copy );
     58 
     59 	ds = AllocDrawSurf();
     60 	ds->mapBrush = NULL;
     61 	ds->side = NULL;
     62 
     63 	ds->patch = qtrue;
     64 	ds->patchWidth = m->width;
     65 	ds->patchHeight = m->height;
     66 	ds->numVerts = ds->patchWidth * ds->patchHeight;
     67 	ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) );
     68 	memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) );
     69 
     70 	ds->lightmapNum = -1;
     71 	ds->fogNum = -1;
     72 
     73 	return ds;
     74 }
     75 
     76 /*
     77 =================
     78 ParsePatch
     79 
     80 Creates a mapDrawSurface_t from the patch text
     81 =================
     82 */
     83 void ParsePatch( void ) {
     84 	vec_t		info[5];
     85 	int			i, j;
     86 	parseMesh_t	*pm;
     87 	char		texture[MAX_QPATH];
     88 	char		shader[MAX_QPATH];
     89 	mesh_t		m;
     90 	drawVert_t	*verts;
     91   epair_t *ep;
     92 
     93 	MatchToken( "{" );
     94 
     95 	// get texture
     96 	GetToken (qtrue);
     97 	strcpy( texture, token );
     98 
     99 	// save the shader name for retexturing
    100 	if ( numMapIndexedShaders == MAX_MAP_BRUSHSIDES ) {
    101 		Error( "MAX_MAP_BRUSHSIDES" );
    102 	}
    103 	strcpy( mapIndexedShaders[numMapIndexedShaders], texture );
    104 	numMapIndexedShaders++;
    105 
    106 
    107 	Parse1DMatrix( 5, info );
    108 	m.width = info[0];
    109 	m.height = info[1];
    110 	m.verts = verts = malloc( m.width * m.height * sizeof( m.verts[0] ) );
    111 
    112 	if ( m.width < 0 || m.width > MAX_PATCH_SIZE
    113 		|| m.height < 0 || m.height > MAX_PATCH_SIZE ) {
    114 		Error("ParsePatch: bad size");
    115 	}
    116 
    117 	MatchToken( "(" );
    118 	for ( j = 0 ; j < m.width ; j++ ) {
    119 		MatchToken( "(" );
    120 		for ( i = 0 ; i < m.height ; i++ ) {
    121 			Parse1DMatrix( 5, verts[i*m.width+j].xyz );
    122 		}
    123 		MatchToken( ")" );
    124 	}
    125 	MatchToken( ")" );
    126 
    127   // if brush primitives format, we may have some epairs to ignore here
    128   GetToken(qtrue);
    129   if (g_bBrushPrimit!=BPRIMIT_OLDBRUSHES && strcmp(token,"}"))
    130   {
    131     // NOTE: we leak that!
    132     ep = ParseEpair();
    133   }
    134   else
    135     UnGetToken();
    136 
    137 	MatchToken( "}" );
    138 	MatchToken( "}" );
    139 
    140 	if ( noCurveBrushes ) {
    141 		return;
    142 	}
    143 
    144 	// find default flags and values
    145 	pm = malloc( sizeof( *pm ) );
    146 	memset( pm, 0, sizeof( *pm ) );
    147 
    148 	sprintf( shader, "textures/%s", texture );
    149 	pm->shaderInfo = ShaderInfoForShader( shader ); 
    150 	pm->mesh = m;
    151 
    152 	// link to the entity
    153 	pm->next = mapent->patches;
    154 	mapent->patches = pm;
    155 }
    156 
    157 
    158 void GrowGroup_r( int patchNum, int patchCount, const byte *bordering, byte *group ) {
    159 	int		i;
    160 	const byte *row;
    161 
    162 	if ( group[patchNum] ) {
    163 		return;
    164 	}
    165 	group[patchNum] = 1;
    166 	row = bordering + patchNum * patchCount;
    167 	for ( i = 0 ; i < patchCount ; i++ ) {
    168 		if ( row[i] ) {
    169 			GrowGroup_r( i, patchCount, bordering, group );
    170 		}
    171 	}
    172 }
    173 
    174 
    175 /*
    176 =====================
    177 PatchMapDrawSurfs
    178 
    179 Any patches that share an edge need to choose their
    180 level of detail as a unit, otherwise the edges would
    181 pull apart.
    182 =====================
    183 */
    184 void PatchMapDrawSurfs( entity_t *e ) {
    185 	parseMesh_t			*pm;
    186 	parseMesh_t			*check, *scan;
    187 	mapDrawSurface_t	*ds;
    188 	int					patchCount, groupCount;
    189 	int					i, j, k, l, c1, c2;
    190 	drawVert_t			*v1, *v2;
    191 	vec3_t				bounds[2];
    192 	byte				*bordering;
    193 	parseMesh_t			*meshes[MAX_MAP_DRAW_SURFS];
    194 	qboolean			grouped[MAX_MAP_DRAW_SURFS];
    195 	byte				group[MAX_MAP_DRAW_SURFS];
    196 
    197 	qprintf( "----- PatchMapDrawSurfs -----\n" );
    198 
    199 	patchCount = 0;
    200 	for ( pm = e->patches ; pm ; pm = pm->next  ) {
    201 		meshes[patchCount] = pm;
    202 		patchCount++;
    203 	}
    204 
    205 	if ( !patchCount ) {
    206 		return;
    207 	}
    208 	bordering = malloc( patchCount * patchCount );
    209 	memset( bordering, 0, patchCount * patchCount );
    210 
    211 	// build the bordering matrix
    212 	for ( k = 0 ; k < patchCount ; k++ ) {
    213 		bordering[k*patchCount+k] = 1;
    214 
    215 		for ( l = k+1 ; l < patchCount ; l++ ) {
    216 			check = meshes[k];
    217 			scan = meshes[l];
    218 			c1 = scan->mesh.width * scan->mesh.height;
    219 			v1 = scan->mesh.verts;
    220 
    221 			for ( i = 0 ; i < c1 ; i++, v1++ ) {
    222 				c2 = check->mesh.width * check->mesh.height;
    223 				v2 = check->mesh.verts;
    224 				for ( j = 0 ; j < c2 ; j++, v2++ ) {
    225 					if ( fabs( v1->xyz[0] - v2->xyz[0] ) < 1.0
    226 						&& fabs( v1->xyz[1] - v2->xyz[1] ) < 1.0
    227 						&& fabs( v1->xyz[2] - v2->xyz[2] ) < 1.0 ) {
    228 						break;
    229 					}
    230 				}
    231 				if ( j != c2 ) {
    232 					break;
    233 				}
    234 			}
    235 			if ( i != c1 ) {
    236 				// we have a connection
    237 				bordering[k*patchCount+l] =
    238 				bordering[l*patchCount+k] = 1;
    239 			} else {
    240 				// no connection
    241 				bordering[k*patchCount+l] =
    242 				bordering[l*patchCount+k] = 0;
    243 			}
    244 
    245 		}
    246 	}
    247 
    248 	// build groups
    249 	memset( grouped, 0, sizeof(grouped) );
    250 	groupCount = 0;
    251 	for ( i = 0 ; i < patchCount ; i++ ) {
    252 		if ( !grouped[i] ) {
    253 			groupCount++;
    254 		}
    255 
    256 		// recursively find all patches that belong in the same group
    257 		memset( group, 0, patchCount );
    258 		GrowGroup_r( i, patchCount, bordering, group );
    259 
    260 		// bound them
    261 		ClearBounds( bounds[0], bounds[1] );
    262 		for ( j = 0 ; j < patchCount ; j++ ) {
    263 			if ( group[j] ) {
    264 				grouped[j] = qtrue;
    265 				scan = meshes[j];
    266 				c1 = scan->mesh.width * scan->mesh.height;
    267 				v1 = scan->mesh.verts;
    268 				for ( k = 0 ; k < c1 ; k++, v1++ ) {
    269 					AddPointToBounds( v1->xyz, bounds[0], bounds[1] );
    270 				}
    271 			}
    272 		}
    273 
    274 		// create drawsurf
    275 		scan = meshes[i];
    276 		scan->grouped = qtrue;
    277 		ds = DrawSurfaceForMesh( &scan->mesh );
    278 		ds->shaderInfo = scan->shaderInfo;
    279 		VectorCopy( bounds[0], ds->lightmapVecs[0] );
    280 		VectorCopy( bounds[1], ds->lightmapVecs[1] );
    281 	}
    282 
    283 	qprintf( "%5i patches\n", patchCount );
    284 	qprintf( "%5i patch LOD groups\n", groupCount );
    285 }
    286