UDIM話が続きます。
UDIMは連番になってはいるのですが、
途中が抜けていても特に自己主張がないので
レンダリングしたら あれなんか変だ? ってことがありました。
なので、UVが配置されているエリアにUDIMファイルが存在するか否かを調べてみます。
追加
とりあえず先述の2つの記事の内容を流用すればなんかできそうですが、
- UDIMで使われているUVエリア
この部分は新規に起こす必要がありそうです。
UV座標を総当たりで確認し、小数点以下を切り捨ててUDIMのIDに変換していきます。
ただ、UDIMの範囲が大きくなるとどうなるのかちょっとわからないので、ひとまず狭い範囲だけ対応ということで。
def checkUVRange(target,uvSet):
mesh_dagPath = om.MGlobal.getSelectionListByName(target).getDagPath(0)
shape_Fn = om.MFnMesh(mesh_dagPath)
face_ids = range(0,shape_Fn.numPolygons)
it = om.MItMeshPolygon(mesh_dagPath)
DUIMAreas = []
for index in face_ids:
it.setIndex(index)
try:
uvs = it.getUVs(uvSet)
except:
continue
for uPoint,vPoint in zip(uvs[0],uvs[1]):
uArea = math.floor(uPoint)+1
vArea = math.floor(vPoint)
UDIMArea = str(vArea) + str(uArea)
if UDIMArea not in DUIMAreas:
DUIMAreas.append(UDIMArea)
return DUIMAreas
テストシーンで確認すると、とれてそうですね。
checkUVRange("pPlane1","map1")
# Result: ['12', '03', '11', '02', '13', '01'] #
実装
import maya.api.OpenMaya as om
import maya.cmds as cmds
import os
import pathlib
import re
import math
def getUDIMFileIDs(fileNode):
filePath = cmds.getAttr(fileNode + ".computedFileTextureNamePattern")
fileDirPath = os.path.dirname(filePath) + "/"
fileName = os.path.basename(filePath)
fileNameSample = fileName.replace("<UDIM>","([0-9|\-]{4})")
pathNode = pathlib.Path(fileDirPath).iterdir()
UDIMIDict = {}
for node in pathNode:
if node.is_dir():
continue
elif node.is_file():
ID = re.findall(fileNameSample,node.name) or None
if ID == None:
continue
if ID[0] not in list(UDIMIDict.keys()):
UDIMIDict[int(ID[0])] = fileDirPath + node.name
return UDIMIDict
def checkUVRange(target,uvSet):
mesh_dagPath = om.MGlobal.getSelectionListByName(target).getDagPath(0)
shape_Fn = om.MFnMesh(mesh_dagPath)
face_ids = range(0,shape_Fn.numPolygons)
it = om.MItMeshPolygon(mesh_dagPath)
DUIMAreas = []
for index in face_ids:
it.setIndex(index)
try:
uvs = it.getUVs(uvSet)
except:
continue
for uPoint,vPoint in zip(uvs[0],uvs[1]):
uArea = math.floor(uPoint)+1
vArea = math.floor(vPoint)
UDIMArea = str(vArea) + str(uArea)
if UDIMArea not in DUIMAreas:
DUIMAreas.append(UDIMArea)
DUIMAreas.sort()
return DUIMAreas
def checkUDIMFiles(fileNode,uvSet):
UDIMFileDict = getUDIMFileIDs(fileNode)
history = cmds.listHistory(fileNode,f=True) or []
SGs = cmds.ls(history, type = "shadingEngine") or []
allUDIMIDs = []
for SG in SGs:
targets = cmds.sets(SG,q=True) or []
for target in targets:
UDIMIDs = checkUVRange(target,uvSet)
for UDIMID in UDIMIDs:
udim = 1000 + int(UDIMID)
if udim not in allUDIMIDs:
allUDIMIDs.append(udim)
missingID = list(set(allUDIMIDs) - set(UDIMFileDict.keys()))
return missingID
試しに 1003だけ逃がして実行してみますと
checkUDIMFiles("file1","map1")
# Result: [1003] #
検知されました。
改修案
UDIMファイルの連番名の生成がちょっと今回雑なので、
もっと大量のUDIM連番になった場合は対応できないかもしれません。
その辺直さねばかなぁ