opengl中旋转公式推导
OPENGL中物体的旋转变换

glLoadIdentity()与glTranslatef()和glRotatef()--坐标变换glLoadIdentity()将当前的用户坐标系的原点移到了屏幕中心:类似于一个复位操作1.X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外。
2.OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。
3.中心左面的坐标值是负值,右面是正值。
移向屏幕顶端是正值,移向屏幕底端是负值。
移入屏幕深处是负值,移出屏幕则是正值。
glTranslatef(x, y, z)沿着X, Y 和Z 轴移动。
注意在glTranslatef(x, y, z)中,当您移动的时候,您并不是相对屏幕中心移动,而是相对与当前所在的屏幕位置。
其作用就是将你绘点坐标的原点在当前原点的基础上平移一个(x,y,z)向量。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////glLoadIdentity();glTranslatef(-1.5f,0.0f,-6.0f);glBegin(GL_TRIANGLES);glVertex3f(0.0f,0.0f, 0.0f);glVertex3f(1.0f,0.0f, 0.0f);glVertex3f(0.0f,1.0f, 0.0f);glEnd();glLoadIdentity();glTranslatef(0.0f,0.0f,-6.0f);glBegin(GL_TRIANGLES);glVertex3f(0.0f,0.0f, 0.0f);glVertex3f(1.0f,0.0f, 0.0f);glVertex3f(0.0f,1.0f, 0.0f);glEnd();/////////////////////////////////////////////////////////////////////////////////////程序的运行结果如下:左边的三角形是第一步绘制的,可以看到该三角形绘制的坐标系,实际上是以(-1.5f,0.0f,-6.0f)为原点的。
坐标旋转变换公式推导过程

坐标旋转变换公式推导过程1. 旋转变换的基本概念在计算机图形学中,我们经常需要对图形对象进行旋转变换。
旋转变换是一种常见的线性变换,可以帮助我们调整图形的方向和角度。
旋转变换通常涉及到一个旋转角度和一个旋转中心。
2. 二维空间中的坐标旋转我们先来看二维空间中的坐标旋转。
假设有一个二维空间中的点P(x, y),我们要将该点绕原点(0, 0)旋转一个角度θ,得到新的点P’(x’, y’)。
根据坐标旋转变换公式的推导过程,我们可以得到如下的数学表达式:x’ = x * cos(θ) - y * sin(θ) y’ = x * sin(θ) + y * cos(θ)3. 推导过程步骤一:旋转变换矩阵的推导我们知道,对于二维空间中的点P(x, y),我们可以用齐次坐标来表示为P(x, y, 1)。
而旋转变换可以表示为一个2x2的矩阵R:R = | cos(θ) -sin(θ) | | sin(θ) cos(θ) |步骤二:推导旋转变换的推导根据矩阵乘法的定义,我们可以得到旋转后的点P’:P’ = R * P展开计算得到:x’ = x * cos(θ) - y * sin(θ) y’ = x * sin(θ) + y * cos(θ)因此,从矩阵和坐标的角度上,我们成功推导出了二维空间中的坐标旋转变换公式。
4. 结论通过上述推导过程,我们可以得到二维空间中坐标旋转变换的具体数学表达式。
这些公式在计算机图形学和计算机视觉中具有重要的应用价值,能够帮助我们实现各种旋转形变效果。
在实际的编程实现中,我们可以根据这些公式进行简单的计算,从而实现图形的旋转变换效果。
希望本文的推导过程对读者有所帮助,引发对坐标旋转变换公式的更深一步探索和研究。
参考资料•计算机图形学教程•计算机视觉基础理论以上就是坐标旋转变换公式推导过程的详细内容,希望对您有所帮助。
openGL+VS2010的例程--旋转立方体(三维)

openGL+VS2010的例程--旋转⽴⽅体(三维)效果图如上:步骤:⾸先,设置模型视⾓往后退,再旋转视⾓;然后,⽤默认绘制⽴⽅体函数绘制;最后,利⽤空闲对模型做⾓度微调。
实现代码如下:1 #include <GL\glut.h>23 GLfloat xRotated, yRotated, zRotated;45void Display(void)6 {7 glClear(GL_COLOR_BUFFER_BIT);8 glLoadIdentity();9 glTranslatef(0.0,0.0,-4.0);10 glRotatef(xRotated,1.0,0.0,0.0);11 glRotatef(yRotated,0.0,1.0,0.0);12 glRotatef(zRotated,0.0,0.0,1.0);13//glScalef(2.0,1.0,1.0);14 glutWireCube(1.5);15 glFlush(); //Finish rendering16 glutSwapBuffers();17 }1819void Reshape(int x, int y)20 {21if (y == 0 || x == 0) return; //Nothing is visible then, so return22//Set a new projection matrix23 glMatrixMode(GL_PROJECTION);24 glLoadIdentity();25//Angle of view:40 degrees26//Near clipping plane distance: 0.527//Far clipping plane distance: 20.028 gluPerspective(40.0,(GLdouble)x/(GLdouble)y,0.5,20.0);29 glMatrixMode(GL_MODELVIEW);30 glViewport(0,0,x,y); //Use the whole window for rendering31 }32static int times = 0;33void Idle(void)34 {35 times++;36if(times >30000)37 times = 0;3839if(times %30000 == 0)40 {41 xRotated += 0.3;42 yRotated += 0.1;43 zRotated += -0.4;44 Display();45 }46 }474849int main (int argc, char **argv)50 {51//Initialize GLUT52 glutInit(&argc, argv);53 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); //For animations you should use double buffering54 glutInitWindowSize(300,300);55//Create a window with rendering context and everything else we need56 glutCreateWindow("Cube example");57 glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);58 xRotated = yRotated = zRotated = 0.0;59 glClearColor(0.0,0.0,0.0,0.0);60//Assign the two used Msg-routines61 glutDisplayFunc(Display);62 glutReshapeFunc(Reshape);63 glutIdleFunc(Idle);64//Let GLUT get the msgs65 glutMainLoop();66return0;67 }。
计算机图形学 OpenGL 外部图形的的加载、旋转和平移

外部图形的加载、旋转和平移1、实验目的和要求外部图形的的加载、旋转和平移2、实验内容用MFC方法和OpengL知识来实现位图和.cur格式图形文件的的加载、旋转和平移。
3、实验步骤1)程序设计Camera.cpp 实现照相机模型与变换。
CoordinateAxis.cpp 实现图中的向量绘制和标注。
MFCGL.cpp 实现的功能相当于主函数调用的功能。
MFCGLView.cpp 主干文件,对图形的编辑的具体实现。
2)程序调试、测试与运行结果分析(1)X视图Y视图Z视图旋转功能平移共能功能选择键,依次为选择、旋转、平移和三种视图。
(2)功能上实现的感觉还可以,基本上已经达到要求,但由于图形文件是从网上下来的,不是自己编辑设计的,而且也不是cad文件,是没有达到题目要求,Win7不能安装CAD软件,这是我自己考虑不周,实验结果还是比较满意的。
4、实验总结此次课程设计,对我的很有挑战。
在课上对文件加载这部分知识没有过多的领会,导致我在网上找了很长时间的加载函数。
后来网上有了个用MFC 加载图形的例子,根据它的截图和关键算法的代码实现,再加上以前对MFC 稍微有点了解,知道函数该添加在什么位置,花了将近一个下午的时间将在RES文件夹中的文件进行了加载、旋转和平移,代码看的不是特别懂,有点糊里糊涂,而且可能对MFC了解的也不是特别深,致使我在编译时错误不断,有时甚至达到了115个错误。
后来原因只是因为一个符号错了,看来还得再细节上多多注意,还有头一次用MFC实现OpengL方法的编程,感觉还好,最起码有结果出来了。
MFC的优点就是框架已经搭建好了,不用在费事去做过多与需求功能无关的事,很多文件都是直接生成的,只需加几个头文件就行了,还有就是添加功能函数。
总体讲收获很大,对自己的编程能力又多了一点自信。
5、附录res/rc2:包含项目使用的附加资源的脚本文件。
1)MFCGLView.cpp文件代码:// MFCGLView.cpp : implementation of the CMFCGLView class//#include "stdafx.h"#include "MFCGL.h"#include "MainFrm.h"#include "MFCGLDoc.h"#include "MFCGLView.h"#include "CoordinateAxis.h"#include <math.h>#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endifGLfloat ambientLight[] = { 0.3f, 0.3f,0.3f, 1.0f };GLfloat diffuseLight[] = { 0.7f, 0.7f,0.7f, 1.0f };GLfloat lightPos[] = {-50.0f, 50.0f,100.0f, 1.0f };/////////////////////////////////////////////////////////////////////////////// CMFCGLViewIMPLEMENT_DYNCREATE(CMFCGLView, CView)BEGIN_MESSAGE_MAP(CMFCGLView, CView)//{{AFX_MSG_MAP(CMFCGLView)ON_WM_CREATE()ON_WM_DESTROY()ON_WM_SIZE()ON_WM_TIMER()ON_WM_ERASEBKGND()ON_COMMAND(C_PAN, OnCameraPan)ON_UPDATE_COMMAND_UI(C_PAN, OnUpdateCameraPan)ON_COMMAND(SELECTMODE, OnSELECTMODE)ON_UPDATE_COMMAND_UI(SELECTMODE, OnUpdateSELECTMODE) ON_WM_MOUSEMOVE()ON_WM_KEYDOWN()ON_WM_LBUTTONDOWN()ON_WM_RBUTTONDOWN()ON_COMMAND(C_ROTATE, OnSceneRotate)ON_UPDATE_COMMAND_UI(C_ROTATE, OnUpdateSceneRotate)ON_WM_PAINT()ON_COMMAND(ID_ORTHO, OnOrtho)ON_UPDATE_COMMAND_UI(ID_ORTHO, OnUpdateOrtho)ON_COMMAND(ID_PERSPECTIVE, OnPerspective)ON_UPDATE_COMMAND_UI(ID_PERSPECTIVE, OnUpdatePerspective)ON_COMMAND(ID_X_VIEW, OnXView)ON_COMMAND(ID_Y_VIEW, OnYView)ON_COMMAND(ID_Z_VIEW, OnZView)ON_COMMAND(ID_FREE_VIEW, OnFreeView)ON_UPDATE_COMMAND_UI(ID_X_VIEW, OnUpdateXView)ON_UPDATE_COMMAND_UI(ID_Y_VIEW, OnUpdateYView)ON_UPDATE_COMMAND_UI(ID_Z_VIEW, OnUpdateZView)ON_UPDATE_COMMAND_UI(ID_FREE_VIEW, OnUpdateFreeView)ON_COMMAND(ID_SHOW_COORDINATE_AXIS, OnShowCoordinateAxis) ON_UPDATE_COMMAND_UI(ID_SHOW_COORDINATE_AXIS, OnUpdateShowCoordinateAxis)ON_COMMAND(ID_DRAWMODE_SOLID, OnDrawmodeSolid)ON_UPDATE_COMMAND_UI(ID_DRAWMODE_SOLID, OnUpdateDrawmodeSolid)ON_COMMAND(ID_DRAWMODE_WIRE, OnDrawmodeWire)ON_UPDATE_COMMAND_UI(ID_DRAWMODE_WIRE, OnUpdateDrawmodeWire)ON_WM_SETCURSOR()ON_COMMAND(ID_DRAWMODE_POINTS, OnDrawmodePoints)ON_UPDATE_COMMAND_UI(ID_DRAWMODE_POINTS, OnUpdateDrawmodePoints)ON_COMMAND(ID_DRAWMODE_SILHOUETTE, OnDrawmodeSilhouette) ON_UPDATE_COMMAND_UI(ID_DRAWMODE_SILHOUETTE,OnUpdateDrawmodeSilhouette)ON_COMMAND(ID_DRAWMODE_ORIENTATION_INSIDE, OnDrawmodeOrientationInside)ON_UPDATE_COMMAND_UI(ID_DRAWMODE_ORIENTATION_INSIDE, OnUpdateDrawmodeOrientationInside)ON_COMMAND(ID_DRAWMODE_ORIENTATION_OUTSIDE, OnDrawmodeOrientationOutside)O N_UPDATE_COMMAND_UI(ID_DRAWMODE_ORIENTATION_OUTSIDE, OnUpdateDrawmodeOrientationOutside)ON_COMMAND(ID_DRAWMODE_SHADING_FLAT, OnDrawmodeShadingFlat)ON_UPDATE_COMMAND_UI(ID_DRAWMODE_SHADING_FLAT, OnUpdateDrawmodeShadingFlat)ON_COMMAND(ID_DRAWMODE_SHADING_NONE, OnDrawmodeShadingNone)ON_UPDATE_COMMAND_UI(ID_DRAWMODE_SHADING_NONE, OnUpdateDrawmodeShadingNone)ON_COMMAND(ID_DRAWMODE_SHADING_SMOOTH, OnDrawmodeShadingSmooth)ON_UPDATE_COMMAND_UI(ID_DRAWMODE_SHADING_SMOOTH, OnUpdateDrawmodeShadingSmooth)//}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CMFCGLView construction/destructionCMFCGLView::CMFCGLView(){// TODO: add construction code herem_pShape = gluNewQuadric();m_fLineWidth = 0.05;m_hGLContext = NULL;m_GLPixelIndex = 0;m_Action = SELECT;m_RotateAxis = AXIS_Z;m_bBuildList = FALSE;m_bOrtho = FALSE;m_ViewMode = FREE_VIEW;m_bShowAxis = TRUE;m_bSelection = FALSE;m_nDrawMode = SOLID;m_nDrawOrient = OUTSIDE;m_nShading = SMOOTH;}CMFCGLView::~CMFCGLView(){gluDeleteQuadric(m_pShape);}BOOL CMFCGLView::PreCreateWindow(CREATESTRUCT& cs) {// TODO: Modify the Window class or styles here by modifyingcs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS);return CView::PreCreateWindow(cs);}/////////////////////////////////////////////////////////////////////////////// CMFCGLView drawingvoid CMFCGLView::OnDraw(CDC* pDC){CMFCGLDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data here}/////////////////////////////////////////////////////////////////////////////// CMFCGLView printingBOOL CMFCGLView::OnPreparePrinting(CPrintInfo* pInfo) {// default preparationreturn DoPreparePrinting(pInfo);}void CMFCGLView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add extra initialization before printing}void CMFCGLView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add cleanup after printing}/////////////////////////////////////////////////////////////////////////////// CMFCGLView diagnostics#ifdef _DEBUGvoid CMFCGLView::AssertValid() const{CView::AssertValid();}void CMFCGLView::Dump(CDumpContext& dc) const{CView::Dump(dc);}CMFCGLDoc* CMFCGLView::GetDocument() // non-debug version is inline {ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCGLDoc))); return (CMFCGLDoc*)m_pDocument;}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CMFCGLView message handlersBOOL CMFCGLView::SetWindowPixelFormat(HDC hDC) {PIXELFORMATDESCRIPTOR pixelDesc;pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); pixelDesc.nVersion = 1;pixelDesc.dwFlags =PFD_DRAW_TO_WINDOW |PFD_SUPPORT_OPENGL |PFD_STEREO_DONTCARE|PFD_DOUBLEBUFFER;pixelDesc.iPixelType = PFD_TYPE_RGBA;olorBits = 32;pixelDesc.cRedBits = 8;pixelDesc.cRedShift = 16;pixelDesc.cGreenBits =8;pixelDesc.cGreenShift =8;pixelDesc.cBlueBits = 8;pixelDesc.cBlueShift = 0;pixelDesc.cAlphaBits = 0;pixelDesc.cAlphaShift = 0;pixelDesc.cAccumBits = 64;pixelDesc.cAccumRedBits = 16;pixelDesc.cAccumGreenBits = 16;pixelDesc.cAccumBlueBits = 16;pixelDesc.cAccumAlphaBits = 0;pixelDesc.cDepthBits = 32;pixelDesc.cStencilBits = 8;pixelDesc.cAuxBuffers = 0;pixelDesc.iLayerType = PFD_MAIN_PLANE;pixelDesc.bReserved = 0;pixelDesc.dwLayerMask = 0;pixelDesc.dwVisibleMask = 0;pixelDesc.dwDamageMask = 0;m_GLPixelIndex = ChoosePixelFormat( hDC, &pixelDesc); if (m_GLPixelIndex==0){m_GLPixelIndex = 1;if (DescribePixelFormat(hDC,m_GLPixelIndex,sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0){return FALSE;}}if (SetPixelFormat( hDC,m_GLPixelIndex,&pixelDesc)==FALSE){return FALSE;}return TRUE;}int CMFCGLView::OnCreate(LPCREATESTRUCT lpCreateStruct) {if (CView::OnCreate(lpCreateStruct) == -1)return -1;HWND hWnd = GetSafeHwnd();HDC hDC = ::GetDC(hWnd);if (SetWindowPixelFormat(hDC)==FALSE)return 0;if (CreateViewGLContext(hDC)==FALSE)return 0;SetTimer(0,100,NULL);return 0;}BOOL CMFCGLView::CreateViewGLContext(HDC hDC){m_hGLContext = wglCreateContext(hDC);if (m_hGLContext == NULL){return FALSE;}if (wglMakeCurrent(hDC, m_hGLContext)==FALSE) {return FALSE;}return TRUE;}void CMFCGLView::OnDestroy(){if(wglGetCurrentContext()!=NULL){wglMakeCurrent(NULL, NULL) ;}if (m_hGLContext!=NULL){wglDeleteContext(m_hGLContext);m_hGLContext = NULL;}CView::OnDestroy();}void CMFCGLView::OnSize(UINT nType, int cx, int cy) {CView::OnSize(nType, cx, cy);GLsizei width, height;GLdouble aspect;width = cx;height = cy;if (cy==0)aspect = (GLdouble)width;elseaspect = (GLdouble)width/(GLdouble)height; m_WHRatio=aspect;glViewport(0, 0, width, height);InitOpenGL();}void CMFCGLView::OnTimer(UINT nIDEvent) {CView::OnTimer(nIDEvent);}//override the virtual function to prevent the window redraw the window client BOOL CMFCGLView::OnEraseBkgnd(CDC* pDC){return FALSE;}void CMFCGLView::OnCameraPan(){m_Action = CAMERA_PAN;m_bSelection = FALSE;}void CMFCGLView::OnUpdateCameraPan(CCmdUI* pCmdUI){pCmdUI->SetCheck(m_Action==CAMERA_PAN);pCmdUI->Enable(m_ViewMode==FREE_VIEW);}void CMFCGLView::OnSELECTMODE(){m_Action = SELECT;m_bSelection = TRUE;}void CMFCGLView::OnUpdateSELECTMODE(CCmdUI* pCmdUI){pCmdUI->SetCheck(m_Action==SELECT);pCmdUI->Enable(m_ViewMode==FREE_VIEW);}void CMFCGLView::OnMouseMove(UINT nFlags, CPoint point) {DisplayWorldCoord(point);if(nFlags==MK_LBUTTON){int rx = point.x-m_OldPoint.x;int ry = point.y-m_OldPoint.y;switch(m_Action){case CAMERA_PAN:m_Camera.Offset(rx/100.0,-ry/100.0,0);break;case SCENE_ROTATE:m_Scene.RotateRoundAxis(rx/10,m_RotateAxis);break;}m_OldPoint=point;Invalidate();}if(nFlags==MK_RBUTTON){int rx=point.x-m_OldPoint.x;switch(m_Action){case CAMERA_PAN:m_Camera.Offset(0,0,rx/100.0);HCURSOR hCursor = NULL;CWinApp *cWinApp = AfxGetApp ();hCursor = cWinApp->LoadCursor (IDC_CUR_ZOOM);::SetCursor(hCursor);break;}m_OldPoint=point;Invalidate();}//DisplayWorldCoord(point);CView::OnMouseMove(nFlags, point);}void CMFCGLView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {if(nChar == VK_TAB && m_Action == SCENE_ROTATE)m_RotateAxis = (m_RotateAxis+1) %3;CView::OnKeyDown(nChar, nRepCnt, nFlags);}void CMFCGLView::OnLButtonDown(UINT nFlags, CPoint point) {m_OldPoint = point;UINT xPos = point.x;WORD yPos = point.y;if(m_bSelection == TRUE){ProcessSelection(xPos, yPos);}CView::OnLButtonDown(nFlags, point);}void CMFCGLView::OnRButtonDown(UINT nFlags, CPoint point) {m_OldPoint = point;HCURSOR hCursor = NULL;CWinApp *cWinApp = AfxGetApp ();if(m_Action == CAMERA_PAN){hCursor = cWinApp->LoadCursor (IDC_CUR_ZOOM);::SetCursor(hCursor);}CView::OnRButtonDown(nFlags, point);}void CMFCGLView::OnSceneRotate(){m_Action = SCENE_ROTATE;m_bSelection = FALSE;}void CMFCGLView::OnUpdateSceneRotate(CCmdUI* pCmdUI) {pCmdUI->SetCheck(m_Action == SCENE_ROTATE);pCmdUI->Enable(m_ViewMode==FREE_VIEW);}void CMFCGLView::OnPaint(){CPaintDC dc(this);glLoadIdentity();glClearColor(0.0,0.0,0.0,1);glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);CheckOrtho();SetViewMode();if(m_bShowAxis){glDisable(GL_DEPTH_TEST);CCoordinateAxis(2,2,2).Display();glEnable(GL_DEPTH_TEST);}RenderScene();SwapBuffers(dc.m_ps.hdc);}void CMFCGLView::OnOrtho(){if(m_bOrtho)return;else{m_bOrtho=TRUE;Invalidate();}}void CMFCGLView::OnUpdateOrtho(CCmdUI* pCmdUI){pCmdUI->SetCheck(m_bOrtho);}void CMFCGLView::OnPerspective(){if(!m_bOrtho)return;else{m_bOrtho=FALSE;Invalidate();}}void CMFCGLView::OnUpdatePerspective(CCmdUI* pCmdUI) {pCmdUI->SetCheck(!m_bOrtho);}void CMFCGLView::InitOpenGL(){glLineWidth(m_fLineWidth);glEnable(GL_LINE_SMOOTH);glFrontFace(GL_CW);glEnable(GL_CULL_FACE);glCullFace(GL_FRONT);glEnable(GL_LIGHTING);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_POSITION, lightPos);glEnable(GL_LIGHT0);glEnable(GL_COLOR_MATERIAL);glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);glDepthFunc(GL_LESS);glEnable(GL_DEPTH_TEST);glEnable(GL_NORMALIZE);}void CMFCGLView::OnXView(){m_ViewMode = X_VIEW;m_bOrtho = TRUE;Invalidate();}void CMFCGLView::OnYView(){m_ViewMode = Y_VIEW;m_bOrtho = TRUE;Invalidate();}void CMFCGLView::OnZView(){m_ViewMode = Z_VIEW;m_bOrtho = TRUE;Invalidate();}void CMFCGLView::OnFreeView(){m_ViewMode = FREE_VIEW;m_bOrtho = FALSE;Invalidate();}void CMFCGLView::OnUpdateXView(CCmdUI* pCmdUI) {pCmdUI->SetCheck(m_ViewMode == X_VIEW);}void CMFCGLView::OnUpdateYView(CCmdUI* pCmdUI) {pCmdUI->SetCheck(m_ViewMode == Y_VIEW);}void CMFCGLView::OnUpdateZView(CCmdUI* pCmdUI) {pCmdUI->SetCheck(m_ViewMode == Z_VIEW);}void CMFCGLView::OnUpdateFreeView(CCmdUI* pCmdUI) {pCmdUI->SetCheck(m_ViewMode == FREE_VIEW);}void CMFCGLView::SetViewMode(){glMatrixMode(GL_MODELVIEW);switch(m_ViewMode){case X_VIEW:gluLookAt(100,0,0,0,0,0,0,0,1);break;case Y_VIEW:gluLookAt(0,100,0,0,0,0,0,0,1);break;case Z_VIEW:gluLookAt(0,0,100,0,0,0,0,1,0);break;case FREE_VIEW:m_Camera.Apply();gluLookAt(5,5,2,0,0,0,0,0,1);m_Scene.Apply();break;}}void CMFCGLView::CheckOrtho() {if(!m_bOrtho){glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(35,m_WHRatio,1,1000); glMatrixMode(GL_MODELVIEW); }else{glMatrixMode(GL_PROJECTION);glLoadIdentity();glOrtho(-3*m_WHRatio,3*m_WHRatio,-3,3,-1000,1000);glMatrixMode(GL_MODELVIEW);}}void CMFCGLView::OnShowCoordinateAxis(){m_bShowAxis =! m_bShowAxis;Invalidate();}void CMFCGLView::OnUpdateShowCoordinateAxis(CCmdUI* pCmdUI) {pCmdUI->SetCheck(m_bShowAxis);}void CMFCGLView::OnDrawmodeSolid(){// TODO: Add your command handler code herem_nDrawMode = SOLID;InvalidateRect(NULL);}void CMFCGLView::OnUpdateDrawmodeSolid(CCmdUI* pCmdUI) {// TODO: Add your command update UI handler code herepCmdUI->SetCheck (m_nDrawMode == SOLID);}void CMFCGLView::OnDrawmodeWire(){// TODO: Add your command handler code herem_nDrawMode = WIRE;Invalidate();}void CMFCGLView::OnUpdateDrawmodeWire(CCmdUI* pCmdUI) {// TODO: Add your command update UI handler code herepCmdUI->SetCheck (m_nDrawMode == WIRE);}// Parse the selection buffer to see which planet/moon was selected void CMFCGLView::ProcessPlanet(GLuint *pSelectBuff){int id,count;char cMessage[64];count = pSelectBuff[0];id = pSelectBuff[3];if(m_Action == SELECT && m_bSelection){switch(id){case DISK:strcpy(cMessage,"Success: Selected Disk.");break;case SPHERE:strcpy(cMessage,"Success: Selected Sphere.");break;case CONE:strcpy(cMessage,"Success: Selected Cone.");break;case CYLINDER:strcpy(cMessage,"Success: Selected Cylinder.");break;case TEAPOT:strcpy(cMessage,"Success: Selected Teapot.");break;case TORUS:strcpy(cMessage,"Success: Selected Torus.");break;case CUBE:strcpy(cMessage,"Success: Selected Cube.");break;default:strcpy(cMessage,"Error - Nothing was clicked on!");break;}}AfxMessageBox(cMessage,0,0);}#define BUFFER_LENGTH 64void CMFCGLView::ProcessSelection(int xPos, int yPos) {GLuint selectBuff[BUFFER_LENGTH];GLint hits, viewport[4];glSelectBuffer(BUFFER_LENGTH, selectBuff);glGetIntegerv(GL_VIEWPORT, viewport);glMatrixMode(GL_PROJECTION);glPushMatrix();glRenderMode(GL_SELECT);glLoadIdentity();gluPickMatrix(xPos, viewport[3] - yPos, 2,2, viewport); gluPerspective(45.0f, m_WHRatio, 1.0, 425.0);RenderScene();hits = glRenderMode(GL_RENDER);if(hits == 1)ProcessPlanet(selectBuff);glMatrixMode(GL_PROJECTION);glPopMatrix();glMatrixMode(GL_MODELVIEW);}void CMFCGLView::RenderScene(){switch(m_nDrawMode){case SOLID:gluQuadricDrawStyle(m_pShape, GLU_FILL);break;case WIRE:gluQuadricDrawStyle(m_pShape, GLU_LINE);break;case POINTS:gluQuadricDrawStyle(m_pShape, GLU_POINT);break;case SILHOUETTE:gluQuadricDrawStyle(m_pShape, GLU_SILHOUETTE);break;}switch(m_nDrawOrient){case INSIDE:gluQuadricOrientation(m_pShape, GLU_INSIDE);break;case OUTSIDE:gluQuadricOrientation(m_pShape, GLU_OUTSIDE);break;}switch(m_nShading){case NONE:gluQuadricNormals(m_pShape, GLU_NONE);break;case FLAT:gluQuadricNormals(m_pShape, GLU_FLAT);break;case SMOOTH:gluQuadricNormals(m_pShape, GLU_SMOOTH);break;}glMatrixMode(GL_MODELVIEW);glPushMatrix();glInitNames();glPushName(0);glColor3ub(255,255,255);glLoadName(SPHERE);gluSphere( m_pShape, 1, 50, 50 );glPushMatrix();glColor3ub(255,255,255);glTranslatef(-3.0,0.0,0.0);glLoadName(CONE);gluCylinder( m_pShape, 1, 0, 2, 50, 50 );CCoordinateAxis(2,2,2).Display();glPopMatrix();glPushMatrix();glColor3ub(255,255,255);glTranslatef(0.0,2.0,0.0);glLoadName(CYLINDER);gluCylinder( m_pShape, 0.5, 0.5, 2, 50, 50 ); CCoordinateAxis(2,2,2).Display();glPopMatrix();glPushMatrix();glColor3ub(255,255,255);glTranslatef(-2.0,-2.0,0.0);glLoadName(DISK);gluDisk( m_pShape, 0.5, 1, 15, 25 );CCoordinateAxis(2,2,2).Display();glPopMatrix();switch(m_nDrawMode){case WIRE:glPushMatrix();glColor3ub(255,255,255);glTranslatef(2.0,2.0,0.0);glLoadName(TEAPOT);auxWireTeapot(0.5);CCoordinateAxis(2,2,2).Display();glPopMatrix();glPushMatrix();glColor3ub(255,255,255);glTranslatef(-2.0,-2.0,0.0);glLoadName(TORUS);auxWireTorus(0.3, 0.09);CCoordinateAxis(2,2,2).Display(); glPopMatrix();glPushMatrix();glColor3ub(255,255,255);glTranslatef(2.5,0.0,0.0);glLoadName(CUBE);auxWireCube(1.0);CCoordinateAxis(2,2,2).Display(); glPopMatrix();break;case SOLID:glPushMatrix();glColor3ub(255,255,255);glTranslatef(2.5,0.0,0.0);glLoadName(CUBE);auxSolidCube(1.0);CCoordinateAxis(2,2,2).Display(); glPopMatrix();glPushMatrix();glColor3ub(255,255,255);glTranslatef(-2.0,-2.0,0.0);glLoadName(TORUS);auxSolidTorus(0.3,0.09);CCoordinateAxis(2,2,2).Display();glPopMatrix();glPushMatrix();glColor3ub(255,255,255);glTranslatef(2.0,2.0,0.0);glLoadName(TEAPOT);auxSolidTeapot(0.5);CCoordinateAxis(2,2,2).Display();glPopMatrix();break;}glFlush();}BOOL CMFCGLView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message){// TODO: Add your message handler code here and/or call defaultif (nHitTest != HTCLIENT){return CView::OnSetCursor(pWnd, nHitTest, message);}HCURSOR hCursor = NULL;CWinApp *cWinApp = AfxGetApp ();switch (m_Action) {case SCENE_ROTATE:hCursor = cWinApp->LoadCursor (IDC_CUR_ROTATE);break;case CAMERA_PAN:hCursor = cWinApp->LoadCursor (IDC_CUR_MOVE);break;case SELECT:hCursor = cWinApp->LoadCursor (IDC_CUR_SELECT);break;default:hCursor = LoadCursor (NULL, IDC_ARROW);break;}if (hCursor) SetCursor (hCursor);return TRUE;}void CMFCGLView::OnDrawmodePoints(){// TODO: Add your command handler code herem_nDrawMode = POINTS;Invalidate();}void CMFCGLView::OnUpdateDrawmodePoints(CCmdUI* pCmdUI) {// TODO: Add your command update UI handler code herepCmdUI->SetCheck (m_nDrawMode == POINTS);}void CMFCGLView::OnDrawmodeSilhouette(){// TODO: Add your command handler code herem_nDrawMode = SILHOUETTE;Invalidate();}void CMFCGLView::OnUpdateDrawmodeSilhouette(CCmdUI* pCmdUI) {// TODO: Add your command update UI handler code herepCmdUI->SetCheck (m_nDrawMode == SILHOUETTE);}void CMFCGLView::OnDrawmodeOrientationInside(){// TODO: Add your command handler code herem_nDrawOrient = INSIDE;Invalidate();}void CMFCGLView::OnUpdateDrawmodeOrientationInside(CCmdUI* pCmdUI) {// TODO: Add your command update UI handler code herepCmdUI->SetCheck(m_nDrawOrient == INSIDE);}void CMFCGLView::OnDrawmodeOrientationOutside(){// TODO: Add your command handler code herem_nDrawOrient = OUTSIDE;Invalidate();}void CMFCGLView::OnUpdateDrawmodeOrientationOutside(CCmdUI* pCmdUI){// TODO: Add your command update UI handler code herepCmdUI->SetCheck(m_nDrawOrient == OUTSIDE);}void CMFCGLView::OnDrawmodeShadingFlat(){// TODO: Add your command handler code herem_nShading = FLAT;Invalidate();}void CMFCGLView::OnUpdateDrawmodeShadingFlat(CCmdUI* pCmdUI) {// TODO: Add your command update UI handler code herepCmdUI->SetCheck(m_nShading == FLAT);}void CMFCGLView::OnDrawmodeShadingNone(){// TODO: Add your command handler code herem_nShading = NONE;Invalidate();}void CMFCGLView::OnUpdateDrawmodeShadingNone(CCmdUI* pCmdUI) {// TODO: Add your command update UI handler code herepCmdUI->SetCheck(m_nShading == NONE);}void CMFCGLView::OnDrawmodeShadingSmooth(){// TODO: Add your command handler code herem_nShading = SMOOTH;Invalidate();}void CMFCGLView::OnUpdateDrawmodeShadingSmooth(CCmdUI* pCmdUI) {// TODO: Add your command update UI handler code herepCmdUI->SetCheck(m_nShading == SMOOTH);}void CMFCGLView::DisplayWorldCoord(CPoint point){// Display the world coordinates on the status barchar buf[80];CPoint x = point.x;CPoint y = point.y;CMainFrame* pFrame = (CMainFrame*) AfxGetApp()->m_pMainWnd;ASSERT(pFrame);CStatusBar* pStatus = &pFrame->m_wndStatusBar;ASSERT(pStatus);sprintf(buf, "X = %5.2f , Y= %5.2f \n", x, y);pStatus->SetPaneText(1, buf, TRUE);pStatus->Invalidate();}2)Camera.cpp代码#include "stdafx.h"#include "Camera.h"void MyMatrixMult(float* V1,float* V2,float* V3) {glPushMatrix();glLoadMatrixf(V1);glMultMatrixf(V2);glGetFloatv(GL_MODELVIEW_MATRIX,V3); glPopMatrix();}CTransferMatrix::CTransferMatrix(){MyIdentity();}void CTransferMatrix::MyIdentity(){int i;for(i=0;i<16;i++)Matrix[i]=0.0;for(i=0;i<16;i+=5)Matrix[i]=1.0;}void CTransferMatrix::Load(float* M){for(int i=0;i<16;i++)Matrix[i]=M[i];}CScene::CScene(){}void CScene::RotateRoundAxis(float r,int axis){ glPushMatrix();glLoadMatrixf(m_TransferMatrix.Matrix);if(axis==AXIS_X)glRotatef(r,1,0,0);if(axis==AXIS_Y)glRotatef(r,0,1,0);if(axis==AXIS_Z)glRotatef(r,0,0,1);float m_newMatrix[16];glGetFloatv(GL_MODELVIEW_MATRIX,m_newMatrix); m_TransferMatrix.Load(m_newMatrix);glPopMatrix();}void CScene::Apply(){glMultMatrixf(m_TransferMatrix.Matrix);}void CCamera::RotateRoundAxis(float r,int axis){glPushMatrix();glLoadMatrixf(m_TransferMatrix.Matrix);if(axis==AXIS_X)glRotatef(r,1,0,0);if(axis==AXIS_Y)glRotatef(r,0,1,0);if(axis==AXIS_Z)glRotatef(r,0,0,1);float m_newMatrix[16];glGetFloatv(GL_MODELVIEW_MATRIX,m_newMatrix); m_TransferMatrix.Load(m_newMatrix);glPopMatrix();}CCamera::CCamera(){}void CCamera::Offset(float x,float y,float z){glPushMatrix();glLoadIdentity();glTranslatef(x,y,z);float m_tempMatrix[16];float m_newMatrix[16];glGetFloatv(GL_MODELVIEW_MATRIX,m_newMatrix);MyMatrixMult(m_newMatrix,m_TransferMatrix.Matrix,m_newMatrix); m_TransferMatrix.Load(m_newMatrix);glPopMatrix();}void CCamera::Apply(){glMultMatrixf(m_TransferMatrix.Matrix);}。
openGL图形的旋转与平移

void reshape(GLsizei w, GLsizei h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-100.0, 100.0, -100.0, 100.0, 0.0, 100.0);
opengl图形的旋转与平移旋转图形平移图形的平移图形的旋转和平移旋转与平移图形的旋转平移和图的旋转
#include <GL/glut.h>
#include <math.h>
#include <stdlib.h>
#define PI 3.1415926535
GLsizei w=650, h=550;
}
void shrink()
{
fraction-=2.0;
if (fraction<-1பைடு நூலகம்.0)
fraction=-10.0;
glutPostRedisplay();
}
void rotate()
{
angle+=20.0;
if (angle>=360.0)
angle=0.0;
glutPostRedisplay();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void specialKeyFunc( int key, int x, int y)
{
switch(key)
{
case GLUT_KEY_LEFT:
moveleft();
break;
OpenGL 球面相机旋转算法

旋转作为三维开发的基本功能,在任何3D程序中都需要。
用户通过旋转来实现对模型各个面的浏览,形成直观印象。
球面相机旋转这种旋转方式用户体验方式要优于x轴y轴混合旋转方式,模型旋转的方向和鼠标移动方向保持一致。
下面给出一种“球面相机”实现旋转的方法。
原理:移动鼠标时,通过gluLookAt来改变视点的位置(采用增量的方式),而模型保持不动。
即:只进行视点变换,不进行模型变换。
下图是用户按下左键,在屏幕上移动的一段距离(从A移动到B)。
由于屏幕坐标y轴向下,为了与投影平面坐标系(传统笛卡尔坐标)保持一致。
AM = y1-y2; /*将消息代码描述*/BM = x2-x1;建立屏幕和投影变换近裁截面之间的对应关系(如下图)。
代码实现:1 void setSphereCameraPos()2 {3 // 左键未按下,直接返回4 if (!is_left_button_down)5 return;67 // 从聚焦点指向视点的向量 OA向量8 vector3dd a(eye-target);910 // 计算球面相机半径11 radius = a.getLength();1213 // 将其单位化14 a.normailize();1516 // 当前相机向上方向与a做叉乘,计算投影面水平向右方向向量u17 vector3dd u = upvector.crossProduct(a);18 // 将其单位化19 u.normailize();2021 // 计算相机向上方向在投影面上的投影向量即垂直向上的方向向量v22 vector3dd v = a.crossProduct(u);23 // 将其单位化24 v.normailize();2526 // 计算屏幕AB在投影面上对应的向量 AB向量27 vector3dd m = u*delta_point.x + v*delta_point.y;2829 // 计算m向量的长度30 double len = m.getLength();31 // 降低灵敏度32 len /= 20.0;3334 if (len>0.0)35 {36 // 角度AOB 弧度表示弧长/半径37 double x = len/radius;38 // 将AB向量单位化39 m.normailize();4041 // 按相反方向转动视点到C 从而使得按与鼠标移动一致的方向转动模型42 x = -1*x;43 // 计算新的相机位置 C44 eye = target+(a*cos(x) + m*sin(x))*radius;4546 // 计算新的相机向上方向47 upvector = v;48 }49 }消息代码1 LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window2 UINT uMsg,// Message For This Window3 WPARAM wParam,// Additional Message Information4 LPARAM lParam)// Additional Message Information5 {6 switch(uMsg) // Check For Windows Messages7 {8 case WM_LBUTTONDOWN:9 {10 is_left_button_down = true;11 pre_point.x = LOWORD(lParam);12 pre_point.y = HIWORD(lParam);1314 return 0;15 }1617 case WM_MOUSEMOVE:18 {19 if (is_left_button_down)20 {21 cur_pt.x = LOWORD(lParam);22 cur_pt.y = HIWORD(lParam);// delta_point为增量点23 delta_point.x= cur_pt.x-pre_point.x);// 保持屏幕坐标系和投影平面坐标系一致24 delta_point.y =-1*(cur_pt.y-pre_point.y);// 将当前点赋值给前一个点25 pre_point = cur_pt;26// 计算相机新的位置27 setSphereCameraPos();28 }30 return 0;31 }3233 case WM_LBUTTONUP:34 {35 is_left_button_down = false;36 return 0;37 }38 }3940 // Pass All Unhandled Messages To DefWindowProc41 return DefWindowProc(hWnd,uMsg,wParam,lParam);42 }43vector3dd类vector3dd1 class vector3dd2 {3 private:4 double x,y,z;56 public:7 vector3dd(){};8 vector3dd(double a, double b, double c){x=a;y=b;z=c;}9 vector3dd(const vector3dd& v){*this=v;}11 public:12 void operator=(const vector3dd& v){x=v.x;y=v.y;z=v.z;}13 vector3dd operator*(double a)14 {15 return vector3dd(a*x,a*y,a*z);16 }17 vector3dd operator+(const vector3dd& v)18 {19 return vector3dd(x+v.x,y+v.y,z+v.z);20 }21 vector3dd operator-(const vector3dd& v)22 {23 return vector3dd(x-v.x,y-v.y,z-v.z);24 }2526 public:27 double getX(){return x;}28 double getY(){return y;}29 double getZ(){return z;}3031 void setValue(double a, double b, double c)32 {33 x = a;34 y = b;35 z = c;36 }3738 double getLength()39 {40 return sqrt(x*x+y*y+z*z);41 }4243 void normailize()44 {45 double length = getLength();46 x/=length;47 y/=length;48 z/=length;49 }5051 void invert()52 {53 x*=-1;54 y*=-1;55 z*=-1;56 }5758 vector3dd crossProduct(const vector3dd& v)59 {60 return vector3dd(y*v.z-z*v.y,z*v.x-x*v.z,x*v.y-y*v.x);61 }6263 double dotProduct(const vector3dd& v)64 {65 return (x*v.x+y*v.y+z*v.z);66 }6768 void traceMsg()69 {70 fprintf(stdout, "%.7f, %.7f, %.7f\n", x, y, z);71 }72 };效果图:。
基于OpenGL的3D旋转魔方实现讲解

华中科技大学电子科学与技术系课程设计报告( 2010-- 2011年度第2 学期)名称:软件课程设计题目:基于OpenGL的3D旋转魔方实现院系:班级:学号:学生姓名:指导教师:设计周数:成绩:日期:年月日目录1.课程设计介绍............................................................................................ (2)1.1目的.............................................................................................................. (2)1.2内容.............................................................................................................. (2)1.3取得的成果 (2)2.程序分析..................................................................................................... (3)2.1 程序原理 (3)2.2 程序流程 (4)2.3 数据结构 (13)2.4 重要函数 (13)3.程序分析与结果演示 (16)3.1 成果演示 (16)3.2 程序分析 (17)4.出现过的问题 (18)5.心得和小节 (19)1.课程设计介绍1.1目的21世纪是高科技时代,是信息技术时代,而计算机技术无疑会引领各行各业,为我们带来一个全新的时代。
作为新世纪的接班人,我们必须拥有良好的计算机应用能力,才能跟上世界发展的大流,不至于在激烈的竞争中被淘汰。
而程序作为计算机的灵魂,因此编程能力对当代大学生来说至关重要。
OpenGL轨迹球实现的鼠标旋转

OpenGL:轨迹球实现的鼠标旋转轨迹球控制By Terence J. Grant 如果只用鼠标来控制你的模型是不是很酷?轨迹球可以帮你做到这一点,我将告诉你我的实现,你可以把它应用在你的工程里。
我的实现是基于Bretton Wade’s,它是基于Ken Shoemake’s 实现的,最初的版本,你可以从游戏编程指南这本图上找到。
但我还是修正了一些错误,并优化了它。
轨迹球实现的内容就是把二维的鼠标点映射到三维的轨迹球,并基于它完成旋转变化。
为了完成这个设想,首先我们把鼠标坐标映射到[-1,1]之间,它很简单:MousePt.X = ((MousePt.X / ((Width -1) / 2)) -1);MousePt.Y = -((MousePt.Y / ((Height -1) / 2))-1);这只是为了数学上的简化,下面我们计算这个长度,如果它大于轨迹球的边界,我们将简单的把z轴设为0,否则我们把z轴设置为这个二维点映射到球面上对应的z值。
一旦我们有了两个点,就可以计算它的法向量了和旋转角了。
下面我们从构造函数开始,完整的讲解这个类:ArcBall_t::ArcBall_t(GLfloat NewWidth, GLfloat NewHeight)当点击鼠标时,记录点击的位置void ArcBall_t::click(const Point2fT* NewPt)当拖动鼠标时,记录当前鼠标的位置,并计算出旋转的量。
void ArcBall_t::drag(const Point2fT* NewPt, Quat4fT* NewRot)如果窗口大小改变,设置鼠标移动的范围void ArcBall_t::setBounds(GLfloat NewWidth, GLfloat NewHeight)下面是完成计算所要用到的数据结果,都是一些矩阵和向量Matrix4fT Transform ={ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f };Matrix3fT LastRot = { 1.0f, 0.0f, 0.0f,0.0f, 1.0f, 0.0f,0.0f, 0.0f, 1.0f };Matrix3fT ThisRot = { 1.0f, 0.0f, 0.0f,0.0f, 1.0f, 0.0f,0.0f, 0.0f, 1.0f };ArcBallT ArcBall(640.0f, 480.0f);Point2fT MousePt;bool isClicked = false; // 是否点击鼠标bool isRClicked = false; // 是否右击鼠标bool isDragging = false; // 是否拖动在上面定义的变量中,transform是我们获得的最终的变换矩阵,lastRot是上一次鼠标拖动得到的旋转矩阵,thisRot为这次鼠标拖动得到的旋转矩阵。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
opengl中旋转公式推导
OpenGL是一个用于渲染2D和3D图形的开放式图形库。
在OpenGL中,旋转是一种常见的变换操作,用于将对象绕某个轴旋转一定角度。
本文将推导出OpenGL中旋转的公式,并解释其原理和应用。
在OpenGL中,旋转变换是通过一个旋转矩阵来实现的。
旋转矩阵可以描述物体绕某个轴旋转一定角度后的新位置。
假设我们要将一个物体绕原点的Z轴旋转,旋转角度为θ。
那么旋转矩阵可以表示为:
R = | cosθ -sinθ 0 |
| sinθ cosθ 0 |
| 0 0 1 |
其中,cosθ表示θ的余弦值,sinθ表示θ的正弦值。
通过将物体的顶点坐标与旋转矩阵相乘,可以得到旋转后的新顶点坐标。
下面我们来推导一下这个旋转矩阵的公式。
假设物体的原始坐标为P(x, y, z),旋转后的新坐标为P'(x', y', z')。
我们可以表示P为一个列向量:
P = | x |
| y |
| z |
旋转矩阵R作用于P,得到P'的计算公式为:
P' = R * P
展开矩阵乘法,可以得到:
P' = | cosθ -sinθ 0 | * | x |
| y |
| z |
经过计算,可以得到:
x' = x * cosθ - y * sinθ
y' = x * sinθ + y * cosθ
z' = z
这就是物体绕Z轴旋转θ角度后的新坐标公式。
同样的,我们可以推导出绕X轴和Y轴旋转的公式,分别为:
绕X轴旋转:
x' = x
y' = y * cosθ - z * sinθ
z' = y * sinθ + z * cosθ
绕Y轴旋转:
x' = x * cosθ + z * sinθ
y' = y
z' = -x * sinθ + z * cosθ
这三个公式分别描述了物体绕X轴、Y轴和Z轴旋转后的新坐标计算方式。
在OpenGL中,我们可以通过调用旋转函数来实现物体的旋转变换。
例如,glRotatef(angle, x, y, z)函数可以将物体绕任意轴旋转angle 角度。
其中,(x, y, z)表示旋转轴的方向向量。
旋转变换在计算机图形学中具有广泛的应用。
通过旋转变换,我们可以实现物体的平移、缩放、旋转等复杂的变换效果。
例如,在三维建模中,我们可以通过旋转变换来调整物体的朝向和角度;在游戏开发中,我们可以通过旋转变换来实现角色的转向和动作。
总结一下,OpenGL中旋转的公式是通过旋转矩阵来实现的。
旋转矩阵描述了物体绕某个轴旋转一定角度后的新位置。
通过将物体的顶点坐标与旋转矩阵相乘,可以得到旋转后的新顶点坐标。
在实际应用中,我们可以通过调用旋转函数来实现物体的旋转变换,从而实现更加生动逼真的图形效果。
通过学习和掌握旋转变换的原理和公式,我们可以更好地理解和应用OpenGL中的旋转操作。