未扭曲的纹理坐标

发布于 2024-10-23 18:48:03 字数 1378 浏览 1 评论 0原文

如何计算平面上点的 UV 坐标?

我有一个多边形 - 3 个或 4 个或更多点 - 在一个平面上 - 也就是说,所有点都在一个平面上。但它可以是空间中的任何角度。

该多边形的一侧(两个点)将被映射到纹理中两个相应的 2D 点 - 我提前知道这两个点。我还知道纹理的 x 和 y 比例,并且没有点落在纹理范围或其他“边缘情况”之外。

这是一张图像,其中最上面的纹理四边形扭曲了:

在此处输入图像描述

我用黄色勾画出一个坏的四边形。想象一下,我知道该四边形上两个最底角的 UV 坐标,并且想要计算其他两点的正确 UV 坐标...

如何计算所有点的 UV 坐标平面上的其他点相对于这两个点?

想象一下我的纹理是现实生活中的一张纸,我想为你的(平坦的)车门提供纹理。我在纸上画了两个点,与你车门上的两个点对齐。如何计算车门上其他位置在纸张下方的位置?

你能使用三边测量吗? 2D 空间中两个已知点的伪代码是什么样的?


使用 Brainjam 的代码成功:

def set_texture(self,texture,a_ofs,a,b):
    self.texture = texture
    self.colour = (1,1,1)
    self.texture_coords = tx = []
    A, B = self.m[a_ofs:a_ofs+2]
    for P in self.m:
        if P == A:
            tx.append(a)
        elif P == B:
            tx.append(b)
        else:
            scale = P.distance(A)/B.distance(A)
            theta = (P-A).dot((B-A)/(P.distance(A)*B.distance(A)))
            theta = math.acos(theta)
            x, y = b[0]-a[0], b[1]-a[1]
            x, y = x*math.cos(theta) - y*math.sin(theta), \
                x*math.sin(theta) + y*math.cos(theta)
            x, y = a[0]+ x*scale, a[1]+ y*scale
            tx.append((x,y))

“在此输入图像描述”

How do you calculate UV coordinates for points on a plane?

I have a polygon - 3 or 4 or more points - that is on a plane - that is to say, all the points are on a plane. But it can be at any angle in space.

One side of this polygon - two points - are to be mapped to two corresponding 2D points in a texture - I know these two points in advance. I also know the x and y scale for the texture, and that no points fall outside the texture extent or other 'edge cases'.

Here's an image where the up-most textured quad is distorted:

enter image description here

I outlined a bad quad in yellow. Imagine that I know the UV coordinates of those two bottom-most corners on that quad, and want to calculate the proper UV coordinates of the other two points...

How do you calculate the UV coordinates of all the other points in the plane relative to these two points?

Imagine my texture is a piece of paper in real life, and I want to texture your (flat) car door. I place two dots on my paper, which I line up with two dots on your car door. How do I calculate where the other locations on the car door are under the paper?

Can you use trilateration? What would the pseudo-code look like for two known points in 2D space?


Success using brainjam's code:

def set_texture(self,texture,a_ofs,a,b):
    self.texture = texture
    self.colour = (1,1,1)
    self.texture_coords = tx = []
    A, B = self.m[a_ofs:a_ofs+2]
    for P in self.m:
        if P == A:
            tx.append(a)
        elif P == B:
            tx.append(b)
        else:
            scale = P.distance(A)/B.distance(A)
            theta = (P-A).dot((B-A)/(P.distance(A)*B.distance(A)))
            theta = math.acos(theta)
            x, y = b[0]-a[0], b[1]-a[1]
            x, y = x*math.cos(theta) - y*math.sin(theta), \
                x*math.sin(theta) + y*math.cos(theta)
            x, y = a[0]+ x*scale, a[1]+ y*scale
            tx.append((x,y))

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

半暖夏伤 2024-10-30 18:48:03

您必须用两个选定的向量和原点来表达其他点。

我会做这样的事情:

选择 3 个 3D 点和相应的 UV 点:

  • A(x,y,z,u,v)
  • B(x,y,z,u,v)
  • C(x,y,z,u, v)

然后使用 x,y,z 坐标,我们希望将给定的 3D 点 D 表示为:

D = A + alpha ( B - A ) + beta ( C - A ) + gamma ( B - A ) X ( C - A )

我们有 3 个 x、y、z 方程,X 是叉积,α、β、gamma 未知。
我们希望这能在 uv 和 xyz 之间创建线性关系。

计算 W = ( B - A ) X ( C - A ),我们需要求解:

Dx - Ax = alpha.(Bx-Ax) + beta.(Cx-Ax) + gamma.Wx

Dy - Ay = alpha.( By-Ay) + beta.(Cy-Ay) + gamma.Wy

Dz - Az = alpha.(Bz-Az) + beta.(Cz-Az) + gamma.Wz

使用 此方法

       | (Bx-Ax) , Cx-Ax , Wx | 
   M = | (By-Ay) , Cy-Ay , Wy | 
       | (Bz-Az) , Cz-Az , Wz | 

我们将结果矩阵称为N,注意它不依赖于D。

然后计算 D 的 alpha,beta,gamma:

(alpha,beta,gamma) = N.(DA)

然后计算 D 的 u,v:

Du = Au + alpha( Bu - Au ) + beta( Cu - Au )

Dv = Av + alpha( Bv - Av ) + beta( Cv - Av )

不使用 gamma,因为它是 D 和 (A,B,C) 3D 平面之间的距离。

You have to express the others points in terms of two chosen vectors and an origin.

I would do something like this :

Choose 3 3D points with corresponding UV points :

  • A(x,y,z,u,v)
  • B(x,y,z,u,v)
  • C(x,y,z,u,v)

Then using the x,y,z coords, we want to express a given 3D point D as :

D = A + alpha ( B - A ) + beta ( C - A ) + gamma ( B - A ) X ( C - A )

We have 3 equations for x,y,z, X is cross product, and alpha,beta,gamma are unknown.
We want this to create a linear relation between uv and xyz.

Compute W = ( B - A ) X ( C - A ), we need to solve :

Dx - Ax = alpha.(Bx-Ax) + beta.(Cx-Ax) + gamma.Wx

Dy - Ay = alpha.(By-Ay) + beta.(Cy-Ay) + gamma.Wy

Dz - Az = alpha.(Bz-Az) + beta.(Cz-Az) + gamma.Wz

Compute the inverse matrix of matrix M with this method :

       | (Bx-Ax) , Cx-Ax , Wx | 
   M = | (By-Ay) , Cy-Ay , Wy | 
       | (Bz-Az) , Cz-Az , Wz | 

We call the result matrix N, note it does not depend on D.

Then compute alpha,beta,gamma for D by :

(alpha,beta,gamma) = N.(D-A)

Then compute u,v for D by :

Du = Au + alpha( Bu - Au ) + beta( Cu - Au )

Dv = Av + alpha( Bv - Av ) + beta( Cv - Av )

gamma is not used as it's a distance between D and the (A,B,C) 3D plane.

梦醒时光 2024-10-30 18:48:03

从 UV 坐标已知的两个顶点开始,按逆时针顺序标记 3D 多边形的顶点。将这些标签命名为 ABCD。 UV空间中对应顶点的标签为abcd,其中 ab 是已知的。

你所说的问题是,对于原始多边形中的一个点P,要确定对应的UV坐标p。 (我相信您只关心计算点CD的UV坐标cd,但P的通解是相同的。)

首先,计算PABA之间的角度θ。使用归一化向量和 acos 的点积可以轻松完成此操作。

α = (PA)⋅(BA)/(|PA||BA|)

θ = acos( α)

我们还计算长度之比:

σ = |PA|/|BA|

现在要计算 UV 空间中的 p,我们只需将向量 ba 旋转角度 θ(保持 a 固定)并按 σ 缩放。

R(旋转角度 θ 的矩阵)为

| +cos(θ) -sin(θ) |
| +sin(θ) +cos(θ) |

那么p = a + σR(ba)。

你就完成了。

Label the vertices of your 3D polygon in counter-clockwise order, starting with the two vertices whose UV coordinates are known. Call these labels A, B, C, D. The labels of the corresponding vertices in UV space are a, b, c, d, where a and b are known.

The problem you've stated is, for a point P in the original polygon, to determine the corresponding UV coordinate p. (I believe that you only care about calculating the UV coordinates c and d for the points C and D, but the general solution for P is the same.)

First, calculate the angle θ between P-A and B-A. This is easily done using the dot product of the normalized vectors, and acos.

α = (P-A)⋅(B-A)/(|P-A||B-A|)

θ = acos(α)

We also calculate the ratio of the lengths:

σ = |P-A|/|B-A|

Now to calculate p in UV space, we simply rotate the vector b-a by angle θ (keeping a fixed) and scale by σ.

Let R, the matrix for a rotation by angle θ, be

| +cos(θ) -sin(θ) |
| +sin(θ) +cos(θ) |

Then p = a + σR( b-a).

And you're done.

澜川若宁 2024-10-30 18:48:03

U 和 V 是 0 到 1 之间的数字。

因此,假设在您的情况下,较大边缘的大小为 10,较小边缘的大小为 5,每个“间隙”为 2.5。然后将其标准化,为您提供所需的数字。

所以一些示例伪代码:

bottomLeftVector(0,0,0)
bottomLeftTexture(0,0)
topLeftVector(2.5, 5, 0)
topLeftTexture(0.25, 0)
topRightVector(7.5, 5, 0)
topRightTexture(0, 0.75)
bottomRightVector(10, 0, 0)
bottomRightTexture(1,1)

希望这有帮助!

U and V are numbers between 0 and 1.

So, say in your situation the size of the larger edge is 10, and the smaller edge is 5, each "gap" is 2.5. This is then normalized to give you a digit that is needed.

so some example pseudo code:

bottomLeftVector(0,0,0)
bottomLeftTexture(0,0)
topLeftVector(2.5, 5, 0)
topLeftTexture(0.25, 0)
topRightVector(7.5, 5, 0)
topRightTexture(0, 0.75)
bottomRightVector(10, 0, 0)
bottomRightTexture(1,1)

Hope this helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文