From b0ece93f8300bac17c320601a09047357e3892fd Mon Sep 17 00:00:00 2001 From: Jonathan Date: Wed, 16 Feb 2022 19:23:19 -0500 Subject: [PATCH] Fix/implement animated textures for Q2 --- common/bspfile.cc | 4 ++-- include/qbsp/map.hh | 3 +++ include/qbsp/qbsp.hh | 3 ++- qbsp/map.cc | 41 ++++++++++++++++++++++++++--------------- qbsp/writebsp.cc | 4 ++++ 5 files changed, 37 insertions(+), 18 deletions(-) diff --git a/common/bspfile.cc b/common/bspfile.cc index 3a2bc496..658db814 100644 --- a/common/bspfile.cc +++ b/common/bspfile.cc @@ -462,8 +462,8 @@ struct gamedef_q2_t : public gamedef_t int32_t get_content_type(const contentflags_t &contents) const { - return (contents.native & ((Q2_LAST_VISIBLE_CONTENTS << 1) - 1)) | - (Q2_CONTENTS_PLAYERCLIP | Q2_CONTENTS_MONSTERCLIP | Q2_CONTENTS_ORIGIN | Q2_CONTENTS_DETAIL | Q2_CONTENTS_TRANSLUCENT | Q2_CONTENTS_AREAPORTAL); + return contents.native & (((Q2_LAST_VISIBLE_CONTENTS << 1) - 1) | + (Q2_CONTENTS_PLAYERCLIP | Q2_CONTENTS_MONSTERCLIP | Q2_CONTENTS_ORIGIN | Q2_CONTENTS_DETAIL | Q2_CONTENTS_TRANSLUCENT | Q2_CONTENTS_AREAPORTAL)); } int32_t contents_priority(const contentflags_t &contents) const diff --git a/include/qbsp/map.hh b/include/qbsp/map.hh index 5e21652d..47c57180 100644 --- a/include/qbsp/map.hh +++ b/include/qbsp/map.hh @@ -110,6 +110,8 @@ struct texdata_t std::string name; surfflags_t flags; int32_t value; + std::string animation; + int32_t animation_miptex = -1; }; struct mapdata_t @@ -178,6 +180,7 @@ struct extended_texinfo_t contentflags_t contents = { 0 }; surfflags_t flags = { 0 }; int value = 0; + std::string animation; }; struct quark_tx_info_t diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index d43d2c8b..6528729a 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -191,9 +191,10 @@ struct mtexinfo_t int32_t miptex = 0; surfflags_t flags = {}; int32_t value = 0; // Q2-specific + int32_t next = -1; // Q2-specific std::optional outputnum = std::nullopt; // nullopt until added to bsp - constexpr auto as_tuple() const { return std::tie(vecs, miptex, flags, value); } + constexpr auto as_tuple() const { return std::tie(vecs, miptex, flags, value, next); } constexpr bool operator<(const mtexinfo_t &other) const { return as_tuple() < other.as_tuple(); } diff --git a/qbsp/map.cc b/qbsp/map.cc index 4423b9b1..f6efe22f 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -188,14 +188,10 @@ int FindMiptex(const char *name, std::optional &extended_inf } } else { // load .wal first - std::optional wal; + std::optional wal = LoadWal(name); - if (!internal && !extended_info.has_value()) { - wal = LoadWal(name); - - if (wal) { - extended_info = extended_texinfo_t{wal->contents, wal->flags, wal->value}; - } + if (wal && !internal && !extended_info.has_value()) { + extended_info = extended_texinfo_t{wal->contents, wal->flags, wal->value, wal->animation}; } if (!extended_info.has_value()) { @@ -205,19 +201,21 @@ int FindMiptex(const char *name, std::optional &extended_inf for (i = 0; i < map.nummiptex(); i++) { const texdata_t &tex = map.miptex.at(i); - if (!Q_strcasecmp(name, tex.name.c_str()) && tex.flags.native == extended_info->flags.native && - tex.value == extended_info->value) { + if (!Q_strcasecmp(name, tex.name.c_str()) && + tex.flags.native == extended_info->flags.native && + tex.value == extended_info->value && + tex.animation == extended_info->animation) { return i; } } i = map.miptex.size(); - map.miptex.push_back({name, extended_info->flags, extended_info->value}); + map.miptex.push_back({name, extended_info->flags, extended_info->value, extended_info->animation}); /* Handle animating textures carefully */ - if (wal && !wal->animation.empty()) { - FindMiptex(wal->animation.data()); + if (!extended_info->animation.empty()) { + map.miptex[i].animation_miptex = FindMiptex(extended_info->animation.data(), internal); } } @@ -295,12 +293,21 @@ int FindTexinfo(const mtexinfo_t &texinfo) /* Allocate a new texinfo at the end of the array */ const int num_texinfo = static_cast(map.mtexinfos.size()); - map.mtexinfos.push_back(texinfo); + map.mtexinfos.emplace_back(texinfo); map.mtexinfo_lookup[texinfo] = num_texinfo; // catch broken < implementations in mtexinfo_t assert(map.mtexinfo_lookup.find(texinfo) != map.mtexinfo_lookup.end()); + // create a copy of the miptex for animation chains + if (map.miptex[texinfo.miptex].animation_miptex != -1) { + mtexinfo_t anim_next = texinfo; + + anim_next.miptex = map.miptex[texinfo.miptex].animation_miptex; + + map.mtexinfos[num_texinfo].next = FindTexinfo(anim_next); + } + return num_texinfo; } @@ -1306,8 +1313,6 @@ static void ParseTextureDef(parser_t &parser, mapface_t &mapface, const mapbrush qvec2d shift, scale; texcoord_style_t tx_type; - memset(tx, 0, sizeof(*tx)); - quark_tx_info_t extinfo; if (brush->format == brushformat_t::BRUSH_PRIMITIVES) { @@ -1362,6 +1367,12 @@ static void ParseTextureDef(parser_t &parser, mapface_t &mapface, const mapbrush // info so it can at least compile. if (options.target_game->id != GAME_QUAKE_II) { extinfo.info = std::nullopt; + } else { + // assign animation to extinfo, so that we load the animated + // first one first + if (auto wal = LoadWal(mapface.texname.c_str())) { + extinfo.info->animation = wal->animation; + } } tx->miptex = FindMiptex(mapface.texname.c_str(), extinfo.info); diff --git a/qbsp/writebsp.cc b/qbsp/writebsp.cc index f24e16f3..ff48003c 100644 --- a/qbsp/writebsp.cc +++ b/qbsp/writebsp.cc @@ -104,6 +104,10 @@ size_t ExportMapTexinfo(size_t texinfonum) src.outputnum = i; + if (src.next != -1) { + map.bsp.texinfo[i].nexttexinfo = ExportMapTexinfo(src.next); + } + return i; }