精华内容
下载资源
问答
  • Blender 导出的,Unity 上 BlendShape 实现的捏脸工程。 Unity 打开工程即可使用。
  • skull 模型 带blendshape

    2018-09-13 13:09:39
    blendshape的骷髅模型。
  • BlendShape表情镜像

    2018-09-30 16:17:31
    blendshape制作面部表情,需要进行表情镜像。 于是开工,做了一个blendshape表情镜像的小插件。 maya2016、2018测试正常,安装使用说明都在压缩包内。 详情请见:https://www.jianshu.com/p/82e1b963b455
  • 在Maya节点优先级别中(仅对角色绑定而言),BlendShape的默认设置(DeformationOrder为Front of chain)是最高级别的,也就是无论是先制作表情还是先绑定骨骼,都不影响BlendShape的节点优先顺序-BendShape会始终...

    角色表情的制作在Maya中,可以理解为模型点的位移。Maya中对于点的控制有多种方式:Springs(弹性约束),Particles(粒子控制),Weighted

    Deformer(变形权重),Rigid

    Skins(刚直蒙皮),BlendShapeDeformers(融合变形),SmoothSkins(光滑蒙皮)等,常用于角色绑定的为变形权重,刚直蒙皮,融合变形,光滑蒙皮。

    动画师调节角色动作,通常都是对控制器设置动画,然后通过控制器驱动各种变形约束来改变模型的形态。

    BlendShape常用于表情的制作,因为其面板有方便的动画操作滑条,并且支持多个变形过渡。虽然它可调节的幅度不是很大,但辅助骨骼控制,可以制作丰富细微的表情(尤其是皱纹)。以下是BlendShape为基础的角色表情绑定介绍。在Maya节点优先级别中(仅对角色绑定而言),BlendShape的默认设置(DeformationOrder为Front

    of

    chain)是最高级别的,也就是无论是先制作表情还是先绑定骨骼,都不影响BlendShape的节点优先顺序-BendShape会始终位于其他变形器和smoothSkin之前。

    变形器常用于角色身体细节的挤压拉伸,一般是在骨骼绑定smoothSkin之后。

    *通常情况下不需要更改BlendShape的DeformationOrder(变形顺序)。

    将角色的表情部位(通常是头部+颈部)作为单独的一个物体,能简化表情绑定的操作,可以最大限度的节省资源;不过相对的,也就产生了模型接缝。这里主要介绍下模型整体绑定(头部与身体无缝接合)的方法。

    这是从Zbrush中导出的一个人体模型(模型虽然简单,但是布线很漂亮)。

    操作前提:在执行绑定前,一定要将模型的所有操作历史删除,并冻结所有变形信息。

    【名词理解】

    基本物体(base object):受控制的原始模型

    目标物体(target object):基本物体的变形副本。目标物体可以有多个。

    【操作流程】

    1.切割头部。选择人体头部的面,执行提取命令:Mesh->Extract。

    *EditMesh菜单下的KeepFacesTogether一定要勾选上,否则会将所选面全部分离成碎片。

    2.删除模型历史,复制头部(基本物体),移动至一侧。复制出的模型保留了原模型的变形信息,因此千万不要将复制出的模型(目标物体)进行冻结操作,否则会在执行BlendShape后出现异常移动。

    3.改变目标物体的外形,如微笑。操作方法有很多,你可以使用各种变形工具来改变模型,也可以直接移动点,甚至可以导出模型到Zbrush中雕刻,然后再导回Maya。只要记住一点,模型的拓扑千万不能改变,也就是不要对模型的点线面进行增减操作(包括点ID的更改)。

    4.删除目标物体历史。现在可以按顺序选择多个目标物体,最后加选基本物体,执行BlendShpe的融合变形操作。但是,这种常规的做法会限制我们对绑定后角色的表情设置。具体来说,就是你无法在绑定后继续增加用于制作表情的目标物体,除非你愿意增加一堆分离合并的历史节点。

    5.属性连接。一个不错的方法:将其中一个目标物体作为其他目标物体和基本物体连接的桥梁。

    *为了便于说明,我将分离出的基本物体命名为BaseHead,复制出的目标物体命令为TotalCon。

    步骤:(1)先选择TotalCon,然后Shift加选BaseHead,按键盘上的“↓”键,选择物体的形节点,然后打开属性连接器:Window->GeneralEditors->ConnectionEditor

    *如果选择顺序相反,可以点击from->to改变基本物体和目标物体的输入输出关系。

    (2)点击Outputs面板中的outMesh属性,与Inputs面板中的inMesh属性进行连接。此时,基本物体BaseHead将受到目标物体TotalCon的控制,改变目标物体的外形(包括点线面的增减操作),基本物体也将跟着发生改变。

    6.缝合模型。选择基本物体(头部)和身体,执行合并操作:Mesh->Combine,然后缝合临近点:EditMesh->Merge。

    *重要:缝合临近点时不要选择多余的非重合点,否则会造成BlendShape和SmoothSkin的组合动作发生异常;不要删除模型保留的历史信息。

    以下是多选点后的异常现象

    7.关系。以下图示可以很好的说明以上操作的意义-在蒙皮和BlendShape之间建立了一个OutMesh的桥梁。

     

    *此时BaseHead已经失去作用,而TotalCon成为了基本物体,新的目标物体将由复制TotalCon而得;对TotalCon执行BlendShape,其效果将同时作用于保留历史信息的BaseHead。

    8.经过以上操作,SmoothSkin和BlendShape是相互独立的,操作的先后顺序不影响绑定的结果。这里只重点说明BlendShape的部分。

    9.融合变形。按顺序选择多个变形后的目标物体,最后加选基本物体TotalCon,执行融合变形操作:CreateDeformers->BlendShape。

    10.开启BlendShape的控制面板:Window->AnimationEditors->BlendShape,拖动相应滑块,可以看到模型的变化。

    11.完成。执行BlendShape操作后,Maya已将动画信息保存在文件中,即使删除目标物体,表情动画仍然存在。不过为了以后的管理和修改,建议保留目标模型。

    12.一些BlendShape的相关操作。

    (1)勾选Basic面板下的In-between选项,可以参考多个目标物体的变形,对基本物体进行变形引导,如制作一个弯曲的管子,你需要先创建弯曲幅度不大的多个目标物体。

    (2)EditDeformers菜单下的PaintBlendShapeWeightsTool可以绘制基本物体受相应目标物体影响的权重。

    (3)EditDeformers->BlendShape:

    Add:对指定的BlendShape节点增加动画控制,可将新增加的表情动画添加到同一个BlendShape节点。

    Remove:将所选目标物体从基本物体的BlendShape节点中移除动画控制。

    Swap:将所选的两个目标物体在BlendShape节点中的动画控制进行互换。

    BakeTopologyToTargets:当基本物体外形改变后,选择基本物体,执行该操作可以同时改变BlendShape节点下的所有目标物体外形。

    (4)对BlendShape设置动画关键帧,在BlendShape的控制面板中点击相应的Key按钮;

    (5)在对基本物体进行权重绘制时,可以对所选目标物体的权重设置动画关键帧:Brush笔刷属性编辑器中的KeySelectedTargetWeights或者Animate菜单下的SetBlendShapeTargetWeightKeys。

    (6)要使用其他元素控制BlendShape动画,需要在BlendShape的控制面板中点击Select按钮,选中BlendShape节点。如使用一个Nurbs圆环的X轴向移动来控制名称为TotalCon1的表情动画,在属性编辑器中将圆环的translateX和BlendShape中的Weight->TotalCon1参数进行连接。另外,BlendShape的权重值可以是大于1的,不过通常都会造成不正确的变形。

    如果在执行outMesh和InMesh的属性连接前已经完成了模型的骨骼绑定,那只能复制整个蒙皮后的模型-模型应为绑定时的基本姿态,解除锁定(UnLock),然后将整个模型作为目标物体对基本物体执行BlendShape。这是因为基本物体的InMesh属性已经被蒙皮变形所占用,强制连接会丢失蒙皮效果。

    不过如果仍打算使用属性连接的方法,那么可以进行以下操作:

    1.先忽略蒙皮中的模型,将复制并解锁的模型当作基本物体,执行上述的表情绑定操作;

    2.将保留有合并及缝合点历史的模型(InMesh属性已受控制的基本物体)移动回骨骼中心,与蒙皮中的模型重合;

    3.选择该模型与根骨骼,执行SmoothSkin操作:

    4.选择最早蒙皮的模型,然后Shift加选新蒙皮的基本物体(可在Outliner中选择),执行:Skin->EditSmoothSkin->CopySkinWeights,将原先模型的蒙皮权重复制给新的模型;

    5.删除原先绑定的模型。

    在完成模型及贴图之后,我们应该先考虑角色的BlendShape表情绑定(或者为BlendShape预留一个基本物体副本),接着才是骨骼蒙皮。尽管这两者并不冲突,但是合理的操作顺序有助于我们工程的管理和完善。

    展开全文
  • 其他相关:X Tesla:【动捕面捕】——价格划算效果好的解决方案(非常详细)​zhuanlan.zhihu.comX Tesla:【三维角色建模】你是...但是上面视频中的方案可以总结提炼,结合之前制作Blendshape的思路,整理一下。【导...

    其他相关:X Tesla:【动捕面捕】——价格划算效果好的解决方案(非常详细)​zhuanlan.zhihu.comX Tesla:【三维角色建模】你是数学家?艺术家?懒人?还是土豪?​zhuanlan.zhihu.com知乎视频​www.zhihu.com

    上面视频中的演示效果还暂时不能一键click就能实现。

    但是上面视频中的方案可以总结提炼,结合之前制作Blendshape的思路,整理一下。

    【导图】Download A Sample​www.polywink.com

    以下简称:Polywink带157个Blendshape的模型=Louise—— (L)

    Polywink单个Blendshape 模型=Louise_n——(Ln)

    导入的其他模型=Custom——(C)

    一、捏得一样(针对L)

    雕刻模式下Grab托顶点 跟建模模式下Propotional Editing是一样的。

    使用 L 作为雕刻的基础模型,这样即使人头怎么捏,横着捏、竖着捏,blendshape对应 变化的顶点信息 都不会变,毕竟verts和faces都始终相同嘛,还是同一个模型。

    如果是输入进来的其他模型 C 的话,想给C制作Blendshape的话,就把L的形状捏得跟这个外来模型一样。

    当然这种的话,就对美术素养要求比较高了,得捏得像,可以借用三视图来捏。

    如果你是个懒人的话,就需要用到包裹了。

    二、进行Wrap包裹

    【2.1】Blender Shrink Wrap+Boolean(针对 Ln)

    因为对L 使用Shrinkwrap(包裹,位置要求两者差不多重合)和Boolean Modifier(再次精确,取交集)的话,是不成功的,Modifier cannot be applied to a mesh with shape keys。

    对齐两模型的时候,可以Shift 加选两模型,然后Object Align Objects,Shift加选三个轴就可以快速对齐了(或者是用Cursor Shift S)

    如果是单个Ln的话,Modifier Apply 之后,Ln 的顶点和面数会变得跟 C大概一致,如下,顶点数会从5034变成4万多。

    但是这样操作出来的模型会有些小碎片小破面的。

    【2.2】ZWrap Wrap(让L 和 C的顶点和面数保持一致,UV也一致)ZWrap 官方文档​www.russian3dscanner.com

    使用Zwrap 软件进行重新自动拓扑。

    注意从Blender 导出L Obj 的时候,枢轴归到原点(先origin to geometry,然后Shift C cursor回原点,再Shift S selected to cursor),而且只导出所选物体。

    填写以下蓝图,并选中Selected Points节点 在Visual Editor中标记点

    在节点上鼠标右键可以看到相关属性(如模型的顶点面数信息等等)

    官方标记点,注意顺序左右要对应上。(可以开启Sync Views左右L C 模型同步)

    Wrapping 节点选项保持默认。官方标记点

    操作出来的口腔会挤出来,C模型没有,需要Save Geometry 到Blender当中把口腔转一下,选中口腔末端顶点,Ctrl+ “+” Select More 。

    然后定义顶点组,透视挪口腔。

    额,单眼皮 变 双眼皮,可爱 变 恶狠,软件还是有限制的,还是说我不受软件欢迎?

    两者顶点和面数一致后,可在Shape Keys中,Transfer Shape Key。

    先选L的Shapekey,然后鼠标选择L,再Shift加选C,点击下箭头 Transfer Shape Key。

    Tab 切换Edit Mode,选择不同的Shape Key即可切换,而不用在Object Mode中 来回左右拖动值。

    如果要同时更改很多ShapeKey的值的话,鼠标悬浮到后面的值0.000处,然后不要放,向下拉动即可。

    取了一个EyeClose Blendshape ,效果并不理想,那是因为模型顶点顺序全部是错乱的。

    解决办法就是不要导obj文件,而要导x3d文件,这样的话Join as Shapes就管用起效啦。

    可勾选自带插件 Corrective Shape Keys,类似Apply Modifier那样的效果,从混合的Blendshape 值生成一个新模型。

    也可以下载免费的插件Mesh Data Transfer 插件试一下。(只对上面Wrap处理过的同一UV模型起效)https://gumroad.com/l/tOKEh​gumroad.com

    Transfer UV可以将贴图转移到新的模型当中(注意在ViewPort 2D 中预览)

    或者是直接在Wrap中直接对Wrap模型进行标记点,最终到Blender中合成,也就是不用Polywink的模型了。

    另外他还有BlendWrapping,效果看着还不错。

    【2.3】Maya 晶格体包裹+Retarget Blendshape Master插件

    这是一年前当时采用的方案了,效果能差不多出来,但是需要稍微调整。Retarget Blendshape​lesterbanks.comGithub_Retarget Blendshape​github.com

    # Auto create Corrective blendshapes from wrapped geos of a corrective blendshape

    # 1. Set the geomatry with the blendshapes

    # 2. Select all geometries wrapped to that one that has the blendshapes

    # 3. Run the script

    import maya.cmds as cmds

    #import maya.mel as mel

    try:

    if (cmds.window( autoBlendsFromWrappedUI, exists=True)):

    cmds.deleteUI( autoBlendsFromWrappedUI )

    except:

    pass

    autoBlendsFromWrappedUI = cmds.window( title="DD Auto Blendshapes creator from wrapped obj", iconName='Short Name', width=(320), s = 1 )

    a1 = cmds.columnLayout( adjustableColumn=True, width = 320 )

    selected = ""

    a2 = cmds.rowLayout ( numberOfColumns = 2, columnWidth2 = (270, 50), p = a1 )

    ownerTx = cmds.textFieldGrp ( label = 'Blendshapes owner geo', text= "", p = a2 )

    ownerBt = cmds.button ( label = "Set", width = 30, command = "setSelected()", p = a2 )

    def setSelected ():

    global selected

    selected = cmds.ls ( sl = 1 )[0]

    cmds.textFieldGrp ( ownerTx, e = 1, text = selected )

    return selected

    cmds.button( label='Create Blendshapes', command = ( 'ddAutoBlendsFromWrapped()' ), width = 90, p = a1 )

    cmds.showWindow( autoBlendsFromWrappedUI )

    def ddAutoBlendsFromWrapped():

    def suffix ( obj ):

    suf = obj[-4:]

    return suf

    sel = cmds.ls ( sl = True )

    blendsOwner = selected

    selHistory = cmds.listHistory ( blendsOwner )

    findBlend = cmds.ls ( selHistory, type = "blendShape" )

    blendList = cmds.listAttr ( findBlend[0] + ".w", m = 1 )

    for eachSel in sel:

    i = 0

    for eachBlend in blendList:

    i += 300

    cmds.setAttr ( findBlend[0] + '.' + eachBlend, 1)

    newDelta = cmds.duplicate ( eachSel, n = eachSel.replace( suffix(eachSel), "" ) + eachBlend.replace( selected.replace( suffix(selected), "" ), "" ) + "_tgt" )

    cmds.setAttr ( findBlend[0] + '.' + eachBlend, 0)

    cmds.select ( newDelta )

    cmds.move ( i, 0, -75 )

    还有一个Retarget Blendshape mel文件,最终效果差不多,但就是涉及嘴唇的Blendshape不太理想,还需稍微调整。(当时的文件早都不知道跑哪儿了)

    下载解压后:拖拽Mel 文件到场景当中

    在Python 栏中复制以下 并Enter(不是Mel呀)

    import retargetBlendshape.ui

    retargetBlendshape.ui.show()

    3.可以看到有框框了

    选mesh,blendshape即可。

    这个是只能针对同面数,同顶点数目的模型才可以。

    Retarget 完成之后,可以用自带的重命名工具命名这些Blendshape。

    Ctrl+G打组,鼠标中键挪动物体在世界大纲中的位置。(解组)

    三、重新用骨骼绑定并根据骨骼制作Blendshape

    【3.1】DAZ+FACEGEN捏脸+MAYA 插件传施工坊根据DAZ模型的面部骨骼一键生成51个Blendshape(推荐)

    但是Daz比较老旧,而且安装也比较麻烦。传世工坊daz到maya整合工具,为daz人物角色一键Humanik,一键FACS表情,支持苹果手机51个面部表情捕捉数据-传世工坊​daz.lianghuadashi.com

    【3.2】Auto-Rig Pro 插件相关:Auto-Rig Pro 3.41 适配Blender 2.8 以上版本(我的Blender版本是 2.82的)

    Auto-Rig Pro 3.40 适配Blender 旧版本,如2.78,2.79这些旧版本(页面灰色旧旧的那种)

    官方文档:(从安装到导出到UE4,应有尽有)Installation - AutoRigPro Doc documentation​www.lucky3d.fr

    这个很傻瓜式了,跟着教程走,和Mixamo指定身体Marker是一样的。

    面部标记点,比Maya 的 Advanced Skeleton绑定过程要方便很多,效果也特别好,尤其是上下嘴唇部分的骨骼权重。

    如果导出UE4骨骼的话,需要在骨骼Edit Mode下,选中Spline 骨骼,设置Count数量为4。

    【3.3】Manuel Bastion Lab 插件

    另外,可以研究一下ManuelbastionLab插件,也是个捏人软件,Blendshape也是自动生成的。

    跟Daz一样,也是通过JSON 数据来动态变化角色Blendshape的,表情身材肌肉胸大小等等。

    【其他绑骨骼:】有些需要绑定骨骼,先选模型再Shift加选骨骼,Ctrl+P With Automatic Weights,自动权重,这样会自动给模型创建一个Armature Modifier

    Bind To Vertex Groups

    Object=Armature

    Object Data中也会自动创建一个Bone Vertex Group

    可以Weight Paint Mode 刷顶点组,也可以Edit Mode指定顶点组。选中模型 Ctrl Tab 切换到Weight Paint Mode刷权重,红色就是所有顶点可以被骨骼影响,蓝色就是不受影响 。

    R=1

    B=0

    或者是 Ctrl Tab 切换到 Edit Mode中Assign 顶点,注意不要更改Vertex Group的名字,默认是Bone就是Bone,改成其他名字骨骼权重就没有了。(Bone、Bone.001 依次排列)

    Weight就是上图中骨骼的权重。

    骨骼其实就是一个hook modifier,定义一个骨骼怎样控制一些顶点。

    如果不加骨骼切换到Weight Paint Mode的话,就是可以直接绘制顶点组,不需要像Edit Mode中 Assign/Remove了。

    【其他拆表情】

    有表情是一整个脸的,需要分成左右脸表情。定义左右顶点组(左脸右脸),权重为1

    定义中间对称轴Vertex Loops,权重为0.5,左边一点,右边一点

    然后下面Vertex Group 为左或右就可以拆开表情了。

    【搜索Blendshape】

    点击下方的小箭头,可以搜索、按字母排序、正序倒序这样子。

    【其他】转移模型贴图UV

    注意模型大小!有些Scale =1,Scale=100,保持模型大小一致。

    【其他好玩的】让人头模型贴图错乱,单个面单个材质先选Shapekey模型,再加选参考模型

    Join as Shapes

    然后进入Edit Mode当中

    Vertex Blend From Shape

    参考选Shapekey

    然后Blend 值为 -1 即可。

    然后就跟我知乎头像那样差不多了。

    【其他Shading 模式切换】

    有时候Retarget之后,模型表面并不平整,右键Shade Smooth并不管用,就需要进入到Edit Mode中进行相关的编辑了。进入Edit Mode

    Mesh->Shading->Smoothing Faces/Verts/Edges (亦可切换到Flat)

    【其他更改ShapeKeys】可以选Vertex Group 只针对选定的顶点组变形

    或进入Edit Mode中,Blend From Shape进行混合编辑

    PropagatetoShapes,对其他所有Shapekeys都应用当前选中顶点组的位置

    本篇就到这里了,以后有更方便的做法再补充。

    展开全文
  • Unity 工具类 之 BlendShape 捏脸的实现

    千次阅读 2020-01-10 22:46:03
    Unity 工具类 之 BlendShape 捏脸的实现 目录 Unity 工具类 之 BlendShape 捏脸的实现 一、简单介绍 二、实现原理 三、注意事项 四、效果预览 五、实现步骤 六、代码 七、参考工程 一、简单介绍 ...

    Unity 工具类 之 BlendShape 捏脸的实现

     

    目录

    Unity 工具类 之 BlendShape 捏脸的实现

    一、简单介绍

    二、实现原理

    三、注意事项

    四、效果预览

    五、实现步骤

    六、代码

    七、参考工程


     

     

    一、简单介绍

    Blender 是一款开源的跨平台全能三维动画制作软件,提供从建模、动画、材质、渲染、到音频处理、视频剪辑等一系列动画短片制作解决方案。

    在Unity程序开发中,使用 Blender 制作的模型,进行 BlendShap 捏脸的实现;

     

    二、实现原理

    1、通过控制改变 Skinned Mesh Renderer 的 BlendShapes 下的参数数值,来实现捏脸的效果

     

    三、注意事项

    1、Blender 中编辑模式下设置的值是实现好的捏脸效果的关键;

     

    四、效果预览

     

    五、实现步骤

    1、打开Unity,新建一个工程,并且导入模型,添加到场景中,如下图

    2、在场景中,添加几个Slider UI 组件,控制捏脸的数值,如下图

    3、编写脚本,控制BlendShapes 对应数值的变化,把对应脚本挂载到对应组件上,如下图

    4、运行场景,效果如下

     

    六、代码

    1、Singleton

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Singleton<T> : MonoBehaviour
    where T:MonoBehaviour
    {
        private static T m_Instance;
    
        public static T Instance
        {
            get
            {
                return m_Instance;
            }
    
        }
    
        protected virtual void Awake()
        {
            m_Instance = this as T;
        }
    
    }
    

    2、BlendShape

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    
    /// <summary>
    /// 存储索引
    /// </summary>
    public class BlendShape
    {
    
        public int postiveIndex { get; set; }
        public int negativeIndex { get; set; }
    
        public BlendShape(int postiveIndex,int negativeIndex)
        {
            this.postiveIndex = postiveIndex;
            this.negativeIndex = negativeIndex;
        }
    }
    

    3、CharacterCustomization

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.Linq;
    
    public class CharacterCustomization : Singleton<CharacterCustomization>{
    
        public string suffixMin = "Min";
        public string suffixMax = "Max";
        public SkinnedMeshRenderer target;
        SkinnedMeshRenderer skm;
        Mesh mesh;
        Dictionary<string, BlendShape> BlendShapeDatabase = new Dictionary<string, BlendShape>();
    
        private void Start()
        {
            Initialize();
        }
    
       public  void Initialize()
        {
            skm = target;
            mesh = skm.sharedMesh;
            SaveBlendShapeDatabase();
        }
    
        #region 存储数据
        
        void SaveBlendShapeDatabase()
        {
            List<string> BlendShapeNames = Enumerable.Range(0, mesh.blendShapeCount).Select(x => mesh.GetBlendShapeName(x)).ToList();
            for(int i = 0; BlendShapeNames.Count > 0;)
            {
                string noSuffix, altSuffix;
                noSuffix = BlendShapeNames[i].TrimEnd(suffixMax.ToCharArray()).TrimEnd(suffixMin.ToCharArray()).Trim();
                string positiveName = string.Empty;
                string negativeName = string.Empty;
                int postiveIndex = -1;
                int negativeIndex = -1;
                bool exist = false;
    
                //后缀是max
                if (BlendShapeNames[i].EndsWith(suffixMax))
                {
                    positiveName = BlendShapeNames[i];
                    altSuffix = noSuffix + " " + suffixMin;
                    
                    if (BlendShapeNames.Contains(altSuffix))
                        exist = true;
    
                    postiveIndex = mesh.GetBlendShapeIndex(positiveName);
    
                    if (exist)
                    {
                        negativeName = altSuffix;
                        negativeIndex = mesh.GetBlendShapeIndex(negativeName);
                    }
                       
    
                    //后缀是min结尾
                }else if (BlendShapeNames[i].EndsWith(suffixMin))
                    {
                        negativeName = BlendShapeNames[i];
                        altSuffix = noSuffix + " " + suffixMax;
                        
                        if (BlendShapeNames.Contains(altSuffix))
                            exist = true;
    
                        negativeIndex = mesh.GetBlendShapeIndex(negativeName);
    
                        if (exist)
                        {
                            positiveName = altSuffix;
                            postiveIndex = mesh.GetBlendShapeIndex(positiveName);
                        }
    
    
                }
    
                if (BlendShapeDatabase.ContainsKey(noSuffix))
                    Debug.LogError(noSuffix +"已经存在");
    
                BlendShapeDatabase.Add(noSuffix, new BlendShape(postiveIndex, negativeIndex));
    
                //移除操作
                if (positiveName != string.Empty)
                    BlendShapeNames.Remove(positiveName);
                if (negativeName != string.Empty)
                    BlendShapeNames.Remove(negativeName);
            }
    
        }
    
        #endregion
    
        public void ChangeBlendShapeValue(string blendShapeName,float value)
        {
            if (!BlendShapeDatabase.ContainsKey(blendShapeName))
            {
                Debug.LogError(blendShapeName + "不存在");
                return;
            }
    
            BlendShape blendshape = BlendShapeDatabase[blendShapeName];
            value = Mathf.Clamp(value, -100, 100);
            if (value > 0)
            {
                if (blendshape.postiveIndex == -1)
                    return;
                skm.SetBlendShapeWeight(blendshape.postiveIndex, value);
                if (blendshape.negativeIndex == -1)
                    return;
                skm.SetBlendShapeWeight(blendshape.negativeIndex, 0);
            }
            else
            {
                if (blendshape.negativeIndex == -1)
                    return;
                skm.SetBlendShapeWeight(blendshape.negativeIndex, -value);
                if (blendshape.postiveIndex == -1)
                    return;
                skm.SetBlendShapeWeight(blendshape.postiveIndex, 0);
      
           
            }
    
    
    
        }
    
    
        public bool DoesTargetMatchSkm()
        {
            return (target == skm) ? true : false;
        }
    
        public void ClearDatabase()
        {
            BlendShapeDatabase.Clear();
        }
    
        public string[] GetBlendshapeNames()
        {
            return BlendShapeDatabase.Keys.ToArray();
        }
    
        public int GetNumber()
        {
            return BlendShapeDatabase.Count;
        }
    
        public BlendShape GetBlendShape(string name)
        {
            return BlendShapeDatabase[name];
        }
    }
    
    
    

    4、BlendShape

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class BlendShapeSlider : MonoBehaviour {
    
        Slider slider;
        [Header("别加后缀!!!")]
        public string BlendShapeName;
    
        private void Start()
        {
            slider = GetComponent<Slider>();
            slider.onValueChanged.AddListener(value => CharacterCustomization.Instance.ChangeBlendShapeValue(BlendShapeName, value));
        }
    }
    

    5、CharacterCustomizationEditor

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEditor;
    using UnityEngine.UI;
    
    [CustomEditor(typeof(CharacterCustomization))]
    public class CharacterCustomizationEditor : Editor
    {
        int selectIndex;
        Canvas canvas;
    
        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();
            EditorGUILayout.Space();
    
            var characterCustomization = (CharacterCustomization)target;
    
            if(characterCustomization.target == null)
            {
                EditorGUILayout.LabelField("请给target赋值!");
                return;
            }
    
            //是否换了新的skm
            if (!characterCustomization.DoesTargetMatchSkm())   
            {
                characterCustomization.ClearDatabase();
            }
    
            if(characterCustomization.GetNumber() <= 0)
            {
                characterCustomization.Initialize();
            }
            
            string[] blendshapeNames = characterCustomization.GetBlendshapeNames();
    
            if(blendshapeNames.Length <= 0)
            {
                EditorGUILayout.LabelField("taget没有blendshape");
                characterCustomization.ClearDatabase(); 
                return;
            }
    
            EditorGUILayout.LabelField("请创建一个滑动条~", EditorStyles.boldLabel);
    
            selectIndex = EditorGUILayout.Popup("blendShapeName", selectIndex, blendshapeNames);
    
            if (GUILayout.Button("创建滑动条"))
            {
                if(canvas == null)
                {
                    canvas = GameObject.FindObjectOfType<Canvas>();
                }
    
                if(canvas == null)
                {
                    throw new System.Exception("场景中没有canvas ,请创建!");
                    
                }
    
                GameObject sliderGo = Instantiate(Resources.Load("slider", typeof(GameObject))) as GameObject;
    
                var BShapeSlider = sliderGo.GetComponent<BlendShapeSlider>();
                //改名字
                //改父物体
                //大小
                BShapeSlider.BlendShapeName = blendshapeNames[selectIndex];
                BShapeSlider.name = blendshapeNames[selectIndex];
                BShapeSlider.transform.parent = canvas.transform;
                BShapeSlider.GetComponent<RectTransform>().sizeDelta = new Vector2(140f, 25f);
                BShapeSlider.GetComponentInChildren<Text>().text = blendshapeNames[selectIndex];
    
                //获取BlendShape
                BlendShape blendShape = characterCustomization.GetBlendShape(blendshapeNames[selectIndex]);
    
                //获取slider
                Slider slider = sliderGo.GetComponent<Slider>();
    
                if (blendShape.negativeIndex == -1)
                    slider.minValue = 0;
    
                if (blendShape.postiveIndex == -1)
                    slider.maxValue = 0;
    
                slider.value = 0;
    
                Debug.Log(blendshapeNames[selectIndex] + "slider 创建完成!");
            }
    
        }
    
    }
    

     

    七、参考工程

    参考工程,点击下载

    展开全文
  • WingOfStar☆ 的 【Maya】角色表情绑定-BlendShape的使用技巧角色表情的制作在Maya中,可以理解为模型点的位移。Maya中对于点的控制有多种方式:Springs(弹性约束),Particles(粒子控制),WeightedDeformer(变形...

    WingOfStar☆ 的 【Maya】角色表情绑定-BlendShape的使用技巧

    角色表情的制作在Maya中,可以理解为模型点的位移。Maya中对于点的控制有多种方式:Springs(弹性约束),Particles(粒子控制),Weighted

    Deformer(变形权重),Rigid

    Skins(刚直蒙皮),BlendShapeDeformers(融合变形),SmoothSkins(光滑蒙皮)等,常用于角色绑定的为变形权重,刚直蒙皮,融合变形,光滑蒙皮。

    动画师调节角色动作,通常都是对控制器设置动画,然后通过控制器驱动各种变形约束来改变模型的形态。

    BlendShape常用于表情的制作,因为其面板有方便的动画操作滑条,并且支持多个变形过渡。虽然它可调节的幅度不是很大,但辅助骨骼控制,可以制作丰富细微的表情(尤其是皱纹)。以下是BlendShape为基础的角色表情绑定介绍。在Maya节点优先级别中(仅对角色绑定而言),BlendShape的默认设置(DeformationOrder为Front

    of

    chain)是最高级别的,也就是无论是先制作表情还是先绑定骨骼,都不影响BlendShape的节点优先顺序-BendShape会始终位于其他变形器和smoothSkin之前。

    变形器常用于角色身体细节的挤压拉伸,一般是在骨骼绑定smoothSkin之后。

    *通常情况下不需要更改BlendShape的DeformationOrder(变形顺序)。

    将角色的表情部位(通常是头部+颈部)作为单独的一个物体,能简化表情绑定的操作,可以最大限度的节省资源;不过相对的,也就产生了模型接缝。这里主要介绍下模型整体绑定(头部与身体无缝接合)的方法。

    这是从Zbrush中导出的一个人体模型(模型虽然简单,但是布线很漂亮)。

    操作前提:在执行绑定前,一定要将模型的所有操作历史删除,并冻结所有变形信息。

    【名词理解】

    基本物体(base object):受控制的原始模型

    目标物体(target object):基本物体的变形副本。目标物体可以有多个。

    【操作流程】

    1.切割头部。选择人体头部的面,执行提取命令:Mesh->Extract。

    *EditMesh菜单下的KeepFacesTogether一定要勾选上,否则会将所选面全部分离成碎片。

    2.删除模型历史,复制头部(基本物体),移动至一侧。复制出的模型保留了原模型的变形信息,因此千万不要将复制出的模型(目标物体)进行冻结操作,否则会在执行BlendShape后出现异常移动。

    3.改变目标物体的外形,如微笑。操作方法有很多,你可以使用各种变形工具来改变模型,也可以直接移动点,甚至可以导出模型到Zbrush中雕刻,然后再导回Maya。只要记住一点,模型的拓扑千万不能改变,也就是不要对模型的点线面进行增减操作(包括点ID的更改)。

    4.删除目标物体历史。现在可以按顺序选择多个目标物体,最后加选基本物体,执行BlendShpe的融合变形操作。但是,这种常规的做法会限制我们对绑定后角色的表情设置。具体来说,就是你无法在绑定后继续增加用于制作表情的目标物体,除非你愿意增加一堆分离合并的历史节点。

    5.属性连接。一个不错的方法:将其中一个目标物体作为其他目标物体和基本物体连接的桥梁。

    *为了便于说明,我将分离出的基本物体命名为BaseHead,复制出的目标物体命令为TotalCon。

    步骤:(1)先选择TotalCon,然后Shift加选BaseHead,按键盘上的“↓”键,选择物体的形节点,然后打开属性连接器:Window->GeneralEditors->ConnectionEditor

    *如果选择顺序相反,可以点击from->to改变基本物体和目标物体的输入输出关系。

    (2)点击Outputs面板中的outMesh属性,与Inputs面板中的inMesh属性进行连接。此时,基本物体BaseHead将受到目标物体TotalCon的控制,改变目标物体的外形(包括点线面的增减操作),基本物体也将跟着发生改变。

    6.缝合模型。选择基本物体(头部)和身体,执行合并操作:Mesh->Combine,然后缝合临近点:EditMesh->Merge。

    *重要:缝合临近点时不要选择多余的非重合点,否则会造成BlendShape和SmoothSkin的组合动作发生异常;不要删除模型保留的历史信息。

    以下是多选点后的异常现象

    7.关系。以下图示可以很好的说明以上操作的意义-在蒙皮和BlendShape之间建立了一个OutMesh的桥梁。

     

    *此时BaseHead已经失去作用,而TotalCon成为了基本物体,新的目标物体将由复制TotalCon而得;对TotalCon执行BlendShape,其效果将同时作用于保留历史信息的BaseHead。

    8.经过以上操作,SmoothSkin和BlendShape是相互独立的,操作的先后顺序不影响绑定的结果。这里只重点说明BlendShape的部分。

    9.融合变形。按顺序选择多个变形后的目标物体,最后加选基本物体TotalCon,执行融合变形操作:CreateDeformers->BlendShape。

    10.开启BlendShape的控制面板:Window->AnimationEditors->BlendShape,拖动相应滑块,可以看到模型的变化。

    11.完成。执行BlendShape操作后,Maya已将动画信息保存在文件中,即使删除目标物体,表情动画仍然存在。不过为了以后的管理和修改,建议保留目标模型。

    12.一些BlendShape的相关操作。

    (1)勾选Basic面板下的In-between选项,可以参考多个目标物体的变形,对基本物体进行变形引导,如制作一个弯曲的管子,你需要先创建弯曲幅度不大的多个目标物体。

    (2)EditDeformers菜单下的PaintBlendShapeWeightsTool可以绘制基本物体受相应目标物体影响的权重。

    (3)EditDeformers->BlendShape:

    Add:对指定的BlendShape节点增加动画控制,可将新增加的表情动画添加到同一个BlendShape节点。

    Remove:将所选目标物体从基本物体的BlendShape节点中移除动画控制。

    Swap:将所选的两个目标物体在BlendShape节点中的动画控制进行互换。

    BakeTopologyToTargets:当基本物体外形改变后,选择基本物体,执行该操作可以同时改变BlendShape节点下的所有目标物体外形。

    (4)对BlendShape设置动画关键帧,在BlendShape的控制面板中点击相应的Key按钮;

    (5)在对基本物体进行权重绘制时,可以对所选目标物体的权重设置动画关键帧:Brush笔刷属性编辑器中的KeySelectedTargetWeights或者Animate菜单下的SetBlendShapeTargetWeightKeys。

    (6)要使用其他元素控制BlendShape动画,需要在BlendShape的控制面板中点击Select按钮,选中BlendShape节点。如使用一个Nurbs圆环的X轴向移动来控制名称为TotalCon1的表情动画,在属性编辑器中将圆环的translateX和BlendShape中的Weight->TotalCon1参数进行连接。另外,BlendShape的权重值可以是大于1的,不过通常都会造成不正确的变形。

    如果在执行outMesh和InMesh的属性连接前已经完成了模型的骨骼绑定,那只能复制整个蒙皮后的模型-模型应为绑定时的基本姿态,解除锁定(UnLock),然后将整个模型作为目标物体对基本物体执行BlendShape。这是因为基本物体的InMesh属性已经被蒙皮变形所占用,强制连接会丢失蒙皮效果。

    不过如果仍打算使用属性连接的方法,那么可以进行以下操作:

    1.先忽略蒙皮中的模型,将复制并解锁的模型当作基本物体,执行上述的表情绑定操作;

    2.将保留有合并及缝合点历史的模型(InMesh属性已受控制的基本物体)移动回骨骼中心,与蒙皮中的模型重合;

    3.选择该模型与根骨骼,执行SmoothSkin操作:

    4.选择最早蒙皮的模型,然后Shift加选新蒙皮的基本物体(可在Outliner中选择),执行:Skin->EditSmoothSkin->CopySkinWeights,将原先模型的蒙皮权重复制给新的模型;

    5.删除原先绑定的模型。

    在完成模型及贴图之后,我们应该先考虑角色的BlendShape表情绑定(或者为BlendShape预留一个基本物体副本),接着才是骨骼蒙皮。尽管这两者并不冲突,但是合理的操作顺序有助于我们工程的管理和完善。

    展开全文
  • 在表情制作中Blendshape的使用技巧(2010-09-09 20:05:41)转载标签:分类:【Maya教程】表情制作blendshape教程雨恒教育角色表情的制作在Maya中,可以理解为模型点的位移。Maya中对于点的控制有多种方式:Springs...
  • WingOfStar☆ 的 【Maya】角色表情绑定-BlendShape的使用技巧角色表情的制作在Maya中,可以理解为模型点的位移。Maya中对于点的控制有多种方式:Springs(弹性约束),Particles(粒子控制),WeightedDeformer(变形...
  • 张梦摘 要:三维动画制作过程中经常会因为调好的表情不能和人物面部绑定在一起,单独使用Blend Shape来控制人物表情比较麻烦,给后期调动画带来不必要的麻烦,使用曲线控制角色表情绑定使得调动画变得更加便捷,能够...
  • Unity项目捏脸解决方案BlendShape

    千次阅读 2020-08-07 23:12:39
    Unity项目捏脸解决方案BlendShapes引子BlendShapes具体使用代码参考链接 引子 最近公司在开发一个捏脸的SDK,使用的核心功能就是使用Unity的SkinnedMeshRenderer上的BlendShapes来实现的。这个功能在Maya和3ds Max...
  • Maya的形状融合变形器BlendShape是制作面部表情动画的有力武器,它能通过使用一系列的目标形状物体(Target)使基础物体得到非常平顺、高精度的变形效果。它在角色动画的时候非常受用,尤其是在表情的制作,基本上都是...
  • browDownRight, browInnerUp, browOuterUpRight
  • Maya 调整blendshape和skinCluster顺序
  • Unity3D Blend Shape简析

    千次阅读 2020-03-30 13:22:00
    什么是 Blend Shape? 它其实是单个网格变形以实现许多预定义形状和任何数量之间组合的技术,在Maya/3ds Max 中我们称它为变形目标,例如单个网格是默认形状的基本形状(例如无表情的面),并且基本形状的...
  • maya blend shape

    2020-04-30 21:23:06
    参考:https://www.bilibili.com/video/BV1sJ411374p 建立两个模型,一个原始模型,一个表情 ...layer bug 导出fbx的时候有时候会出现shape keys所在的物体缩放不正确的问题 勾选selected objects这个就好,可能是bug把
  • 在Unity项目中,我们可能需要实现3D角色表情的过渡切换,本文介绍了通过BlendShape来实现表情过渡切换的功能。
  • 角色表情Blendshape重定向方法

    千次阅读 2019-01-31 18:16:40
    注: 文章是美术同事写的, 我只是放这里记录一下 问题重点: ...其次,由于两个面部模型布线也不一样,也不能通过Blendshape直接实现变形。 解决办法: (1):首先将案例脸型用晶格变形来匹配我们目标角色...
  • unity3d中的BlendShape混合动画 https://blog.csdn.net/ychl87/article/details/11605339 一.unity3d中加载模型时,网格顶点发生变化的解决办法。 unity3d中mesh网格为三角网格,目前unity3d直接导入模型时,会...
  • BlendShape动画(Maya)导入Unity

    千次阅读 2018-11-05 14:10:19
    一、Maya中创建BlendShape动画 Blend Shape(形状融合变形器)是制作面部表情动画的有力武器,它能通过使用一系列的目标形状物体(Target)使基础物体得到非常平顺、高精度的变形效果。它在角色动画的时候非常受用...
  • 所以我找到的解决方案是:def getBlendShape(shape):'''@param Shape: Name of the shape node.Returns MFnBlendShapeDeformer node or None.'''# Create an MDagPath for our shape node:selList = OpenMaya....
  • blendshape变形器详细解释

    万次阅读 2018-06-03 21:20:16
    表情动画需要细致的调整和多个关键帧的配合,所以如果右上角那个表情控制器的控制不够细致的话可以选择进入动画blendshape编辑器中进一步调整,位置如下 接下来会说明如何制作自定义的混合表情来实现想要的效果~~~
  • 在Unity中实现BlendShape表情和骨骼动画混合的实践 https://zhuanlan.zhihu.com/p/71544395 表情实现机制 一般都是三种中选一种 1 换模型面部贴图,UV动画实现 优点:换贴图的话,如果做得精细,可以表现得内容...
  • Max 中制作 BlendShape 的关键帧动画

    千次阅读 2020-01-08 10:08:12
    在 Max 中制作的 BlendShape 关键帧动画,导出 fbx 由于只有 Face 这个骨骼动画,这个时候如果不设置成对应完整模型的 Human 类型的 sourceAvatar ,就会导致导入的 fbx 查找不到对应的 Face 骨骼。 (2) 由于只导出...
  • 编辑混合变形变形器(Blend Shape

    千次阅读 2018-05-20 10:54:30
    这里先说一下自己蒙皮人物角色时如何处理以及只做自己的表情动画时如何用混合变形只做插值目标“混合变形”(Blend Shape)编辑器为我们提供了可用于场景中所有混合变形变形器的控件。使用“通道盒”(Channel Box)...
  • 1)带BlendShape表情的动作文件播放异常​2)Unreal打包Android项目的报错3)Unreal打包Android项目前,执行SetupAndroid.bat脚本报错4)Addressable打包Post Processing产生冗余5)Addressable资源热更新,提示CRC ...
  • 在blender中用ShapeKey制作了一个几何变形动画...我找到这个网页 https://forum.unity.com/threads/blend-shapes-changing-vertex-normals.632230/ ——虽然没有直接帮助,但是了解到,在导入模型的设置面板里【Blend.
  • Unity Animator BlendShape

    2020-01-04 14:35:33
    (1) Unity中的mecnim和blendshape的冲突问题 http://www.mamicode.com/info-detail-1724372.html mecanim会覆盖blendshape动画 如果blendshape用的代码,解决办法是放在LateUpdate里. ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,222
精华内容 1,288
关键字:

blendshape

友情链接: 万年历.zip