目的
用Qt opengl 绘制3D魔方,并用鼠标控制整体的旋转与缩放
效果如下:
准备工作
- 学习Qt opengl绘制简单的立方体,并给立方体贴图Qt opengl教程
- 准备六个面图片素材
实施
1.新建Qt widget工程
这里是以Qt4版本来设计代码的,在pro文件中加上
QT += opengl
2.绘制坐标轴
绘制三条线表示坐标轴,这样便于以后区分,opengl 绘制3D,且控制物体旋转跟坐标轴相关,加上这三条线可以让我们很好地区分当前在什么位置。
void GLWidget::paintGL()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
glTranslatef( 0.0, 0.0, zoom );
glRotatef( xRot, 1.0, 0.0, 0.0 );
glRotatef( yRot, 0.0, 1.0, 0.0 );
//绘制坐标轴,方便调试
glLineWidth(2);
glBegin(GL_LINES);
glColor3f(1,0,0); glVertex3f(0,0,0);//y
glColor3f(1,0,0); glVertex3f(0,6,0);
glColor3f(0,1,0); glVertex3f(0,0,0);//x
glColor3f(0,1,0); glVertex3f(6,0,0);
glColor3f(0,0,1); glVertex3f(0,0,0);//z
glColor3f(0,0,1); glVertex3f(0,0,6);
glEnd();
}
效果:
3.绘制一个立方体
3阶魔方共有27个小立方体组成,先绘制一个小立方体,使用opengl 主要是熟悉坐标系统,哪里是原点哪里是x,y,z轴的正方向
屏幕向外,z轴正向
屏幕向右,x轴正向
屏幕向上,y轴正向
写点代码做几个实验就可以很好的区分
//绘制一个立方体 魔方共27个
void GLWidget::drawOneCube(Cube *b, GLfloat x, GLfloat y, GLfloat z)//
{
x=x-0.5;
y=y-0.5;
z=z-0.5;
const Cube::Color *color = b->getColor();
glBindTexture( GL_TEXTURE_2D, texture[color[0]] );
glBegin( GL_QUADS );
//后面 黄色
glNormal3f( x, y, z );
glTexCoord2f( 0, 0 );glVertex3f(x, y, z);
glTexCoord2f( 0+1, 0 );glVertex3f(x+1, y, z);
glTexCoord2f( 0+1, 0+1);glVertex3f(x+1, y+1, z);
glTexCoord2f( 0, 0+1);glVertex3f(x, y+1, z);
glEnd();
glBindTexture( GL_TEXTURE_2D, texture[color[1]] );
glBegin( GL_QUADS );
//前面 白色
glNormal3f( x, y, z+1 );
glTexCoord2f( 0, 0 );glVertex3f(x, y, z+1);
glTexCoord2f( 0+1, 0 );glVertex3f(x+1, y, z+1);
glTexCoord2f( 0+1, 0+1);glVertex3f(x+1, y+1, z+1);
glTexCoord2f( 0, 0+1);glVertex3f(x, y+1, z+1);
glEnd();
glBindTexture( GL_TEXTURE_2D, texture[color[2]] );
glBegin( GL_QUADS );
//下面 蓝色
glNormal3f( x, y, z);
glTexCoord2f( 0, 0 );glVertex3f(x, y, z);
glTexCoord2f( 0+1, 0 );glVertex3f(x+1, y, z);
glTexCoord2f( 0+1, 0+1);glVertex3f(x+1, y, z+1);
glTexCoord2f( 0, 0+1);glVertex3f(x, y, z+1);
glEnd();
glBindTexture( GL_TEXTURE_2D, texture[color[3]] );
glBegin( GL_QUADS );
//上面 绿色
glNormal3f( x, y+1, z);
glTexCoord2f( 0, 0 );glVertex3f(x, y+1, z);
glTexCoord2f( 0+1, 0 );glVertex3f(x+1, y+1, z);
glTexCoord2f( 0+1, 0+1);glVertex3f(x+1, y+1, z+1);
glTexCoord2f( 0, 0+1);glVertex3f(x, y+1, z+1);
glEnd();
glBindTexture( GL_TEXTURE_2D, texture[color[5]] );
glBegin( GL_QUADS );
//左面 橙色
glNormal3f( x, y, z);
glTexCoord2f( 0, 0 );glVertex3f(x, y, z);
glTexCoord2f( 0+1, 0 );glVertex3f(x, y+1, z);
glTexCoord2f( 0+1, 0+1);glVertex3f(x, y+1, z+1);
glTexCoord2f( 0, 0+1);glVertex3f(x, y, z+1);
glEnd();
glBindTexture( GL_TEXTURE_2D, texture[color[4]] );
glBegin( GL_QUADS );
//右面 红色
glNormal3f( x+1, y, z);
glTexCoord2f( 0, 0 );glVertex3f(x+1, y, z);
glTexCoord2f( 0+1, 0 );glVertex3f(x+1, y+1, z);
glTexCoord2f( 0+1, 0+1);glVertex3f(x+1, y+1, z+1);
glTexCoord2f( 0, 0+1);glVertex3f(x+1, y, z+1);
glEnd();
}
在paintGL里添加
glColor3f(1.0f,1.0f,1.0f);
for(int i=0;i<1;i++)
{
drawOneCube(&cube[i],cube[i].x,cube[i].y,cube[i].z);
}
效果:
4.绘制全部立方体
for(int i=0;i<27;i++)
{
drawOneCube(&cube[i],cube[i].x,cube[i].y,cube[i].z);
}
效果:
5.加上鼠标事件,控制整个魔方
//鼠标控制
void GLWidget::mousePressEvent(QMouseEvent *e)
{
bMousePress = true;
startPoint = e->pos();
}
void GLWidget::mouseMoveEvent(QMouseEvent *e)
{
if(bMousePress)
{
QPoint tmp = startPoint - e->pos();
if(abs(tmp.x()) > abs(tmp.y())){
//x方向
yRot += ((int)(4*(tmp.x()/3.0)))%360;
}else{
//y方向
xRot += ((int)(4*(tmp.y()/3.0)))%360;
}
startPoint = e->pos();
updateGL();
}
}
void GLWidget::mouseReleaseEvent(QMouseEvent *)
{
bMousePress = false;
}
/*鼠标滚轮放大缩小*/
void GLWidget::wheelEvent(QWheelEvent *e)
{
zoom +=e->delta()/abs(e->delta());
updateGL();
}
代码下载
https://download.csdn.net/download/gaobobo138968/10440525
运行代码时候注意data文件图片路径位置,data文件夹要放在编译运行的目录里,如