Merge branch 'master' into integrate-tinyusdz-br-rendermesh-refactor

pull/5628/head
Steve M 2024-07-09 16:33:37 -07:00
commit 22f69da370
30 changed files with 411 additions and 406 deletions

View File

@ -1,6 +1,6 @@
FROM ubuntu:22.04 FROM ubuntu:22.04
RUN apt-get update && apt-get install -y ninja-build \ RUN apt-get update && apt-get install --no-install-recommends -y ninja-build \
git cmake build-essential software-properties-common git cmake build-essential software-properties-common
RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update

View File

@ -57,8 +57,8 @@ static constexpr size_t ColRGBA_Len = 9;
static constexpr size_t ColRGB_Len = 7; static constexpr size_t ColRGB_Len = 7;
// format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1) // format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
bool validateColorString(const char *color) { bool validateColorString(const std::string color) {
const size_t len = strlen(color); const size_t len = color.size();
if (ColRGBA_Len != len && ColRGB_Len != len) { if (ColRGBA_Len != len && ColRGB_Len != len) {
return false; return false;
} }
@ -157,8 +157,8 @@ aiMatrix4x4 parseTransformMatrix(const std::string& matrixStr) {
return transformMatrix; return transformMatrix;
} }
bool parseColor(const char *color, aiColor4D &diffuse) { bool parseColor(const std::string &color, aiColor4D &diffuse) {
if (nullptr == color) { if (color.empty()) {
return false; return false;
} }
@ -178,7 +178,7 @@ bool parseColor(const char *color, aiColor4D &diffuse) {
char b[3] = { color[5], color[6], '\0' }; char b[3] = { color[5], color[6], '\0' };
diffuse.b = static_cast<ai_real>(strtol(b, nullptr, 16)) / ai_real(255.0); diffuse.b = static_cast<ai_real>(strtol(b, nullptr, 16)) / ai_real(255.0);
const size_t len = strlen(color); const size_t len = color.size();
if (ColRGB_Len == len) { if (ColRGB_Len == len) {
return true; return true;
} }

View File

@ -178,28 +178,6 @@ bool AMFImporter::XML_SearchNode(const std::string &nodeName) {
return nullptr != mXmlParser->findNode(nodeName); return nullptr != mXmlParser->findNode(nodeName);
} }
void AMFImporter::ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString) {
size_t instr_len;
pOutString.clear();
instr_len = strlen(pInStr);
if (!instr_len) return;
pOutString.reserve(instr_len * 3 / 2);
// check and correct floats in format ".x". Must be "x.y".
if (pInStr[0] == '.') pOutString.push_back('0');
pOutString.push_back(pInStr[0]);
for (size_t ci = 1; ci < instr_len; ci++) {
if ((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t'))) {
pOutString.push_back('0');
pOutString.push_back('.');
} else {
pOutString.push_back(pInStr[ci]);
}
}
}
static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) { static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) {
return (isalnum((unsigned char)pChar) || (pChar == '+') || (pChar == '/')); return (isalnum((unsigned char)pChar) || (pChar == '+') || (pChar == '/'));
} }
@ -213,7 +191,10 @@ void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std
uint8_t arr4[4], arr3[3]; uint8_t arr4[4], arr3[3];
// check input data // check input data
if (pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four."); if (pInputBase64.size() % 4) {
throw DeadlyImportError("Base64-encoded data must have size multiply of four.");
}
// prepare output place // prepare output place
pOutputData.clear(); pOutputData.clear();
pOutputData.reserve(pInputBase64.size() / 4 * 3); pOutputData.reserve(pInputBase64.size() / 4 * 3);

View File

@ -168,7 +168,6 @@ public:
AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX;
void XML_CheckNode_MustHaveChildren(pugi::xml_node &node); void XML_CheckNode_MustHaveChildren(pugi::xml_node &node);
bool XML_SearchNode(const std::string &nodeName); bool XML_SearchNode(const std::string &nodeName);
void ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString);
AMFImporter(const AMFImporter &pScene) = delete; AMFImporter(const AMFImporter &pScene) = delete;
AMFImporter &operator=(const AMFImporter &pScene) = delete; AMFImporter &operator=(const AMFImporter &pScene) = delete;

View File

@ -56,7 +56,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string> #include <string>
#include <vector> #include <vector>
/// \class CAMFImporter_NodeElement
/// Base class for elements of nodes. /// Base class for elements of nodes.
class AMFNodeElementBase { class AMFNodeElementBase {
public: public:
@ -106,7 +105,6 @@ protected:
} }
}; // class IAMFImporter_NodeElement }; // class IAMFImporter_NodeElement
/// \struct CAMFImporter_NodeElement_Constellation
/// A collection of objects or constellations with specific relative locations. /// A collection of objects or constellations with specific relative locations.
struct AMFConstellation : public AMFNodeElementBase { struct AMFConstellation : public AMFNodeElementBase {
/// Constructor. /// Constructor.
@ -116,7 +114,6 @@ struct AMFConstellation : public AMFNodeElementBase {
}; // struct CAMFImporter_NodeElement_Constellation }; // struct CAMFImporter_NodeElement_Constellation
/// \struct CAMFImporter_NodeElement_Instance
/// Part of constellation. /// Part of constellation.
struct AMFInstance : public AMFNodeElementBase { struct AMFInstance : public AMFNodeElementBase {
@ -135,7 +132,6 @@ struct AMFInstance : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Instance, pParent) {} AMFNodeElementBase(ENET_Instance, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Metadata
/// Structure that define metadata node. /// Structure that define metadata node.
struct AMFMetadata : public AMFNodeElementBase { struct AMFMetadata : public AMFNodeElementBase {
@ -148,7 +144,6 @@ struct AMFMetadata : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Metadata, pParent) {} AMFNodeElementBase(ENET_Metadata, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Root
/// Structure that define root node. /// Structure that define root node.
struct AMFRoot : public AMFNodeElementBase { struct AMFRoot : public AMFNodeElementBase {
@ -161,7 +156,6 @@ struct AMFRoot : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Root, pParent) {} AMFNodeElementBase(ENET_Root, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Color
/// Structure that define object node. /// Structure that define object node.
struct AMFColor : public AMFNodeElementBase { struct AMFColor : public AMFNodeElementBase {
bool Composed; ///< Type of color stored: if true then look for formula in \ref Color_Composed[4], else - in \ref Color. bool Composed; ///< Type of color stored: if true then look for formula in \ref Color_Composed[4], else - in \ref Color.
@ -177,7 +171,6 @@ struct AMFColor : public AMFNodeElementBase {
} }
}; };
/// \struct CAMFImporter_NodeElement_Material
/// Structure that define material node. /// Structure that define material node.
struct AMFMaterial : public AMFNodeElementBase { struct AMFMaterial : public AMFNodeElementBase {
@ -187,7 +180,6 @@ struct AMFMaterial : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Material, pParent) {} AMFNodeElementBase(ENET_Material, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Object
/// Structure that define object node. /// Structure that define object node.
struct AMFObject : public AMFNodeElementBase { struct AMFObject : public AMFNodeElementBase {
@ -206,7 +198,6 @@ struct AMFMesh : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Mesh, pParent) {} AMFNodeElementBase(ENET_Mesh, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Vertex
/// Structure that define vertex node. /// Structure that define vertex node.
struct AMFVertex : public AMFNodeElementBase { struct AMFVertex : public AMFNodeElementBase {
/// Constructor. /// Constructor.
@ -215,7 +206,6 @@ struct AMFVertex : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Vertex, pParent) {} AMFNodeElementBase(ENET_Vertex, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Edge
/// Structure that define edge node. /// Structure that define edge node.
struct AMFEdge : public AMFNodeElementBase { struct AMFEdge : public AMFNodeElementBase {
/// Constructor. /// Constructor.
@ -224,7 +214,6 @@ struct AMFEdge : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Edge, pParent) {} AMFNodeElementBase(ENET_Edge, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Vertices
/// Structure that define vertices node. /// Structure that define vertices node.
struct AMFVertices : public AMFNodeElementBase { struct AMFVertices : public AMFNodeElementBase {
/// Constructor. /// Constructor.
@ -233,7 +222,6 @@ struct AMFVertices : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Vertices, pParent) {} AMFNodeElementBase(ENET_Vertices, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Volume
/// Structure that define volume node. /// Structure that define volume node.
struct AMFVolume : public AMFNodeElementBase { struct AMFVolume : public AMFNodeElementBase {
std::string MaterialID; ///< Which material to use. std::string MaterialID; ///< Which material to use.
@ -245,7 +233,6 @@ struct AMFVolume : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Volume, pParent) {} AMFNodeElementBase(ENET_Volume, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_Coordinates
/// Structure that define coordinates node. /// Structure that define coordinates node.
struct AMFCoordinates : public AMFNodeElementBase { struct AMFCoordinates : public AMFNodeElementBase {
aiVector3D Coordinate; ///< Coordinate. aiVector3D Coordinate; ///< Coordinate.
@ -256,7 +243,6 @@ struct AMFCoordinates : public AMFNodeElementBase {
AMFNodeElementBase(ENET_Coordinates, pParent) {} AMFNodeElementBase(ENET_Coordinates, pParent) {}
}; };
/// \struct CAMFImporter_NodeElement_TexMap
/// Structure that define texture coordinates node. /// Structure that define texture coordinates node.
struct AMFTexMap : public AMFNodeElementBase { struct AMFTexMap : public AMFNodeElementBase {
aiVector3D TextureCoordinate[3]; ///< Texture coordinates. aiVector3D TextureCoordinate[3]; ///< Texture coordinates.
@ -273,7 +259,6 @@ struct AMFTexMap : public AMFNodeElementBase {
} }
}; };
/// \struct CAMFImporter_NodeElement_Triangle
/// Structure that define triangle node. /// Structure that define triangle node.
struct AMFTriangle : public AMFNodeElementBase { struct AMFTriangle : public AMFNodeElementBase {
size_t V[3]; ///< Triangle vertices. size_t V[3]; ///< Triangle vertices.

View File

@ -224,7 +224,8 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string &
} }
// Create format hint. // Create format hint.
strcpy(converted_texture.FormatHint, "rgba0000"); // copy initial string. constexpr char templateColor[] = "rgba0000";
memcpy(converted_texture.FormatHint, templateColor, 8);
if (!r.empty()) converted_texture.FormatHint[4] = '8'; if (!r.empty()) converted_texture.FormatHint[4] = '8';
if (!g.empty()) converted_texture.FormatHint[5] = '8'; if (!g.empty()) converted_texture.FormatHint[5] = '8';
if (!b.empty()) converted_texture.FormatHint[6] = '8'; if (!b.empty()) converted_texture.FormatHint[6] = '8';
@ -867,7 +868,7 @@ nl_clean_loop:
pScene->mTextures[idx]->mHeight = static_cast<unsigned int>(tex_convd.Height); pScene->mTextures[idx]->mHeight = static_cast<unsigned int>(tex_convd.Height);
pScene->mTextures[idx]->pcData = (aiTexel *)tex_convd.Data; pScene->mTextures[idx]->pcData = (aiTexel *)tex_convd.Data;
// texture format description. // texture format description.
strcpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint); strncpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint, HINTMAXTEXTURELEN);
idx++; idx++;
} // for(const SPP_Texture& tex_convd: mTexture_Converted) } // for(const SPP_Texture& tex_convd: mTexture_Converted)

View File

@ -124,7 +124,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
// Allocate storage and copy the contents of the file to a memory buffer // Allocate storage and copy the contents of the file to a memory buffer
std::vector<char> mBuffer2; std::vector<char> mBuffer2;
TextFileToBuffer(file.get(), mBuffer2); TextFileToBuffer(file.get(), mBuffer2);
const size_t fileSize = mBuffer2.size();
this->mBuffer = &mBuffer2[0]; this->mBuffer = &mBuffer2[0];
this->pcScene = pScene; this->pcScene = pScene;
@ -146,7 +146,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
}; };
// Construct an ASE parser and parse the file // Construct an ASE parser and parse the file
ASE::Parser parser(mBuffer, defaultFormat); ASE::Parser parser(mBuffer, fileSize, defaultFormat);
mParser = &parser; mParser = &parser;
mParser->Parse(); mParser->Parse();
@ -446,10 +446,9 @@ void ASEImporter::BuildLights() {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParent, const std::string &name) {
aiNode *pcParent, const char *szName) {
aiMatrix4x4 m; aiMatrix4x4 m;
AddNodes(nodes, pcParent, szName, m); AddNodes(nodes, pcParent, name, m);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -506,10 +505,9 @@ void ASEImporter::AddMeshes(const ASE::BaseNode *snode, aiNode *node) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Add child nodes to a given parent node // Add child nodes to a given parent node
void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParent, const std::string &name,
aiNode *pcParent, const char *szName,
const aiMatrix4x4 &mat) { const aiMatrix4x4 &mat) {
const size_t len = szName ? ::strlen(szName) : 0; const size_t len = name.size();
ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS); ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS);
// Receives child nodes for the pcParent node // Receives child nodes for the pcParent node
@ -519,16 +517,18 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
// which has *us* as parent. // which has *us* as parent.
for (std::vector<BaseNode *>::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) { for (std::vector<BaseNode *>::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) {
const BaseNode *snode = *it; const BaseNode *snode = *it;
if (szName) { if (!name.empty()) {
if (len != snode->mParent.length() || ::strcmp(szName, snode->mParent.c_str())) if (len != snode->mParent.length() || name != snode->mParent.c_str()) {
continue; continue;
} else if (snode->mParent.length()) }
} else if (snode->mParent.length()) {
continue; continue;
}
(*it)->mProcessed = true; (*it)->mProcessed = true;
// Allocate a new node and add it to the output data structure // Allocate a new node and add it to the output data structure
apcNodes.push_back(new aiNode()); apcNodes.push_back(new aiNode);
aiNode *node = apcNodes.back(); aiNode *node = apcNodes.back();
node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node")); node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node"));
@ -541,7 +541,7 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
// Add sub nodes - prevent stack overflow due to recursive parenting // Add sub nodes - prevent stack overflow due to recursive parenting
if (node->mName != node->mParent->mName && node->mName != node->mParent->mParent->mName) { if (node->mName != node->mParent->mName && node->mName != node->mParent->mParent->mName) {
AddNodes(nodes, node, node->mName.data, snode->mTransform); AddNodes(nodes, node, node->mName.C_Str(), snode->mTransform);
} }
// Further processing depends on the type of the node // Further processing depends on the type of the node
@ -619,7 +619,8 @@ void ASEImporter::BuildNodes(std::vector<BaseNode *> &nodes) {
} }
// add all nodes // add all nodes
AddNodes(nodes, ch, nullptr); static const std::string none = "";
AddNodes(nodes, ch, none);
// now iterate through al nodes and find those that have not yet // now iterate through al nodes and find those that have not yet
// been added to the nodegraph (= their parent could not be recognized) // been added to the nodegraph (= their parent could not be recognized)

View File

@ -153,13 +153,13 @@ private:
* \param matrix Current transform * \param matrix Current transform
*/ */
void AddNodes(const std::vector<ASE::BaseNode*>& nodes, void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
aiNode* pcParent,const char* szName); aiNode* pcParent, const std::string &name);
void AddNodes(const std::vector<ASE::BaseNode*>& nodes, void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
aiNode* pcParent,const char* szName, aiNode* pcParent, const std::string &name,
const aiMatrix4x4& matrix); const aiMatrix4x4& matrix);
void AddMeshes(const ASE::BaseNode* snode,aiNode* node); void AddMeshes(const ASE::BaseNode* snode, aiNode* node);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Generate a default material and add it to the parser's list /** Generate a default material and add it to the parser's list
@ -188,5 +188,4 @@ protected:
} // end of namespace Assimp } // end of namespace Assimp
#endif // AI_3DSIMPORTER_H_INC #endif // AI_3DSIMPORTER_H_INC

File diff suppressed because it is too large Load Diff

View File

@ -391,11 +391,11 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Construct a parser from a given input file which is //! Construct a parser from a given input file which is
//! guaranteed to be terminated with zero. //! guaranteed to be terminated with zero.
//! @param szFile Input file //! @param file The name of the input file.
//! @param fileFormatDefault Assumed file format version. If the //! @param fileFormatDefault Assumed file format version. If the
//! file format is specified in the file the new value replaces //! file format is specified in the file the new value replaces
//! the default value. //! the default value.
Parser(const char *szFile, unsigned int fileFormatDefault); Parser(const char *file, size_t fileLen, unsigned int fileFormatDefault);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parses the file into the parsers internal representation //! Parses the file into the parsers internal representation
@ -617,11 +617,8 @@ private:
bool ParseString(std::string &out, const char *szName); bool ParseString(std::string &out, const char *szName);
public: public:
//! Pointer to current data const char *mFilePtr; ////< Pointer to current data
const char *filePtr; const char *mEnd; ///< The end pointer of the file data
/// The end pointer of the file data
const char *mEnd;
//! background color to be passed to the viewer //! background color to be passed to the viewer
//! QNAN if none was found //! QNAN if none was found

View File

@ -2293,9 +2293,9 @@ void ColladaParser::ReadNodeGeometry(XmlNode &node, Node *pNode) {
urlMat++; urlMat++;
s.mMatName = urlMat; s.mMatName = urlMat;
ReadMaterialVertexInputBinding(instanceMatNode, s);
// store the association // store the association
instance.mMaterials[group] = s; instance.mMaterials[group] = s;
ReadMaterialVertexInputBinding(instanceMatNode, s);
} }
} }
} }

View File

@ -1051,7 +1051,7 @@ aiNode* get_node_for_mesh(unsigned int meshIndex, aiNode* node)
aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene) aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene)
{ {
std::vector<const aiNode*> node_chain; std::vector<const aiNode*> node_chain;
while (node != scene->mRootNode) { while (node != scene->mRootNode && node != nullptr) {
node_chain.push_back(node); node_chain.push_back(node);
node = node->mParent; node = node->mParent;
} }
@ -1868,33 +1868,26 @@ void FBXExporter::WriteObjects ()
// one sticky point is that the number of vertices may not match, // one sticky point is that the number of vertices may not match,
// because assimp splits vertices by normal, uv, etc. // 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. // first we should mark the skeleton for each mesh.
// the skeleton must include not only the aiBones, // the skeleton must include not only the aiBones,
// but also all their parent nodes. // but also all their parent nodes.
// anything that affects the position of any bone node must be included. // 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 // note that we want to preserve input order as much as possible here.
std::vector<std::set<const aiNode*, SortNodeByName>> skeleton_by_mesh(mScene->mNumMeshes); // 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, // 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". // which will be used later to mark them as type "limbNode".
std::unordered_set<const aiNode*> limbnodes; std::unordered_set<const aiNode*> limbnodes;
//actual bone nodes in fbx, without parenting-up //actual bone nodes in fbx, without parenting-up
std::unordered_set<std::string> setAllBoneNamesInScene; std::vector<std::string> allBoneNames;
for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m) for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m) {
{
aiMesh* pMesh = mScene->mMeshes[m]; aiMesh* pMesh = mScene->mMeshes[m];
for(unsigned int b = 0; b < pMesh->mNumBones; ++ b) 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; aiMatrix4x4 mxTransIdentity;
@ -1902,7 +1895,7 @@ void FBXExporter::WriteObjects ()
std::map<std::string,aiNode*> node_by_bone; std::map<std::string,aiNode*> node_by_bone;
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) { for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
const aiMesh* m = mScene->mMeshes[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) { for (size_t bi =0; bi < m->mNumBones; ++bi) {
const aiBone* b = m->mBones[bi]; const aiBone* b = m->mBones[bi];
const std::string name(b->mName.C_Str()); const std::string name(b->mName.C_Str());
@ -1921,7 +1914,7 @@ void FBXExporter::WriteObjects ()
node_by_bone[name] = n; node_by_bone[name] = n;
limbnodes.insert(n); limbnodes.insert(n);
} }
skeleton.insert(n); skeleton.push_back(n);
// mark all parent nodes as skeleton as well, // mark all parent nodes as skeleton as well,
// up until we find the root node, // up until we find the root node,
// or else the node containing the mesh, // or else the node containing the mesh,
@ -1932,7 +1925,7 @@ void FBXExporter::WriteObjects ()
parent = parent->mParent parent = parent->mParent
) { ) {
// if we've already done this node we can skip it all // 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; break;
} }
// ignore fbx transform nodes as these will be collapsed later // ignore fbx transform nodes as these will be collapsed later
@ -1942,7 +1935,7 @@ void FBXExporter::WriteObjects ()
continue; continue;
} }
//not a bone in scene && no effect in transform //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) { && parent->mTransformation == mxTransIdentity) {
continue; continue;
} }
@ -2027,7 +2020,7 @@ void FBXExporter::WriteObjects ()
aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene); aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene);
// now make a subdeformer for each bone in the skeleton // 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) { for (const aiNode* bone_node : skeleton) {
// if there's a bone for this node, find it // if there's a bone for this node, find it
const aiBone* b = nullptr; const aiBone* b = nullptr;

View File

@ -644,10 +644,12 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
return; return;
} }
// materials are handled separately. First of all, they are assigned per-face if (source["Materials"]) {
// and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect // materials are handled separately. First of all, they are assigned per-face
// has a slightly different meaning for materials. // and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
ParseVectorDataArray(materials_out,GetRequiredElement(source,"Materials")); // has a slightly different meaning for materials.
ParseVectorDataArray(materials_out, GetRequiredElement(source, "Materials"));
}
if (MappingInformationType == "AllSame") { if (MappingInformationType == "AllSame") {
// easy - same material for all faces // easy - same material for all faces

View File

@ -234,8 +234,12 @@ inline void AI_MD5_READ_TRIPLE(aiVector3D &vec, const char **sz, const char *buf
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber); AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
if ('(' != **sz) { if ('(' != **sz) {
MD5Parser::ReportWarning("Unexpected token: ( was expected", linenumber); MD5Parser::ReportWarning("Unexpected token: ( was expected", linenumber);
if (*sz == bufferEnd)
return;
++*sz; ++*sz;
} }
if (*sz == bufferEnd)
return;
++*sz; ++*sz;
AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber); AI_MD5_SKIP_SPACES(sz, bufferEnd, linenumber);
*sz = fast_atoreal_move<float>(*sz, (float &)vec.x); *sz = fast_atoreal_move<float>(*sz, (float &)vec.x);
@ -247,6 +251,8 @@ inline void AI_MD5_READ_TRIPLE(aiVector3D &vec, const char **sz, const char *buf
if (')' != **sz) { if (')' != **sz) {
MD5Parser::ReportWarning("Unexpected token: ) was expected", linenumber); MD5Parser::ReportWarning("Unexpected token: ) was expected", linenumber);
} }
if (*sz == bufferEnd)
return;
++*sz; ++*sz;
} }

View File

@ -193,7 +193,7 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene
pScene->mRootNode->mChildren = new aiNode *[childCount]; pScene->mRootNode->mChildren = new aiNode *[childCount];
// Create nodes for the whole scene // Create nodes for the whole scene
std::vector<aiMesh *> MeshArray; std::vector<std::unique_ptr<aiMesh>> MeshArray;
MeshArray.reserve(meshCount); MeshArray.reserve(meshCount);
for (size_t index = 0; index < pModel->mObjects.size(); ++index) { for (size_t index = 0; index < pModel->mObjects.size(); ++index) {
createNodes(pModel, pModel->mObjects[index], pScene->mRootNode, pScene, MeshArray); 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) { if (pScene->mNumMeshes > 0) {
pScene->mMeshes = new aiMesh *[MeshArray.size()]; pScene->mMeshes = new aiMesh *[MeshArray.size()];
for (size_t index = 0; index < MeshArray.size(); ++index) { 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 // Creates all nodes of the model
aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pObject, aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pObject,
aiNode *pParent, aiScene *pScene, aiNode *pParent, aiScene *pScene,
std::vector<aiMesh *> &MeshArray) { std::vector<std::unique_ptr<aiMesh>> &MeshArray) {
ai_assert(nullptr != pModel); ai_assert(nullptr != pModel);
if (nullptr == pObject) { if (nullptr == pObject) {
return nullptr; 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) { for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) {
unsigned int meshId = pObject->m_Meshes[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 != nullptr) {
if (pMesh->mNumFaces > 0) { if (pMesh->mNumFaces > 0) {
MeshArray.push_back(pMesh); MeshArray.push_back(std::move(pMesh));
} else {
delete pMesh;
} }
} }
} }
@ -312,7 +310,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Create topology data // 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 // Checking preconditions
ai_assert(nullptr != pModel); ai_assert(nullptr != pModel);
@ -394,7 +392,7 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
// Create mesh vertices // Create mesh vertices
createVertexArray(pModel, pData, meshIndex, pMesh.get(), uiIdxCount); createVertexArray(pModel, pData, meshIndex, pMesh.get(), uiIdxCount);
return pMesh.release(); return pMesh;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include <assimp/material.h> #include <assimp/material.h>
#include <memory>
#include <vector> #include <vector>
struct aiMesh; struct aiMesh;
@ -84,10 +85,10 @@ protected:
//! \brief Creates all nodes stored in imported content. //! \brief Creates all nodes stored in imported content.
aiNode *createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pData, 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. //! \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); unsigned int uiMeshIndex);
//! \brief Creates vertices from model. //! \brief Creates vertices from model.

View File

@ -346,10 +346,22 @@ void PlyExporter::WriteMeshVertsBinary(const aiMesh* m, unsigned int components)
for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) { for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) {
if (m->HasVertexColors(c)) { if (m->HasVertexColors(c)) {
mOutput.write(reinterpret_cast<const char*>(&m->mColors[c][i].r), 16); unsigned char rgba[4] = {
static_cast<unsigned char>(m->mColors[c][i].r * 255),
static_cast<unsigned char>(m->mColors[c][i].g * 255),
static_cast<unsigned char>(m->mColors[c][i].b * 255),
static_cast<unsigned char>(m->mColors[c][i].a * 255)
};
mOutput.write(reinterpret_cast<const char*>(&rgba), 4);
} }
else { else {
mOutput.write(reinterpret_cast<const char*>(&defaultColor.r), 16); unsigned char rgba[4] = {
static_cast<unsigned char>(defaultColor.r * 255),
static_cast<unsigned char>(defaultColor.g * 255),
static_cast<unsigned char>(defaultColor.b * 255),
static_cast<unsigned char>(defaultColor.a * 255)
};
mOutput.write(reinterpret_cast<const char*>(&rgba), 4);
} }
} }

View File

@ -564,6 +564,10 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
if (mGeneratedMesh->mFaces == nullptr) { if (mGeneratedMesh->mFaces == nullptr) {
mGeneratedMesh->mNumFaces = pcElement->NumOccur; mGeneratedMesh->mNumFaces = pcElement->NumOccur;
mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
} else {
if (mGeneratedMesh->mNumFaces < pcElement->NumOccur) {
throw DeadlyImportError("Invalid .ply file: Too many faces");
}
} }
if (!bIsTriStrip) { if (!bIsTriStrip) {

View File

@ -1440,7 +1440,7 @@ inline void MaterialSheen::SetDefaults() {
inline void MaterialVolume::SetDefaults() { inline void MaterialVolume::SetDefaults() {
//KHR_materials_volume properties //KHR_materials_volume properties
thicknessFactor = 0.f; thicknessFactor = 0.f;
attenuationDistance = INFINITY; attenuationDistance = std::numeric_limits<float>::infinity();
SetVector(attenuationColor, defaultAttenuationColor); SetVector(attenuationColor, defaultAttenuationColor);
} }

View File

@ -507,7 +507,7 @@ namespace glTF2 {
WriteTex(materialVolume, volume.thicknessTexture, "thicknessTexture", w.mAl); WriteTex(materialVolume, volume.thicknessTexture, "thicknessTexture", w.mAl);
if (volume.attenuationDistance != INFINITY) { if (volume.attenuationDistance != std::numeric_limits<float>::infinity()) {
WriteFloat(materialVolume, volume.attenuationDistance, "attenuationDistance", w.mAl); WriteFloat(materialVolume, volume.attenuationDistance, "attenuationDistance", w.mAl);
} }

View File

@ -88,6 +88,11 @@ private:
} // namespace Assimp } // namespace Assimp
/// @brief Fixes an undefined reference error when linking in certain build environments.
// May throw warnings about needing stdc++17, but should compile without issues on modern compilers.
inline const size_t Assimp::StackAllocator::g_maxBytesPerBlock;
inline const size_t Assimp::StackAllocator::g_startBytesPerBlock;
#include "StackAllocator.inl" #include "StackAllocator.inl"
#endif // include guard #endif // include guard

View File

@ -53,7 +53,8 @@ namespace Assimp {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
LimitBoneWeightsProcess::LimitBoneWeightsProcess() : mMaxWeights(AI_LMW_MAX_WEIGHTS) { LimitBoneWeightsProcess::LimitBoneWeightsProcess() :
mMaxWeights(AI_LMW_MAX_WEIGHTS), mRemoveEmptyBones(true) {
// empty // empty
} }

View File

@ -13,10 +13,14 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <time.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) || \ #if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
defined(__MINGW32__) defined(__MINGW32__)
/* Win32, DOS, MSVC, MSVS */ /* Win32, DOS, MSVC, MSVS, MinGW(GCC for windows) */
#pragma warning( disable : 4706 )
#include <direct.h> #include <direct.h>
#define STRCLONE(STR) ((STR) ? _strdup(STR) : NULL) #define STRCLONE(STR) ((STR) ? _strdup(STR) : NULL)

View File

@ -113,19 +113,19 @@ struct aiMetadata;
*/ */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
inline aiMetadataType GetAiType(bool) { inline aiMetadataType GetAiType(const bool &) {
return AI_BOOL; return AI_BOOL;
} }
inline aiMetadataType GetAiType(int32_t) { inline aiMetadataType GetAiType(int32_t) {
return AI_INT32; return AI_INT32;
} }
inline aiMetadataType GetAiType(uint64_t) { inline aiMetadataType GetAiType(const uint64_t &) {
return AI_UINT64; return AI_UINT64;
} }
inline aiMetadataType GetAiType(float) { inline aiMetadataType GetAiType(const float &) {
return AI_FLOAT; return AI_FLOAT;
} }
inline aiMetadataType GetAiType(double) { inline aiMetadataType GetAiType(const double &) {
return AI_DOUBLE; return AI_DOUBLE;
} }
inline aiMetadataType GetAiType(const aiString &) { inline aiMetadataType GetAiType(const aiString &) {
@ -137,10 +137,10 @@ inline aiMetadataType GetAiType(const aiVector3D &) {
inline aiMetadataType GetAiType(const aiMetadata &) { inline aiMetadataType GetAiType(const aiMetadata &) {
return AI_AIMETADATA; return AI_AIMETADATA;
} }
inline aiMetadataType GetAiType(int64_t) { inline aiMetadataType GetAiType(const int64_t &) {
return AI_INT64; return AI_INT64;
} }
inline aiMetadataType GetAiType(uint32_t) { inline aiMetadataType GetAiType(const uint32_t &) {
return AI_UINT32; return AI_UINT32;
} }

View File

@ -379,7 +379,7 @@ enum aiPostProcessSteps
* point primitives to separate meshes. * point primitives to separate meshes.
* </li> * </li>
* <li>Set the <tt>#AI_CONFIG_PP_SBP_REMOVE</tt> importer property to * <li>Set the <tt>#AI_CONFIG_PP_SBP_REMOVE</tt> importer property to
* @code aiPrimitiveType_POINTS | aiPrimitiveType_LINES * @code aiPrimitiveType_POINT | aiPrimitiveType_LINE
* @endcode to cause SortByPType to reject point * @endcode to cause SortByPType to reject point
* and line meshes from the scene. * and line meshes from the scene.
* </li> * </li>

View File

@ -270,7 +270,7 @@ aiProcess_SortByPType = 0x8000
# point primitives to separate meshes. # point primitives to separate meshes.
# <li> # <li>
# <li>Set the <tt>AI_CONFIG_PP_SBP_REMOVE<tt> option to # <li>Set the <tt>AI_CONFIG_PP_SBP_REMOVE<tt> option to
# @code aiPrimitiveType_POINTS | aiPrimitiveType_LINES # @code aiPrimitiveType_POINT | aiPrimitiveType_LINE
# @endcode to cause SortByPType to reject point # @endcode to cause SortByPType to reject point
# and line meshes from the scene. # and line meshes from the scene.
# <li> # <li>

View File

@ -348,7 +348,7 @@ extern ( C ) {
* <li>Specify the <code>SortByPType</code> flag. This moves line and * <li>Specify the <code>SortByPType</code> flag. This moves line and
* point primitives to separate meshes.</li> * point primitives to separate meshes.</li>
* <li>Set the <code>AI_CONFIG_PP_SBP_REMOVE</codet> option to * <li>Set the <code>AI_CONFIG_PP_SBP_REMOVE</codet> option to
* <code>aiPrimitiveType_POINTS | aiPrimitiveType_LINES</code> * <code>aiPrimitiveType_POINT | aiPrimitiveType_LINE</code>
* to cause SortByPType to reject point and line meshes from the * to cause SortByPType to reject point and line meshes from the
* scene.</li> * scene.</li>
* </ul> * </ul>

View File

@ -349,7 +349,7 @@ public enum AiPostProcessSteps {
* <li>Specify the #SortByPType flag. This moves line and point * <li>Specify the #SortByPType flag. This moves line and point
* primitives to separate meshes. * primitives to separate meshes.
* <li>Set the <tt>AI_CONFIG_PP_SBP_REMOVE</tt> option to * <li>Set the <tt>AI_CONFIG_PP_SBP_REMOVE</tt> option to
* <code>aiPrimitiveType_POINTS | aiPrimitiveType_LINES</code> * <code>aiPrimitiveType_POINT | aiPrimitiveType_LINE</code>
* to cause SortByPType to reject point and line meshes from the * to cause SortByPType to reject point and line meshes from the
* scene. * scene.
* </ul> * </ul>

View File

@ -56,6 +56,6 @@ public:
} }
}; };
TEST_F(utB3DImportExport, importACFromFileTest) { TEST_F(utB3DImportExport, importB3DFromFileTest) {
EXPECT_TRUE(importerTest()); EXPECT_TRUE(importerTest());
} }

View File

@ -242,6 +242,22 @@ TEST_F( utMetadata, copy_test ) {
EXPECT_EQ( i32v, v ); 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 test
{ {
uint64_t v = 255; uint64_t v = 255;
@ -264,14 +280,14 @@ TEST_F( utMetadata, copy_test ) {
EXPECT_EQ( dv, v ); EXPECT_EQ( dv, v );
} }
// bool test // string test
{ {
aiString v; aiString v;
EXPECT_TRUE( copy.Get( "aiString", v ) ); EXPECT_TRUE( copy.Get( "aiString", v ) );
EXPECT_EQ( strVal, v ); EXPECT_EQ( strVal, v );
} }
// bool test // vector test
{ {
aiVector3D v; aiVector3D v;
EXPECT_TRUE( copy.Get( "aiVector3D", v ) ); EXPECT_TRUE( copy.Get( "aiVector3D", v ) );