From 0b41057244a3b11f8dee0d6802b720320bb4dd54 Mon Sep 17 00:00:00 2001 From: KP Date: Wed, 24 Jul 2024 00:50:42 -0500 Subject: [PATCH] Map gen mostly works now :D --- Data/sandbox-log.txt | 59 ++------- KP3Dii/ext/src/clip2tri/clip2tri.cpp | 2 +- KP3Dii/src/KP3D_Map.cpp | 189 +++++++++++++++++---------- Sandbox/src/Sandbox.cpp | 1 + 4 files changed, 130 insertions(+), 121 deletions(-) diff --git a/Data/sandbox-log.txt b/Data/sandbox-log.txt index 374216d..4129b5f 100644 --- a/Data/sandbox-log.txt +++ b/Data/sandbox-log.txt @@ -1,56 +1,15 @@ -[00:07:49 AM] Info: Starting... +[00:48:43 AM] Info: Starting... KP3D version 2 =============================== Copyright (C) kpworld.xyz 2018-2024 Contact me! @kp_cftsz -[00:07:49 AM] Info: Initializing SDL -[00:07:49 AM] Info: Initializing OpenGL -[00:07:49 AM] Info: OpenGL version: 4.6.0 NVIDIA 536.23 -[00:07:49 AM] Info: Initializing GLEW -[00:07:49 AM] Info: Initializing SDL_mixer -[00:07:49 AM] Info: Reticulating splines... -[00:07:49 AM] Info: Ready! -[00:07:49 AM] Info: SECTOR HIERARCHY -[00:07:49 AM] Info: Sector 3 (area: 1) -[00:07:49 AM] Info: Parent: -[00:07:49 AM] Info: - 1 -[00:07:49 AM] Info: Children: -[00:07:49 AM] Info: - [NO CHILDREN] -[00:07:49 AM] Info: ----- -[00:07:49 AM] Info: Sector 4 (area: 1) -[00:07:49 AM] Info: Parent: -[00:07:49 AM] Info: - 2 -[00:07:49 AM] Info: Children: -[00:07:49 AM] Info: - [NO CHILDREN] -[00:07:49 AM] Info: ----- -[00:07:49 AM] Info: Sector 2 (area: 19) -[00:07:49 AM] Info: Parent: -[00:07:49 AM] Info: - 1 -[00:07:49 AM] Info: Children: -[00:07:49 AM] Info: - 4 -[00:07:49 AM] Info: ----- -[00:07:49 AM] Info: Sector 5 (area: 34) -[00:07:49 AM] Info: Parent: -[00:07:49 AM] Info: - [NO PARENT] -[00:07:49 AM] Info: Children: -[00:07:49 AM] Info: - [NO CHILDREN] -[00:07:49 AM] Info: ----- -[00:07:49 AM] Info: Sector 1 (area: 105.5) -[00:07:49 AM] Info: Parent: -[00:07:49 AM] Info: - [NO PARENT] -[00:07:49 AM] Info: Children: -[00:07:49 AM] Info: - 3 -[00:07:49 AM] Info: - 2 -[00:07:49 AM] Info: ----- -[00:07:49 AM] Info: TRIANGULATING SECTOR: 3 -[00:07:49 AM] Info: TRIANGULATING SECTOR: 3 -[00:07:49 AM] Info: TRIANGULATING SECTOR: 4 -[00:07:49 AM] Info: TRIANGULATING SECTOR: 4 -[00:07:49 AM] Info: TRIANGULATING SECTOR: 2 -[00:07:49 AM] Info: TRIANGULATING SECTOR: 2 -[00:07:49 AM] Info: TRIANGULATING SECTOR: 5 -[00:07:49 AM] Info: TRIANGULATING SECTOR: 5 -[00:07:49 AM] Info: TRIANGULATING SECTOR: 1 -[00:07:49 AM] Info: TRIANGULATING SECTOR: 1 +[00:48:43 AM] Info: Initializing SDL +[00:48:43 AM] Info: Initializing OpenGL +[00:48:43 AM] Info: OpenGL version: 4.6.0 NVIDIA 536.23 +[00:48:43 AM] Info: Initializing GLEW +[00:48:43 AM] Info: Initializing SDL_mixer +[00:48:43 AM] Info: Reticulating splines... +[00:48:43 AM] Info: Ready! +[00:50:29 AM] Info: Stopping... diff --git a/KP3Dii/ext/src/clip2tri/clip2tri.cpp b/KP3Dii/ext/src/clip2tri/clip2tri.cpp index c2aadf2..dfaf561 100644 --- a/KP3Dii/ext/src/clip2tri/clip2tri.cpp +++ b/KP3Dii/ext/src/clip2tri/clip2tri.cpp @@ -251,7 +251,7 @@ bool clip2tri::triangulateComplex(vector &outputTriangles, const Path &ou F64(S64(steiner_points->at(j).x * CLIPPER_SCALE_FACT)), F64(S64(steiner_points->at(j).y * CLIPPER_SCALE_FACT)), }); - //cdt->AddPoint(steiners[j]); + cdt->AddPoint(steiners[j]); } } // end: steiner points diff --git a/KP3Dii/src/KP3D_Map.cpp b/KP3Dii/src/KP3D_Map.cpp index f4f1429..cf83e88 100644 --- a/KP3Dii/src/KP3D_Map.cpp +++ b/KP3Dii/src/KP3D_Map.cpp @@ -56,6 +56,56 @@ bool SectorContains(const kp3d::Sector& outer, const kp3d::Sector& inner) { return completely_inside || (count > 0 && partial_count < 4); } +using namespace kp3d; + +// Function to find the barycentric coordinates of a point within a triangle +void Barycentric(const Vec2& p, const Vec2& a, const Vec2& b, const Vec2& c, float& u, float& v, float& w) { + Vec2 v0 = { b.x - a.x, b.y - a.y }; + Vec2 v1 = { c.x - a.x, c.y - a.y }; + Vec2 v2 = { p.x - a.x, p.y - a.y }; + float d00 = v0.x * v0.x + v0.y * v0.y; + float d01 = v0.x * v1.x + v0.y * v1.y; + float d11 = v1.x * v1.x + v1.y * v1.y; + float d20 = v2.x * v0.x + v2.y * v0.y; + float d21 = v2.x * v1.x + v2.y * v1.y; + float denom = d00 * d11 - d01 * d01; + v = (d11 * d20 - d01 * d21) / denom; + w = (d00 * d21 - d01 * d20) / denom; + u = 1.0f - v - w; +} + +// Function to interpolate Y value +float InterpolateY(const Vec2& p, const Vertex3D& a, const Vertex3D& b, const Vertex3D& c) { + float u, v, w; + Vec2 pa = { a.position.x, a.position.z }; + Vec2 pb = { b.position.x, b.position.z }; + Vec2 pc = { c.position.x, c.position.z }; + Barycentric(p, pa, pb, pc, u, v, w); + return u * a.position.y + v * b.position.y + w * c.position.y; +} + +// Sample floor vertices +float SampleY(const std::vector& floor_vertices, const Vec2& sample_pos) { + for (size_t i = 0; i < floor_vertices.size(); i += 3) { + const Vertex3D& v0 = floor_vertices[i]; + const Vertex3D& v1 = floor_vertices[i + 1]; + const Vertex3D& v2 = floor_vertices[i + 2]; + + Vec2 pa = { v0.position.x, v0.position.z }; + Vec2 pb = { v1.position.x, v1.position.z }; + Vec2 pc = { v2.position.x, v2.position.z }; + + // Check if the sample position is inside the triangle + float u, v, w; + Barycentric(sample_pos, pa, pb, pc, u, v, w); + if (u >= 0 && v >= 0 && w >= 0) { + return InterpolateY(sample_pos, v0, v1, v2); + } + } + return 0.0f; // Default value if the point is not found in any triangle (should not happen if inputs are correct) +} + + } namespace kp3d { @@ -105,7 +155,6 @@ void Map::BuildFlat(Sector& sector, Flat& flat, bool invert) s->floor.texture = nullptr; if (FloatCmp(s->ceiling.base_height, sector.ceiling.base_height, e)) s->ceiling.texture = nullptr; - //continue; } else { @@ -114,83 +163,68 @@ void Map::BuildFlat(Sector& sector, Flat& flat, bool invert) l.portal = §or; } ss.push_back({l.start.x, l.start.y}); - - area += l.start.x * l.end.y; - area -= l.end.x * l.start.y; } - //if (area > 0)//<= 0.0f) - // std::reverse(ss.begin(), ss.end()); - - subsector_polygons.push_back(ss); + if (!s->inverted) + subsector_polygons.push_back(ss); } std::vector flat_polygons; for (Wall& l: sector.walls) flat_polygons.emplace_back(l.start.x, l.start.y); - KP3D_LOG_INFO("TRIANGULATING SECTOR: {}", sector.id); - //std::vector> polygons = ClipPolygonHoles(flat_polygons, subsector_polygons); - //for (const std::vector& polygon: polygons) - //const auto& polygon = polygons[1 % polygons.size()]; + + // Triangulate the sector floors and ceilings and send the result to the mesh. To do this we're using version of the Clipper + // library merged with poly2tri, called clip2tri, which I've since modified to support Steiner points. + c2t::clip2tri clipper; + std::vector clipper_out; + clipper.triangulate(subsector_polygons, clipper_out, flat_polygons, &steiner_points); + + const float MAX = 1000000.0f; + float min_height = MAX; + float max_height = -MAX; + + for (int i = 0; i < clipper_out.size(); i += 3) { + c2t::Point a = clipper_out.at(i + 0); + c2t::Point b = clipper_out.at(i + 1); + c2t::Point c = clipper_out.at(i + 2); - //std::vector sector_polygons; - //for (const Vec2& l: sector.walls) - // sector_polygons.push_back({l.x, l.y}); + float au = a.x * 0.5f, av = a.y * 0.5f; + float bu = b.x * 0.5f, bv = b.y * 0.5f; + float cu = c.x * 0.5f, cv = c.y * 0.5f; - // Triangulate the sector floors and ceilings and send the result to the mesh. To do this we're using version of the Clipper - // library merged with poly2tri, called clip2tri, which I've since modified to support Steiner points. - c2t::clip2tri clipper; - std::vector clipper_out; - clipper.triangulate(subsector_polygons, clipper_out, flat_polygons, &steiner_points); + // Build mesh data for floor + Vec3 fva = Vec3(a.x, flat.base_height, a.y); + Vec3 fvb = Vec3(b.x, flat.base_height, b.y); + Vec3 fvc = Vec3(c.x, flat.base_height, c.y); - const float MAX = 1000000.0f; - float min_height = MAX; - float max_height = -MAX; - - for (int i = 0; i < clipper_out.size(); i += 3) + for (const Vec3& steiner : flat.steiner_points) { - c2t::Point a = clipper_out.at(i + 0); - c2t::Point b = clipper_out.at(i + 1); - c2t::Point c = clipper_out.at(i + 2); - - float au = a.x * 0.5f, av = a.y * 0.5f; - float bu = b.x * 0.5f, bv = b.y * 0.5f; - float cu = c.x * 0.5f, cv = c.y * 0.5f; - - // Build mesh data for floor - Vec3 fva = Vec3(a.x, flat.base_height, a.y); - Vec3 fvb = Vec3(b.x, flat.base_height, b.y); - Vec3 fvc = Vec3(c.x, flat.base_height, c.y); - - for (const Vec3& steiner : flat.steiner_points) - { - if (FloatCmp(fva.x, steiner.x, e) && FloatCmp(fva.z, steiner.z, e)) fva.y += steiner.y; - if (FloatCmp(fvb.x, steiner.x, e) && FloatCmp(fvb.z, steiner.z, e)) fvb.y += steiner.y; - if (FloatCmp(fvc.x, steiner.x, e) && FloatCmp(fvc.z, steiner.z, e)) fvc.y += steiner.y; - } - - if (fva.y < min_height) min_height = fva.y; - if (fvb.y < min_height) min_height = fvb.y; - if (fvc.y < min_height) min_height = fvc.y; - if (fva.y > max_height) max_height = fva.y; - if (fvb.y > max_height) max_height = fvb.y; - if (fvc.y > max_height) max_height = fvc.y; - if (FloatCmp(min_height, MAX)) min_height = flat.base_height; - if (FloatCmp(max_height, -MAX)) max_height = flat.base_height; - - // Fix up the UVs so they keep the right scale - float tw = flat.texture ? texture_scale / flat.texture->GetWidth() : 0.0f; - float th = flat.texture ? texture_scale / flat.texture->GetHeight() : 0.0f; - Vertex3D vtxa = Vertex3D(fva, Vec2(au * tw, av * th)); - Vertex3D vtxb = Vertex3D(fvb, Vec2(bu * tw, bv * th)); - Vertex3D vtxc = Vertex3D(fvc, Vec2(cu * tw, cv * th)); - flat.triangulated_data.push_back(vtxa); - flat.triangulated_data.push_back(vtxb); - flat.triangulated_data.push_back(vtxc); - if (flat.texture) - m_mesh.AddBatch(flat.texture, { vtxa, vtxb, vtxc }, !invert); + if (FloatCmp(fva.x, steiner.x, e) && FloatCmp(fva.z, steiner.z, e)) fva.y += steiner.y; + if (FloatCmp(fvb.x, steiner.x, e) && FloatCmp(fvb.z, steiner.z, e)) fvb.y += steiner.y; + if (FloatCmp(fvc.x, steiner.x, e) && FloatCmp(fvc.z, steiner.z, e)) fvc.y += steiner.y; } + + if (fva.y < min_height) min_height = fva.y; + if (fvb.y < min_height) min_height = fvb.y; + if (fvc.y < min_height) min_height = fvc.y; + if (fva.y > max_height) max_height = fva.y; + if (fvb.y > max_height) max_height = fvb.y; + if (fvc.y > max_height) max_height = fvc.y; + if (FloatCmp(min_height, MAX)) min_height = flat.base_height; + if (FloatCmp(max_height, -MAX)) max_height = flat.base_height; + + // Fix up the UVs so they keep the right scale + float tw = flat.texture ? texture_scale / flat.texture->GetWidth() : 0.0f; + float th = flat.texture ? texture_scale / flat.texture->GetHeight() : 0.0f; + Vertex3D vtxa = Vertex3D(fva, Vec2(au * tw, av * th)); + Vertex3D vtxb = Vertex3D(fvb, Vec2(bu * tw, bv * th)); + Vertex3D vtxc = Vertex3D(fvc, Vec2(cu * tw, cv * th)); + flat.triangulated_data.push_back(vtxa); + flat.triangulated_data.push_back(vtxb); + flat.triangulated_data.push_back(vtxc); + if (flat.texture) + m_mesh.AddBatch(flat.texture, { vtxa, vtxb, vtxc }, !invert); } } @@ -216,6 +250,9 @@ void Map::BuildQuad(Sector& sector, Flat& flat_top, Flat& flat_bottom, const Tex Vec2 mpos = {Distance({v.position.x, v.position.z}, {pos_a.x, pos_a.z}), v.position.y}; points.push_back(mpos); } + if (!points.empty()) + if (!FloatCmp(points.back().x, Distance({ pos_a.x, pos_a.y }, {pos_b.x, pos_b.y}))) + points.push_back({ Distance({ pos_a.x, pos_a.y }, {pos_b.x, pos_b.y}), flat_bottom.base_height}); std::vector top_points; for (const Vertex3D& v: flat_top.triangulated_data) { @@ -224,6 +261,11 @@ void Map::BuildQuad(Sector& sector, Flat& flat_top, Flat& flat_bottom, const Tex Vec2 mpos = {Distance({v.position.x, v.position.z}, {pos_a.x, pos_a.z}), v.position.y}; top_points.push_back(mpos); } + if (!top_points.empty()) + if (!FloatCmp(top_points.back().x, 0.0f)) + top_points.push_back({ 0.0f, flat_top.base_height }); + // if (top_points.empty()) + // top_points.push_back({Distance({pos_a.x, pos_a.z}, {pos_b.x, pos_b.z}), flat_top.base_height}); std::sort(points.begin(), points.end(), [&](Vec2 a, Vec2 b) { return a.x < b.x; }); std::sort(top_points.begin(), top_points.end(), [&](Vec2 a, Vec2 b) { return a.x > b.x; }); points.insert(points.end(), top_points.begin(), top_points.end()); @@ -303,6 +345,7 @@ void Map::JoinSectors(Sector& sector) float yb = s.floor.base_height; float yt = s.ceiling.base_height; + bool not_child = s.parent_id != sector.id; for (Wall& l : s.walls) { @@ -311,9 +354,8 @@ void Map::JoinSectors(Sector& sector) !PosCmp({l.start.x, 0.0f, l.start.y}, {pos_a.x, 0.0f, pos_a.z}) && !PosCmp({l.start.x, 0.0f, l.start.y}, {pos_b.x, 0.0f, pos_b.z}) && !PosCmp({l.end.x, 0.0f, l.end.y}, {pos_b.x, 0.0f, pos_b.z}) && - !PosCmp({l.end.x, 0.0f, l.end.y}, {pos_a.x, 0.0f, pos_a.z})) + !PosCmp({l.end.x, 0.0f, l.end.y}, {pos_a.x, 0.0f, pos_a.z}) && not_child) { - //KP3D_LOG_INFO("{} IS TOUCHING: {}", sector.id, s.id); XYf old_end = ld.end; ld.end.x = l.end.x; ld.end.y = l.end.y; @@ -379,6 +421,10 @@ void Map::Init() {11,4},{14,4},{14,2},{16,2},{16,10},{11,10} // Neighbor of main sector }; + XYf points6[] = { + {1, 4},{3,4}, { 3,7 },{1,7} + }; + BuildSkybox("skybox_16.jpg"); static kp3d::Texture tex, tex2, tex3, tex4; @@ -411,10 +457,12 @@ void Map::Init() build_sector(&tex3, &tex, &tex2, -1.0f, 5.0f, 1, points, std::size(points)); build_sector(&tex4, &tex2, &tex2, -1.5f, 4.0f, 2, points2, std::size(points2)); - build_sector(&tex4, &tex, &tex2, -1.5f, 4.0f, 3, points3, std::size(points3), true); - build_sector(&tex4, &tex, &tex2, -1.0f, 4.0f, 4, points4, std::size(points4), true); + build_sector(&tex4, &tex, &tex2, -1.5f, 5.0f, 3, points3, std::size(points3), true); + build_sector(&tex4, &tex, &tex2, -1.5f, 4.0f, 4, points4, std::size(points4), true); //build_sector(&tex3, &tex, &tex2, -1.2f, 3.0f, 5, points5, std::size(points5)); build_sector(&tex3, &tex, &tex2, test_u, test_l, 5, points5, std::size(points5), false); + build_sector(&tex4, &tex4, &tex4, 1.0f, 1.4f, 6, points6, std::size(points6), true); + // Correct sectors with counter-clockwise linedef order using the shoelace formula, // also while we're at it grab the sector areas (will be useful later) and reset old data. @@ -473,7 +521,7 @@ void Map::Init() } } - +#if 0 KP3D_LOG_INFO("SECTOR HIERARCHY"); for (Sector& s: sectors) { @@ -490,6 +538,7 @@ void Map::Init() KP3D_LOG_INFO(" - [NO CHILDREN]"); KP3D_LOG_INFO("-----"); } +#endif // Preproc for (Sector& s: sectors) diff --git a/Sandbox/src/Sandbox.cpp b/Sandbox/src/Sandbox.cpp index 5fbca99..30f59c0 100644 --- a/Sandbox/src/Sandbox.cpp +++ b/Sandbox/src/Sandbox.cpp @@ -37,6 +37,7 @@ void Sandbox::Update() if (IsKeyDown(kp3d::KEY_GRAVE)) { kp3d::console::open ^= 1; + SetMouseLockEnabled(!GetMouseLockEnabled()); KeyReset(kp3d::KEY_GRAVE); } if (IsKeyDown(kp3d::KEY_F1))