MetaFusion/scripts/utils/CreateLOD.py

200 lines
6.4 KiB
Python
Raw Permalink Normal View History

2025-02-07 05:10:30 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import maya.cmds as cmds
from Core import GetMeshes
def create_lod(index):
"""
创建LOD模型
参数:
index (int): LOD级别索引0表示创建所有级别
"""
# 检查并加载Unfold3D插件
if not cmds.pluginInfo("Unfold3D", query=True, loaded=True):
cmds.loadPlugin("Unfold3D")
# 如果索引为0创建所有LOD级别
if index == 0:
for lod in range(1, 8):
create_lod(lod)
return
# 获取当前轴向设置
axis = cmds.upAxis(query=True, axis=True)
axis = "YAxisUp" if axis == "y" else "ZAxisUp"
# 定义网格体列表
meshes = [
"head", "teeth", "saliva", "eyeLeft", "eyeRight",
"eyeshell", "eyelashes", "eyeEdge", "cartilage", "body"
]
# 创建头部组和网格体
head_grp = f"head_lod{index}_grp"
head_mesh = f"head_lod{index}_mesh"
if not cmds.objExists(head_grp):
cmds.group(empty=True, name=head_grp)
if not cmds.objExists(head_mesh):
# 创建LOD网格体
GetMeshes(cml=index)
head_lod = GetMeshes(lod=0)
create_lod = GetMeshes(lod=index)
# 处理每个创建的LOD模型
for c in create_lod:
create = GetMeshes(i=c)
# 跳过索引大于等于50的模型
if c >= 50:
cmds.delete(create)
continue
exist = False
# 检查是否匹配头部LOD模型
for h in head_lod:
if h >= 50:
continue
if any(create.startswith(mesh) for mesh in meshes[:h+1]):
mesh = GetMeshes(m=h)
if cmds.objExists(mesh):
# 处理模型
cmds.parent(create, head_grp)
# 获取UV集
suv = cmds.polyUVSet(mesh, query=True, currentUVSet=True)
tuv = cmds.polyUVSet(create, query=True, currentUVSet=True)
# 检查UV集
if len(suv) != 1:
raise RuntimeError(f"{mesh}: There are multiple uvSet!!!")
if len(tuv) != 1:
raise RuntimeError(f"{create}: There are multiple uvSet!!!")
# 特殊处理eyeshell模型
if create.startswith("eyeshell"):
_process_eyeshell_model(mesh, create, suv[0], tuv[0])
else:
_process_normal_model(mesh, create, suv[0], tuv[0])
exist = True
# 如果模型不存在则删除
if not exist:
cmds.delete(create)
else:
cmds.warning(f"{head_mesh} Existed!!!")
# 处理身体LOD仅适用于LOD0-3
if index < 4:
body_grp = f"body_lod{index}_grp"
body_mesh = f"body_lod{index}_mesh"
if not cmds.objExists(body_grp):
cmds.group(empty=True, name=body_grp)
if not cmds.objExists(body_mesh):
mesh = GetMeshes(m=50)
if cmds.objExists(mesh):
body_index = 50 + index
GetMeshes(cm=body_index)
cmds.parent(body_mesh, body_grp)
# 获取UV集
suv = cmds.polyUVSet(mesh, query=True, currentUVSet=True)
tuv = cmds.polyUVSet(body_mesh, query=True, currentUVSet=True)
# 检查UV集
if len(suv) != 1:
raise RuntimeError(f"{mesh}: There are multiple uvSet!!!")
if len(tuv) != 1:
raise RuntimeError(f"{body_mesh}: There are multiple uvSet!!!")
# 处理身体模型
_process_normal_model(mesh, body_mesh, suv[0], tuv[0])
# 设置显示属性
body_mesh_shape = cmds.listRelatives(body_mesh, shapes=True)
cmds.setAttr(f"{body_mesh_shape[0]}.displayColors", 0)
else:
cmds.warning(f"{body_mesh} Existed!!!")
def _process_eyeshell_model(source, target, source_uv, target_uv):
"""
处理eyeshell模型的特殊UV和属性
"""
# 复制和设置UV
cmds.polyUVSet(source, copy=True, uvSet=source_uv)
cmds.polyUVSet(source, currentUVSet=True, uvSet="uvSet1")
cmds.u3dLayout(
source,
resolution=256,
scale=1,
spacing=0.0029296875,
margin=0.0029296875,
box=[0, 1, 0.5, 1]
)
cmds.polyUVSet(target, copy=True, uvSet=target_uv)
cmds.polyUVSet(target, currentUVSet=True, uvSet="uvSet1")
cmds.u3dLayout(
target,
resolution=256,
scale=1,
spacing=0.0029296875,
margin=0.0029296875,
box=[0, 1, 0.5, 1]
)
# 传输属性
_transfer_attributes(source, target, "uvSet1", "uvSet1")
# 清理UV集
cmds.polyUVSet(source, currentUVSet=True, uvSet=source_uv)
cmds.polyUVSet(source, delete=True, uvSet="uvSet1")
cmds.polyUVSet(target, currentUVSet=True, uvSet=target_uv)
cmds.polyUVSet(target, delete=True, uvSet="uvSet1")
def _process_normal_model(source, target, source_uv, target_uv):
"""
处理普通模型的属性传输
"""
_transfer_attributes(source, target, source_uv, target_uv)
def _transfer_attributes(source, target, source_uv, target_uv):
"""
传输模型属性
"""
# 传输位置、法线和UV
cmds.transferAttributes(
source,
target,
transferPositions=True,
transferNormals=True,
transferUVs=False,
transferColors=False,
sampleSpace=3,
sourceUvSpace=source_uv,
targetUvSpace=target_uv,
searchMethod=3,
flipUVs=False,
colorBorders=True
)
# 传输材质
cmds.transferShadingSets(
source,
target,
sampleSpace=0,
searchMethod=3
)
# 设置边缘和法线
cmds.polySoftEdge(target, angle=180, constructionHistory=True)
cmds.polyNormalPerVertex(target, unFreezeNormal=True)
cmds.delete(target, constructionHistory=True)