Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[Impeller Scene] Node deserialization #38190

Merged
merged 6 commits into from
Dec 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: const

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one's intentionally mutable.


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

private:
std::vector<Primitive> meshes_;
std::vector<Primitive> primitives_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: DISALLOW_COPY_AND_ASSIGN

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


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