From 35040d1bd3cb7c6070865573c5aa542bb5ca23b3 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Thu, 9 Sep 2021 02:13:28 -0400 Subject: [PATCH] Q2 working sorta --- common/bspfile.cc | 11 +++++++++-- qbsp/brush.cc | 2 +- qbsp/csg4.cc | 6 +++--- qbsp/map.cc | 20 +++++++++++++++++++- qbsp/portals.cc | 1 + qbsp/surfaces.cc | 2 +- qbsp/wad.cc | 5 +++++ qbsp/writebsp.cc | 2 +- 8 files changed, 40 insertions(+), 9 deletions(-) diff --git a/common/bspfile.cc b/common/bspfile.cc index cdf7f133..97d68797 100644 --- a/common/bspfile.cc +++ b/common/bspfile.cc @@ -225,7 +225,7 @@ struct gamedef_q2_t : public gamedef_t { return 7; } else if (contents.extended & CFLAGS_ILLUSIONARY_VISBLOCKER) { return 2; - } else switch( contents.native & (Q2_LAST_VISIBLE_CONTENTS - 1) ) { + } else switch( contents.native & ((Q2_LAST_VISIBLE_CONTENTS << 1) - 1) ) { case Q2_CONTENTS_SOLID: return 10; case Q2_CONTENTS_WINDOW: return 9; case Q2_CONTENTS_AUX: return 5; @@ -262,6 +262,13 @@ struct gamedef_q2_t : public gamedef_t { } } + bool contents_are_empty(const contentflags_t &contents) const { + return !(contents.native & ((Q2_LAST_VISIBLE_CONTENTS << 1) - 1)); + } + bool contents_are_solid(const contentflags_t &contents) const { + return contents.native & Q2_CONTENTS_SOLID; + } + bool contents_are_sky(const contentflags_t &contents) const { return false; } @@ -274,7 +281,7 @@ struct gamedef_q2_t : public gamedef_t { if (!strict) { return true; } - return contents.native & (Q2_CONTENTS_SOLID | Q2_CONTENTS_WINDOW | Q2_CONTENTS_LIQUID | Q2_CONTENTS_MIST | Q2_CONTENTS_AUX); + return !contents_are_empty(contents); } }; diff --git a/qbsp/brush.cc b/qbsp/brush.cc index 9564e796..16e9be67 100644 --- a/qbsp/brush.cc +++ b/qbsp/brush.cc @@ -452,7 +452,7 @@ CreateBrushFaces(const mapentity_t *src, hullbrush_t *hullbrush, if (options.fixRotateObjTexture) { const mtexinfo_t &texinfo = map.mtexinfos.at(mapface->texinfo); mtexinfo_t texInfoNew = texinfo; - texInfoNew.outputnum = -1; + texInfoNew.outputnum = std::nullopt; vec3_t vecs[2]; int k, l; diff --git a/qbsp/csg4.cc b/qbsp/csg4.cc index efd14c41..1bcbe08e 100644 --- a/qbsp/csg4.cc +++ b/qbsp/csg4.cc @@ -423,7 +423,7 @@ contents override the face inside contents. static void SaveInsideFaces(face_t *face, const brush_t *clipbrush, face_t **savelist) { - Q_assert(!clipbrush->contents.is_solid(options.target_version->game)); + Q_assert(!clipbrush->contents.is_structural_solid(options.target_version->game)); face_t *next; @@ -434,7 +434,7 @@ SaveInsideFaces(face_t *face, const brush_t *clipbrush, face_t **savelist) next = face->next; face->contents[0] = clipbrush->contents; - if ((face->contents[1].is_solid(options.target_version->game) || face->contents[1].is_sky(options.target_version->game)) + if (face->contents[1].is_structural_sky_or_solid(options.target_version->game) && clipbrush->contents.is_detail(CFLAGS_DETAIL)) { // This case is when a structural and detail brush are touching, // and we want to save the sturctural face that is @@ -457,7 +457,7 @@ SaveInsideFaces(face_t *face, const brush_t *clipbrush, face_t **savelist) // N.B.: We don't need a hack like above for when clipbrush->contents == CONTENTS_DETAIL_ILLUSIONARY. // These would create leaks - Q_assert(!((face->contents[1].is_sky(options.target_version->game) || face->contents[1].is_solid(options.target_version->game)) && + Q_assert(!(face->contents[1].is_structural_sky_or_solid(options.target_version->game) && face->contents[0].is_detail(CFLAGS_DETAIL))); /* diff --git a/qbsp/map.cc b/qbsp/map.cc index 9503b6c5..caa25bec 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -1537,7 +1537,7 @@ void mapface_t::set_texvecs(const std::array &vecs) { // start with a copy of the current texinfo structure mtexinfo_t texInfoNew = map.mtexinfos.at(this->texinfo); - texInfoNew.outputnum = -1; + texInfoNew.outputnum = std::nullopt; // update vecs for (int i=0; i<2; i++) { @@ -1678,6 +1678,24 @@ ParseBrush(parser_t *parser, const mapentity_t *entity) if (face.get() == nullptr) continue; + if (options.target_version->game->id == GAME_QUAKE_II) { + // translucent objects are automatically classified as detail + //if ((face->flags.native & (Q2_SURF_TRANS33 | Q2_SURF_TRANS66)) + // || (face->contents & (Q2_CONTENTS_PLAYERCLIP | Q2_CONTENTS_MONSTERCLIP))) + // face->contents |= Q2_CONTENTS_DETAIL; + + if (!(face->contents & (((Q2_LAST_VISIBLE_CONTENTS << 1)-1) + | Q2_CONTENTS_PLAYERCLIP | Q2_CONTENTS_MONSTERCLIP) ) ) + face->contents |= Q2_CONTENTS_SOLID; + + // hints and skips are never detail, and have no content + if (face->flags.native & (Q2_SURF_HINT | Q2_SURF_SKIP) ) + { + face->contents = 0; + face->contents &= ~Q2_CONTENTS_DETAIL; + } + } + /* Check for duplicate planes */ bool discardFace = false; for (int i = 0; imaxs[i] + SIDESPACE; } + outside_node.planenum = PLANENUM_LEAF; outside_node.contents = options.target_version->game->create_solid_contents(); outside_node.portals = NULL; diff --git a/qbsp/surfaces.cc b/qbsp/surfaces.cc index 5ccad464..db11c0ba 100644 --- a/qbsp/surfaces.cc +++ b/qbsp/surfaces.cc @@ -292,7 +292,7 @@ GetEdge(mapentity_t *entity, const vec3_t p1, const vec3_t p2, int v1, v2; int i; - if (!face->contents[0].is_valid(options.target_version->game)) + if (!face->contents[0].is_valid(options.target_version->game, false)) Error("Face with invalid contents (%s)", __func__); v1 = GetVertex(entity, p1); diff --git a/qbsp/wad.cc b/qbsp/wad.cc index 0d347198..5644382f 100644 --- a/qbsp/wad.cc +++ b/qbsp/wad.cc @@ -310,6 +310,11 @@ WADList_Process() } } + // Q2 doesn't use texdata + if (options.target_version->game->id == GAME_QUAKE_II) { + return; + } + /* Default texture data to store in worldmodel */ map.exported_texdata = std::string(texdatasize, '\0'); miptexlump = (dmiptexlump_t *)map.exported_texdata.data(); diff --git a/qbsp/writebsp.cc b/qbsp/writebsp.cc index ec10ee4b..2b7e8b26 100644 --- a/qbsp/writebsp.cc +++ b/qbsp/writebsp.cc @@ -384,7 +384,7 @@ WriteExtendedTexinfoFlags(void) int count = 0; for (const auto &tx : texinfos_sorted) { - if (tx.outputnum == -1) + if (tx.outputnum.has_value()) continue; Q_assert(count == tx.outputnum); // check we are outputting them in the proper sequence