Merge branch 'master' into docs-fix
commit
88fb3e4e35
|
@ -1868,33 +1868,26 @@ void FBXExporter::WriteObjects ()
|
|||
// one sticky point is that the number of vertices may not match,
|
||||
// because assimp splits vertices by normal, uv, etc.
|
||||
|
||||
// functor for aiNode sorting
|
||||
struct SortNodeByName
|
||||
{
|
||||
bool operator()(const aiNode *lhs, const aiNode *rhs) const
|
||||
{
|
||||
return strcmp(lhs->mName.C_Str(), rhs->mName.C_Str()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
// first we should mark the skeleton for each mesh.
|
||||
// the skeleton must include not only the aiBones,
|
||||
// but also all their parent nodes.
|
||||
// anything that affects the position of any bone node must be included.
|
||||
// Use SorNodeByName to make sure the exported result will be the same across all systems
|
||||
// Otherwise the aiNodes of the skeleton would be sorted based on the pointer address, which isn't consistent
|
||||
std::vector<std::set<const aiNode*, SortNodeByName>> skeleton_by_mesh(mScene->mNumMeshes);
|
||||
|
||||
// note that we want to preserve input order as much as possible here.
|
||||
// previously, sorting by name lead to consistent output across systems, but was not
|
||||
// suitable for downstream consumption by some applications.
|
||||
std::vector<std::vector<const aiNode*>> skeleton_by_mesh(mScene->mNumMeshes);
|
||||
// at the same time we can build a list of all the skeleton nodes,
|
||||
// which will be used later to mark them as type "limbNode".
|
||||
std::unordered_set<const aiNode*> limbnodes;
|
||||
|
||||
//actual bone nodes in fbx, without parenting-up
|
||||
std::unordered_set<std::string> setAllBoneNamesInScene;
|
||||
for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m)
|
||||
{
|
||||
std::vector<std::string> allBoneNames;
|
||||
for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m) {
|
||||
aiMesh* pMesh = mScene->mMeshes[m];
|
||||
for(unsigned int b = 0; b < pMesh->mNumBones; ++ b)
|
||||
setAllBoneNamesInScene.insert(pMesh->mBones[b]->mName.data);
|
||||
allBoneNames.push_back(pMesh->mBones[b]->mName.data);
|
||||
}
|
||||
aiMatrix4x4 mxTransIdentity;
|
||||
|
||||
|
@ -1902,7 +1895,7 @@ void FBXExporter::WriteObjects ()
|
|||
std::map<std::string,aiNode*> node_by_bone;
|
||||
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
|
||||
const aiMesh* m = mScene->mMeshes[mi];
|
||||
std::set<const aiNode*, SortNodeByName> skeleton;
|
||||
std::vector<const aiNode*> skeleton;
|
||||
for (size_t bi =0; bi < m->mNumBones; ++bi) {
|
||||
const aiBone* b = m->mBones[bi];
|
||||
const std::string name(b->mName.C_Str());
|
||||
|
@ -1921,7 +1914,7 @@ void FBXExporter::WriteObjects ()
|
|||
node_by_bone[name] = n;
|
||||
limbnodes.insert(n);
|
||||
}
|
||||
skeleton.insert(n);
|
||||
skeleton.push_back(n);
|
||||
// mark all parent nodes as skeleton as well,
|
||||
// up until we find the root node,
|
||||
// or else the node containing the mesh,
|
||||
|
@ -1932,7 +1925,7 @@ void FBXExporter::WriteObjects ()
|
|||
parent = parent->mParent
|
||||
) {
|
||||
// if we've already done this node we can skip it all
|
||||
if (skeleton.count(parent)) {
|
||||
if (std::find(skeleton.begin(), skeleton.end(), parent) != skeleton.end()) {
|
||||
break;
|
||||
}
|
||||
// ignore fbx transform nodes as these will be collapsed later
|
||||
|
@ -1942,7 +1935,7 @@ void FBXExporter::WriteObjects ()
|
|||
continue;
|
||||
}
|
||||
//not a bone in scene && no effect in transform
|
||||
if(setAllBoneNamesInScene.find(node_name)==setAllBoneNamesInScene.end()
|
||||
if (std::find(allBoneNames.begin(), allBoneNames.end(), node_name) == allBoneNames.end()
|
||||
&& parent->mTransformation == mxTransIdentity) {
|
||||
continue;
|
||||
}
|
||||
|
@ -2027,7 +2020,7 @@ void FBXExporter::WriteObjects ()
|
|||
aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene);
|
||||
|
||||
// now make a subdeformer for each bone in the skeleton
|
||||
const std::set<const aiNode*, SortNodeByName> skeleton= skeleton_by_mesh[mi];
|
||||
const auto & skeleton= skeleton_by_mesh[mi];
|
||||
for (const aiNode* bone_node : skeleton) {
|
||||
// if there's a bone for this node, find it
|
||||
const aiBone* b = nullptr;
|
||||
|
|
|
@ -193,7 +193,7 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene
|
|||
pScene->mRootNode->mChildren = new aiNode *[childCount];
|
||||
|
||||
// Create nodes for the whole scene
|
||||
std::vector<aiMesh *> MeshArray;
|
||||
std::vector<std::unique_ptr<aiMesh>> MeshArray;
|
||||
MeshArray.reserve(meshCount);
|
||||
for (size_t index = 0; index < pModel->mObjects.size(); ++index) {
|
||||
createNodes(pModel, pModel->mObjects[index], pScene->mRootNode, pScene, MeshArray);
|
||||
|
@ -205,7 +205,7 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene
|
|||
if (pScene->mNumMeshes > 0) {
|
||||
pScene->mMeshes = new aiMesh *[MeshArray.size()];
|
||||
for (size_t index = 0; index < MeshArray.size(); ++index) {
|
||||
pScene->mMeshes[index] = MeshArray[index];
|
||||
pScene->mMeshes[index] = MeshArray[index].release();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,7 +257,7 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene
|
|||
// Creates all nodes of the model
|
||||
aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pObject,
|
||||
aiNode *pParent, aiScene *pScene,
|
||||
std::vector<aiMesh *> &MeshArray) {
|
||||
std::vector<std::unique_ptr<aiMesh>> &MeshArray) {
|
||||
ai_assert(nullptr != pModel);
|
||||
if (nullptr == pObject) {
|
||||
return nullptr;
|
||||
|
@ -275,12 +275,10 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile
|
|||
|
||||
for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) {
|
||||
unsigned int meshId = pObject->m_Meshes[i];
|
||||
aiMesh *pMesh = createTopology(pModel, pObject, meshId);
|
||||
std::unique_ptr<aiMesh> pMesh = createTopology(pModel, pObject, meshId);
|
||||
if (pMesh != nullptr) {
|
||||
if (pMesh->mNumFaces > 0) {
|
||||
MeshArray.push_back(pMesh);
|
||||
} else {
|
||||
delete pMesh;
|
||||
MeshArray.push_back(std::move(pMesh));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -312,7 +310,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Create topology data
|
||||
aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjFile::Object *pData, unsigned int meshIndex) {
|
||||
std::unique_ptr<aiMesh> ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjFile::Object *pData, unsigned int meshIndex) {
|
||||
// Checking preconditions
|
||||
ai_assert(nullptr != pModel);
|
||||
|
||||
|
@ -394,7 +392,7 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
|
|||
// Create mesh vertices
|
||||
createVertexArray(pModel, pData, meshIndex, pMesh.get(), uiIdxCount);
|
||||
|
||||
return pMesh.release();
|
||||
return pMesh;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/material.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
struct aiMesh;
|
||||
|
@ -84,10 +85,10 @@ protected:
|
|||
|
||||
//! \brief Creates all nodes stored in imported content.
|
||||
aiNode *createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pData,
|
||||
aiNode *pParent, aiScene *pScene, std::vector<aiMesh *> &MeshArray);
|
||||
aiNode *pParent, aiScene *pScene, std::vector<std::unique_ptr<aiMesh>> &MeshArray);
|
||||
|
||||
//! \brief Creates topology data like faces and meshes for the geometry.
|
||||
aiMesh *createTopology(const ObjFile::Model *pModel, const ObjFile::Object *pData,
|
||||
std::unique_ptr<aiMesh> createTopology(const ObjFile::Model *pModel, const ObjFile::Object *pData,
|
||||
unsigned int uiMeshIndex);
|
||||
|
||||
//! \brief Creates vertices from model.
|
||||
|
|
|
@ -53,7 +53,8 @@ namespace Assimp {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
LimitBoneWeightsProcess::LimitBoneWeightsProcess() : mMaxWeights(AI_LMW_MAX_WEIGHTS) {
|
||||
LimitBoneWeightsProcess::LimitBoneWeightsProcess() :
|
||||
mMaxWeights(AI_LMW_MAX_WEIGHTS), mRemoveEmptyBones(true) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
|
|
@ -13,10 +13,14 @@
|
|||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/* For Visual Studio only, NOT MinGW (GCC) -- ThatOSDev */
|
||||
#pragma warning( disable : 4706 )
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
|
||||
defined(__MINGW32__)
|
||||
/* Win32, DOS, MSVC, MSVS */
|
||||
#pragma warning( disable : 4706 )
|
||||
/* Win32, DOS, MSVC, MSVS, MinGW(GCC for windows) */
|
||||
#include <direct.h>
|
||||
|
||||
#define STRCLONE(STR) ((STR) ? _strdup(STR) : NULL)
|
||||
|
|
|
@ -113,19 +113,19 @@ struct aiMetadata;
|
|||
*/
|
||||
// -------------------------------------------------------------------------------
|
||||
|
||||
inline aiMetadataType GetAiType(bool) {
|
||||
inline aiMetadataType GetAiType(const bool &) {
|
||||
return AI_BOOL;
|
||||
}
|
||||
inline aiMetadataType GetAiType(int32_t) {
|
||||
return AI_INT32;
|
||||
}
|
||||
inline aiMetadataType GetAiType(uint64_t) {
|
||||
inline aiMetadataType GetAiType(const uint64_t &) {
|
||||
return AI_UINT64;
|
||||
}
|
||||
inline aiMetadataType GetAiType(float) {
|
||||
inline aiMetadataType GetAiType(const float &) {
|
||||
return AI_FLOAT;
|
||||
}
|
||||
inline aiMetadataType GetAiType(double) {
|
||||
inline aiMetadataType GetAiType(const double &) {
|
||||
return AI_DOUBLE;
|
||||
}
|
||||
inline aiMetadataType GetAiType(const aiString &) {
|
||||
|
@ -137,10 +137,10 @@ inline aiMetadataType GetAiType(const aiVector3D &) {
|
|||
inline aiMetadataType GetAiType(const aiMetadata &) {
|
||||
return AI_AIMETADATA;
|
||||
}
|
||||
inline aiMetadataType GetAiType(int64_t) {
|
||||
inline aiMetadataType GetAiType(const int64_t &) {
|
||||
return AI_INT64;
|
||||
}
|
||||
inline aiMetadataType GetAiType(uint32_t) {
|
||||
inline aiMetadataType GetAiType(const uint32_t &) {
|
||||
return AI_UINT32;
|
||||
}
|
||||
|
||||
|
|
|
@ -242,6 +242,22 @@ TEST_F( utMetadata, copy_test ) {
|
|||
EXPECT_EQ( i32v, v );
|
||||
}
|
||||
|
||||
// uint32_t test
|
||||
{
|
||||
uint32_t v = 0;
|
||||
bool ok = copy.Get("uint32_t", v);
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_EQ( ui32, v );
|
||||
}
|
||||
|
||||
// int64_t test
|
||||
{
|
||||
int64_t v = -1;
|
||||
bool ok = copy.Get("int64_t", v);
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_EQ( i64, v );
|
||||
}
|
||||
|
||||
// uint64_t test
|
||||
{
|
||||
uint64_t v = 255;
|
||||
|
@ -264,14 +280,14 @@ TEST_F( utMetadata, copy_test ) {
|
|||
EXPECT_EQ( dv, v );
|
||||
}
|
||||
|
||||
// bool test
|
||||
// string test
|
||||
{
|
||||
aiString v;
|
||||
EXPECT_TRUE( copy.Get( "aiString", v ) );
|
||||
EXPECT_EQ( strVal, v );
|
||||
}
|
||||
|
||||
// bool test
|
||||
// vector test
|
||||
{
|
||||
aiVector3D v;
|
||||
EXPECT_TRUE( copy.Get( "aiVector3D", v ) );
|
||||
|
|
Loading…
Reference in New Issue