【问题标题】:Finding image pixel coordinates (integers) from UV values (floats) of obj file从 obj 文件的 UV 值(浮点数)中查找图像像素坐标(整数)
【发布时间】:2016-05-29 00:33:31
【问题描述】:

我正在解析一个包含纹理坐标 (vt) 值的 obj 文件。据我了解,vt 值是映射到与此 obj 对应的纹理图像中。

假设,我的图像 im = 400x300 像素

我有一个 vt 值

vt .33345 .8998

映射说,在图像中,去坐标:

imageWidth x .3345 , imageHeight x .8998 并使用那里的值。

我已将图像值加载到二维数组中。

问题是,这些映射坐标是浮点值,我想如何将它们映射到像素坐标的整数值?我总是可以截断小数部分,四舍五入等。但是标准是否定义了要完成哪个选项?

【问题讨论】:

  • 您如何使用您希望获得的颜色?标准方法是对屏幕上渲染的三角形内的每个点的 uv 坐标插值进行采样,而不仅仅是角落。这是在渲染期间由 openGL 着色器完成的。

标签: graphics texture-mapping


【解决方案1】:

UV坐标到像素坐标:

pix.x = (uv.x * texture.width) -0.5
pix.y = ((1-uv.y) * texture.height) -0.5

uv 坐标的 y 轴与图像上的 Pixel 坐标相反。

对于最近邻插值,只需将像素坐标四舍五入。

对于双线性插值,计算四个相邻像素的参与百分比并进行加权平均。

当 UV 坐标超出范围时,可以选择如何处理“纹理环绕”:

下面是一些带有“重复”纹理包装的双线性插值的 java 代码:

private static int billinearInterpolation(Point2D uv, BufferedImage texture) {
    uv.x = uv.x>0 ? uv.x%1 : 1+(uv.x%1);
    uv.y = uv.y>0 ? uv.y%1 : 1+(uv.y%1);
    double pixelXCoordinate = uv.x * texture.getWidth() - 0.5;
    double pixelYCoordinate = (1-uv.y) * texture.getHeight() - 0.5;

    pixelXCoordinate = pixelXCoordinate<0?texture.getWidth()-pixelXCoordinate: pixelXCoordinate;
    pixelYCoordinate = pixelYCoordinate<0?texture.getHeight()-pixelYCoordinate : pixelYCoordinate;

    int x = (int) Math.floor(pixelXCoordinate);
    int y = (int) Math.floor(pixelYCoordinate);

    double pX = pixelXCoordinate - x;
    double pY = pixelYCoordinate - y;

    float[] px = new float[]{(float) (1 - pX), (float) pX};
    float[] py = new float[]{(float) (1 - pY), (float) pY};

    float red = 0;
    float green = 0;
    float blue = 0;
    float alpha = 0;
    for (int i = 0; i < px.length; i++) {
        for (int j = 0; j < py.length; j++) {
            float p = px[i] * py[j];
            if (p != 0) {
                int rgb = texture.getRGB((x + i)%texture.getWidth(), (y + j)%texture.getHeight());
                alpha += (float) ((rgb >> 24) & 0xFF) * p;
                red += (float) ((rgb >> 16) & 0xFF) * p;
                green += (float) ((rgb >> 8) & 0xFF) * p;
                blue += (float) ((rgb >> 0) & 0xFF) * p;
            }
        }
    }
    return (((int) alpha & 0xFF) << 24) |
            (((int) red & 0xFF) << 16) |
            (((int) green & 0xFF) << 8) |
            (((int) blue & 0xFF) << 0);
}

【讨论】:

    【解决方案2】:

    Uv 坐标始终在 [0,1] 范围内。这意味着,您将通过将它们与图像大小相乘来获得实际的像素坐标:

    texel_coord = uv_coord * [width, height]
    

    请注意,即使在这里也有浮点值,并且有几种方法可以处理它们。最原始的一种是简单地四舍五入到下一个整数以获得最近的纹素。更复杂的方法是bilinear filtering

    【讨论】:

    • 只转换为整数/截断小数会得到正确的像素坐标吗?如果在浮点值上四舍五入 > 0.5,是否会无意中四舍五入导致答案最终偏离 1 个像素?
    猜你喜欢
    • 2012-08-17
    • 1970-01-01
    • 2020-10-05
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 2018-10-23
    • 2021-01-27
    相关资源
    最近更新 更多