17

I'm writing my own uv editor for a tool of mine, and I'm trying to incorporate as many algorithms as I can for projections. I need to take an arbitrary mesh, and make uv coordinates for each vertex.

So far, I have planar, and Least Squares Conformal Map.

I'd like to incorporate more, such as tri-planar, cylinder, spherical, but I'm having a very difficult time locating the information to perform the algorithms. The tri-planar appear to generate a color, but I need to get everything in UV coordinates.

Help would be very appreciated!!

4

3 回答 3

30

三平面

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

圆柱形、球形

像平面一样,这些都是非常简单的投影算法,可以直接从 XYZ 值给您一个 UV 值,而不考虑与其他顶点的连接性。

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

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

立方体

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

在此处输入图像描述

为此,您只需找到法线(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 贴图中的多个位置进行拆分,以获得不错的结果。

于 2013-09-04T02:44:16.283 回答
3

三次映射

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

首先找到Reflected Vector R = 2(N dot V)N - V, 其中V = Vertex, N = Normal , R Reflected Vector(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 坐标的最小二乘保形映射算法。谢谢你。

于 2013-11-12T17:38:37.017 回答
2

您应该从 siggraph 课程网格参数化:理论与实践开始,然后查看引用的论文以获取有关您正在实施的算法的详细信息

于 2013-09-02T21:05:28.600 回答