Skip to content

Commit

Permalink
AssimpImporter: implement tangent/bitangent import.
Browse files Browse the repository at this point in the history
  • Loading branch information
mosra committed Mar 28, 2020
1 parent 82d9977 commit 1ed63e0
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 18 deletions.
1 change: 1 addition & 0 deletions doc/changelog-plugins.dox
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace Magnum {
consistent with @ref Trade::TinyGltfImporter "TinyGltfImporter" behavior
(see [mosra/magnum-plugins#68](https://github.com/mosra/magnum-plugins/pull/68)
and [mosra/magnum-plugins#81](https://github.com/mosra/magnum-plugins/pull/81))
- Tangent and bitangent import in @ref Trade::AssimpImporter "AssimpImporter"
- Vertex color, normal and texture coordinate import in
@ref Trade::StanfordImporter "StanfordImporter", colors and normals are
supported per-face as well
Expand Down
27 changes: 27 additions & 0 deletions src/MagnumPlugins/AssimpImporter/AssimpImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,11 @@ Containers::Optional<MeshData> AssimpImporter::doMesh(const UnsignedInt id, Unsi
++attributeCount;
stride += sizeof(Vector3);
}
/* Assimp provides either none or both, never just one of these */
if(mesh->HasTangentsAndBitangents()) {
attributeCount += 2;
stride += 2*sizeof(Vector3);
}
for(std::size_t layer = 0; layer < mesh->GetNumUVChannels(); ++layer) {
if(mesh->mNumUVComponents[layer] != 2) {
Warning() << "Trade::AssimpImporter::mesh(): skipping texture coordinate layer" << layer << "which has" << mesh->mNumUVComponents[layer] << "components per coordinate. Only two dimensional texture coordinates are supported.";
Expand Down Expand Up @@ -590,6 +595,28 @@ Containers::Optional<MeshData> AssimpImporter::doMesh(const UnsignedInt id, Unsi
attributeOffset += sizeof(Vector3);
}

/* Tangents + bitangents, if any. Assimp always provides either none or
both, never just one of these. */
if(mesh->HasTangentsAndBitangents()) {
Containers::StridedArrayView1D<Vector3> tangents{vertexData,
reinterpret_cast<Vector3*>(vertexData + attributeOffset),
vertexCount, stride};
Utility::copy(Containers::arrayView(reinterpret_cast<Vector3*>(mesh->mTangents), mesh->mNumVertices), tangents);

attributeData[attributeIndex++] = MeshAttributeData{
MeshAttribute::Tangent, tangents};
attributeOffset += sizeof(Vector3);

Containers::StridedArrayView1D<Vector3> bitangents{vertexData,
reinterpret_cast<Vector3*>(vertexData + attributeOffset),
vertexCount, stride};
Utility::copy(Containers::arrayView(reinterpret_cast<Vector3*>(mesh->mBitangents), mesh->mNumVertices), bitangents);

attributeData[attributeIndex++] = MeshAttributeData{
MeshAttribute::Bitangent, bitangents};
attributeOffset += sizeof(Vector3);
}

/* Texture coordinates */
/** @todo only first uv layer (or "channel") supported) */
for(std::size_t layer = 0; layer < mesh->GetNumUVChannels(); ++layer) {
Expand Down
13 changes: 8 additions & 5 deletions src/MagnumPlugins/AssimpImporter/AssimpImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,14 @@ Import of animation data is not supported at the moment.
"skeleton visualizer" mesh if the file has no mesh data. For others (such
as glTF) not.
- The importer follows types used by Assimp, thus indices are always
@ref MeshIndexType::UnsignedInt, positions and normals are always imported
as @ref VertexFormat::Vector3, texture coordinates as
@ref VertexFormat::Vector2 and colors as @ref VertexFormat::Vector4. In
other words, everything gets expanded by Assimp to floats, even if the
original file might be using different types.
@ref MeshIndexType::UnsignedInt, positions, normals, tangents and
bitangents are always imported as @ref VertexFormat::Vector3, texture
coordinates as @ref VertexFormat::Vector2 and colors as
@ref VertexFormat::Vector4. In other words, everything gets expanded by
Assimp to floats, even if the original file might be using different types.
- The imported model always has either both @ref MeshAttribute::Tangent
@ref MeshAttribute::Bitangent or neither of them, tangents are always
three-component with binormals separate.
- Multi-mesh nodes and multi-primitive meshes are loaded as follows,
consistently with the behavior of @link TinyGltfImporter @endlink:
- Multi-primitive meshes are split by Assimp into individual meshes
Expand Down
23 changes: 14 additions & 9 deletions src/MagnumPlugins/AssimpImporter/Test/AssimpImporterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ void AssimpImporterTest::mesh() {
Containers::arrayView<UnsignedInt>({0, 1, 2}),
TestSuite::Compare::Container);

CORRADE_COMPARE(mesh->attributeCount(), 4);
CORRADE_COMPARE(mesh->attributeCount(), 6);
CORRADE_COMPARE(mesh->attributeCount(MeshAttribute::Position), 1);
CORRADE_COMPARE_AS(mesh->attribute<Vector3>(MeshAttribute::Position),
Containers::arrayView<Vector3>({
Expand All @@ -628,6 +628,16 @@ void AssimpImporterTest::mesh() {
Containers::arrayView<Vector3>({
{0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}
}), TestSuite::Compare::Container);
CORRADE_COMPARE(mesh->attributeCount(MeshAttribute::Tangent), 1);
CORRADE_COMPARE_AS(mesh->attribute<Vector3>(MeshAttribute::Tangent),
Containers::arrayView<Vector3>({
{1.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f},
}), TestSuite::Compare::Container);
CORRADE_COMPARE(mesh->attributeCount(MeshAttribute::Bitangent), 1);
CORRADE_COMPARE_AS(mesh->attribute<Vector3>(MeshAttribute::Bitangent),
Containers::arrayView<Vector3>({
{0.0f, 1.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 1.0f, 0.0f},
}), TestSuite::Compare::Container);
CORRADE_COMPARE(mesh->attributeCount(MeshAttribute::TextureCoordinates), 1);
CORRADE_COMPARE_AS(mesh->attribute<Vector2>(MeshAttribute::TextureCoordinates),
Containers::arrayView<Vector2>({
Expand Down Expand Up @@ -1219,8 +1229,8 @@ void AssimpImporterTest::fileCallback() {
CORRADE_VERIFY(importer->openFile("not/a/path/mesh.dae"));
CORRADE_COMPARE(importer->meshCount(), 1);

/* Same as in mesh(), not testing colors because of the assimp bugs that
need to be worked around */
/* Same as in mesh(), testing just the basics, no need to repeat everything
here */
Containers::Optional<MeshData> mesh = importer->mesh(0);
CORRADE_VERIFY(mesh);
CORRADE_COMPARE(mesh->primitive(), MeshPrimitive::Triangles);
Expand All @@ -1230,7 +1240,7 @@ void AssimpImporterTest::fileCallback() {
Containers::arrayView<UnsignedInt>({0, 1, 2}),
TestSuite::Compare::Container);

CORRADE_COMPARE(mesh->attributeCount(), 4);
CORRADE_COMPARE(mesh->attributeCount(), 6);
CORRADE_COMPARE(mesh->attributeCount(MeshAttribute::Position), 1);
CORRADE_COMPARE_AS(mesh->attribute<Vector3>(MeshAttribute::Position),
Containers::arrayView<Vector3>({
Expand All @@ -1241,11 +1251,6 @@ void AssimpImporterTest::fileCallback() {
Containers::arrayView<Vector3>({
{0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}
}), TestSuite::Compare::Container);
CORRADE_COMPARE(mesh->attributeCount(MeshAttribute::TextureCoordinates), 1);
CORRADE_COMPARE_AS(mesh->attribute<Vector2>(MeshAttribute::TextureCoordinates),
Containers::arrayView<Vector2>({
{0.5f, 1.0f}, {0.75f, 0.5f}, {0.5f, 0.9f}
}), TestSuite::Compare::Container);
}

void AssimpImporterTest::fileCallbackNotFound() {
Expand Down
21 changes: 17 additions & 4 deletions src/MagnumPlugins/AssimpImporter/Test/mesh.dae
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@
</accessor>
</technique_common>
</source>
<source id="Cube-mesh-tangents">
<float_array id="Cube-mesh-tangents-array" count="3">1 0 0</float_array>
<technique_common>
<accessor source="#Cube-mesh-tangents-array" count="1" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<source id="Cube-mesh-map-0">
<float_array id="Cube-mesh-map-0-array" count="6">0.5 1.0 0.75 0.5 0.5 0.9</float_array>
<technique_common>
Expand All @@ -48,10 +58,13 @@
<polylist count="1">
<input semantic="VERTEX" source="#Cube-mesh-vertices" offset="0"/>
<input semantic="NORMAL" source="#Cube-mesh-normals" offset="1"/>
<input semantic="TEXCOORD" source="#Cube-mesh-map-0" offset="2" set="0"/>
<input semantic="COLOR" source="#Cube-mesh-colors-Col" offset="3" set="0"/>
<vcount>3 </vcount>
<p>1 0 0 0 0 0 1 1 2 0 2 2</p>
<input semantic="TANGENT" source="#Cube-mesh-tangents" offset="2"/>
<input semantic="TEXCOORD" source="#Cube-mesh-map-0" offset="3" set="0"/>
<input semantic="COLOR" source="#Cube-mesh-colors-Col" offset="4" set="0"/>
<vcount>3</vcount>
<p>1 0 0 0 0
0 0 0 1 1
2 0 0 2 2</p>
</polylist>
</mesh>
</geometry>
Expand Down

0 comments on commit 1ed63e0

Please sign in to comment.