本文主要讲述如何使用现代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
std::vector<TVertex> pierVertices;
buildCylinderVertices(pierVertices);
unsigned int pierVBO, pierVAO;
glGenVertexArrays(1, &pierVAO);
glGenBuffers(1, &pierVBO);
glBindVertexArray(pierVAO);
glBindBuffer(GL_ARRAY_BUFFER, pierVBO);
glBufferData(GL_ARRAY_BUFFER, pierVertices.size() * sizeof(TVertex), &pierVertices[0], GL_STATIC_DRAW);
// position attribute
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TVertex), (void*)0);
// normal attribute
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(TVertex), (void*)offsetof(TVertex, Normal));
glBindVertexArray(0);
// 单个桥墩的位置
float pierPosY = -(pierHeight + 0.7f);
float pierPosLx = -0.2f + pierRadius + 1.0f;
float pierPosRx = 6.2f - pierRadius - 1.0f;
glm::vec3 pierPosition[] = {
// 前一
glm::vec3( pierPosLx, pierPosY, capSpace / 2.0f),
glm::vec3( pierPosRx, pierPosY, capSpace / 2.0f),
// 后一
glm::vec3( pierPosLx, pierPosY, -capSpace / 2.0f),
glm::vec3( pierPosRx, pierPosY, -capSpace / 2.0f),
// 前二
glm::vec3( pierPosLx, pierPosY, capSpace / 2.0f + capSpace),
glm::vec3( pierPosRx, pierPosY, capSpace / 2.0f + capSpace),
// 后二
glm::vec3( pierPosLx, pierPosY, -(capSpace / 2.0f + capSpace)),
glm::vec3( pierPosRx, pierPosY, -(capSpace / 2.0f + capSpace)),
};
// 单个桥墩的颜色
glm::vec3 pierColor[] = {
glm::vec3( 0.5f, 0.7f, 0.7f),
glm::vec3( 0.5f, 0.7f, 0.7f),
glm::vec3( 0.5f, 0.7f, 0.7f),
glm::vec3( 0.5f, 0.7f, 0.7f),
glm::vec3( 0.5f, 0.7f, 0.7f),
glm::vec3( 0.5f, 0.7f, 0.7f),
glm::vec3( 0.5f, 0.7f, 0.7f),
glm::vec3( 0.5f, 0.7f, 0.7f),
};
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
原文地址:
http://liyanliang.net/index.php/2021/06/30/opengldarwcivilmodel/