diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 35448d4dc..e1ab13396 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,2 +1 @@
-patreon: assimp
open_collective: assimp
diff --git a/Readme.md b/Readme.md
index 71b3c7f10..51684c4aa 100644
--- a/Readme.md
+++ b/Readme.md
@@ -76,9 +76,6 @@ For more information, visit [our website](http://assimp.org/). Or check out the
If the docs don't solve your problem, ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github.
-For development discussions, there is also a (very low-volume) mailing list, _assimp-discussions_
- [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions)
-
Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
And we also have a Gitter-channel:Gitter [](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -103,9 +100,6 @@ Become a financial contributor and help us sustain our community. [[Contribute](
-Monthly donations via Patreon:
-
[](http://www.patreon.com/assimp)
-
#### Organizations
diff --git a/code/AssetLib/3DS/3DSLoader.cpp b/code/AssetLib/3DS/3DSLoader.cpp
index 3dabf9da1..0a64f6870 100644
--- a/code/AssetLib/3DS/3DSLoader.cpp
+++ b/code/AssetLib/3DS/3DSLoader.cpp
@@ -981,9 +981,9 @@ void Discreet3DSImporter::ParseMeshChunk() {
mMesh.mMat.a3 = stream->GetF4();
mMesh.mMat.b3 = stream->GetF4();
mMesh.mMat.c3 = stream->GetF4();
- mMesh.mMat.a4 = stream->GetF4();
- mMesh.mMat.b4 = stream->GetF4();
- mMesh.mMat.c4 = stream->GetF4();
+ mMesh.mMat.d1 = stream->GetF4();
+ mMesh.mMat.d2 = stream->GetF4();
+ mMesh.mMat.d3 = stream->GetF4();
} break;
case Discreet3DS::CHUNK_MAPLIST: {
diff --git a/code/AssetLib/FBX/FBXExporter.cpp b/code/AssetLib/FBX/FBXExporter.cpp
index ae93cba02..322161411 100644
--- a/code/AssetLib/FBX/FBXExporter.cpp
+++ b/code/AssetLib/FBX/FBXExporter.cpp
@@ -812,6 +812,18 @@ void FBXExporter::WriteDefinitions ()
// Geometry / FbxMesh
// <~~ aiMesh
count = mScene->mNumMeshes;
+
+ // Blendshapes are considered Geometry
+ int32_t bsDeformerCount=0;
+ for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
+ aiMesh* m = mScene->mMeshes[mi];
+ if (m->mNumAnimMeshes > 0) {
+ count+=m->mNumAnimMeshes;
+ bsDeformerCount+=m->mNumAnimMeshes; // One deformer per blendshape
+ bsDeformerCount++; // Plus one master blendshape deformer
+ }
+ }
+
if (count) {
n = FBX::Node("ObjectType", "Geometry");
n.AddChild("Count", count);
@@ -978,7 +990,7 @@ void FBXExporter::WriteDefinitions ()
}
// Deformer
- count = int32_t(count_deformers(mScene));
+ count = int32_t(count_deformers(mScene))+bsDeformerCount;
if (count) {
n = FBX::Node("ObjectType", "Deformer");
n.AddChild("Count", count);
@@ -1363,6 +1375,7 @@ void FBXExporter::WriteObjects ()
n.End(outstream, binary, indent, true);
}
+
// aiMaterial
material_uids.clear();
for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
@@ -1697,6 +1710,100 @@ void FBXExporter::WriteObjects ()
}
}
+ // Blendshapes, if any
+ for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
+ const aiMesh* m = mScene->mMeshes[mi];
+ if (m->mNumAnimMeshes == 0) {
+ continue;
+ }
+ // make a deformer for this mesh
+ int64_t deformer_uid = generate_uid();
+ FBX::Node dnode("Deformer");
+ dnode.AddProperties(deformer_uid, m->mName.data + FBX::SEPARATOR + "Blendshapes", "BlendShape");
+ dnode.AddChild("Version", int32_t(101));
+ dnode.Dump(outstream, binary, indent);
+ // connect it
+ connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]);
+ std::vector vertex_indices = vVertexIndice[mi];
+
+ for (unsigned int am = 0; am < m->mNumAnimMeshes; ++am) {
+ aiAnimMesh *pAnimMesh = m->mAnimMeshes[am];
+ std::string blendshape_name = pAnimMesh->mName.data;
+
+ // start the node record
+ FBX::Node bsnode("Geometry");
+ int64_t blendshape_uid = generate_uid();
+ mesh_uids.push_back(blendshape_uid);
+ bsnode.AddProperty(blendshape_uid);
+ bsnode.AddProperty(blendshape_name + FBX::SEPARATOR + "Blendshape");
+ bsnode.AddProperty("Shape");
+ bsnode.AddChild("Version", int32_t(100));
+ bsnode.Begin(outstream, binary, indent);
+ bsnode.DumpProperties(outstream, binary, indent);
+ bsnode.EndProperties(outstream, binary, indent);
+ bsnode.BeginChildren(outstream, binary, indent);
+ indent++;
+ if (pAnimMesh->HasPositions()) {
+ std::vectorshape_indices;
+ std::vectorpPositionDiff;
+ std::vectorpNormalDiff;
+
+ for (unsigned int vt = 0; vt < vertex_indices.size(); ++vt) {
+ aiVector3D pDiff = (pAnimMesh->mVertices[vertex_indices[vt]] - m->mVertices[vertex_indices[vt]]);
+ if(pDiff.Length()>1e-8){
+ shape_indices.push_back(vertex_indices[vt]);
+ pPositionDiff.push_back(pDiff[0]);
+ pPositionDiff.push_back(pDiff[1]);
+ pPositionDiff.push_back(pDiff[2]);
+
+ if (pAnimMesh->HasNormals()) {
+ aiVector3D nDiff = (pAnimMesh->mNormals[vertex_indices[vt]] - m->mNormals[vertex_indices[vt]]);
+ pNormalDiff.push_back(nDiff[0]);
+ pNormalDiff.push_back(nDiff[1]);
+ pNormalDiff.push_back(nDiff[2]);
+ }
+ }
+ }
+
+ FBX::Node::WritePropertyNode(
+ "Indexes", shape_indices, outstream, binary, indent
+ );
+
+ FBX::Node::WritePropertyNode(
+ "Vertices", pPositionDiff, outstream, binary, indent
+ );
+
+ if (pNormalDiff.size()>0) {
+ FBX::Node::WritePropertyNode(
+ "Normals", pNormalDiff, outstream, binary, indent
+ );
+ }
+ }
+ indent--;
+ bsnode.End(outstream, binary, indent, true);
+
+ // Add blendshape Channel Deformer
+ FBX::Node sdnode("Deformer");
+ const int64_t blendchannel_uid = generate_uid();
+ sdnode.AddProperties(
+ blendchannel_uid, blendshape_name + FBX::SEPARATOR + "SubDeformer", "BlendShapeChannel"
+ );
+ sdnode.AddChild("Version", int32_t(100));
+ sdnode.AddChild("DeformPercent", int32_t(100));
+ FBX::Node p("Properties70");
+ p.AddP70numberA("DeformPercent", 100.);
+ sdnode.AddChild(p);
+ // TODO: Normally just one weight per channel, adding stub for later development
+ std::vectorfFullWeights;
+ fFullWeights.push_back(0.);
+ sdnode.AddChild("FullWeights", fFullWeights);
+ sdnode.Dump(outstream, binary, indent);
+
+ connections.emplace_back("C", "OO", blendchannel_uid, deformer_uid);
+ connections.emplace_back("C", "OO", blendshape_uid, blendchannel_uid);
+ }
+ }
+
// bones.
//
// output structure: