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

Commit c7cc1b6

Browse files
authored
[Impeller Scene] Add animation/PBR descriptions to ipscene (#38397)
1 parent 725d47d commit c7cc1b6

10 files changed

+239
-98
lines changed

impeller/scene/geometry.cc

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,17 @@ std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFlatbuffer(
5353
break;
5454
}
5555

56-
const size_t vertices_bytes = mesh.vertices()->size() * sizeof(fb::Vertex);
56+
if (mesh.vertices_type() == fb::VertexBuffer::SkinnedVertexBuffer) {
57+
VALIDATION_LOG << "Skinned meshes not yet supported.";
58+
return nullptr;
59+
}
60+
if (mesh.vertices_type() != fb::VertexBuffer::UnskinnedVertexBuffer) {
61+
VALIDATION_LOG << "Invalid vertex buffer type.";
62+
return nullptr;
63+
}
64+
65+
const auto* vertices = mesh.vertices_as_UnskinnedVertexBuffer()->vertices();
66+
const size_t vertices_bytes = vertices->size() * sizeof(fb::Vertex);
5767
const size_t indices_bytes = mesh.indices()->data()->size();
5868
if (vertices_bytes == 0 || indices_bytes == 0) {
5969
return nullptr;
@@ -67,7 +77,7 @@ std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFlatbuffer(
6777
buffer->SetLabel("Mesh vertices+indices");
6878

6979
const uint8_t* vertices_start =
70-
reinterpret_cast<const uint8_t*>(mesh.vertices()->Get(0));
80+
reinterpret_cast<const uint8_t*>(vertices->Get(0));
7181
const uint8_t* indices_start =
7282
reinterpret_cast<const uint8_t*>(mesh.indices()->data()->Data());
7383

impeller/scene/importer/importer_gltf.cc

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ static bool ProcessMeshPrimitive(const tinygltf::Model& gltf,
9393
accessor.count); // count
9494
}
9595

96-
builder.WriteFBVertices(mesh_primitive.vertices);
96+
builder.WriteFBVertices(mesh_primitive);
9797
}
9898

9999
//---------------------------------------------------------------------------
@@ -136,6 +136,9 @@ static bool ProcessMeshPrimitive(const tinygltf::Model& gltf,
136136
static void ProcessNode(const tinygltf::Model& gltf,
137137
const tinygltf::Node& in_node,
138138
fb::NodeT& out_node) {
139+
out_node.name = in_node.name;
140+
out_node.children = in_node.children;
141+
139142
//---------------------------------------------------------------------------
140143
/// Transform.
141144
///
@@ -184,16 +187,6 @@ static void ProcessNode(const tinygltf::Model& gltf,
184187
out_node.mesh_primitives.push_back(std::move(mesh_primitive));
185188
}
186189
}
187-
188-
//---------------------------------------------------------------------------
189-
/// Children.
190-
///
191-
192-
for (size_t node_i = 0; node_i < in_node.children.size(); node_i++) {
193-
auto child = std::make_unique<fb::NodeT>();
194-
ProcessNode(gltf, gltf.nodes[in_node.children[node_i]], *child);
195-
out_node.children.push_back(std::move(child));
196-
}
197190
}
198191

199192
bool ParseGLTF(const fml::Mapping& source_mapping, fb::SceneT& out_scene) {
@@ -218,10 +211,12 @@ bool ParseGLTF(const fml::Mapping& source_mapping, fb::SceneT& out_scene) {
218211
}
219212

220213
const tinygltf::Scene& scene = gltf.scenes[gltf.defaultScene];
221-
for (size_t node_i = 0; node_i < scene.nodes.size(); node_i++) {
214+
out_scene.children = scene.nodes;
215+
216+
for (size_t node_i = 0; node_i < gltf.nodes.size(); node_i++) {
222217
auto node = std::make_unique<fb::NodeT>();
223-
ProcessNode(gltf, gltf.nodes[scene.nodes[node_i]], *node);
224-
out_scene.children.push_back(std::move(node));
218+
ProcessNode(gltf, gltf.nodes[node_i], *node);
219+
out_scene.nodes.push_back(std::move(node));
225220
}
226221

227222
return true;

impeller/scene/importer/importer_unittests.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,23 @@ TEST(ImporterTest, CanParseGLTF) {
2121
ASSERT_TRUE(ParseGLTF(*mapping, scene));
2222

2323
ASSERT_EQ(scene.children.size(), 1u);
24-
auto& node = *scene.children[0];
24+
auto& node = scene.nodes[scene.children[0]];
2525

26-
Matrix node_transform = ToMatrix(*node.transform);
26+
Matrix node_transform = ToMatrix(*node->transform);
2727
ASSERT_MATRIX_NEAR(node_transform, Matrix());
2828

29-
ASSERT_EQ(node.mesh_primitives.size(), 1u);
30-
auto& mesh = *node.mesh_primitives[0];
29+
ASSERT_EQ(node->mesh_primitives.size(), 1u);
30+
auto& mesh = *node->mesh_primitives[0];
3131
ASSERT_EQ(mesh.indices->count, 918u);
3232

3333
uint16_t first_index =
3434
*reinterpret_cast<uint16_t*>(mesh.indices->data.data());
3535
ASSERT_EQ(first_index, 45u);
3636

37-
ASSERT_EQ(mesh.vertices.size(), 260u);
38-
auto& vertex = mesh.vertices[0];
37+
ASSERT_EQ(mesh.vertices.type, fb::VertexBuffer::UnskinnedVertexBuffer);
38+
auto& vertices = mesh.vertices.AsUnskinnedVertexBuffer()->vertices;
39+
ASSERT_EQ(vertices.size(), 260u);
40+
auto& vertex = vertices[0];
3941

4042
Vector3 position = ToVector3(vertex.position());
4143
ASSERT_VECTOR3_NEAR(position, Vector3(-0.0100185, -0.522907, -0.133178));

impeller/scene/importer/scene.fbs

Lines changed: 122 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,56 @@
44

55
namespace impeller.fb;
66

7+
//-----------------------------------------------------------------------------
8+
/// Materials.
9+
///
10+
11+
struct Color {
12+
r: float;
13+
g: float;
14+
b: float;
15+
a: float;
16+
}
17+
18+
/// A compressed texture for Flutter to decode. The `bytes` field takes
19+
/// precedent over the `uri` field.
20+
table Texture {
21+
/// A Flutter asset URI for an image file to import and decode.
22+
uri: string;
23+
/// Compressed image bytes for Flutter to decode. If this field is not empty,
24+
/// it takes precedent over the `uri` field for sourcing the texture.
25+
bytes: [ubyte];
26+
}
27+
28+
enum MaterialType:byte {
29+
kUnlit,
30+
kPhysicallyBased,
31+
}
32+
33+
/// The final color of each material component is the texture color multiplied
34+
/// by the factor of the component.
35+
/// Texture fields are indices into the `Scene`->`textures` array. All textures
36+
/// are optional -- a texture index value of -1 indicates no texture.
37+
table Material {
38+
// When the `MaterialType` is `kUnlit`, only the `base_color` fields are used.
39+
type: MaterialType;
40+
41+
base_color_factor: Color;
42+
base_color_texture: int = -1;
43+
44+
metallic_factor: float = 0;
45+
roughness_factor: float = 0.5;
46+
metallic_roughness_texture: int = -1; // Red=Metallic, Green=Roughness.
47+
48+
normal_texture: int = -1; // Tangent space normal map.
49+
50+
occlusion_texture: int = -1;
51+
}
52+
53+
//-----------------------------------------------------------------------------
54+
/// Geometry.
55+
///
56+
757
struct Vec2 {
858
x: float;
959
y: float;
@@ -22,17 +72,6 @@ struct Vec4 {
2272
w: float;
2373
}
2474

25-
struct Color {
26-
r: float;
27-
g: float;
28-
b: float;
29-
a: float;
30-
}
31-
32-
struct Matrix {
33-
m: [float:16];
34-
}
35-
3675
// This attribute layout is expected to be identical to that within
3776
// `impeller/scene/shaders/geometry.vert`.
3877
struct Vertex {
@@ -43,6 +82,27 @@ struct Vertex {
4382
color: Color;
4483
}
4584

85+
table UnskinnedVertexBuffer {
86+
vertices: [Vertex];
87+
}
88+
89+
struct SkinnedVertex {
90+
vertex: Vertex;
91+
/// Four joint indices corresponding to this mesh's skin transforms. These
92+
/// are floats instead of ints because this vertex data is uploaded directly
93+
/// to the GPU, and float attributes work for all Impeller backends.
94+
joints: Vec4;
95+
/// Four weight values that specify the influence of the corresponding
96+
/// joints.
97+
weights: Vec4;
98+
}
99+
100+
table SkinnedVertexBuffer {
101+
vertices: [SkinnedVertex];
102+
}
103+
104+
union VertexBuffer { UnskinnedVertexBuffer, SkinnedVertexBuffer }
105+
46106
enum IndexType:byte {
47107
k16Bit,
48108
k32Bit,
@@ -54,31 +114,69 @@ table Indices {
54114
type: IndexType;
55115
}
56116

57-
table Texture {
58-
// TODO(bdero): Allow optional image data embedding.
59-
uri: string;
117+
table MeshPrimitive {
118+
vertices: VertexBuffer;
119+
indices: Indices;
120+
material: Material;
60121
}
61122

62-
table Material {
63-
base_color_factor: Color;
64-
base_color_texture: Texture;
65-
// TODO(bdero): PBR textures.
123+
//-----------------------------------------------------------------------------
124+
/// Animations.
125+
///
126+
127+
table TranslationKeyframes {
128+
values: [Vec3];
66129
}
67130

68-
table MeshPrimitive {
69-
vertices: [Vertex];
70-
indices: Indices;
71-
material: Material;
131+
table RotationKeyframes {
132+
values: [Vec4];
133+
}
134+
135+
table ScaleKeyframes {
136+
values: [Vec3];
137+
}
138+
139+
union Keyframes { TranslationKeyframes, RotationKeyframes, ScaleKeyframes }
140+
141+
table Channel {
142+
node: int; // Index into `Scene`->`nodes`.
143+
timeline: [float];
144+
keyframes: Keyframes;
145+
}
146+
147+
table Animation {
148+
name: string;
149+
channels: [Channel];
150+
}
151+
152+
table Skin {
153+
joints: [int]; // Index into `Scene`->`nodes`.
154+
inverse_bind_matrices: [Matrix];
155+
/// The root joint of the skeleton.
156+
skeleton: int; // Index into `Scene`->`nodes`.
157+
}
158+
159+
//-----------------------------------------------------------------------------
160+
/// Scene graph.
161+
///
162+
163+
struct Matrix {
164+
m: [float:16];
72165
}
73166

74167
table Node {
75-
children: [Node];
168+
name: string;
169+
children: [int]; // Index into `Scene`->`nodes`.
76170
transform: Matrix;
77171
mesh_primitives: [MeshPrimitive];
172+
skin: Skin;
78173
}
79174

80175
table Scene {
81-
children: [Node];
176+
children: [int]; // Index into `Scene`->`nodes`.
177+
nodes: [Node];
178+
textures: [Texture]; // Textures may be reused across different materials.
179+
animations: [Animation];
82180
}
83181

84182
root_type Scene;

impeller/scene/importer/vertices_builder.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <cstring>
88
#include <limits>
9+
#include <memory>
910
#include <type_traits>
1011

1112
#include "flutter/fml/logging.h"
@@ -18,13 +19,15 @@ namespace importer {
1819

1920
VerticesBuilder::VerticesBuilder() = default;
2021

21-
void VerticesBuilder::WriteFBVertices(std::vector<fb::Vertex>& vertices) const {
22-
vertices.resize(0);
22+
void VerticesBuilder::WriteFBVertices(fb::MeshPrimitiveT& primitive) const {
23+
auto vertex_buffer = fb::UnskinnedVertexBufferT();
24+
vertex_buffer.vertices.resize(0);
2325
for (auto& v : vertices_) {
24-
vertices.push_back(fb::Vertex(
26+
vertex_buffer.vertices.push_back(fb::Vertex(
2527
ToFBVec3(v.position), ToFBVec3(v.normal), ToFBVec4(v.tangent),
2628
ToFBVec2(v.texture_coords), ToFBColor(v.color)));
2729
}
30+
primitive.vertices.Set(std::move(vertex_buffer));
2831
}
2932

3033
/// @brief Reads a numeric component from `source` and returns a 32bit float.

impeller/scene/importer/vertices_builder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class VerticesBuilder {
5757

5858
VerticesBuilder();
5959

60-
void WriteFBVertices(std::vector<fb::Vertex>& vertices) const;
60+
void WriteFBVertices(fb::MeshPrimitiveT& primitive) const;
6161

6262
void SetAttributeFromBuffer(AttributeType attribute,
6363
ComponentType component_type,

0 commit comments

Comments
 (0)