Merge pull request #2446 from assimp/issue_2054

closes https://github.com/assimp/assimp/issues/2054: make empty bone …
pull/4057/head
Kim Kulling 2019-05-05 22:20:41 +02:00 committed by GitHub
commit 34084423ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 65 additions and 57 deletions

View File

@ -1299,7 +1299,7 @@ void ASEImporter::BuildMaterialIndices()
} }
} }
// Dekete our temporary array // Delete our temporary array
delete[] pcIntMaterials; delete[] pcIntMaterials;
} }

View File

@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the ASE parser class * @brief Implementation of the ASE parser class
*/ */
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER

View File

@ -188,10 +188,11 @@ struct Animation {
} mRotationType, mScalingType, mPositionType; } mRotationType, mScalingType, mPositionType;
Animation() AI_NO_EXCEPT Animation() AI_NO_EXCEPT
: mRotationType (TRACK) : mRotationType (TRACK)
, mScalingType (TRACK) , mScalingType (TRACK)
, mPositionType (TRACK) , mPositionType (TRACK) {
{} // empty
}
//! List of track rotation keyframes //! List of track rotation keyframes
std::vector< aiQuatKey > akeyRotations; std::vector< aiQuatKey > akeyRotations;
@ -243,7 +244,6 @@ struct BaseNode {
mTargetPosition.x = qnan; mTargetPosition.x = qnan;
} }
//! Name of the mesh //! Name of the mesh
std::string mName; std::string mName;

View File

@ -76,7 +76,7 @@ namespace Assimp {
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L #define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
FBXConverter::FBXConverter(aiScene* out, const Document& doc) FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones)
: defaultMaterialIndex() : defaultMaterialIndex()
, lights() , lights()
, cameras() , cameras()
@ -89,7 +89,8 @@ namespace Assimp {
, mNodeNames() , mNodeNames()
, anim_fps() , anim_fps()
, out(out) , out(out)
, doc(doc) { , doc(doc)
, mRemoveEmptyBones( removeEmptyBones ) {
// animations need to be converted first since this will // animations need to be converted first since this will
// populate the node_anim_chain_bits map, which is needed // populate the node_anim_chain_bits map, which is needed
// to determine which nodes need to be generated. // to determine which nodes need to be generated.
@ -387,6 +388,7 @@ namespace Assimp {
break; break;
default: default:
ai_assert(false); ai_assert(false);
break;
} }
} }
@ -977,7 +979,9 @@ namespace Assimp {
unsigned int epcount = 0; unsigned int epcount = 0;
for (unsigned i = 0; i < indices.size(); i++) for (unsigned i = 0; i < indices.size(); i++)
{ {
if (indices[i] < 0) epcount++; if (indices[i] < 0) {
epcount++;
}
} }
unsigned int pcount = static_cast<unsigned int>( indices.size() ); unsigned int pcount = static_cast<unsigned int>( indices.size() );
unsigned int scount = out_mesh->mNumFaces = pcount - epcount; unsigned int scount = out_mesh->mNumFaces = pcount - epcount;
@ -1407,7 +1411,7 @@ namespace Assimp {
const WeightIndexArray& indices = cluster->GetIndices(); const WeightIndexArray& indices = cluster->GetIndices();
if (indices.empty()) { if (indices.empty() && mRemoveEmptyBones ) {
continue; continue;
} }
@ -1439,13 +1443,11 @@ namespace Assimp {
if (index_out_indices.back() == no_index_sentinel) { if (index_out_indices.back() == no_index_sentinel) {
index_out_indices.back() = out_indices.size(); index_out_indices.back() = out_indices.size();
} }
if (no_mat_check) { if (no_mat_check) {
out_indices.push_back(out_idx[i]); out_indices.push_back(out_idx[i]);
} } else {
else {
// this extra lookup is in O(logn), so the entire algorithm becomes O(nlogn) // this extra lookup is in O(logn), so the entire algorithm becomes O(nlogn)
const std::vector<unsigned int>::iterator it = std::lower_bound( const std::vector<unsigned int>::iterator it = std::lower_bound(
outputVertStartIndices->begin(), outputVertStartIndices->begin(),
@ -1461,11 +1463,11 @@ namespace Assimp {
} }
} }
} }
// if we found at least one, generate the output bones // if we found at least one, generate the output bones
// XXX this could be heavily simplified by collecting the bone // XXX this could be heavily simplified by collecting the bone
// data in a single step. // data in a single step.
if (ok) { if (ok && mRemoveEmptyBones) {
ConvertCluster(bones, model, *cluster, out_indices, index_out_indices, ConvertCluster(bones, model, *cluster, out_indices, index_out_indices,
count_out_indices, node_global_transform); count_out_indices, node_global_transform);
} }
@ -3525,9 +3527,9 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertToAssimpScene(aiScene* out, const Document& doc) void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones)
{ {
FBXConverter converter(out, doc); FBXConverter converter(out, doc, removeEmptyBones);
} }
} // !FBX } // !FBX

View File

@ -79,9 +79,10 @@ class Document;
/** /**
* Convert a FBX #Document to #aiScene * Convert a FBX #Document to #aiScene
* @param out Empty scene to be populated * @param out Empty scene to be populated
* @param doc Parsed FBX document * @param doc Parsed FBX document
* @param removeEmptyBones Will remove bones, which do not have any references to vertices.
*/ */
void ConvertToAssimpScene(aiScene* out, const Document& doc); void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones );
/** Dummy class to encapsulate the conversion process */ /** Dummy class to encapsulate the conversion process */
class FBXConverter { class FBXConverter {
@ -112,7 +113,7 @@ public:
}; };
public: public:
FBXConverter(aiScene* out, const Document& doc); FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones );
~FBXConverter(); ~FBXConverter();
private: private:
@ -453,6 +454,8 @@ private:
aiScene* const out; aiScene* const out;
const FBX::Document& doc; const FBX::Document& doc;
bool mRemoveEmptyBones;
}; };
} }

View File

@ -53,19 +53,21 @@ namespace FBX {
struct ImportSettings struct ImportSettings
{ {
ImportSettings() ImportSettings()
: strictMode(true) : strictMode(true)
, readAllLayers(true) , readAllLayers(true)
, readAllMaterials(false) , readAllMaterials(false)
, readMaterials(true) , readMaterials(true)
, readTextures(true) , readTextures(true)
, readCameras(true) , readCameras(true)
, readLights(true) , readLights(true)
, readAnimations(true) , readAnimations(true)
, readWeights(true) , readWeights(true)
, preservePivots(true) , preservePivots(true)
, optimizeEmptyAnimationCurves(true) , optimizeEmptyAnimationCurves(true)
, useLegacyEmbeddedTextureNaming(false) , useLegacyEmbeddedTextureNaming(false)
{} , removeEmptyBones( true ) {
// empty
}
/** enable strict mode: /** enable strict mode:
@ -141,8 +143,12 @@ struct ImportSettings
bool optimizeEmptyAnimationCurves; bool optimizeEmptyAnimationCurves;
/** use legacy naming for embedded textures eg: (*0, *1, *2) /** use legacy naming for embedded textures eg: (*0, *1, *2)
**/ */
bool useLegacyEmbeddedTextureNaming; bool useLegacyEmbeddedTextureNaming;
/** Empty bones shall be removed
*/
bool removeEmptyBones;
}; };

View File

@ -140,6 +140,7 @@ void FBXImporter::SetupProperties(const Importer* pImp)
settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true); settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true); settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false); settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -184,7 +185,7 @@ void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
Document doc(parser,settings); Document doc(parser,settings);
// convert the FBX DOM to aiScene // convert the FBX DOM to aiScene
ConvertToAssimpScene(pScene,doc); ConvertToAssimpScene(pScene,doc, settings.removeEmptyBones);
std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>()); std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
} }

View File

@ -46,8 +46,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* the data structure returned by Assimp. * the data structure returned by Assimp.
*/ */
// internal headers // internal headers
#include "ValidateDataStructure.h" #include "ValidateDataStructure.h"
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
@ -110,8 +108,8 @@ void ValidateDSProcess::ReportWarning(const char* msg,...)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
inline int HasNameMatch(const aiString& in, aiNode* node) inline
{ int HasNameMatch(const aiString& in, aiNode* node) {
int result = (node->mName == in ? 1 : 0 ); int result = (node->mName == in ? 1 : 0 );
for (unsigned int i = 0; i < node->mNumChildren;++i) { for (unsigned int i = 0; i < node->mNumChildren;++i) {
result += HasNameMatch(in,node->mChildren[i]); result += HasNameMatch(in,node->mChildren[i]);
@ -121,9 +119,8 @@ inline int HasNameMatch(const aiString& in, aiNode* node)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <typename T> template <typename T>
inline void ValidateDSProcess::DoValidation(T** parray, unsigned int size, inline
const char* firstName, const char* secondName) void ValidateDSProcess::DoValidation(T** parray, unsigned int size, const char* firstName, const char* secondName) {
{
// validate all entries // validate all entries
if (size) if (size)
{ {
@ -181,7 +178,8 @@ inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <typename T> template <typename T>
inline inline
void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size, const char* firstName, const char* secondName) { void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size, const char* firstName,
const char* secondName) {
// validate all entries // validate all entries
DoValidationEx(array,size,firstName,secondName); DoValidationEx(array,size,firstName,secondName);
@ -201,9 +199,8 @@ void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void ValidateDSProcess::Execute( aiScene* pScene) void ValidateDSProcess::Execute( aiScene* pScene) {
{ mScene = pScene;
this->mScene = pScene;
ASSIMP_LOG_DEBUG("ValidateDataStructureProcess begin"); ASSIMP_LOG_DEBUG("ValidateDataStructureProcess begin");
// validate the node graph of the scene // validate the node graph of the scene
@ -516,13 +513,11 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiMesh* pMesh, void ValidateDSProcess::Validate( const aiMesh* pMesh, const aiBone* pBone,float* afSum) {
const aiBone* pBone,float* afSum)
{
this->Validate(&pBone->mName); this->Validate(&pBone->mName);
if (!pBone->mNumWeights) { if (!pBone->mNumWeights) {
ReportError("aiBone::mNumWeights is zero"); //ReportError("aiBone::mNumWeights is zero");
} }
// check whether all vertices affected by this bone are valid // check whether all vertices affected by this bone are valid
@ -563,9 +558,6 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
else { else {
ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there."); ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there.");
} }
// Animation duration is allowed to be zero in cases where the anim contains only a single key frame.
// if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -746,8 +738,9 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
"AI_MATKEY_SHININESS_STRENGTH key is 0.0"); "AI_MATKEY_SHININESS_STRENGTH key is 0.0");
} }
break; break;
default: ; default:
}; break;
}
} }
if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp) && (!fTemp || fTemp > 1.01)) { if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp) && (!fTemp || fTemp > 1.01)) {

View File

@ -657,7 +657,11 @@ enum aiComponent
*/ */
#define AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING \ #define AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING \
"AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING" "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
// ---------------------------------------------------------------------------
#define AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES \
"AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief Set the vertex animation keyframe to be imported /** @brief Set the vertex animation keyframe to be imported
* *