fix collision tree

This commit is contained in:
bailehuni 2024-03-14 04:25:02 +00:00
parent d9ea79170f
commit daba5332b9
11 changed files with 403 additions and 298 deletions

View File

@ -24,6 +24,11 @@ struct UniformDescriptor {
gfx::UniformBuffer* uniform_buffer; gfx::UniformBuffer* uniform_buffer;
}; };
struct Line {
glm::vec3 pos1;
glm::vec3 pos2;
};
class Renderer : private ApplicationComponent { class Renderer : private ApplicationComponent {
public: public:
Renderer(Application& app, gfx::GraphicsSettings settings); Renderer(Application& app, gfx::GraphicsSettings settings);
@ -33,23 +38,17 @@ class Renderer : private ApplicationComponent {
void PreRender(bool window_is_resized, glm::mat4 camera_transform); void PreRender(bool window_is_resized, glm::mat4 camera_transform);
// staticList can be nullptr to render nothing // staticList can be nullptr to render nothing
void Render(const RenderList* static_list, const RenderList* dynamic_list); void Render(const RenderList* static_list, const RenderList* dynamic_list, const std::vector<Line>& debug_lines);
// getters // getters
GFXDevice* GetDevice() { return device_.get(); } GFXDevice* GetDevice() { return device_.get(); }
const gfx::DescriptorSetLayout* GetGlobalSetLayout() { const gfx::DescriptorSetLayout* GetGlobalSetLayout() { return global_uniform.layout; }
return global_uniform.layout;
}
const gfx::DescriptorSetLayout* GetFrameSetLayout() { const gfx::DescriptorSetLayout* GetFrameSetLayout() { return frame_uniform.layout; }
return frame_uniform.layout;
}
const gfx::DescriptorSetLayout* GetMaterialSetLayout() { const gfx::DescriptorSetLayout* GetMaterialSetLayout() { return material_set_layout; }
return material_set_layout;
}
std::unordered_map<gfx::SamplerInfo, const gfx::Sampler*> samplers; std::unordered_map<gfx::SamplerInfo, const gfx::Sampler*> samplers;

View File

@ -12,6 +12,7 @@
#include "ecs.h" #include "ecs.h"
#include "event_system.h" #include "event_system.h"
#include "components/transform.h"
namespace engine { namespace engine {
@ -32,38 +33,62 @@ class Scene {
/* ecs stuff */ /* ecs stuff */
Entity CreateEntity(const std::string& tag, Entity parent = 0, Entity CreateEntity(const std::string& tag, Entity parent = 0, const glm::vec3& pos = glm::vec3{0.0f, 0.0f, 0.0f},
const glm::vec3& pos = glm::vec3{0.0f, 0.0f, 0.0f}, const glm::quat& rot = glm::quat{1.0f, 0.0f, 0.0f, 0.0f}, const glm::vec3& scl = glm::vec3{1.0f, 1.0f, 1.0f});
const glm::quat& rot = glm::quat{1.0f, 0.0f, 0.0f, 0.0f},
const glm::vec3& scl = glm::vec3{1.0f, 1.0f, 1.0f});
Entity GetEntity(const std::string& tag, Entity parent = 0); Entity GetEntity(const std::string& tag, Entity parent = 0);
size_t GetComponentSignaturePosition(size_t hash); size_t GetComponentSignaturePosition(size_t hash);
template <typename T> template <typename T>
void RegisterComponent() { void RegisterComponent()
{
size_t hash = typeid(T).hash_code(); size_t hash = typeid(T).hash_code();
assert(component_arrays_.contains(hash) == false && assert(component_arrays_.contains(hash) == false && "Registering component type more than once.");
"Registering component type more than once.");
component_arrays_.emplace(hash, std::make_unique<ComponentArray<T>>()); component_arrays_.emplace(hash, std::make_unique<ComponentArray<T>>());
size_t signature_position = next_signature_position_; size_t signature_position = next_signature_position_;
++next_signature_position_; ++next_signature_position_;
assert(signature_position < kMaxComponents && assert(signature_position < kMaxComponents && "Registering too many components!");
"Registering too many components!");
assert(component_signature_positions_.contains(hash) == false); assert(component_signature_positions_.contains(hash) == false);
component_signature_positions_.emplace(hash, signature_position); component_signature_positions_.emplace(hash, signature_position);
} }
template <typename T> template <typename T>
T* GetComponent(Entity entity) { T* GetComponent(Entity entity)
{
// check if component exists on entity:
size_t hash = typeid(T).hash_code();
size_t signature_position = component_signature_positions_.at(hash);
const auto& entity_signature = signatures_.at(entity);
if (entity_signature.test(signature_position) == false) {
return nullptr;
}
auto array = GetComponentArray<T>(); auto array = GetComponentArray<T>();
return array->GetData(entity); return array->GetData(entity);
} }
// because GetComponent<Transformzzzzzz takes too long
TransformComponent* GetTransform(Entity entity) {
return GetComponent<TransformComponent>(entity);
}
glm::vec3& GetPosition(Entity entity) {
return GetTransform(entity)->position;
}
glm::quat& GetRotation(Entity entity) {
return GetTransform(entity)->rotation;
}
glm::vec3& GetScale(Entity entity) {
return GetTransform(entity)->scale;
}
template <typename T> template <typename T>
T* AddComponent(Entity entity, const T& comp = T{}) { T* AddComponent(Entity entity, const T& comp = T{})
{
size_t hash = typeid(T).hash_code(); size_t hash = typeid(T).hash_code();
auto array = GetComponentArray<T>(); auto array = GetComponentArray<T>();
@ -86,13 +111,15 @@ class Scene {
} }
template <typename T> template <typename T>
void RegisterSystem() { void RegisterSystem()
{
size_t hash = typeid(T).hash_code(); size_t hash = typeid(T).hash_code();
ecs_systems_.emplace_back(hash, std::make_unique<T>(this)); ecs_systems_.emplace_back(hash, std::make_unique<T>(this));
} }
template <typename T> template <typename T>
T* GetSystem() { T* GetSystem()
{
size_t hash = typeid(T).hash_code(); size_t hash = typeid(T).hash_code();
System* found_system = nullptr; System* found_system = nullptr;
for (auto& [system_hash, system] : ecs_systems_) { for (auto& [system_hash, system] : ecs_systems_) {
@ -124,14 +151,14 @@ class Scene {
// maps entity ids to their signatures // maps entity ids to their signatures
std::unordered_map<Entity, std::bitset<kMaxComponents>> signatures_{}; std::unordered_map<Entity, std::bitset<kMaxComponents>> signatures_{};
// maps component hashes to their arrays // maps component hashes to their arrays
std::unordered_map<size_t, std::unique_ptr<IComponentArray>> std::unordered_map<size_t, std::unique_ptr<IComponentArray>> component_arrays_{};
component_arrays_{};
// hashes and associated systems // hashes and associated systems
std::vector<std::pair<size_t, std::unique_ptr<System>>> ecs_systems_{}; std::vector<std::pair<size_t, std::unique_ptr<System>>> ecs_systems_{};
template <typename T> template <typename T>
ComponentArray<T>* GetComponentArray() { ComponentArray<T>* GetComponentArray()
{
size_t hash = typeid(T).hash_code(); size_t hash = typeid(T).hash_code();
auto it = component_arrays_.find(hash); auto it = component_arrays_.find(hash);
if (it == component_arrays_.end()) { if (it == component_arrays_.end()) {

View File

@ -33,7 +33,7 @@ class CollisionSystem : public System {
Raycast GetRaycast(Ray ray); Raycast GetRaycast(Ray ray);
private: public:
// one node of the BVH // one node of the BVH
struct BiTreeNode { struct BiTreeNode {
enum class Type : uint8_t { BoundingVolume, Entity, Empty }; enum class Type : uint8_t { BoundingVolume, Entity, Empty };
@ -53,11 +53,12 @@ class CollisionSystem : public System {
PrimitiveInfo(const AABB& aabb, Entity entity_idx); PrimitiveInfo(const AABB& aabb, Entity entity_idx);
}; };
std::vector<BiTreeNode> bvh_{};
private:
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;
std::vector<BiTreeNode> bvh_{};
bool RaycastTreeNode(const Ray& ray, const BiTreeNode& node, glm::vec3& location, float& t, Entity& object_index); bool RaycastTreeNode(const Ray& ray, const BiTreeNode& node, glm::vec3& location, float& t, Entity& object_index);
static int BuildNode(std::vector<PrimitiveInfo>& prims, std::vector<BiTreeNode>& tree_nodes); static int BuildNode(std::vector<PrimitiveInfo>& prims, std::vector<BiTreeNode>& tree_nodes);

View File

@ -33,7 +33,7 @@ void main() {
const float roughness = metallic_roughness.b; const float roughness = metallic_roughness.b;
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) * 5.0;
const vec3 emission = vec3(0.0, 0.0, 0.0); const vec3 emission = vec3(0.0, 0.0, 0.0);
const float ao = texture(materialSetOcclusionSampler, fragUV).r; const float ao = texture(materialSetOcclusionSampler, fragUV).r;
@ -42,8 +42,8 @@ void main() {
const vec3 N = GetNormal(); const vec3 N = GetNormal();
const vec3 V = normalize(fragViewPosTangentSpace - fragPosTangentSpace); const vec3 V = normalize(fragViewPosTangentSpace - fragPosTangentSpace);
//const vec3 L = normalize(fragLightPosTangentSpace - fragPosTangentSpace); const vec3 L = normalize(fragLightPosTangentSpace - fragPosTangentSpace);
const vec3 L = normalize(vec3(5.0, 0.0, 3.0)); //const vec3 L = normalize(vec3(5.0, 0.0, 3.0));
const vec3 H = normalize(V + L); const vec3 H = normalize(V + L);
//const vec3 dielectric_brdf = FresnelMix(); //const vec3 dielectric_brdf = FresnelMix();

View File

@ -25,6 +25,7 @@
#include "resources/texture.h" #include "resources/texture.h"
#include "systems/mesh_render_system.h" #include "systems/mesh_render_system.h"
#include "components/transform.h" #include "components/transform.h"
#include "components/collider.h"
#include "scene.h" #include "scene.h"
#include "scene_manager.h" #include "scene_manager.h"
#include "window.h" #include "window.h"
@ -34,6 +35,7 @@
#include <direct.h> #include <direct.h>
#define WIN_MAX_PATH 260 #define WIN_MAX_PATH 260
#endif #endif
#include <systems/collisions.h>
static struct ImGuiThings { static struct ImGuiThings {
ImGuiContext* context; ImGuiContext* context;
@ -114,8 +116,8 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
shaderSettings.cull_backface = true; shaderSettings.cull_backface = true;
shaderSettings.write_z = true; shaderSettings.write_z = true;
shaderSettings.render_order = 0; shaderSettings.render_order = 0;
auto fancyShader = std::make_unique<Shader>(renderer(), GetResourcePath("engine/shaders/fancy.vert"), auto fancyShader =
GetResourcePath("engine/shaders/fancy.frag"), shaderSettings); std::make_unique<Shader>(renderer(), GetResourcePath("engine/shaders/fancy.vert"), GetResourcePath("engine/shaders/fancy.frag"), shaderSettings);
GetResourceManager<Shader>()->AddPersistent("builtin.fancy", std::move(fancyShader)); GetResourceManager<Shader>()->AddPersistent("builtin.fancy", std::move(fancyShader));
} }
{ {
@ -129,14 +131,14 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
shaderSettings.cull_backface = true; shaderSettings.cull_backface = true;
shaderSettings.write_z = false; shaderSettings.write_z = false;
shaderSettings.render_order = 1; shaderSettings.render_order = 1;
auto skyboxShader = std::make_unique<Shader>(renderer(), GetResourcePath("engine/shaders/skybox.vert"), auto skyboxShader =
GetResourcePath("engine/shaders/skybox.frag"), shaderSettings); std::make_unique<Shader>(renderer(), GetResourcePath("engine/shaders/skybox.vert"), GetResourcePath("engine/shaders/skybox.frag"), shaderSettings);
GetResourceManager<Shader>()->AddPersistent("builtin.skybox", std::move(skyboxShader)); GetResourceManager<Shader>()->AddPersistent("builtin.skybox", std::move(skyboxShader));
} }
/* default textures */ /* default textures */
{ {
const uint8_t pixel[4] = { 255, 255, 255, 255 }; const uint8_t pixel[4] = {255, 255, 255, 255};
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;
@ -146,7 +148,7 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
GetResourceManager<Texture>()->AddPersistent("builtin.white", std::move(whiteTexture)); GetResourceManager<Texture>()->AddPersistent("builtin.white", std::move(whiteTexture));
} }
{ {
const uint8_t pixel[4] = { 0, 0, 0, 255 }; const uint8_t pixel[4] = {0, 0, 0, 255};
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;
@ -156,7 +158,7 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
GetResourceManager<Texture>()->AddPersistent("builtin.black", std::move(blackTexture)); GetResourceManager<Texture>()->AddPersistent("builtin.black", std::move(blackTexture));
} }
{ {
const uint8_t pixel[4] = { 127, 127, 255, 255 }; const uint8_t pixel[4] = {127, 127, 255, 255};
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;
@ -166,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, 0, 127, 255};
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;
@ -268,7 +270,7 @@ void Application::GameLoop()
int depth = find_depth(i, 0); int depth = find_depth(i, 0);
for (int j = 0; j < depth; ++j) tabs += std::string{" "}; for (int j = 0; j < depth; ++j) tabs += std::string{" "};
ImGui::Text("%s%s", tabs.c_str(), t->tag.c_str()); ImGui::Text("%s%s", tabs.c_str(), t->tag.c_str());
//ImGui::Text("%.1f %.1f %.1f", t->position.x, t->position.y, t->position.z); // ImGui::Text("%.1f %.1f %.1f", t->position.x, t->position.y, t->position.z);
} }
} }
else { else {
@ -283,6 +285,7 @@ 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) {
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>();
@ -290,7 +293,7 @@ void Application::GameLoop()
dynamic_list = mesh_render_system->GetDynamicRenderList(); dynamic_list = mesh_render_system->GetDynamicRenderList();
} }
renderer_->PreRender(window()->GetWindowResized(), camera_transform); renderer_->PreRender(window()->GetWindowResized(), camera_transform);
renderer_->Render(static_list, dynamic_list); renderer_->Render(static_list, dynamic_list, debug_lines);
/* poll events */ /* poll events */
window_->GetInputAndEvents(); window_->GetInputAndEvents();

View File

@ -62,7 +62,7 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
debug_pipeline_info.alpha_blending = false; debug_pipeline_info.alpha_blending = false;
debug_pipeline_info.backface_culling = false; // probably ignored for line rendering debug_pipeline_info.backface_culling = false; // probably ignored for line rendering
debug_pipeline_info.write_z = false; // lines don't need the depth buffer debug_pipeline_info.write_z = false; // lines don't need the depth buffer
//debug_pipeline_info.descriptor_set_layouts = empty; // debug_pipeline_info.descriptor_set_layouts = empty;
debug_pipeline_info.line_primitives = true; debug_pipeline_info.line_primitives = true;
debug_rendering_things_.pipeline = device_->CreatePipeline(debug_pipeline_info); debug_rendering_things_.pipeline = device_->CreatePipeline(debug_pipeline_info);
@ -104,7 +104,7 @@ void Renderer::PreRender(bool window_is_resized, glm::mat4 camera_transform)
device_->WriteUniformBuffer(frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data); device_->WriteUniformBuffer(frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data);
} }
void Renderer::Render(const RenderList* static_list, const RenderList* dynamic_list) void Renderer::Render(const RenderList* static_list, const RenderList* dynamic_list, const std::vector<Line>& debug_lines)
{ {
last_bound_pipeline_ = nullptr; last_bound_pipeline_ = nullptr;
@ -124,8 +124,20 @@ void Renderer::Render(const RenderList* static_list, const RenderList* dynamic_l
// 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] = {}; glm::vec4 debug_positions[2] = {};
debug_positions[0] = global_uniform.uniform_buffer_data.data * frame_uniform.uniform_buffer_data.data * glm::vec4{ 0.0f, 0.0f, 0.0f, 1.0f }; for (const Line& l : debug_lines) {
debug_positions[1] = global_uniform.uniform_buffer_data.data * frame_uniform.uniform_buffer_data.data * glm::vec4{ 0.0f, 0.0f, 1.0f, 1.0f }; debug_positions[0] = 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);
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(glm::vec4) * 2, debug_positions);
device_->CmdDraw(draw_buffer, 2, 1, 0, 0);
}
// also make a lil crosshair
debug_positions[0] = glm::vec4(-0.05f, 0.0f, 0.0f, 1.0f);
debug_positions[1] = 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);
device_->CmdDraw(draw_buffer, 2, 1, 0, 0);
debug_positions[0] = glm::vec4(0.0f, -0.05f, 0.0f, 1.0f);
debug_positions[1] = 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(glm::vec4) * 2, debug_positions);
device_->CmdDraw(draw_buffer, 2, 1, 0, 0); device_->CmdDraw(draw_buffer, 2, 1, 0, 0);

View File

@ -78,13 +78,37 @@ void CollisionSystem::OnUpdate(float ts)
transformed_box.max = t->world_matrix * glm::vec4(c->aabb.max, 1.0f); transformed_box.max = t->world_matrix * glm::vec4(c->aabb.max, 1.0f);
// if a mesh is not rotated a multiple of 90 degrees, the box will not fit the mesh // if a mesh is not rotated a multiple of 90 degrees, the box will not fit the mesh
// TODO fix it // TODO fix it
prims.emplace_back(c->aabb, entity);
// correct min and max
AABB box{};
box.min.x = fminf(transformed_box.min.x, transformed_box.max.x);
box.min.y = fminf(transformed_box.min.y, transformed_box.max.y);
box.min.z = fminf(transformed_box.min.z, transformed_box.max.z);
box.max.x = fmaxf(transformed_box.min.x, transformed_box.max.x);
box.max.y = fmaxf(transformed_box.min.y, transformed_box.max.y);
box.max.z = fmaxf(transformed_box.min.z, transformed_box.max.z);
prims.emplace_back(box, entity);
} }
bvh_.clear(); bvh_.clear();
bvh_.reserve(entities_.size() * 3 / 2); // from testing, bvh is usually 20% larger than number of objects bvh_.reserve(entities_.size() * 3 / 2); // from testing, bvh is usually 20% larger than number of objects
BuildNode(prims, bvh_); BuildNode(prims, bvh_);
// check AABB mins and maxes are the correct order
for (const auto& node : bvh_) {
if (node.type1 != BiTreeNode::Type::Empty) {
if (node.box1.max.x < node.box1.min.x) abort();
if (node.box1.max.y < node.box1.min.y) abort();
if (node.box1.max.z < node.box1.min.z) abort();
}
if (node.type2 != BiTreeNode::Type::Empty) {
if (node.box2.max.x < node.box2.min.x) abort();
if (node.box2.max.y < node.box2.min.y) abort();
if (node.box2.max.z < node.box2.min.z) abort();
}
}
LOG_INFO("BUILT BVH!"); LOG_INFO("BUILT BVH!");
colliders_size_last_update_ = colliders_size_now_; colliders_size_last_update_ = colliders_size_now_;
@ -94,10 +118,13 @@ void CollisionSystem::OnUpdate(float ts)
Raycast CollisionSystem::GetRaycast(Ray ray) Raycast CollisionSystem::GetRaycast(Ray ray)
{ {
Raycast res{}; Raycast res{};
res.hit = false;
ray.direction = glm::normalize(ray.direction); ray.direction = glm::normalize(ray.direction);
if (!bvh_.empty()) {
res.hit = RaycastTreeNode(ray, bvh_.back(), res.location, res.distance, res.hit_entity); res.hit = RaycastTreeNode(ray, bvh_.back(), res.location, res.distance, res.hit_entity);
}
return res; return res;
} }
@ -109,20 +136,41 @@ CollisionSystem::PrimitiveInfo::PrimitiveInfo(const AABB& aabb, Entity entity_id
int CollisionSystem::BuildNode(std::vector<PrimitiveInfo>& prims, std::vector<BiTreeNode>& tree_nodes) int CollisionSystem::BuildNode(std::vector<PrimitiveInfo>& prims, std::vector<BiTreeNode>& tree_nodes)
{ {
if (prims.size() == 0) throw std::runtime_error("Cannot build BVH with no primitives!"); 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 { return (p1.centroid.x < p2.centroid.x); }, [](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool {
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool { return (p1.centroid.y < p2.centroid.y); }, return (p1.centroid.x < p2.centroid.x);
[](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 { return (p1.box.min.x < p2.box.min.x); }, [](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool {
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool { return (p1.box.min.y < p2.box.min.y); }, return (p1.box.min.x < p2.box.min.x);
[](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 { return (p1.box.max.x < p2.box.max.x); }, [](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool {
[](const PrimitiveInfo& p1, const PrimitiveInfo& p2) -> bool { return (p1.box.max.y < p2.box.max.y); }, return (p1.box.max.x < p2.box.max.x);
[](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{};
@ -142,43 +190,31 @@ 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 = float box1_main_min = reinterpret_cast<const float*>(&(std::min_element(prims.begin(), prims.begin() + i + 1, box_min_tests[axis])->box.min))[axis];
reinterpret_cast<const float*>(&(std::min_element(prims.begin(), prims.begin() + i + 1, box_min_tests[axis])->box.min))[axis]; float box1_main_max = reinterpret_cast<const float*>(&(std::max_element(prims.begin(), prims.begin() + i + 1, box_max_tests[axis])->box.max))[axis];
float box1_main_max = float box2_main_min = reinterpret_cast<const float*>(&(std::min_element(prims.begin() + i + 1, prims.end(), box_min_tests[axis])->box.min))[axis];
reinterpret_cast<const float*>(&(std::max_element(prims.begin(), prims.begin() + i + 1, box_max_tests[axis])->box.max))[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 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 = 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];
reinterpret_cast<const float*>(&(std::min_element(prims.begin(), prims.begin() + i + 1, box_min_tests[other_axis1])->box.min))[other_axis1]; 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];
float box1_max1 = 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];
reinterpret_cast<const float*>(&(std::max_element(prims.begin(), prims.begin() + i + 1, box_max_tests[other_axis1])->box.max))[other_axis1]; 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 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 = 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];
reinterpret_cast<const float*>(&(std::min_element(prims.begin() + i + 1, prims.end(), box_min_tests[other_axis1])->box.min))[other_axis1]; 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];
float box2_max1 = 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];
reinterpret_cast<const float*>(&(std::max_element(prims.begin() + i + 1, prims.end(), box_max_tests[other_axis1])->box.max))[other_axis1]; 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];
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) {
@ -235,7 +271,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";
} }
} }
} }
@ -254,6 +290,7 @@ 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) {

BIN
test/res/models/cubes.glb Normal file

Binary file not shown.

View File

@ -39,7 +39,7 @@ void CameraControllerSystem::OnUpdate(float ts)
if (scene_->app()->input_manager()->GetButton("sprint")) speed *= 10.0f; if (scene_->app()->input_manager()->GetButton("sprint")) speed *= 10.0f;
float dx = scene_->app()->input_manager()->GetAxis("movex"); float dx = scene_->app()->input_manager()->GetAxis("movex");
float dy = (-scene_->app()->input_manager()->GetAxis("movey")); float dy = scene_->app()->input_manager()->GetAxis("movey");
// calculate new pitch and yaw // calculate new pitch and yaw
@ -55,15 +55,35 @@ void CameraControllerSystem::OnUpdate(float ts)
// 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);
const glm::vec3 d2y_rotated = glm::rotateZ(glm::rotateX(glm::vec3{0.0f, 0.0f, dy}, c->pitch), c->yaw); const glm::vec3 d2y_rotated = glm::rotateZ(glm::vec3{0.0f, dy, 0.0f}, c->yaw);
glm::vec3 h_vel = (d2x_rotated + d2y_rotated); glm::vec3 h_vel = (d2x_rotated + d2y_rotated);
h_vel *= speed; h_vel *= speed;
t->position += h_vel * dt; t->position += h_vel * dt;
// gravity stuff here:
constexpr float g = -9.81f; // constant velocity gravity???
constexpr float player_height = 71.0f * 25.4f / 1000.0f;
c->vel.z += g * dt;
// check for collision during next frame and push back and remove velocity in the normal of the collision direction if so
engine::Ray ray{};
ray.origin = t->position;
ray.origin.z -= player_height; // check for collision from the player's feet
ray.direction = c->
const engine::Raycast fall_raycast = scene_->GetSystem<engine::CollisionSystem>()->GetRaycast(fall_ray);
if (fall_raycast.hit && fall_raycast.distance < player_height + (-c->fall_vel * dt)) {
t->position.z += -(fall_raycast.distance - player_height);
c->fall_vel = 0.0f;
}
else {
t->position.z += c->fall_vel * dt;
}
constexpr float kMaxDistanceFromOrigin = 10000.0f; constexpr float kMaxDistanceFromOrigin = 10000.0f;
if (glm::length(t->position) > kMaxDistanceFromOrigin) { if (glm::length(t->position) > kMaxDistanceFromOrigin) {
t->position = {0.0f, 5.0f, 0.0f}; t->position = {0.0f, 0.0f, 10.0f};
} }
/* ROTATION STUFF */ /* ROTATION STUFF */
@ -90,13 +110,14 @@ void CameraControllerSystem::OnUpdate(float ts)
/* user interface inputs */ /* user interface inputs */
if (scene_->app()->window()->GetKeyPress(engine::inputs::Key::K_P)) { if (scene_->app()->window()->GetKeyPress(engine::inputs::Key::K_P)) {
std::string pos_string{"x: " + std::to_string(t->world_matrix[3][0]) + " y: " + std::to_string(t->world_matrix[3][1]) + " z: " + std::to_string(t->world_matrix[3][2])}; std::string pos_string{"x: " + std::to_string(t->world_matrix[3][0]) + " y: " + std::to_string(t->world_matrix[3][1]) +
" z: " + std::to_string(t->world_matrix[3][2])};
LOG_INFO("position {}", pos_string); LOG_INFO("position {}", pos_string);
LOG_INFO("rotation w: {} x: {} y: {} z: {}", t->rotation.w, t->rotation.x, t->rotation.y, t->rotation.z); LOG_INFO("rotation w: {} x: {} y: {} z: {}", t->rotation.w, t->rotation.x, t->rotation.y, t->rotation.z);
} }
if (scene_->app()->window()->GetKeyPress(engine::inputs::Key::K_R)) { if (scene_->app()->window()->GetKeyPress(engine::inputs::Key::K_R)) {
t->position = {0.0f, 5.0f, 0.0f}; t->position = {0.0f, 0.0f, 10.0f};
} }
if (scene_->app()->input_manager()->GetButtonPress("fullscreen")) { if (scene_->app()->input_manager()->GetButtonPress("fullscreen")) {
@ -113,11 +134,12 @@ void CameraControllerSystem::OnUpdate(float ts)
if (scene_->app()->window()->GetButtonPress(engine::inputs::MouseButton::M_LEFT)) { if (scene_->app()->window()->GetButtonPress(engine::inputs::MouseButton::M_LEFT)) {
engine::Ray ray{}; engine::Ray ray{};
ray.origin.x = t->world_matrix[3][0]; ray.origin = t->position;
ray.origin.y = t->world_matrix[3][1]; ray.direction = glm::vec3(glm::mat4_cast(t->rotation) * glm::vec4{0.0f, 0.0f, -1.0f, 1.0f});
ray.origin.z = t->world_matrix[3][2];
ray.direction = glm::vec3{ 0.0f, 0.0f, -1.0f };
engine::Raycast cast = scene_->GetSystem<engine::CollisionSystem>()->GetRaycast(ray); engine::Raycast cast = scene_->GetSystem<engine::CollisionSystem>()->GetRaycast(ray);
LOG_INFO("Raycast success? {}", cast.hit ? "YES" : "NO"); if (cast.hit) {
LOG_INFO("Raycast hit {}", scene_->GetComponent<engine::TransformComponent>(cast.hit_entity)->tag);
LOG_INFO("Distance: {} m", cast.distance);
}
} }
} }

View File

@ -11,6 +11,7 @@ struct CameraControllerComponent {
static constexpr float kCameraSensitivity = 0.007f; static constexpr float kCameraSensitivity = 0.007f;
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 };
}; };
class CameraControllerSystem class CameraControllerSystem

View File

@ -103,16 +103,19 @@ void PlayGame(GameSettings settings)
floor_renderable->material->SetMetallicRoughnessTexture(floor_mr); floor_renderable->material->SetMetallicRoughnessTexture(floor_mr);
floor_renderable->material->SetOcclusionTexture(app.GetResource<engine::Texture>("builtin.white")); floor_renderable->material->SetOcclusionTexture(app.GetResource<engine::Texture>("builtin.white"));
floor_renderable->visible = true ; floor_renderable->visible = true ;
auto floor_col = main_scene->AddComponent<engine::ColliderComponent>(floor);
floor_col->aabb.min = glm::vec3{0.0f, 0.0f, 0.0f};
floor_col->aabb.max = glm::vec3{100.0f, 100.0f, 0.1f };
engine::Entity redcube = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/redcube.glb"));
engine::Entity normal_map_test = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/normalmaptest.glb"));
main_scene->GetComponent<engine::TransformComponent>(normal_map_test)->position += glm::vec3{-10.0f, 0.0f, 1.0f};
engine::Entity monke = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/monke.glb")); engine::Entity monke = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/monke.glb"));
main_scene->GetComponent<engine::TransformComponent>(monke)->position.y += 10.0f;
engine::Entity bottle = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/bottle.glb")); //engine::Entity bottle = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/bottle.glb"));
main_scene->GetComponent<engine::TransformComponent>(bottle)->scale *= 50.0f; //main_scene->GetComponent<engine::TransformComponent>(bottle)->scale *= 10.0f;
main_scene->GetComponent<engine::TransformComponent>(bottle)->position.z += 50.0f;; //main_scene->GetComponent<engine::TransformComponent>(bottle)->position.x += 25.0f;
//main_scene->GetComponent<engine::TransformComponent>(bottle)->position.z += 5.0f;
/* skybox */ /* skybox */
engine::Entity skybox = main_scene->CreateEntity("skybox"); engine::Entity skybox = main_scene->CreateEntity("skybox");