From 58c9d2a2dee826adbe7cc493647ead7e16bebd7f Mon Sep 17 00:00:00 2001 From: Raimon Zamora Date: Fri, 27 Feb 2026 19:21:22 +0100 Subject: [PATCH] =?UTF-8?q?-=20He=20fet=20una=20cosa=20que=20m'ha=20dit=20?= =?UTF-8?q?copailot,=20pero=20no=20ha=20valgut=20pa=20res.=20Ja=20ho=20mir?= =?UTF-8?q?ar=C3=A9=20en=20calma?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.cpp | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 145 insertions(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index a1d808a..58da1fe 100644 --- a/main.cpp +++ b/main.cpp @@ -7,6 +7,10 @@ #include "wad.h" #include #include +#include +#include +#include +#include #define FOV 277 @@ -66,6 +70,144 @@ struct sidedef { }; #pragma pack(pop) +// ------------------------------------------------------------ +// Área firmada de un contorno +// ------------------------------------------------------------ +float signed_area(const std::vector& contour, + const std::vector& verts) +{ + float area = 0.0f; + + for (size_t i = 0; i < contour.size(); i++) { + int a = contour[i].v1; + int b = contour[i].v2; + + const vec2& p = verts[a]; + const vec2& q = verts[b]; + + area += (p.x * q.y - q.x * p.y); + } + + return area * 0.5f; +} + +// ------------------------------------------------------------ +// Extrae todos los contornos (ciclos) del sector +// ------------------------------------------------------------ +std::vector> +extract_contours(std::vector walls) +{ + std::vector> contours; + std::unordered_multimap startMap; + + for (int i = 0; i < (int)walls.size(); i++) + startMap.emplace(walls[i].v1, i); + + std::vector used(walls.size(), false); + + for (int i = 0; i < (int)walls.size(); i++) { + if (used[i]) continue; + + std::vector contour; + int current = i; + + contour.push_back(walls[current]); + used[current] = true; + + int v = walls[current].v2; + + while (true) { + auto range = startMap.equal_range(v); + int next = -1; + + for (auto it = range.first; it != range.second; ++it) { + int idx = it->second; + if (!used[idx]) { + next = idx; + break; + } + } + + if (next == -1) + break; // ciclo cerrado + + contour.push_back(walls[next]); + used[next] = true; + v = walls[next].v2; + } + + contours.push_back(contour); + } + + return contours; +} + +// ------------------------------------------------------------ +// Ordena y fuerza sentido horario en contorno exterior +// ------------------------------------------------------------ +void order_sector_walls_with_holes(sector& sector) +{ + if (sector.walls.empty()) return; + + // 1. Extraer contornos + auto contours = extract_contours(sector.walls); + + // 2. Clasificar contornos por área + struct ContourInfo { + std::vector walls; + float area; + }; + + std::vector info; + info.reserve(contours.size()); + + for (auto& c : contours) { + float a = signed_area(c, verts); + info.push_back({c, a}); + } + + // 3. Encontrar el contorno exterior (el de mayor área absoluta) + int exteriorIndex = 0; + float maxAbsArea = std::abs(info[0].area); + + for (int i = 1; i < (int)info.size(); i++) { + float absA = std::abs(info[i].area); + if (absA > maxAbsArea) { + maxAbsArea = absA; + exteriorIndex = i; + } + } + + // 4. Forzar sentido horario en el contorno exterior + if (info[exteriorIndex].area < 0.0f) { + std::reverse(info[exteriorIndex].walls.begin(), + info[exteriorIndex].walls.end()); + for (auto& w : info[exteriorIndex].walls) + std::swap(w.v1, w.v2); + } + + // 5. Mantener agujeros en antihorario (o invertir si tu motor lo exige) + for (int i = 0; i < (int)info.size(); i++) { + if (i == exteriorIndex) continue; + + // Si quieres agujeros en horario, descomenta: + /* + if (info[i].area < 0.0f) { + std::reverse(info[i].walls.begin(), info[i].walls.end()); + for (auto& w : info[i].walls) + std::swap(w.v1, w.v2); + } + */ + } + + // 6. Reconstruir la lista final de paredes + sector.walls.clear(); + for (auto& c : info) + for (auto& w : c.walls) + sector.walls.push_back(w); +} + + void loadMap(const char* name) { int size; @@ -141,6 +283,8 @@ void loadMap(const char* name) for (auto &s : sectors ) { + order_sector_walls_with_holes(s); + for (auto &w : s.walls ) { const int width = w.surf ? w.surf->w : w.upper_surf ? w.upper_surf->w : w.lower_surf ? w.lower_surf->w : 64; @@ -324,7 +468,7 @@ void drawColumn(sector &s, int screen_column, int start, int end, float a_inc, v wall_end = SDL_min(wall_end, end); //SDL_assert(&s != §ors[w->portal]); - printf("Anem al sector: %i\n", w->portal); + //printf("Anem al sector: %i\n", w->portal); //SDL_assert(w->portal != last_sector); last_sector = actual_sector; actual_sector = w->portal;