blob: ab7a5f7617463f8c4f38c424795c6bad0349e1e3 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/scene/node.h"
#include <memory>
#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;
}
Matrix Node::GetLocalTransform() const {
return local_transform_;
}
void Node::SetGlobalTransform(Matrix transform) {
Matrix inverse_global_transform =
parent_ ? parent_->GetGlobalTransform().Invert() : Matrix();
local_transform_ = inverse_global_transform * transform;
}
Matrix Node::GetGlobalTransform() const {
if (parent_) {
return parent_->GetGlobalTransform() * local_transform_;
}
return local_transform_;
}
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);
}
Mesh& Node::GetMesh() {
return mesh_;
}
bool Node::Render(SceneEncoder& encoder, const Matrix& parent_transform) const {
Matrix transform = parent_transform * local_transform_;
mesh_.Render(encoder, transform);
for (auto& child : children_) {
if (!child.Render(encoder, transform)) {
return false;
}
}
return true;
}
} // namespace scene
} // namespace impeller