void Sys_Error(int entitynum, int brushnum, const char *text, ... ) { char out_buffer[4096]; va_list argptr; /* print */ va_start( argptr, text ); vsprintf( out_buffer, text, argptr ); va_end( argptr ); /* send */ xml_Select( out_buffer, entitynum, brushnum, qtrue ); }
void Sys_Warning(int entitynum, const char *text, ... ) { char out_buffer[4096]; va_list argptr; /* print */ va_start( argptr, text ); vsprintf( out_buffer, text, argptr ); va_end( argptr ); /* send */ xml_Select( out_buffer, entitynum, -1, qfalse ); }
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 = 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,"}")) { ep = ParseEPair(); free(ep->key); free(ep->value); free(ep); } 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 ]; VectorInverse( delta3 ); /* compare */ if( VectorCompare( delta, delta2 ) == qfalse && VectorCompare( delta, delta3 ) == qfalse ) degenerate = qfalse; } } } /* warn and select degenerate patch */ if( degenerate ) { xml_Select( "degenerate patch", mapEnt->mapEntityNum, entitySourceBrushes, qfalse ); 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 = safe_malloc( sizeof( *pm ) ); memset( pm, 0, sizeof( *pm ) ); /* ydnar: add entity/brush numbering */ pm->entityNum = 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; }
qboolean FloodEntities( tree_t *tree ) { int i, s; vec3_t origin, offset, scale, angles; qboolean r, inside, tripped, skybox; node_t *headnode; entity_t *e; const char *value; headnode = tree->headnode; Sys_FPrintf( SYS_VRB,"--- FloodEntities ---\n" ); inside = qfalse; tree->outside_node.occupied = 0; tripped = qfalse; c_floodedleafs = 0; for( i = 1; i < numEntities; i++ ) { /* get entity */ e = &entities[ i ]; /* get origin */ GetVectorForKey( e, "origin", origin ); if( VectorCompare( origin, vec3_origin ) ) continue; /* handle skybox entities */ value = ValueForKey( e, "classname" ); if( !Q_stricmp( value, "_skybox" ) ) { skybox = qtrue; skyboxPresent = qtrue; /* invert origin */ VectorScale( origin, -1.0f, offset ); /* get scale */ VectorSet( scale, 64.0f, 64.0f, 64.0f ); value = ValueForKey( e, "_scale" ); if( value[ 0 ] != '\0' ) { s = sscanf( value, "%f %f %f", &scale[ 0 ], &scale[ 1 ], &scale[ 2 ] ); if( s == 1 ) { scale[ 1 ] = scale[ 0 ]; scale[ 2 ] = scale[ 0 ]; } } /* get "angle" (yaw) or "angles" (pitch yaw roll) */ VectorClear( angles ); angles[ 2 ] = FloatForKey( e, "angle" ); value = ValueForKey( e, "angles" ); if( value[ 0 ] != '\0' ) sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] ); /* set transform matrix (thanks spog) */ m4x4_identity( skyboxTransform ); m4x4_pivoted_transform_by_vec3( skyboxTransform, offset, angles, eXYZ, scale, origin ); } else skybox = qfalse; /* nudge off floor */ origin[ 2 ] += 1; /* debugging code */ //% if( i == 1 ) //% origin[ 2 ] += 4096; /* find leaf */ r = PlaceOccupant( headnode, origin, e, skybox ); if( r ) inside = qtrue; if( (!r || tree->outside_node.occupied) && !tripped ) { xml_Select( "Entity leaked", e->mapEntityNum, 0, qfalse ); tripped = qtrue; } } Sys_FPrintf( SYS_VRB, "%9d flooded leafs\n", c_floodedleafs ); if( !inside ) Sys_FPrintf( SYS_VRB, "no entities in open -- no filling\n" ); else if( tree->outside_node.occupied ) Sys_FPrintf( SYS_VRB, "entity reached from outside -- no filling\n" ); return (qboolean) (inside && !tree->outside_node.occupied); }