It's slightly more stable
This commit is contained in:
parent
2f6a6fcbfe
commit
1de17327c0
4 changed files with 1010 additions and 983 deletions
1885
Data/sandbox-log.txt
1885
Data/sandbox-log.txt
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,14 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool SectorContains(const kp3d::Sector& outer, const kp3d::Sector& inner)
|
struct SectorContainmentStatus
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
int partial_count;
|
||||||
|
bool completely_inside;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool SectorContains(const kp3d::Sector& outer, const kp3d::Sector& inner, SectorContainmentStatus* output = nullptr)
|
||||||
{
|
{
|
||||||
using namespace Clipper2Lib;
|
using namespace Clipper2Lib;
|
||||||
using namespace kp3d;
|
using namespace kp3d;
|
||||||
|
@ -45,6 +52,13 @@ bool SectorContains(const kp3d::Sector& outer, const kp3d::Sector& inner)
|
||||||
if (partial_count > 0 && count > 0)
|
if (partial_count > 0 && count > 0)
|
||||||
partially_inside = true;
|
partially_inside = true;
|
||||||
|
|
||||||
|
if (output)
|
||||||
|
{
|
||||||
|
output->count = count;
|
||||||
|
output->partial_count = partial_count;
|
||||||
|
output->completely_inside = completely_inside;
|
||||||
|
}
|
||||||
|
|
||||||
return completely_inside;// || (count > 0 && partial_count < 4); // stupid
|
return completely_inside;// || (count > 0 && partial_count < 4); // stupid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,10 +143,8 @@ void Map::BuildFlat(Sector& sector, Flat& flat, bool invert)
|
||||||
//s->floor.steiner_points.push_back({ l.start.x, s->floor.base_height, l.start.y });
|
//s->floor.steiner_points.push_back({ l.start.x, s->floor.base_height, l.start.y });
|
||||||
//s->ceiling.steiner_points.push_back({ l.start.x, s->ceiling.base_height, l.start.y });
|
//s->ceiling.steiner_points.push_back({ l.start.x, s->ceiling.base_height, l.start.y });
|
||||||
}
|
}
|
||||||
if (l.flags & Wall::FLAG_SUBSECTOR_OPENING)
|
//if (l.flags & Wall::FLAG_SUBSECTOR_OPENING)
|
||||||
{
|
// steiner_points.push_back({l.start.x, l.start.y});
|
||||||
steiner_points.push_back({ l.start.x, l.start.y });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ss.push_back({l.start.x, l.start.y});
|
ss.push_back({l.start.x, l.start.y});
|
||||||
}
|
}
|
||||||
|
@ -208,7 +220,7 @@ void Map::BuildFlat(Sector& sector, Flat& flat, bool invert)
|
||||||
* To do this we perform a similar approach to BuildFlat, but because the walls aren't strictly along one axis we have to
|
* To do this we perform a similar approach to BuildFlat, but because the walls aren't strictly along one axis we have to
|
||||||
* "flatten" them to perform the math to triangulate them. This is done by projecting the 3D points to 2D.
|
* "flatten" them to perform the math to triangulate them. This is done by projecting the 3D points to 2D.
|
||||||
*/
|
*/
|
||||||
void Map::BuildQuad(Sector& sector, Wall& wall, Flat& flat_top, Flat& flat_bottom, const Texture* texture, Vec3 pos_a, Vec3 pos_b, bool flip, bool flip_u, bool flip_v, XYf uv_offset)
|
void Map::BuildQuad(Sector& sector, Wall& wall, Flat& flat_topr, Flat& flat_bottomr, const Texture* texture, Vec3 pos_a, Vec3 pos_b, bool flip, bool flip_u, bool flip_v, XYf uv_offset)
|
||||||
{
|
{
|
||||||
const float E = 4.0f / 128.0f;
|
const float E = 4.0f / 128.0f;
|
||||||
|
|
||||||
|
@ -219,8 +231,15 @@ void Map::BuildQuad(Sector& sector, Wall& wall, Flat& flat_top, Flat& flat_botto
|
||||||
flip ^= 1;
|
flip ^= 1;
|
||||||
|
|
||||||
// Debug: remove all triangulated data (no terrain/slope support)
|
// Debug: remove all triangulated data (no terrain/slope support)
|
||||||
//flat_top.triangulated_data.clear();
|
// Actually I think the way I want to do this now is make the heightmap alignment optional
|
||||||
//flat_bottom.triangulated_data.clear();
|
// It's so much work and so error prone for a feature that will rarely be used, so fuck it
|
||||||
|
Flat flat_top = flat_topr;
|
||||||
|
Flat flat_bottom = flat_bottomr;
|
||||||
|
if (!(wall.user_flags & Wall::UFLAG_ALIGN_WITH_HEIGHTMAP))
|
||||||
|
{
|
||||||
|
flat_top.triangulated_data.clear();
|
||||||
|
flat_bottom.triangulated_data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Vec2> points;
|
std::vector<Vec2> points;
|
||||||
for (const Vertex3D& v: flat_bottom.triangulated_data)
|
for (const Vertex3D& v: flat_bottom.triangulated_data)
|
||||||
|
@ -347,6 +366,33 @@ void Map::BuildWall(Sector& sector, Wall& wall)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Map::SanitizeSectors()
|
||||||
|
{
|
||||||
|
// Before we can build the map, we need to do some safety checks and fix up the level geometry since we could easily encounter
|
||||||
|
// unexpected input, weird edge cases, etc.
|
||||||
|
// For instance, what do we do when two sectors overlap?
|
||||||
|
// - If the overlapping sector is completely contained by the sector it's overlapping, keep it as-is so we can make it a child
|
||||||
|
// - If the overlapping sector is *partially* overlapping, clip the sector it's overlapping so that they'll be two separate,
|
||||||
|
// adjacent sectors
|
||||||
|
for (const auto& sp: sectors)
|
||||||
|
{
|
||||||
|
Sector& s = *sp;
|
||||||
|
for (const auto& sp2: sectors)
|
||||||
|
{
|
||||||
|
Sector& s2 = *sp;
|
||||||
|
|
||||||
|
SectorContainmentStatus status;
|
||||||
|
SectorContains(s, s2, &status);
|
||||||
|
|
||||||
|
if (status.partial_count > 0 && status.count > 0)
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Map::JoinSectors(Sector& sector)
|
void Map::JoinSectors(Sector& sector)
|
||||||
{
|
{
|
||||||
// "Connect" sectors by splitting up their walls where other sectors intersect
|
// "Connect" sectors by splitting up their walls where other sectors intersect
|
||||||
|
@ -603,7 +649,7 @@ void Map::Init()
|
||||||
s->inverted = inverted;
|
s->inverted = inverted;
|
||||||
float scl = 1.0f;
|
float scl = 1.0f;
|
||||||
for (size_t i = 0; i < num_points; i++)
|
for (size_t i = 0; i < num_points; i++)
|
||||||
s->walls.push_back(Wall{ {wall,wall,lower}, {{0, 0}}, points[i], points[(i + 1) % num_points], Wall::NO_FLAGS, (uint)i });
|
s->walls.push_back(Wall{ {wall,wall,lower}, {{0, 0}}, points[i], points[(i + 1) % num_points], Wall::NO_FLAGS, Wall::NO_UFLAGS, (uint)i });
|
||||||
sectors.push_back(s);
|
sectors.push_back(s);
|
||||||
};
|
};
|
||||||
build_sector(&tex3, &tex3, &tex, &tex2, -1.0f, 5.0f, 1, points, std::size(points));
|
build_sector(&tex3, &tex3, &tex, &tex2, -1.0f, 5.0f, 1, points, std::size(points));
|
||||||
|
@ -620,6 +666,8 @@ void Map::Rebuild(NormalGenType gen_normals)
|
||||||
{
|
{
|
||||||
m_mesh.Reset();
|
m_mesh.Reset();
|
||||||
|
|
||||||
|
SanitizeSectors();
|
||||||
|
|
||||||
//sectors.clear();
|
//sectors.clear();
|
||||||
//for (Sector& s : original_sectors)
|
//for (Sector& s : original_sectors)
|
||||||
//{
|
//{
|
||||||
|
|
|
@ -32,6 +32,12 @@ struct Wall
|
||||||
FLAG_SUBSECTOR_OPENING = 1 << 5
|
FLAG_SUBSECTOR_OPENING = 1 << 5
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum UserFlags: byte
|
||||||
|
{
|
||||||
|
NO_UFLAGS,
|
||||||
|
UFLAG_ALIGN_WITH_HEIGHTMAP = 1 << 0
|
||||||
|
};
|
||||||
|
|
||||||
const Texture* textures[3];
|
const Texture* textures[3];
|
||||||
XYf uv_offset[3];
|
XYf uv_offset[3];
|
||||||
|
|
||||||
|
@ -39,6 +45,7 @@ struct Wall
|
||||||
XYf end;
|
XYf end;
|
||||||
|
|
||||||
byte flags;
|
byte flags;
|
||||||
|
byte user_flags;
|
||||||
uint uid;
|
uint uid;
|
||||||
|
|
||||||
Sector* portal = nullptr;
|
Sector* portal = nullptr;
|
||||||
|
@ -125,6 +132,7 @@ public:
|
||||||
void BuildFlat(Sector& sector, Flat& flat, bool invert);
|
void BuildFlat(Sector& sector, Flat& flat, bool invert);
|
||||||
void BuildQuad(Sector& sector, Wall& wall, Flat& flat_top, Flat& flat_bottom, const Texture* texture, Vec3 pos_a, Vec3 pos_b, bool flip, bool flip_u, bool flip_v, XYf uv_offset);
|
void BuildQuad(Sector& sector, Wall& wall, Flat& flat_top, Flat& flat_bottom, const Texture* texture, Vec3 pos_a, Vec3 pos_b, bool flip, bool flip_u, bool flip_v, XYf uv_offset);
|
||||||
void BuildWall(Sector& sector, Wall& wall);
|
void BuildWall(Sector& sector, Wall& wall);
|
||||||
|
void SanitizeSectors();
|
||||||
void JoinSectors(Sector& sector);
|
void JoinSectors(Sector& sector);
|
||||||
bool WallOverlaps(Sector& sector, Wall& wall);
|
bool WallOverlaps(Sector& sector, Wall& wall);
|
||||||
|
|
||||||
|
|
|
@ -226,6 +226,8 @@ void Editor::UpdateModeBuild()
|
||||||
wall.start = { points[i].x, -points[i].z };
|
wall.start = { points[i].x, -points[i].z };
|
||||||
wall.end = { points[i + 1].x, -points[i + 1].z };
|
wall.end = { points[i + 1].x, -points[i + 1].z };
|
||||||
wall.uid = i;
|
wall.uid = i;
|
||||||
|
wall.flags = kp3d::Wall::NO_FLAGS;
|
||||||
|
wall.user_flags = kp3d::Wall::NO_UFLAGS;
|
||||||
for (int j = 0; j < 3; j++)
|
for (int j = 0; j < 3; j++)
|
||||||
wall.textures[j] = &m_block;
|
wall.textures[j] = &m_block;
|
||||||
|
|
||||||
|
@ -265,6 +267,38 @@ void Editor::RenderUI()
|
||||||
|
|
||||||
// Overlay
|
// Overlay
|
||||||
RenderUIInfo();
|
RenderUIInfo();
|
||||||
|
|
||||||
|
// Sector window
|
||||||
|
// ImGui::SetNextWindowSize({400, 500}, ImGuiCond_FirstUseEver);
|
||||||
|
ImGui::SetNextWindowPos({20, 200});
|
||||||
|
if (ImGui::Begin("Selection Information", nullptr, ImGuiWindowFlags_AlwaysAutoResize))
|
||||||
|
{
|
||||||
|
if (kp3d::editor_hovered_batch)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
const auto& info = std::any_cast<kp3d::BatchSectorInfo>(kp3d::editor_hovered_batch->userdata);
|
||||||
|
if (info.sector)
|
||||||
|
{
|
||||||
|
ImGui::SeparatorText("Hierarchy");
|
||||||
|
ImGui::Text("ID: %u\n", info.sector->id);
|
||||||
|
ImGui::Text("Parent ID: %u %s\n", info.sector->parent_id, info.sector->parent_id == 0 ? "(N/A)" : "");
|
||||||
|
ImGui::Text("Children (%u):\n", info.sector->children.size());
|
||||||
|
ImGui::Indent();
|
||||||
|
for (const auto& sc : info.sector->children)
|
||||||
|
ImGui::Text("- ID: %u", sc->id);
|
||||||
|
ImGui::Unindent();
|
||||||
|
ImGui::SeparatorText("Properties");
|
||||||
|
ImGui::InputFloat("Floor height", &info.sector->floor.base_height);
|
||||||
|
ImGui::InputFloat("Ceiling height", &info.sector->ceiling.base_height);
|
||||||
|
ImGui::Checkbox("Inverted", &info.sector->inverted);
|
||||||
|
}
|
||||||
|
} catch (std::bad_any_cast& e) {
|
||||||
|
KP3D_LOG_ERROR("Bad any cast: {}", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::RenderUIInfo()
|
void Editor::RenderUIInfo()
|
||||||
|
|
Loading…
Reference in a new issue