OpenGL绘制桥梁模型

本文主要讲述如何使用现代OpenGL绘制一个完整的桥梁模型,包括箱梁、盖梁和桥墩,关于OpenGL方面,主要添加的shader,使用phong光照模型实现。
一、绘制箱梁
1.1 箱梁的的截面和坐标系
截面:

坐标系:

1.2 箱梁的顶点及其法向量
    float vertices[] = {
        //////////////////////////////////////////////////////////////////////////
        //前视图
        // 左翼缘
        // positions          // normals 
        -1.0f, 0.3f, 30.1f,    0.0f, 0.0f, 1.0f,
        -1.0f, 0.2f, 30.1f,    0.0f, 0.0f, 1.0f,
        -0.5f, 0.3f, 30.1f,    0.0f, 0.0f, 1.0f,
    
        -1.0f, 0.2f, 30.1f,    0.0f, 0.0f, 1.0f,
        -0.5f, 0.1f, 30.1f,   0.0f, 0.0f, 1.0f,
        -0.5f, 0.3f, 30.1f,   0.0f, 0.0f, 1.0f,
    
        // 左矩形
        -0.5f, 0.3f,   30.1f,  0.0f, 0.0f, 1.0f,
        -0.5f, -0.3f,  30.1f,  0.0f, 0.0f, 1.0f,
        -0.35f, -0.3f, 30.1f,  0.0f, 0.0f, 1.0f,
    
        -0.5f, 0.3f,   30.1f,  0.0f, 0.0f, 1.0f,
        -0.35f, -0.3f, 30.1f,  0.0f, 0.0f, 1.0f,
        -0.35f, 0.3f,  30.1f,  0.0f, 0.0f, 1.0f,
    
        // 上矩形
        -0.35f, 0.3f, 30.1f,   0.0f, 0.0f, 1.0f,
        -0.35f, 0.2f, 30.1f,   0.0f, 0.0f, 1.0f,
        -0.0f, 0.3f,  30.1f,   0.0f, 0.0f, 1.0f,
    
        -0.35f, 0.2f, 30.1f,   0.0f, 0.0f, 1.0f,
        -0.0f, 0.3f,  30.1f,   0.0f, 0.0f, 1.0f,
        -0.0f, 0.2f,  30.1f,      0.0f, 0.0f, 1.0f,
    
        // 下矩形
        -0.35f, -0.3f, 30.1f,  0.0f, 0.0f, 1.0f,
        -0.35f, -0.2f, 30.1f,  0.0f, 0.0f, 1.0f,
        -0.0f, -0.3f,  30.1f,  0.0f, 0.0f, 1.0f,
    
        -0.35f, -0.2f, 30.1f,  0.0f, 0.0f, 1.0f,
        -0.0f, -0.3f,  30.1f,  0.0f, 0.0f, 1.0f,
        -0.0f, -0.2f,  30.1f,  0.0f, 0.0f, 1.0f,
    
        // 左上倒角
        -0.35f, 0.2f,  30.1f,  0.0f, 0.0f, 1.0f,
        -0.35f, 0.15f, 30.1f,  0.0f, 0.0f, 1.0f,
        -0.25f, 0.2f,  30.1f,  0.0f, 0.0f, 1.0f,
    
        // 左下倒角
        -0.35f, -0.2f,  30.1f, 0.0f, 0.0f, 1.0f,
        -0.35f, -0.15f, 30.1f, 0.0f, 0.0f, 1.0f,
        -0.25f, -0.2f,  30.1f, 0.0f, 0.0f, 1.0f,
    
            //对称 右边
            //右翼缘
        1.0f, 0.3f, 30.1f,   0.0f, 0.0f, 1.0f,
        1.0f, 0.2f, 30.1f,  0.0f, 0.0f, 1.0f,
        0.5f, 0.3f, 30.1f,  0.0f, 0.0f, 1.0f,
    
        1.0f, 0.2f, 30.1f,   0.0f, 0.0f, 1.0f,
        0.5f, 0.1f, 30.1f,  0.0f, 0.0f, 1.0f,
        0.5f, 0.3f, 30.1f,  0.0f, 0.0f, 1.0f,
    
        // 右矩形
        0.5f, 0.3f,   30.1f, 0.0f, 0.0f, 1.0f,
        0.5f, -0.3f,  30.1f, 0.0f, 0.0f, 1.0f,
        0.35f, -0.3f, 30.1f, 0.0f, 0.0f, 1.0f,
    
        0.5f, 0.3f,   30.1f, 0.0f, 0.0f, 1.0f,
        0.35f, -0.3f, 30.1f,    0.0f, 0.0f, 1.0f,
        0.35f, 0.3f,  30.1f,    0.0f, 0.0f, 1.0f,
    
        // 上矩形
        0.35f, 0.3f, 30.1f, 0.0f, 0.0f, 1.0f,
        0.35f, 0.2f, 30.1f, 0.0f, 0.0f, 1.0f,
        0.0f, 0.3f,  30.1f, 0.0f, 0.0f, 1.0f,
    
        0.35f, 0.2f, 30.1f, 0.0f, 0.0f, 1.0f,
        0.0f, 0.3f,  30.1f, 0.0f, 0.0f, 1.0f,
        0.0f, 0.2f,  30.1f, 0.0f, 0.0f, 1.0f,
    
        // 下矩形
        0.35f, -0.3f, 30.1f, 0.0f, 0.0f, 1.0f,
        0.35f, -0.2f, 30.1f, 0.0f, 0.0f, 1.0f,
        0.0f, -0.3f,  30.1f, 0.0f, 0.0f, 1.0f,
    
        0.35f, -0.2f, 30.1f, 0.0f, 0.0f, 1.0f,
        0.0f, -0.3f,  30.1f, 0.0f, 0.0f, 1.0f,
        0.0f, -0.2f,  30.1f,    0.0f, 0.0f, 1.0f,
    
        // 右上倒角
        0.35f, 0.2f,  30.1f, 0.0f, 0.0f, 1.0f,
        0.35f, 0.15f, 30.1f, 0.0f, 0.0f, 1.0f,
        0.25f, 0.2f,  30.1f, 0.0f, 0.0f, 1.0f,
    
        // 右下倒角
        0.35f, -0.2f,  30.1f, 0.0f, 0.0f, 1.0f,
        0.35f, -0.15f, 30.1f, 0.0f, 0.0f, 1.0f,
        0.25f, -0.2f,  30.1f, 0.0f, 0.0f, 1.0f,
    
        //////////////////////////////////////////////////////////////////////////
        //后视图
        // 左翼缘
        -1.0f, 0.3f, -30.1f, 0.0f, 0.0f, -1.0f,
        -1.0f, 0.2f, -30.1f, 0.0f, 0.0f, -1.0f,
        -0.5f, 0.3f, -30.1f, 0.0f, 0.0f, -1.0f,
    
        -1.0f, 0.2f, -30.1f, 0.0f, 0.0f, -1.0f,
        -0.5f, 0.1f, -30.1f,    0.0f, 0.0f, -1.0f,
        -0.5f, 0.3f, -30.1f,    0.0f, 0.0f, -1.0f,
    
        // 左矩形
        -0.5f, 0.3f,   -30.1f, 0.0f, 0.0f, -1.0f,
        -0.5f, -0.3f,  -30.1f, 0.0f, 0.0f, -1.0f,
        -0.35f, -0.3f, -30.1f, 0.0f, 0.0f, -1.0f,
    
        -0.5f, 0.3f,   -30.1f,  0.0f, 0.0f, -1.0f,
        -0.35f, -0.3f, -30.1f,  0.0f, 0.0f, -1.0f,
        -0.35f, 0.3f,  -30.1f,  0.0f, 0.0f, -1.0f,
    
        // 上矩形
        -0.35f, 0.3f, -30.1f,   0.0f, 0.0f, -1.0f,
        -0.35f, 0.2f, -30.1f,   0.0f, 0.0f, -1.0f,
        -0.0f, 0.3f,  -30.1f,   0.0f, 0.0f, -1.0f,
    
        -0.35f, 0.2f, -30.1f,   0.0f, 0.0f, -1.0f,
        -0.0f, 0.3f,  -30.1f,   0.0f, 0.0f, -1.0f,
        -0.0f, 0.2f,  -30.1f,   0.0f, 0.0f, -1.0f,
    
        // 下矩形
        -0.35f, -0.3f, -30.1f,  0.0f, 0.0f, -1.0f,
        -0.35f, -0.2f, -30.1f,  0.0f, 0.0f, -1.0f,
        -0.0f, -0.3f,  -30.1f,  0.0f, 0.0f, -1.0f,
    
        -0.35f, -0.2f, -30.1f,  0.0f, 0.0f, -1.0f,
        -0.0f, -0.3f,  -30.1f,  0.0f, 0.0f, -1.0f,
        -0.0f, -0.2f,  -30.1f,  0.0f, 0.0f, -1.0f,
    
        // 左上倒角
        -0.35f, 0.2f,  -30.1f,  0.0f, 0.0f, -1.0f,
        -0.35f, 0.15f, -30.1f,  0.0f, 0.0f, -1.0f,
        -0.25f, 0.2f,  -30.1f,  0.0f, 0.0f, -1.0f,
    
        // 左下倒角
        -0.35f, -0.2f,  -30.1f, 0.0f, 0.0f, -1.0f,
        -0.35f, -0.15f, -30.1f, 0.0f, 0.0f, -1.0f,
        -0.25f, -0.2f,  -30.1f, 0.0f, 0.0f, -1.0f,
    
        //对称 右边
        //右翼缘
        1.0f, 0.3f, -30.1f,    0.0f, 0.0f, -1.0f,
        1.0f, 0.2f, -30.1f,       0.0f, 0.0f, -1.0f,
        0.5f, 0.3f, -30.1f,       0.0f, 0.0f, -1.0f,
    
        1.0f, 0.2f, -30.1f,    0.0f, 0.0f, -1.0f,
        0.5f, 0.1f, -30.1f,   0.0f, 0.0f, -1.0f,
        0.5f, 0.3f, -30.1f,   0.0f, 0.0f, -1.0f,
    
        // 右矩形
        0.5f, 0.3f,   -30.1f,  0.0f, 0.0f, -1.0f,
        0.5f, -0.3f,  -30.1f,  0.0f, 0.0f, -1.0f,
        0.35f, -0.3f, -30.1f,  0.0f, 0.0f, -1.0f,
    
        0.5f, 0.3f,   -30.1f,  0.0f, 0.0f, -1.0f,
        0.35f, -0.3f, -30.1f,  0.0f, 0.0f, -1.0f,
        0.35f, 0.3f,  -30.1f,  0.0f, 0.0f, -1.0f,
    
        // 上矩形
        0.35f, 0.3f, -30.1f,   0.0f, 0.0f, -1.0f,
        0.35f, 0.2f, -30.1f,   0.0f, 0.0f, -1.0f,
        0.0f, 0.3f,  -30.1f,   0.0f, 0.0f, -1.0f,
    
        0.35f, 0.2f, -30.1f,   0.0f, 0.0f, -1.0f,
        0.0f, 0.3f,  -30.1f,   0.0f, 0.0f, -1.0f,
        0.0f, 0.2f,  -30.1f,      0.0f, 0.0f, -1.0f,
    
        // 下矩形
        0.35f, -0.3f, -30.1f,  0.0f, 0.0f, -1.0f,
        0.35f, -0.2f, -30.1f,  0.0f, 0.0f, -1.0f,
        0.0f, -0.3f,  -30.1f,  0.0f, 0.0f, -1.0f,
    
        0.35f, -0.2f, -30.1f,  0.0f, 0.0f, -1.0f,
        0.0f, -0.3f,  -30.1f,  0.0f, 0.0f, -1.0f,
        0.0f, -0.2f,  -30.1f,  0.0f, 0.0f, -1.0f,
    
        // 右上倒角
        0.35f, 0.2f,  -30.1f, 0.0f, 0.0f, -1.0f,
        0.35f, 0.15f, -30.1f, 0.0f, 0.0f, -1.0f,
        0.25f, 0.2f,  -30.1f, 0.0f, 0.0f, -1.0f,
    
        // 右下倒角
        0.35f, -0.2f,  -30.1f,  0.0f, 0.0f, -1.0f,
        0.35f, -0.15f, -30.1f,  0.0f, 0.0f, -1.0f,
        0.25f, -0.2f,  -30.1f,  0.0f, 0.0f, -1.0f,
        //////////////////////////////////////////////////////////////////////////
        //左视图
        // 上矩形
        -1.0f, 0.3f, -30.1f,  -1.0f, 0.0f, 0.0f,
        -1.0f, 0.2f, -30.1f,  -1.0f, 0.0f, 0.0f,
        -1.0f, 0.3f,  30.1f,  -1.0f, 0.0f, 0.0f,
        -1.0f, 0.2f, -30.1f,  -1.0f, 0.0f, 0.0f,
        -1.0f, 0.3f,  30.1f,  -1.0f, 0.0f, 0.0f,
        -1.0f, 0.2f,  30.1f,     -1.0f, 0.0f, 0.0f,
        // 左翼缘斜面 
        -1.0f, 0.2f, -30.1f,  -0.196116135f, -0.980580688f, -0.0f,
        -0.5f, 0.1f, -30.1f,  -0.196116135f, -0.980580688f, -0.0f,
        -1.0f, 0.2f,  30.1f,  -0.196116135f, -0.980580688f, -0.0f,
        
        -0.5f, 0.1f, -30.1f,  -0.196116135f, -0.980580688f, -0.0f,
        -1.0f, 0.2f,  30.1f,  -0.196116135f, -0.980580688f, -0.0f,
        -0.5f, 0.1f,  30.1f,  -0.196116135f, -0.980580688f, -0.0f,
        // 下矩形
        -0.5f, 0.1f, -30.1f,  -1.0f, 0.0f, 0.0f,
        -0.5f, -0.3f, -30.1f, -1.0f, 0.0f, 0.0f,
        -0.5f, 0.1f,  30.1f,  -1.0f, 0.0f, 0.0f,
        
        -0.5f, -0.3f, -30.1f, -1.0f, 0.0f, 0.0f,
        -0.5f, 0.1f,  30.1f,  -1.0f, 0.0f, 0.0f,
        -0.5f, -0.3f, 30.1f,  -1.0f, 0.0f, 0.0f,
        //////////////////////////////////////////////////////////////////////////
        //右视图
        // 上矩形
        1.0f, 0.3f, -30.1f,  1.0f, 0.0f, 0.0f,
        1.0f, 0.2f, -30.1f,     1.0f, 0.0f, 0.0f,
        1.0f, 0.3f,  30.1f,     1.0f, 0.0f, 0.0f,
        1.0f, 0.2f, -30.1f,  1.0f, 0.0f, 0.0f,
        1.0f, 0.3f,  30.1f,  1.0f, 0.0f, 0.0f,
        1.0f, 0.2f,  30.1f,  1.0f, 0.0f, 0.0f,
        // 右翼缘斜面
        1.0f, 0.2f, -30.1f, 0.196116135f, -0.980580688f, 0.0f,
        0.5f, 0.1f, -30.1f, 0.196116135f, -0.980580688f, 0.0f,
        1.0f, 0.2f,  30.1f, 0.196116135f, -0.980580688f, 0.0f,
        0.5f, 0.1f, -30.1f, 0.196116135f, -0.980580688f, 0.0f,
        1.0f, 0.2f,  30.1f, 0.196116135f, -0.980580688f, 0.0f,
        0.5f, 0.1f,  30.1f, 0.196116135f, -0.980580688f, 0.0f,
        // 下矩形
        0.5f, 0.1f, -30.1f,  1.0f, 0.0f, 0.0f,
        0.5f, -0.3f, -30.1f, 1.0f, 0.0f, 0.0f,
        0.5f, 0.1f,  30.1f,     1.0f, 0.0f, 0.0f,
        0.5f, -0.3f, -30.1f, 1.0f, 0.0f, 0.0f,
        0.5f, 0.1f,  30.1f,     1.0f, 0.0f, 0.0f,
        0.5f, -0.3f, 30.1f,     1.0f, 0.0f, 0.0f,
        //////////////////////////////////////////////////////////////////////////
        //附视图
        -1.0f, 0.3f, -30.1f, 0.0f, 1.0f, 0.0f,
        -1.0f, 0.3f,  30.1f,    0.0f, 1.0f, 0.0f,
        1.0f, 0.3f, -30.1f,     0.0f, 1.0f, 0.0f,
        -1.0f, 0.3f,  30.1f, 0.0f, 1.0f, 0.0f,
        1.0f, 0.3f, -30.1f,     0.0f, 1.0f, 0.0f,
        1.0f, 0.3f, 30.1f,  0.0f, 1.0f, 0.0f,
        //////////////////////////////////////////////////////////////////////////
        //底视图
        -0.5f, -0.3f, -30.1f, 0.0f, -1.0f, 0.0f,
        -0.5f, -0.3f,  30.1f, 0.0f, -1.0f, 0.0f,
        0.5f, -0.3f, -30.1f,  0.0f, -1.0f, 0.0f,
        -0.5f, -0.3f,  30.1f, 0.0f, -1.0f, 0.0f,
        0.5f, -0.3f, -30.1f,  0.0f, -1.0f, 0.0f,
        0.5f, -0.3f, 30.1f,      0.0f, -1.0f, 0.0f,
        //////////////////////////////////////////////////////////////////////////
        // 内侧平面
        //////////////////////////////////////////////////////////////////////////
        // 内-左半部分
        // 左矩形
        -0.35f, 0.15f, 30.1f,    1.0f, 0.0f, 0.0f,
        -0.35f, -0.15f, 30.1f,   1.0f, 0.0f, 0.0f,
        -0.35f, -0.15f, -30.1f,  1.0f, 0.0f, 0.0f,
        -0.35f, 0.15f, 30.1f,    1.0f, 0.0f, 0.0f,
        -0.35f, -0.15f, -30.1f,  1.0f, 0.0f, 0.0f,
        -0.35f, 0.15f, -30.1f,   1.0f, 0.0f, 0.0f,
        // 上矩形
        -0.25f, 0.2f, 30.1f,    0.0f, -1.0f, 0.0f,
         0.0f, 0.2f,  30.1f,    0.0f, -1.0f, 0.0f,
         0.0f, 0.2f, -30.1f,    0.0f, -1.0f, 0.0f,
         -0.25f, 0.2f, 30.1f,    0.0f, -1.0f, 0.0f,
          0.0f, 0.2f, -30.1f,    0.0f, -1.0f, 0.0f,
         -0.25f, 0.2f, -30.1f,   0.0f, -1.0f, 0.0f,
         // 下矩形
         -0.25f, -0.2f, 30.1f,    0.0f, 1.0f, 0.0f,
         0.0f,  -0.2f,  30.1f,    0.0f, 1.0f, 0.0f,
         0.0f,  -0.2f, -30.1f,    0.0f, 1.0f, 0.0f,
         -0.25f, -0.2f, 30.1f,    0.0f, 1.0f, 0.0f,
          0.0f,  -0.2f, -30.1f,   0.0f, 1.0f, 0.0f,
         -0.25f, -0.2f, -30.1f,   0.0f, 1.0f, 0.0f,
         // 左上斜面 
         -0.35f, 0.15f, 30.1f,    0.447213620f, -0.894427240f, 0.0f,
         -0.25f, 0.2f,  30.1f,    0.447213620f, -0.894427240f, 0.0f,
         -0.25f, 0.2f, -30.1f,    0.447213620f, -0.894427240f, 0.0f,
         -0.35f, 0.15f, 30.1f,    0.447213620f, -0.894427240f, 0.0f,
         -0.25f, 0.2f, -30.1f,    0.447213620f, -0.894427240f, 0.0f,
         -0.35f, 0.15f, -30.1f,   0.447213620f, -0.894427240f, 0.0f,
         // 左下斜面  
         -0.35f, -0.15f, 30.1f,     0.447213620f, 0.894427240f, 0.0f,
         -0.25f, -0.2f,  30.1f,     0.447213620f, 0.894427240f, 0.0f,
         -0.25f, -0.2f, -30.1f,     0.447213620f, 0.894427240f, 0.0f,
         -0.35f, -0.15f, 30.1f,    0.447213620f, 0.894427240f, 0.0f,
         -0.25f, -0.2f, -30.1f,    0.447213620f, 0.894427240f, 0.0f,
         -0.35f, -0.15f, -30.1f,   0.447213620f, 0.894427240f, 0.0f,
         //////////////////////////////////////////////////////////////////////////
         // 内-右半部分
         // 右矩形
         0.35f, 0.15f, 30.1f,    -1.0f, 0.0f, 0.0f,
         0.35f, -0.15f, 30.1f,   -1.0f, 0.0f, 0.0f,
         0.35f, -0.15f, -30.1f,  -1.0f, 0.0f, 0.0f,
         0.35f, 0.15f, 30.1f,    -1.0f, 0.0f, 0.0f,
         0.35f, -0.15f, -30.1f,  -1.0f, 0.0f, 0.0f,
         0.35f, 0.15f, -30.1f,   -1.0f, 0.0f, 0.0f,
         // 上矩形
         0.25f, 0.2f, 30.1f,    0.0f, -1.0f, 0.0f,
         0.0f, 0.2f,  30.1f,    0.0f, -1.0f, 0.0f,
         0.0f, 0.2f, -30.1f,    0.0f, -1.0f, 0.0f,
         0.25f, 0.2f, 30.1f,    0.0f, -1.0f, 0.0f,
         0.0f, 0.2f, -30.1f,    0.0f, -1.0f, 0.0f,
         0.25f, 0.2f, -30.1f,   0.0f, -1.0f, 0.0f,
         // 下矩形
         0.25f, -0.2f, 30.1f,    0.0f, 1.0f, 0.0f,
         0.0f,  -0.2f,  30.1f,    0.0f, 1.0f, 0.0f,
         0.0f,  -0.2f, -30.1f,    0.0f, 1.0f, 0.0f,
         0.25f, -0.2f, 30.1f,    0.0f, 1.0f, 0.0f,
         0.0f,  -0.2f, -30.1f,   0.0f, 1.0f, 0.0f,
         0.25f, -0.2f, -30.1f,   0.0f, 1.0f, 0.0f,
         // 右上斜面 
         0.35f, 0.15f, 30.1f,    -0.447213620f, -0.894427240f, 0.0f,
         0.25f, 0.2f,  30.1f,    -0.447213620f, -0.894427240f, 0.0f,
         0.25f, 0.2f, -30.1f,    -0.447213620f, -0.894427240f, 0.0f,
         0.35f, 0.15f, 30.1f,    -0.447213620f, -0.894427240f, 0.0f,
         0.25f, 0.2f, -30.1f,    -0.447213620f, -0.894427240f, 0.0f,
         0.35f, 0.15f, -30.1f,   -0.447213620f, -0.894427240f, 0.0f,
         // 右下斜面  
         0.35f, -0.15f, 30.1f,    -0.447213620f, 0.894427240f, 0.0f,
         0.25f, -0.2f,  30.1f,    -0.447213620f, 0.894427240f, 0.0f,
         0.25f, -0.2f, -30.1f,    -0.447213620f, 0.894427240f, 0.0f,
         0.35f, -0.15f, 30.1f,   -0.447213620f, 0.894427240f, 0.0f,
         0.25f, -0.2f, -30.1f,   -0.447213620f, 0.894427240f, 0.0f,
         0.35f, -0.15f, -30.1f,  -0.447213620f, 0.894427240f, 0.0f,
        
    }; 
1.3箱梁的VAO、VBO
    unsigned int VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glBindVertexArray(VAO);
    // position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    // normal attribute
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
    // 单片箱梁的位置
    glm::vec3 beamPosition[] = {
        glm::vec3( 0.0f,  0.0f,  0.0f),
        glm::vec3( 2.0f,  0.0f,  0.0f),
        glm::vec3( 4.0f,  0.0f,  0.0f),
        glm::vec3( 6.0f,  0.0f,  0.0f),
    };
    // 单片箱梁的颜色
    glm::vec3 modelColor[] = {
        glm::vec3( 1.0f,  0.75f, 0.51f),
        glm::vec3( 1.0f,  0.75f, 0.51f),
        glm::vec3( 1.0f,  0.75f, 0.51f),
        glm::vec3( 1.0f,  0.75f, 0.51f),
    };
1.4绘制箱梁
        glm::mat4 viewOrigin = camera.GetViewMatrix();
        lightingShader.setMat4("view", viewOrigin);
        // 绘制箱梁
        int nPntCount = sizeof(vertices)/sizeof(float) / 2 / 3;
        int nBeamCount = sizeof(beamPosition) / sizeof(glm::vec3);
        // 复制箱梁
        for (int i = 0; i < nBeamCount; ++i)
        {
            glm::mat4 model = glm::mat4(1.0);
            //移动
            model = glm::translate(model, beamPosition[i]);
            lightingShader.setMat4("model", model);
            //颜色
            lightingShader.setVec3("objectColor", modelColor[i]);
            glBindVertexArray(VAO);
            glDrawArrays(GL_TRIANGLES, 0, nPntCount);
        }   
二、绘制盖梁
2.1盖梁的顶点及其法向量
    float capBeamVertices[] = {
        //////////////////////////////////////////////////////////////////////////
        // 前视图
        // 左梯形
        // positions          // normals 
        -0.5f, -0.3f, 0.31f,  0.0f, 0.0f, 1.0f,
        -0.5f, -0.5f, 0.31f,  0.0f, 0.0f, 1.0f,
        -0.2f, -0.3f, 0.31f,  0.0f, 0.0f, 1.0f,
        -0.5f, -0.5f, 0.31f,  0.0f, 0.0f, 1.0f,
        -0.2f, -0.7f, 0.31f,  0.0f, 0.0f, 1.0f,
        -0.2f, -0.3f, 0.31f,  0.0f, 0.0f, 1.0f,
        // 矩形
        -0.2f, -0.3f, 0.31f,  0.0f, 0.0f, 1.0f,
        -0.2f, -0.7f, 0.31f,  0.0f, 0.0f, 1.0f,
         6.2f, -0.3f, 0.31f,  0.0f, 0.0f, 1.0f,
        -0.2f, -0.7f, 0.31f,  0.0f, 0.0f, 1.0f,
         6.2f, -0.3f, 0.31f,  0.0f, 0.0f, 1.0f,
         6.2f, -0.7f, 0.31f,  0.0f, 0.0f, 1.0f,
        //右半部分
        // 右梯形
        // positions          // normals 
        6.5f, -0.3f, 0.31f,  0.0f, 0.0f, 1.0f,
        6.5f, -0.5f, 0.31f,  0.0f, 0.0f, 1.0f,
        6.2f, -0.3f, 0.31f,  0.0f, 0.0f, 1.0f,
        6.5f, -0.5f, 0.31f,  0.0f, 0.0f, 1.0f,
        6.2f, -0.3f, 0.31f,  0.0f, 0.0f, 1.0f,
        6.2f, -0.7f, 0.31f,  0.0f, 0.0f, 1.0f,
        ////////////////////////////////////////////////////////////////////////////
        // 后视图
        // 左梯形
        // positions          // normals 
        -0.5f, -0.3f, -0.31f,  0.0f, 0.0f, 1.0f,
        -0.5f, -0.5f, -0.31f,  0.0f, 0.0f, 1.0f,
        -0.2f, -0.3f, -0.31f,  0.0f, 0.0f, 1.0f,
        -0.5f, -0.5f, -0.31f,  0.0f, 0.0f, 1.0f,
        -0.2f, -0.7f, -0.31f,  0.0f, 0.0f, 1.0f,
        -0.2f, -0.3f, -0.31f,  0.0f, 0.0f, 1.0f,
        // 矩形
        -0.2f, -0.3f, -0.31f,  0.0f, 0.0f, 1.0f,
        -0.2f, -0.7f, -0.31f,  0.0f, 0.0f, 1.0f,
         6.2f, -0.3f, -0.31f,  0.0f, 0.0f, 1.0f,
        -0.2f, -0.7f, -0.31f,  0.0f, 0.0f, 1.0f,
         6.2f, -0.3f, -0.31f,  0.0f, 0.0f, 1.0f,
         6.2f, -0.7f, -0.31f,  0.0f, 0.0f, 1.0f,
        //右半部分
        // 右梯形
        // positions          // normals 
        6.5f, -0.3f, -0.31f,  0.0f, 0.0f, 1.0f,
        6.5f, -0.5f, -0.31f,  0.0f, 0.0f, 1.0f,
        6.2f, -0.3f, -0.31f,  0.0f, 0.0f, 1.0f,
        6.5f, -0.5f, -0.31f,  0.0f, 0.0f, 1.0f,
        6.2f, -0.3f, -0.31f,  0.0f, 0.0f, 1.0f,
        6.2f, -0.7f, -0.31f,  0.0f, 0.0f, 1.0f,
        //////////////////////////////////////////////////////////////////////////
        //顶视图
        // positions          // normals 
        -0.5f, -0.3f, -0.31f,  0.0f, 1.0f, 0.0f,
        -0.5f, -0.3f,  0.31f,  0.0f, 1.0f, 0.0f,
         6.5f, -0.3f, -0.31f,  0.0f, 1.0f, 0.0f,
        -0.5f, -0.3f,  0.31f,  0.0f, 1.0f, 0.0f,
         6.5f, -0.3f, -0.31f,  0.0f, 1.0f, 0.0f,
         6.5f, -0.3f,  0.31f,  0.0f, 1.0f, 0.0f,
        //////////////////////////////////////////////////////////////////////////
        // 底视图
        // 矩形
        -0.2f, -0.7f,  -0.31f,  0.0f, -1.0f, 0.0f,
        -0.2f, -0.7f,   0.31f,  0.0f, -1.0f, 0.0f,
         6.2f, -0.7f,  -0.31f,  0.0f, -1.0f, 0.0f,
        -0.2f, -0.7f,   0.31f,  0.0f, -1.0f, 0.0f,
         6.2f, -0.7f,  -0.31f,  0.0f, -1.0f, 0.0f,
         6.2f, -0.7f,   0.31f,  0.0f, -1.0f, 0.0f,
        //////////////////////////////////////////////////////////////////////////
        // 左视图
        // 上矩形
        -0.5f,  -0.3f,  -0.31f,  -1.0f, 0.0f, 0.0f,
        -0.5f,  -0.5f,  -0.31f,  -1.0f, 0.0f, 0.0f,
        -0.5f,  -0.3f,   0.31f,  -1.0f, 0.0f, 0.0f,
        -0.5f,  -0.5f,  -0.31f,  -1.0f, 0.0f, 0.0f,
        -0.5f,  -0.3f,   0.31f,  -1.0f, 0.0f, 0.0f,
        -0.5f,  -0.5f,   0.31f,  -1.0f, 0.0f, 0.0f,
        // 下斜面 
        -0.5f,  -0.5f,  -0.31f,  -1.0f, 0.0f, 0.0f,
        -0.2f,  -0.7f,  -0.31f,  -1.0f, 0.0f, 0.0f,
        -0.5f,  -0.5f,   0.31f,  -1.0f, 0.0f, 0.0f,
        -0.2f,  -0.7f,  -0.31f,  -1.0f, 0.0f, 0.0f,
        -0.5f,  -0.5f,   0.31f,  -1.0f, 0.0f, 0.0f,
        -0.2f,  -0.7f,   0.31f,  -1.0f, 0.0f, 0.0f,
        //////////////////////////////////////////////////////////////////////////
        // 右视图
        // 上矩形
        6.5f,  -0.3f,  -0.31f,  1.0f, 0.0f, 0.0f,
        6.5f,  -0.5f,  -0.31f,  1.0f, 0.0f, 0.0f,
        6.5f,  -0.5f,   0.31f,  1.0f, 0.0f, 0.0f,
        6.5f,  -0.3f,  -0.31f,  1.0f, 0.0f, 0.0f,
        6.5f,  -0.5f,   0.31f,  1.0f, 0.0f, 0.0f,
        6.5f,  -0.3f,   0.31f,  1.0f, 0.0f, 0.0f,
        // 下斜面
        6.5f,  -0.5f,  -0.31f,  1.0f, 0.0f, 0.0f,
        6.2f,  -0.7f,  -0.31f,  1.0f, 0.0f, 0.0f,
        6.5f,  -0.5f,   0.31f,  1.0f, 0.0f, 0.0f,
        6.2f,  -0.7f,  -0.31f,  1.0f, 0.0f, 0.0f,
        6.5f,  -0.5f,   0.31f,  1.0f, 0.0f, 0.0f,
        6.2f,  -0.7f,   0.31f,  1.0f, 0.0f, 0.0f,
    };
2.2盖梁的VAO、VBO
    unsigned int capVBO, capVAO;
    glGenVertexArrays(1, &capVAO);
    glGenBuffers(1, &capVBO);
    glBindBuffer(GL_ARRAY_BUFFER, capVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(capBeamVertices), capBeamVertices, GL_STATIC_DRAW);
    glBindVertexArray(capVAO);
    // position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    // normal attribute
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
    // 单片箱梁的位置
    glm::vec3 capPosition[] = {
        glm::vec3( 0.0f,  0.0f,   capSpace/2.0f),  // 前一
        glm::vec3( 0.0f,  0.0f,  -capSpace/2.0f),  // 后一
        glm::vec3( 0.0f,  0.0f,   capSpace/2.0f + capSpace),   // 前二
        glm::vec3( 0.0f,  0.0f,  -(capSpace/2.0f + capSpace)), // 后二
    };
    // 单片箱梁的颜色
    glm::vec3 capColor[] = {
        glm::vec3(  1.0f, 0.5f, 0.31f),
        glm::vec3(  1.0f, 0.5f, 0.31f),
        glm::vec3(  1.0f, 0.5f, 0.31f),
        glm::vec3(  1.0f, 0.5f, 0.31f),
    };
2.3绘制盖梁
        int capCount = sizeof(capPosition) / sizeof(glm::vec3);
        int nCapPtCount = sizeof(capBeamVertices)/sizeof(float) / 2 / 3;
        for (int iCap = 0; iCap < capCount; ++iCap)
        {
            glm::mat4 modelCap = glm::mat4(1.0);
            modelCap = glm::translate(modelCap, capPosition[iCap]);
            lightingShader.setMat4("model", modelCap);
            lightingShader.setVec3("objectColor", capColor[iCap]);
            glBindVertexArray(capVAO);
            glDrawArrays(GL_TRIANGLES, 0, nCapPtCount);
        }   
三、绘制桥墩
3.1计算圆周上的点和法向量
struct TVertex {
    // position
    glm::vec3 Position;
    // normal
    glm::vec3 Normal;
};
std::vector<TVertex> getUnitCircleVertices()
{
    const float PI = 3.1415926f;
    float sectorStep = 2 * PI / sectorCount;
    float sectorAngle = 0.0f;
    glm::vec3 position;
    glm::vec3 normal;
    TVertex tVertex;
    std::vector<TVertex> unitCircleVertices;
    for (int i = 0; i <= sectorCount; ++i)
    {
        sectorAngle = i * sectorStep;
        position.x = pierRadius * cos(sectorAngle);
        position.y = 0.0f;
        position.z = pierRadius * sin(sectorAngle);
        normal.x = cos(sectorAngle);
        normal.y = 0.0f;
        normal.z = sin(sectorAngle);
        tVertex.Position = position;
        tVertex.Normal = normal;
        unitCircleVertices.push_back(tVertex);
    }
    return unitCircleVertices;
}
3.2计算圆柱side和上圆形和下圆形
// generate vertices for a cylinder
void buildCylinderVertices(std::vector<TVertex>& vertices)
{
    std::vector<TVertex> unitVertices = getUnitCircleVertices();
    // 获取上、下圆周点数组
    std::vector<TVertex> vctTop;
    std::vector<TVertex> vctBot;
    TVertex tVertex;
    for(int i = 0; i < unitVertices.size(); ++i)
    {
        tVertex.Position = unitVertices[i].Position;
        tVertex.Position.y = pierHeight;
        tVertex.Normal = unitVertices[i].Normal;
        vctTop.push_back(tVertex);  
        tVertex.Position.y = 0.0f;
        vctBot.push_back(tVertex);     
    }
    assert(vctTop.size() >= 2);
    assert(vctBot.size() >= 2);
    // put side vertices to arrays
    for(int i = 0; i < vctTop.size() - 1; ++i)
    {
        // 左三角形
        vertices.push_back(vctTop[i]);
        vertices.push_back(vctBot[i]);
        vertices.push_back(vctBot[i+1]);
        
        // 右三角形
        vertices.push_back(vctTop[i]);
        vertices.push_back(vctTop[i+1]);
        vertices.push_back(vctBot[i+1]);
    }
    
    // 顶部圆形
    glm::vec3 position;
    for (int i = 0; i < vctTop.size() - 1; ++i)
    {
        glm::vec3 position(0.0f, pierHeight, 0.0f);
        glm::vec3 normal(0.0f, 1.0f, 0.0f);
        tVertex.Position = position;
        tVertex.Normal = normal;
        vertices.push_back(tVertex);
        tVertex.Position = vctTop[i].Position;
        vertices.push_back(tVertex);
        tVertex.Position = vctTop[i+1].Position;
        vertices.push_back(tVertex);
    }
    // 底部圆形
    for (int i = 0; i < vctBot.size() - 1; ++i)
    {
        glm::vec3 position(0.0f, 0.0f, 0.0f);
        glm::vec3 normal(0.0f, -1.0f, 0.0f);
        tVertex.Position = position;
        tVertex.Normal = normal;
        vertices.push_back(tVertex);
        tVertex.Position = vctBot[i].Position;
        vertices.push_back(tVertex);
        tVertex.Position = vctBot[i+1].Position;
        vertices.push_back(tVertex);
    }
}
3.3桥墩的VAO、VBO
  // generate vertices for a cylinder
void buildCylinderVertices(std::vector<TVertex>& vertices)
{
    std::vector<TVertex> unitVertices = getUnitCircleVertices();
    // 获取上、下圆周点数组
    std::vector<TVertex> vctTop;
    std::vector<TVertex> vctBot;
    TVertex tVertex;
    for(int i = 0; i < unitVertices.size(); ++i)
    {
        tVertex.Position = unitVertices[i].Position;
        tVertex.Position.y = pierHeight;
        tVertex.Normal = unitVertices[i].Normal;
        vctTop.push_back(tVertex);  
        tVertex.Position.y = 0.0f;
        vctBot.push_back(tVertex);     
    }
    assert(vctTop.size() >= 2);
    assert(vctBot.size() >= 2);
    // put side vertices to arrays
    for(int i = 0; i < vctTop.size() - 1; ++i)
    {
        // 左三角形
        vertices.push_back(vctTop[i]);
        vertices.push_back(vctBot[i]);
        vertices.push_back(vctBot[i+1]);
        
        // 右三角形
        vertices.push_back(vctTop[i]);
        vertices.push_back(vctTop[i+1]);
        vertices.push_back(vctBot[i+1]);
    }
    
    // 顶部圆形
    glm::vec3 position;
    for (int i = 0; i < vctTop.size() - 1; ++i)
    {
        glm::vec3 position(0.0f, pierHeight, 0.0f);
        glm::vec3 normal(0.0f, 1.0f, 0.0f);
        tVertex.Position = position;
        tVertex.Normal = normal;
        vertices.push_back(tVertex);
        tVertex.Position = vctTop[i].Position;
        vertices.push_back(tVertex);
        tVertex.Position = vctTop[i+1].Position;
        vertices.push_back(tVertex);
    }
    // 底部圆形
    for (int i = 0; i < vctBot.size() - 1; ++i)
    {
        glm::vec3 position(0.0f, 0.0f, 0.0f);
        glm::vec3 normal(0.0f, -1.0f, 0.0f);
        tVertex.Position = position;
        tVertex.Normal = normal;
        vertices.push_back(tVertex);
        tVertex.Position = vctBot[i].Position;
        vertices.push_back(tVertex);
        tVertex.Position = vctBot[i+1].Position;
        vertices.push_back(tVertex);
    }
}
3.4绘制桥墩
        int pierCount = sizeof(pierPosition) / sizeof(glm::vec3);
        for (int iPier = 0; iPier < pierCount; ++iPier)
        {
            lightingShader.setMat4("view", viewOrigin);
            glm::mat4 modelPier = glm::mat4(1.0f);
            modelPier = glm::translate(modelPier, pierPosition[iPier]);
            lightingShader.setMat4("model", modelPier);
            lightingShader.setVec3("objectColor", pierColor[iPier]);
            glBindVertexArray(pierVAO);
            glDrawArrays(GL_TRIANGLES, 0, pierVertices.size());
        }
四、着色器
4.1顶点着色器
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
out vec3 FragPos;
out vec3 Normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
    FragPos = vec3(model * vec4(aPos, 1.0));
    Normal = mat3(transpose(inverse(model))) * aNormal;  
    
    gl_Position = projection * view * vec4(FragPos, 1.0);
}
4.2片段着色器
#version 330 core
out vec4 FragColor;
in vec3 Normal;  
in vec3 FragPos;  
  
uniform vec3 lightPos; 
uniform vec3 lightDirection; 
uniform vec3 viewPos; 
uniform vec3 lightColor;
uniform vec3 objectColor;
void main()
{
    // ambient
    float ambientStrength = 0.1;
    vec3 ambient = ambientStrength * lightColor;
    
    // diffuse 
    vec3 norm = normalize(Normal);
    //vec3 lightDir = normalize(lightPos - FragPos);
    vec3 lightDir = normalize(-lightDirection);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = diff * lightColor;
    
    // specular
    float specularStrength = 0.5;
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);  
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
    vec3 specular = specularStrength * spec * lightColor;  
        
    vec3 result = (ambient + diffuse + specular) * objectColor;
    FragColor = vec4(result, 1.0);
} 
五、项目源代码
链接:https://pan.baidu.com/s/1EA2wd_Rooj-748uKAUugAw 提取码:3d51





One thought on “OpenGL绘制桥梁模型”
内容好多,感谢