使用SharpGL三位点云图的绘制时,一般是将所有的数据处理好然后通过OpenGLDraw整体绘制出来。
我现在想要用线程来控制点云图的绘制,同时要是动态的。我试过用OpenGLDraw来动态绘制,将z轴数据固定加1,第一次画一个点,然后擦除,第二次两个点,擦除,这样循环直到绘制完成。
这个方法是可以的,然后我又试了用线程代替OpenGLDraw,将每次绘制擦除的代码放到一个while循环内,但是结果有问题,OpenGLControl控件上没有显示点。
请问能否给我提供一个思路,或者在我的思路上帮我解答一下问题。
以下是我线程上挂的方法代码。
private void DynamicShow()
{
for (int i = 0; i < xds; i++)//xds为总点数
{
dynamicZ.Add(maxz[i] + i);//准备Z轴数据
}
while (openFileReadyFlag)
{
gl.LoadIdentity();//重置当前指定的矩阵为单位矩阵
gl.Translate(_ZBx, _ZBy, _ZBz);//平移函数,参数为XYZ方向上的平移大小;最后一个参数为距离屏幕距离;
gl.Rotate(_x, 1.0f, 0.0f, 0.0f);//绕x轴旋转_x度,_x为正表示逆时针
gl.Rotate(_y, 0.0f, 1.0f, 0.0f);
gl.Rotate(_z, 0.0f, 0.0f, 1.0f);
gl.Begin(_model);
gl.Color(1.0f, 1.0f, 0.0f);
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
for (int i = 0; i < max; i++)//用max来控制使每次绘制比上一次多一个点
{
gl.Vertex((maxx[i] - _ZBxT) / _ZBv, (maxy[i] - _ZByT) / _ZBv, maxz[i] / _ZBzT);//数组为点云坐标数组,其他为坐标换算参数
}
max++;
Thread.Sleep(2);
gl.End();
if (max == xds)
{
break;
}
}
}
你的方法是通过循环不断地在OpenGL中添加和删除点来动态绘制点云图的。然而,这种方式可能会在每次迭代中花费较长的时间,因为你需要在绘图上下文中进行许多操作,包括重置矩阵、平移、旋转、清除颜色缓冲区和绘制点。
在这种情况下,使用线程可以提高绘制速度,但是你的线程函数中的操作似乎也是一个死循环,只会导致OpenGL控件一直处于绘图状态。此外,你的线程函数似乎没有使用OpenGL的双缓冲技术,这可能会导致绘图不连贯或闪烁。
下面是一种更有效的方法来实现动态绘制点云图:
以下是使用Task来实现动态绘制点云图的代码示例:
private void InitScene()
{
// 初始化点云对象,例如使用VBO或者VAO
// 这里使用VBO作为示例
float[] points = new float[xds * 3]; // 每个点包含x、y、z三个分量
// 将x、y、z坐标按顺序存入points数组
// ...
int vbo;
gl.GenBuffers(1, out vbo);
gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, vbo);
gl.BufferData(OpenGL.GL_ARRAY_BUFFER, points.Length * sizeof(float), points, OpenGL.GL_STATIC_DRAW);
gl.VertexPointer(3, OpenGL.GL_FLOAT, 0, IntPtr.Zero);
gl.EnableClientState(OpenGL.GL_VERTEX_ARRAY);
}
private void StartDrawing()
{
Task.Run(() =>
{
int max = 0;
while (openFileReadyFlag)
{
float[] dynamicZ = new float[xds];
for (int i = 0; i < xds; i++)
{
dynamicZ[i] = maxz[i] + i;
}
// 将dynamicZ数组的值更新到点云对象中的z坐标上
// ...
max++; // 增加每次绘制的点数
Thread.Sleep(2);
if (max >= xds) break;
}
});
}
private void DrawScene()
{
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
gl.DrawArrays(_model, 0, max); // 渲染点云对象中的前max个点
gl.Flush();
}
注意,在使用OpenGL绘图函数之前,需要确保已经初始化了点
gl.LoadIdentity();//重置当前指定的矩阵为单位矩阵
gl.Translate(_ZBx, _ZBy, _ZBz);//平移函数,参数为XYZ方向上的平移大小;最后一个参数为距离屏幕距离;
gl.Rotate(_x, 1.0f, 0.0f, 0.0f);//绕x轴旋转_x度,_x为正表示逆时针
gl.Rotate(_y, 0.0f, 1.0f, 0.0f);
gl.Rotate(_z, 0.0f, 0.0f, 1.0f);
gl.Begin(_model);
gl.Color(1.0f, 1.0f, 0.0f);
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); // 在循环外清除帧缓冲区
while (openFileReadyFlag)
{
for (int i = 0; i < max; i++)//用max来控制使每次绘制比上一次多一个点
{
gl.Vertex((maxx[i] - _ZBxT) / _ZBv, (maxy[i] - _ZByT) / _ZBv, maxz[i] / _ZBzT);//数组为点云坐标数组,其他为坐标换算参数
}
max++;
Thread.Sleep(2);
gl.End();
if (max == xds)
{
break;
}
}