Skip to content

Commit

Permalink
[Impeller Scene] Node deserialization (flutter#38190)
Browse files Browse the repository at this point in the history
* [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
  • Loading branch information
bdero authored and loic-sharma committed Dec 16, 2022
1 parent 6ac22d0 commit 3e30e6f
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 41 deletions.
2 changes: 1 addition & 1 deletion impeller/scene/geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ std::shared_ptr<VertexBufferGeometry> Geometry::MakeVertexBuffer(
return result;
}

std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFBMeshPrimitive(
std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFlatbuffer(
const fb::MeshPrimitive& mesh,
Allocator& allocator) {
IndexType index_type;
Expand Down
2 changes: 1 addition & 1 deletion impeller/scene/geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Geometry {
static std::shared_ptr<VertexBufferGeometry> MakeVertexBuffer(
VertexBuffer vertex_buffer);

static std::shared_ptr<VertexBufferGeometry> MakeFromFBMeshPrimitive(
static std::shared_ptr<VertexBufferGeometry> MakeFromFlatbuffer(
const fb::MeshPrimitive& mesh,
Allocator& allocator);

Expand Down
6 changes: 6 additions & 0 deletions impeller/scene/material.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ namespace scene {
/// Material
///

Material::~Material() = default;

std::unique_ptr<UnlitMaterial> Material::MakeUnlit() {
return std::make_unique<UnlitMaterial>();
}
Expand Down Expand Up @@ -47,6 +49,8 @@ SceneContextOptions Material::GetContextOptions(const RenderPass& pass) const {
/// UnlitMaterial
///

UnlitMaterial::~UnlitMaterial() = default;

void UnlitMaterial::SetColor(Color color) {
color_ = color;
}
Expand Down Expand Up @@ -94,6 +98,8 @@ void UnlitMaterial::BindToCommand(const SceneContext& scene_context,
/// StandardMaterial
///

StandardMaterial::~StandardMaterial() = default;

void StandardMaterial::SetAlbedo(Color albedo) {
albedo_ = albedo;
}
Expand Down
6 changes: 6 additions & 0 deletions impeller/scene/material.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class StandardMaterial;

class Material {
public:
virtual ~Material();

struct BlendConfig {
BlendOperation color_op = BlendOperation::kAdd;
BlendFactor source_color_factor = BlendFactor::kOne;
Expand Down Expand Up @@ -62,6 +64,8 @@ class Material {

class UnlitMaterial final : public Material {
public:
~UnlitMaterial();

void SetColor(Color color);

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

class StandardMaterial final : public Material {
public:
~StandardMaterial();

void SetAlbedo(Color albedo);
void SetRoughness(Scalar roughness);
void SetMetallic(Scalar metallic);
Expand Down
16 changes: 10 additions & 6 deletions impeller/scene/mesh.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,27 @@ Mesh::Mesh() = default;
Mesh::~Mesh() = default;

void Mesh::AddPrimitive(Primitive mesh) {
if (mesh.geometry_ == nullptr) {
if (mesh.geometry == nullptr) {
VALIDATION_LOG << "Mesh geometry cannot be null.";
}
if (mesh.material_ == nullptr) {
if (mesh.material == nullptr) {
VALIDATION_LOG << "Mesh material cannot be null.";
}

meshes_.push_back(std::move(mesh));
primitives_.push_back(std::move(mesh));
}

std::vector<Mesh::Primitive>& Mesh::GetPrimitives() {
return primitives_;
}

bool Mesh::Render(SceneEncoder& encoder, const Matrix& transform) const {
for (const auto& mesh : meshes_) {
for (const auto& mesh : primitives_) {
SceneCommand command = {
.label = "Mesh Primitive",
.transform = transform,
.geometry = mesh.geometry_.get(),
.material = mesh.material_.get(),
.geometry = mesh.geometry.get(),
.material = mesh.material.get(),
};
encoder.Add(command);
}
Expand Down
12 changes: 9 additions & 3 deletions impeller/scene/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,25 @@ namespace scene {
class Mesh final {
public:
struct Primitive {
std::shared_ptr<Geometry> geometry_;
std::shared_ptr<Material> material_;
std::shared_ptr<Geometry> geometry;
std::shared_ptr<Material> material;
};

Mesh();
~Mesh();

Mesh(Mesh&& mesh);
Mesh& operator=(Mesh&& mesh);

void AddPrimitive(Primitive mesh_);
std::vector<Primitive>& GetPrimitives();

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

private:
std::vector<Primitive> meshes_;
std::vector<Primitive> primitives_;

FML_DISALLOW_COPY_AND_ASSIGN(Mesh);
};

} // namespace scene
Expand Down
83 changes: 78 additions & 5 deletions impeller/scene/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,70 @@

#include "impeller/base/validation.h"
#include "impeller/geometry/matrix.h"
#include "impeller/scene/importer/scene_flatbuffers.h"
#include "impeller/scene/mesh.h"
#include "impeller/scene/node.h"
#include "impeller/scene/scene_encoder.h"

namespace impeller {
namespace scene {

std::optional<Node> Node::MakeFromFlatbuffer(fml::Mapping& mapping,
Allocator& allocator) {
flatbuffers::Verifier verifier(mapping.GetMapping(), mapping.GetSize());
if (!fb::VerifySceneBuffer(verifier)) {
return std::nullopt;
}

return Node::MakeFromFlatbuffer(*fb::GetScene(mapping.GetMapping()),
allocator);
}

Node Node::MakeFromFlatbuffer(const fb::Scene& scene, Allocator& allocator) {
Node result;

if (!scene.children()) {
return result;
}
for (const auto* child : *scene.children()) {
result.AddChild(Node::MakeFromFlatbuffer(*child, allocator));
}

return result;
}

Node Node::MakeFromFlatbuffer(const fb::Node& node, Allocator& allocator) {
Node result;

Mesh mesh;
for (const auto* primitives : *node.mesh_primitives()) {
auto geometry = Geometry::MakeFromFlatbuffer(*primitives, allocator);
mesh.AddPrimitive({geometry, Material::MakeUnlit()});
}
result.SetMesh(std::move(mesh));

if (!node.children()) {
return result;
}
for (const auto* child : *node.children()) {
result.AddChild(Node::MakeFromFlatbuffer(*child, allocator));
}

return result;
}

Node::Node() = default;

Node::~Node() = default;

Mesh::Mesh(Mesh&& mesh) = default;

Mesh& Mesh::operator=(Mesh&& mesh) = default;

Node::Node(Node&& node) = default;

Node& Node::operator=(Node&& node) = default;

void Node::SetLocalTransform(Matrix transform) {
local_transform_ = transform;
}
Expand All @@ -41,13 +94,33 @@ Matrix Node::GetGlobalTransform() const {
return local_transform_;
}

void Node::AddChild(Node child) {
children_.push_back(child);
child.parent_ = this;
bool Node::AddChild(Node node) {
if (node.parent_ != nullptr) {
VALIDATION_LOG
<< "Cannot add a node as a child which already has a parent.";
return false;
}
node.parent_ = this;
children_.push_back(std::move(node));

Node& ref = children_.back();
for (Node& child : ref.children_) {
child.parent_ = &ref;
}

return true;
}

std::vector<Node>& Node::GetChildren() {
return children_;
}

void Node::SetMesh(Mesh mesh) {
mesh_ = std::move(mesh);
}

void Node::SetMesh(const Mesh& mesh) {
mesh_ = mesh;
Mesh& Node::GetMesh() {
return mesh_;
}

bool Node::Render(SceneEncoder& encoder, const Matrix& parent_transform) const {
Expand Down
16 changes: 14 additions & 2 deletions impeller/scene/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,28 @@ namespace scene {

class Node final {
public:
static std::optional<Node> MakeFromFlatbuffer(fml::Mapping& mapping,
Allocator& allocator);
static Node MakeFromFlatbuffer(const fb::Scene& scene, Allocator& allocator);
static Node MakeFromFlatbuffer(const fb::Node& node, Allocator& allocator);

Node();
~Node();

Node(Node&& node);
Node& operator=(Node&& node);

void SetLocalTransform(Matrix transform);
Matrix GetLocalTransform() const;

void SetGlobalTransform(Matrix transform);
Matrix GetGlobalTransform() const;

void AddChild(Node child);
bool AddChild(Node child);
std::vector<Node>& GetChildren();

void SetMesh(const Mesh& mesh);
void SetMesh(Mesh mesh);
Mesh& GetMesh();

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

Expand All @@ -42,6 +52,8 @@ class Node final {
Node* parent_ = nullptr;
std::vector<Node> children_;
Mesh mesh_;

FML_DISALLOW_COPY_AND_ASSIGN(Node);
};

} // namespace scene
Expand Down
2 changes: 1 addition & 1 deletion impeller/scene/scene_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ SceneContext::SceneContext(std::shared_ptr<Context> context)
{
impeller::TextureDescriptor texture_descriptor;
texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
texture_descriptor.format = PixelFormat::kDefaultColor;
texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
texture_descriptor.size = {1, 1};
texture_descriptor.mip_count = 1u;

Expand Down
36 changes: 14 additions & 22 deletions impeller/scene/scene_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ TEST_P(SceneTest, CuboidUnlit) {

Node& root = scene.GetRoot();
root.SetLocalTransform(Matrix::MakeTranslation(-size / 2));
root.SetMesh(mesh);
root.SetMesh(std::move(mesh));
}

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

auto mapping =
flutter::testing::OpenFixtureAsMapping("flutter_logo.glb.ipscene");
ASSERT_NE(mapping, nullptr);

flatbuffers::Verifier verifier(mapping->GetMapping(), mapping->GetSize());
ASSERT_TRUE(fb::VerifySceneBuffer(verifier));

// TODO(bdero): Add full scene deserialization utilities.
const auto* fb_scene = fb::GetScene(mapping->GetMapping());
const auto fb_nodes = fb_scene->children();
ASSERT_EQ(fb_nodes->size(), 1u);
const auto fb_meshes = fb_nodes->begin()->mesh_primitives();
ASSERT_EQ(fb_meshes->size(), 1u);
const auto* fb_mesh = fb_meshes->Get(0);
auto geometry = Geometry::MakeFromFBMeshPrimitive(*fb_mesh, *allocator);
ASSERT_NE(geometry, nullptr);
std::optional<Node> gltf_scene =
Node::MakeFromFlatbuffer(*mapping, *allocator);
ASSERT_TRUE(gltf_scene.has_value());

std::shared_ptr<UnlitMaterial> material = Material::MakeUnlit();
auto bridge = CreateTextureForFixture("flutter_logo_baked.png");
material->SetColorTexture(bridge);
auto color_baked = CreateTextureForFixture("flutter_logo_baked.png");
material->SetColorTexture(color_baked);
material->SetVertexColorWeight(0);

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

Mesh mesh;
mesh.AddPrimitive({geometry, material});

scene.GetRoot().SetLocalTransform(Matrix::MakeScale({3, 3, 3}));
scene.GetRoot().SetMesh(mesh);
auto scene = Scene(GetContext());
scene.GetRoot().AddChild(std::move(gltf_scene.value()));
scene.GetRoot().SetLocalTransform(Matrix::MakeScale({3, 3, 3}));

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

Expand Down

0 comments on commit 3e30e6f

Please sign in to comment.