| Flutter Impeller |

Namespaces | Classes | Enumerations | Functions | Variables
impeller::scene::importer Namespace Reference

## Namespaces
| testing

## Classes
class | SkinnedVerticesBuilder
struct | Switches
class | UnskinnedVerticesBuilder
class | VerticesBuilder

## Enumerations
enum | SourceType { SourceType::kUnknown, SourceType::kGLTF }

## Functions
Matrix | ToMatrix (const std::vector< double > &m)
Matrix | ToMatrix (const fb::Matrix &m)
Vector2 | ToVector2 (const fb::Vec2 &v)
Vector3 | ToVector3 (const fb::Vec3 &v)
Vector4 | ToVector4 (const fb::Vec4 &v)
Color | ToColor (const fb::Color &c)
fb::Matrix | ToFBMatrix (const Matrix &m)
std::unique_ptr< fb::Matrix > | ToFBMatrixUniquePtr (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)
std::unique_ptr< fb::Color > | ToFBColor (const std::vector< double > &c)
bool | ParseGLTF (const fml::Mapping &source_mapping, fb::SceneT &out_scene)
static bool | WithinRange (int index, size_t size)
static bool | MeshPrimitiveIsSkinned (const tinygltf::Primitive &primitive)
static void | ProcessMaterial (const tinygltf::Model &gltf, const tinygltf::Material &in_material, fb::MaterialT &out_material)
static bool | ProcessMeshPrimitive (const tinygltf::Model &gltf, const tinygltf::Primitive &primitive, fb::MeshPrimitiveT &mesh_primitive)
static void | ProcessNode (const tinygltf::Model &gltf, const tinygltf::Node &in_node, fb::NodeT &out_node)
static void | ProcessTexture (const tinygltf::Model &gltf, const tinygltf::Texture &in_texture, fb::TextureT &out_texture)
static void | ProcessAnimation (const tinygltf::Model &gltf, const tinygltf::Animation &in_animation, fb::AnimationT &out_animation)
static bool | SetPermissiveAccess (const std::filesystem::path &p)
bool | Main (const fml::CommandLine &command_line)
static SourceType | SourceTypeFromCommandLine (const fml::CommandLine &command_line)
template<typename SourceType >
static Scalar | ToScalar (const void *source, size_t index, bool normalized)
| Reads a numeric component from `source` and returns a 32bit float. If `normalized` is `true`, signed SourceTypes convert to a range of -1 to 1, and unsigned SourceTypes convert to a range of 0 to 1. More...
static void | PassthroughAttributeWriter (Scalar *destination, const void *source, const VerticesBuilder::ComponentProperties &component, const VerticesBuilder::AttributeProperties &attribute)
| A ComponentWriter which simply converts all of an attribute's components to normalized scalar form. More...
static void | JointsAttributeWriter (Scalar *destination, const void *source, const VerticesBuilder::ComponentProperties &component, const VerticesBuilder::AttributeProperties &attribute)
| A ComponentWriter which converts four vertex indices to scalars. More...

## Variables
static const std::map< std::string, VerticesBuilder::AttributeType > | kAttributes
static const std::map< std::string, SourceType > | kKnownSourceTypes
static std::map< VerticesBuilder::ComponentType, VerticesBuilder::ComponentProperties > | kComponentTypes

## Enumeration Type Documentation

## ◆ SourceType

enum impeller::scene::importer::SourceType
| strong

Enumerator
kUnknown |
kGLTF |

Definition at line 12 of file types.h.

12 {
13 kUnknown,
14 kGLTF,
15 };

## Function Documentation

## ◆ JointsAttributeWriter()

static void impeller::scene::importer::JointsAttributeWriter | ( | Scalar * | destination,
|  | const void * | source,
|  | const VerticesBuilder::ComponentProperties & | component,
|  | const VerticesBuilder::AttributeProperties & | attribute
| ) |  |
| static

A ComponentWriter which converts four vertex indices to scalars.

Definition at line 70 of file vertices_builder.cc.

74 {
75 FML_DCHECK(attribute.component_count == 4);
76 for (int i = 0; i < 4; i++) {
77 *(destination + i) = component.convert_proc(source, i, false);
78 }
79 }

References impeller::scene::importer::VerticesBuilder::AttributeProperties::component_count, and impeller::scene::importer::VerticesBuilder::ComponentProperties::convert_proc.

## ◆ Main()

bool impeller::scene::importer::Main | ( | const fml::CommandLine & | command_line | ) |

Definition at line 41 of file scenec_main.cc.

41 {
42 fml::InstallCrashHandler();
43 if (command_line.HasOption("help")) {
44 Switches::PrintHelp(std::cout);
45 return true;
46 }
47
48 Switches switches(command_line);
49 if (!switches.AreValid(std::cerr)) {
50 std::cerr << "Invalid flags specified." << std::endl;
51 Switches::PrintHelp(std::cerr);
52 return false;
53 }
54
55 auto source_file_mapping =
56 fml::FileMapping::CreateReadOnly(switches.source_file_name);
57 if (!source_file_mapping) {
58 std::cerr << "Could not open input file." << std::endl;
59 return false;
60 }
61
62 fb::SceneT scene;
63 bool success = false;
64 switch (switches.input_type) {
65 case SourceType::kGLTF:
66 success = ParseGLTF(*source_file_mapping, scene);
67 break;
68 case SourceType::kUnknown:
69 std::cerr << "Unknown input type." << std::endl;
70 return false;
71 }
72 if (!success) {
73 std::cerr << "Failed to parse input file." << std::endl;
74 return false;
75 }
76
77 flatbuffers::FlatBufferBuilder builder;
78 builder.Finish(fb::Scene::Pack(builder, &scene), fb::SceneIdentifier());
79
80 auto output_file_name = std::filesystem::absolute(
81 std::filesystem::current_path() / switches.output_file_name);
82 fml::NonOwnedMapping mapping(builder.GetCurrentBufferPointer(),
83 builder.GetSize());
84 if (!fml::WriteAtomically(*switches.working_directory,
85 compiler::Utf8FromPath(output_file_name).c_str(),
86 mapping)) {
87 std::cerr << "Could not write file to " << switches.output_file_name
88 << std::endl;
89 return false;
90 }
91
92 // Tools that consume the geometry data expect the access mode to be 0644.
93 if (!SetPermissiveAccess(output_file_name)) {
94 return false;
95 }
96
97 return true;
98 }

References impeller::scene::importer::Switches::AreValid(), impeller::scene::importer::Switches::input_type, kGLTF, kUnknown, impeller::scene::importer::Switches::output_file_name, ParseGLTF(), impeller::scene::importer::Switches::PrintHelp(), SetPermissiveAccess(), impeller::scene::importer::Switches::source_file_name, impeller::compiler::Utf8FromPath(), and impeller::scene::importer::Switches::working_directory.

Referenced by main().

## ◆ MeshPrimitiveIsSkinned()

static bool impeller::scene::importer::MeshPrimitiveIsSkinned | ( | const tinygltf::Primitive & | primitive | ) |
| static

Definition at line 39 of file importer_gltf.cc.

39 {
40 return primitive.attributes.find("JOINTS_0") != primitive.attributes.end() &&
41 primitive.attributes.find("WEIGHTS_0") != primitive.attributes.end();
42 }

Referenced by ProcessMeshPrimitive().

## ◆ ParseGLTF()

bool impeller::scene::importer::ParseGLTF | ( | const fml::Mapping & | source_mapping,
|  | fb::SceneT & | out_scene
| ) |  |

Definition at line 450 of file importer_gltf.cc.

450 {
451 tinygltf::Model gltf;
452
453 {
454 tinygltf::TinyGLTF loader;
455 std::string error;
456 std::string warning;
457 bool success = loader.LoadBinaryFromMemory(&gltf, &error, &warning,
458 source_mapping.GetMapping(),
459 source_mapping.GetSize());
460 if (!warning.empty()) {
461 std::cerr << "Warning while loading GLTF: " << warning << std::endl;
462 }
463 if (!error.empty()) {
464 std::cerr << "Error while loading GLTF: " << error << std::endl;
465 }
466 if (!success) {
467 return false;
468 }
469 }
470
471 const tinygltf::Scene& scene = gltf.scenes[gltf.defaultScene];
472 out_scene.children = scene.nodes;
473
474 out_scene.transform =
475 ToFBMatrixUniquePtr(Matrix::MakeScale(Vector3(1, 1, -1)));
476
477 for (size_t texture_i = 0; texture_i < gltf.textures.size(); texture_i++) {
478 auto texture = std::make_unique<fb::TextureT>();
479 ProcessTexture(gltf, gltf.textures[texture_i], *texture);
480 out_scene.textures.push_back(std::move(texture));
481 }
482
483 for (size_t node_i = 0; node_i < gltf.nodes.size(); node_i++) {
484 auto node = std::make_unique<fb::NodeT>();
485 ProcessNode(gltf, gltf.nodes[node_i], *node);
486 out_scene.nodes.push_back(std::move(node));
487 }
488
489 for (size_t animation_i = 0; animation_i < gltf.animations.size();
490 animation_i++) {
491 auto animation = std::make_unique<fb::AnimationT>();
492 ProcessAnimation(gltf, gltf.animations[animation_i], *animation);
493 out_scene.animations.push_back(std::move(animation));
494 }
495
496 return true;
497 }

References impeller::Matrix::MakeScale(), ProcessAnimation(), ProcessNode(), ProcessTexture(), and ToFBMatrixUniquePtr().

Referenced by Main(), and impeller::scene::importer::testing::TEST().

## ◆ PassthroughAttributeWriter()

static void impeller::scene::importer::PassthroughAttributeWriter | ( | Scalar * | destination,
|  | const void * | source,
|  | const VerticesBuilder::ComponentProperties & | component,
|  | const VerticesBuilder::AttributeProperties & | attribute
| ) |  |
| static

A ComponentWriter which simply converts all of an attribute's components to normalized scalar form.

Definition at line 55 of file vertices_builder.cc.

59 {
60 FML_DCHECK(attribute.size_bytes ==
61 attribute.component_count * sizeof(Scalar));
62 for (size_t component_i = 0; component_i < attribute.component_count;
63 component_i++) {
64 *(destination + component_i) =
65 component.convert_proc(source, component_i, true);
66 }
67 }

References impeller::scene::importer::VerticesBuilder::AttributeProperties::component_count, impeller::scene::importer::VerticesBuilder::ComponentProperties::convert_proc, and impeller::scene::importer::VerticesBuilder::AttributeProperties::size_bytes.

## ◆ ProcessAnimation()

static void impeller::scene::importer::ProcessAnimation | ( | const tinygltf::Model & | gltf,
|  | const tinygltf::Animation & | in_animation,
|  | fb::AnimationT & | out_animation
| ) |  |
| static

Keyframe times.

Keyframe values.

Definition at line 316 of file importer_gltf.cc.

318 {
319 out_animation.name = in_animation.name;
320
321 // std::vector<impeller::fb::ChannelT> channels;
322 std::vector<impeller::fb::ChannelT> translation_channels;
323 std::vector<impeller::fb::ChannelT> rotation_channels;
324 std::vector<impeller::fb::ChannelT> scale_channels;
325 for (auto& in_channel : in_animation.channels) {
326 auto out_channel = fb::ChannelT();
327
328 out_channel.node = in_channel.target_node;
329 auto& sampler = in_animation.samplers[in_channel.sampler];
330
331 /// Keyframe times.
332 auto& times_accessor = gltf.accessors[sampler.input];
333 if (times_accessor.count <= 0) {
334 continue; // Nothing to record.
335 }
336 {
337 auto& times_bufferview = gltf.bufferViews[times_accessor.bufferView];
338 auto& times_buffer = gltf.buffers[times_bufferview.buffer];
339 if (times_accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) {
340 std::cerr << "Unexpected component type \""
341 << times_accessor.componentType
342 << "\" for animation channel times accessor. Skipping."
343 << std::endl;
344 continue;
345 }
346 if (times_accessor.type != TINYGLTF_TYPE_SCALAR) {
347 std::cerr << "Unexpected type \"" << times_accessor.type
348 << "\" for animation channel times accessor. Skipping."
349 << std::endl;
350 continue;
351 }
352 for (size_t time_i = 0; time_i < times_accessor.count; time_i++) {
353 const float* time_p = reinterpret_cast<const float*>(
354 times_buffer.data.data() + times_bufferview.byteOffset +
355 times_accessor.ByteStride(times_bufferview) * time_i);
356 out_channel.timeline.push_back(*time_p);
357 }
358 }
359
360 /// Keyframe values.
361 auto& values_accessor = gltf.accessors[sampler.output];
362 if (values_accessor.count != times_accessor.count) {
363 std::cerr << "Mismatch between time and value accessors for animation "
364 "channel. Skipping."
365 << std::endl;
366 continue;
367 }
368 {
369 auto& values_bufferview = gltf.bufferViews[values_accessor.bufferView];
370 auto& values_buffer = gltf.buffers[values_bufferview.buffer];
371 if (values_accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) {
372 std::cerr << "Unexpected component type \""
373 << values_accessor.componentType
374 << "\" for animation channel values accessor. Skipping."
375 << std::endl;
376 continue;
377 }
378 if (in_channel.target_path == "translation") {
379 if (values_accessor.type != TINYGLTF_TYPE_VEC3) {
380 std::cerr << "Unexpected type \"" << values_accessor.type
381 << "\" for animation channel \"translation\" accessor. "
382 "Skipping."
383 << std::endl;
384 continue;
385 }
386 fb::TranslationKeyframesT keyframes;
387 for (size_t value_i = 0; value_i < values_accessor.count; value_i++) {
388 const float* value_p = reinterpret_cast<const float*>(
389 values_buffer.data.data() + values_bufferview.byteOffset +
390 values_accessor.ByteStride(values_bufferview) * value_i);
391 keyframes.values.push_back(
392 fb::Vec3(value_p[0], value_p[1], value_p[2]));
393 }
394 out_channel.keyframes.Set(std::move(keyframes));
395 translation_channels.push_back(std::move(out_channel));
396 } else if (in_channel.target_path == "rotation") {
397 if (values_accessor.type != TINYGLTF_TYPE_VEC4) {
398 std::cerr << "Unexpected type \"" << values_accessor.type
399 << "\" for animation channel \"rotation\" accessor. "
400 "Skipping."
401 << std::endl;
402 continue;
403 }
404 fb::RotationKeyframesT keyframes;
405 for (size_t value_i = 0; value_i < values_accessor.count; value_i++) {
406 const float* value_p = reinterpret_cast<const float*>(
407 values_buffer.data.data() + values_bufferview.byteOffset +
408 values_accessor.ByteStride(values_bufferview) * value_i);
409 keyframes.values.push_back(
410 fb::Vec4(value_p[0], value_p[1], value_p[2], value_p[3]));
411 }
412 out_channel.keyframes.Set(std::move(keyframes));
413 rotation_channels.push_back(std::move(out_channel));
414 } else if (in_channel.target_path == "scale") {
415 if (values_accessor.type != TINYGLTF_TYPE_VEC3) {
416 std::cerr << "Unexpected type \"" << values_accessor.type
417 << "\" for animation channel \"scale\" accessor. "
418 "Skipping."
419 << std::endl;
420 continue;
421 }
422 fb::ScaleKeyframesT keyframes;
423 for (size_t value_i = 0; value_i < values_accessor.count; value_i++) {
424 const float* value_p = reinterpret_cast<const float*>(
425 values_buffer.data.data() + values_bufferview.byteOffset +
426 values_accessor.ByteStride(values_bufferview) * value_i);
427 keyframes.values.push_back(
428 fb::Vec3(value_p[0], value_p[1], value_p[2]));
429 }
430 out_channel.keyframes.Set(std::move(keyframes));
431 scale_channels.push_back(std::move(out_channel));
432 } else {
433 std::cerr << "Unsupported animation channel target path \""
434 << in_channel.target_path << "\". Skipping." << std::endl;
435 continue;
436 }
437 }
438 }
439
440 std::vector<std::unique_ptr<impeller::fb::ChannelT>> channels;
441 for (const auto& channel_list :
442 {translation_channels, rotation_channels, scale_channels}) {
443 for (const auto& channel : channel_list) {
444 channels.push_back(std::make_unique<fb::ChannelT>(channel));
445 }
446 }
447 out_animation.channels = std::move(channels);
448 }

Referenced by ParseGLTF().

## ◆ ProcessMaterial()

static void impeller::scene::importer::ProcessMaterial | ( | const tinygltf::Model & | gltf,
|  | const tinygltf::Material & | in_material,
|  | fb::MaterialT & | out_material
| ) |  |
| static

Definition at line 44 of file importer_gltf.cc.

46 {
47 out_material.type = fb::MaterialType::kUnlit;
48 out_material.base_color_factor =
49 ToFBColor(in_material.pbrMetallicRoughness.baseColorFactor);
50 bool base_color_texture_valid =
51 in_material.pbrMetallicRoughness.baseColorTexture.texCoord == 0 &&
52 in_material.pbrMetallicRoughness.baseColorTexture.index >= 0 &&
53 in_material.pbrMetallicRoughness.baseColorTexture.index <
54 static_cast<int32_t>(gltf.textures.size());
55 out_material.base_color_texture =
56 base_color_texture_valid
57 // This is safe because every GLTF input texture is mapped to a
58 // `Scene->texture`.
59 ? in_material.pbrMetallicRoughness.baseColorTexture.index
60 : -1;
61 }

References ToFBColor().

Referenced by ProcessMeshPrimitive().

## ◆ ProcessMeshPrimitive()

static bool impeller::scene::importer::ProcessMeshPrimitive | ( | const tinygltf::Model & | gltf,
|  | const tinygltf::Primitive & | primitive,
|  | fb::MeshPrimitiveT & | mesh_primitive
| ) |  |
| static

Vertices.

Indices.

Material.

Definition at line 63 of file importer_gltf.cc.

65 {
66 //---------------------------------------------------------------------------
67 /// Vertices.
68 ///
69
70 {
71 bool is_skinned = MeshPrimitiveIsSkinned(primitive);
72 std::unique_ptr<VerticesBuilder> builder =
73 is_skinned ? VerticesBuilder::MakeSkinned()
74 : VerticesBuilder::MakeUnskinned();
75
76 for (const auto& attribute : primitive.attributes) {
77 auto attribute_type = kAttributes.find(attribute.first);
78 if (attribute_type == kAttributes.end()) {
79 std::cerr << "Vertex attribute \"" << attribute.first
80 << "\" not supported." << std::endl;
81 continue;
82 }
83 if (!is_skinned &&
84 (attribute_type->second == VerticesBuilder::AttributeType::kJoints ||
85 attribute_type->second ==
86 VerticesBuilder::AttributeType::kWeights)) {
87 // If the primitive doesn't have enough information to be skinned, skip
88 // skinning-related attributes.
89 continue;
90 }
91
92 const auto accessor = gltf.accessors[attribute.second];
93 const auto view = gltf.bufferViews[accessor.bufferView];
94
95 const auto buffer = gltf.buffers[view.buffer];
96 const unsigned char* source_start = &buffer.data[view.byteOffset];
97
98 VerticesBuilder::ComponentType type;
99 switch (accessor.componentType) {
100 case TINYGLTF_COMPONENT_TYPE_BYTE:
101 type = VerticesBuilder::ComponentType::kSignedByte;
102 break;
103 case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
104 type = VerticesBuilder::ComponentType::kUnsignedByte;
105 break;
106 case TINYGLTF_COMPONENT_TYPE_SHORT:
107 type = VerticesBuilder::ComponentType::kSignedShort;
108 break;
109 case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
110 type = VerticesBuilder::ComponentType::kUnsignedShort;
111 break;
112 case TINYGLTF_COMPONENT_TYPE_INT:
113 type = VerticesBuilder::ComponentType::kSignedInt;
114 break;
115 case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
116 type = VerticesBuilder::ComponentType::kUnsignedInt;
117 break;
118 case TINYGLTF_COMPONENT_TYPE_FLOAT:
119 type = VerticesBuilder::ComponentType::kFloat;
120 break;
121 default:
122 std::cerr << "Skipping attribute \"" << attribute.first
123 << "\" due to invalid component type." << std::endl;
124 continue;
125 }
126
127 builder->SetAttributeFromBuffer(
128 attribute_type->second, // attribute
129 type, // component_type
130 source_start, // buffer_start
131 accessor.ByteStride(view), // stride_bytes
132 accessor.count); // count
133 }
134
135 builder->WriteFBVertices(mesh_primitive);
136 }
137
138 //---------------------------------------------------------------------------
139 /// Indices.
140 ///
141
142 {
143 if (!WithinRange(primitive.indices, gltf.accessors.size())) {
144 std::cerr << "Mesh primitive has no index buffer. Skipping." << std::endl;
145 return false;
146 }
147
148 auto index_accessor = gltf.accessors[primitive.indices];
149 auto index_view = gltf.bufferViews[index_accessor.bufferView];
150
151 auto indices = std::make_unique<fb::IndicesT>();
152
153 switch (index_accessor.componentType) {
154 case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
155 indices->type = fb::IndexType::k16Bit;
156 break;
157 case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
158 indices->type = fb::IndexType::k32Bit;
159 break;
160 default:
161 std::cerr << "Mesh primitive has unsupported index type "
162 << index_accessor.componentType << ". Skipping.";
163 return false;
164 }
165 indices->count = index_accessor.count;
166 indices->data.resize(index_view.byteLength);
167 const auto* index_buffer =
168 &gltf.buffers[index_view.buffer].data[index_view.byteOffset];
169 std::memcpy(indices->data.data(), index_buffer, indices->data.size());
170
171 mesh_primitive.indices = std::move(indices);
172 }
173
174 //---------------------------------------------------------------------------
175 /// Material.
176 ///
177
178 {
179 auto material = std::make_unique<fb::MaterialT>();
180 if (primitive.material >= 0 &&
181 primitive.material < static_cast<int>(gltf.materials.size())) {
182 ProcessMaterial(gltf, gltf.materials[primitive.material], *material);
183 } else {
184 material->type = fb::MaterialType::kUnlit;
185 }
186 mesh_primitive.material = std::move(material);
187 }
188
189 return true;
190 }

References kAttributes, impeller::scene::importer::VerticesBuilder::kFloat, impeller::scene::importer::VerticesBuilder::kJoints, impeller::scene::importer::VerticesBuilder::kSignedByte, impeller::scene::importer::VerticesBuilder::kSignedInt, impeller::scene::importer::VerticesBuilder::kSignedShort, impeller::scene::importer::VerticesBuilder::kUnsignedByte, impeller::scene::importer::VerticesBuilder::kUnsignedInt, impeller::scene::importer::VerticesBuilder::kUnsignedShort, impeller::scene::importer::VerticesBuilder::kWeights, impeller::scene::importer::VerticesBuilder::MakeSkinned(), impeller::scene::importer::VerticesBuilder::MakeUnskinned(), MeshPrimitiveIsSkinned(), ProcessMaterial(), and WithinRange().

Referenced by ProcessNode().

## ◆ ProcessNode()

static void impeller::scene::importer::ProcessNode | ( | const tinygltf::Model & | gltf,
|  | const tinygltf::Node & | in_node,
|  | fb::NodeT & | out_node
| ) |  |
| static

Transform.

Static meshes.

Skin.

Definition at line 192 of file importer_gltf.cc.

194 {
195 out_node.name = in_node.name;
196 out_node.children = in_node.children;
197
198 //---------------------------------------------------------------------------
199 /// Transform.
200 ///
201
202 Matrix transform;
203 if (in_node.scale.size() == 3) {
204 transform =
205 transform * Matrix::MakeScale({static_cast<Scalar>(in_node.scale[0]),
206 static_cast<Scalar>(in_node.scale[1]),
207 static_cast<Scalar>(in_node.scale[2])});
208 }
209 if (in_node.rotation.size() == 4) {
210 transform = transform * Matrix::MakeRotation(Quaternion(
211 in_node.rotation[0], in_node.rotation[1],
212 in_node.rotation[2], in_node.rotation[3]));
213 }
214 if (in_node.translation.size() == 3) {
215 transform = transform * Matrix::MakeTranslation(
216 {static_cast<Scalar>(in_node.translation[0]),
217 static_cast<Scalar>(in_node.translation[1]),
218 static_cast<Scalar>(in_node.translation[2])});
219 }
220 if (in_node.matrix.size() == 16) {
221 if (!transform.IsIdentity()) {
222 std::cerr << "The `matrix` attribute of node (name: " << in_node.name
223 << ") is set in addition to one or more of the "
224 "`translation/rotation/scale` attributes. Using only the "
225 "`matrix` "
226 "attribute.";
227 }
228 transform = ToMatrix(in_node.matrix);
229 }
230 out_node.transform = ToFBMatrixUniquePtr(transform);
231
232 //---------------------------------------------------------------------------
233 /// Static meshes.
234 ///
235
236 if (WithinRange(in_node.mesh, gltf.meshes.size())) {
237 auto& mesh = gltf.meshes[in_node.mesh];
238 for (const auto& primitive : mesh.primitives) {
239 auto mesh_primitive = std::make_unique<fb::MeshPrimitiveT>();
240 if (!ProcessMeshPrimitive(gltf, primitive, *mesh_primitive)) {
241 continue;
242 }
243 out_node.mesh_primitives.push_back(std::move(mesh_primitive));
244 }
245 }
246
247 //---------------------------------------------------------------------------
248 /// Skin.
249 ///
250
251 if (WithinRange(in_node.skin, gltf.skins.size())) {
252 auto& skin = gltf.skins[in_node.skin];
253
254 auto ipskin = std::make_unique<fb::SkinT>();
255 ipskin->joints = skin.joints;
256 {
257 std::vector<fb::Matrix> matrices;
258 auto& matrix_accessor = gltf.accessors[skin.inverseBindMatrices];
259 auto& matrix_view = gltf.bufferViews[matrix_accessor.bufferView];
260 auto& matrix_buffer = gltf.buffers[matrix_view.buffer];
261 for (size_t matrix_i = 0; matrix_i < matrix_accessor.count; matrix_i++) {
262 auto* s = reinterpret_cast<const float*>(
263 matrix_buffer.data.data() + matrix_view.byteOffset +
264 matrix_accessor.ByteStride(matrix_view) * matrix_i);
265 Matrix m(s[0], s[1], s[2], s[3], //
266 s[4], s[5], s[6], s[7], //
267 s[8], s[9], s[10], s[11], //
268 s[12], s[13], s[14], s[15]);
269 matrices.push_back(ToFBMatrix(m));
270 }
271 ipskin->inverse_bind_matrices = std::move(matrices);
272 }
273 ipskin->skeleton = skin.skeleton;
274 out_node.skin = std::move(ipskin);
275 }
276 }

References impeller::Matrix::IsIdentity(), impeller::Matrix::MakeRotation(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), ProcessMeshPrimitive(), ToFBMatrix(), ToFBMatrixUniquePtr(), ToMatrix(), and WithinRange().

Referenced by ParseGLTF().

## ◆ ProcessTexture()

static void impeller::scene::importer::ProcessTexture | ( | const tinygltf::Model & | gltf,
|  | const tinygltf::Texture & | in_texture,
|  | fb::TextureT & | out_texture
| ) |  |
| static

Definition at line 278 of file importer_gltf.cc.

280 {
281 if (!WithinRange(in_texture.source, gltf.images.size())) {
282 return;
283 }
284 auto& image = gltf.images[in_texture.source];
285
286 auto embedded = std::make_unique<fb::EmbeddedImageT>();
287 embedded->bytes = image.image;
288 size_t bytes_per_component = 0;
289 switch (image.pixel_type) {
290 case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
291 embedded->component_type = fb::ComponentType::k8Bit;
292 bytes_per_component = 1;
293 break;
294 case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
295 embedded->component_type = fb::ComponentType::k16Bit;
296 bytes_per_component = 2;
297 break;
298 default:
299 std::cerr << "Texture component type " << image.pixel_type
300 << " not supported." << std::endl;
301 return;
302 }
303 if (image.image.size() !=
304 bytes_per_component * image.component * image.width * image.height) {
305 std::cerr << "Decompressed texture had unexpected buffer size. Skipping."
306 << std::endl;
307 return;
308 }
309 embedded->component_count = image.component;
310 embedded->width = image.width;
311 embedded->height = image.height;
312 out_texture.embedded_image = std::move(embedded);
313 out_texture.uri = image.uri;
314 }

References WithinRange().

Referenced by ParseGLTF().

## ◆ SetPermissiveAccess()

static bool impeller::scene::importer::SetPermissiveAccess | ( | const std::filesystem::path & | p | ) |
| static

Definition at line 27 of file scenec_main.cc.

27 {
28 auto permissions =
29 std::filesystem::perms::owner_read | std::filesystem::perms::owner_write |
30 std::filesystem::perms::group_read | std::filesystem::perms::others_read;
31 std::error_code error;
32 std::filesystem::permissions(p, permissions, error);
33 if (error) {
34 std::cerr << "Failed to set access on file '" << p
35 << "': " << error.message() << std::endl;
36 return false;
37 }
38 return true;
39 }

Referenced by Main().

## ◆ SourceTypeFromCommandLine()

static SourceType impeller::scene::importer::SourceTypeFromCommandLine | ( | const fml::CommandLine & | command_line | ) |
| static

Definition at line 43 of file switches.cc.

44 {
45 auto source_type_option =
46 command_line.GetOptionValueWithDefault("input-type", "gltf");
47 auto source_type_search = kKnownSourceTypes.find(source_type_option);
48 if (source_type_search == kKnownSourceTypes.end()) {
49 return SourceType::kUnknown;
50 }
51 return source_type_search->second;
52 }

References kKnownSourceTypes, and kUnknown.

## ◆ ToColor()

Color impeller::scene::importer::ToColor | ( | const fb::Color & | c | ) |

Definition at line 46 of file conversions.cc.

46 {
47 return Color(c.r(), c.g(), c.b(), c.a());
48 }

Referenced by impeller::scene::UnlitMaterial::MakeFromFlatbuffer(), impeller::scene::PhysicallyBasedMaterial::MakeFromFlatbuffer(), and impeller::scene::importer::testing::TEST().

## ◆ ToFBColor() [1/2]

fb::Color impeller::scene::importer::ToFBColor | ( | const Color | c | ) |

Definition at line 82 of file conversions.cc.

82 {
83 return fb::Color(c.red, c.green, c.blue, c.alpha);
84 }

References impeller::Color::alpha, impeller::Color::blue, impeller::Color::green, and impeller::Color::red.

Referenced by ProcessMaterial(), impeller::scene::importer::UnskinnedVerticesBuilder::WriteFBVertices(), and impeller::scene::importer::SkinnedVerticesBuilder::WriteFBVertices().

## ◆ ToFBColor() [2/2]

std::unique_ptr< fb::Color > impeller::scene::importer::ToFBColor | ( | const std::vector< double > & | c | ) |

Definition at line 86 of file conversions.cc.

86 {
87 auto* color = new fb::Color(c.size() > 0 ? c[0] : 1, //
88 c.size() > 1 ? c[1] : 1, //
89 c.size() > 2 ? c[2] : 1, //
90 c.size() > 3 ? c[3] : 1);
91 return std::unique_ptr<fb::Color>(color);
92 }

## ◆ ToFBMatrix()

fb::Matrix impeller::scene::importer::ToFBMatrix | ( | const Matrix & | m | ) |

Impeller -> Flatbuffers

Definition at line 54 of file conversions.cc.

54 {
55 auto array = std::array<Scalar, 16>{m.m[0], m.m[1], m.m[2], m.m[3], //
56 m.m[4], m.m[5], m.m[6], m.m[7], //
57 m.m[8], m.m[9], m.m[10], m.m[11], //
58 m.m[12], m.m[13], m.m[14], m.m[15]};
59 return fb::Matrix(array);
60 }

References impeller::Matrix::m.

Referenced by ProcessNode().

## ◆ ToFBMatrixUniquePtr()

std::unique_ptr< fb::Matrix > impeller::scene::importer::ToFBMatrixUniquePtr | ( | const Matrix & | m | ) |

Definition at line 62 of file conversions.cc.

62 {
63 auto array = std::array<Scalar, 16>{m.m[0], m.m[1], m.m[2], m.m[3], //
64 m.m[4], m.m[5], m.m[6], m.m[7], //
65 m.m[8], m.m[9], m.m[10], m.m[11], //
66 m.m[12], m.m[13], m.m[14], m.m[15]};
67 return std::make_unique<fb::Matrix>(array);
68 }

References impeller::Matrix::m.

Referenced by ParseGLTF(), and ProcessNode().

## ◆ ToFBVec2()

fb::Vec2 impeller::scene::importer::ToFBVec2 | ( | const Vector2 | v | ) |

Definition at line 70 of file conversions.cc.

70 {
71 return fb::Vec2(v.x, v.y);
72 }

References impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by impeller::scene::importer::UnskinnedVerticesBuilder::WriteFBVertices(), and impeller::scene::importer::SkinnedVerticesBuilder::WriteFBVertices().

## ◆ ToFBVec3()

fb::Vec3 impeller::scene::importer::ToFBVec3 | ( | const Vector3 | v | ) |

Definition at line 74 of file conversions.cc.

74 {
75 return fb::Vec3(v.x, v.y, v.z);
76 }

References impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

Referenced by impeller::scene::importer::UnskinnedVerticesBuilder::WriteFBVertices(), and impeller::scene::importer::SkinnedVerticesBuilder::WriteFBVertices().

## ◆ ToFBVec4()

fb::Vec4 impeller::scene::importer::ToFBVec4 | ( | const Vector4 | v | ) |

Definition at line 78 of file conversions.cc.

78 {
79 return fb::Vec4(v.x, v.y, v.z, v.w);
80 }

References impeller::Vector4::w, impeller::Vector4::x, impeller::Vector4::y, and impeller::Vector4::z.

Referenced by impeller::scene::importer::UnskinnedVerticesBuilder::WriteFBVertices(), and impeller::scene::importer::SkinnedVerticesBuilder::WriteFBVertices().

## ◆ ToMatrix() [1/2]

Matrix impeller::scene::importer::ToMatrix | ( | const fb::Matrix & | m | ) |

Flatbuffers -> Impeller

Definition at line 26 of file conversions.cc.

26 {
27 auto& a = *m.m();
28 return Matrix(a[0], a[1], a[2], a[3], //
29 a[4], a[5], a[6], a[7], //
30 a[8], a[9], a[10], a[11], //
31 a[12], a[13], a[14], a[15]);
32 }

References impeller::Matrix::m.

## ◆ ToMatrix() [2/2]

Matrix impeller::scene::importer::ToMatrix | ( | const std::vector< double > & | m | ) |

Definition at line 15 of file conversions.cc.

15 {
16 return Matrix(m[0], m[1], m[2], m[3], //
17 m[4], m[5], m[6], m[7], //
18 m[8], m[9], m[10], m[11], //
19 m[12], m[13], m[14], m[15]);
20 }

Referenced by impeller::scene::Skin::MakeFromFlatbuffer(), impeller::scene::Node::MakeFromFlatbuffer(), ProcessNode(), and impeller::scene::importer::testing::TEST().

## ◆ ToScalar()

template<typename SourceType >

static Scalar impeller::scene::importer::ToScalar | ( | const void * | source,
|  | size_t | index,
|  | bool | normalized
| ) |  |
| static

Reads a numeric component from `source` and returns a 32bit float. If `normalized` is `true`, signed SourceTypes convert to a range of -1 to 1, and unsigned SourceTypes convert to a range of 0 to 1.

Definition at line 41 of file vertices_builder.cc.

41 {
42 const SourceType* s = reinterpret_cast<const SourceType*>(source) + index;
43 Scalar result = static_cast<Scalar>(*s);
44 if (normalized) {
45 constexpr SourceType divisor = std::is_integral_v<SourceType>
46 ? std::numeric_limits<SourceType>::max()
47 : 1;
48 result = static_cast<Scalar>(*s) / static_cast<Scalar>(divisor);
49 }
50 return result;
51 }

## ◆ ToVector2()

Vector2 impeller::scene::importer::ToVector2 | ( | const fb::Vec2 & | v | ) |

Definition at line 34 of file conversions.cc.

34 {
35 return Vector2(v.x(), v.y());
36 }

Referenced by impeller::scene::importer::testing::TEST().

## ◆ ToVector3()

Vector3 impeller::scene::importer::ToVector3 | ( | const fb::Vec3 & | v | ) |

Definition at line 38 of file conversions.cc.

38 {
39 return Vector3(v.x(), v.y(), v.z());
40 }

Referenced by impeller::scene::importer::testing::TEST().

## ◆ ToVector4()

Vector4 impeller::scene::importer::ToVector4 | ( | const fb::Vec4 & | v | ) |

Definition at line 42 of file conversions.cc.

42 {
43 return Vector4(v.x(), v.y(), v.z(), v.w());
44 }

Referenced by impeller::scene::importer::testing::TEST().

## ◆ WithinRange()

static bool impeller::scene::importer::WithinRange | ( | int | index,
|  | size_t | size
| ) |  |
| static

Definition at line 35 of file importer_gltf.cc.

35 {
36 return index >= 0 && static_cast<size_t>(index) < size;
37 }

Referenced by ProcessMeshPrimitive(), ProcessNode(), and ProcessTexture().

## Variable Documentation

## ◆ kAttributes

const std::map<std::string, VerticesBuilder::AttributeType> impeller::scene::importer::kAttributes
| static

Initial value:
=
{{"POSITION", VerticesBuilder::AttributeType::kPosition},
{"NORMAL", VerticesBuilder::AttributeType::kNormal},
{"TANGENT", VerticesBuilder::AttributeType::kTangent},
{"TEXCOORD_0", VerticesBuilder::AttributeType::kTextureCoords},
{"COLOR_0", VerticesBuilder::AttributeType::kColor},
{"JOINTS_0", VerticesBuilder::AttributeType::kJoints},
{"WEIGHTS_0", VerticesBuilder::AttributeType::kWeights}}

Definition at line 26 of file importer_gltf.cc.

Referenced by ProcessMeshPrimitive().

## ◆ kComponentTypes

std::map<VerticesBuilder::ComponentType, VerticesBuilder::ComponentProperties> impeller::scene::importer::kComponentTypes
| static

Initial value:
= {
{VerticesBuilder::ComponentType::kSignedByte,
{.size_bytes = sizeof(int8_t), .convert_proc = ToScalar<int8_t>}},
{VerticesBuilder::ComponentType::kUnsignedByte,
{.size_bytes = sizeof(int8_t), .convert_proc = ToScalar<uint8_t>}},
{VerticesBuilder::ComponentType::kSignedShort,
{.size_bytes = sizeof(int16_t), .convert_proc = ToScalar<int16_t>}},
{VerticesBuilder::ComponentType::kUnsignedShort,
{.size_bytes = sizeof(int16_t), .convert_proc = ToScalar<uint16_t>}},
{VerticesBuilder::ComponentType::kSignedInt,
{.size_bytes = sizeof(int32_t), .convert_proc = ToScalar<int32_t>}},
{VerticesBuilder::ComponentType::kUnsignedInt,
{.size_bytes = sizeof(int32_t), .convert_proc = ToScalar<uint32_t>}},
{VerticesBuilder::ComponentType::kFloat,
{.size_bytes = sizeof(float), .convert_proc = ToScalar<float>}},
}

Definition at line 123 of file vertices_builder.cc.

Referenced by impeller::scene::importer::VerticesBuilder::WriteAttribute().

## ◆ kKnownSourceTypes

const std::map<std::string, SourceType> impeller::scene::importer::kKnownSourceTypes
| static

Initial value:
= {
{"gltf", SourceType::kGLTF},
}

Definition at line 20 of file switches.cc.

Referenced by impeller::scene::importer::Switches::PrintHelp(), and SourceTypeFromCommandLine().

impeller::kFloat
@ kFloat
Definition: runtime_types.h:23
impeller::scene::importer::ParseGLTF
bool ParseGLTF(const fml::Mapping &source_mapping, fb::SceneT &out_scene)
Definition: importer_gltf.cc:450
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::scene::importer::ProcessMaterial
static void ProcessMaterial(const tinygltf::Model &gltf, const tinygltf::Material &in_material, fb::MaterialT &out_material)
Definition: importer_gltf.cc:44
impeller::compiler::SourceType::kUnknown
@ kUnknown
impeller::scene::importer::ProcessMeshPrimitive
static bool ProcessMeshPrimitive(const tinygltf::Model &gltf, const tinygltf::Primitive &primitive, fb::MeshPrimitiveT &mesh_primitive)
Definition: importer_gltf.cc:63
impeller::Vector2
Point Vector2
Definition: point.h:320
impeller::ToMatrix
static Matrix ToMatrix(const SkMatrix &m)
Definition: dl_dispatcher.cc:166
impeller::scene::importer::ProcessNode
static void ProcessNode(const tinygltf::Model &gltf, const tinygltf::Node &in_node, fb::NodeT &out_node)
Definition: importer_gltf.cc:192
impeller::kColor
@ kColor
Definition: geometry.h:51
impeller::scene::importer::ToFBMatrix
fb::Matrix ToFBMatrix(const Matrix &m)
Definition: conversions.cc:54
impeller::scene::importer::SetPermissiveAccess
static bool SetPermissiveAccess(const std::filesystem::path &p)
Definition: scenec_main.cc:27
impeller::scene::importer::ProcessTexture
static void ProcessTexture(const tinygltf::Model &gltf, const tinygltf::Texture &in_texture, fb::TextureT &out_texture)
Definition: importer_gltf.cc:278
impeller::scene::importer::kKnownSourceTypes
static const std::map< std::string, SourceType > kKnownSourceTypes
Definition: switches.cc:20
impeller::scene::importer::MeshPrimitiveIsSkinned
static bool MeshPrimitiveIsSkinned(const tinygltf::Primitive &primitive)
Definition: importer_gltf.cc:39
impeller::compiler::SourceType
SourceType
Definition: types.h:22
impeller::scene::importer::ToFBColor
fb::Color ToFBColor(const Color c)
Definition: conversions.cc:82
impeller::scene::importer::SourceType::kGLTF
@ kGLTF
impeller::scene::importer::ToFBMatrixUniquePtr
std::unique_ptr< fb::Matrix > ToFBMatrixUniquePtr(const Matrix &m)
Definition: conversions.cc:62
impeller::scene::importer::ProcessAnimation
static void ProcessAnimation(const tinygltf::Model &gltf, const tinygltf::Animation &in_animation, fb::AnimationT &out_animation)
Definition: importer_gltf.cc:316
impeller::compiler::Utf8FromPath
std::string Utf8FromPath(const std::filesystem::path &path)
Converts a native format path to a utf8 string.
Definition: utilities.cc:30
impeller::kPosition
@ kPosition
Definition: geometry.h:50
impeller::scene::importer::WithinRange
static bool WithinRange(int index, size_t size)
Definition: importer_gltf.cc:35
impeller::scene::importer::kAttributes
static const std::map< std::string, VerticesBuilder::AttributeType > kAttributes
Definition: importer_gltf.cc:26