diff --git a/cgogn/rendering/CMakeLists.txt b/cgogn/rendering/CMakeLists.txt index 1634cdae9..f7c53b2c7 100644 --- a/cgogn/rendering/CMakeLists.txt +++ b/cgogn/rendering/CMakeLists.txt @@ -67,6 +67,9 @@ set(src_list "${CMAKE_CURRENT_LIST_DIR}/shaders/shader_flat_color_per_face.h" "${CMAKE_CURRENT_LIST_DIR}/shaders/shader_flat_color_per_face.cpp" + "${CMAKE_CURRENT_LIST_DIR}/shaders/shader_flat_texture.h" + "${CMAKE_CURRENT_LIST_DIR}/shaders/shader_flat_texture.cpp" + "${CMAKE_CURRENT_LIST_DIR}/shaders/shader_phong.h" "${CMAKE_CURRENT_LIST_DIR}/shaders/shader_phong.cpp" "${CMAKE_CURRENT_LIST_DIR}/shaders/shader_phong_color_per_vertex.h" diff --git a/cgogn/rendering/apps/simple_surface_viewer.cpp b/cgogn/rendering/apps/simple_surface_viewer.cpp index 635f47792..623122378 100644 --- a/cgogn/rendering/apps/simple_surface_viewer.cpp +++ b/cgogn/rendering/apps/simple_surface_viewer.cpp @@ -38,7 +38,12 @@ #include #include + #include +#include + + + #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_DATA_PATH) "/meshes/" @@ -54,11 +59,15 @@ using Mesh = cgogn::CMap2; template using Attribute = typename cgogn::mesh_traits::Attribute; using Vertex = typename cgogn::mesh_traits::Vertex; +using Edge = typename cgogn::mesh_traits::Edge; using Face = typename cgogn::mesh_traits::Face; using Vec3 = cgogn::geometry::Vec3; +using Vec2 = cgogn::geometry::Vec2; using Scalar = cgogn::geometry::Scalar; + + int main(int argc, char** argv) { std::string filename; @@ -75,6 +84,7 @@ int main(int argc, char** argv) cgogn::ui::MeshProvider mp(app); cgogn::ui::SurfaceRender sr(app); + cgogn::ui::SurfaceTexRender str(app); cgogn::ui::SurfaceDifferentialProperties sdp(app); app.init_modules(); @@ -82,10 +92,8 @@ int main(int argc, char** argv) cgogn::ui::View* v1 = app.current_view(); v1->link_module(&mp); v1->link_module(&sr); + v1->link_module(&str); - // cgogn::ui::View* v2 = app.add_view(); - // v2->link_module(&mp); - // v2->link_module(&sr); if (filename.length() > 0) { @@ -97,18 +105,45 @@ int main(int argc, char** argv) } std::shared_ptr> vertex_position = cgogn::get_attribute(*m, "position"); - std::shared_ptr> vertex_normal = cgogn::add_attribute(*m, "normal"); + std::shared_ptr> vertex_normal = cgogn::add_attribute(*m, "normal"); + + using Vec4 = cgogn::geometry::Vec4; + + // // attrinut de couleur sur l'arĂȘte + // std::shared_ptr> edge_color = cgogn::add_attribute(*m, "edge_color"); + // std::shared_ptr> face_color = cgogn::add_attribute(*m, "face_color"); + + + // plan diagonal de la BB + // std::pair bb = mp.meshes_bb(); + // Vec3 N = (bb.second - bb.first).normalized(); + // Vec4 plane(N[0],N[1],N[2], - N.dot((bb.first+ bb.second)/Scalar(2))); + // plane.topRows<3>() = bb.second - bb.first; + + // //parcours de arĂȘtes rouge si coupee par le plan, inon bleu + // cgogn::foreach_cell(*m, [&](Edge e) -> bool { + // if (cgogn::is_incident_to_boundary(*m,e)) + // { + // cgogn::value(*m, edge_color, e) = Vec3(0,1,0); + // std::vector incF = incident_faces(*m, e); + // for(auto f: incF) + // cgogn::value(*m, face_color, f) = Vec3(1,0,1); + // } + // else + // { + // std::vector iv = incident_vertices(*m, e); + // const Vec3& A = cgogn::value(*m, vertex_position, iv[0]); + // const Vec3& B = cgogn::value(*m, vertex_position, iv[1]); + // bool Sa = std::signbit(plane.dot(Vec4(A[0],A[1],A[2],1))); + // bool Sb = std::signbit(plane.dot(Vec4(B[0],B[1],B[2],1))); + // if (Sa != Sb) + // cgogn::value(*m, edge_color, e) = Vec3(1,0,0); + // else + // cgogn::value(*m, edge_color, e) = Vec3(0,0,1); + // } + // return true; + // }); - std::shared_ptr> face_color = cgogn::add_attribute(*m, "color"); - std::shared_ptr> face_weight = cgogn::add_attribute(*m, "weight"); - - cgogn::foreach_cell(*m, [&](Face f) -> bool { - Vec3 c(0, 0, 0); - c[rand() % 3] = 1; - cgogn::value(*m, face_color, f) = c; - cgogn::value(*m, face_weight, f) = double(rand()) / RAND_MAX; - return true; - }); mp.set_mesh_bb_vertex_position(*m, vertex_position); @@ -116,6 +151,22 @@ int main(int argc, char** argv) sr.set_vertex_position(*v1, *m, vertex_position); sr.set_vertex_normal(*v1, *m, vertex_normal); + + str.set_vertex_position(*v1, *m, vertex_position); + std::shared_ptr> vertex_tc = cgogn::add_attribute(*m, "tc"); + + std::pair bb = mp.meshes_bb(); + Vec3 bbw = bb.second - bb.first; + + cgogn::foreach_cell(*m, [&](Vertex v) -> bool { + Vec2 P = cgogn::value(*m, vertex_position, v).topRows<2>(); + Vec2 TC{(P.x() - bb.first.x())/ bbw.x(), (P.y() - bb.first.y())/ bbw.y()}; + cgogn::value(*m, vertex_tc, v) = TC; + // std::cout<< TC.transpose() << std::endl; + return true; + }); + str.set_vertex_texcoord(*v1, *m, vertex_tc); + str.chekered_texture(); } return app.launch(); diff --git a/cgogn/rendering/shaders/shader_flat_texture.cpp b/cgogn/rendering/shaders/shader_flat_texture.cpp new file mode 100644 index 000000000..6643d3b00 --- /dev/null +++ b/cgogn/rendering/shaders/shader_flat_texture.cpp @@ -0,0 +1,91 @@ +/******************************************************************************* + * CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * + * Copyright (C), IGG Group, ICube, University of Strasbourg, France * + * * + * This library is free software; you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as published by the * + * Free Software Foundation; either version 2.1 of the License, or (at your * + * option) any later version. * + * * + * This library is distributed in the hope that it will be useful, but WITHOUT * + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * + * for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with this library; if not, write to the Free Software Foundation, * + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * * + * Web site: http://cgogn.unistra.fr/ * + * Contact information: cgogn@unistra.fr * + * * + *******************************************************************************/ + +#define CGOGN_RENDER_SHADERS_FLAT_CPP_ + +#include + +#include + +namespace cgogn +{ + +namespace rendering +{ + +ShaderFlatTexture* ShaderFlatTexture::instance_ = nullptr; + +ShaderFlatTexture::ShaderFlatTexture() +{ + const char* vertex_shader_source = R"( + #version 330 + uniform mat4 projection_matrix; + uniform mat4 model_view_matrix; + + in vec3 vertex_position; + in vec2 vertex_tc; + + out vec3 position; + out vec2 tc; + void main() + { + vec4 position4 = model_view_matrix * vec4(vertex_position, 1.0); + position = position4.xyz; + tc = vertex_tc; + gl_Position = projection_matrix * position4; + } + )"; + + const char* fragment_shader_source = R"( + #version 330 + + uniform sampler2D texture_img_unit; + uniform vec3 light_position; + uniform bool draw_param; + + in vec3 position; + in vec2 tc; + + out vec3 frag_out; + + void main() + { + vec3 N = normalize(cross(dFdx(position), dFdy(position))); + vec3 L = normalize(light_position - position); + float lambert = 0.25 + 0.75 * max(0.0,dot(N, L)); + frag_out = (draw_param) ? vec3(tc,0) : texture(texture_img_unit,vec2(tc.x,1.0-tc.y)).rgb*lambert; + } + )"; + + load2_bind(vertex_shader_source, fragment_shader_source, "vertex_position", "vertex_tc"); + get_uniforms("texture_img_unit","light_position", "draw_param"); +} + +void ShaderParamFlatTexture::set_uniforms() +{ + shader_->set_uniforms_values(texture_->bind(0), light_position_, draw_param_); +} + +} // namespace rendering + +} // namespace cgogn diff --git a/cgogn/rendering/shaders/shader_flat_texture.h b/cgogn/rendering/shaders/shader_flat_texture.h new file mode 100644 index 000000000..178824147 --- /dev/null +++ b/cgogn/rendering/shaders/shader_flat_texture.h @@ -0,0 +1,64 @@ +/******************************************************************************* + * CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * + * Copyright (C), IGG Group, ICube, University of Strasbourg, France * + * * + * This library is free software; you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as published by the * + * Free Software Foundation; either version 2.1 of the License, or (at your * + * option) any later version. * + * * + * This library is distributed in the hope that it will be useful, but WITHOUT * + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * + * for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with this library; if not, write to the Free Software Foundation, * + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * * + * Web site: http://cgogn.unistra.fr/ * + * Contact information: cgogn@unistra.fr * + * * + *******************************************************************************/ + +#ifndef CGOGN_RENDERING_SHADERS_FLAT_TEXTURE_H_ +#define CGOGN_RENDERING_SHADERS_FLAT_TEXTURE_H_ + +#include +#include +#include +namespace cgogn +{ + +namespace rendering +{ +DECLARE_SHADER_CLASS(FlatTexture, false, CGOGN_STR(FlatTexture)) + +class CGOGN_RENDERING_EXPORT ShaderParamFlatTexture : public ShaderParam +{ + void set_uniforms() override; + + enum VBOName : uint32 + { + VERTEX_POSITION = 0, + VERTEX_TC + }; + +public: + GLVec3 light_position_; + std::shared_ptr texture_; + bool draw_param_; + + using ShaderType = ShaderFlatTexture; + + ShaderParamFlatTexture(ShaderType* sh) + : ShaderParam(sh), light_position_(1000, 10000, 100000), texture_(nullptr), draw_param_(false) + { + } +}; + +} // namespace rendering + +} // namespace cgogn + +#endif // CGOGN_RENDERING_SHADERS_FLAT_TEXTURE_H__ diff --git a/cgogn/rendering/shaders/shader_obj_flat_texture.cpp b/cgogn/rendering/shaders/shader_obj_flat_texture.cpp index 2be07d15b..06c4fd2bb 100644 --- a/cgogn/rendering/shaders/shader_obj_flat_texture.cpp +++ b/cgogn/rendering/shaders/shader_obj_flat_texture.cpp @@ -41,7 +41,6 @@ ShaderObjFlatTexture::ShaderObjFlatTexture() #version 330 uniform mat4 projection_matrix; uniform mat4 model_view_matrix; - uniform mat3 normal_matrix; uniform usamplerBuffer position_ind; uniform usamplerBuffer tex_coord_ind; diff --git a/cgogn/rendering/ui_modules/surface_tex_render.h b/cgogn/rendering/ui_modules/surface_tex_render.h new file mode 100644 index 000000000..a979d029f --- /dev/null +++ b/cgogn/rendering/ui_modules/surface_tex_render.h @@ -0,0 +1,271 @@ +/******************************************************************************* + * CGoGN * + * Copyright (C), IGG Group, ICube, University of Strasbourg, France * + * * + * This library is free software; you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as published by the * + * Free Software Foundation; either version 2.1 of the License, or (at your * + * option) any later version. * + * * + * This library is distributed in the hope that it will be useful, but WITHOUT * + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * + * for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with this library; if not, write to the Free Software Foundation, * + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * * + * Web site: http://cgogn.unistra.fr/ * + * Contact information: cgogn@unistra.fr * + * * + *******************************************************************************/ + +#ifndef CGOGN_MODULE_SURFACE_TEX_RENDER_H_ +#define CGOGN_MODULE_SURFACE_TEX_RENDER_H_ + +#include +#include +#include +#include +#include +#include + + +#include +#include + +#include + +#include +#include + +namespace cgogn +{ + +namespace ui +{ + +using geometry::Scalar; +using geometry::Vec3; +using geometry::Vec2; + +template +class SurfaceTexRender : public ViewModule +{ + static_assert(mesh_traits::dimension >= 2, "SurfaceRender can only be used with meshes of dimension >= 2"); + + + template + using Attribute = typename mesh_traits::template Attribute; + + using Vertex = typename mesh_traits::Vertex; + using Edge = typename mesh_traits::Edge; + using Face = typename mesh_traits::Face; + + struct Parameters + { + Parameters() + : vertex_position_(nullptr), vertex_position_vbo_(nullptr), vertex_tc_(nullptr), vertex_tc_vbo_(nullptr), + render_texture_(true) + { + param_textured_ = rendering::ShaderFlatTexture::generate_param(); + + //param_textured_->draw_param_ = true; + } + + CGOGN_NOT_COPYABLE_NOR_MOVABLE(Parameters); + + std::unique_ptr param_textured_; + + std::shared_ptr> vertex_position_; + rendering::VBO* vertex_position_vbo_; + + std::shared_ptr> vertex_tc_; + rendering::VBO* vertex_tc_vbo_; + bool render_texture_; + + }; + +public: + SurfaceTexRender(const App& app) + : ViewModule(app, "SurfaceTextureRender (" + std::string{mesh_traits::name} + ")"), + selected_view_(app.current_view()), selected_mesh_(nullptr) + { + } + + ~SurfaceTexRender() + { + } + +private: + + + void init_mesh(MESH* m) + { + for (View* v : linked_views_) + { + parameters_[v][m]; + std::shared_ptr> vertex_position = cgogn::get_attribute(*m, "position"); + if (vertex_position) + set_vertex_position(*v, *m, vertex_position); + std::shared_ptr> vertex_tc = cgogn::get_attribute(*m, "tex_coord"); + if (vertex_tc) + set_vertex_texcoord(*v, *m, vertex_tc); + } + } + + + +public: + void load_texture(const std::string& img_name) + { + rendering::GLImage img(img_name); + tex_->load(img); + } + + void load_texture(const rendering::GLImage& img) + { + tex_->load(img); + } + + void chekered_texture() + { + cgogn::rendering::GLImage img(16, 16, 3); + std::vector> pix; + pix.reserve(16*16); + for (int i = 0; i < 16; ++i) + for (int j = 0; j < 16; ++j) + if ((i + j) % 2 == 0) + pix.push_back({0u, 0u, 0u}); + else + pix.push_back({255u, 255u, 255u}); + img.copy_pixels_data(pix.data()->data()); + load_texture(img); + } + + void set_vertex_position(View& v, const MESH& m, const std::shared_ptr>& vertex_position) + { + Parameters& p = parameters_[&v][&m]; + if (p.vertex_position_ == vertex_position) + return; + + MeshData& md = mesh_provider_->mesh_data(m); + + p.vertex_position_ = vertex_position; + if (p.vertex_position_) + p.vertex_position_vbo_ = md.update_vbo(p.vertex_position_.get(), true); + else + p.vertex_position_vbo_ = nullptr; + + p.param_textured_->set_vbos({p.vertex_position_vbo_, p.vertex_tc_vbo_}); + v.request_update(); + } + + + void set_vertex_texcoord(View& v, const MESH& m, const std::shared_ptr>& vertex_tc) + { + Parameters& p = parameters_[&v][&m]; + if (p.vertex_tc_ == vertex_tc) + return; + + MeshData& md = mesh_provider_->mesh_data(m); + + p.vertex_tc_ = vertex_tc; + if (p.vertex_tc_) + p.vertex_tc_vbo_ = md.update_vbo(p.vertex_tc_.get(), true); + else + p.vertex_tc_vbo_ = nullptr; + + p.param_textured_->set_vbos({p.vertex_position_vbo_, p.vertex_tc_vbo_}); + v.request_update(); + } + + void init() override + { + mesh_provider_ = static_cast*>( + app_.module("MeshProvider (" + std::string{mesh_traits::name} + ")")); + mesh_provider_->foreach_mesh([this](MESH& m, const std::string&) { init_mesh(&m); }); + connections_.push_back(boost::synapse::connect::mesh_added>( + mesh_provider_, this, &SurfaceTexRender::init_mesh)); + tex_ = std::make_shared( + std::vector>{ + {GL_TEXTURE_MIN_FILTER, GL_LINEAR}, {GL_TEXTURE_MAG_FILTER, GL_NEAREST}, {GL_TEXTURE_WRAP_S, GL_REPEAT}, + {GL_TEXTURE_WRAP_T, GL_REPEAT}}); + } + + + void draw(View* view) override + { + for (auto& [m, pp] : parameters_[view]) + { + Parameters& p = pp; + if (p.render_texture_) + { + MeshData& md = mesh_provider_->mesh_data(*m); + + const rendering::GLMat4& proj_matrix = view->projection_matrix(); + const rendering::GLMat4& view_matrix = view->modelview_matrix(); + if (p.param_textured_->attributes_initialized()) + { + p.param_textured_->texture_ = tex_; + p.param_textured_->bind(proj_matrix, view_matrix); + md.draw(rendering::TRIANGLES, p.vertex_position_); + p.param_textured_->release(); + + } + } + } + } + + + + void left_panel() override + { + bool need_update = false; + + if (app_.nb_views() > 1) + imgui_view_selector(this, selected_view_, [&](View* v) { selected_view_ = v; }); + + imgui_mesh_selector(mesh_provider_, selected_mesh_, "Surface", [&](MESH& m) { + selected_mesh_ = &m; +// mesh_provider_->mesh_data(m).outlined_until_ = App::frame_time_ + 1.0; + }); + + if (selected_view_ && selected_mesh_) + { + Parameters& p = parameters_[selected_view_][selected_mesh_]; + + imgui_combo_attribute(*selected_mesh_, p.vertex_position_, "Position", + [&](const std::shared_ptr>& attribute) { + set_vertex_position(*selected_view_, *selected_mesh_, attribute); + }); + ImGui::Separator(); + imgui_combo_attribute(*selected_mesh_, p.vertex_tc_, "TexCoord", + [&](const std::shared_ptr>& attribute) { + set_vertex_texcoord(*selected_view_, *selected_mesh_, attribute); + }); + + need_update |= ImGui::Checkbox("Render texture", &p.render_texture_); + } + + if (need_update) + for (View* v : linked_views_) + v->request_update(); + } + +private: + View* selected_view_; + const MESH* selected_mesh_; + std::unordered_map> parameters_; + std::vector> connections_; + std::unordered_map>> mesh_connections_; + MeshProvider* mesh_provider_; + std::shared_ptr tex_; +}; + +} // namespace ui + +} // namespace cgogn + +#endif // CGOGN_MODULE_SURFACE_RENDER_H_