void Com_Parse2DMatrix( const char *( *buf_p ), int y, int x, float *m ) { int i; Com_MatchToken( buf_p, "(" ); for ( i = 0 ; i < y ; i++ ) { Com_Parse1DMatrix( buf_p, x, m + i * x ); } Com_MatchToken( buf_p, ")" ); }
void idSplineList::parse(const char *(*text) ) { const char *token; //Com_MatchToken( text, "{" ); do { token = Com_Parse( text ); if ( !token[0] ) { break; } if ( !Q_stricmp (token, "}") ) { break; } do { // if token is not a brace, it is a key for a key/value pair if ( !token[0] || !Q_stricmp (token, "(") || !Q_stricmp(token, "}")) { break; } Com_UngetToken(); idStr key = Com_ParseOnLine(text); const char *token = Com_Parse(text); if (Q_stricmp(key.c_str(), "granularity") == 0) { granularity = atof(token); } else if (Q_stricmp(key.c_str(), "name") == 0) { name = token; } token = Com_Parse(text); } while (1); if ( !Q_stricmp (token, "}") ) { break; } Com_UngetToken(); // read the control point idVec3_t point; Com_Parse1DMatrix( text, 3, point ); addPoint(point.x, point.y, point.z); } while (1); //Com_UngetToken(); //Com_MatchToken( text, "}" ); dirty = true; }
void idFixedPosition::parse(const char *(*text) ) { const char *token; Com_MatchToken( text, "{" ); do { token = Com_Parse( text ); if ( !token[0] ) { break; } if ( !strcmp (token, "}") ) { break; } // here we may have to jump over brush epairs ( only used in editor ) do { // if token is not a brace, it is a key for a key/value pair if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) { break; } Com_UngetToken(); idStr key = Com_ParseOnLine(text); //const char *token = Com_Parse(text); Com_Parse(text); if (Q_stricmp(key.c_str(), "pos") == 0) { Com_UngetToken(); Com_Parse1DMatrix( text, 3, pos ); } else { Com_UngetToken(); idCameraPosition::parseToken(key.c_str(), text); } token = Com_Parse(text); } while (1); if ( !strcmp (token, "}") ) { break; } } while (1); Com_UngetToken(); Com_MatchToken( text, "}" ); }
/* ================= 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, "}" ); } }
/* ================= 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 ); }