Add ability to place and select things in the map editor
This commit is contained in:
parent
5b36b9820a
commit
2f155d3fe9
9 changed files with 13909 additions and 248 deletions
13892
Data/sandbox-log.txt
13892
Data/sandbox-log.txt
File diff suppressed because it is too large
Load diff
|
@ -561,15 +561,11 @@ void Map::Init()
|
|||
sectors.clear();
|
||||
m_mesh.Reset();
|
||||
sectors.reserve(10000);
|
||||
things.reserve(100000);
|
||||
|
||||
BuildSkybox(res::texture_cache["skyboxes/skybox_14.jpg"].get());
|
||||
BuildGrid();
|
||||
|
||||
//static Texture tex, tex2, tex3, tex4;
|
||||
//tex.Load("GRASS2.png", true);
|
||||
//tex2.Load("floor0.png", true);
|
||||
//tex3.Load("FLAT5_7.png", true);
|
||||
//tex4.Load("block.png", true);
|
||||
m_dot.Load("dot.png");
|
||||
|
||||
static Material* tex;
|
||||
|
@ -582,8 +578,6 @@ void Map::Init()
|
|||
tex3 = res::material_cache["FLAT5_7.png"].get();
|
||||
tex4 = res::material_cache["block.png"].get();
|
||||
|
||||
|
||||
|
||||
// Build a stupid little test map
|
||||
// ------------------------------
|
||||
// Main sector
|
||||
|
@ -793,7 +787,9 @@ void Map::Rebuild(NormalGenType gen_normals)
|
|||
|
||||
void Map::Update()
|
||||
{
|
||||
// ...
|
||||
// Things
|
||||
for (Thing& thing: things)
|
||||
thing.Update();
|
||||
}
|
||||
|
||||
void Map::Render()
|
||||
|
@ -807,6 +803,10 @@ void Map::Render()
|
|||
kp3d::Renderer3D::DrawMesh(m_mesh, m_transform, true, ShouldHighlight);
|
||||
kp3d::Renderer3D::PopShader();
|
||||
|
||||
// Things
|
||||
for (Thing& thing: things)
|
||||
thing.Render();
|
||||
|
||||
// Debug dots
|
||||
for (Vec3 v: m_dots)
|
||||
kp3d::Renderer3D::DrawBillboard(m_dot, {v.x, v.y, -v.z}, {0.1f, 0.1f}, true);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "KP3D_Transform.h"
|
||||
#include "KP3D_Shader.h"
|
||||
#include "KP3D_Material.h"
|
||||
#include "KP3D_Thing.h"
|
||||
|
||||
namespace kp3d {
|
||||
|
||||
|
@ -173,6 +174,7 @@ public:
|
|||
public:
|
||||
bool join_disabled = false;
|
||||
std::vector<std::shared_ptr<Sector>> sectors;
|
||||
std::vector<Thing> things;
|
||||
bool render_wireframe = false;
|
||||
float texture_scale = 128.0f;
|
||||
Vec3 grid_box[6];
|
||||
|
|
|
@ -308,7 +308,7 @@ void Renderer3D::DrawBillboard(const Texture& texture, const Vec3& position, Vec
|
|||
}
|
||||
|
||||
void Renderer3D::DrawBillboardSprites(
|
||||
const Texture** textures,
|
||||
const Texture* textures[8],
|
||||
float degrees,
|
||||
const Vec3& position,
|
||||
Vec2 size,
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
static void DrawMesh(StaticMesh& mesh, Transform& m, bool bind_shader = true, uint (*func_highlight)(const RenderBatch3D&) = nullptr);
|
||||
static void DrawBillboard(const Texture& texture, const Vec3& position, Vec2 size, bool both_axes = false, float yaw = 90.0f);
|
||||
static void DrawBillboardSprites(
|
||||
const Texture** textures,
|
||||
const Texture* textures[8],
|
||||
float degrees,
|
||||
const Vec3& position,
|
||||
Vec2 size,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <memory>
|
||||
|
||||
#include "KP3D_Renderer3D.h"
|
||||
#include "KP3D_Renderer2D.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -20,10 +21,13 @@ void LoadDefaultSprite()
|
|||
|
||||
namespace kp3d {
|
||||
|
||||
Thing::Thing():
|
||||
Thing::Thing(Vec3 position):
|
||||
display{Display::NONE}
|
||||
{
|
||||
LoadDefaultSprite();
|
||||
|
||||
transform.translation = position;
|
||||
transform.scale = {0.5f, 0.5f, 0.5f};
|
||||
}
|
||||
|
||||
Thing::~Thing()
|
||||
|
@ -39,15 +43,94 @@ void Thing::Render()
|
|||
switch (display.type)
|
||||
{
|
||||
case Display::NONE:
|
||||
// Debug:
|
||||
Renderer3D::DrawBillboard(*default_sprite.get(), transform.translation, {1.0f, 1.0f});
|
||||
break;
|
||||
case Display::MESH:
|
||||
Renderer3D::DrawModel(*display.data.mesh.model, transform);
|
||||
break;
|
||||
case Display::SPRITES:
|
||||
Renderer3D::DrawBillboardSprites(display.data.sprites.textures, transform.rotation.y, transform.translation, {1.0f, 1.0f});
|
||||
Renderer3D::DrawBillboardSprites(display.data.sprites.textures[display.data.sprites.current_sprite], transform.rotation.y, transform.translation, {1.0f, 1.0f});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// For debugging, use by the map editor, etc.
|
||||
void Thing::RenderBox(Vec3 color)
|
||||
{
|
||||
static StaticMesh box_mesh;
|
||||
if (box_mesh.GetBatchesRef().empty())
|
||||
{
|
||||
std::vector<Vertex3D> box_vertex_data = GetBox();
|
||||
box_mesh.AddBatch(&Renderer2D::GetDefaultTexture(), box_vertex_data);
|
||||
box_mesh.Finalize();
|
||||
}
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
Renderer3D::PushShader(Renderer3D::GetWireframeShader());
|
||||
Renderer3D::GetShader().Bind();
|
||||
Renderer3D::GetShader().SetUniform("u_wireframe_color", color);
|
||||
Renderer3D::GetShader().SetUniform("u_wireframe_alpha", 1.0f);
|
||||
Renderer3D::DrawMesh(box_mesh, transform);
|
||||
Renderer3D::PopShader();
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
|
||||
std::vector<Vertex3D> Thing::GetBox(bool apply_transform)
|
||||
{
|
||||
std::vector<Vertex3D> box_vertex_data;
|
||||
box_vertex_data = {
|
||||
Vertex3D(Vec3(-1.0f, -1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, 1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, 1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, 1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, -1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, 1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, -1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, -1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, -1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, 1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, -1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, -1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, 1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, -1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, -1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, -1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, -1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, -1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, 1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, -1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, -1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, 1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, -1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, 1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, -1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, 1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, -1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, 1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, 1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, 1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, 1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, 1.0f, -1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, 1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, 1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3(-1.0f, 1.0f, 1.0f), Vec2(0.0f, 0.0f)),
|
||||
Vertex3D(Vec3( 1.0f, -1.0f, 1.0f), Vec2(0.0f, 0.0f))
|
||||
};
|
||||
|
||||
if (apply_transform)
|
||||
{
|
||||
for (Vertex3D& v: box_vertex_data)
|
||||
{
|
||||
Mat4 scale = Mat4().InitScale(transform.scale);
|
||||
Mat4 rot = Mat4().InitRotation(transform.rotation);
|
||||
Mat4 trans = Mat4().InitTranslation(v.position * 0.5f + transform.translation);
|
||||
Mat4 mat = trans * rot * scale;
|
||||
v.position = {mat.mat[12], mat.mat[13], mat.mat[14]};
|
||||
}
|
||||
}
|
||||
|
||||
return box_vertex_data;
|
||||
}
|
||||
|
||||
} // namespace kp3d
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
namespace kp3d {
|
||||
|
||||
inline static constexpr size_t NUM_SPRITES_PER_DISPLAY = 8;
|
||||
inline static constexpr size_t NUM_SPRITES = 4;
|
||||
|
||||
struct Display
|
||||
{
|
||||
|
@ -25,17 +26,6 @@ struct Display
|
|||
OTHER
|
||||
} type;
|
||||
|
||||
enum Flags: byte
|
||||
{
|
||||
NO_FLAGS,
|
||||
FLAG_FACE_CAMERA = 1 << 0,
|
||||
FLAG_GROUNDED = 1 << 1,
|
||||
FLAG_VISIBLE = 1 << 2,
|
||||
FLAG_DELETE = 1 << 3,
|
||||
FLAG_COLLISIONS = 1 << 4,
|
||||
FLAG_RELATIVE_HR = 1 << 5
|
||||
};
|
||||
|
||||
union Data
|
||||
{
|
||||
struct Mesh
|
||||
|
@ -48,7 +38,9 @@ struct Display
|
|||
|
||||
struct Sprites
|
||||
{
|
||||
Texture* textures[NUM_SPRITES_PER_DISPLAY];
|
||||
const Texture* textures[NUM_SPRITES][NUM_SPRITES_PER_DISPLAY];
|
||||
size_t num_sprites;
|
||||
size_t current_sprite;
|
||||
} sprites;
|
||||
} data;
|
||||
};
|
||||
|
@ -56,16 +48,29 @@ struct Display
|
|||
class Thing
|
||||
{
|
||||
public:
|
||||
Thing();
|
||||
Thing(Vec3 position = {});
|
||||
virtual ~Thing();
|
||||
|
||||
void Update();
|
||||
void Render();
|
||||
void RenderBox(Vec3 color = {0.33f, 0.33f, 1.0f});
|
||||
std::vector<Vertex3D> GetBox(bool apply_transform = false);
|
||||
|
||||
public:
|
||||
Display display;
|
||||
Transform transform;
|
||||
|
||||
enum Flags: byte
|
||||
{
|
||||
NO_FLAGS,
|
||||
FLAG_FACE_CAMERA = 1 << 0,
|
||||
FLAG_GROUNDED = 1 << 1,
|
||||
FLAG_VISIBLE = 1 << 2,
|
||||
FLAG_DELETE = 1 << 3,
|
||||
FLAG_COLLISIONS = 1 << 4,
|
||||
FLAG_RELATIVE_HR = 1 << 5
|
||||
} flags;
|
||||
|
||||
};
|
||||
|
||||
} // namespace kp3d
|
||||
|
|
|
@ -240,6 +240,7 @@ void Editor::Update()
|
|||
|
||||
KEY_SHORTCUT(SPACE, m_mode = MODE_NORMAL);
|
||||
KEY_SHORTCUT(V, m_mode = MODE_BUILD);
|
||||
KEY_SHORTCUT(T, m_mode = MODE_THINGS);
|
||||
KEY_SHORTCUT(Z, {
|
||||
if (sandbox->IsKeyDown(kp3d::KEY_LCTRL))
|
||||
Undo();
|
||||
|
@ -256,6 +257,7 @@ void Editor::Update()
|
|||
{
|
||||
case MODE_BUILD: UpdateModeBuild(); break;
|
||||
case MODE_NORMAL: UpdateModeNormal(); break;
|
||||
case MODE_THINGS: UpdateModeThings(); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,6 +270,7 @@ void Editor::RenderMap()
|
|||
{
|
||||
case MODE_BUILD: RenderModeBuild(); break;
|
||||
case MODE_NORMAL: RenderModeNormal(); break;
|
||||
case MODE_THINGS: RenderModeThings(); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -510,7 +513,7 @@ void Editor::UpdateModeNormal()
|
|||
}
|
||||
if (!targets.empty())
|
||||
{
|
||||
std::sort(targets.begin(), targets.end(), [&](const Target& a, const Target& b) { return a.distance > b.distance; });
|
||||
std::sort(targets.begin(), targets.end(), [](const Target& a, const Target& b) { return a.distance > b.distance; });
|
||||
const Target& target = targets.back();
|
||||
ray_pos = target.position;
|
||||
}
|
||||
|
@ -858,6 +861,108 @@ void Editor::RenderModeNormal()
|
|||
}
|
||||
}
|
||||
|
||||
void Editor::UpdateModeThings()
|
||||
{
|
||||
using namespace kp3d;
|
||||
|
||||
struct Target
|
||||
{
|
||||
Vec3 position;
|
||||
float distance;
|
||||
union Data { RenderBatch3D* b; Thing* t; } object;
|
||||
enum { BATCH, THING } object_type;
|
||||
};
|
||||
std::vector<Target> targets;
|
||||
for (Thing& thing: sandbox->map.things)
|
||||
{
|
||||
std::vector<Vertex3D> vertex_data = thing.GetBox(true);
|
||||
for (size_t i = 0; i < vertex_data.size(); i += 3)
|
||||
{
|
||||
Vec3 pos;
|
||||
Triangle tri = {vertex_data[i].position, vertex_data[i + 1].position, vertex_data[i + 2].position};
|
||||
auto ray = GetRayFromCamera(sandbox->camera);
|
||||
bool raycast = RayIntersectsTriangle(ray[0], ray[1], &tri, pos);
|
||||
if (raycast)
|
||||
{
|
||||
Target target;
|
||||
target.position = pos;
|
||||
target.distance = sqrtf(
|
||||
pow(pos.x - sandbox->camera.position.x, 2) +
|
||||
pow(pos.y - sandbox->camera.position.y, 2) +
|
||||
pow(pos.z - sandbox->camera.position.z, 2)
|
||||
);
|
||||
target.object.b = nullptr;
|
||||
target.object.t = &thing;
|
||||
target.object_type = Target::THING;
|
||||
targets.push_back(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (RenderBatch3D& b: sandbox->map.GetMeshRef().GetBatchesRef())
|
||||
{
|
||||
for (size_t i = 0; i < b.vertex_data.size(); i += 3)
|
||||
{
|
||||
Vec3 pos;
|
||||
Triangle tri = {b.vertex_data[i].position, b.vertex_data[i + 1].position, b.vertex_data[i + 2].position};
|
||||
auto ray = GetRayFromCamera(sandbox->camera);
|
||||
bool raycast = RayIntersectsTriangle(ray[0], ray[1], &tri, pos);
|
||||
if (raycast)
|
||||
{
|
||||
Target target;
|
||||
target.position = pos;
|
||||
target.distance = sqrtf(
|
||||
pow(pos.x - sandbox->camera.position.x, 2) +
|
||||
pow(pos.y - sandbox->camera.position.y, 2) +
|
||||
pow(pos.z - sandbox->camera.position.z, 2)
|
||||
);
|
||||
target.object.b = &b;
|
||||
target.object.t = nullptr;
|
||||
target.object_type = Target::BATCH;
|
||||
targets.push_back(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!targets.empty())
|
||||
{
|
||||
std::sort(targets.begin(), targets.end(), [](const Target& a, const Target& b) { return a.distance > b.distance; });
|
||||
const Target& target = targets.back();
|
||||
if (target.object_type == Target::BATCH)
|
||||
{
|
||||
ray_pos = target.position;
|
||||
if (sandbox->IsMouseButtonDown(MOUSE_BUTTON_LEFT))
|
||||
{
|
||||
KP3D_LOG_INFO("Placed thing at {}", ray_pos);
|
||||
PushAction();
|
||||
sandbox->map.things.push_back(Thing(ray_pos));
|
||||
sandbox->MouseButtonReset(MOUSE_BUTTON_LEFT);
|
||||
}
|
||||
m_hovered_thing = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hovered_thing = target.object.t;
|
||||
if (sandbox->IsMouseButtonDown(MOUSE_BUTTON_LEFT))
|
||||
{
|
||||
m_selected_thing = m_hovered_thing;
|
||||
sandbox->MouseButtonReset(MOUSE_BUTTON_LEFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hovered_thing = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::RenderModeThings()
|
||||
{
|
||||
for (kp3d::Thing& thing: sandbox->map.things)
|
||||
thing.RenderBox(
|
||||
&thing == m_selected_thing ? kp3d::Vec3{0.33f, 0.33f, 1.0f} :
|
||||
(&thing == m_hovered_thing ? kp3d::Vec3{1.0f, 1.0f, 1.0f} : kp3d::Vec3{0.5f, 0.5f, 0.5f})
|
||||
);
|
||||
}
|
||||
|
||||
void Editor::RenderUI()
|
||||
{
|
||||
// Menu bar
|
||||
|
@ -881,8 +986,9 @@ void Editor::RenderUI()
|
|||
}
|
||||
if (ImGui::BeginMenu("Mode"))
|
||||
{
|
||||
if (ImGui::MenuItem("Normal Mode", "Space")) m_mode = MODE_NORMAL;
|
||||
if (ImGui::MenuItem("Build Mode", "V")) m_mode = MODE_BUILD;
|
||||
if (ImGui::MenuItem("Normal Mode", "Space", m_mode == MODE_NORMAL)) m_mode = MODE_NORMAL;
|
||||
if (ImGui::MenuItem("Build Mode", "V", m_mode == MODE_BUILD)) m_mode = MODE_BUILD;
|
||||
if (ImGui::MenuItem("Things Mode", "T", m_mode == MODE_THINGS)) m_mode = MODE_THINGS;
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("View"))
|
||||
|
@ -1006,6 +1112,7 @@ void Editor::RenderUIInfo()
|
|||
{
|
||||
case MODE_NORMAL: mode_str = "Normal"; break;
|
||||
case MODE_BUILD: mode_str = "Build"; break;
|
||||
case MODE_THINGS: mode_str = "Things"; break;
|
||||
}
|
||||
ImGui::Text("Mode: %s\n", mode_str.c_str());
|
||||
if (m_mode == MODE_BUILD)
|
||||
|
@ -1022,8 +1129,11 @@ void Editor::RenderUIInfo()
|
|||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Map built in %fms\n", m_build_time);
|
||||
if (m_build_time > 0)
|
||||
{
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Map built in %fms\n", m_build_time);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,13 @@
|
|||
#include "KP3D_IOEvents.h"
|
||||
#include "KP3D_Material.h"
|
||||
#include "KP3D_Map.h"
|
||||
#include "KP3D_Thing.h"
|
||||
|
||||
enum EditMode
|
||||
{
|
||||
MODE_NORMAL,
|
||||
MODE_BUILD,
|
||||
MODE_THINGS
|
||||
};
|
||||
|
||||
enum WallPoint
|
||||
|
@ -45,6 +47,8 @@ public:
|
|||
void RenderModeBuild();
|
||||
void UpdateModeNormal();
|
||||
void RenderModeNormal();
|
||||
void UpdateModeThings();
|
||||
void RenderModeThings();
|
||||
|
||||
void RenderUI();
|
||||
void RenderUIInfo();
|
||||
|
@ -96,6 +100,7 @@ private:
|
|||
char m_tex_filter_buf[512];
|
||||
std::vector<const kp3d::Material**> m_materials_to_update;
|
||||
std::vector<const kp3d::Texture**> m_textures_to_update;
|
||||
kp3d::Thing* m_hovered_thing = nullptr,* m_selected_thing = nullptr;
|
||||
|
||||
WallUpdate wall_update;
|
||||
bool can_wall_update = false;
|
||||
|
|
Loading…
Reference in a new issue