从 obj 文件的 UV 值(浮点数)中查找图像像素坐标(整数)
Finding image pixel coordinates (integers) from UV values (floats) of obj file
我正在解析包含纹理坐标 (vt) 值的 obj 文件。据我了解,vt 值是映射到与此对象对应的纹理图像。
假设,我的图像 im = 400x300 像素
我有一个 vt 值
vt .33345 .8998
映射说,在图像中,去坐标:
imageWidth x .3345 , imageHeight x .8998 并使用那里的值。
我已将图像值加载到二维数组中。
问题是,这些映射坐标是浮点值,我应该如何将它们映射到像素坐标的整数值?我总是可以截断小数部分、四舍五入等。但是标准是否定义了要完成的选项之一?
Uv 坐标始终在 [0,1] 范围内。这意味着,您将通过将它们乘以图像大小来获得实际像素坐标:
texel_coord = uv_coord * [width, height]
请注意,即使在此处也可以获得浮点值,并且有多种方法可以处理它们。最原始的一种是简单地四舍五入到下一个整数以获得最近的纹素。更复杂的方法是 bilinear filtering.
UV 坐标到像素坐标:
pix.x = (uv.x * texture.width) -0.5
pix.y = ((1-uv.y) * texture.height) -0.5
uv坐标的y轴与图像上的像素坐标相反。
对于最近邻插值,只需对像素坐标进行四舍五入。
对于双线性插值,计算相邻四个像素的参与百分比并进行加权平均。
当 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);
}
我正在解析包含纹理坐标 (vt) 值的 obj 文件。据我了解,vt 值是映射到与此对象对应的纹理图像。
假设,我的图像 im = 400x300 像素
我有一个 vt 值
vt .33345 .8998
映射说,在图像中,去坐标:
imageWidth x .3345 , imageHeight x .8998 并使用那里的值。
我已将图像值加载到二维数组中。
问题是,这些映射坐标是浮点值,我应该如何将它们映射到像素坐标的整数值?我总是可以截断小数部分、四舍五入等。但是标准是否定义了要完成的选项之一?
Uv 坐标始终在 [0,1] 范围内。这意味着,您将通过将它们乘以图像大小来获得实际像素坐标:
texel_coord = uv_coord * [width, height]
请注意,即使在此处也可以获得浮点值,并且有多种方法可以处理它们。最原始的一种是简单地四舍五入到下一个整数以获得最近的纹素。更复杂的方法是 bilinear filtering.
UV 坐标到像素坐标:
pix.x = (uv.x * texture.width) -0.5
pix.y = ((1-uv.y) * texture.height) -0.5
uv坐标的y轴与图像上的像素坐标相反。
对于最近邻插值,只需对像素坐标进行四舍五入。
对于双线性插值,计算相邻四个像素的参与百分比并进行加权平均。
当 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);
}