// ******************************************************************************* // Name : glut_cv.hxx // : callback GLUT // Author : I. Nakagawa // Create : 2019/10/24 // Modify : 2019/10/24 // ******************************************************************************* #pragma once #include "glut_cb.hxx" #include "vxx_fnc3.hxx" #include "extent.hxx" #include "i_define.hxx" #define cv_init cb_init //#define cv_keyboard cb_keyboard #define cv_idle cb_idle //#define cv_resize cb_resize //// // ******************************************************************************* // eye ... // Create : 2019/10/24 // ******************************************************************************* class C_glut { public: C_glut () { EP = Vd3(7,-10, 6) ; TP = Vd3(2, 5, 3) ; Up = Vd3(0, 0, 1) ; Distnc = LastDs = 50 ; Anchor = Vd2(-1) ; Button = -1 ; D_min = 10 ; D_max = 200 ; Rotate = false ; } public: Vd3 EP ; // Eye Vd3 TP ; // Target Vd3 Up ; // up double Distnc ; // distance Vd4 BG ; // BG color bool Rotate ; // rotate public: int Button ; // button Left : Eye , Middle : Distance Vd2 Anchor ; // Eye Drag Start Vd3 LastEP ; // Last eye double LastDs ; // Last distnce public: Ed3 Ext ; // extent double D_min ; // distance min double D_max ; // distancd max } ; inline C_glut* get_c_glut (void) { static C_glut G_c_glut ; return &G_c_glut ; } //// // ******************************************************************************* // ClearColor // Create : 2019/10/25 // ******************************************************************************* inline void ClearColor (const Vd4& bg) { ::glClearColor(float(bg.x),float(bg.y),float(bg.z),float(bg.w)) ; #ifdef _DEBUG // std::tout << ::V4_To_tstring(bg) << std::endl ; #endif } //// // ******************************************************************************* // mouse // Create : 2019/10/24 // ******************************************************************************* inline void cv_mouse (int button,int state,int x,int y) { C_glut* gm = ::get_c_glut() ; //#ifdef _DEBUG // std::tout << _T("Button=") << button << _T("\t") << x << _T(" , ") << y << _T("\t") << state << std::endl ; //#endif // LastEP = Vd3(0) ; switch (button) { case GLUT_LEFT_BUTTON : if (state == GLUT_DOWN) { gm->Anchor = Vd2(x,y) ; gm->LastEP = gm->EP ; } if (state == GLUT_DOWN) { ::glutIdleFunc(cb_idle) ; } else { ::glutIdleFunc(NULL) ; } break; case GLUT_MIDDLE_BUTTON : if (state == GLUT_DOWN) { gm->Anchor = Vd2(x,y) ; // gm->LastEP = gm->EP ; gm->LastDs = gm->Distnc ; } if (state == GLUT_DOWN) { ::glutIdleFunc(cb_idle) ; } else { ::glutIdleFunc(NULL) ; } break; default: break; } if (state == GLUT_DOWN) { gm->Button = button ; } else { gm->Button = -1 ; } } //// // ******************************************************************************* // motion // Create : 2019/10/24 // ******************************************************************************* inline void cv_motion (int x,int y) { C_glut* gm = ::get_c_glut() ; // std::tout << _T("MouseMove") << _T("\t") << x << _T(" , ") << y << std::endl ; // if (LastEP == Vd3(0)) { return; } if (gm->Button == GLUT_LEFT_BUTTON) { Vd3 eye = gm->LastEP ; { double width_ = ::glutGet(GLUT_WINDOW_WIDTH) ; double height = ::glutGet(GLUT_WINDOW_HEIGHT); double angleXY = rad(180 * (gm->Anchor.x - x) / width_) ; double angle_Z = -rad(180 * (gm->Anchor.y - y) / height) ; eye = ::Eye_GetSpinXY(eye,angleXY) ; eye = ::Eye_GetSpin_Z(eye,angle_Z) ; // std::tout << deg(angleXY) << _T("\t") << deg(angle_Z) << std::endl ; } gm->EP = eye ; } else if (gm->Button == GLUT_MIDDLE_BUTTON) { double distnc = gm->LastDs ; { double height = ::glutGet(GLUT_WINDOW_HEIGHT) ; double ratio = (gm->Anchor.y-y) / height ; if (ratio > 0) { distnc *= 1 + ratio ; } else { distnc *= 1 + ratio ; } if (distnc < gm->D_min) { distnc = gm->D_min ; } if (distnc > gm->D_max) { distnc = gm->D_max ; } // std::tout << ratio << _T("\t") << distnc << std::endl ; } gm->Distnc = distnc ; } } //// // ******************************************************************************* // resize // Create : 2019/10/29 // ******************************************************************************* inline void cv_resize (int w,int h) { ::glViewport(0,0,w,h) ; ::glMatrixMode(GL_PROJECTION) ; ::glLoadIdentity() ; C_glut* gm = ::get_c_glut() ; ::Perspective(gm->D_max*1.5) ; } //// // ******************************************************************************* // LookAt // Create : 2019/10/24 // ******************************************************************************* inline void LookAt (Vd3& ep,Vd3& tp,Vd3& up) { ::glMatrixMode(GL_MODELVIEW) ; ::glLoadIdentity() ; ::gluLookAt(ep.x,ep.y,ep.z, tp.x,tp.y,tp.z, up.x,up.y,up.z) ; } inline void LookAt (void) { C_glut* gm = ::get_c_glut() ; { Vd3 ep = gm->EP ; ep.Normalize() ; // ep *= 100 ; ep *= gm->Distnc ; gm->EP = ep ; } Vd3 eye = gm->EP + gm->TP ; ::LookAt(eye,gm->TP,gm->Up) ; } //// // ******************************************************************************* // display // Create : 2019/10/24 // ******************************************************************************* inline void cv_draw (const Vd3& col=Vd3(0)) { GLdouble vertex[][3] = { { 0, 0, 0 }, { 4, 0, 0 }, { 4, 10, 0 }, { 0, 10, 0 }, { 0, 0, 6 }, { 4, 0, 6 }, { 4, 10, 6 }, { 0, 10, 6 } } ; int edge[][2] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 4 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 } } ; ::glColor3d(col.x,col.y,col.z) ; ::glBegin(GL_LINES) ; for (int i = 0; i < int(countof(edge)) ; ++i) { ::glVertex3dv(vertex[edge[i][0]]) ; ::glVertex3dv(vertex[edge[i][1]]) ; } ::glEnd() ; } inline void cv_display(void) { ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ; ::LookAt() ; ::cv_draw() ; ::glutSwapBuffers(); } //// // ******************************************************************************* // set extent // Create : 2019/10/28 // ******************************************************************************* inline bool set_Extent (const Ed3& ext) { C_glut* gm = ::get_c_glut() ; if (gm->Ext == ext) { return true ; } gm->Ext = ext ; gm->TP = ext.mmm() ; gm->D_min = ext.Volume().Length() ; gm->D_max = gm->D_min * 10. ; gm->Distnc= gm->D_min * 1.5 ; if (::glutGetWindow() != 0) { int w = ::glutGet(GLUT_WINDOW_WIDTH) ; int h = ::glutGet(GLUT_WINDOW_HEIGHT); cv_resize(w,h) ; } return true ; } //// // ******************************************************************************* // rotate // Create : 2019/10/29 // ******************************************************************************* inline bool ut_Rotate (const double deg_rz=1) { C_glut* gm = ::get_c_glut() ; if (gm->Rotate) { Vd3 eye = gm->EP ; { double angleXY = rad(deg_rz) ; eye = ::Eye_GetSpinXY(eye,angleXY) ; } gm->EP = eye ; } return true ; } //// // ******************************************************************************* // timer // Create : 2019/10/29 // ******************************************************************************* inline void cv_timer (int value) { ::ut_Rotate(1) ; int timing = value ; if (::get_c_glut()->Rotate) { timing = 100 ; } else { timing = 1000 ; } ::glutTimerFunc(timing,cv_timer,timing) ; ::glutPostRedisplay() ; } //// // ******************************************************************************* // keyboard // Create : 2019/10/25 // Modify : 2019/11/14 // Modify : 2019/12/05 'w' // ******************************************************************************* inline void cv_keyboard (unsigned char key,int x,int y) { C_glut* gm = ::get_c_glut() ; switch (key) { case 'b' : // ::glutIdleFunc(NULL) ; gm->BG = Vd4(1)-gm->BG ; ::ClearColor(gm->BG) ; // ::glutIdleFunc(cb_idle) ; ::glutPostRedisplay() ; break ; case 'r' : gm->Rotate = !gm->Rotate ; if (gm->Rotate) { ::glutTimerFunc(10,cv_timer,10) ; } break ; case 't' : if (::glIsEnabled(GL_TEXTURE_2D)) { ::glDisable(GL_TEXTURE_2D) ; } else { ::glEnable (GL_TEXTURE_2D) ; } ::glutPostRedisplay() ; break ; case 'w' : if (::glIsEnabled(GL_LINE_SMOOTH)) { ::glDisable(GL_LINE_SMOOTH) ; } else { ::glEnable (GL_LINE_SMOOTH) ; } ::glutPostRedisplay() ; break ; case 'l' : if (::glIsEnabled(GL_LIGHTING)) { ::glDisable(GL_LIGHTING) ; } else { ::glEnable (GL_LIGHTING) ; ::glEnable(GL_LIGHT0) ; } ::glutPostRedisplay() ; break ; // case 'q' : // case 'Q' : // case '\x1b' : // ::exit(0) ; // break ; default : ::cb_keyboard(key,x,y) ; break ; } }