自动生成UV坐标算法

时间:2013-09-02 18:25:34

标签: graphics 3d uv-mapping

我正在为自己的工具编写自己的uv编辑器,并且我正在尝试将尽可能多的算法合并到投影中。我需要采用任意网格,并为每个顶点制作uv坐标。

到目前为止,我有平面和最小二乘保形贴图。

我想加入更多,例如三平面,圆柱,球面,但我很难找到信息来执行算法。三平面似乎会产生一种颜色,但我需要在UV坐标中获取所有颜色。

非常感谢帮助!!

3 个答案:

答案 0 :(得分:25)

<强>三平面

忘了它:它不是投影算法(一种为你提供UV坐标的算法),你无法从中获取UV坐标。这是一个渲染算法,它为您提供了一种颜色,通过混合使用每个X-Y-Z平面投影分别获得的颜色。

Cylindrincal,Spherical

与平面一样,这些是非常简单的投影算法,直接从XYZ值为您提供UV值,而不考虑与其他顶点的连接。

  • 对于圆柱形:将(x,y,z)转换为Cylindrical Coordinates(ρ,φ,z),并用作UV坐标u =φ和v = z
  • 对于球形:在Spherical Coordinates(r,θ,φ)中转换(x,y,z),并用作UV坐标u =θ和v =φ

当然,您可以使用不同的轴切换X,Y和Z的角色,或者执行一些平移/旋转/缩放以获得更多控制(与控制大小和方向相同的方式)你用于平面投影的平面。)

<强>立方

首先,您需要确定为网格的每个面分配哪个“投影面”。我将投影面X,-X,Y,-Y,Z和-Z命名为如下图所示(其中我假设X,Y和Z轴分别具有红色,绿色和蓝色):

enter image description here

为此,您只需找到法线(nx,ny,nz)的哪个坐标具有最大绝对值,并将其指定给与此轴和符号对应的面。例如:

  • 如果n =(0.8,0.5,0.3),那么相应的面是X(| nx |是最大的,nx是正的)
  • 如果n =(0.3,0.8,0.5),那么相应的面是Y(| ny |是最大的,ny是正的)
  • 如果n =(0.3,-0.8,0.5),那么相应的面是-Y(| ny |是最大的,ny是负的)

然后,一旦知道为网格的每个面分配哪个投影面,就可以将相应的平面投影应用于该面周围的顶点以获得临时值(u_temp,v_temp)∈[0,1] x [0,1]。

下一步是将该值uv_temp∈[0,1] x [0,1]变换为包含在较小正方形中的值uv,如上面的图像A所示。例如,如果你应用投影“X”,那么你想要uv∈[2 / 3,3 / 3] x [2 / 4,3 / 4],那么你会这样做:

u = 2./3. + u_temp/3.;
v = 2./4. + v_temp/4.; 

最后,最后一步是不要忘记复制属于具有不同平面投影的两个面的UV顶点(图片上不同颜色之间的边界)。实际上,网格的某些顶点可以(并且在大多数情况下应该)在UV贴图中的几个位置分割,以获得不错的结果。

答案 1 :(得分:2)

立方映射

基于(rx,ry,rz)向量执行此操作的标准方法是首先在表中查找某些值。这些值用于每个顶点的(s,t)(或(u,v))纹理坐标。

首先找到反射矢量 R = 2(N点V)N - V,其中V =顶点,N =正常,R反射矢量(rx,ry,rz)

                      major axis 
                      direction      sc     tc     ma 
                      ---------      ---    ---    -- 
                      +rx            -rz    -ry    rx 
                      -rx            +rz    -ry    rx 
                      +ry            +rx    +rz    ry 
                      -ry            +rx    -rz    ry 
                      +rz            +rx    -ry    rz 
                      -rz            -rx    -ry    rz 

一旦为sc,tc和ma指定了值,可以使用以下公式计算该面的(s,t)坐标。

if((rx >= ry) && (rx  >= rz)) 
{ 
sc = -rz; 
tc = -ry; 
ma = fabs(rx);  //absolute value
s = ((sc/ma) + 1) / 2; 
t = ((tc/ma) + 1) / 2; 

cout << "+rx (" << s << "," << t << ")" << endl; 
} 

  if((rx <= ry) && (rx  <= rz)) 
{ 
sc = +rz; 
tc = -ry; 
ma = fabs(rx); 
s = ((sc/ma) + 1) / 2; 
t = ((tc/ma) + 1) / 2; 

cout << "-rx (" << s << "," << t << ")" << endl; 
} 

if((ry >= rz) && (ry >= rx)) 
{ 
sc = +rx; 
tc = +rz; 
ma = fabs(ry); 
s = ((sc/ma) + 1) / 2; 
t = ((tc/ma) + 1) / 2; 

cout << "+ry (" << s << "," << t << ")" << endl; 
} 

if((ry <= rz) && (ry <= rx)) 
{ 
sc = +rx; 
tc = -rz; 
ma = fabs(ry); 
s = ((sc/ma) + 1) / 2; 
t = ((tc/ma) + 1) / 2; 

cout << "-ry (" << s << "," << t << ")" << endl; 
} 

if((rz >= ry) && (rz >= rx)) 
{ 
sc = +rx; 
tc = -ry; 
ma = fabs(rz); 
s = ((sc/ma) + 1) / 2; 
t = ((tc/ma) + 1) / 2; 

cout << "+rz (" << s << "," << t << ")" << endl; 
} 

if((rz <= ry) && (rz <= rx)) 
{ 
sc = -rx; 
tc = -ry; 
ma = fabs(rz); 
s = ((sc/ma) + 1) / 2; 
t = ((tc/ma) + 1) / 2; 

cout << "-rz (" << s << "," << t << ")" << endl; 
} 

参考 http://www.unc.edu/~zimmons/cs238/maps/cubeind.html

球面,立方体和抛物线环境映射http://www.unc.edu/~zimmons/cs238/maps/environment.html

OP请你分享你的最小二乘保形映射算法来生成UV坐标。谢谢。

答案 2 :(得分:1)

您应该从siggraph课程Mesh Parameterization: Theory and Practice开始,然后查看引用的论文,了解您正在实施的算法的详细信息