一、环境配置
参考链接:计算机图形学OpenGL中的MFC框架划线功能实现
二、画线功能实现
(一) 基本思路
鼠标按下时确定绘制起点,抬起时确定终点,两点自动连线即可。需要用到鼠标响应函数和画线函数。参考链接:MFC之绘制线条
(二) 开始画线
MFC中能直接调用 MoveToEx 和 LineTo 函数画线,或者使用 SetPixel 函数一个点一个点地把直线描出来。这两种方法都非常的便捷,但是!好巧不巧,我们想用的是OpenGL库里的 glVertex 方法。这就有点折磨了……
1. 首先要有一个坐标变换
是的没错画个线居然要涉及到坐标变换。参考 MFC坐标系之间的关系 我们可以发现,鼠标坐标的原点是在左上角,长宽貌似为视口长宽(cx,cy);而视口的坐标原点是在视口中心,高度固定为2(即无论视口大小高度都为2),宽度则为2*cx/cy。结合老师画的图更好理解:
所以二者的对应关系是这样:
//传入鼠标坐标
float x,y;
CRect rc;
GetClientRect(rc);
/*
输出视口长宽信息
CString strDlg;
strDlg.Format(L"%d,%d,%d,%d", rc.left, rc.top, rc.right, rc.bottom);
MessageBox(strDlg);
*/
float width = rc.right - rc.left;
float height = rc.top - rc.bottom;
// 变换为视口坐标
// x = -(x / width * width / height * 2 - width / height);
x = (width - 2 * x) / height;
y = y / height * 2 + 1;
这时在Display函数里就能用glVertex2f函数正常画线了!
2. 数组存储多条线段
要想避免画好的线段直接被扬了,就得把它好好地保存下来,以后每次调用Display函数都再画一次。定义一个CPoint类型的二维数组,在鼠标抬起时存入线段即可:
CPoint linePoints[1000][2];
// linePoints[x][0]是起点,linePoints[x][1]是终点,x代表线段数
3. DDA算法沿线画圆
参考链接:DDA直线生成算法|MFC|计算机图形学
就是我们的坐标都是浮点型的,算着可能会慢点?
画圆也是用OpenGL的方法就好了:
glBegin(GL_TRIANGLE_FAN);
for (int i = 0; i <= 360; i += 30)
{
float p = (float)(i * 3.14 / 180);
glVertex2f(x + (float)sin(p) * gridGap * 0.5f, y + (float)cos(p) * gridGap * 0.5f);
// 起点(x,y),半径是网格gridGap的一半
}
glEnd();