使用 Morph 资源

变形将一个形状无缝转换为另一个形状。使用 Morph 资源在网格之间进行变形。

Kanzi 使用着色器来启用变形。请参阅 着色器 (Shaders)。

在您可以在 Kanzi 中进行网格变形之前,您需要在第三方工具中创建3D模型并将其导入到 Kanzi Studio。

当在第三方工具中创建网格以便在它们之间进行变形时,首先创建基础网格。从基础网格开始,塑造要变形到的网格。在创建网格时,请记住:

  • 所有网格必须都具有相同数量的顶点和组合仪表。

  • 请勿更改网格的拓扑。

添加变形

在您可以将变形添加到 Kanzi Studio 项目之前,需在第三方工具中创建带有变形的3D模型,并将其导出为gltf、glb、fbx或dae格式。

要在您的 Kanzi Studio 项目中添加变形:

  1. 在 Assets 中,单击 Import Assets 并导入使用变形网格的 3D 模型,该模型具有您希望在其间进行变形的变形目标。

    每个变形目标都是变形基础形状的变形版本。

    ../../_images/assets-import-assets1.png

    如果模型包含没有法线的网格,Kanzi Studio 提供生成法线的功能。Kanzi 在光照计算中使用法线。当您不让 Kanzi Studio 生成法线时,网格使用变形基网格的法线。请参阅 使用 morph target normals。

    当 Kanzi Studio 导入变形时,它会创建:

    • 在 Library > Meshes 中,来自 3D 模型的网格和使用导入网格的 Morph 资源。

      ../../_images/library-morph-cube.png
    • 在 Library > Materials and Textures 中,如果您的项目尚不包含此类材质类型,则需要支持变形的材质类型。

      Kanzi Studio 创建使用此材质类型的材质,并将您的变形的基础网格设置为使用这些材质。

      在材质类型中,Kanzi Studio 设置同时激活的变形目标的最大数量,以匹配导入变形中的网格数量。为了优化性能,您可以限制同时激活的变形目标的数量。请参阅 限制同时激活的变形目标的数量。

      ../../_images/library-morph-material-type.png
    • 在 Prefabs 中,一个 Scene 预设包含使用 Morph 和 Mesh 资源的 Model 节点。

      要在 Prefabs 中的 Preview 中显示 Scene 预设的内容,请双击该预设。

      Kanzi Studio 在新的 Preview 选项卡中打开预设,并在 Preview 中显示该预设的内容。

      ../../_images/morph-composition.png
  2. 在 Prefabs 中,选择一个显示 Morph 资源的 Model 节点。在 Morph Target Weights 属性中的 Properties 中,您可以调整 Morph 资源中每个网格的权重。

    通过这种方式,您可以控制 Morph 的形状。

    值越高,Morph 越接近该网格的形状。Kanzi 变形着色器设置基础变形形状的权重,使 Morph Target Weights 的总和为 1。这使得生成形状的比例保持与目标形状一致。

    例如,可以使用关键帧动画来更改变形的形状。请参阅 创建变形权重动画。

    ../../_images/prefabs-main-model.png ../../_images/properties-main-model-adjust-weights.png

将目标添加到 Morph 中

要添加您希望在其间变形的形状,请将网格添加到 Morph。

为了使变形正常工作,仅添加符合以下条件的网格:

  • 由相同的基础网格塑造而成。

  • 具有相同的拓扑结构以及相同数量的顶点和簇。

要将目标添加到 Morph:

  1. 在 Library > Meshes 中,创建或选择一个 Morph 资源。

    ../../_images/library-morph-cube.png
  2. 在 Morph Target Weights 属性中的 Properties:

    1. 单击 Add。在下拉菜单中,选择要添加为 Morph 目标的网格,并调整网格的权重。值越高,Morph 越接近该网格的形状。

      ../../_images/morph-targets-add.png ../../_images/set-morph-targets.png
    2. 重复上一步以添加您要在其间进行变形的所有变形目标。

  3. 在 Library > Materials and Textures > Material Types 中,选择您的变形基网格使用的每个材质类型。在 Properties 的 Preprocessor Definitions 中,将 KANZI_SHADER_MORPH_TARGET_COUNT 设置为您希望 Kanzi 一次激活的变形目标数量。

    如果您使用智能材质,Kanzi 会根据为材质设置的属性自动设置 Preprocessor Definitions。

    当一个变形具有的目标多于 KANZI_SHADER_MORPH_TARGET_COUNT 的值时,Kanzi 会自动选择那些权重最大的变形目标进行激活。

    ../../_images/library-vertex-phong-morph.png ../../_images/properties-morph-target-count-9.png
  4. (可选) 如果您的图形驱动程序不支持您设置的变形目标数量:

    1. 在 Properties 的 Preprocessor Definitions 中,将 KANZI_SHADER_USE_MORPH_DATA_TEXTURE 设置为 1。

      通过这种方式,您可以启用材质类型使用变形数据纹理。数据纹理允许同时拥有任意数量的活动变形目标,但会带来性能成本。

      ../../_images/properties-use-morph-data-texture-1.png
    2. 在 Library > Meshes 中,选择您的 Morph 资源。在 Properties 中,添加并启用 Morph > Export as Data Texture 属性。

      ../../_images/library-morph-cube.png ../../_images/properties-export-as-data-texture.png

使用 morph target normals

当您将使用变形网格的3D模型导入到 Kanzi Studio 时,如果该模型中的某些网格没有法线,Kanzi Studio 会提供生成法线的选项。Kanzi 在光照计算中使用法线。当您在导入过程中不让 Kanzi Studio 生成缺失的法线时,变形目标会自动使用变形基础网格的法线。

小技巧

要手动生成网格的法线, 在 Library > Meshes 中右键单击该网格并选择 Generate Normals。

../../_images/library-mesh-generate-normals.png

控制使用变形目标法线

要控制变形目标法线的使用:

  1. 在 Library > Materials and Textures > Materials Types 中,选择您的变形基网格使用的材质类型。

    ../../_images/library-vertex-phong-morph.png
  2. 在 Properties 的 Preprocessor Definitions 中,将 KANZI_SHADER_USE_MORPH_TARGET_NORMALS 的值设置为:

    • 0 将形变目标设置为使用形变基础网格的法线。

    • 1 将每个变形目标设置为使用其自身的法线。

    ../../_images/properties-use-morph-target-normals-1.png

改进生成的变形目标法线

当 Kanzi Studio 为变形目标生成的法线与变形基础形状的法线不同时,随着您激活更多的变形目标,这种差异会累积。这可能导致法线的逐步视觉退化。

要改进生成的变形目标法线:

  1. 在 Library > Materials and Textures > Materials Types 中,选择您的变形基网格使用的材质类型。

    ../../_images/library-vertex-phong-morph.png
  2. 在 Properties 的 Preprocessor Definitions 中,将 KANZI_SHADER_USE_MORPH_NORMAL_LIMIT 的值设置为 1。

    这将限制法线的差异仅由单个目标形状引起。

    ../../_images/properties-morph-normal-limit-1.png

限制同时激活的变形目标的数量

当您将包含变形的3D模型导入到 Kanzi Studio 时,Kanzi Studio 将该变形设置为使用支持同时激活所有变形目标的材质类型。如果您的变形包含大量目标,Kanzi 会将变形设置为在数据纹理中存储其变形目标的顶点属性。数据纹理允许同时拥有任意数量的活动变形目标,但会带来性能成本。一次激活的变形目标越多,处理顶点着色器所需的时间就越长。要优化性能,您可以:

  • 限制一次可以激活的变形目标的数量。

  • 禁用数据纹理的使用。

在没有数据纹理的情况下,同时激活的变形目标的最大数量是

\[N = floor((MaxChannels - ConstantChannels) / PerTargetChannels)\]

在其中:

  • \(MaxChannels\) 是您的图形驱动程序支持的最大顶点属性通道数。

    例如,16。

  • \(ConstantChannels\) 是包含所有变形目标相同属性数据的通道数量。

    例如,纹理坐标、骨骼权重和骨骼索引对于所有变形目标都是相同的。

  • \(PerTargetChannels\) 是包含目标特定属性数据的通道数量。

    例如,顶点位置、法线和切线可以在每个变形目标中有所不同。

要优化性能,当您不需要在您的变形中一次激活超过 \(N\) 个目标时,禁用数据纹理的使用。

当您的变形不使用数据纹理时,只有具有最大权重的 \(N\) 目标可以同时激活。

要限制同时激活的变形目标的数量:

  1. 在 Library > Materials and Textures > Material Types 中,选择您的变形基网格使用的每个材质类型。在 Properties 的 Preprocessor Definitions 中,将 KANZI_SHADER_MORPH_TARGET_COUNT 设置为您希望 Kanzi 一次激活的变形目标数量。

    当一个变形具有的目标多于 KANZI_SHADER_MORPH_TARGET_COUNT 的值时,Kanzi 会自动选择那些权重最大的变形目标进行激活。

    ../../_images/library-vertex-phong-morph.png ../../_images/properties-morph-target-count-6.png
  2. (可选) 如果您将 KANZI_SHADER_MORPH_TARGET_COUNT 设置为您的图形驱动程序在不使用数据纹理的情况下支持的值,请禁用数据纹理:

    1. 在 Library > Materials and Textures > Material Types 中,选择您的变形基网格使用的每个材质类型。在 Properties 的 Preprocessor Definitions 中,将 KANZI_SHADER_USE_MORPH_DATA_TEXTURE 设置为 0。

      如果您这样做,请确保将 KANZI_SHADER_MORPH_TARGET_COUNT 设置为您的图形驱动程序在不使用数据纹理的情况下支持的值。否则,Kanzi Studio 会使用红色错误材质渲染您的模型,并在日志中打印警告。

      ../../_images/library-vertex-phong-morph.png ../../_images/properties-use-morph-data-texture-0.png
    2. 在 Library > Meshes 中,选择 Morph 资源。在 Properties 中,禁用或移除 Export as Data Texture 属性。

      ../../_images/library-morph-cube.png ../../_images/properties-disable-morph-data-texture.png

创建变形权重动画

要更改变形的形状,使用关键帧动画。您可以从 gltf、glb、fbx 或 dae 文件中导入变形权重动画,或者在 Kanzi Studio 中创建动画。

要在 Kanzi Studio 中创建变形权重动画:

  1. 在 Library > Animations 中,按 Alt 并右键单击 Animation Clip 并选择 Animation。

    例如,将动画命名为 Middle Animation,并在 Properties 中设置:

    • 要将 Target Property 更改为 <Expression>,请单击 image0 以添加 Morph Weight 属性,并将其设置为 <MorphWeight>[1]。

    • Property Field 到 Whole property

    您使用 Animation Clip 来存放变形中各网格的关键帧动画。每个动画以变形中的特定网格为目标,并定义该网格在不同时间点的权重。Middle Animation 是您要变形的第一个网格的关键帧动画。

    ../../_images/create-morph-animation.png ../../_images/middle-animation-target-property-add-morph-weight-adding.png ../../_images/middle-animation-properties.png
  2. 根据您想在 Morph 中动画化的目标形状的数量重复上一步。对于 <MorphWeight>[n] 中的每个动画,将 n 设置为 Morph 中的网格,您希望通过动画更改其权重。不要为基础网格添加动画。

    例如,要使用三个网格对变形进行动画化,请创建两个动画。将它们命名为 Middle Animation 和 Ready Animation,并设置:

    • Middle Animation Target Property 到 <Expression> <MorphWeight>[1]

    • Ready Animation Target Property 到 <Expression> <MorphWeight>[2]

    使用 Middle Animation 设置变形中第二个网格的权重。使用 Ready Animation 在不同时间点设置变形中第三个网格的权重。Kanzi 变形着色器设置第一个网格的权重。

    ../../_images/morph-animations-in-the-library.png ../../_images/middle-animation-properties.png ../../_images/ready-animation-properties.png
  3. 为您在上一步中创建的动画创建关键帧。请参阅 为目标属性字段创建关键帧动画。

    您使用关键帧值在不同时间点设置变形中网格的 Weight 属性。

    值越高,Morph 越接近该网格的形状。Kanzi 变形着色器设置基础变形形状的权重,使 Morph Target Weights 的总和为 1。这使得生成形状的比例保持与目标形状一致。

    例如,要为包含三个网格的变形创建一秒钟的线性动画,请在 Library 中双击 Middle Animation,然后在 Animation Clip Editor 中创建以下关键帧:

    • Middle Animation:

      • 第一个关键帧:

        • 将 Time 设为 0。

        • Value 到 0

      • 第二个关键帧:

        • Time 到 0.5

        • Value 到 1

      • 第三个关键帧:

        • Time 到 1

        • Value 到 0

      ../../_images/middle-animation-in-animation-clip-editor.png
    • Ready Animation:

      • 第一个关键帧:

        • 将 Time 设为 0。

        • Value 到 0

      • 第二个关键帧:

        • Time 到 0.5

        • Value 到 0

      • 第三个关键帧:

        • Time 到 1

        • Value 到 1

      ../../_images/ready-animation-in-animation-clip-editor.png
    ../../_images/morph-animation-clip-in-animation-clip-editor.png
  4. 使用您创建的关键帧动画对变形进行动画化:

    1. 在 Node Tree 中,选择其 Mesh 属性设置为您想要动画的 Morph 的 Model 节点。请参阅 添加变形。

      ../../_images/model-in-the-project.png ../../_images/set-model-mesh-property.png
    2. 在 Node Components 中,按 Alt 并右键单击 Animation 并选择 Animation Player。

      ../../_images/triggers-add-animation-player.png
    3. 在您创建的 Animation Player 中的 Node Components 中,将 Target Animation Timeline 属性设置为您在第一步中创建的 Animation Clip,并设置动画播放。请参阅 播放关键帧动画。

      例如,设置:

      • 将 Autoplay Enabled 设置为 enabled。

      • Playback Mode 到 Ping pong

      • 将 Repeat Count Infinite 设置为 enabled。

      ../../_images/animation-player-target-animation-timeline-morph-animation-clip.png ../../_images/morph-animation.gif

在 API 中使用变形

要手动创建变形时间线并为时间线时钟创建回放:

// Create morph and add meshes (created beforehand) into it.
MorphSharedPtr morph = Morph::create(domain, "testMorph");
morph->add(mesh1, 0.0f);
morph->add(mesh2, 1.0f);

// Add node that will hold the morph, then add it to the scene graph (scene).
Model3DSharedPtr model = Model3D::create(domain, "testSphere");
model->setMesh(morph);
scene->addChild(model);

// Create float animation and add two keyframes.
FloatKeyframeAnimationSharedPtr animation = FloatKeyframeAnimation::create(domain);
animation->addLinearKeyframe(chrono::milliseconds(0), 0.0f);
animation->addLinearKeyframe(chrono::milliseconds(100), 1.0f);

// Create timeline and playback.
MorphWeightTimelineSharedPtr morphTimeline = MorphWeightTimeline::create(domain, "testSphere", 1, animation);
SceneGraphTimelinePlaybackContext context(*scene);
TimelinePlaybackSharedPtr playback = morphTimeline->createPlayback(context);

// Add playback to root clock
domain->getRootTimelineClock()->addTimelinePlayback(playback);

有关详细信息,请参阅 Morph 类。

另请参阅

3D 资产 (3D Assets)

导入 3D 资产

在第三方工具中准备 3D 资产

使用网格

网格最佳实践

材质类型和材质

使用材料类型

使用智能材质

动画 (Animations)

为目标属性字段创建关键帧动画

使用关键帧动画

编辑着色器

属性优先级