mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
fix collision tree
This commit is contained in:
parent
d9ea79170f
commit
daba5332b9
@ -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;
|
||||||
|
|
||||||
|
@ -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()) {
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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,8 +131,8 @@ 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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();
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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{};
|
||||||
|
|
||||||
@ -153,32 +201,20 @@ int CollisionSystem::BuildNode(std::vector<PrimitiveInfo>& prims, std::vector<Bi
|
|||||||
// 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
BIN
test/res/models/cubes.glb
Normal file
Binary file not shown.
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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
|
||||||
|
@ -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");
|
||||||
|
Loading…
Reference in New Issue
Block a user