write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie
讨论新闻组及文件
OpenGL系列文章都已经写到3D部分了,但是感觉2D的例子还是少了点,特意弄个外篇,引入一些稍微复杂的例子,这些例子不适合作为概念介绍时写入此系列文章,只好独立成篇,自己完成一个就发布一个吧。
此次完成的是一个七巧板图形的绘制,绘制时参考了网上的七巧板程序的颜色(此处
),因为我仅仅是为了加深对OpenGL的学习,没有添加具体的真实游戏代码,仅仅只有OpenGL图形绘制的演示。
另外,因为作为学习OpenGL例子之用,自然要使用OpenGL来绘制啦,虽然这么简单的图形根本用不着OpenGL,别说我用大炮打苍蝇,用牛刀杀鸡-_-!因为是学习OpenGL嘛,所以在2D坐标系中还是使用了OpenGL的坐标系,并且,为了追求显示的完美(主要是旋转的),我选取了所有图形的重心作为每个图形的坐标系的原点,这样旋转时的中心就是每个图形的中心,这样比使用rgnbox获取边框然后取中心旋转效果要好,具体的旋转效果需要自己添加代码去尝试了,Rotate和RotateTo的实现已经有了。添加到绘制部分即可。
下面简单介绍一下所有源代码。
所有的七巧板图形全部继承自CGLShape,此类实现如下
// 此类实现移动,旋转,
class
CGLShape
{
public
:
CGLShape(void
)
{
mfPosX = 0.0;
mfPosY = 0.0;
memset(mfvColor, 0, sizeof
(mfvColor));
mfDegree = 0.0;
mfSize = 1.0;
}
virtual
~CGLShape(void
) { }
void
SetSize(GLfloat afSize) { mfSize = afSize; }
void
SetColor(GLfloat afRed, GLfloat afGreen, GLfloat afBlue, GLfloat afAlpha = 1.0)
{
mfvColor[0] = afRed;
mfvColor[1] = afGreen;
mfvColor[2] = afBlue;
mfvColor[3] = afAlpha;
}
// 相对偏移(外部坐标系长度)
void
Move(int
aiPosX, int
aiPosY)
{
mfPosX += 2.0f * aiPosX/(float
)WIDTH;
mfPosY += -(2.0f * aiPosY/(float
)HEIGHT);
}
// 移动到的位置(Windows坐标系点)
void
MoveTo(int
aiPosX, int
aiPosY)
{
mfPosX = (2.0f * aiPosX - (float
)WIDTH) / (float
)WIDTH;
mfPosY = -(2.0f * aiPosY - (float
)HEIGHT) / (float
)HEIGHT;
}
// 旋转,以逆时针为正方向
void
Rotate(GLfloat aiDegree) { mfDegree += aiDegree; }
// 旋转到
void
RotateTo(GLfloat aiDegree) { mfDegree = aiDegree; }
// OpenGL坐标系
void
SetPos(GLfloat afPosX, GLfloat afPosY) { mfPosX = afPosX; mfPosY = afPosY; }
void
GetPos(GLfloat& afPosX, GLfloat& afPosY) { afPosX = mfPosX; afPosY = mfPosY; }
void
Draw()
{
glLoadIdentity();
glColor4fv(mfvColor);
glPushMatrix();
glTranslatef(mfPosX, mfPosY, 0.0);
glRotatef(mfDegree, 0.0, 0.0, 1.0);
DrawImp();
glPopMatrix();
}
protected
:
// 重绘时需要调用的函数,由各子类实现
virtual
void
DrawImp() = 0;
// 位置信息,没有用POINT是为了将来方便移植
GLfloat mfPosX;
GLfloat mfPosY;
// 颜色
GLfloat mfvColor[4];
// 旋转度数
GLfloat mfDegree;
// 大小
GLfloat mfSize;
};
大小,颜色,旋转角度都以成员变量的方式保存在CGLShape中,并且在Draw函数中已经实际的完成了使用,具体的DrawImp交由子类实现,完成具体图形的绘制。(此处使用template模式)具体的各个实现按照七巧板的要求如下:
三角形:
class
CGLTriangle : public
CGLShape
{
public
:
CGLTriangle() { }
virtual
~CGLTriangle() { }
// 重绘时需要调用的函数,由各子类实现
virtual
void
DrawImp()
{
static
GLfloat fvTop[3] = { 0.0, (1.0/3.0), 0.0};
static
GLfloat fvLeftBottom[3] = { -0.5, -(1.0/6.0), 0.0};
static
GLfloat fvRightBottom[3] = { 0.5, -(1.0/6.0), 0.0};
GLfloat fvSizeTop[3] = {fvTop[0], fvTop[1] * mfSize, fvTop[2]};
GLfloat fvSizeLeftBottom[3] = {fvLeftBottom[0] * mfSize, fvLeftBottom[1] * mfSize, fvLeftBottom[2]};
GLfloat fvSizeRightBottom[3] = {fvRightBottom[0] * mfSize, fvRightBottom[1] * mfSize, fvRightBottom[2]};
glBegin(GL_TRIANGLES);
glVertex3fv(fvSizeTop);
glVertex3fv(fvSizeLeftBottom);
glVertex3fv(fvSizeRightBottom);
glEnd();
}
};
实际上DrawImp仅仅关心绘制一个三角形而已,这里因为其他图形只有一个,所以不关心大小,而三角形在七巧板中有多个,所以将大小的计算放在三角形中,独立计算大小,事实上更通用的办法是在CShape的Draw函数中用glScale实现。三角形的3个顶点的坐标相对来说还比较容易计算。
矩形:
class
CGLRectangle: public
CGLShape
{
public
:
CGLRectangle() { }
virtual
~CGLRectangle() { }
// 重绘时需要调用的函数,由各子类实现
virtual
void
DrawImp()
{
static
GLfloat fLength = sqrt(2.0)/4.0;
static
GLfloat fLengthHalf = fLength/2.0;
static
GLfloat fvLeftTop[3] = { -fLengthHalf, fLengthHalf, 0.0};
static
GLfloat fvRightTop[3] = { fLengthHalf, fLengthHalf, 0.0};
static
GLfloat fvLeftBottom[3] = { -fLengthHalf, -fLengthHalf, 0.0};
static
GLfloat fvRightBottom[3] = { fLengthHalf, -fLengthHalf, 0.0};
// TODO:因为七角板此例中方形只有一个不需要考虑大小,暂时不计算大小
glColor4fv(mfvColor);
glPushMatrix();
glBegin(GL_QUADS);
glVertex3fv(fvLeftTop);
glVertex3fv(fvRightTop);
glVertex3fv(fvRightBottom);
glVertex3fv(fvLeftBottom);
glEnd();
glPopMatrix();
}
};
很简单,不多说了,DrawImp实现一个矩形的绘制而已。四个顶点的坐标时最容易计算的。
平行四边形:
class
CGLParallelogram: public
CGLShape
{
public
:
CGLParallelogram() { }
virtual
~CGLParallelogram() { }
// 重绘时需要调用的函数,由各子类实现
virtual
void
DrawImp()
{
static
GLfloat fRightBottomX = 0.375;
static
GLfloat fHeight = 0.25;
static
GLfloat fvLeftTop[3] = { -fRightBottomX, fHeight/2.0, 0.0};
static
GLfloat fvRightTop[3] = { 0.5-fRightBottomX, fHeight/2, 0.0};
static
GLfloat fvLeftBottom[3] = { fRightBottomX-0.5, -fHeight/2.0, 0.0};
static
GLfloat fvRightBottom[3] = { fRightBottomX, -fHeight/2.0, 0.0};
// TODO:因为七角板此例中四边形只有一个不需要考虑大小,暂时不计算大小
glColor4fv(mfvColor);
glPushMatrix();
glRotatef(mfDegree, 0.0, 0.0, 1.0);
glBegin(GL_QUADS);
glVertex3fv(fvLeftTop);
glVertex3fv(fvRightTop);
glVertex3fv(fvRightBottom);
glVertex3fv(fvLeftBottom);
glEnd();
glPopMatrix();
}
};
绘制是同样简单,但是在以平行四边形的重心为原点的坐标系中,计算平时四边形的4个顶点的坐标需要一定的计算量,上述那几个数值可不是随便掰出来的啊。
将上述图形组合在一起
CGLTriangle gTriBTop; // 上方的大三角形
CGLTriangle gTriBRight; // 右边的大三角形
CGLTriangle gTriSLeft; // 左上方的小上角形
CGLTriangle gTriSMid; // 中间的小三角形
CGLTriangle gTriMLeft; // 左下方的中三角形
CGLRectangle gRectangle; // 唯一的正方形
CGLParallelogram gParal; // 唯一的平行四边形
//OpenGL初始化开始
void
SceneInit(int
w,int
h)
{
GLenum err = glewInit();
if
(err != GLEW_OK)
{
MessageBox(NULL, _T("Error"
), _T("Glew init failed."
), MB_OK);
exit(-1);
}
gTriBTop.SetColor(1.0, 0.0, 0.0); // 上方的大三角形,红色,
gTriBTop.SetPos(0.0, 1.0/3.0);
gTriBTop.RotateTo(180.0);
gTriBRight.SetColor(0.0, 0.0, 1.0); // 右边的大三角形,蓝色
gTriBRight.SetPos(1.0/3.0, 0.0);
gTriBRight.RotateTo(90.0);
gTriSLeft.SetColor(1.0, 1.0, 0.0); // 左上方的小上角形,黄色
gTriSLeft.SetSize(0.5); // 小三角形只有大的一半大
gTriSLeft.SetPos(-(5.0/12.0), 0.25);
gTriSLeft.RotateTo(-90.0);
gRectangle.SetColor(1.0, 175.0/255.0, 175.0/255.0); // 唯一的正方形,不知道什么颜色
gRectangle.SetPos(-0.25, 0.0);
gRectangle.RotateTo(45.0);
gTriSMid.SetColor(0.0, 1.0, 0.0); // 中间的小三角形,绿色
gTriSMid.SetSize(0.5); // 小三角形只有大的一半大
gTriSMid.SetPos(0.0, -1.0/6.0);
gTriMLeft.SetColor(0.0, 1.0, 1.0); // 左下方的中三角形
gTriMLeft.SetSize( sqrt(2.0) / 2.0 ); // 以底边计算,2分之根号2倍
gTriMLeft.SetPos(-0.5 + 1.0/6.0, -0.5 + 1.0/6.0 );
gTriMLeft.RotateTo(135.0);
gParal.SetColor(1.0, 0.0, 1.0); // 唯一的平行四边形,紫色
gParal.SetPos(0.125, -0.375);
}
void
ReShape(unsigned
auWidth, unsigned
auHeight)
{
glViewport(0, 0, auWidth, auHeight);
}
//这里进行所有的绘图工作
void
SceneShow(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT); // 清空颜色缓冲区
gTriBTop.Draw();
gTriBRight.Draw();
gTriSLeft.Draw();
gRectangle.Draw();
gTriSMid.Draw();
gTriMLeft.Draw();
gParal.Draw();
glFlush();
}
上述代码中程序逻辑非常简单,无非就是设定好每个图形的大小,位置,旋转角度(三角形需要)等,每个图形的绘制都是以其重心为原点,所以计算的实际是七巧板每个图形的重心的位置,有一定的计算量,上述每个数值都是精确计算出来的,所以最后的图形才能完美,实际上也可以通过移动所有图形到一起,然后记录下每个值的方式来完成,但是此方式可能没有完整的数学描述精确,效果也就没有那么完美了。显示的截图如下:
最后演示一下每个图形的旋转效果:
只需要将代码改成如下形式即可:
//这里进行所有的绘图工作
void
SceneShow(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT); // 清空颜色缓冲区
gTriBTop.Draw();
gTriBRight.Draw();
gTriSLeft.Draw();
gRectangle.Draw();
gTriSMid.Draw();
gTriMLeft.Draw();
gParal.Draw();
gTriBTop.Rotate(1.0);
gTriBRight.Rotate(1.0);
gTriSLeft.Rotate(1.0);
gRectangle.Rotate(1.0);
gTriSMid.Rotate(1.0);
gTriMLeft.Rotate(1.0);
gParal.Rotate(1.0);
glFlush();
}
见视频:
此文演示的完整代码在博客代码的JTTangram目录。有兴趣的可以将整个七巧板游戏完成然后再告诉我。最后,开始实际的完成稍微复杂点的图形的绘制时就会发现,就会发现技术的学习都是比较简单的,但是,实际的使用全靠数学撑着,此例算是比较简单了,但是平面几何,三角函数等东西不懂一点根本无法计算各个图形的位置-_-!数学还是得学好啊。。。。。。。。。。。
本OpenGL系列其他文章
1.
《 Win32 OpenGL 编程(1)Win32下的OpenGL编程必须步骤
》
2. 《Win32 OpenGL编程(2) 寻找缺失的OpenGL函数
》
3. 《Win32 OpenGL编程(3) 基本图元(点,直线,多边形)的绘制
》
4. 《Win32 OpenGL编程(4) 2D图形基础(颜色及坐标体系进阶知识)
》
5. 《Win32 OpenGL编程(5)顶点数组详细介绍
》
6.《Win32 OpenGL编程(6) 踏入3D世界
》
完整源代码获取说明
由于篇幅限制,本文一般仅贴出代码的主要关心的部分,代码带工程(或者makefile)完整版(如果有的话)都能用Mercurial在Google Code中下载。文章以博文发表的日期分目录存放,请直接使用Mercurial克隆下库:
https://blog-sample-code.jtianling.googlecode.com/hg/
Mercurial使用方法见《分布式的,新一代版本控制系统Mercurial的介绍及简要入门
》
要是仅仅想浏览全部代码也可以直接到google code上去看,在下面的地址:
http://code.google.com/p/jtianling/source/browse?repo=blog-sample-code
原创文章作者保留版权 转载请注明原作者 并给出链接
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie
分享到:
相关推荐
html5 canvas绘制七巧板图形代码 html5 canvas绘制七巧板图形代码
Scratch 是一种图形化编程语言,适合初学者进行编程学习和创作各种项目。以下是学习 Scratch 的好处: 简单易学:Scratch 使用图形拼图的方式代替传统编程语言中的复杂代码,使得编程变得更容易理解和上手。即使...
参考资料-龙湖地产七巧板运营体系.zip
利用windows api写的一个七巧板游戏,并实现了一副目标图案的智能判断。内附源文件(没有执行文件),和一张目标图片seven.bmp,本例中判断是根据七巧板中心坐标 差实现。需要的可以下载借鉴,我没分了,没办法多...
2-七巧板-项目源码与素材,Scratch少儿编程,经典教学作品,儿童益智游戏
2021高职 机器视觉系统应用 任务书2-七巧板创意造型摆拼(赛项赛题).docx2021高职 机器视觉系统应用 任务书2-七巧板创意造型摆拼(赛项赛题).docx2021高职 机器视觉系统应用 任务书2-七巧板创意造型摆拼(赛项赛题)....
2021高职 机器视觉系统应用 任务书2-七巧板创意造型摆拼(赛项赛题).pdf2021高职 机器视觉系统应用 任务书2-七巧板创意造型摆拼(赛项赛题).pdf2021高职 机器视觉系统应用 任务书2-七巧板创意造型摆拼(赛项赛题).pdf...
科技七巧板教材里面可供参考七巧板图形.zip
canvas绘制七巧板
参考资料-产七巧板运营体系.zip
参考资料-地产七巧板运营体系.zip
HTML5初学canvas,绘制七巧板图形,练练手。
行业资料-电子功用-基于七巧板UI的智能电视主场景交互方法
创业计划书-七巧板-手工坊--DIY--创业计划书
七巧板-手工坊--DIY--创业计划书商业计划书精品模板.ppt
HTML5 canvas绘制七巧板代码,代码有详细中文注释。
scratch编程项目源代码文件案例素材-七巧板.zip
☆ 资料介绍:☆ 游戏名称:经典小游戏 - 七巧板; 开发环境:Visual Studio 2010 SP1;
七巧板场景文件的编辑器 Tangram Play是一个交互式文本编辑器,用于使用Mapzen的创建地图。 使用Play,您可以在YAML中编写和编辑地图样式,并在网络浏览器中实时预览更改。 从Mapzen的基础地图之一开始,或创建自己...