使用变形

变形是指通过无缝过渡将一个形状转换为另一个形状。使用包含变形数据的 Mesh 资源在形状之间变形。

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

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

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

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

  • 请勿更改网格的拓扑。

添加变形

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

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

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

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

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

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

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

    • 在 Library > Meshes 中,包含其基础顶点数据和差分变形数据的网格。

      ../../_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 中,选择显示包含变形数据的 Mesh 资源的 Model 节点。在 Properties 的 Morphing 属性中,您可以调整 Morph 资源中每个网格的权重。

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

    值越高,Mesh 就越接近给定的形状。Kanzi 变形着色器使用网格的基础通道数据,并将所有形状累加到基础形状上。由于变形形状表示为与基础形状的差值,因此使用大于 1 的权重,或在 Morphing 属性中为多个形状设置较高的权重,可能会导致视觉错误。

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

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

将目标添加到 Morph 中

要添加您想在其间变形的形状,请使用 Model 节点中 Morphing 属性的下拉菜单向变形添加形状。您只能从与分配给该 Model 的 Mesh 关联的形状中添加变形目标。

要将目标添加到 Morph:

  1. 在要变形的 Model 节点的 Morphing 属性中,点击 + Morph shape 按钮,然后选择要添加到变形的形状。

    ../../_images/morph-targets-add.png
  2. 要重新排列变形列表,请使用 Morphing 属性中与形状关联的向上和向下箭头。

    ../../_images/rearrange-morphing-property.png
  3. 要移除形状,请使用 Morphing 属性中与形状关联的叉号按钮。

    ../../_images/remove-morph-shape.png
  4. 要从头开始并使用默认权重添加所有形状,请移除 Morphing 属性,然后使用 + 按钮重新添加该属性。

    ../../_images/remove-morphing-property.png ../../_images/add-morphing-property.png
  5. (可选) 在 Library > Materials and Textures > Material Types 中,选择您的变形基网格使用的每个材质类型。在 Properties 的 Preprocessor Definitions 中,将 KANZI_SHADER_MORPH_TARGET_COUNT 设置为您希望 Kanzi 一次可以激活的变形目标数量。

    ../../_images/library-vertex-phong-morph.png ../../_images/properties-morph-target-count-9.png

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

    导入带有变形的 Mesh 时,Kanzi 会自动为您创建合适的材质并将其分配给该 Mesh。

    如果变形数据中的变形形状数量无需使用 Morph Data Texture 即可容纳在 GPU 特性通道中,则应使用 Mesh 变形数据中确切的变形目标数量,并且无需更改 KANZI_SHADER_MORPH_TARGET_COUNT。请参阅 限制同时激活的变形目标数量。

  6. (可选) 如果您的图形驱动程序不支持 Mesh 中的变形目标数量,请在 Properties 的 Preprocessor Definitions 中,将 KANZI_SHADER_USE_MORPH_DATA_TEXTURE 设置为 1。

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

    ../../_images/properties-use-morph-data-texture-1.png

    Kanzi 会自动检测是否需要 Morph Data Texture,创建该纹理,并将其分配给 Model。在这种情况下,更改所分配变形目标的顺序和数量会就地修改该纹理。您可以通过移除不必要的变形形状来降低性能开销。请参阅 限制同时激活的变形目标的数量。

使用 morph target normals

当您将使用变形网格的 3D 模型导入 Kanzi Studio,并且该模型中的某些网格没有法线时,Kanzi Studio 会自动为变形目标生成法线。Kanzi 在光照计算中使用这些法线。

由于 Kanzi Studio 为变形目标生成的法线可能与变形基础形状的法线不同,因此随着您激活更多变形目标,这种差异会累积误差,从而导致视觉效果逐渐下降。为避免这种情况,Kanzi Studio 在为变形目标生成法线时也会重新生成基网格的法线。

要避免 Kanzi Studio 生成或更改法线,请从 3D 编辑软件中导出所有变形形状的法线。

小技巧

要手动生成网格的法线, 在 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

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

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

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

  • 禁用数据纹理的使用。

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

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

在其中:

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

    例如,16。

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

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

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

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

Kanzi Studio 根据实际网格数据选择操作模式:

  1. 如果通道数量足够少,无需 Morph Data Texture 即可使用,Kanzi 始终使用所有变形数据通道。移除形状对性能没有影响——未选定的形状权重为 \(0.0\)。

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

      ../../_images/library-vertex-phong-morph.png ../../_images/properties-use-morph-data-texture-0.png
    • 如果这样做,请确保将 KANZI_SHADER_MORPH_TARGET_COUNT 设置为与 Mesh 中变形目标数量完全相同的值。否则,Kanzi Studio 会使用红色错误材质渲染您的模型,并在日志中打印警告。

      ../../_images/properties-morph-target-count-6.png
  2. 如果变形数据的通道数量足够多,可能需要使用 Morph Data Texture,Kanzi 始终使用数据纹理。移除形状可以提高性能并减小数据纹理,从而降低内存需求。

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

      ../../_images/library-vertex-phong-morph.png ../../_images/properties-use-morph-data-texture-1.png
    • 为优化性能,当您不需要网格数据中的某些变形形状时:

      • 从 Morphing 属性的形状列表中移除该形状。

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

      • 在 Properties 的 Preprocessor Definitions 中,将 KANZI_SHADER_MORPH_TARGET_COUNT 设置为您需要的变形目标数量。

      ../../_images/remove-morph-shape.png ../../_images/properties-morph-target-count-9.png
  3. (可选) 如果网格包含在任何情况下都不会使用的变形目标,最好在 3D 编辑软件中禁用这些目标的导出,从一开始就不导出它们。这样,无论如何 Kanzi 都不会使用这些变形目标。

创建变形权重动画

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

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

  1. 在 Library > Animation Data 中,按 Alt 并右键单击 Animation Data,然后选择 Animation。

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

    • 将 Target Property 设置为 Model3D.Morphing 属性,并将目标形状索引设置为 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. 对您要动画化的 Mesh 中的每个目标形状重复上一步。对于范围索引 n 中的每个动画,将 n 设置为 Model 中您要通过该动画更改其权重的形状的索引。不要为基础网格添加动画。

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

    • 将 Middle Animation 的 Target Property 设置为 Model3D.Morphing 索引 1

    • 将 Ready Animation 的 Target Property 设置为 Model3D.Morphing 索引 2

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

    ../../_images/morph-animations-in-the-library.png ../../_images/middle-animation-properties.png ../../_images/ready-animation-properties.png

    备注

    动画数据中的索引指向被动画化的 Model3D 中的形状索引。

    如果网格的变形目标数量足够少,不需要 Morph Data Texture,则此项指向变形数据中的确切形状。如果使用了 Morph Data Texture`,则此项取决于为 Morphing 属性选择的形状的顺序和数量。

  3. 为您在上一步中创建的动画创建关键帧。请参阅 为目标属性字段创建关键帧动画。

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

    值越高,Mesh 就越接近给定的形状。Kanzi 变形着色器使用网格的基础通道数据,并将所有形状累加到基础形状上。由于变形形状表示为与基础形状的差值,因此使用大于 1 的权重,或在 Morphing 属性中为多个形状设置较高的权重,可能会导致视觉错误。

    例如,要为包含三个网格的变形创建一秒钟的线性动画,请在 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 属性设置为您要动画化的 Mesh 的 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 float animation and add two keyframes.
FloatKeyframeAnimationSharedPtr morphAnimation =
    FloatKeyframeAnimation::create(domain);
morphAnimation->addLinearKeyframe(chrono::milliseconds(0), 0.0f);
morphAnimation->addLinearKeyframe(chrono::milliseconds(100), 1.0f);

// Create a range index animation timeline and apply it to the Morphing property of the current node.
RangeIndexAnimationTimelineSharedPtr rangeIndexTimeline =
    RangeIndexAnimationTimeline::create(domain, ".", Model3D::MorphingProperty);

// Animate the first morph target using the keyframe animation (this animation goes from weight zero to one).
rangeIndexTimeline->addEntry(0, PropertyFieldWhole, morphAnimation);

// Create range index animation timeline playback.
RangeIndexAnimationTimelinePlaybackSharedPtr playback =
    RangeIndexAnimationTimelinePlayback::create(rangeIndexTimeline, context);

另请参阅

3D 资产 (3D Assets)

导入 3D 资产

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

使用网格

网格最佳实践

材质类型和材质

使用材料类型

使用智能材质

动画 (Animations)

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

使用关键帧动画

编辑着色器

属性优先级