123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /*
- ===========================================================================
- 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"
- void PrintCtrl( vec3_t ctrl[9] ) {
- int i, j;
- for ( i = 0 ; i < 3 ; i++ ) {
- for ( j = 0 ; j < 3 ; j++ ) {
- _printf("(%5.2f %5.2f %5.2f) ", ctrl[i*3+j][0], ctrl[i*3+j][1], ctrl[i*3+j][2] );
- }
- _printf("\n");
- }
- }
- /*
- ================
- DrawSurfaceForMesh
- ================
- */
- mapDrawSurface_t *DrawSurfaceForMesh( mesh_t *m ) {
- mapDrawSurface_t *ds;
- int i, j;
- mesh_t *copy;
- // to make valid normals for patches with degenerate edges,
- // we need to make a copy of the mesh and put the aproximating
- // points onto the curve
- copy = CopyMesh( m );
- PutMeshOnCurve( *copy );
- MakeMeshNormals( *copy );
- for ( j = 0 ; j < m->width ; j++ ) {
- for ( i = 0 ; i < m->height ; i++ ) {
- VectorCopy( copy->verts[i*m->width+j].normal, m->verts[i*m->width+j].normal );
- }
- }
- FreeMesh( copy );
- ds = AllocDrawSurf();
- ds->mapBrush = NULL;
- ds->side = NULL;
- ds->patch = qtrue;
- ds->patchWidth = m->width;
- ds->patchHeight = m->height;
- ds->numVerts = ds->patchWidth * ds->patchHeight;
- ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) );
- memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) );
- ds->lightmapNum = -1;
- ds->fogNum = -1;
- return ds;
- }
- /*
- =================
- ParsePatch
- Creates a mapDrawSurface_t from the patch text
- =================
- */
- void ParsePatch( void ) {
- vec_t info[5];
- int i, j;
- parseMesh_t *pm;
- char texture[MAX_QPATH];
- char shader[MAX_QPATH];
- mesh_t m;
- drawVert_t *verts;
- epair_t *ep;
- MatchToken( "{" );
- // get texture
- GetToken (qtrue);
- strcpy( texture, token );
- // save the shader name for retexturing
- if ( numMapIndexedShaders == MAX_MAP_BRUSHSIDES ) {
- Error( "MAX_MAP_BRUSHSIDES" );
- }
- strcpy( mapIndexedShaders[numMapIndexedShaders], texture );
- numMapIndexedShaders++;
- Parse1DMatrix( 5, info );
- m.width = info[0];
- m.height = info[1];
- m.verts = verts = malloc( m.width * m.height * sizeof( m.verts[0] ) );
- if ( m.width < 0 || m.width > MAX_PATCH_SIZE
- || m.height < 0 || m.height > MAX_PATCH_SIZE ) {
- Error("ParsePatch: bad size");
- }
- MatchToken( "(" );
- for ( j = 0 ; j < m.width ; j++ ) {
- MatchToken( "(" );
- for ( i = 0 ; i < m.height ; i++ ) {
- Parse1DMatrix( 5, verts[i*m.width+j].xyz );
- }
- MatchToken( ")" );
- }
- MatchToken( ")" );
- // if brush primitives format, we may have some epairs to ignore here
- GetToken(qtrue);
- if (g_bBrushPrimit!=BPRIMIT_OLDBRUSHES && strcmp(token,"}"))
- {
- // NOTE: we leak that!
- ep = ParseEpair();
- }
- else
- UnGetToken();
- MatchToken( "}" );
- MatchToken( "}" );
- if ( noCurveBrushes ) {
- return;
- }
- // find default flags and values
- pm = malloc( sizeof( *pm ) );
- memset( pm, 0, sizeof( *pm ) );
- sprintf( shader, "textures/%s", texture );
- pm->shaderInfo = ShaderInfoForShader( shader );
- pm->mesh = m;
- // link to the entity
- pm->next = mapent->patches;
- mapent->patches = pm;
- }
- void GrowGroup_r( int patchNum, int patchCount, const byte *bordering, byte *group ) {
- int i;
- const byte *row;
- if ( group[patchNum] ) {
- return;
- }
- group[patchNum] = 1;
- row = bordering + patchNum * patchCount;
- for ( i = 0 ; i < patchCount ; i++ ) {
- if ( row[i] ) {
- GrowGroup_r( i, patchCount, bordering, group );
- }
- }
- }
- /*
- =====================
- PatchMapDrawSurfs
- Any patches that share an edge need to choose their
- level of detail as a unit, otherwise the edges would
- pull apart.
- =====================
- */
- void PatchMapDrawSurfs( entity_t *e ) {
- parseMesh_t *pm;
- parseMesh_t *check, *scan;
- mapDrawSurface_t *ds;
- int patchCount, groupCount;
- int i, j, k, l, c1, c2;
- drawVert_t *v1, *v2;
- vec3_t bounds[2];
- byte *bordering;
- parseMesh_t *meshes[MAX_MAP_DRAW_SURFS];
- qboolean grouped[MAX_MAP_DRAW_SURFS];
- byte group[MAX_MAP_DRAW_SURFS];
- qprintf( "----- PatchMapDrawSurfs -----\n" );
- patchCount = 0;
- for ( pm = e->patches ; pm ; pm = pm->next ) {
- meshes[patchCount] = pm;
- patchCount++;
- }
- if ( !patchCount ) {
- return;
- }
- bordering = malloc( patchCount * patchCount );
- memset( bordering, 0, patchCount * patchCount );
- // build the bordering matrix
- for ( k = 0 ; k < patchCount ; k++ ) {
- bordering[k*patchCount+k] = 1;
- for ( l = k+1 ; l < patchCount ; l++ ) {
- check = meshes[k];
- scan = meshes[l];
- c1 = scan->mesh.width * scan->mesh.height;
- v1 = scan->mesh.verts;
- for ( i = 0 ; i < c1 ; i++, v1++ ) {
- c2 = check->mesh.width * check->mesh.height;
- v2 = check->mesh.verts;
- for ( j = 0 ; j < c2 ; j++, v2++ ) {
- if ( fabs( v1->xyz[0] - v2->xyz[0] ) < 1.0
- && fabs( v1->xyz[1] - v2->xyz[1] ) < 1.0
- && fabs( v1->xyz[2] - v2->xyz[2] ) < 1.0 ) {
- break;
- }
- }
- if ( j != c2 ) {
- break;
- }
- }
- if ( i != c1 ) {
- // we have a connection
- bordering[k*patchCount+l] =
- bordering[l*patchCount+k] = 1;
- } else {
- // no connection
- bordering[k*patchCount+l] =
- bordering[l*patchCount+k] = 0;
- }
- }
- }
- // build groups
- memset( grouped, 0, sizeof(grouped) );
- groupCount = 0;
- for ( i = 0 ; i < patchCount ; i++ ) {
- if ( !grouped[i] ) {
- groupCount++;
- }
- // recursively find all patches that belong in the same group
- memset( group, 0, patchCount );
- GrowGroup_r( i, patchCount, bordering, group );
- // bound them
- ClearBounds( bounds[0], bounds[1] );
- for ( j = 0 ; j < patchCount ; j++ ) {
- if ( group[j] ) {
- grouped[j] = qtrue;
- scan = meshes[j];
- c1 = scan->mesh.width * scan->mesh.height;
- v1 = scan->mesh.verts;
- for ( k = 0 ; k < c1 ; k++, v1++ ) {
- AddPointToBounds( v1->xyz, bounds[0], bounds[1] );
- }
- }
- }
- // create drawsurf
- scan = meshes[i];
- scan->grouped = qtrue;
- ds = DrawSurfaceForMesh( &scan->mesh );
- ds->shaderInfo = scan->shaderInfo;
- VectorCopy( bounds[0], ds->lightmapVecs[0] );
- VectorCopy( bounds[1], ds->lightmapVecs[1] );
- }
- qprintf( "%5i patches\n", patchCount );
- qprintf( "%5i patch LOD groups\n", groupCount );
- }
|