import maya.cmds as cmds
import maya.api.OpenMaya as om
# 선택된 오브젝트 가져오기
sel = cmds.ls(sl=True, dag=True, shapes=True)
if not sel:
cmds.warning("오브젝트를 선택하세요.")
else:
obj = sel[0]
dag_path = om.MSelectionList().add(obj).getDagPath(0)
mesh = om.MFnMesh(dag_path)
faces_to_select = []
threshold = 0.05 # Y축과 평행한 정도 (값이 작을수록 더 정확함)
for i in range(mesh.numPolygons):
normal = mesh.getPolygonNormal(i, om.MSpace.kWorld)
# Y축 방향 벡터와의 내적 검사
# Y축과 평행한 면은 normal.y ≈ 0
if abs(normal.y) < threshold:
faces_to_select.append(f"{obj}.f[{i}]")
if faces_to_select:
cmds.select(faces_to_select, r=True)
print(f"Y축에 평행한 면 {len(faces_to_select)}개 선택됨.")
else:
cmds.warning("Y축에 평행한 면을 찾지 못했습니다.")
실행하면 이렇게 옆면만 선택을 해준다.
threshold 값이 0.05면 거의 수직인 면만 선택이 되는데 0.1을 해주면 약간 틀어진 면도 수직이니까 선택을 하게 된다. 응용하면 0.4~0.5정도로 해주면 기울어진면도 선택이 되겠지만 이것은 자칫 내가 의도치 않은 면까지 선택이 될 수 있으므로 여러번 테스트가 필요할 듯 하다.
import maya.cmds as cmds
import maya.api.OpenMaya as om
# 선택된 항목 가져오기
sel = cmds.ls(sl=True)
if len(sel) < 2:
cmds.warning("오브젝트와 셰이더를 모두 선택하세요. (오브젝트 먼저, 셰이더 나중)")
else:
obj = sel[0]
shader = sel[-1]
# 셰이딩 그룹(SG) 찾기
sg_nodes = cmds.listConnections(shader, type='shadingEngine')
if not sg_nodes:
# 없으면 새로 생성
sg_nodes = [cmds.sets(renderable=True, noSurfaceShader=True, empty=True, name=f"{shader}SG")]
cmds.connectAttr(f"{shader}.outColor", f"{sg_nodes[0]}.surfaceShader", force=True)
print(f"'{shader}'용 셰이딩그룹 '{sg_nodes[0]}' 새로 생성됨.")
sg = sg_nodes[0]
# 메시 접근
shapes = cmds.listRelatives(obj, shapes=True, fullPath=True)
if not shapes:
cmds.warning("선택한 오브젝트에 메시가 없습니다.")
else:
dag_path = om.MSelectionList().add(shapes[0]).getDagPath(0)
mesh = om.MFnMesh(dag_path)
faces_to_select = []
threshold = 0.05 # Y축 평행 판정 기준
for i in range(mesh.numPolygons):
normal = mesh.getPolygonNormal(i, om.MSpace.kWorld)
if abs(normal.y) < threshold:
faces_to_select.append(f"{obj}.f[{i}]")
if faces_to_select:
cmds.select(faces_to_select, r=True)
cmds.sets(faces_to_select, e=True, forceElement=sg)
print(f"{len(faces_to_select)}개의 Y축 평행 면에 '{shader}' 셰이더 적용 완료.")
else:
cmds.warning("Y축에 평행한 면을 찾지 못했습니다.")
오브젝트를 선택하고 셰이더를 선택후 실행시키면
자동으로 수직면을 선택해서 해당 셰이더를 적용시켜준다
여기서 스크립트 더 발전 시켜서 여러개의 오브젝트를 동시에 수행하도록 할 수 있다
여러 오브젝트를 선택하고 마지막에 셰이더를 선택한 후 스크립트를 실행하면
여러개의 오브젝트를 일괄적으로 자동으로 처리할 수 있다.
import maya.cmds as cmds
import maya.api.OpenMaya as om
# ======================
# 선택 순서:
# ① 오브젝트 여러 개 선택
# ② 적용할 셰이더 마지막에 선택
# ======================
sel = cmds.ls(sl=True)
if len(sel) < 2:
cmds.warning("오브젝트와 셰이더를 모두 선택하세요. (순서: 오브젝트들 → 셰이더)")
else:
shader = sel[-1] # 마지막 선택 = 셰이더
objects = sel[:-1] # 나머지 = 대상 오브젝트들
# 셰이더에 연결된 쉐이딩그룹 찾기
sg_list = cmds.listConnections(shader, type="shadingEngine") or []
if not sg_list:
# 쉐이딩그룹이 없으면 새로 생성
shading_group = cmds.sets(renderable=True, noSurfaceShader=True, empty=True, name=f"{shader}SG")
cmds.connectAttr(f"{shader}.outColor", f"{shading_group}.surfaceShader", f=True)
print(f"'{shader}'에 새 쉐이딩그룹 '{shading_group}' 생성 및 연결 완료.")
else:
shading_group = sg_list[0]
print(f"적용할 쉐이딩그룹: {shading_group}")
threshold = 0.1 # Y축 평행 허용치
all_faces = [] # 전체 선택용 리스트
for obj in objects:
# 메시 확인
shapes = cmds.listRelatives(obj, s=True, ni=True) or []
if not shapes:
print(f"'{obj}'은(는) 메시 오브젝트가 아닙니다. 건너뜀.")
continue
# 메시 데이터 접근
dag = om.MSelectionList()
dag.add(shapes[0])
mesh = om.MFnMesh(dag.getDagPath(0))
# Y축 평행 면 찾기
faces = [
f"{obj}.f[{i}]"
for i in range(mesh.numPolygons)
if abs(mesh.getPolygonNormal(i, om.MSpace.kWorld).y) < threshold
]
if faces:
all_faces.extend(faces)
print(f"{obj}에서 {len(faces)}개 면 선택됨.")
else:
print(f"{obj}에서 Y축 평행 면 없음.")
# 면이 하나라도 있으면 셰이더 적용
if all_faces:
cmds.select(all_faces, r=True)
cmds.hyperShade(assign=shading_group)
print(f"\n✅ 총 {len(all_faces)}개 면에 '{shader}' 셰이더 적용 완료!")
else:
cmds.warning("Y축 평행한 면을 찾지 못했습니다.")
그런데 너무 편한것만 찾으면 결국 그에 대한 반대작용도 있기 마련. 스캔 데이터처럼 너무 복잡한 메쉬 구조로 된 오브젝트를 여러개 일괄 처리하고자 이런 스크립트를 실행하면 컴퓨터가 다운되거나 마야 프로그램이 다운 될 수도 있다. 그러니 적당히 사용해야할 듯.

0 comments:
댓글 쓰기