0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MayaAdvent Calendar 2024

Day 12

UDIMのファイルがあるかチェックしたい

Last updated at Posted at 2024-12-13

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

テストシーンで確認すると、とれてそうですね。

image.png

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だけ逃がして実行してみますと

image.png

checkUDIMFiles("file1","map1")
# Result: [1003] # 

検知されました。

改修案

UDIMファイルの連番名の生成がちょっと今回雑なので、
もっと大量のUDIM連番になった場合は対応できないかもしれません。

その辺直さねばかなぁ

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?