UVの傾きを計算して水平・垂直にする!! part2




前回の「UVの傾きを計算して水平・垂直にする!! part1」の続き、今度はプログラムに落とし込んでいきます!

選択の取得

まずは、選択の取得です。今回は2つのUVを選択してもらい処理を開始したいので、「filterExpand」を使って取得します。選択がない場合、2つのUV選択でない場合は、処理を続行しないようにしましょう。

import math
from maya import cmds

def main():
	uvs = cmds.filterExpand(sm=35)
	if not uvs or len(uvs) != 2:
		return False

UVの座標を取得

UVの座標を取得するには、「polyEditUV」をクエリーモードで実行すればOKです!それぞれ変数「pointA」「pointB」に代入します。

import math
from maya import cmds

def main():
	uvs = cmds.filterExpand(sm=35)
	if not uvs or len(uvs) != 2:
		return False
		
	pointA = cmds.polyEditUV(uvs[0], q=True)
	pointB = cmds.polyEditUV(uvs[1], q=True)

2点のベクトルを求める

取得した座標を元に、2点のベクトルを求めていきます。計算は終点の座標から始点の座標を引き算するだけですが、ちょっと問題があります。

filterExpandを使って取得したコンポーネントのリストは、インデックスが若い順番になってしまいます。。。っということは、、、

どちらの向きでベクトルができるかわからなくなってしまいます、、、後々の計算を簡単にを楽にするために、「-90°~90°」の範囲に制限して計算を行いたいと思いました。

コレをやるには、「Uの座標が大きい点を終点」っとしてすることで可能になります。画像にすると、このようになります。

これがどのように役立つかは、後ほどわかります!(`・ω・´)ゞ

import math
from maya import cmds

def main():
	uvs = cmds.filterExpand(sm=35)
	if not uvs or len(uvs) != 2:
		return False
		
	pointA = cmds.polyEditUV(uvs[0], q=True)
	pointB = cmds.polyEditUV(uvs[1], q=True)
	
	if pointA[0] >= pointB[0]:
		u = pointA[0] - pointB[0]
		v = pointA[1] - pointB[1]
	else:
		u = pointB[0] - pointA[0]
		v = pointB[1] - pointA[1]

角度を求める

前回の記事で考えたように、「atan2」を使ってやっていきたいと思います。厳密には(-90°~90°)に制限しているので「atan」でいいのですが、0の割り算の対応が面倒なので「atan2」にしました。

import math
from maya import cmds

def main():
	uvs = cmds.filterExpand(sm=35)
	if not uvs or len(uvs) != 2:
		return False
		
	pointA = cmds.polyEditUV(uvs[0], q=True)
	pointB = cmds.polyEditUV(uvs[1], q=True)
	
	if pointA[0] >= pointB[0]:
		u = pointA[0] - pointB[0]
		v = pointA[1] - pointB[1]
	else:
		u = pointB[0] - pointA[0]
		v = pointB[1] - pointA[1]
		
	angle = math.degrees(math.atan2(v, u))#(1)

atan2の角度は、「ラジアル」と言われる単位で返って来るので、馴染みのある「度」に変換して、変数「angle」に代入します(1)。

水平・垂直にする角度を求める

UVの傾きがわかったところで、UVを水平にするのか、垂直にするのか考える必要があります。

そこで、今回は、「45°」「-45°」を境目に水平か、垂直にするか決めたいと思います。コレをシンプルにやるために、先程「-90°~90°」の範囲に制限しました!

import math
from maya import cmds

def main():
	uvs = cmds.filterExpand(sm=35)
	if not uvs or len(uvs) != 2:
		return False
		
	pointA = cmds.polyEditUV(uvs[0], q=True)
	pointB = cmds.polyEditUV(uvs[1], q=True)
	
	if pointA[0] >= pointB[0]:
		u = pointA[0] - pointB[0]
		v = pointA[1] - pointB[1]
	else:
		u = pointB[0] - pointA[0]
		v = pointB[1] - pointA[1]
		
	angle = math.degrees(math.atan2(v, u))
	
	if angle > -45 and angle < 45:#(1)
		angle = - angle
		
	elif angle > 45 and angle < 90:#(2)
		angle = 90 - angle
		
	elif angle < -45 and angle > -90:#(3)
		angle = 90 + angle
		angle = -angle

傾きが「-45°~45°」の場合は、傾きの逆値になるように変数「angle」を補正します。傾きが30°なら-30°回転することで水平になる!っということです(1)。

傾きが「45°~89.999999°」の場合は、「90°」から傾きの角度を引き算して、三角形の残りの角度を求めます(2)。

三角形の内角の和は「180°」ですね!この三角形は必ず直角三角形になるので、「180°-90°」は毎回計算する必要がないので、略して「90°-傾き」としました。

「-45°~-89.999999°」の場合は、「90°」に傾きを足し算して、逆値にします(3)。

UVシェルの取得

傾きを直したいのはUVのシェルになりますが、選択してもらったのは2点のUVだけです。なので、この2点のUVをシェルに変更し、回転させるUVを見つけておきます。

コチラについては、以前の「選択したコンポーネントのShellを取得する!!」をご覧ください。

import math
from maya import cmds

def main():
	uvs = cmds.filterExpand(sm=35)
	if not uvs or len(uvs) != 2:
		return False
		
	pointA = cmds.polyEditUV(uvs[0], q=True)
	pointB = cmds.polyEditUV(uvs[1], q=True)
	
	if pointA[0] >= pointB[0]:
		u = pointA[0] - pointB[0]
		v = pointA[1] - pointB[1]
	else:
		u = pointB[0] - pointA[0]
		v = pointB[1] - pointA[1]
		
	angle = math.degrees(math.atan2(v, u))
	
	if angle > -45 and angle < 45:
		angle = - angle
		
	elif angle > 45 and angle < 90:
		angle = 90 - angle
		
	elif angle < -45 and angle > -90:
		angle = 90 + angle
		angle = -angle
		
	cmds.polySelectConstraint(mode=2, shell=True)
	cmds.polySelectConstraint(bo=0, mode=0, shell=False)
	shell = cmds.ls(sl=True, fl=True)

回転の起点を求める

始点か、終点を中心に回転してもいいのですが、今回はUVシェルのBoundingBoxのセンターで回転させてたいと思います。

import math
from maya import cmds

def main():
	uvs = cmds.filterExpand(sm=35)
	if not uvs or len(uvs) != 2:
		return False
		
	pointA = cmds.polyEditUV(uvs[0], q=True)
	pointB = cmds.polyEditUV(uvs[1], q=True)
	
	if pointA[0] >= pointB[0]:
		u = pointA[0] - pointB[0]
		v = pointA[1] - pointB[1]
	else:
		u = pointB[0] - pointA[0]
		v = pointB[1] - pointA[1]
		
	angle = math.degrees(math.atan2(v, u))
	
	if angle &gt; -45 and angle &lt; 45:
		angle = - angle
		
	elif angle &gt; 45 and angle &lt; 90:
		angle = 90 - angle
		
	elif angle &lt; -45 and angle &gt; -90:
		angle = 90 + angle
		angle = -angle
		
	cmds.polySelectConstraint(mode=2, shell=True)
	cmds.polySelectConstraint(bo=0, mode=0, shell=False)
	shell = cmds.ls(sl=True, fl=True)
	
	boudingBox = cmds.polyEvaluate(bc2=True)#(1)
	centerU = (boudingBox[0][0] + boudingBox[0][1]) / 2
	centerV = (boudingBox[1][0] + boudingBox[1][1]) / 2#(2)

UVのシェルを取得するために、Maya上で選択が変わっている状態になっているので「polyEvaluate」を使えば、UVの最小値、最大値を簡単に取得することができます(1)。

それぞれ最小値と最大値を足し算し、2で割ることで、UVシェルのセンターを取得することができます(2)。

傾きを修正する

import math
from maya import cmds

def main():
	uvs = cmds.filterExpand(sm=35)
	if not uvs or len(uvs) != 2:
		return False
		
	pointA = cmds.polyEditUV(uvs[0], q=True)
	pointB = cmds.polyEditUV(uvs[1], q=True)
	
	if pointA[0] >= pointB[0]:
		u = pointA[0] - pointB[0]
		v = pointA[1] - pointB[1]
	else:
		u = pointB[0] - pointA[0]
		v = pointB[1] - pointA[1]
		
	angle = math.degrees(math.atan2(v, u))
	
	if angle > -45 and angle < 45:
		angle = - angle
		
	elif angle > 45 and angle < 90:
		angle = 90 - angle
		
	elif angle < -45 and angle > -90:
		angle = 90 + angle
		angle = -angle
		
	cmds.polySelectConstraint(mode=2, shell=True)
	cmds.polySelectConstraint(bo=0, mode=0, shell=False)
	shell = cmds.ls(sl=True, fl=True)
	
	boudingBox = cmds.polyEvaluate(bc2=True)
	centerU = (boudingBox[0][0] + boudingBox[0][1]) / 2
	centerV = (boudingBox[1][0] + boudingBox[1][1]) / 2
	
	cmds.polyEditUV(angle=angle, pivotU=centerU, pivotV=centerV)#(1)
	cmds.select(uvs)#(2)

最後に計算して求めた角度と、UVのセンターを指定して回転させて傾きを修正します(1)。

このまま終わってしまうとUVシェルが選択された状態になってしまうので、もともと選択されていたUVに選択を戻して終わりです(2)。


あれこれ色々やりましたが、コード自体は40行ほどで思ったよりシンプルになりました。これでキッチリUVの傾きを調整できるので、几帳面な人にも、めんどくさがり屋の人にもモッテコイなのではないでしょうか!?(*´ω`*)

この記事がイイネ!っと思ったら、ぜひSNSで拡散お願い致します!