Qt之opengl画钻石

4 篇文章 0 订阅

每个点需要精确计算,采用qt绘制
在这里插入图片描述

#pragma execution_character_set("utf-8")
#include "lesson09widegt.h"
#include <QKeyEvent>
#include <QTimer>
#include <QDebug>
GLfloat lightAmbient[4] = { 0.5, 0.5, 5.5, 1.0 };//环境光参数,半亮白色
GLfloat lightDiffuse[4] = { 1.0, 5.0, 5.0, 1.0 }; //漫射光参数
GLfloat lightPosition[4] = { 5.0, 5.0, 5.0, 1.0 };//光源位置
GLfloat lightPositiona[4] = { 7.0, 8.0, 5.0, 1.0 };//光源位置
GLuint fogMode[3] = { GL_EXP, GL_EXP2, GL_LINEAR };
GLfloat fogColor[4] = { 0.5, 0.5, 0.5, 1.0 };

lesson9widegt::lesson9widegt( QWidget* parent )
    : QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
    m_target = QVector3D(0,0,-1);
    lightnum = 0;
    mousePressState = false;
    paintstate = true;
    xRot = yRot = zRot = 0.0;
    zoom = -15.8;
    xSpeed = ySpeed = 0.0;
    filter = 0;
    light = false;
    fogFilter = 0;
    setGeometry( 500,400, 640, 480 );
    QTimer *timer = new QTimer(this);                   //创建一个定时器
    //将定时器的计时信号与updateGL()绑定
    connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
    timer->start(10);                                   //以10ms为一个计时周期
}

lesson9widegt::~lesson9widegt()
{

}

void lesson9widegt::glPerspective( GLdouble fov, GLdouble aspectRatio, GLdouble zNear, GLdouble zFar )
{
    // 使用OpenGL函数,但是需要添加math.h头文件
    GLdouble rFov = fov * 3.14159265 / 180.0;
    glFrustum( -zNear * tan( rFov / 2.0 ) * aspectRatio,
               zNear * tan( rFov / 2.0 ) * aspectRatio,
               -zNear * tan( rFov / 2.0 ),
               zNear * tan( rFov / 2.0 ),
               zNear, zFar );
}

void lesson9widegt::initializeGL()
{
    initializeOpenGLFunctions();//初始化
    loadGLTextures();
    glEnable( GL_TEXTURE_2D );//启用2D
    glShadeModel( GL_SMOOTH ); //启用阴影平滑
    glClearColor( 0.0, 0.0, 0.0, 1.0 );//设置颜色
    glClearDepth( 1.0 );//设置深度缓存
    glEnable( GL_DEPTH_TEST ); //启用深度测试
    glDepthFunc( GL_LEQUAL ); //所作深度测试的类型
    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );//告诉系统对透视进行修正
    glLightfv( GL_LIGHT1, GL_AMBIENT, lightAmbient );//创建光源 glLightfv()
    glLightfv( GL_LIGHT2, GL_DIFFUSE, lightDiffuse );//创建光源 glLightfv()
    glLightfv( GL_LIGHT3, GL_POSITION, lightPosition );//创建光源 glLightfv()
    glLightfv( GL_LIGHT4, GL_POSITION, lightPositiona );//创建光源 glLightfv()
    glEnable(GL_LIGHT1); //启用一号光源
    glEnable(GL_LIGHT2); //启用一号光源
    glEnable(GL_LIGHT3); //启用一号光源
    glEnable(GL_LIGHT4); //启用一号光源
    glEnable(GL_LIGHTING); //开光
    glFogi( GL_FOG_MODE, fogMode[fogFilter] );//雾气模式
    glFogfv( GL_FOG_COLOR, fogColor );//雾气颜色
    glFogf( GL_FOG_DENSITY, 0.05 );//雾气密度.
    glHint( GL_FOG_HINT, GL_DONT_CARE );//告诉系统对透视进行修正
    glFogf( GL_FOG_START, 0.0 );//雾气密度
    glFogf( GL_FOG_END, 1.0 );//雾气密度
    // glEnable( GL_FOG );//启用雾
    object = makeObject();              // 生成一个OpenGL显示列表
}

void lesson9widegt::paintGL()
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glLoadIdentity();
    glTranslatef(  0.0,  1.0, zoom );
    glRotatef(xRot / 16.0, 1.0f, 0.0f, 0.0f);//旋转函数glRotatef()x
    glRotatef(yRot / 16.0, 0.0f, 1.0f, 0.0f);//旋转函数glRotatef()y
    glRotatef(zRot / 16.0, 0.0f, 0.0f, 1.0f);//旋转函数glRotatef()z

    glBindTexture(GL_TEXTURE_2D, texture[filter] );
    drawFloor();
    glCallList( object );

    xRot += xSpeed;
    yRot += ySpeed;
}

void lesson9widegt::resizeGL(int width, int height)
{
    //摄像机
    QMatrix4x4 camera;
    m_eye.setZ(m_ez);
    camera.lookAt(m_eye,m_eye + m_target,QVector3D(0,1,0));

    glViewport(0,0, width, height);//指定视口位置。
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
}

void lesson9widegt::mousePressEvent(QMouseEvent *event)
{
    qDebug()<<"paintstate"<<paintstate;
    update();
    lastPos = event->pos();
}

static void qNormalizeAngle(int &angle)
{
    while (angle < 0)
        angle += 360 * 16;
    while (angle > 360 * 16)
        angle -= 360 * 16;
}

void lesson9widegt::setXRotation(int angle)
{
    qNormalizeAngle(angle);
    if (angle != xRot) {
        xRot = angle;
        update();
    }
}

void lesson9widegt::setYRotation(int angle)
{
    qNormalizeAngle(angle);
    if (angle != yRot) {
        yRot = angle;
        update();
    }
}

void lesson9widegt::setZRotation(int angle)
{
    qNormalizeAngle(angle);
    if (angle != zRot) {
        zRot = angle;
        update();
    }
}

void lesson9widegt::mouseMoveEvent(QMouseEvent *event)
{
    int dx = event->x() - lastPos.x();
    int dy = event->y() - lastPos.y();
    if (event->buttons() & Qt::LeftButton) {
        setXRotation(xRot + 8 * dy);
        setYRotation(yRot + 8 * dx);
    } else if (event->buttons() & Qt::RightButton) {
        setXRotation(xRot + 8 * dy);
        setZRotation(zRot + 8 * dx);
    }
    lastPos = event->pos();
}

void lesson9widegt::drawFloor()
{
    texture[1] = bindTexture(QPixmap(":/image/data/zuan1.png")); //载入位图并转换成纹理
    glBegin(GL_QUADS);
    glVertex3f(  -3.0,  3.0, -1.0 );
    glVertex3f(  -3.0,  -3.0, -1.0 );
    glVertex3f(  3.0,  -3.0, -1.0 );
    glVertex3f(  3.0,  3.0, -1.0 );
    glEnd();

}

void lesson9widegt::mouseReleaseEvent(QMouseEvent *event)
{
    mousePressState = false;
}

void lesson9widegt::keyPressEvent(QKeyEvent *event)
{
    switch ( event->key() )
    {
    case  Qt::Key_Space:
        ySpeed = 0;
        xSpeed = 0;
        break;
    case  Qt::Key_Meta:
        break;
    case Qt::Key_L:
        glDisable(GL_LIGHT1); //启用一号光源
        glDisable(GL_LIGHT2); //启用一号光源
        glDisable(GL_LIGHT3); //启用一号光源
        glDisable(GL_LIGHT4); //启用一号光源
        glEnable( GL_FOG );
        if(lightnum == 0){
            glEnable(GL_LIGHT1); //启用一号光源
        }else if(lightnum == 1){
            glEnable(GL_LIGHT2); //启用一号光源
        }else if(lightnum == 2){
            glEnable(GL_LIGHT3); //启用一号光源
        }else if(lightnum == 3){
            glEnable(GL_LIGHT4); //启用一号光源
        }else{
            glDisable( GL_FOG );
        }
        lightnum++;
        if(lightnum > 4){
            lightnum = 0;
        }
        updateGL();
        break;
    case Qt::Key_F:
        filter += 1;;
        if ( filter > 2 )
        {
            filter = 0;
        }
        updateGL();
        break;
    case Qt::Key_G:
        fogFilter += 1;;
        if ( fogFilter > 2 )
        {
            fogFilter = 0;
        }
        glFogi( GL_FOG_MODE, fogMode[fogFilter] );
        updateGL();
        break;
    case Qt::Key_PageUp:
        zoom -= 0.2;
        updateGL();
        break;
    case Qt::Key_PageDown:
        zoom += 0.2;
        updateGL();
        break;
    case Qt::Key_Up:
        xSpeed -= 0.5;
        updateGL();
        break;
    case Qt::Key_Down:
        xSpeed += 0.5;
        updateGL();
        break;
    case Qt::Key_Right:
        ySpeed += 0.5;
        updateGL();
        break;
    case Qt::Key_Left:
        ySpeed -= 0.5;
        updateGL();
        break;
    case Qt::Key_F2:
        fullscreen = !fullscreen;
        if ( fullscreen )
        {
            showFullScreen();
        }
        else
        {
            showNormal();
            setGeometry( 0, 0, 640, 480 );
        }
        update();
        break;
    case Qt::Key_Escape:
        close();
    }
}

void lesson9widegt::wheelEvent(QWheelEvent *event)
{
    if (! event->pixelDelta().isNull()) {
        m_ez += event->pixelDelta().y();
    } else if (!event->angleDelta().isNull()) {
        m_ez += (event->angleDelta() / 120).y();
    }
    QPoint p = event->angleDelta();
    if(p.y () >= 120)
    {
        zoom += 0.2;
        updateGL();
    }else
    {
        zoom -= 0.2;
        updateGL();
    }
}

void lesson9widegt::loadGLTextures()
{
    QImage tex, buf;
    if ( !buf.load( ":/image/data/zuan.png" ) )
    {
        qWarning( "Could not read image file, using single-color instead." );
        QImage dummy;
        dummy.fill( QColor(22,66,99));
        buf = dummy;
    }
    tex = QGLWidget::convertToGLFormat( buf );
    //glGenTextures用来生成纹理的函数。函数根据纹理参数返回n个纹理索引
    glGenTextures( 3, &texture[0] );
    // 一幅具有真实感的图像或者照片作为纹理贴到一个矩形上
    glBindTexture( GL_TEXTURE_2D, texture[0] );
    //映射需要重新构造纹理图像,这样就会造成应用到多边形上的图像失真),
    //这时就可用glTexParmeteri()函数来确定如何把纹理象素映射成像素.
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    //生成一个2D纹理(Texture)
    glTexImage2D( GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0,
                  GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );

    glBindTexture( GL_TEXTURE_2D, texture[1] );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexImage2D( GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0,
                  GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );

    glBindTexture( GL_TEXTURE_2D, texture[2] );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexImage2D( GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0,
                  GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );

}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qt5_qt6

你的鼓励是我们创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值