This page has been translated automatically.
视频教程
界面
要领
高级
实用建议
基础
专业(SIM)
UnigineEditor
界面概述
资源工作流程
Version Control
设置和首选项
项目开发
调整节点参数
Setting Up Materials
设置属性
照明
Sandworm
使用编辑器工具执行特定任务
如何擴展編輯器功能
嵌入式节点类型
Nodes
Objects
Effects
Decals
光源
Geodetics
World Nodes
Sound Objects
Pathfinding Objects
Players
编程
基本原理
搭建开发环境
使用范例
C++
C#
UnigineScript
统一的Unigine着色器语言 UUSL (Unified UNIGINE Shader Language)
Plugins
File Formats
材质和着色器
Rebuilding the Engine Tools
GUI
双精度坐标
应用程序接口
Animations-Related Classes
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Objects-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
IG Plugin
CIGIConnector Plugin
Rendering-Related Classes
VR-Related Classes
创建内容
内容优化
材质
Material Nodes Library
Miscellaneous
Input
Math
Matrix
Textures
Art Samples
Tutorials

添加变形目标

本文描述了如何使用 morph target(变形目标)动画,在UNIGINE中也称为blend shape(混合形状)。通常,变形目标是用来改变人物的面部表情。

这篇文章展示了如何从Autodesk Maya导出带有变形目标的网格,然后将其添加到UNIGINE。

本教程中使用的模型是分布在CC0 1.0 Universal下的SpotKeenan Crane

需求#

  • 假设您已经有一个混合形状的3D模型准备导出,并且该模型在UNIGINE设置的限制范围内。
  • 假设您已经创造了一个世界。

另请参阅#

步骤1。从玛雅导出一个网格与混合形状#

本节展示了从Autodesk Maya导出FBX格式的混合形状网格的方法。它包含一个小牛的示例网格,它有2个混合形状(变形目标)。

要导出具有混合形状的网格,请执行以下操作:

  1. Autodesk Maya中,选择要导出的混合形状网格。

  2. 在主菜单中,单击File -> Export Selection...

  3. Export Selection窗口中,选择一个文件夹来保存网格,并为FBX文件指定一个名称。在Files of type下拉列表中选择FBX export
  4. 在带有导出选项的File Type Specific Options选项卡中,指定参数以导出网格。
  5. Deformed Models选项卡中,选中Blend Shapes复选框以导出混合形状。
  6. 单击Export Selection

现在您有了FBX格式的网格,可以很容易地添加到您的项目中。

步骤2。在世界中添加网格#

本节将展示如何添加导出的网格动画世界,建立变形目标。

将导出的网格添加到世界中:

  1. 启用 Import Morph Targets 选项并导入*.fbx文件。

  2. 将导入的文件添加到场景中。
  3. 保存世界。

网格的每个混合形状都是一个目标。您需要为网格的表面启用变形目标,并为这些目标设置参数来控制变形目标动画。下面的例子展示了如何从代码中创建变形目标和设置参数:

注意
代码被实现为一个组件,应该通过UnigineEditor分配给节点。查看关于组件系统的文章了解更多细节。
Morph.h
#pragma once
#include <UnigineComponentSystem.h>
#include <UnigineWorld.h>
#include <UnigineGame.h>

class Morph :
	public Unigine::ComponentBase
{
public:
	// declare constructor and destructor for the Morph class
	COMPONENT_DEFINE(Morph, Unigine::ComponentBase);

	// declare methods to be called at the corresponding stages of the execution sequence
	COMPONENT_INIT(init);
	COMPONENT_UPDATE(update);

private:
	Unigine::ObjectMeshSkinnedPtr mesh;

protected:
	// world main loop
	void init();
	void update();
};
Morph.cpp
#include "Morph.h"

REGISTER_COMPONENT(Morph);		// macro for component registration by the Component System
using namespace Unigine;
using namespace Math;

void Morph::init()
{
	// get the node and cast it to a skinned mesh
	mesh = static_ptr_cast<ObjectMeshSkinned>(node);
	
	// enable targets of the surface
	mesh->setSurfaceTargetEnabled(0, 1, true);
	mesh->setSurfaceTargetEnabled(0, 2, true);
}

void Morph::update()
{
	float time = Game::getTime() * 2.0f;
	// calculate weights of targets
	float k0 = Unigine::Math::sin(time * 3.0f) + 0.75f;
	float k1 = Unigine::Math::cos(time * 3.0f) + 0.75f;

	// set targets with parameters
	mesh->setSurfaceTargetWeight(0, 0, 1.0f - k0 - k1);
	mesh->setSurfaceTargetWeight(0, 1, k0);
	mesh->setSurfaceTargetWeight(0, 2, k1);
}

上面给出的代码获取引用FBX文件的节点,并设置参数以变形目标。让我们来澄清一些重要的事情:

  • 网格是通过将指向FBX资源的节点强制转换到ObjectMeshSkinned来获得的。要强制转换的节点是组件分配给的节点。在强制转换该节点之前,您可能还需要添加一个检查,以确定该节点是否为ObjectMeshSkinned

    源代码 (C++)
    //check if the node to which the component is assigned is MeshSkinned
    if (node->getType() != Node::OBJECT_MESH_SKINNED)
    	return;
    // get the node and cast it to a skinned mesh
    mesh = static_ptr_cast<ObjectMeshSkinned>(node);
  • setSurfaceTargetEnabled() 函数为指定的网格表面设置目标。
  • 通过 setSurfaceTargetWeight() 函数设置变形目标的权值。 每个目标都有其目标权重。权重对网格的坐标有影响:坐标乘以它们的权重。因此,所有启用的目标都乘以它们的权重,并创建新的网格:

    final_xyz = target_0_xyz * weight_0 + target_1_xyz * weight_1 + ...
  • 为对象启用了三个目标,并以以下方式使用sin()cos()函数对这些目标进行动画混合:

    • 从绑定姿态(bind pose)减去其他两个变形目标的影响,以获得用于混合的规范化权重。

      源代码 (C++)
      mesh->setSurfaceTargetWeight(0, 0, 1.0f - k0 - k1);
    • 使用sin()函数修改第一个目标权重。

      源代码 (C++)
      mesh->setSurfaceTargetWeight(0, 1, k0);
    • 使用cos()函数修改第二个目标权重。

      源代码 (C++)
      mesh->setSurfaceTargetWeight(0, 2, k1);

将组件分配给网格后,结果如下:

最新更新: 2024-09-18
Build: ()