| // 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_asserts.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, CanParseUnskinnedGLTF) { |
| auto mapping = |
| flutter::testing::OpenFixtureAsMapping("flutter_logo_baked.glb"); |
| |
| fb::SceneT scene; |
| ASSERT_TRUE(ParseGLTF(*mapping, scene)); |
| |
| ASSERT_EQ(scene.children.size(), 1u); |
| auto& node = scene.nodes[scene.children[0]]; |
| |
| Matrix node_transform = ToMatrix(*node->transform); |
| ASSERT_MATRIX_NEAR(node_transform, Matrix()); |
| |
| ASSERT_EQ(node->mesh_primitives.size(), 1u); |
| auto& mesh = *node->mesh_primitives[0]; |
| ASSERT_EQ(mesh.indices->count, 918u); |
| |
| uint16_t first_index = |
| *reinterpret_cast<uint16_t*>(mesh.indices->data.data()); |
| ASSERT_EQ(first_index, 45u); |
| |
| ASSERT_EQ(mesh.vertices.type, fb::VertexBuffer::UnskinnedVertexBuffer); |
| auto& vertices = mesh.vertices.AsUnskinnedVertexBuffer()->vertices; |
| ASSERT_EQ(vertices.size(), 260u); |
| auto& vertex = 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)); |
| } |
| |
| TEST(ImporterTest, CanParseSkinnedGLTF) { |
| auto mapping = flutter::testing::OpenFixtureAsMapping("two_triangles.glb"); |
| |
| fb::SceneT scene; |
| ASSERT_TRUE(ParseGLTF(*mapping, scene)); |
| |
| ASSERT_EQ(scene.children.size(), 1u); |
| auto& node = scene.nodes[scene.children[0]]; |
| |
| Matrix node_transform = ToMatrix(*node->transform); |
| ASSERT_MATRIX_NEAR(node_transform, Matrix()); |
| |
| ASSERT_EQ(node->mesh_primitives.size(), 0u); |
| ASSERT_EQ(node->children.size(), 2u); |
| |
| // The skinned node contains both a skeleton and skinned mesh primitives that |
| // reference bones in the skeleton. |
| auto& skinned_node = scene.nodes[node->children[0]]; |
| ASSERT_NE(skinned_node->skin, nullptr); |
| |
| ASSERT_EQ(skinned_node->mesh_primitives.size(), 2u); |
| auto& bottom_triangle = *skinned_node->mesh_primitives[0]; |
| ASSERT_EQ(bottom_triangle.indices->count, 3u); |
| |
| ASSERT_EQ(bottom_triangle.vertices.type, |
| fb::VertexBuffer::SkinnedVertexBuffer); |
| auto& vertices = bottom_triangle.vertices.AsSkinnedVertexBuffer()->vertices; |
| ASSERT_EQ(vertices.size(), 3u); |
| auto& vertex = vertices[0]; |
| |
| Vector3 position = ToVector3(vertex.vertex().position()); |
| ASSERT_VECTOR3_NEAR(position, Vector3(1, 1, 0)); |
| |
| Vector3 normal = ToVector3(vertex.vertex().normal()); |
| ASSERT_VECTOR3_NEAR(normal, Vector3(0, 0, 1)); |
| |
| Vector4 tangent = ToVector4(vertex.vertex().tangent()); |
| ASSERT_VECTOR4_NEAR(tangent, Vector4(1, 0, 0, -1)); |
| |
| Vector2 texture_coords = ToVector2(vertex.vertex().texture_coords()); |
| ASSERT_POINT_NEAR(texture_coords, Vector2(0, 1)); |
| |
| Color color = ToColor(vertex.vertex().color()); |
| ASSERT_COLOR_NEAR(color, Color(1, 1, 1, 1)); |
| |
| Vector4 joints = ToVector4(vertex.joints()); |
| ASSERT_VECTOR4_NEAR(joints, Vector4(0, 0, 0, 0)); |
| |
| Vector4 weights = ToVector4(vertex.weights()); |
| ASSERT_VECTOR4_NEAR(weights, Vector4(1, 0, 0, 0)); |
| |
| ASSERT_EQ(scene.animations.size(), 2u); |
| ASSERT_EQ(scene.animations[0]->name, "Idle"); |
| ASSERT_EQ(scene.animations[1]->name, "Metronome"); |
| ASSERT_EQ(scene.animations[1]->channels.size(), 6u); |
| auto& channel = scene.animations[1]->channels[3]; |
| ASSERT_EQ(channel->keyframes.type, fb::Keyframes::RotationKeyframes); |
| auto* keyframes = channel->keyframes.AsRotationKeyframes(); |
| ASSERT_EQ(keyframes->values.size(), 40u); |
| ASSERT_VECTOR4_NEAR(ToVector4(keyframes->values[0]), |
| Vector4(0.653281, -0.270598, 0.270598, 0.653281)); |
| ASSERT_VECTOR4_NEAR(ToVector4(keyframes->values[10]), |
| Vector4(0.700151, 0.0989373, -0.0989373, 0.700151)); |
| } |
| |
| } // namespace testing |
| } // namespace importer |
| } // namespace scene |
| } // namespace impeller |