Skip to content

Commit

Permalink
Fix invalid faces at load (bad winding)
Browse files Browse the repository at this point in the history
  • Loading branch information
UnrealKaraulov committed Nov 13, 2024
1 parent 0040d58 commit 35dc184
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 94 deletions.
63 changes: 25 additions & 38 deletions src/bsp/Bsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ Bsp::Bsp(std::string fpath)
world->setOrAddKeyvalue("_editor", g_version_string);
}

for (int i = 0; i < faceCount; i++)
/*for (int i = 0; i < faceCount; i++)
{
BSPFACE32& face = faces[i];
BSPTEXTUREINFO& info = texinfos[face.iTextureInfo];
Expand All @@ -365,7 +365,7 @@ Bsp::Bsp(std::string fpath)
{
info.nFlags |= TEX_SPECIAL;
}
}
}*/

save_undo_lightmaps();
}
Expand Down Expand Up @@ -448,19 +448,6 @@ bool Bsp::get_model_vertex_bounds(int modelIdx, vec3& mins, vec3& maxs)
expandBoundingBox(s.pos, mins, maxs);
}

/*for (int i = 0; i < model.nFaces; i++)
{
BSPFACE32& face = faces[model.iFirstFace + i];

for (int e = 0; e < face.nEdges; e++)
{
int edgeIdx = surfedges[face.iFirstEdge + e];
BSPEDGE32& edge = edges[abs(edgeIdx)];
int vertIdx = edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0];

expandBoundingBox(verts[vertIdx], mins, maxs);
}
}*/
return true;
}

Expand All @@ -478,7 +465,7 @@ std::vector<int> Bsp::getModelVertsIds(int modelIdx)
{
int edgeIdx = surfedges[face.iFirstEdge + e];
BSPEDGE32& edge = edges[abs(edgeIdx)];
int vertIdx = edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0];
int vertIdx = edgeIdx > 0 ? edge.iVertex[0] : edge.iVertex[1];

if (!visited.count(vertIdx))
{
Expand All @@ -504,7 +491,7 @@ std::vector<TransformVert> Bsp::getModelTransformVerts(int modelIdx)
{
int edgeIdx = surfedges[face.iFirstEdge + e];
BSPEDGE32& edge = edges[abs(edgeIdx)];
int vertIdx = edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0];
int vertIdx = edgeIdx > 0 ? edge.iVertex[0] : edge.iVertex[1];

if (!visited.count(vertIdx))
{
Expand Down Expand Up @@ -614,7 +601,7 @@ bool Bsp::getModelPlaneIntersectVerts(int modelIdx, const std::vector<int>& node
{
int edgeIdx = surfedges[face.iFirstEdge + e];
BSPEDGE32& edge = edges[abs(edgeIdx)];
int vertIdx = edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0];
int vertIdx = edgeIdx > 0 ? edge.iVertex[0] : edge.iVertex[1];

if (verts[vertIdx] != v)
{
Expand Down Expand Up @@ -5373,7 +5360,7 @@ void Bsp::mark_face_structures(int iFace, STRUCTUSAGE* usage)
{
int edgeIdx = surfedges[face.iFirstEdge + e];
BSPEDGE32& edge = edges[abs(edgeIdx)];
int vertIdx = edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0];
int vertIdx = edgeIdx > 0 ? edge.iVertex[0] : edge.iVertex[1];

usage->surfEdges[face.iFirstEdge + e] = true;
usage->edges[abs(edgeIdx)] = true;
Expand Down Expand Up @@ -8669,7 +8656,7 @@ std::vector<vec3> Bsp::get_face_verts(int faceIdx, int limited)
{
int edgeIdx = surfedges[e];
BSPEDGE32& edge = edges[abs(edgeIdx)];
vec3 v = edgeIdx < 0 ? verts[edge.iVertex[1]] : verts[edge.iVertex[0]];
vec3 v = edgeIdx > 0 ? verts[edge.iVertex[0]] : verts[edge.iVertex[1]];
out.push_back(v);
limited--;
if (limited == 0)
Expand All @@ -8685,7 +8672,7 @@ std::vector<int> Bsp::get_face_verts_idx(int faceIdx, int limited)
{
int edgeIdx = surfedges[e];
BSPEDGE32& edge = edges[abs(edgeIdx)];
out.push_back(edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0]);
out.push_back(edgeIdx > 0 ? edge.iVertex[0] : edge.iVertex[1]);
limited--;
if (limited == 0)
break;
Expand Down Expand Up @@ -9004,7 +8991,7 @@ void Bsp::write_csg_polys(int nodeIdx, FILE* polyfile, int flipPlaneSkip, bool d
{
int edgeIdx = surfedges[e];
BSPEDGE32& edge = edges[abs(edgeIdx)];
vec3 v = edgeIdx < 0 ? verts[edge.iVertex[1]] : verts[edge.iVertex[0]];
vec3 v = edgeIdx > 0 ? verts[edge.iVertex[0]] : verts[edge.iVertex[1]];
fprintf(polyfile, "%5.8f %5.8f %5.8f\n", v.x, v.y, v.z);
}
}
Expand All @@ -9014,7 +9001,7 @@ void Bsp::write_csg_polys(int nodeIdx, FILE* polyfile, int flipPlaneSkip, bool d
{
int edgeIdx = surfedges[e];
BSPEDGE32& edge = edges[abs(edgeIdx)];
vec3 v = edgeIdx < 0 ? verts[edge.iVertex[1]] : verts[edge.iVertex[0]];
vec3 v = edgeIdx > 0 ? verts[edge.iVertex[0]] : verts[edge.iVertex[1]];
fprintf(polyfile, "%5.8f %5.8f %5.8f\n", v.x, v.y, v.z);
}
}
Expand Down Expand Up @@ -12273,16 +12260,16 @@ int Bsp::import_mdl_to_bspmodel(std::vector<StudioMesh>& meshes, mat4x4 angles,

BSPPLANE& plane = newplanes[newfaces[v].iPlane];

int vert_id1 = newsurfedges[edgeIdx + 0] < 0 ? newedges[abs(newsurfedges[edgeIdx + 0])].iVertex[1]
: newedges[abs(newsurfedges[edgeIdx + 0])].iVertex[0];
int vert_id1 = newsurfedges[edgeIdx + 0] > 0 ? newedges[abs(newsurfedges[edgeIdx + 0])].iVertex[0]
: newedges[abs(newsurfedges[edgeIdx + 0])].iVertex[1];
vec3 vertex1 = newverts[vert_id1];

int vert_id2 = newsurfedges[edgeIdx + 1] < 0 ? newedges[abs(newsurfedges[edgeIdx + 1])].iVertex[1]
: newedges[abs(newsurfedges[edgeIdx + 1])].iVertex[0];
int vert_id2 = newsurfedges[edgeIdx + 1] > 0 ? newedges[abs(newsurfedges[edgeIdx + 1])].iVertex[0]
: newedges[abs(newsurfedges[edgeIdx + 1])].iVertex[1];
vec3 vertex2 = newverts[vert_id2];

int vert_id3 = newsurfedges[edgeIdx + 2] < 0 ? newedges[abs(newsurfedges[edgeIdx + 2])].iVertex[1]
: newedges[abs(newsurfedges[edgeIdx + 2])].iVertex[0];
int vert_id3 = newsurfedges[edgeIdx + 2] > 0 ? newedges[abs(newsurfedges[edgeIdx + 2])].iVertex[0]
: newedges[abs(newsurfedges[edgeIdx + 2])].iVertex[1];
vec3 vertex3 = newverts[vert_id3];


Expand All @@ -12293,12 +12280,12 @@ int Bsp::import_mdl_to_bspmodel(std::vector<StudioMesh>& meshes, mat4x4 angles,

// Texture coordinates
std::vector<vec2> uvs{};
uvs.push_back(newsurfedges[edgeIdx + 0] < 0 ? newuv[newedges[abs(newsurfedges[edgeIdx + 0])].iVertex[1]]
: newuv[newedges[abs(newsurfedges[edgeIdx])].iVertex[0]]);
uvs.push_back(newsurfedges[edgeIdx + 1] < 0 ? newuv[newedges[abs(newsurfedges[edgeIdx + 1])].iVertex[1]]
: newuv[newedges[abs(newsurfedges[edgeIdx + 1])].iVertex[0]]);
uvs.push_back(newsurfedges[edgeIdx + 2] < 0 ? newuv[newedges[abs(newsurfedges[edgeIdx + 2])].iVertex[1]]
: newuv[newedges[abs(newsurfedges[edgeIdx + 2])].iVertex[0]]);
uvs.push_back(newsurfedges[edgeIdx + 0] > 0 ? newuv[newedges[abs(newsurfedges[edgeIdx + 0])].iVertex[0]]
: newuv[newedges[abs(newsurfedges[edgeIdx])].iVertex[1]]);
uvs.push_back(newsurfedges[edgeIdx + 1] > 0 ? newuv[newedges[abs(newsurfedges[edgeIdx + 1])].iVertex[0]]
: newuv[newedges[abs(newsurfedges[edgeIdx + 1])].iVertex[1]]);
uvs.push_back(newsurfedges[edgeIdx + 2] > 0 ? newuv[newedges[abs(newsurfedges[edgeIdx + 2])].iVertex[0]]
: newuv[newedges[abs(newsurfedges[edgeIdx + 2])].iVertex[1]]);

for (auto& uv : uvs)
{
Expand Down Expand Up @@ -12691,7 +12678,7 @@ bool Bsp::is_texture_with_pal(int textureid)
return is_texture_has_pal;
}

void Bsp::face_fix_duplicate_edges(int faceIdx)
void Bsp::face_fix_duplicate_edges_index(int faceIdx)
{
if (faceIdx < 0 || faceIdx >= faceCount)
{
Expand All @@ -12705,7 +12692,7 @@ void Bsp::face_fix_duplicate_edges(int faceIdx)
{
int edgeIdx = surfedges[e];
BSPEDGE32& edge = edges[abs(edgeIdx)];
int vert = edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0];
int vert = edgeIdx > 0 ? edge.iVertex[0] : edge.iVertex[1];;
if (verts_usage.count(vert))
{
int newedge_id = create_edge();
Expand Down Expand Up @@ -12750,7 +12737,7 @@ bool Bsp::is_face_duplicate_edges(int faceIdx)
{
int edgeIdx = surfedges[e];
BSPEDGE32 edge = edges[abs(edgeIdx)];
int vert = edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0];
int vert = edgeIdx > 0 ? edge.iVertex[0] : edge.iVertex[1];
if (verts_usage.count(vert))
{
return true;
Expand Down
2 changes: 1 addition & 1 deletion src/bsp/Bsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class Bsp

// face has duplicate verts, this is bad?
bool is_face_duplicate_edges(int faceIdx);
void face_fix_duplicate_edges(int faceIdx);
void face_fix_duplicate_edges_index(int faceIdx);

// get all verts used by this model
// TODO: split any verts shared with other models!
Expand Down
6 changes: 3 additions & 3 deletions src/editor/BspRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1099,7 +1099,7 @@ int BspRenderer::refreshModel(int modelIdx, bool refreshClipnodes, bool triangul
{
int edgeIdx = map->surfedges[face.iFirstEdge + e];
BSPEDGE32& edge = map->edges[abs(edgeIdx)];
int vertIdx = edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0];
int vertIdx = edgeIdx > 0 ? edge.iVertex[0] : edge.iVertex[1];

vec3 vert = map->verts[vertIdx];
verts[e].pos = vert.flip();
Expand Down Expand Up @@ -2128,7 +2128,7 @@ void BspRenderer::refreshFace(int faceIdx)
{
int edgeIdx = map->surfedges[face.iFirstEdge + e];
BSPEDGE32& edge = map->edges[abs(edgeIdx)];
int vertIdx = edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0];
int vertIdx = edgeIdx > 0 ? edge.iVertex[0] : edge.iVertex[1];
allVerts[e] = map->verts[vertIdx];

// 2 verts can share the same position on a face, so need to find one that isn't shared (aomdc_1intro)
Expand Down Expand Up @@ -3244,7 +3244,7 @@ bool BspRenderer::pickModelPoly(vec3 start, const vec3& dir, vec3 offset, int mo
{
int edgeIdx = map->surfedges[e];
BSPEDGE32 edge = map->edges[abs(edgeIdx)];
vec3& v = edgeIdx < 0 ? map->verts[edge.iVertex[1]] : map->verts[edge.iVertex[0]];
vec3& v = edgeIdx > 0 ? map->verts[edge.iVertex[0]] : map->verts[edge.iVertex[1]];
if (vectest != vec3() && vectest == v)
{
badface = true;
Expand Down
40 changes: 5 additions & 35 deletions src/editor/Gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3225,7 +3225,7 @@ void Gui::drawMenuBar()
{
int edgeIdx = map->surfedges[face.iFirstEdge + e];
BSPEDGE32& edge = map->edges[abs(edgeIdx)];
int vertIdx = edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0];
int vertIdx = edgeIdx > 0 ? edge.iVertex[0] : edge.iVertex[1];
expandBoundingBox(map->verts[vertIdx], mins, maxs);
}
}
Expand Down Expand Up @@ -3326,7 +3326,7 @@ void Gui::drawMenuBar()
{
int edgeIdx = map->surfedges[face.iFirstEdge + e];
BSPEDGE32& edge = map->edges[abs(edgeIdx)];
int vertIdx = edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0];
int vertIdx = edgeIdx > 0 ? edge.iVertex[0] : edge.iVertex[1];
expandBoundingBox(map->verts[vertIdx], model_mins, model_maxs);
}
}
Expand Down Expand Up @@ -11394,7 +11394,7 @@ void Gui::drawFaceEditorWidget()
{
int edgeIdx = map->surfedges[e];
BSPEDGE32 edge = map->edges[abs(edgeIdx)];
vec3 v = edgeIdx < 0 ? map->verts[edge.iVertex[1]] : map->verts[edge.iVertex[0]];
vec3 v = edgeIdx > 0 ? map->verts[edge.iVertex[0]] : map->verts[edge.iVertex[1]];
edgeVerts.push_back(v);
}
}
Expand Down Expand Up @@ -11518,7 +11518,7 @@ void Gui::drawFaceEditorWidget()
int edgeIdx = map->surfedges[e];
BSPEDGE32 edge = map->edges[abs(edgeIdx)];

vec3& vec = edgeIdx < 0 ? map->verts[edge.iVertex[1]] : map->verts[edge.iVertex[0]];
vec3& vec = edgeIdx > 0 ? map->verts[edge.iVertex[0]] : map->verts[edge.iVertex[1]];

for (int v = 0; v < map->vertCount; v++)
{
Expand Down Expand Up @@ -11655,36 +11655,6 @@ void Gui::drawFaceEditorWidget()
}
ImGui::SetClipboardText(outstr.c_str());
}

//if (ImGui::Button("Optimize"))
//{
// auto edge_copy_verts = edgeVerts;
// removeColinearPoints(edge_copy_verts, EPSILON);

// bool swap_need = false;
// for (int e = face.iFirstEdge, v = 0; e < face.iFirstEdge + face.nEdges && v < (int)edge_copy_verts.size(); e++, v++)
// {
// int edge_id = map->surfedges[e];
// BSPEDGE32 edge = map->edges[abs(edge_id)];
// vec3 vert = edge_id >= 0 ? map->verts[edge.iVertex[1]] : map->verts[edge.iVertex[0]];
// if (vert == edge_copy_verts[v]) continue; // already in
//
// for (int z = e; z < face.iFirstEdge + face.nEdges - 1; z++)
// {
// map->surfedges[z] = map->surfedges[z + 1];
// }

// e--;
// v--;
// face.nEdges--;
// }

// face.nEdges = (int)edge_copy_verts.size();

// edgeVerts = edge_copy_verts;

// updatedFaceVec = true;
//}
}

ImGui::PopItemWidth();
Expand Down Expand Up @@ -11848,7 +11818,7 @@ void Gui::drawFaceEditorWidget()
{
int edgeIdx = map->surfedges[e];
BSPEDGE32 edge = map->edges[abs(edgeIdx)];
vec3& v = edgeIdx < 0 ? map->verts[edge.iVertex[1]] : map->verts[edge.iVertex[0]];
vec3& v = edgeIdx > 0 ? map->verts[edge.iVertex[0]] : map->verts[edge.iVertex[1]];
v = edgeVerts[vecId];
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/editor/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4133,7 +4133,7 @@ void Renderer::goToFace(Bsp* map, int faceIdx)
{
int edgeIdx = map->surfedges[face.iFirstEdge + i];
BSPEDGE32& edge = map->edges[abs(edgeIdx)];
int vertIdx = edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0];
int vertIdx = edgeIdx > 0 ? edge.iVertex[0] : edge.iVertex[1];
edgeVerts.push_back(map->verts[vertIdx]);
}

Expand Down
2 changes: 1 addition & 1 deletion src/qtools/rad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ bool CanFindFacePosition(Bsp* bsp, int facenum, int imins[2], int imaxs[2])

if (!facewinding.m_Points.size())
{
print_log(PRINT_RED, "CanFindFacePosition error facewinding face {} [facewind size {}]!\n", facenum, facewinding.m_Points.size());
print_log(PRINT_RED, "CanFindFacePosition error face {} [facewind size {} verts {}]!\n", facenum, facewinding.m_Points.size(), bsp->get_face_verts(facenum).size());
imins[0] = imins[1] = imaxs[0] = imaxs[1] = 1;
return false;
}
Expand Down
32 changes: 17 additions & 15 deletions src/qtools/winding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ Winding::Winding(Bsp* bsp, const BSPFACE32& face, float epsilon)
int edgeIdx = bsp->surfedges[face.iFirstEdge + e];
BSPEDGE32& edge = bsp->edges[abs(edgeIdx)];

int v = edgeIdx < 0 ? edge.iVertex[1] : edge.iVertex[0];
int v = edgeIdx > 0 ? edge.iVertex[0] : edge.iVertex[1];
m_Points[e] = bsp->verts[v];
}

Expand All @@ -144,27 +144,29 @@ void Winding::MergeVerts(Bsp* src, float epsilon)
// Remove the colinear point of any three points that forms a triangle which is thinner than ON_EPSILON
void Winding::RemoveColinearPoints(float epsilon)
{
int NumPoints = (int)m_Points.size();
size_t NumPoints = m_Points.size();

for (int i = 0; i < NumPoints; i++) {

if (NumPoints <= 3) {
break;
}

for (int i = 0; i < NumPoints; i++)
{
vec3 p1 = m_Points[(i + NumPoints - 1) % NumPoints];
vec3 p2 = m_Points[i];
vec3 p3 = m_Points[(i + 1) % NumPoints];
vec3 v1 = p2 - p1;
vec3 v2 = p3 - p2;
// v1 or v2 might be close to 0
if (dotProduct(v1, v2) * dotProduct(v1, v2) >= dotProduct(v1, v1) * dotProduct(v2, v2)
- epsilon * epsilon * (dotProduct(v1, v1) + dotProduct(v2, v2) + epsilon * epsilon))
// v2 == k * v1 + v3 && abs (v3) < ON_EPSILON || v1 == k * v2 + v3 && abs (v3) < ON_EPSILON
{

// Normalize vectors
v1.normalize();
v2.normalize();

// Check if vectors are collinear
if (abs(dotProduct(v1, v2) - 1.0) < epsilon) {
m_Points.erase(m_Points.begin() + i);
NumPoints--;
for (; i < NumPoints; i++)
{
m_Points[i] = m_Points[i + 1];
}
i = -1;
continue;
i = -1; // Restart the loop to handle updated points list
}
}

Expand Down

0 comments on commit 35dc184

Please sign in to comment.