圆柱的顶面和底面都是一个圆形,其顶点坐标为(R*cos(弧度),y,R*sin(弧度))其中R分别为圆柱高的峰值,比如正放于中心时y就是h/2或者-h/2,h/2表示顶面,-h/2表示底面。其纹理坐标为(0.5-0.5*cos(弧度),0.5-0.5*sin(弧度)),法向量为垂直向上或向下的单位向量。

圆柱的侧面可以将其分割为n份,用GL_TRIANGLE_FAN绘制三角形的方式将其绘出;我们可以以弧度为分割标准,将其分成n份,其中分成的小三角形为两个相邻弧度求出的上、下顶点的四个坐标;纹理坐标可理解为弧度占整个圆周的比例,以此来从0-1中取值得到纹理坐标;法向量则为其顶点坐标。

了解了圆柱的顶点生成原理后,我们就可以写出渲染器了,其实现如下

#ifndef CYLINDERRENDER_H
#define CYLINDERRENDER_H#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QOpenGLExtraFunctions>
#define PI 3.14159265f
class CylinderRender
{
public:CylinderRender() = default;void initsize(QImage &ce,QImage &top,QImage &bottom,float r,float h);void render(QOpenGLExtraFunctions *f,QMatrix4x4 &pMatrix,QMatrix4x4 &vMatrix,QMatrix4x4 &mMatrix,QVector3D &light,QVector3D &camera);private:QOpenGLShaderProgram program_;QOpenGLBuffer vbo_;QVector<GLfloat> vertVec_,textVec_,normalVec_;QVector<GLfloat> ceVec,ceTextVec,ceNorVec,topVec,topTexVec,topNorVec,bottomVec,bottomTexVec,bottomNorVec;QOpenGLTexture *ceTexture_{nullptr},*topTexture_{nullptr},*bottomTexture_{nullptr};
};#endif // CYLINDERRENDER_H
#include "cylinderrender.h"void CylinderRender::initsize(QImage &ce, QImage &top, QImage &bottom, float r, float h)
{program_.addCacheableShaderFromSourceFile(QOpenGLShader::Vertex,"vsrc.vert");program_.addCacheableShaderFromSourceFile(QOpenGLShader::Fragment,"fsrc.frag");program_.link();topTexture_ = new QOpenGLTexture(top);bottomTexture_ = new QOpenGLTexture(bottom);ceTexture_ = new QOpenGLTexture(ce);topTexture_->setWrapMode(QOpenGLTexture::ClampToEdge);topTexture_->setMinMagFilters(QOpenGLTexture::NearestMipMapNearest,QOpenGLTexture::LinearMipMapNearest);bottomTexture_->setWrapMode(QOpenGLTexture::ClampToEdge);bottomTexture_->setMinMagFilters(QOpenGLTexture::NearestMipMapNearest,QOpenGLTexture::LinearMipMapNearest);ceTexture_->setWrapMode(QOpenGLTexture::ClampToEdge);ceTexture_->setMinMagFilters(QOpenGLTexture::NearestMipMapNearest,QOpenGLTexture::LinearMipMapNearest);float angleSpan = 5;topVec << 0 << h/2 << 0;topTexVec << 0.5 << 0.5;topNorVec << 0 << 1 << 0;bottomVec << 0 << -h/2 << 0;bottomTexVec << 0.5 << 0.5;bottomNorVec << 0 << -1 << 0;for(float angle = 0; angle <= 360; angle += angleSpan){//侧面float curRad = angle * PI / 180;float x1 = r * ::cos(curRad);float y1 = - h/2;float z1 = r * ::sin(curRad);float hx1 = (angle/360);float hy1 = 0;float nx1 = x1;float ny1 = 0;float nz1 = z1;float x2 = x1;float y2 = h/2;float z2 = z1;float hx2 = hx1;float hy2 = 1;float nx2 = x2;float ny2 = 0;float nz2 = z2;float nextRad = angle + angleSpan;float x3 = r * ::cos(nextRad * PI / 180);float y3 = h/2;float z3 = r * ::sin(nextRad * PI / 180);float hx3 = (nextRad/360);float hy3 = 1;float nx3 = x3;float ny3 = 0;float nz3 = z3;float x4 = x3;float y4 = -h/2;float z4 = z3;float hx4 = hx3;float hy4 = 0;float nx4 = x4;float ny4 = 0;float nz4 = z4;ceVec << x1 << y1 << z1 << x2 << y2 << z2 << x3 << y3 << z3 << x4 << y4 << z4;ceTextVec << hx2 << hy2  << hx1 << hy1<< hx4 << hy4 << hx3 << hy3;ceNorVec << nx1 << ny1 << nz1 << nx2 << ny2 << nz2 << nx3 << ny3 << nz3 << nx4 << ny4 << nz4;//顶面x2 = r * ::cos(-curRad);z2 = r * ::sin(-curRad);topVec << x2 << y2 << z2;float topTx1 = 0.5 - 0.5 * ::cos(curRad);float topTy1 = 0.5 - 0.5 * ::sin(-curRad);topTexVec << topTx1 << topTy1;topNorVec << 0 << 1 << 0;//底面bottomVec << x1 << y1 << z1;bottomTexVec << topTx1 << topTy1;bottomNorVec << 0 << -1 << 0;}vertVec_ << ceVec  << topVec << bottomVec;textVec_ << ceTextVec << topTexVec << bottomTexVec;normalVec_ << ceNorVec << topNorVec << bottomNorVec;QVector<GLfloat> bytesVec;bytesVec << vertVec_ << textVec_ << normalVec_;vbo_.create();vbo_.bind();vbo_.allocate(bytesVec.data(),bytesVec.count() * sizeof GLfloat);
}void CylinderRender::render(QOpenGLExtraFunctions *f, QMatrix4x4 &pMatrix, QMatrix4x4 &vMatrix, QMatrix4x4 &mMatrix, QVector3D &light, QVector3D &camera)
{f->glEnable(GL_DEPTH_TEST);f->glEnable(GL_CULL_FACE);program_.bind();vbo_.bind();f->glActiveTexture(GL_TEXTURE0 + 0);program_.setUniformValue("uPMatrix",pMatrix);program_.setUniformValue("uVMatrix",vMatrix);program_.setUniformValue("uMMatrix",mMatrix);program_.setUniformValue("uLightLocation",light);program_.setUniformValue("uCamera",camera);program_.setUniformValue("sTextures",0);program_.enableAttributeArray(0);program_.enableAttributeArray(1);program_.enableAttributeArray(2);program_.setAttributeBuffer(0,GL_FLOAT,0,3,3*sizeof(GLfloat));program_.setAttributeBuffer(1,GL_FLOAT,vertVec_.count() * sizeof(GLfloat),2,2*sizeof(GLfloat));program_.setAttributeBuffer(2,GL_FLOAT,(vertVec_.count() + textVec_.count())*sizeof(GLfloat),3,3*sizeof(GLfloat));ceTexture_->bind();f->glDrawArrays(GL_QUADS,0,ceVec.count()/3);topTexture_->bind();f->glDrawArrays(GL_TRIANGLE_FAN,ceVec.count()/3,topVec.count()/3);bottomTexture_->bind();f->glDrawArrays(GL_TRIANGLE_FAN,(ceVec.count() + topVec.count())/3,bottomVec.count()/3);program_.disableAttributeArray(0);program_.disableAttributeArray(1);program_.disableAttributeArray(2);topTexture_->release();ceTexture_->release();bottomTexture_->release();vbo_.release();program_.release();f->glDisable(GL_CULL_FACE);f->glDisable(GL_DEPTH_TEST);
}

其shader和平时的差不多,只不过用了上、下、侧三个纹理

#version 330
uniform mat4 uPMatrix,uVMatrix,uMMatrix;
uniform vec3 uCamera,uLightLocation;
layout (location = 0)in vec3 aPosition;
layout (location = 1)in vec2 aTexture;
layout (location = 2)in vec3 aNormal;
smooth out vec3 vPosition;
smooth out vec2 vTexture;
smooth out vec4 vAmbient,vDiffuse,vSpecular;void pointLight(in vec3 normal,inout vec4 ambient,inout vec4 diffuse,inout vec4 specular,in vec4 lightAmbient,in vec4 lightDiffuse,in vec4 lightSpecular,in float shininess){ambient = lightAmbient;vec3 normalTarget = aPosition + normal;vec3 newNormal = normalize((uMMatrix * vec4(normalTarget,1)).xyz - (uMMatrix * vec4(aPosition,1)).xyz);vec3 eye = normalize(uCamera - (uMMatrix * vec4(aPosition,1)).xyz);vec3 vp = normalize(uLightLocation - (uMMatrix * vec4(aPosition,1)).xyz);vec3 halfVector = normalize(eye + vp);float nDotViewPotision = max(0.0,dot(newNormal,vp));diffuse = lightDiffuse * nDotViewPotision;float nDotViewHalfVector = dot(newNormal,halfVector);float powerFactor = max(0.0,pow(nDotViewHalfVector,shininess));specular = lightSpecular * powerFactor;
}void main(void)
{gl_Position = uPMatrix * uVMatrix * uMMatrix * vec4(aPosition,1);vec4 ambient = vec4(0.0,0.0,0.0,0.0),diffuse = vec4(0.0,0.0,0.0,0.0),specular = vec4(0.0,0.0,0.0,0.0);pointLight(aNormal,ambient,diffuse,specular,vec4(0.5,0.5,0.5,1),vec4(0.8,0.8,0.8,1),vec4(0.7,0.7,0.7,1),50.0);vPosition = aPosition;vTexture = aTexture;vAmbient = ambient;vDiffuse = diffuse;vSpecular = specular;
}
#version 330
uniform sampler2D sTextures;
in vec3 vPosition;
in vec4 vAmbient,vDiffuse,vSpecular;
in vec2 vTexture;
out vec4 fragColor;void main(void)
{vec4 color = vec4(0.0,0.0,0.0,1.0);color = texture2D(sTextures,vTexture);fragColor = color * (vAmbient + vDiffuse + vSpecular);
}

其使用和前面一样了,传入参数即可

#ifndef WIDGET_H
#define WIDGET_H#include <QOpenGLWidget>
#include <QTimer>
#include "cylinderrender.h"
class Widget : public QOpenGLWidget
{Q_OBJECTpublic:Widget(QWidget *parent = 0);~Widget();protected:void paintGL() override;void resizeGL(int w,int h) override;void initializeGL() override;void mouseMoveEvent(QMouseEvent *event) override;void mousePressEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;private:QMatrix4x4 pMatrix_;QVector3D lightLocation_,camera_;CylinderRender render_;QTimer tm;qreal angleX_ = 0,angleY_ = 0,angleZ_ = 0;private slots:void slotTimeout();
};#endif // WIDGET_H
#include <QTimer>
#include "widget.h"Widget::Widget(QWidget *parent): QOpenGLWidget(parent)
{connect(&tm,SIGNAL(timeout()),this,SLOT(slotTimeout()));tm.start(40);
}Widget::~Widget()
{}void Widget::paintGL()
{QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();f->glClearColor(0.0,0.0,0.0,1.0);f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);QMatrix4x4 vMatrix;vMatrix.lookAt(camera_,QVector3D(0,0,0),QVector3D(0,1,0));QMatrix4x4 mMatrix;mMatrix.rotate(angleX_,1,0,0);mMatrix.rotate(angleY_,0,1,0);mMatrix.rotate(angleZ_,0,0,1);render_.render(f,pMatrix_,vMatrix,mMatrix,lightLocation_,camera_);
}void Widget::resizeGL(int w, int h)
{pMatrix_.setToIdentity();pMatrix_.perspective(45,float(w)/h,0.01f,100.0f);
}void Widget::initializeGL()
{render_.initsize(QImage("rect.jpg"),QImage("circle.jpg"),QImage("circle.jpg"),0.8,0.8);camera_.setX(0);camera_.setY(0);camera_.setZ(3);lightLocation_.setX(5);lightLocation_.setY(2);lightLocation_.setZ(1);
}void Widget::mouseMoveEvent(QMouseEvent *event)
{Q_UNUSED(event)angleX_ += 5;angleY_ += 5;angleZ_ += 5;update();
}void Widget::mousePressEvent(QMouseEvent *event)
{tm.stop();
}void Widget::mouseReleaseEvent(QMouseEvent *event)
{tm.start();
}void Widget::slotTimeout()
{angleX_ += 5;angleY_ += 5;angleZ_ += 5;update();
}

到此结束。

qt opengl 3d基本形状-圆柱相关推荐

  1. qt opengl 3d基本形状-螺旋管

    螺旋管的做法和上一节的圆柱非常类似,就是在大圆径每转过一定角度时,将y值加上一定值.另个其纹理坐标生成的方法也和上一节一致.我做出的效果如下 其渲染器实现如下 #ifndef LUOXUANGUANR ...

  2. qt opengl 3d基本形状圆锥

    圆锥与上一节的圆柱很相似,其侧面的顶点坐标同样拆分成很多个小三角形,顶点位于一点,底面顶点和圆柱计算底面顶点的方法一样,都是(r*cos(弧度),-h/2,r*sin(弧度));底面顶点纹理坐标的计算 ...

  3. Qt+OpenGL——3D坐标转2D坐标

    原理介绍:https://learnopengl-cn.github.io/01%20Getting%20started/08%20Coordinate%20Systems/ 代码实现 为了获取模型中 ...

  4. QT实现绘制3D基本形状

    QT实现绘制3D基本形状 一项目简介 二项目技术 三项目展示 主要源码片段解析 获取完整项目源码传送门 一项目简介 显示Qt 3D提供的四个基本形状,并为每个形状设置一个网格. 基本形状显示了Qt 3 ...

  5. 【Qt OpenGL】Qt Creator中的3D绘图及动画教程

    Qt Creator中的3D绘图及动画教程(参照NeHe) 刚刚学习了Qt Creator,发现Qt提供了QtOpenGL模块,对OpenGL做了不错的封装,这使得我们可以很轻松地在Qt程序中使用Op ...

  6. OpenGL(十八)——Qt OpenGL绘制一个3D世界

    OpenGL(十八)--Qt OpenGL绘制一个3D世界 一.说明 本篇介绍构建一个3D的世界. 二.简介 加载3D世界,并在其中漫游: 在这一课中,你将学会如何加载3D世界,并在3D世界中漫游. ...

  7. Qt实现3D纹理渲染自由旋转空间立方体

    昨天七夕,关于七夕美好的爱情传说源自于浩瀚银河星空,又碰巧最近在学习QtOpenGL实现三维纹理防体重建,突发奇想用Qt实现一个立方体星空模型,并且能随着鼠标操作实现空间自由旋转 核心思想是用到Qt ...

  8. OpenGL(十四)——Qt OpenGL纹理

    OpenGL(十四)--Qt OpenGL纹理 一.纹理 终于写到纹理的部分了: 纹理(Texture)的本质是一个2D图片(1D和3D),或者叫图形数据.只是在OpenGL中专业术语中称其为纹理. ...

  9. Qt文档阅读笔记-Qt Quick 3D - Simple Example解析

    程序运行截图如下: 还是动的. 官方出这篇博文的目的是如何教我们使用Qt Quick 3D去渲染简单的场景. 首先是设置其场景. 在main.qml文件中设置整个场景,导入QtQuick3D组建,用于 ...

最新文章

  1. ArrayList与LinkedList区别
  2. [svc]ext4文件删除访问原理
  3. Cluster_analysis
  4. 智能电网时代的网络空间安全
  5. Java程序员必经的实践之路:微服务与SOA架构
  6. 最大子序列的和算法分析一
  7. 解决TeamViewer的“现在无法捕捉画面。可能由于快速切换或者远程桌面断开或者最小化”问题...
  8. 小D课堂 - 新版本微服务springcloud+Docker教程_6-03 高级篇幅之zuul常用问题分析
  9. Java 在线反编译反编译工具
  10. Excel VBA-批量导出图片.vba
  11. 微信公众号迁移公证书办理流程与条件
  12. 计算机一级考试可以带滴眼液,长期看电脑的人适宜滴眼药水缓解眼干吗?有害吗?...
  13. 笔记本重装win7旗舰版原版操作系统
  14. 杰奇cms,杰奇cms程序,杰奇cms建站方法
  15. cdr圆形渐变填充怎么设置_cdr渐变怎么设置?CorelDRAW渐变设置方法
  16. spoj2142 Arranging Flowers
  17. Python-基于OpenCV的轮廓填充 泛洪算法 孔洞填充
  18. JavaScript——ES8新特性
  19. 阿里云国际站:阿里云启用第三座日本数据中心,加快海外市场扩展
  20. 【计算机网络】知识点总结

热门文章

  1. 华为云数据库 RDS for MySQL ,助力数字化企业安全发展
  2. 从同步阻塞聊到Java三种IO方式
  3. 产品思考:如何计算资讯类产品的日活跃用户天花板?
  4. 105、二氧化碳灭火系统的设计浓度
  5. 将汉字转为阿拉伯数字(oracle函数方式)
  6. 如何在linux系统安装igh,Linux下IGH Ethercat Master安装
  7. 网络安全学习路线,入门到入坟,史上最全网络安全学习路线整理
  8. 6-5 实验5_6_设计函数mypow (100分)
  9. 微信开放标签<wx-open-launch-app>之Vue项目H5唤醒APP
  10. 上海亚商投顾:沪指失守3100点 教育板块逆势大涨