lightpreview: add "show bmodels" checkbox

This commit is contained in:
Eric Wasylishen 2023-09-30 15:18:14 -06:00
parent 248ed7c614
commit a109dfca28
3 changed files with 98 additions and 73 deletions

View File

@ -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<uint8_t> 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<entdict_t> &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;

View File

@ -30,6 +30,7 @@ See file, 'COPYING', for details.
#include <QVector3D>
#include <QMatrix4x4>
#include <optional>
#include <vector>
#include <common/qvec.hh>
@ -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<face_visibility_key_t> 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);

View File

@ -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<QTimer>();