⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 copenglview.cpp

📁 本文以数字图像处理、压缩技术和MATLAB应用为基础
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	// if ticks < 0 and delta is larger than 1, place the ticks
	// on each scales unit length
	if ( 0 > ticks )
		{
		float delta = finish-start;
		ticks = delta > 1.0 ? (int)delta : 0;
		}

	// draw the tickmarked axes
	Draw3DAxesLine( start, finish, 0, ticks );
	Draw3DAxesLine( start, finish, 1, ticks );
	Draw3DAxesLine( start, finish, 2, ticks );
}

/////////////////////////////////////////////////////////////////////////////
// Draw3DAxesLine
// This routine draws a colored line along a specified axis.
// axis_id = 0 for the x, 1 for the y, and anything else for the z
// start and finish are the starting and ending location, start < finish.
// ticks is the number of ticks to place along the axis.
// If you are using lighting/materials, you might want to wrapper this routine
// so that it's called with lighting disabled, or else the axis lines will be effected
// by lighting claculations - which generally means hard to see.
void COpenGLView::Draw3DAxesLine( float start, float finish, int axis_id, int ticks )
{
	float *px, *py, *pz, zero = 0.0f;
	float tickx, ticky, tickz;
	float *pdx, *pdy, *pdz, tinytick, delta = (finish-start)/(ticks<1?1:ticks);
	GLfloat negativeColor[3] = { 1.0f, 0.0f, 0.0f };
	GLfloat positiveColor[3] = { 0.0f, 1.0f, 0.0f };

	pdx = pdy = pdz = px = py = pz = &zero;
	tickx = ticky = tickz = 0.0f;
	tinytick = 0.05f;

	// select which of the 3 axes is going to vary
	if ( 0 == axis_id ) // X axis
		{
		pdx = &delta;	  
		ticky = tinytick;	  
		px = &start;	  
		}
	else if ( 1 == axis_id ) // Y axis
		{
		pdy = &delta;	  
		tickx = tinytick;	  
		py = &start;	  
		}
	else 	// default Z axis
		{
		pdz = &delta;	  
		ticky = tinytick;	  
		pz = &start;	  
		}

	// turn off the lighting effects
	// since we don't want the axes lines effected by the
	// lighting. You might need to call ::glDisable(GL_LIGHTING)
	// before this routine

	::glBegin(GL_LINES);

	// now draw the two lines that make up the axis
	::glColor3fv( negativeColor ); // negative color
	::glVertex3f( *px, *py, *pz );
	::glVertex3f( 0.0f, 0.0f, 0.0f );

	::glColor3fv( positiveColor ); // positive color
	::glVertex3f( 0.0f, 0.0f, 0.0f );
	::glVertex3f( *px+*pdx*ticks, *py+*pdy*ticks, *pz+*pdz*ticks );

	// now draw the tick marks
	int i;
	for ( i = 0; i < ticks  ; i++ )
		{
		if ( i < ticks/2 )
			{
			::glColor3fv( negativeColor );
			}
		else
			{
			::glColor3fv( positiveColor );
			}

		::glVertex3f( *px-tickx, *py-ticky, *pz-tickz );
		::glVertex3f( *px+tickx, *py+ticky, *pz+tickz );

		*px += *pdx;
		*py += *pdy;
		*pz += *pdz;
		}

	::glEnd();

	// don't forget to turn lighting effects back on
	// via glEnable(GL_LIGHTING)

}


/////////////////////////////////////////////////////////////////////////////
// COpenGLView Text-Specific routines follow
/////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////
// GenerateDefaultFonts
// Generate the default 3D and flat text disp;ay lists
void COpenGLView::GenerateDefaultFonts( char* font3D, char* fontFlat )
{
   m_DefaultTextID		= GenerateDisplayListForFont( font3D );
   m_DefaultFlatTextID	= GenerateBitmapListForFont( fontFlat );
}

/////////////////////////////////////////////////////////////////////////////
// GLTextOut
// Output text (either Bitmap or Outline)
void COpenGLView::GLTextOut( GLuint id, const char * const textstring )
{
	if ( 0 == id || 0 == textstring )
		{
		return;
		}

	GLsizei size = strlen( textstring );

	::glListBase( id );
	::glCallLists( size, GL_UNSIGNED_BYTE, (const GLvoid*)textstring ); 

} 

/////////////////////////////////////////////////////////////////////////////
// GenerateDisplayListForFont
// The routines used for generating 3D text.
GLuint COpenGLView::GenerateDisplayListForFont( char* fontname, double xt )
{
	GLuint id;

	if ( 0 == m_pDC ||
		 0 == fontname || 
		 (GLuint)0 == (id = GetNewDisplayListIDs(256)) )
		{
        return 0;
		}

	LOGFONT     logfont;
	GLYPHMETRICSFLOAT gmf[256];

	// lfHeight can't be used to change the font size
	logfont.lfHeight		= -12; // use glScale to change size
	logfont.lfWidth			= 0;
	logfont.lfEscapement	= 0;
	logfont.lfOrientation	= logfont.lfEscapement;
	logfont.lfWeight		= FW_NORMAL;
	logfont.lfItalic		= FALSE;
	logfont.lfUnderline		= FALSE;
	logfont.lfStrikeOut		= FALSE;
	logfont.lfCharSet		= ANSI_CHARSET;
	logfont.lfOutPrecision	= OUT_TT_ONLY_PRECIS;
	logfont.lfClipPrecision	= CLIP_DEFAULT_PRECIS;
	logfont.lfQuality		= DEFAULT_QUALITY;
	logfont.lfPitchAndFamily = FF_DONTCARE|DEFAULT_PITCH;
	lstrcpy ( logfont.lfFaceName, fontname );

	CFont newfont;

	// returns 0 if it fails
	BOOL success = newfont.CreateFontIndirect( &logfont );
	CFont* oldfont =	m_pDC->SelectObject( &newfont );	
	ASSERT( 0 != oldfont );

    // Create a set of display lists based on the glyphs of the TrueType font 
	// notice that we really waste the first 32 spaces....
	// if there's a problem delete the display lists
	// Note that this single call takes MOST of the initialization time
	// for the COpenGLView class (probably a couple of seconds!) so if you don't
	// want/need 3D text, you might comment this functionality out.
	if (	0 == success ||
		FALSE == ::wglUseFontOutlines( m_pDC->m_hDC, 0, 256, id, 0.0f,
			(float)xt, WGL_FONT_POLYGONS,  gmf) )
		{
		::glDeleteLists( id, 256 );
		id  = 0;
		}
	else
		{
		m_pDC->SelectObject( oldfont );
		}

	return id;
}

/////////////////////////////////////////////////////////////////////////////
// GenerateBitmapListForFont
// The routines used for generating flat text
GLuint COpenGLView::GenerateBitmapListForFont( char* fontname )
{
	GLuint id;

	if ( 0 == m_pDC ||
		 (GLuint)0 == (id = GetNewDisplayListIDs(256)) )
		{
        return 0;
		}

	CFont newfont;
	CFont* oldfont;
	BOOL success;

	if ( NULL != fontname )
		{

		LOGFONT     logfont;
	
		logfont.lfHeight		= -12;
		logfont.lfWidth			= 0;
		logfont.lfEscapement	= 0;
		logfont.lfOrientation	= logfont.lfEscapement;
		logfont.lfWeight		= FW_NORMAL;
		logfont.lfItalic		= FALSE;
		logfont.lfUnderline		= FALSE;
		logfont.lfStrikeOut		= FALSE;
		logfont.lfCharSet		= ANSI_CHARSET;
		logfont.lfOutPrecision	= OUT_DEFAULT_PRECIS;
		logfont.lfClipPrecision	= CLIP_DEFAULT_PRECIS;
		logfont.lfQuality		= DEFAULT_QUALITY;
		logfont.lfPitchAndFamily = FF_DONTCARE|DEFAULT_PITCH;
		lstrcpy ( logfont.lfFaceName, fontname );

		// returns 0 if it fails
		success = newfont.CreateFontIndirect( &logfont );
		oldfont =	m_pDC->SelectObject( &newfont );
		ASSERT( 0 != oldfont );
		}
	else
		{
		// make the system font the device context's selected font
		oldfont =	(CFont*)m_pDC->SelectStockObject( SYSTEM_FONT );
		ASSERT( 0 != oldfont );
		}
	
    // Create a set of display lists based on the glyphs of the font 
	// notice that we really waste the first 32 spaces....
	// if there's a problem delete the display lists
   if (	0 == success ||
		FALSE == ::wglUseFontBitmaps( m_pDC->m_hDC, 0, 256, id ) )
		{
		::glDeleteLists( id, 256 );
		id  = 0;
		}
   else
		{
		m_pDC->SelectObject( oldfont );
		}

   return id;
}


/////////////////////////////////////////////////////////////////////////////
// Animation routines
/////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////
void COpenGLView::OnAnimate() 
{
	// TODO: Add your command handler code here
	ToggleAnimationFlag();

	if ( m_bAnimationRunning )
		{
		InvalidateRect( 0, FALSE );
		UpdateWindow();
		}
	else
		{
		// turn off animation message
		GetParentFrame()->SetWindowText( (const char*)m_WindowTitle );
		}
}

/////////////////////////////////////////////////////////////////////////////
void COpenGLView::OnUpdateAnimate(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetCheck( m_bAnimationRunning );
}

/////////////////////////////////////////////////////////////////////////////
// CalculateDynamics
// This routine uses simple velocity-based values to change the viewpoint.
// Thus there is no acceleration component, just a velocity component.
// Most people can't get used to an acceleration-based control as it's
// too difficult to get used to. This setup is much more predictable.
//
// The values used for velocity, rotation, and acceleration are
// all in units per second. This allows you to pick reasonable,
// intuitive values.
void COpenGLView::CalculateDynamics()
{
	ASSERT( AnimationRunning() );

   	double eTime = (double)ElapsedTimeinMSSinceLastRender()/1000.0;

	// Limit translational acceleration values
	if ( m_deltaZ > m_MaxVelocity )
		m_deltaZ = m_MaxVelocity;
 	if ( m_deltaX > m_MaxVelocity )
		m_deltaX = m_MaxVelocity;
	if ( m_deltaY > m_MaxVelocity )
		m_deltaY = m_MaxVelocity;
   	if ( -m_deltaZ > m_MaxVelocity )
		m_deltaZ = -m_MaxVelocity;
 	if ( -m_deltaX > m_MaxVelocity )
		m_deltaX = -m_MaxVelocity;
	if ( -m_deltaY > m_MaxVelocity )
		m_deltaY = -m_MaxVelocity;

	// Limit rotational acceleration values
	if ( m_rotdeltaZ > m_MaxRotation )
		m_rotdeltaZ = m_MaxRotation;
 	if ( m_rotdeltaX > m_MaxRotation )
		m_rotdeltaX = m_MaxRotation;
	if ( m_rotdeltaY > m_MaxRotation )
		m_rotdeltaY = m_MaxRotation;
   	if ( -m_rotdeltaZ > m_MaxRotation )
		m_rotdeltaZ = -m_MaxRotation;
 	if ( -m_rotdeltaX > m_MaxRotation )
		m_rotdeltaX = -m_MaxRotation;
	if ( -m_rotdeltaY > m_MaxRotation )
		m_rotdeltaY = -m_MaxRotation;


	// This is where the actual values for rotation and
	// acceleration change. Note that I'm really ignoring the acceleration
	// values. Most people simply find changing velocity by
	// tweaking the acceleration values too hard to understand, so I
	// take the easy way out and hook up the user controls to the velocity
	// instead. If you're building a space simulation, then you might want to
	// redo these equations.

	// (Actually, when I said I'm ingoring the acceleration values,
	// I really meant that I was using the acceleration variables in place
	// of the velocity variables in these equations. I do this so that if you
	// wanted to correctly use acceleration to tweak velocity (via the UI)
	// and then velocity to tweak position, only these equations would change.
	m_X += m_accelX * eTime;
  	m_Y += m_accelY * eTime;
	m_Z += m_accelZ * eTime;

	m_rotX += m_rotaccelX * eTime;
  	m_rotY += m_rotaccelY * eTime;
	m_rotZ += m_rotaccelZ * eTime;

}


/////////////////////////////////////////////////////////////////////////////
// ViewpointOriginRotation
// This viewpoint spins about the origin and accepts
// changes in rotation rates and distance from the origin.
// The distance to the origin can be varied
BOOL COpenGLView::ViewpointOriginRotation()
{

    ::glLoadIdentity();

	// Move away from the origin
	::glTranslatef( 0.0f, 0.0f, (GLfloat)m_Z );

	// Rotate about the origin
	::glRotatef( (GLfloat)m_rotX, 1.0f, 0.0f, 0.0f );
	::glRotatef( (GLfloat)m_rotY, 0.0f, 1.0f, 0.0f );
	::glRotatef( (GLfloat)m_rotZ, 0.0f, 0.0f, 1.0f );

    return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
// OnKeyDown
// This routine runs the keyboard interface.
// Most of the keys accepted are from the numeric keypad

// HOME: Resets viewpoint to initial values (animation keeps going)
// SHIFT-HOME: reset viewpoint & clear movement vectors
// 5: Clear movement vectors
// Up/Down Arrows: change velocity in Z (if shifted, change rotation)
// Left/Right Arrows: change velocity in X (if shifted, change rotation)
// Plus/Minus: change velocity in Y (if shifted, change rotation)
// ESC: Exit animation

void COpenGLView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
	BOOL ctrl = 0x8000 & GetKeyState( VK_CONTROL );
	BOOL shift= 0x8000 & GetKeyState( VK_SHIFT );

	if ( AnimationRunning() )
		{
		switch ( nChar )
			{
			case VK_HOME: // reset position to viewpoint's origin
				m_X = m_HomeX;
				m_Y = m_HomeY;
				m_Z = m_HomeZ;
				m_rotX = m_HomerotX;
				m_rotY = m_HomerotY;
				m_rotZ = m_HomerotZ;

			 	if ( !shift )  // drop through if shifted
					return;
				// i.e shift home resets viewpoint AND movement

			case VK_CLEAR: // numeric 5 keypad key
				// kill velocity & acceleration & rotation
			  	m_deltaX = m_deltaY = m_deltaZ = 0.0f;
			  	m_accelX = m_accelY = m_accelZ = 0.0f;
			  	m_rotdeltaX = m_rotdeltaY = m_rotdeltaZ = 0.0f;
			  	m_rotaccelX = m_rotaccelY = m_rotaccelZ = 0.0f;
				return;
   			case VK_UP: // up arrow
				shift ?
					IncreaseRotation( m_rotaccelZ ):
					IncreaseVelocity(m_accelZ);
					return;
			case VK_DOWN: // down arrow
				shift ?
					DecreaseRotation( m_rotaccelZ ):
					DecreaseVelocity(m_accelZ);
					return;
 			case VK_LEFT: // left arrow
				shift ?
					IncreaseRotation( m_rotaccelX ):
					IncreaseVelocity(m_accelX);
					return;
			case VK_RIGHT: // right arrow
				shift ?
					DecreaseRotation( m_rotaccelX ):
					DecreaseVelocity(m_accelX);
				return;
 			case VK_SUBTRACT: // minus 
				shift ?
					IncreaseRotation( m_rotaccelY ):
					IncreaseVelocity( m_accelY );
				return;
			case VK_ADD: // plus
				shift ?
					DecreaseRotation( m_rotaccelY ):
					DecreaseVelocity( m_accelY );
				return;
		}
	// end if animated
	}

	switch ( nChar )
	   {
	   case VK_ESCAPE:	// close down the app
			GetParent()->PostMessage(WM_CLOSE);
			return;
	   default:
			return;
	   }

	// Probably don't ever need this
	//CView::OnKeyDown(nChar, nRepCnt, nFlags);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -