900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 平移变换计算机图形学c语言代码 计算机图形学第一次作业——平移 缩放和旋转...

平移变换计算机图形学c语言代码 计算机图形学第一次作业——平移 缩放和旋转...

时间:2022-01-02 12:23:41

相关推荐

平移变换计算机图形学c语言代码 计算机图形学第一次作业——平移 缩放和旋转...

一、

MFC

框架下使用

OpenGL

绘图演示平移、旋转、缩放等操作的具体实现

二、

实现算法

绘制的图形以各种顶点及顶点之间的线、面构成

要想对这些图形进行操作,只需要对各种顶点在坐标系中的坐标进行转换即可

顶点在

OpenGL

中的坐标以四维形式表示:(

X,Y,Z,W

)

其中

X,Y,Z

对应三维系统中

X

Y

Z

三个柚;

W

默认为

1

,一般为了方便各种操作时坐标换算而将三维坐标系提升为四次,即齐次坐标系。

平移操作——对应

glTranslate

函数:

初始点:(

X,Y,Z,W

)

使用转换矩阵

TMatrix

1, 0, 0, Tx

0, 1, 0, Ty

0, 0, 1, Tz

0, 0, 0, 1

(X’, Y’, Z’) =

TMatrix * (X, Y, Z),

其中

Tx

Ty

Tz

对应

glTranslate

函数中的三个参数,分别表示三个方向的的平移量;原始坐标右乘平移矩阵后即得到新的坐标

缩放操作——对应

glScale

函数:

使用转换矩阵为

SMatrix

Sx, 0, 0, 0

0, Sy, 0, 0

0, 0, Sz, 0

0, 0, 0, 1

(X’, Y’, Z’) =

SMatrix * (X, Y, Z)

此次自己实现的缩放函数与

OpenGL

有所不同,我实现的是与图形的中心点为基准进行缩放,所以进行矩阵变换前需要计算各个坐标的位置并求几何中心。

旋转操作——对应

glRotate

函数(逆时针方向):

在三维坐标系统中,旋转操作与二维情况有所不同,因为三维中的一个点可以绕不同的方向进行旋转,所以除了要指定旋转角度外,还要指定旋转轴

当所取旋转轴为

X

Y

Z

三个坐标轴时,与二维情况相似

即所选取的轴那一方向上的坐标不变,在其它两个轴所成的平面上进行二维旋转变换

根据这个规律可以把三维中绕任意轴旋转的操作分为几个操作来完成

步骤:

先将待旋转的坐标与旋转轴平移,使旋转轴经过原点

进行若干次旋转操作,例旋转轴与

Z

轴正向重合

依据对坐标轴旋转的方法将待旋转坐标进行旋转操作

应用逆旋转使旋转轴回到原方向

应用逆平移使旋转轴回到原位置

二维情况下旋转矩阵为:

cosQ, -sinQ, 0

sinQ, cosQ, 0

0, 0, 1

此次采用先绕

X

转做旋转

Rx

,再绕

Y

转旋转

Ry

使旋转轴与

Z

转正向重合,再绕

Z

轴做

Rz

旋转

Q

度,再进行逆操作还原位置

: (X’, Y’, Z’) = Rx*Ry*Rz(Q)*(Ry

-1

)*(Rx-1)

其中

Q

是需要旋转的角度,

逆矩阵

A

-1

= A*/|A|

代数余子式:

(-1)^(i+j)Aij

三、

程序结构

使用

MFC

生成程序界面,

OpenGL

负责绘制图形

文档

/

视图结构

文件数据为,图形的类型以及各个顶点坐标

从菜单中选择要进行的操作:平移,旋转,缩放后出现对话框输入参数

平移——

3

个参数,分别表示

X,Y,Z

各个轴向的平移量

旋转——

4

个参数,第一个角度

Angle,

后三个表示转轴向量

缩放——

3

个参数,表示

X,Y,Z

轴方向上的缩放比例,可以为负数

文件数据为:

一个

CArray

Point> m_PointArray

保存图形的各个顶点信息

一个表示图形形状的

int m_nShape

表示

glBegin

函数里的参数

四、

MFC

中使用

OpenGL

绘图

具体还没有研究,只是照搬网上教程,以后补上

View

头文件中加入

HGLRC m_hRC;//Rendering

Context

CDC* m_pDC;//Device

Context

BOOL InitializeOpenGL();//Initialize OpenGL

BOOL SetupPixelFormat();//Set up the Pixel Format

实现部分:

InitializeOpenGL

BOOLCHomeWork1View::InitializeOpenGL()

{

//

GetaDCfortheClientArea

m_pDC

=

new

CClientDC(

this

);

//

FailuretoGetDC

if

(m_pDC

==

NULL)

{

MessageBox(_T(

"

ErrorObtainingDC

"

));

return

FALSE;

}

//

Failuretosetthepixelformat

if

(

!

SetupPixelFormat())

{

return

FALSE;

}

//

CreateRenderingContext

m_hRC

=

::wglCreateContext(m_pDC

->

GetSafeHdc());

//

FailuretoCreateRenderingContext

if

(m_hRC

==

0

)

{

MessageBox(_T(

"

ErrorCreatingRC

"

));

return

FALSE;

}

//

MaketheRCCurrent

if

(::wglMakeCurrent(m_pDC

->

GetSafeHdc(),m_hRC)

==

FALSE)

{

MessageBox(_T(

"

ErrormakingRCCurrent

"

));

return

FALSE;

}

//

SpecifyBlackastheclearcolor

::glClearColor(

0.0f

,

0.0f

,

0.0f

,

0.0f

);

//

Specifythebackofthebufferascleardepth

::glClearDepth(

1.0f

);

//

EnableDepthTesting

::glEnable(GL_DEPTH_TEST);

return

TRUE;

}

SetupPixelFormat

BOOLCHomeWork1View::SetupPixelFormat()

{

static

PIXELFORMATDESCRIPTORpfd

=

{

sizeof

(PIXELFORMATDESCRIPTOR),

//

sizeofthispfd

1

,

//

versionnumber

PFD_DRAW_TO_WINDOW

|

//

supportwindow

PFD_SUPPORT_OPENGL

|

//

supportOpenGL

PFD_DOUBLEBUFFER,

//

doublebuffered

PFD_TYPE_RGBA,

//

RGBAtype

24

,

//

24-bitcolordepth

0

,

0

,

0

,

0

,

0

,

0

,

//

colorbitsignored

0

,

//

noalphabuffer

0

,

//

shiftbitignored

0

,

//

noaccumulationbuffer

0

,

0

,

0

,

0

,

//

accumbitsignored

16

,

//

16-bitz-buffer

0

,

//

nostencilbuffer

0

,

//

noauxiliarybuffer

PFD_MAIN_PLANE,

//

mainlayer

0

,

//

reserved

0

,

0

,

0

//

layermasksignored

};

int

m_nPixelFormat

=

::ChoosePixelFormat(m_pDC

->

GetSafeHdc(),

&

pfd);

if

(m_nPixelFormat

==

0

)

{

return

FALSE;

}

if

(::SetPixelFormat(m_pDC

->

GetSafeHdc(),m_nPixelFormat,

&

pfd)

==

FALSE)

{

return

FALSE;

}

return

TRUE;

}

此外需要将

View

类中的

OnEraseBkgnd

消息屏蔽掉,使之直接返回

TRUE

,因为消除背景的工作已经将由

OpenGL

来做,不需要由这个函数再来做一遍。

PreCreateWindow

函数中修改

cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

保证

OpenGL

不会绘制到其它窗口中去

OnCreate

函数中调用

InitializeOpenGL

函数就可以在

View

中进行绘制了

另外,为了适应窗口大小变化,还需要在

OnSize

函数中加入高速视域的代码

OnSize

void

CHomeWork1View::OnSize(UINTnType,

int

cx,

int

cy)

{

CView::OnSize(nType,cx,cy);

//

TODO:在此处添加消息处理程序代码

GLdoubleaspect_ratio;

//

width/heightratio

if

(

0

>=

cx

||

0

>=

cy)

{

return

;

}

//

selectthefullclientarea

::glViewport(

0

,

0

,cx,cy);

//

computetheaspectratio

//

thiswillkeepalldimensionscalesequal

aspect_ratio

=

(GLdouble)cx

/

(GLdouble)cy;

//

selecttheprojectionmatrixandclearit

::glMatrixMode(GL_PROJECTION);

::glLoadIdentity();

//

selecttheviewingvolume

::gluPerspective(

120

,aspect_ratio,

1.0f

,

150.0f

);

//

switchbacktothemodelviewmatrixandclearit

::glMatrixMode(GL_MODELVIEW);

::glLoadIdentity();

}

做好一切准备工作后,就可以在

OnDraw

中使用

OpenGL

函数进行绘制了,不过别忘了程序最后要进行资源的释放,在

OnDestroy

中加入清理工作

OnDestroy

void

CHomeWork1View::OnDestroy()

{

CView::OnDestroy();

//

TODO:在此处添加消息处理程序代码

//

MaketheRCnon-current

if

(::wglMakeCurrent(

0

,

0

)

==

FALSE)

{

MessageBox(_T(

"

CouldnotmakeRCnon-current

"

));

}

//

Deletetherenderingcontext

if

(::wglDeleteContext(m_hRC)

==

FALSE)

{

MessageBox(_T(

"

CouldnotdeleteRC

"

));

}

//

DeletetheDC

if

(m_pDC)

{

deletem_pDC;

}

//

SetittoNULL

m_pDC

=

NULL;

}

最后程序演示结果:

五、

编程中遇到的问题总结

1.

复习了操作符重载的相关内容

2.

浮点数的比较,这个比较重要,以前在课上只是听说,没有特别印象,在耗费了我

2

个小时的调试之后,以后应该再也不会忘了。

Fabs

(

f1-f2

)

<=

精度要求

3.

此次写的工具类

Matrix

胜于处理向量,矩阵的相关操作,因为偷懒还不太完善,尤其是矩阵的一些操作比较求模,求逆都没有实现,以后补上

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。