Skip to content

Commit 8951b0c

Browse files
bderoloic-sharma
authored andcommitted
[Impeller Scene] Import skinned mesh vertex data (flutter#38554)
1 parent e78f246 commit 8951b0c

11 files changed

+498
-118
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,6 +1635,7 @@ ORIGIN: ../../../flutter/impeller/scene/scene_context.cc + ../../../flutter/LICE
16351635
ORIGIN: ../../../flutter/impeller/scene/scene_context.h + ../../../flutter/LICENSE
16361636
ORIGIN: ../../../flutter/impeller/scene/scene_encoder.cc + ../../../flutter/LICENSE
16371637
ORIGIN: ../../../flutter/impeller/scene/scene_encoder.h + ../../../flutter/LICENSE
1638+
ORIGIN: ../../../flutter/impeller/scene/shaders/skinned.vert + ../../../flutter/LICENSE
16381639
ORIGIN: ../../../flutter/impeller/scene/shaders/unlit.frag + ../../../flutter/LICENSE
16391640
ORIGIN: ../../../flutter/impeller/scene/shaders/unskinned.vert + ../../../flutter/LICENSE
16401641
ORIGIN: ../../../flutter/impeller/tessellator/c/tessellator.cc + ../../../flutter/LICENSE
@@ -4094,6 +4095,7 @@ FILE: ../../../flutter/impeller/scene/scene_context.cc
40944095
FILE: ../../../flutter/impeller/scene/scene_context.h
40954096
FILE: ../../../flutter/impeller/scene/scene_encoder.cc
40964097
FILE: ../../../flutter/impeller/scene/scene_encoder.h
4098+
FILE: ../../../flutter/impeller/scene/shaders/skinned.vert
40974099
FILE: ../../../flutter/impeller/scene/shaders/unlit.frag
40984100
FILE: ../../../flutter/impeller/scene/shaders/unskinned.vert
40994101
FILE: ../../../flutter/impeller/tessellator/c/tessellator.cc

impeller/scene/geometry.cc

Lines changed: 90 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "impeller/renderer/vertex_buffer.h"
1616
#include "impeller/renderer/vertex_buffer_builder.h"
1717
#include "impeller/scene/importer/scene_flatbuffers.h"
18+
#include "impeller/scene/shaders/skinned.vert.h"
1819
#include "impeller/scene/shaders/unskinned.vert.h"
1920

2021
namespace impeller {
@@ -32,14 +33,20 @@ std::shared_ptr<CuboidGeometry> Geometry::MakeCuboid(Vector3 size) {
3233
return result;
3334
}
3435

35-
std::shared_ptr<VertexBufferGeometry> Geometry::MakeVertexBuffer(
36-
VertexBuffer vertex_buffer) {
37-
auto result = std::make_shared<VertexBufferGeometry>();
38-
result->SetVertexBuffer(std::move(vertex_buffer));
39-
return result;
36+
std::shared_ptr<Geometry> Geometry::MakeVertexBuffer(VertexBuffer vertex_buffer,
37+
bool is_skinned) {
38+
if (is_skinned) {
39+
auto result = std::make_shared<SkinnedVertexBufferGeometry>();
40+
result->SetVertexBuffer(std::move(vertex_buffer));
41+
return result;
42+
} else {
43+
auto result = std::make_shared<UnskinnedVertexBufferGeometry>();
44+
result->SetVertexBuffer(std::move(vertex_buffer));
45+
return result;
46+
}
4047
}
4148

42-
std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFlatbuffer(
49+
std::shared_ptr<Geometry> Geometry::MakeFromFlatbuffer(
4350
const fb::MeshPrimitive& mesh,
4451
Allocator& allocator) {
4552
IndexType index_type;
@@ -52,17 +59,34 @@ std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFlatbuffer(
5259
break;
5360
}
5461

55-
if (mesh.vertices_type() == fb::VertexBuffer::SkinnedVertexBuffer) {
56-
VALIDATION_LOG << "Skinned meshes not yet supported.";
57-
return nullptr;
58-
}
59-
if (mesh.vertices_type() != fb::VertexBuffer::UnskinnedVertexBuffer) {
60-
VALIDATION_LOG << "Invalid vertex buffer type.";
61-
return nullptr;
62+
const uint8_t* vertices_start;
63+
size_t vertices_bytes;
64+
bool is_skinned;
65+
66+
switch (mesh.vertices_type()) {
67+
case fb::VertexBuffer::UnskinnedVertexBuffer: {
68+
const auto* vertices =
69+
mesh.vertices_as_UnskinnedVertexBuffer()->vertices();
70+
vertices_start = reinterpret_cast<const uint8_t*>(vertices->Get(0));
71+
vertices_bytes = vertices->size() * sizeof(fb::Vertex);
72+
is_skinned = false;
73+
break;
74+
}
75+
case fb::VertexBuffer::SkinnedVertexBuffer: {
76+
const auto* vertices = mesh.vertices_as_SkinnedVertexBuffer()->vertices();
77+
vertices_start = reinterpret_cast<const uint8_t*>(vertices->Get(0));
78+
vertices_bytes = vertices->size() * sizeof(fb::SkinnedVertex);
79+
is_skinned = true;
80+
break;
81+
}
82+
case fb::VertexBuffer::NONE:
83+
VALIDATION_LOG << "Invalid vertex buffer type.";
84+
return nullptr;
6285
}
6386

64-
const auto* vertices = mesh.vertices_as_UnskinnedVertexBuffer()->vertices();
65-
const size_t vertices_bytes = vertices->size() * sizeof(fb::Vertex);
87+
const uint8_t* indices_start =
88+
reinterpret_cast<const uint8_t*>(mesh.indices()->data()->Data());
89+
6690
const size_t indices_bytes = mesh.indices()->data()->size();
6791
if (vertices_bytes == 0 || indices_bytes == 0) {
6892
return nullptr;
@@ -75,11 +99,6 @@ std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFlatbuffer(
7599
auto buffer = allocator.CreateBuffer(buffer_desc);
76100
buffer->SetLabel("Mesh vertices+indices");
77101

78-
const uint8_t* vertices_start =
79-
reinterpret_cast<const uint8_t*>(vertices->Get(0));
80-
const uint8_t* indices_start =
81-
reinterpret_cast<const uint8_t*>(mesh.indices()->data()->Data());
82-
83102
if (!buffer->CopyHostBuffer(vertices_start, Range(0, vertices_bytes))) {
84103
return nullptr;
85104
}
@@ -95,7 +114,7 @@ std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFlatbuffer(
95114
.index_count = mesh.indices()->count(),
96115
.index_type = index_type,
97116
};
98-
return MakeVertexBuffer(std::move(vertex_buffer));
117+
return MakeVertexBuffer(std::move(vertex_buffer), is_skinned);
99118
}
100119

101120
//------------------------------------------------------------------------------
@@ -151,32 +170,35 @@ void CuboidGeometry::BindToCommand(const SceneContext& scene_context,
151170
}
152171

153172
//------------------------------------------------------------------------------
154-
/// VertexBufferGeometry
173+
/// UnskinnedVertexBufferGeometry
155174
///
156175

157-
VertexBufferGeometry::VertexBufferGeometry() = default;
176+
UnskinnedVertexBufferGeometry::UnskinnedVertexBufferGeometry() = default;
158177

159-
VertexBufferGeometry::~VertexBufferGeometry() = default;
178+
UnskinnedVertexBufferGeometry::~UnskinnedVertexBufferGeometry() = default;
160179

161-
void VertexBufferGeometry::SetVertexBuffer(VertexBuffer vertex_buffer) {
180+
void UnskinnedVertexBufferGeometry::SetVertexBuffer(
181+
VertexBuffer vertex_buffer) {
162182
vertex_buffer_ = std::move(vertex_buffer);
163183
}
164184

165185
// |Geometry|
166-
GeometryType VertexBufferGeometry::GetGeometryType() const {
186+
GeometryType UnskinnedVertexBufferGeometry::GetGeometryType() const {
167187
return GeometryType::kUnskinned;
168188
}
169189

170190
// |Geometry|
171-
VertexBuffer VertexBufferGeometry::GetVertexBuffer(Allocator& allocator) const {
191+
VertexBuffer UnskinnedVertexBufferGeometry::GetVertexBuffer(
192+
Allocator& allocator) const {
172193
return vertex_buffer_;
173194
}
174195

175196
// |Geometry|
176-
void VertexBufferGeometry::BindToCommand(const SceneContext& scene_context,
177-
HostBuffer& buffer,
178-
const Matrix& transform,
179-
Command& command) const {
197+
void UnskinnedVertexBufferGeometry::BindToCommand(
198+
const SceneContext& scene_context,
199+
HostBuffer& buffer,
200+
const Matrix& transform,
201+
Command& command) const {
180202
command.BindVertices(
181203
GetVertexBuffer(*scene_context.GetContext()->GetResourceAllocator()));
182204

@@ -185,5 +207,42 @@ void VertexBufferGeometry::BindToCommand(const SceneContext& scene_context,
185207
UnskinnedVertexShader::BindVertInfo(command, buffer.EmplaceUniform(info));
186208
}
187209

210+
//------------------------------------------------------------------------------
211+
/// SkinnedVertexBufferGeometry
212+
///
213+
214+
SkinnedVertexBufferGeometry::SkinnedVertexBufferGeometry() = default;
215+
216+
SkinnedVertexBufferGeometry::~SkinnedVertexBufferGeometry() = default;
217+
218+
void SkinnedVertexBufferGeometry::SetVertexBuffer(VertexBuffer vertex_buffer) {
219+
vertex_buffer_ = std::move(vertex_buffer);
220+
}
221+
222+
// |Geometry|
223+
GeometryType SkinnedVertexBufferGeometry::GetGeometryType() const {
224+
return GeometryType::kSkinned;
225+
}
226+
227+
// |Geometry|
228+
VertexBuffer SkinnedVertexBufferGeometry::GetVertexBuffer(
229+
Allocator& allocator) const {
230+
return vertex_buffer_;
231+
}
232+
233+
// |Geometry|
234+
void SkinnedVertexBufferGeometry::BindToCommand(
235+
const SceneContext& scene_context,
236+
HostBuffer& buffer,
237+
const Matrix& transform,
238+
Command& command) const {
239+
command.BindVertices(
240+
GetVertexBuffer(*scene_context.GetContext()->GetResourceAllocator()));
241+
242+
SkinnedVertexShader::VertInfo info;
243+
info.mvp = transform;
244+
SkinnedVertexShader::BindVertInfo(command, buffer.EmplaceUniform(info));
245+
}
246+
188247
} // namespace scene
189248
} // namespace impeller

impeller/scene/geometry.h

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,18 @@ namespace impeller {
2222
namespace scene {
2323

2424
class CuboidGeometry;
25-
class VertexBufferGeometry;
25+
class UnskinnedVertexBufferGeometry;
2626

2727
class Geometry {
2828
public:
2929
virtual ~Geometry();
3030

3131
static std::shared_ptr<CuboidGeometry> MakeCuboid(Vector3 size);
3232

33-
static std::shared_ptr<VertexBufferGeometry> MakeVertexBuffer(
34-
VertexBuffer vertex_buffer);
33+
static std::shared_ptr<Geometry> MakeVertexBuffer(VertexBuffer vertex_buffer,
34+
bool is_skinned);
3535

36-
static std::shared_ptr<VertexBufferGeometry> MakeFromFlatbuffer(
36+
static std::shared_ptr<Geometry> MakeFromFlatbuffer(
3737
const fb::MeshPrimitive& mesh,
3838
Allocator& allocator);
3939

@@ -73,11 +73,11 @@ class CuboidGeometry final : public Geometry {
7373
FML_DISALLOW_COPY_AND_ASSIGN(CuboidGeometry);
7474
};
7575

76-
class VertexBufferGeometry final : public Geometry {
76+
class UnskinnedVertexBufferGeometry final : public Geometry {
7777
public:
78-
VertexBufferGeometry();
78+
UnskinnedVertexBufferGeometry();
7979

80-
~VertexBufferGeometry() override;
80+
~UnskinnedVertexBufferGeometry() override;
8181

8282
void SetVertexBuffer(VertexBuffer vertex_buffer);
8383

@@ -96,7 +96,33 @@ class VertexBufferGeometry final : public Geometry {
9696
private:
9797
VertexBuffer vertex_buffer_;
9898

99-
FML_DISALLOW_COPY_AND_ASSIGN(VertexBufferGeometry);
99+
FML_DISALLOW_COPY_AND_ASSIGN(UnskinnedVertexBufferGeometry);
100+
};
101+
102+
class SkinnedVertexBufferGeometry final : public Geometry {
103+
public:
104+
SkinnedVertexBufferGeometry();
105+
106+
~SkinnedVertexBufferGeometry() override;
107+
108+
void SetVertexBuffer(VertexBuffer vertex_buffer);
109+
110+
// |Geometry|
111+
GeometryType GetGeometryType() const override;
112+
113+
// |Geometry|
114+
VertexBuffer GetVertexBuffer(Allocator& allocator) const override;
115+
116+
// |Geometry|
117+
void BindToCommand(const SceneContext& scene_context,
118+
HostBuffer& buffer,
119+
const Matrix& transform,
120+
Command& command) const override;
121+
122+
private:
123+
VertexBuffer vertex_buffer_;
124+
125+
FML_DISALLOW_COPY_AND_ASSIGN(SkinnedVertexBufferGeometry);
100126
};
101127

102128
} // namespace scene

impeller/scene/importer/importer_gltf.cc

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,19 @@ static const std::map<std::string, VerticesBuilder::AttributeType> kAttributes =
2727
{"NORMAL", VerticesBuilder::AttributeType::kNormal},
2828
{"TANGENT", VerticesBuilder::AttributeType::kTangent},
2929
{"TEXCOORD_0", VerticesBuilder::AttributeType::kTextureCoords},
30-
{"COLOR_0", VerticesBuilder::AttributeType::kColor}};
30+
{"COLOR_0", VerticesBuilder::AttributeType::kColor},
31+
{"JOINTS_0", VerticesBuilder::AttributeType::kJoints},
32+
{"WEIGHTS_0", VerticesBuilder::AttributeType::kWeights}};
3133

3234
static bool WithinRange(int index, size_t size) {
3335
return index >= 0 && static_cast<size_t>(index) < size;
3436
}
3537

38+
static bool MeshPrimitiveIsSkinned(const tinygltf::Primitive& primitive) {
39+
return primitive.attributes.find("JOINTS_0") != primitive.attributes.end() &&
40+
primitive.attributes.find("WEIGHTS_0") != primitive.attributes.end();
41+
}
42+
3643
static bool ProcessMeshPrimitive(const tinygltf::Model& gltf,
3744
const tinygltf::Primitive& primitive,
3845
fb::MeshPrimitiveT& mesh_primitive) {
@@ -41,7 +48,10 @@ static bool ProcessMeshPrimitive(const tinygltf::Model& gltf,
4148
///
4249

4350
{
44-
VerticesBuilder builder;
51+
bool is_skinned = MeshPrimitiveIsSkinned(primitive);
52+
std::unique_ptr<VerticesBuilder> builder =
53+
is_skinned ? VerticesBuilder::MakeSkinned()
54+
: VerticesBuilder::MakeUnskinned();
4555

4656
for (const auto& attribute : primitive.attributes) {
4757
auto attribute_type = kAttributes.find(attribute.first);
@@ -50,6 +60,14 @@ static bool ProcessMeshPrimitive(const tinygltf::Model& gltf,
5060
<< "\" not supported." << std::endl;
5161
continue;
5262
}
63+
if (!is_skinned &&
64+
(attribute_type->second == VerticesBuilder::AttributeType::kJoints ||
65+
attribute_type->second ==
66+
VerticesBuilder::AttributeType::kWeights)) {
67+
// If the primitive doesn't have enough information to be skinned, skip
68+
// skinning-related attributes.
69+
continue;
70+
}
5371

5472
const auto accessor = gltf.accessors[attribute.second];
5573
const auto view = gltf.bufferViews[accessor.bufferView];
@@ -86,14 +104,15 @@ static bool ProcessMeshPrimitive(const tinygltf::Model& gltf,
86104
continue;
87105
}
88106

89-
builder.SetAttributeFromBuffer(attribute_type->second, // attribute
90-
type, // component_type
91-
source_start, // buffer_start
92-
accessor.ByteStride(view), // stride_bytes
93-
accessor.count); // count
107+
builder->SetAttributeFromBuffer(
108+
attribute_type->second, // attribute
109+
type, // component_type
110+
source_start, // buffer_start
111+
accessor.ByteStride(view), // stride_bytes
112+
accessor.count); // count
94113
}
95114

96-
builder.WriteFBVertices(mesh_primitive);
115+
builder->WriteFBVertices(mesh_primitive);
97116
}
98117

99118
//---------------------------------------------------------------------------

0 commit comments

Comments
 (0)