From dce50b1f84a2e724fc51d4f2d9bc3e6d4e2ec0d9 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sun, 4 Dec 2022 18:30:24 -0800 Subject: [PATCH 1/7] Bump buildroot --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index b0cf330bfedf6..86c410bf6003a 100644 --- a/DEPS +++ b/DEPS @@ -236,7 +236,7 @@ allowed_hosts = [ ] deps = { - 'src': 'https://github.com/flutter/buildroot.git' + '@' + '8747bce41d0dc6d9dc45c4d1b46d2100bb9ee688', + 'src': 'https://github.com/flutter/buildroot.git' + '@' + '908edab91bffdea18876868b20bef94f44746d21', # Fuchsia compatibility # From 09bb0199fa464d0239c8e825bf3f8f08cf6b3329 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sun, 4 Dec 2022 22:00:42 -0800 Subject: [PATCH 2/7] [Impeller Scene] Parse GLTF geometry --- ci/licenses_golden/licenses_flutter | 7 +- impeller/BUILD.gn | 1 + impeller/fixtures/BUILD.gn | 1 + impeller/scene/importer/BUILD.gn | 28 ++- impeller/scene/importer/conversions.cc | 81 +++++++ impeller/scene/importer/conversions.h | 47 ++++ impeller/scene/importer/importer.h | 4 +- impeller/scene/importer/importer_gltf.cc | 201 +++++++++++++++++- impeller/scene/importer/importer_unittests.cc | 55 +++++ impeller/scene/importer/mesh.fbs | 37 ---- impeller/scene/importer/scene.fbs | 72 +++++++ impeller/scene/importer/scenec_main.cc | 6 +- impeller/scene/importer/vertices_builder.cc | 107 ++++++++++ impeller/scene/importer/vertices_builder.h | 72 +++++++ 14 files changed, 666 insertions(+), 53 deletions(-) create mode 100644 impeller/scene/importer/conversions.cc create mode 100644 impeller/scene/importer/conversions.h create mode 100644 impeller/scene/importer/importer_unittests.cc delete mode 100644 impeller/scene/importer/mesh.fbs create mode 100644 impeller/scene/importer/scene.fbs create mode 100644 impeller/scene/importer/vertices_builder.cc create mode 100644 impeller/scene/importer/vertices_builder.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 951638d5c9eda..ea0738c72c1b3 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1648,13 +1648,18 @@ FILE: ../../../flutter/impeller/scene/camera.cc FILE: ../../../flutter/impeller/scene/camera.h FILE: ../../../flutter/impeller/scene/geometry.cc FILE: ../../../flutter/impeller/scene/geometry.h +FILE: ../../../flutter/impeller/scene/importer/conversions.cc +FILE: ../../../flutter/impeller/scene/importer/conversions.h FILE: ../../../flutter/impeller/scene/importer/importer.h FILE: ../../../flutter/impeller/scene/importer/importer_gltf.cc -FILE: ../../../flutter/impeller/scene/importer/mesh.fbs +FILE: ../../../flutter/impeller/scene/importer/importer_unittests.cc +FILE: ../../../flutter/impeller/scene/importer/scene.fbs FILE: ../../../flutter/impeller/scene/importer/scenec_main.cc FILE: ../../../flutter/impeller/scene/importer/switches.cc FILE: ../../../flutter/impeller/scene/importer/switches.h FILE: ../../../flutter/impeller/scene/importer/types.h +FILE: ../../../flutter/impeller/scene/importer/vertices_builder.cc +FILE: ../../../flutter/impeller/scene/importer/vertices_builder.h FILE: ../../../flutter/impeller/scene/material.cc FILE: ../../../flutter/impeller/scene/material.h FILE: ../../../flutter/impeller/scene/scene.cc diff --git a/impeller/BUILD.gn b/impeller/BUILD.gn index 2920b94f91949..496ec8c9c498b 100644 --- a/impeller/BUILD.gn +++ b/impeller/BUILD.gn @@ -74,6 +74,7 @@ impeller_component("impeller_unittests") { "compiler:compiler_unittests", "geometry:geometry_unittests", "runtime_stage:runtime_stage_unittests", + "scene/importer:importer_unittests", "tessellator:tessellator_unittests", ] diff --git a/impeller/fixtures/BUILD.gn b/impeller/fixtures/BUILD.gn index 055110133720d..d0a17e970781d 100644 --- a/impeller/fixtures/BUILD.gn +++ b/impeller/fixtures/BUILD.gn @@ -58,6 +58,7 @@ test_fixtures("file_fixtures") { "blue_noise.png", "boston.jpg", "embarcadero.jpg", + "flutter_logo.glb", "kalimba.jpg", "multiple_stages.hlsl", "resources_limit.vert", diff --git a/impeller/scene/importer/BUILD.gn b/impeller/scene/importer/BUILD.gn index f7ec98c0f5f38..87b9946cb636e 100644 --- a/impeller/scene/importer/BUILD.gn +++ b/impeller/scene/importer/BUILD.gn @@ -12,22 +12,26 @@ config("runtime_stage_config") { } flatbuffers("importer_flatbuffers") { - flatbuffers = [ "mesh.fbs" ] + flatbuffers = [ "scene.fbs" ] public_configs = [ ":runtime_stage_config" ] public_deps = [ "//third_party/flatbuffers" ] } -impeller_component("scenec_lib") { +impeller_component("importer_lib") { # Current versions of libcxx have deprecated some of the UTF-16 string # conversion APIs. defines = [ "_LIBCPP_DISABLE_DEPRECATION_WARNINGS" ] sources = [ + "conversions.cc", + "conversions.h", "importer.h", "importer_gltf.cc", "switches.cc", "switches.h", "types.h", + "vertices_builder.cc", + "vertices_builder.h", ] public_deps = [ @@ -39,8 +43,7 @@ impeller_component("scenec_lib") { # All third_party deps must be reflected below in the scenec_license # target. - # TODO(bdero): Fix tinygltf compilation warnings. - #"//third_party/tinygltf", + "//third_party/tinygltf", ] } @@ -85,9 +88,24 @@ impeller_component("scenec") { sources = [ "scenec_main.cc" ] - deps = [ ":scenec_lib" ] + deps = [ ":importer_lib" ] metadata = { entitlement_file_path = [ "scenec" ] } } + +impeller_component("importer_unittests") { + testonly = true + + output_name = "scenec_unittests" + + sources = [ "importer_unittests.cc" ] + + deps = [ + ":importer_lib", + "../../fixtures", + "../../geometry:geometry_unittests", + "//flutter/testing:testing_lib", + ] +} diff --git a/impeller/scene/importer/conversions.cc b/impeller/scene/importer/conversions.cc new file mode 100644 index 0000000000000..21966cb8fbf91 --- /dev/null +++ b/impeller/scene/importer/conversions.cc @@ -0,0 +1,81 @@ + +// 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/importer/conversions.h" + +#include + +#include "impeller/scene/importer/scene_flatbuffers.h" + +namespace impeller { +namespace scene { +namespace importer { + +Matrix ToMatrix(const std::vector& m) { + return Matrix(m[0], m[1], m[2], m[3], // + m[4], m[5], m[6], m[7], // + m[8], m[9], m[10], m[11], // + m[12], m[13], m[14], m[15]); +} + +//----------------------------------------------------------------------------- +/// Flatbuffers -> Impeller +/// + +Matrix ToMatrix(const fb::Matrix& m) { + auto& a = *m.m(); + return Matrix(a[0], a[1], a[2], a[3], // + a[4], a[5], a[6], a[7], // + a[8], a[9], a[10], a[11], // + a[12], a[13], a[14], a[15]); +} + +Vector2 ToVector2(const fb::Vec2& v) { + return Vector2(v.x(), v.y()); +} + +Vector3 ToVector3(const fb::Vec3& v) { + return Vector3(v.x(), v.y(), v.z()); +} + +Vector4 ToVector4(const fb::Vec4& v) { + return Vector4(v.x(), v.y(), v.z(), v.w()); +} + +Color ToColor(const fb::Color& c) { + return Color(c.r(), c.g(), c.b(), c.a()); +} + +//----------------------------------------------------------------------------- +/// Impeller -> Flatbuffers +/// + +std::unique_ptr ToFBMatrix(const Matrix& m) { + auto array = std::array{m.m[0], m.m[1], m.m[2], m.m[3], // + m.m[4], m.m[5], m.m[6], m.m[7], // + m.m[8], m.m[9], m.m[10], m.m[11], // + m.m[12], m.m[13], m.m[14], m.m[15]}; + return std::make_unique(array); +} + +fb::Vec2 ToFBVec2(const Vector2 v) { + return fb::Vec2(v.x, v.y); +} + +fb::Vec3 ToFBVec3(const Vector3 v) { + return fb::Vec3(v.x, v.y, v.z); +} + +fb::Vec4 ToFBVec4(const Vector4 v) { + return fb::Vec4(v.x, v.y, v.z, v.w); +} + +fb::Color ToFBColor(const Color c) { + return fb::Color(c.red, c.green, c.blue, c.alpha); +} + +} // namespace importer +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/importer/conversions.h b/impeller/scene/importer/conversions.h new file mode 100644 index 0000000000000..1aa07d20b3450 --- /dev/null +++ b/impeller/scene/importer/conversions.h @@ -0,0 +1,47 @@ +// 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 +#include + +#include "impeller/geometry/matrix.h" +#include "impeller/scene/importer/scene_flatbuffers.h" + +namespace impeller { +namespace scene { +namespace importer { + +Matrix ToMatrix(const std::vector& m); + +//----------------------------------------------------------------------------- +/// Flatbuffers -> Impeller +/// + +Matrix ToMatrix(const fb::Matrix& m); + +Vector2 ToVector2(const fb::Vec2& c); + +Vector3 ToVector3(const fb::Vec3& c); + +Vector4 ToVector4(const fb::Vec4& c); + +Color ToColor(const fb::Color& c); + +//----------------------------------------------------------------------------- +/// Impeller -> Flatbuffers +/// + +std::unique_ptr ToFBMatrix(const Matrix& m); + +fb::Vec2 ToFBVec2(const Vector2 v); + +fb::Vec3 ToFBVec3(const Vector3 v); + +fb::Vec4 ToFBVec4(const Vector4 v); + +fb::Color ToFBColor(const Color c); + +} // namespace importer +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/importer/importer.h b/impeller/scene/importer/importer.h index 69abcf90d510f..a786f89c1398a 100644 --- a/impeller/scene/importer/importer.h +++ b/impeller/scene/importer/importer.h @@ -6,13 +6,13 @@ #include #include "flutter/fml/mapping.h" -#include "impeller/scene/importer/mesh_flatbuffers.h" +#include "impeller/scene/importer/scene_flatbuffers.h" namespace impeller { namespace scene { namespace importer { -bool ParseGLTF(const fml::Mapping& source_mapping, fb::MeshT& out_mesh); +bool ParseGLTF(const fml::Mapping& source_mapping, fb::SceneT& out_scene); } } // namespace scene diff --git a/impeller/scene/importer/importer_gltf.cc b/impeller/scene/importer/importer_gltf.cc index b39831a6eba32..c0e7e8194cc98 100644 --- a/impeller/scene/importer/importer_gltf.cc +++ b/impeller/scene/importer/importer_gltf.cc @@ -2,20 +2,211 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "impeller/scene/importer/importer.h" + #include +#include +#include +#include #include - -#include "impeller/scene/importer/importer.h" +#include #include "flutter/fml/mapping.h" +#include "impeller/geometry/matrix.h" +#include "impeller/scene/importer/conversions.h" +#include "impeller/scene/importer/scene_flatbuffers.h" +#include "impeller/scene/importer/vertices_builder.h" +#include "third_party/tinygltf/tiny_gltf.h" namespace impeller { namespace scene { namespace importer { -bool ParseGLTF(const fml::Mapping& source_mapping, fb::MeshT& out_mesh) { - // TODO(bdero): Parse source_mapping and populare out_mesh with just the first - // mesh in the GLTF. +static const std::map kAttributes = { + {"POSITION", VerticesBuilder::Attribute::kPosition}, + {"NORMAL", VerticesBuilder::Attribute::kNormal}, + {"TANGENT", VerticesBuilder::Attribute::kTangent}, + {"TEXCOORD_0", VerticesBuilder::Attribute::kTextureCoords}, + {"COLOR_0", VerticesBuilder::Attribute::kColor}, +}; + +static bool WithinRange(int index, size_t size) { + return index >= 0 && static_cast(index) < size; +} + +static bool ProcessStaticMesh(const tinygltf::Model& gltf, + const tinygltf::Primitive& primitive, + fb::StaticMeshT& static_mesh) { + //--------------------------------------------------------------------------- + /// Vertices. + /// + + { + VerticesBuilder builder; + + for (const auto& attribute : primitive.attributes) { + auto attribute_type = kAttributes.find(attribute.first); + if (attribute_type == kAttributes.end()) { + std::cerr << "Vertex attribute \"" << attribute.first + << "\" not supported." << std::endl; + continue; + } + + const auto accessor = gltf.accessors[attribute.second]; + const auto view = gltf.bufferViews[accessor.bufferView]; + + const auto buffer = gltf.buffers[view.buffer]; + const unsigned char* source_start = &buffer.data[view.byteOffset]; + + VerticesBuilder::ComponentType type; + switch (accessor.componentType) { + case TINYGLTF_COMPONENT_TYPE_BYTE: + type = VerticesBuilder::ComponentType::kSignedByte; + break; + case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE: + type = VerticesBuilder::ComponentType::kUnsignedByte; + break; + case TINYGLTF_COMPONENT_TYPE_SHORT: + type = VerticesBuilder::ComponentType::kSignedShort; + break; + case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT: + type = VerticesBuilder::ComponentType::kUnsignedShort; + break; + case TINYGLTF_COMPONENT_TYPE_INT: + type = VerticesBuilder::ComponentType::kSignedInt; + break; + case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT: + type = VerticesBuilder::ComponentType::kUnsignedInt; + break; + case TINYGLTF_COMPONENT_TYPE_FLOAT: + type = VerticesBuilder::ComponentType::kFloat; + break; + default: + std::cerr << "Skipping attribute \"" << attribute.first + << "\" due to invalid component type." << std::endl; + continue; + } + + builder.SetAttributeFromBuffer(attribute_type->second, // attribute + type, // component_type + source_start, // buffer_start + accessor.ByteStride(view), // stride_bytes + accessor.count); // count + } + + builder.WriteFBVertices(static_mesh.vertices); + } + + //--------------------------------------------------------------------------- + /// Indices. + /// + + if (!WithinRange(primitive.indices, gltf.accessors.size())) { + std::cout << "Mesh primitive has no index buffer. Skipping." << std::endl; + return false; + } + + auto index_accessor = gltf.accessors[primitive.indices]; + auto index_view = gltf.bufferViews[index_accessor.bufferView]; + static_mesh.indices.resize(index_accessor.count); + const auto* index_buffer = + &gltf.buffers[index_view.buffer].data[index_view.byteOffset]; + std::memcpy(static_mesh.indices.data(), index_buffer, index_view.byteLength); + + return true; +} + +static void ProcessNode(const tinygltf::Model& gltf, + const tinygltf::Node& in_node, + fb::NodeT& out_node) { + //--------------------------------------------------------------------------- + /// Transform. + /// + + Matrix transform; + if (in_node.translation.size() == 3) { + transform = transform * Matrix::MakeTranslation( + {static_cast(in_node.translation[0]), + static_cast(in_node.translation[0]), + static_cast(in_node.translation[0])}); + } + if (in_node.rotation.size() == 4) { + transform = transform * Matrix::MakeRotation(Quaternion( + in_node.rotation[0], in_node.rotation[1], + in_node.rotation[2], in_node.rotation[3])); + } + if (in_node.scale.size() == 3) { + transform = + transform * Matrix::MakeScale({static_cast(in_node.scale[0]), + static_cast(in_node.scale[1]), + static_cast(in_node.scale[2])}); + } + if (in_node.matrix.size() == 16) { + if (!transform.IsIdentity()) { + std::cerr << "The `matrix` attribute of node (name: " << in_node.name + << ") is set in addition to one or more of the " + "`translation/rotation/scale` attributes. Using only the " + "`matrix` " + "attribute."; + } + transform = ToMatrix(in_node.matrix); + } + out_node.transform = ToFBMatrix(transform); + + //--------------------------------------------------------------------------- + /// Static meshes. + /// + + if (WithinRange(in_node.mesh, gltf.meshes.size())) { + auto& mesh = gltf.meshes[in_node.mesh]; + for (const auto& primitive : mesh.primitives) { + auto static_mesh = std::make_unique(); + if (!ProcessStaticMesh(gltf, primitive, *static_mesh)) { + continue; + } + out_node.meshes.push_back(std::move(static_mesh)); + } + } + + //--------------------------------------------------------------------------- + /// Children. + /// + + for (size_t node_i = 0; node_i < out_node.children.size(); node_i++) { + auto child = std::make_unique(); + ProcessNode(gltf, gltf.nodes[in_node.children[node_i]], *child); + out_node.children.push_back(std::move(child)); + } +} + +bool ParseGLTF(const fml::Mapping& source_mapping, fb::SceneT& out_scene) { + tinygltf::Model gltf; + + { + tinygltf::TinyGLTF loader; + std::string error; + std::string warning; + bool success = loader.LoadBinaryFromMemory(&gltf, &error, &warning, + source_mapping.GetMapping(), + source_mapping.GetSize()); + if (!warning.empty()) { + std::cerr << "Warning while loading GLTF: " << warning << std::endl; + } + if (!error.empty()) { + std::cerr << "Error while loading GLTF: " << error << std::endl; + } + if (!success) { + return false; + } + } + + const tinygltf::Scene& scene = gltf.scenes[gltf.defaultScene]; + for (size_t node_i = 0; node_i < scene.nodes.size(); node_i++) { + auto node = std::make_unique(); + ProcessNode(gltf, gltf.nodes[scene.nodes[node_i]], *node); + out_scene.children.push_back(std::move(node)); + } + return true; } diff --git a/impeller/scene/importer/importer_unittests.cc b/impeller/scene/importer/importer_unittests.cc new file mode 100644 index 0000000000000..5a8accc0dfb39 --- /dev/null +++ b/impeller/scene/importer/importer_unittests.cc @@ -0,0 +1,55 @@ +// 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 "flutter/testing/testing.h" +#include "impeller/geometry/geometry_unittests.h" +#include "impeller/geometry/matrix.h" +#include "impeller/scene/importer/conversions.h" +#include "impeller/scene/importer/importer.h" +#include "impeller/scene/importer/scene_flatbuffers.h" + +namespace impeller { +namespace scene { +namespace importer { +namespace testing { + +TEST(ImporterTest, CanParseGLTF) { + auto mapping = flutter::testing::OpenFixtureAsMapping("flutter_logo.glb"); + + fb::SceneT scene; + ASSERT_TRUE(ParseGLTF(*mapping, scene)); + + ASSERT_EQ(scene.children.size(), 1u); + auto& node = *scene.children[0]; + + Matrix node_transform = ToMatrix(*node.transform); + ASSERT_MATRIX_NEAR(node_transform, Matrix()); + + ASSERT_EQ(node.meshes.size(), 1u); + auto& mesh = *node.meshes[0]; + ASSERT_EQ(mesh.indices.size(), 918u); + + ASSERT_EQ(mesh.vertices.size(), 260u); + auto& vertex = mesh.vertices[0]; + + Vector3 position = ToVector3(vertex.position()); + ASSERT_VECTOR3_NEAR(position, Vector3(-0.0100185, -0.522907, 0.133178)); + + Vector3 normal = ToVector3(vertex.normal()); + ASSERT_VECTOR3_NEAR(normal, Vector3(0.556997, -0.810833, 0.179733)); + + Vector4 tangent = ToVector4(vertex.tangent()); + ASSERT_VECTOR4_NEAR(tangent, Vector4(0.155901, -0.110485, -0.981574, 1)); + + Vector2 texture_coords = ToVector2(vertex.texture_coords()); + ASSERT_POINT_NEAR(texture_coords, Vector2(0.727937, 0.713817)); + + Color color = ToColor(vertex.color()); + ASSERT_COLOR_NEAR(color, Color(0.0221714, 0.467781, 0.921584, 1)); +} + +} // namespace testing +} // namespace importer +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/importer/mesh.fbs b/impeller/scene/importer/mesh.fbs deleted file mode 100644 index 87044f1527a0c..0000000000000 --- a/impeller/scene/importer/mesh.fbs +++ /dev/null @@ -1,37 +0,0 @@ -// 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. - -namespace impeller.fb; - -struct Vec2 { - x: float; - y: float; -} - -struct Vec3 { - x: float; - y: float; - z: float; -} - -struct Color { - r: float; - g: float; - b: float; -} - -struct Vertex { - position: Vec3; - normal: Vec3; - tangent: Vec3; - texture_coords: Vec2; -} - -table Mesh { - vertices: [Vertex]; - indices: [uint16]; -} - -root_type Mesh; -file_identifier "IPME"; diff --git a/impeller/scene/importer/scene.fbs b/impeller/scene/importer/scene.fbs new file mode 100644 index 0000000000000..f998be4858efc --- /dev/null +++ b/impeller/scene/importer/scene.fbs @@ -0,0 +1,72 @@ +// 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. + +namespace impeller.fb; + +struct Vec2 { + x: float; + y: float; +} + +struct Vec3 { + x: float; + y: float; + z: float; +} + +struct Vec4 { + x: float; + y: float; + z: float; + w: float; +} + +struct Color { + r: float; + g: float; + b: float; + a: float; +} + +struct Matrix { + m: [float:16]; +} + +struct Vertex { + position: Vec3; + normal: Vec3; + tangent: Vec4; // The 4th component determines the handedness of the tangent. + texture_coords: Vec2; + color: Color; +} + +table Texture { + // TODO(bdero): Allow optional image data embedding. + uri: string; +} + +table Material { + base_color_factor: Color; + base_color_texture: Texture; + // TODO(bdero): PBR textures. +} + +table StaticMesh { + vertices: [Vertex]; + indices: [uint32]; + material: Material; +} + +table Node { + children: [Node]; + transform: Matrix; + meshes: [StaticMesh]; +} + +table Scene { + children: [Node]; +} + +root_type Scene; +file_identifier "IPSC"; diff --git a/impeller/scene/importer/scenec_main.cc b/impeller/scene/importer/scenec_main.cc index 52538d6c2585f..73d0982798971 100644 --- a/impeller/scene/importer/scenec_main.cc +++ b/impeller/scene/importer/scenec_main.cc @@ -58,11 +58,11 @@ bool Main(const fml::CommandLine& command_line) { return false; } - fb::MeshT mesh; + fb::SceneT scene; bool success = false; switch (switches.input_type) { case SourceType::kGLTF: - success = ParseGLTF(*source_file_mapping, mesh); + success = ParseGLTF(*source_file_mapping, scene); break; case SourceType::kUnknown: std::cerr << "Unknown input type." << std::endl; @@ -74,7 +74,7 @@ bool Main(const fml::CommandLine& command_line) { } flatbuffers::FlatBufferBuilder builder; - builder.Finish(fb::Mesh::Pack(builder, &mesh)); + builder.Finish(fb::Scene::Pack(builder, &scene)); auto output_file_name = std::filesystem::absolute( std::filesystem::current_path() / switches.output_file_name); diff --git a/impeller/scene/importer/vertices_builder.cc b/impeller/scene/importer/vertices_builder.cc new file mode 100644 index 0000000000000..9c72f4b50fbe7 --- /dev/null +++ b/impeller/scene/importer/vertices_builder.cc @@ -0,0 +1,107 @@ + +// 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/importer/vertices_builder.h" + +#include +#include + +#include "impeller/scene/importer/conversions.h" +#include "impeller/scene/importer/scene_flatbuffers.h" + +namespace impeller { +namespace scene { +namespace importer { + +VerticesBuilder::VerticesBuilder() = default; + +std::map + VerticesBuilder::kAttributes = { + {VerticesBuilder::Attribute::kPosition, + {.offset_bytes = offsetof(Vertex, position), + .size_bytes = sizeof(Vertex::position), + .component_count = 3}}, + {VerticesBuilder::Attribute::kNormal, + {.offset_bytes = offsetof(Vertex, normal), + .size_bytes = sizeof(Vertex::normal), + .component_count = 3}}, + {VerticesBuilder::Attribute::kTangent, + {.offset_bytes = offsetof(Vertex, tangent), + .size_bytes = sizeof(Vertex::tangent), + .component_count = 4}}, + {VerticesBuilder::Attribute::kTextureCoords, + {.offset_bytes = offsetof(Vertex, texture_coords), + .size_bytes = sizeof(Vertex::texture_coords), + .component_count = 2}}, + {VerticesBuilder::Attribute::kColor, + {.offset_bytes = offsetof(Vertex, color), + .size_bytes = sizeof(Vertex::color), + .component_count = 4}}}; + +void VerticesBuilder::WriteFBVertices(std::vector& vertices) const { + vertices.resize(0); + for (auto& v : vertices_) { + vertices.push_back(fb::Vertex( + ToFBVec3(v.position), ToFBVec3(v.normal), ToFBVec4(v.tangent), + ToFBVec2(v.texture_coords), ToFBColor(v.color))); + } +} + +template +void WriteScalars(void* destination, + const void* source, + size_t component_count) { + for (size_t i = 0; i < component_count; i++) { + const SourceType* s = reinterpret_cast(source) + i; + Scalar v = static_cast(*s) / Divisor; + Scalar* dest = reinterpret_cast(destination) + i; + *dest = v; + } +} + +static std::map< + VerticesBuilder::ComponentType, + std::function< + void(void* destination, const void* source, size_t component_count)>> + kAttributeWriters = { + {VerticesBuilder::ComponentType::kSignedByte, + WriteScalars::max()>}, + {VerticesBuilder::ComponentType::kUnsignedByte, + WriteScalars::max()>}, + {VerticesBuilder::ComponentType::kSignedShort, + WriteScalars::max()>}, + {VerticesBuilder::ComponentType::kUnsignedShort, + WriteScalars::max()>}, + {VerticesBuilder::ComponentType::kSignedInt, + WriteScalars::max()>}, + {VerticesBuilder::ComponentType::kUnsignedInt, + WriteScalars::max()>}, + {VerticesBuilder::ComponentType::kFloat, WriteScalars}, +}; + +void VerticesBuilder::SetAttributeFromBuffer(Attribute attribute, + ComponentType component_type, + const void* buffer_start, + size_t stride_bytes, + size_t count) { + if (count > vertices_.size()) { + vertices_.resize(count, Vertex()); + } + + const auto& properties = kAttributes[attribute]; + const auto& writer = kAttributeWriters[component_type]; + for (size_t i = 0; i < count; i++) { + const char* source = + reinterpret_cast(buffer_start) + stride_bytes * i; + char* destination = + reinterpret_cast(&vertices_.data()[i]) + properties.offset_bytes; + + writer(destination, source, properties.component_count); + } +} + +} // namespace importer +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/importer/vertices_builder.h b/impeller/scene/importer/vertices_builder.h new file mode 100644 index 0000000000000..e5b0180889420 --- /dev/null +++ b/impeller/scene/importer/vertices_builder.h @@ -0,0 +1,72 @@ +// 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 +#include + +#include "flutter/fml/macros.h" +#include "impeller/geometry/matrix.h" +#include "impeller/scene/importer/scene_flatbuffers.h" + +namespace impeller { +namespace scene { +namespace importer { + +class VerticesBuilder { + public: + enum class Attribute { + kPosition, + kNormal, + kTangent, + kTextureCoords, + kColor, + }; + + enum class ComponentType { + kSignedByte = 5120, + kUnsignedByte, + kSignedShort, + kUnsignedShort, + kSignedInt, + kUnsignedInt, + kFloat, + }; + + VerticesBuilder(); + + void WriteFBVertices(std::vector& vertices) const; + + void SetAttributeFromBuffer(Attribute attribute, + ComponentType component_type, + const void* buffer_start, + size_t stride_bytes, + size_t count); + + private: + struct AttributeProperties { + size_t offset_bytes; + size_t size_bytes; + size_t component_count; + }; + + static std::map + kAttributes; + + struct Vertex { + Vector3 position; + Vector3 normal; + Vector4 tangent; + Vector2 texture_coords; + Color color = Color::White(); + }; + + std::vector vertices_; + + FML_DISALLOW_COPY_AND_ASSIGN(VerticesBuilder); +}; + +} // namespace importer +} // namespace scene +} // namespace impeller From a9d668e5db4b95385cee1feab3f7474b85befeca Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sun, 4 Dec 2022 23:17:52 -0800 Subject: [PATCH 3/7] Add Divisor cast --- impeller/scene/importer/vertices_builder.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impeller/scene/importer/vertices_builder.cc b/impeller/scene/importer/vertices_builder.cc index 9c72f4b50fbe7..c9d650645b345 100644 --- a/impeller/scene/importer/vertices_builder.cc +++ b/impeller/scene/importer/vertices_builder.cc @@ -55,7 +55,7 @@ void WriteScalars(void* destination, size_t component_count) { for (size_t i = 0; i < component_count; i++) { const SourceType* s = reinterpret_cast(source) + i; - Scalar v = static_cast(*s) / Divisor; + Scalar v = static_cast(*s) / static_cast(Divisor); Scalar* dest = reinterpret_cast(destination) + i; *dest = v; } From c34e1923228e46b726ec122fce595c56f4191c14 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Mon, 5 Dec 2022 10:38:18 -0800 Subject: [PATCH 4/7] Address comments --- impeller/scene/importer/conversions.cc | 1 - impeller/scene/importer/conversions.h | 2 ++ impeller/scene/importer/importer.h | 2 ++ impeller/scene/importer/importer_gltf.cc | 2 +- impeller/scene/importer/vertices_builder.cc | 17 ++++++++--------- impeller/scene/importer/vertices_builder.h | 2 ++ 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/impeller/scene/importer/conversions.cc b/impeller/scene/importer/conversions.cc index 21966cb8fbf91..7031ed3ba7ccd 100644 --- a/impeller/scene/importer/conversions.cc +++ b/impeller/scene/importer/conversions.cc @@ -1,4 +1,3 @@ - // 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. diff --git a/impeller/scene/importer/conversions.h b/impeller/scene/importer/conversions.h index 1aa07d20b3450..9388e7ed4b79d 100644 --- a/impeller/scene/importer/conversions.h +++ b/impeller/scene/importer/conversions.h @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#pragma once + #include #include diff --git a/impeller/scene/importer/importer.h b/impeller/scene/importer/importer.h index a786f89c1398a..6766adbce19da 100644 --- a/impeller/scene/importer/importer.h +++ b/impeller/scene/importer/importer.h @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#pragma once + #include #include diff --git a/impeller/scene/importer/importer_gltf.cc b/impeller/scene/importer/importer_gltf.cc index c0e7e8194cc98..0edbe7ea3402b 100644 --- a/impeller/scene/importer/importer_gltf.cc +++ b/impeller/scene/importer/importer_gltf.cc @@ -102,7 +102,7 @@ static bool ProcessStaticMesh(const tinygltf::Model& gltf, /// if (!WithinRange(primitive.indices, gltf.accessors.size())) { - std::cout << "Mesh primitive has no index buffer. Skipping." << std::endl; + std::cerr << "Mesh primitive has no index buffer. Skipping." << std::endl; return false; } diff --git a/impeller/scene/importer/vertices_builder.cc b/impeller/scene/importer/vertices_builder.cc index c9d650645b345..b4395a0e9b2cf 100644 --- a/impeller/scene/importer/vertices_builder.cc +++ b/impeller/scene/importer/vertices_builder.cc @@ -1,4 +1,3 @@ - // 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. @@ -50,7 +49,7 @@ void VerticesBuilder::WriteFBVertices(std::vector& vertices) const { } template -void WriteScalars(void* destination, +void WriteComponentsAsScalars(void* destination, const void* source, size_t component_count) { for (size_t i = 0; i < component_count; i++) { @@ -67,18 +66,18 @@ static std::map< void(void* destination, const void* source, size_t component_count)>> kAttributeWriters = { {VerticesBuilder::ComponentType::kSignedByte, - WriteScalars::max()>}, + WriteComponentsAsScalars::max()>}, {VerticesBuilder::ComponentType::kUnsignedByte, - WriteScalars::max()>}, + WriteComponentsAsScalars::max()>}, {VerticesBuilder::ComponentType::kSignedShort, - WriteScalars::max()>}, + WriteComponentsAsScalars::max()>}, {VerticesBuilder::ComponentType::kUnsignedShort, - WriteScalars::max()>}, + WriteComponentsAsScalars::max()>}, {VerticesBuilder::ComponentType::kSignedInt, - WriteScalars::max()>}, + WriteComponentsAsScalars::max()>}, {VerticesBuilder::ComponentType::kUnsignedInt, - WriteScalars::max()>}, - {VerticesBuilder::ComponentType::kFloat, WriteScalars}, + WriteComponentsAsScalars::max()>}, + {VerticesBuilder::ComponentType::kFloat, WriteComponentsAsScalars}, }; void VerticesBuilder::SetAttributeFromBuffer(Attribute attribute, diff --git a/impeller/scene/importer/vertices_builder.h b/impeller/scene/importer/vertices_builder.h index e5b0180889420..1ff3d42894964 100644 --- a/impeller/scene/importer/vertices_builder.h +++ b/impeller/scene/importer/vertices_builder.h @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#pragma once + #include #include From ab0bb2f41c9b36b7f4c2f6f8bf1bb97c062218e8 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Mon, 5 Dec 2022 10:56:17 -0800 Subject: [PATCH 5/7] Improve scalar conversion mechanism --- impeller/scene/importer/vertices_builder.cc | 33 +++++++++++++-------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/impeller/scene/importer/vertices_builder.cc b/impeller/scene/importer/vertices_builder.cc index b4395a0e9b2cf..fe8edf18d3f82 100644 --- a/impeller/scene/importer/vertices_builder.cc +++ b/impeller/scene/importer/vertices_builder.cc @@ -6,6 +6,7 @@ #include #include +#include #include "impeller/scene/importer/conversions.h" #include "impeller/scene/importer/scene_flatbuffers.h" @@ -48,13 +49,20 @@ void VerticesBuilder::WriteFBVertices(std::vector& vertices) const { } } -template -void WriteComponentsAsScalars(void* destination, - const void* source, - size_t component_count) { +/// @brief Reads a contiguous sequence of numeric components from `source` and +/// writes them to `destination` buffer as 32bit floats. Signed +/// SourceTypes convert to a range of -1 to 1, and unsigned SourceTypes +/// convert to a range of 0 to 1. +template +static void WriteComponentsAsScalars(void* destination, + const void* source, + size_t component_count) { + constexpr size_t divisor = std::is_integral_v + ? std::numeric_limits::max() + : 1; for (size_t i = 0; i < component_count; i++) { const SourceType* s = reinterpret_cast(source) + i; - Scalar v = static_cast(*s) / static_cast(Divisor); + Scalar v = static_cast(*s) / static_cast(divisor); Scalar* dest = reinterpret_cast(destination) + i; *dest = v; } @@ -66,18 +74,19 @@ static std::map< void(void* destination, const void* source, size_t component_count)>> kAttributeWriters = { {VerticesBuilder::ComponentType::kSignedByte, - WriteComponentsAsScalars::max()>}, + WriteComponentsAsScalars}, {VerticesBuilder::ComponentType::kUnsignedByte, - WriteComponentsAsScalars::max()>}, + WriteComponentsAsScalars}, {VerticesBuilder::ComponentType::kSignedShort, - WriteComponentsAsScalars::max()>}, + WriteComponentsAsScalars}, {VerticesBuilder::ComponentType::kUnsignedShort, - WriteComponentsAsScalars::max()>}, + WriteComponentsAsScalars}, {VerticesBuilder::ComponentType::kSignedInt, - WriteComponentsAsScalars::max()>}, + WriteComponentsAsScalars}, {VerticesBuilder::ComponentType::kUnsignedInt, - WriteComponentsAsScalars::max()>}, - {VerticesBuilder::ComponentType::kFloat, WriteComponentsAsScalars}, + WriteComponentsAsScalars}, + {VerticesBuilder::ComponentType::kFloat, + WriteComponentsAsScalars}, }; void VerticesBuilder::SetAttributeFromBuffer(Attribute attribute, From 8e807cb87a21174ea492e04a4bba9b38a3de887d Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Mon, 5 Dec 2022 11:01:40 -0800 Subject: [PATCH 6/7] Use source type for divisor --- impeller/scene/importer/vertices_builder.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/impeller/scene/importer/vertices_builder.cc b/impeller/scene/importer/vertices_builder.cc index fe8edf18d3f82..11ec1c009e4dc 100644 --- a/impeller/scene/importer/vertices_builder.cc +++ b/impeller/scene/importer/vertices_builder.cc @@ -57,9 +57,9 @@ template static void WriteComponentsAsScalars(void* destination, const void* source, size_t component_count) { - constexpr size_t divisor = std::is_integral_v - ? std::numeric_limits::max() - : 1; + constexpr SourceType divisor = std::is_integral_v + ? std::numeric_limits::max() + : 1; for (size_t i = 0; i < component_count; i++) { const SourceType* s = reinterpret_cast(source) + i; Scalar v = static_cast(*s) / static_cast(divisor); From c917e708601535b524c8ad9963efe244d8c50b77 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Mon, 5 Dec 2022 11:10:36 -0800 Subject: [PATCH 7/7] Better wording --- impeller/scene/importer/vertices_builder.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/impeller/scene/importer/vertices_builder.cc b/impeller/scene/importer/vertices_builder.cc index 11ec1c009e4dc..d08268df4fdf9 100644 --- a/impeller/scene/importer/vertices_builder.cc +++ b/impeller/scene/importer/vertices_builder.cc @@ -50,9 +50,9 @@ void VerticesBuilder::WriteFBVertices(std::vector& vertices) const { } /// @brief Reads a contiguous sequence of numeric components from `source` and -/// writes them to `destination` buffer as 32bit floats. Signed -/// SourceTypes convert to a range of -1 to 1, and unsigned SourceTypes -/// convert to a range of 0 to 1. +/// writes them to `destination` as 32bit floats. Signed SourceTypes +/// convert to a range of -1 to 1, and unsigned SourceTypes convert to a +/// range of 0 to 1. template static void WriteComponentsAsScalars(void* destination, const void* source,