diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c0ed133c..037f9c43a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,9 +66,12 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${C configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) -# add make uninstall capability -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) -add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") +# Only generate this target if no higher-level project already has +IF (NOT TARGET uninstall) + # add make uninstall capability + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) + add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") +ENDIF() # Globally enbale Boost resp. the Boost workaround – it is also needed by the # tools which include the Assimp headers. diff --git a/cmake-modules/PrecompiledHeader.cmake b/cmake-modules/PrecompiledHeader.cmake index 07879f466..99c43a3cb 100644 --- a/cmake-modules/PrecompiledHeader.cmake +++ b/cmake-modules/PrecompiledHeader.cmake @@ -1,7 +1,7 @@ MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar) IF(MSVC) GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE) - SET(PrecompiledBinary "${CMAKE_CURRENT_BINARY_DIR}/${PrecompiledBasename}.pch") + SET(PrecompiledBinary "${CMAKE_CFG_INTDIR}/${PrecompiledBasename}.pch") SET(Sources ${${SourcesVar}}) SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource} diff --git a/code/ObjFileData.h b/code/ObjFileData.h index 7b30efe2e..7b2b6cf12 100755 --- a/code/ObjFileData.h +++ b/code/ObjFileData.h @@ -161,6 +161,19 @@ struct Material aiString textureSpecularity; aiString textureOpacity; aiString textureDisp; + enum TextureType + { + TextureDiffuseType = 0, + TextureSpecularType, + TextureAmbientType, + TextureBumpType, + TextureNormalType, + TextureSpecularityType, + TextureOpacityType, + TextureDispType, + TextureTypeCount + }; + bool clamp[TextureTypeCount]; //! Ambient color aiColor3D ambient; @@ -186,6 +199,10 @@ struct Material , ior (1.f) { // empty + for (size_t i = 0; i < TextureTypeCount; ++i) + { + clamp[i] = false; + } } // Destructor diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index 14c8e8aff..13dfee203 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -484,6 +484,15 @@ void ObjFileImporter::countObjects(const std::vector &rObjects } } +// ------------------------------------------------------------------------------------------------ +// Add clamp mode property to material if necessary +void ObjFileImporter::addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode) +{ + ai_assert( NULL != mat); + mat->AddProperty(&clampMode, 1, AI_MATKEY_MAPPINGMODE_U(type, 0)); + mat->AddProperty(&clampMode, 1, AI_MATKEY_MAPPINGMODE_V(type, 0)); +} + // ------------------------------------------------------------------------------------------------ // Creates the material void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pScene ) @@ -548,29 +557,77 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc mat->AddProperty( &pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI ); // Adding textures - if ( 0 != pCurrentMaterial->texture.length ) + if ( 0 != pCurrentMaterial->texture.length ) + { mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0)); + if (pCurrentMaterial->clamp[ObjFile::Material::TextureDiffuseType]) + { + addTextureMappingModeProperty(mat, aiTextureType_DIFFUSE); + } + } if ( 0 != pCurrentMaterial->textureAmbient.length ) + { mat->AddProperty( &pCurrentMaterial->textureAmbient, AI_MATKEY_TEXTURE_AMBIENT(0)); + if (pCurrentMaterial->clamp[ObjFile::Material::TextureAmbientType]) + { + addTextureMappingModeProperty(mat, aiTextureType_AMBIENT); + } + } if ( 0 != pCurrentMaterial->textureSpecular.length ) + { mat->AddProperty( &pCurrentMaterial->textureSpecular, AI_MATKEY_TEXTURE_SPECULAR(0)); + if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularType]) + { + addTextureMappingModeProperty(mat, aiTextureType_SPECULAR); + } + } if ( 0 != pCurrentMaterial->textureBump.length ) + { mat->AddProperty( &pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0)); + if (pCurrentMaterial->clamp[ObjFile::Material::TextureBumpType]) + { + addTextureMappingModeProperty(mat, aiTextureType_HEIGHT); + } + } if ( 0 != pCurrentMaterial->textureNormal.length ) + { mat->AddProperty( &pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0)); + if (pCurrentMaterial->clamp[ObjFile::Material::TextureNormalType]) + { + addTextureMappingModeProperty(mat, aiTextureType_NORMALS); + } + } if ( 0 != pCurrentMaterial->textureDisp.length ) + { mat->AddProperty( &pCurrentMaterial->textureDisp, AI_MATKEY_TEXTURE_DISPLACEMENT(0) ); + if (pCurrentMaterial->clamp[ObjFile::Material::TextureDispType]) + { + addTextureMappingModeProperty(mat, aiTextureType_DISPLACEMENT); + } + } if ( 0 != pCurrentMaterial->textureOpacity.length ) + { mat->AddProperty( &pCurrentMaterial->textureOpacity, AI_MATKEY_TEXTURE_OPACITY(0)); + if (pCurrentMaterial->clamp[ObjFile::Material::TextureOpacityType]) + { + addTextureMappingModeProperty(mat, aiTextureType_OPACITY); + } + } if ( 0 != pCurrentMaterial->textureSpecularity.length ) + { mat->AddProperty( &pCurrentMaterial->textureSpecularity, AI_MATKEY_TEXTURE_SHININESS(0)); + if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularityType]) + { + addTextureMappingModeProperty(mat, aiTextureType_SHININESS); + } + } // Store material property info in material array in scene pScene->mMaterials[ pScene->mNumMaterials ] = mat; diff --git a/code/ObjFileImporter.h b/code/ObjFileImporter.h index ca931088a..814a65652 100644 --- a/code/ObjFileImporter.h +++ b/code/ObjFileImporter.h @@ -103,6 +103,7 @@ private: //! \brief Material creation. void createMaterials(const ObjFile::Model* pModel, aiScene* pScene); + void addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode = 1); //! \brief Appends a child node to a parent node and updates the data structures. void appendChildToParentNode(aiNode *pParent, aiNode *pChild); diff --git a/code/ObjFileMtlImporter.cpp b/code/ObjFileMtlImporter.cpp index c6816577d..f0d2f1795 100644 --- a/code/ObjFileMtlImporter.cpp +++ b/code/ObjFileMtlImporter.cpp @@ -61,6 +61,22 @@ static const std::string NormalTexture = "map_Kn"; static const std::string DisplacementTexture = "disp"; static const std::string SpecularityTexture = "map_ns"; +// texture option specific token +static const std::string BlendUOption = "-blendu"; +static const std::string BlendVOption = "-blendv"; +static const std::string BoostOption = "-boost"; +static const std::string ModifyMapOption = "-mm"; +static const std::string OffsetOption = "-o"; +static const std::string ScaleOption = "-s"; +static const std::string TurbulenceOption = "-t"; +static const std::string ResolutionOption = "-texres"; +static const std::string ClampOption = "-clamp"; +static const std::string BumpOption = "-bm"; +static const std::string ChannelOption = "-imfchan"; +static const std::string TypeOption = "-type"; + + + // ------------------------------------------------------------------- // Constructor ObjFileMtlImporter::ObjFileMtlImporter( std::vector &buffer, @@ -263,47 +279,128 @@ void ObjFileMtlImporter::createMaterial() // Gets a texture name from data. void ObjFileMtlImporter::getTexture() { aiString *out( NULL ); + int clampIndex = -1; const char *pPtr( &(*m_DataIt) ); if ( !ASSIMP_strincmp( pPtr, DiffuseTexture.c_str(), DiffuseTexture.size() ) ) { // Diffuse texture out = & m_pModel->m_pCurrentMaterial->texture; + clampIndex = ObjFile::Material::TextureDiffuseType; } else if ( !ASSIMP_strincmp( pPtr,AmbientTexture.c_str(),AmbientTexture.size() ) ) { // Ambient texture out = & m_pModel->m_pCurrentMaterial->textureAmbient; + clampIndex = ObjFile::Material::TextureAmbientType; } else if (!ASSIMP_strincmp( pPtr, SpecularTexture.c_str(), SpecularTexture.size())) { // Specular texture out = & m_pModel->m_pCurrentMaterial->textureSpecular; + clampIndex = ObjFile::Material::TextureSpecularType; } else if ( !ASSIMP_strincmp( pPtr, OpacityTexture.c_str(), OpacityTexture.size() ) ) { // Opacity texture out = & m_pModel->m_pCurrentMaterial->textureOpacity; + clampIndex = ObjFile::Material::TextureOpacityType; } else if (!ASSIMP_strincmp( pPtr,"map_ka",6)) { // Ambient texture out = & m_pModel->m_pCurrentMaterial->textureAmbient; + clampIndex = ObjFile::Material::TextureAmbientType; } else if ( !ASSIMP_strincmp( pPtr, BumpTexture1.c_str(), BumpTexture1.size() ) || !ASSIMP_strincmp( pPtr, BumpTexture2.c_str(), BumpTexture2.size() ) || !ASSIMP_strincmp( pPtr, BumpTexture3.c_str(), BumpTexture3.size() ) ) { // Bump texture out = & m_pModel->m_pCurrentMaterial->textureBump; + clampIndex = ObjFile::Material::TextureBumpType; } else if (!ASSIMP_strincmp( pPtr,NormalTexture.c_str(), NormalTexture.size())) { // Normal map out = & m_pModel->m_pCurrentMaterial->textureNormal; + clampIndex = ObjFile::Material::TextureNormalType; } else if (!ASSIMP_strincmp( pPtr, DisplacementTexture.c_str(), DisplacementTexture.size() ) ) { // Displacement texture out = &m_pModel->m_pCurrentMaterial->textureDisp; + clampIndex = ObjFile::Material::TextureDispType; } else if (!ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(),SpecularityTexture.size() ) ) { // Specularity scaling (glossiness) out = & m_pModel->m_pCurrentMaterial->textureSpecularity; + clampIndex = ObjFile::Material::TextureSpecularityType; } else { DefaultLogger::get()->error("OBJ/MTL: Encountered unknown texture type"); return; } + bool clamp = false; + getTextureOption(clamp); + m_pModel->m_pCurrentMaterial->clamp[clampIndex] = clamp; + std::string strTexture; m_DataIt = getName( m_DataIt, m_DataItEnd, strTexture ); out->Set( strTexture ); } +/* ///////////////////////////////////////////////////////////////////////////// + * Texture Option + * ///////////////////////////////////////////////////////////////////////////// + * According to http://en.wikipedia.org/wiki/Wavefront_.obj_file#Texture_options + * Texture map statement can contains various texture option, for example: + * + * map_Ka -o 1 1 1 some.png + * map_Kd -clamp on some.png + * + * So we need to parse and skip these options, and leave the last part which is + * the url of image, otherwise we will get a wrong url like "-clamp on some.png". + * + * Because aiMaterial supports clamp option, so we also want to return it + * ///////////////////////////////////////////////////////////////////////////// + */ +void ObjFileMtlImporter::getTextureOption(bool &clamp) +{ + m_DataIt = getNextToken(m_DataIt, m_DataItEnd); + + //If there is any more texture option + while (!isEndOfBuffer(m_DataIt, m_DataItEnd) && *m_DataIt == '-') + { + const char *pPtr( &(*m_DataIt) ); + //skip option key and value + int skipToken = 1; + + if (!ASSIMP_strincmp(pPtr, ClampOption.c_str(), ClampOption.size())) + { + DataArrayIt it = getNextToken(m_DataIt, m_DataItEnd); + char value[3]; + CopyNextWord(it, m_DataItEnd, value, sizeof(value) / sizeof(*value)); + if (!ASSIMP_strincmp(value, "on", 2)) + { + clamp = true; + } + + skipToken = 2; + } + else if ( !ASSIMP_strincmp(pPtr, BlendUOption.c_str(), BlendUOption.size()) + || !ASSIMP_strincmp(pPtr, BlendVOption.c_str(), BlendVOption.size()) + || !ASSIMP_strincmp(pPtr, BoostOption.c_str(), BoostOption.size()) + || !ASSIMP_strincmp(pPtr, ResolutionOption.c_str(), ResolutionOption.size()) + || !ASSIMP_strincmp(pPtr, BumpOption.c_str(), BumpOption.size()) + || !ASSIMP_strincmp(pPtr, ChannelOption.c_str(), ChannelOption.size()) + || !ASSIMP_strincmp(pPtr, TypeOption.c_str(), TypeOption.size()) ) + { + skipToken = 2; + } + else if (!ASSIMP_strincmp(pPtr, ModifyMapOption.c_str(), ModifyMapOption.size())) + { + skipToken = 3; + } + else if ( !ASSIMP_strincmp(pPtr, OffsetOption.c_str(), OffsetOption.size()) + || !ASSIMP_strincmp(pPtr, ScaleOption.c_str(), ScaleOption.size()) + || !ASSIMP_strincmp(pPtr, TurbulenceOption.c_str(), TurbulenceOption.size()) + ) + { + skipToken = 4; + } + + for (int i = 0; i < skipToken; ++i) + { + m_DataIt = getNextToken(m_DataIt, m_DataItEnd); + } + } +} + // ------------------------------------------------------------------- } // Namespace Assimp diff --git a/code/ObjFileMtlImporter.h b/code/ObjFileMtlImporter.h index a2111194d..67609b41b 100644 --- a/code/ObjFileMtlImporter.h +++ b/code/ObjFileMtlImporter.h @@ -92,6 +92,7 @@ private: void createMaterial(); /// Get texture name from loaded data. void getTexture(); + void getTextureOption(bool &clamp); private: //! Absolute pathname diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index ef3deb20f..02b95ee64 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -149,9 +149,12 @@ void ObjFileParser::parseFile() } break; - case 'm': // Parse a material library + case 'm': // Parse a material library or merging group ('mg') { - getMaterialLib(); + if (*(m_DataIt + 1) == 'g') + getGroupNumberAndResolution(); + else + getMaterialLib(); } break; @@ -609,6 +612,15 @@ void ObjFileParser::getGroupNumber() m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } +// ------------------------------------------------------------------- +// Not supported +void ObjFileParser::getGroupNumberAndResolution() +{ + // Not used + + m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); +} + // ------------------------------------------------------------------- // Stores values for a new object instance, name will be used to // identify it. diff --git a/code/ObjFileParser.h b/code/ObjFileParser.h index 1a9a1b498..c5effcfed 100644 --- a/code/ObjFileParser.h +++ b/code/ObjFileParser.h @@ -102,6 +102,8 @@ private: void getGroupName(); /// Gets the group number from file. void getGroupNumber(); + /// Gets the group number and resolution from file. + void getGroupNumberAndResolution(); /// Returns the index of the material. Is -1 if not material was found. int getMaterialIndex( const std::string &strMaterialName ); /// Parse object name diff --git a/code/ObjTools.h b/code/ObjTools.h index 41de3f61f..7a9a57769 100644 --- a/code/ObjTools.h +++ b/code/ObjTools.h @@ -157,7 +157,6 @@ template inline char_t getName( char_t it, char_t end, std::string &name ) { name = ""; - it = getNextToken( it, end ); if ( isEndOfBuffer( it, end ) ) return end; diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index 39c6ac9cd..ebd320c1a 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -153,8 +153,8 @@ void STLImporter::InternReadFile( const std::string& pFile, this->pScene = pScene; this->mBuffer = &mBuffer2[0]; - // the default vertex color is white - clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = 1.0f; + // the default vertex color is light gray. + clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = 0.6f; // allocate one mesh pScene->mNumMeshes = 1; @@ -189,13 +189,14 @@ void STLImporter::InternReadFile( const std::string& pFile, } } - // create a single default material - everything white, as we have vertex colors + // create a single default material, using a light gray diffuse color for consistency with + // other geometric types (e.g., PLY). aiMaterial* pcMat = new aiMaterial(); aiString s; s.Set(AI_DEFAULT_MATERIAL_NAME); pcMat->AddProperty(&s, AI_MATKEY_NAME); - aiColor4D clrDiffuse(1.0f,1.0f,1.0f,1.0f); + aiColor4D clrDiffuse(0.6f,0.6f,0.6f,1.0f); if (bMatClr) { clrDiffuse = clrColorDefault; } diff --git a/test/models/BLEND/BlenderDefault_269.blend b/test/models/BLEND/BlenderDefault_269.blend new file mode 100644 index 000000000..ed4352f4d Binary files /dev/null and b/test/models/BLEND/BlenderDefault_269.blend differ diff --git a/test/models/BLEND/blender_269_regress1.blend b/test/models/BLEND/blender_269_regress1.blend new file mode 100644 index 000000000..f8ecf7483 Binary files /dev/null and b/test/models/BLEND/blender_269_regress1.blend differ