PDA

View Full Version : Panning Newbie Problems



IssamTP
04-15-2014, 09:29 AM
Hi everybody, I'm very new to OpenGL so this might be a very silly question.

What I'm using: Visual Studio 2010, MFC framework, Windows 7.
What I'm trying to do: A MFC control based on OpenGL that can show some files preview with zooming, panning and rotation.
What I've already done:
1) Derived a class from CButton to handle all events and having a easy access to CClientDC;
2) Following a less or more recent tutorial I've encapsulated the creation of the OpenGL Device in a class. I don't know if it's good or if I've understood what I've done, but it works:


int COpenGLCtrl::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
if( CButton::OnCreate( lpCreateStruct ) == -1 )
return -1;
m_pDC = new CClientDC( this );
// This is my encapsulated device.
m_GLDevice.Create( m_pDC->m_hDC );
InitGL();
return 0;
}
void COpenGLCtrl::InitGL( void )
{
glShadeModel( GL_SMOOTH );
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
}
// Drawing inside button.
void COpenGLCtrl::OnPaint( void )
{
m_GLDevice.MakeCurrent();
DrawGLScene();
}
// This function is called before DrawGLScene the first time the control is being redrawed.
void COpenGLCtrl::ZoomOut( int nVal )
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0.0f, nVal * 1.0f, 0.0f, nVal * 1.0f, nVal * 1.0f, 0.0f );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
void COpenGLCtrl::DrawGLScene( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

glLoadIdentity();
glRotatef( m_fRotation_X, 1.0f, .0f, 0.0f );
glRotatef( m_fRotation_Y, 0.0f, 1.0f, 0.0f );
glTranslatef( m_fTraslation_X, m_fTraslation_Y, 0.0f );
glScalef( 1.0f, 1.0f, 0.0f );

glBegin( GL_TRIANGLES );
glColor3f( 1.0f, 0.0f, 0.0f );
glVertex3f( 0.0f, 0.0f, 0.0f );
glColor3f( 0.0f, 1.0f, 0.0f );
glVertex3f( 0.5f, 1.0f, 0.0f );
glColor3f( 0.0f, 0.0f, 1.0f );
glVertex3f( 1.0f, 0.0f, 0.0f );
glEnd();

SwapBuffers( m_pDC->m_hDC );
}

This stuff is sufficient to draw a small rectangle in my control with low-left vertex centered in OpenGL axis origin. All good, I showed you all this stuff to see if there are some error somewhere.
Now, I want to pan around my triangle. From what I've understood, I've to modify the value of m_fTranslation_X and _Y. I've decided to pan the view when the user holds down the left button and moves it around:


void COpenGLCtrl::OnMouseMove( UINT nFlags, CPoint point )
{
int nRes;
CString strOut;
GLfloat winX, winY, winZ;
GLint viewport[4];
GLdouble vPos[3], modelview[16], projection[16];

// Converting CPoint MFC coordinates to OpenGL viewport coordinates.
m_p2dPosMouse = point;
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetIntegerv( GL_VIEWPORT, viewport );
winX = (GLfloat)point.x;
winY = (GLfloat)viewport[3] - (GLfloat)point.y;
glReadPixels( point.x, int( winY ), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
nRes = gluUnProject( winX, winY, winZ, modelview, projection, viewport, &vPos[0], &vPos[1], &vPos[2] );
m_vPosMouse[0] = (GLfloat)vPos[0];
m_vPosMouse[1] = (GLfloat)vPos[1];
m_vPosMouse[2] = (GLfloat)vPos[2];
if( nFlags == MK_LBUTTON )
{
if( !m_bTrasla )
{
ATLTRACE2( _T("\nInizio traslazione\n\n") );
memcpy( m_vPosMouse_ult, m_vPosMouse, 3 * sizeof( GLfloat ) );
m_p2dUltPos = point;
m_bTrasla = true;
}
/*OPENGL-WAY
m_fTraslation_X += m_vPosMouse[0] - m_vPosMouse_ult[0];
m_fTraslation_Y += m_vPosMouse[1] - m_vPosMouse_ult[1];
*/
/*MFC-WAY*/
m_fTraslation_X += ( point.x - m_p2dUltPos.x ) / 5000.0f;
m_fTraslation_Y += ( m_p2dUltPos.y - point.y ) / 5000.0f;
CString strBuf;
strBuf.Format( _T("%f - %f || CPoint.x: %ld CPoint.y: %ld\n"), m_fTraslation_X, m_fTraslation_Y, point.x, point.y );
ATLTRACE2( strBuf );
memcpy( m_vPosMouse_ult, m_vPosMouse, 3 * sizeof( GLfloat ) );
}
if( m_CB_PosAgg.Valid() )
m_CB_PosAgg.Execute();
Invalidate();
}

In short words: I keep track of mouse last position and calculate how much I've moved on X and on Y. These differences are my traslations.
Finally my problems:
1) If I use OpenGL coordinate (commented and labelled OPENGL-WAY) the pan is smooth and precise but shakes. This is because even if my CPoint coordinates increase (or decrease) and so the difference, the OpenGL don't. Here's some values:



m_fTraslate_X m_fTraslate_Y CPoint.x CPoint.y
0.000000 0.000000 274 328
0.014377 0.141573 283 265
0.020767 0.152809 287 260
0.001597 0.002247 288 259
0.007987 0.020225 292 251
0.025559 0.164045 295 246
0.027157 0.170786 296 243



As you can see, while mouse control position increases (in MFC Y axis is inverted), at step 3 the values for X-axis are suddenly decreased from 0.02 to 0.002 and then back to 0.02! Why this?
2) If I use MFC coordinate, labelled MFC-WAY, I've got no shakes but a strong inertia. Sometimes happen that if I start moving my mouse to the right (assuming no up-down) then change the direction back to left, my view continues to move to the right. Where is the error?

Thanks in advance, hope you won't ban me for this noobish essay.

tonyo_au
04-15-2014, 11:21 PM
m_fTraslation_X += m_vPosMouse[0] - m_vPosMouse_ult[0];

Are you sure you want to keep adding

I would have thought you want

m_fTranslation_X = original_x+(
m_vPosMouse[0] - m_vPosMouse_ult[0]);

because m_vPosMouse_ult[0] is not changing

IssamTP
04-16-2014, 12:01 AM
because m_vPosMouse_ult[0] is not changing

What you mean? m_vPosMouse_ult[0] is actually changing:

memcpy( m_vPosMouse_ult, m_vPosMouse, 3 * sizeof( GLfloat ) );

EDIT
You were partially right, in the MFC-WAY I didn't update the last position of mouse. Adding:

m_p2dUltPos = point;

tonyo_au
04-16-2014, 07:13 PM
Sorry, I was looking at the OPENGL_WAY and thought all the code after MFC-WAY was removed.