原理:
设置一个定时器,在定时器内部不断将更新后的末端位置(轨迹跟踪点)输入到动态数组中,再利用OpenGL画直线的功能绘制轨迹。
实现代码:
设置一个定时器:
//定时器ID
int myTimerID;
//定时器函数
virtual void timerEvent( QTimerEvent *event);
void Simulation::openFile()
{
myTimerID = this->startTimer(100);
}
void Simulation::closemodel()
{
killTimer(myTimerID);
}
初始化存放末端位置的数组、存放数据的数量:
float *pointarray;
int pointnum = 0;
在定时器中动态更新顶点数据:
void Simulation::timerEvent(QTimerEvent *event)
{
pointarray[pointnum] = point60.x;
pointarray[pointnum + 1] = point60.y;
pointarray[pointnum + 2] = point60.z;
pointnum = pointnum +3;
}
这里的point60是末端位置,可以动态变化,博主这个轨迹跟踪是在仿真软件内建立的,因此point60在仿真过程中会动态变化。
建立点的着色器point.vs,point.fs:
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
#version 330 core
out vec4 FragColor;
uniform vec3 pointColor;
void main()
{
FragColor = vec4(pointColor, 1.0f);
}
调用着色器:
Shader pointShader("路径/point.vs", "路径/point.fs");
在glfw的while()循环中定义一个静态数组,因为OpenGL绘制的时候只能识别静态数组:
float lines[36000] = {};
if(pointnum > 0)
{
for(int i=0;i{
lines[i]=pointarray[i];
}
for(int j=pointnum;j<36000;j=j+3){
lines[j]=lines[pointnum-3];lines[j+1]=lines[pointnum-2];lines[j+2]=lines[pointnum-1];}
}
在while()中设定顶点顶点数组对象、顶点缓冲对象,并画直线,不了解的可以去学习learnOpenGL:
unsigned int pointVAO, pointVBO;glGenVertexArrays(1, &pointVAO);glGenBuffers(1, &pointVBO);glBindVertexArray(pointVAO);glBindBuffer(GL_ARRAY_BUFFER, pointVBO);glBufferData(GL_ARRAY_BUFFER, sizeof(lines), lines, GL_STATIC_DRAW);// position attributeglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);pointShader.use();
pointShader.setVec3("pointColor", 0.0, 0.0, 1.0);pointShader.setMat4("projection", projection);pointShader.setMat4("view", view);model = glm::mat4();pointShader.setMat4("model", model);glBindVertexArray(pointVAO);glDrawArrays(GL_LINE_STRIP, 0, pointnum);这里的GL_LINE_STRIP是画出按顺序连接所有顶点的直线,0是画的第一个点对应序号,pointnum是画的点数。以上这些就是轨迹跟踪的实现过程。当然,在数组方面还有些问题,影响效率,后期试着改进。