Map gen mostly works now :D

This commit is contained in:
KP 2024-07-24 00:50:42 -05:00
parent 5a13579849
commit 0b41057244
4 changed files with 130 additions and 121 deletions

View file

@ -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...

View file

@ -251,7 +251,7 @@ bool clip2tri::triangulateComplex(vector<Point> &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

View file

@ -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<Vertex3D>& 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 = &sector;
}
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<c2t::Point> 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<std::vector<Vec2>> polygons = ClipPolygonHoles(flat_polygons, subsector_polygons);
//for (const std::vector<Vec2>& 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<c2t::Point> 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<c2t::Point> 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<c2t::Point> 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<Vec2> 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)

View file

@ -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))