- 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:
146
main.cpp
146
main.cpp
@@ -7,6 +7,10 @@
|
||||
#include "wad.h"
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
#define FOV 277
|
||||
|
||||
@@ -66,6 +70,144 @@ struct sidedef {
|
||||
};
|
||||
#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)
|
||||
{
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user