Flutter Impeller
impeller::scene::Skin Class Referencefinal

#include <skin.h>

Public Member Functions

 ~Skin ()
 
 Skin (Skin &&)
 
Skinoperator= (Skin &&)
 
std::shared_ptr< TextureGetJointsTexture (Allocator &allocator)
 

Static Public Member Functions

static std::unique_ptr< SkinMakeFromFlatbuffer (const fb::Skin &skin, const std::vector< std::shared_ptr< Node >> &scene_nodes)
 

Detailed Description

Definition at line 21 of file skin.h.

Constructor & Destructor Documentation

◆ ~Skin()

impeller::scene::Skin::~Skin ( )
default

◆ Skin()

impeller::scene::Skin::Skin ( Skin &&  )
default

Member Function Documentation

◆ GetJointsTexture()

std::shared_ptr< Texture > impeller::scene::Skin::GetJointsTexture ( Allocator allocator)

Definition at line 65 of file skin.cc.

65  {
66  // Each joint has a matrix. 1 matrix = 16 floats. 1 pixel = 4 floats.
67  // Therefore, each joint needs 4 pixels.
68  auto required_pixels = joints_.size() * 4;
69  auto dimension_size = std::max(
70  2u,
71  Allocation::NextPowerOfTwoSize(std::ceil(std::sqrt(required_pixels))));
72 
73  impeller::TextureDescriptor texture_descriptor;
75  texture_descriptor.format = PixelFormat::kR32G32B32A32Float;
76  texture_descriptor.size = {dimension_size, dimension_size};
77  texture_descriptor.mip_count = 1u;
78 
79  auto result = allocator.CreateTexture(texture_descriptor);
80  result->SetLabel("Joints Texture");
81  if (!result) {
82  FML_LOG(ERROR) << "Could not create joint texture.";
83  return nullptr;
84  }
85 
86  std::vector<Matrix> joints;
87  joints.resize(result->GetSize().Area() / 4, Matrix());
88  FML_DCHECK(joints.size() >= joints_.size());
89  for (size_t joint_i = 0; joint_i < joints_.size(); joint_i++) {
90  const Node* joint = joints_[joint_i].get();
91  if (!joint) {
92  // When a joint is missing, just let it remain as an identity matrix.
93  continue;
94  }
95 
96  // Compute a model space matrix for the joint by walking up the bones to the
97  // skeleton root.
98  while (joint && joint->IsJoint()) {
99  joints[joint_i] = joint->GetLocalTransform() * joints[joint_i];
100  joint = joint->GetParent();
101  }
102 
103  // Get the joint transform relative to the default pose of the bone by
104  // incorporating the joint's inverse bind matrix. The inverse bind matrix
105  // transforms from model space to the default pose space of the joint. The
106  // result is a model space matrix that only captures the difference between
107  // the joint's default pose and the joint's current pose in the scene. This
108  // is necessary because the skinned model's vertex positions (which _define_
109  // the default pose) are all in model space.
110  joints[joint_i] = joints[joint_i] * inverse_bind_matrices_[joint_i];
111  }
112 
113  if (!result->SetContents(reinterpret_cast<uint8_t*>(joints.data()),
114  joints.size() * sizeof(Matrix))) {
115  FML_LOG(ERROR) << "Could not set contents of joint texture.";
116  return nullptr;
117  }
118 
119  return result;
120 }

References impeller::Allocator::CreateTexture(), impeller::TextureDescriptor::format, impeller::scene::Node::GetLocalTransform(), impeller::scene::Node::GetParent(), impeller::scene::Node::IsJoint(), impeller::kHostVisible, impeller::kR32G32B32A32Float, impeller::TextureDescriptor::mip_count, impeller::Allocation::NextPowerOfTwoSize(), impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

◆ MakeFromFlatbuffer()

std::unique_ptr< Skin > impeller::scene::Skin::MakeFromFlatbuffer ( const fb::Skin &  skin,
const std::vector< std::shared_ptr< Node >> &  scene_nodes 
)
static

Definition at line 19 of file skin.cc.

21  {
22  if (!skin.joints() || !skin.inverse_bind_matrices() ||
23  skin.joints()->size() != skin.inverse_bind_matrices()->size()) {
24  VALIDATION_LOG << "Skin data is missing joints or bind matrices.";
25  return nullptr;
26  }
27 
28  Skin result;
29 
30  result.joints_.reserve(skin.joints()->size());
31  for (auto joint : *skin.joints()) {
32  if (joint < 0 || static_cast<size_t>(joint) > scene_nodes.size()) {
33  VALIDATION_LOG << "Skin joint index out of range.";
34  result.joints_.push_back(nullptr);
35  continue;
36  }
37  if (scene_nodes[joint]) {
38  scene_nodes[joint]->SetIsJoint(true);
39  }
40  result.joints_.push_back(scene_nodes[joint]);
41  }
42 
43  result.inverse_bind_matrices_.reserve(skin.inverse_bind_matrices()->size());
44  for (size_t matrix_i = 0; matrix_i < skin.inverse_bind_matrices()->size();
45  matrix_i++) {
46  const auto* ip_matrix = skin.inverse_bind_matrices()->Get(matrix_i);
47  Matrix matrix = ip_matrix ? importer::ToMatrix(*ip_matrix) : Matrix();
48 
49  result.inverse_bind_matrices_.push_back(matrix);
50  // Overwrite the joint transforms with the inverse bind pose.
51  result.joints_[matrix_i]->SetGlobalTransform(matrix.Invert());
52  }
53 
54  return std::make_unique<Skin>(std::move(result));
55 }

References impeller::Matrix::Invert(), impeller::scene::importer::ToMatrix(), and VALIDATION_LOG.

◆ operator=()

Skin & impeller::scene::Skin::operator= ( Skin &&  )
default

The documentation for this class was generated from the following files:
impeller::Allocation::NextPowerOfTwoSize
static uint32_t NextPowerOfTwoSize(uint32_t x)
Definition: allocation.cc:41
impeller::TextureDescriptor::format
PixelFormat format
Definition: texture_descriptor.h:40
impeller::TextureDescriptor::mip_count
size_t mip_count
Definition: texture_descriptor.h:42
impeller::StorageMode::kHostVisible
@ kHostVisible
impeller::scene::Skin::Skin
Skin(Skin &&)
impeller::PixelFormat::kR32G32B32A32Float
@ kR32G32B32A32Float
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:41
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:73
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:38
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:37
impeller::scene::importer::ToMatrix
Matrix ToMatrix(const std::vector< double > &m)
Definition: conversions.cc:15