Qt OpenGL - 网格式的直角坐标系

Qt OpenGL - 网格式的直角坐标系

  • 引言
  • 一、绘制3D网格
    • 1.1 绘制平行于y轴的线段
    • 1.2 绘制平行于三个轴的线段
    • 1.3 绘制不同的3D网格
  • 二、网格式的直角坐标系
  • 三、参考链接

引言

Qt OpenGL - 网格式的直角坐标系_第1张图片
在OpenGL进行3D可视化,只绘制三条坐标轴略显单薄,而绘制网格形式的坐标系则能更清晰的展示所画图形位置,如上图所示。

OpenGL可视化须知1:https://blog.csdn.net/sinat_36772813/article/details/129338953 OpenGL中的坐标系
OpenGL三维坐标系例子-只有三个轴2:https://blog.csdn.net/qq_37996632/article/details/103178120 OpenGL画坐标系2
OpenGL三维坐标系例子-网格形式3:https://blog.csdn.net/qq_40004575/article/details/109547793 Qt+OpenGL绘制三维坐标系(动态曲线显示)

一、绘制3D网格

paintGL()函数:

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除屏幕和深度缓存
    glLoadIdentity();

    //旋转显示窗口
    glTranslatef(0, 0, -30);
    //glRotatef(45, 0, 1, 0);

    //画3D网格
    std::vector<float> p1 = {-4.0f, -4.0f, -4.0f}, p2 = {4.0f, 4.0f, 4.0f};
    GL3DGrid(p1, p2, 3);

1.1 绘制平行于y轴的线段

Qt OpenGL - 网格式的直角坐标系_第2张图片

  • 先绘制平行于y轴的线段,效果如上图,算法核心思想:
    给定两个3D坐标,要通过其绘制平行于y轴的若干线段,保证每个线段首尾点的x和z坐标是一致的,首尾点的y坐标即两个3D坐标的y坐标。
void QtDraw3DCtrl::GL3DGrid(std::vector<float> p1, std::vector<float> p2, int num)
{
    if(p1.size() !=3 || p2.size() !=3){
        return; // 稳健
    }
    num = num -1;
    const float _xLen = (p2[0] - p1[0]) / num;
    const float _yLen = (p2[1] - p1[1]) / num;
    const float _zLen = (p2[2] - p1[2]) / num;

    // 绘制参数
    glLineWidth(0.1f);
    glBegin(GL_LINES);
    glEnable(GL_LINE_SMOOTH);

    // 绘制平行于某轴的线段 比如y轴 y坐标固定从p1到p2  x,z坐标变换(无脑遍历即可)
    for (int xi = 0; xi <= num; xi++) {
        float x = _xLen * xi + p1[0];
        for (int zi = 0; zi <= num; zi++) {
            float z = _zLen * zi + p1[2];
            glVertex3f(x, p1[1], z);
            glVertex3f(x, p2[1], z);
        }
    }
    glEnd();
}

1.2 绘制平行于三个轴的线段

Qt OpenGL - 网格式的直角坐标系_第3张图片

  • 绘制平行于三个轴的线段,如上图所示。增加绘制平行于x轴和z轴的线段,代码与绘制平行于y轴的线段类似,只是改几个参数。
void QopenGLDemo::GL3DGrid(std::vector<float> p1, std::vector<float> p2, int num)
{
    if(p1.size() !=3 || p2.size() !=3){
        return; // 稳健
    }
    num = num -1;
    const float _xLen = (p2[0] - p1[0]) / num;
    const float _yLen = (p2[1] - p1[1]) / num;
    const float _zLen = (p2[2] - p1[2]) / num;

    // 绘制参数
    glLineWidth(0.1f);
    glBegin(GL_LINES);
    glEnable(GL_LINE_SMOOTH);

    // 绘制平行y轴的线段 y坐标固定从p1到p2  x,z坐标变换(无脑遍历即可)
    for (int xi = 0; xi <= num; xi++) {
        float x = _xLen * xi + p1[0];
        for (int zi = 0; zi <= num; zi++) {
            float z = _zLen * zi + p1[2];
            glVertex3f(x, p1[1], z);
            glVertex3f(x, p2[1], z);
        }
    }

    // 绘制平行x轴的线段 x坐标固定从p1到p2  y,z坐标变换(无脑遍历即可)
    for (int yi = 0; yi <= num; yi++) {
        float y = _yLen * yi + p1[1];
        for (int zi = 0; zi <= num; zi++) {
            float z = _zLen * zi + p1[2];
            glVertex3f(p1[0], y, z);
            glVertex3f(p2[1], y, z);
        }
    }

    // 绘制平行z轴的线段 z坐标固定从p1到p2  x,y坐标变换(无脑遍历即可)
    for (int xi = 0; xi <= num; xi++) {
        float x = _xLen * xi + p1[0];
        for (int yi = 0; yi <= num; yi++) {
            float y = _yLen * yi + p1[1];
            glVertex3f(x, y, p1[2]);
            glVertex3f(x, y, p2[2]);
        }
    }

    // 结束绘制
    glEnd();
}

1.3 绘制不同的3D网格

Qt OpenGL - 网格式的直角坐标系_第4张图片 Qt OpenGL - 网格式的直角坐标系_第5张图片Qt OpenGL - 网格式的直角坐标系_第6张图片

  • 修改GL3DGrid(p1, p2, 3)最后一个参数为4,6,10;

二、网格式的直角坐标系

Qt OpenGL - 网格式的直角坐标系_第7张图片

  • 由以上代码已可绘制3D网格,但如果在其中绘制目标模型会被遮挡。故,可绘制3个2D网格方便显示,效果如上图所示。(写到这,发现一个bug,之前代码在绘制平行x轴的线段的时候,p2[1]应改为p2[0]) 核心源码如下所示:
void QopenGLDemo::paintGL(){
    // 初始化
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除屏幕和深度缓存
    glLoadIdentity();

    //旋转显示窗口
    glTranslatef(0, 0, -30);
    //glRotatef(45, 0, 1, 0);

    //画3D直角坐标系
    std::vector<float> x1 = {-4.0f, -4.0f, -4.0f}, x2 = {-4.0f, 4.0f, 4.0f};
    GL3DGrid(x1, x2, 10);

    std::vector<float> y1 = {-4.0f, -4.0f, -4.0f}, y2 = {4.0f, -4.0f, 4.0f};
    GL3DGrid(y1, y2, 10);

    std::vector<float> z1 = {-4.0f, -4.0f, -4.0f}, z2 = {4.0f, 4.0f, -4.0f};
    GL3DGrid(z1, z2, 10);
}

void QopenGLDemo::GL3DGrid(std::vector<float> p1, std::vector<float> p2, int num)
{
    if(p1.size() !=3 || p2.size() !=3){
        return; // 稳健
    }
    num = num -1;
    const float _xLen = (p2[0] - p1[0]) / num;
    const float _yLen = (p2[1] - p1[1]) / num;
    const float _zLen = (p2[2] - p1[2]) / num;

    // 绘制参数
    glLineWidth(0.1f);
    glBegin(GL_LINES);
    glEnable(GL_LINE_SMOOTH);

    // 绘制平行y轴的线段 y坐标固定从p1到p2  x,z坐标变换(无脑遍历即可)
    for (int xi = 0; xi <= num; xi++) {
        float x = _xLen * xi + p1[0];
        for (int zi = 0; zi <= num; zi++) {
            float z = _zLen * zi + p1[2];
            glVertex3f(x, p1[1], z);
            glVertex3f(x, p2[1], z);
        }
    }

    // 绘制平行x轴的线段 x坐标固定从p1到p2  y,z坐标变换(无脑遍历即可)
    for (int yi = 0; yi <= num; yi++) {
        float y = _yLen * yi + p1[1];
        for (int zi = 0; zi <= num; zi++) {
            float z = _zLen * zi + p1[2];
            glVertex3f(p1[0], y, z);
            glVertex3f(p2[0], y, z);
        }
    }

    // 绘制平行z轴的线段 z坐标固定从p1到p2  x,y坐标变换(无脑遍历即可)
    for (int xi = 0; xi <= num; xi++) {
        float x = _xLen * xi + p1[0];
        for (int yi = 0; yi <= num; yi++) {
            float y = _yLen * yi + p1[1];
            glVertex3f(x, y, p1[2]);
            glVertex3f(x, y, p2[2]);
        }
    }

    // 结束绘制
    glEnd();
}

三、参考链接


  1. https://blog.csdn.net/sinat_36772813/article/details/129338953 OpenGL中的坐标系 ↩︎

  2. https://blog.csdn.net/qq_37996632/article/details/103178120 OpenGL画坐标系2 ↩︎

  3. https://blog.csdn.net/qq_40004575/article/details/109547793 Qt+OpenGL绘制三维坐标系(动态曲线显示) ↩︎

你可能感兴趣的:(#,Qt,qt,开发语言,opengl,c++,直角坐标系,3D坐标系可视化)