Qt OpenGL - 网格式的直角坐标系
- 引言
- 一、绘制3D网格
- 1.1 绘制平行于y轴的线段
- 1.2 绘制平行于三个轴的线段
- 1.3 绘制不同的3D网格
- 二、网格式的直角坐标系
- 三、参考链接
引言
在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轴的线段
- 先绘制平行于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 绘制平行于三个轴的线段
- 绘制平行于三个轴的线段,如上图所示。增加绘制平行于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网格
- 修改
GL3DGrid
(p1, p2,3
)最后一个参数为4,6,10;
二、网格式的直角坐标系
- 由以上代码已可绘制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();
}
三、参考链接
https://blog.csdn.net/sinat_36772813/article/details/129338953 OpenGL中的坐标系 ↩︎
https://blog.csdn.net/qq_37996632/article/details/103178120 OpenGL画坐标系2 ↩︎
https://blog.csdn.net/qq_40004575/article/details/109547793 Qt+OpenGL绘制三维坐标系(动态曲线显示) ↩︎