首页 > 解决方案 > 需要帮助了解如何使用 2D/3D 字形

问题描述

这是我想帮助理解的代码片段

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

标签: c++openglgraphicsdata-visualization

解决方案


你那里的代码片段本来可以写得更简单(也需要一些有根据的猜测一些变量和函数的含义)。

让我们分解一下。

前两行很容易理解,它们是迭代二维数组的标准节

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

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

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

下一行很容易出错。它将newIandnewJ转换为一维数组的运行一维索引,由i和寻址j

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

实现这一点的正确方法是让 DIM 为整数并对其执行定点运算,最终截断小数位。但我离题了。下一个块本质上是执行一个穷人的查找表查找。vx``vy并且fx``fy是一些扁平的二维数组,通过一维索引访问,并direction_to_color映射到一个可能调用的值glColor;可能也是如此set_colormap。这是对 OpenGL 的不好使用。

i从和jDIM然后查找的整个重新映射只是纹理查找的糟糕实现。OpenGL 已经有了纹理。只需加载为纹理坐标数组并启用纹理。

最后,对于每个脊椎,进行两次调用glVertex,一次调用位于网格中心上的起始点(wn, hn)到偏移位置(wn, hn) + (i, j)

我对该代码的判断:完全垃圾!所有这一切都可以更优雅地完成,即使是在 1994 年使用 OpenGL-1.0 时,似乎已经为它编写了代码。如果您想实现自己的向量场图,请不要以此为起点。

如今,我们拥有带着色器的可编程 GPU。可以完成的所有这些操作都是几行着色器代码。


推荐阅读