qbsp: re-factor ParseBrush into smaller pieces
Factor out some of the processing involved with parsing a brush. When checking for duplicate planes, use the same "PlaneEqual" functions as used in brush.c. Replace the enum style errors with the new Error_ function for all of map.c so the error string is at the call site. Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
This commit is contained in:
parent
5082e3ffaa
commit
30caae09e5
|
|
@ -178,7 +178,7 @@ NormalizePlane(plane_t *p)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
int
|
||||
PlaneEqual(const plane_t *p1, const plane_t *p2)
|
||||
{
|
||||
return (fabs(p1->normal[0] - p2->normal[0]) < NORMAL_EPSILON &&
|
||||
|
|
@ -187,7 +187,7 @@ PlaneEqual(const plane_t *p1, const plane_t *p2)
|
|||
fabs(p1->dist - p2->dist) < DIST_EPSILON);
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
PlaneInvEqual(const plane_t *p1, const plane_t *p2)
|
||||
{
|
||||
return (fabs(p1->normal[0] + p2->normal[0]) < NORMAL_EPSILON &&
|
||||
|
|
|
|||
|
|
@ -81,14 +81,6 @@ const char *rgszWarnings[cWarnings] = {
|
|||
const char *rgszErrors[cErrors] = {
|
||||
"No leak node in WriteLeakNode",
|
||||
"Unknown option '%s'",
|
||||
"line %d: Entity key or value too long",
|
||||
"line %d: Invalid brush plane format",
|
||||
"Internal error: face count mismatched during map file parsing",
|
||||
"line %d: Invalid entity format, { not found",
|
||||
"Internal error: entity count mismatched during map file parsing",
|
||||
"Unexpected EOF (no closing brace)",
|
||||
"Internal error: map.nummiptex > map.maxmiptex",
|
||||
"Internal error: pWorldEnt->iTexinfo > pWorldEnt->cTexinfo",
|
||||
|
||||
"%s is version %i, not %i",
|
||||
"No axis found for winding",
|
||||
|
|
@ -144,8 +136,5 @@ const char *rgszErrors[cErrors] = {
|
|||
"Invalid argument to option %s",
|
||||
"Internal error: numleaks > num_visportals",
|
||||
"Clipnodes in map exceed " stringify(MAX_BSP_CLIPNODES),
|
||||
"Internal error: bad texture coordinate style",
|
||||
"Internal error: brush count mismatched during map file parsing",
|
||||
"Internal error: Detail cluster mismatch",
|
||||
"line %d: couldn't parse Valve220 texture info",
|
||||
};
|
||||
|
|
|
|||
308
qbsp/map.c
308
qbsp/map.c
|
|
@ -41,7 +41,7 @@ FindMiptex(const char *name)
|
|||
return i;
|
||||
}
|
||||
if (map.nummiptex == map.maxmiptex)
|
||||
Error(errLowMiptexCount);
|
||||
Error_("Internal error: map.nummiptex > map.maxmiptex");
|
||||
|
||||
strcpy(map.miptex[i], name);
|
||||
map.nummiptex++;
|
||||
|
|
@ -155,11 +155,11 @@ ParseEpair(parser_t *parser, mapentity_t *entity)
|
|||
entity->epairs = epair;
|
||||
|
||||
if (strlen(parser->token) >= MAX_KEY - 1)
|
||||
Error(errEpairTooLong, parser->linenum);
|
||||
goto parse_error;
|
||||
epair->key = copystring(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
if (strlen(parser->token) >= MAX_VALUE - 1)
|
||||
Error(errEpairTooLong, parser->linenum);
|
||||
goto parse_error;
|
||||
epair->value = copystring(parser->token);
|
||||
|
||||
if (!strcasecmp(epair->key, "origin")) {
|
||||
|
|
@ -175,6 +175,10 @@ ParseEpair(parser_t *parser, mapentity_t *entity)
|
|||
rgfStartSpots |= info_player_coop;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
parse_error:
|
||||
Error_("line %d: Entity key or value too long", parser->linenum);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -247,7 +251,7 @@ SetTexinfo_QuakeEd(const plane_t *plane, const vec_t shift[2], vec_t rotate,
|
|||
TextureAxisFromPlane(plane, vecs[0], vecs[1]);
|
||||
|
||||
/* Rotate axis */
|
||||
ang = (vec_t)rotate / 180 * Q_PI;
|
||||
ang = rotate / 180.0 * Q_PI;
|
||||
sinv = sin(ang);
|
||||
cosv = cos(ang);
|
||||
|
||||
|
|
@ -282,8 +286,8 @@ SetTexinfo_QuakeEd(const plane_t *plane, const vec_t shift[2], vec_t rotate,
|
|||
}
|
||||
|
||||
static void
|
||||
SetTexinfo_QuArK(parser_t *parser, vec3_t planepts[3], texcoord_style_t style,
|
||||
texinfo_t *out)
|
||||
SetTexinfo_QuArK(parser_t *parser, vec3_t planepts[3],
|
||||
texcoord_style_t style, texinfo_t *out)
|
||||
{
|
||||
int i;
|
||||
vec3_t vecs[2];
|
||||
|
|
@ -305,7 +309,7 @@ SetTexinfo_QuArK(parser_t *parser, vec3_t planepts[3], texcoord_style_t style,
|
|||
VectorSubtract(planepts[2], planepts[0], vecs[1]);
|
||||
break;
|
||||
default:
|
||||
Error(errBadTXStyle);
|
||||
Error_("Internal error: bad texture coordinate style");
|
||||
}
|
||||
VectorScale(vecs[0], 1.0 / 128.0, vecs[0]);
|
||||
VectorScale(vecs[1], 1.0 / 128.0, vecs[1]);
|
||||
|
|
@ -345,34 +349,6 @@ SetTexinfo_QuArK(parser_t *parser, vec3_t planepts[3], texcoord_style_t style,
|
|||
out->vecs[1][3] = -DotProduct(vecs[1], planepts[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
ParseValve220TX(parser_t *parser, vec3_t axis[2], vec_t shift[2],
|
||||
vec_t *rotate, vec_t scale[2])
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
if (strcmp(parser->token, "["))
|
||||
Error(errBadValve220TX, 9999);//parser->linenum);
|
||||
for (j = 0; j < 3; j++) {
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
axis[i][j] = atof(parser->token);
|
||||
}
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
shift[i] = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
if (strcmp(parser->token, "]"))
|
||||
Error(errBadValve220TX, parser->linenum);
|
||||
}
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
rotate[0] = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
scale[0] = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
scale[1] = atof(parser->token);
|
||||
}
|
||||
|
||||
static void
|
||||
SetTexinfo_Valve220(vec3_t axis[2], const vec_t shift[2], const vec_t scale[2],
|
||||
texinfo_t *out)
|
||||
|
|
@ -387,117 +363,177 @@ SetTexinfo_Valve220(vec3_t axis[2], const vec_t shift[2], const vec_t scale[2],
|
|||
out->vecs[1][3] = shift[1];
|
||||
}
|
||||
|
||||
static void
|
||||
ParsePlaneDef(parser_t *parser, vec3_t planepts[3])
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (i != 0)
|
||||
ParseToken(parser, PARSE_NORMAL);
|
||||
if (strcmp(parser->token, "("))
|
||||
goto parse_error;
|
||||
|
||||
for (j = 0; j < 3; j++) {
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
planepts[i][j] = atof(parser->token);
|
||||
}
|
||||
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
if (strcmp(parser->token, ")"))
|
||||
goto parse_error;
|
||||
}
|
||||
return;
|
||||
|
||||
parse_error:
|
||||
Error_("line %d: Invalid brush plane format", parser->linenum);
|
||||
}
|
||||
|
||||
static void
|
||||
ParseValve220TX(parser_t *parser, vec3_t axis[2], vec_t shift[2],
|
||||
vec_t *rotate, vec_t scale[2])
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
if (strcmp(parser->token, "["))
|
||||
goto parse_error;
|
||||
for (j = 0; j < 3; j++) {
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
axis[i][j] = atof(parser->token);
|
||||
}
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
shift[i] = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
if (strcmp(parser->token, "]"))
|
||||
goto parse_error;
|
||||
}
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
rotate[0] = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
scale[0] = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
scale[1] = atof(parser->token);
|
||||
return;
|
||||
|
||||
parse_error:
|
||||
Error_("line %d: couldn't parse Valve220 texture info", parser->linenum);
|
||||
}
|
||||
|
||||
static void
|
||||
ParseTextureDef(parser_t *parser, texinfo_t *tx,
|
||||
vec3_t planepts[3], const plane_t *plane)
|
||||
{
|
||||
vec3_t axis[2];
|
||||
vec_t shift[2], rotate, scale[2];
|
||||
texcoord_style_t tx_type;
|
||||
|
||||
memset(tx, 0, sizeof(*tx));
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
tx->miptex = FindMiptex(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
if (!strcmp(parser->token, "[")) {
|
||||
parser->unget = true;
|
||||
ParseValve220TX(parser, axis, shift, &rotate, scale);
|
||||
tx_type = TX_VALVE_220;
|
||||
} else {
|
||||
shift[0] = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
shift[1] = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
rotate = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
scale[0] = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
scale[1] = atof(parser->token);
|
||||
tx_type = ParseExtendedTX(parser);
|
||||
}
|
||||
|
||||
if (!planepts || !plane)
|
||||
return;
|
||||
|
||||
switch (tx_type) {
|
||||
case TX_QUARK_TYPE1:
|
||||
case TX_QUARK_TYPE2:
|
||||
SetTexinfo_QuArK(parser, &planepts[0], tx_type, tx);
|
||||
break;
|
||||
case TX_VALVE_220:
|
||||
SetTexinfo_Valve220(axis, shift, scale, tx);
|
||||
break;
|
||||
case TX_QUAKED:
|
||||
default:
|
||||
SetTexinfo_QuakeEd(plane, shift, rotate, scale, tx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
ParseBrushFace(parser_t *parser, mapface_t *face)
|
||||
{
|
||||
vec3_t planepts[3], planevecs[2];
|
||||
vec_t length;
|
||||
plane_t *plane;
|
||||
texinfo_t tx;
|
||||
|
||||
ParsePlaneDef(parser, planepts);
|
||||
|
||||
/* calculate the normal/dist plane equation */
|
||||
VectorSubtract(planepts[0], planepts[1], planevecs[0]);
|
||||
VectorSubtract(planepts[2], planepts[1], planevecs[1]);
|
||||
plane = &face->plane;
|
||||
CrossProduct(planevecs[0], planevecs[1], plane->normal);
|
||||
length = VectorNormalize(plane->normal);
|
||||
plane->dist = DotProduct(planepts[1], plane->normal);
|
||||
|
||||
ParseTextureDef(parser, &tx, planepts, plane);
|
||||
|
||||
if (length < NORMAL_EPSILON) {
|
||||
Message(msgWarning, warnNoPlaneNormal, parser->linenum);
|
||||
return false;
|
||||
}
|
||||
|
||||
face->texinfo = FindTexinfo(&tx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ParseBrush(parser_t *parser, mapbrush_t *brush)
|
||||
{
|
||||
vec3_t planepts[3], axis[2];
|
||||
vec3_t t1, t2, t3;
|
||||
int i, j;
|
||||
texinfo_t tx;
|
||||
vec_t d;
|
||||
vec_t shift[2], rotate, scale[2];
|
||||
int tx_type;
|
||||
plane_t *plane;
|
||||
mapface_t *face, *checkface;
|
||||
const mapface_t *check;
|
||||
mapface_t *face;
|
||||
bool faceok;
|
||||
|
||||
brush->faces = face = map.faces + map.numfaces;
|
||||
while (ParseToken(parser, PARSE_NORMAL)) {
|
||||
if (!strcmp(parser->token, "}"))
|
||||
break;
|
||||
|
||||
// read the three point plane definition
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (i != 0)
|
||||
ParseToken(parser, PARSE_NORMAL);
|
||||
if (strcmp(parser->token, "("))
|
||||
Error(errInvalidMapPlane, parser->linenum);
|
||||
|
||||
for (j = 0; j < 3; j++) {
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
planepts[i][j] = atof(parser->token);
|
||||
}
|
||||
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
if (strcmp(parser->token, ")"))
|
||||
Error(errInvalidMapPlane, parser->linenum);
|
||||
}
|
||||
|
||||
// Read the texturedef
|
||||
memset(&tx, 0, sizeof(tx));
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
tx.miptex = FindMiptex(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
if (!strcmp(parser->token, "[")) {
|
||||
parser->unget = true;
|
||||
ParseValve220TX(parser, axis, shift, &rotate, scale);
|
||||
tx_type = TX_VALVE_220;
|
||||
} else {
|
||||
shift[0] = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
shift[1] = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
rotate = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
scale[0] = atof(parser->token);
|
||||
ParseToken(parser, PARSE_SAMELINE);
|
||||
scale[1] = atof(parser->token);
|
||||
tx_type = ParseExtendedTX(parser);
|
||||
}
|
||||
|
||||
// if the three points are all on a previous plane, it is a
|
||||
// duplicate plane
|
||||
for (checkface = brush->faces; checkface < face; checkface++) {
|
||||
plane = &checkface->plane;
|
||||
for (i = 0; i < 3; i++) {
|
||||
d = DotProduct(planepts[i], plane->normal) - plane->dist;
|
||||
if (d < -ON_EPSILON || d > ON_EPSILON)
|
||||
break;
|
||||
}
|
||||
if (i == 3)
|
||||
break;
|
||||
}
|
||||
if (checkface < face) {
|
||||
Message(msgWarning, warnBrushDuplicatePlane, parser->linenum);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (map.numfaces == map.maxfaces)
|
||||
Error(errLowFaceCount);
|
||||
Error_("Internal error: didn't allocate enough faces?");
|
||||
|
||||
// convert to a vector / dist plane
|
||||
for (j = 0; j < 3; j++) {
|
||||
t1[j] = planepts[0][j] - planepts[1][j];
|
||||
t2[j] = planepts[2][j] - planepts[1][j];
|
||||
t3[j] = planepts[1][j];
|
||||
}
|
||||
|
||||
plane = &face->plane;
|
||||
CrossProduct(t1, t2, plane->normal);
|
||||
if (VectorCompare(plane->normal, vec3_origin)) {
|
||||
Message(msgWarning, warnNoPlaneNormal, parser->linenum);
|
||||
faceok = ParseBrushFace(parser, face);
|
||||
if (!faceok)
|
||||
continue;
|
||||
}
|
||||
VectorNormalize(plane->normal);
|
||||
plane->dist = DotProduct(t3, plane->normal);
|
||||
|
||||
switch (tx_type) {
|
||||
case TX_QUARK_TYPE1:
|
||||
case TX_QUARK_TYPE2:
|
||||
SetTexinfo_QuArK(parser, &planepts[0], tx_type, &tx);
|
||||
break;
|
||||
case TX_VALVE_220:
|
||||
SetTexinfo_Valve220(axis, shift, scale, &tx);
|
||||
break;
|
||||
case TX_QUAKED:
|
||||
default:
|
||||
SetTexinfo_QuakeEd(plane, shift, rotate, scale, &tx);
|
||||
break;
|
||||
/* Check for duplicate planes */
|
||||
for (check = brush->faces; check < face; check++) {
|
||||
if (PlaneEqual(&check->plane, &face->plane)) {
|
||||
Message(msgWarning, warnBrushDuplicatePlane, parser->linenum);
|
||||
continue;
|
||||
}
|
||||
if (PlaneInvEqual(&check->plane, &face->plane)) {
|
||||
/* FIXME - this is actually an invalid brush */
|
||||
Message(msgWarning, warnBrushDuplicatePlane, parser->linenum);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
face->texinfo = FindTexinfo(&tx);
|
||||
|
||||
face++;
|
||||
/* Save the face, update progress */
|
||||
map.numfaces++;
|
||||
Message(msgPercent, map.numfaces, map.maxfaces);
|
||||
face++;
|
||||
}
|
||||
|
||||
brush->numfaces = face - brush->faces;
|
||||
|
|
@ -514,20 +550,20 @@ ParseEntity(parser_t *parser, mapentity_t *entity)
|
|||
return false;
|
||||
|
||||
if (strcmp(parser->token, "{"))
|
||||
Error(errParseEntity, parser->linenum);
|
||||
Error_("line %d: Invalid entity format, { not found", parser->linenum);
|
||||
|
||||
if (map.numentities == map.maxentities)
|
||||
Error(errLowEntCount);
|
||||
Error_("Internal error: didn't allocate enough entities?");
|
||||
|
||||
entity->mapbrushes = brush = map.brushes + map.numbrushes;
|
||||
do {
|
||||
if (!ParseToken(parser, PARSE_NORMAL))
|
||||
Error(errUnexpectedEOF);
|
||||
Error_("Unexpected EOF (no closing brace)");
|
||||
if (!strcmp(parser->token, "}"))
|
||||
break;
|
||||
else if (!strcmp(parser->token, "{")) {
|
||||
if (map.numbrushes == map.maxbrushes)
|
||||
Error(errLowMapbrushCount);
|
||||
Error_("Internal error: didn't allocate enough brushes?");
|
||||
ParseBrush(parser, brush++);
|
||||
map.numbrushes++;
|
||||
} else
|
||||
|
|
@ -649,7 +685,7 @@ LoadMapFile(void)
|
|||
|
||||
/* Double check the entity count matches our pre-parse count */
|
||||
if (map.numentities != map.maxentities)
|
||||
Error(errLowEntCount);
|
||||
Error_("Internal error: mismatched entity count?");
|
||||
|
||||
FreeMem(buf, OTHER, length + 1);
|
||||
|
||||
|
|
@ -663,7 +699,7 @@ LoadMapFile(void)
|
|||
|
||||
// Clean up texture memory
|
||||
if (map.nummiptex > map.maxfaces)
|
||||
Error(errLowMiptexCount);
|
||||
Error_("Internal error: map.nummiptex > map.maxfaces");
|
||||
else if (map.nummiptex < map.maxfaces) {
|
||||
// For stuff in AddAnimatingTex, make room available
|
||||
pTemp = map.miptex;
|
||||
|
|
@ -675,7 +711,7 @@ LoadMapFile(void)
|
|||
|
||||
texinfo = &pWorldEnt->lumps[BSPTEXINFO];
|
||||
if (texinfo->index > texinfo->count)
|
||||
Error(errLowTexinfoCount);
|
||||
Error_("Internal error: didn't allocate enough texinfos?");
|
||||
else if (texinfo->index < texinfo->count) {
|
||||
pTemp = texinfo->data;
|
||||
texinfo->data = AllocMem(BSPTEXINFO, texinfo->index, true);
|
||||
|
|
|
|||
|
|
@ -443,6 +443,8 @@ void FreeBrushes(brush_t *brushlist);
|
|||
|
||||
void PlaneHash_Init(void);
|
||||
int FindPlane(const plane_t *plane, int *side);
|
||||
int PlaneEqual(const plane_t *p1, const plane_t *p2);
|
||||
int PlaneInvEqual(const plane_t *p1, const plane_t *p2);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
|
|
|||
|
|
@ -52,14 +52,7 @@ enum {
|
|||
enum {
|
||||
errNoLeakNode,
|
||||
errUnknownOption,
|
||||
errEpairTooLong,
|
||||
errInvalidMapPlane,
|
||||
errLowFaceCount,
|
||||
errParseEntity,
|
||||
errLowEntCount,
|
||||
errUnexpectedEOF,
|
||||
errLowMiptexCount,
|
||||
errLowTexinfoCount,
|
||||
|
||||
errBadVersion, // 10
|
||||
errNoWindingAxis,
|
||||
errLowPointCount,
|
||||
|
|
@ -110,9 +103,6 @@ enum {
|
|||
errInvalidOption,
|
||||
errLowLeakCount,
|
||||
errTooManyClipnodes,
|
||||
errBadTXStyle, // 60
|
||||
errLowMapbrushCount,
|
||||
errDetailClusterMismatch,
|
||||
errBadValve220TX,
|
||||
cErrors
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue