1
$\begingroup$

I'm writing python scripts that preserve UV coordinates when faces are translated/rotated/scaled.
And I know similar feature exists in Presages Creator.

https://youtu.be/QH3G9qZgjfw?t=3m32s

However, I don't get what algorithm this tool uses.
For testing, I wrote test code about this problem following below algorithm.

  1. Transform 3D coord of face's vertex to 2D coord
  2. Calculate destination UV coord to use ratio between 2D vertex coord and UV coord

However, it does not work when target face is not rectangle...
This is a example.
When UV coord is same direction as vertex coords, it works correctly.

before:
enter image description here

after:
enter image description here

However, when UV coord is not same direction as vertex coords, it does not work.

before:
enter image description here

after:
enter image description here

Is there any problem about this algorithm or code?
Or is there better solution?

src_vlist       # vertex coord list before transformation of face
src_uvlist      # UV coord list before transformation of face
dest_vlist      # vertex coord list after transformation of face
dest_uvlist     # UV coord list after transformation of face
src_vlist_2d    # transformed 2D vertex coord list before transformation of face
dest_vlist_2d   # transformed 2D vertex coord list after transformation of face
dest_uvlist_2d  # target UV coord **I want to calculate this!!**

# transform 3D coord to 2D coord about verticies
v = src_vlist[0:3]
trans_mat = Matrix.Translation(-v[0])
src_vlist_2d = [trans_mat * sv for sv in src_vlist]
v = src_vlist_2d[0:3]
rotz_mat = Matrix.Rotation(-atan2(v[1].y, v[1].x), 3, 'Z')
src_vlist_2d = [rotz_mat * sv for sv in src_vlist_2d]
v = src_vlist_2d[0:3]
roty_mat = Matrix.Rotation(atan2(v[1].z, sqrt(v[1].x * v[1].x + v[1].y * v[1].y)), 3, 'Y')
src_vlist_2d = [roty_mat * sv for sv in src_vlist_2d]
v = src_vlist_2d[0:3]
rotx_mat = Matrix.Rotation(-atan2(v[2].z, v[2].y), 3, 'X')
src_vlist_2d = [rotx_mat * sv for sv in src_vlist_2d]
for sv in src_vlist_2d:
    sv.z = 0.0
dest_vlist_2d = [trans_mat * dv for dv in dest_vlist]
dest_vlist_2d = [rotz_mat * dv for dv in dest_vlist_2d]
dest_vlist_2d = [roty_mat * dv for dv in dest_vlist_2d]
dest_vlist_2d = [rotx_mat * dv for dv in dest_vlist_2d]
for dv in dest_vlist_2d:
    dv.z = 0.0

# transform UV coordinate for calculation
trans_uv = src_uvlist[0].copy()
src_uvlist_2d = [suv - trans_uv for suv in src_uvlist]
uv = src_uvlist_2d[1].copy()
uv_rot_mat = Matrix.Rotation(atan2(uv.y, uv.x), 2, 'Z')
src_uvlist_2d = [uv_rot_mat * suv for suv in src_uvlist_2d]

# calculate destination UV coordinate
dest_uvlist_2d = []
ov = src_vlist_2d[0].copy()
ouv = src_uvlist_2d[0].copy()
r = (src_uvlist_2d[1].x - src_uvlist_2d[0].x) / (src_vlist_2d[1].x - src_vlist_2d[0].x)
for sv, suv, dv in zip(src_vlist_2d, src_uvlist_2d, dest_vlist_2d):
    u = suv.x + (dv.x - sv.x) * r
    w = suv.y + (dv.y - sv.y) * r
    dest_uvlist_2d.append(Vector((u, w)))

# reverse transform
dest_uvlist_2d = [uv_rot_mat.transposed() * duv for duv in dest_uvlist_2d]
dest_uvlist_2d = [duv + trans_uv for duv in dest_uvlist_2d]

Thanks,

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.