MFC按方向键旋转立方体线框

MFC按方向键旋转立方体线框
Author: W
我想让三维的正方体线框可以通过按键盘方向键旋转起来,我把这个分成两步:一 绘制立方体线框;二 几何变换让其旋 转。

一,绘制立方体线框:

立方体共有六个表面,八个顶点, 每个表面有四个顶点
假定正方体中心位于三维坐标系原点,边长2a
可以写出立方体的顶点表(CP3 P[8],每个点的三维坐标)
可以写出立方体的面表 (每个面的四个顶点对应的索引号 四个面 CFacet F[4],索引号int pIndex[4] )

  1. 在CTestView里添加函数 ReadPoint() 读入立方体点表
    void CTestView::ReadPoint()//点表 { //顶点的三维坐标(x,y,z),立方体边长为2a double a=160.0; P[0].x=-a;P[0].y=-a;P[0].z=-a; P[1].x=+a;P[1].y=-a;P[1].z=-a; P[2].x=+a;P[2].y=+a;P[2].z=-a; P[3].x=-a;P[3].y=+a;P[3].z=-a; P[4].x=-a;P[4].y=-a;P[4].z=+a; P[5].x=+a;P[5].y=-a;P[5].z=+a; P[6].x=+a;P[6].y=+a;P[6].z=+a; P[7].x=-a;P[7].y=+a;P[7].z=+a; }

2.在CTestView里添加函数 ReadFacet() 读入立方体面表

void CTestView::ReadFacet()//面表 { //面的顶点数和面的顶点索引 F[0].pIndex[0]=4; F[0].pIndex[1]=5; F[0].pIndex[2]=6; F[0].pIndex[3]=7;//前面 F[1].pIndex[0]=0; F[1].pIndex[1]=3; F[1].pIndex[2]=2; F[1].pIndex[3]=1;//后面 F[2].pIndex[0]=0; F[2].pIndex[1]=4; F[2].pIndex[2]=7; F[2].pIndex[3]=3;//左面 F[3].pIndex[0]=1; F[3].pIndex[1]=2; F[3].pIndex[2]=6; F[3].pIndex[3]=5;//右面 F[4].pIndex[0]=2; F[4].pIndex[1]=3; F[4].pIndex[2]=7; F[4].pIndex[3]=6;//顶面 F[5].pIndex[0]=0; F[5].pIndex[1]=1; F[5].pIndex[2]=5; F[5].pIndex[3]=4;//底面 }

注:需要在CTestView的构造函数中调用ReadPoint() 和ReadFacet()读入点面和面表

3.在CTestView 里添加DrawGraph() 绘制立方体线框
循环访问立方体的每个表面(for (int nFacet=0;nFacet<6;nFacet++))
顶点循环,根据面的索引号F[nFacet].pIndex 找到每个顶点,对其做二维投影
连接二维投影点,闭合多边形线框

void CTestView::DrawGraph(CDC* pDC)//绘制立方体线框 { CPoint ScreenP[4]; //二维投影点 for(int nFacet=0;nFacet<6;nFacet++)//面循环 { for(int nPoint=0;nPoint<4;nPoint++)//顶点循环 { ScreenP[nPoint].x=P[F[nFacet].pIndex[nPoint]].x; //第nPoint个二维投影点=第nFacet个面的第nPoint个索引号找到的点的横坐标 ScreenP[nPoint].y=P[F[nFacet].pIndex[nPoint]].y; } pDC->MoveTo(ScreenP[0].x,ScreenP[0].y); pDC->LineTo(ScreenP[1].x,ScreenP[1].y); pDC->LineTo(ScreenP[2].x,ScreenP[2].y); pDC->LineTo(ScreenP[3].x,ScreenP[3].y); pDC->LineTo(ScreenP[0].x,ScreenP[0].y);//闭合多边形 } }

4.双缓冲
CTestView类的OnDraw函数调用双缓冲函数DoubleBuffer(),双缓冲函数DoubleBuffer()中调用DrawGraph()函数
向内存中绘制立方体线框模型
void CTestView::DoubleBuffer(CDC* pDC)//双缓冲 { CRect rect;//定义客户区矩形 GetClientRect(&rect);//获得客户区的大小 pDC->SetMapMode(MM_ANISOTROPIC);//pDC自定义坐标系 pDC->SetWindowExt(rect.Width(),rect.Height());//设置窗口范围 pDC->SetViewportExt(rect.Width(),-rect.Height());//设置视区范围,x轴水平向右,y轴垂直向上 pDC->SetViewportOrg(rect.Width()/2,rect.Height()/2);//客户区中心为原点 CDC memDC;//内存DC memDC.CreateCompatibleDC(pDC);//创建一个与显示pDC兼容的内存memDC CBitmap NewBitmap,*pOldBitmap;//内存中承载的临时位图 NewBitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());//创建兼容位图 pOldBitmap=memDC.SelectObject(&NewBitmap);//将兼容位图选入memDC memDC.FillSolidRect(rect,pDC->GetBkColor());//按原来背景填充客户区,否则是黑色 memDC.SetMapMode(MM_ANISOTROPIC);//memDC自定义坐标系 memDC.SetWindowExt(rect.Width(),rect.Height()); memDC.SetViewportExt(rect.Width(),-rect.Height()); memDC.SetViewportOrg(rect.Width()/2,rect.Height()/2); rect.OffsetRect(-rect.Width()/2,-rect.Height()/2); DrawGraph(&memDC);//向memDC绘制图形 pDC->BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),&memDC,-rect.Width()/2,-rect.Height()/2,SRCCOPY);//将内存memDC中的位图拷贝到显示pDC中 memDC.SelectObject(pOldBitmap);//恢复位图 NewBitmap.DeleteObject();//删除位图 memDC.DeleteDC();//删除memDC }

二,通过键盘方向键旋转立方体
由于使用了双缓冲,因此程序支持动画和交互操作
向CTestView添加WM_KEYDOWN的消息映射函数OnKeyDown后 使用三维几何变换实现绕x轴和绕y轴的旋转
需要添加三维变换类CTransform3
需要在CTestView头文件里添加一个CTransform3类的对象tran 通过对象调用成员函数
需要在CTestView的构造函数中对绕x轴和y轴的旋转角Alpha Bate初始化为0,同时调用CTransform3类的对象tran的函数SetMatrix(CP3,ptNumber) tran.SetMatrix(P,8);把顶点坐标和顶点个数传给CTransform3类
在消息映射函数OnKeyDown中 调用tran.RotateX(Alpha) 和 tran.RotateX(Bate) 实现不同按键下不同方向的变换

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值