diff --git a/config/rel.mk b/config/rel.mk index c76ca99..83fb1a9 100644 --- a/config/rel.mk +++ b/config/rel.mk @@ -2,7 +2,7 @@ include $(config_dir)base/base.mk this_cxxflags += -O3 -#this_lint_cmd = $(prorab_lint_cmd_clang_tidy) +this_lint_cmd = $(prorab_lint_cmd_clang_tidy) # WORKAROUND: on ubuntu jammy dpkg-buildpackage passes -ffat-lto-objects compilation flag # which is not supported by clang and clang-tidy complains about it: diff --git a/res/main.res b/res/main.res index 9f3dde4..ecc472e 100644 --- a/res/main.res +++ b/res/main.res @@ -89,11 +89,24 @@ texture_default_normal{ tex_cube_env_hata{ file_px{envs/hata/px.png} file_nx{envs/hata/nx.png} - file_py{envs/hata/py.png} - file_ny{envs/hata/ny.png} + file_py{envs/hata/ny.png} + file_ny{envs/hata/py.png} file_pz{envs/hata/pz.png} file_nz{envs/hata/nz.png} + min_filter{linear} + mag_filter{linear} + mipmap{nearest} +} + +tex_cube_env_castle{ + file_px{envs/castle/px.jpg} + file_nx{envs/castle/nx.jpg} + file_py{envs/castle/ny.jpg} + file_ny{envs/castle/py.jpg} + file_pz{envs/castle/pz.jpg} + file_nz{envs/castle/nz.jpg} + min_filter{linear} mag_filter{linear} mipmap{nearest} diff --git a/res/samples_gltf/ball.glb b/res/samples_gltf/ball.glb new file mode 100644 index 0000000..62a9113 Binary files /dev/null and b/res/samples_gltf/ball.glb differ diff --git a/res/samples_gltf/ball_bb.glb b/res/samples_gltf/ball_bb.glb new file mode 100644 index 0000000..9aa2cf7 Binary files /dev/null and b/res/samples_gltf/ball_bb.glb differ diff --git a/res/test/bake.jpg b/res/test/bake.jpg deleted file mode 100644 index b5d01e3..0000000 Binary files a/res/test/bake.jpg and /dev/null differ diff --git a/res/test/bake.obj b/res/test/bake.obj deleted file mode 100644 index 7d1bcca..0000000 --- a/res/test/bake.obj +++ /dev/null @@ -1,143 +0,0 @@ -# Blender 4.2.0 Alpha -# www.blender.org -mtllib bake.mtl -o Cube.001 -v 3.000000 -0.993709 -3.000000 -v 3.000000 -1.193709 -3.000000 -v 3.000000 -0.993709 3.000000 -v 3.000000 -1.193709 3.000000 -v -3.000000 -0.993709 -3.000000 -v -3.000000 -1.193709 -3.000000 -v -3.000000 -0.993709 3.000000 -v -3.000000 -1.193709 3.000000 -vn -0.0000 1.0000 -0.0000 -vn -0.0000 -0.0000 1.0000 -vn -1.0000 -0.0000 -0.0000 -vn 1.0000 -0.0000 -0.0000 -vn -0.0000 -0.0000 -1.0000 -vt 0.566429 0.005000 -vt 0.005000 0.005000 -vt 0.005000 0.566429 -vt 0.566429 0.566429 -vt 0.709286 0.005000 -vt 0.576429 0.005000 -vt 0.576429 0.566429 -vt 0.709286 0.566429 -vt 0.566429 0.709286 -vt 0.566429 0.576429 -vt 0.005000 0.576429 -vt 0.005000 0.709286 -vt 0.852143 0.005000 -vt 0.719286 0.005000 -vt 0.719286 0.566429 -vt 0.852143 0.566429 -vt 0.566429 0.852143 -vt 0.566429 0.719286 -vt 0.005000 0.719286 -vt 0.005000 0.852143 -s 0 -usemtl Material -f 1/1/1 5/2/1 7/3/1 3/4/1 -f 4/5/2 3/6/2 7/7/2 8/8/2 -f 8/9/3 7/10/3 5/11/3 6/12/3 -f 2/13/4 1/14/4 3/15/4 4/16/4 -f 6/17/5 5/18/5 1/19/5 2/20/5 -o Cube.002 -v 0.706686 1.660500 -0.840424 -v 0.956800 -0.265104 -1.319479 -v 1.004954 1.219624 1.087441 -v -1.255068 1.347964 -0.608386 -v 0.947885 1.058549 -0.473931 -v 1.067454 0.137991 -0.702949 -v 1.090475 0.847783 0.447707 -v -0.472155 0.832316 -0.305968 -v -0.352585 -0.088242 -0.534986 -v -0.329565 0.621550 0.615671 -v -0.209995 -0.299008 0.386653 -v 1.210045 -0.072775 0.218689 -v 1.255068 -0.705980 0.608386 -v -0.706686 -1.018516 0.840424 -v -1.004954 -0.577640 -1.087441 -v -0.956800 0.907087 1.319479 -vn 0.9353 0.1950 -0.2953 -vn -0.1491 0.2204 -0.9639 -vn 0.9398 0.3346 -0.0689 -vn -0.1251 0.9628 0.2395 -vn 0.1491 -0.2204 0.9639 -vn 0.1251 -0.9628 -0.2395 -vn 0.9809 0.1563 -0.1160 -vn 0.9914 0.1120 0.0674 -vn 0.9869 -0.0277 -0.1590 -vn -0.9809 -0.1563 0.1160 -vt 0.995000 0.576429 -vt 0.862143 0.576429 -vt 0.862143 0.709286 -vt 0.995000 0.709286 -vt 0.566429 0.862143 -vt 0.433571 0.862143 -vt 0.433571 0.995000 -vt 0.566429 0.995000 -vt 0.995000 0.433571 -vt 0.862143 0.433571 -vt 0.862143 0.566429 -vt 0.995000 0.566429 -vt 0.995000 0.290714 -vt 0.862143 0.290714 -vt 0.862143 0.423571 -vt 0.995000 0.423571 -vt 0.137857 0.862143 -vt 0.005000 0.862143 -vt 0.005000 0.995000 -vt 0.137857 0.995000 -vt 0.709286 0.576429 -vt 0.576429 0.576429 -vt 0.576429 0.709286 -vt 0.709286 0.709286 -vt 0.852143 0.576429 -vt 0.719286 0.576429 -vt 0.719286 0.709286 -vt 0.852143 0.709286 -vt 0.709286 0.719286 -vt 0.576429 0.719286 -vt 0.576429 0.852143 -vt 0.709286 0.852143 -vt 0.852143 0.719286 -vt 0.719286 0.719286 -vt 0.719286 0.852143 -vt 0.852143 0.852143 -vt 0.709286 0.862143 -vt 0.576429 0.862143 -vt 0.576429 0.995000 -vt 0.709286 0.995000 -vt 0.995000 0.005000 -vt 0.862143 0.005000 -vt 0.862143 0.137857 -vt 0.995000 0.137857 -vt 0.995000 0.147857 -vt 0.862143 0.147857 -vt 0.862143 0.280714 -vt 0.995000 0.280714 -vt 0.280714 0.862143 -vt 0.147857 0.862143 -vt 0.147857 0.995000 -vt 0.280714 0.995000 -vt 0.423571 0.862143 -vt 0.290714 0.862143 -vt 0.290714 0.995000 -vt 0.423571 0.995000 -s 0 -usemtl Material.001 -f 10/21/6 9/22/6 13/23/6 14/24/6 -f 23/25/7 12/26/7 9/27/7 10/28/7 -f 9/29/8 11/30/8 15/31/8 13/32/8 -f 9/33/9 12/34/9 24/35/9 11/36/9 -f 14/37/10 13/38/10 16/39/10 17/40/10 -f 13/41/11 15/42/11 18/43/11 16/44/11 -f 17/45/12 16/46/12 18/47/12 19/48/12 -f 15/49/7 20/50/7 19/51/7 18/52/7 -f 20/53/9 14/54/9 17/55/9 19/56/9 -f 11/57/13 21/58/13 20/59/13 15/60/13 -f 21/61/14 10/62/14 14/63/14 20/64/14 -f 21/65/10 11/66/10 24/67/10 22/68/10 -f 23/69/11 10/70/11 21/71/11 22/72/11 -f 22/73/15 24/74/15 12/75/15 23/76/15 diff --git a/src/carcockpit/application.cpp b/src/carcockpit/application.cpp index e3b091a..e36da71 100644 --- a/src/carcockpit/application.cpp +++ b/src/carcockpit/application.cpp @@ -51,9 +51,9 @@ application::application(bool window, std::string_view res_path) : if (e.combo.key == ruis::key::escape) { this->quit(); } else if (e.combo.key == ruis::key::space) { - this->toggleCamera(); + this->toggle_camera(); } else if (e.combo.key == ruis::key::n) { - this->toggleNormalMapping(); + this->toggle_normal_mapping(); } } return false; @@ -62,16 +62,16 @@ application::application(bool window, std::string_view res_path) : this->gui.set_root(std::move(kp)); } -void application::toggleCamera() +void application::toggle_camera() { cam_toggle = !cam_toggle; auto car_w = this->gui.get_root().try_get_widget_as("gltf_viewer_widget"); if (car_w) { - car_w->toggleCamera(cam_toggle); + car_w->toggle_camera(cam_toggle); } } -void application::toggleNormalMapping() +void application::toggle_normal_mapping() { nm_toggle = !nm_toggle; auto car_w = this->gui.get_root().try_get_widget_as("gltf_viewer_widget"); diff --git a/src/carcockpit/application.hpp b/src/carcockpit/application.hpp index cbde242..1b21fe4 100644 --- a/src/carcockpit/application.hpp +++ b/src/carcockpit/application.hpp @@ -36,14 +36,14 @@ class application : public ruisapp::application public: application(bool window, std::string_view res_path); - void toggleCamera(); - void toggleNormalMapping(); + void toggle_camera(); + void toggle_normal_mapping(); static constexpr std::string_view app_name = "carcockpit"sv; static application& inst() { - return static_cast(ruisapp::application::inst()); + return dynamic_cast(ruisapp::application::inst()); } ruis::render::shader_skybox shader_skybox_v; diff --git a/src/carcockpit/gltf_viewer_widget.cpp b/src/carcockpit/gltf_viewer_widget.cpp index f7ba376..30d9809 100644 --- a/src/carcockpit/gltf_viewer_widget.cpp +++ b/src/carcockpit/gltf_viewer_widget.cpp @@ -30,7 +30,7 @@ along with this program. If not, see . #include #include -#include "../ruis/render/scene/gltf_loader.hpp" +#include "../ruis/render/scene/gltf_loader.hxx" #include "application.hpp" @@ -39,30 +39,24 @@ using namespace ruis::render; gltf_viewer_widget::gltf_viewer_widget(utki::shared_ref context, all_parameters params) : ruis::widget(std::move(context), {.widget_params = std::move(params.widget_params)}), - ruis::fraction_widget(this->context, {}) + ruis::fraction_widget(this->context, {}), + params(std::move(params.gltf_params)) { - // this->tex = this->context.get().loader.load("tex_sample").to_shared_ptr(); - // this->rot.set_identity(); - - int maxTextureSize; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); - LOG([&](auto& o) { - o << "Max texture size: " << maxTextureSize << std::endl; - }) LOG([&](auto& o) { - o << "<< LOAD GLTF >>" << std::endl; + o << "[LOAD GLTF] " << this->params.path_to_gltf << std::endl; }) ruis::render::gltf_loader l(*this->context.get().renderer.get().factory); - // demoscene = l.load(papki::fs_file("../res/samples_gltf/parent_and_children.glb")).to_shared_ptr(); - // demoscene = l.load(papki::fs_file("../res/samples_gltf/camera.glb")).to_shared_ptr(); - demoscene = l.load(papki::fs_file("../res/samples_gltf/spray.glb")).to_shared_ptr(); + + demoscene = l.load(papki::fs_file(this->params.path_to_gltf)).to_shared_ptr(); sc_renderer = std::make_shared(this->context); sc_renderer->set_scene(demoscene); camrip = std::make_shared(); sc_renderer->set_external_camera(camrip); + sc_renderer->set_scene_scaling_factor(this->params.scaling_factor); + sc_renderer->set_environment_cube(this->params.environment_cube); } void gltf_viewer_widget::update(uint32_t dt) @@ -88,7 +82,6 @@ void gltf_viewer_widget::update(uint32_t dt) ruis::real l2 = remains.x() * remains.x() + remains.y() * remains.y() + remains.z() * remains.z(); const ruis::real threshold = 0.00001; if (l2 < threshold) { - // camera_transition_ongoing = false; camera_position = camera_attractor; } } @@ -102,7 +95,7 @@ void gltf_viewer_widget::update(uint32_t dt) this->clear_cache(); } -void gltf_viewer_widget::toggleCamera(bool toggle) +void gltf_viewer_widget::toggle_camera(bool toggle) { // camera_transition_ongoing = true; if (toggle) @@ -116,14 +109,32 @@ void gltf_viewer_widget::set_normal_mapping(bool toggle) application::inst().shader_adv_v.set_normal_mapping(toggle); } +constexpr float snap_speed = 1.07; // 1 is zero speed + bool gltf_viewer_widget::on_mouse_button(const ruis::mouse_button_event& e) { - std::cout << "Is Down = " << e.is_down << std::endl; - if (e.button == ruis::mouse_button::wheel_up) { - camera_attractor /= 1.07; + camera_attractor -= this->params.camera_target; + camera_attractor /= snap_speed; + camera_attractor += this->params.camera_target; + + if (!this->params.smooth_navigation_zoom) { + camera_attractor -= this->params.camera_target; + camera_position /= snap_speed; + camera_attractor += this->params.camera_target; + } + } else if (e.button == ruis::mouse_button::wheel_down) { - camera_attractor *= 1.07; + camera_attractor -= this->params.camera_target; + camera_attractor *= snap_speed; + camera_attractor += this->params.camera_target; + + if (!this->params.smooth_navigation_zoom) { + camera_attractor -= this->params.camera_target; + camera_position *= snap_speed; + camera_attractor += this->params.camera_target; + } + } else if (e.button == ruis::mouse_button::left) { mouse_rotate = e.is_down; if (e.is_down) { @@ -138,22 +149,26 @@ bool gltf_viewer_widget::on_mouse_move(const ruis::mouse_move_event& e) { if (mouse_rotate) { ruis::vec2 diff = e.pos - mouse_changeview_start; - ruis::vec4 diff4 = diff; - // ruis::mat4 inv_view = get_view_matrix().inv(); - // diff4 = inv_view * diff4; + ruis::vec3 axis = -camera_changeview_start.cross(ruis::vec3(0, 1, 0)); + axis.normalize(); ruis::quat q1, q2; - q1.set_rotation(0, 1, 0, -diff4.x() / 200.0f); - // camera_attractor.rotate(q); - q2.set_rotation(1, 0, 0, -diff4.y() / 200.0f); - // camera_attractor.rotate(q); + q1.set_rotation(axis.x(), axis.y(), axis.z(), -diff.y() * 2 / rect().d.y()); + q2.set_rotation(0, 1, 0, -diff.x() * 2 / rect().d.x()); + + this->params.orbit_angle_lower_limit += this->params.orbit_angle_upper_limit; // TODO: restrict camera orbit ruis::vec3 cam2go = camera_changeview_start; + cam2go -= this->params.camera_target; cam2go.rotate(q1); cam2go.rotate(q2); + cam2go += this->params.camera_target; - camera_attractor = cam2go; + if (this->params.smooth_navigation_orbit) + camera_attractor = cam2go; + else + camera_position = camera_attractor = cam2go; } return false; @@ -168,7 +183,7 @@ ruis::mat4 gltf_viewer_widget::get_view_matrix() const { ruis::mat4 view; view.set_identity(); - view.set_look_at(camera_position, camera_target, ruis::vec3(0, 2, 0)); + view.set_look_at(camera_position, this->params.camera_target, ruis::vec3(0, 1, 0)); return view; } @@ -181,44 +196,14 @@ void gltf_viewer_widget::render(const ruis::matrix4& matrix) const viewport_matrix.translate(1, 1); viewport_matrix.scale(1, -1, -1); - ruis::mat4 viewport; - viewport.set_identity(); - - // viewport = matrix; - // viewport.scale(1.0f / this->rect().d[0], 1.0f / this->rect().d[1], 1.0f); - // float fms = static_cast(this->time) / std::milli::den; // float xx = 3 * cosf(fms / 2); // float zz = 3 * sinf(fms / 2); - // glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glClear(GL_DEPTH_BUFFER_BIT); // TODO: probably this should be done externally, - // because it clears all the framebuffer, not just area of this widget - camrip->pos = camera_position; - camrip->target = camera_target; - camrip->up = ruis::vec3(0, 2, 0); - camrip->fovy = 3.1415926535f / 4.f; - camrip->near = .1f; - camrip->far = 20.f; + camrip->target = this->params.camera_target; + camrip->up = ruis::vec3(0, 1, 0); + camrip->fovy = M_PI_4; this->sc_renderer->render(rect(), viewport_matrix); - - // advanced_s->render( - // *this->car_vao, - // mvp, - // modelview, - // projection, - // this->tex_rust_diffuse->tex(), - // this->tex_rust_normal->tex(), - // this->tex_rust_roughness->tex(), - // this->tex_cube_env_hata->tex(), - // light_pos_view, - // light_int - // ); - - glDisable(GL_DEPTH_TEST); } - -/// How to register mouse events outside app window ? \ No newline at end of file diff --git a/src/carcockpit/gltf_viewer_widget.hpp b/src/carcockpit/gltf_viewer_widget.hpp index f34f0d8..4b636a1 100644 --- a/src/carcockpit/gltf_viewer_widget.hpp +++ b/src/carcockpit/gltf_viewer_widget.hpp @@ -31,7 +31,7 @@ along with this program. If not, see . // #include "../ruis/render/scene/shaders/shader_phong.hpp" // #include "../ruis/render/scene/shaders/shader_skybox.hpp" #include "../ruis/render/scene/scene.hpp" -#include "../ruis/render/scene/scene_renderer.hpp" +#include "../ruis/render/scene/scene_renderer.hxx" #include "shaders/shader_adv.hpp" #include "shaders/shader_phong.hpp" @@ -39,49 +39,58 @@ along with this program. If not, see . namespace carcockpit { +constexpr ruis::vec3 default_camera_position_front{0, 1.5, 7}; +constexpr ruis::vec3 default_camera_position_top{0, 9, 0}; +constexpr float default_camera_transition_duration{0.1}; + class gltf_viewer_widget : public ruis::fraction_widget, public ruis::updateable, virtual public ruis::widget { std::shared_ptr demoscene; std::shared_ptr sc_renderer; std::shared_ptr camrip; + // std::shared_ptr texture_environment_cube; - ruis::vec3 camera_position_front{0, 1.5, 7}; - ruis::vec3 camera_position_top{0, 9, 0}; + ruis::vec3 camera_position_front{default_camera_position_front}; + ruis::vec3 camera_position_top{default_camera_position_top}; ruis::vec3 camera_position{camera_position_top}; ruis::vec3 camera_attractor{camera_position_front}; - ruis::vec3 camera_target{0, 0, 0}; - ruis::real camera_transition_duration = 0.2; // not seconds ;) - // bool camera_transition_ongoing = true; + ruis::real camera_transition_duration{default_camera_transition_duration}; // not seconds bool mouse_rotate = false; - bool mouse_pan = false; + // bool mouse_pan = false; ruis::vec2 mouse_changeview_start; ruis::vec3 camera_changeview_start; - unsigned fps = 0; - + uint32_t fps = 0; uint32_t fps_sec_counter = 0; uint32_t time = 0; public: - struct parameters {}; + struct parameters { + std::string path_to_gltf; + float scaling_factor{1.0f}; + ruis::vec3 camera_target{0, 0, 0}; + bool smooth_navigation_orbit = true; + bool smooth_navigation_zoom = true; + ruis::real orbit_angle_upper_limit = M_PI_2; + ruis::real orbit_angle_lower_limit = -M_PI_2; + std::shared_ptr environment_cube; + }; private: - // TODO: remove lint suppression - // NOLINTNEXTLINE(clang-diagnostic-unused-private-field) parameters params; public: struct all_parameters { ruis::widget::parameters widget_params; - parameters car_params; + parameters gltf_params; }; gltf_viewer_widget(utki::shared_ref context, all_parameters params); void render(const ruis::matrix4& matrix) const override; void update(uint32_t dt) override; - void toggleCamera(bool toggle); + void toggle_camera(bool toggle); void set_normal_mapping(bool toggle); bool on_mouse_button(const ruis::mouse_button_event& e) override; diff --git a/src/carcockpit/gui.cpp b/src/carcockpit/gui.cpp index ca1c5ac..ab5a927 100644 --- a/src/carcockpit/gui.cpp +++ b/src/carcockpit/gui.cpp @@ -128,20 +128,50 @@ utki::shared_ref carcockpit::make_root_widgets(utki::shared_ref m::gltf_viewer_widget(c, { .widget_params = { - .id = "gltf_viewer_widget"s, + .id = "gltf_viewer_widget_1"s, .lp = { .dims = {lp::fill, lp::fill}, .weight = 5 // NOLINT(cppcoreguidelines-avoid-magic-numbers) }, - .clip=true + .clip = true, + .depth = true + } + , + .gltf_params = { + .path_to_gltf = "../res/samples_gltf/spray.glb"s, + // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) + .scaling_factor = 10.0f, + // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) + .camera_target = ruis::vec3(1, 1, 1), + .smooth_navigation_orbit = true, + .smooth_navigation_zoom = true, + .orbit_angle_upper_limit = M_PI_4, + .orbit_angle_lower_limit = -M_PI_4, + .environment_cube = c.get().loader.load("tex_cube_env_castle").to_shared_ptr() + } + } + ), + m::gltf_viewer_widget(c, + { + .widget_params = { + .id = "gltf_viewer_widget_2"s, + .lp = { + .dims = {lp::fill, lp::fill}, + .weight = 5 // NOLINT(cppcoreguidelines-avoid-magic-numbers) + }, + .clip = true, + .depth = true + } + , + .gltf_params = { + .path_to_gltf = "../res/samples_gltf/camera.glb"s, + // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) + .scaling_factor = 10.0f, + // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) + .camera_target = ruis::vec3(0, 0, 0), + .smooth_navigation_orbit = false, + .smooth_navigation_zoom = false } - // , - // .params = { - // .diffuse = c.get().loader.load("img_gauge_arrow"), - // .specular = c.get().loader.load("img_gauge_arrow"), - // .roughness = c.get().loader.load("img_gauge_arrow_shadow"), - // .normal = c.get().loader.load("img_gauge_arrow_shadow") - // } } ) } @@ -160,17 +190,18 @@ utki::shared_ref carcockpit::make_root_widgets(utki::shared_ref auto& gauge = kp.get().get_widget_as("gauge"); auto& slider = kp.get().get_widget_as("gauge_slider"); - auto& gltf_viewer_widget = kp.get().get_widget_as("gltf_viewer_widget"); + // auto& gltf_viewer_widget = kp.get().get_widget_as("gltf_viewer_widget"); - slider.fraction_change_handler = [&cw = gltf_viewer_widget, &g = gauge](ruis::fraction_widget& s) { + slider.fraction_change_handler = [&g = gauge](ruis::fraction_widget& s) { g.set_fraction(s.get_fraction()); - // cw.set_rotation(s.fraction()); - cw.set_fraction(s.get_fraction()); + // cw.set_fraction(s.get_fraction()); }; - auto car = kp.get().try_get_widget_as("gltf_viewer_widget"); + auto viewer1 = kp.get().try_get_widget_as("gltf_viewer_widget_1"); + auto viewer2 = kp.get().try_get_widget_as("gltf_viewer_widget_2"); - c.get().updater.get().start(car, 0); + c.get().updater.get().start(viewer1, 0); + c.get().updater.get().start(viewer2, 0); return kp; } diff --git a/src/carcockpit/shaders/shader_adv.cpp b/src/carcockpit/shaders/shader_adv.cpp index 6c3a995..10844aa 100644 --- a/src/carcockpit/shaders/shader_adv.cpp +++ b/src/carcockpit/shaders/shader_adv.cpp @@ -30,17 +30,8 @@ along with this program. If not, see . using namespace ruis::render; -static ruis::mat3 from_mat4(const ruis::mat4& mat) -{ - ruis::mat3 m; - for (int i = 0; i < 3; ++i) - for (int j = 0; j < 3; ++j) - m[i][j] = mat[i][j]; - return m; -} - -static const ruis::vec4 default_light_position{5.0f, 5.0f, 5.0f, 1.0f}; -static const ruis::vec3 default_light_intensity{2.0f, 2.0f, 2.0f}; +constexpr ruis::vec4 default_light_position{5.0f, 5.0f, 5.0f, 1.0f}; +constexpr ruis::vec3 default_light_intensity{2.0f, 2.0f, 2.0f}; shader_adv::shader_adv() : shader_base( @@ -205,7 +196,7 @@ void shader_adv::render( // NOLINTNEXTLINE(cppcoreguidelines-pro-type-static-cast-downcast) static_cast(tex_cube_env).bind(3); - ruis::mat3 normal = from_mat4(modelview); + ruis::mat3 normal = modelview.submatrix<0, 0, 3, 3>(); normal.invert(); normal.transpose(); diff --git a/src/carcockpit/shaders/shader_phong.cpp b/src/carcockpit/shaders/shader_phong.cpp index 833d66c..ef355b8 100644 --- a/src/carcockpit/shaders/shader_phong.cpp +++ b/src/carcockpit/shaders/shader_phong.cpp @@ -29,17 +29,8 @@ along with this program. If not, see . using namespace ruis::render; -static ruis::mat3 from_mat4(const ruis::mat4& mat) -{ - ruis::mat3 m; - for (int i = 0; i < 3; ++i) - for (int j = 0; j < 3; ++j) - m[i][j] = mat[i][j]; - return m; -} - -static const ruis::vec4 default_light_position{5.0f, 5.0f, 5.0f, 1.0f}; -static const ruis::vec3 default_light_intensity{2.0f, 2.0f, 2.0f}; +constexpr ruis::vec4 default_light_position{5.0f, 5.0f, 5.0f, 1.0f}; +constexpr ruis::vec3 default_light_intensity{2.0f, 2.0f, 2.0f}; shader_phong::shader_phong() : shader_base( @@ -126,7 +117,7 @@ void shader_phong::render( this->bind(); // bind the program - ruis::mat3 normal = from_mat4(modelview); + ruis::mat3 normal = modelview.submatrix<0, 0, 3, 3>(); normal.invert(); normal.transpose(); diff --git a/src/carcockpit/shaders/shader_skybox.cpp b/src/carcockpit/shaders/shader_skybox.cpp index 783121e..fd9ed6c 100644 --- a/src/carcockpit/shaders/shader_skybox.cpp +++ b/src/carcockpit/shaders/shader_skybox.cpp @@ -52,6 +52,7 @@ shader_skybox::shader_skybox() : { vec3 unprojected = (matrix * a0).xyz; eyeDirection = mat3_imv * unprojected; + eyeDirection.y = -eyeDirection.y; gl_Position = a0; } diff --git a/src/ruis/render/scene/gltf_loader.cpp b/src/ruis/render/scene/gltf_loader.cpp index 298abb7..2410f0e 100644 --- a/src/ruis/render/scene/gltf_loader.cpp +++ b/src/ruis/render/scene/gltf_loader.cpp @@ -19,7 +19,7 @@ along with this program. If not, see . /* ================ LICENSE END ================ */ -#include "gltf_loader.hpp" +#include "gltf_loader.hxx" #include #include @@ -36,22 +36,24 @@ accessor::accessor( uint32_t count, uint32_t byte_offset, // uint32_t byte_stride, - type type_, - component_type component_type_ + type type_v, + component_type component_type_v ) : - bv(bv), + bv(std::move(bv)), count(count), byte_offset(byte_offset), // byte_stride(byte_stride), - type_(type_), - component_type_(component_type_) + type_v(type_v), + component_type_v(component_type_v) {} -gltf_loader::gltf_loader(ruis::render::factory& factory_) : - factory_(factory_) +gltf_loader::gltf_loader(ruis::render::factory& factory_v) : + factory_v(factory_v) {} -inline int read_int(const jsondom::value& json, const std::string& name, const int default_value = -1) +namespace { + +int read_int(const jsondom::value& json, const std::string& name, const int default_value = -1) { auto it = json.object().find(name); if (it != json.object().end()) @@ -60,7 +62,7 @@ inline int read_int(const jsondom::value& json, const std::string& name, const i return default_value; } -inline uint32_t read_uint(const jsondom::value& json, const std::string& name, const uint32_t default_value = 0) +uint32_t read_uint(const jsondom::value& json, const std::string& name, const uint32_t default_value = 0) { auto it = json.object().find(name); if (it != json.object().end()) @@ -69,20 +71,16 @@ inline uint32_t read_uint(const jsondom::value& json, const std::string& name, c return default_value; } -inline float read_float(const jsondom::value& json, const std::string& name, const float default_value = 0.0f) -{ - auto it = json.object().find(name); - if (it != json.object().end()) - return it->second.number().to_float(); +// float read_float(const jsondom::value& json, const std::string& name, const float default_value = 0.0f) +// { +// auto it = json.object().find(name); +// if (it != json.object().end()) +// return it->second.number().to_float(); - return default_value; -} +// return default_value; +// } -inline std::string read_string( - const jsondom::value& json, - const std::string& name, - const std::string default_value = "" -) +std::string read_string(const jsondom::value& json, const std::string& name, const std::string default_value = "") { auto it = json.object().find(name); if (it != json.object().end()) @@ -104,11 +102,11 @@ std::vector read_uint_array(const jsondom::value& json, const std::str return arr; } -template -r4::vector read_vec( +template +r4::vector read_vec( const jsondom::value& json, const std::string& name, - const r4::vector default_value + const r4::vector default_value ) { auto it = json.object().find(name); @@ -116,7 +114,7 @@ r4::vector read_vec( if (it == json.object().end() || !json.object().at(name).is_array()) return default_value; - r4::vector value; + r4::vector value; int i = 0; for (const auto& subjson : json.object().at(name).array()) { value[i++] = subjson.number().to_float(); @@ -124,38 +122,14 @@ r4::vector read_vec( return value; } -ruis::vec2 read_vec2(const jsondom::value& json, const std::string& name, const ruis::vec2 default_value = {0, 0}) +ruis::quat read_quat(const jsondom::value& json, const std::string& name, const ruis::quat default_value) { - return read_vec(json, name, default_value); + ruis::vec4 default_vec = default_value.to_vector4(); + auto vec = read_vec(json, name, default_vec); + return ruis::quat{vec}; } -ruis::vec3 read_vec3(const jsondom::value& json, const std::string& name, const ruis::vec3 default_value = {0, 0, 0}) -{ - return read_vec(json, name, default_value); -} - -ruis::vec4 read_vec4(const jsondom::value& json, const std::string& name, const ruis::vec4 default_value = {0, 0, 0, 0}) -{ - return read_vec(json, name, default_value); -} - -ruis::quat read_quat(const jsondom::value& json, const std::string& name, const ruis::quat default_value = {1, 0, 0, 0}) -{ - auto it = json.object().find(name); - - if (it == json.object().end() || !json.object().at(name).is_array()) - return default_value; - - ruis::quat value; - int i = 0; - for (const auto& subjson : json.object().at(name).array()) { - if (i < 3) - value.v[i++] = subjson.number().to_float(); - else - value.s = subjson.number().to_float(); - } - return value; -} +} // namespace utki::shared_ref gltf_loader::read_buffer_view(const jsondom::value& buffer_view_json) { @@ -169,7 +143,7 @@ utki::shared_ref gltf_loader::read_buffer_view(const jsondom::value return new_buffer_view; } -template +template void gltf_loader::create_vertex_buffer_float( utki::shared_ref new_accessor, utki::span buffer, @@ -179,21 +153,22 @@ void gltf_loader::create_vertex_buffer_float( ) { utki::deserializer d(buffer); - std::vector vertex_attribute_buffer; + std::vector vertex_attribute_buffer; vertex_attribute_buffer.reserve(acc_count); - int n_skip_bytes = int(acc_stride) - int(sizeof(T)); - if (n_skip_bytes < 0) // TODO exception - n_skip_bytes = 0; + int n_skip_bytes = int(acc_stride) - int(sizeof(tp_type)); + if (n_skip_bytes < 0) { + throw std::invalid_argument("read_gltf(): n_skip_bytes < 0"); + } // // skip offset: // for (uint32_t skip = 0; skip < acc_offset; skip += sizeof(float)) // d.read_float_le(); for (uint32_t i = 0; i < acc_count; ++i) { - T t; + tp_type t; - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { t = d.read_float_le(); } else { for (uint32_t j = 0; j < t.size(); ++j) @@ -208,7 +183,7 @@ void gltf_loader::create_vertex_buffer_float( // new_accessor.get().data = var; // new_accessor.get().vbo = factory_.create_vertex_buffer(utki::make_span(new_accessor.get().data.get())); - new_accessor.get().vbo = factory_.create_vertex_buffer(utki::make_span(vertex_attribute_buffer)); + new_accessor.get().vbo = factory_v.create_vertex_buffer(utki::make_span(vertex_attribute_buffer)); new_accessor.get().data = std::move(vertex_attribute_buffer); // return std::make_shared(var); @@ -216,22 +191,22 @@ void gltf_loader::create_vertex_buffer_float( utki::shared_ref gltf_loader::read_accessor(const jsondom::value& accessor_json) { - accessor::type type_ = accessor::type::vec3; + accessor::type type_v = accessor::type::vec3; const std::string type_s = read_string(accessor_json, "type"); if (type_s == "SCALAR") - type_ = accessor::type::scalar; + type_v = accessor::type::scalar; else if (type_s == "VEC2") - type_ = accessor::type::vec2; + type_v = accessor::type::vec2; // else if(type_s == "VEC3") type_ = accessor::type::vec3; // huge performance boost else if (type_s == "VEC4") - type_ = accessor::type::vec4; + type_v = accessor::type::vec4; else if (type_s == "MAT2") - type_ = accessor::type::mat2; + type_v = accessor::type::mat2; else if (type_s == "MAT3") - type_ = accessor::type::mat3; + type_v = accessor::type::mat3; else if (type_s == "MAT4") - type_ = accessor::type::mat4; + type_v = accessor::type::mat4; const uint32_t buffer_view_index = read_uint(accessor_json, "bufferView"); const uint32_t acc_count = read_uint(accessor_json, "count"); @@ -243,12 +218,10 @@ utki::shared_ref gltf_loader::read_accessor(const jsondom::value& acce acc_count, acc_offset, // acc_stride, - type_, + type_v, static_cast(component_type) ); - // TODO: take count and byteOffset into account - const uint32_t bv_offset = new_accessor.get().bv.get().byte_offset; const uint32_t bv_length = new_accessor.get().bv.get().byte_length; const uint32_t bv_stride = new_accessor.get().bv.get().byte_stride; @@ -259,29 +232,29 @@ utki::shared_ref gltf_loader::read_accessor(const jsondom::value& acce // if (new_accessor.get().bv.get().target_ == buffer_view::target::array_buffer) { - if (new_accessor.get().component_type_ == accessor::component_type::act_float) { - if (new_accessor.get().type_ == accessor::type::scalar) + if (new_accessor.get().component_type_v == accessor::component_type::act_float) { + if (new_accessor.get().type_v == accessor::type::scalar) create_vertex_buffer_float(new_accessor, buf, acc_count, bv_stride); - else if (new_accessor.get().type_ == accessor::type::vec2) + else if (new_accessor.get().type_v == accessor::type::vec2) create_vertex_buffer_float(new_accessor, buf, acc_count, bv_stride); - else if (new_accessor.get().type_ == accessor::type::vec3) + else if (new_accessor.get().type_v == accessor::type::vec3) create_vertex_buffer_float(new_accessor, buf, acc_count, bv_stride); - else if (new_accessor.get().type_ == accessor::type::vec4) + else if (new_accessor.get().type_v == accessor::type::vec4) create_vertex_buffer_float(new_accessor, buf, acc_count, bv_stride); else { throw std::logic_error("Matrix vertex attributes currently not supported"); } // create_vertex_buffer_float>(buf); - } else if ((new_accessor.get().component_type_ == accessor::component_type::act_unsigned_short || - new_accessor.get().component_type_ == accessor::component_type::act_unsigned_int) && + } else if ((new_accessor.get().component_type_v == accessor::component_type::act_unsigned_short || + new_accessor.get().component_type_v == accessor::component_type::act_unsigned_int) && // new_accessor.get().bv.get().target_ == buffer_view::target::element_Array_buffer && // there are gltf exporters which don't mark target at all. So we must detect index arrays another way - new_accessor.get().type_ == accessor::type::scalar) + new_accessor.get().type_v == accessor::type::scalar) { utki::deserializer d(buf); - // TODO: think about what to do if index count > 65535 - if (new_accessor.get().component_type_ == accessor::component_type::act_unsigned_short /*|| acc_count < 65536*/) + if (new_accessor.get().component_type_v == + accessor::component_type::act_unsigned_short /*|| acc_count < 65536*/) { std::vector index_attribute_buffer; index_attribute_buffer.reserve(acc_count); @@ -290,9 +263,9 @@ utki::shared_ref gltf_loader::read_accessor(const jsondom::value& acce index_attribute_buffer.push_back(d.read_uint16_le()); new_accessor.get().data = index_attribute_buffer; - new_accessor.get().ibo = factory_.create_index_buffer(utki::make_span(index_attribute_buffer)); + new_accessor.get().ibo = factory_v.create_index_buffer(utki::make_span(index_attribute_buffer)); - } else if (new_accessor.get().component_type_ == + } else if (new_accessor.get().component_type_v == accessor::component_type::act_unsigned_int /*|| acc_count >= 65536*/) { std::vector index_attribute_buffer; @@ -302,7 +275,7 @@ utki::shared_ref gltf_loader::read_accessor(const jsondom::value& acce index_attribute_buffer.push_back(d.read_uint32_le()); new_accessor.get().data = index_attribute_buffer; - new_accessor.get().ibo = factory_.create_index_buffer(utki::make_span(index_attribute_buffer)); + new_accessor.get().ibo = factory_v.create_index_buffer(utki::make_span(index_attribute_buffer)); } // if (use_short_indices) { // opengles 2.0 does not support 32-bit indices by default @@ -338,7 +311,7 @@ utki::shared_ref gltf_loader::read_mesh(const jsondom::value& mesh_json) if (index_accessor >= 0 && texcoord_0_accessor >= 0 && normal_accessor >= 0 && tangent_accessor < 0) { // generate tangents and bitangents - if (accessors[index_accessor].get().component_type_ == accessor::component_type::act_unsigned_int) { + if (accessors[index_accessor].get().component_type_v == accessor::component_type::act_unsigned_int) { auto vao = create_vao_with_tangent_space( accessors[index_accessor], accessors[position_accessor], @@ -346,10 +319,10 @@ utki::shared_ref gltf_loader::read_mesh(const jsondom::value& mesh_json) accessors[normal_accessor] ); - auto material_ = material_index >= 0 ? materials[material_index] : utki::make_shared(); - primitives.push_back(utki::make_shared(vao, material_)); + auto material_v = material_index >= 0 ? materials[material_index] : utki::make_shared(); + primitives.push_back(utki::make_shared(vao, material_v)); - } else if (accessors[index_accessor].get().component_type_ == accessor::component_type::act_unsigned_short) + } else if (accessors[index_accessor].get().component_type_v == accessor::component_type::act_unsigned_short) { auto vao = create_vao_with_tangent_space( accessors[index_accessor], @@ -358,8 +331,8 @@ utki::shared_ref gltf_loader::read_mesh(const jsondom::value& mesh_json) accessors[normal_accessor] ); - auto material_ = material_index >= 0 ? materials[material_index] : utki::make_shared(); - primitives.push_back(utki::make_shared(vao, material_)); + auto material_v = material_index >= 0 ? materials[material_index] : utki::make_shared(); + primitives.push_back(utki::make_shared(vao, material_v)); } else { // TODO: branch all possible combinations if input data } @@ -384,21 +357,25 @@ utki::shared_ref gltf_loader::read_mesh(const jsondom::value& mesh_json) utki::shared_ref gltf_loader::read_node(const jsondom::value& node_json) { + constexpr ruis::vec3 default_scale{1, 1, 1}; + constexpr ruis::vec3 default_translation{0, 0, 0}; + constexpr ruis::quat default_rotation{1, 0, 0, 0}; + trs transformation = transformation_identity; std::string name = read_string(node_json, "name"); auto it = node_json.object().find("rotation"); if (it != node_json.object().end()) - transformation.rotation = read_quat(node_json, "rotation"); + transformation.rotation = read_quat(node_json, "rotation", default_rotation); it = node_json.object().find("scale"); if (it != node_json.object().end()) - transformation.scale = read_vec3(node_json, "scale"); + transformation.scale = read_vec(node_json, "scale", default_scale); it = node_json.object().find("translation"); if (it != node_json.object().end()) - transformation.translation = read_vec3(node_json, "translation"); + transformation.translation = read_vec(node_json, "translation", default_translation); int mesh_index = read_int(node_json, "mesh"); child_indices.push_back(read_uint_array(node_json, "children")); @@ -459,9 +436,9 @@ utki::shared_ref gltf_loader::read_texture(const jsond const papki::span_file fi(image_span); rasterimage::image_variant imvar; - if (image.get().mime_type_ == image_l::mime_type::image_png) { + if (image.get().mime_type_v == image_l::mime_type::image_png) { imvar = rasterimage::read_png(fi); - } else if (image.get().mime_type_ == image_l::mime_type::image_jpeg) { + } else if (image.get().mime_type_v == image_l::mime_type::image_jpeg) { imvar = rasterimage::read_jpeg(fi); } else { throw std::invalid_argument("gltf: unknown texture image format"); @@ -472,7 +449,7 @@ utki::shared_ref gltf_loader::read_texture(const jsond tex_params.min_filter = ruis::render::texture_2d::filter::linear; tex_params.mipmap = texture_2d::mipmap::linear; - return factory_.create_texture_2d(std::move(imvar), tex_params); + return factory_v.create_texture_2d(std::move(imvar), tex_params); } // "materials": [ @@ -535,14 +512,14 @@ utki::shared_ref gltf_loader::read_material(const jsondom::value& mate return mat; } -template -std::vector> gltf_loader::read_root_array( - std::function read_func, +template +std::vector> gltf_loader::read_root_array( + std::function read_func, const jsondom::value& root_json, const std::string& name ) { - std::vector> all; + std::vector> all; std::cout << "loading " << name << std::endl; auto it = root_json.object().find(name); if (it != root_json.object().end() && it->second.is_array()) { @@ -593,7 +570,7 @@ utki::shared_ref gltf_loader::load(const papki::file& fi) if (chunk_length == 0) { throw std::invalid_argument("read_gltf(): chunk length = 0"); } - if (auto chunk_type = d.read_string(chunk_type_length); chunk_type != "BIN\0"sv) { // TODO null terminator ? + if (auto chunk_type = d.read_string(chunk_type_length); chunk_type != "BIN\0"sv) { throw std::invalid_argument( utki::cat("read_gltf(): unexpected first chunk type: ", chunk_type, ", expected JSON") ); @@ -709,24 +686,24 @@ utki::shared_ref gltf_loader::load(const papki::file& fi) } // create cameras (currently generates one default camera) - std::cout << "create camera" << std::endl; + // std::cout << "create camera" << std::endl; - auto cam = utki::make_shared(); - cam.get().pos = {0, 3.5, -8}; - cam.get().target = {0, 1, 0}; - cam.get().up = {0, 1, 0}; - cam.get().near = 0.1; - cam.get().far = 100; - cam.get().fovy = 3.1415926 / 3; + // auto cam = utki::make_shared(); + // cam.get().pos = {0, 3.5, -8}; + // cam.get().target = {0, 1, 0}; + // cam.get().up = {0, 1, 0}; + // cam.get().near = 0.1; + // cam.get().far = 100; + // cam.get().fovy = 3.1415926 / 3; - active_scene.get().cameras.push_back(cam); - active_scene.get().active_camera = cam.to_shared_ptr(); + // active_scene.get().cameras.push_back(cam); + // active_scene.get().active_camera = cam.to_shared_ptr(); std::cout << "gltf load finished" << std::endl; return active_scene; } -template +template utki::shared_ref gltf_loader::create_vao_with_tangent_space( utki::shared_ref index_accessor, utki::shared_ref position_accessor, @@ -734,31 +711,24 @@ utki::shared_ref gltf_loader::create_vao_with_tangen utki::shared_ref normal_accessor ) { - int total_vertices = position_accessor.get().count; - int total_triangles = index_accessor.get().count / 3; + uint32_t total_vertices = position_accessor.get().count; + uint32_t total_triangles = index_accessor.get().count / 3; - // const index_t* index_data = static_cast(index_accessor.get().data); - // const index_t* pTriangle; + std::cout << "index is " << sizeof(tp_type) << "-byte" << std::endl; - std::cout << "index is " << sizeof(index_t) << "-byte" << std::endl; - - const auto& indices = std::get>(index_accessor.get().data); + const auto& indices = std::get>(index_accessor.get().data); const auto& positions = std::get>(position_accessor.get().data); const auto& texcoords = std::get>(texcoord_0_accessor.get().data); const auto& normals = std::get>(normal_accessor.get().data); - // const float* position_data = static_cast(position_accessor.get().data); - // const float* texcoord_data = static_cast(texcoord_0_accessor.get().data); - // const float* normal_data = static_cast(normal_accessor.get().data); - std::vector tangents; // or vec4 ? std::vector bitangents; tangents.resize(total_vertices); bitangents.resize(total_vertices); - ruis::vec2 texEdge1 = {0.0f, 0.0f}; - ruis::vec2 texEdge2 = {0.0f, 0.0f}; + ruis::vec2 tex_edge_1 = {0.0f, 0.0f}; + ruis::vec2 tex_edge_2 = {0.0f, 0.0f}; ruis::vec3 edge1 = {0.0f, 0.0f, 0.0f}; ruis::vec3 edge2 = {0.0f, 0.0f, 0.0f}; @@ -768,47 +738,33 @@ utki::shared_ref gltf_loader::create_vao_with_tangen ruis::vec4 tangent = {0.0f, 0.0f, 0.0f, 0.0f}; // Calculate the vertex tangents and bitangents. - for (int i = 0; i < total_triangles; ++i) { - // pTriangle = &index_data[i * 3]; - + for (uint32_t i = 0; i < total_triangles; ++i) { edge1 = positions[indices[i * 3 + 1]] - positions[indices[i * 3 + 0]]; edge2 = positions[indices[i * 3 + 2]] - positions[indices[i * 3 + 0]]; - texEdge1 = texcoords[indices[i * 3 + 1]] - texcoords[indices[i * 3 + 0]]; - texEdge2 = texcoords[indices[i * 3 + 2]] - texcoords[indices[i * 3 + 0]]; - - // edge1[0] = position_data[pTriangle[1] + 0] - position_data[pTriangle[0] + 0]; - // edge1[1] = position_data[pTriangle[1] + 1] - position_data[pTriangle[0] + 1]; - // edge1[2] = position_data[pTriangle[1] + 2] - position_data[pTriangle[0] + 2]; - - // edge2[0] = position_data[pTriangle[2] + 0] - position_data[pTriangle[0] + 0]; - // edge2[1] = position_data[pTriangle[2] + 1] - position_data[pTriangle[0] + 1]; - // edge2[2] = position_data[pTriangle[2] + 2] - position_data[pTriangle[0] + 2]; - - // texEdge1[0] = texcoord_data[pTriangle[1] + 0] - texcoord_data[pTriangle[0] + 0]; - // texEdge1[1] = texcoord_data[pTriangle[1] + 1] - texcoord_data[pTriangle[0] + 1]; - - // texEdge2[0] = texcoord_data[pTriangle[2] + 0] - texcoord_data[pTriangle[0] + 0]; - // texEdge2[1] = texcoord_data[pTriangle[2] + 1] - texcoord_data[pTriangle[0] + 1]; + tex_edge_1 = texcoords[indices[i * 3 + 1]] - texcoords[indices[i * 3 + 0]]; + tex_edge_2 = texcoords[indices[i * 3 + 2]] - texcoords[indices[i * 3 + 0]]; // Calculate the triangle face tangent and bitangent. - float det = texEdge1[0] * texEdge2[1] - texEdge2[0] * texEdge1[1]; + float det = tex_edge_1[0] * tex_edge_2[1] - tex_edge_2[0] * tex_edge_1[1]; + + constexpr float epsilon = 1e-6f; using std::abs; - if (abs(det) < 1e-6f) { + if (abs(det) < epsilon) { tangent = {1.0f, 0.0f, 0.0f, 0.0f}; bitangent = {0.0f, 1.0f, 0.0f}; } else { det = 1.0f / det; - tangent[0] = (texEdge2[1] * edge1[0] - texEdge1[1] * edge2[0]) * det; - tangent[1] = (texEdge2[1] * edge1[1] - texEdge1[1] * edge2[1]) * det; - tangent[2] = (texEdge2[1] * edge1[2] - texEdge1[1] * edge2[2]) * det; + tangent[0] = (tex_edge_2[1] * edge1[0] - tex_edge_1[1] * edge2[0]) * det; + tangent[1] = (tex_edge_2[1] * edge1[1] - tex_edge_1[1] * edge2[1]) * det; + tangent[2] = (tex_edge_2[1] * edge1[2] - tex_edge_1[1] * edge2[2]) * det; - bitangent[0] = (-texEdge2[0] * edge1[0] + texEdge1[0] * edge2[0]) * det; - bitangent[1] = (-texEdge2[0] * edge1[1] + texEdge1[0] * edge2[1]) * det; - bitangent[2] = (-texEdge2[0] * edge1[2] + texEdge1[0] * edge2[2]) * det; + bitangent[0] = (-tex_edge_2[0] * edge1[0] + tex_edge_1[0] * edge2[0]) * det; + bitangent[1] = (-tex_edge_2[0] * edge1[1] + tex_edge_1[0] * edge2[1]) * det; + bitangent[2] = (-tex_edge_2[0] * edge1[2] + tex_edge_1[0] * edge2[2]) * det; } // TODO: figure out what is happening here and refactor with vector ops @@ -825,43 +781,29 @@ utki::shared_ref gltf_loader::create_vao_with_tangen } // Orthogonalize and normalize the vertex tangents. - for (int i = 0; i < total_vertices; ++i) { + for (uint32_t i = 0; i < total_vertices; ++i) { // Gram-Schmidt orthogonalize tangent with normal. - // ruis::vec3 normal{normal_data[i * 3], normal_data[i * 3 + 1], normal_data[i * 3 + 2]}; - float nDotT = normals[i] * tangents[i]; // dot product + float n_dot_t = normals[i] * tangents[i]; // dot product - tangents[i] -= normals[i] * nDotT; + tangents[i] -= normals[i] * n_dot_t; // Normalize the tangent. tangents[i].normalize(); - // Calculate the handedness of the local tangent space. - // The bitangent vector is the cross product between the triangle face - // normal vector and the calculated tangent vector. The resulting - // bitangent vector should be the same as the bitangent vector - // calculated from the set of linear equations above. If they point in - // different directions then we need to invert the cross product - // calculated bitangent vector. We store this scalar multiplier in the - // tangent vector's 'w' component so that the correct bitangent vector - // can be generated in the normal mapping shader's vertex shader. - // - // TODO: revise this comment - ruis::vec3 bitangent_other = normals[i].cross(tangents[i]); - float bDotB = bitangent_other * bitangents[i]; + float b_dot_b = bitangent_other * bitangents[i]; - // tangents[i][3] = (bDotB < 0.0f) ? 1.0f : -1.0f; - float sign = (bDotB < 0.0f) ? -1.0f : 1.0f; + float sign = (b_dot_b < 0.0f) ? -1.0f : 1.0f; bitangents[i] = bitangent_other * sign; } - auto tangents_vbo = factory_.create_vertex_buffer(utki::make_span(tangents)); - auto bitangents_vbo = factory_.create_vertex_buffer(utki::make_span(bitangents)); + auto tangents_vbo = factory_v.create_vertex_buffer(utki::make_span(tangents)); + auto bitangents_vbo = factory_v.create_vertex_buffer(utki::make_span(bitangents)); - auto vao = factory_.create_vertex_array( + auto vao = factory_v.create_vertex_array( {utki::shared_ref(position_accessor.get().vbo), utki::shared_ref(texcoord_0_accessor.get().vbo), utki::shared_ref(normal_accessor.get().vbo), diff --git a/src/ruis/render/scene/gltf_loader.hpp b/src/ruis/render/scene/gltf_loader.hxx similarity index 87% rename from src/ruis/render/scene/gltf_loader.hpp rename to src/ruis/render/scene/gltf_loader.hxx index 3dafa7d..e175454 100644 --- a/src/ruis/render/scene/gltf_loader.hpp +++ b/src/ruis/render/scene/gltf_loader.hxx @@ -38,18 +38,17 @@ struct accessor; struct image_l; struct sampler_l; class material; -typedef std::variant< +using vertex_data_t = std::variant< std::vector, std::vector, std::vector, std::vector, std::vector, - std::vector> - vertex_data_t; + std::vector>; class gltf_loader { - ruis::render::factory& factory_; + ruis::render::factory& factory_v; utki::span glb_binary_buffer; @@ -68,7 +67,7 @@ class gltf_loader std::vector> child_indices; // storage for node child hierarchy (only during loading stage) - template + template // std::shared_ptr void create_vertex_buffer_float( utki::shared_ref, @@ -78,17 +77,14 @@ class gltf_loader uint32_t acc_stride ); - template - r4::vector read_vec(const jsondom::value& json, const std::string& name); - - template - std::vector> read_root_array( - std::function read_func, + template + std::vector> read_root_array( + std::function read_func, const jsondom::value& root_json, const std::string& name ); - template + template utki::shared_ref create_vao_with_tangent_space( utki::shared_ref index_accessor, utki::shared_ref position_accessor, @@ -109,7 +105,7 @@ class gltf_loader public: utki::shared_ref load(const papki::file& fi); - gltf_loader(ruis::render::factory& factory_); + gltf_loader(ruis::render::factory& factory_v); }; struct buffer_view // currently we support only one data buffer, the single data buffer located in the .glb file @@ -122,14 +118,14 @@ struct buffer_view // currently we support only one data buffer, the single data enum class target { undefined = 0, array_buffer = 34962, - element_Array_buffer = 34963 - } target_; + element_array_buffer = 34963 + } target_v; - buffer_view(uint32_t byte_length, uint32_t byte_offset, uint32_t byte_stride, target target_) : + buffer_view(uint32_t byte_length, uint32_t byte_offset, uint32_t byte_stride, target target_v) : byte_length(byte_length), byte_offset(byte_offset), byte_stride(byte_stride), - target_(target_) + target_v(target_v) {} }; @@ -148,7 +144,7 @@ struct accessor { mat2 = 5, // whoa mat3 = 9, mat4 = 16 - } type_; + } type_v; enum class component_type { undefined = 0, @@ -158,7 +154,7 @@ struct accessor { act_unsigned_short = 5123, act_unsigned_int = 5125, act_float = 5126 - } component_type_; + } component_type_v; std::shared_ptr vbo; std::shared_ptr ibo; @@ -173,24 +169,24 @@ struct accessor { uint32_t count, uint32_t byte_offset, // uint32_t byte_stride, - type type_, - component_type component_type_ + type type_v, + component_type component_type_v ); }; -struct image_l { // TODO: put loader helper classes into separate namespace +struct image_l { std::string name; utki::shared_ref bv; enum class mime_type { undefined = 0, image_jpeg = 1, image_png = 2 - } mime_type_; + } mime_type_v; - image_l(std::string name, utki::shared_ref bv, mime_type mime_type_) : + image_l(std::string name, utki::shared_ref bv, mime_type mime_type_v) : name(std::move(name)), bv(std::move(bv)), - mime_type_(mime_type_) + mime_type_v(mime_type_v) {} }; diff --git a/src/ruis/render/scene/mesh.cpp b/src/ruis/render/scene/mesh.cpp index 87967ee..7056151 100644 --- a/src/ruis/render/scene/mesh.cpp +++ b/src/ruis/render/scene/mesh.cpp @@ -23,24 +23,12 @@ along with this program. If not, see . using namespace ruis::render; -mesh::mesh(const std::vector>& primitives, const std::string& name) : +mesh::mesh(const std::vector>& primitives, std::string name) : primitives(primitives), - name(name) + name(std::move(name)) {} -// void mesh::render() -// { -// for (const auto& primitive : primitives) { -// primitive.get().render(); -// } -// } - -primitive::primitive(utki::shared_ref vao, utki::shared_ref material_) : - vao(vao), - material_(material_) +primitive::primitive(utki::shared_ref vao, utki::shared_ref material_v) : + vao(std::move(vao)), + material_v(std::move(material_v)) {} - -// void primitive::render() -// { -// // material_.get().shader.get()->render(m, vao.get()); -// } \ No newline at end of file diff --git a/src/ruis/render/scene/mesh.hpp b/src/ruis/render/scene/mesh.hpp index 9bed9ed..1085c0d 100644 --- a/src/ruis/render/scene/mesh.hpp +++ b/src/ruis/render/scene/mesh.hpp @@ -41,8 +41,8 @@ class primitive { public: utki::shared_ref vao; - utki::shared_ref material_; - primitive(utki::shared_ref vao, utki::shared_ref material_); + utki::shared_ref material_v; + primitive(utki::shared_ref vao, utki::shared_ref material_v); // void render(); }; @@ -51,9 +51,7 @@ class mesh public: std::vector> primitives; std::string name; - mesh(const std::vector>& primitives, const std::string& name); - - void render(); + mesh(const std::vector>& primitives, std::string name); }; } // namespace ruis::render \ No newline at end of file diff --git a/src/ruis/render/scene/node.cpp b/src/ruis/render/scene/node.cpp index e2a128e..567718f 100644 --- a/src/ruis/render/scene/node.cpp +++ b/src/ruis/render/scene/node.cpp @@ -23,9 +23,9 @@ along with this program. If not, see . using namespace ruis::render; -node::node(std::shared_ptr mesh_, const std::string name, const trs& transformation) : - mesh_(mesh_), - name(name), +node::node(std::shared_ptr mesh_v, std::string name, const trs& transformation) : + mesh_v(std::move(mesh_v)), + name(std::move(name)), transformation(transformation) {} @@ -38,12 +38,3 @@ const ruis::mat4& node::get_transformation_matrix() return transformation_matrix; } - -// void node::render(const scene& s) -// { -// if (mesh_ != nullptr) -// mesh_->render(); -// for (const auto& child : children) { -// child.get().render(s); -// } -// } \ No newline at end of file diff --git a/src/ruis/render/scene/node.hpp b/src/ruis/render/scene/node.hpp index 507cbeb..cfa0c89 100644 --- a/src/ruis/render/scene/node.hpp +++ b/src/ruis/render/scene/node.hpp @@ -52,8 +52,7 @@ class node ruis::mat4 transformation_matrix; public: - // TODO: add extras as JSON? - std::shared_ptr mesh_; // can be null, empty (intermediate) node + std::shared_ptr mesh_v; // can be null, empty (intermediate) node std::string name; trs transformation; @@ -62,7 +61,7 @@ class node const ruis::mat4& get_transformation_matrix(); // std::variant transformation; - node(std::shared_ptr mesh_, const std::string name, const trs& transformation = transformation_identity); + node(std::shared_ptr mesh_v, std::string name, const trs& transformation = transformation_identity); // void render(const scene& s); }; diff --git a/src/ruis/render/scene/scene.cpp b/src/ruis/render/scene/scene.cpp index d7f5489..45ed199 100644 --- a/src/ruis/render/scene/scene.cpp +++ b/src/ruis/render/scene/scene.cpp @@ -25,8 +25,6 @@ along with this program. If not, see . using namespace ruis::render; -scene::scene() {} - void scene::update(uint32_t dt) { time += dt; @@ -34,12 +32,6 @@ void scene::update(uint32_t dt) [[maybe_unused]] float fdt = static_cast(dt) / std::milli::den; } -// void scene::render(ruis::render::renderer& r) -// { -// // TODO: render from here -// [[maybe_unused]] auto& phong = carcockpit::application::inst().shader_phong_v; -// } - ruis::mat4 camera::get_projection_matrix(ruis::real aspect_ratio) { ruis::mat4 projection; diff --git a/src/ruis/render/scene/scene.hpp b/src/ruis/render/scene/scene.hpp index ef3cd51..b79cd9e 100644 --- a/src/ruis/render/scene/scene.hpp +++ b/src/ruis/render/scene/scene.hpp @@ -35,6 +35,8 @@ class light; class scene { + uint32_t time = 0; + public: std::string name; @@ -43,12 +45,14 @@ class scene std::vector> lights; std::shared_ptr active_camera; - scene(); + + scene() = default; void update(uint32_t dt); - uint32_t time = 0; - // void render(ruis::render::renderer& r); }; +constexpr float default_camera_near = 0.1; +constexpr float default_camera_far = 100.0; + class camera // TODO: derive from node { public: @@ -56,9 +60,9 @@ class camera // TODO: derive from node ruis::vec3 target; ruis::vec3 up{0, 1, 0}; - ruis::real fovy; - ruis::real near{0.1}; - ruis::real far{100}; + ruis::real fovy{M_PI_2}; + ruis::real near{default_camera_near}; + ruis::real far{default_camera_far}; ruis::mat4 get_projection_matrix(ruis::real aspect_ratio); ruis::mat4 get_view_matrix(); @@ -67,10 +71,11 @@ class camera // TODO: derive from node }; class light // TODO: derive from node + // TODO: give user options to tweak light { public: - ruis::vec4 pos; // vec4, because w = 0 means light is at infinite distance - ruis::vec3 intensity; + ruis::vec4 pos{1, 1, 1, 1}; // vec4, because w = 0 means light is at infinite distance + ruis::vec3 intensity{1, 1, 1}; }; } // namespace ruis::render \ No newline at end of file diff --git a/src/ruis/render/scene/scene_renderer.cpp b/src/ruis/render/scene/scene_renderer.cpp index 98217a3..2d410ce 100644 --- a/src/ruis/render/scene/scene_renderer.cpp +++ b/src/ruis/render/scene/scene_renderer.cpp @@ -19,7 +19,7 @@ along with this program. If not, see . /* ================ LICENSE END ================ */ -#include "scene_renderer.hpp" +#include "scene_renderer.hxx" #include @@ -28,7 +28,7 @@ along with this program. If not, see . using namespace ruis::render; scene_renderer::scene_renderer(utki::shared_ref c) : - context_v(c) + context_v(std::move(c)) { texture_default_black = context_v.get().loader.load("texture_default_black").to_shared_ptr(); texture_default_white = context_v.get().loader.load("texture_default_white").to_shared_ptr(); @@ -40,11 +40,21 @@ scene_renderer::scene_renderer(utki::shared_ref c) : prepare_fullscreen_quad_vao(); } +void scene_renderer::set_scene_scaling_factor(ruis::real scene_scaling_factor) +{ + this->scene_scaling_factor = scene_scaling_factor; +} + void scene_renderer::set_scene(std::shared_ptr scene_v) { this->scene_v = scene_v; } +void scene_renderer::set_environment_cube(std::shared_ptr texture_environment_cube) +{ + this->texture_environment_cube = texture_environment_cube; +} + void scene_renderer::set_external_camera(std::shared_ptr cam) { external_camera = cam; @@ -65,26 +75,33 @@ void scene_renderer::render(const ruis::rect& dims, const ruis::mat4& viewport_m view_matrix = cam->get_view_matrix(); + constexpr ruis::vec4 default_light_position{2, 4, -2, 1}; + constexpr ruis::vec3 default_light_intensity{2, 2, 2}; + if (scene_v.get()->lights.size() > 0) // scene has at least 1 light { main_light = scene_v.get()->lights[0].get(); } else { - main_light.pos = {2, 4, -2, 1}; - main_light.intensity = {1, 1, 1}; - main_light.intensity *= 2.0; + main_light.pos = default_light_position; + main_light.intensity = default_light_intensity; } - glDisable(GL_DEPTH_TEST); - render_environment(); - glEnable(GL_DEPTH_TEST); + { + auto& r = this->context_v.get().renderer.get(); + bool depth = r.is_depth_enabled(); + r.enable_depth(false); + utki::scope_exit scope_exit([&r, depth]() { + r.enable_depth(depth); + }); + render_environment(); + } ruis::mat4 root_model_matrix; root_model_matrix.set_identity(); - root_model_matrix.scale(35, 35, 35); // TODO: get rid of - root_model_matrix.translate(0, -0.1, 0); + root_model_matrix.scale(scene_scaling_factor, scene_scaling_factor, scene_scaling_factor); - for (const auto& node_ : scene_v->nodes) { - this->render_node(node_, root_model_matrix); + for (const auto& node_v : scene_v->nodes) { + this->render_node(node_v, root_model_matrix); } } @@ -113,9 +130,13 @@ void scene_renderer::prepare_fullscreen_quad_vao() void scene_renderer::render_environment() { - [[maybe_unused]] auto& skybox = carcockpit::application::inst().shader_skybox_v; - - skybox.render(*fullscreen_quad_vao.get(), view_matrix, projection_matrix, texture_default_environment_cube->tex()); + auto& skybox = carcockpit::application::inst().shader_skybox_v; + skybox.render( + *fullscreen_quad_vao.get(), + view_matrix, + projection_matrix, + texture_environment_cube ? texture_environment_cube->tex() : texture_default_environment_cube->tex() + ); } void scene_renderer::render_node(utki::shared_ref n, ruis::mat4 parent_model_matrix) @@ -129,16 +150,16 @@ void scene_renderer::render_node(utki::shared_ref n, ruis::mat4 parent_mod view_matrix * main_light.pos; // light position in view (camera) coords // render the node itself - if (n.get().mesh_) { - for (const auto& primitive : n.get().mesh_->primitives) { + if (n.get().mesh_v) { + for (const auto& primitive : n.get().mesh_v->primitives) { [[maybe_unused]] auto& phong = carcockpit::application::inst().shader_phong_v; [[maybe_unused]] auto& advanced = carcockpit::application::inst().shader_adv_v; // choose shader and textures here, set material-specific uniforms - auto tex_diffuse = primitive.get().material_.get().tex_diffuse; - auto tex_normal = primitive.get().material_.get().tex_normal; - auto tex_arm = primitive.get().material_.get().tex_arm; + auto tex_diffuse = primitive.get().material_v.get().tex_diffuse; + auto tex_normal = primitive.get().material_v.get().tex_normal; + auto tex_arm = primitive.get().material_v.get().tex_arm; advanced.render( primitive.get().vao.get(), @@ -148,7 +169,7 @@ void scene_renderer::render_node(utki::shared_ref n, ruis::mat4 parent_mod tex_diffuse ? *tex_diffuse.get() : texture_default_white->tex(), tex_normal ? *tex_normal.get() : texture_default_normal->tex(), tex_arm ? *tex_arm.get() : texture_default_white->tex(), - texture_default_environment_cube->tex(), // TODO load environment as well, if supported by gltf ? + texture_environment_cube ? texture_environment_cube->tex() : texture_default_environment_cube->tex(), light_pos_view_coords, main_light.intensity ); @@ -164,7 +185,7 @@ void scene_renderer::render_node(utki::shared_ref n, ruis::mat4 parent_mod } } // render children - for (const auto& node_ : n.get().children) { - this->render_node(node_, parent_model_matrix); + for (const auto& node_v : n.get().children) { + this->render_node(node_v, parent_model_matrix); } } diff --git a/src/ruis/render/scene/scene_renderer.hpp b/src/ruis/render/scene/scene_renderer.hxx similarity index 62% rename from src/ruis/render/scene/scene_renderer.hpp rename to src/ruis/render/scene/scene_renderer.hxx index fac6654..425e037 100644 --- a/src/ruis/render/scene/scene_renderer.hpp +++ b/src/ruis/render/scene/scene_renderer.hxx @@ -26,10 +26,6 @@ along with this program. If not, see . #include #include -// #include "shaders/shader_adv.hpp" -// #include "shaders/shader_phong.hpp" -// #include "shaders/shader_skybox.hpp" - #include "node.hpp" #include "scene.hpp" @@ -45,20 +41,18 @@ class scene_renderer std::shared_ptr fullscreen_quad_vao; std::shared_ptr scene_v; std::shared_ptr external_camera; - // ruis::render::renderer& r; utki::shared_ref context_v; ruis::mat4 view_matrix; ruis::mat4 projection_matrix; - light main_light; + ruis::render::light main_light; + ruis::real scene_scaling_factor{1}; std::shared_ptr texture_default_white; std::shared_ptr texture_default_black; std::shared_ptr texture_default_normal; std::shared_ptr texture_default_environment_cube; - // camera main_camera; + std::shared_ptr texture_environment_cube; void render_node(utki::shared_ref n, ruis::mat4 parent_model_matrix); - // void render_mesh(utki::shared_ref n, ruis::mat4 model); - // void render_primitive(utki::shared_ref n, ruis::mat4 model); void render_environment(); void prepare_fullscreen_quad_vao(); @@ -66,47 +60,9 @@ class scene_renderer scene_renderer(utki::shared_ref c); void render(const ruis::rect& dims, const ruis::mat4& viewport_matrix); void set_scene(std::shared_ptr scene_v); + void set_scene_scaling_factor(ruis::real scene_scaling_factor); + void set_environment_cube(std::shared_ptr texture_environment_cube); void set_external_camera(std::shared_ptr cam); - - virtual ~scene_renderer() {} }; -// class scene_renderer_regular : public scene_renderer -// { -// // std::shared_ptr skybox_shader; -// // std::shared_ptr phong_shader; -// // std::shared_ptr advanced_shader; - -// public: -// ruis::mat4 view_matrix; - -// void render_node(utki::shared_ref n, ruis::mat4 model) override; -// scene_renderer_regular(ruis::render::renderer& r); -// }; - -// class shadow_scene_renderer : public scene_renderer{ -// public: -// const matrix shadow_matrix; - -// void render_node(const node& n, matrix model)override{ -// // efwefew -// } -// }; - -// auto shadow_tex; - -// scene::render(){ -// ordinary_scene_renderer or; - -// or.render(root_node); - -// if(shadow_cache_dirty){ -// shadow_scene_renderer sr(light_pos); - -// sr.render(root_node); - -// shadow_tex = sr.get_result(); -// } -// } - } // namespace ruis::render \ No newline at end of file diff --git a/tests/unit/src/scene.cpp b/tests/unit/src/scene.cpp index e43ff90..9cf68ee 100644 --- a/tests/unit/src/scene.cpp +++ b/tests/unit/src/scene.cpp @@ -1,11 +1,11 @@ #include #include -#include +#include #include #include namespace { -tst::set set("scene", [](tst::suite& suite) { +const tst::set set("scene", [](tst::suite& suite) { suite.add("basic_read", []() { ruis::render::opengles::factory rf;