Merge branch 'master' into patch-1

pull/1827/head
JeffH-BMG 2018-03-22 13:09:32 -04:00 committed by GitHub
commit 376586b164
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 563 additions and 361 deletions

View File

@ -32,8 +32,8 @@ Please check our Wiki as well: https://github.com/assimp/assimp/wiki
#### Supported file formats #### #### Supported file formats ####
A full list [is here](http://assimp.org/main_features_formats.html).
__Importers__: __Importers__:
- 3D - 3D
- 3DS - 3DS
- 3MF - 3MF
@ -109,6 +109,8 @@ __Exporters__:
- STEP - STEP
- glTF 1.0 (partial) - glTF 1.0 (partial)
- glTF 2.0 (partial) - glTF 2.0 (partial)
- 3MF ( experimental )
- FBX ( experimental )
### Building ### ### Building ###
Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do. Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.

View File

@ -72,7 +72,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial()
unsigned int idx( NotSet ); unsigned int idx( NotSet );
for (unsigned int i = 0; i < mScene->mMaterials.size();++i) for (unsigned int i = 0; i < mScene->mMaterials.size();++i)
{ {
std::string s = mScene->mMaterials[i].mName; std::string &s = mScene->mMaterials[i].mName;
for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) { for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) {
*it = static_cast< char >( ::tolower( *it ) ); *it = static_cast< char >( ::tolower( *it ) );
} }

View File

@ -156,10 +156,11 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string&
TextureConverted_Index = 0; TextureConverted_Index = 0;
for(const SPP_Texture& tex_convd: mTexture_Converted) for(const SPP_Texture& tex_convd: mTexture_Converted)
{ {
if(tex_convd.ID == TextureConverted_ID) if ( tex_convd.ID == TextureConverted_ID ) {
return TextureConverted_Index; return TextureConverted_Index;
else } else {
TextureConverted_Index++; ++TextureConverted_Index;
}
} }
// //

View File

@ -267,7 +267,9 @@ void Parser::Parse()
// at the file extension (ASE, ASK, ASC) // at the file extension (ASE, ASK, ASC)
// ************************************************************* // *************************************************************
if (fmt)iFileFormat = fmt; if ( fmt ) {
iFileFormat = fmt;
}
continue; continue;
} }
// main scene information // main scene information
@ -427,28 +429,25 @@ void Parser::ParseLV1SoftSkinBlock()
// Reserve enough storage // Reserve enough storage
vert.mBoneWeights.reserve(numWeights); vert.mBoneWeights.reserve(numWeights);
for (unsigned int w = 0; w < numWeights;++w) std::string bone;
{ for (unsigned int w = 0; w < numWeights;++w) {
std::string bone; bone.clear();
ParseString(bone,"*MESH_SOFTSKINVERTS.Bone"); ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
// Find the bone in the mesh's list // Find the bone in the mesh's list
std::pair<int,ai_real> me; std::pair<int,ai_real> me;
me.first = -1; me.first = -1;
for (unsigned int n = 0; n < curMesh->mBones.size();++n) for (unsigned int n = 0; n < curMesh->mBones.size();++n) {
{ if (curMesh->mBones[n].mName == bone) {
if (curMesh->mBones[n].mName == bone)
{
me.first = n; me.first = n;
break; break;
} }
} }
if (-1 == me.first) if (-1 == me.first) {
{
// We don't have this bone yet, so add it to the list // We don't have this bone yet, so add it to the list
me.first = (int)curMesh->mBones.size(); me.first = static_cast<int>( curMesh->mBones.size() );
curMesh->mBones.push_back(ASE::Bone(bone)); curMesh->mBones.push_back( ASE::Bone( bone ) );
} }
ParseLV4MeshFloat( me.second ); ParseLV4MeshFloat( me.second );
@ -745,6 +744,7 @@ void Parser::ParseLV3MapBlock(Texture& map)
// empty the texture won't be used later. // empty the texture won't be used later.
// *********************************************************** // ***********************************************************
bool parsePath = true; bool parsePath = true;
std::string temp;
while (true) while (true)
{ {
if ('*' == *filePtr) if ('*' == *filePtr)
@ -753,7 +753,7 @@ void Parser::ParseLV3MapBlock(Texture& map)
// type of map // type of map
if (TokenMatch(filePtr,"MAP_CLASS" ,9)) if (TokenMatch(filePtr,"MAP_CLASS" ,9))
{ {
std::string temp; temp.clear();
if(!ParseString(temp,"*MAP_CLASS")) if(!ParseString(temp,"*MAP_CLASS"))
SkipToNextToken(); SkipToNextToken();
if (temp != "Bitmap" && temp != "Normal Bump") if (temp != "Bitmap" && temp != "Normal Bump")

View File

@ -199,6 +199,7 @@ aiNode* BVHLoader::ReadNode()
Node& internNode = mNodes.back(); Node& internNode = mNodes.back();
// now read the node's contents // now read the node's contents
std::string siteToken;
while( 1) while( 1)
{ {
std::string token = GetNextToken(); std::string token = GetNextToken();
@ -218,7 +219,8 @@ aiNode* BVHLoader::ReadNode()
else if( token == "End") else if( token == "End")
{ {
// The real symbol is "End Site". Second part comes in a separate token // The real symbol is "End Site". Second part comes in a separate token
std::string siteToken = GetNextToken(); siteToken.clear();
siteToken = GetNextToken();
if( siteToken != "Site") if( siteToken != "Site")
ThrowException( format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"." ); ThrowException( format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"." );
@ -262,21 +264,18 @@ aiNode* BVHLoader::ReadEndSite( const std::string& pParentName)
aiNode* node = new aiNode( "EndSite_" + pParentName); aiNode* node = new aiNode( "EndSite_" + pParentName);
// now read the node's contents. Only possible entry is "OFFSET" // now read the node's contents. Only possible entry is "OFFSET"
while( 1) std::string token;
{ while( 1) {
std::string token = GetNextToken(); token.clear();
token = GetNextToken();
// end node's offset // end node's offset
if( token == "OFFSET") if( token == "OFFSET") {
{
ReadNodeOffset( node); ReadNodeOffset( node);
} } else if( token == "}") {
else if( token == "}")
{
// we're done with the end node // we're done with the end node
break; break;
} else } else {
{
// everything else is a parse error // everything else is a parse error
ThrowException( format() << "Unknown keyword \"" << token << "\"." ); ThrowException( format() << "Unknown keyword \"" << token << "\"." );
} }
@ -296,8 +295,10 @@ void BVHLoader::ReadNodeOffset( aiNode* pNode)
offset.z = GetNextTokenAsFloat(); offset.z = GetNextTokenAsFloat();
// build a transformation matrix from it // build a transformation matrix from it
pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y, pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x,
0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f); 0.0f, 1.0f, 0.0f, offset.y,
0.0f, 0.0f, 1.0f, offset.z,
0.0f, 0.0f, 0.0f, 1.0f);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -251,7 +251,8 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
/* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile, /* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile,
const void* _magic, unsigned int num, unsigned int offset, unsigned int size) const void* _magic, unsigned int num, unsigned int offset, unsigned int size)
{ {
ai_assert(size <= 16 && _magic); ai_assert( size <= 16 );
ai_assert( _magic );
if (!pIOHandler) { if (!pIOHandler) {
return false; return false;

View File

@ -1269,7 +1269,8 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr; mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr;
PushTag(); PushTag();
std::string node_idstr;
for (size_t a = 0; a < anim->mNumChannels; ++a) { for (size_t a = 0; a < anim->mNumChannels; ++a) {
const aiNodeAnim * nodeAnim = anim->mChannels[a]; const aiNodeAnim * nodeAnim = anim->mChannels[a];
@ -1277,7 +1278,9 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue; if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue;
{ {
const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-input"); node_idstr.clear();
node_idstr += nodeAnim->mNodeName.data;
node_idstr += std::string( "_matrix-input" );
std::vector<ai_real> frames; std::vector<ai_real> frames;
for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
@ -1289,12 +1292,14 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
} }
{ {
const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-output"); node_idstr.clear();
node_idstr += nodeAnim->mNodeName.data;
node_idstr += std::string("_matrix-output");
std::vector<ai_real> keyframes; std::vector<ai_real> keyframes;
keyframes.reserve(nodeAnim->mNumPositionKeys * 16); keyframes.reserve(nodeAnim->mNumPositionKeys * 16);
for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue; aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue;
aiMatrix4x4 ScalingM; // identity aiMatrix4x4 ScalingM; // identity
ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z; ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z;
@ -1361,7 +1366,6 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
PopTag(); PopTag();
mOutput << startstr << "</source>" << endstr; mOutput << startstr << "</source>" << endstr;
} }
} }
for (size_t a = 0; a < anim->mNumChannels; ++a) { for (size_t a = 0; a < anim->mNumChannels; ++a) {

View File

@ -1121,6 +1121,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
continue; continue;
// now check all channels if they affect the current node // now check all channels if they affect the current node
std::string targetID, subElement;
for( std::vector<Collada::AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin(); for( std::vector<Collada::AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin();
cit != pSrcAnim->mChannels.end(); ++cit) cit != pSrcAnim->mChannels.end(); ++cit)
{ {
@ -1147,7 +1148,9 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
} }
if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos) if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos)
continue; continue;
std::string targetID = srcChannel.mTarget.substr( 0, slashPos);
targetID.clear();
targetID = srcChannel.mTarget.substr( 0, slashPos);
if( targetID != srcNode->mID) if( targetID != srcNode->mID)
continue; continue;
@ -1160,7 +1163,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
entry.mTransformId = srcChannel.mTarget.substr( slashPos+1, dotPos - slashPos - 1); entry.mTransformId = srcChannel.mTarget.substr( slashPos+1, dotPos - slashPos - 1);
std::string subElement = srcChannel.mTarget.substr( dotPos+1); subElement.clear();
subElement = srcChannel.mTarget.substr( dotPos+1);
if( subElement == "ANGLE") if( subElement == "ANGLE")
entry.mSubElement = 3; // last number in an Axis-Angle-Transform is the angle entry.mSubElement = 3; // last number in an Axis-Angle-Transform is the angle
else if( subElement == "X") else if( subElement == "X")
@ -1181,7 +1185,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
if (bracketPos != std::string::npos) if (bracketPos != std::string::npos)
{ {
entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1, bracketPos - slashPos - 1); entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1, bracketPos - slashPos - 1);
std::string subElement = srcChannel.mTarget.substr(bracketPos); subElement.clear();
subElement = srcChannel.mTarget.substr(bracketPos);
if (subElement == "(0)(0)") if (subElement == "(0)(0)")
entry.mSubElement = 0; entry.mSubElement = 0;
@ -1215,7 +1220,6 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
entry.mSubElement = 14; entry.mSubElement = 14;
else if (subElement == "(3)(3)") else if (subElement == "(3)(3)")
entry.mSubElement = 15; entry.mSubElement = 15;
} }
// determine which transform step is affected by this channel // determine which transform step is affected by this channel

View File

@ -117,6 +117,7 @@ bool D3MFExporter::exportArchive( const char *file ) {
if ( nullptr == m_zipArchive ) { if ( nullptr == m_zipArchive ) {
return false; return false;
} }
ok |= exportContentTypes(); ok |= exportContentTypes();
ok |= export3DModel(); ok |= export3DModel();
ok |= exportRelations(); ok |= exportRelations();
@ -181,6 +182,8 @@ bool D3MFExporter::export3DModel() {
mModelOutput << "<" << XmlTag::resources << ">"; mModelOutput << "<" << XmlTag::resources << ">";
mModelOutput << std::endl; mModelOutput << std::endl;
writeMetaData();
writeBaseMaterials(); writeBaseMaterials();
writeObjects(); writeObjects();
@ -209,22 +212,45 @@ void D3MFExporter::writeHeader() {
mModelOutput << std::endl; mModelOutput << std::endl;
} }
void D3MFExporter::writeMetaData() {
if ( nullptr == mScene->mMetaData ) {
return;
}
const unsigned int numMetaEntries( mScene->mMetaData->mNumProperties );
if ( 0 == numMetaEntries ) {
return;
}
const aiString *key;
const aiMetadataEntry *entry(nullptr);
for ( size_t i = 0; i < numMetaEntries; ++i ) {
mScene->mMetaData->Get( i, key, entry );
std::string k( key->C_Str() );
aiString value;
mScene->mMetaData->Get( k, value );
mModelOutput << "<" << XmlTag::meta << " " << XmlTag::meta_name << "=\"" << key->C_Str() << "\">";
mModelOutput << value.C_Str();
mModelOutput << "</" << XmlTag::meta << ">" << std::endl;
}
}
void D3MFExporter::writeBaseMaterials() { void D3MFExporter::writeBaseMaterials() {
mModelOutput << "<basematerials id=\"1\">\n"; mModelOutput << "<basematerials id=\"1\">\n";
std::string strName, hexDiffuseColor , tmp;
for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) { for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) {
aiMaterial *mat = mScene->mMaterials[ i ]; aiMaterial *mat = mScene->mMaterials[ i ];
std::string strName;
aiString name; aiString name;
if ( mat->Get( AI_MATKEY_NAME, name ) != aiReturn_SUCCESS ) { if ( mat->Get( AI_MATKEY_NAME, name ) != aiReturn_SUCCESS ) {
strName = "basemat_" + to_string( i ); strName = "basemat_" + to_string( i );
} else { } else {
strName = name.C_Str(); strName = name.C_Str();
} }
std::string hexDiffuseColor;
aiColor4D color; aiColor4D color;
if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) { if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) {
hexDiffuseColor.clear();
tmp.clear();
hexDiffuseColor = "#"; hexDiffuseColor = "#";
std::string tmp;
tmp = DecimalToHexa( color.r ); tmp = DecimalToHexa( color.r );
hexDiffuseColor += tmp; hexDiffuseColor += tmp;

View File

@ -76,6 +76,7 @@ public:
protected: protected:
void writeHeader(); void writeHeader();
void writeMetaData();
void writeBaseMaterials(); void writeBaseMaterials();
void writeObjects(); void writeObjects();
void writeMesh( aiMesh *mesh ); void writeMesh( aiMesh *mesh );

View File

@ -94,14 +94,17 @@ public:
scene->mRootNode = new aiNode(); scene->mRootNode = new aiNode();
std::vector<aiNode*> children; std::vector<aiNode*> children;
std::string nodeName;
while(ReadToEndElement(D3MF::XmlTag::model)) { while(ReadToEndElement(D3MF::XmlTag::model)) {
const std::string nodeName( xmlReader->getNodeName() ); nodeName = xmlReader->getNodeName();
if( nodeName == D3MF::XmlTag::object) { if( nodeName == D3MF::XmlTag::object) {
children.push_back(ReadObject(scene)); children.push_back(ReadObject(scene));
} else if( nodeName == D3MF::XmlTag::build) { } else if( nodeName == D3MF::XmlTag::build) {
// //
} else if ( nodeName == D3MF::XmlTag::basematerials ) { } else if ( nodeName == D3MF::XmlTag::basematerials ) {
ReadBaseMaterials(); ReadBaseMaterials();
} else if ( nodeName == D3MF::XmlTag::meta ) {
ReadMetadata();
} }
} }
@ -109,19 +112,31 @@ public:
scene->mRootNode->mName.Set( "3MF" ); scene->mRootNode->mName.Set( "3MF" );
} }
// import the metadata
if ( !mMetaData.empty() ) {
const size_t numMeta( mMetaData.size() );
scene->mMetaData = aiMetadata::Alloc( numMeta );
for ( size_t i = 0; i < numMeta; ++i ) {
aiString val( mMetaData[ i ].value );
scene->mMetaData->Set( i, mMetaData[ i ].name, val );
}
}
// import the meshes
scene->mNumMeshes = static_cast<unsigned int>( mMeshes.size()); scene->mNumMeshes = static_cast<unsigned int>( mMeshes.size());
scene->mMeshes = new aiMesh*[scene->mNumMeshes](); scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes);
// import the materials
scene->mNumMaterials = static_cast<unsigned int>( mMatArray.size() ); scene->mNumMaterials = static_cast<unsigned int>( mMatArray.size() );
if ( 0 != scene->mNumMaterials ) { if ( 0 != scene->mNumMaterials ) {
scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ]; scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ];
std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials ); std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials );
} }
// create the scenegraph
scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size()); scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size());
scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren]();
std::copy(children.begin(), children.end(), scene->mRootNode->mChildren); std::copy(children.begin(), children.end(), scene->mRootNode->mChildren);
} }
@ -180,6 +195,21 @@ private:
return mesh; return mesh;
} }
void ReadMetadata() {
const std::string name = xmlReader->getAttributeValue( D3MF::XmlTag::meta_name.c_str() );
xmlReader->read();
const std::string value = xmlReader->getNodeData();
if ( name.empty() ) {
return;
}
MetaEntry entry;
entry.name = name;
entry.value = value;
mMetaData.push_back( entry );
}
void ImportVertices(aiMesh* mesh) { void ImportVertices(aiMesh* mesh) {
std::vector<aiVector3D> vertices; std::vector<aiVector3D> vertices;
while(ReadToEndElement(D3MF::XmlTag::vertices)) { while(ReadToEndElement(D3MF::XmlTag::vertices)) {
@ -253,7 +283,7 @@ private:
MatIdArray = it->second; MatIdArray = it->second;
} }
} }
MatIdArray.push_back( newMatIdx ); MatIdArray.push_back( static_cast<unsigned int>( newMatIdx ) );
mMatId2MatArray[ mActiveMatGroup ] = MatIdArray; mMatId2MatArray[ mActiveMatGroup ] = MatIdArray;
} }
@ -371,8 +401,12 @@ private:
return false; return false;
} }
private: private:
struct MetaEntry {
std::string name;
std::string value;
};
std::vector<MetaEntry> mMetaData;
std::vector<aiMesh*> mMeshes; std::vector<aiMesh*> mMeshes;
MatArray mMatArray; MatArray mMatArray;
unsigned int mActiveMatGroup; unsigned int mActiveMatGroup;

View File

@ -288,8 +288,8 @@ bool D3MFZipArchive::Exists(const char* pFile) const {
return false; return false;
} }
std::string rFile(pFile); std::string filename(pFile);
std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(rFile); std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(filename);
bool exist( false ); bool exist( false );
if(it != m_ArchiveMap.end()) { if(it != m_ArchiveMap.end()) {
exist = true; exist = true;

View File

@ -169,7 +169,6 @@ public:
} }
private: private:
LineSplitter splitter; LineSplitter splitter;
int groupcode; int groupcode;
std::string value; std::string value;

View File

@ -76,7 +76,7 @@ bool DefaultIOSystem::Exists( const char* pFile) const
#ifdef _WIN32 #ifdef _WIN32
wchar_t fileName16[PATHLIMIT]; wchar_t fileName16[PATHLIMIT];
bool isUnicode = IsTextUnicode(pFile, strlen(pFile), NULL); bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL);
if (isUnicode) { if (isUnicode) {
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT); MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT);
@ -110,7 +110,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
FILE* file; FILE* file;
#ifdef _WIN32 #ifdef _WIN32
wchar_t fileName16[PATHLIMIT]; wchar_t fileName16[PATHLIMIT];
bool isUnicode = IsTextUnicode(strFile, strlen(strFile), NULL ); bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL );
if (isUnicode) { if (isUnicode) {
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT); MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
std::string mode8(strMode); std::string mode8(strMode);
@ -158,7 +158,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
{ {
ai_assert(in && _out); ai_assert(in && _out);
#if defined( _MSC_VER ) || defined( __MINGW32__ ) #if defined( _MSC_VER ) || defined( __MINGW32__ )
bool isUnicode = IsTextUnicode(in, strlen(in), NULL); bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL);
if (isUnicode) { if (isUnicode) {
wchar_t out16[PATHLIMIT]; wchar_t out16[PATHLIMIT];
wchar_t in16[PATHLIMIT]; wchar_t in16[PATHLIMIT];

View File

@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of DefaultLogger (and Logger) * @brief Implementation of DefaultLogger (and Logger)
*/ */
// Default log streams // Default log streams
#include "Win32DebugLogStream.h" #include "Win32DebugLogStream.h"
#include "StdOStreamLogStream.h" #include "StdOStreamLogStream.h"
@ -62,8 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
# include <thread> # include <thread>
# include <mutex> # include <mutex>
std::mutex loggerMutex;
std::mutex loggerMutex;
#endif #endif
namespace Assimp { namespace Assimp {
@ -76,22 +74,19 @@ static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::War
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Represents a log-stream + its error severity // Represents a log-stream + its error severity
struct LogStreamInfo struct LogStreamInfo {
{ unsigned int m_uiErrorSeverity;
unsigned int m_uiErrorSeverity; LogStream *m_pStream;
LogStream *m_pStream;
// Constructor // Constructor
LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) : LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) :
m_uiErrorSeverity( uiErrorSev ), m_uiErrorSeverity( uiErrorSev ),
m_pStream( pStream ) m_pStream( pStream ) {
{
// empty // empty
} }
// Destructor // Destructor
~LogStreamInfo() ~LogStreamInfo() {
{
delete m_pStream; delete m_pStream;
} }
}; };
@ -109,7 +104,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
#ifdef WIN32 #ifdef WIN32
return new Win32DebugLogStream(); return new Win32DebugLogStream();
#else #else
return NULL; return nullptr;
#endif #endif
// Platform-independent default streams // Platform-independent default streams
@ -118,7 +113,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
case aiDefaultLogStream_STDOUT: case aiDefaultLogStream_STDOUT:
return new StdOStreamLogStream(std::cout); return new StdOStreamLogStream(std::cout);
case aiDefaultLogStream_FILE: case aiDefaultLogStream_FILE:
return (name && *name ? new FileLogStream(name,io) : NULL); return (name && *name ? new FileLogStream(name,io) : nullptr );
default: default:
// We don't know this default log stream, so raise an assertion // We don't know this default log stream, so raise an assertion
ai_assert(false); ai_assert(false);
@ -134,34 +129,38 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/, Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/,
LogSeverity severity /*= NORMAL*/, LogSeverity severity /*= NORMAL*/,
unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/, unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
IOSystem* io /*= NULL*/) IOSystem* io /*= NULL*/) {
{
// enter the mutex here to avoid concurrency problems // enter the mutex here to avoid concurrency problems
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
std::lock_guard<std::mutex> lock(loggerMutex); std::lock_guard<std::mutex> lock(loggerMutex);
#endif #endif
if (m_pLogger && !isNullLogger() ) if ( m_pLogger && !isNullLogger() ) {
delete m_pLogger; delete m_pLogger;
}
m_pLogger = new DefaultLogger( severity ); m_pLogger = new DefaultLogger( severity );
// Attach default log streams // Attach default log streams
// Stream the log to the MSVC debugger? // Stream the log to the MSVC debugger?
if (defStreams & aiDefaultLogStream_DEBUGGER) if ( defStreams & aiDefaultLogStream_DEBUGGER ) {
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER)); m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_DEBUGGER ) );
}
// Stream the log to COUT? // Stream the log to COUT?
if (defStreams & aiDefaultLogStream_STDOUT) if ( defStreams & aiDefaultLogStream_STDOUT ) {
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDOUT)); m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDOUT ) );
}
// Stream the log to CERR? // Stream the log to CERR?
if (defStreams & aiDefaultLogStream_STDERR) if ( defStreams & aiDefaultLogStream_STDERR ) {
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR)); m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDERR ) );
}
// Stream the log to a file // Stream the log to a file
if (defStreams & aiDefaultLogStream_FILE && name && *name) if ( defStreams & aiDefaultLogStream_FILE && name && *name ) {
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_FILE,name,io)); m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_FILE, name, io ) );
}
return m_pLogger; return m_pLogger;
} }
@ -200,7 +199,6 @@ void Logger::warn(const char* message) {
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
void Logger::error(const char* message) { void Logger::error(const char* message) {
// SECURITY FIX: see above // SECURITY FIX: see above
if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
return; return;
@ -209,23 +207,24 @@ void Logger::error(const char* message) {
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
void DefaultLogger::set( Logger *logger ) void DefaultLogger::set( Logger *logger ) {
{
// enter the mutex here to avoid concurrency problems // enter the mutex here to avoid concurrency problems
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
std::lock_guard<std::mutex> lock(loggerMutex); std::lock_guard<std::mutex> lock(loggerMutex);
#endif #endif
if (!logger)logger = &s_pNullLogger; if ( nullptr == logger ) {
if (m_pLogger && !isNullLogger() ) logger = &s_pNullLogger;
}
if ( nullptr != m_pLogger && !isNullLogger() ) {
delete m_pLogger; delete m_pLogger;
}
DefaultLogger::m_pLogger = logger; DefaultLogger::m_pLogger = logger;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
bool DefaultLogger::isNullLogger() bool DefaultLogger::isNullLogger() {
{
return m_pLogger == &s_pNullLogger; return m_pLogger == &s_pNullLogger;
} }
@ -236,8 +235,7 @@ Logger *DefaultLogger::get() {
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Kills the only instance // Kills the only instance
void DefaultLogger::kill() void DefaultLogger::kill() {
{
// enter the mutex here to avoid concurrency problems // enter the mutex here to avoid concurrency problems
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
std::lock_guard<std::mutex> lock(loggerMutex); std::lock_guard<std::mutex> lock(loggerMutex);
@ -252,10 +250,10 @@ void DefaultLogger::kill()
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Debug message // Debug message
void DefaultLogger::OnDebug( const char* message ) void DefaultLogger::OnDebug( const char* message ) {
{ if ( m_Severity == Logger::NORMAL ) {
if ( m_Severity == Logger::NORMAL ) return;
return; }
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
char msg[Size]; char msg[Size];
@ -266,8 +264,7 @@ void DefaultLogger::OnDebug( const char* message )
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Logs an info // Logs an info
void DefaultLogger::OnInfo( const char* message ) void DefaultLogger::OnInfo( const char* message ){
{
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
char msg[Size]; char msg[Size];
ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message ); ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message );
@ -277,8 +274,7 @@ void DefaultLogger::OnInfo( const char* message )
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Logs a warning // Logs a warning
void DefaultLogger::OnWarn( const char* message ) void DefaultLogger::OnWarn( const char* message ) {
{
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
char msg[Size]; char msg[Size];
ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message ); ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message );
@ -288,8 +284,7 @@ void DefaultLogger::OnWarn( const char* message )
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Logs an error // Logs an error
void DefaultLogger::OnError( const char* message ) void DefaultLogger::OnError( const char* message ) {
{
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
char msg[ Size ]; char msg[ Size ];
ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message ); ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message );
@ -299,10 +294,10 @@ void DefaultLogger::OnError( const char* message )
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Will attach a new stream // Will attach a new stream
bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) {
{ if ( nullptr == pStream ) {
if (!pStream)
return false; return false;
}
if (0 == severity) { if (0 == severity) {
severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging; severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
@ -312,8 +307,7 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
it != m_StreamArray.end(); it != m_StreamArray.end();
++it ) ++it )
{ {
if ( (*it)->m_pStream == pStream ) if ( (*it)->m_pStream == pStream ) {
{
(*it)->m_uiErrorSeverity |= severity; (*it)->m_uiErrorSeverity |= severity;
return true; return true;
} }
@ -326,34 +320,31 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Detach a stream // Detach a stream
bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) {
{ if ( nullptr == pStream ) {
if (!pStream)
return false; return false;
}
if (0 == severity) { if (0 == severity) {
severity = SeverityAll; severity = SeverityAll;
} }
for ( StreamIt it = m_StreamArray.begin(); bool res( false );
it != m_StreamArray.end(); for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
++it ) if ( (*it)->m_pStream == pStream ) {
{
if ( (*it)->m_pStream == pStream )
{
(*it)->m_uiErrorSeverity &= ~severity; (*it)->m_uiErrorSeverity &= ~severity;
if ( (*it)->m_uiErrorSeverity == 0 ) if ( (*it)->m_uiErrorSeverity == 0 ) {
{
// don't delete the underlying stream 'cause the caller gains ownership again // don't delete the underlying stream 'cause the caller gains ownership again
(**it).m_pStream = NULL; (**it).m_pStream = nullptr;
delete *it; delete *it;
m_StreamArray.erase( it ); m_StreamArray.erase( it );
res = true;
break; break;
} }
return true; return true;
} }
} }
return false; return res;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
@ -361,15 +352,13 @@ bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
DefaultLogger::DefaultLogger(LogSeverity severity) DefaultLogger::DefaultLogger(LogSeverity severity)
: Logger ( severity ) : Logger ( severity )
, noRepeatMsg (false) , noRepeatMsg (false)
, lastLen( 0 ) , lastLen( 0 ) {
{
lastMsg[0] = '\0'; lastMsg[0] = '\0';
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Destructor // Destructor
DefaultLogger::~DefaultLogger() DefaultLogger::~DefaultLogger() {
{
for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) { for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
// also frees the underlying stream, we are its owner. // also frees the underlying stream, we are its owner.
delete *it; delete *it;
@ -378,9 +367,8 @@ DefaultLogger::~DefaultLogger()
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Writes message to stream // Writes message to stream
void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) {
{ ai_assert(nullptr != message);
ai_assert(NULL != message);
// Check whether this is a repeated message // Check whether this is a repeated message
if (! ::strncmp( message,lastMsg, lastLen-1)) if (! ::strncmp( message,lastMsg, lastLen-1))

View File

@ -99,22 +99,22 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) {
} }
bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
uint32_t imageSize = 0; std::streampos imageSize = 0;
std::string imagePath = path; std::string imagePath = path;
// Test path directly // Test path directly
std::ifstream file(imagePath, std::ios::binary | std::ios::ate); std::ifstream file(imagePath, std::ios::binary | std::ios::ate);
if ((imageSize = file.tellg()) == -1u) { if ((imageSize = file.tellg()) == std::streampos(-1)) {
DefaultLogger::get()->warn("EmbedTexturesProcess: Cannot find image: " + imagePath + ". Will try to find it in root folder."); DefaultLogger::get()->warn("EmbedTexturesProcess: Cannot find image: " + imagePath + ". Will try to find it in root folder.");
// Test path in root path // Test path in root path
imagePath = mRootPath + path; imagePath = mRootPath + path;
file.open(imagePath, std::ios::binary | std::ios::ate); file.open(imagePath, std::ios::binary | std::ios::ate);
if ((imageSize = file.tellg()) == -1u) { if ((imageSize = file.tellg()) == std::streampos(-1)) {
// Test path basename in root path // Test path basename in root path
imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u); imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u);
file.open(imagePath, std::ios::binary | std::ios::ate); file.open(imagePath, std::ios::binary | std::ios::ate);
if ((imageSize = file.tellg()) == -1u) { if ((imageSize = file.tellg()) == std::streampos(-1)) {
DefaultLogger::get()->error("EmbedTexturesProcess: Unable to embed texture: " + path + "."); DefaultLogger::get()->error("EmbedTexturesProcess: Unable to embed texture: " + path + ".");
return false; return false;
} }
@ -134,7 +134,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
// Add the new texture // Add the new texture
auto pTexture = new aiTexture(); auto pTexture = new aiTexture();
pTexture->mHeight = 0; // Means that this is still compressed pTexture->mHeight = 0; // Means that this is still compressed
pTexture->mWidth = imageSize; pTexture->mWidth = static_cast<uint32_t>(imageSize);
pTexture->pcData = imageContent; pTexture->pcData = imageContent;
auto extension = path.substr(path.find_last_of('.') + 1u); auto extension = path.substr(path.find_last_of('.') + 1u);

View File

@ -308,7 +308,8 @@ bool IsVerboseFormat(const aiScene* pScene) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties) { aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath,
unsigned int pPreprocessing, const ExportProperties* pProperties) {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
// when they create scenes from scratch, users will likely create them not in verbose // when they create scenes from scratch, users will likely create them not in verbose

View File

@ -704,7 +704,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] ); aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] );
aiVector3D GeometricScalingInverse = GeometricScaling; aiVector3D GeometricScalingInverse = GeometricScaling;
bool canscale = true; bool canscale = true;
for (size_t i = 0; i < 3; ++i) { for (unsigned int i = 0; i < 3; ++i) {
if ( std::fabs( GeometricScalingInverse[i] ) > zero_epsilon ) { if ( std::fabs( GeometricScalingInverse[i] ) > zero_epsilon ) {
GeometricScalingInverse[i] = 1.0f / GeometricScaling[i]; GeometricScalingInverse[i] = 1.0f / GeometricScaling[i];
} else { } else {
@ -1642,9 +1642,8 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap&
} }
void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures,
const std::string& propName, const std::string& propName,
aiTextureType target, const MeshGeometry* const mesh ) aiTextureType target, const MeshGeometry* const mesh ) {
{
LayeredTextureMap::const_iterator it = layeredTextures.find( propName ); LayeredTextureMap::const_iterator it = layeredTextures.find( propName );
if ( it == layeredTextures.end() ) { if ( it == layeredTextures.end() ) {
return; return;
@ -1888,11 +1887,11 @@ void Converter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyT
// TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes: // TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes:
const aiColor3D& Transparent = GetColorPropertyFactored( props, "TransparentColor", "TransparencyFactor", ok ); const aiColor3D& Transparent = GetColorPropertyFactored( props, "TransparentColor", "TransparencyFactor", ok );
float CalculatedOpacity = 1.0; float CalculatedOpacity = 1.0f;
if ( ok ) { if ( ok ) {
out_mat->AddProperty( &Transparent, 1, AI_MATKEY_COLOR_TRANSPARENT ); out_mat->AddProperty( &Transparent, 1, AI_MATKEY_COLOR_TRANSPARENT );
// as calculated by FBX SDK 2017: // as calculated by FBX SDK 2017:
CalculatedOpacity = 1.0 - ((Transparent.r + Transparent.g + Transparent.b) / 3.0); CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f);
} }
// use of TransparencyFactor is inconsistent. // use of TransparencyFactor is inconsistent.

View File

@ -182,7 +182,7 @@ void FBX::Node::Begin(Assimp::StreamWriterLE &s)
s.PutU4(0); // total property section length s.PutU4(0); // total property section length
// node name // node name
s.PutU1(name.size()); // length of node name s.PutU1(uint8_t(name.size())); // length of node name
s.PutString(name); // node name as raw bytes s.PutString(name); // node name as raw bytes
// property data comes after here // property data comes after here
@ -217,8 +217,8 @@ void FBX::Node::EndProperties(
ai_assert(pos > property_start); ai_assert(pos > property_start);
size_t property_section_size = pos - property_start; size_t property_section_size = pos - property_start;
s.Seek(start_pos + 4); s.Seek(start_pos + 4);
s.PutU4(num_properties); s.PutU4(uint32_t(num_properties));
s.PutU4(property_section_size); s.PutU4(uint32_t(property_section_size));
s.Seek(pos); s.Seek(pos);
} }
@ -232,7 +232,7 @@ void FBX::Node::End(
// now go back and write initial pos // now go back and write initial pos
this->end_pos = s.Tell(); this->end_pos = s.Tell();
s.Seek(start_pos); s.Seek(start_pos);
s.PutU4(end_pos); s.PutU4(uint32_t(end_pos));
s.Seek(end_pos); s.Seek(end_pos);
} }
@ -251,9 +251,9 @@ void FBX::Node::WritePropertyNode(
Node node(name); Node node(name);
node.Begin(s); node.Begin(s);
s.PutU1('d'); s.PutU1('d');
s.PutU4(v.size()); // number of elements s.PutU4(uint32_t(v.size())); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed) s.PutU4(0); // no encoding (1 would be zip-compressed)
s.PutU4(v.size() * 8); // data size s.PutU4(uint32_t(v.size()) * 8); // data size
for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); } for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); }
node.EndProperties(s, 1); node.EndProperties(s, 1);
node.End(s, false); node.End(s, false);
@ -271,9 +271,9 @@ void FBX::Node::WritePropertyNode(
Node node(name); Node node(name);
node.Begin(s); node.Begin(s);
s.PutU1('i'); s.PutU1('i');
s.PutU4(v.size()); // number of elements s.PutU4(uint32_t(v.size())); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed) s.PutU4(0); // no encoding (1 would be zip-compressed)
s.PutU4(v.size() * 4); // data size s.PutU4(uint32_t(v.size()) * 4); // data size
for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); } for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); }
node.EndProperties(s, 1); node.EndProperties(s, 1);
node.End(s, false); node.End(s, false);

View File

@ -127,8 +127,8 @@ FBX::Property::Property(const aiMatrix4x4& vm)
: type('d'), data(8*16) : type('d'), data(8*16)
{ {
double* d = reinterpret_cast<double*>(data.data()); double* d = reinterpret_cast<double*>(data.data());
for (size_t c = 0; c < 4; ++c) { for (unsigned int c = 0; c < 4; ++c) {
for (size_t r = 0; r < 4; ++r) { for (unsigned int r = 0; r < 4; ++r) {
d[4*c+r] = vm[r][c]; d[4*c+r] = vm[r][c];
} }
} }
@ -164,15 +164,15 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s)
case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(data.data()))); return; case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(data.data()))); return;
case 'S': case 'S':
case 'R': case 'R':
s.PutU4(data.size()); s.PutU4(uint32_t(data.size()));
for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); } for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); }
return; return;
case 'i': case 'i':
N = data.size() / 4; N = data.size() / 4;
s.PutU4(N); // number of elements s.PutU4(uint32_t(N)); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed) s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large? // TODO: compress if large?
s.PutU4(data.size()); // data size s.PutU4(uint32_t(data.size())); // data size
d = data.data(); d = data.data();
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
s.PutI4((reinterpret_cast<int32_t*>(d))[i]); s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
@ -180,10 +180,10 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s)
return; return;
case 'd': case 'd':
N = data.size() / 8; N = data.size() / 8;
s.PutU4(N); // number of elements s.PutU4(uint32_t(N)); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed) s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large? // TODO: compress if large?
s.PutU4(data.size()); // data size s.PutU4(uint32_t(data.size())); // data size
d = data.data(); d = data.data();
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
s.PutF8((reinterpret_cast<double*>(d))[i]); s.PutF8((reinterpret_cast<double*>(d))[i]);

View File

@ -460,7 +460,7 @@ size_t count_images(const aiScene* scene) {
){ ){
const aiTextureType textype = static_cast<aiTextureType>(tt); const aiTextureType textype = static_cast<aiTextureType>(tt);
const size_t texcount = mat->GetTextureCount(textype); const size_t texcount = mat->GetTextureCount(textype);
for (size_t j = 0; j < texcount; ++j) { for (unsigned int j = 0; j < texcount; ++j) {
mat->GetTexture(textype, j, &texpath); mat->GetTexture(textype, j, &texpath);
images.insert(std::string(texpath.C_Str())); images.insert(std::string(texpath.C_Str()));
} }
@ -593,7 +593,7 @@ void FBXExporter::WriteDefinitions ()
// Model / FbxNode // Model / FbxNode
// <~~ node heirarchy // <~~ node heirarchy
count = count_nodes(mScene->mRootNode) - 1; // (not counting root node) count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node)
if (count) { if (count) {
n = FBX::Node("ObjectType", Property("Model")); n = FBX::Node("ObjectType", Property("Model"));
n.AddChild("Count", count); n.AddChild("Count", count);
@ -763,7 +763,7 @@ void FBXExporter::WriteDefinitions ()
// Video / FbxVideo // Video / FbxVideo
// one for each image file. // one for each image file.
count = count_images(mScene); count = int32_t(count_images(mScene));
if (count) { if (count) {
n = FBX::Node("ObjectType", Property("Video")); n = FBX::Node("ObjectType", Property("Video"));
n.AddChild("Count", count); n.AddChild("Count", count);
@ -792,7 +792,7 @@ void FBXExporter::WriteDefinitions ()
// Texture / FbxFileTexture // Texture / FbxFileTexture
// <~~ aiTexture // <~~ aiTexture
count = count_textures(mScene); count = int32_t(count_textures(mScene));
if (count) { if (count) {
n = FBX::Node("ObjectType", Property("Texture")); n = FBX::Node("ObjectType", Property("Texture"));
n.AddChild("Count", count); n.AddChild("Count", count);
@ -848,7 +848,7 @@ void FBXExporter::WriteDefinitions ()
} }
// Deformer // Deformer
count = count_deformers(mScene); count = int32_t(count_deformers(mScene));
if (count) { if (count) {
n = FBX::Node("ObjectType", Property("Deformer")); n = FBX::Node("ObjectType", Property("Deformer"));
n.AddChild("Count", count); n.AddChild("Count", count);
@ -943,7 +943,7 @@ void FBXExporter::WriteObjects ()
std::vector<int32_t> vertex_indices; std::vector<int32_t> vertex_indices;
// map of vertex value to its index in the data vector // map of vertex value to its index in the data vector
std::map<aiVector3D,size_t> index_by_vertex_value; std::map<aiVector3D,size_t> index_by_vertex_value;
size_t index = 0; int32_t index = 0;
for (size_t vi = 0; vi < m->mNumVertices; ++vi) { for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
aiVector3D vtx = m->mVertices[vi]; aiVector3D vtx = m->mVertices[vi];
auto elem = index_by_vertex_value.find(vtx); auto elem = index_by_vertex_value.find(vtx);
@ -955,7 +955,7 @@ void FBXExporter::WriteObjects ()
flattened_vertices.push_back(vtx[2]); flattened_vertices.push_back(vtx[2]);
++index; ++index;
} else { } else {
vertex_indices.push_back(elem->second); vertex_indices.push_back(int32_t(elem->second));
} }
} }
FBX::Node::WritePropertyNode( FBX::Node::WritePropertyNode(
@ -1052,7 +1052,7 @@ void FBXExporter::WriteObjects ()
std::vector<double> uv_data; std::vector<double> uv_data;
std::vector<int32_t> uv_indices; std::vector<int32_t> uv_indices;
std::map<aiVector3D,int32_t> index_by_uv; std::map<aiVector3D,int32_t> index_by_uv;
size_t index = 0; int32_t index = 0;
for (size_t fi = 0; fi < m->mNumFaces; ++fi) { for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
const aiFace &f = m->mFaces[fi]; const aiFace &f = m->mFaces[fi];
for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) { for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
@ -1062,7 +1062,7 @@ void FBXExporter::WriteObjects ()
if (elem == index_by_uv.end()) { if (elem == index_by_uv.end()) {
index_by_uv[uv] = index; index_by_uv[uv] = index;
uv_indices.push_back(index); uv_indices.push_back(index);
for (size_t x = 0; x < m->mNumUVComponents[uvi]; ++x) { for (unsigned int x = 0; x < m->mNumUVComponents[uvi]; ++x) {
uv_data.push_back(uv[x]); uv_data.push_back(uv[x]);
} }
++index; ++index;
@ -1208,13 +1208,13 @@ void FBXExporter::WriteObjects ()
// and usualy are completely ignored when loading. // and usualy are completely ignored when loading.
// One notable exception is the "Opacity" property, // One notable exception is the "Opacity" property,
// which Blender uses as (1.0 - alpha). // which Blender uses as (1.0 - alpha).
c.r = 0; c.g = 0; c.b = 0; c.r = 0.0f; c.g = 0.0f; c.b = 0.0f;
m->Get(AI_MATKEY_COLOR_EMISSIVE, c); m->Get(AI_MATKEY_COLOR_EMISSIVE, c);
p.AddP70vector("Emissive", c.r, c.g, c.b); p.AddP70vector("Emissive", c.r, c.g, c.b);
c.r = 0.2; c.g = 0.2; c.b = 0.2; c.r = 0.2f; c.g = 0.2f; c.b = 0.2f;
m->Get(AI_MATKEY_COLOR_AMBIENT, c); m->Get(AI_MATKEY_COLOR_AMBIENT, c);
p.AddP70vector("Ambient", c.r, c.g, c.b); p.AddP70vector("Ambient", c.r, c.g, c.b);
c.r = 0.8; c.g = 0.8; c.b = 0.8; c.r = 0.8f; c.g = 0.8f; c.b = 0.8f;
m->Get(AI_MATKEY_COLOR_DIFFUSE, c); m->Get(AI_MATKEY_COLOR_DIFFUSE, c);
p.AddP70vector("Diffuse", c.r, c.g, c.b); p.AddP70vector("Diffuse", c.r, c.g, c.b);
// The FBX SDK determines "Opacity" from transparency colour (RGB) // The FBX SDK determines "Opacity" from transparency colour (RGB)
@ -1223,29 +1223,29 @@ void FBXExporter::WriteObjects ()
// so we should take it from AI_MATKEY_OPACITY if possible. // so we should take it from AI_MATKEY_OPACITY if possible.
// It might make more sense to use TransparencyFactor, // It might make more sense to use TransparencyFactor,
// but Blender actually loads "Opacity" correctly, so let's use it. // but Blender actually loads "Opacity" correctly, so let's use it.
f = 1.0; f = 1.0f;
if (m->Get(AI_MATKEY_COLOR_TRANSPARENT, c) == aiReturn_SUCCESS) { if (m->Get(AI_MATKEY_COLOR_TRANSPARENT, c) == aiReturn_SUCCESS) {
f = 1.0 - ((c.r + c.g + c.b) / 3); f = 1.0f - ((c.r + c.g + c.b) / 3.0f);
} }
m->Get(AI_MATKEY_OPACITY, f); m->Get(AI_MATKEY_OPACITY, f);
p.AddP70double("Opacity", f); p.AddP70double("Opacity", f);
if (phong) { if (phong) {
// specular color is multiplied by shininess_strength // specular color is multiplied by shininess_strength
c.r = 0.2; c.g = 0.2; c.b = 0.2; c.r = 0.2f; c.g = 0.2f; c.b = 0.2f;
m->Get(AI_MATKEY_COLOR_SPECULAR, c); m->Get(AI_MATKEY_COLOR_SPECULAR, c);
f = 1.0; f = 1.0f;
m->Get(AI_MATKEY_SHININESS_STRENGTH, f); m->Get(AI_MATKEY_SHININESS_STRENGTH, f);
p.AddP70vector("Specular", f*c.r, f*c.g, f*c.b); p.AddP70vector("Specular", f*c.r, f*c.g, f*c.b);
f = 20.0; f = 20.0f;
m->Get(AI_MATKEY_SHININESS, f); m->Get(AI_MATKEY_SHININESS, f);
p.AddP70double("Shininess", f); p.AddP70double("Shininess", f);
// Legacy "Reflectivity" is F*F*((R+G+B)/3), // Legacy "Reflectivity" is F*F*((R+G+B)/3),
// where F is the proportion of light reflected (AKA reflectivity), // where F is the proportion of light reflected (AKA reflectivity),
// and RGB is the reflective colour of the material. // and RGB is the reflective colour of the material.
// No idea why, but we might as well set it the same way. // No idea why, but we might as well set it the same way.
f = 0.0; f = 0.0f;
m->Get(AI_MATKEY_REFLECTIVITY, f); m->Get(AI_MATKEY_REFLECTIVITY, f);
c.r = 1.0, c.g = 1.0, c.b = 1.0; c.r = 1.0f, c.g = 1.0f, c.b = 1.0f;
m->Get(AI_MATKEY_COLOR_REFLECTIVE, c); m->Get(AI_MATKEY_COLOR_REFLECTIVE, c);
p.AddP70double("Reflectivity", f*f*((c.r+c.g+c.b)/3.0)); p.AddP70double("Reflectivity", f*f*((c.r+c.g+c.b)/3.0));
} }
@ -1269,7 +1269,7 @@ void FBXExporter::WriteObjects ()
const aiTextureType textype = static_cast<aiTextureType>(tt); const aiTextureType textype = static_cast<aiTextureType>(tt);
const size_t texcount = mat->GetTextureCount(textype); const size_t texcount = mat->GetTextureCount(textype);
for (size_t j = 0; j < texcount; ++j) { for (size_t j = 0; j < texcount; ++j) {
mat->GetTexture(textype, j, &texpath); mat->GetTexture(textype, (unsigned int)j, &texpath);
const std::string texstring = texpath.C_Str(); const std::string texstring = texpath.C_Str();
auto elem = uid_by_image.find(texstring); auto elem = uid_by_image.find(texstring);
if (elem == uid_by_image.end()) { if (elem == uid_by_image.end()) {
@ -1591,7 +1591,7 @@ void FBXExporter::WriteObjects ()
std::vector<int32_t> vertex_indices; std::vector<int32_t> vertex_indices;
// map of vertex value to its index in the data vector // map of vertex value to its index in the data vector
std::map<aiVector3D,size_t> index_by_vertex_value; std::map<aiVector3D,size_t> index_by_vertex_value;
size_t index = 0; int32_t index = 0;
for (size_t vi = 0; vi < m->mNumVertices; ++vi) { for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
aiVector3D vtx = m->mVertices[vi]; aiVector3D vtx = m->mVertices[vi];
auto elem = index_by_vertex_value.find(vtx); auto elem = index_by_vertex_value.find(vtx);
@ -1600,7 +1600,7 @@ void FBXExporter::WriteObjects ()
index_by_vertex_value[vtx] = index; index_by_vertex_value[vtx] = index;
++index; ++index;
} else { } else {
vertex_indices.push_back(elem->second); vertex_indices.push_back(int32_t(elem->second));
} }
} }
@ -1616,7 +1616,7 @@ void FBXExporter::WriteObjects ()
// as it can be instanced to many nodes. // as it can be instanced to many nodes.
// All we can do is assume no instancing, // All we can do is assume no instancing,
// and take the first node we find that contains the mesh. // and take the first node we find that contains the mesh.
aiNode* mesh_node = get_node_for_mesh(mi, mScene->mRootNode); aiNode* mesh_node = get_node_for_mesh((unsigned int)mi, mScene->mRootNode);
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
@ -1682,7 +1682,7 @@ void FBXExporter::WriteObjects ()
// this should be the same as the bone's mOffsetMatrix. // this should be the same as the bone's mOffsetMatrix.
// if it's not the same, the skeleton isn't in the bind pose. // if it's not the same, the skeleton isn't in the bind pose.
const float epsilon = 1e-5; // some error is to be expected const float epsilon = 1e-5f; // some error is to be expected
bool bone_xform_okay = true; bool bone_xform_okay = true;
if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) { if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) {
not_in_bind_pose.insert(b); not_in_bind_pose.insert(b);
@ -2002,7 +2002,7 @@ void FBXExporter::WriteModelNodes(
transform_chain.emplace_back(elem->first, t); transform_chain.emplace_back(elem->first, t);
break; break;
case 'r': // rotation case 'r': // rotation
r *= DEG; r *= float(DEG);
transform_chain.emplace_back(elem->first, r); transform_chain.emplace_back(elem->first, r);
break; break;
case 's': // scale case 's': // scale

View File

@ -622,7 +622,6 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
if (s != std::string::npos) { if (s != std::string::npos) {
DefaultLogger::get()->info("File extension not known, trying signature-based detection"); DefaultLogger::get()->info("File extension not known, trying signature-based detection");
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) { if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
imp = pimpl->mImporter[a]; imp = pimpl->mImporter[a];
break; break;
@ -947,6 +946,7 @@ BaseImporter* Importer::GetImporter (const char* szExtension) const
size_t Importer::GetImporterIndex (const char* szExtension) const size_t Importer::GetImporterIndex (const char* szExtension) const
{ {
ai_assert(szExtension); ai_assert(szExtension);
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
// skip over wildcard and dot characters at string head -- // skip over wildcard and dot characters at string head --

View File

@ -583,9 +583,8 @@ typedef std::map<std::string, std::string> Metadata;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessMetadata(const Schema_2x3::ListOf< Schema_2x3::Lazy< Schema_2x3::IfcProperty >, 1, 0 >& set, ConversionData& conv, Metadata& properties, void ProcessMetadata(const Schema_2x3::ListOf< Schema_2x3::Lazy< Schema_2x3::IfcProperty >, 1, 0 >& set, ConversionData& conv, Metadata& properties,
const std::string& prefix = "", const std::string& prefix = "",
unsigned int nest = 0) unsigned int nest = 0) {
{
for(const Schema_2x3::IfcProperty& property : set) { for(const Schema_2x3::IfcProperty& property : set) {
const std::string& key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name; const std::string& key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name;
if (const Schema_2x3::IfcPropertySingleValue* const singleValue = property.ToPtr<Schema_2x3::IfcPropertySingleValue>()) { if (const Schema_2x3::IfcPropertySingleValue* const singleValue = property.ToPtr<Schema_2x3::IfcPropertySingleValue>()) {

View File

@ -132,18 +132,18 @@ ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMt
mOutputMat.precision(16); mOutputMat.precision(16);
WriteGeometryFile(noMtl); WriteGeometryFile(noMtl);
if (!noMtl) if ( !noMtl ) {
WriteMaterialFile(); WriteMaterialFile();
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ObjExporter::~ObjExporter() { ObjExporter::~ObjExporter() {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string ObjExporter :: GetMaterialLibName() std::string ObjExporter::GetMaterialLibName() {
{
// within the Obj file, we use just the relative file name with the path stripped // within the Obj file, we use just the relative file name with the path stripped
const std::string& s = GetMaterialLibFileName(); const std::string& s = GetMaterialLibFileName();
std::string::size_type il = s.find_last_of("/\\"); std::string::size_type il = s.find_last_of("/\\");
@ -158,8 +158,9 @@ std::string ObjExporter :: GetMaterialLibName()
std::string ObjExporter::GetMaterialLibFileName() { std::string ObjExporter::GetMaterialLibFileName() {
// Remove existing .obj file extension so that the final material file name will be fileName.mtl and not fileName.obj.mtl // Remove existing .obj file extension so that the final material file name will be fileName.mtl and not fileName.obj.mtl
size_t lastdot = filename.find_last_of('.'); size_t lastdot = filename.find_last_of('.');
if (lastdot != std::string::npos) if ( lastdot != std::string::npos ) {
return filename.substr(0, lastdot) + MaterialExt; return filename.substr( 0, lastdot ) + MaterialExt;
}
return filename + MaterialExt; return filename + MaterialExt;
} }
@ -172,8 +173,7 @@ void ObjExporter::WriteHeader(std::ostringstream& out) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string ObjExporter::GetMaterialName(unsigned int index) std::string ObjExporter::GetMaterialName(unsigned int index) {
{
const aiMaterial* const mat = pScene->mMaterials[index]; const aiMaterial* const mat = pScene->mMaterials[index];
if ( nullptr == mat ) { if ( nullptr == mat ) {
static const std::string EmptyStr; static const std::string EmptyStr;
@ -191,8 +191,7 @@ std::string ObjExporter::GetMaterialName(unsigned int index)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ObjExporter::WriteMaterialFile() void ObjExporter::WriteMaterialFile() {
{
WriteHeader(mOutputMat); WriteHeader(mOutputMat);
for(unsigned int i = 0; i < pScene->mNumMaterials; ++i) { for(unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
@ -310,8 +309,9 @@ void ObjExporter::WriteGeometryFile(bool noMtl) {
if (!m.name.empty()) { if (!m.name.empty()) {
mOutput << "g " << m.name << endl; mOutput << "g " << m.name << endl;
} }
if (!noMtl) if ( !noMtl ) {
mOutput << "usemtl " << m.matname << endl; mOutput << "usemtl " << m.matname << endl;
}
for(const Face& f : m.faces) { for(const Face& f : m.faces) {
mOutput << f.kind << ' '; mOutput << f.kind << ' ';
@ -382,7 +382,7 @@ void ObjExporter::colIndexMap::getColors( std::vector<aiColor4D> &colors ) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) { void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) {
mMeshes.push_back(MeshInstance()); mMeshes.push_back(MeshInstance() );
MeshInstance& mesh = mMeshes.back(); MeshInstance& mesh = mMeshes.back();
mesh.name = std::string( name.data, name.length ); mesh.name = std::string( name.data, name.length );
@ -436,8 +436,7 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) {
{
const aiMatrix4x4& mAbs = mParent * nd->mTransformation; const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
for(unsigned int i = 0; i < nd->mNumMeshes; ++i) { for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {

View File

@ -207,30 +207,24 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
// Create the root node of the scene // Create the root node of the scene
pScene->mRootNode = new aiNode; pScene->mRootNode = new aiNode;
if ( !pModel->m_ModelName.empty() ) if ( !pModel->m_ModelName.empty() ) {
{
// Set the name of the scene // Set the name of the scene
pScene->mRootNode->mName.Set(pModel->m_ModelName); pScene->mRootNode->mName.Set(pModel->m_ModelName);
} } else {
else
{
// This is a fatal error, so break down the application // This is a fatal error, so break down the application
ai_assert(false); ai_assert(false);
} }
// Create nodes for the whole scene // Create nodes for the whole scene
std::vector<aiMesh*> MeshArray; std::vector<aiMesh*> MeshArray;
for (size_t index = 0; index < pModel->m_Objects.size(); index++) for (size_t index = 0; index < pModel->m_Objects.size(); ++index ) {
{
createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray); createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray);
} }
// Create mesh pointer buffer for this scene // Create mesh pointer buffer for this scene
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 ];
} }
} }
@ -261,8 +255,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
appendChildToParentNode( pParent, pNode ); appendChildToParentNode( pParent, pNode );
} }
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 ); aiMesh *pMesh = createTopology( pModel, pObject, meshId );
if( pMesh ) { if( pMesh ) {
@ -275,8 +268,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
} }
// Create all nodes from the sub-objects stored in the current object // Create all nodes from the sub-objects stored in the current object
if ( !pObject->m_SubObjects.empty() ) if ( !pObject->m_SubObjects.empty() ) {
{
size_t numChilds = pObject->m_SubObjects.size(); size_t numChilds = pObject->m_SubObjects.size();
pNode->mNumChildren = static_cast<unsigned int>( numChilds ); pNode->mNumChildren = static_cast<unsigned int>( numChilds );
pNode->mChildren = new aiNode*[ numChilds ]; pNode->mChildren = new aiNode*[ numChilds ];
@ -286,16 +278,14 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
// Set mesh instances into scene- and node-instances // Set mesh instances into scene- and node-instances
const size_t meshSizeDiff = MeshArray.size()- oldMeshSize; const size_t meshSizeDiff = MeshArray.size()- oldMeshSize;
if ( meshSizeDiff > 0 ) if ( meshSizeDiff > 0 ) {
{
pNode->mMeshes = new unsigned int[ meshSizeDiff ]; pNode->mMeshes = new unsigned int[ meshSizeDiff ];
pNode->mNumMeshes = static_cast<unsigned int>( meshSizeDiff ); pNode->mNumMeshes = static_cast<unsigned int>( meshSizeDiff );
size_t index = 0; size_t index = 0;
for (size_t i = oldMeshSize; i < MeshArray.size(); i++) for (size_t i = oldMeshSize; i < MeshArray.size(); ++i ) {
{
pNode->mMeshes[ index ] = pScene->mNumMeshes; pNode->mMeshes[ index ] = pScene->mNumMeshes;
pScene->mNumMeshes++; pScene->mNumMeshes++;
index++; ++index;
} }
} }

View File

@ -612,13 +612,14 @@ void ObjFileParser::getMaterialLib() {
if ( '/' != *path.rbegin() ) { if ( '/' != *path.rbegin() ) {
path += '/'; path += '/';
} }
absName = path + strMatName; absName += path;
absName += strMatName;
} else { } else {
absName = strMatName; absName = strMatName;
} }
IOStream *pFile = m_pIO->Open( absName );
if (!pFile ) { IOStream *pFile = m_pIO->Open( absName );
if ( nullptr == pFile ) {
DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName); DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName);
std::string strMatFallbackName = m_originalObjFileName.substr(0, m_originalObjFileName.length() - 3) + "mtl"; std::string strMatFallbackName = m_originalObjFileName.substr(0, m_originalObjFileName.length() - 3) + "mtl";
DefaultLogger::get()->info("OBJ: Opening fallback material file " + strMatFallbackName); DefaultLogger::get()->info("OBJ: Opening fallback material file " + strMatFallbackName);

View File

@ -52,27 +52,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream> #include <sstream>
#include <cctype> #include <cctype>
namespace Assimp namespace Assimp {
{ namespace Ogre {
namespace Ogre
{
/// Returns a lower cased copy of @s. /// Returns a lower cased copy of @s.
static inline std::string ToLower(std::string s) static AI_FORCE_INLINE
std::string ToLower(std::string s)
{ {
std::transform(s.begin(), s.end(), s.begin(), ::tolower); std::transform(s.begin(), s.end(), s.begin(), ::tolower);
return s; return s;
} }
/// Returns if @c s ends with @c suffix. If @c caseSensitive is false, both strings will be lower cased before matching. /// Returns if @c s ends with @c suffix. If @c caseSensitive is false, both strings will be lower cased before matching.
static inline bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true) static AI_FORCE_INLINE
{ bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true) {
if (s.empty() || suffix.empty()) if (s.empty() || suffix.empty()) {
{
return false; return false;
} } else if (s.length() < suffix.length()) {
else if (s.length() < suffix.length())
{
return false; return false;
} }
@ -82,48 +78,43 @@ static inline bool EndsWith(const std::string &s, const std::string &suffix, boo
size_t len = suffix.length(); size_t len = suffix.length();
std::string sSuffix = s.substr(s.length()-len, len); std::string sSuffix = s.substr(s.length()-len, len);
return (ASSIMP_stricmp(sSuffix, suffix) == 0); return (ASSIMP_stricmp(sSuffix, suffix) == 0);
} }
// Below trim functions adapted from http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring // Below trim functions adapted from http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
/// Trim from start /// Trim from start
static inline std::string &TrimLeft(std::string &s, bool newlines = true) static AI_FORCE_INLINE
{ std::string &TrimLeft(std::string &s, bool newlines = true) {
if (!newlines) if (!newlines) {
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace<char>(c); })); s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace<char>(c); }));
} } else {
else
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); })); s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
} }
return s; return s;
} }
/// Trim from end /// Trim from end
static inline std::string &TrimRight(std::string &s, bool newlines = true) static AI_FORCE_INLINE
{ std::string &TrimRight(std::string &s, bool newlines = true) {
if (!newlines) if (!newlines) {
{
s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace<char>(c); }).base(),s.end()); s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace<char>(c); }).base(),s.end());
} } else {
else
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); })); s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
} }
return s; return s;
} }
/// Trim from both ends /// Trim from both ends
static inline std::string &Trim(std::string &s, bool newlines = true) static AI_FORCE_INLINE
{ std::string &Trim(std::string &s, bool newlines = true) {
return TrimLeft(TrimRight(s, newlines), newlines); return TrimLeft(TrimRight(s, newlines), newlines);
} }
/// Skips a line from current @ss position until a newline. Returns the skipped part. /// Skips a line from current @ss position until a newline. Returns the skipped part.
static inline std::string SkipLine(std::stringstream &ss) static AI_FORCE_INLINE
{ std::string SkipLine(std::stringstream &ss) {
std::string skipped; std::string skipped;
getline(ss, skipped); getline(ss, skipped);
return skipped; return skipped;
@ -131,8 +122,8 @@ static inline std::string SkipLine(std::stringstream &ss)
/// Skips a line and reads next element from @c ss to @c nextElement. /// Skips a line and reads next element from @c ss to @c nextElement.
/** @return Skipped line content until newline. */ /** @return Skipped line content until newline. */
static inline std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement) static AI_FORCE_INLINE
{ std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement) {
std::string skipped = SkipLine(ss); std::string skipped = SkipLine(ss);
ss >> nextElement; ss >> nextElement;
return skipped; return skipped;

View File

@ -213,18 +213,18 @@ std::string &OgreXmlSerializer::SkipCurrentNode()
DefaultLogger::get()->debug("Skipping node <" + m_currentNodeName + ">"); DefaultLogger::get()->debug("Skipping node <" + m_currentNodeName + ">");
#endif #endif
for(;;) for(;;) {
{ if (!m_reader->read()) {
if (!m_reader->read())
{
m_currentNodeName = ""; m_currentNodeName = "";
return m_currentNodeName; return m_currentNodeName;
} }
if (m_reader->getNodeType() != irr::io::EXN_ELEMENT_END) if ( m_reader->getNodeType() != irr::io::EXN_ELEMENT_END ) {
continue; continue;
else if (std::string(m_reader->getNodeName()) == m_currentNodeName) } else if ( std::string( m_reader->getNodeName() ) == m_currentNodeName ) {
break; break;
}
} }
return NextNode(); return NextNode();
} }
@ -303,17 +303,16 @@ static const char *anZ = "z";
// Mesh // Mesh
MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader) MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader) {
{
OgreXmlSerializer serializer(reader); OgreXmlSerializer serializer(reader);
MeshXml *mesh = new MeshXml(); MeshXml *mesh = new MeshXml();
serializer.ReadMesh(mesh); serializer.ReadMesh(mesh);
return mesh; return mesh;
} }
void OgreXmlSerializer::ReadMesh(MeshXml *mesh) void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
{
if (NextNode() != nnMesh) { if (NextNode() != nnMesh) {
throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <mesh>"); throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <mesh>");
} }

View File

@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/SceneCombiner.h> #include <assimp/SceneCombiner.h>
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/metadata.h>
#include <assimp/Hash.h> #include <assimp/Hash.h>
#include "time.h" #include "time.h"
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
@ -806,8 +807,9 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/,
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
if ((*it)->mNormals) { if ((*it)->mNormals) {
::memcpy(pv2,(*it)->mNormals,(*it)->mNumVertices*sizeof(aiVector3D)); ::memcpy(pv2,(*it)->mNormals,(*it)->mNumVertices*sizeof(aiVector3D));
} else {
DefaultLogger::get()->warn( "JoinMeshes: Normals expected but input mesh contains no normals" );
} }
else DefaultLogger::get()->warn("JoinMeshes: Normals expected but input mesh contains no normals");
pv2 += (*it)->mNumVertices; pv2 += (*it)->mNumVertices;
} }
} }
@ -817,28 +819,29 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/,
pv2 = out->mTangents = new aiVector3D[out->mNumVertices]; pv2 = out->mTangents = new aiVector3D[out->mNumVertices];
aiVector3D* pv2b = out->mBitangents = new aiVector3D[out->mNumVertices]; aiVector3D* pv2b = out->mBitangents = new aiVector3D[out->mNumVertices];
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
if ((*it)->mTangents) { if ((*it)->mTangents) {
::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices*sizeof(aiVector3D)); ::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices*sizeof(aiVector3D));
::memcpy(pv2b,(*it)->mBitangents,(*it)->mNumVertices*sizeof(aiVector3D)); ::memcpy(pv2b,(*it)->mBitangents,(*it)->mNumVertices*sizeof(aiVector3D));
} else {
DefaultLogger::get()->warn( "JoinMeshes: Tangents expected but input mesh contains no tangents" );
} }
else DefaultLogger::get()->warn("JoinMeshes: Tangents expected but input mesh contains no tangents");
pv2 += (*it)->mNumVertices; pv2 += (*it)->mNumVertices;
pv2b += (*it)->mNumVertices; pv2b += (*it)->mNumVertices;
} }
} }
// copy texture coordinates // copy texture coordinates
unsigned int n = 0; unsigned int n = 0;
while ((**begin).HasTextureCoords(n)) { while ((**begin).HasTextureCoords(n)) {
out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n]; out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n];
pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices]; pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices];
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
if ((*it)->mTextureCoords[n]) { if ((*it)->mTextureCoords[n]) {
::memcpy(pv2,(*it)->mTextureCoords[n],(*it)->mNumVertices*sizeof(aiVector3D)); ::memcpy(pv2,(*it)->mTextureCoords[n],(*it)->mNumVertices*sizeof(aiVector3D));
} else {
DefaultLogger::get()->warn( "JoinMeshes: UVs expected but input mesh contains no UVs" );
} }
else DefaultLogger::get()->warn("JoinMeshes: UVs expected but input mesh contains no UVs");
pv2 += (*it)->mNumVertices; pv2 += (*it)->mNumVertices;
} }
++n; ++n;
@ -848,11 +851,11 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/,
while ((**begin).HasVertexColors(n)) { while ((**begin).HasVertexColors(n)) {
aiColor4D* pv2 = out->mColors[n] = new aiColor4D[out->mNumVertices]; aiColor4D* pv2 = out->mColors[n] = new aiColor4D[out->mNumVertices];
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
if ((*it)->mColors[n]) { if ((*it)->mColors[n]) {
::memcpy(pv2,(*it)->mColors[n],(*it)->mNumVertices*sizeof(aiColor4D)); ::memcpy(pv2,(*it)->mColors[n],(*it)->mNumVertices*sizeof(aiColor4D));
} else {
DefaultLogger::get()->warn( "JoinMeshes: VCs expected but input mesh contains no VCs" );
} }
else DefaultLogger::get()->warn("JoinMeshes: VCs expected but input mesh contains no VCs");
pv2 += (*it)->mNumVertices; pv2 += (*it)->mNumVertices;
} }
++n; ++n;
@ -1001,7 +1004,12 @@ void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate)
*_dest = new aiScene(); *_dest = new aiScene();
} }
aiScene* dest = *_dest; aiScene* dest = *_dest;
ai_assert(dest); ai_assert(nullptr != dest);
// copy metadata
if ( nullptr != src->mMetaData ) {
dest->mMetaData = new aiMetadata( *src->mMetaData );
}
// copy animations // copy animations
dest->mNumAnimations = src->mNumAnimations; dest->mNumAnimations = src->mNumAnimations;

View File

@ -1076,8 +1076,8 @@ std::string XFileParser::GetNextToken() {
return s; return s;
} }
len = ReadBinDWord(); len = ReadBinDWord();
const int bounds( mEnd - mP ); const int bounds = int( mEnd - mP );
const int iLen( len ); const int iLen = int( len );
if ( iLen < 0 ) { if ( iLen < 0 ) {
return s; return s;
} }

View File

@ -667,27 +667,31 @@ need them at all.
Normally textures used by assets are stored in separate files, however, Normally textures used by assets are stored in separate files, however,
there are file formats embedding their textures directly into the model file. there are file formats embedding their textures directly into the model file.
Such textures are loaded into an aiTexture structure. Such textures are loaded into an aiTexture structure.
For embedded textures, the value of `AI_MATKEY_TEXTURE(textureType, index)` will be `*<index>` where
`<index>` is the index of the texture in aiScene::mTextures. In previous versions, the path from the query for `AI_MATKEY_TEXTURE(textureType, index)` would be
<br> `*<index>` where `<index>` is the index of the texture in aiScene::mTextures. Now this call will
return a file path for embedded textures in FBX files. To test if it is an embdedded texture use
aiScene::GetEmbeddedTexture. If the returned pointer is not null, it is embedded und can be loaded
from the data structure. If it is null, search for a separate file. Other file types still use the
old behaviour.<br>
If your rely on the old behaviour, you can use Assimp::Importer::SetPropertyBool with the key
#AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING to force the old behaviour.
There are two cases: There are two cases:
<br> 1. The texture is NOT compressed. Its color data is directly stored in the aiTexture structure as an
<b>1)</b> The texture is NOT compressed. Its color data is directly stored array of aiTexture::mWidth * aiTexture::mHeight aiTexel structures. Each aiTexel represents a
in the aiTexture structure as an array of aiTexture::mWidth * aiTexture::mHeight aiTexel structures. Each aiTexel represents a pixel (or "texel") of the texture pixel (or "texel") of the texture image. The color data is stored in an unsigned RGBA8888 format,
image. The color data is stored in an unsigned RGBA8888 format, which can be easily used for which can be easily used for both Direct3D and OpenGL (swizzling the order of the color
both Direct3D and OpenGL (swizzling the order of the color components might be necessary). components might be necessary). RGBA8888 has been chosen because it is well-known, easy to use
RGBA8888 has been chosen because it is well-known, easy to use and natively and natively supported by nearly all graphics APIs.
supported by nearly all graphics APIs. 2. This applies if aiTexture::mHeight == 0 is fulfilled. Then, texture is stored in a "compressed"
<br> format such as DDS or PNG. The term "compressed" does not mean that the texture data must
<b>2)</b> This applies if aiTexture::mHeight == 0 is fulfilled. Then, texture is stored in a actually be compressed, however the texture was found in the model file as if it was stored in a
"compressed" format such as DDS or PNG. The term "compressed" does not mean that the separate file on the harddisk. Appropriate decoders (such as libjpeg, libpng, D3DX, DevIL) are
texture data must actually be compressed, however the texture was found in the required to load theses textures. aiTexture::mWidth specifies the size of the texture data in
model file as if it was stored in a separate file on the harddisk. Appropriate bytes, aiTexture::pcData is a pointer to the raw image data and aiTexture::achFormatHint is
decoders (such as libjpeg, libpng, D3DX, DevIL) are required to load theses textures. either zeroed or contains the most common file extension of the embedded texture's format. This
aiTexture::mWidth specifies the size of the texture data in bytes, aiTexture::pcData is value is only set if assimp is able to determine the file format.
a pointer to the raw image data and aiTexture::achFormatHint is either zeroed or
contains the most common file extension of the embedded texture's format. This value is only
set if assimp is able to determine the file format.
*/ */
@ -871,8 +875,11 @@ All material key constants start with 'AI_MATKEY' (it's an ugly macro for histor
<td><tt>TEXTURE(t,n)</tt></td> <td><tt>TEXTURE(t,n)</tt></td>
<td>aiString</td> <td>aiString</td>
<td>n/a</td> <td>n/a</td>
<td>Defines the path of the n'th texture on the stack 't', where 'n' is any value >= 0 and 't' is one of the #aiTextureType enumerated values. Either a filepath or `*<index>`, where `<index>` is the index of an embedded texture in aiScene::mTextures.</td> <td>Defines the path of the n'th texture on the stack 't', where 'n' is any value >= 0 and 't'
<td>See the 'Textures' section above.</td> is one of the #aiTextureType enumerated values. A file path to an external file or an embedded
texture. Use aiScene::GetEmbeddedTexture to test if it is embedded for FBX files, in other cases
embedded textures start with '*' followed by an index into aiScene::mTextures.</td>
<td>See the @ref mat_tex section above. Also see @ref textures for a more information about texture retrieval.</td>
</tr> </tr>
<tr> <tr>

View File

@ -131,9 +131,7 @@ public:
bool detatchStream(LogStream *pStream, bool detatchStream(LogStream *pStream,
unsigned int severity); unsigned int severity);
private: private:
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** @briefPrivate construction for internal use by create(). /** @briefPrivate construction for internal use by create().
* @param severity Logging granularity */ * @param severity Logging granularity */
@ -143,8 +141,6 @@ private:
/** @briefDestructor */ /** @briefDestructor */
~DefaultLogger(); ~DefaultLogger();
private:
/** @brief Logs debug infos, only been written when severity level VERBOSE is set */ /** @brief Logs debug infos, only been written when severity level VERBOSE is set */
void OnDebug(const char* message); void OnDebug(const char* message);

View File

@ -115,8 +115,8 @@ bool IsSpaceOrNewLine( char_t in) {
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out) AI_FORCE_INLINE
{ bool SkipSpaces( const char_t* in, const char_t** out) {
while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) { while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) {
++in; ++in;
} }
@ -126,15 +126,15 @@ AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out)
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool SkipSpaces( const char_t** inout) AI_FORCE_INLINE
{ bool SkipSpaces( const char_t** inout) {
return SkipSpaces<char_t>(*inout,inout); return SkipSpaces<char_t>(*inout,inout);
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out) AI_FORCE_INLINE
{ bool SkipLine( const char_t* in, const char_t** out) {
while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) { while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) {
++in; ++in;
} }
@ -149,15 +149,15 @@ AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out)
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool SkipLine( const char_t** inout) AI_FORCE_INLINE
{ bool SkipLine( const char_t** inout) {
return SkipLine<char_t>(*inout,inout); return SkipLine<char_t>(*inout,inout);
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) AI_FORCE_INLINE
{ bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) {
while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) { while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
++in; ++in;
} }
@ -167,15 +167,15 @@ AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out)
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout) AI_FORCE_INLINE
{ bool SkipSpacesAndLineEnd( const char_t** inout) {
return SkipSpacesAndLineEnd<char_t>(*inout,inout); return SkipSpacesAndLineEnd<char_t>(*inout,inout);
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) AI_FORCE_INLINE
{ bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) {
if( ( char_t )'\0' == *buffer ) { if( ( char_t )'\0' == *buffer ) {
return false; return false;
} }
@ -203,7 +203,8 @@ AI_FORCE_INLINE bool IsNumeric( char_t in)
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len) AI_FORCE_INLINE
bool TokenMatch(char_t*& in, const char* token, unsigned int len)
{ {
if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) { if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
if (in[len] != '\0') { if (in[len] != '\0') {
@ -223,26 +224,32 @@ AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len
* @param token Token to check for * @param token Token to check for
* @param len Number of characters to check * @param len Number of characters to check
*/ */
AI_FORCE_INLINE bool TokenMatchI(const char*& in, const char* token, unsigned int len) AI_FORCE_INLINE
{ bool TokenMatchI(const char*& in, const char* token, unsigned int len) {
if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) { if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
in += len+1; in += len+1;
return true; return true;
} }
return false; return false;
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
AI_FORCE_INLINE void SkipToken(const char*& in) AI_FORCE_INLINE
{ void SkipToken(const char*& in) {
SkipSpaces(&in); SkipSpaces(&in);
while (!IsSpaceOrNewLine(*in))++in; while ( !IsSpaceOrNewLine( *in ) ) {
++in;
}
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
AI_FORCE_INLINE std::string GetNextToken(const char*& in) AI_FORCE_INLINE
{ std::string GetNextToken(const char*& in) {
SkipSpacesAndLineEnd(&in); SkipSpacesAndLineEnd(&in);
const char* cur = in; const char* cur = in;
while (!IsSpaceOrNewLine(*in))++in; while ( !IsSpaceOrNewLine( *in ) ) {
++in;
}
return std::string(cur,(size_t)(in-cur)); return std::string(cur,(size_t)(in-cur));
} }

View File

@ -104,7 +104,7 @@ public:
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
~StreamWriter() { ~StreamWriter() {
stream->Write(&buffer[0], 1, buffer.size()); stream->Write(buffer.data(), 1, buffer.size());
stream->Flush(); stream->Flush();
} }
@ -114,7 +114,7 @@ public:
/** Flush the contents of the internal buffer, and the output IOStream */ /** Flush the contents of the internal buffer, and the output IOStream */
void Flush() void Flush()
{ {
stream->Write(&buffer[0], 1, buffer.size()); stream->Write(buffer.data(), 1, buffer.size());
stream->Flush(); stream->Flush();
buffer.clear(); buffer.clear();
cursor = 0; cursor = 0;

View File

@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_STRING_WORKERS_H #define INCLUDED_AI_STRING_WORKERS_H
#include <assimp/ai_assert.h> #include <assimp/ai_assert.h>
#include <assimp/defs.h>
#include "StringComparison.h" #include "StringComparison.h"
#include <string.h> #include <string.h>
@ -72,8 +73,8 @@ namespace Assimp {
* @param number Number to be written * @param number Number to be written
* @return Length of the output string, excluding the '\0' * @return Length of the output string, excluding the '\0'
*/ */
inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) AI_FORCE_INLINE
{ unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) {
ai_assert(NULL != out); ai_assert(NULL != out);
// write the unary minus to indicate we have a negative number // write the unary minus to indicate we have a negative number
@ -91,7 +92,7 @@ inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number)
const unsigned int digit = number / cur; const unsigned int digit = number / cur;
if (mustPrint || digit > 0 || 1 == cur) { if (mustPrint || digit > 0 || 1 == cur) {
// print all future zeroes from now // print all future zeroe's from now
mustPrint = true; mustPrint = true;
*out++ = '0'+static_cast<char>(digit); *out++ = '0'+static_cast<char>(digit);
@ -116,8 +117,8 @@ inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number)
* size of the array automatically. * size of the array automatically.
*/ */
template <size_t length> template <size_t length>
inline unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) AI_FORCE_INLINE
{ unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) {
return ASSIMP_itoa10(out,length,number); return ASSIMP_itoa10(out,length,number);
} }
@ -132,9 +133,10 @@ inline unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number)
* @param s2 Second input string * @param s2 Second input string
* @return 0 if the given strings are identical * @return 0 if the given strings are identical
*/ */
inline int ASSIMP_stricmp(const char *s1, const char *s2) AI_FORCE_INLINE
{ int ASSIMP_stricmp(const char *s1, const char *s2) {
ai_assert(NULL != s1 && NULL != s2); ai_assert( NULL != s1 );
ai_assert( NULL != s2 );
#if (defined _MSC_VER) #if (defined _MSC_VER)
@ -161,8 +163,8 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
* @param b Second string * @param b Second string
* @return 0 if a == b * @return 0 if a == b
*/ */
inline int ASSIMP_stricmp(const std::string& a, const std::string& b) AI_FORCE_INLINE
{ int ASSIMP_stricmp(const std::string& a, const std::string& b) {
int i = (int)b.length()-(int)a.length(); int i = (int)b.length()-(int)a.length();
return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str())); return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str()));
} }
@ -179,10 +181,13 @@ inline int ASSIMP_stricmp(const std::string& a, const std::string& b)
* @param n Macimum number of characters to compare * @param n Macimum number of characters to compare
* @return 0 if the given strings are identical * @return 0 if the given strings are identical
*/ */
inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) AI_FORCE_INLINE
{ int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) {
ai_assert(NULL != s1 && NULL != s2); ai_assert( NULL != s1 );
if (!n)return 0; ai_assert( NULL != s2 );
if ( !n ) {
return 0;
}
#if (defined _MSC_VER) #if (defined _MSC_VER)
@ -213,14 +218,16 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
* *
* todo: move somewhere where it fits better in than here * todo: move somewhere where it fits better in than here
*/ */
inline unsigned int integer_pow (unsigned int base, unsigned int power) AI_FORCE_INLINE
{ unsigned int integer_pow( unsigned int base, unsigned int power ) {
unsigned int res = 1; unsigned int res = 1;
for (unsigned int i = 0; i < power;++i) for ( unsigned int i = 0; i < power; ++i ) {
res *= base; res *= base;
}
return res; return res;
} }
} // end of namespace } // end of namespace
#endif // ! AI_STRINGCOMPARISON_H_INC #endif // ! AI_STRINGCOMPARISON_H_INC

View File

@ -42,6 +42,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_STRINGUTILS_H #ifndef INCLUDED_AI_STRINGUTILS_H
#define INCLUDED_AI_STRINGUTILS_H #define INCLUDED_AI_STRINGUTILS_H
#include <assimp/defs.h>
#include <sstream> #include <sstream>
#include <stdarg.h> #include <stdarg.h>
#include <cstdlib> #include <cstdlib>
@ -55,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/// @return The number of written characters if the buffer size was big enough. If an encoding error occurs, a negative number is returned. /// @return The number of written characters if the buffer size was big enough. If an encoding error occurs, a negative number is returned.
#if defined(_MSC_VER) && _MSC_VER < 1900 #if defined(_MSC_VER) && _MSC_VER < 1900
inline AI_FORCE_INLINE
int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) { int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
int count(-1); int count(-1);
if (0 != size) { if (0 != size) {
@ -68,7 +70,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
return count; return count;
} }
inline AI_FORCE_INLINE
int ai_snprintf(char *outBuf, size_t size, const char *format, ...) { int ai_snprintf(char *outBuf, size_t size, const char *format, ...) {
int count; int count;
va_list ap; va_list ap;
@ -89,7 +91,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/// @param value The value to write into the std::string. /// @param value The value to write into the std::string.
/// @return The value as a std::string /// @return The value as a std::string
template <typename T> template <typename T>
inline AI_FORCE_INLINE
std::string to_string( T value ) { std::string to_string( T value ) {
std::ostringstream os; std::ostringstream os;
os << value; os << value;
@ -102,7 +104,7 @@ std::string to_string( T value ) {
/// @param begin The first character of the string. /// @param begin The first character of the string.
/// @param end The last character /// @param end The last character
/// @return The float value, 0.0f in cas of an error. /// @return The float value, 0.0f in cas of an error.
inline AI_FORCE_INLINE
float ai_strtof( const char *begin, const char *end ) { float ai_strtof( const char *begin, const char *end ) {
if ( nullptr == begin ) { if ( nullptr == begin ) {
return 0.0f; return 0.0f;
@ -124,7 +126,7 @@ float ai_strtof( const char *begin, const char *end ) {
/// @param toConvert Value to convert /// @param toConvert Value to convert
/// @return The hexadecimal string, is empty in case of an error. /// @return The hexadecimal string, is empty in case of an error.
template<class T> template<class T>
inline AI_FORCE_INLINE
std::string DecimalToHexa( T toConvert ) { std::string DecimalToHexa( T toConvert ) {
std::string result; std::string result;
std::stringstream ss; std::stringstream ss;

View File

@ -67,6 +67,7 @@ typedef enum aiMetadataType {
AI_DOUBLE = 4, AI_DOUBLE = 4,
AI_AISTRING = 5, AI_AISTRING = 5,
AI_AIVECTOR3D = 6, AI_AIVECTOR3D = 6,
AI_META_MAX = 7,
#ifndef SWIG #ifndef SWIG
FORCE_32BIT = INT_MAX FORCE_32BIT = INT_MAX
@ -130,42 +131,103 @@ struct aiMetadata {
*/ */
aiMetadata() aiMetadata()
: mNumProperties(0) : mNumProperties(0)
, mKeys(NULL) , mKeys(nullptr)
, mValues(NULL) { , mValues(nullptr) {
// empty // empty
} }
aiMetadata( const aiMetadata &rhs )
: mNumProperties( rhs.mNumProperties )
, mKeys( nullptr )
, mValues( nullptr ) {
mKeys = new aiString[ mNumProperties ];
for ( unsigned int i = 0; i < mNumProperties; ++i ) {
mKeys[ i ] = rhs.mKeys[ i ];
}
mValues = new aiMetadataEntry[ mNumProperties ];
for ( unsigned int i = 0; i < mNumProperties; ++i ) {
mValues[ i ].mType = rhs.mValues[ i ].mType;
switch ( rhs.mValues[ i ].mType ) {
case AI_BOOL:
mValues[ i ].mData = new bool( rhs.mValues[i].mData );
break;
case AI_INT32: {
int32_t v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( int32_t ) );
mValues[ i ].mData = new int32_t( v );
}
break;
case AI_UINT64: {
uint64_t v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( uint64_t ) );
mValues[ i ].mData = new uint64_t( v );
}
break;
case AI_FLOAT: {
float v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( float ) );
mValues[ i ].mData = new float( v );
}
break;
case AI_DOUBLE: {
double v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( double ) );
mValues[ i ].mData = new double( v );
}
break;
case AI_AISTRING: {
aiString v;
rhs.Get<aiString>( mKeys[ i ], v );
mValues[ i ].mData = new aiString( v );
}
break;
case AI_AIVECTOR3D: {
aiVector3D v;
rhs.Get<aiVector3D>( mKeys[ i ], v );
mValues[ i ].mData = new aiVector3D( v );
}
break;
#ifndef SWIG
case FORCE_32BIT:
#endif
default:
break;
}
}
}
/** /**
* @brief The destructor. * @brief The destructor.
*/ */
~aiMetadata() { ~aiMetadata() {
delete [] mKeys; delete [] mKeys;
mKeys = NULL; mKeys = nullptr;
if (mValues) { if (mValues) {
// Delete each metadata entry // Delete each metadata entry
for (unsigned i=0; i<mNumProperties; ++i) { for (unsigned i=0; i<mNumProperties; ++i) {
void* data = mValues[i].mData; void* data = mValues[i].mData;
switch (mValues[i].mType) { switch (mValues[i].mType) {
case AI_BOOL: case AI_BOOL:
delete static_cast<bool*>(data); delete static_cast< bool* >( data );
break; break;
case AI_INT32: case AI_INT32:
delete static_cast<int32_t*>(data); delete static_cast< int32_t* >( data );
break; break;
case AI_UINT64: case AI_UINT64:
delete static_cast<uint64_t*>(data); delete static_cast< uint64_t* >( data );
break; break;
case AI_FLOAT: case AI_FLOAT:
delete static_cast<float*>(data); delete static_cast< float* >( data );
break; break;
case AI_DOUBLE: case AI_DOUBLE:
delete static_cast<double*>(data); delete static_cast< double* >( data );
break; break;
case AI_AISTRING: case AI_AISTRING:
delete static_cast<aiString*>(data); delete static_cast< aiString* >( data );
break; break;
case AI_AIVECTOR3D: case AI_AIVECTOR3D:
delete static_cast<aiVector3D*>(data); delete static_cast< aiVector3D* >( data );
break; break;
#ifndef SWIG #ifndef SWIG
case FORCE_32BIT: case FORCE_32BIT:
@ -177,7 +239,7 @@ struct aiMetadata {
// Delete the metadata array // Delete the metadata array
delete [] mValues; delete [] mValues;
mValues = NULL; mValues = nullptr;
} }
} }
@ -208,8 +270,8 @@ struct aiMetadata {
} }
template<typename T> template<typename T>
inline void Add(const std::string& key, const T& value) inline
{ void Add(const std::string& key, const T& value) {
aiString* new_keys = new aiString[mNumProperties + 1]; aiString* new_keys = new aiString[mNumProperties + 1];
aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1]; aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1];
@ -256,7 +318,7 @@ struct aiMetadata {
template<typename T> template<typename T>
inline inline
bool Get( unsigned index, T& value ) { bool Get( unsigned index, T& value ) const {
// In range assertion // In range assertion
if ( index >= mNumProperties ) { if ( index >= mNumProperties ) {
return false; return false;
@ -277,7 +339,7 @@ struct aiMetadata {
template<typename T> template<typename T>
inline inline
bool Get( const aiString& key, T& value ) { bool Get( const aiString& key, T& value ) const {
// Search for the given key // Search for the given key
for ( unsigned int i = 0; i < mNumProperties; ++i ) { for ( unsigned int i = 0; i < mNumProperties; ++i ) {
if ( mKeys[ i ] == key ) { if ( mKeys[ i ] == key ) {
@ -288,7 +350,8 @@ struct aiMetadata {
} }
template<typename T> template<typename T>
inline bool Get( const std::string& key, T& value ) { inline
bool Get( const std::string& key, T& value ) const {
return Get(aiString(key), value); return Get(aiString(key), value);
} }
@ -297,7 +360,8 @@ struct aiMetadata {
/// \param [out] pKey - pointer to the key value. /// \param [out] pKey - pointer to the key value.
/// \param [out] pEntry - pointer to the entry: type and value. /// \param [out] pEntry - pointer to the entry: type and value.
/// \return false - if pIndex is out of range, else - true. /// \return false - if pIndex is out of range, else - true.
inline bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) { inline
bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) const {
if ( index >= mNumProperties ) { if ( index >= mNumProperties ) {
return false; return false;
} }

View File

@ -181,3 +181,74 @@ TEST_F( utMetadata, get_set_aiVector3D_Test ) {
EXPECT_TRUE( success ); EXPECT_TRUE( success );
} }
TEST_F( utMetadata, copy_test ) {
m_data = aiMetadata::Alloc( AI_META_MAX );
bool bv = true;
m_data->Set( 0, "bool", bv );
int32_t i32v = -10;
m_data->Set( 1, "int32", i32v );
uint64_t ui64v = static_cast<uint64_t>( 10 );
m_data->Set( 2, "uint64", ui64v );
float fv = 1.0f;
m_data->Set( 3, "float", fv );
double dv = 2.0;
m_data->Set( 4, "double", dv );
const aiString strVal( std::string( "test" ) );
m_data->Set( 5, "aiString", strVal );
aiVector3D vecVal( 1, 2, 3 );
m_data->Set( 6, "aiVector3D", vecVal );
aiMetadata copy( *m_data );
EXPECT_EQ( 7, copy.mNumProperties );
// bool test
{
bool v;
EXPECT_TRUE( copy.Get( "bool", v ) );
EXPECT_EQ( bv, v );
}
// int32_t test
{
int32_t v;
bool ok = copy.Get( "int32", v );
EXPECT_TRUE( ok );
EXPECT_EQ( i32v, v );
}
// uint64_t test
{
uint64_t v;
bool ok = copy.Get( "uint64", v );
EXPECT_TRUE( ok );
EXPECT_EQ( ui64v, v );
}
// float test
{
float v;
EXPECT_TRUE( copy.Get( "float", v ) );
EXPECT_EQ( fv, v );
}
// double test
{
double v;
EXPECT_TRUE( copy.Get( "double", v ) );
EXPECT_EQ( dv, v );
}
// bool test
{
aiString v;
EXPECT_TRUE( copy.Get( "aiString", v ) );
EXPECT_EQ( strVal, v );
}
// bool test
{
aiVector3D v;
EXPECT_TRUE( copy.Get( "aiVector3D", v ) );
EXPECT_EQ( vecVal, v );
}
}