diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index 633f96ad9..204e6f77b 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -117,6 +117,7 @@ bool D3MFExporter::exportArchive( const char *file ) { if ( nullptr == m_zipArchive ) { return false; } + ok |= exportContentTypes(); ok |= export3DModel(); ok |= exportRelations(); @@ -181,6 +182,8 @@ bool D3MFExporter::export3DModel() { mModelOutput << "<" << XmlTag::resources << ">"; mModelOutput << std::endl; + writeMetaData(); + writeBaseMaterials(); writeObjects(); @@ -209,6 +212,29 @@ void D3MFExporter::writeHeader() { 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 << "" << std::endl; + } +} + void D3MFExporter::writeBaseMaterials() { mModelOutput << "\n"; std::string strName, hexDiffuseColor , tmp; diff --git a/code/D3MFExporter.h b/code/D3MFExporter.h index b553e0ab5..110862b99 100644 --- a/code/D3MFExporter.h +++ b/code/D3MFExporter.h @@ -76,6 +76,7 @@ public: protected: void writeHeader(); + void writeMetaData(); void writeBaseMaterials(); void writeObjects(); void writeMesh( aiMesh *mesh ); diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index dc99f007e..2732c73c4 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -103,6 +103,8 @@ public: // } else if ( nodeName == D3MF::XmlTag::basematerials ) { ReadBaseMaterials(); + } else if ( nodeName == D3MF::XmlTag::meta ) { + ReadMetadata(); } } @@ -110,19 +112,31 @@ public: 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( mMeshes.size()); scene->mMeshes = new aiMesh*[scene->mNumMeshes](); - std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); + // import the materials scene->mNumMaterials = static_cast( mMatArray.size() ); if ( 0 != scene->mNumMaterials ) { scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ]; std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials ); } + + // create the scenegraph scene->mRootNode->mNumChildren = static_cast(children.size()); scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); - std::copy(children.begin(), children.end(), scene->mRootNode->mChildren); } @@ -181,6 +195,21 @@ private: 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) { std::vector vertices; while(ReadToEndElement(D3MF::XmlTag::vertices)) { @@ -254,7 +283,7 @@ private: MatIdArray = it->second; } } - MatIdArray.push_back( newMatIdx ); + MatIdArray.push_back( static_cast( newMatIdx ) ); mMatId2MatArray[ mActiveMatGroup ] = MatIdArray; } @@ -372,8 +401,12 @@ private: return false; } - private: + struct MetaEntry { + std::string name; + std::string value; + }; + std::vector mMetaData; std::vector mMeshes; MatArray mMatArray; unsigned int mActiveMatGroup; diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 5e50be8bd..36c14e41d 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -76,7 +76,7 @@ bool DefaultIOSystem::Exists( const char* pFile) const #ifdef _WIN32 wchar_t fileName16[PATHLIMIT]; - bool isUnicode = IsTextUnicode(pFile, strlen(pFile), NULL); + bool isUnicode = IsTextUnicode(pFile, static_cast(strlen(pFile)), NULL); if (isUnicode) { MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT); @@ -110,7 +110,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) FILE* file; #ifdef _WIN32 wchar_t fileName16[PATHLIMIT]; - bool isUnicode = IsTextUnicode(strFile, strlen(strFile), NULL ); + bool isUnicode = IsTextUnicode(strFile, static_cast(strlen(strFile)), NULL ); if (isUnicode) { MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT); std::string mode8(strMode); @@ -158,7 +158,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out) { ai_assert(in && _out); #if defined( _MSC_VER ) || defined( __MINGW32__ ) - bool isUnicode = IsTextUnicode(in, strlen(in), NULL); + bool isUnicode = IsTextUnicode(in, static_cast(strlen(in)), NULL); if (isUnicode) { wchar_t out16[PATHLIMIT]; wchar_t in16[PATHLIMIT]; diff --git a/code/EmbedTexturesProcess.cpp b/code/EmbedTexturesProcess.cpp index addfb9746..076339468 100644 --- a/code/EmbedTexturesProcess.cpp +++ b/code/EmbedTexturesProcess.cpp @@ -99,22 +99,22 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) { } bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { - uint32_t imageSize = 0; - std::string imagePath = path; + std::streampos imageSize = 0; + std::string imagePath = path; // Test path directly 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."); // Test path in root path imagePath = mRootPath + path; 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 imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u); 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 + "."); return false; } @@ -134,7 +134,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { // Add the new texture auto pTexture = new aiTexture(); pTexture->mHeight = 0; // Means that this is still compressed - pTexture->mWidth = imageSize; + pTexture->mWidth = static_cast(imageSize); pTexture->pcData = imageContent; auto extension = path.substr(path.find_last_of('.') + 1u); diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 4951c70ef..49523e658 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -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(); // when they create scenes from scratch, users will likely create them not in verbose diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 537a4f558..f3a908dd4 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -704,7 +704,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] ); aiVector3D GeometricScalingInverse = GeometricScaling; 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 ) { GeometricScalingInverse[i] = 1.0f / GeometricScaling[i]; } else { @@ -1887,11 +1887,11 @@ void Converter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyT // TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes: const aiColor3D& Transparent = GetColorPropertyFactored( props, "TransparentColor", "TransparencyFactor", ok ); - float CalculatedOpacity = 1.0; + float CalculatedOpacity = 1.0f; if ( ok ) { out_mat->AddProperty( &Transparent, 1, AI_MATKEY_COLOR_TRANSPARENT ); // 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. diff --git a/code/FBXExportNode.cpp b/code/FBXExportNode.cpp index f218f068d..596901989 100644 --- a/code/FBXExportNode.cpp +++ b/code/FBXExportNode.cpp @@ -182,7 +182,7 @@ void FBX::Node::Begin(Assimp::StreamWriterLE &s) s.PutU4(0); // total property section length // 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 // property data comes after here @@ -217,8 +217,8 @@ void FBX::Node::EndProperties( ai_assert(pos > property_start); size_t property_section_size = pos - property_start; s.Seek(start_pos + 4); - s.PutU4(num_properties); - s.PutU4(property_section_size); + s.PutU4(uint32_t(num_properties)); + s.PutU4(uint32_t(property_section_size)); s.Seek(pos); } @@ -232,7 +232,7 @@ void FBX::Node::End( // now go back and write initial pos this->end_pos = s.Tell(); s.Seek(start_pos); - s.PutU4(end_pos); + s.PutU4(uint32_t(end_pos)); s.Seek(end_pos); } @@ -251,9 +251,9 @@ void FBX::Node::WritePropertyNode( Node node(name); node.Begin(s); 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(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); } node.EndProperties(s, 1); node.End(s, false); @@ -271,9 +271,9 @@ void FBX::Node::WritePropertyNode( Node node(name); node.Begin(s); 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(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); } node.EndProperties(s, 1); node.End(s, false); diff --git a/code/FBXExportProperty.cpp b/code/FBXExportProperty.cpp index 1beaa4d27..975e9a09a 100644 --- a/code/FBXExportProperty.cpp +++ b/code/FBXExportProperty.cpp @@ -127,8 +127,8 @@ FBX::Property::Property(const aiMatrix4x4& vm) : type('d'), data(8*16) { double* d = reinterpret_cast(data.data()); - for (size_t c = 0; c < 4; ++c) { - for (size_t r = 0; r < 4; ++r) { + for (unsigned int c = 0; c < 4; ++c) { + for (unsigned int r = 0; r < 4; ++r) { d[4*c+r] = vm[r][c]; } } @@ -164,15 +164,15 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s) case 'L': s.PutI8(*(reinterpret_cast(data.data()))); return; case 'S': 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]); } return; case 'i': 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) // TODO: compress if large? - s.PutU4(data.size()); // data size + s.PutU4(uint32_t(data.size())); // data size d = data.data(); for (size_t i = 0; i < N; ++i) { s.PutI4((reinterpret_cast(d))[i]); @@ -180,10 +180,10 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s) return; case 'd': 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) // TODO: compress if large? - s.PutU4(data.size()); // data size + s.PutU4(uint32_t(data.size())); // data size d = data.data(); for (size_t i = 0; i < N; ++i) { s.PutF8((reinterpret_cast(d))[i]); diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index a2e6024ed..9ba5c0333 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -460,7 +460,7 @@ size_t count_images(const aiScene* scene) { ){ const aiTextureType textype = static_cast(tt); 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); images.insert(std::string(texpath.C_Str())); } @@ -593,7 +593,7 @@ void FBXExporter::WriteDefinitions () // Model / FbxNode // <~~ 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) { n = FBX::Node("ObjectType", Property("Model")); n.AddChild("Count", count); @@ -763,7 +763,7 @@ void FBXExporter::WriteDefinitions () // Video / FbxVideo // one for each image file. - count = count_images(mScene); + count = int32_t(count_images(mScene)); if (count) { n = FBX::Node("ObjectType", Property("Video")); n.AddChild("Count", count); @@ -792,7 +792,7 @@ void FBXExporter::WriteDefinitions () // Texture / FbxFileTexture // <~~ aiTexture - count = count_textures(mScene); + count = int32_t(count_textures(mScene)); if (count) { n = FBX::Node("ObjectType", Property("Texture")); n.AddChild("Count", count); @@ -848,7 +848,7 @@ void FBXExporter::WriteDefinitions () } // Deformer - count = count_deformers(mScene); + count = int32_t(count_deformers(mScene)); if (count) { n = FBX::Node("ObjectType", Property("Deformer")); n.AddChild("Count", count); @@ -943,7 +943,7 @@ void FBXExporter::WriteObjects () std::vector vertex_indices; // map of vertex value to its index in the data vector std::map index_by_vertex_value; - size_t index = 0; + int32_t index = 0; for (size_t vi = 0; vi < m->mNumVertices; ++vi) { aiVector3D vtx = m->mVertices[vi]; auto elem = index_by_vertex_value.find(vtx); @@ -955,7 +955,7 @@ void FBXExporter::WriteObjects () flattened_vertices.push_back(vtx[2]); ++index; } else { - vertex_indices.push_back(elem->second); + vertex_indices.push_back(int32_t(elem->second)); } } FBX::Node::WritePropertyNode( @@ -1052,7 +1052,7 @@ void FBXExporter::WriteObjects () std::vector uv_data; std::vector uv_indices; std::map index_by_uv; - size_t index = 0; + int32_t index = 0; for (size_t fi = 0; fi < m->mNumFaces; ++fi) { const aiFace &f = m->mFaces[fi]; for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) { @@ -1062,7 +1062,7 @@ void FBXExporter::WriteObjects () if (elem == index_by_uv.end()) { index_by_uv[uv] = 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]); } ++index; @@ -1208,13 +1208,13 @@ void FBXExporter::WriteObjects () // and usualy are completely ignored when loading. // One notable exception is the "Opacity" property, // 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); 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); 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); p.AddP70vector("Diffuse", c.r, c.g, c.b); // 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. // It might make more sense to use TransparencyFactor, // 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) { - 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); p.AddP70double("Opacity", f); if (phong) { // 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); - f = 1.0; + f = 1.0f; m->Get(AI_MATKEY_SHININESS_STRENGTH, f); p.AddP70vector("Specular", f*c.r, f*c.g, f*c.b); - f = 20.0; + f = 20.0f; m->Get(AI_MATKEY_SHININESS, f); p.AddP70double("Shininess", f); // Legacy "Reflectivity" is F*F*((R+G+B)/3), // where F is the proportion of light reflected (AKA reflectivity), // and RGB is the reflective colour of the material. // 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); - 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); 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(tt); const size_t texcount = mat->GetTextureCount(textype); 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(); auto elem = uid_by_image.find(texstring); if (elem == uid_by_image.end()) { @@ -1591,7 +1591,7 @@ void FBXExporter::WriteObjects () std::vector vertex_indices; // map of vertex value to its index in the data vector std::map index_by_vertex_value; - size_t index = 0; + int32_t index = 0; for (size_t vi = 0; vi < m->mNumVertices; ++vi) { aiVector3D vtx = m->mVertices[vi]; auto elem = index_by_vertex_value.find(vtx); @@ -1600,7 +1600,7 @@ void FBXExporter::WriteObjects () index_by_vertex_value[vtx] = index; ++index; } 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. // All we can do is assume no instancing, // 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); // 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. // 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; if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) { not_in_bind_pose.insert(b); @@ -2002,7 +2002,7 @@ void FBXExporter::WriteModelNodes( transform_chain.emplace_back(elem->first, t); break; case 'r': // rotation - r *= DEG; + r *= float(DEG); transform_chain.emplace_back(elem->first, r); break; case 's': // scale diff --git a/code/SceneCombiner.cpp b/code/SceneCombiner.cpp index 240dbbb12..589291131 100644 --- a/code/SceneCombiner.cpp +++ b/code/SceneCombiner.cpp @@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include "time.h" #include @@ -1003,7 +1004,12 @@ void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate) *_dest = new aiScene(); } aiScene* dest = *_dest; - ai_assert(dest); + ai_assert(nullptr != dest); + + // copy metadata + if ( nullptr != src->mMetaData ) { + dest->mMetaData = new aiMetadata( *src->mMetaData ); + } // copy animations dest->mNumAnimations = src->mNumAnimations; diff --git a/code/XFileParser.cpp b/code/XFileParser.cpp index bda59ba59..4dd2c990b 100644 --- a/code/XFileParser.cpp +++ b/code/XFileParser.cpp @@ -1076,8 +1076,8 @@ std::string XFileParser::GetNextToken() { return s; } len = ReadBinDWord(); - const int bounds( mEnd - mP ); - const int iLen( len ); + const int bounds = int( mEnd - mP ); + const int iLen = int( len ); if ( iLen < 0 ) { return s; } diff --git a/include/assimp/StreamWriter.h b/include/assimp/StreamWriter.h index e955a7255..6f492df90 100644 --- a/include/assimp/StreamWriter.h +++ b/include/assimp/StreamWriter.h @@ -104,7 +104,7 @@ public: // --------------------------------------------------------------------- ~StreamWriter() { - stream->Write(&buffer[0], 1, buffer.size()); + stream->Write(buffer.data(), 1, buffer.size()); stream->Flush(); } @@ -114,7 +114,7 @@ public: /** Flush the contents of the internal buffer, and the output IOStream */ void Flush() { - stream->Write(&buffer[0], 1, buffer.size()); + stream->Write(buffer.data(), 1, buffer.size()); stream->Flush(); buffer.clear(); cursor = 0; diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 2dba61abc..70a604de9 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -67,6 +67,7 @@ typedef enum aiMetadataType { AI_DOUBLE = 4, AI_AISTRING = 5, AI_AIVECTOR3D = 6, + AI_META_MAX = 7, #ifndef SWIG FORCE_32BIT = INT_MAX @@ -130,42 +131,103 @@ struct aiMetadata { */ aiMetadata() : mNumProperties(0) - , mKeys(NULL) - , mValues(NULL) { + , mKeys(nullptr) + , mValues(nullptr) { // 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( mKeys[ i ], v ); + mValues[ i ].mData = new aiString( v ); + } + break; + case AI_AIVECTOR3D: { + aiVector3D v; + rhs.Get( mKeys[ i ], v ); + mValues[ i ].mData = new aiVector3D( v ); + } + break; +#ifndef SWIG + case FORCE_32BIT: +#endif + default: + break; + } + + } + } + /** * @brief The destructor. */ ~aiMetadata() { delete [] mKeys; - mKeys = NULL; + mKeys = nullptr; if (mValues) { // Delete each metadata entry for (unsigned i=0; i(data); + delete static_cast< bool* >( data ); break; case AI_INT32: - delete static_cast(data); + delete static_cast< int32_t* >( data ); break; case AI_UINT64: - delete static_cast(data); + delete static_cast< uint64_t* >( data ); break; case AI_FLOAT: - delete static_cast(data); + delete static_cast< float* >( data ); break; case AI_DOUBLE: - delete static_cast(data); + delete static_cast< double* >( data ); break; case AI_AISTRING: - delete static_cast(data); + delete static_cast< aiString* >( data ); break; case AI_AIVECTOR3D: - delete static_cast(data); + delete static_cast< aiVector3D* >( data ); break; #ifndef SWIG case FORCE_32BIT: @@ -177,7 +239,7 @@ struct aiMetadata { // Delete the metadata array delete [] mValues; - mValues = NULL; + mValues = nullptr; } } @@ -208,8 +270,8 @@ struct aiMetadata { } template - 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]; aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1]; @@ -256,7 +318,7 @@ struct aiMetadata { template inline - bool Get( unsigned index, T& value ) { + bool Get( unsigned index, T& value ) const { // In range assertion if ( index >= mNumProperties ) { return false; @@ -277,7 +339,7 @@ struct aiMetadata { template inline - bool Get( const aiString& key, T& value ) { + bool Get( const aiString& key, T& value ) const { // Search for the given key for ( unsigned int i = 0; i < mNumProperties; ++i ) { if ( mKeys[ i ] == key ) { @@ -288,7 +350,8 @@ struct aiMetadata { } template - inline bool Get( const std::string& key, T& value ) { + inline + bool Get( const std::string& key, T& value ) const { return Get(aiString(key), value); } @@ -297,7 +360,8 @@ struct aiMetadata { /// \param [out] pKey - pointer to the key value. /// \param [out] pEntry - pointer to the entry: type and value. /// \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 ) { return false; } diff --git a/test/unit/utMetadata.cpp b/test/unit/utMetadata.cpp index 7fda143b7..42f632bce 100644 --- a/test/unit/utMetadata.cpp +++ b/test/unit/utMetadata.cpp @@ -181,3 +181,74 @@ TEST_F( utMetadata, get_set_aiVector3D_Test ) { 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( 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 ); + } +}