- He fet una cosa que m'ha dit copailot, pero no ha valgut pa res. Ja ho miraré en calma

This commit is contained in:
2026-02-27 19:21:22 +01:00
parent 943b79d9bb
commit 58c9d2a2de

146
main.cpp
View File

@@ -7,6 +7,10 @@
#include "wad.h" #include "wad.h"
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <vector>
#include <unordered_map>
#include <stdexcept>
#include <algorithm>
#define FOV 277 #define FOV 277
@@ -66,6 +70,144 @@ struct sidedef {
}; };
#pragma pack(pop) #pragma pack(pop)
// ------------------------------------------------------------
// Área firmada de un contorno
// ------------------------------------------------------------
float signed_area(const std::vector<wall>& contour,
const std::vector<vec2>& 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<std::vector<wall>>
extract_contours(std::vector<wall> walls)
{
std::vector<std::vector<wall>> contours;
std::unordered_multimap<int,int> startMap;
for (int i = 0; i < (int)walls.size(); i++)
startMap.emplace(walls[i].v1, i);
std::vector<bool> used(walls.size(), false);
for (int i = 0; i < (int)walls.size(); i++) {
if (used[i]) continue;
std::vector<wall> 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<wall> walls;
float area;
};
std::vector<ContourInfo> 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) void loadMap(const char* name)
{ {
int size; int size;
@@ -141,6 +283,8 @@ void loadMap(const char* name)
for (auto &s : sectors ) for (auto &s : sectors )
{ {
order_sector_walls_with_holes(s);
for (auto &w : s.walls ) 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; 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); wall_end = SDL_min(wall_end, end);
//SDL_assert(&s != &sectors[w->portal]); //SDL_assert(&s != &sectors[w->portal]);
printf("Anem al sector: %i\n", w->portal); //printf("Anem al sector: %i\n", w->portal);
//SDL_assert(w->portal != last_sector); //SDL_assert(w->portal != last_sector);
last_sector = actual_sector; last_sector = actual_sector;
actual_sector = w->portal; actual_sector = w->portal;