diff --git a/lightpreview/glview.cpp b/lightpreview/glview.cpp index 19dc15f8..6a227ef4 100644 --- a/lightpreview/glview.cpp +++ b/lightpreview/glview.cpp @@ -350,6 +350,30 @@ void main() { } )"; +GLView::face_visibility_key_t GLView::desiredFaceVisibility() const +{ + face_visibility_key_t result; + result.show_bmodels = m_showBmodels; + + if (m_visCulling) { + const mbsp_t &bsp = *m_bsp; + const auto &world = bsp.dmodels.at(0); + + auto *leaf = + BSP_FindLeafAtPoint(&bsp, &world, qvec3d{m_cameraOrigin.x(), m_cameraOrigin.y(), m_cameraOrigin.z()}); + + int leafnum = leaf - bsp.dleafs.data(); + int clusternum = leaf->cluster; + + result.leafnum = leafnum; + result.clusternum = clusternum; + } else { + result.leafnum = -1; + result.clusternum = -1; + } + return result; +} + void GLView::updateFaceVisibility() { if (!m_bsp) @@ -358,72 +382,65 @@ void GLView::updateFaceVisibility() const mbsp_t &bsp = *m_bsp; const auto &world = bsp.dmodels.at(0); - auto *leaf = BSP_FindLeafAtPoint(&bsp, &world, qvec3d{m_cameraOrigin.x(), m_cameraOrigin.y(), m_cameraOrigin.z()}); + const face_visibility_key_t desired = desiredFaceVisibility(); - int leafnum = leaf - bsp.dleafs.data(); - int clusternum = leaf->cluster; - - if (!m_visCulling) { - clusternum = -1; - } - - if (m_lastLeaf == clusternum) { - qDebug() << "reusing last frame visdata for leaf " << leafnum << " cluster " << clusternum; + if (m_uploaded_face_visibility && + *m_uploaded_face_visibility == desired) { + qDebug() << "reusing last frame visdata"; return; } - qDebug() << "looking up pvs for clusternum " << clusternum; - - auto it = m_decompressedVis.find(clusternum); - if (it == m_decompressedVis.end()) { - qDebug() << "no visdata, must be in void"; - - m_lastLeaf = -1; - setFaceVisibilityToAllVisible(); - - return; - } - - Q_assert(it != m_decompressedVis.end()); - - const auto &pvs = it->second; - qDebug() << "found bitvec of size " << pvs.size(); - - // check leaf visibility - - auto leaf_sees = [&](const mleaf_t *b) -> bool { - if (b->cluster < 0) - return true; - - return !!(pvs[b->cluster >> 3] & (1 << (b->cluster & 7))); - }; + qDebug() << "looking up pvs for clusternum " << desired.clusternum; const int face_visibility_width = m_bsp->dfaces.size(); std::vector face_flags; face_flags.resize(face_visibility_width, 0); - // visit all world leafs: if they're visible, mark the appropriate faces - BSP_VisitAllLeafs(bsp, bsp.dmodels[0], [&](const mleaf_t &leaf) { - if (leaf_sees(&leaf)) { - for (int ms = 0; ms < leaf.nummarksurfaces; ++ms) { - int fnum = bsp.dleaffaces[leaf.firstmarksurface + ms]; - face_flags[fnum] = 16; + if (auto it = m_decompressedVis.find(desired.clusternum); + desired.leafnum != -1 && it != m_decompressedVis.end()) { + + const auto &pvs = it->second; + qDebug() << "found bitvec of size " << pvs.size(); + + // check leaf visibility + + auto leaf_sees = [&](const mleaf_t *b) -> bool { + if (b->cluster < 0) + return true; + + return !!(pvs[b->cluster >> 3] & (1 << (b->cluster & 7))); + }; + + // visit all world leafs: if they're visible, mark the appropriate faces + BSP_VisitAllLeafs(bsp, bsp.dmodels[0], [&](const mleaf_t &leaf) { + if (leaf_sees(&leaf)) { + for (int ms = 0; ms < leaf.nummarksurfaces; ++ms) { + int fnum = bsp.dleaffaces[leaf.firstmarksurface + ms]; + face_flags[fnum] = 16; + } } + }); + } else { + // mark all world faces + for (int fi = world.firstface; fi < (world.firstface + world.numfaces); ++fi) { + face_flags[fi] = 16; } - }); + } // set all bmodel faces to visible - for (int mi = 1; mi < bsp.dmodels.size(); ++mi) { - auto &model = bsp.dmodels[mi]; - for (int fi = model.firstface; fi < (model.firstface + model.numfaces); ++fi) { - face_flags[fi] = 16; + if (m_showBmodels) { + for (int mi = 1; mi < bsp.dmodels.size(); ++mi) { + auto &model = bsp.dmodels[mi]; + for (int fi = model.firstface; fi < (model.firstface + model.numfaces); ++fi) { + face_flags[fi] = 16; + } } } setFaceVisibilityArray(face_flags.data()); - m_lastLeaf = clusternum; + m_uploaded_face_visibility = desired; } bool GLView::shouldLiveUpdate() const @@ -812,11 +829,13 @@ void GLView::setKeepOrigin(bool keeporigin) void GLView::setDrawPortals(bool drawportals) { m_drawPortals = drawportals; + update(); } void GLView::setDrawLeak(bool drawleak) { m_drawLeak = drawleak; + update(); } void GLView::setLightStyleIntensity(int style_id, int intensity) @@ -850,6 +869,14 @@ void GLView::setDrawTranslucencyAsOpaque(bool drawopaque) update(); } +void GLView::setShowBmodels(bool bmodels) +{ + // force re-upload of face visibility + m_uploaded_face_visibility = std::nullopt; + m_showBmodels = bmodels; + update(); +} + void GLView::takeScreenshot(QString destPath, int w, int h) { // update aspect ratio @@ -900,21 +927,6 @@ void GLView::setFaceVisibilityArray(uint8_t *data) logging::print("uploaded {} bytes face visibility texture", face_visibility_width); } -void GLView::setFaceVisibilityToAllVisible() -{ - // one byte per face - int face_visibility_width = m_bsp->dfaces.size(); - - uint8_t *data = new uint8_t[face_visibility_width]; - for (int x = 0; x < face_visibility_width; ++x) { - data[x] = 16; - } - - setFaceVisibilityArray(data); - - delete[] data; -} - void GLView::renderBSP(const QString &file, const mbsp_t &bsp, const bspxentries_t &bspx, const std::vector &entities, const full_atlas_t &lightmap, const settings::common_settings &settings, bool use_bspx_normals) @@ -957,7 +969,7 @@ void GLView::renderBSP(const QString &file, const mbsp_t &bsp, const bspxentries m_portalIndexBuffer.allocate(0); num_leak_points = 0; num_portal_indices = 0; - m_lastLeaf = -1; + m_uploaded_face_visibility = std::nullopt; int32_t highest_depth = 0; @@ -1018,11 +1030,6 @@ void GLView::renderBSP(const QString &file, const mbsp_t &bsp, const bspxentries delete[] data; } - // upload face visibility - if (!bsp.dfaces.empty()) { - setFaceVisibilityToAllVisible(); - } - struct face_payload { const mface_t *face; diff --git a/lightpreview/glview.h b/lightpreview/glview.h index a22ec477..4a9fcd53 100644 --- a/lightpreview/glview.h +++ b/lightpreview/glview.h @@ -30,6 +30,7 @@ See file, 'COPYING', for details. #include #include +#include #include #include @@ -68,10 +69,21 @@ private: float m_moveSpeed; // vis culling stuff - /** - * -1 indicates solid leaf or no visdata (render all) - */ - int m_lastLeaf = -1; + struct face_visibility_key_t + { + bool show_bmodels; + // -1 indicates solid leaf or no visdata (render all world faces) + int leafnum; + int clusternum; + + bool operator==(const face_visibility_key_t &other) const + { + return show_bmodels == other.show_bmodels && leafnum == other.leafnum && clusternum == other.clusternum; + } + }; + face_visibility_key_t desiredFaceVisibility() const; + + std::optional m_uploaded_face_visibility; bool m_visCulling = true; // camera stuff @@ -97,6 +109,7 @@ private: bool m_drawLeak = false; QOpenGLTexture::Filter m_filter = QOpenGLTexture::Linear; bool m_drawTranslucencyAsOpaque = false; + bool m_showBmodels = true; QOpenGLVertexArrayObject m_vao; QOpenGLBuffer m_vbo; @@ -187,7 +200,6 @@ public: private: void setFaceVisibilityArray(uint8_t *data); - void setFaceVisibilityToAllVisible(); public: void renderBSP(const QString &file, const mbsp_t &bsp, const bspxentries_t &bspx, @@ -209,6 +221,7 @@ public: void setMagFilter(QOpenGLTexture::Filter filter); const bool &getKeepOrigin() const { return m_keepOrigin; } void setDrawTranslucencyAsOpaque(bool drawopaque); + void setShowBmodels(bool bmodels); void takeScreenshot(QString destPath, int w, int h); diff --git a/lightpreview/mainwindow.cpp b/lightpreview/mainwindow.cpp index 0b740497..6a06858f 100644 --- a/lightpreview/mainwindow.cpp +++ b/lightpreview/mainwindow.cpp @@ -200,6 +200,8 @@ void MainWindow::createPropertiesSidebar() bspx_normals->setChecked(true); auto *draw_opaque = new QCheckBox(tr("Draw Translucency as Opaque")); + auto *show_bmodels = new QCheckBox(tr("Show Bmodels")); + show_bmodels->setChecked(true); formLayout->addRow(tr("common"), common_options); formLayout->addRow(tr("qbsp"), qbsp_options); @@ -217,6 +219,7 @@ void MainWindow::createPropertiesSidebar() formLayout->addRow(bspx_decoupled_lm); formLayout->addRow(bspx_normals); formLayout->addRow(draw_opaque); + formLayout->addRow(show_bmodels); lightstyles = new QVBoxLayout(); @@ -271,6 +274,8 @@ void MainWindow::createPropertiesSidebar() connect(draw_opaque, &QAbstractButton::toggled, this, [=](bool checked) { glView->setDrawTranslucencyAsOpaque(checked); }); connect(glView, &GLView::cameraMoved, this, &MainWindow::displayCameraPositionInfo); + connect(show_bmodels, &QAbstractButton::toggled, this, + [=](bool checked) { glView->setShowBmodels(checked); }); // set up load timer m_fileReloadTimer = std::make_unique();