Skip to content

Commit 14a4d8e

Browse files
bderoloic-sharma
authored andcommitted
[Impeller Scene] Node deserialization (flutter#38190)
* [Impeller Scene] Node deserialization * Address comments * Always use RGBA for the placeholder texture * Fix node child update * Temporarily disable test for GLES * Remove GLES test skip
1 parent d2958c4 commit 14a4d8e

File tree

10 files changed

+140
-41
lines changed

10 files changed

+140
-41
lines changed

impeller/scene/geometry.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ std::shared_ptr<VertexBufferGeometry> Geometry::MakeVertexBuffer(
4040
return result;
4141
}
4242

43-
std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFBMeshPrimitive(
43+
std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFlatbuffer(
4444
const fb::MeshPrimitive& mesh,
4545
Allocator& allocator) {
4646
IndexType index_type;

impeller/scene/geometry.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Geometry {
2828
static std::shared_ptr<VertexBufferGeometry> MakeVertexBuffer(
2929
VertexBuffer vertex_buffer);
3030

31-
static std::shared_ptr<VertexBufferGeometry> MakeFromFBMeshPrimitive(
31+
static std::shared_ptr<VertexBufferGeometry> MakeFromFlatbuffer(
3232
const fb::MeshPrimitive& mesh,
3333
Allocator& allocator);
3434

impeller/scene/material.cc

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ namespace scene {
1818
/// Material
1919
///
2020

21+
Material::~Material() = default;
22+
2123
std::unique_ptr<UnlitMaterial> Material::MakeUnlit() {
2224
return std::make_unique<UnlitMaterial>();
2325
}
@@ -47,6 +49,8 @@ SceneContextOptions Material::GetContextOptions(const RenderPass& pass) const {
4749
/// UnlitMaterial
4850
///
4951

52+
UnlitMaterial::~UnlitMaterial() = default;
53+
5054
void UnlitMaterial::SetColor(Color color) {
5155
color_ = color;
5256
}
@@ -94,6 +98,8 @@ void UnlitMaterial::BindToCommand(const SceneContext& scene_context,
9498
/// StandardMaterial
9599
///
96100

101+
StandardMaterial::~StandardMaterial() = default;
102+
97103
void StandardMaterial::SetAlbedo(Color albedo) {
98104
albedo_ = albedo;
99105
}

impeller/scene/material.h

+6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ class StandardMaterial;
2323

2424
class Material {
2525
public:
26+
virtual ~Material();
27+
2628
struct BlendConfig {
2729
BlendOperation color_op = BlendOperation::kAdd;
2830
BlendFactor source_color_factor = BlendFactor::kOne;
@@ -62,6 +64,8 @@ class Material {
6264

6365
class UnlitMaterial final : public Material {
6466
public:
67+
~UnlitMaterial();
68+
6569
void SetColor(Color color);
6670

6771
void SetColorTexture(std::shared_ptr<Texture> color_texture);
@@ -86,6 +90,8 @@ class UnlitMaterial final : public Material {
8690

8791
class StandardMaterial final : public Material {
8892
public:
93+
~StandardMaterial();
94+
8995
void SetAlbedo(Color albedo);
9096
void SetRoughness(Scalar roughness);
9197
void SetMetallic(Scalar metallic);

impeller/scene/mesh.cc

+10-6
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,27 @@ Mesh::Mesh() = default;
1717
Mesh::~Mesh() = default;
1818

1919
void Mesh::AddPrimitive(Primitive mesh) {
20-
if (mesh.geometry_ == nullptr) {
20+
if (mesh.geometry == nullptr) {
2121
VALIDATION_LOG << "Mesh geometry cannot be null.";
2222
}
23-
if (mesh.material_ == nullptr) {
23+
if (mesh.material == nullptr) {
2424
VALIDATION_LOG << "Mesh material cannot be null.";
2525
}
2626

27-
meshes_.push_back(std::move(mesh));
27+
primitives_.push_back(std::move(mesh));
28+
}
29+
30+
std::vector<Mesh::Primitive>& Mesh::GetPrimitives() {
31+
return primitives_;
2832
}
2933

3034
bool Mesh::Render(SceneEncoder& encoder, const Matrix& transform) const {
31-
for (const auto& mesh : meshes_) {
35+
for (const auto& mesh : primitives_) {
3236
SceneCommand command = {
3337
.label = "Mesh Primitive",
3438
.transform = transform,
35-
.geometry = mesh.geometry_.get(),
36-
.material = mesh.material_.get(),
39+
.geometry = mesh.geometry.get(),
40+
.material = mesh.material.get(),
3741
};
3842
encoder.Add(command);
3943
}

impeller/scene/mesh.h

+9-3
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,25 @@ namespace scene {
1818
class Mesh final {
1919
public:
2020
struct Primitive {
21-
std::shared_ptr<Geometry> geometry_;
22-
std::shared_ptr<Material> material_;
21+
std::shared_ptr<Geometry> geometry;
22+
std::shared_ptr<Material> material;
2323
};
2424

2525
Mesh();
2626
~Mesh();
2727

28+
Mesh(Mesh&& mesh);
29+
Mesh& operator=(Mesh&& mesh);
30+
2831
void AddPrimitive(Primitive mesh_);
32+
std::vector<Primitive>& GetPrimitives();
2933

3034
bool Render(SceneEncoder& encoder, const Matrix& transform) const;
3135

3236
private:
33-
std::vector<Primitive> meshes_;
37+
std::vector<Primitive> primitives_;
38+
39+
FML_DISALLOW_COPY_AND_ASSIGN(Mesh);
3440
};
3541

3642
} // namespace scene

impeller/scene/node.cc

+78-5
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,70 @@
88

99
#include "impeller/base/validation.h"
1010
#include "impeller/geometry/matrix.h"
11+
#include "impeller/scene/importer/scene_flatbuffers.h"
1112
#include "impeller/scene/mesh.h"
1213
#include "impeller/scene/node.h"
1314
#include "impeller/scene/scene_encoder.h"
1415

1516
namespace impeller {
1617
namespace scene {
1718

19+
std::optional<Node> Node::MakeFromFlatbuffer(fml::Mapping& mapping,
20+
Allocator& allocator) {
21+
flatbuffers::Verifier verifier(mapping.GetMapping(), mapping.GetSize());
22+
if (!fb::VerifySceneBuffer(verifier)) {
23+
return std::nullopt;
24+
}
25+
26+
return Node::MakeFromFlatbuffer(*fb::GetScene(mapping.GetMapping()),
27+
allocator);
28+
}
29+
30+
Node Node::MakeFromFlatbuffer(const fb::Scene& scene, Allocator& allocator) {
31+
Node result;
32+
33+
if (!scene.children()) {
34+
return result;
35+
}
36+
for (const auto* child : *scene.children()) {
37+
result.AddChild(Node::MakeFromFlatbuffer(*child, allocator));
38+
}
39+
40+
return result;
41+
}
42+
43+
Node Node::MakeFromFlatbuffer(const fb::Node& node, Allocator& allocator) {
44+
Node result;
45+
46+
Mesh mesh;
47+
for (const auto* primitives : *node.mesh_primitives()) {
48+
auto geometry = Geometry::MakeFromFlatbuffer(*primitives, allocator);
49+
mesh.AddPrimitive({geometry, Material::MakeUnlit()});
50+
}
51+
result.SetMesh(std::move(mesh));
52+
53+
if (!node.children()) {
54+
return result;
55+
}
56+
for (const auto* child : *node.children()) {
57+
result.AddChild(Node::MakeFromFlatbuffer(*child, allocator));
58+
}
59+
60+
return result;
61+
}
62+
1863
Node::Node() = default;
1964

2065
Node::~Node() = default;
2166

67+
Mesh::Mesh(Mesh&& mesh) = default;
68+
69+
Mesh& Mesh::operator=(Mesh&& mesh) = default;
70+
71+
Node::Node(Node&& node) = default;
72+
73+
Node& Node::operator=(Node&& node) = default;
74+
2275
void Node::SetLocalTransform(Matrix transform) {
2376
local_transform_ = transform;
2477
}
@@ -41,13 +94,33 @@ Matrix Node::GetGlobalTransform() const {
4194
return local_transform_;
4295
}
4396

44-
void Node::AddChild(Node child) {
45-
children_.push_back(child);
46-
child.parent_ = this;
97+
bool Node::AddChild(Node node) {
98+
if (node.parent_ != nullptr) {
99+
VALIDATION_LOG
100+
<< "Cannot add a node as a child which already has a parent.";
101+
return false;
102+
}
103+
node.parent_ = this;
104+
children_.push_back(std::move(node));
105+
106+
Node& ref = children_.back();
107+
for (Node& child : ref.children_) {
108+
child.parent_ = &ref;
109+
}
110+
111+
return true;
112+
}
113+
114+
std::vector<Node>& Node::GetChildren() {
115+
return children_;
116+
}
117+
118+
void Node::SetMesh(Mesh mesh) {
119+
mesh_ = std::move(mesh);
47120
}
48121

49-
void Node::SetMesh(const Mesh& mesh) {
50-
mesh_ = mesh;
122+
Mesh& Node::GetMesh() {
123+
return mesh_;
51124
}
52125

53126
bool Node::Render(SceneEncoder& encoder, const Matrix& parent_transform) const {

impeller/scene/node.h

+14-2
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,28 @@ namespace scene {
2020

2121
class Node final {
2222
public:
23+
static std::optional<Node> MakeFromFlatbuffer(fml::Mapping& mapping,
24+
Allocator& allocator);
25+
static Node MakeFromFlatbuffer(const fb::Scene& scene, Allocator& allocator);
26+
static Node MakeFromFlatbuffer(const fb::Node& node, Allocator& allocator);
27+
2328
Node();
2429
~Node();
2530

31+
Node(Node&& node);
32+
Node& operator=(Node&& node);
33+
2634
void SetLocalTransform(Matrix transform);
2735
Matrix GetLocalTransform() const;
2836

2937
void SetGlobalTransform(Matrix transform);
3038
Matrix GetGlobalTransform() const;
3139

32-
void AddChild(Node child);
40+
bool AddChild(Node child);
41+
std::vector<Node>& GetChildren();
3342

34-
void SetMesh(const Mesh& mesh);
43+
void SetMesh(Mesh mesh);
44+
Mesh& GetMesh();
3545

3646
bool Render(SceneEncoder& encoder, const Matrix& parent_transform) const;
3747

@@ -42,6 +52,8 @@ class Node final {
4252
Node* parent_ = nullptr;
4353
std::vector<Node> children_;
4454
Mesh mesh_;
55+
56+
FML_DISALLOW_COPY_AND_ASSIGN(Node);
4557
};
4658

4759
} // namespace scene

impeller/scene/scene_context.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ SceneContext::SceneContext(std::shared_ptr<Context> context)
4949
{
5050
impeller::TextureDescriptor texture_descriptor;
5151
texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
52-
texture_descriptor.format = PixelFormat::kDefaultColor;
52+
texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
5353
texture_descriptor.size = {1, 1};
5454
texture_descriptor.mip_count = 1u;
5555

impeller/scene/scene_unittests.cc

+14-22
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ TEST_P(SceneTest, CuboidUnlit) {
4747

4848
Node& root = scene.GetRoot();
4949
root.SetLocalTransform(Matrix::MakeTranslation(-size / 2));
50-
root.SetMesh(mesh);
50+
root.SetMesh(std::move(mesh));
5151
}
5252

5353
// Face towards the +Z direction (+X right, +Y up).
@@ -70,34 +70,26 @@ TEST_P(SceneTest, GLTFScene) {
7070

7171
auto mapping =
7272
flutter::testing::OpenFixtureAsMapping("flutter_logo.glb.ipscene");
73+
ASSERT_NE(mapping, nullptr);
7374

74-
flatbuffers::Verifier verifier(mapping->GetMapping(), mapping->GetSize());
75-
ASSERT_TRUE(fb::VerifySceneBuffer(verifier));
76-
77-
// TODO(bdero): Add full scene deserialization utilities.
78-
const auto* fb_scene = fb::GetScene(mapping->GetMapping());
79-
const auto fb_nodes = fb_scene->children();
80-
ASSERT_EQ(fb_nodes->size(), 1u);
81-
const auto fb_meshes = fb_nodes->begin()->mesh_primitives();
82-
ASSERT_EQ(fb_meshes->size(), 1u);
83-
const auto* fb_mesh = fb_meshes->Get(0);
84-
auto geometry = Geometry::MakeFromFBMeshPrimitive(*fb_mesh, *allocator);
85-
ASSERT_NE(geometry, nullptr);
75+
std::optional<Node> gltf_scene =
76+
Node::MakeFromFlatbuffer(*mapping, *allocator);
77+
ASSERT_TRUE(gltf_scene.has_value());
8678

8779
std::shared_ptr<UnlitMaterial> material = Material::MakeUnlit();
88-
auto bridge = CreateTextureForFixture("flutter_logo_baked.png");
89-
material->SetColorTexture(bridge);
80+
auto color_baked = CreateTextureForFixture("flutter_logo_baked.png");
81+
material->SetColorTexture(color_baked);
9082
material->SetVertexColorWeight(0);
9183

92-
Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
93-
auto scene = Scene(GetContext());
84+
ASSERT_EQ(gltf_scene->GetChildren().size(), 1u);
85+
ASSERT_EQ(gltf_scene->GetChildren()[0].GetMesh().GetPrimitives().size(), 1u);
86+
gltf_scene->GetChildren()[0].GetMesh().GetPrimitives()[0].material = material;
9487

95-
Mesh mesh;
96-
mesh.AddPrimitive({geometry, material});
97-
98-
scene.GetRoot().SetLocalTransform(Matrix::MakeScale({3, 3, 3}));
99-
scene.GetRoot().SetMesh(mesh);
88+
auto scene = Scene(GetContext());
89+
scene.GetRoot().AddChild(std::move(gltf_scene.value()));
90+
scene.GetRoot().SetLocalTransform(Matrix::MakeScale({3, 3, 3}));
10091

92+
Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
10193
Quaternion rotation({0, 1, 0}, -GetSecondsElapsed() * 0.5);
10294
Vector3 start_position(-1, -1.5, -5);
10395

0 commit comments

Comments
 (0)