mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
Get player controller wall collisions working
This commit is contained in:
parent
a4d58a1490
commit
1b0af6cd8b
71
cloc
71
cloc
@ -1,71 +0,0 @@
|
|||||||
include/application.h
|
|
||||||
include/components/collider.h
|
|
||||||
include/components/custom.h
|
|
||||||
include/components/mesh_renderable.h
|
|
||||||
include/components/transform.h
|
|
||||||
include/components/ui_renderable.h
|
|
||||||
include/ecs.h
|
|
||||||
include/engine_api.h
|
|
||||||
include/event_system.h
|
|
||||||
include/gfx.h
|
|
||||||
include/gfx_device.h
|
|
||||||
include/input_manager.h
|
|
||||||
include/inputs/keyboard.h
|
|
||||||
include/inputs/mouse.h
|
|
||||||
include/log.h
|
|
||||||
include/logger.h
|
|
||||||
include/renderer.h
|
|
||||||
include/resource_manager.h
|
|
||||||
include/resources/font.h
|
|
||||||
include/resources/material.h
|
|
||||||
include/resources/mesh.h
|
|
||||||
include/resources/shader.h
|
|
||||||
include/resources/texture.h
|
|
||||||
include/scene.h
|
|
||||||
include/scene_manager.h
|
|
||||||
include/systems/collisions.h
|
|
||||||
include/systems/custom_behaviour.h
|
|
||||||
include/systems/mesh_render_system.h
|
|
||||||
include/systems/transform.h
|
|
||||||
include/systems/ui_render_system.h
|
|
||||||
include/util.h
|
|
||||||
include/util/files.h
|
|
||||||
include/util/gltf_loader.h
|
|
||||||
include/util/model_loader.h
|
|
||||||
include/window.h
|
|
||||||
src/application.cpp
|
|
||||||
src/ecs.cpp
|
|
||||||
src/gfx_device_vulkan.cpp
|
|
||||||
src/input_manager.cpp
|
|
||||||
src/renderer.cpp
|
|
||||||
src/resources/font.cpp
|
|
||||||
src/resources/material.cpp
|
|
||||||
src/resources/mesh.cpp
|
|
||||||
src/resources/shader.cpp
|
|
||||||
src/resources/texture.cpp
|
|
||||||
src/scene.cpp
|
|
||||||
src/scene_manager.cpp
|
|
||||||
src/systems/collisions.cpp
|
|
||||||
src/systems/custom_behaviour.cpp
|
|
||||||
src/systems/mesh_render_system.cpp
|
|
||||||
src/systems/transform.cpp
|
|
||||||
src/systems/ui_render_system.cpp
|
|
||||||
src/util/files.cpp
|
|
||||||
src/util/gltf_loader.cpp
|
|
||||||
src/util/model_loader.cpp
|
|
||||||
src/vulkan/device.cpp
|
|
||||||
src/vulkan/device.h
|
|
||||||
src/vulkan/gpu_allocator.cpp
|
|
||||||
src/vulkan/gpu_allocator.h
|
|
||||||
src/vulkan/instance.cpp
|
|
||||||
src/vulkan/instance.h
|
|
||||||
src/vulkan/swapchain.cpp
|
|
||||||
src/vulkan/swapchain.h
|
|
||||||
src/window.cpp
|
|
||||||
test/src/camera_controller.cpp
|
|
||||||
test/src/camera_controller.hpp
|
|
||||||
test/src/game.cpp
|
|
||||||
test/src/game.hpp
|
|
||||||
test/src/main.cpp
|
|
||||||
test/src/meshgen.cpp
|
|
||||||
test/src/meshgen.hpp
|
|
@ -66,6 +66,8 @@ class Application {
|
|||||||
|
|
||||||
std::string GetResourcePath(const std::string relative_path) const { return (resources_path_ / relative_path).string(); }
|
std::string GetResourcePath(const std::string relative_path) const { return (resources_path_ / relative_path).string(); }
|
||||||
|
|
||||||
|
std::vector<Line> debug_lines{};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Window> window_;
|
std::unique_ptr<Window> window_;
|
||||||
std::unique_ptr<InputManager> input_manager_;
|
std::unique_ptr<InputManager> input_manager_;
|
||||||
|
@ -27,6 +27,7 @@ struct UniformDescriptor {
|
|||||||
struct Line {
|
struct Line {
|
||||||
glm::vec3 pos1;
|
glm::vec3 pos1;
|
||||||
glm::vec3 pos2;
|
glm::vec3 pos2;
|
||||||
|
glm::vec3 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Renderer : private ApplicationComponent {
|
class Renderer : private ApplicationComponent {
|
||||||
|
@ -18,11 +18,14 @@ struct Ray {
|
|||||||
|
|
||||||
struct Raycast {
|
struct Raycast {
|
||||||
glm::vec3 location;
|
glm::vec3 location;
|
||||||
Entity hit_entity;
|
glm::vec3 normal;
|
||||||
|
Entity hit_entity; // broken
|
||||||
float distance;
|
float distance;
|
||||||
bool hit;
|
bool hit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class AABBSide { Left, Right, Bottom, Top, Front, Back };
|
||||||
|
|
||||||
class CollisionSystem : public System {
|
class CollisionSystem : public System {
|
||||||
public:
|
public:
|
||||||
CollisionSystem(Scene* scene);
|
CollisionSystem(Scene* scene);
|
||||||
@ -59,7 +62,14 @@ class CollisionSystem : public System {
|
|||||||
size_t colliders_size_last_update_ = 0;
|
size_t colliders_size_last_update_ = 0;
|
||||||
size_t colliders_size_now_ = 0;
|
size_t colliders_size_now_ = 0;
|
||||||
|
|
||||||
bool RaycastTreeNode(const Ray& ray, const BiTreeNode& node, glm::vec3& location, float& t, Entity& object_index);
|
struct RaycastTreeNodeResult {
|
||||||
|
glm::vec3 location;
|
||||||
|
Entity object_index;
|
||||||
|
AABBSide side;
|
||||||
|
float t;
|
||||||
|
bool hit; // if this is false, all other values are undefined
|
||||||
|
};
|
||||||
|
RaycastTreeNodeResult RaycastTreeNode(const Ray& ray, const BiTreeNode& node);
|
||||||
|
|
||||||
static int BuildNode(std::vector<PrimitiveInfo>& prims, std::vector<BiTreeNode>& tree_nodes);
|
static int BuildNode(std::vector<PrimitiveInfo>& prims, std::vector<BiTreeNode>& tree_nodes);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 inColor;
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
layout(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
outColor = vec4(1.0);
|
outColor = vec4(inColor, 1.0);
|
||||||
}
|
}
|
@ -2,9 +2,13 @@
|
|||||||
|
|
||||||
layout( push_constant ) uniform Constants {
|
layout( push_constant ) uniform Constants {
|
||||||
vec4 positions[2];
|
vec4 positions[2];
|
||||||
|
vec3 color;
|
||||||
} constants;
|
} constants;
|
||||||
|
|
||||||
|
layout(location = 0) out vec3 color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
color = constants.color;
|
||||||
gl_Position = constants.positions[gl_VertexIndex];
|
gl_Position = constants.positions[gl_VertexIndex];
|
||||||
gl_Position.y *= -1.0;
|
gl_Position.y *= -1.0;
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,8 @@ float GGXDist(float alpha_2, float N_dot_H) {
|
|||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
const vec3 metallic_roughness = vec3(texture(materialSetMetallicRoughnessSampler, fragUV));
|
const vec3 metallic_roughness = vec3(texture(materialSetMetallicRoughnessSampler, fragUV));
|
||||||
const float metallic = metallic_roughness.g;
|
const float metallic = metallic_roughness.b;
|
||||||
const float roughness = metallic_roughness.b;
|
const float roughness = metallic_roughness.g; // roughness of zero is completely black?
|
||||||
const float roughness_2 = roughness * roughness;
|
const float roughness_2 = roughness * roughness;
|
||||||
|
|
||||||
const vec3 light_colour = vec3(1.0, 1.0, 1.0) * 2.4;
|
const vec3 light_colour = vec3(1.0, 1.0, 1.0) * 2.4;
|
||||||
|
@ -34,7 +34,7 @@ void main() {
|
|||||||
fragUV = inUV;
|
fragUV = inUV;
|
||||||
fragPosTangentSpace = worldToTangentSpace * vec3(worldPosition);
|
fragPosTangentSpace = worldToTangentSpace * vec3(worldPosition);
|
||||||
fragViewPosTangentSpace = worldToTangentSpace * vec3(inverse(frameSetUniformBuffer.view) * vec4(0.0, 0.0, 0.0, 1.0));
|
fragViewPosTangentSpace = worldToTangentSpace * vec3(inverse(frameSetUniformBuffer.view) * vec4(0.0, 0.0, 0.0, 1.0));
|
||||||
fragLightPosTangentSpace = worldToTangentSpace * vec3(10000.0, 0000.0, 59000.0);
|
fragLightPosTangentSpace = worldToTangentSpace * vec3(10000.0, 0000.0, 20000.0);
|
||||||
|
|
||||||
gl_Position.y *= -1.0;
|
gl_Position.y *= -1.0;
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
|
|||||||
GetResourceManager<Texture>()->AddPersistent("builtin.normal", std::move(normalTexture));
|
GetResourceManager<Texture>()->AddPersistent("builtin.normal", std::move(normalTexture));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const uint8_t pixel[4] = {255, 0, 127, 255};
|
const uint8_t pixel[4] = {255, 127, 0, 255}; // AO, roughness, metallic
|
||||||
gfx::SamplerInfo samplerInfo{};
|
gfx::SamplerInfo samplerInfo{};
|
||||||
samplerInfo.minify = gfx::Filter::kNearest;
|
samplerInfo.minify = gfx::Filter::kNearest;
|
||||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
samplerInfo.magnify = gfx::Filter::kNearest;
|
||||||
@ -208,7 +208,8 @@ void Application::GameLoop()
|
|||||||
|
|
||||||
struct DebugMenuState {
|
struct DebugMenuState {
|
||||||
bool menu_active = false;
|
bool menu_active = false;
|
||||||
bool show_info_window = true;
|
bool show_aabbs = false;
|
||||||
|
bool show_info_window = false;
|
||||||
} debug_menu_state;
|
} debug_menu_state;
|
||||||
|
|
||||||
// single-threaded game loop
|
// single-threaded game loop
|
||||||
@ -245,6 +246,7 @@ void Application::GameLoop()
|
|||||||
if (ImGui::Begin("debugMenu", 0)) {
|
if (ImGui::Begin("debugMenu", 0)) {
|
||||||
ImGui::Text("Test!");
|
ImGui::Text("Test!");
|
||||||
ImGui::Text("FPS: %.3f", std::roundf(avg_fps));
|
ImGui::Text("FPS: %.3f", std::roundf(avg_fps));
|
||||||
|
ImGui::Checkbox("Show AABBs?", &debug_menu_state.show_aabbs);
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
@ -285,8 +287,73 @@ void Application::GameLoop()
|
|||||||
const RenderList* static_list = nullptr;
|
const RenderList* static_list = nullptr;
|
||||||
const RenderList* dynamic_list = nullptr;
|
const RenderList* dynamic_list = nullptr;
|
||||||
glm::mat4 camera_transform{1.0f};
|
glm::mat4 camera_transform{1.0f};
|
||||||
std::vector<Line> debug_lines{};
|
|
||||||
if (scene) {
|
if (scene) {
|
||||||
|
if (debug_menu_state.show_aabbs) {
|
||||||
|
if (CollisionSystem* colsys = scene->GetSystem<CollisionSystem>()) {
|
||||||
|
for (const auto& node : colsys->bvh_) {
|
||||||
|
if (node.type1 == CollisionSystem::BiTreeNode::Type::Entity) {
|
||||||
|
const glm::vec3 col =
|
||||||
|
(node.type1 == CollisionSystem::BiTreeNode::Type::BoundingVolume) ? glm::vec3{ 1.0f, 0.0f, 0.0f } : glm::vec3{ 0.0f, 1.0f, 0.0f };
|
||||||
|
Line line1{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z}, col };
|
||||||
|
debug_lines.push_back(line1);
|
||||||
|
Line line2{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z}, col };
|
||||||
|
debug_lines.push_back(line2);
|
||||||
|
Line line3{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z}, col };
|
||||||
|
debug_lines.push_back(line3);
|
||||||
|
Line line4{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z}, col };
|
||||||
|
debug_lines.push_back(line4);
|
||||||
|
|
||||||
|
Line line5{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z}, glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z}, col };
|
||||||
|
debug_lines.push_back(line5);
|
||||||
|
Line line6{ glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col };
|
||||||
|
debug_lines.push_back(line6);
|
||||||
|
Line line7{ glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col };
|
||||||
|
debug_lines.push_back(line7);
|
||||||
|
Line line8{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z}, glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z}, col };
|
||||||
|
debug_lines.push_back(line8);
|
||||||
|
|
||||||
|
Line line9{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col };
|
||||||
|
debug_lines.push_back(line9);
|
||||||
|
Line line10{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col };
|
||||||
|
debug_lines.push_back(line10);
|
||||||
|
Line line11{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col };
|
||||||
|
debug_lines.push_back(line11);
|
||||||
|
Line line12{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col };
|
||||||
|
debug_lines.push_back(line12);
|
||||||
|
}
|
||||||
|
if (node.type2 == CollisionSystem::BiTreeNode::Type::Entity) {
|
||||||
|
const glm::vec3 col =
|
||||||
|
(node.type2 == CollisionSystem::BiTreeNode::Type::BoundingVolume) ? glm::vec3{ 1.0f, 0.0f, 0.0f } : glm::vec3{ 0.0f, 1.0f, 0.0f };
|
||||||
|
Line line1{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z}, col };
|
||||||
|
debug_lines.push_back(line1);
|
||||||
|
Line line2{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z}, col };
|
||||||
|
debug_lines.push_back(line2);
|
||||||
|
Line line3{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z}, col };
|
||||||
|
debug_lines.push_back(line3);
|
||||||
|
Line line4{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z}, col };
|
||||||
|
debug_lines.push_back(line4);
|
||||||
|
|
||||||
|
Line line5{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z}, glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z}, col };
|
||||||
|
debug_lines.push_back(line5);
|
||||||
|
Line line6{ glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col };
|
||||||
|
debug_lines.push_back(line6);
|
||||||
|
Line line7{ glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col };
|
||||||
|
debug_lines.push_back(line7);
|
||||||
|
Line line8{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z}, glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z}, col };
|
||||||
|
debug_lines.push_back(line8);
|
||||||
|
|
||||||
|
Line line9{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col };
|
||||||
|
debug_lines.push_back(line9);
|
||||||
|
Line line10{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col };
|
||||||
|
debug_lines.push_back(line10);
|
||||||
|
Line line11{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col };
|
||||||
|
debug_lines.push_back(line11);
|
||||||
|
Line line12{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col };
|
||||||
|
debug_lines.push_back(line12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
camera_transform = scene->GetComponent<TransformComponent>(scene->GetEntity("camera"))->world_matrix;
|
camera_transform = scene->GetComponent<TransformComponent>(scene->GetEntity("camera"))->world_matrix;
|
||||||
auto mesh_render_system = scene->GetSystem<MeshRenderSystem>();
|
auto mesh_render_system = scene->GetSystem<MeshRenderSystem>();
|
||||||
static_list = mesh_render_system->GetStaticRenderList();
|
static_list = mesh_render_system->GetStaticRenderList();
|
||||||
@ -294,6 +361,7 @@ void Application::GameLoop()
|
|||||||
}
|
}
|
||||||
renderer_->PreRender(window()->GetWindowResized(), camera_transform);
|
renderer_->PreRender(window()->GetWindowResized(), camera_transform);
|
||||||
renderer_->Render(static_list, dynamic_list, debug_lines);
|
renderer_->Render(static_list, dynamic_list, debug_lines);
|
||||||
|
debug_lines.clear(); // gets remade every frame :0
|
||||||
|
|
||||||
/* poll events */
|
/* poll events */
|
||||||
window_->GetInputAndEvents();
|
window_->GetInputAndEvents();
|
||||||
|
@ -121,24 +121,32 @@ void Renderer::Render(const RenderList* static_list, const RenderList* dynamic_l
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DebugPush {
|
||||||
|
glm::vec4 pos1;
|
||||||
|
glm::vec4 pos2;
|
||||||
|
glm::vec3 color;
|
||||||
|
};
|
||||||
|
|
||||||
// draw debug shit here
|
// draw debug shit here
|
||||||
device_->CmdBindPipeline(draw_buffer, debug_rendering_things_.pipeline);
|
device_->CmdBindPipeline(draw_buffer, debug_rendering_things_.pipeline);
|
||||||
glm::vec4 debug_positions[2] = {};
|
DebugPush push{};
|
||||||
for (const Line& l : debug_lines) {
|
for (const Line& l : debug_lines) {
|
||||||
debug_positions[0] = global_uniform.uniform_buffer_data.data * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos1, 1.0f);
|
push.pos1 = global_uniform.uniform_buffer_data.data * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos1, 1.0f);
|
||||||
debug_positions[1] = global_uniform.uniform_buffer_data.data * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos2, 1.0f);
|
push.pos2 = global_uniform.uniform_buffer_data.data * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos2, 1.0f);
|
||||||
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(glm::vec4) * 2, debug_positions);
|
push.color = l.color;
|
||||||
|
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
||||||
device_->CmdDraw(draw_buffer, 2, 1, 0, 0);
|
device_->CmdDraw(draw_buffer, 2, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// also make a lil crosshair
|
// also make a lil crosshair
|
||||||
debug_positions[0] = glm::vec4(-0.05f, 0.0f, 0.0f, 1.0f);
|
push.color = glm::vec3{ 1.0f, 1.0f, 1.0f };
|
||||||
debug_positions[1] = glm::vec4(0.05f, 0.0f, 0.0f, 1.0f);
|
push.pos1 = glm::vec4(-0.05f, 0.0f, 0.0f, 1.0f);
|
||||||
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(glm::vec4) * 2, debug_positions);
|
push.pos2 = glm::vec4(0.05f, 0.0f, 0.0f, 1.0f);
|
||||||
|
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
||||||
device_->CmdDraw(draw_buffer, 2, 1, 0, 0);
|
device_->CmdDraw(draw_buffer, 2, 1, 0, 0);
|
||||||
debug_positions[0] = glm::vec4(0.0f, -0.05f, 0.0f, 1.0f);
|
push.pos1 = glm::vec4(0.0f, -0.05f, 0.0f, 1.0f);
|
||||||
debug_positions[1] = glm::vec4(0.0f, 0.05f, 0.0f, 1.0f);
|
push.pos2 = glm::vec4(0.0f, 0.05f, 0.0f, 1.0f);
|
||||||
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(glm::vec4) * 2, debug_positions);
|
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
||||||
device_->CmdDraw(draw_buffer, 2, 1, 0, 0);
|
device_->CmdDraw(draw_buffer, 2, 1, 0, 0);
|
||||||
|
|
||||||
device_->CmdRenderImguiDrawData(draw_buffer, ImGui::GetDrawData());
|
device_->CmdRenderImguiDrawData(draw_buffer, ImGui::GetDrawData());
|
||||||
|
@ -29,7 +29,8 @@ static float GetBoxArea(const AABB& box)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns true on hit and tmin
|
// returns true on hit and tmin
|
||||||
static std::pair<bool, float> RayBoxIntersection(const Ray& ray, const AABB& box, float t)
|
// also modifies 'side' reference
|
||||||
|
static std::pair<bool, float> RayBoxIntersection(const Ray& ray, const AABB& box, float t, AABBSide& side)
|
||||||
{
|
{
|
||||||
// Thank you https://tavianator.com/cgit/dimension.git/tree/libdimension/bvh/bvh.c
|
// Thank you https://tavianator.com/cgit/dimension.git/tree/libdimension/bvh/bvh.c
|
||||||
glm::vec3 n_inv{1.0f / ray.direction.x, 1.0f / ray.direction.y, 1.0f / ray.direction.z};
|
glm::vec3 n_inv{1.0f / ray.direction.x, 1.0f / ray.direction.y, 1.0f / ray.direction.z};
|
||||||
@ -52,6 +53,20 @@ static std::pair<bool, float> RayBoxIntersection(const Ray& ray, const AABB& box
|
|||||||
tmin = fmaxf(tmin, fminf(tz1, tz2));
|
tmin = fmaxf(tmin, fminf(tz1, tz2));
|
||||||
tmax = fminf(tmax, fmaxf(tz1, tz2));
|
tmax = fminf(tmax, fmaxf(tz1, tz2));
|
||||||
|
|
||||||
|
side = AABBSide::Left;
|
||||||
|
if (tmin == tx2)
|
||||||
|
side = AABBSide::Right;
|
||||||
|
else if (tmin == tx1)
|
||||||
|
side = AABBSide::Left;
|
||||||
|
else if (tmin == ty2)
|
||||||
|
side = AABBSide::Back;
|
||||||
|
else if (tmin == ty1)
|
||||||
|
side = AABBSide::Front;
|
||||||
|
else if (tmin == tz2)
|
||||||
|
side = AABBSide::Top;
|
||||||
|
else if (tmin == tz1)
|
||||||
|
side = AABBSide::Bottom;
|
||||||
|
|
||||||
return std::make_pair((tmax >= fmaxf(0.0, tmin) && tmin < t), tmin);
|
return std::make_pair((tmax >= fmaxf(0.0, tmin) && tmin < t), tmin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,13 +132,40 @@ void CollisionSystem::OnUpdate(float ts)
|
|||||||
|
|
||||||
Raycast CollisionSystem::GetRaycast(Ray ray)
|
Raycast CollisionSystem::GetRaycast(Ray ray)
|
||||||
{
|
{
|
||||||
|
ray.direction = glm::normalize(ray.direction);
|
||||||
|
|
||||||
Raycast res{};
|
Raycast res{};
|
||||||
res.hit = false;
|
res.hit = false;
|
||||||
|
|
||||||
ray.direction = glm::normalize(ray.direction);
|
|
||||||
|
|
||||||
if (!bvh_.empty()) {
|
if (!bvh_.empty()) {
|
||||||
res.hit = RaycastTreeNode(ray, bvh_.back(), res.location, res.distance, res.hit_entity);
|
const RaycastTreeNodeResult tree_node_cast_res = RaycastTreeNode(ray, bvh_.back());
|
||||||
|
if (tree_node_cast_res.hit) {
|
||||||
|
res.hit = true;
|
||||||
|
res.distance = tree_node_cast_res.t;
|
||||||
|
res.location = tree_node_cast_res.location;
|
||||||
|
res.hit_entity = tree_node_cast_res.object_index;
|
||||||
|
// find normal
|
||||||
|
switch (tree_node_cast_res.side) {
|
||||||
|
case AABBSide::Left:
|
||||||
|
res.normal = glm::vec3{-1.0, 0.0f, 0.0f};
|
||||||
|
break;
|
||||||
|
case AABBSide::Right:
|
||||||
|
res.normal = glm::vec3{1.0, 0.0f, 0.0f};
|
||||||
|
break;
|
||||||
|
case AABBSide::Bottom:
|
||||||
|
res.normal = glm::vec3{0.0, 0.0f, -1.0f};
|
||||||
|
break;
|
||||||
|
case AABBSide::Top:
|
||||||
|
res.normal = glm::vec3{0.0, 0.0f, 1.0f};
|
||||||
|
break;
|
||||||
|
case AABBSide::Front:
|
||||||
|
res.normal = glm::vec3{0.0, -1.0f, 0.0f};
|
||||||
|
break;
|
||||||
|
case AABBSide::Back:
|
||||||
|
res.normal = glm::vec3{0.0, 1.0f, 0.0f};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@ -139,38 +181,17 @@ int CollisionSystem::BuildNode(std::vector<PrimitiveInfo>& prims, std::vector<Bi
|
|||||||
if (prims.size() == 0) abort();
|
if (prims.size() == 0) abort();
|
||||||
|
|
||||||
std::array<std::function<bool(const PrimitiveInfo&, const PrimitiveInfo&)>, 3> centroid_tests{
|
std::array<std::function<bool(const PrimitiveInfo&, const PrimitiveInfo&)>, 3> centroid_tests{
|
||||||
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool {
|
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool { return (p1.centroid.x < p2.centroid.x); },
|
||||||
return (p1.centroid.x < p2.centroid.x);
|
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool { return (p1.centroid.y < p2.centroid.y); },
|
||||||
},
|
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool { return (p1.centroid.z < p2.centroid.z); }};
|
||||||
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool {
|
|
||||||
return (p1.centroid.y < p2.centroid.y);
|
|
||||||
},
|
|
||||||
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool {
|
|
||||||
return (p1.centroid.z < p2.centroid.z);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
std::array<std::function<bool(const PrimitiveInfo&, const PrimitiveInfo&)>, 3> box_min_tests{
|
std::array<std::function<bool(const PrimitiveInfo&, const PrimitiveInfo&)>, 3> box_min_tests{
|
||||||
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool {
|
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool { return (p1.box.min.x < p2.box.min.x); },
|
||||||
return (p1.box.min.x < p2.box.min.x);
|
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool { return (p1.box.min.y < p2.box.min.y); },
|
||||||
},
|
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool { return (p1.box.min.z < p2.box.min.z); }};
|
||||||
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool {
|
|
||||||
return (p1.box.min.y < p2.box.min.y);
|
|
||||||
},
|
|
||||||
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool {
|
|
||||||
return (p1.box.min.z < p2.box.min.z);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
std::array<std::function<bool(const PrimitiveInfo&, const PrimitiveInfo&)>, 3> box_max_tests{
|
std::array<std::function<bool(const PrimitiveInfo&, const PrimitiveInfo&)>, 3> box_max_tests{
|
||||||
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool {
|
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool { return (p1.box.max.x < p2.box.max.x); },
|
||||||
return (p1.box.max.x < p2.box.max.x);
|
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool { return (p1.box.max.y < p2.box.max.y); },
|
||||||
},
|
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool { return (p1.box.max.z < p2.box.max.z); }};
|
||||||
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool {
|
|
||||||
return (p1.box.max.y < p2.box.max.y);
|
|
||||||
},
|
|
||||||
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool {
|
|
||||||
return (p1.box.max.z < p2.box.max.z);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
BiTreeNode node{};
|
BiTreeNode node{};
|
||||||
|
|
||||||
@ -190,31 +211,43 @@ int CollisionSystem::BuildNode(std::vector<PrimitiveInfo>& prims, std::vector<Bi
|
|||||||
|
|
||||||
std::sort(prims.begin(), prims.end(), centroid_tests[axis]);
|
std::sort(prims.begin(), prims.end(), centroid_tests[axis]);
|
||||||
|
|
||||||
//std::cout << "Sorting on axis " << axis << "...\n";
|
// std::cout << "Sorting on axis " << axis << "...\n";
|
||||||
for (const auto& p : prims) {
|
for (const auto& p : prims) {
|
||||||
//std::cout << p.centroid.x << "\t" << p.centroid.y << "\t" << p.centroid.z << "\n";
|
// std::cout << p.centroid.x << "\t" << p.centroid.y << "\t" << p.centroid.z << "\n";
|
||||||
}
|
}
|
||||||
//std::cout << "\n\n\n";
|
// std::cout << "\n\n\n";
|
||||||
|
|
||||||
//break;
|
// break;
|
||||||
|
|
||||||
// split the boxes
|
// split the boxes
|
||||||
for (int i = 0; i < prims.size() - 1; i++) {
|
for (int i = 0; i < prims.size() - 1; i++) {
|
||||||
|
|
||||||
float box1_main_min = reinterpret_cast<const float*>(&(std::min_element(prims.begin(), prims.begin() + i + 1, box_min_tests[axis])->box.min))[axis];
|
float box1_main_min =
|
||||||
float box1_main_max = reinterpret_cast<const float*>(&(std::max_element(prims.begin(), prims.begin() + i + 1, box_max_tests[axis])->box.max))[axis];
|
reinterpret_cast<const float*>(&(std::min_element(prims.begin(), prims.begin() + i + 1, box_min_tests[axis])->box.min))[axis];
|
||||||
float box2_main_min = reinterpret_cast<const float*>(&(std::min_element(prims.begin() + i + 1, prims.end(), box_min_tests[axis])->box.min))[axis];
|
float box1_main_max =
|
||||||
float box2_main_max = reinterpret_cast<const float*>(&(std::max_element(prims.begin() + i + 1, prims.end(), box_max_tests[axis])->box.max))[axis];
|
reinterpret_cast<const float*>(&(std::max_element(prims.begin(), prims.begin() + i + 1, box_max_tests[axis])->box.max))[axis];
|
||||||
|
float box2_main_min =
|
||||||
|
reinterpret_cast<const float*>(&(std::min_element(prims.begin() + i + 1, prims.end(), box_min_tests[axis])->box.min))[axis];
|
||||||
|
float box2_main_max =
|
||||||
|
reinterpret_cast<const float*>(&(std::max_element(prims.begin() + i + 1, prims.end(), box_max_tests[axis])->box.max))[axis];
|
||||||
|
|
||||||
float box1_min1 = reinterpret_cast<const float*>(&(std::min_element(prims.begin(), prims.begin() + i + 1, box_min_tests[other_axis1])->box.min))[other_axis1];
|
float box1_min1 =
|
||||||
float box1_max1 = reinterpret_cast<const float*>(&(std::max_element(prims.begin(), prims.begin() + i + 1, box_max_tests[other_axis1])->box.max))[other_axis1];
|
reinterpret_cast<const float*>(&(std::min_element(prims.begin(), prims.begin() + i + 1, box_min_tests[other_axis1])->box.min))[other_axis1];
|
||||||
float box1_min2 = reinterpret_cast<const float*>(&(std::min_element(prims.begin(), prims.begin() + i + 1, box_min_tests[other_axis2])->box.min))[other_axis2];
|
float box1_max1 =
|
||||||
float box1_max2 = reinterpret_cast<const float*>(&(std::max_element(prims.begin(), prims.begin() + i + 1, box_max_tests[other_axis2])->box.max))[other_axis2];
|
reinterpret_cast<const float*>(&(std::max_element(prims.begin(), prims.begin() + i + 1, box_max_tests[other_axis1])->box.max))[other_axis1];
|
||||||
|
float box1_min2 =
|
||||||
|
reinterpret_cast<const float*>(&(std::min_element(prims.begin(), prims.begin() + i + 1, box_min_tests[other_axis2])->box.min))[other_axis2];
|
||||||
|
float box1_max2 =
|
||||||
|
reinterpret_cast<const float*>(&(std::max_element(prims.begin(), prims.begin() + i + 1, box_max_tests[other_axis2])->box.max))[other_axis2];
|
||||||
|
|
||||||
float box2_min1 = reinterpret_cast<const float*>(&(std::min_element(prims.begin() + i + 1, prims.end(), box_min_tests[other_axis1])->box.min))[other_axis1];
|
float box2_min1 =
|
||||||
float box2_max1 = reinterpret_cast<const float*>(&(std::max_element(prims.begin() + i + 1, prims.end(), box_max_tests[other_axis1])->box.max))[other_axis1];
|
reinterpret_cast<const float*>(&(std::min_element(prims.begin() + i + 1, prims.end(), box_min_tests[other_axis1])->box.min))[other_axis1];
|
||||||
float box2_min2 = reinterpret_cast<const float*>(&(std::min_element(prims.begin() + i + 1, prims.end(), box_min_tests[other_axis2])->box.min))[other_axis2];
|
float box2_max1 =
|
||||||
float box2_max2 = reinterpret_cast<const float*>(&(std::max_element(prims.begin() + i + 1, prims.end(), box_max_tests[other_axis2])->box.max))[other_axis2];
|
reinterpret_cast<const float*>(&(std::max_element(prims.begin() + i + 1, prims.end(), box_max_tests[other_axis1])->box.max))[other_axis1];
|
||||||
|
float box2_min2 =
|
||||||
|
reinterpret_cast<const float*>(&(std::min_element(prims.begin() + i + 1, prims.end(), box_min_tests[other_axis2])->box.min))[other_axis2];
|
||||||
|
float box2_max2 =
|
||||||
|
reinterpret_cast<const float*>(&(std::max_element(prims.begin() + i + 1, prims.end(), box_max_tests[other_axis2])->box.max))[other_axis2];
|
||||||
|
|
||||||
AABB box1{}, box2{};
|
AABB box1{}, box2{};
|
||||||
switch (axis) {
|
switch (axis) {
|
||||||
@ -271,7 +304,7 @@ int CollisionSystem::BuildNode(std::vector<PrimitiveInfo>& prims, std::vector<Bi
|
|||||||
optimal_box2 = box2;
|
optimal_box2 = box2;
|
||||||
sorted_prims = prims; // VECTOR COPY!
|
sorted_prims = prims; // VECTOR COPY!
|
||||||
sorted_prims_split_index = i;
|
sorted_prims_split_index = i;
|
||||||
//std::cout << "picking new boxes, axis: " << axis << " i: " << i << " sah: " << combined_surface_area << "\n";
|
// std::cout << "picking new boxes, axis: " << axis << " i: " << i << " sah: " << combined_surface_area << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,7 +323,6 @@ int CollisionSystem::BuildNode(std::vector<PrimitiveInfo>& prims, std::vector<Bi
|
|||||||
node.index2 = index2;
|
node.index2 = index2;
|
||||||
node.type1 = BiTreeNode::Type::BoundingVolume;
|
node.type1 = BiTreeNode::Type::BoundingVolume;
|
||||||
node.type2 = BiTreeNode::Type::BoundingVolume;
|
node.type2 = BiTreeNode::Type::BoundingVolume;
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (prims.size() == 2) {
|
if (prims.size() == 2) {
|
||||||
@ -317,142 +349,161 @@ int CollisionSystem::BuildNode(std::vector<PrimitiveInfo>& prims, std::vector<Bi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns true on ray hit
|
// returns true on ray hit
|
||||||
bool CollisionSystem::RaycastTreeNode(const Ray& ray, const BiTreeNode& node, glm::vec3& location, float& t, Entity& object_index)
|
CollisionSystem::RaycastTreeNodeResult CollisionSystem::RaycastTreeNode(const Ray& ray, const BiTreeNode& node)
|
||||||
{
|
{
|
||||||
|
|
||||||
using Type = BiTreeNode::Type;
|
using Type = BiTreeNode::Type;
|
||||||
|
|
||||||
constexpr float T = 1000.0f;
|
constexpr float T = 1000.0f;
|
||||||
|
|
||||||
|
RaycastTreeNodeResult res{};
|
||||||
|
|
||||||
bool is_hit1 = false;
|
bool is_hit1 = false;
|
||||||
bool is_hit2 = false;
|
bool is_hit2 = false;
|
||||||
float t1 = std::numeric_limits<float>::infinity();
|
float t1 = std::numeric_limits<float>::infinity();
|
||||||
float t2 = std::numeric_limits<float>::infinity();
|
float t2 = std::numeric_limits<float>::infinity();
|
||||||
|
|
||||||
|
AABBSide side1;
|
||||||
|
AABBSide side2;
|
||||||
|
|
||||||
if (node.type1 != Type::Empty) {
|
if (node.type1 != Type::Empty) {
|
||||||
auto [is_hit, t] = RayBoxIntersection(ray, node.box1, T);
|
auto [is_hit, t] = RayBoxIntersection(ray, node.box1, T, side1);
|
||||||
is_hit1 = is_hit;
|
is_hit1 = is_hit;
|
||||||
t1 = t;
|
t1 = t;
|
||||||
}
|
}
|
||||||
if (node.type2 != Type::Empty) {
|
if (node.type2 != Type::Empty) {
|
||||||
auto [is_hit, t] = RayBoxIntersection(ray, node.box2, T);
|
auto [is_hit, t] = RayBoxIntersection(ray, node.box2, T, side2);
|
||||||
is_hit2 = is_hit;
|
is_hit2 = is_hit;
|
||||||
t2 = t;
|
t2 = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
// possible outcomes:
|
// possible outcomes:
|
||||||
|
|
||||||
// neither hit
|
if (!is_hit1 && !is_hit2) {
|
||||||
if (!is_hit1 && !is_hit2) return false;
|
res.hit = false;
|
||||||
|
return res;
|
||||||
// when both hit
|
}
|
||||||
if (is_hit1 && is_hit2) {
|
else if (is_hit1 && is_hit2) {
|
||||||
// if 1 is a BV and 2 a gameobject, see if gameobject is in front
|
// if 1 is a BV and 2 a gameobject, see if gameobject is in front
|
||||||
if (node.type1 == Type::BoundingVolume && node.type2 == Type::Entity) {
|
if (node.type1 == Type::BoundingVolume && node.type2 == Type::Entity) {
|
||||||
if (t2 < t1) {
|
if (t2 < t1) {
|
||||||
location = (ray.direction * t2) + ray.origin;
|
res.location = (ray.direction * t2) + ray.origin;
|
||||||
t = t2;
|
res.t = t2;
|
||||||
object_index = node.index2;
|
res.object_index = node.index2;
|
||||||
return true;
|
res.side = side2;
|
||||||
|
res.hit = true;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return RaycastTreeNode(ray, bvh_.at(node.index1), location, t, object_index);
|
return RaycastTreeNode(ray, bvh_.at(node.index1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// if 1 is a gameobject and 2 a BV, see if gameobject is in front
|
// if 1 is a gameobject and 2 a BV, see if gameobject is in front
|
||||||
if (node.type1 == Type::Entity && node.type2 == Type::BoundingVolume) {
|
if (node.type1 == Type::Entity && node.type2 == Type::BoundingVolume) {
|
||||||
if (t1 < t2) {
|
if (t1 < t2) {
|
||||||
location = (ray.direction * t1) + ray.origin;
|
res.location = (ray.direction * t1) + ray.origin;
|
||||||
t = t1;
|
res.t = t1;
|
||||||
object_index = node.index1;
|
res.object_index = node.index1;
|
||||||
return true;
|
res.side = side1;
|
||||||
|
res.hit = true;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return RaycastTreeNode(ray, bvh_.at(node.index2), location, t, object_index);
|
return RaycastTreeNode(ray, bvh_.at(node.index2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// if 1 is a BV and 2 is a BV
|
// if 1 is a BV and 2 is a BV
|
||||||
if (node.type1 == Type::BoundingVolume && node.type2 == Type::BoundingVolume) {
|
if (node.type1 == Type::BoundingVolume && node.type2 == Type::BoundingVolume) {
|
||||||
float node1_t{};
|
auto node1_intersection = RaycastTreeNode(ray, bvh_.at(node.index1));
|
||||||
glm::vec3 location1{};
|
auto node2_intersection = RaycastTreeNode(ray, bvh_.at(node.index2));
|
||||||
Entity object_index1{};
|
if (node1_intersection.hit && node2_intersection.hit) {
|
||||||
bool node1_intersects = RaycastTreeNode(ray, bvh_.at(node.index1), location1, node1_t, object_index1);
|
if (node1_intersection.t < node2_intersection.t) {
|
||||||
float node2_t{};
|
res.location = node1_intersection.location;
|
||||||
glm::vec3 location2{};
|
res.t = node1_intersection.t;
|
||||||
Entity object_index2;
|
res.object_index = node1_intersection.object_index;
|
||||||
bool node2_intersects = RaycastTreeNode(ray, bvh_.at(node.index2), location2, node2_t, object_index2);
|
res.side = node1_intersection.side;
|
||||||
if (node1_intersects && node2_intersects) {
|
res.hit = true;
|
||||||
if (node1_t < node2_t) {
|
return res;
|
||||||
location = location1;
|
|
||||||
t = node1_t;
|
|
||||||
object_index = object_index1;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
location = location2;
|
res.location = node2_intersection.location;
|
||||||
t = node2_t;
|
res.t = node2_intersection.t;
|
||||||
object_index = object_index1;
|
res.object_index = node2_intersection.object_index;
|
||||||
return true;
|
res.side = node2_intersection.side;
|
||||||
|
res.hit = true;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (node1_intersects) {
|
else if (node1_intersection.hit) {
|
||||||
t = node1_t;
|
res.location = node1_intersection.location;
|
||||||
location = location1;
|
res.t = node1_intersection.t;
|
||||||
object_index = object_index1;
|
res.object_index = node1_intersection.object_index;
|
||||||
return true;
|
res.side = node1_intersection.side;
|
||||||
|
res.hit = true;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
else if (node2_intersects) {
|
else if (node2_intersection.hit) {
|
||||||
t = node2_t;
|
res.location = node2_intersection.location;
|
||||||
location = location2;
|
res.t = node2_intersection.t;
|
||||||
object_index = object_index2;
|
res.object_index = node2_intersection.object_index;
|
||||||
return true;
|
res.side = node2_intersection.side;
|
||||||
|
res.hit = true;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
res.hit = false;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if 1 is a gameobject and 2 is a gameobject
|
// if 1 is a gameobject and 2 is a gameobject
|
||||||
if (node.type1 == Type::Entity && node.type2 == Type::Entity) {
|
if (node.type1 == Type::Entity && node.type2 == Type::Entity) {
|
||||||
if (t1 < t2) {
|
if (t1 < t2) {
|
||||||
location = (ray.direction * t1) + ray.origin;
|
res.location = (ray.direction * t1) + ray.origin;
|
||||||
t = t1;
|
res.t = t1;
|
||||||
object_index = node.index1;
|
res.object_index = node.index1;
|
||||||
|
res.side = side1;
|
||||||
|
res.hit = true;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
location = (ray.direction * t2) + ray.origin;
|
res.location = (ray.direction * t2) + ray.origin;
|
||||||
t = t2;
|
res.t = t2;
|
||||||
object_index = node.index2;
|
res.object_index = node.index2;
|
||||||
}
|
res.side = side2;
|
||||||
return true;
|
res.hit = true;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// only 1 hits
|
else if (is_hit1) {
|
||||||
if (is_hit1) {
|
|
||||||
switch (node.type1) {
|
switch (node.type1) {
|
||||||
case Type::BoundingVolume:
|
case Type::BoundingVolume:
|
||||||
return RaycastTreeNode(ray, bvh_.at(node.index1), location, t, object_index);
|
return RaycastTreeNode(ray, bvh_.at(node.index1));
|
||||||
case Type::Entity:
|
case Type::Entity:
|
||||||
location = (ray.direction * t1) + ray.origin;
|
res.location = (ray.direction * t1) + ray.origin;
|
||||||
t = t1;
|
res.t = t1;
|
||||||
object_index = node.index1;
|
res.object_index = node.index1;
|
||||||
return true;
|
res.side = side1;
|
||||||
|
res.hit = true;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (is_hit2) {
|
||||||
|
switch (node.type2) {
|
||||||
|
case Type::BoundingVolume:
|
||||||
|
return RaycastTreeNode(ray, bvh_.at(node.index2));
|
||||||
|
case Type::Entity:
|
||||||
|
res.location = (ray.direction * t2) + ray.origin;
|
||||||
|
res.t = t2;
|
||||||
|
res.object_index = node.index2;
|
||||||
|
res.side = side2;
|
||||||
|
res.hit = true;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only 2 hits
|
throw std::runtime_error("RaycastTreeNode() hit end of function. This should not be possible");
|
||||||
if (is_hit2) {
|
|
||||||
switch (node.type2) {
|
|
||||||
case Type::BoundingVolume:
|
|
||||||
return RaycastTreeNode(ray, bvh_.at(node.index2), location, t, object_index);
|
|
||||||
case Type::Entity:
|
|
||||||
location = (ray.direction * t2) + ray.origin;
|
|
||||||
t = t2;
|
|
||||||
object_index = node.index2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
@ -209,28 +209,23 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
|||||||
for (const tg::Material& material : model.materials) {
|
for (const tg::Material& material : model.materials) {
|
||||||
if (material.alphaMode != "OPAQUE") {
|
if (material.alphaMode != "OPAQUE") {
|
||||||
LOG_WARN("Material {} contains alphaMode {} which isn't supported yet", material.name, material.alphaMode);
|
LOG_WARN("Material {} contains alphaMode {} which isn't supported yet", material.name, material.alphaMode);
|
||||||
LOG_WARN("Material will be opaque");
|
|
||||||
}
|
}
|
||||||
if (material.doubleSided == true) {
|
if (material.doubleSided == true) {
|
||||||
LOG_WARN("Material {} specifies double-sided mesh rendering which isn't supported yet", material.name);
|
LOG_WARN("Material {} specifies double-sided mesh rendering which isn't supported yet", material.name);
|
||||||
LOG_WARN("Material will be single-sided.");
|
|
||||||
}
|
}
|
||||||
if (material.emissiveTexture.index != -1 || material.emissiveFactor[0] != 0.0 || material.emissiveFactor[1] != 0.0 ||
|
if (material.emissiveTexture.index != -1 || material.emissiveFactor[0] != 0.0 || material.emissiveFactor[1] != 0.0 ||
|
||||||
material.emissiveFactor[2] != 0.0) {
|
material.emissiveFactor[2] != 0.0) {
|
||||||
LOG_WARN("Material {} contains an emissive texture or non-zero emissive factor. Emission is currently unsupported.", material.name);
|
LOG_WARN("Material {} contains an emissive texture or non-zero emissive factor. Emission is currently unsupported.", material.name);
|
||||||
LOG_WARN("Material will be created without emission.");
|
|
||||||
}
|
}
|
||||||
const auto& baseColorFactor4 = material.pbrMetallicRoughness.baseColorFactor;
|
const auto& baseColorFactor4 = material.pbrMetallicRoughness.baseColorFactor;
|
||||||
if (baseColorFactor4[0] != 1.0 || baseColorFactor4[1] != 1.0 || baseColorFactor4[2] != 1.0 || baseColorFactor4[3] != 1.0) {
|
if (baseColorFactor4[0] != 1.0 || baseColorFactor4[1] != 1.0 || baseColorFactor4[2] != 1.0 || baseColorFactor4[3] != 1.0) {
|
||||||
if (material.pbrMetallicRoughness.baseColorTexture.index != -1) {
|
if (material.pbrMetallicRoughness.baseColorTexture.index != -1) {
|
||||||
LOG_WARN("Material {} contains a base color multiplier which isn't supported yet.", material.name);
|
LOG_WARN("Material {} contains a base color multiplier which isn't supported yet.", material.name);
|
||||||
LOG_WARN("The material's base color texture will be used as-is.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (material.pbrMetallicRoughness.metallicFactor != 1.0 || material.pbrMetallicRoughness.roughnessFactor != 1.0) {
|
if (material.pbrMetallicRoughness.metallicFactor != 1.0 || material.pbrMetallicRoughness.roughnessFactor != 1.0) {
|
||||||
if (material.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) {
|
if (material.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) {
|
||||||
LOG_WARN("Material {} contains a metallic and/or roughness multiplier which isn't supported yet.", material.name);
|
LOG_WARN("Material {} contains a metallic and/or roughness multiplier which isn't supported yet.", material.name);
|
||||||
LOG_WARN("The material's metallic-roughness texture will be used as-is.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +239,6 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG_WARN("Material {} base color texture specifies a UV channel other than zero which is unsupported.", material.name);
|
LOG_WARN("Material {} base color texture specifies a UV channel other than zero which is unsupported.", material.name);
|
||||||
LOG_WARN("Material will be created with a white base color");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (baseColorFactor4[0] != 1.0 || baseColorFactor4[1] != 1.0 || baseColorFactor4[2] != 1.0 || baseColorFactor4[3] != 1.0) {
|
else if (baseColorFactor4[0] != 1.0 || baseColorFactor4[1] != 1.0 || baseColorFactor4[2] != 1.0 || baseColorFactor4[3] != 1.0) {
|
||||||
@ -271,12 +265,11 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG_WARN("Material {} metallic roughness texture specifies a UV channel other than zero which is unsupported.", material.name);
|
LOG_WARN("Material {} metallic roughness texture specifies a UV channel other than zero which is unsupported.", material.name);
|
||||||
LOG_WARN("Material will be created with a default metallic roughness");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG_INFO("Creating a metallic-roughness texture...");
|
LOG_INFO("Creating a metallic-roughness texture...");
|
||||||
const std::vector<double> mr_values{1.0f, material.pbrMetallicRoughness.metallicFactor, material.pbrMetallicRoughness.roughnessFactor, 1.0f};
|
const std::vector<double> mr_values{1.0f, material.pbrMetallicRoughness.roughnessFactor, material.pbrMetallicRoughness.metallicFactor, 1.0f};
|
||||||
Color mr(mr_values);
|
Color mr(mr_values);
|
||||||
if (metal_rough_textures.contains(mr) == false) {
|
if (metal_rough_textures.contains(mr) == false) {
|
||||||
const uint8_t pixel[4] = {mr.r, mr.g, mr.b, mr.a};
|
const uint8_t pixel[4] = {mr.r, mr.g, mr.b, mr.a};
|
||||||
@ -299,7 +292,6 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG_WARN("Material {} occlusion texture specifies a UV channel other than zero which is unsupported.", material.name);
|
LOG_WARN("Material {} occlusion texture specifies a UV channel other than zero which is unsupported.", material.name);
|
||||||
LOG_WARN("Material will be created with no ambient occlusion");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,7 +303,6 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG_WARN("Material {} normal texture specifies a UV channel other than zero which is unsupported.", material.name);
|
LOG_WARN("Material {} normal texture specifies a UV channel other than zero which is unsupported.", material.name);
|
||||||
LOG_WARN("Material will be created with no normal map");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
test/res/models/MY_AXES.glb
Normal file
BIN
test/res/models/MY_AXES.glb
Normal file
Binary file not shown.
BIN
test/res/models/stairs.glb
Normal file
BIN
test/res/models/stairs.glb
Normal file
Binary file not shown.
@ -34,20 +34,17 @@ void CameraControllerSystem::OnUpdate(float ts)
|
|||||||
|
|
||||||
const float dt = ts;
|
const float dt = ts;
|
||||||
|
|
||||||
float dx = scene_->app()->input_manager()->GetAxis("movex");
|
float dx = scene_->app()->input_manager()->GetAxis("movex") * CameraControllerComponent::kSpeedStrafe;
|
||||||
float dy = scene_->app()->input_manager()->GetAxis("movey");
|
float dy = scene_->app()->input_manager()->GetAxis("movey") * CameraControllerComponent::kSpeedForwardBack;
|
||||||
|
|
||||||
// calculate new pitch and yaw
|
// calculate new pitch and yaw
|
||||||
|
|
||||||
constexpr float kMaxPitch = glm::pi<float>();
|
float d_pitch = scene_->app()->input_manager()->GetAxis("looky") * -1.0f * CameraControllerComponent::kCameraSensitivity;
|
||||||
constexpr float kMinPitch = 0.0f;
|
|
||||||
|
|
||||||
float d_pitch = scene_->app()->input_manager()->GetAxis("looky") * -1.0f * c->kCameraSensitivity;
|
|
||||||
c->pitch += d_pitch;
|
c->pitch += d_pitch;
|
||||||
if (c->pitch <= kMinPitch || c->pitch >= kMaxPitch) {
|
if (c->pitch <= CameraControllerComponent::kMinPitch || c->pitch >= CameraControllerComponent::kMaxPitch) {
|
||||||
c->pitch -= d_pitch;
|
c->pitch -= d_pitch;
|
||||||
}
|
}
|
||||||
c->yaw += scene_->app()->input_manager()->GetAxis("lookx") * -1.0f * c->kCameraSensitivity;
|
c->yaw += scene_->app()->input_manager()->GetAxis("lookx") * -1.0f * CameraControllerComponent::kCameraSensitivity;
|
||||||
|
|
||||||
// update position relative to camera direction in xz plane
|
// update position relative to camera direction in xz plane
|
||||||
const glm::vec3 d2x_rotated = glm::rotateZ(glm::vec3{dx, 0.0f, 0.0f}, c->yaw);
|
const glm::vec3 d2x_rotated = glm::rotateZ(glm::vec3{dx, 0.0f, 0.0f}, c->yaw);
|
||||||
@ -58,36 +55,81 @@ void CameraControllerSystem::OnUpdate(float ts)
|
|||||||
// keep vel.z as gravity can increase it every frame
|
// keep vel.z as gravity can increase it every frame
|
||||||
|
|
||||||
// gravity stuff here:
|
// gravity stuff here:
|
||||||
constexpr float g = -9.81f; // constant velocity gravity???
|
c->vel.z += CameraControllerComponent::kGravAccel * dt;
|
||||||
constexpr float player_height = 71.0f * 25.4f / 1000.0f;
|
|
||||||
c->vel.z += g * dt;
|
|
||||||
|
|
||||||
if (scene_->app()->input_manager()->GetButtonPress("jump")) {
|
// jumping
|
||||||
|
if (scene_->app()->input_manager()->GetButtonPress("jump") && c->grounded) {
|
||||||
c->vel.z += 4.4f; // m/s
|
c->vel.z += 4.4f; // m/s
|
||||||
}
|
}
|
||||||
|
|
||||||
// update position with velocity:
|
// update position with velocity:
|
||||||
|
|
||||||
// check for collision during next frame and push back and remove velocity in the normal of the collision direction if so
|
// check horizontal collisions first as otherwise the player may be teleported above a wall instead of colliding against it
|
||||||
engine::Ray ray{};
|
if (c->vel.x != 0.0f || c->vel.y != 0.0f) { // just in case, to avoid a ray with direction = (0,0,0)
|
||||||
ray.origin = t->position;
|
engine::Ray horiz_ray{};
|
||||||
ray.origin.z -= player_height; // check for collision from the player's feet
|
horiz_ray.origin = t->position; // set origin to 'MaxStairHeight' units above player's feet
|
||||||
|
horiz_ray.origin.z += CameraControllerComponent::kMaxStairHeight - CameraControllerComponent::kPlayerHeight;
|
||||||
|
horiz_ray.direction.x = c->vel.x;
|
||||||
|
horiz_ray.direction.y = c->vel.y; // this is normalized by GetRayCast()
|
||||||
|
horiz_ray.direction.z = 0.0f;
|
||||||
|
const engine::Raycast horiz_raycast = scene_->GetSystem<engine::CollisionSystem>()->GetRaycast(horiz_ray);
|
||||||
|
if (horiz_raycast.hit) {
|
||||||
|
const glm::vec2 norm_xy = glm::normalize(glm::vec2{horiz_raycast.normal.x, horiz_raycast.normal.y}) * -1.0f; // make it point towards object
|
||||||
|
const glm::vec2 vel_xy = glm::vec2{ c->vel.x, c->vel.y };
|
||||||
|
// find the extent of the player's velocity in the direction of the wall's normal vector
|
||||||
|
const glm::vec2 partial_vel = norm_xy * glm::dot(norm_xy, vel_xy);
|
||||||
|
const glm::vec2 partial_dX = partial_vel * dt;
|
||||||
|
if (glm::length(partial_dX) > horiz_raycast.distance - CameraControllerComponent::kPlayerCollisionRadius) {
|
||||||
|
// player will collide with wall
|
||||||
|
// push player out of collision zone
|
||||||
|
const glm::vec2 push_vector = glm::normalize(vel_xy) * fmaxf(CameraControllerComponent::kPlayerCollisionRadius, horiz_raycast.distance);
|
||||||
|
t->position.x = horiz_raycast.location.x - push_vector.x;
|
||||||
|
t->position.y = horiz_raycast.location.y - push_vector.y;
|
||||||
|
c->vel.x -= partial_vel.x;
|
||||||
|
c->vel.y -= partial_vel.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const glm::vec3 dX = c->vel * dt; // where player will end up with no collision
|
// check falling collisions
|
||||||
ray.direction = glm::normalize(dX);
|
if (c->vel.z < 0.0f) { // if falling
|
||||||
const engine::Raycast raycast = scene_->GetSystem<engine::CollisionSystem>()->GetRaycast(ray);
|
engine::Ray fall_ray{};
|
||||||
if (raycast.hit && raycast.distance < glm::length(dX)) {
|
fall_ray.origin = t->position;
|
||||||
// will collide
|
fall_ray.origin.z += CameraControllerComponent::kMaxStairHeight - CameraControllerComponent::kPlayerHeight;
|
||||||
t->position -= raycast.distance * ray.direction; // push out of collision zone
|
fall_ray.direction = {0.0f, 0.0f, -1.0f}; // down
|
||||||
c->vel.z = 0.0f; // remove velocity normal to collision surface
|
const engine::Raycast fall_raycast = scene_->GetSystem<engine::CollisionSystem>()->GetRaycast(fall_ray);
|
||||||
|
if (fall_raycast.hit) { // there is ground below player
|
||||||
|
// find how far the player will move (downwards) if velocity is applied without collision
|
||||||
|
const float mag_dz = fabsf(c->vel.z * dt);
|
||||||
|
// check if the player will be less than 'height' units above the collided ground
|
||||||
|
if (mag_dz > fall_raycast.distance - CameraControllerComponent::kMaxStairHeight) {
|
||||||
|
LOG_INFO("HIT");
|
||||||
|
// push player up to ground level and set as grounded
|
||||||
|
t->position.z = fall_raycast.location.z + CameraControllerComponent::kPlayerHeight;
|
||||||
|
c->vel.z = 0.0f;
|
||||||
|
c->grounded = true;
|
||||||
|
}
|
||||||
|
else { // there is ground below player, however they are not grounded
|
||||||
|
c->grounded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // there is no ground below player (THEY ARE FALLING INTO THE VOID)
|
||||||
|
c->grounded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c->vel.z > 0.0f) {
|
||||||
|
c->grounded = false; // they are jumping
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->was_grounded != c->grounded) {
|
||||||
|
LOG_INFO("GROUNDED? {}", c->grounded);
|
||||||
|
c->was_grounded = c->grounded;
|
||||||
}
|
}
|
||||||
|
|
||||||
t->position += c->vel * dt;
|
t->position += c->vel * dt;
|
||||||
|
|
||||||
constexpr float kMaxDistanceFromOrigin = 10000.0f;
|
if (glm::length(t->position) > CameraControllerComponent::kMaxDistanceFromOrigin) {
|
||||||
|
t->position = {0.0f, 0.0f, 100.0f};
|
||||||
if (glm::length(t->position) > kMaxDistanceFromOrigin) {
|
|
||||||
t->position = {0.0f, 0.0f, 10.0f};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ROTATION STUFF */
|
/* ROTATION STUFF */
|
||||||
@ -122,6 +164,9 @@ void CameraControllerSystem::OnUpdate(float ts)
|
|||||||
|
|
||||||
if (scene_->app()->window()->GetKeyPress(engine::inputs::Key::K_R)) {
|
if (scene_->app()->window()->GetKeyPress(engine::inputs::Key::K_R)) {
|
||||||
t->position = {0.0f, 0.0f, 10.0f};
|
t->position = {0.0f, 0.0f, 10.0f};
|
||||||
|
c->vel = {0.0f, 0.0f, 0.0f};
|
||||||
|
c->pitch = glm::half_pi<float>();
|
||||||
|
c->yaw = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scene_->app()->input_manager()->GetButtonPress("fullscreen")) {
|
if (scene_->app()->input_manager()->GetButtonPress("fullscreen")) {
|
||||||
@ -136,14 +181,38 @@ void CameraControllerSystem::OnUpdate(float ts)
|
|||||||
scene_->app()->scene_manager()->SetActiveScene(next_scene_);
|
scene_->app()->scene_manager()->SetActiveScene(next_scene_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scene_->app()->window()->GetButtonPress(engine::inputs::MouseButton::M_LEFT)) {
|
static std::vector<engine::Line> perm_lines{};
|
||||||
|
|
||||||
|
if (scene_->app()->window()->GetButton(engine::inputs::MouseButton::M_LEFT)) {
|
||||||
engine::Ray ray{};
|
engine::Ray ray{};
|
||||||
ray.origin = t->position;
|
ray.origin = t->position;
|
||||||
ray.direction = glm::vec3(glm::mat4_cast(t->rotation) * glm::vec4{0.0f, 0.0f, -1.0f, 1.0f});
|
ray.direction = glm::vec3(glm::mat4_cast(t->rotation) * glm::vec4{0.0f, 0.0f, -1.0f, 1.0f});
|
||||||
engine::Raycast cast = scene_->GetSystem<engine::CollisionSystem>()->GetRaycast(ray);
|
engine::Raycast cast = scene_->GetSystem<engine::CollisionSystem>()->GetRaycast(ray);
|
||||||
|
|
||||||
if (cast.hit) {
|
if (cast.hit) {
|
||||||
LOG_INFO("Raycast hit {}", scene_->GetComponent<engine::TransformComponent>(cast.hit_entity)->tag);
|
|
||||||
LOG_INFO("Distance: {} m", cast.distance);
|
LOG_INFO("Distance: {} m", cast.distance);
|
||||||
|
LOG_INFO("Location: {} {} {}", cast.location.x, cast.location.y, cast.location.z);
|
||||||
|
LOG_INFO("Normal: {} {} {}", cast.normal.x, cast.normal.y, cast.normal.z);
|
||||||
|
LOG_INFO("Ray direction: {} {} {}", ray.direction.x, ray.direction.y, ray.direction.z);
|
||||||
|
LOG_INFO("Hit Entity: {}", scene_->GetComponent<engine::TransformComponent>(cast.hit_entity)->tag);
|
||||||
|
perm_lines.emplace_back(ray.origin, cast.location, glm::vec3{0.0f, 0.0f, 1.0f});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (scene_->app()->window()->GetButtonPress(engine::inputs::MouseButton::M_RIGHT)) {
|
||||||
|
engine::Ray horiz_ray{};
|
||||||
|
horiz_ray.origin = t->position; // set origin to 'MaxStairHeight' units above player's feet
|
||||||
|
horiz_ray.origin.z += CameraControllerComponent::kMaxStairHeight - CameraControllerComponent::kPlayerHeight;
|
||||||
|
horiz_ray.direction.x = c->vel.x;
|
||||||
|
horiz_ray.direction.y = c->vel.y; // this is normalized by GetRayCast()
|
||||||
|
horiz_ray.direction.z = 0.0f;
|
||||||
|
const engine::Raycast cast = scene_->GetSystem<engine::CollisionSystem>()->GetRaycast(horiz_ray);
|
||||||
|
if (cast.hit) {
|
||||||
|
LOG_INFO("Distance: {} m", cast.distance);
|
||||||
|
LOG_INFO("Location: {} {} {}", cast.location.x, cast.location.y, cast.location.z);
|
||||||
|
LOG_INFO("Normal: {} {} {}", cast.normal.x, cast.normal.y, cast.normal.z);
|
||||||
|
perm_lines.emplace_back(horiz_ray.origin, cast.location, glm::vec3{ 0.0f, 0.0f, 1.0f });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scene_->app()->debug_lines.insert(scene_->app()->debug_lines.end(), perm_lines.begin(), perm_lines.end());
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,21 @@
|
|||||||
#include "ecs.h"
|
#include "ecs.h"
|
||||||
|
|
||||||
struct CameraControllerComponent {
|
struct CameraControllerComponent {
|
||||||
static constexpr float kWalkSpeed = 4.0f;
|
static constexpr float kSpeedForwardBack = 4.0f;
|
||||||
|
static constexpr float kSpeedStrafe = 4.0f;
|
||||||
static constexpr float kCameraSensitivity = 0.007f;
|
static constexpr float kCameraSensitivity = 0.007f;
|
||||||
|
static constexpr float kMaxDistanceFromOrigin = 10000.0f;
|
||||||
|
static constexpr float kGravAccel = -9.81f;
|
||||||
|
static constexpr float kPlayerHeight = 71.0f * 25.4f / 1000.0f;
|
||||||
|
static constexpr float kMaxStairHeight = 0.2f;
|
||||||
|
static constexpr float kPlayerCollisionRadius = 0.2f;
|
||||||
|
static constexpr float kMaxPitch = glm::pi<float>();
|
||||||
|
static constexpr float kMinPitch = 0.0f;
|
||||||
float yaw = 0.0f;
|
float yaw = 0.0f;
|
||||||
float pitch = glm::half_pi<float>();
|
float pitch = glm::half_pi<float>();
|
||||||
glm::vec3 vel{ 0.0f, 0.0f, 0.0f };
|
glm::vec3 vel{ 0.0f, 0.0f, 0.0f };
|
||||||
|
bool grounded = false;
|
||||||
|
bool was_grounded = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CameraControllerSystem
|
class CameraControllerSystem
|
||||||
|
@ -127,18 +127,20 @@ void PlayGame(GameSettings settings)
|
|||||||
skybox_renderable->material->SetAlbedoTexture(app.GetResource<engine::Texture>("builtin.black"));
|
skybox_renderable->material->SetAlbedoTexture(app.GetResource<engine::Texture>("builtin.black"));
|
||||||
|
|
||||||
engine::Entity helmet = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/DamagedHelmet.glb"));
|
engine::Entity helmet = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/DamagedHelmet.glb"));
|
||||||
main_scene->GetPosition(helmet) += glm::vec3{20.0f, 10.0f, 5.0f};
|
main_scene->GetPosition(helmet) += glm::vec3{5.0f, 5.0f, 1.0f};
|
||||||
|
main_scene->GetScale(helmet) *= 3.0f;
|
||||||
|
|
||||||
engine::Entity toycar = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/ToyCar.glb"));
|
engine::Entity toycar = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/ToyCar.glb"));
|
||||||
main_scene->GetScale(toycar) *= 100.0f;
|
main_scene->GetScale(toycar) *= 100.0f;
|
||||||
auto car_spin = main_scene->AddComponent<engine::CustomComponent>(toycar);
|
main_scene->GetPosition(toycar).z += 1.8f;
|
||||||
car_spin->onInit = []() -> void {};
|
|
||||||
car_spin->onUpdate = [&](float dt) -> void {
|
engine::Entity stairs = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/stairs.glb"));
|
||||||
static float yaw = 0.0f;
|
main_scene->GetPosition(stairs) += glm::vec3{-8.0f, -5.0f, 0.1f};
|
||||||
yaw += dt;
|
main_scene->GetRotation(stairs) = glm::angleAxis(glm::half_pi<float>(), glm::vec3{ 0.0f, 0.0f, 1.0f });
|
||||||
main_scene->GetRotation(toycar) = glm::angleAxis(yaw, glm::vec3{0.0f, 0.0f, 1.0f});
|
main_scene->GetRotation(stairs) *= glm::angleAxis(glm::half_pi<float>(), glm::vec3{ 1.0f, 0.0f, 0.0f });
|
||||||
main_scene->GetRotation(toycar) *= glm::angleAxis(glm::half_pi<float>(), glm::vec3{1.0f, 0.0f, 0.0f});
|
|
||||||
};
|
engine::Entity axes = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/MY_AXES.glb"));
|
||||||
|
main_scene->GetPosition(axes) += glm::vec3{-40.0f, -40.0f, 1.0f};
|
||||||
}
|
}
|
||||||
|
|
||||||
start_scene->GetSystem<CameraControllerSystem>()->next_scene_ = main_scene;
|
start_scene->GetSystem<CameraControllerSystem>()->next_scene_ = main_scene;
|
||||||
|
@ -1 +0,0 @@
|
|||||||
This is a test
|
|
Loading…
Reference in New Issue
Block a user