Add ability to make new walls

This commit is contained in:
KP 2024-07-31 00:10:57 -05:00
parent e051973022
commit e5a7498ef3
5 changed files with 1070 additions and 320 deletions

File diff suppressed because it is too large Load diff

View file

@ -199,7 +199,7 @@ void Map::BuildFlat(Sector& sector, Flat& flat, bool invert)
flat.triangulated_data.push_back(vtxa); flat.triangulated_data.push_back(vtxa);
flat.triangulated_data.push_back(vtxb); flat.triangulated_data.push_back(vtxb);
flat.triangulated_data.push_back(vtxc); flat.triangulated_data.push_back(vtxc);
BatchSectorInfo info = {BatchSectorInfo::BATCH_FLAT, &sector, &flat, nullptr}; BatchSectorInfo info = {BatchSectorInfo::BATCH_FLAT, flat.floor ? MAT_FLOOR_TEX : MAT_CEILING_TEX, &sector, &flat, nullptr};
if (flat.material) if (flat.material)
m_mesh.AddBatch( m_mesh.AddBatch(
&flat.material->textures[MAT_TEX_DIFFUSE], &flat.material->textures[MAT_TEX_DIFFUSE],
@ -217,11 +217,11 @@ 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_topr, Flat& flat_bottomr, const Material* material, 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, WallTextureIndex mat_type, 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;
if (!material) if (!wall.materials[mat_type])
return; return;
if (sector.inverted) if (sector.inverted)
@ -302,14 +302,13 @@ void Map::BuildQuad(Sector& sector, Wall& wall, Flat& flat_topr, Flat& flat_bott
Vec3 fvc = Vec3(c.x, c.y, 0.0f).Rotated({0, 1, 0}, -ToDegrees(angle)); fvc.x += pos_a.x; fvc.z += pos_a.z; Vec3 fvc = Vec3(c.x, c.y, 0.0f).Rotated({0, 1, 0}, -ToDegrees(angle)); fvc.x += pos_a.x; fvc.z += pos_a.z;
// Fix up the UVs so they keep the right scale // Fix up the UVs so they keep the right scale
float tw = material ? texture_scale / material->textures[MAT_TEX_DIFFUSE].GetWidth() : 0.0f; float tw = texture_scale / wall.materials[mat_type]->textures[MAT_TEX_DIFFUSE].GetWidth();
float th = material ? texture_scale / material->textures[MAT_TEX_DIFFUSE].GetHeight() : 0.0f; float th = texture_scale / wall.materials[mat_type]->textures[MAT_TEX_DIFFUSE].GetHeight();
Vertex3D vtxa = Vertex3D(fva, Vec2(au * tw, av * th)); Vertex3D vtxa = Vertex3D(fva, Vec2(au * tw, av * th));
Vertex3D vtxb = Vertex3D(fvb, Vec2(bu * tw, bv * th)); Vertex3D vtxb = Vertex3D(fvb, Vec2(bu * tw, bv * th));
Vertex3D vtxc = Vertex3D(fvc, Vec2(cu * tw, cv * th)); Vertex3D vtxc = Vertex3D(fvc, Vec2(cu * tw, cv * th));
BatchSectorInfo info = {BatchSectorInfo::BATCH_WALL, &sector, nullptr, &wall}; BatchSectorInfo info = {BatchSectorInfo::BATCH_WALL, (MaterialType)(mat_type + 2), &sector, nullptr, &wall};
if (material) m_mesh.AddBatch(&wall.materials[mat_type]->textures[MAT_TEX_DIFFUSE], {vtxa, vtxb, vtxc}, flip, std::make_any<BatchSectorInfo>(info), &wall.materials[mat_type]->textures[MAT_TEX_NORMAL]);
m_mesh.AddBatch(&material->textures[MAT_TEX_DIFFUSE], {vtxa, vtxb, vtxc}, flip, std::make_any<BatchSectorInfo>(info), &material->textures[MAT_TEX_NORMAL]);
} }
} }
} }
@ -321,7 +320,7 @@ void Map::BuildWall(Sector& sector, Wall& wall)
{ {
Vec3 a = {wall.start.x, 0.0f, wall.start.y}; Vec3 a = {wall.start.x, 0.0f, wall.start.y};
Vec3 b = {wall.end.x, 0.0f, wall.end.y}; Vec3 b = {wall.end.x, 0.0f, wall.end.y};
BuildQuad(sector, wall, sector.floor, sector.ceiling, wall.materials[TEX_FRONT], a, b, false, false, false, wall.uv_offset[TEX_FRONT]); BuildQuad(sector, wall, sector.floor, sector.ceiling, TEX_FRONT, a, b, false, false, false, wall.uv_offset[TEX_FRONT]);
if (!(wall.flags & Wall::FLAG_SUBSECTOR_OPENING)) if (!(wall.flags & Wall::FLAG_SUBSECTOR_OPENING))
{ {
@ -330,10 +329,10 @@ void Map::BuildWall(Sector& sector, Wall& wall)
// Build upper and lower walls for sectors connected to other sectors (or sectors within sectors) // Build upper and lower walls for sectors connected to other sectors (or sectors within sectors)
bool flip = wall.portal->floor.base_height < sector.floor.base_height; bool flip = wall.portal->floor.base_height < sector.floor.base_height;
if (flip && !FloatCmp(wall.portal->floor.base_height, sector.floor.base_height)) if (flip && !FloatCmp(wall.portal->floor.base_height, sector.floor.base_height))
BuildQuad(sector, wall, sector.floor, wall.portal->floor, wall.materials[TEX_LOWER], a, b, flip, false, false, wall.uv_offset[TEX_LOWER]); BuildQuad(sector, wall, sector.floor, wall.portal->floor, TEX_LOWER, a, b, flip, false, false, wall.uv_offset[TEX_LOWER]);
flip = wall.portal->ceiling.base_height < sector.ceiling.base_height; flip = wall.portal->ceiling.base_height < sector.ceiling.base_height;
if (!flip && !FloatCmp(wall.portal->ceiling.base_height, sector.ceiling.base_height)) if (!flip && !FloatCmp(wall.portal->ceiling.base_height, sector.ceiling.base_height))
BuildQuad(sector, wall, sector.ceiling, wall.portal->ceiling, wall.materials[TEX_UPPER], a, b, !flip, false, false, wall.uv_offset[TEX_UPPER]); BuildQuad(sector, wall, sector.ceiling, wall.portal->ceiling, TEX_UPPER, a, b, !flip, false, false, wall.uv_offset[TEX_UPPER]);
wall.flags |= Wall::FLAG_JOINED; wall.flags |= Wall::FLAG_JOINED;
} }
@ -343,9 +342,9 @@ void Map::BuildWall(Sector& sector, Wall& wall)
if (!(wall.flags & Wall::FLAG_JOINED)) if (!(wall.flags & Wall::FLAG_JOINED))
{ {
bool flip = wall.portal->floor.base_height < sector.floor.base_height; bool flip = wall.portal->floor.base_height < sector.floor.base_height;
BuildQuad(sector, wall, sector.floor, wall.portal->floor, wall.materials[TEX_LOWER], a, b, flip, false, false, wall.uv_offset[TEX_LOWER]); BuildQuad(sector, wall, sector.floor, wall.portal->floor, TEX_LOWER, a, b, flip, false, false, wall.uv_offset[TEX_LOWER]);
flip = wall.portal->ceiling.base_height < sector.ceiling.base_height; flip = wall.portal->ceiling.base_height < sector.ceiling.base_height;
BuildQuad(sector, wall, sector.ceiling, wall.portal->ceiling, wall.materials[TEX_UPPER], a, b, !flip, false, false, wall.uv_offset[TEX_UPPER]); BuildQuad(sector, wall, sector.ceiling, wall.portal->ceiling, TEX_UPPER, a, b, !flip, false, false, wall.uv_offset[TEX_UPPER]);
wall.flags |= Wall::FLAG_JOINED; wall.flags |= Wall::FLAG_JOINED;
} }
@ -775,7 +774,7 @@ void Map::Rebuild(NormalGenType gen_normals)
const auto& bu = std::any_cast<BatchSectorInfo>(b.userdata); const auto& bu = std::any_cast<BatchSectorInfo>(b.userdata);
return a.texture->GetGLID() != b.texture->GetGLID() || return a.texture->GetGLID() != b.texture->GetGLID() ||
(au.sector != bu.sector || au.flat != bu.flat || au.wall != bu.wall); (au.sector != bu.sector || au.flat != bu.flat || au.wall != bu.wall || au.mat_type != bu.mat_type);
} }
); );
KP3D_LOG_INFO("Finalized mesh with {} batches", m_mesh.GetBatchesRef().size()); KP3D_LOG_INFO("Finalized mesh with {} batches", m_mesh.GetBatchesRef().size());

View file

@ -18,6 +18,15 @@ enum WallTextureIndex
TEX_LOWER TEX_LOWER
}; };
enum MaterialType
{
MAT_FLOOR_TEX,
MAT_CEILING_TEX,
MAT_UPPER_TEX,
MAT_MIDDLE_TEX,
MAT_LOWER_TEX
};
struct Sector; struct Sector;
struct Wall struct Wall
@ -117,6 +126,7 @@ struct BatchSectorInfo
BATCH_FLAT, BATCH_FLAT,
BATCH_WALL BATCH_WALL
} type; } type;
MaterialType mat_type;
kp3d::Sector* sector = nullptr; kp3d::Sector* sector = nullptr;
kp3d::Flat* flat = nullptr; kp3d::Flat* flat = nullptr;
kp3d::Wall* wall = nullptr; kp3d::Wall* wall = nullptr;
@ -132,7 +142,7 @@ public:
ErrCode SaveToFile(const std::string& path); ErrCode SaveToFile(const std::string& path);
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 Material* material, 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, WallTextureIndex mat_type, 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 JoinSectors(Sector& sector); void JoinSectors(Sector& sector);
void SanitizeSectors(); void SanitizeSectors();

View file

@ -230,7 +230,7 @@ void Editor::UpdateModeNormal()
{ {
using namespace kp3d; using namespace kp3d;
// Raycast through everything on the map // Wall/flat selection
if (sandbox->IsMouseButtonDown(kp3d::MOUSE_BUTTON_LEFT) && !editing_gizmo) if (sandbox->IsMouseButtonDown(kp3d::MOUSE_BUTTON_LEFT) && !editing_gizmo)
{ {
// editor_hovered_batch = nullptr; // editor_hovered_batch = nullptr;
@ -293,6 +293,7 @@ void Editor::UpdateModeNormal()
catch (std::bad_any_cast& e) catch (std::bad_any_cast& e)
{ {
KP3D_LOG_ERROR("Bad any cast: {}", e.what()); KP3D_LOG_ERROR("Bad any cast: {}", e.what());
kp3d::editor_hovered_batch.clear();
} }
} }
} }
@ -302,9 +303,63 @@ void Editor::UpdateModeNormal()
sandbox->MouseButtonReset(kp3d::MOUSE_BUTTON_LEFT); sandbox->MouseButtonReset(kp3d::MOUSE_BUTTON_LEFT);
} }
// Wall split
if (sandbox->IsMouseButtonDown(kp3d::MOUSE_BUTTON_RIGHT) && !editing_gizmo)
{
try
{
const auto& info = std::any_cast<kp3d::BatchSectorInfo>(kp3d::editor_hovered_batch[0]->userdata);
if (info.wall)
{
int wall_idx = -1;
for (const auto& sp : sandbox->map.sectors)
{
for (int i = 0; i < sp->walls.size(); i++)
{
Wall& wall = sp->walls[i];
if (&wall == info.wall)
wall_idx = i;
}
}
XYf in_between = {
(info.wall->start.x + info.wall->end.x) * 0.5f,
(info.wall->start.y + info.wall->end.y) * 0.5f
};
XYf old_end = info.wall->end;
info.wall->end = in_between;
kp3d::Wall new_wall = *info.wall;
new_wall.start = in_between;
new_wall.end = old_end;
kp3d::InsertLine(info.sector->walls, wall_idx + 1, new_wall);
RebuildMap();
kp3d::editor_hovered_batch.clear();
}
}
catch (std::bad_any_cast& e)
{
KP3D_LOG_ERROR("Bad any cast: {}", e.what());
kp3d::editor_hovered_batch.clear();
}
sandbox->MouseButtonReset(kp3d::MOUSE_BUTTON_RIGHT);
}
// Wall/sector remove
if (sandbox->IsKeyDown(kp3d::KEY_DELETE))
{
sandbox->KeyReset(kp3d::KEY_DELETE);
}
// UV adjust
if (sandbox->IsMouseButtonDown(kp3d::MOUSE_BUTTON_MIDDLE))
{
}
if (editing_gizmo) if (editing_gizmo)
kp3d::editor_hovered_batch.clear(); kp3d::editor_hovered_batch.clear();
// Wall moving
if (!editor_hovered_batch.empty() && !editing_gizmo) if (!editor_hovered_batch.empty() && !editing_gizmo)
{ {
try try
@ -371,6 +426,7 @@ void Editor::UpdateModeNormal()
{ {
can_wall_update = false; can_wall_update = false;
KP3D_LOG_ERROR("Bad any cast: {}", e.what()); KP3D_LOG_ERROR("Bad any cast: {}", e.what());
kp3d::editor_hovered_batch.clear();
} }
} }
} }
@ -505,9 +561,9 @@ void Editor::RenderUI()
ImGui::CheckboxFlags("Double-sided", (unsigned*)&info.wall->user_flags, kp3d::Wall::UFLAG_DOUBLESIDED); ImGui::CheckboxFlags("Double-sided", (unsigned*)&info.wall->user_flags, kp3d::Wall::UFLAG_DOUBLESIDED);
ImGui::SeparatorText("Materials"); ImGui::SeparatorText("Materials");
RenderUIMaterialSelect("Middle", MAT_MIDDLE_TEX, &info.wall->materials[kp3d::TEX_FRONT]); RenderUIMaterialSelect("Middle", kp3d::MAT_MIDDLE_TEX, &info.wall->materials[kp3d::TEX_FRONT]);
RenderUIMaterialSelect("Upper", MAT_UPPER_TEX, &info.wall->materials[kp3d::TEX_UPPER]); RenderUIMaterialSelect("Upper", kp3d::MAT_UPPER_TEX, &info.wall->materials[kp3d::TEX_UPPER]);
RenderUIMaterialSelect("Lower", MAT_LOWER_TEX, &info.wall->materials[kp3d::TEX_LOWER]); RenderUIMaterialSelect("Lower", kp3d::MAT_LOWER_TEX, &info.wall->materials[kp3d::TEX_LOWER]);
} }
else if (info.sector) else if (info.sector)
{ {
@ -527,13 +583,14 @@ void Editor::RenderUI()
if (changed) if (changed)
RebuildMap(); RebuildMap();
ImGui::SeparatorText("Materials"); ImGui::SeparatorText("Materials");
RenderUIMaterialSelect("Floor", MAT_FLOOR_TEX, &info.sector->floor.material); RenderUIMaterialSelect("Floor", kp3d::MAT_FLOOR_TEX, &info.sector->floor.material);
RenderUIMaterialSelect("Ceiling", MAT_CEILING_TEX, &info.sector->ceiling.material); RenderUIMaterialSelect("Ceiling", kp3d::MAT_CEILING_TEX, &info.sector->ceiling.material);
} }
} }
catch (std::bad_any_cast& e) catch (std::bad_any_cast& e)
{ {
KP3D_LOG_ERROR("Bad any cast: {}", e.what()); KP3D_LOG_ERROR("Bad any cast: {}", e.what());
kp3d::editor_hovered_batch.clear();
} }
} }
else else
@ -621,9 +678,9 @@ void Editor::RenderUIMaterialSelect(const char* name, int type, const kp3d::Mate
{ {
switch (type) switch (type)
{ {
case MAT_UPPER_TEX: m_materials_to_update.push_back(&info.wall->materials[kp3d::TEX_UPPER]); case kp3d::MAT_UPPER_TEX: m_materials_to_update.push_back(&info.wall->materials[kp3d::TEX_UPPER]); break;
case MAT_LOWER_TEX: m_materials_to_update.push_back(&info.wall->materials[kp3d::TEX_LOWER]); case kp3d::MAT_LOWER_TEX: m_materials_to_update.push_back(&info.wall->materials[kp3d::TEX_LOWER]); break;
case MAT_MIDDLE_TEX: m_materials_to_update.push_back(&info.wall->materials[kp3d::TEX_FRONT]); case kp3d::MAT_MIDDLE_TEX: m_materials_to_update.push_back(&info.wall->materials[kp3d::TEX_FRONT]); break;
} }
} }
else if (info.flat) else if (info.flat)

View file

@ -14,15 +14,6 @@ enum EditMode
MODE_BUILD, MODE_BUILD,
}; };
enum MaterialType
{
MAT_FLOOR_TEX,
MAT_CEILING_TEX,
MAT_UPPER_TEX,
MAT_LOWER_TEX,
MAT_MIDDLE_TEX
};
enum WallPoint enum WallPoint
{ {
WP_START, WP_START,