IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> QT+OpenGL导入STL文件(二进制/ascll码格式),鼠标交互实现缩放旋转 -> 正文阅读

[C++知识库]QT+OpenGL导入STL文件(二进制/ascll码格式),鼠标交互实现缩放旋转

碎碎念

? ? ? ? 由于课设和大创涉及到了模型的旋转,因此专门去学习了模型的导入,也是废了不少心思,现在总结一下两种格式的简单导入,以及对stl模型两种格式的简单介绍。网上有很多大佬都有详细的解答,结尾附上链接;在导入较大网格数的模型时发现qt不是运行不了就是加载时间很长,网上找了很多办法也没有解决,并且当面片数过高时,由于二进制文件的三角形面片数占4字节(最多65535个三角形),因此超出时便会报溢出异常。本人太菜不知道怎么解决,只好采取blender的精简修改器减少面片数,当然面片数过低模型精度会降低,希望有大佬能解答疑问。欢迎指正。

下面是效果图展示:

?(ps:模型来自Three D Scans

1. stl格式介绍及导出

STL文件:STL文件是一种用许多空间小三角形面片逼近三维实体表面的数据模型,STL模型的数据通过给出组成三角形法向量的3个分量(用于确定三角面片的正反方向)及三角形的3个顶点坐标来实现,一个完整的STL文件记载了组成实体模型的所有三角形面片的法向量数据和顶点坐标数据信息。目前的STL文件格式包括二进制文件(BINARY)和文本文件(ASCII)两种。

1.1 ascll码格式

1.2 二进制格式

1.3 模型导出

模型可以自己在建模软件中制作或者去建模软件下载stl格式,这里以blender为例:

? ? ? ? 1. 首先打开blender,点击你想要导出的物体,注意在OpenGL中为右手坐标系,z轴朝外,如果发现方向不对需要将模型导入建模软件中调整一下模型方向再导出;

导出模型时最好以模型原点为中心,旋转时将以模型中心旋转;

?????????2. 点击文件,导出,选择stl格式;导出模型时注意点击仅导出选中物体,可根据需要选择是否导出ascll码格式,默认导出二进制格式。

这样就成功导出stl模型文件了。

1.4?举例解释两种格式文件

以上方导出的正方体为例解释:

????????显然正方体有六个面,每个面由两个等腰直角三角形拼接而成,故一共有2*6=12个三角形,即下图这样的三角形有12组?

下面使用二进制查看器查看机器码:(或者用qt的资源文件打开也可查看)

前八十字节记录了模型基本信息,即模型是从blender导出的;

紧接着四字节为三角形面片信息;

剩下对于每个三角形有3个四字节浮点数(面片法矢量),3个顶点坐标(每个坐标为4字节的三元组)最后两个字节描述三角形面片属性信息。即每个三角形占50字节(3*4 + 3*(3*4)=50)

?2 QOpenGLWidget类进行opengl绘图

基础准备

  1. 在qt中新建一个c++类,继承QWidget;
  2. 接着在该类导入相应的头文件
    #include <QOpenGLWidget>
    #include<QVector>
    #include<QOpenGLExtraFunctions>
    #include<QOpenGLShaderProgram>
    #include<QOpenGLVertexArrayObject>
    #include<QOpenGLBuffer>
    #include<QMatrix3x3>
    #include<QMatrix4x4>
    #include<QMouseEvent>
    #include<QWheelEvent>
  3. 将demoOpenglWidget的继承类改为
    class demoOpenglWidget : public QOpenGLWidget,public QOpenGLExtraFunctions

    点击QOpenGLWidget头文件,找到下面三个函数进行重载:

    protected:
    //建立OpenGL的资源和状态。在第一次调用resizeGL()或paintGL()之前调用一次
        void initializeGL();
    //设置OpenGL视口,投影等。每当调整Widget的大小时(第一次显示窗口Widget时会调用它,因为所有新创建Widget都会自动获得调整大小的事件)
        void resizeGL(int width, int height);
    //渲染OpenGL场景,需要更新Widget时就会调用
        void paintGL();
  4. demoOpenglWidget.h

    #ifndef DEMOOPENGLWIDGET_H
    #define DEMOOPENGLWIDGET_H
    
    #include <QOpenGLWidget>
    #include<QVector>
    #include<QOpenGLExtraFunctions>
    #include<QOpenGLShaderProgram>
    #include<QOpenGLVertexArrayObject>
    #include<QOpenGLBuffer>
    #include<QMatrix3x3>
    #include<QMatrix4x4>
    #include<QMouseEvent>
    #include<QWheelEvent>
    
    class demoOpenglWidget : public QOpenGLWidget,public QOpenGLExtraFunctions
    {
        Q_OBJECT
    public:
        explicit demoOpenglWidget(QWidget *parent = nullptr);
        ~demoOpenglWidget();
    public:
        double rotate_y=0;
        double rotate_x=0;
        double rotate_z=0;
    protected:
        void initializeGL();
        void resizeGL(int width, int height);
        void paintGL();
        QVector<float> loadAscllStl(QString filename,int ratio);//加载Ascll格式的stl文件
        QVector<float> loadBinStl(std::string filename, int ratio);//加载二进制格式的stl文件
        void mousePressEvent(QMouseEvent *event);
        void mouseMoveEvent(QMouseEvent *event);
        void wheelEvent(QWheelEvent *event);//图片缩放功能
    
    private:
        QVector<float> vertices;
        QVector<float> Position;//顶点位置
        QVector<float> Normal;//法向量
        QOpenGLShaderProgram shaderprogram;
        QOpenGLVertexArrayObject VAO;
        QOpenGLBuffer VBO;
    
        //MVP
        QMatrix4x4 model;
        QMatrix4x4 view;
        QMatrix4x4 projection;
    
    //    int verticesCnt;
        GLfloat xtrans,ytrans,ztrans;
        QVector2D mousePos;
        QQuaternion rotation;
    };
    
    
    
    
    #endif // DEMOOPENGLWIDGET_H
    
  5. 在qt资源中导入顶点着色器、片段着色器,并重载initializeGL、resizeGL和paintGL。
    //stl.vert
    #version 330 core
    layout (location = 0) in vec3 aPos;   // 位置变量的属性位置值为 0
    layout (location = 1) in vec3 aNormal; // 颜色变量的属性位置值为 1
    
    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;
    
    out vec3 FragPos;
    out vec3 Normal;
    
    void main()
    {
        gl_Position = projection * view * model * vec4(aPos, 1.0);
        Normal = mat3(model) * aNormal;//用于旋转时,使得法向量一起改变
        FragPos = vec3(model * vec4(aPos, 1.0));
    }
    
    
    //stl.frag
    #version 330 core
    //layout( location = 0 ) out vec4 FragColor;
    
    out vec4 FragColor;
    uniform vec3 objectColor;
    uniform vec3 lightColor;
    in vec3 FragPos;
    in vec3 Normal;
    uniform vec3 lightPos;
    
    void main()
    {
         float ambientStrength = 0.1;
           vec3 ambient = ambientStrength * lightColor;
    
           vec3 norm = normalize(Normal);
           vec3 lightDir = normalize(lightPos - FragPos);
           float diff = max(dot(norm, lightDir), 0.0);
           vec3 diffuse = diff * lightColor;
    
           vec3 result = (ambient + diffuse) * objectColor;
           FragColor = vec4(result, 1.0);
    
    }
    
    
    //渲染OpenGL场景,widget需要更新时调用
    void demoOpenglWidget::initializeGL()
    {
        this->initializeOpenGLFunctions();
        shaderprogram.create();
    
    //将着色器加载到shaderprogram小程序中(注意路径根据自己的路径名称修改)    
    if(!shaderprogram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shaders/stl.vert"))
            qDebug()<<"ERROR:"<<shaderprogram.log();
    
        if(!shaderprogram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shaders/stl.frag"))
            qDebug()<<"ERROR:"<<shaderprogram.log();    //如果编译出错,打印报错信息
    
        //将添加到此程序的着色器与addshader链接在一起
        if(!shaderprogram.link())
            qDebug()<<"ERROR:"<<shaderprogram.log();    //如果链接出错,打印报错信息
    
    
    //创建VAO、VBO对象并绑定
        VAO.create();
        VAO.bind();
        VBO.create();
        VBO.bind();
        VBO.allocate(vertices.data(),sizeof(float)*vertices.size());
    
    //向着色器中传入顶点、法向量属性信息
        shaderprogram.setAttributeBuffer("aPos",GL_FLOAT,0,3,sizeof(GLfloat)*6);
        shaderprogram.enableAttributeArray("aPos");
        shaderprogram.setAttributeBuffer("aNormal", GL_FLOAT,sizeof(GLfloat) * 3, 3, sizeof(GLfloat) * 6);
        shaderprogram.enableAttributeArray("aNormal");
        this->glEnable(GL_DEPTH_TEST);
    
        view.setToIdentity();
        view.lookAt(QVector3D(0.0f,0.0f,3.0f),QVector3D(0.0f,0.0f,0.0f),QVector3D(0.0f,1.0f,0.0f));
    
    }
    
    //设置OpenGL视口、投影等。
    void demoOpenglWidget::resizeGL(int w, int h)
    {
        this->glViewport(0,0,w,h);
        projection.setToIdentity();
        projection.perspective(60.0f,(GLfloat)w/(GLfloat)h, 0.001f, 100.0f);//视角-宽高比例-zNear-zFar
    
    }
    
    //设置OenGL资源和状态;第一次调用resizeGL/paintGL调用
    void demoOpenglWidget::paintGL()
    {
        this->glClearColor(0.0f,0.0f,0.0f,1.0f);
        this->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        shaderprogram.bind();
    
    
        //定义参数
        QVector3D lightColor(1.0f,1.0f,1.0f);
        QVector3D objectColor(1.0f,1.0f,0.88f);//模型颜色
        QVector3D lightPos(0.0f,0.0f,50.0f);
        //传值到小程序
        shaderprogram.setUniformValue("objectColor",objectColor);
        shaderprogram.setUniformValue("lightColor",lightColor);
        shaderprogram.setUniformValue("lightPos", lightPos);
    
        model.setToIdentity();
        model.translate(xtrans,ytrans,ztrans);
        model.rotate(rotation);
        shaderprogram.setUniformValue("view",view);
        shaderprogram.setUniformValue("projection", projection);
        shaderprogram.setUniformValue("model", model);
    
        int n = vertices.capacity()/sizeof(float);
        qDebug() << n;//打印stl中三角形的数量(stl是多个三角形组成的文件)
        QOpenGLVertexArrayObject::Binder bind(&VAO);//绑定VAO
        this->glDrawArrays(GL_TRIANGLES,0,n);
    
    }

2.1 读取ascll码文件

?

QVector<float> demoOpenglWidget::loadAscllStl(QString filename, int ratio)
{//ratio为缩放系数
    QVector<float> vertices_temp;
    qDebug()<<"load text file:"<<filename;

    //读取ascll码文件
    QFile file(filename);
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
        qDebug() << "Open stl_file failed." << endl;
    }
    while(!file.atEnd()){
        //将文件内各个信息通过空格分隔,保存在words数组内
        QString line = file.readLine().trimmed();//trim去除首尾空白字符
        QStringList words = line.split(' ',QString::SkipEmptyParts);
        //法向量坐标开头为"facet"
        if(!file.atEnd() && words[0]=="facet"){
            Normal = {ratio*words[2].toFloat(),ratio*words[3].toFloat(),ratio*words[4].toFloat()};
        }
        //三角形各个顶点开头为"vertex"
        else if (!file.atEnd() && words[0] == "vertex") {
            Position = {ratio*words[1].toFloat(), ratio*words[2].toFloat(),ratio*words[3].toFloat()};
            vertices_temp.append(Position);
            vertices_temp.append(Normal);
        }
        else
            continue;
    }
    file.close();

            qDebug() << "write vertice_temp success!" << filename;
            return vertices_temp;
}

2.2 读取二进制文件

QVector<float> demoOpenglWidget::loadBinStl(std::string filename, int ratio)
{//ratio为缩放系数
    QVector<float> vertices_temp;
    qDebug()<<"load text file:"<<filename.c_str();

    FILE *file = fopen(filename.c_str(),"rb");

    //80字节文件头
    char header[80];
    fread(header,80,1,file);
    //4字节三角形面片数量
    uint32_t triangleNum;
    fread(&triangleNum,sizeof(uint32_t),1,file);
    float n1,n2,n3;
    float p1,p2,p3;
    for(auto i=0;i<triangleNum;i++){//读取法向量信息
        fread(&n1,sizeof(float),1,file);
        fread(&n2,sizeof(float),1,file);
        fread(&n3,sizeof(float),1,file);
        qDebug()<<"n1="<<n1<<" n2="<<n2<<" n3="<<n3;
        Normal={n1*ratio,n2*ratio,n3*ratio};

        for(auto j=0;j<3;j++){//读取顶点信息
            fread(&p1,sizeof(float),1,file);
            fread(&p2,sizeof(float),1,file);
            fread(&p3,sizeof(float),1,file);
            qDebug()<<"p1="<<p1<<" p2="<<p2<<" p3="<<p3;
            Position = {p1*ratio,p2*ratio,p3*ratio};
            vertices_temp.append(Position);
            vertices_temp.append(Normal);
        }
        //2字节三角形面片属性
        char c[2];
        fread(c,2,1,file);
    }
    fclose(file);
    delete file;
    qDebug() << "write vertice_temp success!" << filename.c_str();
    return vertices_temp;
}

?2.3 鼠标交互


void demoOpenglWidget::mousePressEvent(QMouseEvent *event)
{
    mousePos = QVector2D(event->pos());
    event->accept();
}

void demoOpenglWidget::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() == Qt::LeftButton){
        QVector2D newPos = (QVector2D)event->pos();
        QVector2D diff = newPos - mousePos;
        qreal angle = (diff.length())/3.6;

        QVector3D rotationAxis = QVector3D(diff.y(), diff.x(), 0.0).normalized();
        rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angle) * rotation;
        mousePos = newPos;
        this->update();
    }
    event->accept();
}

//鼠标滚轮缩放模型

void demoOpenglWidget::wheelEvent(QWheelEvent *event)
{
    QPoint numDegrees = event->angleDelta()/8;

    if(numDegrees.y() > 0){
        ztrans += 0.25f;
    }
    else if(numDegrees.y() < 0){
        ztrans -= 0.25f;
    }
    this->update();
    event->accept();
}

?2.4 cpp源代码

#include "demoopenglwidget.h"
#include"QDebug"
#include<QStringList>
#include <QFile>
#include<QtMath>


demoOpenglWidget::demoOpenglWidget(QWidget *parent)
    : QOpenGLWidget(parent),
      VBO(QOpenGLBuffer::VertexBuffer),
      xtrans(0),ytrans(0),ztrans(0.0)
//      verticesCnt(0)//顶点坐标计数
{
    QSurfaceFormat format;
    format.setAlphaBufferSize(24);
    format.setVersion(3,3);
    format.setSamples(10);//设置重采样次数,用于反走样

    this->setFormat(format);


//导入模型文件(路径根据自己情况更改)
//    vertices=loadAscllStl(":/res/stl/demo_ascll.txt",1);
    vertices=loadBinStl(":/res/stl/demo_bin.stl",1);
}

demoOpenglWidget::~demoOpenglWidget()
{
    makeCurrent();
}

//渲染OpenGL场景,widget需要更新时调用
void demoOpenglWidget::initializeGL()
{
    this->initializeOpenGLFunctions();
    shaderprogram.create();
    if(!shaderprogram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shaders/stl.vert"))
        qDebug()<<"ERROR:"<<shaderprogram.log();

    if(!shaderprogram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shaders/stl.frag"))
        qDebug()<<"ERROR:"<<shaderprogram.log();    //如果编译出错,打印报错信息

    //将添加到此程序的着色器与addshader链接在一起
    if(!shaderprogram.link())
        qDebug()<<"ERROR:"<<shaderprogram.log();    //如果链接出错,打印报错信息


    VAO.create();
    VAO.bind();
    VBO.create();
    VBO.bind();
    VBO.allocate(vertices.data(),sizeof(float)*vertices.size());


    shaderprogram.setAttributeBuffer("aPos",GL_FLOAT,0,3,sizeof(GLfloat)*6);
    shaderprogram.enableAttributeArray("aPos");
    shaderprogram.setAttributeBuffer("aNormal", GL_FLOAT,sizeof(GLfloat) * 3, 3, sizeof(GLfloat) * 6);
    shaderprogram.enableAttributeArray("aNormal");
    this->glEnable(GL_DEPTH_TEST);

    view.setToIdentity();
    view.lookAt(QVector3D(0.0f,0.0f,3.0f),QVector3D(0.0f,0.0f,0.0f),QVector3D(0.0f,1.0f,0.0f));

}

//设置OpenGL视口、投影等。
void demoOpenglWidget::resizeGL(int w, int h)
{
    this->glViewport(0,0,w,h);
    projection.setToIdentity();
    projection.perspective(60.0f,(GLfloat)w/(GLfloat)h, 0.001f, 100.0f);//视角-宽高比例-zNear-zFar

}

//设置OenGL资源和状态;第一次调用resizeGL/paintGL调用
void demoOpenglWidget::paintGL()
{
    this->glClearColor(0.0f,0.0f,0.0f,1.0f);
    this->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    shaderprogram.bind();


    //定义参数
    QVector3D lightColor(1.0f,1.0f,1.0f);
    QVector3D objectColor(1.0f,1.0f,0.88f);//模型颜色
    QVector3D lightPos(0.0f,0.0f,50.0f);
    //传值到小程序
    shaderprogram.setUniformValue("objectColor",objectColor);
    shaderprogram.setUniformValue("lightColor",lightColor);
    shaderprogram.setUniformValue("lightPos", lightPos);

    model.setToIdentity();
    model.translate(xtrans,ytrans,ztrans);
    model.rotate(rotation);
    shaderprogram.setUniformValue("view",view);
    shaderprogram.setUniformValue("projection", projection);
    shaderprogram.setUniformValue("model", model);

    int n = vertices.capacity()/sizeof(float);
    qDebug() << n;//打印stl中三角形的数量(stl是多个三角形组成的文件)
    QOpenGLVertexArrayObject::Binder bind(&VAO);//绑定VAO
    this->glDrawArrays(GL_TRIANGLES,0,n);

}

QVector<float> demoOpenglWidget::loadAscllStl(QString filename, int ratio)
{
    QVector<float> vertices_temp;
    qDebug()<<"load text file:"<<filename;

    QFile file(filename);
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
        qDebug() << "Open stl_file failed." << endl;
    }
    while(!file.atEnd()){
        QString line = file.readLine().trimmed();//trim去除首尾空白字符
        QStringList words = line.split(' ',QString::SkipEmptyParts);

        if(!file.atEnd() && words[0]=="facet"){
            Normal = {ratio*words[2].toFloat(),ratio*words[3].toFloat(),ratio*words[4].toFloat()};
        }
        else if (!file.atEnd() && words[0] == "vertex") {
            Position = {ratio*words[1].toFloat(), ratio*words[2].toFloat(),ratio*words[3].toFloat()};
            vertices_temp.append(Position);
            vertices_temp.append(Normal);
        }
        else
            continue;
    }
    file.close();

            qDebug() << "write vertice_temp success!" << filename;
            return vertices_temp;
}

QVector<float> demoOpenglWidget::loadBinStl(std::string filename, int ratio)
{
    QVector<float> vertices_temp;
    qDebug()<<"load text file:"<<filename.c_str();

    FILE *file = fopen(filename.c_str(),"rb");

    //80字节文件头
    char header[80];
    fread(header,80,1,file);
    //4字节三角形面片数量
    uint32_t triangleNum;
    fread(&triangleNum,sizeof(uint32_t),1,file);
    float n1,n2,n3;
    float p1,p2,p3;
    for(auto i=0;i<triangleNum;i++){//读取法向量信息
        fread(&n1,sizeof(float),1,file);
        fread(&n2,sizeof(float),1,file);
        fread(&n3,sizeof(float),1,file);
        qDebug()<<"n1="<<n1<<" n2="<<n2<<" n3="<<n3;
        Normal={n1*ratio,n2*ratio,n3*ratio};

        for(auto j=0;j<3;j++){//读取顶点信息
            fread(&p1,sizeof(float),1,file);
            fread(&p2,sizeof(float),1,file);
            fread(&p3,sizeof(float),1,file);
            qDebug()<<"p1="<<p1<<" p2="<<p2<<" p3="<<p3;
            Position = {p1*ratio,p2*ratio,p3*ratio};
            vertices_temp.append(Position);
            vertices_temp.append(Normal);
        }
        //2字节三角形面片属性
        char c[2];
        fread(c,2,1,file);
    }
    fclose(file);
    delete file;
    qDebug() << "write vertice_temp success!" << filename.c_str();
    return vertices_temp;
}

void demoOpenglWidget::mousePressEvent(QMouseEvent *event)
{
    mousePos = QVector2D(event->pos());
    event->accept();
}

void demoOpenglWidget::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() == Qt::LeftButton){
        QVector2D newPos = (QVector2D)event->pos();
        QVector2D diff = newPos - mousePos;
        qreal angle = (diff.length())/3.6;

        QVector3D rotationAxis = QVector3D(diff.y(), diff.x(), 0.0).normalized();
        rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angle) * rotation;
        mousePos = newPos;
        this->update();
    }
    event->accept();
}

void demoOpenglWidget::wheelEvent(QWheelEvent *event)//鼠标滚轮缩放模型
{
    QPoint numDegrees = event->angleDelta()/8;

    if(numDegrees.y() > 0){
        ztrans += 0.25f;
    }
    else if(numDegrees.y() < 0){
        ztrans -= 0.25f;
    }
    this->update();
    event->accept();
}


?3.问题

3.1 内存溢出

out of memory 内存溢出 在pro配置文件加入CONFIG+=resources_big

3.2 三角形面片过多

可以发现在解析bin的文件时,默认四字节的三角形面片数,也即超过0xFFFF(65535)个面片将会内存溢出。当在解析函数中更改为64位读取时发现也不成功,仍然出现out of memory内存溢出错误;

解决方案:

配置文件加CONFIG+=resources_big

采取精简面片,此时面片为0xfe0e刚好在32位内,但此时发现文件读取不了,fopen一直打开是空指针。

查了很多博客发现还是无法解决,突然想到之前打开ascll码文件时出现文件内存溢出,再试一下ascll码打开文件,成功。

  1. 选择物体,打开修改器,选择精简
  2. 修改塌陷比率,越低三角形面片越少,当然模型越粗糙。
  3. 可以看出此时模型三角形清晰可见,面片变少,当然模型非常粗糙。

?

这样做的目的是:

  • ascll码&&二进制文件过大,加载较慢甚至加载不出来,故此步骤相当于压缩

  • 当面片数过多时,在读取ascll码文件时,在提取完80个字节的头文件信息后,发现三角形面片数量保存在32位4字节中,当面片数量超出0xffff时,猜测面片数量将会以64位存储(甚至更大),但是具体怎么处理我还没有实现。to be continue....

?4.总结

模型处理时:

- 坐标中心位于模型中心,方便绕着模型中心旋转
- 面片过大时在blender中修改精简比例
- 输出文件注意是ascll码格式还是二进制文件

工程目录中:

- 内存溢出时加入配置文件:CONFIG+=resources_big
- 目录注意更改(ascll可用相对路径,二进制用绝对(不要出现中文))?

?

?5.参考博客

QT OpenGL加载STL模型文件并旋转放缩_GT_L_0813的博客-CSDN博客

Qt/C++ + opengl 解析stl文件(二进制和Ascii两种格式)_shenmingyi.blog.csdn.net-CSDN博客_qt stl文件

6.工程文件

OpenGL_Qt: 实现加载ascll码&&二进制格式stl文件加载,并在OpenGL控件中展示。实现了鼠标拖动旋转,滚轮缩放。注意ascll可用相对路径加载,二进制仅可用绝对路径加载。值得注意的是二进制文件无法打开过大文件(打开文件指针为空),此项目只适用于较小stl文件读取。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-14 01:47:11  更:2022-01-14 01:48:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:28:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码