Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
skin.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <cmath>
8#include <memory>
9#include <vector>
10
11#include "flutter/fml/logging.h"
15
16namespace impeller {
17namespace scene {
18
19std::unique_ptr<Skin> Skin::MakeFromFlatbuffer(
20 const fb::Skin& skin,
21 const std::vector<std::shared_ptr<Node>>& scene_nodes) {
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
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}
56
57Skin::Skin() = default;
58
59Skin::~Skin() = default;
60
61Skin::Skin(Skin&&) = default;
62
63Skin& Skin::operator=(Skin&&) = default;
64
65std::shared_ptr<Texture> Skin::GetJointsTexture(Allocator& allocator) {
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}
121
122} // namespace scene
123} // namespace impeller
static uint32_t NextPowerOfTwoSize(uint32_t x)
Definition allocation.cc:41
An object that allocates device memory.
Definition allocator.h:22
std::shared_ptr< Texture > CreateTexture(const TextureDescriptor &desc)
Definition allocator.cc:49
Node * GetParent() const
Definition node.cc:240
bool IsJoint() const
Definition node.cc:341
Matrix GetLocalTransform() const
Definition node.cc:282
std::shared_ptr< Texture > GetJointsTexture(Allocator &allocator)
Definition skin.cc:65
static std::unique_ptr< Skin > MakeFromFlatbuffer(const fb::Skin &skin, const std::vector< std::shared_ptr< Node > > &scene_nodes)
Definition skin.cc:19
Skin & operator=(Skin &&)
GAsyncResult * result
#define FML_LOG(severity)
Definition logging.h:82
#define FML_DCHECK(condition)
Definition logging.h:103
Matrix ToMatrix(const std::vector< double > &m)
A 4x4 matrix using column-major storage.
Definition matrix.h:37
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
#define ERROR(message)
#define VALIDATION_LOG
Definition validation.h:73