You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
363 lines
11 KiB
363 lines
11 KiB
|
|
|
|
#include <GL/glew.h> |
|
#include <GLFW/glfw3.h> |
|
#include "imgui.h" |
|
#include "imgui_impl_glfw.h" |
|
#include "imgui_impl_opengl2.h" |
|
#include <stdio.h> |
|
#include "FileBrowser/ImGuiFileBrowser.h" |
|
#include "triangle_mesh_type.h" |
|
#include <wrap/gui/trackball.h> |
|
#include <wrap/gl/trimesh.h> |
|
|
|
// Interface variables |
|
GLFWwindow* window; |
|
vcg::GlTrimesh<MyTriMesh> glWrap; |
|
vcg::Trackball trackball; |
|
imgui_addons::ImGuiFileBrowser file_dialog; |
|
std::ostringstream oss; // String stream used for the log |
|
|
|
// Interface options |
|
ImVec4 clear_color = ImVec4(0.33f, 0.33f, 0.33f, 1.00f); |
|
ImVec4 mesh_color = ImVec4(0.79f, 0.9f, 0.87f, 1.00f); |
|
float line_thick=1.f; |
|
int selected_rend_mode = 5; |
|
bool showMesh=true; |
|
bool showTrackBall=true; |
|
vcg::GLW::DrawMode DMode=vcg::GLW::DMSmooth; |
|
std::string PathMesh="../../meshes/fertility_tri.off"; |
|
|
|
// Mesh data |
|
MyTriMesh mesh; |
|
|
|
void LoadMesh(std::string path) |
|
{ |
|
oss<<"Loading "<<path.c_str()<<std::endl; |
|
int ret = vcg::tri::io::Importer<MyTriMesh>::Open(mesh,path.c_str()); |
|
vcg::tri::UpdateBounding<MyTriMesh>::Box(mesh); |
|
vcg::tri::UpdateNormal<MyTriMesh>::PerVertexNormalizedPerFaceNormalized(mesh); |
|
|
|
|
|
if (ret==0) |
|
oss<<"Loaded "<<mesh.fn<<" faces "<<mesh.vn<<" vertices"<<std::endl; |
|
else |
|
oss<<"Mesh not loaded"<<std::endl; |
|
} |
|
|
|
static void glfw_error_callback(int error, const char* description) |
|
{ |
|
fprintf(stderr, "Glfw Error %d: %s\n", error, description); |
|
} |
|
|
|
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos) |
|
{ |
|
if(ImGui::GetIO().WantCaptureMouse) return; |
|
|
|
int display_w, display_h; |
|
glfwGetFramebufferSize(window, &display_w, &display_h); |
|
float xscale, yscale; |
|
glfwGetWindowContentScale(window, &xscale, &yscale); |
|
xpos*=xscale; |
|
ypos*=yscale; |
|
ypos=(display_h)-ypos; |
|
trackball.MouseMove((int)xpos,(int)ypos); |
|
} |
|
|
|
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) |
|
{ |
|
if(ImGui::GetIO().WantCaptureMouse) return; |
|
|
|
int display_w, display_h; |
|
glfwGetFramebufferSize(window, &display_w, &display_h); |
|
float xscale, yscale; |
|
glfwGetWindowContentScale(window, &xscale, &yscale); |
|
double xpos, ypos; |
|
glfwGetCursorPos(window, &xpos, &ypos); |
|
xpos*=xscale; |
|
ypos*=yscale; |
|
ypos=(display_h)-ypos; |
|
|
|
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) |
|
trackball.MouseDown((int)xpos,(int)ypos,vcg::Trackball::BUTTON_LEFT); |
|
|
|
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) |
|
trackball.MouseUp((int)xpos,(int)ypos,vcg::Trackball::BUTTON_LEFT); |
|
|
|
} |
|
|
|
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) |
|
{ |
|
trackball.MouseWheel(yoffset/4); |
|
} |
|
|
|
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) |
|
{ |
|
if (key == GLFW_KEY_LEFT_SHIFT && action == GLFW_PRESS) |
|
trackball.ButtonDown(vcg::Trackball::KEY_SHIFT); |
|
if (key == GLFW_KEY_LEFT_SHIFT && action == GLFW_RELEASE) |
|
trackball.ButtonUp(vcg::Trackball::KEY_SHIFT); |
|
|
|
if (key == GLFW_KEY_LEFT_CONTROL && action == GLFW_PRESS) |
|
trackball.ButtonDown(vcg::Trackball::KEY_CTRL); |
|
if (key == GLFW_KEY_LEFT_CONTROL && action == GLFW_RELEASE) |
|
trackball.ButtonUp(vcg::Trackball::KEY_CTRL); |
|
|
|
if (key == GLFW_KEY_LEFT_ALT && action == GLFW_PRESS) |
|
trackball.ButtonDown(vcg::Trackball::KEY_ALT); |
|
if (key == GLFW_KEY_LEFT_ALT && action == GLFW_RELEASE) |
|
trackball.ButtonUp(vcg::Trackball::KEY_ALT); |
|
} |
|
|
|
// Now inside any function |
|
void showMainMenu() |
|
{ |
|
bool open = false, save = false; |
|
if(ImGui::BeginMainMenuBar()) |
|
{ |
|
if (ImGui::BeginMenu("File")) |
|
{ |
|
if (ImGui::MenuItem("Open", NULL)) |
|
open = true; |
|
if (ImGui::MenuItem("Quit", NULL)) |
|
exit(0); |
|
|
|
ImGui::EndMenu(); |
|
} |
|
ImGui::EndMainMenuBar(); |
|
} |
|
|
|
//Remember the name to ImGui::OpenPopup() and showFileDialog() must be same... |
|
if(open) |
|
ImGui::OpenPopup("Open File"); |
|
|
|
if(file_dialog.showFileDialog("Open File", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(700, 310), ".obj,.ply,.off")) |
|
{ |
|
LoadMesh(file_dialog.selected_path); |
|
PathMesh= file_dialog.selected_path; |
|
} |
|
} |
|
|
|
void InitGLFW_Window() |
|
{ |
|
if (!glfwInit()) |
|
{ |
|
std::cout<<"Error Initializing GLFW"<<std::endl; |
|
exit(0); |
|
} |
|
|
|
window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL2 example", NULL, NULL); |
|
if (window == NULL) |
|
{ |
|
std::cout<<"Error Initializing GLFW Window"<<std::endl; |
|
exit(0); |
|
} |
|
|
|
glfwMakeContextCurrent(window); |
|
glfwSwapInterval(1); // Enable vsync |
|
|
|
// Setup window |
|
glfwSetErrorCallback(glfw_error_callback); |
|
glfwSetCursorPosCallback(window, cursor_position_callback); |
|
glfwSetMouseButtonCallback(window, mouse_button_callback); |
|
glfwSetScrollCallback(window, scroll_callback); |
|
glfwSetKeyCallback(window, key_callback); |
|
} |
|
|
|
void InitIMGui() |
|
{ |
|
// Setup Dear ImGui context |
|
IMGUI_CHECKVERSION(); |
|
ImGui::CreateContext(); |
|
ImGuiIO& io = ImGui::GetIO(); (void)io; |
|
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls |
|
|
|
// Setup Dear ImGui style |
|
// ImGui::StyleColorsClassic(); |
|
ImGui::StyleColorsDark(); |
|
|
|
// Setup Platform/Renderer backends |
|
ImGui_ImplGlfw_InitForOpenGL(window, true); |
|
ImGui_ImplOpenGL2_Init(); |
|
} |
|
|
|
void SetRenderBar() |
|
{ |
|
ImGui::Begin("Simple VCG Mesh Visualizer",NULL,ImGuiWindowFlags_AlwaysAutoResize); // Create a window called "Hello, world!" and append into it. |
|
|
|
ImGui::Checkbox("Show Mesh", &showMesh); |
|
ImGui::SameLine(); |
|
ImGui::Checkbox("Show TBall", &showTrackBall); |
|
|
|
ImGui::ColorEdit3("mesh color", (float*)&mesh_color); // Edit 3 floats representing a color |
|
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color |
|
const char* items[] = { "Box", "Points", "DMWire", |
|
"Hidden", "Flat", "Smooth", |
|
"FlatWire","Radar" |
|
}; |
|
|
|
if (ImGui::BeginCombo("Rendering", items[selected_rend_mode])) |
|
{ |
|
for (int i = 0; i < IM_ARRAYSIZE(items); i++) |
|
{ |
|
bool is_selected = (selected_rend_mode == i); |
|
if (ImGui::Selectable(items[i], is_selected)) |
|
{ |
|
selected_rend_mode = i; |
|
|
|
switch(selected_rend_mode) |
|
{ |
|
case 0 : DMode=vcg::GLW::DMBox; break; |
|
case 1 : DMode=vcg::GLW::DMPoints; break; |
|
case 2 : DMode=vcg::GLW::DMWire; break; |
|
case 3 : DMode=vcg::GLW::DMHidden; break; |
|
case 4 : DMode=vcg::GLW::DMFlat; break; |
|
case 5 : DMode=vcg::GLW::DMSmooth; break; |
|
case 6 : DMode=vcg::GLW::DMFlatWire; break; |
|
default : DMode=vcg::GLW::DMFlatWire; |
|
} |
|
} |
|
if (is_selected) |
|
{ |
|
ImGui::SetItemDefaultFocus(); |
|
} |
|
} |
|
ImGui::EndCombo(); |
|
} |
|
ImGui::SliderFloat("thickness", &line_thick, 0.5f, 20.0f); |
|
|
|
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); |
|
ImGui::End(); |
|
} |
|
|
|
void SetLogWindow() |
|
{ |
|
ImGui::Begin("Log",NULL,ImGuiWindowFlags_AlwaysAutoResize); |
|
std::string LogPrint= oss.str(); |
|
ImGui::Text("%s",LogPrint.c_str()); |
|
ImGui::End(); |
|
} |
|
|
|
void SetUserBar() |
|
{ |
|
ImGui::Begin("User",NULL,ImGuiWindowFlags_AlwaysAutoResize); |
|
if(ImGui::Button("Reload Mesh")) |
|
{ |
|
LoadMesh(PathMesh); |
|
oss<<"Reloaded mesh"; |
|
} |
|
|
|
if(ImGui::Button("Smooth Mesh")) |
|
{ |
|
vcg::tri::Smooth<MyTriMesh>::VertexCoordLaplacian(mesh, 1, false); |
|
vcg::tri::UpdateNormal<MyTriMesh>::PerVertexNormalizedPerFaceNormalized(mesh); |
|
oss<<"Smoothed mesh"; |
|
} |
|
|
|
ImGui::End(); |
|
} |
|
|
|
|
|
void GLDrawMesh() |
|
{ |
|
int display_w, display_h; |
|
glfwGetFramebufferSize(window, &display_w, &display_h); |
|
glViewport(0, 0, display_w, display_h); |
|
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); |
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
|
|
|
glEnable(GL_LIGHTING); |
|
glEnable(GL_LIGHT0); |
|
|
|
glEnable(GL_NORMALIZE); |
|
glEnable(GL_COLOR_MATERIAL); |
|
glEnable(GL_CULL_FACE); |
|
glEnable(GL_DEPTH_TEST); |
|
|
|
glMatrixMode(GL_PROJECTION); |
|
glLoadIdentity(); |
|
|
|
gluPerspective(40, (GLdouble)display_w/(GLdouble)display_h, 0.1, 100); |
|
glMatrixMode(GL_MODELVIEW); |
|
glLoadIdentity(); |
|
gluLookAt(0,0,4.f, 0,0,0, 0,1,0); |
|
|
|
trackball.GetView(); |
|
trackball.Apply(); |
|
glDisable(GL_CULL_FACE); |
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); |
|
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); |
|
|
|
// save modelview matrix |
|
glPushMatrix(); |
|
vcg::glScale(2.0f/mesh.bbox.Diag()); |
|
vcg::glTranslate(-mesh.bbox.Center()); |
|
if (showMesh) |
|
{ |
|
glColor4f(mesh_color.x * mesh_color.w, mesh_color.y * mesh_color.w, mesh_color.z * mesh_color.w, mesh_color.w); |
|
glPushAttrib(GL_ALL_ATTRIB_BITS); |
|
glLineWidth(line_thick); |
|
glWrap.SetHintParamf(vcg::GLW::HNPPointSize,line_thick); |
|
glWrap.Draw(DMode,vcg::GLW::CMNone,vcg::GLW::TMNone); |
|
glPopAttrib(); |
|
} |
|
glPopMatrix(); |
|
if (showTrackBall) trackball.DrawPostApply(); |
|
} |
|
|
|
|
|
|
|
int main(int, char**) |
|
{ |
|
LoadMesh(PathMesh); |
|
|
|
glWrap.m=&mesh; |
|
|
|
InitGLFW_Window(); |
|
|
|
InitIMGui(); |
|
glewInit(); |
|
|
|
// Main loop |
|
while (!glfwWindowShouldClose(window)) |
|
{ |
|
// Poll and handle events (inputs, window resize, etc.) |
|
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. |
|
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. |
|
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. |
|
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. |
|
glfwPollEvents(); |
|
|
|
// Start the Dear ImGui frame |
|
ImGui_ImplOpenGL2_NewFrame(); |
|
ImGui_ImplGlfw_NewFrame(); |
|
ImGui::NewFrame(); |
|
{ |
|
SetRenderBar(); |
|
SetLogWindow(); |
|
SetUserBar(); |
|
showMainMenu(); |
|
} |
|
// Rendering |
|
ImGui::Render(); |
|
|
|
GLDrawMesh(); |
|
|
|
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!), |
|
// you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below. |
|
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); |
|
|
|
glfwMakeContextCurrent(window); |
|
glfwSwapBuffers(window); |
|
} |
|
|
|
// Cleanup |
|
ImGui_ImplOpenGL2_Shutdown(); |
|
ImGui_ImplGlfw_Shutdown(); |
|
ImGui::DestroyContext(); |
|
|
|
glfwDestroyWindow(window); |
|
glfwTerminate(); |
|
|
|
return 0; |
|
} |