Maya-UE xgen-UE 毛发导入UE流程整理

news2025/1/24 14:37:06

首先声明:maya建议用2022版本及一下,因为要用到Python 2 ,Maya2023以后默认是Python3不再支持Python2;

第一步:Xgen做好的毛发转成交互式Groom
在这里插入图片描述
第二步:导出刚生成的交互式Groom缓存,需要设置一下当前帧,和写入宽度;到这里其实就可以直接导入到UE了,为了后面能做多颜色毛发和渐变毛发可以继续看,如果不需要,到这一步就可以直接打开UE导入了,按照后面的流程导入UE就可以了!
在这里插入图片描述
在这里插入图片描述

第三步:导入刚刚导出的缓存文件,导入后会根据毛发数量自动分组;
在这里插入图片描述
在这里插入图片描述
第四步:利用官方文档的Python脚本分别重新导出这三个分好组的缓存文件,这一步的目的是为了让缓存文件拥有UV,方便进去UE后根据需求继续调整(举例做渐变毛发和多颜色毛发);可以直接复制,有几个代码需要修改,看说明;

from maya import cmds
from maya import OpenMaya
import os


def create_root_uv_attribute(curves_group, mesh_node, uv_set='map1'):
    '''
    Create "groom_root_uv" attribute on group of curves.
    '''

    # check curves group
    if not cmds.objExists(curves_group):
        raise RuntimeError('Group not found: "{}"'.format(curves_group))

    # get curves in group
    curve_shapes = cmds.listRelatives(curves_group, shapes=True, noIntermediate=True)
    curve_shapes = cmds.ls(curve_shapes, type='nurbsCurve')
    if not curve_shapes:
        raise RuntimeError('Invalid curves group. No nurbs-curves found in group.')
    else:
        print "found curves"
        print curve_shapes

    # get curve roots
    points = list()
    for curve_shape in curve_shapes:
        point = cmds.pointPosition('{}.cv[0]'.format(curve_shape), world=True)
        points.append(point)

    # get uvs
    values = list()
    uvs = find_closest_uv_point(points, mesh_node, uv_set=uv_set)
    for u, v in uvs:
        values.append([u, v, 0])
        #print (str(u) + " , " + str(v)  )

    # create attribute
    name = 'groom_root_uv'
    cmds.addAttr(curves_group, ln=name, dt='vectorArray')
    cmds.addAttr(curves_group, ln='{}_AbcGeomScope'.format(name), dt='string')
    cmds.addAttr(curves_group, ln='{}_AbcType'.format(name), dt='string')

    cmds.setAttr('{}.{}'.format(curves_group, name), len(values), *values, type='vectorArray')
    cmds.setAttr('{}.{}_AbcGeomScope'.format(curves_group, name), 'uni', type='string')
    cmds.setAttr('{}.{}_AbcType'.format(curves_group, name), 'vector2', type='string')

    return uvs

def find_closest_uv_point(points, mesh_node, uv_set='map1'):
    '''
    Find mesh UV-coordinates at given points.
    '''

    # check mesh
    if not cmds.objExists(mesh_node):
        raise RuntimeError('Node not found: "{}"'.format(mesh_node))

    # check uv_set
    uv_sets = cmds.polyUVSet(mesh_node, q=True, allUVSets=True)
    if uv_set not in uv_sets:
        raise RuntimeError('Invalid uv_set provided: "{}"'.format(uv_set))

    # get mesh as dag-path
    selection_list = OpenMaya.MSelectionList()
    selection_list.add(mesh_node)

    mesh_dagpath = OpenMaya.MDagPath()
    selection_list.getDagPath(0, mesh_dagpath)
    mesh_dagpath.extendToShape()

    # get mesh function set
    fn_mesh = OpenMaya.MFnMesh(mesh_dagpath)

    uvs = list()
    for i in range(len(points)):

        script_util = OpenMaya.MScriptUtil()
        script_util.createFromDouble(0.0, 0.0)
        uv_point = script_util.asFloat2Ptr()

        point = OpenMaya.MPoint(*points[i])
        fn_mesh.getUVAtPoint(point, uv_point, OpenMaya.MSpace.kWorld, uv_set)

        u = OpenMaya.MScriptUtil.getFloat2ArrayItem(uv_point, 0, 0)
        v = OpenMaya.MScriptUtil.getFloat2ArrayItem(uv_point, 0, 1)

        uvs.append((u, v))

    return uvs

def abc_export(filepath, node=None, start_frame=1, end_frame=1, data_format='otawa', uv_write=True):
    
    job_command = '-frameRange {} {} '.format(start_frame, end_frame)
    job_command += '-dataFormat {} '.format(data_format)
    
    job_command += '-attr groom_root_uv '

    if uv_write:
        job_command += '-uvWrite '
    
    job_command += '-root {} '.format(node)   
    
    job_command += '-file {} '.format(filepath) 
    
    cmds.AbcExport(verbose=True, j=job_command)
    
    


def main():
    
    export_directory = 'D:/Dev/Ref'
    hair_file = os.path.join(export_directory, 'hair_export.abc')
    curve_top_group= 'description1|SplineGrp0'
    uv_mesh='pPlane1'
    
    create_root_uv_attribute( curve_top_group , uv_mesh)
    abc_export(hair_file, curve_top_group)
    
main()


在这里插入图片描述
第五步:由于是分别导出的3个文件,因为三个分别导入UE有些麻烦也没必要,需要重新整合一下;重新开一个新的maya文件,把3个缓存文件重新导入到新的maya里面,再次整体导出一个缓存文件;这里需要添加一个groom_root_UV(说明 :groom_root_uv属性为每根头发指定它所附加到的基础网格uv。该属性是可选的,如果未指定,将使用球形贴图在引擎中自动生成一个根UV)
在这里插入图片描述
第六步:导入UE,需要设置一下项目设置和插件;
在这里插入图片描述
在这里插入图片描述
然后导入窗口的旋转设置一下;
在这里插入图片描述
这里可以设置一下基础属性;
在这里插入图片描述
这里可以开启物理模拟;
在这里插入图片描述可以创建绑定;这样就可以替换默认的头发了,也可以通道添加组件添加到骨骼模型上;
在这里插入图片描述
打开角色蓝图,就可以替换之前的模型资产和材质了;
在这里插入图片描述
材质球设置:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里可以通过绘画贴图来实现不同颜色的发色;

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1347062.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python开源项目月排行 2023年12月

Python 趋势月报,按月浏览往期 GitHub,Gitee 等最热门的Python开源项目,入选的项目主要参考GitHub Trending,部分参考了Gitee和其他。排名不分先后,都是当前月份内相对热门的项目。 入选公式=70%GitHub Trending20%Gitee10%其他 …

UCi数据集处理技巧记录

如何起步使用UCI数据集 这里记录一下如何把带分号的数据变成经常使用的csv形式。这里使用wine的例子 https://archive.ics.uci.edu/dataset/186/winequality 原始数据 Wine UCI数据操作 这种带分号的使用python的不好阅读,可以尝试以下步骤: 转变为t…

c# listbox 添加图标和文字

给listbox 添加 DrawItem 事件 private void listBox1_DrawItem(object sender, DrawItemEventArgs e){int index e.Index;//获取当前要进行绘制的行的序号,从0开始。Graphics g e.Graphics;//获取Graphics对象。Rectangle bound e.Bounds;//获取当前要绘制的行的…

ppp会话建立的第二阶段:ppp认证

ppp认证的两种协议: pap 密码认证协议:是一种简单的明文认证,使用两次握手建立身份验证。如果碰到动态攻击,pap认证不会断开。一旦pap认证通过,就不会断开chap 挑战握手验证协议:通过三次握手的方式进行MD…

C/C++ 函数的默认参数

下面介绍一项新内容 - 默认参数。 默认参数指的是当函数调用中省略了实参时自动使用的一个值。 例如,如果将 void wow (int n)设置成n 有默认值为1,则函数调用 wow()相当于 wow(1)这极大地提高了使用函数的灵活性。 假设有一个名为left()的函数&#xff…

[Verilog] 加法器实现

1. 4位的加法器 先来一个最基本的的Verilog加法器 设计代码 module adder_4bit (input [3:0] a, b, output [3:0] sum, output carry);assign

arkts中@Watch监听的使用

概述 Watch用于监听状态变量的变化,当状态变量变化时,Watch的回调方法将被调用。Watch在ArkUI框架内部判断数值有无更新使用的是严格相等(),遵循严格相等规范。当在严格相等为false的情况下,就会触发Watch的…

2024年【安全员-A证】考试内容及安全员-A证最新解析

题库来源:安全生产模拟考试一点通公众号小程序 安全员-A证考试内容参考答案及安全员-A证考试试题解析是安全生产模拟考试一点通题库老师及安全员-A证操作证已考过的学员汇总,相对有效帮助安全员-A证最新解析学员顺利通过考试。 1、【多选题】下列关于门…

Python序列之集合

系列文章目录 Python序列之列表Python序列之元组Python序列之字典Python序列之集合(本篇文章) Python序列之集合 系列文章目录前言一、集合是什么?二、集合的操作1.集合的创建(1)使用{}创建(2)…

全渠道客服系统推荐:选型指南与最佳实践分享

售后服务是影响客户满意度的最直接的因素。有些企业不注重产品的售后服务,不仅是对客户的伤害,更是对企业品牌的损害。所以,做好售后服务对于企业来讲至关重要。 企业谈到做好售后服务,少不了一款好用的客服系统工具。其中&#…

9年900亿:印钞机Tether想搞大模型

作者:Daniel KuhnConsensus Magazine 编译:秦晋 碳链价值 在经历有望盈利45亿美元辉煌的一年之后,这位新晋升的Tether首席执行官正寻求实现公司投资的多元化。 加密货币行业受过教育或具有影响力的精英们的「明智看法」是,世界上最…

【零基础入门VUE】VueJS - 模板

✍面向读者:所有人 ✍所属专栏:零基础入门VUE专栏https://blog.csdn.net/arthas777/category_12537076.html 我们在前面的章节中学习了如何在屏幕上以文本内容的形式输出。在本章中,我们将学习如何在屏幕上以 HTML 模板的形式获取输出。 为了…

Generalized Focal Loss V1论文解读

摘要 单级检测器基本上将物体检测表述为密集分类和定位(即边界框回归)。分类通常通过Focal Loss进行优化,而边界框的定位通常根据Dirac delta分布进行学习。单级检测器的最新趋势是引入一个单独的预测分支来估计定位质量,预测质量…

华清远见作业第十六天

思维导图: 双向循环链表头插入: 代码: Doublelist insert_head(Doublelist head,datatype element) {//创建新节点sDoublelist screate_node();if(NULLs){return head;}s->dataelement;//数据存储//判断链表是否为空if(NULLhead){heads;…

CCSK认证:开启云安全领域的黄金大门

🌟你是否对云安全领域充满热情?是否希望提升自己在云安全领域的专业性和竞争力?CCSK认证是你的不二之选! 🔥CCSK简介: CCSK是国际云安全联盟(Cloud Security Alliance,CSA&#xff…

OCP NVME SSD规范解读-2.复位与控制器配置要求-part2

Maximum Data Transfer Size (MDTS):设备应支持至少256KB的最大数据传输大小。 CSTS.CFS Reporting: 设备固件应支持报告CSTS.CFS(Controller Status and Capabilities Field in the Status Register)。 Queue Depths: 每个提交队列的SQ最小…

ESP32入门七(中断)

中断用于处理在程序正常执行期间通过外部事件或者响应软件指令触发时发生的事件。比如,在一段呼吸灯的代码中,正常运行时的结果为LED从暗到亮,再从亮到暗持续地运行。我们可以通过一个中断来控制呼吸灯的运行和停止。使用中断功能&#xff0c…

Linux操作系统( YUM软件仓库技术 )

镜像文件的回环挂载(把iso镜像文件释放成系统安装光盘)foundation0上操作 回环挂载的用法: du -sh 对象名 //估算文件(一切对象皆文件)大小 !$ //上一条命令的最后一个参数 新创建的挂载点目录是空白目录 挂载&#xf…

移动端开发框架mui代码在安卓模拟器上运行(HbuilderX连接到模拟器)

开发工具 HBuilder X 3.8.12.20230817 注意:开发工具尽量用最新的或较新的。太旧的版本在开发调试过程中可能会出现莫名其妙的问题。 1、电脑下载安装安卓模拟器 我这里使用的是 夜神模拟器 ,也可以选择其他安卓模拟器 夜神模拟器官网:夜神安…

Python教程(19)——python异常处理

异常处理 什么是异常异常处理方式try-except语句捕获异常类型 相关的异常类型 什么是异常 在计算机编程中,异常(Exception)是指在程序执行过程中发生的错误或异常情况。当出现异常时,程序无法正常继续执行,因此需要采…