/*
=================
LoadSurfaceExtraFile

reads a surface info file (<map>.srf)
=================
*/
void LoadSurfaceExtraFile( const char *path )
{
	char		srfPath[MAX_SYSPATH];
	surfaceExtra_t	*se;
	int		surfaceNum;
	script_t		*script;
	token_t		token;
	
	if( path == NULL || path[0] == '\0' )
		return;
	
	com.strcpy( srfPath, path );
	FS_StripExtension( srfPath );
	FS_DefaultExtension( srfPath, ".srf" );
	Msg( "Loading %s\n", srfPath );

	script = (void *)Com_OpenScript( srfPath, NULL, 0 );
	if( !script ) Sys_Break( "unable to load %s\n", srfPath ); // q3map is always crashed if this missed
	
	while( 1 )
	{
		if( !Com_ReadToken( script, SC_ALLOW_NEWLINES|SC_PARSE_GENERIC, &token ))
			break;
		
		if( !com.stricmp( token.string, "default" )) se = &seDefault;
		else
		{
			surfaceNum = com.atoi( token.string );
			if( surfaceNum < 0 || surfaceNum > MAX_MAP_DRAW_SURFS )
				Sys_Error( "ReadSurfaceExtraFile(): %s, line %d: bogus surface num %d", srfPath, token.line, surfaceNum );
			while( surfaceNum >= numSurfaceExtras )
				se = AllocSurfaceExtra();
			se = &surfaceExtras[surfaceNum];
		}
		
		// handle { } section
		if( !Com_ReadToken( script, SC_ALLOW_NEWLINES|SC_PARSE_GENERIC, &token ) || com.strcmp( token.string, "{" ))
			Sys_Error( "ReadSurfaceExtraFile(): %s, line %d: { not found\n", srfPath, token.line );
		while( 1 )
		{
			if( !Com_ReadToken( script, SC_ALLOW_NEWLINES|SC_PARSE_GENERIC, &token ))
				break;
			if( !com.strcmp( token.string, "}" ))
				break;
			
			if( !com.stricmp( token.string, "shader" ))
			{
				Com_ReadToken( script, SC_ALLOW_PATHNAMES|SC_PARSE_GENERIC, &token );
				se->si = ShaderInfoForShader( token.string );
			}
			else if( !com.stricmp( token.string, "parent" ))
			{
				Com_ReadLong( script, false, &se->parentSurfaceNum );
			}
			else if( !com.stricmp( token.string, "entity" ))
			{
				Com_ReadLong( script, false, &se->entityNum );
			}
			else if( !com.stricmp( token.string, "castShadows" ))
			{
				Com_ReadLong( script, false, &se->castShadows );
			}
			else if( !com.stricmp( token.string, "receiveShadows" ))
			{
				Com_ReadLong( script, false, &se->recvShadows );
			}
			else if( !com.stricmp( token.string, "sampleSize" ))
			{
				Com_ReadLong( script, false, &se->sampleSize );
			}
			else if( !com.stricmp( token.string, "longestCurve" ))
			{
				Com_ReadFloat( script, false, &se->longestCurve );
			}
			else if( !com.stricmp( token.string, "lightmapAxis" ))
				Com_Parse1DMatrix( script, 3, se->lightmapAxis );
			
			// ignore all other tokens on the line
			Com_SkipRestOfLine( script );
		}
	}
	Com_CloseScript( script );
}
Beispiel #2
0
/*
=================
ParseRawBrush

parses the sides into buildBrush->sides[], nothing else.
no validation, back plane removal, etc.
=================
*/
static void ParseRawBrush( bool onlyLights )
{
	side_t		*side;
	float		planePoints[3][3];
	int		planenum;
	char 		name[MAX_SHADERPATH];
	char		shader[MAX_SHADERPATH];
	shaderInfo_t	*si;
	token_t		token;
	vects_t		vects;
	int		flags;
	
	buildBrush->numsides = 0;
	buildBrush->detail = false;
	
	if( g_bBrushPrimit == BRUSH_RADIANT )
		Com_CheckToken( mapfile, "{" );
	
	while( 1 )
	{
		if( !Com_ReadToken( mapfile, SC_ALLOW_NEWLINES|SC_COMMENT_SEMICOLON, &token ))
			break;
		if( !com.stricmp( token.string, "}" )) break;
		if( g_bBrushPrimit == BRUSH_RADIANT )
		{
			while( 1 )
			{
				if( com.strcmp( token.string, "(" ))
					Com_ReadToken( mapfile, 0, &token );
				else break;
				Com_ReadToken( mapfile, SC_ALLOW_NEWLINES, &token );
			}
		}
		Com_SaveToken( mapfile, &token );
		
		if( buildBrush->numsides >= MAX_BUILD_SIDES )
			Sys_Break( "Entity %i, Brush %i MAX_BUILD_SIDES\n", buildBrush->entityNum, buildBrush->brushNum );
		
		side = &buildBrush->sides[ buildBrush->numsides ];
		Mem_Set( side, 0, sizeof( *side ));
		buildBrush->numsides++;
		
		// read the three point plane definition
		Com_Parse1DMatrix( mapfile, 3, planePoints[0] );
		Com_Parse1DMatrix( mapfile, 3, planePoints[1] );
		Com_Parse1DMatrix( mapfile, 3, planePoints[2] );
		
		// read the texture matrix
		if( g_bBrushPrimit == BRUSH_RADIANT )
			Com_Parse2DMatrix( mapfile, 2, 3, (float *)side->texMat );
		
		// read the texturedef or shadername
		Com_ReadToken( mapfile, SC_ALLOW_PATHNAMES|SC_PARSE_GENERIC, &token );
		com.strncpy( name, token.string, sizeof( name ));
		
		if( g_bBrushPrimit == BRUSH_WORLDCRAFT_22 || g_bBrushPrimit == BRUSH_GEARCRAFT_40 ) // Worldcraft 2.2+
                    {
			// texture U axis
			Com_ReadToken( mapfile, 0, &token );
			if( com.strcmp( token.string, "[" )) Sys_Break( "missing '[' in texturedef (U)\n" );
			Com_ReadFloat( mapfile, false, &vects.hammer.UAxis[0] );
			Com_ReadFloat( mapfile, false, &vects.hammer.UAxis[1] );
			Com_ReadFloat( mapfile, false, &vects.hammer.UAxis[2] );
			Com_ReadFloat( mapfile, false, &vects.hammer.shift[0] );
			Com_ReadToken( mapfile, 0, &token );
			if( com.strcmp( token.string, "]" )) Sys_Break( "missing ']' in texturedef (U)\n" );

			// texture V axis
			Com_ReadToken( mapfile, 0, &token );
			if( com.strcmp( token.string, "[" )) Sys_Break( "missing '[' in texturedef (V)\n" );
			Com_ReadFloat( mapfile, false, &vects.hammer.VAxis[0] );
			Com_ReadFloat( mapfile, false, &vects.hammer.VAxis[1] );
			Com_ReadFloat( mapfile, false, &vects.hammer.VAxis[2] );
			Com_ReadFloat( mapfile, false, &vects.hammer.shift[1] );
			Com_ReadToken( mapfile, 0, &token );
			if( com.strcmp( token.string, "]" )) Sys_Break( "missing ']' in texturedef (V)\n");

			// texture rotation is implicit in U/V axes.
			Com_ReadToken( mapfile, 0, &token );
			vects.hammer.rotate = 0;

			// texure scale
			Com_ReadFloat( mapfile, false, &vects.hammer.scale[0] );
			Com_ReadFloat( mapfile, false, &vects.hammer.scale[1] );

			if( g_bBrushPrimit == BRUSH_GEARCRAFT_40 )
			{
				Com_ReadLong( mapfile, false, &flags );	// read gearcraft flags
				Com_SkipRestOfLine( mapfile );	// gearcraft lightmap scale and rotate

				if( flags & GEARBOX_DETAIL )
					side->compileFlags |= C_DETAIL;

			}
                    }
		else if( g_bBrushPrimit == BRUSH_WORLDCRAFT_21 || g_bBrushPrimit == BRUSH_QUARK )
		{
			// worldcraft 2.1-, old Radiant, QuArK
			Com_ReadFloat( mapfile, false, &vects.hammer.shift[0] );
			Com_ReadFloat( mapfile, false, &vects.hammer.shift[1] );
			Com_ReadFloat( mapfile, false, &vects.hammer.rotate );
			Com_ReadFloat( mapfile, false, &vects.hammer.scale[0] );
			Com_ReadFloat( mapfile, SC_COMMENT_SEMICOLON, &vects.hammer.scale[1] );
                    }

		// set default flags and values
		com.sprintf( shader, "textures/%s", name );
		if( onlyLights ) si = &shaderInfo[0];
		else si = ShaderInfoForShader( shader );

		side->shaderInfo = si;
		side->surfaceFlags = si->surfaceFlags;
		side->contentFlags = si->contentFlags;
		side->compileFlags = si->compileFlags;
		side->value = si->value;
		
		// bias texture shift for non-radiant sides
		if( g_bBrushPrimit != BRUSH_RADIANT && si->globalTexture == false )
		{
			vects.hammer.shift[0] -= (floor( vects.hammer.shift[0] / si->shaderWidth ) * si->shaderWidth);
			vects.hammer.shift[1] -= (floor( vects.hammer.shift[1] / si->shaderHeight ) * si->shaderHeight);
		}
		
		// historically, there are 3 integer values at the end of a brushside line in a .map file.
		// in quake 3, the only thing that mattered was the first of these three values, which
		// was previously the content flags. and only then did a single bit matter, the detail
		// bit. because every game has its own special flags for specifying detail, the
		// traditionally game-specified BASECONT_DETAIL flag was overridden for Q3Map 2.3.0
		// by C_DETAIL, defined in q3map2.h. the value is exactly as it was before, but
		// is stored in compileFlags, as opposed to contentFlags, for multiple-game
		// portability. :sigh:
                    if( g_bBrushPrimit != BRUSH_QUARK && Com_ReadToken( mapfile, SC_COMMENT_SEMICOLON, &token ))
		{
			// overwrite shader values directly from .map file
			Com_SaveToken( mapfile, &token );
			Com_ReadLong( mapfile, false, &flags );
			Com_ReadLong( mapfile, false, NULL );
			Com_ReadLong( mapfile, false, NULL );
			if( flags & C_DETAIL ) side->compileFlags |= C_DETAIL;
		}		

		if( mapfile->TXcommand == '1' || mapfile->TXcommand == '2' )
		{
			// we are QuArK mode and need to translate some numbers to align textures its way
			// from QuArK, the texture vectors are given directly from the three points
			vec3_t          texMat[2];
			float           dot22, dot23, dot33, mdet, aa, bb, dd;
			int             j, k;

			g_bBrushPrimit = BRUSH_QUARK;	// we can detect it only here
			k = mapfile->TXcommand - '0';
			for( j = 0; j < 3; j++ )
				texMat[1][j] = (planePoints[k][j] - planePoints[0][j]) * (0.0078125f);	// QuArK magic value

			k = 3 - k;
			for( j = 0; j < 3; j++ )
				texMat[0][j] = (planePoints[k][j] - planePoints[0][j]) * (0.0078125f);	// QuArK magic value

			dot22 = DotProduct( texMat[0], texMat[0] );
			dot23 = DotProduct( texMat[0], texMat[1] );
			dot33 = DotProduct( texMat[1], texMat[1] );
			mdet = dot22 * dot33 - dot23 * dot23;
			if( mdet < 1E-6 && mdet > -1E-6 )
			{
				aa = bb = dd = 0;
				MsgDev( D_WARN, "Entity %i, Brush %i: degenerate QuArK-style texture: \n", buildBrush->entityNum, buildBrush->brushNum );
			}
			else
			{
				mdet = 1.0 / mdet;
				aa = dot33 * mdet;
				bb = -dot23 * mdet;
				dd = dot22 * mdet;
			}
			for( j = 0; j < 3; j++ )
			{
				vects.quark.vecs[0][j] = aa * texMat[0][j] + bb * texMat[1][j];
				vects.quark.vecs[1][j] = -(bb * texMat[0][j] + dd * texMat[1][j]);
			}
			vects.quark.vecs[0][3] = -DotProduct( vects.quark.vecs[0], planePoints[0] );
			vects.quark.vecs[1][3] = -DotProduct( vects.quark.vecs[1], planePoints[0] );
		}

		// find the plane number
		planenum = MapPlaneFromPoints( planePoints );
		if( planenum == -1 )
		{
			MsgDev( D_ERROR, "Entity %i, Brush %i: plane with no normal\n", buildBrush->entityNum, buildBrush->brushNum );
			continue;
		}
		side->planenum = planenum;

		if( g_bBrushPrimit == BRUSH_QUARK ) 
		{
			// QuArK format completely matched with internal
			// FIXME: don't calculate vecs, use QuArK texMat instead ?
			Mem_Copy( side->vecs, vects.quark.vecs, sizeof( side->vecs ));
		}
		else if( g_bBrushPrimit != BRUSH_RADIANT )
		{
			vec3_t	vecs[2];
			float	ang, sinv, cosv, ns, nt;
			int	i, j, sv, tv;
			
			if( g_bBrushPrimit == BRUSH_WORLDCRAFT_21 )
				TextureAxisFromPlane( &mapplanes[planenum], vecs[0], vecs[1] );
			if( !vects.hammer.scale[0] ) vects.hammer.scale[0] = 1.0f;
			if( !vects.hammer.scale[1] ) vects.hammer.scale[1] = 1.0f;

			if( g_bBrushPrimit == BRUSH_WORLDCRAFT_21 )
			{
				// rotate axis
				if( vects.hammer.rotate == 0 )
				{
					sinv = 0;
					cosv = 1;
				}
				else if( vects.hammer.rotate == 90 )
				{
					sinv = 1;
					cosv = 0;
				}
				else if( vects.hammer.rotate == 180 )
				{
					sinv = 0;
					cosv = -1;
				}
				else if( vects.hammer.rotate == 270 )
				{
					sinv = -1;
					cosv = 0;
				}
				else
				{
					ang = vects.hammer.rotate / 180 * M_PI;
					sinv = sin( ang );
					cosv = cos( ang );
				}
				if( vecs[0][0] ) sv = 0;
				else if( vecs[0][1] ) sv = 1;
				else sv = 2;

				if( vecs[1][0] ) tv = 0;
				else if( vecs[1][1] ) tv = 1;
				else tv = 2;
			
				for( i = 0; i < 2; i++ )
				{
					ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
					nt = sinv * vecs[i][sv] + cosv * vecs[i][tv];
					vecs[i][sv] = ns;
					vecs[i][tv] = nt;
				}

				for( i = 0; i < 2; i++ )
					for( j = 0; j < 3; j++ )
						side->vecs[i][j] = vecs[i][j] / vects.hammer.scale[i];
			}
			else if( g_bBrushPrimit == BRUSH_WORLDCRAFT_22 || g_bBrushPrimit == BRUSH_GEARCRAFT_40 )
			{
				float	scale;

				scale = 1.0f / vects.hammer.scale[0];
				VectorScale( vects.hammer.UAxis, scale, side->vecs[0] );
				scale = 1.0f / vects.hammer.scale[1];
				VectorScale( vects.hammer.VAxis, scale, side->vecs[1] );
			}

			// add shifts
			side->vecs[0][3] = vects.hammer.shift[0];
			side->vecs[1][3] = vects.hammer.shift[1];
		}
	}
	
	if( g_bBrushPrimit == BRUSH_RADIANT )
	{
		Com_SaveToken( mapfile, &token );
		Com_CheckToken( mapfile, "}" );
		Com_CheckToken( mapfile, "}" );
	}
}
qboolean __cdecl Com_LoadDvarsFromBuffer(const char **inputbuf, unsigned int length, const char *data_p, const char *filename)
{
    const char *cvar_name;
    int i, count;
    char buf[16384];
    const char* line;

    Com_Memset(buf, 0, sizeof(buf));

    for(i = 0; i < length; i++)
    {
         Cvar_Reset(inputbuf[i]);
    }
	Com_BeginParseSession(filename);
	count = 0;

	while ( (cvar_name = Com_Parse(&data_p)) && cvar_name[0])
	{
		for(i = 0; i < length; i++)
		{
			if(!Q_stricmp(cvar_name, inputbuf[i]))
				break;
		}
		if(i == length)
		{
			if(com_developer && com_developer->integer)
			{
				Com_PrintWarning("WARNING: unknown cvar '%s' in file '%s'\n", cvar_name, filename);
			}
			Com_SkipRestOfLine(&data_p);
		}else{
			line = Com_ParseOnLine(&data_p);
			if(com_developer && com_developer->integer)
			{
				Cvar_Set(inputbuf[i], line);
			}else{
				if((!Q_strncmp(inputbuf[i],"bg_shock_viewKickPeriod", 23) || !Q_strncmp(inputbuf[i],"bg_shock_viewKickFadeTime", 25)) && (line[0] == '0' && line[1] == '\0'))
				{
					/* Quite this spam */
				}else{
					Cvar_Set(inputbuf[i], line);
				}
			}
			if ( !buf[i] )
			{
				buf[i] = 1;
				++count;
			}
		}
	}
	Com_EndParseSession();

	if ( length == count )
	{
		/* No Errors */
		return 1;
	}

	Com_PrintError("ERROR: the following cvars were not specified in file '%s'\n", filename);
	for(i = 0; i < length; i++)
	{
		while ( buf[i] && i < length )
		{
			++i;
		}
		if(i < length)
			Com_PrintError("  %s\n", inputbuf[i]);
	}
	return 0;
}