Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Impeller Scene] Import skinned mesh vertex data #38554

Merged
merged 3 commits into from
Dec 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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