OpenGL Programming for Windows MFC


6. Trackball

Trackball については OpenGL Programming for the X Window System / glut (dinospn)参照
Refer to "OpenGL Programming for the X Window System" / glut (dinospn) for Trackball.


6.1 XXXView.cpp に以下の include 追加

extern "C" {
     :
     :
#include "trackball.h"    // for trackball.c

}
include added to XXXView.cpp

6.2 XXXView.h に以下のメンバー変数追加


    float   m_curquat[4] ;
    float   m_lastquat[4] ;

    int     m_spin , m_move ;
    int     m_begin_x,m_begin_y ;
    int     m_W , m_H ;

This member variable addition to XXXView.h.

6.3 Constructor に以下の行追加

CXXXView::CXXXView()
{

    trackball(m_curquat, 0.0, 0.0, 0.0, 0.0) ;

    m_spin = 0 ;
    m_move = 0 ;
    
    m_begin_x = 0 ;
    m_begin_y = 0 ;

    m_W = 300 ; m_H = 300 ;

}
The above line is added to CXXXView(Constructor).


6.4 OnDrawを以下のように変更

void CXXXView::OnDraw(CDC* pDC)
{

    CXXXDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    if (m_spin == 1) {
        add_quats(m_lastquat, m_curquat, m_curquat) ;
        InvalidateRect (NULL, FALSE);
    }

    DrawGL(m_curquat) ;

    SwapBuffers(m_pDC->m_hDC) ;    // Double buffer
}
OnDraw is changed as mentioned above.


6.5 DrawGLを以下のように変更


GLint DrawGL(GLfloat m_curquat[4])
{
    GLfloat m[4][4] ;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;

    glMatrixMode(GL_MODELVIEW) ;
    glLoadIdentity() ;
    glTranslated(0.0, 0.0, -3.0) ;

    build_rotmatrix(m , m_curquat) ;
    glMultMatrixf(&m[0][0]) ;

    glCallList(1) ;    // Object material

    glEnable(GL_TEXTURE_2D ) ;
    glCallList(2) ;    // Texture 

    glEnable(GL_NORMALIZE) ;
    glEnable(GL_AUTO_NORMAL) ;
        auxSolidTeapot(1.0) ;
    glDisable(GL_AUTO_NORMAL) ;
    glDisable(GL_NORMALIZE) ;
    glDisable(GL_TEXTURE_2D ) ;

    return(0) ;
}
DrawGL is changed as mentioned above.

6.6 ClassWizard により WM_LBOTTONDOWN(OnLButtonDown)をオーバライド し以下の行追加

void CXXXView::OnLButtonDown(UINT nFlags, CPoint point) 
{

    m_spin = 0 ;
    m_move = 1 ;
    
    m_begin_x = point.x ;
    m_begin_y = point.y ;

    CView::OnLButtonDown(nFlags, point);
}
Overrid WM_LBOTTONDOWN(OnLButtonDown) of CXXXView by Class Wizard.
And add the above line.

6.7 ClassWizard により WM_LBOTTONUP(OnLButtonUp)をオーバライド し以下の行追加


void CXXXView::OnLButtonUp(UINT nFlags, CPoint point) 
{

    m_move = 0 ;

    CView::OnLButtonUp(nFlags, point);
}
Overrid WM_LBOTTONUP(OnLButtonUp) of CXXXView by Class Wizard.
And add the above line.

6.8 ClassWizard により WM_MOUSEMOVE(OnMouseMove)をオーバライド し以下の行追加

void CXXXView::OnMouseMove(UINT nFlags, CPoint point) 
{

    int x,y ;
    CRect rect ;

    x = point.x ;
    y = point.y ;

    if ((nFlags & MK_LBUTTON) != 0) { // with left button down
        if (m_move == 1) {
            GetClientRect(&rect) ;
            m_W = rect.Width() ;
            m_H = rect.Height() ;
            trackball(m_lastquat,
                        (float)(      2.0 * m_begin_x - m_W) / m_W ,
                        (float)(m_H - 2.0 * m_begin_y      ) / m_H ,
                        (float)(      2.0 * x         - m_W) / m_W ,
                        (float)(m_H - 2.0 * y              ) / m_H 
                       ) ;
            m_begin_x = x ;
            m_begin_y = y ;
            m_spin = 1 ;
            InvalidateRect (NULL, FALSE);
        }
    }

    CView::OnMouseMove(nFlags, point);
}
Overrid WM_MOUSEMOVE(OnMouseMove) of CXXXView by Class Wizard.
And add the above line.

6.9 表示を reset する場合は、任意の Menu に Display->Reset などを追加し、以下の処理を 実行する

void CXXXView::OnDisplayReset() 
{

    trackball(m_curquat, 0.0, 0.0, 0.0, 0.0) ;
    m_spin = 0 ;
    m_move = 0 ;
    InvalidateRect (NULL, FALSE);

}
if display is reset , Display->Reset is added to Menu, and the above line is added .

6.10 Build and Execute

Project に trackball を追加し、ビルド・実行すると、マウスの左ボタン+マウス移動 に従いオブジェクトが回転するようになる。アニメーションも可能。


An object rotates in accordance with the left button + movement of the mouse. And animation is possible,too.

prev next