Merge pull request #3487 from inhosens/master

Prevent to generate redundant morph targets for glTF2
pull/3511/head
Kim Kulling 2020-11-25 17:13:38 +01:00 committed by GitHub
commit 11b4153949
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 59 additions and 31 deletions

View File

@ -453,11 +453,16 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
aim->mNumAnimMeshes = (unsigned int)targets.size(); aim->mNumAnimMeshes = (unsigned int)targets.size();
aim->mAnimMeshes = new aiAnimMesh *[aim->mNumAnimMeshes]; aim->mAnimMeshes = new aiAnimMesh *[aim->mNumAnimMeshes];
for (size_t i = 0; i < targets.size(); i++) { for (size_t i = 0; i < targets.size(); i++) {
aim->mAnimMeshes[i] = aiCreateAnimMesh(aim); bool needPositions = targets[i].position.size() > 0;
bool needNormals = targets[i].normal.size() > 0;
bool needTangents = targets[i].tangent.size() > 0;
// GLTF morph does not support colors and texCoords
aim->mAnimMeshes[i] = aiCreateAnimMesh(aim,
needPositions, needNormals, needTangents, false, false);
aiAnimMesh &aiAnimMesh = *(aim->mAnimMeshes[i]); aiAnimMesh &aiAnimMesh = *(aim->mAnimMeshes[i]);
Mesh::Primitive::Target &target = targets[i]; Mesh::Primitive::Target &target = targets[i];
if (target.position.size() > 0) { if (needPositions) {
aiVector3D *positionDiff = nullptr; aiVector3D *positionDiff = nullptr;
target.position[0]->ExtractData(positionDiff); target.position[0]->ExtractData(positionDiff);
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
@ -465,7 +470,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
} }
delete[] positionDiff; delete[] positionDiff;
} }
if (target.normal.size() > 0) { if (needNormals) {
aiVector3D *normalDiff = nullptr; aiVector3D *normalDiff = nullptr;
target.normal[0]->ExtractData(normalDiff); target.normal[0]->ExtractData(normalDiff);
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
@ -473,7 +478,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
} }
delete[] normalDiff; delete[] normalDiff;
} }
if (target.tangent.size() > 0) { if (needTangents) {
Tangent *tangent = nullptr; Tangent *tangent = nullptr;
attr.tangent[0]->ExtractData(tangent); attr.tangent[0]->ExtractData(tangent);
@ -1069,9 +1074,11 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
samplers.translation->output->ExtractData(values); samplers.translation->output->ExtractData(values);
anim->mNumPositionKeys = static_cast<uint32_t>(samplers.translation->input->count); anim->mNumPositionKeys = static_cast<uint32_t>(samplers.translation->input->count);
anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
unsigned int ii = (samplers.translation->interpolation == Interpolation_CUBICSPLINE) ? 1 : 0;
for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) { for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) {
anim->mPositionKeys[i].mTime = times[i] * kMillisecondsFromSeconds; anim->mPositionKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
anim->mPositionKeys[i].mValue = values[i]; anim->mPositionKeys[i].mValue = values[ii];
ii += (samplers.translation->interpolation == Interpolation_CUBICSPLINE) ? 3 : 1;
} }
delete[] times; delete[] times;
delete[] values; delete[] values;
@ -1091,12 +1098,14 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
samplers.rotation->output->ExtractData(values); samplers.rotation->output->ExtractData(values);
anim->mNumRotationKeys = static_cast<uint32_t>(samplers.rotation->input->count); anim->mNumRotationKeys = static_cast<uint32_t>(samplers.rotation->input->count);
anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys]; anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys];
unsigned int ii = (samplers.rotation->interpolation == Interpolation_CUBICSPLINE) ? 1 : 0;
for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) { for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) {
anim->mRotationKeys[i].mTime = times[i] * kMillisecondsFromSeconds; anim->mRotationKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
anim->mRotationKeys[i].mValue.x = values[i].w; anim->mRotationKeys[i].mValue.x = values[ii].w;
anim->mRotationKeys[i].mValue.y = values[i].x; anim->mRotationKeys[i].mValue.y = values[ii].x;
anim->mRotationKeys[i].mValue.z = values[i].y; anim->mRotationKeys[i].mValue.z = values[ii].y;
anim->mRotationKeys[i].mValue.w = values[i].z; anim->mRotationKeys[i].mValue.w = values[ii].z;
ii += (samplers.rotation->interpolation == Interpolation_CUBICSPLINE) ? 3 : 1;
} }
delete[] times; delete[] times;
delete[] values; delete[] values;
@ -1117,9 +1126,11 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
samplers.scale->output->ExtractData(values); samplers.scale->output->ExtractData(values);
anim->mNumScalingKeys = static_cast<uint32_t>(samplers.scale->input->count); anim->mNumScalingKeys = static_cast<uint32_t>(samplers.scale->input->count);
anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys]; anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys];
unsigned int ii = (samplers.scale->interpolation == Interpolation_CUBICSPLINE) ? 1 : 0;
for (unsigned int i = 0; i < anim->mNumScalingKeys; ++i) { for (unsigned int i = 0; i < anim->mNumScalingKeys; ++i) {
anim->mScalingKeys[i].mTime = times[i] * kMillisecondsFromSeconds; anim->mScalingKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
anim->mScalingKeys[i].mValue = values[i]; anim->mScalingKeys[i].mValue = values[ii];
ii += (samplers.scale->interpolation == Interpolation_CUBICSPLINE) ? 3 : 1;
} }
delete[] times; delete[] times;
delete[] values; delete[] values;
@ -1148,11 +1159,14 @@ aiMeshMorphAnim *CreateMeshMorphAnim(glTF2::Asset&, Node &node, AnimationSampler
samplers.weight->output->ExtractData(values); samplers.weight->output->ExtractData(values);
anim->mNumKeys = static_cast<uint32_t>(samplers.weight->input->count); anim->mNumKeys = static_cast<uint32_t>(samplers.weight->input->count);
const unsigned int numMorphs = (unsigned int)samplers.weight->output->count / anim->mNumKeys; // for Interpolation_CUBICSPLINE can have more outputs
const unsigned int weightStride = (unsigned int)samplers.weight->output->count / anim->mNumKeys;
const unsigned int numMorphs = (samplers.weight->interpolation == Interpolation_CUBICSPLINE) ? weightStride - 2 : weightStride;
anim->mKeys = new aiMeshMorphKey[anim->mNumKeys]; anim->mKeys = new aiMeshMorphKey[anim->mNumKeys];
unsigned int k = 0u; unsigned int ii = (samplers.weight->interpolation == Interpolation_CUBICSPLINE) ? 1 : 0;
for (unsigned int i = 0u; i < anim->mNumKeys; ++i) { for (unsigned int i = 0u; i < anim->mNumKeys; ++i) {
unsigned int k = weightStride * i + ii;
anim->mKeys[i].mTime = times[i] * kMillisecondsFromSeconds; anim->mKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
anim->mKeys[i].mNumValuesAndWeights = numMorphs; anim->mKeys[i].mNumValuesAndWeights = numMorphs;
anim->mKeys[i].mValues = new unsigned int[numMorphs]; anim->mKeys[i].mValues = new unsigned int[numMorphs];

View File

@ -44,27 +44,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh) aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh, bool needPositions, bool needNormals, bool needTangents, bool needColors, bool needTexCoords)
{ {
aiAnimMesh *animesh = new aiAnimMesh; aiAnimMesh *animesh = new aiAnimMesh;
animesh->mNumVertices = mesh->mNumVertices; animesh->mNumVertices = mesh->mNumVertices;
if (mesh->mVertices) { if (needPositions && mesh->mVertices) {
animesh->mVertices = new aiVector3D[animesh->mNumVertices]; animesh->mVertices = new aiVector3D[animesh->mNumVertices];
std::memcpy(animesh->mVertices, mesh->mVertices, mesh->mNumVertices * sizeof(aiVector3D)); std::memcpy(animesh->mVertices, mesh->mVertices, mesh->mNumVertices * sizeof(aiVector3D));
} }
if (mesh->mNormals) { if (needNormals && mesh->mNormals) {
animesh->mNormals = new aiVector3D[animesh->mNumVertices]; animesh->mNormals = new aiVector3D[animesh->mNumVertices];
std::memcpy(animesh->mNormals, mesh->mNormals, mesh->mNumVertices * sizeof(aiVector3D)); std::memcpy(animesh->mNormals, mesh->mNormals, mesh->mNumVertices * sizeof(aiVector3D));
} }
if (mesh->mTangents) { if (needTangents && mesh->mTangents) {
animesh->mTangents = new aiVector3D[animesh->mNumVertices]; animesh->mTangents = new aiVector3D[animesh->mNumVertices];
std::memcpy(animesh->mTangents, mesh->mTangents, mesh->mNumVertices * sizeof(aiVector3D)); std::memcpy(animesh->mTangents, mesh->mTangents, mesh->mNumVertices * sizeof(aiVector3D));
} }
if (mesh->mBitangents) { if (needTangents && mesh->mBitangents) {
animesh->mBitangents = new aiVector3D[animesh->mNumVertices]; animesh->mBitangents = new aiVector3D[animesh->mNumVertices];
std::memcpy(animesh->mBitangents, mesh->mBitangents, mesh->mNumVertices * sizeof(aiVector3D)); std::memcpy(animesh->mBitangents, mesh->mBitangents, mesh->mNumVertices * sizeof(aiVector3D));
} }
if (needColors) {
for (int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) { for (int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
if (mesh->mColors[i]) { if (mesh->mColors[i]) {
animesh->mColors[i] = new aiColor4D[animesh->mNumVertices]; animesh->mColors[i] = new aiColor4D[animesh->mNumVertices];
@ -73,7 +74,9 @@ aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh)
animesh->mColors[i] = nullptr; animesh->mColors[i] = nullptr;
} }
} }
}
if (needTexCoords) {
for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if (mesh->mTextureCoords[i]) { if (mesh->mTextureCoords[i]) {
animesh->mTextureCoords[i] = new aiVector3D[animesh->mNumVertices]; animesh->mTextureCoords[i] = new aiVector3D[animesh->mNumVertices];
@ -82,6 +85,7 @@ aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh)
animesh->mTextureCoords[i] = nullptr; animesh->mTextureCoords[i] = nullptr;
} }
} }
}
return animesh; return animesh;
} }

View File

@ -58,9 +58,19 @@ namespace Assimp {
/** /**
* Create aiAnimMesh from aiMesh. * Create aiAnimMesh from aiMesh.
* @param mesh The input mesh to create an animated mesh from. * @param mesh The input mesh to create an animated mesh from.
* @param needPositions If true, positions will be copied from.
* @param needNormals If true, normals will be copied from.
* @param needTangents If true, tangents and bitangents will be copied from.
* @param needColors If true, colors will be copied from.
* @param needTexCoords If true, texCoords will be copied from.
* @return The new created animated mesh. * @return The new created animated mesh.
*/ */
ASSIMP_API aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh); ASSIMP_API aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh,
bool needPositions = true,
bool needNormals = true,
bool needTangents = true,
bool needColors = true,
bool needTexCoords = true);
} // end of namespace Assimp } // end of namespace Assimp