精华内容
下载资源
问答
  • matlab如何读取并显示stl模型
    千次阅读
    2020-12-27 19:45:06

    matlab函数如何读取并显示stl模型

    利用stlread函数可方便的实现stl文件读取的操作,不过该实现只可读取binary格式的stl文件,并不能读取ASCII格式的stl文件,相应实现也很简单。不过本文的重点不在stl模型的读取上,而在stl模型的显示上。

    patch绘制一个四边形

    matlab自带的patch函数可以实现多边形的绘制

    patch(X,Y,Z,C) 使用 XYZ 在三维坐标中创建多边形。

    X指的是多边形各顶点的x坐标构成的一维向量。Y,Z同理,C表示Color,通过改变C的参数改变面片的颜色。

    例如:

    创建一个红色正方形,顶点位于 (0,0)(1,0)(1,1)(0,1)。将 x 指定为顶点的 x 坐标,并将 y 指定为 y 坐标。patch 会自动将最后一个 (x,y) 坐标与第一个 (x,y) 坐标连接。

    x = [0 1 1 0];
    y = [0 0 1 1];
    patch(x,y,'red')
    

    红色正方形

    我们在绘制stl模型的时候实际上要一个不拉的绘制组成stl模型的所有三角面片。可以通过遍历的方法来实现,但通过改造数据的存储方式可直接调用patch(x,y,z)函数绘制出stl模型


    patch函数绘制两个三角形

    通过将 xyz指定为三行两列矩阵,创建两个三角形。

    x =		   	[95.5147094726563,91.7259368896484;94.4062042236328,95.5147094726563;89.4406509399414,89.4406509399414];
    y = 
    [17.7316799163818,17.7316799163818;0,17.7316799163818;0,0];
    z = [0.283457338809967,0.159092247486115;14.8238019943237,0.283457338809967;14.5865011215210,14.5865011215210];
    patch(x,y,z,'green');
    

    看上去很复杂。但把这组数据解读一下

    x=[第一个三角形的第一个点的x坐标,第二个三角形的第一个点的x坐标;...;第n个三角形的第一个点的x坐标;
       第一个三角形的第二个点的x坐标,第二个三角形的第二个点的x坐标;...;第n个三角形的第二个点的x坐标;
       第一个三角形的第三个点的x坐标,第二个三角形的第三个点的x坐标;...;第n个三角形的第三个点的x坐标;]
    y=[第一个三角形的第一个点的y坐标,第二个三角形的第一个点的y坐标;...;第n个三角形的第一个点的y坐标;
       第一个三角形的第二个点的y坐标,第二个三角形的第二个点的y坐标;...;第n个三角形的第二个点的y坐标;
       第一个三角形的第三个点的y坐标,第二个三角形的第三个点的y坐标;...;第n个三角形的第三个点的y坐标;]
    z=[第一个三角形的第一个点的z坐标,第二个三角形的第一个点的z坐标;...;第n个三角形的第一个点的z坐标;
       第一个三角形的第二个点的z坐标,第二个三角形的第二个点的z坐标;...;第n个三角形的第二个点的z坐标;
       第一个三角形的第三个点的z坐标,第二个三角形的第三个点的z坐标;...;第n个三角形的第三个点的z坐标;]
    

    只要按这样的格式对数据进行存储就可以使用patch函数直接绘制出stl模型。

    绘制两个三角形

    ver1,ver2, ver3 分别表示组成该三角面片的第一个顶点,第二个顶点,第三个顶点。

    x(:,i)=[ver1(1); ver2(1); ver3(1)]; % 第一个三角面片的三个点的x坐标
    y(:,i)=[ver1(2); ver2(2); ver3(2)]; % 第一个三角面片的三个点的y坐标
    z(:,i)=[ver1(3); ver2(3); ver3(3)]; % 第一个三角面片的三个点的z坐标
    

    x的第i列为第i个三角面片的第一个顶点的x坐标,

    ​ 第二个顶点的x坐标,

    ​ 第三个顶点的x坐标。

    y的第i列为第i个三角面片的第一个顶点的y坐标,

    ​ 第二个顶点的y坐标,

    ​ 第三个顶点的y坐标。

    z的第i列为第i个三角面片的第一个顶点的z坐标,

    ​ 第二个顶点的z坐标,

    ​ 第三个顶点的z坐标。

    patch函数额外参数

    matlab允许在调用patch()时提供一些额外的参数来改变透明度,面片颜色,线条样式等信息

    示例: patch(x,y,c,'FaceAlpha',.5,'LineStyle',':') 创建包含点线边的半透明多边形。

    在’FaceAlpha’后输入0-1的值表示透明度,范围 [0,1] 中的标量 - 在所有面上使用统一的透明度。值为 1 时完全不透明,值为 0 时完全透明;

    在’LineStyle’后输入线性参数,改变线条样式;

    matlab绘制stl模型

    [x,y,z,c] = stlread('C:\Users\Admin\Desktop\stlread\skeletonTest.STL');
            		backcolor = 'white';
            		patch(x,y,z,'w','FaceAlpha',.5,'EdgeColor','black');
            		set(gca,'xtick',0:10:200);  
           		 	set(gca,'ytick',0:10:90);
           		 	set(gca,'ztick',-20:10:140);
            		view(3);
    

    stl模型绘制

    更多相关内容
  • java加载obj,stl模型资源,html页面展示。 部署即可运行,提供基础数据样例展示
  • 针对如何快速求取空间点到STL模型表面有符号距离这一问题,提出一种基于线性八叉树的参考球方法。通过线性八叉树的分割将STL模型的三角面片集划分到线性八叉树内的不同节点中,把三角面片与线性八叉树的终端节点联系...
  • c# 解析二进制.stl模型

    2020-11-14 11:42:19
    .stl有两种格式:二进制和ASCII,请注意区分。本资源为c# 解析二进制.stl模型,分享一个demo,希望各位网友下载能用得上。
  • stl模型碰撞检测.txt

    2019-12-29 14:13:15
    对于两个模型中的每一个三角形,总共会有6种情况, 1)两个三角形形成的平面的交线上没有上述两个三角形之一 2)有其中一个在交线上 3)两三角形在同一平面 4)一个三角形的角碰到另一个三角形 5)一个三角形...
  • Unity3D导入STL模型

    2018-03-24 22:25:36
    unity导入stl模型的例子。里面有示例程序,导入资源包运动demo。
  • 常用STL模型文件

    2016-04-25 14:26:27
    常用的STL模型文件,可用于STL显示与编辑相关程序的开发与测试
  • 为了将具有开口边界的动脉血管STL模型转化为封闭边界的模型,探讨了动脉血管STL模型的拓扑重建、边界识别及其三角剖分的方法。采用半边数据结构重建STL文件的拓扑结构,通过一个边查找过程将STL文件表示的各个边界...
  • 对基于STL模型的切片处理技术进行了深入分析,并在吸收现有算法优点的基础上,提出了分组排序、对边求交的分层算法。该算法先根据三角面片中顶点在分层方向的最大坐标值和最小坐标值对各面片进行排序并形成分层关系...
  • 为生成STL模型无干涉的刀具轨迹,利用与顶点相连的各三角面片的法向向量,计算出各顶点的偏置点,并由这些偏置点构造完全由三角面片组成的偏置模型:用平行截面对偏置模型进行切片,在二维空间内对所得交线段进行...
  • 针对传统STL模型布尔运算计算精度不高的问题,采用六元组结构记录相交三角面片的交线段,将相交三角面片分为4种情况,依据STL模型中三角面片的拓扑关系,采用递归搜索交线段记录的方法提取出交线链和交线环,对于共...
  • VC++2012 MFC实现调用TetGen对stl模型数据进行四面体剖分
  • 为提高STL模型的切片效率,提出一种基于MATLAB的STL模型切片分层新算法。首先对STL模型进行数据预处理,筛选出只与切平面相交的三角片集合,然后利用相邻三角面片边的拓扑关系依次求交,获得各层截面轮廓信息。实验结果...
  • 浩克 绿巨人拆件3d打印stl模型.zip 3D打印
  • 针对传统基于立体平面印刷(STL)文件的三维模型表面区域拾取生成算法速度慢、效率低且不易识别裂缝等非正常情况,提出了一种采用递归搜索的表面区域快速拾取算法.该算法利用模型中所有三角面片构造拓扑信息,通过...
  • 模型的分层是3D打印前处理的一个重要环节,针对目前分层算法效率低、不能有效保留模型细微特征的问题,提出了一种新的基于STL模型特征信息的思想。首先提取模型的特征边,对特征边内实体表面采用区域增长算法进行...
  • 简易设计的压书指环,用于解决纸质书过厚不便展平阅读的问题,模型已封装好,因为是stl文件不能再改动,可直接用于3D打印
  • 方便侧睡的stl模型,文件不大。stl模型-机器小人-测试模型
  • 采用STL模型对激光头进行模型化,并将其分为凸型和凹型两种类型;利用工件STL模型的离散点与激光头各三角面片法向量位置关系找出干涉区域;给出了通过旋转激光头来消除干涉并利用一系列切平面切割激光头来计算临界旋转...
  • 利用openGL库编写,采用VC++6.0开发环境,实现STL文件读取、显示、操作、控制、分层。
  • QT OpenGL加载STL模型文件并旋转放缩

    千次阅读 2021-06-03 16:22:20
    但是本人太菜,网上搜索的各种方法我都没能成功在QT中实现,而且本人项目需求不高,所以我选择了简单的方法来加载模型文件——STL模型文件加载,也就是说我这个只能加载一个格式的模型文件,但对我来说够用了。...

    在这里插入图片描述

    加载模型文件

    模型文件有很多种格式,有一种方法是利用Assimp库来加载各类格式的模型,也就是众生平等!
    但是本人太菜,网上搜索的各种方法我都没能成功在QT中实现,而且本人项目需求不高,所以我选择了简单的方法来加载模型文件——STL模型文件加载,也就是说我这个只能加载一个格式的模型文件,但对我来说够用了。

    STL文件格式

    在这里插入图片描述
    文件格式如上图:STL格式是将模型保存为一个又一个的小三角形,精度越高,三角形数量越多。
    其中fact-endfact之间是一个三角形的信息,包括facet normal后面的是该面的法向量,用于光照。
    三个vertex是三角形三个顶点。通过如下函数可将该模型文件的信息读入数组之中。

    vertices = loadAscllStl("C:\\Users\\86132\\Desktop\\STL_model_ascll\\test1.STL",1);
    

    ratio是放大系数,用于模型文件尺寸数据过大或者过小时,可用该系数调整。

    QVector<float> Widget::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(); // trimmed去除了开头和结尾的空白字符串
          QStringList  words = line.split(' ', QString::SkipEmptyParts);
    
          if (words[0] == "facet") {
          Normal = {ratio*words[2].toFloat(), ratio*words[3].toFloat(),ratio*words[4].toFloat()};//获取法向量
          }
          else if (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;
          }
    
          }
    
        qDebug() << "write vertice_temp success!" << filename;
        return vertices_temp;
     //   file.close();
    }
    

    这里填写模型文件地址时,我始终加载不成功,最后找到个说法,得用双斜杠在地址中才能加载成功!

    SolidWorks绘制模型保存时要注意的地方

    首先,最好以原点为模型的中心,这样旋转的时候才会以模型的中心旋转,而不是以某一顶点旋转。
    其次,保存文件时,在选项中可选择单位,精度,以及勾选不将坐标转为正空间。如果不勾选,软件回默认将你的模型坐标全部转为正坐标,这样,即使你画模型时,将模型中心放在原点,也会全部被转为正坐标,到时候出来的模型旋转会以一个顶点而非中心旋转。
    精度选取可自行选取,看上面的GIF,中间圆柱很明显像是很多长方形连起来的,这是因为我选的精度不高。

    鼠标事件实现旋转放缩

    这部分原理与坐标变换那部分相同。主要是获取鼠标的操作信息,来获取xtrans,ytrans,ztrans。然后改变model矩阵,通过该矩阵与模型顶点数据相乘,即可得到旋转放缩的模型。之前的旋转的立方体的model是随时间变化,这里只不过改成了随鼠标的输入变化而已。

    鼠标事件代码

    void Widget::mousePressEvent(QMouseEvent *event)//鼠标事件获取
    {
        mousePos = QVector2D(event->pos());
        event->accept();
    }
    
    void Widget::mouseMoveEvent(QMouseEvent *event)//鼠标移动
    {
        if(event->buttons() == Qt::LeftButton)
        {
            QVector2D newPos = (QVector2D)event->pos();
            QVector2D diff = newPos - mousePos;
            qreal angle = (diff.length())/3.6;
            // Rotation axis is perpendicular to the mouse position difference
            // vector
            QVector3D rotationAxis = QVector3D(diff.y(), diff.x(), 0.0).normalized();
            rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angle) * rotation;
            mousePos = newPos;
            this->update();
        }
        event->accept();
    }
    
    void Widget::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();
    }
    

    model改变

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

    顶点着色器改变

       gl_Position = projection * view * model * vec4(aPos, 1.0);
    

    光照部分

        QVector3D lightColor(1.0f,1.0f,1.0f);
        QVector3D objectColor(1.0f,0.5f,0.31f);
        QVector3D lightPos(0.0f,0.0f,50.0f);//光源位置
    
        shaderprogram.setUniformValue("objectColor",objectColor);
        shaderprogram.setUniformValue("lightColor",lightColor);
        shaderprogram.setUniformValue("lightPos", lightPos);
    

    片段着色器改变

         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);
    

    整体代码分享

    main.cpp

    #include "widget.h"
    
    #include <QApplication>
    #include <QDebug>
    #include <QVector>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Widget w;
        w.show();
            w.resize(800, 600);
    
            return a.exec();
    }
    

    widget.h

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QOpenGLWidget>
    #include <QOpenGLExtraFunctions>
    #include <QVector>
    #include <QStringList>
    #include <QOpenGLShaderProgram>
    #include <QOpenGLVertexArrayObject>
    #include <QOpenGLBuffer>
    #include <QTimer>
    #include <QTime>
    #include <QMatrix4x4>
    #include <QMatrix3x3>
    #include <QQuaternion>
    #include <QVector2D>
    
    class Widget : public QOpenGLWidget,public QOpenGLExtraFunctions
    {
        Q_OBJECT
    
    public:
        Widget(QWidget *parent = nullptr);
        ~Widget();
    
    protected:
        virtual void initializeGL() override;
        virtual void paintGL() override;
        virtual void resizeGL(int w,int h) override;
        QVector<float> loadAscllStl(QString filename,int ratio);//文件名和放大系数
        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;//声明VAO顶点数组对象
        QOpenGLBuffer VBO;//声明VBO数组缓冲对象
    
        QMatrix4x4 model;
        QMatrix4x4 view;
        QMatrix4x4 projection;
    
        GLfloat xtrans, ytrans, ztrans; // translation on x,y,z-axis
        QVector2D mousePos;
        QQuaternion rotation;
    };
    #endif // WIDGET_H
    
    

    widget.cpp

    #include "widget.h"
    #include <QDebug>
    #include <QFile>
    #include <QStringList>
    #include <QtMath>
    #include <QOpenGLShaderProgram>
    #include <QMouseEvent>
    #include <QWheelEvent>
    
    Widget::Widget(QWidget *parent)
        : QOpenGLWidget(parent)
        ,VBO(QOpenGLBuffer::VertexBuffer)
        ,xtrans(0),ytrans(0),ztrans(0.0)
    {
        QSurfaceFormat format;
        format.setAlphaBufferSize(24);  //设置alpha缓冲大小
        format.setVersion(3,3);         //设置版本号
        format.setSamples(10);          //设置重采样次数,用于反走样
    
        this->setFormat(format);
    
             vertices = loadAscllStl("C:\\Users\\86132\\Desktop\\STL_model_ascll\\test1.STL",1);
    
    }
    
    Widget::~Widget()
    {
        makeCurrent();
    }
    
    QVector<float> Widget::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(); // trimmed去除了开头和结尾的空白字符串
          QStringList  words = line.split(' ', QString::SkipEmptyParts);
    
          if (words[0] == "facet") {
          Normal = {ratio*words[2].toFloat(), ratio*words[3].toFloat(),ratio*words[4].toFloat()};
          }
          else if (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;
          }
    
          }
    
        qDebug() << "write vertice_temp success!" << filename;
        return vertices_temp;
     //   file.close();
    }
    
    void Widget::initializeGL()
    {
        this->initializeOpenGLFunctions();//初始化opengl函数
        shaderprogram.create();//生成着色器程序
        if(!shaderprogram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/stl.vert")){
            qDebug()<<"ERROR:"<<shaderprogram.log();    //如果编译出错,打印报错信息
        }
        if(!shaderprogram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/stl.frag")){
            qDebug()<<"ERROR:"<<shaderprogram.log();    //如果编译出错,打印报错信息
        }
        //将添加到此程序的着色器与addshader链接在一起
         if(!shaderprogram.link()){
             qDebug()<<"ERROR:"<<shaderprogram.log();    //如果链接出错,打印报错信息
         }
    //    QOpenGLVertexArrayObject::Binder{&VAO};
    
        VAO.create();// 创建一个VAO对象,OpenGL会给它(顶点数组缓存对象)分配一个id
        VAO.bind();//将RC中的当前顶点数组缓存对象Id设置为VAO的id
        VBO.create();
        VBO.bind();
        VBO.allocate(vertices.data(),sizeof(float)*vertices.size());//将顶点数据分配到VBO中,第一个参数为数据指针,第二个参数为数据的字节长度
    
    
    
        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);
    //    VAO.release();//释放
    //    VBO.release();
    
        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));
        //shaderprogram.setUniformValue("view", view);
    }
    void Widget::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);
        //shaderprogram.setUniformValue("projection", projection);
    }
    
    void Widget::paintGL()
    {
        this->glClearColor(0.0f,0.0f,0.0f,1.0f);//设置清屏颜色
        this->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清空颜色缓冲区
    
        shaderprogram.bind();
        //将此着色器程序绑定到活动的qopenglcontext,并使其成为当前着色器程序。任何先前绑定的着色器程序都将被释放
        //成功绑定返回ture,反之,返回false.
      {
        QVector3D lightColor(1.0f,1.0f,1.0f);
        QVector3D objectColor(1.0f,0.5f,0.31f);
        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;
        QOpenGLVertexArrayObject::Binder bind(&VAO);//绑定VAO
        this->glDrawArrays(GL_TRIANGLES,0,n);
    
        }
    }
    
    
    void Widget::mousePressEvent(QMouseEvent *event)
    {
        mousePos = QVector2D(event->pos());
        event->accept();
    }
    
    void Widget::mouseMoveEvent(QMouseEvent *event)
    {
        if(event->buttons() == Qt::LeftButton)
        {
            QVector2D newPos = (QVector2D)event->pos();
            QVector2D diff = newPos - mousePos;
            qreal angle = (diff.length())/3.6;
            // Rotation axis is perpendicular to the mouse position difference
            // vector
            QVector3D rotationAxis = QVector3D(diff.y(), diff.x(), 0.0).normalized();
            rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angle) * rotation;
            mousePos = newPos;
            this->update();
        }
        event->accept();
    }
    
    void Widget::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();
    }
    
    

    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);
    
    }
    
    

    在这里插入图片描述

    至此,在Windows下的QT5.9.9下实现了STL模型文件的加载放缩旋转展示。

    展开全文
  • STL模型简化技术

    2018-07-20 11:41:43
    STL模型的某些区域存在一些狭长的钝角三角形,它们对模型逼近误差的影响非常小,在精度允许的条件下可以将其忽略。通过剔除部分符合一定条件的钝角三角形,合理简化了STL模型,节省了文件存储空间和后续数据处理时间...
  • 基于MATLAB的STL模型切片分层算法

    千次阅读 2021-05-06 09:01:53
    吴建 吴婷 陈廷豪 包涵摘 要:为提高STL模型的切片效率,提出一种基于MATLAB的STL模型切片分层新算法。首先对STL模型进行数据预处理,筛选出只与切平面相交的三角片集合,然后利用相邻三角面片边的拓扑关系依次求交...

    吴建 吴婷 陈廷豪 包涵

    5382a186500fe54805482ae5a4a6972c.png

    2397c8f32e56af5ab1ff0c704985812e.png

    c22e8c5ed617064ae19aba6c9dc0049b.png

    摘  要:为提高STL模型的切片效率,提出一种基于MATLAB的STL模型切片分层新算法。首先对STL模型进行数据预处理,筛选出只与切平面相交的三角片集合,然后利用相邻三角面片边的拓扑关系依次求交,获得各层截面轮廓信息。實验结果表明,该方法简单、有效,不仅优化了数据结构,而且提高了切片效率,具有较好的可行性和准确性。

    关键词:3D打印;切片;STL模型;MATLAB

    中图分类号:TP391.73      文献标志码:A         文章编号:2095-2945(2020)02-0023-02

    Abstract: In order to improve the slicing efficiency of STL model, a new slicing algorithm of STL model based on MATLAB is proposed. First, the STL model is preprocessed, and the set of triangles which only intersect with the tangent plane is selected, and then the topological relationship between the edges of the adjacent triangular patches is used to obtain the profile information of each layer. The experimental results show that the method is simple and effective, not only optimizes the data structure, but also improves the slicing efficiency and has good feasibility and accuracy.

    Keywords: 3D printing; slicing; STL model; MATLAB

    引言

    3D打印,又称作快速成形,是一种以数字模型文件为基础,运用粉末状金属或塑料等可粘合材料,通过逐层堆叠累积的方式来构造物体的技术[1]。它对结构复杂、形态多变、骨架分支多的难加工形体具有显著优势,因而在现代医学、高端制造等领域有着广泛的应用[2]。在3D打印工艺过程中,分层切片处理是最为关键的内容之一。它通过层切平面与3D模型截面相交, 得到各层截面轮廓信息,因此切片处理的效率和精度直接影响模型制作的精度和质量[3]。

    本文以MATLAB软件作为开发平台,对3D打印切片问题展开研究,运用矩阵和数组及MATLAB自带的一些函数,在MATLAB软件平台下实现STL模型的快速分层切片处理。

    1 算法原理

    STL模型是由多个三角形面片组成的三维物体,因此对模型进行切片就是沿切层方向(z轴)建立多个切平面,分别求出每层切平面与三角面片的交点,然后进行拓扑重连,从而获得截面轮廓线。

    由于STL模型数据量较大,为提高切片处理的效率,本文采用如下方法进行计算:首先对STL模型进行数据排序,然后筛选出与各层切平面相交的三角面片集合, 以减少三角面片与切平面的求交判断次数;在计算三角面片与各层切平面间的交点时, 利用相邻三角面片边的拓扑关系求交,可快速确定交点,减少冗余点计算。

    1.1 数据预处理

    利用MATLAB软件的stlread函数读取STL模型数据,得到一个三角网格对象,其中包含两个矩阵成员:一个为网格顶点的坐标矩阵,设为P;另一个为组成三角面片的顶点索引矩阵,设为T。

    依次从三角面片索引矩阵T中取出每个三角面片的顶点索引号,并从顶点坐标矩阵P中找到其顶点的x、y、z坐标,然后将它们按照z坐标值的大小进行排序,并排成一行:

    [x1,y1,zmin,x2,y2,zmid,x3,y3,zmax]

    从而得到一个新的三角面片坐标矩阵Vm×9,其中每行表示一个三角面片坐标信息,m为三角面片总数。然后将矩阵V按照zmin进行升序排序,如果zmin相同的,将zmax值小的三角面片排在前面。

    1.2 相交三角片的智能筛选

    在计算每层切平面与三角面片的交点时,根据每个三角面片的z坐标数据进行判断,筛选出只与当前切平面相交的三角面片集合,以提高分层处理速度。具体步骤如下:

    步骤1,首先根据切片精度Δz和模型z坐标的最大值与最小值进行等厚度分层,得到各层切平面的高度zi(i=1,2,…,n,n为切片总数)。

    步骤2,利用判断条件筛选出与每层切平面zi相交的三角面片集合。若三角面片与切平面zi相交,则需满足zmin≤zi≤zmax,如图1所示,具体分为以下几种情况:

    (1)三角面片的两条边与切片面相交(图1(a));(2)三角面片的一条边与切平面重合(图1(b)(c)),若图1(b)三角片和图1(c)三角片共边,为避免产生冗余点,只保留图1(b)所示三角片;(3)三角面片的一个顶点在切平面上(图1(d)(e)),为避免产生冗余点,只保留图1(d)所示三角片;(4)三角面片与切平面重合(图1(f)),这种情况无法产生有效相交线段,故做排除。

    1.3 拓扑求交

    三角网格模型中,每条边都有两个三角面片与之共享,因此利用这种邻接拓扑关系,按顺序依次求交即可得到首尾相连的切片轮廓。具体步骤如下:

    步骤1,从筛选出的相交三角面片集合中,随机确定一个三角面片作为起始三角面片,计算该三角面片与切平面的交点,并保存交点所在的边,然后从集合中删除这个三角面片。

    步骤2,在相交三角面片的集合中找到一个和上一个三角面片的交点边是公共边的三角面片,然后再对这个三角面片进行交点计算,保存交点所在的边后,从集合中删除这个三角面片。如图2所示,根据三角面片1的交点P1所在的边AB找到与之相邻的三角面片2,然后计算切平面与三角面片2的另一个交点P2,根据交点P2所在的边BC找到三角面片3,依次类推。

    步骤3,重复步骤2,直到找不到下一个拓扑三角面片,按顺序连接交点即可获得当前封闭轮廓。

    步骤4,重复步骤1、步骤2、步骤3,直到相交的三角面片集合为空集,从而完成该层切片所有封闭轮廓的创建。

    2 实例验证

    为检验本文算法的有效性,以图3所示的蝎子模型为实例,进行切片测试。该模型共有461708个三角面片,230856个顶点,X、Y、Z方向总体尺寸约为59mm、42mm、20mm。采用0.4mm的分层精度对该模型进行切片测试,从图4结果可以看出,即使该模型复杂、具有多条分支结构,本文算法也能产生较好的效果。

    3 结束语

    本文以MATLAB软件为平台,通过数据预处理、筛选相交三角面片集合、拓扑求交等步骤有效地对模型进行切片分层处理,最大化的保留了原始形状特征,重构出准确率高的切片模型。该方法方便快捷,加强了切片数据的可控性,优化了切片的效率,提高了切片轮廓的准确性,且该程序简短易懂,具有较好的应用价值。

    参考文献:

    [1]郭亮,安芬菊,王贵.便携式3D打印机设计[J].机电工程技术,2017,46(10):90-92+108.

    [2]徐敬华,任新华,陈前勇,等.基于双倾斜度概率的流形模型3D打印层切优化方法[J].机械工程学报,2019,55(13):129-143.

    [3]徐敬华,盛红升,张树有,等.基于邻接拓扑的流形网格模型层切多连通域构建方法[J].计算机辅助设计与图形学学报,2018,30(1):180-190.

    展开全文
  • Threejs-stl-演示 用于解析和呈现 STL(ascii 和二进制)文件的纯 Javascript 演示代码。 ...用于通过 Javascript 在 WebGL/Canvas 中渲染 3D 模型的能力 灵感来自 执照 Threejs-stl-demo 是在下。
  • 一个简单的STL二进制模型STL (STereoLithography, 立体光刻)是由3D Systems软件公司创立、原本用于立体光刻计算机辅助设计软件的文件格式。它有一些事后诸葛的字头语如“标准三角语言(Standard Triangle Language)...
  • 读取STL模型 并用opengl显示

    千次阅读 2020-12-10 10:53:20
    说起STL模型,相信使用过CAD三维软件的人都不陌生,STL = STL文件,一种3D模型文件格式STL(STereo Lithography的缩写)STL文件格式是由3D SYSTEMS 公司于1988 年制定的一个接口协议,是一种为快速原型制造技术服务的...

    说起STL模型,相信使用过CAD三维软件的人都不陌生,

    STL = STL文件,一种3D模型文件格式STL(STereo Lithography的缩写)

    STL文件格式是由3D SYSTEMS 公司于1988 年制定的一个接口协议,是一种为快速原型制造技术服务的三维图形文件格式。STL 文件由多个三角形面片的定义组成,每个三角形面片的定义包括三角形各个定点的三维坐标及三角形面片的法矢量。三角形顶点的排列顺序遵循右手法则。 STL 文件有2 种类型:文本文件(ASCII格式)和二进制文件(BINARY)。

    在此文中我们对ASCII格式的STL文件进行解析,并且用opengl对其进行显示。

    STL的ASCII格式如下:

    solid filenamestl //文件路径及文件名

    facet normal x y z // 三角面片法向量的3个分量值

    outer loop

    vertex x y z ∥三角面片第一个顶点的坐标

    vertex x y z // 三角面片第二个顶点的坐标

    vertex x y z ∥三角面片第三个顶点的坐标

    endloop

    endfacet // 第一个三角面片定义完毕

    ……

    ……

    endsolid filenamestl ∥整个文件结束

    下面来说说处理这个解析的思路,首先我们可以按行一行行读来下,去掉第一行开始一直往下读,每读一行都检查是不是到了最后一行,但是这样显然效率不高,不如我们一开始把三角面片个个数求出来,循环中对每个三角面片进行解析,可以观察出每个三角面片所占的ASCII文件的行数为7行,那么把行数读出来除以七所得的商就是三角面片的个数,那么我们再一一对每个三角面片进行解析,实际上这个工作并不是很难,关键是要知道STL的格式与OPENGLBATCH的接口,OPENGL的接口实际上是一串float的数组,这里面保存了verts即顶点坐标信息,以及norms即法向量信息,那么刚好和我们的stl文件相一致。

    以下是我们的核心代码;

    #include "windows.h"#include //OpenGL toolkit

    #include #include#include#include#include#ifdef __APPLE__

    #include

    #else

    #define FREEGLUT_STATIC#include

    #endifGLFrame viewFrame;

    GLFrustum viewFrustum;

    GLBatch triangleBatch;

    GLMatrixStack modelViewMatix;

    GLMatrixStack projectionMatrix;

    GLGeometryTransform transformPipeline;

    GLShaderManager shaderManager;intnum;float*verts;float*vnorms;voidgetstlmodel()

    {int max=0;bool isbegin=false;long size=0;int nlines=0;int count1=0;int count2=0;

    FILE* file=fopen("mystl.stl","r");

    fseek(file,0L,SEEK_END);

    size=ftell(file);

    fclose(file);

    file=fopen("mystl.stl","r");for (int i=0;i

    {if(getc(file)=='\n')

    {

    nlines++;

    }

    }

    num=nlines/7;

    rewind(file);while (getc(file) != '\n');

    verts=new float[9*num];

    vnorms=new float[9*num];for (int i=0;i

    {char x[200]="";char y[200]="";char z[200]="";if(3!=fscanf(file,"%*s %*s %80s %80s %80s\n",x,y,z))

    {break;

    }

    vnorms[count1]=vnorms[count1+3]=vnorms[count1+6]=atof(x);

    count1++;

    vnorms[count1]=vnorms[count1+3]=vnorms[count1+6]=atof(y);

    count1++;

    vnorms[count1]=vnorms[count1+3]=vnorms[count1+6]=atof(z);

    count1+=7;

    fscanf(file,"%*s %*s");if (3!=fscanf(file,"%*s %80s %80s %80s\n",x,y,z))

    {break;

    }if (isbegin==false)

    {

    isbegin=true;

    max=atof(z);

    }

    verts[count2]=atof(x);

    count2++;

    verts[count2]=atof(y);

    count2++;

    verts[count2]=atof(z);

    count2++;if (3!=fscanf(file,"%*s %80s %80s %80s\n",x,y,z))

    {break;

    }

    verts[count2]=atof(x);

    count2++;

    verts[count2]=atof(y);

    count2++;

    verts[count2]=atof(z);

    count2++;if (3!=fscanf(file,"%*s %80s %80s %80s\n",x,y,z))

    {break;

    }

    verts[count2]=atof(x);

    count2++;

    verts[count2]=atof(y);

    count2++;

    verts[count2]=atof(z);

    count2++;

    fscanf(file,"%*s");

    fscanf(file,"%*s");

    }

    }voidSetupRC()

    {//Black background

    glClearColor(0.3f, 0.3f, 0.3f, 1.0f);

    shaderManager.InitializeStockShaders();

    viewFrame.MoveForward(1000.0f);

    triangleBatch.Begin(GL_TRIANGLES, num*3);

    triangleBatch.CopyVertexData3f(verts);

    triangleBatch.CopyNormalDataf(vnorms);

    triangleBatch.End();//Make the torus

    }void SpecialKeys(int key, int x, inty)

    {if(key ==GLUT_KEY_UP)

    viewFrame.RotateWorld(m3dDegToRad(-5.0), 1.0f, 0.0f, 0.0f);if(key ==GLUT_KEY_DOWN)

    viewFrame.RotateWorld(m3dDegToRad(5.0), 1.0f, 0.0f, 0.0f);if(key ==GLUT_KEY_LEFT)

    viewFrame.RotateWorld(m3dDegToRad(-5.0), 0.0f, 1.0f, 0.0f);if(key ==GLUT_KEY_RIGHT)

    viewFrame.RotateWorld(m3dDegToRad(5.0), 0.0f, 1.0f, 0.0f);//Refresh the Window

    glutPostRedisplay();

    }void ChangeSize(int w, inth)

    {//Prevent a divide by zero

    if(h == 0)

    h= 1;//Set Viewport to window dimensions

    glViewport(0, 0, w, h);

    viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 2000.0f);

    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());

    transformPipeline.SetMatrixStacks(modelViewMatix, projectionMatrix);

    }void RenderScene(void)

    {

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glEnable(GL_CULL_FACE);

    glEnable(GL_DEPTH_TEST);

    modelViewMatix.PushMatrix(viewFrame);

    GLfloat vRed[]= { 1.0f, 0.0f, 0.0f, 1.0f};//shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vRed);

    shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vRed);

    triangleBatch.Draw();

    modelViewMatix.PopMatrix();

    glutSwapBuffers();

    }int main(int argc, char*argv[])

    {

    getstlmodel();

    gltSetWorkingDirectory(argv[0]);

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE| GLUT_RGBA | GLUT_DEPTH |GLUT_STENCIL);

    glutInitWindowSize(800, 600);

    glutCreateWindow("Geometry Test Program");

    glutReshapeFunc(ChangeSize);

    glutDisplayFunc(RenderScene);

    glutSpecialFunc(SpecialKeys);

    GLenum err=glewInit();if (GLEW_OK !=err) {

    fprintf(stderr,"GLEW Error: %s\n", glewGetErrorString(err));return 1;

    }

    SetupRC();

    glutMainLoop();return 0;

    }

    以下是我们解析stl模型生成图形的实例:

    其实,程序中还有一个地方还有缺陷,就是一开始我们设置的

    viewFrame.MoveForward(1000.0f);

    即是在里原点1000米的地方进行观测,然后

    viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 2000.0f);

    这里是对投影的平截头体进行的设置,我们也设置的为角度35,深度为1到2000,但是stl模型不一定是落在这个区域内,那这个时候我们就不一定能观测得到图像,或者只能观测到部分图像。

    关于stl解析并且显示的部分,在OPENCASCADE中也有功能非常强大的代码,其中还包括了对二进制STL模型的解析和显示,如果想深究的童鞋可以看看这个博客:http://www.cppblog.com/eryar/archive/2013/05/01/199882.aspx

    展开全文
  • 此版本目前仅支持 ASCII,但未来的修订版将支持二进制。 此功能基于 Luigi Giaccari 的 STL 导入器,但使用 textscan 功能显着提高速度,这对大文件有显着影响。
  • 通过C++编程实现stl模型的分割与拼接
  • 为解决三维网格曲面(stereolithogrphy interface,STL)模型体素化结构单一和计算效率不高等问题,基于几何求交运算的STL模型体素化处理技术,提出一种基于逆向几何求交算法实现STL模型的快速体素化方法。通过对STL模型...
  • 显示STL模型, 全部都是三角面片, 使用光照需要注意三角面片的法线, 法线的归一化尤为重要。 模型经过glScale变换之后, 原来的法线变得不正确, 光照效果变得不理想。解决此问题的方法是 启用OpenGL自动法线单位化功能...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 29,840
精华内容 11,936
关键字:

stl模型

友情链接: SignerTest.rar