32 #include "../../shared/parse.h"
46 #define PLANE_HASHES 1024
64 int hash = (
int)fabs(distance) * 27;
77 if (normal[0] == 1.0 || normal[0] == -1.0)
79 if (normal[1] == 1.0 || normal[1] == -1.0)
81 if (normal[2] == 1.0 || normal[2] == -1.0)
88 if (ax >= ay && ax >= az)
90 if (ay >= ax && ay >= az)
124 Sys_Error(
"FloatPlane: bad normal (%.3f:%.3f:%.3f)", normal[0], normal[1], normal[2]);
135 (p + 1)->dist = -dist;
165 for (
int i = 0;
i < 3;
i++) {
204 for (i = -1; i <= 1; i++) {
206 for (p = planehash[h]; p; p = p->
hash_chain) {
209 return (int16_t)
index;
261 for (i = 1; i < b->
numsides; i++, s++) {
297 for (axis = 0; axis < 3; axis++) {
298 for (dir = -1; dir <= 1; dir += 2, order++) {
334 side_brushtextures[index + order] = side_brushtextures[index +
i];
335 side_brushtextures[index +
i] = tdtemp;
361 for (k = 0; k < 3; k++)
362 if (vec[k] == -1 || vec[k] == 1
363 || (vec[k] == 0.0
f && vec[(k + 1) % 3] == 0.0
f))
369 for (axis = 0; axis < 3; axis++) {
370 for (dir = -1; dir <= 1; dir += 2) {
400 const float d =
DotProduct(w2->
p[l], normal) - dist;
442 for (i = 0; i < brush->
numsides; i++) {
445 for (j = 0; j < brush->
numsides && w; j++) {
466 for (i = 0; i < 3; i++) {
468 Com_Printf(
"entity %i, brush %i: bounds out of world range (%f:%f)\n",
500 bool terrainByTexture =
false;
503 if (!
config.generateMaterialFile)
518 Com_Printf(
"Could not open material file '%s' for writing\n", materialPath);
519 config.generateMaterialFile =
false;
524 || strstr(
textureref[mipTexIndex].name,
"rock")
525 || strstr(
textureref[mipTexIndex].name,
"grass")) {
526 terrainByTexture =
true;
530 FS_Printf(&f,
"{\n\tmaterial %s\n\t{\n\t\ttexture <fillme>\n\t\tterrain 0 64\n\t\tlightmap\n\t}\n}\n",
textureref[mipTexIndex].name);
537 || strstr(
textureref[mipTexIndex].name,
"glass")
538 || strstr(
textureref[mipTexIndex].name,
"window")) {
539 FS_Printf(&f,
"{\n\tmaterial %s\n\tspecular 2.0\n\t{\n\t\tenvmap 0\n\t}\n}\n",
textureref[mipTexIndex].name);
544 if (strstr(
textureref[mipTexIndex].name,
"wood")) {
550 if (strstr(
textureref[mipTexIndex].name,
"wall")) {
551 FS_Printf(&f,
"{\n\tmaterial %s\n\tspecular 0.6\n\tbump 2.0\n}\n",
textureref[mipTexIndex].name);
570 if (!
config.generateFootstepFile)
584 Com_Printf(
"Could not open footstep file '%s.footsteps' for writing\n", fileBase);
585 config.generateFootstepFile =
false;
608 const int checkOrFix =
config.performMapCheck ||
config.fixMap ;
630 for (
int i = 0;
i < 3;
i++) {
636 for (j = 0; j < 3; j++) {
653 Sys_Error(
"Aborting, as -fix is active and saving might corrupt *.map by truncating texture name");
712 int planenum =
PlaneFromPoints(b, planepts[0], planepts[1], planepts[2]);
718 for (j = 0; j < 3; j++)
719 VectorCopy(planepts[j], mapplanes[planenum].planeVector[j]);
728 if (s2->
planenum == (planenum ^ 1)) {
748 planepts[0][0], planepts[0][1], planepts[0][2],
749 planepts[1][0], planepts[1][1], planepts[1][2],
750 planepts[2][0], planepts[2][1], planepts[2][2],
797 Sys_Error(
"Entity %i, Brush %i: origin brushes not allowed in world"
804 Com_sprintf(
string,
sizeof(
string),
"%i %i %i", (
int)origin[0], (
int)origin[1], (
int)origin[2]);
833 int newbrushes, worldbrushes,
i;
843 Sys_Error(
"Empty func_group - clean your map");
846 memcpy(temp, mapbrushes + mapent->
firstbrush, newbrushes *
sizeof(*temp));
849 memmove(mapbrushes + worldbrushes + newbrushes,
850 mapbrushes + worldbrushes,
854 memcpy(mapbrushes + worldbrushes, temp,
sizeof(*temp) * newbrushes);
859 entities[i].firstbrush += newbrushes;
873 for (
int j = 0; j < b->
numsides; j++) {
897 const bool inlineModelEntity = (
Q_streq(
"func_breakable", entName)
898 ||
Q_streq(
"func_door", entName)
899 ||
Q_streq(
"func_door_sliding", entName)
900 ||
Q_streq(
"func_rotating", entName)
902 return inlineModelEntity;
932 static int worldspawnCount = 0;
933 int notCheckOrFix = !(
config.performMapCheck ||
config.fixMap);
939 Sys_Error(
"ParseMapEntity: { not found");
951 Sys_Error(
"ParseMapEntity: EOF without closing brace");
972 Sys_Error(
"The first entity must be worldspawn, it is: %s", entName);
973 if (notCheckOrFix &&
Q_streq(
"func_group", entName)) {
979 if (mapent->
numbrushes == 0 && notCheckOrFix) {
983 }
else if (
Q_streq(
"worldspawn", entName)) {
985 if (worldspawnCount > 1)
986 Com_Printf(
"Warning: more than one %s in one map\n", entName);
988 const char* text = entityString;
1035 for (
int k = 0; k < brush->
numsides; k++) {
1041 for (
int i = 0;
i < 3;
i++)
1064 Sys_Error(
"Could not open %s for writing", filename);
1076 FS_Printf(&f,
"// entity %i\n{\n",
i - removed);
1083 for (j = 0, jc = 0; j < mapent->
numbrushes; j++) {
1094 if (brushesToAdd !=
nullptr) {
1095 for (
int k = 0; k < numToAdd; k++) {
1096 if (brushesToAdd[k]->skipWriteBack)
1123 *entityString =
'\0';
1126 Com_sprintf(filename,
sizeof(filename),
"maps/%s.ump", name);
1132 text = (
const char*)buf;
1138 if (
Q_streq(token,
"extends")) {
1141 Com_Printf(
"ParseUMP: Too many extends in %s 'extends %s' ignored\n", filename, token);
1143 ParseUMP(token, entityString,
true);
1144 }
else if (
Q_streq(token,
"worldspawn")) {
1145 const char* start =
nullptr;
1148 Com_Printf(
"ParseUMP: Not a valid worldspawn block in '%s'\n", filename);
1152 }
else if (length == 0) {
1153 Com_Printf(
"no worldspawn settings in ump file\n");
1156 Com_Printf(
"use worldspawn settings from ump file\n");
1159 }
else if (token[0] ==
'{') {
1161 text = strchr(text,
'}') + 1;
1179 if (filename ==
nullptr)
1182 const char* mapsDir =
"maps/";
1183 const int lMaps = strlen(mapsDir);
1184 const int l = strlen(filename);
1185 const int targetLength = strlen(mapFilename) - lMaps - l;
1186 if (targetLength <= 0)
1188 Q_strncpyz(name, mapFilename + lMaps, targetLength);
1189 Com_Printf(
"...ump: '%s%s.ump'\n", mapsDir, name);
1222 ParseUMP(ump, entityString,
false);
1227 if (subdivide >= 256 && subdivide <= 2048) {
1229 config.subdivideSize = subdivide;
1242 mapBox.
add(mapbrushes[
i].mbBox);
bool Q_strnull(const char *string)
vec_t VectorLength(const vec3_t v)
Calculate the length of a vector.
Performs check on a loaded mapfile, and makes changes that can be saved back to the source map...
#define VectorCopy(src, dest)
#define Mem_AllocTypeN(type, n)
#define CONTENTS_WEAPONCLIP
void setNegativeVolume()
Sets mins and maxs to their starting points before using addPoint.
void Sys_Error(const char *error,...)
textureref_t textureref[MAX_MAP_TEXTURES]
#define LAST_VISIBLE_CONTENTS
mapbrush_t mapbrushes[MAX_MAP_BRUSHES]
QGL_EXTERN GLint GLenum type
const char * Com_SkipPath(const char *pathname)
Returns just the filename from a given path.
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
static void MoveBrushesToWorld(entity_t *mapent)
Takes all of the brushes from the current entity and adds them to the world's brush list...
#define CONTENTS_PASSABLE
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
static char mapFilename[MAX_OSPATH]
static bool IsInlineModelEntity(const char *entName)
Checks whether this entity is an inline model that should have brushes.
static int materialsCnt
How many materials were created for this map.
brush_texture_t side_brushtextures[MAX_MAP_SIDES]
bool EpairCheckForDuplicate(const entity_t *ent, const epair_t *e)
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
void Com_StripExtension(const char *in, char *out, const size_t size)
Removes the file extension from a filename.
int TexinfoForBrushTexture(plane_t *plane, brush_texture_t *bt, const vec3_t origin, bool isTerrain)
plane_t mapplanes[MAX_MAP_PLANES]
void CheckPropagateParserContentFlags(mapbrush_t *b)
some contentlflags are set as a result of some surface flag. For example, if one face is TRANS* then ...
void CrossProduct(const vec3_t v1, const vec3_t v2, vec3_t cross)
binary operation on vectors in a three-dimensional space
void ChopWindingInPlace(winding_t **inout, const vec3_t normal, const vec_t dist, const vec_t epsilon)
void SetImpliedFlags(side_t *side, brush_texture_t *tex, const mapbrush_t *brush)
Sets surface flags dependent on assigned texture.
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
void Com_Printf(const char *const fmt,...)
static void WriteMapBrush(const mapbrush_t *brush, const int j, qFILE *f)
write a brush to the .map file
static int footstepsCnt
Amount of footstep surfaces found in this map.
void LoadScriptFile(const char *filename)
entity_t entities[MAX_MAP_ENTITIES]
void WriteMapFile(const char *filename)
static const char * GetUMPName(const char *mapFilename)
The contract is that the directory name is equal to the base of the ump filename. ...
static void ParseBrush(entity_t *mapent, const char *filename)
Parses a brush from the map file.
side_t brushsides[MAX_MAP_SIDES]
epair_t * ParseEpair(int entNum)
Parses one key and value for an entity from the current tokens.
static void AdjustBrushesForOrigin(const entity_t *ent)
If there was an origin brush, offset all of the planes and texinfo.
static int16_t PlaneFromPoints(const mapbrush_t *b, const vec3_t p0, const vec3_t p1, const vec3_t p2)
Builds a plane normal and distance from three points on the plane. If the normal is nearly axial...
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
#define MAX_MAP_BRUSHSIDES
void SetKeyValue(entity_t *ent, const char *key, const char *value)
static bool MakeBrushWindings(mapbrush_t *brush)
makes basewindings for sides and mins / maxs for the brush
void add(const vec3_t point)
If the point is outside the box, expand the box to accommodate it.
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
static void AddBrushBevels(mapbrush_t *b)
Adds any additional planes necessary to allow the brush to be expanded against axial bounding boxes...
void GetVectorForKey(const entity_t *ent, const char *key, vec3_t vec)
Converts the value of a entity parameter into a vec3_t.
QGL_EXTERN GLuint GLsizei GLsizei * length
static void CheckFlags(side_t *side, const mapbrush_t *b)
Checks whether the surface and content flags are correct.
static int PlaneTypeForNormal(const vec3_t normal)
Set the type of the plane according to it's normal vector.
static int BrushContents(mapbrush_t *b)
Get the content flags for a given brush.
static wrapCache_t * hash[MAX_WRAP_HASH]
static uint16_t CreateNewFloatPlane(vec3_t normal, vec_t dist)
static int GetPlaneHashValueForDistance(const vec_t distance)
Planes are stored by their distance (resp. the calculated hash) in the plane hash table...
mapbrush_t ** Check_ExtraBrushesForWorldspawn(int *numBrushes)
single brushes in func_groups are moved to worldspawn. this function allocates space for pointers to ...
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
int FS_Printf(qFILE *f, const char *msg,...)
Can print chunks for 1024 chars into a file.
void LoadMapFile(const char *filename)
entity_t * FindTargetEntity(const char *target)
Searches the entities array for an entity with the parameter targetname that matches the searched tar...
struct side_s * original_sides
struct mapbrush_s * brush
for storing the vertices of the side of a brush or other polygon
#define VectorNotEmpty(a)
void getCenter(vec3_t center) const
Calculates the center of the bounding box.
char parsedToken[MAX_TOKEN_CHARS]
int Com_GetBlock(const char **text, const char **start)
Get the start and end point of a block in the given text.
static void GenerateMaterialFile(const char *filename, int mipTexIndex, side_t *s)
Generates material files in case the settings can be guessed from map file.
void asIntString(char *str, size_t len)
Prints a representation of the box.
static void SnapPlane(vec3_t normal, vec_t *dist)
Snaps normal to axis-aligned if it is within an epsilon of axial.
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
static void WriteMapEntities(qFILE *f, const epair_t *e)
Recurse down the epair list.
struct plane_s * hash_chain
#define CONTENTS_ACTORCLIP
TR_TILE_TYPE mapTiles[MAX_MAPTILES]
static bool SnapVector(vec3_t normal)
Round the vector to int values.
vec_t VectorNormalize(vec3_t v)
Calculate unit vector for a given vec3_t.
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
#define CONTENTS_TRANSLUCENT
byte GetLevelFlagsFromBrush(const mapbrush_t *brush)
Extract the level flags (1-8) from the content flags of the given brush.
static void AddPlaneToHash(plane_t *p)
static plane_t * planehash[PLANE_HASHES]
winding_t * BaseWindingForPlane(const vec3_t normal, const vec_t dist)
const char * GetToken()
Parses the next token from the current script on the stack and store the result in parsedToken...
static void GenerateFootstepList(const char *filename, int mipTexIndex)
Generate a list of textures that should have footsteps when walking on them.
#define MAX_WORLD_WIDTH
-MAX_WORLD_WIDTH up tp +MAX_WORLD_WIDTH
vec_t Q_rint(const vec_t in)
Round to nearest integer.
static bool ParseMapEntity(const char *filename, const char *entityString)
Parsed map entites and brushes.
int FindMiptex(const char *name)
const char * ValueForKey(const entity_t *ent, const char *key)
bool TokenAvailable(void)
Returns true if there is another token on the line.
epair_t * AddEpair(const char *key, const char *value, int entNum)
static bool PlaneEqual(const plane_t *p, const vec3_t normal, const vec_t dist)
Checks whether the given normal and distance vectors match the given plane by some epsilon value...
#define CONTENTS_LIGHTCLIP
uint16_t FindOrCreateFloatPlane(vec3_t normal, vec_t dist)
#define VectorSubtract(a, b, dest)
static mapTiles_t mapTiles
void FS_FreeFile(void *buffer)
static void ParseUMP(const char *name, char *entityString, bool inherit)
Parses an ump file that contains the random map definition.