diff --git a/examples/components/example.cpp b/examples/components/example.cpp new file mode 100644 index 000000000..6e28b5fec --- /dev/null +++ b/examples/components/example.cpp @@ -0,0 +1,1095 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#ifndef GLUT_WHEEL_UP +#define GLUT_WHEEL_UP 3 +#endif +#ifndef GLUT_WHEEL_DOWN +#define GLUT_WHEEL_DOWN 4 +#endif +#ifndef GLUT_WHEEL_RIGHT +#define GLUT_WHEEL_RIGHT 5 +#endif +#ifndef GLUT_WHEEL_LEFT +#define GLUT_WHEEL_LEFT 6 +#endif +#ifndef GLUT_ACTIVE_COMMAND +#define GLUT_ACTIVE_COMMAND 8 +#endif + +#include +#include +#include +#include +#include + +int cc_hover = -1; + +Eigen::MatrixXd V; +Eigen::VectorXd Vmid,Vmin,Vmax; +double bbd = 1.0; +Eigen::MatrixXi F; +Eigen::VectorXi CC; +Eigen::MatrixXd N; +struct State +{ + igl::Camera camera; + Eigen::VectorXf I; + Eigen::Matrix selected; + GLuint mask_id; +} s; +std::string out_filename; + +GLuint pick_tex = 0; +GLuint pick_fbo = 0; +GLuint pick_dfbo = 0; + +// See README for descriptions +enum RotationType +{ + ROTATION_TYPE_IGL_TRACKBALL = 0, + ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP = 1, + NUM_ROTATION_TYPES = 2, +} rotation_type; + +enum CenterType +{ + CENTER_TYPE_ORBIT = 0, + CENTER_TYPE_FPS = 1, + NUM_CENTER_TYPES = 2, +} center_type = CENTER_TYPE_ORBIT; + + +std::stack undo_stack; +std::stack redo_stack; + +bool wireframe_visible = false; +bool fill_visible = true; + +bool is_rotating = false; +int down_x,down_y; +igl::Camera down_camera; + +bool is_animating = false; +double animation_start_time = 0; +double ANIMATION_DURATION = 0.5; +Eigen::Quaterniond animation_from_quat; +Eigen::Quaterniond animation_to_quat; + +int width,height; +Eigen::Vector4f light_pos(-0.1,-0.1,0.9,0); + +#define REBAR_NAME "temp.rbr" +igl::ReTwBar rebar; + +// Forward +void init_components(); +void init_relative(); + +void push_undo() +{ + undo_stack.push(s); + // Clear + redo_stack = std::stack(); +} + +void TW_CALL set_rotation_type(const void * value, void * clientData) +{ + using namespace Eigen; + using namespace std; + using namespace igl; + const RotationType old_rotation_type = rotation_type; + rotation_type = *(const RotationType *)(value); + if(rotation_type == ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP && + old_rotation_type != ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP) + { + animation_from_quat = s.camera.m_rotation_conj; + snap_to_fixed_up(animation_from_quat,animation_to_quat); + // start animation + animation_start_time = get_seconds(); + is_animating = true; + } +} +void TW_CALL get_rotation_type(void * value, void *clientData) +{ + RotationType * rt = (RotationType *)(value); + *rt = rotation_type; +} + +void reshape(int width, int height) +{ + ::width = width; + ::height = height; + glViewport(0,0,width,height); + // Send the new window size to AntTweakBar + TwWindowSize(width, height); + s.camera.m_aspect = (double)width/(double)height; + igl::init_render_to_texture(width,height, pick_tex, pick_fbo, pick_dfbo); + igl::report_gl_error("init_render_to_texture: "); + glutPostRedisplay(); +} + +void push_scene() +{ + using namespace igl; + using namespace std; + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + auto & camera = s.camera; + glMultMatrixd(camera.projection().data()); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + gluLookAt( + camera.eye()(0), camera.eye()(1), camera.eye()(2), + camera.at()(0), camera.at()(1), camera.at()(2), + camera.up()(0), camera.up()(1), camera.up()(2)); + glScaled(2./bbd,2./bbd,2./bbd); + glTranslated(-Vmid(0),-Vmid(1),-Vmid(2)); +} + +void pop_scene() +{ + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + +void draw_mesh( + const Eigen::MatrixXd & V, + const Eigen::MatrixXi & F, + const Eigen::MatrixXd & N, + const Eigen::VectorXf & S, + const GLuint & S_loc) +{ + using namespace Eigen; + using namespace std; + static Matrix VR,NR; + static Matrix FR; + static Matrix SR; + static GLuint ibo,vbo,sbo,nbo; + static bool scene_dirty = true; + if(scene_dirty) + { + VR.resize(F.rows()*3,3); + NR.resize(F.rows()*3,3); + SR.resize(F.rows()*3,1); + FR.resize(F.rows(),3); + for(int f = 0;f(); + SR(3*f+c) = S(F(f,c)); + NR.row(3*f+c) = N.row(f).cast(); + FR(f,c) = 3*f+c; + } + } + + glGenBuffers(1,&ibo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLuint)*FR.size(),FR.data(),GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); + glGenBuffers(1,&vbo); + glGenBuffers(1,&nbo); + glGenBuffers(1,&sbo); + + glBindBuffer(GL_ARRAY_BUFFER,vbo); + glBufferData(GL_ARRAY_BUFFER,sizeof(float)*VR.size(),VR.data(),GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER,nbo); + glBufferData(GL_ARRAY_BUFFER,sizeof(float)*NR.size(),NR.data(),GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER,sbo); + glBufferData(GL_ARRAY_BUFFER,sizeof(float)*SR.size(),SR.data(),GL_STATIC_DRAW); + igl::report_gl_error("glBindBuffer: "); + + scene_dirty = false; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glBindBuffer(GL_ARRAY_BUFFER,vbo); + glVertexPointer(3,GL_FLOAT,0,0); + glEnableClientState(GL_NORMAL_ARRAY); + glBindBuffer(GL_ARRAY_BUFFER,nbo); + glNormalPointer(GL_FLOAT,0,0); + + glBindBuffer(GL_ARRAY_BUFFER,sbo); + glVertexAttribPointer(S_loc, 1, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(S_loc); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo); + glDrawElements(GL_TRIANGLES,FR.size(),GL_UNSIGNED_INT,0); + glBindBuffer(GL_ARRAY_BUFFER,0); +} + +// Set up double-sided lights +void lights() +{ + using namespace std; + using namespace Eigen; + glEnable(GL_LIGHTING); + glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); + glEnable(GL_LIGHT0); + float WHITE[4] = {1,1,1,1.}; + float BLACK[4] = {0.,0.,0.,1.}; + Vector4f pos = light_pos; + glLightfv(GL_LIGHT0,GL_AMBIENT,BLACK); + glLightfv(GL_LIGHT0,GL_DIFFUSE,WHITE); + glLightfv(GL_LIGHT0,GL_SPECULAR,BLACK); + glLightfv(GL_LIGHT0,GL_POSITION,pos.data()); + //glEnable(GL_LIGHT1); + //pos(0) *= -1; + //pos(1) *= -1; + //pos(2) *= -1; + //glLightfv(GL_LIGHT1,GL_AMBIENT,BLACK); + //glLightfv(GL_LIGHT1,GL_DIFFUSE,NEAR_BLACK); + //glLightfv(GL_LIGHT1,GL_SPECULAR,BLACK); + //glLightfv(GL_LIGHT1,GL_POSITION,pos.data()); +} + +template +GLuint generate_1d_texture( + const Eigen::Matrix & colors) +{ + assert(colors.cols() == 3 && "Seems colors.cols() must be 3"); + GLuint tex_id = 0; + glGenTextures(1,&tex_id); + glBindTexture(GL_TEXTURE_1D,tex_id); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage1D(GL_TEXTURE_1D, 0, colors.cols(),colors.rows(), + 0,GL_RGB, GL_UNSIGNED_BYTE, + colors.data()); + igl::report_gl_error("glTexImage1D: "); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER,GL_NEAREST); + igl::report_gl_error("texture: "); + return tex_id; +} + +GLuint color_shader(const size_t max_ids, GLuint & scalar_loc, GLuint & tex_id) +{ + std::string vertex_shader = R"( +#version 120 +attribute float scalar_in; +varying float scalar_out; +void main() +{ + scalar_out = scalar_in; + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; +} +)"; + std::string fragment_shader = R"( +#version 120 +varying float scalar_out; +uniform float cmin; +uniform float cmax; +uniform sampler1D color_map; +void main() +{ + float scalar_normalized = max(min((scalar_out-cmin)/(cmax-cmin),1.0),0.0); + gl_FragColor = texture1D(color_map,scalar_normalized); +} +)"; + Eigen::Matrix colors(max_ids,3); + for(size_t id = 0;id 1) + { + t = 1; + is_animating = false; + } + Quaterniond q = animation_from_quat.slerp(t,animation_to_quat).normalized(); + auto & camera = s.camera; + switch(center_type) + { + default: + case CENTER_TYPE_ORBIT: + camera.orbit(q.conjugate()); + break; + case CENTER_TYPE_FPS: + camera.turn_eye(q.conjugate()); + break; + } + } + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + lights(); + push_scene(); + + + const auto & color_components_shader = []( + const GLuint scalar_loc, + GLuint & tex_id)->GLuint + { + std::string vertex_shader = R"( +#version 120 +attribute float scalar_in; +varying vec3 normal; +varying float scalar_out; +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + normal = normalize(gl_NormalMatrix * gl_Normal); + scalar_out = scalar_in; +} +)"; + std::string fragment_shader = R"( +#version 120 +varying vec3 normal; +varying float scalar_out; +uniform float cmin; +uniform float cmax; +uniform float cc_hover; +uniform sampler1D color_map; +uniform sampler1D selected_mask; +void main() +{ + float scalar_normalized = max(min((scalar_out-cmin)/(cmax-cmin),1.0),0.0); + vec4 texture_color = texture1D(color_map,scalar_normalized); + bool is_selected = texture1D(selected_mask,scalar_normalized).x > 0.5; + const vec4 selected_color = vec4(1,0.2,0.2,1); + if(scalar_out==cc_hover) + { + texture_color = 0.5*(texture_color + selected_color); + } + if(is_selected) + { + texture_color = selected_color; + } + const float num_lights = 1.0; + vec4 diffuse = (1.0/num_lights)*(gl_LightSource[0].diffuse); + vec4 ambient = vec4(0,0,0,0); + ambient += (1.0/num_lights)*(gl_FrontMaterial.ambient * gl_LightSource[0].ambient); + ambient += (1.0/num_lights)*(gl_LightModel.ambient * gl_FrontMaterial.ambient); + vec4 color = ambient; + // Phong + vec3 lightDir = normalize(vec3(gl_LightSource[0].position)); + vec3 halfVector = gl_LightSource[0].halfVector.xyz; + vec3 n = normalize(normal); + float NdotL = max(abs(dot(n.xyz,lightDir)), 0.0); + vec4 specular = vec4(0.0,0.0,0.0,0.0); + if (NdotL > 0.0) { + color += diffuse * NdotL; + vec3 halfV = normalize(halfVector); + float NdotHV = max(abs(dot(n,halfV)),0.0); + specular += gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(NdotHV, gl_FrontMaterial.shininess); + } + gl_FragColor = color * texture_color + specular; +} + +)"; + + typedef Matrix Matrix64_3_R_ubyte; + typedef Matrix Matrix64_3_R_float; + Matrix64_3_R_ubyte colors; + { + Matrix64_3_R_float rgb = (Matrix64_3_R_ubyte()<< + 255, 0, 0, + 255, 24, 0, + 255, 48, 0, + 255, 72, 0, + 255, 96, 0, + 255, 120, 0, + 255, 143, 0, + 255, 167, 0, + 255, 191, 0, + 255, 215, 0, + 255, 239, 0, + 247, 255, 0, + 223, 255, 0, + 199, 255, 0, + 175, 255, 0, + 151, 255, 0, + 128, 255, 0, + 104, 255, 0, + 80, 255, 0, + 56, 255, 0, + 32, 255, 0, + 8, 255, 0, + 0, 255, 16, + 0, 255, 40, + 0, 255, 64, + 0, 255, 88, + 0, 255, 112, + 0, 255, 135, + 0, 255, 159, + 0, 255, 183, + 0, 255, 207, + 0, 255, 231, + 0, 255, 255, + 0, 231, 255, + 0, 207, 255, + 0, 183, 255, + 0, 159, 255, + 0, 135, 255, + 0, 112, 255, + 0, 88, 255, + 0, 64, 255, + 0, 40, 255, + 0, 16, 255, + 8, 0, 255, + 32, 0, 255, + 56, 0, 255, + 80, 0, 255, + 104, 0, 255, + 128, 0, 255, + 151, 0, 255, + 175, 0, 255, + 199, 0, 255, + 223, 0, 255, + 247, 0, 255, + 255, 0, 239, + 255, 0, 215, + 255, 0, 191, + 255, 0, 167, + 255, 0, 143, + 255, 0, 120, + 255, 0, 96, + 255, 0, 72, + 255, 0, 48, + 255, 0, 24).finished().cast()/255.f; + + Matrix64_3_R_float H; + rgb_to_hsv(rgb,H); + H.col(1) *= 0.1; + H.col(2) = (H.col(2).array() + 0.1*(1.-H.col(2).array())).eval(); + hsv_to_rgb(H,rgb); + colors = (rgb*255.).cast(); + } + + tex_id = generate_1d_texture(colors); + + GLuint prog_id = igl::create_shader_program( + vertex_shader.c_str(), + fragment_shader.c_str(), + {{"scalar_in",scalar_loc}} + ); + igl::report_gl_error("create_shader_program: "); + return prog_id; + }; + static GLuint scalar_loc = 1; + static GLuint tex_id = 0; + static GLuint color_components_prog = + color_components_shader(scalar_loc,tex_id); + + // Set material properties + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); + glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,(const GLfloat[]){1,1,1,1}); + if(wireframe_visible) + { + glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + if(fill_visible) + { + glColor3f(0,0,0); + glUseProgram(0); + draw_mesh(V,F,N,s.I,scalar_loc); + }else + { + glUseProgram(color_components_prog); + igl::report_gl_error("UseProgram: "); + draw_mesh(V,F,N,s.I,scalar_loc); + } + } + + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + + glPushAttrib(GL_ALL_ATTRIB_BITS); + glUseProgram(color_components_prog); + igl::report_gl_error("use: "); + glUniform1f(glGetUniformLocation(color_components_prog,"cmin"),s.I.minCoeff()); + glUniform1f(glGetUniformLocation(color_components_prog,"cmax"),s.I.maxCoeff()); + //glUniform1f(glGetUniformLocation(color_components_prog,"cc_selected"),cc_selected); + glUniform1f(glGetUniformLocation(color_components_prog,"cc_hover"),cc_hover); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_1D, tex_id); + glUniform1i(glGetUniformLocation(color_components_prog,"color_map"),0); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_1D, s.mask_id); + glUniform1i(glGetUniformLocation(color_components_prog,"selected_mask"),1); + + igl::report_gl_error("unif: "); + if(fill_visible) + { + glEnable(GL_POLYGON_OFFSET_FILL); // Avoid Stitching! + glPolygonOffset(1.0, 0); + } + draw_mesh(V,F,N,s.I,scalar_loc); + glPopAttrib(); + glUseProgram(0); + + // Draw a nice floor + glPushMatrix(); + const double floor_offset = + -2./bbd*(V.col(1).maxCoeff()-Vmid(1)); + glTranslated(0,floor_offset,0); + const float GREY[4] = {0.5,0.5,0.6,1.0}; + const float DARK_GREY[4] = {0.2,0.2,0.3,1.0}; + draw_floor(GREY,DARK_GREY); + glPopMatrix(); + + pop_scene(); + + TwDraw(); + glutSwapBuffers(); + if(is_animating) + { + glutPostRedisplay(); + } +} + +void mouse_wheel(int wheel, int direction, int mouse_x, int mouse_y) +{ + using namespace std; + using namespace igl; + using namespace Eigen; + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT,viewport); + if(wheel == 0 && TwMouseMotion(mouse_x, viewport[3] - mouse_y)) + { + static double mouse_scroll_y = 0; + const double delta_y = 0.125*direction; + mouse_scroll_y += delta_y; + TwMouseWheel(mouse_scroll_y); + return; + } + + auto & camera = s.camera; + switch(center_type) + { + case CENTER_TYPE_ORBIT: + if(wheel==0) + { + // factor of zoom change + double s = (1.-0.01*direction); + //// FOV zoom: just widen angle. This is hardly ever appropriate. + //camera.m_angle *= s; + //camera.m_angle = min(max(camera.m_angle,1),89); + camera.push_away(s); + }else + { + // Dolly zoom: + camera.dolly_zoom((double)direction*1.0); + } + break; + default: + case CENTER_TYPE_FPS: + // Move `eye` and `at` + camera.dolly((wheel==0?Vector3d(0,0,1):Vector3d(-1,0,0))*0.1*direction); + break; + } + glutPostRedisplay(); +} + +bool pick(const int x, const int y, int & cc_selected) +{ + using namespace Eigen; + using namespace igl; + using namespace std; + static GLuint scalar_loc = 1; + static GLuint tex_id = 0; + static const size_t max_ids = s.I.maxCoeff()+1; + static GLuint color_shader_prog = color_shader(max_ids,scalar_loc,tex_id); + const int pick_s = 0; + const int pick_w = pick_s; + GLint old_vp[4]; + glGetIntegerv(GL_VIEWPORT,old_vp); + const double pick_ratio = double(pick_w)/double(old_vp[2]); + // ceil, cause might otherwise round down to 0 + const int pick_h = ceil(double(old_vp[3])*pick_ratio); + glViewport( + x-pick_w, + old_vp[3]-y-pick_h,2*pick_w+1,2*pick_h+1); + glMatrixMode(GL_PROJECTION); + Matrix4d proj; + glGetDoublev(GL_PROJECTION_MATRIX,proj.data()); + glPushMatrix(); + glLoadIdentity(); + gluPickMatrix( + x, + old_vp[3]-y, + pick_w*2+1, + pick_h*2+1, + old_vp); + glMultMatrixd(proj.data()); + glMatrixMode(GL_MODELVIEW); + // Activate color shader + glUseProgram(color_shader_prog); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,pick_fbo); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,pick_dfbo); + // Clear screen + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushAttrib(GL_ALL_ATTRIB_BITS); + glEnable(GL_TEXTURE_1D); + glBindTexture(GL_TEXTURE_1D, tex_id); + glUniform1f(glGetUniformLocation(color_shader_prog,"cmin"),s.I.minCoeff()); + glUniform1f(glGetUniformLocation(color_shader_prog,"cmax"),s.I.maxCoeff()); + draw_mesh(V,F,N,s.I,scalar_loc); + glPopAttrib(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glViewport(old_vp[0],old_vp[1],old_vp[2],old_vp[3]); + + Matrix pixel; + glReadPixels(x,old_vp[3]-y,1,1,GL_RGBA,GL_UNSIGNED_BYTE,pixel.data()); + + glUseProgram(0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,0); + + if(pixel(3) == 0) + { + cc_selected = -1; + return false; + } + cc_selected = pixel(0)*256*256+pixel(1)*256+pixel(2); + return true; +} + +void regenerate_mask() +{ + if(glIsTexture(s.mask_id)) + { + glDeleteTextures(1,&s.mask_id); + } + s.mask_id = generate_1d_texture(s.selected); +} + +void mouse(int glutButton, int glutState, int mouse_x, int mouse_y) +{ + using namespace std; + using namespace Eigen; + using namespace igl; + bool tw_using = TwEventMouseButtonGLUT(glutButton,glutState,mouse_x,mouse_y); + int mod = glutGetModifiers(); + switch(glutButton) + { + case GLUT_RIGHT_BUTTON: + { + switch(glutState) + { + case 1: + // up + glutSetCursor(GLUT_CURSOR_INHERIT); + is_rotating = false; + break; + case 0: + glutSetCursor(GLUT_CURSOR_CYCLE); + // collect information for trackball + is_rotating = true; + down_camera = s.camera; + down_x = mouse_x; + down_y = mouse_y; + break; + } + break; + } + case GLUT_LEFT_BUTTON: + { + switch(glutState) + { + case 1: + // up + glutSetCursor(GLUT_CURSOR_INHERIT); + is_rotating = false; + break; + case 0: + if(!tw_using) + { + push_scene(); + int cc_selected=-1; + if(pick(mouse_x,mouse_y,cc_selected)) + { + push_undo(); + if(!(mod & GLUT_ACTIVE_SHIFT)) + { + s.selected.setConstant(0); + } + s.selected(cc_selected,0) = 255; + regenerate_mask(); + }else + { + glutSetCursor(GLUT_CURSOR_CYCLE); + // collect information for trackball + is_rotating = true; + down_camera = s.camera; + down_x = mouse_x; + down_y = mouse_y; + } + pop_scene(); + } + break; + } + break; + } + // Scroll down + case GLUT_WHEEL_DOWN: + { + mouse_wheel(0,-1,mouse_x,mouse_y); + break; + } + // Scroll up + case GLUT_WHEEL_UP: + { + mouse_wheel(0,1,mouse_x,mouse_y); + break; + } + // Scroll left + case GLUT_WHEEL_LEFT: + { + mouse_wheel(1,-1,mouse_x,mouse_y); + break; + } + // Scroll right + case GLUT_WHEEL_RIGHT: + { + mouse_wheel(1,1,mouse_x,mouse_y); + break; + } + } + glutPostRedisplay(); +} + +void mouse_move(int mouse_x, int mouse_y) +{ + using namespace igl; + using namespace std; + using namespace Eigen; + bool tw_using = TwMouseMotion(mouse_x,mouse_y); + push_scene(); + pick(mouse_x,mouse_y,cc_hover); + pop_scene(); + glutPostRedisplay(); +} + +void mouse_drag(int mouse_x, int mouse_y) +{ + using namespace igl; + using namespace std; + using namespace Eigen; + bool tw_using = TwMouseMotion(mouse_x,mouse_y); + + if(is_rotating) + { + glutSetCursor(GLUT_CURSOR_CYCLE); + Quaterniond q; + auto & camera = s.camera; + switch(rotation_type) + { + case ROTATION_TYPE_IGL_TRACKBALL: + { + // Rotate according to trackball + igl::trackball( + width, + height, + 2.0, + down_camera.m_rotation_conj.coeffs().data(), + down_x, + down_y, + mouse_x, + mouse_y, + q.coeffs().data()); + break; + } + case ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP: + { + // Rotate according to two axis valuator with fixed up vector + two_axis_valuator_fixed_up( + width, height, + 2.0, + down_camera.m_rotation_conj, + down_x, down_y, mouse_x, mouse_y, + q); + break; + } + default: + break; + } + switch(center_type) + { + default: + case CENTER_TYPE_ORBIT: + camera.orbit(q.conjugate()); + break; + case CENTER_TYPE_FPS: + camera.turn_eye(q.conjugate()); + break; + } + } + glutPostRedisplay(); +} + +void init_relative() +{ + using namespace Eigen; + using namespace igl; + per_face_normals(V,F,N); + Vmax = V.colwise().maxCoeff(); + Vmin = V.colwise().minCoeff(); + Vmid = 0.5*(Vmax + Vmin); + bbd = (Vmax-Vmin).norm(); +} + +void init_components() +{ + using namespace Eigen; + using namespace igl; + using namespace std; + components(F,CC); + s.I = CC.cast(); + s.selected = Matrix::Zero(s.I.maxCoeff()+1,3); + cout<<"s.selected: "<=8"); + glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH)/2.0,glutGet(GLUT_SCREEN_HEIGHT)/2.0); + glutCreateWindow("components"); + glutDisplayFunc(display); + glutReshapeFunc(reshape); + glutKeyboardFunc(key); + glutMouseFunc(mouse); + glutMotionFunc(mouse_drag); + glutPassiveMotionFunc(mouse_move); + + init_components(); + init_relative(); + regenerate_mask(); + + std::cout<<"OpenGL version: "<