/* ================= ParseBrush ================= */ void ParseBrush (entity_t *mapent) { mapbrush_t *b; int i,j, k; int mt; side_t *side, *s2; int planenum; brush_texture_t td; int planepts[3][3]; if (nummapbrushes == MAX_MAP_BRUSHES) Error ("nummapbrushes == MAX_MAP_BRUSHES"); b = &mapbrushes[nummapbrushes]; b->original_sides = &brushsides[nummapbrushsides]; b->entitynum = num_entities-1; b->brushnum = nummapbrushes - mapent->firstbrush; do { if (!GetToken (true)) break; if (!strcmp (token, "}") ) break; if (nummapbrushsides == MAX_MAP_BRUSHSIDES) Error ("MAX_MAP_BRUSHSIDES"); side = &brushsides[nummapbrushsides]; // read the three point plane definition for (i=0 ; i<3 ; i++) { if (i != 0) GetToken (true); if (strcmp (token, "(") ) Error ("parsing brush"); for (j=0 ; j<3 ; j++) { GetToken (false); planepts[i][j] = atoi(token); } GetToken (false); if (strcmp (token, ")") ) Error ("parsing brush"); } // // read the texturedef // GetToken (false); strcpy (td.name, token); GetToken (false); td.shift[0] = atoi(token); GetToken (false); td.shift[1] = atoi(token); GetToken (false); td.rotate = atoi(token); GetToken (false); td.scale[0] = atof(token); GetToken (false); td.scale[1] = atof(token); // find default flags and values mt = FindMiptex (td.name); td.flags = textureref[mt].flags; td.value = textureref[mt].value; side->contents = textureref[mt].contents; side->surf = td.flags = textureref[mt].flags; if (TokenAvailable()) { GetToken (false); side->contents = atoi(token); GetToken (false); side->surf = td.flags = atoi(token); GetToken (false); td.value = atoi(token); } // translucent objects are automatically classified as detail if (side->surf & (SURF_TRANS33|SURF_TRANS66) ) side->contents |= CONTENTS_DETAIL; if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) side->contents |= CONTENTS_DETAIL; if (fulldetail) side->contents &= ~CONTENTS_DETAIL; if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST) ) ) side->contents |= CONTENTS_SOLID; // hints and skips are never detail, and have no content if (side->surf & (SURF_HINT|SURF_SKIP) ) { side->contents = 0; side->surf &= ~CONTENTS_DETAIL; } // // find the plane number // planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]); if (planenum == -1) { printf ("Entity %i, Brush %i: plane with no normal\n" , b->entitynum, b->brushnum); continue; } // // see if the plane has been used already // for (k=0 ; k<b->numsides ; k++) { s2 = b->original_sides + k; if (s2->planenum == planenum) { printf ("Entity %i, Brush %i: duplicate plane\n" , b->entitynum, b->brushnum); break; } if ( s2->planenum == (planenum^1) ) { printf ("Entity %i, Brush %i: mirrored plane\n" , b->entitynum, b->brushnum); break; } } if (k != b->numsides) continue; // duplicated // // keep this side // side = b->original_sides + b->numsides; side->planenum = planenum; side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum], &td, vec3_origin); // save the td off in case there is an origin brush and we // have to recalculate the texinfo side_brushtextures[nummapbrushsides] = td; nummapbrushsides++; b->numsides++; } while (1); // get the content for the entire brush b->contents = BrushContents (b); // allow detail brushes to be removed if (nodetail && (b->contents & CONTENTS_DETAIL) ) { b->numsides = 0; return; } // allow water brushes to be removed if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) ) { b->numsides = 0; return; } // create windings for sides and bounds for brush MakeBrushWindings (b); // brushes that will not be visible at all will never be // used as bsp splitters if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) { c_clipbrushes++; for (i=0 ; i<b->numsides ; i++) b->original_sides[i].texinfo = TEXINFO_NODE; } // // origin brushes are removed, but they set // the rotation origin for the rest of the brushes // in the entity. After the entire entity is parsed, // the planenums and texinfos will be adjusted for // the origin brush // if (b->contents & CONTENTS_ORIGIN) { char string[32]; vec3_t origin; if (num_entities == 1) { Error ("Entity %i, Brush %i: origin brushes not allowed in world" , b->entitynum, b->brushnum); return; } VectorAdd (b->mins, b->maxs, origin); VectorScale (origin, 0.5, origin); sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); SetKeyValue (&entities[b->entitynum], "origin", string); VectorCopy (origin, entities[b->entitynum].origin); // don't keep this brush b->numsides = 0; return; } AddBrushBevels (b); nummapbrushes++; mapent->numbrushes++; }
/* ================= ParseBrush ================= */ void ParseBrush (entity_t *mapent) { char *tl; mapbrush_t *b; int i,j, k; int mt; side_t *side, *s2; int planenum; brush_texture_t td; float planepts[3][3]; qboolean phongShading; MarkBrushBegin(); if (nummapbrushes == MAX_MAP_BRUSHES) Error ("nummapbrushes == MAX_MAP_BRUSHES"); b = &mapbrushes[nummapbrushes]; b->original_sides = &brushsides[nummapbrushsides]; b->entitynum = num_entities-1; b->brushnum = nummapbrushes - mapent->firstbrush; // Knightmare added b->optimizedDetail = false; b->isTerrain = (!strcmp("func_group", ValueForKey (&entities[b->entitynum], "classname")) && strlen(ValueForKey (&entities[b->entitynum], "terrain")) > 0); b->isGenSurf = (!strcmp("func_group", ValueForKey (&entities[b->entitynum], "classname")) && strlen(ValueForKey (&entities[b->entitynum], "gensurf")) > 0); phongShading = (!strcmp("func_group", ValueForKey (&entities[b->entitynum], "classname")) && strlen(ValueForKey (&entities[b->entitynum], "phongshading")) > 0); //if (b->isTerrain) // printf ("Brush number %i in enitity number %i has terrain flag set.\n", b->brushnum, b->entitynum); //if (b->phongShading) // printf ("Brush number %i in enitity number %i has phong shading flag set.\n", b->brushnum, b->entitynum); if (verbosebrushes) printf ("enitity %i, brush %i\n", b->entitynum, b->brushnum); // end Knightmare do { if (!GetToken (true)) break; if (!strcmp (token, "}") ) break; if (nummapbrushsides == MAX_MAP_BRUSHSIDES) Error ("MAX_MAP_BRUSHSIDES"); side = &brushsides[nummapbrushsides]; // read the three point plane definition for (i=0 ; i<3 ; i++) { if (i != 0) GetToken (true); if (strcmp (token, "(") ) Error ("parsing brush\n Brush: %s", i+1, brush_info); for (j=0 ; j<3 ; j++) { GetToken (false); planepts[i][j] = atof(token); } GetToken (false); if (strcmp (token, ")") ) Error ("parsing brush\n Brush: %s", i+1, brush_info); } // // read the texturedef // GetToken (false); strcpy (td.name, token); tl = td.name; for(tl = td.name; *tl != 0; tl++) *tl = tolower(*tl); GetToken (false); td.shift[0] = atoi(token); GetToken (false); td.shift[1] = atoi(token); GetToken (false); td.rotate = atoi(token); GetToken (false); td.scale[0] = atof(token); GetToken (false); td.scale[1] = atof(token); // find default flags and values mt = FindMiptex (td.name); td.flags = textureref[mt].flags; td.value = textureref[mt].value; side->contents = textureref[mt].contents; side->surf = td.flags = textureref[mt].flags; if (TokenAvailable()) { GetToken (false); side->contents = atoi(token); GetToken (false); side->surf = td.flags = atoi(token); GetToken (false); td.value = atoi(token); } // translucent objects are automatically classified as detail if (side->surf & (SURF_TRANS33|SURF_TRANS66|SURF_ALPHATEST) ) // Knightmare- added alphatest side->contents |= CONTENTS_DETAIL; if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) side->contents |= CONTENTS_DETAIL; if (fulldetail) side->contents &= ~CONTENTS_DETAIL; if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST) ) ) side->contents |= CONTENTS_SOLID; // hints and skips are never detail, and have no content if (side->surf & (SURF_HINT|SURF_SKIP) ) { //side->contents = 0; //side->surf &= ~CONTENTS_DETAIL; side->contents &= CONTENTS_DETAIL; // allow only detail content- Geoffery DeWan? } // // find the plane number // planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]); if (planenum == -1) { printf ("Entity %i, Brush %i: plane with no normal\n Brush: %s\n" , b->entitynum, b->brushnum, brush_info); continue; } // // see if the plane has been used already // for (k=0 ; k<b->numsides ; k++) { s2 = b->original_sides + k; if (s2->planenum == planenum) { printf ("Entity %i, Brush %i: duplicate plane\n Brush: %s\n" , b->entitynum, b->brushnum, brush_info); break; } if ( s2->planenum == (planenum^1) ) { printf ("Entity %i, Brush %i: mirrored plane\n Brush: %s\n" , b->entitynum, b->brushnum, brush_info); break; } } if (k != b->numsides) continue; // duplicated // // keep this side // side = b->original_sides + b->numsides; side->planenum = planenum; side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum], &td, vec3_origin, b->isTerrain); // Knightmare added // save the td off in case there is an origin brush and we // have to recalculate the texinfo side_brushtextures[nummapbrushsides] = td; nummapbrushsides++; b->numsides++; } while (1); // get the content for the entire brush b->contents = BrushContents (b); // allow detail brushes to be removed if (nodetail && (b->contents & CONTENTS_DETAIL) ) { b->numsides = 0; return; } // allow water brushes to be removed if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) ) { b->numsides = 0; return; } // Knightmare- check if this is an optimized detail brush (has caulk faces) // also exclude trans brushes and terrain if ((b->contents & CONTENTS_DETAIL) && (b->contents & CONTENTS_SOLID) && !b->isTerrain && !b->isGenSurf) for (i=0; i<b->numsides; i++) { if ( !strcmp(texinfo[b->original_sides[i].texinfo].texture, "system/caulk") || !strcmp(texinfo[b->original_sides[i].texinfo].texture, "common/caulk") ) { b->optimizedDetail = true; //printf ("Entity %i, Brush %i: optimized detail\n", b->entitynum, b->brushnum); break; } } // Knightmare- special handling for terrain brushes if (b->isTerrain || b->isGenSurf || phongShading) for (i=0; i<b->numsides; i++) { s2 = &b->original_sides[i]; // set ArghRad phong shading value (because EasyGen/GTKGenSurf doesn't allow this) if (strcmp(texinfo[b->original_sides[i].texinfo].texture, "system/caulk") && strcmp(texinfo[b->original_sides[i].texinfo].texture, "common/caulk")) { texinfo[s2->texinfo].value = 777 + b->entitynum; // lucky 7's texinfo[s2->texinfo].flags &= ~SURF_LIGHT; // must not be light-emitting } } // create windings for sides and bounds for brush // MEM_LEAK MakeBrushWindings (b); t_w = b->original_sides[0].winding; // brushes that will not be visible at all will never be // used as bsp splitters if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) { c_clipbrushes++; for (i=0 ; i<b->numsides ; i++) b->original_sides[i].texinfo = TEXINFO_NODE; } // // origin brushes are removed, but they set // the rotation origin for the rest of the brushes // in the entity. After the entire entity is parsed, // the planenums and texinfos will be adjusted for // the origin brush // if (b->contents & CONTENTS_ORIGIN) { char string[32]; vec3_t origin; if (num_entities == 1) { Error ("Entity %i, Brush %i: origin brushes not allowed in world\n BrushL %s", b->entitynum, b->brushnum, brush_info); return; } VectorAdd (b->mins, b->maxs, origin); VectorScale (origin, 0.5, origin); sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); SetKeyValue (&entities[b->entitynum], "origin", string); VectorCopy (origin, entities[b->entitynum].origin); // don't keep this brush b->numsides = 0; return; } AddBrushBevels (b); nummapbrushes++; mapent->numbrushes++; }
/* * @brief */ static void ParseBrush(entity_t *mapent) { map_brush_t *b; int32_t i, j, k; side_t *side, *s2; int32_t plane_num; map_brush_texture_t td; vec3_t planepts[3]; if (num_map_brushes == MAX_BSP_BRUSHES) Com_Error(ERR_FATAL, "MAX_BSP_BRUSHES\n"); b = &map_brushes[num_map_brushes]; b->original_sides = &map_brush_sides[num_map_brush_sides]; b->entity_num = num_entities - 1; b->brush_num = num_map_brushes - mapent->first_brush; do { if (!GetToken(true)) break; if (!g_strcmp0(token, "}")) break; if (num_map_brush_sides == MAX_BSP_BRUSH_SIDES) Com_Error(ERR_FATAL, "MAX_BSP_BRUSH_SIDES\n"); side = &map_brush_sides[num_map_brush_sides]; // read the three point plane definition for (i = 0; i < 3; i++) { if (i != 0) GetToken(true); if (g_strcmp0(token, "(")) Com_Error(ERR_FATAL, "Parsing brush\n"); for (j = 0; j < 3; j++) { GetToken(false); planepts[i][j] = atof(token); } GetToken(false); if (g_strcmp0(token, ")")) Com_Error(ERR_FATAL, "Parsing brush\n"); } memset(&td, 0, sizeof(td)); // read the texturedef GetToken(false); if (strlen(token) > sizeof(td.name) - 1) Com_Error(ERR_FATAL, "Texture name \"%s\" is too long.\n", token); g_strlcpy(td.name, token, sizeof(td.name)); GetToken(false); td.shift[0] = atoi(token); GetToken(false); td.shift[1] = atoi(token); GetToken(false); td.rotate = atoi(token); GetToken(false); td.scale[0] = atof(token); GetToken(false); td.scale[1] = atof(token); if (TokenAvailable()) { GetToken(false); side->contents = atoi(token); GetToken(false); side->surf = td.flags = atoi(token); GetToken(false); td.value = atoi(token); } else { side->contents = CONTENTS_SOLID; side->surf = td.flags = 0; td.value = 0; } // resolve implicit surface and contents flags SetImpliedFlags(side, td.name); // translucent objects are automatically classified as detail if (side->surf & (SURF_ALPHA_TEST | SURF_BLEND_33 | SURF_BLEND_66)) side->contents |= CONTENTS_DETAIL; if (side->contents & (CONTENTS_PLAYER_CLIP | CONTENTS_MONSTER_CLIP)) side->contents |= CONTENTS_DETAIL; if (fulldetail) side->contents &= ~CONTENTS_DETAIL; if (!(side->contents & ((LAST_VISIBLE_CONTENTS - 1) | CONTENTS_PLAYER_CLIP | CONTENTS_MONSTER_CLIP | CONTENTS_MIST))) side->contents |= CONTENTS_SOLID; // hints and skips are never detail, and have no content if (side->surf & (SURF_HINT | SURF_SKIP)) { side->contents = 0; side->surf &= ~CONTENTS_DETAIL; } // find the plane number plane_num = PlaneFromPoints(planepts[0], planepts[1], planepts[2]); if (plane_num == -1) { Com_Verbose("Entity %i, Brush %i: plane with no normal\n", b->entity_num, b->brush_num); continue; } // see if the plane has been used already for (k = 0; k < b->num_sides; k++) { s2 = b->original_sides + k; if (s2->plane_num == plane_num) { Com_Verbose("Entity %i, Brush %i: duplicate plane\n", b->entity_num, b->brush_num); break; } if (s2->plane_num == (plane_num ^ 1)) { Com_Verbose("Entity %i, Brush %i: mirrored plane\n", b->entity_num, b->brush_num); break; } } if (k != b->num_sides) continue; // duplicated // keep this side side = b->original_sides + b->num_sides; side->plane_num = plane_num; side->texinfo = TexinfoForBrushTexture(&map_planes[plane_num], &td, vec3_origin); // save the td off in case there is an origin brush and we // have to recalculate the texinfo map_brush_textures[num_map_brush_sides] = td; num_map_brush_sides++; b->num_sides++; } while (true); // get the content for the entire brush b->contents = BrushContents(b); // allow detail brushes to be removed if (nodetail && (b->contents & CONTENTS_DETAIL)) { b->num_sides = 0; return; } // allow water brushes to be removed if (nowater && (b->contents & MASK_LIQUID)) { b->num_sides = 0; return; } // create windings for sides and bounds for brush MakeBrushWindings(b); // brushes that will not be visible at all will never be // used as bsp splitters if (b->contents & (CONTENTS_PLAYER_CLIP | CONTENTS_MONSTER_CLIP)) { c_clip_brushes++; for (i = 0; i < b->num_sides; i++) b->original_sides[i].texinfo = TEXINFO_NODE; } // origin brushes are removed, but they set // the rotation origin for the rest of the brushes // in the entity. After the entire entity is parsed, // the plane_nums and texinfos will be adjusted for // the origin brush if (b->contents & CONTENTS_ORIGIN) { char string[32]; vec3_t origin; if (num_entities == 1) { Com_Error(ERR_FATAL, "Entity %i, Brush %i: origin brushes not allowed in world\n", b->entity_num, b->brush_num); return; } VectorAdd(b->mins, b->maxs, origin); VectorScale(origin, 0.5, origin); sprintf(string, "%i %i %i", (int32_t)origin[0], (int32_t)origin[1], (int32_t)origin[2]); SetKeyValue(&entities[b->entity_num], "origin", string); VectorCopy(origin, entities[b->entity_num].origin); // don't keep this brush b->num_sides = 0; return; } AddBrushBevels(b); num_map_brushes++; mapent->num_brushes++; }
/** * @brief Parses a brush from the map file * @sa FindMiptex * @param[in] mapent The entity the brush to parse belongs to * @param[in] filename The map filename, used to derive the name for the footsteps file */ static void ParseBrush (entity_t* mapent, const char* filename) { int j, k; brush_texture_t td; vec3_t planepts[3]; const int checkOrFix = config.performMapCheck || config.fixMap ; if (nummapbrushes == MAX_MAP_BRUSHES) Sys_Error("nummapbrushes == MAX_MAP_BRUSHES (%i)", nummapbrushes); mapbrush_t* b = &mapbrushes[nummapbrushes]; OBJZERO(*b); b->original_sides = &brushsides[nummapbrushsides]; b->entitynum = num_entities - 1; b->brushnum = nummapbrushes - mapent->firstbrush; do { if (Q_strnull(GetToken())) break; if (*parsedToken == '}') break; if (nummapbrushsides == MAX_MAP_BRUSHSIDES) Sys_Error("nummapbrushsides == MAX_MAP_BRUSHSIDES (%i)", nummapbrushsides); side_t* side = &brushsides[nummapbrushsides]; /* read the three point plane definition */ for (int i = 0; i < 3; i++) { if (i != 0) GetToken(); if (*parsedToken != '(') Sys_Error("parsing brush"); for (j = 0; j < 3; j++) { GetToken(); planepts[i][j] = atof(parsedToken); } GetToken(); if (*parsedToken != ')') Sys_Error("parsing brush"); } /* read the texturedef */ GetToken(); if (strlen(parsedToken) >= MAX_TEXPATH) { if (config.performMapCheck || config.fixMap) Com_Printf(" ");/* hack to make this look like output from Check_Printf() */ Com_Printf("ParseBrush: texture name too long (limit %i): %s\n", MAX_TEXPATH, parsedToken); if (config.fixMap) Sys_Error("Aborting, as -fix is active and saving might corrupt *.map by truncating texture name"); } Q_strncpyz(td.name, parsedToken, sizeof(td.name)); td.shift[0] = atof(GetToken()); td.shift[1] = atof(GetToken()); td.rotate = atof(GetToken()); td.scale[0] = atof(GetToken()); td.scale[1] = atof(GetToken()); /* find default flags and values */ const int mt = FindMiptex(td.name); side->surfaceFlags = td.surfaceFlags = side->contentFlags = td.value = 0; if (TokenAvailable()) { side->contentFlags = atoi(GetToken()); side->surfaceFlags = td.surfaceFlags = atoi(GetToken()); td.value = atoi(GetToken()); } /* if in check or fix mode, let them choose to do this (with command line options), * and then call is made elsewhere */ if (!checkOrFix) { SetImpliedFlags(side, &td, b); /* if no other content flags are set - make this solid */ if (!checkOrFix && side->contentFlags == 0) side->contentFlags = CONTENTS_SOLID; } /* translucent objects are automatically classified as detail and window */ if (side->surfaceFlags & (SURF_BLEND33 | SURF_BLEND66 | SURF_ALPHATEST)) { side->contentFlags |= CONTENTS_DETAIL; side->contentFlags |= CONTENTS_TRANSLUCENT; side->contentFlags |= CONTENTS_WINDOW; side->contentFlags &= ~CONTENTS_SOLID; } if (config.fulldetail) side->contentFlags &= ~CONTENTS_DETAIL; if (!checkOrFix) { if (!(side->contentFlags & ((LAST_VISIBLE_CONTENTS - 1) | CONTENTS_ACTORCLIP | CONTENTS_WEAPONCLIP | CONTENTS_LIGHTCLIP))) side->contentFlags |= CONTENTS_SOLID; /* hints and skips are never detail, and have no content */ if (side->surfaceFlags & (SURF_HINT | SURF_SKIP)) { side->contentFlags = 0; side->surfaceFlags &= ~CONTENTS_DETAIL; } } /* check whether the flags are ok */ CheckFlags(side, b); /* generate a list of textures that should have footsteps when walking on them */ if (mt > 0 && (side->surfaceFlags & SURF_FOOTSTEP)) GenerateFootstepList(filename, mt); GenerateMaterialFile(filename, mt, side); /* find the plane number */ int planenum = PlaneFromPoints(b, planepts[0], planepts[1], planepts[2]); if (planenum == PLANENUM_LEAF) { Com_Printf("Entity %i, Brush %i: plane with no normal\n", b->entitynum, b->brushnum); continue; } for (j = 0; j < 3; j++) VectorCopy(planepts[j], mapplanes[planenum].planeVector[j]); /* see if the plane has been used already */ for (k = 0; k < b->numsides; k++) { const side_t* s2 = b->original_sides + k; if (s2->planenum == planenum) { Com_Printf("Entity %i, Brush %i: duplicate plane\n", b->entitynum, b->brushnum); break; } if (s2->planenum == (planenum ^ 1)) { Com_Printf("Entity %i, Brush %i: mirrored plane\n", b->entitynum, b->brushnum); break; } } if (k != b->numsides) continue; /* duplicated */ /* keep this side */ side = b->original_sides + b->numsides; side->planenum = planenum; side->texinfo = TexinfoForBrushTexture(&mapplanes[planenum], &td, vec3_origin, side->contentFlags & CONTENTS_TERRAIN); side->brush = b; /* save the td off in case there is an origin brush and we * have to recalculate the texinfo */ side_brushtextures[nummapbrushsides] = td; Verb_Printf(VERB_DUMP, "Brush %i Side %i (%f %f %f) (%f %f %f) (%f %f %f) texinfo:%i[%s] plane:%i\n", nummapbrushes, nummapbrushsides, planepts[0][0], planepts[0][1], planepts[0][2], planepts[1][0], planepts[1][1], planepts[1][2], planepts[2][0], planepts[2][1], planepts[2][2], side->texinfo, td.name, planenum); nummapbrushsides++; b->numsides++; } while (1); /* get the content for the entire brush */ b->contentFlags = BrushContents(b); /* copy all set face contentflags to the brush contentflags */ for (int m = 0; m < b->numsides; m++) b->contentFlags |= b->original_sides[m].contentFlags; /* set DETAIL, TRANSLUCENT contentflags on all faces, if they have been set on any. * called separately, if in check/fix mode */ if (!checkOrFix) CheckPropagateParserContentFlags(b); /* allow detail brushes to be removed */ if (config.nodetail && (b->contentFlags & CONTENTS_DETAIL)) { b->numsides = 0; return; } /* allow water brushes to be removed */ if (config.nowater && (b->contentFlags & CONTENTS_WATER)) { b->numsides = 0; return; } /* create windings for sides and bounds for brush */ MakeBrushWindings(b); Verb_Printf(VERB_DUMP, "Brush %i mins (%f %f %f) maxs (%f %f %f)\n", nummapbrushes, b->mbBox.mins[0], b->mbBox.mins[1], b->mbBox.mins[2], b->mbBox.maxs[0], b->mbBox.maxs[1], b->mbBox.maxs[2]); /* origin brushes are removed, but they set * the rotation origin for the rest of the brushes (like func_door) * in the entity. After the entire entity is parsed, the planenums * and texinfos will be adjusted for the origin brush */ if (!checkOrFix && (b->contentFlags & CONTENTS_ORIGIN)) { char string[32]; vec3_t origin; if (num_entities == 1) { Sys_Error("Entity %i, Brush %i: origin brushes not allowed in world" , b->entitynum, b->brushnum); return; } b->mbBox.getCenter(origin); Com_sprintf(string, sizeof(string), "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); SetKeyValue(&entities[b->entitynum], "origin", string); Verb_Printf(VERB_EXTRA, "Entity %i, Brush %i: set origin to %s\n", b->entitynum, b->brushnum, string); VectorCopy(origin, entities[b->entitynum].origin); /* don't keep this brush */ b->numsides = 0; return; } if (!checkOrFix) AddBrushBevels(b); nummapbrushes++; mapent->numbrushes++; }