diff --git a/examples/01-HelloWorld/01-HelloWorld.exe b/examples/01-HelloWorld/01-HelloWorld.exe index 7900022..c7d8f15 100644 Binary files a/examples/01-HelloWorld/01-HelloWorld.exe and b/examples/01-HelloWorld/01-HelloWorld.exe differ diff --git a/examples/02-Instancing/02-Instancing.exe b/examples/02-Instancing/02-Instancing.exe index 60eaba4..fc4eb2f 100644 Binary files a/examples/02-Instancing/02-Instancing.exe and b/examples/02-Instancing/02-Instancing.exe differ diff --git a/examples/02-Instancing/instancing.cpp b/examples/02-Instancing/instancing.cpp index eb034f3..54b7527 100644 --- a/examples/02-Instancing/instancing.cpp +++ b/examples/02-Instancing/instancing.cpp @@ -181,7 +181,7 @@ namespace vxr Engine::ref().submitDisplayList(std::move(frame)); } - void Main::update() + void Main::update(float dt) { // 15. Update instances position. This operations are performed in the update() instead of the renderUpdate() for them to take into account deltaTime() and be framerate independent. static float v = 0; @@ -190,13 +190,13 @@ namespace vxr instance_positions_[i] = { (i / 500)*1.5f, - 750.0f*(float)(sin(i*3.1415 / 10 + v) * deltaTime()), + 750.0f*(float)(sin(i*3.1415 / 10 + v) * dt), (float)(i % 500)*1.5f }; } v += 0.01f; - Application::update(); + Application::update(dt); } void Main::renderUpdate() diff --git a/examples/02-Instancing/instancing.h b/examples/02-Instancing/instancing.h index 04f6dca..5fe360e 100644 --- a/examples/02-Instancing/instancing.h +++ b/examples/02-Instancing/instancing.h @@ -44,7 +44,7 @@ namespace vxr public: virtual void start() override; - virtual void update() override; + virtual void update(float dt) override; virtual void renderUpdate() override; virtual void stop() override; diff --git a/examples/03-Framebuffers/03-Framebuffers.exe b/examples/03-Framebuffers/03-Framebuffers.exe index e387839..9d227e1 100644 Binary files a/examples/03-Framebuffers/03-Framebuffers.exe and b/examples/03-Framebuffers/03-Framebuffers.exe differ diff --git a/examples/03-Framebuffers/framebuffers.cpp b/examples/03-Framebuffers/framebuffers.cpp index a14cca5..be0d1a6 100644 --- a/examples/03-Framebuffers/framebuffers.cpp +++ b/examples/03-Framebuffers/framebuffers.cpp @@ -237,13 +237,13 @@ namespace vxr Application::start(); } - void Main::update() + void Main::update(float dt) { // 6. Update the contrast settings with the deltaTime(). static double v = 0.0; v += 0.003; - u_state_contrast_.brightness = sin(u_state_contrast_.brightness * 50.0f * deltaTime() + v) + 2.0f * 0.2f; - u_state_contrast_.contrast = sin(u_state_contrast_.contrast * 21.0f * deltaTime() + v) + 1.5f; + u_state_contrast_.brightness = sin(u_state_contrast_.brightness * 50.0f * dt + v) + 2.0f * 0.2f; + u_state_contrast_.contrast = sin(u_state_contrast_.contrast * 21.0f * dt + v) + 1.5f; // 7. Update the cubes model matrix by applying rotation. for (uint32 x = 0; x < kNUM_CUBES_ROW; ++x) @@ -253,14 +253,14 @@ namespace vxr uint32 i = x * kNUM_CUBES_ROW + y; mat4 model = u_state_stream_[i].model; - mat4 rot_x = glm::rotate((x + 1) * 0.21f * deltaTime(), glm::vec3(1.0f, 0.0f, 0.0f)); - mat4 rot_y = glm::rotate((y + 1) * 0.37f * deltaTime(), glm::vec3(0.0f, 1.0f, 0.0f)); + mat4 rot_x = glm::rotate((x + 1) * 0.21f * dt, glm::vec3(1.0f, 0.0f, 0.0f)); + mat4 rot_y = glm::rotate((y + 1) * 0.37f * dt, glm::vec3(0.0f, 1.0f, 0.0f)); u_state_stream_[i].model = model * rot_x * rot_y; } } - Application::update(); + Application::update(dt); } void Main::renderUpdate() diff --git a/examples/03-Framebuffers/framebuffers.h b/examples/03-Framebuffers/framebuffers.h index 0ce45f4..aa69156 100644 --- a/examples/03-Framebuffers/framebuffers.h +++ b/examples/03-Framebuffers/framebuffers.h @@ -44,7 +44,7 @@ namespace vxr public: virtual void start() override; - virtual void update() override; + virtual void update(float dt) override; virtual void renderUpdate() override; virtual void stop() override; diff --git a/examples/04-Mesh/04-Mesh.exe b/examples/04-Mesh/04-Mesh.exe index c7a275f..db2e5d3 100644 Binary files a/examples/04-Mesh/04-Mesh.exe and b/examples/04-Mesh/04-Mesh.exe differ diff --git a/examples/04-Mesh/mesh.cpp b/examples/04-Mesh/mesh.cpp index 3055a95..c5d6a33 100644 --- a/examples/04-Mesh/mesh.cpp +++ b/examples/04-Mesh/mesh.cpp @@ -128,25 +128,25 @@ namespace vxr Application::start(); } - void Main::update() + void Main::update(float dt) { // 9. Rotate the meshes in update() instead of renderUpdate() to make the transformations framerate // independent by multiplying it by deltaTime().The update() method may be executed several times in // a frame to catch up with the render thread. float t = Engine::ref().window()->uptime(); - teapot_->transform()->rotateX(30.0f * deltaTime()); - teapot_->transform()->rotateZ(25.0f * deltaTime()); - teapot_->transform()->set_world_position(vec3(-2, cos(t) * 100 * deltaTime(), 0)); + teapot_->transform()->rotateX(30.0f * dt); + teapot_->transform()->rotateZ(25.0f * dt); + teapot_->transform()->set_world_position(vec3(-2, cos(t) * 100 * dt, 0)); - suzanne_->transform()->rotate(vec3(-15.0f, 10.0f, -5.0f) * deltaTime()); - suzanne_->transform()->set_world_position(vec3(2, sin(t) * 100 * deltaTime(), 0)); + suzanne_->transform()->rotate(vec3(-15.0f, 10.0f, -5.0f) * dt); + suzanne_->transform()->set_world_position(vec3(2, sin(t) * 100 * dt, 0)); - sphere_->transform()->set_local_scale(vec3(sin(t) * 100 * deltaTime() * 0.5f + 1.0f)); + sphere_->transform()->set_local_scale(vec3(sin(t) * 100 * dt * 0.5f + 1.0f)); - cam_->transform()->rotateAround(sphere_, vec3(0,10,0) * deltaTime()); + cam_->transform()->rotateAround(sphere_, vec3(0,10,0) * dt); - Application::update(); + Application::update(dt); } } /* end of vxr namespace */ \ No newline at end of file diff --git a/examples/04-Mesh/mesh.h b/examples/04-Mesh/mesh.h index e6a1f1b..de93a76 100644 --- a/examples/04-Mesh/mesh.h +++ b/examples/04-Mesh/mesh.h @@ -50,7 +50,7 @@ namespace vxr Main(); virtual void start() override; - virtual void update() override; + virtual void update(float dt) override; private: ref_ptr cam_; diff --git a/examples/05-Materials/05-Materials.exe b/examples/05-Materials/05-Materials.exe index e1d90f5..6d5fc56 100644 Binary files a/examples/05-Materials/05-Materials.exe and b/examples/05-Materials/05-Materials.exe differ diff --git a/examples/06-Procedural/06-Procedural.exe b/examples/06-Procedural/06-Procedural.exe index eb9989c..cfb208a 100644 Binary files a/examples/06-Procedural/06-Procedural.exe and b/examples/06-Procedural/06-Procedural.exe differ diff --git a/examples/06-Procedural/imgui.ini b/examples/06-Procedural/imgui.ini index fbc219f..3e41fbe 100644 --- a/examples/06-Procedural/imgui.ini +++ b/examples/06-Procedural/imgui.ini @@ -35,6 +35,6 @@ Collapsed=0 [Window][VXR] Pos=0,0 -Size=1920,1017 +Size=1280,720 Collapsed=0 diff --git a/examples/06-Procedural/procedural.cpp b/examples/06-Procedural/procedural.cpp index a90aa7a..f732905 100644 --- a/examples/06-Procedural/procedural.cpp +++ b/examples/06-Procedural/procedural.cpp @@ -76,7 +76,7 @@ namespace vxr Application::start(); } - void Main::update() + void Main::update(float dt) { // 7. Interpolate camera position float speed = 5.0f; @@ -84,14 +84,14 @@ namespace vxr if (planet_->getComponent()->zoom) { first_zoom = true; - cam_->transform()->set_local_position(Math::lerp(cam_->transform()->local_position(), zoom_on, speed * deltaTime())); - cam_->transform()->set_local_rotation(Math::lerp(cam_->transform()->local_rotation_angles(), vec3(0.0f), speed * deltaTime())); + cam_->transform()->set_local_position(Math::lerp(cam_->transform()->local_position(), zoom_on, speed * dt)); + cam_->transform()->set_local_rotation(Math::lerp(cam_->transform()->local_rotation_angles(), vec3(0.0f), speed * dt)); } else { if (first_zoom) { - cam_->transform()->set_local_position(Math::lerp(cam_->transform()->local_position(), zoom_off, speed * deltaTime())); + cam_->transform()->set_local_position(Math::lerp(cam_->transform()->local_position(), zoom_off, speed * dt)); if (glm::epsilonEqual(cam_->transform()->local_position(), zoom_off, 0.001f) == bvec3(true)) { first_zoom = false; @@ -99,10 +99,10 @@ namespace vxr } else { - cam_->transform()->rotateAround(planet_, vec3(0.1f, 0.2f, -0.2f) * deltaTime()); + cam_->transform()->rotateAround(planet_, vec3(0.1f, 0.2f, -0.2f) * dt); } } - Application::update(); + Application::update(dt); } } /* end of vxr namespace */ \ No newline at end of file diff --git a/examples/06-Procedural/procedural.h b/examples/06-Procedural/procedural.h index 26efc14..a69bf86 100644 --- a/examples/06-Procedural/procedural.h +++ b/examples/06-Procedural/procedural.h @@ -53,7 +53,7 @@ namespace vxr Main(); virtual void start() override; - virtual void update() override; + virtual void update(float dt) override; private: ref_ptr cam_; diff --git a/examples/07-Physics/07-Physics.exe b/examples/07-Physics/07-Physics.exe new file mode 100644 index 0000000..a38f973 Binary files /dev/null and b/examples/07-Physics/07-Physics.exe differ diff --git a/examples/07-Physics/assets/circle.bmp b/examples/07-Physics/assets/circle.bmp new file mode 100644 index 0000000..19231fa Binary files /dev/null and b/examples/07-Physics/assets/circle.bmp differ diff --git a/examples/07-Physics/assets/diagonal.bmp b/examples/07-Physics/assets/diagonal.bmp new file mode 100644 index 0000000..59531e1 Binary files /dev/null and b/examples/07-Physics/assets/diagonal.bmp differ diff --git a/examples/07-Physics/assets/fall.bmp b/examples/07-Physics/assets/fall.bmp new file mode 100644 index 0000000..fd224be Binary files /dev/null and b/examples/07-Physics/assets/fall.bmp differ diff --git a/examples/07-Physics/assets/heightmap.bmp b/examples/07-Physics/assets/heightmap.bmp new file mode 100644 index 0000000..c8a0766 Binary files /dev/null and b/examples/07-Physics/assets/heightmap.bmp differ diff --git a/examples/07-Physics/assets/plane.bmp b/examples/07-Physics/assets/plane.bmp new file mode 100644 index 0000000..fca87b0 Binary files /dev/null and b/examples/07-Physics/assets/plane.bmp differ diff --git a/examples/07-Physics/imgui.ini b/examples/07-Physics/imgui.ini new file mode 100644 index 0000000..ff6dfef --- /dev/null +++ b/examples/07-Physics/imgui.ini @@ -0,0 +1,20 @@ +[Window][Debug##Default] +Pos=60,60 +Size=400,400 +Collapsed=0 + +[Window][Scene Selector] +Pos=60,60 +Size=442,71 +Collapsed=0 + +[Window][Material Editor] +Pos=60,60 +Size=190,422 +Collapsed=0 + +[Window][VXR] +Pos=0,0 +Size=1280,720 +Collapsed=0 + diff --git a/examples/07-Physics/physics.cpp b/examples/07-Physics/physics.cpp new file mode 100644 index 0000000..d8e12d1 --- /dev/null +++ b/examples/07-Physics/physics.cpp @@ -0,0 +1,328 @@ +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "physics.h" + +#include "../../include/physics/collider_sphere.h" +#include "../../include/components/rigidbody.h" +#include "../../include/components/collider.h" + +// 0. Define the entry point. +VXR_DEFINE_APP_MAIN(vxr::Main) + +namespace vxr +{ + + Main::Main() + { + // 1. Initialize GPU and Window parameters. + Params p; + p.gpu = { 100, 100, 100, 100 }; + p.window = { { 1280, 720 } }; + Engine::ref().set_preinit_params(p); + } + + void Main::start() + { + // 2. Create a Scene, parent the objects and load. + scene_.alloc(); + Engine::ref().loadScene(scene_); + + // 2.1. Create a skybox. + ref_ptr skybox; + skybox.alloc(); + ref_ptr background; + background.alloc()->set_size(1, 1); + background->set_texels_format(TexelsFormat::RGB_U8); + background->set_type(TextureType::T2D); + background->set_data(Color::PhyreBlue); + background->set_hdr(true); + skybox->set_texture(background); + scene_->set_skybox(skybox); + + // 2.2. Add Cameras. + camera_[0].alloc()->set_name("Camera"); + camera_[0]->addComponent()->transform()->set_local_position(vec3(0.0f, cam_height_, 35.0f)); + camera_[0]->getComponent()->transform()->set_local_rotation(vec3(cam_incl_, 0.0f, 0.0f)); + camera_[0]->getComponent()->set_background_color(Color::PhyreBlue); + camera_[0]->getComponent()->set_clear_flags(Camera::ClearFlags::Skybox); + scene_->addObject(camera_[0]); + + camera_[1].alloc()->set_name("Camera Top"); + camera_[1]->addComponent()->transform()->set_local_position(vec3(0.0f, 85.0f, 0.0f)); + camera_[1]->getComponent()->transform()->set_local_rotation(vec3(-90.0f, 0.0f, 0.0f)); + camera_[1]->getComponent()->set_fov(25.0f); + camera_[1]->getComponent()->set_background_color(Color::PhyreBlue); + camera_[1]->getComponent()->set_clear_flags(Camera::ClearFlags::Skybox); + scene_->addObject(camera_[1]); + + // 2.3. Load all height map textures into meshes. + height_map_[0].alloc()->loadHeightMap("assets/heightmap.bmp", 2.0f, 0.75f, 2.0f); + height_map_[1].alloc()->loadHeightMap("assets/heightmap.bmp", 2.0f, 0.75f); + height_map_[2].alloc()->loadHeightMap("assets/circle.bmp", 2.0f, 0.75f); + height_map_[3].alloc()->loadHeightMap("assets/fall.bmp", 2.0f, 0.75f); + height_map_[4].alloc()->loadHeightMap("assets/diagonal.bmp", 2.0f, 0.75f); + + // 2.4. Create the different materials for the height maps. + collider_materials_[0].allocT()->set_color(Color::White); + collider_materials_[1].allocT()->set_albedo(Color::Gold); + + // 2.5. Create the height map object, with a Rigidbody and add its physical properties. + collider_.alloc()->set_name("Collider"); + collider_->addComponent()->material = collider_materials_[current_collider_material_]; + collider_->addComponent()->mesh = height_map_[current_height_map_].get(); + collider_->addComponent()->set_use_gravity(false); + collider_->getComponent()->set_mass(0.0f); + collider_->getComponent()->set_restitution(1.0f); + + // 2.6. Add a Collider component and set the shape to a height map collider with the proper mesh assigned. + collider_hm_.alloc()->set_height_map(height_map_[current_height_map_]); + collider_hm_->setAabbExtents(vec3(-30.0f), vec3(30.0f)); + collider_->addComponent()->set_shape(collider_hm_.get()); + + scene_->addObject(collider_); + + // 2.7. Add a directional light to the scene. + ref_ptr dir_light; + dir_light.alloc()->set_name("Directional Light"); + dir_light->addComponent()->set_type(Light::Type::Directional); + dir_light->transform()->set_local_rotation(vec3(90.0f, 60.0f, 90.0f)); + scene_->addObject(dir_light); + + // 3. Submit the UI function. + /// TODO: Heavy custom UI work can cause a crash due to UI not being executed thread safely at the moment. + Engine::ref().submitUIFunction([this]() { Input(); ui::Editor(); }); + + Application::start(); + } + + void Main::update(float dt) + { + // 4. Bring back up spheres that fall below a certain height. + for (auto& sphere : spheres_) + { + if (sphere->transform()->local_position().y < -15.0f) + { + vec3 random_pos = vec3(rand() % 28 - 14, 40.0f, rand() % 28 - 14); + RespawnObject(sphere, random_pos); + } + } + + Application::update(dt); + } + + void Main::SpawnNewSphere(const vec3& position, const float& scale, const Color& color) + { + ref_ptr sphere; + sphere.alloc()->set_name("Sphere"); + sphere->transform()->set_local_position(position); + sphere->transform()->set_local_scale(vec3(scale)); + + ref_ptr std_sphere_mat; + std_sphere_mat.alloc()->set_albedo(color); + sphere->addComponent()->material = std_sphere_mat.get(); + sphere->addComponent()->mesh = Engine::ref().assetManager()->loadMesh("../../assets/models/sphere/sphere.obj"); + sphere->addComponent()->set_mass(scale * 0.5f); + sphere->getComponent()->set_restitution(0.4f); + ref_ptr coll; + coll.alloc()->set_radius(scale * 0.5f); + sphere->addComponent()->set_shape(coll.get()); + + scene_->addObject(sphere); + spheres_.push_back(sphere); + } + + void Main::RespawnObject(ref_ptr obj, const vec3& position) + { + obj->transform()->set_local_position(position); + + ref_ptr rg = obj->getComponent().get(); + if (rg != nullptr) + { + rg->set_velocity(vec3(0.0f)); + } + } + + void Main::Input() + { + // Change collider material. + if (ImGui::IsKeyPressed('W')) + { + if (++current_collider_material_ >= NUM_COLLIDER_MATERIALS) + { + current_collider_material_ = 0; + } + + collider_->getComponent()->material = collider_materials_[current_collider_material_]; + } + + // Change active camera. + if (ImGui::IsKeyPressed('C')) + { + if (++current_camera_ >= NUM_CAMERAS) + { + current_camera_ = 0; + } + + Engine::ref().camera()->set_main(camera_[current_camera_]->getComponent()); + } + + // Handle camera rotation + if (ImGui::IsKeyDown('Q')) + { + cam_height_ += rotation_speed_; + } + if (ImGui::IsKeyDown('A')) + { + cam_height_ -= rotation_speed_; + } + + vec3 collider_pos = collider_->transform()->local_position(); + collider_pos.y = cam_height_; + quat cam_incl = camera_[0]->transform()->local_rotation(); + cam_incl = quat(cam_incl.w, -cam_incl.x, 0.0f, 0.0f); + camera_[0]->transform()->rotate(cam_incl); + + if (ImGui::IsKeyDown('O')) + { + camera_[0]->transform()->rotateAround(collider_pos, vec3(0.0f, rotation_speed_, 0.0f)); + } + if (ImGui::IsKeyDown('P')) + { + camera_[0]->transform()->rotateAround(collider_pos, vec3(0.0f,-rotation_speed_, 0.0f)); + } + + cam_incl = quat(cam_incl.w, -cam_incl.x, 0.0f, 0.0f); + camera_[0]->transform()->rotate(cam_incl); + camera_[0]->transform()->set_local_position_y(cam_height_); + + // Slow down physics to 1fps + if (ImGui::IsKeyDown(' ')) + { + Engine::ref().rigidbody()->set_debug_update(true, 1.0, deltaTime()); + } + else + { + Engine::ref().rigidbody()->set_debug_update(false, 1.0, deltaTime()); + } + + // Spawn opposable spheres + if (ImGui::IsKeyPressed('F')) + { + SpawnNewSphere(vec3(+14.0f, 30.0f, 0.0f), 2.0f, Color::Red); + SpawnNewSphere(vec3(-14.0f, 30.0f, 0.0f), 2.0f, Color::Red); + } + + // (UP) Spawn random sphere + if (ImGui::IsKeyPressed(265) || ImGui::IsKeyPressed('R')) + { + float random_scale = 1.0f + (rand() % 30 * 0.1f); + vec3 random_pos = vec3(rand() % 28 - 14, 30.0f, rand() % 28 - 14); + if (current_first_sphere_ > 0) + { + current_first_sphere_--; + spheres_[current_first_sphere_]->set_active(true); + RespawnObject(spheres_[current_first_sphere_], random_pos); + } + else + { + SpawnNewSphere(random_pos, random_scale, Color::Random()); + } + } + + // (DOWN) Hide first sphere + if (ImGui::IsKeyPressed(264)) + { + if (current_first_sphere_ <= spheres_.size() - 1) + { + spheres_[current_first_sphere_]->set_active(false); + current_first_sphere_++; + } + } + + // Change active height map + if (ImGui::IsKeyPressed('H')) + { + if (++current_height_map_ >= NUM_HEIGHT_MAPS) + { + current_height_map_ = 0; + } + + collider_->addComponent()->mesh = height_map_[current_height_map_].get(); + collider_hm_->set_height_map(height_map_[current_height_map_]); + + if (triangle_drop_index_ > height_map_[current_height_map_]->face_count()) + { + triangle_drop_index_ = 0; + } + } + + if (ImGui::IsKeyPressed('U')) + { + if (++triangle_drop_index_ > height_map_[current_height_map_]->face_count()) + { + triangle_drop_index_ = 0; + } + vertex_drop_index_ = 3; + } + + if (ImGui::IsKeyPressed('I')) + { + if (--triangle_drop_index_ < 0) + { + triangle_drop_index_ = height_map_[current_height_map_]->face_count() - 1; + } + vertex_drop_index_ = 3; + } + + if (ImGui::IsKeyPressed('D') || ImGui::IsKeyPressed('U') || ImGui::IsKeyPressed('I')) + { + vec3 pos; + if (++vertex_drop_index_ > 3) + { + vertex_drop_index_ = 0; + } + if (vertex_drop_index_ == 3) + { + pos = (height_map_[current_height_map_]->vertices()[triangle_drop_index_ * 3 + 0] + height_map_[current_height_map_]->vertices()[triangle_drop_index_ * 3 + 1] + height_map_[current_height_map_]->vertices()[triangle_drop_index_ * 3 + 2]) / 3.0f; + } + else + { + pos = height_map_[current_height_map_]->vertices()[triangle_drop_index_ * 3 + vertex_drop_index_]; + } + + pos.y = 15.0f; + if (spheres_.size() > 0) + { + RespawnObject(spheres_[spheres_.size() - 1], pos); + } + else + { + SpawnNewSphere(pos, 1.0f, Color::Random()); + } + } + } + + +} /* end of vxr namespace */ \ No newline at end of file diff --git a/examples/07-Physics/physics.h b/examples/07-Physics/physics.h new file mode 100644 index 0000000..67a5a43 --- /dev/null +++ b/examples/07-Physics/physics.h @@ -0,0 +1,87 @@ +#pragma once + +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "../../include/engine/application.h" +#include "../../include/engine/core_minimal.h" +#include "../../include/graphics/height_map.h" +#include "../../include/physics/collider_height_map.h" + +/** +* \file physics.h +* +* \author Victor Avila (avilapa.github.io) +* +* \brief This example showcases the use of rigidbody physics and collision detection in the engine. +*/ +namespace vxr +{ + + class Main : public Application + { + VXR_OBJECT(Main, Application); + public: + Main(); + + virtual void start() override; + virtual void update(float dt) override; + + private: + void SpawnNewSphere(const vec3& position, const float& scale, const Color& color); + void RespawnObject(ref_ptr obj, const vec3& position); + + void Input(); + + private: + static const uint32 NUM_HEIGHT_MAPS = 5; + static const uint32 NUM_CAMERAS = 2; + static const uint32 NUM_COLLIDER_MATERIALS = 2; + uint32 current_height_map_ = 0; + uint32 current_camera_ = 0; + uint32 current_collider_material_ = 0; + + uint32 current_first_sphere_ = 0; + + std::vector> spheres_; + ref_ptr light_; + ref_ptr scene_; + + ref_ptr camera_[NUM_CAMERAS]; + + ref_ptr height_map_[NUM_HEIGHT_MAPS]; + ref_ptr collider_hm_; + ref_ptr collider_; + ref_ptr collider_materials_[NUM_COLLIDER_MATERIALS]; + + // Camera settings + float cam_incl_ = -35.0f; + float cam_height_ = 40.0f; + float rotation_speed_ = 0.5f; + + uint32 triangle_drop_index_ = 0; + uint32 vertex_drop_index_ = 0; + }; + +} /* end of vxr namespace */ \ No newline at end of file diff --git a/examples/dev/dev.cpp b/examples/dev/dev.cpp index e649cd0..e642197 100644 --- a/examples/dev/dev.cpp +++ b/examples/dev/dev.cpp @@ -164,9 +164,9 @@ namespace vxr Engine::ref().submitUIFunction([]() { ui::Editor(); }); } - void Main::update() + void Main::update(float dt) { - Application::update(); + Application::update(dt); //light_node_->transform()->set_local_rotation(light_node_->transform()->local_rotation() + vec3(0.31, 1.06, 0.3) * deltaTime()); //light_node_->transform()->set_local_scale(vec3(1 + sin(Engine::ref().window()->uptime() * 0.1f))); } diff --git a/examples/dev/dev.exe b/examples/dev/dev.exe index 9cc92a3..fef54cd 100644 Binary files a/examples/dev/dev.exe and b/examples/dev/dev.exe differ diff --git a/examples/dev/dev.h b/examples/dev/dev.h index 7cab8d0..1850dd1 100644 --- a/examples/dev/dev.h +++ b/examples/dev/dev.h @@ -46,7 +46,7 @@ namespace vxr virtual void init() override; virtual void start() override; - virtual void update() override; + virtual void update(float dt) override; virtual void renderUpdate() override; virtual void stop() override; diff --git a/include/components/camera.h b/include/components/camera.h index a857b7b..e34adee 100644 --- a/include/components/camera.h +++ b/include/components/camera.h @@ -109,14 +109,13 @@ namespace vxr mat4 view_; }; - class Scene; namespace mat { class MaterialInstance; } namespace System { class Camera : public ComponentSystem { - VXR_OBJECT(System::Camera, ComponentSystem); + VXR_COMPONENT_SYSTEM(Camera, ComponentSystem); public: Camera(); ~Camera(); @@ -125,10 +124,13 @@ namespace vxr ref_ptr main() const; void init() override; - void update() override; + void start() override; + void renderPreUpdate() override; void renderUpdate() override; void renderPostUpdate() override; + void onSceneChanged() override; + void set_render_to_screen(bool enabled); bool render_to_screen() const; uint32 screen_texture_id(); @@ -136,9 +138,6 @@ namespace vxr gpu::Buffer common_uniforms_buffer() const; private: - std::vector> components_; - - ref_ptr scene_; ref_ptr main_; bool render_to_screen_; @@ -148,15 +147,6 @@ namespace vxr gpu::Buffer buffer; Shader::CommonData data; } common_uniforms_; - - public: - template ref_ptr createInstance() - { - ref_ptr c; - c.alloc(); - components_.push_back(c.get()); - return c.get(); - } }; template<> class Getter diff --git a/include/components/collider.h b/include/components/collider.h new file mode 100644 index 0000000..94c5675 --- /dev/null +++ b/include/components/collider.h @@ -0,0 +1,76 @@ +#pragma once + +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "../../include/core/component.h" +#include "../../include/graphics/materials/material_instance.h" +#include "../../include/physics/collider_shape.h" + +/** +* \file collider.h +* +* \author Victor Avila (avilapa.github.io) +* +* \brief +* +*/ +namespace vxr +{ + + class Collider : public Component + { + VXR_OBJECT(Collider, Component); + public: + Collider(); + ~Collider(); + + virtual void onGUI() override; + + void set_shape(ref_ptr shape); + ref_ptr shape() const; + + private: + ref_ptr shape_; + }; + + namespace System + { + class Collider : public ComponentSystem + { + VXR_COMPONENT_SYSTEM(Collider, ComponentSystem); + public: + Collider(); + ~Collider(); + }; + + template<> class Getter + { + public: + static ref_ptr get(); + }; + + } + +} /* end of vxr namespace */ \ No newline at end of file diff --git a/include/components/custom.h b/include/components/custom.h index 31195d1..e4dab41 100644 --- a/include/components/custom.h +++ b/include/components/custom.h @@ -47,9 +47,12 @@ namespace vxr Custom(); virtual ~Custom(); + virtual void init() {} virtual void start() {} - virtual void update() {} + virtual void preUpdate() {} + virtual void update(float dt) {} virtual void postUpdate() {} + virtual void renderPreUpdate() {} virtual void renderUpdate() {} virtual void renderPostUpdate() {} virtual void stop() {} @@ -58,6 +61,7 @@ namespace vxr virtual void onEnable() {} virtual void onDisable() {} + virtual void onSceneChanged() {} void set_enabled(const bool enabled) { enabled_ = enabled; } bool enabled() const { return enabled_; } @@ -73,32 +77,23 @@ namespace vxr { class Custom : public ComponentSystem { - VXR_OBJECT(System::Custom, ComponentSystem); + VXR_COMPONENT_SYSTEM(Custom, ComponentSystem); public: Custom(); virtual ~Custom(); + void init() override; void start() override; - void update() override; + void preUpdate() override; + void update(float dt) override; void postUpdate() override; + void renderPreUpdate() override; void renderUpdate() override; void renderPostUpdate() override; void stop() override; private: - std::vector> components_; std::vector new_components_; - ref_ptr scene_; - - public: - template ref_ptr createInstance() - { - ref_ptr c; - c.alloc(); - new_components_.push_back(components_.size()); - components_.push_back(c.get()); - return c.get(); - } }; template<> class Getter diff --git a/include/components/ibl.h b/include/components/ibl.h index 19daba0..47a1e60 100644 --- a/include/components/ibl.h +++ b/include/components/ibl.h @@ -73,13 +73,11 @@ namespace vxr ref_ptr build_cubemap_; }; - class Scene; - namespace System { class IBL : public ComponentSystem { - VXR_OBJECT(System::IBL, ComponentSystem); + VXR_COMPONENT_SYSTEM(IBL, ComponentSystem); public: IBL(); ~IBL(); @@ -87,10 +85,10 @@ namespace vxr void set_main(ref_ptr light); ref_ptr main() const; - void init() override; - void update() override; + void start() override; void renderUpdate() override; - void renderPostUpdate() override; + + void onSceneChanged() override; void subscribeMaterialForIBLTextures(const string& material_name); @@ -104,19 +102,8 @@ namespace vxr void cleanMaterialIBLTextures(); private: - std::vector> components_; std::vector pbr_materials_; - ref_ptr scene_; ref_ptr main_; - - public: - template ref_ptr createInstance() - { - ref_ptr c; - c.alloc(); - components_.push_back(c.get()); - return c.get(); - } }; template<> class Getter diff --git a/include/components/light.h b/include/components/light.h index 61a5d2a..01143ac 100644 --- a/include/components/light.h +++ b/include/components/light.h @@ -76,45 +76,29 @@ namespace vxr float cone_angle_; }; - class Scene; - namespace System { class Light : public ComponentSystem { - VXR_OBJECT(System::Light, ComponentSystem); + VXR_COMPONENT_SYSTEM(Light, ComponentSystem); public: Light(); virtual ~Light(); void init() override; - void update() override; - void renderUpdate() override; - void renderPostUpdate() override; + void renderPreUpdate() override; uint32 num_lights() const; - gpu::Buffer light_uniforms_buffer() const; private: - std::vector> components_; - ref_ptr scene_; - uint32 num_lights_; + uint32 num_lights_ = 0; struct LightUniforms { gpu::Buffer buffer; Shader::LightData data; } light_uniforms_; - - public: - template ref_ptr createInstance() - { - ref_ptr c; - c.alloc(); - components_.push_back(c.get()); - return c.get(); - } }; template<> class Getter diff --git a/include/components/mesh_filter.h b/include/components/mesh_filter.h index 66561c8..54c21de 100644 --- a/include/components/mesh_filter.h +++ b/include/components/mesh_filter.h @@ -54,24 +54,10 @@ namespace vxr { class MeshFilter : public ComponentSystem { - VXR_OBJECT(System::MeshFilter, ComponentSystem); + VXR_COMPONENT_SYSTEM(MeshFilter, ComponentSystem); public: MeshFilter(); ~MeshFilter(); - - void init() override; - - private: - std::vector> components_; - - public: - template ref_ptr createInstance() - { - ref_ptr c; - c.alloc(); - components_.push_back(c.get()); - return c.get(); - } }; template<> class Getter diff --git a/include/components/renderer.h b/include/components/renderer.h index 4e648b9..8efbb38 100644 --- a/include/components/renderer.h +++ b/include/components/renderer.h @@ -50,20 +50,17 @@ namespace vxr ref_ptr material; }; - class Scene; class DisplayList; namespace System { class Renderer : public ComponentSystem { - VXR_OBJECT(System::Renderer, ComponentSystem); + VXR_COMPONENT_SYSTEM(Renderer, ComponentSystem); public: Renderer(); ~Renderer(); - void init() override; - void update() override; void renderUpdate() override; void renderPostUpdate() override; @@ -75,18 +72,7 @@ namespace vxr void renderSkybox(); private: - std::vector> components_; std::vector> transparent_; - ref_ptr scene_; - - public: - template ref_ptr createInstance() - { - ref_ptr c; - c.alloc(); - components_.push_back(c.get()); - return c.get(); - } }; template<> class Getter diff --git a/include/components/rigidbody.h b/include/components/rigidbody.h new file mode 100644 index 0000000..77a8217 --- /dev/null +++ b/include/components/rigidbody.h @@ -0,0 +1,144 @@ +#pragma once + +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "../../include/physics/hit.h" +#include "../../include/core/component.h" +#include "../../include/graphics/materials/material_instance.h" + +/** +* \file rigidbody.h +* +* \author Victor Avila (avilapa.github.io) +* +* \brief +* +*/ +namespace vxr +{ + + class Rigidbody : public Component + { + VXR_OBJECT(Rigidbody, Component); + public: + Rigidbody(); + ~Rigidbody(); + + virtual void onGUI() override; + + void set_use_gravity(const bool use_gravity); + void set_velocity(const vec3& velocity); + void addVelocity(const vec3& velocity); + void set_mass(const float mass); + void set_restitution(const float restitution_coeff); + + const bool use_gravity() const; + const vec3 velocity() const; + const float mass() const; + const float inverseMass() const; + const float restitution() const; + + void applyCentralForce(const vec3& force); + + void applyGravity(); + void integrateVelocities(float dt); + void applyDamping(float dt); + + void clearForces(); + + private: + bool use_gravity_ = true; + + vec3 velocity_ = vec3(0.0f); + vec3 linear_factor_ = vec3(1.0f); + + float mass_ = 1.0f; + float inv_mass_; + float restitution_ = 0.5f; // Elasticity/Bounciness + + vec3 total_force_ = vec3(0.0f); + }; + + class Collider; + + namespace System + { + class Rigidbody : public ComponentSystem + { + VXR_COMPONENT_SYSTEM(Rigidbody, ComponentSystem); + public: + Rigidbody(); + ~Rigidbody(); + + void preUpdate() override; + void update(float dt) override; + + void set_debug_update(bool enabled, double ratio = 1.0, double step = 1.0 / 60.0); + + const vec3& gravity() const; + const float& linearDamping() const; + + private: + void performCollisionDetection(); + void clearForces(); + + void resolveImpulse(Hit& hit); + void positionCorrection(Hit& hit); + + private: + struct AABB + { + vec3 min, max; + uint32 scene_index_; + }; + + bool System::Rigidbody::aabbVsAabb(const AABB& a, const AABB& b); + uint32 sorting_axis_ = 0; + + std::vector> scene_components_; + std::vector scene_collision_pairs_; + std::vector scene_aabb_; + + vec3 gravity_ = vec3(0.0f, -9.8f, 0.0f); + float damping_linear_ = 0.01f; + + // Debug + bool debug_mode_ = false; + double debug_ratio_ = 1.0; + double debug_step_ = 1.0 / 60.0; + double debug_seconds_counter_ = 0; + }; + + template<> class Getter + { + public: + static ref_ptr get(); + }; + + } + + + +} /* end of vxr namespace */ \ No newline at end of file diff --git a/include/components/transform.h b/include/components/transform.h index fa7430d..99532ee 100644 --- a/include/components/transform.h +++ b/include/components/transform.h @@ -48,6 +48,9 @@ namespace vxr virtual void onGUI() override; void set_local_position(const vec3& position); + void set_local_position_x(const float& v); + void set_local_position_y(const float& v); + void set_local_position_z(const float& v); void set_local_rotation(const quat& rotation); void set_local_rotation(const vec3& rotation); void set_local_scale(const float& scale); @@ -134,38 +137,20 @@ namespace vxr mutable mat4 world_transform_; - // Euler Angles is used internally just to display quaternions in UI properly + // Euler Angles is used internally just to display quaternions in UI properly. vec3 euler_angles_; }; - class Scene; - namespace System { class Transform : public ComponentSystem { - VXR_OBJECT(System::Transform, ComponentSystem); + VXR_COMPONENT_SYSTEM(Transform, ComponentSystem); public: Transform(); ~Transform(); - void init() override; - void update() override; void renderUpdate() override; - void renderPostUpdate() override; - - private: - std::vector> components_; - ref_ptr scene_; - - public: - template ref_ptr createInstance() - { - ref_ptr c; - c.alloc(); - components_.push_back(c.get()); - return c.get(); - } }; template<> class Getter diff --git a/include/core/component.h b/include/core/component.h index 0325860..9f04c79 100644 --- a/include/core/component.h +++ b/include/core/component.h @@ -71,30 +71,48 @@ namespace vxr } }; + class Scene; + namespace System { class ComponentSystem : public Object { - VXR_OBJECT(ComponentSystem, Object); - public: ComponentSystem(); virtual ~ComponentSystem(); virtual void init() {}; virtual void start() {}; - virtual void update() {}; + virtual void preUpdate() {}; + virtual void update(float dt) {}; virtual void postUpdate() {}; + virtual void renderPreUpdate() {}; virtual void renderUpdate() {}; virtual void renderPostUpdate() {}; virtual void stop() {}; + + virtual void onSceneChanged(); + + protected: + ref_ptr scene_; }; template class Getter { - }; } +#define VXR_COMPONENT_SYSTEM(type_name, base_type_name) \ + VXR_OBJECT(System::##type_name, System::##base_type_name); \ + template ref_ptr createInstance() \ + { \ + ref_ptr c; \ + c.alloc(); \ + components_.push_back(c.get()); \ + return c.get(); \ + } \ + private: \ + std::vector> components_; + } /* end of vxr namespace */ \ No newline at end of file diff --git a/include/engine/application.h b/include/engine/application.h index 4f3c6b5..d544ebd 100644 --- a/include/engine/application.h +++ b/include/engine/application.h @@ -47,8 +47,10 @@ namespace vxr virtual void init(); virtual void start(); - virtual void update(); + virtual void preUpdate(); + virtual void update(float dt); virtual void postUpdate(); + virtual void renderPreUpdate(); virtual void renderUpdate(); virtual void renderPostUpdate(); virtual void stop(); @@ -68,8 +70,8 @@ namespace vxr struct Framerate { - double time_step = 1.0 / 120.0; - uint32 max_steps = 15; + double time_step = (1.0 / 60.0); + uint32 max_steps = 10; uint32 fps = 0; } framerate_; }; diff --git a/include/engine/engine.h b/include/engine/engine.h index fff4a57..3c983c1 100644 --- a/include/engine/engine.h +++ b/include/engine/engine.h @@ -54,7 +54,9 @@ namespace vxr namespace System { class Custom; } namespace System { class Camera; } namespace System { class Renderer; } + namespace System { class Collider; } namespace System { class Transform; } + namespace System { class Rigidbody; } namespace System { class MeshFilter; } class Engine : public Object @@ -87,7 +89,9 @@ namespace vxr ref_ptr custom(); ref_ptr camera(); ref_ptr renderer(); + ref_ptr collider(); ref_ptr transform(); + ref_ptr rigidbody(); ref_ptr meshFilter(); vxr::ui::EditorLog Log; @@ -108,7 +112,9 @@ namespace vxr ref_ptr custom_; ref_ptr camera_; ref_ptr renderer_; + ref_ptr collider_; ref_ptr transform_; + ref_ptr rigidbody_; ref_ptr mesh_filter_; private: @@ -116,11 +122,16 @@ namespace vxr bool init(); void start(); - void update(); + void preUpdate(); + void update(float dt); void postUpdate(); + void renderPreUpdate(); void renderUpdate(); void renderPostUpdate(); void stop(); + + void startSystems(); + void stopSystems(); }; #define VXR_LOG(LEVEL, ...) \ diff --git a/include/graphics/height_map.h b/include/graphics/height_map.h new file mode 100644 index 0000000..a2bda5f --- /dev/null +++ b/include/graphics/height_map.h @@ -0,0 +1,59 @@ +#pragma once + +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "../../include/graphics/mesh.h" + +/** +* \file height_map.h +* +* \author Victor Avila (avilapa.github.io) +* +* \brief . +* +*/ +namespace vxr +{ + namespace mesh + { + class HeightMap : public Mesh + { + VXR_OBJECT(HeightMap, Mesh); + public: + HeightMap(); + virtual ~HeightMap(); + + void loadHeightMap(const char* file, float grid_size, float height_range, float height_clamp = 0.0f); + + uint32 face_count() const; + + private: + std::vector height_map_; + + uint32 face_count_; + }; + } + +} /* end of vxr namespace */ \ No newline at end of file diff --git a/include/graphics/mesh.h b/include/graphics/mesh.h index 97bf6b7..3c68919 100644 --- a/include/graphics/mesh.h +++ b/include/graphics/mesh.h @@ -51,8 +51,8 @@ namespace vxr private:\ type name = __VA_ARGS__;\ public:\ - void set_##fname(const type &data) { name = data; dirty_ = true; }\ - type fname() const { return name; } + void set_##fname(const type& data) { name = data; dirty_ = true; }\ + const type& fname() const { return name; } PROPERTY(std::vector, vertices_, vertices, {}); PROPERTY(std::vector, normals_, normals, {}); @@ -104,9 +104,7 @@ namespace vxr { class Cube : public Mesh { - VXR_OBJECT(Cube, Mesh); - public: Cube(); virtual ~Cube(); @@ -114,9 +112,7 @@ namespace vxr class Quad : public Mesh { - VXR_OBJECT(Quad, Mesh); - public: Quad(); virtual ~Quad(); diff --git a/include/graphics/texture.h b/include/graphics/texture.h index 10e9f9b..b9f8cf0 100644 --- a/include/graphics/texture.h +++ b/include/graphics/texture.h @@ -59,6 +59,7 @@ namespace vxr void set_type(TextureType::Enum type); void set_build_mipmap(bool build_mipmap); void set_data(void* data, uint32 index = 0); + void set_data(Color color, uint32 index = 0); void set_hdr(bool hdr); uvec2 size() const; diff --git a/include/physics/collider_height_map.h b/include/physics/collider_height_map.h new file mode 100644 index 0000000..4de1a19 --- /dev/null +++ b/include/physics/collider_height_map.h @@ -0,0 +1,62 @@ +#pragma once + +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "collider_shape.h" + +/** +* \file collider_height_map.h +* +* \author Victor Avila (avilapa.github.io) +* +* \brief +* +*/ +namespace vxr +{ + + namespace mesh { class HeightMap; } + + class ColliderHeightMap : public ColliderShape + { + VXR_OBJECT(ColliderHeightMap, ColliderShape); + public: + ColliderHeightMap(); + ~ColliderHeightMap(); + + void checkCollision(Hit& hit) const override; + void getAabb(ref_ptr transform, vec3& aabb_min, vec3& aabb_max) const override; + void setAabbExtents(vec3 min, vec3 max); + + void set_height_map(ref_ptr mesh); + ref_ptr height_map() const; + + private: + ref_ptr height_map_; + vec3 local_aabb_min_; + vec3 local_aabb_max_; + }; + +} /* end of vxr namespace */ \ No newline at end of file diff --git a/include/physics/collider_shape.h b/include/physics/collider_shape.h new file mode 100644 index 0000000..8bd48ae --- /dev/null +++ b/include/physics/collider_shape.h @@ -0,0 +1,71 @@ +#pragma once + +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "hit.h" +#include "../../include/core/object.h" + +/** +* \file collider_shape.h +* +* \author Victor Avila (avilapa.github.io) +* +* \brief +* +*/ +namespace vxr +{ + + class Transform; + + class ColliderShape : public Object + { + VXR_OBJECT(ColliderShape, Object); + public: + virtual ~ColliderShape(); + + struct Type + { + enum Enum + { + Undefined = 0, + Sphere, + HeightMap, + }; + }; + + const Type::Enum& colType() const; + + virtual void checkCollision(Hit& hit) const; + virtual void getAabb(ref_ptr transform, vec3& aabb_min, vec3& aabb_max) const = 0; + + protected: + ColliderShape(); + + protected: + Type::Enum type_; + }; + +} /* end of vxr namespace */ \ No newline at end of file diff --git a/include/physics/collider_sphere.h b/include/physics/collider_sphere.h new file mode 100644 index 0000000..03e0366 --- /dev/null +++ b/include/physics/collider_sphere.h @@ -0,0 +1,56 @@ +#pragma once + +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "collider_shape.h" + +/** +* \file collider_sphere.h +* +* \author Victor Avila (avilapa.github.io) +* +* \brief +* +*/ +namespace vxr +{ + + class ColliderSphere : public ColliderShape + { + VXR_OBJECT(ColliderSphere, ColliderShape); + public: + ColliderSphere(); + ~ColliderSphere(); + + void checkCollision(Hit& hit) const override; + void getAabb(ref_ptr transform, vec3& aabb_min, vec3& aabb_max) const override; + + void set_radius(const float radius); + float radius() const; + private: + float radius_ = 1.0f; + }; + +} /* end of vxr namespace */ \ No newline at end of file diff --git a/include/physics/hit.h b/include/physics/hit.h new file mode 100644 index 0000000..c11978f --- /dev/null +++ b/include/physics/hit.h @@ -0,0 +1,59 @@ +#pragma once + +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "../../include/core/object.h" + +/** +* \file hit.h +* +* \author Victor Avila (avilapa.github.io) +* +* \brief +* +*/ +namespace vxr +{ + + class Rigidbody; + class Collider; + + struct Hit /// TODO: Make this a general HitResult struct, separate from the Manifold. + { + ref_ptr rg1; + ref_ptr rg2; + ref_ptr col1; + ref_ptr col2; + vec3 normal; + float penetration_depth; + bool hit = false; + + Hit(ref_ptr collider1, ref_ptr collider2, ref_ptr rigidbody1, ref_ptr rigidbody2); + }; + + vec3 closestPtPointTriangle(const vec3& p, const vec3& v0, const vec3& v1, const vec3& v2); + + +} /* end of vxr namespace */ \ No newline at end of file diff --git a/project/VXR.lib b/project/VXR.lib index b2221b3..8062ced 100644 Binary files a/project/VXR.lib and b/project/VXR.lib differ diff --git a/project/VXR.pdb b/project/VXR.pdb deleted file mode 100644 index 08b8905..0000000 Binary files a/project/VXR.pdb and /dev/null differ diff --git a/project/genie.lua b/project/genie.lua index 6ec3c66..66fbfe2 100644 --- a/project/genie.lua +++ b/project/genie.lua @@ -180,4 +180,5 @@ makeProject("02-Instancing") makeProject("03-Framebuffers") makeProject("04-Mesh") makeProject("05-Materials") -makeProject("06-Procedural") \ No newline at end of file +makeProject("06-Procedural") +makeProject("07-Physics") \ No newline at end of file diff --git a/project/vs2017/01-HelloWorld.vcxproj b/project/vs/01-HelloWorld.vcxproj similarity index 97% rename from project/vs2017/01-HelloWorld.vcxproj rename to project/vs/01-HelloWorld.vcxproj index 079ad53..fb0cbe7 100644 --- a/project/vs2017/01-HelloWorld.vcxproj +++ b/project/vs/01-HelloWorld.vcxproj @@ -209,7 +209,6 @@ - diff --git a/project/vs2017/01-HelloWorld.vcxproj.filters b/project/vs/01-HelloWorld.vcxproj.filters similarity index 85% rename from project/vs2017/01-HelloWorld.vcxproj.filters rename to project/vs/01-HelloWorld.vcxproj.filters index df394da..21534ad 100644 --- a/project/vs2017/01-HelloWorld.vcxproj.filters +++ b/project/vs/01-HelloWorld.vcxproj.filters @@ -9,9 +9,6 @@ - - examples\01-HelloWorld - examples\01-HelloWorld diff --git a/project/vs2017/01-HelloWorld.vcxproj.user b/project/vs/01-HelloWorld.vcxproj.user similarity index 100% rename from project/vs2017/01-HelloWorld.vcxproj.user rename to project/vs/01-HelloWorld.vcxproj.user diff --git a/project/vs2017/02-Instancing.vcxproj b/project/vs/02-Instancing.vcxproj similarity index 97% rename from project/vs2017/02-Instancing.vcxproj rename to project/vs/02-Instancing.vcxproj index 4b201c5..799aefa 100644 --- a/project/vs2017/02-Instancing.vcxproj +++ b/project/vs/02-Instancing.vcxproj @@ -209,7 +209,6 @@ - diff --git a/project/vs2017/02-Instancing.vcxproj.filters b/project/vs/02-Instancing.vcxproj.filters similarity index 85% rename from project/vs2017/02-Instancing.vcxproj.filters rename to project/vs/02-Instancing.vcxproj.filters index 81adb5d..9e87354 100644 --- a/project/vs2017/02-Instancing.vcxproj.filters +++ b/project/vs/02-Instancing.vcxproj.filters @@ -9,9 +9,6 @@ - - examples\02-Instancing - examples\02-Instancing diff --git a/project/vs2017/02-Instancing.vcxproj.user b/project/vs/02-Instancing.vcxproj.user similarity index 100% rename from project/vs2017/02-Instancing.vcxproj.user rename to project/vs/02-Instancing.vcxproj.user diff --git a/project/vs2017/03-Framebuffers.vcxproj b/project/vs/03-Framebuffers.vcxproj similarity index 97% rename from project/vs2017/03-Framebuffers.vcxproj rename to project/vs/03-Framebuffers.vcxproj index 97acdfa..e5f9fdc 100644 --- a/project/vs2017/03-Framebuffers.vcxproj +++ b/project/vs/03-Framebuffers.vcxproj @@ -209,7 +209,6 @@ - diff --git a/project/vs2017/03-Framebuffers.vcxproj.filters b/project/vs/03-Framebuffers.vcxproj.filters similarity index 85% rename from project/vs2017/03-Framebuffers.vcxproj.filters rename to project/vs/03-Framebuffers.vcxproj.filters index 6c2409c..cc1281a 100644 --- a/project/vs2017/03-Framebuffers.vcxproj.filters +++ b/project/vs/03-Framebuffers.vcxproj.filters @@ -9,9 +9,6 @@ - - examples\03-Framebuffers - examples\03-Framebuffers diff --git a/project/vs2017/03-Framebuffers.vcxproj.user b/project/vs/03-Framebuffers.vcxproj.user similarity index 100% rename from project/vs2017/03-Framebuffers.vcxproj.user rename to project/vs/03-Framebuffers.vcxproj.user diff --git a/project/vs2017/04-Mesh.vcxproj b/project/vs/04-Mesh.vcxproj similarity index 97% rename from project/vs2017/04-Mesh.vcxproj rename to project/vs/04-Mesh.vcxproj index 281a6d3..70d0514 100644 --- a/project/vs2017/04-Mesh.vcxproj +++ b/project/vs/04-Mesh.vcxproj @@ -209,8 +209,6 @@ - - diff --git a/project/vs2017/04-Mesh.vcxproj.filters b/project/vs/04-Mesh.vcxproj.filters similarity index 77% rename from project/vs2017/04-Mesh.vcxproj.filters rename to project/vs/04-Mesh.vcxproj.filters index 672eb6c..2d2aea3 100644 --- a/project/vs2017/04-Mesh.vcxproj.filters +++ b/project/vs/04-Mesh.vcxproj.filters @@ -9,12 +9,6 @@ - - examples\04-Mesh - - - examples\04-Mesh - examples\04-Mesh diff --git a/project/vs2017/04-Mesh.vcxproj.user b/project/vs/04-Mesh.vcxproj.user similarity index 100% rename from project/vs2017/04-Mesh.vcxproj.user rename to project/vs/04-Mesh.vcxproj.user diff --git a/project/vs2017/05-Materials.vcxproj b/project/vs/05-Materials.vcxproj similarity index 96% rename from project/vs2017/05-Materials.vcxproj rename to project/vs/05-Materials.vcxproj index 71a9769..98b23a9 100644 --- a/project/vs2017/05-Materials.vcxproj +++ b/project/vs/05-Materials.vcxproj @@ -209,8 +209,6 @@ - - diff --git a/project/vs2017/05-Materials.vcxproj.filters b/project/vs/05-Materials.vcxproj.filters similarity index 76% rename from project/vs2017/05-Materials.vcxproj.filters rename to project/vs/05-Materials.vcxproj.filters index 885f727..310f55f 100644 --- a/project/vs2017/05-Materials.vcxproj.filters +++ b/project/vs/05-Materials.vcxproj.filters @@ -9,12 +9,6 @@ - - examples\05-Materials - - - examples\05-Materials - examples\05-Materials diff --git a/project/vs2017/05-Materials.vcxproj.user b/project/vs/05-Materials.vcxproj.user similarity index 100% rename from project/vs2017/05-Materials.vcxproj.user rename to project/vs/05-Materials.vcxproj.user diff --git a/project/vs2017/06-Procedural.vcxproj b/project/vs/06-Procedural.vcxproj similarity index 97% rename from project/vs2017/06-Procedural.vcxproj rename to project/vs/06-Procedural.vcxproj index b868b2a..d72d965 100644 --- a/project/vs2017/06-Procedural.vcxproj +++ b/project/vs/06-Procedural.vcxproj @@ -249,8 +249,6 @@ - - diff --git a/project/vs2017/06-Procedural.vcxproj.filters b/project/vs/06-Procedural.vcxproj.filters similarity index 92% rename from project/vs2017/06-Procedural.vcxproj.filters rename to project/vs/06-Procedural.vcxproj.filters index e37445e..11d8a1f 100644 --- a/project/vs2017/06-Procedural.vcxproj.filters +++ b/project/vs/06-Procedural.vcxproj.filters @@ -18,12 +18,6 @@ - - examples\06-Procedural - - - examples\06-Procedural - examples\06-Procedural diff --git a/project/vs2017/06-Procedural.vcxproj.user b/project/vs/06-Procedural.vcxproj.user similarity index 100% rename from project/vs2017/06-Procedural.vcxproj.user rename to project/vs/06-Procedural.vcxproj.user diff --git a/project/vs/07-Physics.vcxproj b/project/vs/07-Physics.vcxproj new file mode 100644 index 0000000..56a9441 --- /dev/null +++ b/project/vs/07-Physics.vcxproj @@ -0,0 +1,235 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {5CB6918F-486E-D3DC-B175-AC389D4C6ECD} + 07-Physics + 10.0.17134.0 + 10.0.10240.0 + Win32Proj + + + + Application + true + v141 + + + Application + true + v141 + + + Application + false + v141 + + + Application + false + v141 + + + + + + + + + + + + + + + + + + + ..\..\examples\07-Physics\ + d:\GoogleDrive\Programming\Current Projects\VXR\vxr-engine\project\vs\obj\x32\Debug\07-Physics\ + 07-Physics + .exe + true + + + ..\..\examples\07-Physics\ + d:\GoogleDrive\Programming\Current Projects\VXR\vxr-engine\project\vs\obj\x64\Debug\07-Physics\ + 07-Physics + .exe + true + + + ..\..\examples\07-Physics\ + d:\GoogleDrive\Programming\Current Projects\VXR\vxr-engine\project\vs\obj\x32\Release\07-Physics\ + 07-Physics + .exe + false + + + ..\..\examples\07-Physics\ + d:\GoogleDrive\Programming\Current Projects\VXR\vxr-engine\project\vs\obj\x64\Release\07-Physics\ + 07-Physics + .exe + false + + + + /wd4100 /wd4127 /wd4244 %(AdditionalOptions) + Disabled + ..\..\examples\07-Physics\assets;%(AdditionalIncludeDirectories) + VXR_DEBUG;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebugDLL + true + true + + Level4 + EditAndContinue + + + VXR_DEBUG;%(PreprocessorDefinitions) + ..\..\examples\07-Physics\assets;%(AdditionalIncludeDirectories) + + + Console + true + $(OutDir)07-Physics.pdb + opengl32.lib;%(AdditionalDependencies) + $(OutDir)07-Physics.exe + mainCRTStartup + MachineX86 + + + + + /wd4100 /wd4127 /wd4244 %(AdditionalOptions) + Disabled + ..\..\examples\07-Physics\assets;%(AdditionalIncludeDirectories) + VXR_DEBUG;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebugDLL + true + true + + Level4 + EditAndContinue + + + VXR_DEBUG;%(PreprocessorDefinitions) + ..\..\examples\07-Physics\assets;%(AdditionalIncludeDirectories) + + + Console + true + $(OutDir)07-Physics.pdb + opengl32.lib;%(AdditionalDependencies) + $(OutDir)07-Physics.exe + mainCRTStartup + MachineX64 + + + + + /wd4100 /wd4127 /wd4244 %(AdditionalOptions) + Full + ..\..\examples\07-Physics\assets;%(AdditionalIncludeDirectories) + VXR_RELEASE;%(PreprocessorDefinitions) + false + true + MultiThreadedDLL + true + true + + Level3 + + + + VXR_RELEASE;%(PreprocessorDefinitions) + ..\..\examples\07-Physics\assets;%(AdditionalIncludeDirectories) + + + Console + false + true + true + opengl32.lib;%(AdditionalDependencies) + $(OutDir)07-Physics.exe + mainCRTStartup + MachineX86 + + + + + /wd4100 /wd4127 /wd4244 %(AdditionalOptions) + Full + ..\..\examples\07-Physics\assets;%(AdditionalIncludeDirectories) + VXR_RELEASE;%(PreprocessorDefinitions) + false + true + MultiThreadedDLL + true + true + + Level3 + + + + VXR_RELEASE;%(PreprocessorDefinitions) + ..\..\examples\07-Physics\assets;%(AdditionalIncludeDirectories) + + + Console + false + true + true + opengl32.lib;%(AdditionalDependencies) + $(OutDir)07-Physics.exe + mainCRTStartup + MachineX64 + + + + + + + + $(IntDir)examples\07-Physics\ + + + + + + + + + + + + + {652C880B-D135-887C-5AB1-9E7CC6B9937C} + + + + + + diff --git a/project/vs/07-Physics.vcxproj.filters b/project/vs/07-Physics.vcxproj.filters new file mode 100644 index 0000000..4757cd9 --- /dev/null +++ b/project/vs/07-Physics.vcxproj.filters @@ -0,0 +1,44 @@ + + + + + {84D830B1-70A5-8BBC-99BE-796485EAC04A} + + + {77F8AA6E-E359-887C-6CC7-CE2ED827BF3B} + + + {86F5D138-7205-7E09-DBBE-E227C7ED6CA2} + + + + + examples\07-Physics + + + examples\07-Physics\assets + + + examples\07-Physics\assets + + + examples\07-Physics\assets + + + examples\07-Physics\assets + + + examples\07-Physics\assets + + + + + examples\07-Physics + + + + + examples\07-Physics + + + diff --git a/project/vs/07-Physics.vcxproj.user b/project/vs/07-Physics.vcxproj.user new file mode 100644 index 0000000..6039300 --- /dev/null +++ b/project/vs/07-Physics.vcxproj.user @@ -0,0 +1,23 @@ + + + + WindowsLocalDebugger + ..\..\examples\07-Physics + + + + WindowsLocalDebugger + ..\..\examples\07-Physics + + + + WindowsLocalDebugger + ..\..\examples\07-Physics + + + + WindowsLocalDebugger + ..\..\examples\07-Physics + + + diff --git a/project/vs2017/VXR-Engine.sln b/project/vs/VXR-Engine.sln similarity index 88% rename from project/vs2017/VXR-Engine.sln rename to project/vs/VXR-Engine.sln index c8b76fd..a7d5153 100644 --- a/project/vs2017/VXR-Engine.sln +++ b/project/vs/VXR-Engine.sln @@ -38,6 +38,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "06-Procedural", "06-Procedu {652C880B-D135-887C-5AB1-9E7CC6B9937C} = {652C880B-D135-887C-5AB1-9E7CC6B9937C} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "07-Physics", "07-Physics.vcxproj", "{5CB6918F-486E-D3DC-B175-AC389D4C6ECD}" + ProjectSection(ProjectDependencies) = postProject + {652C880B-D135-887C-5AB1-9E7CC6B9937C} = {652C880B-D135-887C-5AB1-9E7CC6B9937C} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -110,6 +115,14 @@ Global {49D9635E-B599-DF94-7ED4-2812EA532471}.Release|Win32.Build.0 = Release|Win32 {49D9635E-B599-DF94-7ED4-2812EA532471}.Release|x64.ActiveCfg = Release|x64 {49D9635E-B599-DF94-7ED4-2812EA532471}.Release|x64.Build.0 = Release|x64 + {5CB6918F-486E-D3DC-B175-AC389D4C6ECD}.Debug|Win32.ActiveCfg = Debug|Win32 + {5CB6918F-486E-D3DC-B175-AC389D4C6ECD}.Debug|Win32.Build.0 = Debug|Win32 + {5CB6918F-486E-D3DC-B175-AC389D4C6ECD}.Debug|x64.ActiveCfg = Debug|x64 + {5CB6918F-486E-D3DC-B175-AC389D4C6ECD}.Debug|x64.Build.0 = Debug|x64 + {5CB6918F-486E-D3DC-B175-AC389D4C6ECD}.Release|Win32.ActiveCfg = Release|Win32 + {5CB6918F-486E-D3DC-B175-AC389D4C6ECD}.Release|Win32.Build.0 = Release|Win32 + {5CB6918F-486E-D3DC-B175-AC389D4C6ECD}.Release|x64.ActiveCfg = Release|x64 + {5CB6918F-486E-D3DC-B175-AC389D4C6ECD}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/project/vs2017/VXR.vcxproj b/project/vs/VXR.vcxproj similarity index 94% rename from project/vs2017/VXR.vcxproj rename to project/vs/VXR.vcxproj index 2afdd0f..fe35eb0 100644 --- a/project/vs2017/VXR.vcxproj +++ b/project/vs/VXR.vcxproj @@ -198,11 +198,13 @@ + + @@ -221,6 +223,7 @@ + @@ -243,6 +246,10 @@ + + + + @@ -427,6 +434,9 @@ $(IntDir)src\components\ + + $(IntDir)src\components\ + $(IntDir)src\components\ @@ -442,6 +452,9 @@ $(IntDir)src\components\ + + $(IntDir)src\components\ + $(IntDir)src\components\ @@ -484,6 +497,9 @@ $(IntDir)src\graphics\ + + $(IntDir)src\graphics\ + $(IntDir)src\graphics\ @@ -553,6 +569,18 @@ $(IntDir)src\graphics\ui\ + + $(IntDir)src\physics\ + + + $(IntDir)src\physics\ + + + $(IntDir)src\physics\ + + + $(IntDir)src\physics\ + $(IntDir)src\utils\ diff --git a/project/vs2017/VXR.vcxproj.filters b/project/vs/VXR.vcxproj.filters similarity index 94% rename from project/vs2017/VXR.vcxproj.filters rename to project/vs/VXR.vcxproj.filters index d62752a..e57ba24 100644 --- a/project/vs2017/VXR.vcxproj.filters +++ b/project/vs/VXR.vcxproj.filters @@ -28,6 +28,9 @@ {DE34C8E4-CA02-BCEA-B396-2C119F03984F} + + {A82F986C-14BB-0531-1DCC-882589D66131} + {16A8490F-8268-C545-4BA3-0EC3B7220A22} @@ -64,6 +67,9 @@ {F45FD7D4-60EB-4499-69FC-C78DD506A199} + + {4C8F6D3D-B844-E632-4139-E009ADEDDC36} + {BACE3A1F-2639-EF95-6F77-A03BDB20CDEA} @@ -488,6 +494,9 @@ include\components + + include\components + include\components @@ -503,6 +512,9 @@ include\components + + include\components + include\components @@ -557,6 +569,9 @@ include\graphics + + include\graphics + include\graphics @@ -623,6 +638,18 @@ include\memory + + include\physics + + + include\physics + + + include\physics + + + include\physics + include\utils @@ -1165,6 +1192,9 @@ src\components + + src\components + src\components @@ -1180,6 +1210,9 @@ src\components + + src\components + src\components @@ -1222,6 +1255,9 @@ src\graphics + + src\graphics + src\graphics @@ -1291,6 +1327,18 @@ src\graphics\ui + + src\physics + + + src\physics + + + src\physics + + + src\physics + src\utils diff --git a/project/vs2017/VXR.vcxproj.user b/project/vs/VXR.vcxproj.user similarity index 100% rename from project/vs2017/VXR.vcxproj.user rename to project/vs/VXR.vcxproj.user diff --git a/project/vs2017/dev.vcxproj b/project/vs/dev.vcxproj similarity index 96% rename from project/vs2017/dev.vcxproj rename to project/vs/dev.vcxproj index 86d9d3e..abe89be 100644 --- a/project/vs2017/dev.vcxproj +++ b/project/vs/dev.vcxproj @@ -210,7 +210,10 @@ + + + diff --git a/project/vs2017/dev.vcxproj.filters b/project/vs/dev.vcxproj.filters similarity index 73% rename from project/vs2017/dev.vcxproj.filters rename to project/vs/dev.vcxproj.filters index 4a3391a..55f0b71 100644 --- a/project/vs2017/dev.vcxproj.filters +++ b/project/vs/dev.vcxproj.filters @@ -12,9 +12,18 @@ examples\dev + + examples\dev + + + examples\dev + examples\dev + + examples\dev + diff --git a/project/vs2017/dev.vcxproj.user b/project/vs/dev.vcxproj.user similarity index 100% rename from project/vs2017/dev.vcxproj.user rename to project/vs/dev.vcxproj.user diff --git a/src/components/camera.cpp b/src/components/camera.cpp index e2491ca..eb41971 100644 --- a/src/components/camera.cpp +++ b/src/components/camera.cpp @@ -170,7 +170,6 @@ namespace vxr } System::Camera::Camera() : - scene_(nullptr), main_(nullptr), render_to_screen_(true) { @@ -178,13 +177,13 @@ namespace vxr System::Camera::~Camera() { - } void System::Camera::set_main(ref_ptr camera) { if (!camera || !scene_) { + main_ = nullptr; return; } @@ -210,30 +209,23 @@ namespace vxr common_uniforms_.buffer = Engine::ref().gpu()->createBuffer({ BufferType::Uniform, sizeof(common_uniforms_.data), Usage::Static, "Common" }); } - void System::Camera::update() + void System::Camera::onSceneChanged() { - if (scene_ != Engine::ref().scene()) - { - scene_ = Engine::ref().scene(); - main_ = nullptr; - set_main(scene_->default_camera()); - // Scene changed - } + ComponentSystem::onSceneChanged(); + set_main(nullptr); + } - if (!main_ && scene_.get()) + void System::Camera::start() + { + set_main(scene_->default_camera()); + if (!main_) { - // Find camera in scene set_main(scene_->findCameraInScene()); } } - void System::Camera::renderUpdate() + void System::Camera::renderPreUpdate() { - if (!scene_) - { - return; - } - if (!main_) { // Dummy commands to keep the engine running. @@ -244,9 +236,16 @@ namespace vxr VXR_LOG(VXR_DEBUG_LEVEL_ERROR, "[ERROR]: [CAMERA] No camera instantiated in the scene.\n"); return; } + } - VXR_TRACE_SCOPE("VXR", "Camera Render Update"); + void System::Camera::renderUpdate() + { + if (!main_) + { + return; + } + VXR_TRACE_SCOPE("VXR", "Camera Render Update"); main_->composer()->setupFirstPass(); DisplayList frame; @@ -281,7 +280,7 @@ namespace vxr void System::Camera::renderPostUpdate() { - if (!main_ || !scene_) + if (!main_) { return; } diff --git a/src/components/collider.cpp b/src/components/collider.cpp new file mode 100644 index 0000000..163bc80 --- /dev/null +++ b/src/components/collider.cpp @@ -0,0 +1,71 @@ +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "../../include/components/collider.h" +#include "../../include/components/rigidbody.h" +#include "../../include/engine/engine.h" +#include "../../include/core/gameobject.h" +#include "../../include/core/scene.h" + +namespace vxr +{ + + Collider::Collider() + { + set_name("Collider"); + } + + Collider::~Collider() + { + } + + void Collider::onGUI() + { + Component::onGUI(); + } + + void Collider::set_shape(ref_ptr shape) + { + shape_ = shape; + } + + ref_ptr Collider::shape() const + { + return shape_; + } + + System::Collider::Collider() + { + set_name("Collider System"); + } + + System::Collider::~Collider() + { + } + + ref_ptr System::Getter::get() + { + return Engine::ref().collider(); + } +} \ No newline at end of file diff --git a/src/components/custom.cpp b/src/components/custom.cpp index e854420..83a6ed0 100644 --- a/src/components/custom.cpp +++ b/src/components/custom.cpp @@ -50,69 +50,64 @@ namespace vxr } - void System::Custom::start() + void System::Custom::init() { - if (scene_ != Engine::ref().scene()) - { - scene_ = Engine::ref().scene(); - } - if (!scene_) - { - return; - } for (auto &c : components_) { if (scene_->id() != c->gameObject()->scene_id()) { continue; } + if (c->enabled()) { if (!c->initialized_) { - c->start(); + c->init(); c->initialized_ = true; } } } } - void System::Custom::update() + void System::Custom::start() { - if (scene_ != Engine::ref().scene()) - { - scene_ = Engine::ref().scene(); - // Scene changed - } - if (!scene_) - { - return; - } for (auto &c : components_) { if (scene_->id() != c->gameObject()->scene_id()) { continue; } - if (c->enabled()) + + if (c->enabled()) { if (!c->initialized_) { - c->start(); + c->init(); c->initialized_ = true; } - - c->update(); + c->start(); } } } - void System::Custom::postUpdate() + void System::Custom::preUpdate() { - if (!scene_) + for (auto &c : components_) { - return; + if (scene_->id() != c->gameObject()->scene_id()) + { + continue; + } + if (c->enabled()) + { + c->preUpdate(); + } } + } + + void System::Custom::update(float dt) + { for (auto &c : components_) { if (scene_->id() != c->gameObject()->scene_id()) @@ -120,18 +115,44 @@ namespace vxr continue; } if (c->enabled()) + { + c->update(dt); + } + } + } + + void System::Custom::postUpdate() + { + for (auto &c : components_) + { + if (scene_->id() != c->gameObject()->scene_id()) + { + continue; + } + if (c->enabled()) { c->postUpdate(); } } } - void System::Custom::renderUpdate() + void System::Custom::renderPreUpdate() { - if (!scene_) + for (auto &c : components_) { - return; + if (scene_->id() != c->gameObject()->scene_id()) + { + continue; + } + if (c->enabled()) + { + c->renderPreUpdate(); + } } + } + + void System::Custom::renderUpdate() + { for (auto &c : components_) { if (scene_->id() != c->gameObject()->scene_id()) @@ -147,10 +168,6 @@ namespace vxr void System::Custom::renderPostUpdate() { - if (!scene_) - { - return; - } for (auto &c : components_) { if (scene_->id() != c->gameObject()->scene_id()) @@ -166,10 +183,6 @@ namespace vxr void System::Custom::stop() { - if (!scene_) - { - return; - } for (auto &c : components_) { if (scene_->id() != c->gameObject()->scene_id()) @@ -178,7 +191,10 @@ namespace vxr } if (c->enabled()) { - c->stop(); + if (c->initialized_) + { + c->stop(); + } } } } diff --git a/src/components/ibl.cpp b/src/components/ibl.cpp index 7490c8e..6fe2ede 100644 --- a/src/components/ibl.cpp +++ b/src/components/ibl.cpp @@ -138,7 +138,7 @@ namespace vxr main_ = light; if (main_->initialized()) { - //main_->initialization_level_ = 0; + ///main_->initialization_level_ = 0; updateMaterialIBLTextures(); } } @@ -149,43 +149,34 @@ namespace vxr return main_; } - void System::IBL::init() + void System::IBL::onSceneChanged() { + ComponentSystem::onSceneChanged(); + set_main(nullptr); } - void System::IBL::update() + void System::IBL::start() { - if (scene_ != Engine::ref().scene()) + // Find IBL in scene + ref_ptr skybox = Engine::ref().scene()->skybox(); + if (skybox != nullptr) { - scene_ = Engine::ref().scene(); - set_main(nullptr); - // Scene changed + set_main(skybox->getComponent()); } - - if (!main_ && scene_.get()) + else { - // Find IBL in scene - ref_ptr skybox = Engine::ref().scene()->skybox(); - if (skybox != nullptr) - { - set_main(skybox->getComponent()); - } - else - { - set_main(nullptr); - } + set_main(nullptr); } } void System::IBL::renderUpdate() { - if (!main_ || !scene_) + if (!main_) { return; } VXR_TRACE_SCOPE("VXR", "IBL Render Update"); - if (!main_->gameObject()->active() || main_->initialized()) { return; @@ -222,16 +213,6 @@ namespace vxr VXR_LOG(VXR_DEBUG_LEVEL_INFO, "[INFO]: [IBL] Maps recomputed correctly.\n"); } - void System::IBL::renderPostUpdate() - { - if (!main_ || !scene_) - { - return; - } - - VXR_TRACE_SCOPE("VXR", "IBL Render Post Update"); - } - bool System::IBL::buildCubemap() { if (main_->initialization_level_ >= 1) diff --git a/src/components/light.cpp b/src/components/light.cpp index 437d904..1de8915 100644 --- a/src/components/light.cpp +++ b/src/components/light.cpp @@ -68,7 +68,7 @@ namespace vxr ImGui::Combo(uiText("##Type").c_str(), (int*)&type_, "Punctual\0Directional\0\0"); ImGui::Spacing(); ImGui::Text("Ambient "); ImGui::SameLine(); - ImGui::DragFloat(uiText("##Ambient").c_str(), &ambient_, 0.01f, -FLT_MAX, FLT_MAX); + ImGui::DragFloat(uiText("##Ambient").c_str(), &ambient_, 0.01f, -FLT_MAX, FLT_MAX);/// ImGui::Text("Intensity "); ImGui::SameLine(); ImGui::DragFloat(uiText("##Intensity").c_str(), &intensity_, 0.01f, -FLT_MAX, FLT_MAX); ImGui::Spacing(); @@ -115,12 +115,10 @@ namespace vxr System::Light::Light() { - num_lights_ = 0; } System::Light::~Light() { - } void System::Light::init() @@ -131,23 +129,9 @@ namespace vxr "Lights" }); } - void System::Light::update() + void System::Light::renderPreUpdate() { - if (scene_ != Engine::ref().scene()) - { - scene_ = Engine::ref().scene(); - // Scene changed - } - } - - void System::Light::renderUpdate() - { - VXR_TRACE_SCOPE("VXR", "Light Render Update"); - if (!scene_) - { - return; - } - + VXR_TRACE_SCOPE("VXR", "Light Render Pre Update"); num_lights_ = 0; for (auto &c : components_) { @@ -160,6 +144,7 @@ namespace vxr if (num_lights_ < kMaxLightSources) { c->contributes_ = true; + /// Will need transformations for shadows /*if (c->hasChanged()) { c->computeTransformations(); @@ -182,20 +167,6 @@ namespace vxr Engine::ref().submitDisplayList(std::move(frame)); } - void System::Light::renderPostUpdate() - { - VXR_TRACE_SCOPE("VXR", "Light Render Post Update"); - if (!scene_) - { - return; - } - - /*for (auto &c : components_) - { - //c->dirty_ = false; - }*/ - } - uint32 System::Light::num_lights() const { return num_lights_; diff --git a/src/components/mesh_filter.cpp b/src/components/mesh_filter.cpp index d4ada27..ea23743 100644 --- a/src/components/mesh_filter.cpp +++ b/src/components/mesh_filter.cpp @@ -59,11 +59,6 @@ namespace vxr } - void System::MeshFilter::init() - { - - } - ref_ptr System::Getter::get() { return Engine::ref().meshFilter(); diff --git a/src/components/renderer.cpp b/src/components/renderer.cpp index 5f98ac5..5d1a2df 100644 --- a/src/components/renderer.cpp +++ b/src/components/renderer.cpp @@ -61,28 +61,9 @@ namespace vxr { } - void System::Renderer::init() - { - - } - - void System::Renderer::update() - { - if (scene_ != Engine::ref().scene()) - { - scene_ = Engine::ref().scene(); - // Scene changed - } - } - void System::Renderer::renderUpdate() { VXR_TRACE_SCOPE("VXR", "Renderer Render Update"); - if (!scene_) - { - return; - } - transparent_.clear(); DisplayList frame; @@ -107,11 +88,6 @@ namespace vxr void System::Renderer::renderPostUpdate() { VXR_TRACE_SCOPE("VXR", "Renderer Render Post Update"); - if (!scene_) - { - return; - } - ref_ptr camera = Engine::ref().camera()->main(); if (!camera) { @@ -124,7 +100,7 @@ namespace vxr } DisplayList frame; - for (auto &c : transparent_) + for (auto &c : transparent_) /// Need to sort the transparent objects. { // Send render commands. render(c, &frame); diff --git a/src/components/rigidbody.cpp b/src/components/rigidbody.cpp new file mode 100644 index 0000000..e3eb3e4 --- /dev/null +++ b/src/components/rigidbody.cpp @@ -0,0 +1,380 @@ +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "../../include/components/rigidbody.h" +#include "../../include/components/collider.h" +#include "../../include/engine/engine.h" +#include "../../include/graphics/window.h" +#include "../../include/core/gameobject.h" +#include "../../include/core/scene.h" + +namespace vxr +{ + + Rigidbody::Rigidbody() + { + set_name("Rigidbody"); + set_mass(mass_); + } + + Rigidbody::~Rigidbody() + { + } + + void Rigidbody::onGUI() + { + ImGui::Text("Use Gravity "); ImGui::SameLine(); + ImGui::Checkbox(uiText("##UseGravity").c_str(), &use_gravity_); + ImGui::Text("Mass "); ImGui::SameLine(); + ImGui::DragFloat(uiText("##Mass").c_str(), (float*)&mass_, 0.01f, -FLT_MAX, FLT_MAX); + ImGui::Text("Velocity "); ImGui::SameLine(); + ImGui::DragFloat3(uiText("##Velocity").c_str(), (float*)&velocity_, 0.01f, -FLT_MAX, FLT_MAX); + } + + void Rigidbody::set_use_gravity(const bool use_gravity) + { + use_gravity_ = use_gravity; + } + + void Rigidbody::set_velocity(const vec3& velocity) + { + velocity_ = velocity; + } + + void Rigidbody::addVelocity(const vec3& velocity) + { + velocity_ += velocity; + } + + void Rigidbody::set_mass(const float mass) + { + mass_ = mass; + inv_mass_ = (mass == 0.0f) ? 0.0f : 1 / mass_; + } + + void Rigidbody::set_restitution(const float restitution_coeff) + { + restitution_ = restitution_coeff; + } + + const bool Rigidbody::use_gravity() const + { + return use_gravity_; + } + + const vec3 Rigidbody::velocity() const + { + return velocity_; + } + + const float Rigidbody::mass() const + { + return mass_; + } + + const float Rigidbody::inverseMass() const + { + return inv_mass_; + } + + const float Rigidbody::restitution() const + { + return restitution_; + } + + void Rigidbody::applyCentralForce(const vec3& force) + { + total_force_ += force * linear_factor_; + } + + void Rigidbody::applyGravity() + { + if (use_gravity_) + { + applyCentralForce(Engine::ref().rigidbody()->gravity()); + } + } + + void Rigidbody::integrateVelocities(float dt) + { + velocity_ += total_force_ * inv_mass_ * dt; + /// Update angular velocity. + } + + void Rigidbody::applyDamping(float dt) + { + velocity_ *= glm::pow(1.0f - Engine::ref().rigidbody()->linearDamping(), dt); + } + + void Rigidbody::clearForces() + { + total_force_ = vec3(0.0f); + } + + System::Rigidbody::Rigidbody() + { + } + + System::Rigidbody::~Rigidbody() + { + } + + void System::Rigidbody::preUpdate() + { + VXR_TRACE_SCOPE("VXR", "Rigidbody Pre Update"); + + scene_components_.clear(); + scene_collision_pairs_.clear(); + scene_aabb_.clear(); + +#ifdef VXR_PHYSICS_NO_BROADPHASE + for (uint32 i = 0; i < components_.size(); ++i) + { + if (scene_->id() != components_[i]->gameObject()->scene_id() || !components_[i]->gameObject()->active()) + { + continue; + } + + scene_components_.push_back(components_[i]); + + ref_ptr rg1 = components_[i]; + ref_ptr col1 = rg1->getComponent(); + + if (!col1) + { + continue; + } + + for (uint32 j = i + 1; j < components_.size(); ++j) + { + if (scene_->id() != components_[j]->gameObject()->scene_id() || !components_[j]->gameObject()->active()) + { + continue; + } + + ref_ptr rg2 = components_[j]; + ref_ptr col2 = rg2->getComponent(); + if (!col2 || col1 == col2) + { + continue; + } + + scene_collision_pairs_.push_back(Hit(col1, col2, rg1, rg2)); + } + } +#else + for (uint32 i = 0; i < components_.size(); ++i) + { + if (scene_->id() != components_[i]->gameObject()->scene_id() || !components_[i]->gameObject()->active()) + { + continue; + } + + scene_components_.push_back(components_[i]); + + ref_ptr rg1 = components_[i]; + ref_ptr col1 = rg1->getComponent(); + + if (!col1) + { + continue; + } + + AABB aabb; + col1->shape()->getAabb(rg1->transform(), aabb.min, aabb.max); + aabb.scene_index_ = i; + scene_aabb_.push_back(aabb); + } + + std::sort(scene_aabb_.begin(), scene_aabb_.end(), [this](const AABB& a, const AABB& b) -> int { return a.min[sorting_axis_] > b.min[sorting_axis_]; }); + + vec3 s1 = vec3(0.0f); + vec3 s2 = vec3(0.0f); + scene_collision_pairs_.clear(); + for (uint32 i = 0; i < scene_aabb_.size(); ++i) + { + AABB aabb_i = scene_aabb_[i]; + ref_ptr rg1 = components_[aabb_i.scene_index_]; + ref_ptr col1 = rg1->getComponent(); + + if (!col1) + { + continue; + } + + vec3 p = 0.5f * (aabb_i.min + aabb_i.max); + + s1 += p; + s2 += p * p; + + for (uint32 j = i + 1; j < scene_aabb_.size(); ++j) + { + AABB aabb_j = scene_aabb_[j]; + ref_ptr rg2 = components_[aabb_j.scene_index_]; + ref_ptr col2 = rg2->getComponent(); + if (!col2 || col1 == col2) + { + continue; + } + + if (col2->shape()->colType() == ColliderShape::Type::HeightMap || col1->shape()->colType() == ColliderShape::Type::HeightMap) + { + scene_collision_pairs_.push_back(Hit(col1, col2, rg1, rg2)); + continue; + } + + if (aabb_j.min[sorting_axis_] > aabb_i.max[sorting_axis_]) + { + break; + } + + if (aabbVsAabb(aabb_i, aabb_j)) + { + scene_collision_pairs_.push_back(Hit(col1, col2, rg1, rg2)); + } + } + } +#endif + } + + void System::Rigidbody::update(float dt) + { + VXR_TRACE_SCOPE("VXR", "Rigidbody Update"); + if (debug_mode_) + { + if (Engine::ref().window()->uptime() - debug_seconds_counter_ >= debug_ratio_) + { + debug_seconds_counter_ += debug_ratio_; + dt = debug_step_; + } + else + { + return; + } + } + + for (auto &c : scene_components_) + { + c->transform()->translate(c->velocity() * dt); + c->applyGravity(); + c->integrateVelocities(dt); + c->applyDamping(dt); + } + + performCollisionDetection(); + + clearForces(); + } + + void System::Rigidbody::set_debug_update(bool enabled, double ratio /* = 1.0 */, double step /* = 1.0 / 60.0 */) + { + debug_mode_ = enabled; + debug_ratio_ = ratio; + debug_step_ = step; + } + + const vec3& System::Rigidbody::gravity() const + { + return gravity_; + } + + const float& System::Rigidbody::linearDamping() const + { + return damping_linear_; + } + + void System::Rigidbody::performCollisionDetection() + { + VXR_TRACE_SCOPE("VXR", "Perform Collision Detection"); + for (auto &hit : scene_collision_pairs_) + { + + hit.col1->shape()->checkCollision(hit); + + if (hit.hit) + { + resolveImpulse(hit); + positionCorrection(hit); + } + } + } + + void System::Rigidbody::clearForces() + { + for (auto &c : scene_components_) + { + c->clearForces(); + } + } + + void System::Rigidbody::resolveImpulse(Hit& hit) + { + vec3 relative_vel = hit.rg2->velocity() - hit.rg1->velocity(); + const float normal_vel = glm::dot(relative_vel, hit.normal); + + // Do not resolve if velocities are separating + if (normal_vel > 0) + { + return; + } + + const float inv_mass_sum = hit.rg1->inverseMass() + hit.rg2->inverseMass(); + const float e = glm::min(hit.rg1->restitution(), hit.rg2->restitution()); + + float j = -(1 + e) * normal_vel; + j /= inv_mass_sum; + + // Apply impulse + vec3 impulse = j * hit.normal; + //const float ratio1 = hit.rg1->mass() * inv_mass_sum; + //const float ratio2 = hit.rg2->mass() * inv_mass_sum; + //hit.rg1->addVelocity(-ratio1 * impulse); + //hit.rg2->addVelocity(+ratio2 * impulse); + hit.rg1->addVelocity(-hit.rg1->inverseMass() * impulse); + hit.rg2->addVelocity(+hit.rg2->inverseMass() * impulse); + } + + void System::Rigidbody::positionCorrection(Hit& hit) + { + const float percent = 0.99f; // Penetration percentage to correct. + const float k_slop = 0.001f; // Penetration allowance. + const float inv_mass_sum = hit.rg1->inverseMass() + hit.rg2->inverseMass(); + vec3 correction = glm::max(hit.penetration_depth - k_slop, 0.0f) / inv_mass_sum * percent * hit.normal; + hit.rg1->transform()->translate(-hit.rg1->inverseMass() * correction); + hit.rg2->transform()->translate(+hit.rg2->inverseMass() * correction); + } + + bool System::Rigidbody::aabbVsAabb(const AABB& a, const AABB& b) + { + if (a.max.x < b.min.x || a.min.x > b.max.x) return false; + if (a.max.y < b.min.y || a.min.y > b.max.y) return false; + if (a.max.z < b.min.z || a.min.z > b.max.z) return false; + return true; + } + + ref_ptr System::Getter::get() + { + return Engine::ref().rigidbody(); + } +} \ No newline at end of file diff --git a/src/components/transform.cpp b/src/components/transform.cpp index 9dfa0d1..0937860 100644 --- a/src/components/transform.cpp +++ b/src/components/transform.cpp @@ -73,6 +73,24 @@ namespace vxr markForUpdate(); } + void Transform::set_local_position_x(const float& v) + { + position_.x = v; + markForUpdate(); + } + + void Transform::set_local_position_y(const float& v) + { + position_.y = v; + markForUpdate(); + } + + void Transform::set_local_position_z(const float& v) + { + position_.z = v; + markForUpdate(); + } + void Transform::set_local_rotation(const quat& rotation) { rotation_ = rotation; @@ -602,36 +620,15 @@ namespace vxr System::Transform::Transform() { - } System::Transform::~Transform() { - - } - - void System::Transform::init() - { - - } - - void System::Transform::update() - { - if (scene_ != Engine::ref().scene()) - { - scene_ = Engine::ref().scene(); - // Scene changed - } } void System::Transform::renderUpdate() { VXR_TRACE_SCOPE("VXR", "Transform Render Update"); - if (!scene_) - { - return; - } - for (auto &c : components_) { if (scene_->id() != c->gameObject()->scene_id()) @@ -655,11 +652,6 @@ namespace vxr } } - void System::Transform::renderPostUpdate() - { - VXR_TRACE_SCOPE("VXR", "Transform Render Post Update"); - } - ref_ptr System::Getter::get() { return Engine::ref().transform(); diff --git a/src/core/component.cpp b/src/core/component.cpp index 7397550..f88295e 100644 --- a/src/core/component.cpp +++ b/src/core/component.cpp @@ -24,6 +24,7 @@ #include "../../include/core/component.h" #include "../../include/core/gameobject.h" +#include "../../include/core/scene.h" namespace vxr { @@ -65,4 +66,9 @@ namespace vxr } + void System::ComponentSystem::onSceneChanged() + { + scene_ = Engine::ref().scene(); + } + } \ No newline at end of file diff --git a/src/engine/application.cpp b/src/engine/application.cpp index 3b55094..cb1bf3f 100644 --- a/src/engine/application.cpp +++ b/src/engine/application.cpp @@ -53,9 +53,14 @@ namespace vxr Engine::ref().start(); } - void Application::update() + void Application::preUpdate() { - Engine::ref().update(); + Engine::ref().preUpdate(); + } + + void Application::update(float dt) + { + Engine::ref().update(dt); } void Application::postUpdate() @@ -63,6 +68,11 @@ namespace vxr Engine::ref().postUpdate(); } + void Application::renderPreUpdate() + { + Engine::ref().renderPreUpdate(); + } + void Application::renderUpdate() { Engine::ref().renderUpdate(); @@ -128,6 +138,7 @@ namespace vxr num_updates = 0; accumulator += deltaTime; VXR_TRACE_BEGIN("VXR", "Loop Update"); + preUpdate(); while (accumulator > framerate_.time_step) { if (num_updates >= framerate_.max_steps) @@ -136,15 +147,16 @@ namespace vxr break; } VXR_TRACE_BEGIN("VXR", "App Update"); - update(); - postUpdate(); + update(this->deltaTime()); VXR_TRACE_END("VXR", "App Update"); accumulator -= framerate_.time_step; num_updates++; } + postUpdate(); VXR_TRACE_END("VXR", "Loop Update"); VXR_TRACE_BEGIN("VXR", "Render Update"); + renderPreUpdate(); renderUpdate(); renderPostUpdate(); VXR_TRACE_END("VXR", "Render Update"); diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index fa1f743..ef49a5b 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -32,6 +32,8 @@ #include "../../include/components/light.h" #include "../../include/components/renderer.h" #include "../../include/components/transform.h" +#include "../../include/components/rigidbody.h" +#include "../../include/components/collider.h" #include "../../include/components/mesh_filter.h" #include "../../include/components/camera.h" #include "../../include/components/custom.h" @@ -84,14 +86,15 @@ namespace vxr custom_.alloc(); camera_.alloc(); renderer_.alloc(); + collider_.alloc(); transform_.alloc(); + rigidbody_.alloc(); mesh_filter_.alloc(); - // Initialize systems gpu_->init(); asset_manager_->init(); - ibl_->init(); + // Initialize systems light_->init(); camera_->init(); @@ -101,40 +104,79 @@ namespace vxr void Engine::start() { - VXR_TRACE_BEGIN("VXR", "Engine Systems Start"); - VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [ENGINE] Engine Start.\n"); - custom_->start(); - VXR_TRACE_END("VXR", "Engine Systems Start"); + if (!scene_) + { + return; + } + startSystems(); + } + + void Engine::preUpdate() + { + if (scene_.get()) + { + VXR_TRACE_BEGIN("VXR", "Engine Systems Pre Update"); + custom_->preUpdate(); + rigidbody_->preUpdate(); + VXR_TRACE_END("VXR", "Engine Systems Pre Update"); + } } - void Engine::update() + void Engine::update(float dt) { + if (!scene_) + { + return; + } + VXR_TRACE_BEGIN("VXR", "Engine Systems Update"); VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [ENGINE] Engine Update.\n"); - custom_->update(); - transform_->update(); - ibl_->update(); - light_->update(); - camera_->update(); - renderer_->update(); + custom_->update(dt); + rigidbody_->update(dt); + VXR_TRACE_END("VXR", "Engine Systems Update"); } void Engine::postUpdate() { + if (!scene_) + { + return; + } + VXR_TRACE_BEGIN("VXR", "Engine Systems Post Update"); VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [ENGINE] Engine Post Update.\n"); custom_->postUpdate(); + VXR_TRACE_END("VXR", "Engine Systems Post Update"); } - void Engine::renderUpdate() + void Engine::renderPreUpdate() { #ifdef VXR_THREADING gpu_->prepareRender(); #endif + if (!scene_) + { + return; + } + + VXR_TRACE_BEGIN("VXR", "Engine Systems Render Pre Update"); + VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [ENGINE] Engine Render Pre Update.\n"); + custom_->renderPreUpdate(); + camera_->renderPreUpdate(); + light_->renderPreUpdate(); + VXR_TRACE_END("VXR", "Engine Systems Render Pre Update"); + + } + + void Engine::renderUpdate() + { + if (!scene_) + { + return; + } VXR_TRACE_BEGIN("VXR", "Systems Render Update"); VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [ENGINE] Engine Render Update.\n"); custom_->renderUpdate(); transform_->renderUpdate(); ibl_->renderUpdate(); - light_->renderUpdate(); camera_->renderUpdate(); renderer_->renderUpdate(); VXR_TRACE_END("VXR", "Systems Render Update"); @@ -142,21 +184,40 @@ namespace vxr void Engine::renderPostUpdate() { - VXR_TRACE_BEGIN("VXR", "Systems Render Post Update"); - VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [ENGINE] Engine Post Render Update.\n"); - custom_->renderPostUpdate(); - transform_->renderPostUpdate(); - renderer_->renderPostUpdate(); - camera_->renderPostUpdate(); - VXR_TRACE_END("VXR", "Systems Render Post Update"); + if (scene_.get()) + { + VXR_TRACE_BEGIN("VXR", "Systems Render Post Update"); + VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [ENGINE] Engine Post Render Update.\n"); + custom_->renderPostUpdate(); + renderer_->renderPostUpdate(); + camera_->renderPostUpdate(); + VXR_TRACE_END("VXR", "Systems Render Post Update"); + } gpu_->execute(); } void Engine::stop() { gpu_->stop(); + stopSystems(); + } + void Engine::startSystems() + { + VXR_TRACE_BEGIN("VXR", "Engine Systems Start"); + VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [ENGINE] Engine Start.\n"); + custom_->start(); + camera_->start(); + ibl_->start(); + VXR_TRACE_END("VXR", "Engine Systems Start"); + } + + void Engine::stopSystems() + { + VXR_TRACE_BEGIN("VXR", "Systems Stop"); + VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [ENGINE] Engine Stop.\n"); custom_->stop(); + VXR_TRACE_END("VXR", "Systems Stop"); } bool Engine::is_exiting() @@ -199,7 +260,30 @@ namespace vxr void Engine::loadScene(ref_ptr scene) { + VXR_TRACE_SCOPE("VXR", "Load Scene"); + VXR_LOG(VXR_DEBUG_LEVEL_INFO, "[INFO]: [ENGINE] Loading scene...\n"); + if (!scene) + { + VXR_LOG(VXR_DEBUG_LEVEL_ERROR, "[ERROR]: [ENGINE] Could not load scene.\n"); + return; + } + + stopSystems(); + scene_ = scene; + + // Update components + ibl_->onSceneChanged(); + light_->onSceneChanged(); + custom_->onSceneChanged(); + camera_->onSceneChanged(); + renderer_->onSceneChanged(); + collider_->onSceneChanged(); + transform_->onSceneChanged(); + rigidbody_->onSceneChanged(); + mesh_filter_->onSceneChanged(); + + startSystems(); } ref_ptr Engine::scene() @@ -237,11 +321,21 @@ namespace vxr return renderer_; } + ref_ptr Engine::collider() + { + return collider_; + } + ref_ptr Engine::transform() { return transform_; } + ref_ptr Engine::rigidbody() + { + return rigidbody_; + } + ref_ptr Engine::meshFilter() { return mesh_filter_; diff --git a/src/engine/gpu.cpp b/src/engine/gpu.cpp index 5da6d14..2e37bfe 100644 --- a/src/engine/gpu.cpp +++ b/src/engine/gpu.cpp @@ -82,29 +82,41 @@ namespace vxr thread_data_.initialized = true; thread_data_.cv_l.notify_one(); + VXR_TRACE_BEGIN("VXR", "Frame"); + VXR_TRACE_BEGIN("VXR", "WAITING (Render)"); + while (!(is_exiting_ = window_->is_exiting())) { VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [GPU] GPU Synchronization (Render Waiting).\n"); std::unique_lock lock(thread_data_.mx_r); - thread_data_.cv_r.wait(lock, [this] { return render_frame_.commands_.empty(); }); - - VXR_TRACE_BEGIN("VXR", "Frame"); - VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [GPU] GPU Synchronization (Render Start).\n"); - window_->events(); + thread_data_.cv_r.wait(lock, [this] { return render_frame_.commands_.empty() /*&& !thread_data_.next_frame.commands_.empty()*/; }); if (!thread_data_.next_frame.commands_.empty()) { + VXR_TRACE_END("VXR", "WAITING (Render)"); + VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [GPU] GPU Synchronization (Render Start).\n"); + window_->events(); render_frame_.commands_.swap(thread_data_.next_frame.commands_); - } - thread_data_.cv_l.notify_one(); - VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [GPU] GPU Synchronization (Render Ready).\n"); + thread_data_.cv_l.notify_one(); + VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [GPU] GPU Synchronization (Render Ready).\n"); - render_frame_.update(); - window_->swap(); - VXR_TRACE_END("VXR", "Frame"); + render_frame_.update(); + window_->swap(); + VXR_TRACE_END("VXR", "Frame"); + VXR_TRACE_BEGIN("VXR", "Frame"); + VXR_TRACE_BEGIN("VXR", "WAITING (Render)"); + } + else + { + thread_data_.cv_l.notify_one(); + VXR_LOG(VXR_DEBUG_LEVEL_DEBUG, "[DEBUG]: [GPU] GPU Synchronization (Render Ready).\n"); + } } + VXR_TRACE_END("VXR", "WAITING (Render)"); + VXR_TRACE_END("VXR", "Frame"); + window_->stop(); thread_data_.cv_l.notify_one(); } diff --git a/src/graphics/backend/opengl/gl_backend.cpp b/src/graphics/backend/opengl/gl_backend.cpp index 3dc459c..2a61566 100644 --- a/src/graphics/backend/opengl/gl_backend.cpp +++ b/src/graphics/backend/opengl/gl_backend.cpp @@ -316,21 +316,33 @@ namespace vxr switch (t.first->info.type) { case TextureType::T1D: - GLCHECK(glTexSubImage1D(GL_TEXTURE_1D, 0, d.offset_x, d.width, back_end.format, back_end.type, d.data)); - break; + if (d.data != nullptr) + { + GLCHECK(glTexSubImage1D(GL_TEXTURE_1D, 0, d.offset_x, d.width, back_end.format, back_end.type, d.data)); + } + break; case TextureType::T2D: - GLCHECK(glTexSubImage2D(GL_TEXTURE_2D, 0, d.offset_x, d.offset_y, d.width, d.height, back_end.format, back_end.type, d.data)); - break; + if (d.data != nullptr) + { + GLCHECK(glTexSubImage2D(GL_TEXTURE_2D, 0, d.offset_x, d.offset_y, d.width, d.height, back_end.format, back_end.type, d.data)); + } + break; case TextureType::T3D: - GLCHECK(glTexSubImage3D(GL_TEXTURE_3D, 0, d.offset_x, d.offset_y, d.offset_z, d.width, d.height, d.depth, back_end.format, back_end.type, d.data)); - break; + if (d.data != nullptr) + { + GLCHECK(glTexSubImage3D(GL_TEXTURE_3D, 0, d.offset_x, d.offset_y, d.offset_z, d.width, d.height, d.depth, back_end.format, back_end.type, d.data)); + } + break; case TextureType::CubeMap: void* data[6] = { (void*)d.data, (void*)d.data_1, (void*)d.data_2, (void*)d.data_3, (void*)d.data_4, (void*)d.data_5 }; for (uint16 i = 0; i < 6; ++i) { - GLCHECK(glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, d.offset_x, d.offset_y, d.width, d.height, back_end.format, back_end.type, data[i])); + if (data[i] != nullptr) + { + GLCHECK(glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, d.offset_x, d.offset_y, d.width, d.height, back_end.format, back_end.type, data[i])); + } } - break; + break; } if (d.build_mipmap) { diff --git a/src/graphics/height_map.cpp b/src/graphics/height_map.cpp new file mode 100644 index 0000000..069664d --- /dev/null +++ b/src/graphics/height_map.cpp @@ -0,0 +1,181 @@ +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "../../include/graphics/height_map.h" + +#include "../../deps/stb/stb_image.h" + +namespace vxr +{ + + mesh::HeightMap::HeightMap() + { + + } + + mesh::HeightMap::~HeightMap() + { + + } + + void mesh::HeightMap::loadHeightMap(const char* file, float grid_size, float height_range, float height_clamp) + { + // Load texture. + int w, h, comp, bytes_per_pixel; + unsigned char* data; + + data = stbi_load(file, &w, &h, &comp, 0); + bytes_per_pixel = comp * sizeof(stbi_uc); + + if (!data) + { + VXR_LOG(VXR_DEBUG_LEVEL_ERROR, "[ERROR]: [HEIGHTMAP] Load failed. Unknown texture format.\n"); + return; + } + + if (w < 1 || h < 1) + { + free(data); + VXR_LOG(VXR_DEBUG_LEVEL_ERROR, "[ERROR]: [HEIGHTMAP] Load failed. Invalid texture data.\n"); + return; + } + + height_map_.resize(w * h); + + uint32 k = 0; + for (int j = 0; j < h; j++) + { + for (int i = 0; i < w; i++) + { + unsigned char height = data[k]; + + uint32 index = w * j + i; + + vec4 pixel; + pixel.x = (i - (((float)w - 1) / 2)) * grid_size; + pixel.y = (float)height / 6 * height_range; + pixel.z = (j - (((float)h - 1) / 2)) * grid_size; + pixel.w = 0; + + height_map_[index] = pixel; + + k += 3; + } + } + + free(data); + data = nullptr; + + // Rebuild vertex data. + + face_count_ = (h - 1)*(w - 1) * 2; + + vec3 v0, v1, v2, v3; + int i0, i1, i2, i3; + + std::vector v; + std::vector n; + std::vector t; + std::vector indices; + + uint32 map_index = 0; + k = 0; + + for (int j = 0; j < h; ++j) + { + for (int i = 0; i < w; ++i) + { + if (j < w - 1 && i < h - 1) + { + i0 = map_index; + i1 = map_index + w; + i2 = map_index + 1; + i3 = map_index + w + 1; + + v0 = height_map_[i0]; + v1 = height_map_[i1]; + v2 = height_map_[i2]; + v3 = height_map_[i3]; + + vec3 vA = v0 - v1; + vec3 vB = v1 - v2; + vec3 vC = v3 - v1; + + if (v0.y >= height_clamp && v1.y >= height_clamp && v2.y >= height_clamp && v3.y >= height_clamp || height_clamp == 0.0f) + { + vec3 vN1; + vN1 = glm::cross(vA, vB); + vN1 = glm::normalize(vN1); + v.push_back(v0); + v.push_back(v1); + v.push_back(v2); + n.push_back(vN1); + n.push_back(vN1); + n.push_back(vN1); + t.push_back(vec2(0.0f, 0.0f)); + t.push_back(vec2(0.0f, 1.0f)); + t.push_back(vec2(1.0f, 0.0f)); + indices.push_back(k + 0); + indices.push_back(k + 1); + indices.push_back(k + 2); + k += 3; + + vec3 vN2; + vN2 = glm::cross(vB, vC); + vN2 = glm::normalize(vN2); + v.push_back(v2); + v.push_back(v1); + v.push_back(v3); + n.push_back(vN2); + n.push_back(vN2); + n.push_back(vN2); + t.push_back(vec2(1.0f, 0.0f)); + t.push_back(vec2(0.0f, 1.0f)); + t.push_back(vec2(1.0f, 1.0f)); + indices.push_back(k + 0); + indices.push_back(k + 1); + indices.push_back(k + 2); + k += 3; + } + else + { + face_count_ -= 6; + } + } + map_index++; + + } + } + + set_indices(indices); + set_vertices(v); + set_normals(n); + set_uv(t); + } + + uint32 mesh::HeightMap::face_count() const + { + return face_count_; + } +} \ No newline at end of file diff --git a/src/graphics/mesh.cpp b/src/graphics/mesh.cpp index 9df0daa..dc4386c 100644 --- a/src/graphics/mesh.cpp +++ b/src/graphics/mesh.cpp @@ -27,9 +27,13 @@ #include "../../include/engine/engine.h" #include "../../include/engine/gpu.h" +#ifndef VOXELIZER_IMPLEMENTATION #define VOXELIZER_IMPLEMENTATION +#endif #include "../../deps/mesh/voxelizer/voxelizer.h" +#include "../../deps/stb/stb_image.h" + namespace vxr { diff --git a/src/graphics/texture.cpp b/src/graphics/texture.cpp index bafabae..aa0d1d7 100644 --- a/src/graphics/texture.cpp +++ b/src/graphics/texture.cpp @@ -164,6 +164,27 @@ namespace vxr data_[index] = data; } + void Texture::set_data(Color color, uint32 index) + { + if (data_[index] != nullptr) + { + free(data_[index]); + data_[index] = nullptr; + } + + /// TODO: Assumes uchar type. + data_[index] = (void*)malloc(3 * sizeof(unsigned char)); + + static const unsigned char background_color[] = + { + (unsigned char)(color.r * 255.0f), + (unsigned char)(color.g * 255.0f), + (unsigned char)(color.b * 255.0f), + }; + + data_[index] = (void*)background_color; + } + void Texture::set_hdr(bool hdr) { hdr_ = hdr; diff --git a/src/graphics/ui/editor.cpp b/src/graphics/ui/editor.cpp index a78a061..8d864d1 100644 --- a/src/graphics/ui/editor.cpp +++ b/src/graphics/ui/editor.cpp @@ -84,6 +84,7 @@ namespace vxr static bool show_statistics = false; static bool show_texture_viewer = false; + ref_ptr cam = Engine::ref().camera()->main(); ImGuiIO& io = ImGui::GetIO(); ImGui::SetNextWindowPos(ImVec2(0, 0)); @@ -131,9 +132,9 @@ namespace vxr if (!show_editor) { ImGui::Image((void*)(intptr_t)Engine::ref().camera()->screen_texture_id(), { io.DisplaySize.x, io.DisplaySize.y }, ImVec2(0, 1), ImVec2(1, 0)); - Engine::ref().camera()->main()->composer()->set_render_size({ io.DisplaySize.x, io.DisplaySize.y }); - Engine::ref().camera()->main()->set_aspect(io.DisplaySize.x / io.DisplaySize.y); - Engine::ref().camera()->set_render_to_screen(true); + cam->composer()->set_render_size({ io.DisplaySize.x, io.DisplaySize.y }); + cam->set_aspect(io.DisplaySize.x / io.DisplaySize.y); + Engine::ref().camera()->set_render_to_screen(false); ImGui::End(); ImGui::PopStyleVar(); @@ -161,12 +162,12 @@ namespace vxr ImGui::Text("Scene"); ImGui::Separator(); ImGui::Spacing(); - if (Engine::ref().camera()->main() != nullptr) + if (cam != nullptr) { ImVec2 scene_size = ImVec2(io.DisplaySize.x * 0.6f - 16.0f, io.DisplaySize.y * 0.7f - 41.0f); ImGui::Image((void*)(intptr_t)Engine::ref().camera()->screen_texture_id(), scene_size, ImVec2(0,1), ImVec2(1,0)); - Engine::ref().camera()->main()->composer()->set_render_size({ scene_size.x, scene_size.y }); - Engine::ref().camera()->main()->set_aspect(scene_size.x / (scene_size.y)); + cam->composer()->set_render_size({ scene_size.x, scene_size.y }); + cam->set_aspect(scene_size.x / (scene_size.y)); Engine::ref().camera()->set_render_to_screen(false); } ImGui::EndChild(); diff --git a/src/physics/collider_height_map.cpp b/src/physics/collider_height_map.cpp new file mode 100644 index 0000000..e3d78f5 --- /dev/null +++ b/src/physics/collider_height_map.cpp @@ -0,0 +1,104 @@ +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "../../include/physics/collider_height_map.h" +#include "../../include/physics/collider_sphere.h" +#include "../../include/graphics/height_map.h" +#include "../../include/components/collider.h" +#include "../../include/components/rigidbody.h" +#include "../../include/components/transform.h" + +namespace vxr +{ + + ColliderHeightMap::ColliderHeightMap() + { + set_name("Collider HeightMap"); + type_ = Type::HeightMap; + } + + ColliderHeightMap::~ColliderHeightMap() + { + } + + void ColliderHeightMap::checkCollision(Hit& hit) const + { + switch (hit.col2->shape()->colType()) + { + case ColliderShape::Type::Sphere: + { + VXR_TRACE_SCOPE("VXR", "HeightMap VS Sphere"); + ref_ptr c = (ColliderSphere*)hit.col2->shape().get(); + vec3 sphere_pos = hit.rg2->transform()->local_position(); + for (uint32 i = 0; i < height_map_->face_count(); ++i) + { + vec3 v0 = height_map_->vertices()[i * 3 + 0]; + vec3 v1 = height_map_->vertices()[i * 3 + 1]; + vec3 v2 = height_map_->vertices()[i * 3 + 2]; + vec3 n = height_map_->normals()[i * 3]; + + // Find point P on triangle ABC closest to sphere center + vec3 p = closestPtPointTriangle(sphere_pos, v0, v1, v2); + + // Sphere and triangle intersect if the (squared) distance from sphere + // center to point p is less than the (squared) sphere radius + vec3 v = p - sphere_pos; + float vDot = glm::dot(v, v); + if (vDot <= c->radius() * c->radius()) + { + hit.normal = n; + hit.penetration_depth = c->radius() - sqrtf(vDot); + hit.hit = true; + break; + } + } + break; + } + default: + break; + } + } + + void ColliderHeightMap::getAabb(ref_ptr transform, vec3& aabb_min, vec3& aabb_max) const + { + aabb_min = transform->local_position() - vec3(local_aabb_min_); + aabb_max = transform->local_position() + vec3(local_aabb_max_); + } + + void ColliderHeightMap::setAabbExtents(vec3 min, vec3 max) + { + local_aabb_min_ = min; + local_aabb_max_ = max; + } + + void ColliderHeightMap::set_height_map(ref_ptr mesh) + { + height_map_ = mesh; + } + + ref_ptr ColliderHeightMap::height_map() const + { + return height_map_; + } +} \ No newline at end of file diff --git a/src/physics/collider_shape.cpp b/src/physics/collider_shape.cpp new file mode 100644 index 0000000..04bfe3b --- /dev/null +++ b/src/physics/collider_shape.cpp @@ -0,0 +1,49 @@ +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "../../include/physics/collider_shape.h" + +namespace vxr +{ + + ColliderShape::ColliderShape() + { + set_name("Collider Shape"); + type_ = Type::Undefined; + } + + ColliderShape::~ColliderShape() + { + } + + const ColliderShape::Type::Enum& ColliderShape::colType() const + { + return type_; + } + + void ColliderShape::checkCollision(Hit& hit) const + { + } + +} \ No newline at end of file diff --git a/src/physics/collider_sphere.cpp b/src/physics/collider_sphere.cpp new file mode 100644 index 0000000..2d95d58 --- /dev/null +++ b/src/physics/collider_sphere.cpp @@ -0,0 +1,130 @@ +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "../../include/physics/collider_sphere.h" +#include "../../include/physics/collider_height_map.h" +#include "../../include/graphics/height_map.h" +#include "../../include/components/collider.h" +#include "../../include/components/rigidbody.h" +#include "../../include/components/transform.h" + +namespace vxr +{ + + ColliderSphere::ColliderSphere() + { + set_name("Collider Sphere"); + type_ = Type::Sphere; + } + + ColliderSphere::~ColliderSphere() + { + } + + void ColliderSphere::getAabb(ref_ptr transform, vec3& aabb_min, vec3& aabb_max) const + { + aabb_min = transform->local_position() - vec3(radius_) - 0.5f; + aabb_max = transform->local_position() + vec3(radius_) + 0.5f; + } + + void ColliderSphere::checkCollision(Hit& hit) const + { + switch (hit.col2->shape()->colType()) + { + case ColliderShape::Type::Sphere: + { + //VXR_TRACE_SCOPE("VXR", "Sphere VS Sphere"); + const vec3 posA = hit.col1->transform()->local_position(); + const vec3 posB = hit.col2->transform()->local_position(); + const float radiusA = ((ColliderSphere*)hit.col1->shape().get())->radius(); + const float radiusB = ((ColliderSphere*)hit.col2->shape().get())->radius(); + + const float distSquared = glm::length2(posA - posB); + const float radiusSumSquared = (radiusA + radiusB) * (radiusA + radiusB); + if (distSquared > radiusSumSquared) + { + hit.hit = false; + break; + } + + const float distance = sqrtf(distSquared); + + if (distance == 0.0f) + { + hit.normal = vec3(0.0f, 1.0f, 0.0f); + hit.penetration_depth = radiusA; + } + else + { + hit.normal = (posB - posA) / distance; + hit.penetration_depth = (radiusA + radiusB) - distance; + } + + hit.hit = true; + break; + } + case ColliderShape::Type::HeightMap: + { + VXR_TRACE_SCOPE("VXR", "Sphere VS HeightMap"); + ref_ptr c = ((ColliderHeightMap*)hit.col2->shape().get())->height_map(); + vec3 sphere_pos = hit.rg1->transform()->local_position(); + for (uint32 i = 0; i < c->face_count(); ++i) + { + vec3 v0 = c->vertices()[i * 3 + 0]; + vec3 v1 = c->vertices()[i * 3 + 1]; + vec3 v2 = c->vertices()[i * 3 + 2]; + vec3 n = c->normals()[i * 3]; + + // Find point P on triangle ABC closest to sphere center + vec3 p = closestPtPointTriangle(sphere_pos, v0, v1, v2); + + // Sphere and triangle intersect if the (squared) distance from sphere + // center to point p is less than the (squared) sphere radius + vec3 v = p - sphere_pos; + float vDot = glm::dot(v, v); + if (vDot <= radius_ * radius_) + { + hit.normal = n; + hit.penetration_depth = radius_ - sqrtf(vDot); + hit.hit = true; + break; + } + } + break; + } + default: + break; + } + } + + void ColliderSphere::set_radius(const float radius) + { + radius_ = radius; + } + + float ColliderSphere::radius() const + { + return radius_; + } +} \ No newline at end of file diff --git a/src/physics/hit.cpp b/src/physics/hit.cpp new file mode 100644 index 0000000..39d4f3c --- /dev/null +++ b/src/physics/hit.cpp @@ -0,0 +1,103 @@ +// ---------------------------------------------------------------------------------------- +// MIT License +// +// Copyright(c) 2018 Víctor Ávila +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// ---------------------------------------------------------------------------------------- + +#include "../../include/physics/hit.h" + +#include "../../include/components/rigidbody.h" +#include "../../include/components/collider.h" + +namespace vxr +{ + + Hit::Hit(ref_ptr collider1, ref_ptr collider2, ref_ptr rigidbody1, ref_ptr rigidbody2) + { + col1 = collider1; + col2 = collider2; + rg1 = rigidbody1; + rg2 = rigidbody2; + } + + vec3 closestPtPointTriangle(const vec3& p, const vec3& a, const vec3& b, const vec3& c) + { + // Ericson, C. (2004). Real-time collision detection. CRC Press. + // Check if P in vertex region outside A + vec3 ab = b - a; + vec3 ac = c - a; + vec3 ap = p - a; + float d1 = glm::dot(ab, ap); + float d2 = glm::dot(ac, ap); + if (d1 <= 0.0f && d2 <= 0.0f) + { + return a; // barycentric coordinates (1,0,0) + } + + // Check if P in vertex region outside B + vec3 bp = p - b; + float d3 = glm::dot(ab, bp); + float d4 = glm::dot(ac, bp); + if (d3 >= 0.0f && d4 <= d3) + { + return b; // barycentric coordinates (0,1,0) + } + + // Check if P in edge region of AB, if so return projection of P onto AB + float vc = d1 * d4 - d3 * d2; + if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) + { + float v = d1 / (d1 - d3); + return a + v * ab; // barycentric coordinates (1-v,v,0) + } + + // Check if P in vertex region outside C + vec3 cp = p - c; + float d5 = glm::dot(ab, cp); + float d6 = glm::dot(ac, cp); + if (d6 >= 0.0f && d5 <= d6) + { + return c; // barycentric coordinates (0,0,1) + } + + // Check if P in edge region of AC, if so return projection of P onto AC + float vb = d5 * d2 - d1 * d6; + if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) + { + float w = d2 / (d2 - d6); + return a + w * ac; // barycentric coordinates (1-w,0,w) + } + + // Check if P in edge region of BC, if so return projection of P onto BC + float va = d3 * d6 - d5 * d4; + if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) + { + float w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); + return b + w * (c - b); // barycentric coordinates (0,1-w,w) + } + + // P inside face region. Compute Q through its barycentric coordinates (u,v,w) + float denom = 1.0f / (va + vb + vc); + float v = vb * denom; + float w = vc * denom; + return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = 1.0f-v-w + } +} \ No newline at end of file