需要帮助以了解如何使用2D / 3D字形

时间:2019-03-07 16:07:42

标签: c++ opengl graphics data-visualization

这是我希望帮助理解的代码段

for (i = 0; i < samplesX; i++)
        for (j = 0; j < samplesY; j++)
        {
            newI = DIM * i / samplesX;
            newJ = DIM * j / samplesY;
            idx = (round(newJ) * DIM) + round(newI);
            if (color_dir == 1 && draw_vecs == 1) {
                direction_to_color(vx[idx], vy[idx], color_dir);
            }
            if (color_dir == 1 && draw_vecs == 2) {
                direction_to_color(fx[idx], fy[idx], color_dir);
            }
            else if (color_dir == 2) {
                scalar = rho[idx];
                set_colormap(scalar, min, max, clampLow, clampHigh);
            }
            else if (color_dir == 3) {
                scalar = sqrt(vx[idx] * vx[idx] + vy[idx] * vy[idx]);
                set_colormap(scalar, min, max, clampLow, clampHigh);
            }
            else if (color_dir == 4) {
                scalar = sqrt(fx[idx] * fx[idx] + fy[idx] * fy[idx]);
                set_colormap(scalar, min, max, clampLow, clampHigh);
            }
            /*if (draw_vecs == 1) {
                glVertex2f(wn + (fftw_real)newI * wn, hn + (fftw_real)newJ * hn);
                glVertex2f((wn + (fftw_real)newI * wn) + vec_scale * vx[idx], (hn + (fftw_real)newJ * hn) + vec_scale * vy[idx]);
            }
            else if (draw_vecs == 2) {
                glVertex2f(wn + (fftw_real)newI * wn, hn + (fftw_real)newJ * hn);
                glVertex2f((wn + (fftw_real)newI * wn) + vec_scale * fx[idx], (hn + (fftw_real)newJ * hn) + vec_scale * fy[idx]);
            }*/
            if (draw_vecs == 1) {
                glVertex2f(wn + (fftw_real)i * wn, hn + (fftw_real)j * hn);
                glVertex2f((wn + (fftw_real)i * wn) + vec_scale * vx[idx], (hn + (fftw_real)j * hn) + vec_scale * vy[idx]);
            }
            else if (draw_vecs == 2) {
                glVertex2f(wn + (fftw_real)i * wn, hn + (fftw_real)j * hn);
                glVertex2f((wn + (fftw_real)i * wn) + vec_scale * fx[idx], (hn + (fftw_real)j * hn) + vec_scale * fy[idx]);
            }
        }
    glEnd();
}

据我所知,这目前正在做的是显示这些二维线/箭头(刺猬),这些线/箭头以2D形式可视化力/速度,如下图所示。

-

可悲的是,我对线性代数,微积分和计算机图形学的一般理解至今为止,我很难剖析这部分。

理想情况下,我想了解这一点,也希望了解如何使用此预先存在的代码,并添加功能以显示其他两个显示矢量和/或标量字段的字形类型,例如

  • 三维圆锥
  • 三维椭球

如果我在这里什么都不见了,请告诉我!

上面的代码段中包含一些变量:

const int DIM = 50;             //size of simulation grid
int   color_dir = 0;            //use direction color-coding or not
float scalar;
int newI, newJ;
float temp;
float vec_scale = 1000;         //scaling of hedgehogs
int   draw_vecs = 1;            //draw the vector field or not

1 个答案:

答案 0 :(得分:0)

您那里的代码段本来可以写得更简单(还需要一些有根据的猜测,以了解某些变量和函数的含义)。

让我们分解一下。

前两行很容易理解,它们是在2D数组上进行迭代的标准节

for (i = 0; i < samplesX; i++)
        for (j = 0; j < samplesY; j++)

ij是运行索引,它将遍历(i,j) ∈ [i, samplesX) × [j, samplesY)中的每个离散坐标元组。接下来的两行将2D索引重新映射到新的值范围内,特别是[i, samplesX)×[j, samplesY) → [0, DIM)×[0, DIM)。缺少的一条信息是DIM的类型。它将使其成为某种浮点类型。

     newI = DIM * i / samplesX;
     newJ = DIM * j / samplesY;

下一行容易出现错误。它将newInewJ转换为一维数组的运行中一维索引,该索引由ij解决。

为什么会有问题?因为在转换为DIM空间时,信息可能已经丢失。这种信息丢失可能会导致安全漏洞(!),事实上,Google Chrome,Android和其他项目使用的渲染库Skia最近确实具有这种漏洞;该文章值得一读:https://googleprojectzero.blogspot.com/2019/02/the-curious-case-of-convexity-confusion.html

实现此目的的正确方法是让DIM为整数并对其执行定点运算,最终将小数位截断。但是我离题了。下一步实际上是执行可怜人的查找表查找。 vx``vyfx``fy是一些扁平的2D数组,可通过1D索引进行访问,并且direction_to_color映射到值大概到调用{{1} }; glColor可能也是如此。这是对OpenGL的错误使用。

set_colormapij的整个重新映射,然后查找只是纹理查找的不良实现。 OpenGL已经具有纹理。只需加载为纹理坐标数组并启用纹理即可。

最后,对每个书脊进行两次DIM呼叫,其中一个凝视点位于网格中心glVertex上,移至偏移位置(wn, hn)

我对该代码的判断是:完全垃圾!所有这些本来可以更加优雅地完成,甚至可以追溯到1994年使用OpenGL-1.0编写的代码。如果要实现自己的矢量场图,请不要以此为起点。

这几天,我们有了带有着色器的可编程GPU。可以完成的所有工作就是几行着色器代码。