下面简单介绍下所有源代码
所有 7巧板图形全部继承自CGLShape此类实现如下
// 此类实现移动旋转
CGLShape
{
public:
CGLShape(void)
{
mfPosX = 0.0;
mfPosY = 0.0;
mem(mfvColor, 0, (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( aiPosX, aiPosY)
{
mfPosX 2.0f * aiPosX/(float)WIDTH;
mfPosY -(2.0f * aiPosY/(float)HEIGHT);
}
// 移动到位置(Windows坐标系点)
void MoveTo( aiPosX, 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模式)具体各个实现按照 7巧板要求如下:
3角形:
CGLTriangle : public CGLShape
{
public:
CGLTriangle { }
virtual ~CGLTriangle { }
// 重绘时需要,由各子类实现
virtual void DrawImp
{
GLfloat fvTop[3] = { 0.0, (1.0/3.0), 0.0};
GLfloat fvLeftBottom[3] = { -0.5, -(1.0/6.0), 0.0};
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仅仅关心绘制个 3角形而已这里其他图形只有个所以不关心大小而 3角形在 7巧板中有多个所以将大小计算放在 3角形中独立计算大小事实上更通用办法是在CShapeDraw中用 glScale实现 3角形3个顶点坐标相对来说还比较容易计算
矩形:
CGLRectangle: public CGLShape
{
public:
CGLRectangle { }
virtual ~CGLRectangle { }
// 重绘时需要,由各子类实现
virtual void DrawImp
{
GLfloat fLength = sqrt(2.0)/4.0;
GLfloat fLengthHalf = fLength/2.0;
GLfloat fvLeftTop[3] = { -fLengthHalf, fLengthHalf, 0.0};
GLfloat fvRightTop[3] = { fLengthHalf, fLengthHalf, 0.0};
GLfloat fvLeftBottom[3] = { -fLengthHalf, -fLengthHalf, 0.0};
GLfloat fvRightBottom[3] = { fLengthHalf, -fLengthHalf, 0.0};
// TODO: 7角板此例中方形只有个不需要考虑大小暂时不计算大小
glColor4fv(mfvColor);
glPushMatrix;
glBegin(GL_QUADS);
glVertex3fv(fvLeftTop);
glVertex3fv(fvRightTop);
glVertex3fv(fvRightBottom);
glVertex3fv(fvLeftBottom);
glEnd;
glPopMatrix;
}
};
很简单不多说了DrawImp实现个矩形绘制而已 4个顶点坐标时最容易计算
平行 4边形:
CGLParallelogram: public CGLShape
{
public:
CGLParallelogram { }
virtual ~CGLParallelogram { }
// 重绘时需要,由各子类实现
virtual void DrawImp
{
GLfloat fRightBottomX = 0.375;
GLfloat fHeight = 0.25;
GLfloat fvLeftTop[3] = { -fRightBottomX, fHeight/2.0, 0.0};
GLfloat fvRightTop[3] = { 0.5-fRightBottomX, fHeight/2, 0.0};
GLfloat fvLeftBottom[3] = { fRightBottomX-0.5, -fHeight/2.0, 0.0};
GLfloat fvRightBottom[3] = { fRightBottomX, -fHeight/2.0, 0.0};
// TODO: 7角板此例中 4边形只有个不需要考虑大小暂时不计算大小
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边形重心为原点坐标系中计算平时 4边形4个顶点坐标需要定计算量上述那几个数值可不是随便掰出来啊
将上述图形组合在起
CGLTriangle gTriBTop; // 上方大 3角形
CGLTriangle gTriBRight; // 右边大 3角形
CGLTriangle gTriSLeft; // 左上方小上角形
CGLTriangle gTriSMid; // 中间小 3角形
CGLTriangle gTriMLeft; // 左下方中 3角形
CGLRectangle gRectangle; // 唯正方形
CGLParallelogram gParal; // 唯平行 4边形
//OpenGL化开始
void SceneInit( w, h)
{
GLenum err = glewInit;
(err != GLEW_OK)
{
MessageBox(NULL, _T("Error"), _T("Glew init failed."), MB_OK);
exit(-1);
}
gTriBTop.SetColor(1.0, 0.0, 0.0); // 上方大 3角形,红色,
gTriBTop.SetPos(0.0, 1.0/3.0);
gTriBTop.RotateTo(180.0);
gTriBRight.SetColor(0.0, 0.0, 1.0); // 右边大 3角形,蓝色
gTriBRight.SetPos(1.0/3.0, 0.0);
gTriBRight.RotateTo(90.0);
gTriSLeft.SetColor(1.0, 1.0, 0.0); // 左上方小上角形,黄色
gTriSLeft.SetSize(0.5); // 小 3角形只有大半大
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); // 中间小 3角形,绿色
gTriSMid.SetSize(0.5); // 小 3角形只有大半大
gTriSMid.SetPos(0.0, -1.0/6.0);
gTriMLeft.SetColor(0.0, 1.0, 1.0); // 左下方中 3角形
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); // 唯平行 4边形,紫色
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;
}
上述代码中逻辑非常简单无非就是设定好每个图形大小位置旋转角度( 3角形需要)等每个图形绘制都是以其重心为原点所以计算实际是 7巧板每个图形重心位置有定计算量上述每个数值都是精确计算出来所以最后图形才能完美实际上也可以通过移动所有图形到起然后记录下每个值方式来完成但是此方式可能没有完整数学描述精确效果也就没有那么完美了显示截图如下:
最后演示下每个图形旋转效果:
只需要将代码改成如下形式即可:
//这里进行所有绘图工作
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;
}
最后开始实际完成稍微复杂点图形绘制时就会发现就会发现技术学习都是比较简单但是实际使用全靠数学撑着此例算是比较简单了但是平面几何 3角等东西不懂点根本无法计算各个图形位置-_-!数学还是得学好啊
最新评论