From 1c577f66f7f6afa4d46508e1ba1ac4fdfa765ade Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 7 Sep 2018 19:14:52 +0200 Subject: [PATCH 1/7] Collada-Exporter: fix some minor findings. --- code/ColladaExporter.cpp | 388 +++++++++++++++++++-------------------- 1 file changed, 190 insertions(+), 198 deletions(-) diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 96421a532..82a755c58 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -62,15 +62,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; - -namespace Assimp -{ +namespace Assimp { // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp -void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) -{ +void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { std::string path = DefaultIOSystem::absolutePath(std::string(pFile)); std::string file = DefaultIOSystem::completeBaseName(std::string(pFile)); @@ -83,7 +79,7 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p // we're still here - export successfully completed. Write result to the given IOSYstem std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); - if(outfile == NULL) { + if(outfile == nullptr) { throw DeadlyExportError("could not open output .dae file: " + std::string(pFile)); } @@ -93,19 +89,20 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p } // end of namespace Assimp - +using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor for a specific scene to export -ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file) -{ +ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) +: mIOSystem( pIOSystem ) +, mPath( path ) +, mFile( file ) +, mScene(pScene) +, mSceneOwned(false) { // make sure that all formatting happens using the standard, C locale and not the user's current locale mOutput.imbue( std::locale("C") ); mOutput.precision(16); - mScene = pScene; - mSceneOwned = false; - // set up strings endstr = "\n"; @@ -115,17 +112,16 @@ ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, co // ------------------------------------------------------------------------------------------------ // Destructor -ColladaExporter::~ColladaExporter() -{ +ColladaExporter::~ColladaExporter() { if(mSceneOwned) { delete mScene; + mScene = nullptr; } } // ------------------------------------------------------------------------------------------------ // Starts writing the contents -void ColladaExporter::WriteFile() -{ +void ColladaExporter::WriteFile() { // write the DTD mOutput << "" << endstr; // COLLADA element start @@ -158,8 +154,7 @@ void ColladaExporter::WriteFile() // ------------------------------------------------------------------------------------------------ // Writes the asset header -void ColladaExporter::WriteHeader() -{ +void ColladaExporter::WriteHeader() { static const ai_real epsilon = ai_real( 0.00001 ); static const aiQuaternion x_rot(aiMatrix3x3( 0, -1, 0, @@ -269,54 +264,56 @@ void ColladaExporter::WriteTextures() { static const unsigned int buffer_size = 1024; char str[buffer_size]; - if(mScene->HasTextures()) { - for(unsigned int i = 0; i < mScene->mNumTextures; i++) { - // It would be great to be able to create a directory in portable standard C++, but it's not the case, - // so we just write the textures in the current directory. + if (!mScene->HasTextures()) { + return; + } - aiTexture* texture = mScene->mTextures[i]; + for(unsigned int i = 0; i < mScene->mNumTextures; i++) { + // It would be great to be able to create a directory in portable standard C++, but it's not the case, + // so we just write the textures in the current directory. - ASSIMP_itoa10(str, buffer_size, i + 1); + aiTexture* texture = mScene->mTextures[i]; - std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint); + ASSIMP_itoa10(str, buffer_size, i + 1); - std::unique_ptr outfile(mIOSystem->Open(mPath + name, "wb")); - if(outfile == NULL) { - throw DeadlyExportError("could not open output texture file: " + mPath + name); - } + std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint); - if(texture->mHeight == 0) { - outfile->Write((void*) texture->pcData, texture->mWidth, 1); - } else { - Bitmap::Save(texture, outfile.get()); - } - - outfile->Flush(); - - textures.insert(std::make_pair(i, name)); + std::unique_ptr outfile(mIOSystem->Open(mPath + name, "wb")); + if(outfile == NULL) { + throw DeadlyExportError("could not open output texture file: " + mPath + name); } + + if(texture->mHeight == 0) { + outfile->Write((void*) texture->pcData, texture->mWidth, 1); + } else { + Bitmap::Save(texture, outfile.get()); + } + + outfile->Flush(); + + textures.insert(std::make_pair(i, name)); } } // ------------------------------------------------------------------------------------------------ // Write the embedded textures void ColladaExporter::WriteCamerasLibrary() { - if(mScene->HasCameras()) { - - mOutput << startstr << "" << endstr; - PushTag(); - - for( size_t a = 0; a < mScene->mNumCameras; ++a) - WriteCamera( a); - - PopTag(); - mOutput << startstr << "" << endstr; - + if (mScene->HasCameras()) { + return; } + + mOutput << startstr << "" << endstr; + PushTag(); + + for (size_t a = 0; a < mScene->mNumCameras; ++a) { + WriteCamera(a); + } + + PopTag(); + mOutput << startstr << "" << endstr; } void ColladaExporter::WriteCamera(size_t pIndex){ - const aiCamera *cam = mScene->mCameras[pIndex]; const std::string idstrEscaped = XMLEscape(cam->mName.C_Str()); @@ -350,30 +347,29 @@ void ColladaExporter::WriteCamera(size_t pIndex){ mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; - } - // ------------------------------------------------------------------------------------------------ // Write the embedded textures void ColladaExporter::WriteLightsLibrary() { - if(mScene->HasLights()) { - - mOutput << startstr << "" << endstr; - PushTag(); - - for( size_t a = 0; a < mScene->mNumLights; ++a) - WriteLight( a); - - PopTag(); - mOutput << startstr << "" << endstr; - + if (!mScene->HasLights()) { + return; } + + mOutput << startstr << "" << endstr; + PushTag(); + + for (size_t a = 0; a < mScene->mNumLights; ++a) { + WriteLight(a); + } + + PopTag(); + mOutput << startstr << "" << endstr; } void ColladaExporter::WriteLight(size_t pIndex){ - const aiLight *light = mScene->mLights[pIndex]; + ai_assert(nullptr != light); const std::string idstrEscaped = XMLEscape(light->mName.C_Str()); mOutput << startstr << "" << light->mAttenuationQuadratic <<"" << endstr; - /* - out->mAngleOuterCone = AI_DEG_TO_RAD (std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+ - srcLight->mFalloffAngle); - */ const ai_real fallOffAngle = AI_RAD_TO_DEG(light->mAngleInnerCone); mOutput << startstr <<"" @@ -481,8 +473,7 @@ void ColladaExporter::WriteSpotLight(const aiLight *const light){ } -void ColladaExporter::WriteAmbienttLight(const aiLight *const light){ - +void ColladaExporter::WriteAmbienttLight(const aiLight *const light) { const aiColor3D &color= light->mColorAmbient; mOutput << startstr << "" << endstr; PushTag(); @@ -496,8 +487,7 @@ void ColladaExporter::WriteAmbienttLight(const aiLight *const light){ // ------------------------------------------------------------------------------------------------ // Reads a single surface entry from the given material keys -void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) -{ +void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) { if( pSrcMat->GetTextureCount( pTexture) > 0 ) { aiString texfile; @@ -623,8 +613,7 @@ void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std // ------------------------------------------------------------------------------------------------ // Writes a scalar property -void ColladaExporter::WriteFloatEntry( const Property& pProperty, const std::string& pTypeName) -{ +void ColladaExporter::WriteFloatEntry( const Property& pProperty, const std::string& pTypeName) { if(pProperty.exist) { mOutput << startstr << "<" << pTypeName << ">" << endstr; PushTag(); @@ -798,13 +787,13 @@ void ColladaExporter::WriteMaterials() // ------------------------------------------------------------------------------------------------ // Writes the controller library -void ColladaExporter::WriteControllerLibrary() -{ +void ColladaExporter::WriteControllerLibrary() { mOutput << startstr << "" << endstr; PushTag(); - for( size_t a = 0; a < mScene->mNumMeshes; ++a) - WriteController( a); + for (size_t a = 0; a < mScene->mNumMeshes; ++a) { + WriteController( a ); + } PopTag(); mOutput << startstr << "" << endstr; @@ -812,8 +801,7 @@ void ColladaExporter::WriteControllerLibrary() // ------------------------------------------------------------------------------------------------ // Writes a skin controller of the given mesh -void ColladaExporter::WriteController( size_t pIndex) -{ +void ColladaExporter::WriteController( size_t pIndex) { const aiMesh* mesh = mScene->mMeshes[pIndex]; const std::string idstr = GetMeshId( pIndex); const std::string idstrEscaped = XMLEscape(idstr); @@ -874,9 +862,11 @@ void ColladaExporter::WriteController( size_t pIndex) std::vector bind_poses; bind_poses.reserve(mesh->mNumBones * 16); - for(unsigned int i = 0; i < mesh->mNumBones; ++i) - for( unsigned int j = 0; j < 4; ++j) + for (unsigned int i = 0; i < mesh->mNumBones; ++i) { + for (unsigned int j = 0; j < 4; ++j) { bind_poses.insert(bind_poses.end(), mesh->mBones[i]->mOffsetMatrix[j], mesh->mBones[i]->mOffsetMatrix[j] + 4); + } + } WriteFloatArray( idstr + "-skin-bind_poses", FloatType_Mat4x4, (const ai_real*) bind_poses.data(), bind_poses.size() / 16); @@ -884,9 +874,11 @@ void ColladaExporter::WriteController( size_t pIndex) std::vector skin_weights; skin_weights.reserve(mesh->mNumVertices * mesh->mNumBones); - for( size_t i = 0; i < mesh->mNumBones; ++i) - for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) + for (size_t i = 0; i < mesh->mNumBones; ++i) { + for (size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) { skin_weights.push_back(mesh->mBones[i]->mWeights[j].mWeight); + } + } WriteFloatArray( idstr + "-skin-weights", FloatType_Weight, (const ai_real*) skin_weights.data(), skin_weights.size()); @@ -910,12 +902,15 @@ void ColladaExporter::WriteController( size_t pIndex) mOutput << startstr << ""; std::vector num_influences(mesh->mNumVertices, (ai_uint)0); - for( size_t i = 0; i < mesh->mNumBones; ++i) - for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) + for (size_t i = 0; i < mesh->mNumBones; ++i) { + for (size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) { ++num_influences[mesh->mBones[i]->mWeights[j].mVertexId]; + } + } - for( size_t i = 0; i < mesh->mNumVertices; ++i) + for (size_t i = 0; i < mesh->mNumVertices; ++i) { mOutput << num_influences[i] << " "; + } mOutput << "" << endstr; @@ -924,19 +919,17 @@ void ColladaExporter::WriteController( size_t pIndex) ai_uint joint_weight_indices_length = 0; std::vector accum_influences; accum_influences.reserve(num_influences.size()); - for( size_t i = 0; i < num_influences.size(); ++i) - { + for( size_t i = 0; i < num_influences.size(); ++i) { accum_influences.push_back(joint_weight_indices_length); joint_weight_indices_length += num_influences[i]; } ai_uint weight_index = 0; std::vector joint_weight_indices(2 * joint_weight_indices_length, (ai_int)-1); - for( unsigned int i = 0; i < mesh->mNumBones; ++i) - for( unsigned j = 0; j < mesh->mBones[i]->mNumWeights; ++j) - { + for (unsigned int i = 0; i < mesh->mNumBones; ++i) { + for (unsigned j = 0; j < mesh->mBones[i]->mNumWeights; ++j) { unsigned int vId = mesh->mBones[i]->mWeights[j].mVertexId; - for( ai_uint k = 0; k < num_influences[vId]; ++k) + for (ai_uint k = 0; k < num_influences[vId]; ++k) { if (joint_weight_indices[2 * (accum_influences[vId] + k)] == -1) { @@ -947,9 +940,11 @@ void ColladaExporter::WriteController( size_t pIndex) } ++weight_index; } + } - for( size_t i = 0; i < joint_weight_indices.size(); ++i) + for (size_t i = 0; i < joint_weight_indices.size(); ++i) { mOutput << joint_weight_indices[i] << " "; + } num_influences.clear(); accum_influences.clear(); @@ -969,13 +964,13 @@ void ColladaExporter::WriteController( size_t pIndex) // ------------------------------------------------------------------------------------------------ // Writes the geometry library -void ColladaExporter::WriteGeometryLibrary() -{ +void ColladaExporter::WriteGeometryLibrary() { mOutput << startstr << "" << endstr; PushTag(); - for( size_t a = 0; a < mScene->mNumMeshes; ++a) - WriteGeometry( a); + for (size_t a = 0; a < mScene->mNumMeshes; ++a) { + WriteGeometry(a); + } PopTag(); mOutput << startstr << "" << endstr; @@ -983,14 +978,14 @@ void ColladaExporter::WriteGeometryLibrary() // ------------------------------------------------------------------------------------------------ // Writes the given mesh -void ColladaExporter::WriteGeometry( size_t pIndex) -{ +void ColladaExporter::WriteGeometry( size_t pIndex) { const aiMesh* mesh = mScene->mMeshes[pIndex]; const std::string idstr = GetMeshId( pIndex); const std::string idstrEscaped = XMLEscape(idstr); - if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) + if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0) { return; + } // opening tag mOutput << startstr << "" << endstr; @@ -1002,24 +997,23 @@ void ColladaExporter::WriteGeometry( size_t pIndex) // Positions WriteFloatArray( idstr + "-positions", FloatType_Vector, (ai_real*) mesh->mVertices, mesh->mNumVertices); // Normals, if any - if( mesh->HasNormals() ) - WriteFloatArray( idstr + "-normals", FloatType_Vector, (ai_real*) mesh->mNormals, mesh->mNumVertices); + if (mesh->HasNormals()) { + WriteFloatArray(idstr + "-normals", FloatType_Vector, (ai_real*)mesh->mNormals, mesh->mNumVertices); + } // texture coords - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - { + for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { + if( mesh->HasTextureCoords(static_cast(a)) ){ WriteFloatArray( idstr + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2, (ai_real*) mesh->mTextureCoords[a], mesh->mNumVertices); } } // vertex colors - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) - { - if( mesh->HasVertexColors(static_cast(a)) ) - WriteFloatArray( idstr + "-color" + to_string(a), FloatType_Color, (ai_real*) mesh->mColors[a], mesh->mNumVertices); + for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { + if (mesh->HasVertexColors(static_cast(a))) { + WriteFloatArray(idstr + "-color" + to_string(a), FloatType_Color, (ai_real*)mesh->mColors[a], mesh->mNumVertices); + } } // assemble vertex structure @@ -1031,40 +1025,43 @@ void ColladaExporter::WriteGeometry( size_t pIndex) mOutput << startstr << "" << endstr; // count the number of lines, triangles and polygon meshes - int countLines = 0; - int countPoly = 0; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - if (mesh->mFaces[a].mNumIndices == 2) countLines++; - else if (mesh->mFaces[a].mNumIndices >= 3) countPoly++; + int countLines( 0 ), countPoly( 0 ); + for( size_t a = 0; a < mesh->mNumFaces; ++a ) { + if (mesh->mFaces[a].mNumIndices == 2) { + countLines++; + } else if (mesh->mFaces[a].mNumIndices >= 3) { + countPoly++; + } } // lines - if (countLines) - { + if (countLines) { mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; - if( mesh->HasNormals() ) + if (mesh->HasNormals()) { mOutput << startstr << "" << endstr; - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - mOutput << startstr << "" << endstr; } - for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) - { - if( mesh->HasVertexColors(static_cast(a) ) ) - mOutput << startstr << "" << endstr; + for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) { + if (mesh->HasTextureCoords(static_cast(a))) { + mOutput << startstr << "" << endstr; + } + } + for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) { + if (mesh->HasVertexColors(static_cast(a))) { + mOutput << startstr << "" << endstr; + } } mOutput << startstr << "

"; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { + for( size_t a = 0; a < mesh->mNumFaces; ++a ) { const aiFace& face = mesh->mFaces[a]; - if (face.mNumIndices != 2) continue; - for( size_t b = 0; b < face.mNumIndices; ++b ) + if (face.mNumIndices != 2) { + continue; + } + for (size_t b = 0; b < face.mNumIndices; ++b) { mOutput << face.mIndices[b] << " "; + } } mOutput << "

" << endstr; PopTag(); @@ -1074,39 +1071,42 @@ void ColladaExporter::WriteGeometry( size_t pIndex) // triangle - don't use it, because compatibility problems // polygons - if (countPoly) - { + if (countPoly) { mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; - if( mesh->HasNormals() ) + if (mesh->HasNormals()) { mOutput << startstr << "" << endstr; - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - mOutput << startstr << "" << endstr; } - for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) - { - if( mesh->HasVertexColors(static_cast(a) ) ) - mOutput << startstr << "" << endstr; + for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) { + if (mesh->HasTextureCoords(static_cast(a))) { + mOutput << startstr << "" << endstr; + } + } + for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) { + if (mesh->HasVertexColors(static_cast(a))) { + mOutput << startstr << "" << endstr; + } } mOutput << startstr << ""; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - if (mesh->mFaces[a].mNumIndices < 3) continue; + for( size_t a = 0; a < mesh->mNumFaces; ++a ) { + if (mesh->mFaces[a].mNumIndices < 3) { + continue; + } mOutput << mesh->mFaces[a].mNumIndices << " "; } mOutput << "" << endstr; mOutput << startstr << "

"; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { + for( size_t a = 0; a < mesh->mNumFaces; ++a ) { const aiFace& face = mesh->mFaces[a]; - if (face.mNumIndices < 3) continue; - for( size_t b = 0; b < face.mNumIndices; ++b ) + if (face.mNumIndices < 3) { + continue; + } + for (size_t b = 0; b < face.mNumIndices; ++b) { mOutput << face.mIndices[b] << " "; + } } mOutput << "

" << endstr; PopTag(); @@ -1122,18 +1122,23 @@ void ColladaExporter::WriteGeometry( size_t pIndex) // ------------------------------------------------------------------------------------------------ // Writes a float array of the given type -void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount) -{ +void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount) { size_t floatsPerElement = 0; - switch( pType ) - { - case FloatType_Vector: floatsPerElement = 3; break; - case FloatType_TexCoord2: floatsPerElement = 2; break; - case FloatType_TexCoord3: floatsPerElement = 3; break; - case FloatType_Color: floatsPerElement = 3; break; - case FloatType_Mat4x4: floatsPerElement = 16; break; - case FloatType_Weight: floatsPerElement = 1; break; - case FloatType_Time: floatsPerElement = 1; break; + switch( pType ) { + case FloatType_TexCoord2: + floatsPerElement = 2; + break; + case FloatType_Vector: + case FloatType_TexCoord3: + case FloatType_Color: + floatsPerElement = 3; + break; + case FloatType_Mat4x4: floatsPerElement = 16; + break; + case FloatType_Weight: + case FloatType_Time: + floatsPerElement = 1; + break; default: return; } @@ -1147,28 +1152,23 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy mOutput << startstr << " "; PushTag(); - if( pType == FloatType_TexCoord2 ) - { - for( size_t a = 0; a < pElementCount; ++a ) - { + if( pType == FloatType_TexCoord2 ) { + for( size_t a = 0; a < pElementCount; ++a ) { mOutput << pData[a*3+0] << " "; mOutput << pData[a*3+1] << " "; } - } - else if( pType == FloatType_Color ) - { - for( size_t a = 0; a < pElementCount; ++a ) - { + } else if( pType == FloatType_Color ) { + for( size_t a = 0; a < pElementCount; ++a ) { mOutput << pData[a*4+0] << " "; mOutput << pData[a*4+1] << " "; mOutput << pData[a*4+2] << " "; } - } - else - { - for( size_t a = 0; a < pElementCount * floatsPerElement; ++a ) + } else { + for (size_t a = 0; a < pElementCount * floatsPerElement; ++a) { mOutput << pData[a] << " "; + } } + mOutput << "" << endstr; PopTag(); @@ -1178,8 +1178,7 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy mOutput << startstr << "" << endstr; PushTag(); - switch( pType ) - { + switch( pType ) { case FloatType_Vector: mOutput << startstr << "" << endstr; mOutput << startstr << "" << endstr; @@ -1228,8 +1227,7 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy // ------------------------------------------------------------------------------------------------ // Writes the scene library -void ColladaExporter::WriteSceneLibrary() -{ +void ColladaExporter::WriteSceneLibrary() { const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str()); mOutput << startstr << "" << endstr; @@ -1238,21 +1236,23 @@ void ColladaExporter::WriteSceneLibrary() PushTag(); // start recursive write at the root node - for( size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a ) - WriteNode( mScene, mScene->mRootNode->mChildren[a]); + for (size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a) { + WriteNode(mScene, mScene->mRootNode->mChildren[a]); + } PopTag(); mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; } + // ------------------------------------------------------------------------------------------------ -void ColladaExporter::WriteAnimationLibrary(size_t pIndex) -{ +void ColladaExporter::WriteAnimationLibrary(size_t pIndex) { const aiAnimation * anim = mScene->mAnimations[pIndex]; - if ( anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels ==0 ) - return; + if (anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels == 0) { + return; + } const std::string animation_name_escaped = XMLEscape( anim->mName.C_Str() ); std::string idstr = anim->mName.C_Str(); @@ -1428,7 +1428,7 @@ aiBone* findBone( const aiScene* scene, const char * name) { } } } - return NULL; + return nullptr; } // ------------------------------------------------------------------------------------------------ @@ -1449,7 +1449,7 @@ const aiNode * findBoneNode( const aiNode* aNode, const aiBone* bone) } } - return NULL; + return nullptr; } const aiNode * findSkeletonRootNode( const aiScene* scene, const aiMesh * mesh) @@ -1481,7 +1481,7 @@ const aiNode * findSkeletonRootNode( const aiScene* scene, const aiMesh * mesh) } } - return NULL; + return nullptr; } // ------------------------------------------------------------------------------------------------ @@ -1500,24 +1500,17 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) // otherwise it is a normal node (NODE) const char * node_type; bool is_joint, is_skeleton_root = false; - if (NULL == findBone(pScene, pNode->mName.C_Str())) { + if (nullptr == findBone(pScene, pNode->mName.C_Str())) { node_type = "NODE"; is_joint = false; } else { node_type = "JOINT"; is_joint = true; - if(!pNode->mParent || NULL == findBone(pScene, pNode->mParent->mName.C_Str())) + if(!pNode->mParent || nullptr == findBone(pScene, pNode->mParent->mName.C_Str())) is_skeleton_root = true; } const std::string node_name_escaped = XMLEscape(pNode->mName.data); - /* // customized, Note! the id field is crucial for inter-xml look up, it cannot be replaced with sid ?! - mOutput << startstr - << "mTransformation; // customized, sid should be 'matrix' to match with loader code. - //mOutput << startstr << ""; mOutput << startstr << ""; mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " "; From 4f7bacd10888313671f751d3278254417605e083 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 11 Sep 2018 20:01:16 +0200 Subject: [PATCH 2/7] Collada: some reformatting + minor findings. --- code/ColladaExporter.cpp | 452 +++++++++++++++++----------------- code/ColladaExporter.h | 3 +- include/assimp/ParsingUtils.h | 3 +- include/assimp/defs.h | 8 +- 4 files changed, 237 insertions(+), 229 deletions(-) diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 82a755c58..d3abe7366 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -155,7 +155,6 @@ void ColladaExporter::WriteFile() { // ------------------------------------------------------------------------------------------------ // Writes the asset header void ColladaExporter::WriteHeader() { - static const ai_real epsilon = ai_real( 0.00001 ); static const aiQuaternion x_rot(aiMatrix3x3( 0, -1, 0, 1, 0, 0, @@ -182,19 +181,19 @@ void ColladaExporter::WriteHeader() { bool add_root_node = false; - ai_real scale = 1.0; - if(std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) { + ai_real scale( 1.0 ); + if(std::abs(scaling.x - scaling.y) <= ai_epsilon && std::abs(scaling.x - scaling.z) <= ai_epsilon && std::abs(scaling.y - scaling.z) <= ai_epsilon) { scale = (ai_real) ((((double) scaling.x) + ((double) scaling.y) + ((double) scaling.z)) / 3.0); } else { add_root_node = true; } std::string up_axis = "Y_UP"; - if(rotation.Equal(x_rot, epsilon)) { + if(rotation.Equal(x_rot, ai_epsilon)) { up_axis = "X_UP"; - } else if(rotation.Equal(y_rot, epsilon)) { + } else if(rotation.Equal(y_rot, ai_epsilon)) { up_axis = "Y_UP"; - } else if(rotation.Equal(z_rot, epsilon)) { + } else if(rotation.Equal(z_rot, ai_epsilon)) { up_axis = "Z_UP"; } else { add_root_node = true; @@ -235,15 +234,17 @@ void ColladaExporter::WriteHeader() { aiMetadata* meta = mScene->mRootNode->mMetaData; aiString value; - if (!meta || !meta->Get("Author", value)) + if (!meta || !meta->Get("Author", value)) { mOutput << startstr << "" << "Assimp" << "" << endstr; - else + } else { mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; + } - if (!meta || !meta->Get("AuthoringTool", value)) + if (!meta || !meta->Get("AuthoringTool", value)) { mOutput << startstr << "" << "Assimp Exporter" << "" << endstr; - else + } else { mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; + } //mOutput << startstr << "" << mScene->author.C_Str() << "" << endstr; //mOutput << startstr << "" << mScene->authoringTool.C_Str() << "" << endstr; @@ -261,13 +262,12 @@ void ColladaExporter::WriteHeader() { // ------------------------------------------------------------------------------------------------ // Write the embedded textures void ColladaExporter::WriteTextures() { - static const unsigned int buffer_size = 1024; - char str[buffer_size]; - if (!mScene->HasTextures()) { return; } + static const size_t buffer_size = 1024; + char str[buffer_size]; for(unsigned int i = 0; i < mScene->mNumTextures; i++) { // It would be great to be able to create a directory in portable standard C++, but it's not the case, // so we just write the textures in the current directory. @@ -279,7 +279,7 @@ void ColladaExporter::WriteTextures() { std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint); std::unique_ptr outfile(mIOSystem->Open(mPath + name, "wb")); - if(outfile == NULL) { + if(outfile == nullptr) { throw DeadlyExportError("could not open output texture file: " + mPath + name); } @@ -425,7 +425,7 @@ void ColladaExporter::WritePointLight(const aiLight *const light){ } void ColladaExporter::WriteDirectionalLight(const aiLight *const light){ - const aiColor3D &color= light->mColorDiffuse; + const aiColor3D &color( light->mColorDiffuse ); mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" @@ -437,8 +437,7 @@ void ColladaExporter::WriteDirectionalLight(const aiLight *const light){ } void ColladaExporter::WriteSpotLight(const aiLight *const light){ - - const aiColor3D &color= light->mColorDiffuse; + const aiColor3D &color( light->mColorDiffuse ); mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" @@ -474,7 +473,7 @@ void ColladaExporter::WriteSpotLight(const aiLight *const light){ } void ColladaExporter::WriteAmbienttLight(const aiLight *const light) { - const aiColor3D &color= light->mColorAmbient; + const aiColor3D &color(light->mColorAmbient); mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" @@ -488,18 +487,21 @@ void ColladaExporter::WriteAmbienttLight(const aiLight *const light) { // ------------------------------------------------------------------------------------------------ // Reads a single surface entry from the given material keys void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) { - if( pSrcMat->GetTextureCount( pTexture) > 0 ) - { + if (pSrcMat->GetTextureCount(pTexture) < 1) { + if (pKey) { + poSurface.exist = pSrcMat->Get(pKey, static_cast(pType), static_cast(pIndex), poSurface.color) == aiReturn_SUCCESS; + } + return; + } + aiString texfile; unsigned int uvChannel = 0; - pSrcMat->GetTexture( pTexture, 0, &texfile, NULL, &uvChannel); + pSrcMat->GetTexture( pTexture, 0, &texfile, nullptr, &uvChannel); std::string index_str(texfile.C_Str()); - if(index_str.size() != 0 && index_str[0] == '*') - { + if(index_str.size() != 0 && index_str[0] == '*') { unsigned int index; - index_str = index_str.substr(1, std::string::npos); try { @@ -507,88 +509,82 @@ void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* } catch(std::exception& error) { throw DeadlyExportError(error.what()); } - std::map::const_iterator name = textures.find(index); - if(name != textures.end()) { + if (name != textures.end()) { poSurface.texture = name->second; } else { throw DeadlyExportError("could not find embedded texture at index " + index_str); } - } else - { + } else { poSurface.texture = texfile.C_Str(); } poSurface.channel = uvChannel; poSurface.exist = true; - } else - { - if( pKey ) - poSurface.exist = pSrcMat->Get( pKey, static_cast(pType), static_cast(pIndex), poSurface.color) == aiReturn_SUCCESS; - } } // ------------------------------------------------------------------------------------------------ // Reimplementation of isalnum(,C locale), because AppVeyor does not see standard version. -static bool isalnum_C(char c) -{ +static bool isalnum_C(char c) { return ( nullptr != strchr("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",c) ); } // ------------------------------------------------------------------------------------------------ // Writes an image entry for the given surface -void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd) -{ - if( !pSurface.texture.empty() ) - { +void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd) { + if (pSurface.texture.empty()) { + return; + } + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << ""; // URL encode image file name first, then XML encode on top std::stringstream imageUrlEncoded; - for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it ) - { - if( isalnum_C( (unsigned char) *it) || *it == ':' || *it == '_' || *it == '-' || *it == '.' || *it == '/' || *it == '\\' ) - imageUrlEncoded << *it; - else - imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec; + for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it ) { + if (isalnum_C((unsigned char)*it) || *it == ':' || *it == '_' || *it == '-' || *it == '.' || *it == '/' || *it == '\\') { + imageUrlEncoded << *it; + } else { + imageUrlEncoded << '%' << std::hex << size_t((unsigned char)*it) << std::dec; + } } mOutput << XMLEscape(imageUrlEncoded.str()); mOutput << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; - } } // ------------------------------------------------------------------------------------------------ // Writes a color-or-texture entry into an effect definition -void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pImageName) -{ - if(pSurface.exist) { +void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, + const std::string& pImageName) { + if (!pSurface.exist) { + return; + } + mOutput << startstr << "<" << pTypeName << ">" << endstr; PushTag(); - if( pSurface.texture.empty() ) - { - mOutput << startstr << "" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "" << endstr; - } - else - { - mOutput << startstr << "" << endstr; + if( pSurface.texture.empty() ) { + mOutput << startstr << "" + << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a + << "" << endstr; + } else { + mOutput << startstr << "" << endstr; } PopTag(); mOutput << startstr << "" << endstr; - } } // ------------------------------------------------------------------------------------------------ // Writes the two parameters necessary for referencing a texture in an effect entry -void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pMatName) -{ - // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture - if( !pSurface.texture.empty() ) - { +void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pMatName) { + if (pSurface.texture.empty()) { + return; + } + + // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; @@ -608,181 +604,194 @@ void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; - } } // ------------------------------------------------------------------------------------------------ // Writes a scalar property void ColladaExporter::WriteFloatEntry( const Property& pProperty, const std::string& pTypeName) { - if(pProperty.exist) { - mOutput << startstr << "<" << pTypeName << ">" << endstr; - PushTag(); - mOutput << startstr << "" << pProperty.value << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; + if (!pProperty.exist) { + return; } + + mOutput << startstr << "<" << pTypeName << ">" << endstr; + PushTag(); + mOutput << startstr << "" << pProperty.value << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; } // ------------------------------------------------------------------------------------------------ // Writes the material setup -void ColladaExporter::WriteMaterials() +void ColladaExporter::WriteMaterials() { + materials.resize( mScene->mNumMaterials); + + // collect all materials from the scene + size_t numTextures = 0; + for( size_t a = 0; a < mScene->mNumMaterials; ++a ) { + const aiMaterial* mat = mScene->mMaterials[a]; + aiString name; + if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS ) { + name = "mat"; + materials[a].name = std::string( "m") + to_string(a) + name.C_Str(); + } else { + // try to use the material's name if no other material has already taken it, else append # + std::string testName = name.C_Str(); + size_t materialCountWithThisName = 0; + for( size_t i = 0; i < a; i ++ ) { + if( materials[i].name == testName ) { + ++materialCountWithThisName; + } + } + if( materialCountWithThisName == 0 ) { + materials[a].name = name.C_Str(); + } else { + materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName); + } + } + + for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) { + if( !isalnum_C( *it ) ) { + *it = '_'; + } + } + + aiShadingMode shading = aiShadingMode_Flat; + materials[a].shading_model = "phong"; + if(mat->Get( AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) { + if(shading == aiShadingMode_Phong) { + materials[a].shading_model = "phong"; + } else if(shading == aiShadingMode_Blinn) { + materials[a].shading_model = "blinn"; + } else if(shading == aiShadingMode_NoShading) { + materials[a].shading_model = "constant"; + } else if(shading == aiShadingMode_Gouraud) { + materials[a].shading_model = "lambert"; + } + } + + ReadMaterialSurface( materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); + if (!materials[a].ambient.texture.empty()) { + ++numTextures; + } + ReadMaterialSurface( materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); + if (!materials[a].diffuse.texture.empty()) { + ++numTextures; + } + ReadMaterialSurface( materials[a].specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); + if (!materials[a].specular.texture.empty()) { + numTextures++; + } + ReadMaterialSurface( materials[a].emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); + if (!materials[a].emissive.texture.empty()) { + numTextures++; + } + ReadMaterialSurface( materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE); + if (!materials[a].reflective.texture.empty()) { + numTextures++; + } + ReadMaterialSurface( materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT); + if (!materials[a].transparent.texture.empty()) { + numTextures++; + } + ReadMaterialSurface( materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0); + if (!materials[a].normal.texture.empty()) { + numTextures++; + } + +materials[a].shininess.exist = mat->Get( AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS; +materials[a].transparency.exist = mat->Get( AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS; +materials[a].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS; +} + +// output textures if present +if( numTextures > 0 ) { - materials.resize( mScene->mNumMaterials); +mOutput << startstr << "" << endstr; +PushTag(); +for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) +{ +const Material& mat = *it; +WriteImageEntry( mat.ambient, mat.name + "-ambient-image"); +WriteImageEntry( mat.diffuse, mat.name + "-diffuse-image"); +WriteImageEntry( mat.specular, mat.name + "-specular-image"); +WriteImageEntry( mat.emissive, mat.name + "-emission-image"); +WriteImageEntry( mat.reflective, mat.name + "-reflective-image"); +WriteImageEntry( mat.transparent, mat.name + "-transparent-image"); +WriteImageEntry( mat.normal, mat.name + "-normal-image"); +} +PopTag(); +mOutput << startstr << "" << endstr; +} - /// collect all materials from the scene - size_t numTextures = 0; - for( size_t a = 0; a < mScene->mNumMaterials; ++a ) - { - const aiMaterial* mat = mScene->mMaterials[a]; +// output effects - those are the actual carriers of information +if( !materials.empty() ) +{ +mOutput << startstr << "" << endstr; +PushTag(); +for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) +{ +const Material& mat = *it; +// this is so ridiculous it must be right +mOutput << startstr << "" << endstr; +PushTag(); +mOutput << startstr << "" << endstr; +PushTag(); - aiString name; - if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS ) { - name = "mat"; - materials[a].name = std::string( "m") + to_string(a) + name.C_Str(); - } else { - // try to use the material's name if no other material has already taken it, else append # - std::string testName = name.C_Str(); - size_t materialCountWithThisName = 0; - for( size_t i = 0; i < a; i ++ ) { - if( materials[i].name == testName ) { - materialCountWithThisName ++; - } - } - if( materialCountWithThisName == 0 ) { - materials[a].name = name.C_Str(); - } else { - materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName); - } - } - for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) { - if( !isalnum_C( *it ) ) { - *it = '_'; - } - } +// write sampler- and surface params for the texture entries +WriteTextureParamEntry( mat.emissive, "emission", mat.name); +WriteTextureParamEntry( mat.ambient, "ambient", mat.name); +WriteTextureParamEntry( mat.diffuse, "diffuse", mat.name); +WriteTextureParamEntry( mat.specular, "specular", mat.name); +WriteTextureParamEntry( mat.reflective, "reflective", mat.name); +WriteTextureParamEntry( mat.transparent, "transparent", mat.name); +WriteTextureParamEntry( mat.normal, "normal", mat.name); - aiShadingMode shading = aiShadingMode_Flat; - materials[a].shading_model = "phong"; - if(mat->Get( AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) { - if(shading == aiShadingMode_Phong) { - materials[a].shading_model = "phong"; - } else if(shading == aiShadingMode_Blinn) { - materials[a].shading_model = "blinn"; - } else if(shading == aiShadingMode_NoShading) { - materials[a].shading_model = "constant"; - } else if(shading == aiShadingMode_Gouraud) { - materials[a].shading_model = "lambert"; - } - } +mOutput << startstr << "" << endstr; +PushTag(); +mOutput << startstr << "<" << mat.shading_model << ">" << endstr; +PushTag(); - ReadMaterialSurface( materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); - if( !materials[a].ambient.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); - if( !materials[a].diffuse.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); - if( !materials[a].specular.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); - if( !materials[a].emissive.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE); - if( !materials[a].reflective.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT); - if( !materials[a].transparent.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0); - if( !materials[a].normal.texture.empty() ) numTextures++; +WriteTextureColorEntry( mat.emissive, "emission", mat.name + "-emission-sampler"); +WriteTextureColorEntry( mat.ambient, "ambient", mat.name + "-ambient-sampler"); +WriteTextureColorEntry( mat.diffuse, "diffuse", mat.name + "-diffuse-sampler"); +WriteTextureColorEntry( mat.specular, "specular", mat.name + "-specular-sampler"); +WriteFloatEntry(mat.shininess, "shininess"); +WriteTextureColorEntry( mat.reflective, "reflective", mat.name + "-reflective-sampler"); +WriteTextureColorEntry( mat.transparent, "transparent", mat.name + "-transparent-sampler"); +WriteFloatEntry(mat.transparency, "transparency"); +WriteFloatEntry(mat.index_refraction, "index_of_refraction"); - materials[a].shininess.exist = mat->Get( AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS; - materials[a].transparency.exist = mat->Get( AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS; - materials[a].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS; - } +if(! mat.normal.texture.empty()) { +WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler"); +} - // output textures if present - if( numTextures > 0 ) - { - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - WriteImageEntry( mat.ambient, mat.name + "-ambient-image"); - WriteImageEntry( mat.diffuse, mat.name + "-diffuse-image"); - WriteImageEntry( mat.specular, mat.name + "-specular-image"); - WriteImageEntry( mat.emissive, mat.name + "-emission-image"); - WriteImageEntry( mat.reflective, mat.name + "-reflective-image"); - WriteImageEntry( mat.transparent, mat.name + "-transparent-image"); - WriteImageEntry( mat.normal, mat.name + "-normal-image"); - } - PopTag(); - mOutput << startstr << "" << endstr; - } +PopTag(); +mOutput << startstr << "" << endstr; +PopTag(); +mOutput << startstr << "" << endstr; +PopTag(); +mOutput << startstr << "" << endstr; +PopTag(); +mOutput << startstr << "" << endstr; +} +PopTag(); +mOutput << startstr << "" << endstr; - // output effects - those are the actual carriers of information - if( !materials.empty() ) - { - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - // this is so ridiculous it must be right - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - - // write sampler- and surface params for the texture entries - WriteTextureParamEntry( mat.emissive, "emission", mat.name); - WriteTextureParamEntry( mat.ambient, "ambient", mat.name); - WriteTextureParamEntry( mat.diffuse, "diffuse", mat.name); - WriteTextureParamEntry( mat.specular, "specular", mat.name); - WriteTextureParamEntry( mat.reflective, "reflective", mat.name); - WriteTextureParamEntry( mat.transparent, "transparent", mat.name); - WriteTextureParamEntry( mat.normal, "normal", mat.name); - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "<" << mat.shading_model << ">" << endstr; - PushTag(); - - WriteTextureColorEntry( mat.emissive, "emission", mat.name + "-emission-sampler"); - WriteTextureColorEntry( mat.ambient, "ambient", mat.name + "-ambient-sampler"); - WriteTextureColorEntry( mat.diffuse, "diffuse", mat.name + "-diffuse-sampler"); - WriteTextureColorEntry( mat.specular, "specular", mat.name + "-specular-sampler"); - WriteFloatEntry(mat.shininess, "shininess"); - WriteTextureColorEntry( mat.reflective, "reflective", mat.name + "-reflective-sampler"); - WriteTextureColorEntry( mat.transparent, "transparent", mat.name + "-transparent-sampler"); - WriteFloatEntry(mat.transparency, "transparency"); - WriteFloatEntry(mat.index_refraction, "index_of_refraction"); - - if(! mat.normal.texture.empty()) { - WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler"); - } - - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - - // write materials - they're just effect references - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - } +// write materials - they're just effect references +mOutput << startstr << "" << endstr; +PushTag(); +for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) +{ +const Material& mat = *it; +mOutput << startstr << "" << endstr; +PushTag(); +mOutput << startstr << "" << endstr; +PopTag(); +mOutput << startstr << "" << endstr; +} +PopTag(); +mOutput << startstr << "" << endstr; +} } // ------------------------------------------------------------------------------------------------ @@ -1611,8 +1620,9 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) } // recurse into subnodes - for( size_t a = 0; a < pNode->mNumChildren; ++a ) - WriteNode( pScene, pNode->mChildren[a]); + for (size_t a = 0; a < pNode->mNumChildren; ++a) { + WriteNode(pScene, pNode->mChildren[a]); + } PopTag(); mOutput << startstr << "" << endstr; diff --git a/code/ColladaExporter.h b/code/ColladaExporter.h index d1a307532..65f82d4ad 100644 --- a/code/ColladaExporter.h +++ b/code/ColladaExporter.h @@ -150,7 +150,6 @@ public: /// Stringstream to write all output into std::stringstream mOutput; -protected: /// The IOSystem for output IOSystem* mIOSystem; @@ -204,7 +203,7 @@ protected: std::map textures; -protected: +public: /// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions /// Reads a single surface entry from the given material keys void ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex); diff --git a/include/assimp/ParsingUtils.h b/include/assimp/ParsingUtils.h index 4553072db..9b3a9ddce 100644 --- a/include/assimp/ParsingUtils.h +++ b/include/assimp/ParsingUtils.h @@ -196,8 +196,7 @@ bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) { // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool IsNumeric( char_t in) -{ +AI_FORCE_INLINE bool IsNumeric( char_t in) { return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in; } diff --git a/include/assimp/defs.h b/include/assimp/defs.h index b587396bf..b2e837eef 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -213,10 +213,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #if (defined(__BORLANDC__) || defined (__BCPLUSPLUS__)) -#error Currently, Borland is unsupported. Feel free to port Assimp. - -// "W8059 Packgröße der Struktur geändert" - +# error Currently, Borland is unsupported. Feel free to port Assimp. #endif @@ -266,6 +263,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_DEG_TO_RAD(x) ((x)*(ai_real)0.0174532925) #define AI_RAD_TO_DEG(x) ((x)*(ai_real)57.2957795) +/* Numerical limits */ +static const ai_real ai_epsilon = (ai_real) 0.00001; + /* Support for big-endian builds */ #if defined(__BYTE_ORDER__) # if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) From 59f732e10d23df3104b161c66efcde3805dade4e Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Thu, 20 Jun 2019 16:30:52 +0100 Subject: [PATCH 3/7] DAE Import: Don't use SkipElement() to skip empty Text IrrXML doesn't recognise the construction: `` as being an empty element, and so ColladaParser::TestTextContent advances the element stream into the `` element. Use TestClosing(const char*) instead of SkipElement() to skip an empty text element. --- code/Collada/ColladaParser.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/Collada/ColladaParser.cpp b/code/Collada/ColladaParser.cpp index 2106bf01c..860ae2ae9 100644 --- a/code/Collada/ColladaParser.cpp +++ b/code/Collada/ColladaParser.cpp @@ -323,10 +323,8 @@ void ColladaParser::ReadMetaDataItem(StringMetaData &metadata) aiString aistr; aistr.Set(value_char); metadata.emplace(camel_key_str, aistr); - TestClosing(key_str.c_str()); } - else - SkipElement(); + TestClosing(key_str.c_str()); } else SkipElement(); From bf252c4452b76f9318b56d8c91f515bc13412a9c Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Thu, 20 Jun 2019 18:11:11 +0100 Subject: [PATCH 4/7] Add configuration of text format precision Define ASSIMP_AI_REAL_TEXT_PRECISION 8 when ai_real is float 16 when ai_real is double --- code/Collada/ColladaExporter.cpp | 2 +- code/Obj/ObjExporter.cpp | 4 ++-- code/Ply/PlyExporter.cpp | 2 +- code/STL/STLExporter.cpp | 2 +- code/Step/StepExporter.cpp | 16 ++++++++-------- code/X/XFileExporter.cpp | 4 ++-- include/assimp/defs.h | 6 ++++++ 7 files changed, 21 insertions(+), 15 deletions(-) diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp index 7c21dde43..639f0e032 100644 --- a/code/Collada/ColladaExporter.cpp +++ b/code/Collada/ColladaExporter.cpp @@ -99,7 +99,7 @@ ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, co , mFile(file) { // make sure that all formatting happens using the standard, C locale and not the user's current locale mOutput.imbue( std::locale("C") ); - mOutput.precision(16); + mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); mScene = pScene; mSceneOwned = false; diff --git a/code/Obj/ObjExporter.cpp b/code/Obj/ObjExporter.cpp index 08cba43f7..0a0dbd62c 100644 --- a/code/Obj/ObjExporter.cpp +++ b/code/Obj/ObjExporter.cpp @@ -126,9 +126,9 @@ ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMt // make sure that all formatting happens using the standard, C locale and not the user's current locale const std::locale& l = std::locale("C"); mOutput.imbue(l); - mOutput.precision(16); + mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); mOutputMat.imbue(l); - mOutputMat.precision(16); + mOutputMat.precision(ASSIMP_AI_REAL_TEXT_PRECISION); WriteGeometryFile(noMtl); if ( !noMtl ) { diff --git a/code/Ply/PlyExporter.cpp b/code/Ply/PlyExporter.cpp index 4f9fa6c6f..5e21a88ac 100644 --- a/code/Ply/PlyExporter.cpp +++ b/code/Ply/PlyExporter.cpp @@ -111,7 +111,7 @@ PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool bina // make sure that all formatting happens using the standard, C locale and not the user's current locale const std::locale& l = std::locale("C"); mOutput.imbue(l); - mOutput.precision(16); + mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); unsigned int faces = 0u, vertices = 0u, components = 0u; for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { diff --git a/code/STL/STLExporter.cpp b/code/STL/STLExporter.cpp index d56c42835..43bc752ae 100644 --- a/code/STL/STLExporter.cpp +++ b/code/STL/STLExporter.cpp @@ -111,7 +111,7 @@ STLExporter::STLExporter(const char* _filename, const aiScene* pScene, bool expo // make sure that all formatting happens using the standard, C locale and not the user's current locale const std::locale& l = std::locale("C"); mOutput.imbue(l); - mOutput.precision(16); + mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); if (binary) { char buf[80] = {0} ; buf[0] = 'A'; buf[1] = 's'; buf[2] = 's'; buf[3] = 'i'; buf[4] = 'm'; buf[5] = 'p'; diff --git a/code/Step/StepExporter.cpp b/code/Step/StepExporter.cpp index 2b4dbdbac..70035d9ea 100644 --- a/code/Step/StepExporter.cpp +++ b/code/Step/StepExporter.cpp @@ -143,15 +143,15 @@ namespace { // ------------------------------------------------------------------------------------------------ // Constructor for a specific scene to export StepExporter::StepExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, - const std::string& file, const ExportProperties* pProperties): - mProperties(pProperties),mIOSystem(pIOSystem),mFile(file), mPath(path), - mScene(pScene), endstr(";\n") { - CollectTrafos(pScene->mRootNode, trafos); - CollectMeshes(pScene->mRootNode, meshes); + const std::string& file, const ExportProperties* pProperties) : + mProperties(pProperties), mIOSystem(pIOSystem), mFile(file), mPath(path), + mScene(pScene), endstr(";\n") { + CollectTrafos(pScene->mRootNode, trafos); + CollectMeshes(pScene->mRootNode, meshes); // make sure that all formatting happens using the standard, C locale and not the user's current locale - mOutput.imbue( std::locale("C") ); - mOutput.precision(16); + mOutput.imbue(std::locale("C")); + mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); // start writing WriteFile(); @@ -166,7 +166,7 @@ void StepExporter::WriteFile() mOutput.setf(std::ios::fixed); // precision for double // see http://stackoverflow.com/questions/554063/how-do-i-print-a-double-value-with-full-precision-using-cout - mOutput.precision(16); + mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); // standard color aiColor4D fColor; diff --git a/code/X/XFileExporter.cpp b/code/X/XFileExporter.cpp index b2cc51852..ae9fd58fc 100644 --- a/code/X/XFileExporter.cpp +++ b/code/X/XFileExporter.cpp @@ -113,7 +113,7 @@ XFileExporter::XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const s { // make sure that all formatting happens using the standard, C locale and not the user's current locale mOutput.imbue( std::locale("C") ); - mOutput.precision(16); + mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); // start writing WriteFile(); @@ -134,7 +134,7 @@ void XFileExporter::WriteFile() { // note, that all realnumber values must be comma separated in x files mOutput.setf(std::ios::fixed); - mOutput.precision(16); // precision for double + mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); // precision for ai_real // entry of writing the file WriteHeader(); diff --git a/include/assimp/defs.h b/include/assimp/defs.h index 2631263f5..1b9a97b6b 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -243,10 +243,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. typedef double ai_real; typedef signed long long int ai_int; typedef unsigned long long int ai_uint; +#ifndef ASSIMP_AI_REAL_TEXT_PRECISION +#define ASSIMP_AI_REAL_TEXT_PRECISION 16 +#endif // ASSIMP_AI_REAL_TEXT_PRECISION #else // ASSIMP_DOUBLE_PRECISION typedef float ai_real; typedef signed int ai_int; typedef unsigned int ai_uint; +#ifndef ASSIMP_AI_REAL_TEXT_PRECISION +#define ASSIMP_AI_REAL_TEXT_PRECISION 8 +#endif // ASSIMP_AI_REAL_TEXT_PRECISION #endif // ASSIMP_DOUBLE_PRECISION ////////////////////////////////////////////////////////////////////////// From 26bd54ae0b014c084e6436b81b85f6d94908162d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 23 Jun 2019 20:24:32 +0200 Subject: [PATCH 5/7] PostProcesswing: add gen-aabb process to postprocessing. --- code/CMakeLists.txt | 1 + .../GenBoundingBoxesProcess.cpp | 115 ++++++++++++++++++ code/PostProcessing/GenBoundingBoxesProcess.h | 61 ++++++++++ include/assimp/camera.h | 1 - include/assimp/defs.h | 5 +- include/assimp/mesh.h | 11 +- include/assimp/postprocess.h | 13 +- 7 files changed, 198 insertions(+), 9 deletions(-) create mode 100644 code/PostProcessing/GenBoundingBoxesProcess.cpp create mode 100644 code/PostProcessing/GenBoundingBoxesProcess.h diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index c0f870dd3..8668d4e6b 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -60,6 +60,7 @@ SOURCE_GROUP( Compiler FILES ${COMPILER_HEADERS}) SET( PUBLIC_HEADERS ${HEADER_PATH}/anim.h + ${HEADER_PATH}/aabb.h ${HEADER_PATH}/ai_assert.h ${HEADER_PATH}/camera.h ${HEADER_PATH}/color4.h diff --git a/code/PostProcessing/GenBoundingBoxesProcess.cpp b/code/PostProcessing/GenBoundingBoxesProcess.cpp new file mode 100644 index 000000000..c013454fc --- /dev/null +++ b/code/PostProcessing/GenBoundingBoxesProcess.cpp @@ -0,0 +1,115 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#ifndef ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS + +#include "PostProcessing/GenBoundingBoxesProcess.h" + +#include +#include + +namespace Assimp { + +GenBoundingBoxesProcess::GenBoundingBoxesProcess() +: BaseProcess() { + +} + +GenBoundingBoxesProcess::~GenBoundingBoxesProcess() { + // empty +} + +bool GenBoundingBoxesProcess::IsActive(unsigned int pFlags) const { + return 0 != ( pFlags & aiProcess_GenBoundingBoxes ); +} + +void checkMesh(aiMesh* mesh, aiVector3D& min, aiVector3D& max) { + ai_assert(nullptr != mesh); + + if (0 == mesh->mNumVertices) { + return; + } + + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + const aiVector3D &pos = mesh->mVertices[i]; + if (pos.x < min.x) { + min.x = pos.x; + } + if (pos.y < min.y) { + min.y = pos.y; + } + if (pos.z < min.z) { + min.z = pos.z; + } + + if (pos.x > max.x) { + max.x = pos.x; + } + if (pos.y > max.y) { + max.y = pos.y; + } + if (pos.z > max.z) { + max.z = pos.z; + } + } +} + +void GenBoundingBoxesProcess::Execute(aiScene* pScene) { + if (nullptr == pScene) { + return; + } + + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { + aiMesh* mesh = pScene->mMeshes[i]; + if (nullptr == mesh) { + continue; + } + + aiVector3D min(999999, 999999, 999999), max(-999999, -999999, -999999); + checkMesh(mesh, min, max); + mesh->mAABB.mMin = min; + mesh->mAABB.mMax = max; + } +} + +} // Namespace Assimp + +#endif // ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS diff --git a/code/PostProcessing/GenBoundingBoxesProcess.h b/code/PostProcessing/GenBoundingBoxesProcess.h new file mode 100644 index 000000000..433144e8e --- /dev/null +++ b/code/PostProcessing/GenBoundingBoxesProcess.h @@ -0,0 +1,61 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#pragma once + +#ifndef AI_GENBOUNDINGBOXESPROCESS_H_INC +#define AI_GENBOUNDINGBOXESPROCESS_H_INC + +#include "Common/BaseProcess.h" + +namespace Assimp { + +class GenBoundingBoxesProcess : public BaseProcess { +public: + GenBoundingBoxesProcess(); + ~GenBoundingBoxesProcess(); + bool IsActive(unsigned int pFlags) const override; + void Execute(aiScene* pScene) override; +}; + +} // Namespace Assimp + +#endif // AI_GENBOUNDINGBOXESPROCESS_H_INC diff --git a/include/assimp/camera.h b/include/assimp/camera.h index 99daf6993..dd45d90d1 100644 --- a/include/assimp/camera.h +++ b/include/assimp/camera.h @@ -162,7 +162,6 @@ struct aiCamera */ float mClipPlaneFar; - /** Screen aspect ratio. * * This is the ration between the width and the height of the diff --git a/include/assimp/defs.h b/include/assimp/defs.h index 2631263f5..af4615a1f 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -122,7 +122,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OPTIMIZEANIMS * OPTIMIZEGRAPH * GENENTITYMESHES - * FIXTEXTUREPATHS */ + * FIXTEXTUREPATHS + * GENBOUNDINGBOXES */ ////////////////////////////////////////////////////////////////////////// #ifdef _MSC_VER @@ -298,6 +299,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # else # define AI_NO_EXCEPT # endif -#endif +#endif // _MSC_VER #endif // !! AI_DEFINES_H_INC diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index 36f3ed2af..f1628f1f5 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -48,7 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_MESH_H_INC #define AI_MESH_H_INC -#include "types.h" +#include +#include #ifdef __cplusplus extern "C" { @@ -714,6 +715,11 @@ struct aiMesh * Method of morphing when animeshes are specified. */ unsigned int mMethod; + + /** + * + */ + C_STRUCT aiAABB mAABB; #ifdef __cplusplus @@ -735,7 +741,8 @@ struct aiMesh , mMaterialIndex( 0 ) , mNumAnimMeshes( 0 ) , mAnimMeshes(nullptr) - , mMethod( 0 ) { + , mMethod( 0 ) + , mAABB() { for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) { mNumUVComponents[a] = 0; mTextureCoords[a] = nullptr; diff --git a/include/assimp/postprocess.h b/include/assimp/postprocess.h index c23a5490a..2a7441421 100644 --- a/include/assimp/postprocess.h +++ b/include/assimp/postprocess.h @@ -438,7 +438,7 @@ enum aiPostProcessSteps aiProcess_FindInstances = 0x100000, // ------------------------------------------------------------------------- - /**
A postprocessing step to reduce the number of meshes. + /**
A post-processing step to reduce the number of meshes. * * This will, in fact, reduce the number of draw calls. * @@ -450,7 +450,7 @@ enum aiPostProcessSteps // ------------------------------------------------------------------------- - /**
A postprocessing step to optimize the scene hierarchy. + /**
A post-processing step to optimize the scene hierarchy. * * Nodes without animations, bones, lights or cameras assigned are * collapsed and joined. @@ -514,7 +514,7 @@ enum aiPostProcessSteps // ------------------------------------------------------------------------- /**
This step splits meshes with many bones into sub-meshes so that each - * su-bmesh has fewer or as many bones as a given limit. + * sub-mesh has fewer or as many bones as a given limit. */ aiProcess_SplitByBoneCount = 0x2000000, @@ -541,7 +541,7 @@ enum aiPostProcessSteps * global scaling from your importer settings like in FBX. Use the flag * AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY from the global property table to configure this. * - * Use #AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY to setup the global scaing factor. + * Use #AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY to setup the global scaling factor. */ aiProcess_GlobalScale = 0x8000000, @@ -574,6 +574,11 @@ enum aiPostProcessSteps * This process gives sense back to aiProcess_JoinIdenticalVertices */ aiProcess_DropNormals = 0x40000000, + + // ------------------------------------------------------------------------- + /** + */ + aiProcess_GenBoundingBoxes = 0x80000000 }; From 0f66a917e5a53f8b89591e6c71fd48730f8f52f7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 24 Jun 2019 21:37:53 +0200 Subject: [PATCH 6/7] Add unittest. --- code/CMakeLists.txt | 2 + code/Common/BaseProcess.cpp | 2 +- code/Common/PostStepRegistry.cpp | 7 ++ code/PostProcessing/GenBoundingBoxesProcess.h | 17 +++- code/PostProcessing/SplitLargeMeshes.h | 7 +- test/CMakeLists.txt | 1 + test/models/PLY/cube_test.ply | 2 +- test/unit/utGenBoundingBoxesProcess.cpp | 88 +++++++++++++++++++ 8 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 test/unit/utGenBoundingBoxesProcess.cpp diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 8668d4e6b..40840759b 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -669,6 +669,8 @@ SET( PostProcessing_SRCS PostProcessing/MakeVerboseFormat.h PostProcessing/ScaleProcess.cpp PostProcessing/ScaleProcess.h + PostProcessing/GenBoundingBoxesProcess.cpp + PostProcessing/GenBoundingBoxesProcess.h ) SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS}) diff --git a/code/Common/BaseProcess.cpp b/code/Common/BaseProcess.cpp index 18872c369..e247be418 100644 --- a/code/Common/BaseProcess.cpp +++ b/code/Common/BaseProcess.cpp @@ -89,7 +89,7 @@ void BaseProcess::ExecuteOnScene( Importer* pImp) // and kill the partially imported data delete pImp->Pimpl()->mScene; - pImp->Pimpl()->mScene = NULL; + pImp->Pimpl()->mScene = nullptr; } } diff --git a/code/Common/PostStepRegistry.cpp b/code/Common/PostStepRegistry.cpp index c08963817..ef58f8ddf 100644 --- a/code/Common/PostStepRegistry.cpp +++ b/code/Common/PostStepRegistry.cpp @@ -131,6 +131,10 @@ corresponding preprocessor flag to selectively disable steps. #if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS) # include "PostProcessing/ScaleProcess.h" #endif +#if (!defined ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS) +# include "PostProcessing/GenBoundingBoxesProcess.h" +#endif + namespace Assimp { @@ -246,6 +250,9 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out) #if (!defined ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS) out.push_back( new ImproveCacheLocalityProcess()); #endif +#if (!defined ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS) + out.push_back(new GenBoundingBoxesProcess); +#endif } } diff --git a/code/PostProcessing/GenBoundingBoxesProcess.h b/code/PostProcessing/GenBoundingBoxesProcess.h index 433144e8e..4b43c82a4 100644 --- a/code/PostProcessing/GenBoundingBoxesProcess.h +++ b/code/PostProcessing/GenBoundingBoxesProcess.h @@ -39,23 +39,38 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ +/** @file Defines a post-processing step to generate Axis-aligned bounding + * volumes for all meshes. + */ + #pragma once #ifndef AI_GENBOUNDINGBOXESPROCESS_H_INC #define AI_GENBOUNDINGBOXESPROCESS_H_INC +#ifndef ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS + #include "Common/BaseProcess.h" namespace Assimp { -class GenBoundingBoxesProcess : public BaseProcess { +/** Post-processing process to find axis-aligned bounding volumes for amm meshes + * used in a scene + */ +class ASSIMP_API GenBoundingBoxesProcess : public BaseProcess { public: + /// The class constructor. GenBoundingBoxesProcess(); + /// The class destructor. ~GenBoundingBoxesProcess(); + /// Will return true, if aiProcess_GenBoundingBoxes is defined. bool IsActive(unsigned int pFlags) const override; + /// The execution callback. void Execute(aiScene* pScene) override; }; } // Namespace Assimp +#endif // #ifndef ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS + #endif // AI_GENBOUNDINGBOXESPROCESS_H_INC diff --git a/code/PostProcessing/SplitLargeMeshes.h b/code/PostProcessing/SplitLargeMeshes.h index f683663b8..3f90576ea 100644 --- a/code/PostProcessing/SplitLargeMeshes.h +++ b/code/PostProcessing/SplitLargeMeshes.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -40,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ -/** @file Defines a post processing step to split large meshes into submeshes +/** @file Defines a post processing step to split large meshes into sub-meshes */ #ifndef AI_SPLITLARGEMESHES_H_INC #define AI_SPLITLARGEMESHES_H_INC @@ -51,10 +50,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +// Forward declarations class SplitLargeMeshesTest; -namespace Assimp -{ +namespace Assimp { class SplitLargeMeshesProcess_Triangle; class SplitLargeMeshesProcess_Vertex; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4db319725..737a34610 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -161,6 +161,7 @@ SET( POST_PROCESSES unit/utTargetAnimation.cpp unit/utSortByPType.cpp unit/utSceneCombiner.cpp + unit/utGenBoundingBoxesProcess.cpp ) SOURCE_GROUP( UnitTests\\Compiler FILES unit/CCompilerTest.c ) diff --git a/test/models/PLY/cube_test.ply b/test/models/PLY/cube_test.ply index 194798cf0..eef7cd426 100644 --- a/test/models/PLY/cube_test.ply +++ b/test/models/PLY/cube_test.ply @@ -1,6 +1,6 @@ ply format ascii 1.0 -comment Created by Open Asset Import Library - http://assimp.sf.net (v4.1.3945266037) +comment Created by Open Asset Import Library - http://assimp.sf.net (v4.1.649942190) element vertex 8 property float x property float y diff --git a/test/unit/utGenBoundingBoxesProcess.cpp b/test/unit/utGenBoundingBoxesProcess.cpp new file mode 100644 index 000000000..a26edb7e3 --- /dev/null +++ b/test/unit/utGenBoundingBoxesProcess.cpp @@ -0,0 +1,88 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" + +#include "PostProcessing/GenBoundingBoxesProcess.h" +#include +#include + +using namespace Assimp; + +class utGenBoundingBoxesProcess : public ::testing::Test { +public: + void SetUp() override { + mProcess = new GenBoundingBoxesProcess; + mMesh = new aiMesh(); + mMesh->mNumVertices = 100; + mMesh->mVertices = new aiVector3D[100]; + for (unsigned int i = 0; i < 100; ++i) { + mMesh->mVertices[i] = aiVector3D(i, i, i); + } + mScene = new aiScene(); + mScene->mNumMeshes = 1; + mScene->mMeshes = new aiMesh*[1]; + mScene->mMeshes[0] = mMesh; + } + + void TearDown() override { + delete mProcess; + delete mScene; + } + +protected: + GenBoundingBoxesProcess *mProcess; + aiMesh *mMesh; + aiScene* mScene; +}; + +TEST_F(utGenBoundingBoxesProcess, executeTest) { + mProcess->Execute(mScene); + + aiMesh* mesh = mScene->mMeshes[0]; + EXPECT_NE(nullptr, mesh); + EXPECT_EQ(0, mesh->mAABB.mMin.x); + EXPECT_EQ(0, mesh->mAABB.mMin.y); + EXPECT_EQ(0, mesh->mAABB.mMin.z); + + EXPECT_EQ(99, mesh->mAABB.mMax.x); + EXPECT_EQ(99, mesh->mAABB.mMax.y); + EXPECT_EQ(99, mesh->mAABB.mMax.z); +} From d7e442f78a02e6b00e0614985b85e3fb55a65ab1 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 24 Jun 2019 21:48:52 +0200 Subject: [PATCH 7/7] Add missing file. --- include/assimp/aabb.h | 76 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 include/assimp/aabb.h diff --git a/include/assimp/aabb.h b/include/assimp/aabb.h new file mode 100644 index 000000000..a20f31742 --- /dev/null +++ b/include/assimp/aabb.h @@ -0,0 +1,76 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#pragma once +#ifndef AI_AABB_H_INC +#define AI_AABB_H_INC + +#include + +struct aiAABB { + C_STRUCT aiVector3D mMin; + C_STRUCT aiVector3D mMax; + +#ifdef __cplusplus + + aiAABB() + : mMin() + , mMax() { + // empty + } + + aiAABB(const aiVector3D &min, const aiVector3D &max ) + : mMin(min) + , mMax(max) { + // empty + } + + ~aiAABB() { + // empty + } + +#endif +}; + + +#endif