Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,10 @@ void Level::Clear(bool clearErrors)
m_rendererQueryPoint = Vec3();
m_rendererSelectedQuadblockIndexes.clear();
m_genVisTree = false;
m_simpleVisTree = false;
m_bspVis.Clear();
m_maxQuadPerLeaf = 31;
m_maxLeafAxisLength = 64.0f;
m_distanceNearClip = -1.0f;
m_distanceFarClip = 1000.0f;
m_visTreeSettings = VisTreeSettings();
m_pythonConsole.clear();
m_saveScript = false;
m_vrm.clear();
Expand Down Expand Up @@ -188,7 +186,7 @@ bool Level::GenerateBSP()
if (m_bsp.IsValid())
{
GenerateRenderBspData();
if (m_genVisTree) { m_bspVis = GenerateVisTree(m_quadblocks, &m_bsp, m_simpleVisTree, m_distanceNearClip, m_distanceFarClip); }
if (m_genVisTree) { m_bspVis = GenerateVisTree(m_quadblocks, &m_bsp, m_visTreeSettings); }
return true;
}
m_bsp.Clear();
Expand Down Expand Up @@ -1857,8 +1855,10 @@ void Level::GenerateRenderLevData()
size_t triangleOffset = 0;
for (Quadblock& qb : m_quadblocks)
{
qb.SetRenderPrimitiveIndex(triangleOffset);
std::vector<Primitive> qbTriangles = qb.ToGeometry(false);
if (qbTriangles.empty()) { continue; }

qb.SetRenderPrimitiveIndex(triangleOffset);
std::vector<Primitive> qbFilterTriangles = qb.ToGeometry(true);
levTriangles.insert(levTriangles.end(), qbTriangles.begin(), qbTriangles.end());
filterTriangles.insert(filterTriangles.end(), qbFilterTriangles.begin(), qbFilterTriangles.end());
Expand Down
4 changes: 1 addition & 3 deletions src/level.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,10 @@ class Level
bool m_showLogWindow;
bool m_showHotReloadWindow;
bool m_loaded;
bool m_simpleVisTree;
bool m_genVisTree;
int m_maxQuadPerLeaf;
float m_maxLeafAxisLength;
float m_distanceNearClip;
float m_distanceFarClip;
VisTreeSettings m_visTreeSettings;

std::vector<std::tuple<std::string, std::string>> m_invalidQuadblocks;
std::string m_logMessage;
Expand Down
37 changes: 25 additions & 12 deletions src/levelui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -749,18 +749,31 @@ void Level::RenderUI(Renderer& renderer)
static ButtonUI generateBSPButton = ButtonUI();
if (ImGui::TreeNode("Advanced"))
{
if (ImGui::InputInt("Max Quad Per Leaf", &m_maxQuadPerLeaf)) { m_maxQuadPerLeaf = std::max(m_maxQuadPerLeaf, 1); }
ImGui::SetItemTooltip("Lower values improve rendering performance, but increases file size and slows down vis tree generation.");
if (ImGui::InputFloat("Max Leaf Axis Length", &m_maxLeafAxisLength)) { m_maxLeafAxisLength = std::max(m_maxLeafAxisLength, 0.0f); }
ImGui::SetItemTooltip("Lower values improve rendering performance, but increases file size and slows down vis tree generation.");
if (ImGui::InputFloat("Near Clip Distance", &m_distanceNearClip)) { m_distanceNearClip = std::max(m_distanceNearClip, -1.0f); }
ImGui::SetItemTooltip("Minimum drawing distance. Higher values decrease performance and speed up the vis tree generation.");
if (ImGui::InputFloat("Far Clip Distance", &m_distanceFarClip)) { m_distanceFarClip = std::max(m_distanceFarClip, 0.0f); }
ImGui::SetItemTooltip("Maximum drawing distance. Lower values improve performance and speed up the vis tree generation.");
ImGui::Checkbox("Simple Vis Tree", &m_simpleVisTree);
ImGui::SetItemTooltip("The vis tree will be generated faster, but will be less precise");
ImGui::Checkbox("Generate Vis Tree", &m_genVisTree);
ImGui::SetItemTooltip("Generating the vis tree may take several minutes, but the gameplay will be more performant.");
if (ImGui::TreeNodeEx("BSP Settings", ImGuiTreeNodeFlags_DefaultOpen))
{
if (ImGui::InputInt("Max Quad Per Leaf", &m_maxQuadPerLeaf)) { m_maxQuadPerLeaf = std::max(m_maxQuadPerLeaf, 1); }
ImGui::SetItemTooltip("Lower values improve rendering performance, but increases file size and slows down vis tree generation.");
if (ImGui::InputFloat("Max Leaf Axis Length", &m_maxLeafAxisLength)) { m_maxLeafAxisLength = std::max(m_maxLeafAxisLength, 0.0f); }
ImGui::SetItemTooltip("Lower values improve rendering performance, but increases file size and slows down vis tree generation.");

ImGui::TreePop();
}
if (ImGui::TreeNodeEx("Vis Tree Settings", ImGuiTreeNodeFlags_DefaultOpen))
{
ImGui::Checkbox("Generate Vis Tree", &m_genVisTree);
ImGui::SetItemTooltip("Generating the vis tree may take several minutes, but the gameplay will be more performant.");
ImGui::BeginDisabled(!m_genVisTree);
if (ImGui::InputFloat("Near Clip Distance", &m_visTreeSettings.nearClipDistance)) { m_visTreeSettings.nearClipDistance = std::max(m_visTreeSettings.nearClipDistance, -1.0f); }
ImGui::SetItemTooltip("Minimum drawing distance. Higher values decrease performance and speed up the vis tree generation.");
if (ImGui::InputFloat("Far Clip Distance", &m_visTreeSettings.farClipDistance)) { m_visTreeSettings.farClipDistance = std::max(m_visTreeSettings.farClipDistance, 0.0f); }
ImGui::SetItemTooltip("Maximum drawing distance. Lower values improve performance and speed up the vis tree generation.");
ImGui::Checkbox("Assume Commutative Rays", &m_visTreeSettings.commutativeRays);
ImGui::SetItemTooltip("Speeds up VisTree generation by a factor of 2x to 3x with minimal loss of precision.");
ImGui::Checkbox("Center-Only Samples", &m_visTreeSettings.centerOnlySamples);
ImGui::SetItemTooltip("Only casts rays from each quad center (skips corner samples). Much faster, but may miss narrow visibility paths.");
ImGui::EndDisabled();
ImGui::TreePop();
}
ImGui::TreePop();
}
if (generateBSPButton.Show("Generate", buttonMessage, false))
Expand Down
84 changes: 65 additions & 19 deletions src/quadblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Quadblock::Quadblock(const std::string& name, Tri& t0, Tri& t1, Tri& t2, Tri& t3
{
throw QuadException(
("Unique Vertices: " + std::to_string(uniqueCount) + "/3\n" +
"Shared Vertices: " + std::to_string(sharedCount) + "/3\n")
"Shared Vertices: " + std::to_string(sharedCount) + "/3\n")
);
}

Expand Down Expand Up @@ -193,11 +193,11 @@ Quadblock::Quadblock(const std::string& name, Tri& t0, Tri& t1, Tri& t2, Tri& t3
const Tri* uvt1 = FindTri(m_p[2].m_pos, t0, t1, t2, t3);
const Tri* uvt2 = FindTri(m_p[6].m_pos, t0, t1, t2, t3);

m_uvs[0] = { GetUV(m_p[0].m_pos, *uvt0), GetUV(m_p[1].m_pos, *uvt0), GetUV(m_p[3].m_pos, *uvt0), GetUV(m_p[4].m_pos, *centerTri) };
m_uvs[1] = { GetUV(m_p[1].m_pos, *uvt1), GetUV(m_p[2].m_pos, *uvt1), GetUV(m_p[4].m_pos, *uvt1), Vec2() };
m_uvs[2] = { GetUV(m_p[3].m_pos, *uvt2), GetUV(m_p[4].m_pos, *uvt2), GetUV(m_p[6].m_pos, *uvt2), Vec2() };
m_uvs[3] = { Vec2(), Vec2(), Vec2(), Vec2() };
m_uvs[4] = { GetUV(m_p[0].m_pos, *uvt0), GetUV(m_p[2].m_pos, *uvt1), GetUV(m_p[6].m_pos, *uvt2), Vec2() };
m_uvs[0] = {GetUV(m_p[0].m_pos, *uvt0), GetUV(m_p[1].m_pos, *uvt0), GetUV(m_p[3].m_pos, *uvt0), GetUV(m_p[4].m_pos, *centerTri)};
m_uvs[1] = {GetUV(m_p[1].m_pos, *uvt1), GetUV(m_p[2].m_pos, *uvt1), GetUV(m_p[4].m_pos, *uvt1), Vec2()};
m_uvs[2] = {GetUV(m_p[3].m_pos, *uvt2), GetUV(m_p[4].m_pos, *uvt2), GetUV(m_p[6].m_pos, *uvt2), Vec2()};
m_uvs[3] = {Vec2(), Vec2(), Vec2(), Vec2()};
m_uvs[4] = {GetUV(m_p[0].m_pos, *uvt0), GetUV(m_p[2].m_pos, *uvt1), GetUV(m_p[6].m_pos, *uvt2), Vec2()};
}
else { ResetUVs(); }

Expand Down Expand Up @@ -233,8 +233,8 @@ Quadblock::Quadblock(const std::string& name, Quad& q0, Quad& q1, Quad& q2, Quad
{
throw QuadException(
("Unique Vertices: " + std::to_string(uniqueCount) + "/4\n" +
"Shared Vertices: " + std::to_string(sharedCount) + "/4\n" +
"Center Vertices: " + std::to_string(centerCount) + "/1\n")
"Shared Vertices: " + std::to_string(sharedCount) + "/4\n" +
"Center Vertices: " + std::to_string(centerCount) + "/1\n")
);
}

Expand Down Expand Up @@ -306,7 +306,7 @@ Quadblock::Quadblock(const std::string& name, Quad& q0, Quad& q1, Quad& q2, Quad

auto FindQuad = [](const Vec3& pos, const Quad& q0, const Quad& q1, const Quad& q2, const Quad& q3) -> const Quad*
{
const Quad* quads[] = { &q0, &q1, &q2, &q3 };
const Quad* quads[] = {&q0, &q1, &q2, &q3};
for (size_t i = 0; i < 4; i++)
{
const Quad* quad = quads[i];
Expand Down Expand Up @@ -334,10 +334,10 @@ Quadblock::Quadblock(const std::string& name, Quad& q0, Quad& q1, Quad& q2, Quad

if (hasUV)
{
m_uvs[0] = { GetUV(m_p[0].m_pos, *uvq0), GetUV(m_p[1].m_pos, *uvq0), GetUV(m_p[3].m_pos, *uvq0), GetUV(m_p[4].m_pos, *uvq0) };
m_uvs[1] = { GetUV(m_p[1].m_pos, *uvq1), GetUV(m_p[2].m_pos, *uvq1), GetUV(m_p[4].m_pos, *uvq1), GetUV(m_p[5].m_pos, *uvq1) };
m_uvs[2] = { GetUV(m_p[3].m_pos, *uvq2), GetUV(m_p[4].m_pos, *uvq2), GetUV(m_p[6].m_pos, *uvq2), GetUV(m_p[7].m_pos, *uvq2) };
m_uvs[3] = { GetUV(m_p[4].m_pos, *uvq3), GetUV(m_p[5].m_pos, *uvq3), GetUV(m_p[7].m_pos, *uvq3), GetUV(m_p[8].m_pos, *uvq3) };
m_uvs[0] = {GetUV(m_p[0].m_pos, *uvq0), GetUV(m_p[1].m_pos, *uvq0), GetUV(m_p[3].m_pos, *uvq0), GetUV(m_p[4].m_pos, *uvq0)};
m_uvs[1] = {GetUV(m_p[1].m_pos, *uvq1), GetUV(m_p[2].m_pos, *uvq1), GetUV(m_p[4].m_pos, *uvq1), GetUV(m_p[5].m_pos, *uvq1)};
m_uvs[2] = {GetUV(m_p[3].m_pos, *uvq2), GetUV(m_p[4].m_pos, *uvq2), GetUV(m_p[6].m_pos, *uvq2), GetUV(m_p[7].m_pos, *uvq2)};
m_uvs[3] = {GetUV(m_p[4].m_pos, *uvq3), GetUV(m_p[5].m_pos, *uvq3), GetUV(m_p[7].m_pos, *uvq3), GetUV(m_p[8].m_pos, *uvq3)};

float uMin = std::numeric_limits<float>::max(); float vMin = std::numeric_limits<float>::max();
float uMax = -std::numeric_limits<float>::max(); float vMax = -std::numeric_limits<float>::max();
Expand All @@ -352,7 +352,7 @@ Quadblock::Quadblock(const std::string& name, Quad& q0, Quad& q1, Quad& q2, Quad

bool indexPicked[4] = {false, false, false, false};
bool boundPicked[4] = {false, false, false, false};
const QuadUV uvBounds = { Vec2(uMin, vMin), Vec2(uMax, vMin), Vec2(uMin, vMax), Vec2(uMax, vMax)};
const QuadUV uvBounds = {Vec2(uMin, vMin), Vec2(uMax, vMin), Vec2(uMin, vMax), Vec2(uMax, vMax)};

for (size_t indexCount = 0; indexCount < 4; indexCount++)
{
Expand Down Expand Up @@ -390,7 +390,7 @@ Quadblock::Quadblock(const std::string& name, Quad& q0, Quad& q1, Quad& q2, Quad

Quadblock::Quadblock(const PSX::Quadblock& quadblock, const std::vector<PSX::Vertex>& vertices, UpdateFilterCallback filterCallback)
{
uint16_t reverseIndexMapping[NUM_VERTICES_QUADBLOCK] = { 0, 2, 6, 8, 1, 3, 4, 5, 7 };
uint16_t reverseIndexMapping[NUM_VERTICES_QUADBLOCK] = {0, 2, 6, 8, 1, 3, 4, 5, 7};
for (size_t i = 0; i < NUM_VERTICES_QUADBLOCK; i++)
{
uint16_t index = quadblock.index[i];
Expand Down Expand Up @@ -449,13 +449,18 @@ Vec3 Quadblock::GetNormal() const
return normal;
}

const std::vector<std::array<size_t, 3>>& Quadblock::GetCollTriFacesIndexes() const
{
return m_collTriFaces;
}

std::vector<std::array<size_t, 3>> Quadblock::GetTriFacesIndexes() const
{
// Return a list of (size_t, size_t, size_t) containing vertex ID
// of every triface composing the quad, ordered clockwise
std::vector<std::array<size_t, 3>> triFaces;

if (!m_triblock)
if (!m_triblock)
{
triFaces = {
{0, 1, 3},
Expand All @@ -468,7 +473,7 @@ std::vector<std::array<size_t, 3>> Quadblock::GetTriFacesIndexes() const
{5, 8, 7}
};
}
else
else
{
triFaces = {
{0, 1, 3},
Expand Down Expand Up @@ -699,6 +704,8 @@ const BoundingBox& Quadblock::GetBoundingBox() const

std::vector<Primitive> Quadblock::ToGeometry(bool filterTriangles, const std::array<QuadUV, NUM_FACES_QUADBLOCK + 1>* overrideUvs, const std::filesystem::path* overrideTexturePath) const
{
if (GetHide()) { return std::vector<Primitive>(); } /* Turbo Pads */

constexpr int NUM_VERTICES_QUAD = 4;
constexpr int uvVertInd[NUM_FACES_QUADBLOCK][NUM_VERTICES_QUAD] =
{
Expand Down Expand Up @@ -756,7 +763,7 @@ std::vector<Primitive> Quadblock::ToGeometry(bool filterTriangles, const std::ar
{ 3, 4, 6 },
{ 1, 4, 3 },
};
constexpr int triblockQuadIndex[triCount] = { 0, 1, 2, 0 };
constexpr int triblockQuadIndex[triCount] = {0, 1, 2, 0};
for (int triIndex = 0; triIndex < triCount; triIndex++)
{
const int quadIndex = triblockQuadIndex[triIndex];
Expand All @@ -783,7 +790,7 @@ std::vector<Primitive> Quadblock::ToGeometry(bool filterTriangles, const std::ar
std::vector<Vertex> Quadblock::GetVertices() const
{
/* 0 1 2 3 4 5 6 7 8 */
std::vector<Vertex> vertices = { m_p[0], m_p[2], m_p[6], m_p[8], m_p[1], m_p[3], m_p[4], m_p[5], m_p[7] };
std::vector<Vertex> vertices = {m_p[0], m_p[2], m_p[6], m_p[8], m_p[1], m_p[3], m_p[4], m_p[5], m_p[7]};
return vertices;
}

Expand Down Expand Up @@ -894,6 +901,45 @@ void Quadblock::SetDefaultValues()
m_faceDrawMode[i] = FaceDrawMode::DRAW_BOTH;
m_faceRotateFlip[i] = FaceRotateFlip::NONE;
}

const bool equivalentDiagonal = ((m_p[2].m_pos - m_p[6].m_pos).Length() - ((m_p[2].m_pos - m_p[4].m_pos).Length() + (m_p[4].m_pos - m_p[6].m_pos).Length())) <= EPSILON;
if (
equivalentDiagonal &&
(((m_p[0].m_pos - m_p[2].m_pos).Length() - ((m_p[0].m_pos - m_p[1].m_pos).Length() + (m_p[1].m_pos - m_p[2].m_pos).Length())) <= EPSILON) &&
(((m_p[0].m_pos - m_p[6].m_pos).Length() - ((m_p[0].m_pos - m_p[3].m_pos).Length() + (m_p[3].m_pos - m_p[6].m_pos).Length())) <= EPSILON)
)
{
m_collTriFaces = {{0, 2, 6}};
}
else
{
m_collTriFaces = {
{0, 1, 3},
{1, 2, 4},
{1, 4, 3},
{4, 6, 3}
};
}

if (!m_triblock)
{
if (
equivalentDiagonal &&
(((m_p[2].m_pos - m_p[8].m_pos).Length() - ((m_p[2].m_pos - m_p[5].m_pos).Length() + (m_p[5].m_pos - m_p[8].m_pos).Length())) <= EPSILON) &&
(((m_p[6].m_pos - m_p[8].m_pos).Length() - ((m_p[6].m_pos - m_p[7].m_pos).Length() + (m_p[7].m_pos - m_p[8].m_pos).Length())) <= EPSILON)
)
{
m_collTriFaces.push_back({2, 8, 6});
}
else
{
m_collTriFaces.push_back({2, 5, 4});
m_collTriFaces.push_back({4, 7, 6});
m_collTriFaces.push_back({4, 5, 7});
m_collTriFaces.push_back({5, 8, 7});
}
}

m_doubleSided = false;
m_checkpointPathable = true;
m_checkpointStatus = false;
Expand Down
2 changes: 2 additions & 0 deletions src/quadblock.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class Quadblock
const std::string& GetName() const;
Vec3 GetCenter() const;
Vec3 GetNormal() const;
const std::vector<std::array<size_t, 3>>& GetCollTriFacesIndexes() const;
std::vector<std::array<size_t, 3>> GetTriFacesIndexes() const;
std::array<Vec3, 3> GetTriFace(size_t id0, size_t id1, size_t id2) const;
uint8_t GetTerrain() const;
Expand Down Expand Up @@ -205,6 +206,7 @@ class Quadblock
size_t m_turboPadIndex;
Color m_filterColor;
mutable size_t m_bspID;
std::vector<std::array<size_t, 3>> m_collTriFaces;
std::array<QuadUV, NUM_FACES_QUADBLOCK + 1> m_uvs; /* Last id is reserved for low tex */
std::array<size_t, NUM_FACES_QUADBLOCK + 1> m_textureIDs = { 0, 0, 0, 0, 0 };
std::array<size_t, NUM_FACES_QUADBLOCK + 1> m_animTexOffset = {0, 0, 0, 0, 0};
Expand Down
Loading