Skip to content

Commit

Permalink
[Impeller Scene] Import skinned mesh vertex data (flutter#38554)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdero authored Dec 29, 2022
1 parent 5713a21 commit fd94b04
Show file tree
Hide file tree
Showing 11 changed files with 498 additions and 118 deletions.
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1635,6 +1635,7 @@ ORIGIN: ../../../flutter/impeller/scene/scene_context.cc + ../../../flutter/LICE
ORIGIN: ../../../flutter/impeller/scene/scene_context.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/scene/scene_encoder.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/scene/scene_encoder.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/scene/shaders/skinned.vert + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/scene/shaders/unlit.frag + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/scene/shaders/unskinned.vert + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/tessellator/c/tessellator.cc + ../../../flutter/LICENSE
Expand Down Expand Up @@ -4094,6 +4095,7 @@ FILE: ../../../flutter/impeller/scene/scene_context.cc
FILE: ../../../flutter/impeller/scene/scene_context.h
FILE: ../../../flutter/impeller/scene/scene_encoder.cc
FILE: ../../../flutter/impeller/scene/scene_encoder.h
FILE: ../../../flutter/impeller/scene/shaders/skinned.vert
FILE: ../../../flutter/impeller/scene/shaders/unlit.frag
FILE: ../../../flutter/impeller/scene/shaders/unskinned.vert
FILE: ../../../flutter/impeller/tessellator/c/tessellator.cc
Expand Down
121 changes: 90 additions & 31 deletions impeller/scene/geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "impeller/renderer/vertex_buffer.h"
#include "impeller/renderer/vertex_buffer_builder.h"
#include "impeller/scene/importer/scene_flatbuffers.h"
#include "impeller/scene/shaders/skinned.vert.h"
#include "impeller/scene/shaders/unskinned.vert.h"

namespace impeller {
Expand All @@ -32,14 +33,20 @@ std::shared_ptr<CuboidGeometry> Geometry::MakeCuboid(Vector3 size) {
return result;
}

std::shared_ptr<VertexBufferGeometry> Geometry::MakeVertexBuffer(
VertexBuffer vertex_buffer) {
auto result = std::make_shared<VertexBufferGeometry>();
result->SetVertexBuffer(std::move(vertex_buffer));
return result;
std::shared_ptr<Geometry> Geometry::MakeVertexBuffer(VertexBuffer vertex_buffer,
bool is_skinned) {
if (is_skinned) {
auto result = std::make_shared<SkinnedVertexBufferGeometry>();
result->SetVertexBuffer(std::move(vertex_buffer));
return result;
} else {
auto result = std::make_shared<UnskinnedVertexBufferGeometry>();
result->SetVertexBuffer(std::move(vertex_buffer));
return result;
}
}

std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFlatbuffer(
std::shared_ptr<Geometry> Geometry::MakeFromFlatbuffer(
const fb::MeshPrimitive& mesh,
Allocator& allocator) {
IndexType index_type;
Expand All @@ -52,17 +59,34 @@ std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFlatbuffer(
break;
}

if (mesh.vertices_type() == fb::VertexBuffer::SkinnedVertexBuffer) {
VALIDATION_LOG << "Skinned meshes not yet supported.";
return nullptr;
}
if (mesh.vertices_type() != fb::VertexBuffer::UnskinnedVertexBuffer) {
VALIDATION_LOG << "Invalid vertex buffer type.";
return nullptr;
const uint8_t* vertices_start;
size_t vertices_bytes;
bool is_skinned;

switch (mesh.vertices_type()) {
case fb::VertexBuffer::UnskinnedVertexBuffer: {
const auto* vertices =
mesh.vertices_as_UnskinnedVertexBuffer()->vertices();
vertices_start = reinterpret_cast<const uint8_t*>(vertices->Get(0));
vertices_bytes = vertices->size() * sizeof(fb::Vertex);
is_skinned = false;
break;
}
case fb::VertexBuffer::SkinnedVertexBuffer: {
const auto* vertices = mesh.vertices_as_SkinnedVertexBuffer()->vertices();
vertices_start = reinterpret_cast<const uint8_t*>(vertices->Get(0));
vertices_bytes = vertices->size() * sizeof(fb::SkinnedVertex);
is_skinned = true;
break;
}
case fb::VertexBuffer::NONE:
VALIDATION_LOG << "Invalid vertex buffer type.";
return nullptr;
}

const auto* vertices = mesh.vertices_as_UnskinnedVertexBuffer()->vertices();
const size_t vertices_bytes = vertices->size() * sizeof(fb::Vertex);
const uint8_t* indices_start =
reinterpret_cast<const uint8_t*>(mesh.indices()->data()->Data());

const size_t indices_bytes = mesh.indices()->data()->size();
if (vertices_bytes == 0 || indices_bytes == 0) {
return nullptr;
Expand All @@ -75,11 +99,6 @@ std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFlatbuffer(
auto buffer = allocator.CreateBuffer(buffer_desc);
buffer->SetLabel("Mesh vertices+indices");

const uint8_t* vertices_start =
reinterpret_cast<const uint8_t*>(vertices->Get(0));
const uint8_t* indices_start =
reinterpret_cast<const uint8_t*>(mesh.indices()->data()->Data());

if (!buffer->CopyHostBuffer(vertices_start, Range(0, vertices_bytes))) {
return nullptr;
}
Expand All @@ -95,7 +114,7 @@ std::shared_ptr<VertexBufferGeometry> Geometry::MakeFromFlatbuffer(
.index_count = mesh.indices()->count(),
.index_type = index_type,
};
return MakeVertexBuffer(std::move(vertex_buffer));
return MakeVertexBuffer(std::move(vertex_buffer), is_skinned);
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -151,32 +170,35 @@ void CuboidGeometry::BindToCommand(const SceneContext& scene_context,
}

//------------------------------------------------------------------------------
/// VertexBufferGeometry
/// UnskinnedVertexBufferGeometry
///

VertexBufferGeometry::VertexBufferGeometry() = default;
UnskinnedVertexBufferGeometry::UnskinnedVertexBufferGeometry() = default;

VertexBufferGeometry::~VertexBufferGeometry() = default;
UnskinnedVertexBufferGeometry::~UnskinnedVertexBufferGeometry() = default;

void VertexBufferGeometry::SetVertexBuffer(VertexBuffer vertex_buffer) {
void UnskinnedVertexBufferGeometry::SetVertexBuffer(
VertexBuffer vertex_buffer) {
vertex_buffer_ = std::move(vertex_buffer);
}

// |Geometry|
GeometryType VertexBufferGeometry::GetGeometryType() const {
GeometryType UnskinnedVertexBufferGeometry::GetGeometryType() const {
return GeometryType::kUnskinned;
}

// |Geometry|
VertexBuffer VertexBufferGeometry::GetVertexBuffer(Allocator& allocator) const {
VertexBuffer UnskinnedVertexBufferGeometry::GetVertexBuffer(
Allocator& allocator) const {
return vertex_buffer_;
}

// |Geometry|
void VertexBufferGeometry::BindToCommand(const SceneContext& scene_context,
HostBuffer& buffer,
const Matrix& transform,
Command& command) const {
void UnskinnedVertexBufferGeometry::BindToCommand(
const SceneContext& scene_context,
HostBuffer& buffer,
const Matrix& transform,
Command& command) const {
command.BindVertices(
GetVertexBuffer(*scene_context.GetContext()->GetResourceAllocator()));

Expand All @@ -185,5 +207,42 @@ void VertexBufferGeometry::BindToCommand(const SceneContext& scene_context,
UnskinnedVertexShader::BindVertInfo(command, buffer.EmplaceUniform(info));
}

//------------------------------------------------------------------------------
/// SkinnedVertexBufferGeometry
///

SkinnedVertexBufferGeometry::SkinnedVertexBufferGeometry() = default;

SkinnedVertexBufferGeometry::~SkinnedVertexBufferGeometry() = default;

void SkinnedVertexBufferGeometry::SetVertexBuffer(VertexBuffer vertex_buffer) {
vertex_buffer_ = std::move(vertex_buffer);
}

// |Geometry|
GeometryType SkinnedVertexBufferGeometry::GetGeometryType() const {
return GeometryType::kSkinned;
}

// |Geometry|
VertexBuffer SkinnedVertexBufferGeometry::GetVertexBuffer(
Allocator& allocator) const {
return vertex_buffer_;
}

// |Geometry|
void SkinnedVertexBufferGeometry::BindToCommand(
const SceneContext& scene_context,
HostBuffer& buffer,
const Matrix& transform,
Command& command) const {
command.BindVertices(
GetVertexBuffer(*scene_context.GetContext()->GetResourceAllocator()));

SkinnedVertexShader::VertInfo info;
info.mvp = transform;
SkinnedVertexShader::BindVertInfo(command, buffer.EmplaceUniform(info));
}

} // namespace scene
} // namespace impeller
42 changes: 34 additions & 8 deletions impeller/scene/geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ namespace impeller {
namespace scene {

class CuboidGeometry;
class VertexBufferGeometry;
class UnskinnedVertexBufferGeometry;

class Geometry {
public:
virtual ~Geometry();

static std::shared_ptr<CuboidGeometry> MakeCuboid(Vector3 size);

static std::shared_ptr<VertexBufferGeometry> MakeVertexBuffer(
VertexBuffer vertex_buffer);
static std::shared_ptr<Geometry> MakeVertexBuffer(VertexBuffer vertex_buffer,
bool is_skinned);

static std::shared_ptr<VertexBufferGeometry> MakeFromFlatbuffer(
static std::shared_ptr<Geometry> MakeFromFlatbuffer(
const fb::MeshPrimitive& mesh,
Allocator& allocator);

Expand Down Expand Up @@ -73,11 +73,11 @@ class CuboidGeometry final : public Geometry {
FML_DISALLOW_COPY_AND_ASSIGN(CuboidGeometry);
};

class VertexBufferGeometry final : public Geometry {
class UnskinnedVertexBufferGeometry final : public Geometry {
public:
VertexBufferGeometry();
UnskinnedVertexBufferGeometry();

~VertexBufferGeometry() override;
~UnskinnedVertexBufferGeometry() override;

void SetVertexBuffer(VertexBuffer vertex_buffer);

Expand All @@ -96,7 +96,33 @@ class VertexBufferGeometry final : public Geometry {
private:
VertexBuffer vertex_buffer_;

FML_DISALLOW_COPY_AND_ASSIGN(VertexBufferGeometry);
FML_DISALLOW_COPY_AND_ASSIGN(UnskinnedVertexBufferGeometry);
};

class SkinnedVertexBufferGeometry final : public Geometry {
public:
SkinnedVertexBufferGeometry();

~SkinnedVertexBufferGeometry() override;

void SetVertexBuffer(VertexBuffer vertex_buffer);

// |Geometry|
GeometryType GetGeometryType() const override;

// |Geometry|
VertexBuffer GetVertexBuffer(Allocator& allocator) const override;

// |Geometry|
void BindToCommand(const SceneContext& scene_context,
HostBuffer& buffer,
const Matrix& transform,
Command& command) const override;

private:
VertexBuffer vertex_buffer_;

FML_DISALLOW_COPY_AND_ASSIGN(SkinnedVertexBufferGeometry);
};

} // namespace scene
Expand Down
35 changes: 27 additions & 8 deletions impeller/scene/importer/importer_gltf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,19 @@ static const std::map<std::string, VerticesBuilder::AttributeType> kAttributes =
{"NORMAL", VerticesBuilder::AttributeType::kNormal},
{"TANGENT", VerticesBuilder::AttributeType::kTangent},
{"TEXCOORD_0", VerticesBuilder::AttributeType::kTextureCoords},
{"COLOR_0", VerticesBuilder::AttributeType::kColor}};
{"COLOR_0", VerticesBuilder::AttributeType::kColor},
{"JOINTS_0", VerticesBuilder::AttributeType::kJoints},
{"WEIGHTS_0", VerticesBuilder::AttributeType::kWeights}};

static bool WithinRange(int index, size_t size) {
return index >= 0 && static_cast<size_t>(index) < size;
}

static bool MeshPrimitiveIsSkinned(const tinygltf::Primitive& primitive) {
return primitive.attributes.find("JOINTS_0") != primitive.attributes.end() &&
primitive.attributes.find("WEIGHTS_0") != primitive.attributes.end();
}

static bool ProcessMeshPrimitive(const tinygltf::Model& gltf,
const tinygltf::Primitive& primitive,
fb::MeshPrimitiveT& mesh_primitive) {
Expand All @@ -41,7 +48,10 @@ static bool ProcessMeshPrimitive(const tinygltf::Model& gltf,
///

{
VerticesBuilder builder;
bool is_skinned = MeshPrimitiveIsSkinned(primitive);
std::unique_ptr<VerticesBuilder> builder =
is_skinned ? VerticesBuilder::MakeSkinned()
: VerticesBuilder::MakeUnskinned();

for (const auto& attribute : primitive.attributes) {
auto attribute_type = kAttributes.find(attribute.first);
Expand All @@ -50,6 +60,14 @@ static bool ProcessMeshPrimitive(const tinygltf::Model& gltf,
<< "\" not supported." << std::endl;
continue;
}
if (!is_skinned &&
(attribute_type->second == VerticesBuilder::AttributeType::kJoints ||
attribute_type->second ==
VerticesBuilder::AttributeType::kWeights)) {
// If the primitive doesn't have enough information to be skinned, skip
// skinning-related attributes.
continue;
}

const auto accessor = gltf.accessors[attribute.second];
const auto view = gltf.bufferViews[accessor.bufferView];
Expand Down Expand Up @@ -86,14 +104,15 @@ static bool ProcessMeshPrimitive(const tinygltf::Model& gltf,
continue;
}

builder.SetAttributeFromBuffer(attribute_type->second, // attribute
type, // component_type
source_start, // buffer_start
accessor.ByteStride(view), // stride_bytes
accessor.count); // count
builder->SetAttributeFromBuffer(
attribute_type->second, // attribute
type, // component_type
source_start, // buffer_start
accessor.ByteStride(view), // stride_bytes
accessor.count); // count
}

builder.WriteFBVertices(mesh_primitive);
builder->WriteFBVertices(mesh_primitive);
}

//---------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit fd94b04

Please sign in to comment.