Skip to content

Commit

Permalink
Merge branch 'USTC-CG:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhi0467 authored May 16, 2024
2 parents a88be00 + e55eb50 commit 9d1192f
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ namespace USTC_CG::node_character_animation {

using namespace pxr;

Joint::Joint(int idx, string name, int parent_idx) : idx_(idx), name_(name), parent_idx_(parent_idx)
Joint::Joint(int idx, string name, int parent_idx, const GfMatrix4f& bind_transform)
: idx_(idx), name_(name), parent_idx_(parent_idx), bind_transform_(bind_transform)
{
}

Expand All @@ -23,9 +24,9 @@ void JointTree::compute_world_transforms_for_each_joint()
// ---------------------------------------------
}

void JointTree::add_joint(int idx, std::string name, int parent_idx)
void JointTree::add_joint(int idx, std::string name, int parent_idx, const GfMatrix4f& bind_transform)
{
auto joint = make_shared<Joint>(idx, name, parent_idx);
auto joint = make_shared<Joint>(idx, name, parent_idx, bind_transform);
joints_.push_back(joint);
if (parent_idx < 0) {
root_ = joint;
Expand Down Expand Up @@ -71,7 +72,7 @@ Animator::Animator(const shared_ptr<MeshComponent> mesh, const shared_ptr<SkelCo
string joint_name = jointPath.GetName();
int parent_idx = topology.GetParent(i);

joint_tree_.add_joint(i, joint_name, parent_idx);
joint_tree_.add_joint(i, joint_name, parent_idx, GfMatrix4f(skel->bindTransforms[i]));
}

joint_tree_.print();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ class Joint
{

public:
Joint(int idx, string name, int parent_idx = -1);
Joint(int idx, string name, int parent_idx, const GfMatrix4f& bind_transform);

void compute_world_transform();

GfMatrix4f get_local_transform() { return local_transform_; }
GfMatrix4f get_world_transform() { return world_transform_; }
GfMatrix4f get_bind_transform() { return bind_transform_; }

shared_ptr<Joint> parent_;
vector<shared_ptr<Joint>> children_;
Expand All @@ -41,6 +42,7 @@ class Joint

GfMatrix4f local_transform_;
GfMatrix4f world_transform_;
GfMatrix4f bind_transform_;
};

class JointTree
Expand All @@ -53,7 +55,7 @@ class JointTree

void compute_world_transforms_for_each_joint();

void add_joint(int idx, std::string name, int parent_idx);
void add_joint(int idx, std::string name, int parent_idx, const GfMatrix4f& bind_transform);

void update_joint_local_transform(const VtArray<GfMatrix4f>& new_local_transforms);

Expand Down
13 changes: 7 additions & 6 deletions Homeworks/10_character_animation/documents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,20 @@ void JointTree::compute_world_transforms_for_each_joint()

## 3. 骨骼如何驱动蒙皮运动

蒙皮上的每个顶点可能受到多个关节影响,其运动是多个关节transform线性组合作用后的结果(这种做法被称为[Linear Blend Skinning,LBS](http://graphics.cs.cmu.edu/courses/15-466-f17/notes/skinning.html)),每个顶点相关的关节index和响应的影响权重存储在`jointWeight``jointIndices`中。
蒙皮上的每个顶点可能受到多个关节影响,其运动是多个关节transform线性组合作用后的结果(这种做法被称为[Linear Blend Skinning,LBS](http://graphics.cs.cmu.edu/courses/15-466-f17/notes/skinning.html)),每个顶点相关的关节index和响应的影响权重存储在`jointWeight``jointIndices`,这两个数组的长度为 顶点数×对其有影响的关节数,影响每个顶点的关节数相同

为了让我们的mesh的顶点的空间位置从“相对于世界坐标系原点”转换为“相对于影响这个顶点的关节”,根据`bindTransform`的定义,我们可以通过对其求逆实现,称为逆绑定变换(Inverse Bind Transforms, IBTs)

最后,mesh顶点位置的更新公式如下:

$$
\~{\mathbf{x}} = \sum_i w_i \mathbf{T}_i * \mathbf{B}_i^{-1} \~{\mathbf{x}}^0
\~{\mathbf{x}} = \sum_i^n w_i \mathbf{T}_i * \mathbf{B}_i^{-1} \~{\mathbf{x}}^0
$$

其中 $\mathbf{T}_i$ 和 $\mathbf{B}_i$ 分别为第 $i$ 个关节的 `worldTransform``bindTransform`,
$n$ 为对顶点 $\mathbf{x}$ 产生影响的关节数 (需要通过`jointIndices`的长度除以顶点数得到)

$\~{\mathbf{x}} = [\vec{\mathbf{x}}, 1] \in \mathbb{R}^{4 \times 1}$ , 可以使用`GfMatrix4f::TransformAffine` 函数实现。
$\~{\mathbf{x}} = [\vec{\mathbf{x}}, 1] \in \mathbb{R}^{4 \times 1}$ , 可以使用`GfMatrix4f``TransformAffine` 函数实现。

你需要实现[`animator.cpp`](../../../Framework3D/source/nodes/nodes/geometry/character_animation/animator.cpp)中的函数:

Expand All @@ -101,7 +102,7 @@ void Animator::update_mesh_vertices()
<img src="../images/hw10-arm-demo.gif" style="zoom:40%" />
</div>

节点图如下
节点图如下`Prim Path``/Model/Mesh`
<div align="center">
<img src="../images/arm-node.png" style="zoom:80%" />
</div>
Expand All @@ -112,7 +113,7 @@ void Animator::update_mesh_vertices()
<img src="../images/hw10-demo.gif" style="zoom:100%" />
</div>

所需要连接的节点图如下
所需要连接的节点图如下, `Prim Path``/root/Armature/Ch03/Mesh_001`

<div align="center">
<img src="../images/nodes-dance.png" style="zoom:100%" />
Expand All @@ -135,4 +136,4 @@ void Animator::update_mesh_vertices()

## 参考资料 & 扩展阅读材料
1. [GAMES 105:计算机角色动画基础](https://games-105.github.io/)
2. [Game Engine Blog: How I Implemented Skeletal Animation](https://vladh.net/game-engine-skeletal-animation/)
2. [Game Engine Blog: How I Implemented Skeletal Animation](https://vladh.net/game-engine-skeletal-animation/)
2 changes: 1 addition & 1 deletion Homeworks/9_sph_fluid/documents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ for (auto& p : ps_.particles()) {
SPH中密度的计算公式为:

$$
\rho_i = \sum_{j+i} \left(\frac{m_j}{\rho_j} \right) m_j W(\mathbf{x}_ i - \mathbf{x}_ j, h) = \sum_{j+i} m_j W_{ij}
\rho_i = \sum_{j+i} \left(\frac{m_j}{\rho_j} \right) \rho_j W(\mathbf{x}_ i - \mathbf{x}_ j, h) = \sum_{j+i} m_j W_{ij}
$$

这里我们记 $W_{ij} = W(\mathbf{x}_i, \mathbf{x}_j, h)$, $j$ 表示粒子 $i$ 的所有邻居粒子。 在SPH方法中, $h$ 表示核函数半径,我们用 $\Delta t$ 来表示时间步长。
Expand Down

0 comments on commit 9d1192f

Please sign in to comment.