qboolean ParseEntity(void) { epair_t *e; /* dummy check */ if(!GetToken(qtrue)) return qfalse; if(strcmp(token, "{")) Error("ParseEntity: { not found"); if(numEntities == MAX_MAP_ENTITIES) Error("numEntities == MAX_MAP_ENTITIES"); /* create new entity */ mapEnt = &entities[numEntities]; numEntities++; /* parse */ while(1) { if(!GetToken(qtrue)) Error("ParseEntity: EOF without closing brace"); if(!EPAIR_STRCMP(token, "}")) break; e = ParseEPair(); e->next = mapEnt->epairs; mapEnt->epairs = e; } /* return to sender */ return qtrue; }
void ParsePatch( qboolean onlyLights ) { vec_t info[ 5 ]; int i, j, k; parseMesh_t *pm; char texture[ MAX_QPATH ]; char shader[ MAX_QPATH ]; mesh_t m; bspDrawVert_t *verts; epair_t *ep; vec4_t delta, delta2, delta3; qboolean degenerate; float longestCurve; int maxIterations; MatchToken( "{" ); /* get texture */ GetToken( qtrue ); strcpy( texture, token ); Parse1DMatrix( 5, info ); m.width = info[0]; m.height = info[1]; m.verts = verts = (bspDrawVert_t *)safe_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 ); /* ydnar: fix colors */ for( k = 0; k < MAX_LIGHTMAPS; k++ ) { verts[ i * m.width + j ].color[ k ][ 0 ] = 255; verts[ i * m.width + j ].color[ k ][ 1 ] = 255; verts[ i * m.width + j ].color[ k ][ 2 ] = 255; verts[ i * m.width + j ].color[ k ][ 3 ] = 255; } } 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( "}" ); /* short circuit */ if( noCurveBrushes || onlyLights ) return; /* ydnar: delete and warn about degenerate patches */ j = (m.width * m.height); VectorClear( delta ); delta[ 3 ] = 0; degenerate = qtrue; /* find first valid vector */ for( i = 1; i < j && delta[ 3 ] == 0; i++ ) { VectorSubtract( m.verts[ 0 ].xyz, m.verts[ i ].xyz, delta ); delta[ 3 ] = VectorNormalize( delta, delta ); } /* secondary degenerate test */ if( delta[ 3 ] == 0 ) degenerate = qtrue; else { /* if all vectors match this or are zero, then this is a degenerate patch */ for( i = 1; i < j && degenerate == qtrue; i++ ) { VectorSubtract( m.verts[ 0 ].xyz, m.verts[ i ].xyz, delta2 ); delta2[ 3 ] = VectorNormalize( delta2, delta2 ); if( delta2[ 3 ] != 0 ) { /* create inverse vector */ VectorCopy( delta2, delta3 ); delta3[ 3 ] = delta2[ 3 ]; VectorNegate( delta3, delta3 ); /* compare */ if( VectorCompare( delta, delta2 ) == qfalse && VectorCompare( delta, delta3 ) == qfalse ) degenerate = qfalse; } } } /* warn and select degenerate patch */ if( degenerate ) { Sys_Warning( mapEnt->mapEntityNum, entitySourceBrushes, "Degenerate patch" ); free( m.verts ); return; } /* find longest curve on the mesh */ longestCurve = 0.0f; maxIterations = 0; for( j = 0; j + 2 < m.width; j += 2 ) { for( i = 0; i + 2 < m.height; i += 2 ) { ExpandLongestCurve( &longestCurve, verts[ i * m.width + j ].xyz, verts[ i * m.width + (j + 1) ].xyz, verts[ i * m.width + (j + 2) ].xyz ); /* row */ ExpandLongestCurve( &longestCurve, verts[ i * m.width + j ].xyz, verts[ (i + 1) * m.width + j ].xyz, verts[ (i + 2) * m.width + j ].xyz ); /* col */ ExpandMaxIterations( &maxIterations, patchSubdivisions, verts[ i * m.width + j ].xyz, verts[ i * m.width + (j + 1) ].xyz, verts[ i * m.width + (j + 2) ].xyz ); /* row */ ExpandMaxIterations( &maxIterations, patchSubdivisions, verts[ i * m.width + j ].xyz, verts[ (i + 1) * m.width + j ].xyz, verts[ (i + 2) * m.width + j ].xyz ); /* col */ } } /* allocate patch mesh */ pm = (parseMesh_t *)safe_malloc( sizeof( *pm ) ); memset( pm, 0, sizeof( *pm ) ); /* ydnar: add entity/brush numbering */ pm->entityNum = mapEnt->mapEntityNum; pm->mapEntityNum = mapEnt->mapEntityNum; pm->brushNum = entitySourceBrushes; /* set shader */ sprintf( shader, "textures/%s", texture ); pm->shaderInfo = ShaderInfoForShader( shader ); /* set mesh */ pm->mesh = m; /* set longest curve */ pm->longestCurve = longestCurve; pm->maxIterations = maxIterations; /* link to the entity */ pm->next = mapEnt->patches; mapEnt->patches = pm; }