diff options
Diffstat (limited to 'NvCloth/samples/external/assimp-4.1.0/code/ObjFileMtlImporter.cpp')
| -rw-r--r-- | NvCloth/samples/external/assimp-4.1.0/code/ObjFileMtlImporter.cpp | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/NvCloth/samples/external/assimp-4.1.0/code/ObjFileMtlImporter.cpp b/NvCloth/samples/external/assimp-4.1.0/code/ObjFileMtlImporter.cpp new file mode 100644 index 0000000..6ef655f --- /dev/null +++ b/NvCloth/samples/external/assimp-4.1.0/code/ObjFileMtlImporter.cpp @@ -0,0 +1,495 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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_OBJ_IMPORTER + +#include <stdlib.h> +#include "ObjFileMtlImporter.h" +#include "ObjTools.h" +#include "ObjFileData.h" +#include "fast_atof.h" +#include "ParsingUtils.h" +#include <assimp/material.h> +#include <assimp/DefaultLogger.hpp> + + +namespace Assimp { + +// Material specific token (case insensitive compare) +static const std::string DiffuseTexture = "map_Kd"; +static const std::string AmbientTexture = "map_Ka"; +static const std::string SpecularTexture = "map_Ks"; +static const std::string OpacityTexture = "map_d"; +static const std::string EmissiveTexture1 = "map_emissive"; +static const std::string EmissiveTexture2 = "map_Ke"; +static const std::string BumpTexture1 = "map_bump"; +static const std::string BumpTexture2 = "bump"; +static const std::string NormalTexture = "map_Kn"; +static const std::string ReflectionTexture = "refl"; +static const std::string DisplacementTexture1 = "map_disp"; +static const std::string DisplacementTexture2 = "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<char> &buffer, + const std::string &, + ObjFile::Model *pModel ) : + m_DataIt( buffer.begin() ), + m_DataItEnd( buffer.end() ), + m_pModel( pModel ), + m_uiLine( 0 ) +{ + ai_assert( NULL != m_pModel ); + if ( NULL == m_pModel->m_pDefaultMaterial ) + { + m_pModel->m_pDefaultMaterial = new ObjFile::Material; + m_pModel->m_pDefaultMaterial->MaterialName.Set( "default" ); + } + load(); +} + +// ------------------------------------------------------------------- +// Destructor +ObjFileMtlImporter::~ObjFileMtlImporter() +{ + // empty +} + +// ------------------------------------------------------------------- +// Private copy constructor +ObjFileMtlImporter::ObjFileMtlImporter(const ObjFileMtlImporter & ) +{ + // empty +} + +// ------------------------------------------------------------------- +// Private copy constructor +ObjFileMtlImporter &ObjFileMtlImporter::operator = ( const ObjFileMtlImporter & ) +{ + return *this; +} + +// ------------------------------------------------------------------- +// Loads the material description +void ObjFileMtlImporter::load() +{ + if ( m_DataIt == m_DataItEnd ) + return; + + while ( m_DataIt != m_DataItEnd ) + { + switch (*m_DataIt) + { + case 'k': + case 'K': + { + ++m_DataIt; + if (*m_DataIt == 'a') // Ambient color + { + ++m_DataIt; + getColorRGBA( &m_pModel->m_pCurrentMaterial->ambient ); + } + else if (*m_DataIt == 'd') // Diffuse color + { + ++m_DataIt; + getColorRGBA( &m_pModel->m_pCurrentMaterial->diffuse ); + } + else if (*m_DataIt == 's') + { + ++m_DataIt; + getColorRGBA( &m_pModel->m_pCurrentMaterial->specular ); + } + else if (*m_DataIt == 'e') + { + ++m_DataIt; + getColorRGBA( &m_pModel->m_pCurrentMaterial->emissive ); + } + m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); + } + break; + case 'T': + { + ++m_DataIt; + if (*m_DataIt == 'f') // Material transmission + { + ++m_DataIt; + getColorRGBA( &m_pModel->m_pCurrentMaterial->transparent); + } + m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); + } + break; + case 'd': + { + if( *(m_DataIt+1) == 'i' && *( m_DataIt + 2 ) == 's' && *( m_DataIt + 3 ) == 'p' ) { + // A displacement map + getTexture(); + } else { + // Alpha value + ++m_DataIt; + getFloatValue( m_pModel->m_pCurrentMaterial->alpha ); + m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); + } + } + break; + + case 'N': + case 'n': + { + ++m_DataIt; + switch(*m_DataIt) + { + case 's': // Specular exponent + ++m_DataIt; + getFloatValue(m_pModel->m_pCurrentMaterial->shineness); + break; + case 'i': // Index Of refraction + ++m_DataIt; + getFloatValue(m_pModel->m_pCurrentMaterial->ior); + break; + case 'e': // New material + createMaterial(); + break; + } + m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); + } + break; + + case 'm': // Texture + case 'b': // quick'n'dirty - for 'bump' sections + case 'r': // quick'n'dirty - for 'refl' sections + { + getTexture(); + m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); + } + break; + + case 'i': // Illumination model + { + m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); + getIlluminationModel( m_pModel->m_pCurrentMaterial->illumination_model ); + m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); + } + break; + + default: + { + m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); + } + break; + } + } +} + +// ------------------------------------------------------------------- +// Loads a color definition +void ObjFileMtlImporter::getColorRGBA( aiColor3D *pColor ) +{ + ai_assert( NULL != pColor ); + + ai_real r( 0.0 ), g( 0.0 ), b( 0.0 ); + m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, r ); + pColor->r = r; + + // we have to check if color is default 0 with only one token + if( !IsLineEnd( *m_DataIt ) ) { + m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, g ); + m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, b ); + } + pColor->g = g; + pColor->b = b; +} + +// ------------------------------------------------------------------- +// Loads the kind of illumination model. +void ObjFileMtlImporter::getIlluminationModel( int &illum_model ) +{ + m_DataIt = CopyNextWord<DataArrayIt>( m_DataIt, m_DataItEnd, m_buffer, BUFFERSIZE ); + illum_model = atoi(m_buffer); +} + +// ------------------------------------------------------------------- +// Loads a single float value. +void ObjFileMtlImporter::getFloatValue( ai_real &value ) +{ + m_DataIt = CopyNextWord<DataArrayIt>( m_DataIt, m_DataItEnd, m_buffer, BUFFERSIZE ); + value = (ai_real) fast_atof(m_buffer); +} + +// ------------------------------------------------------------------- +// Creates a material from loaded data. +void ObjFileMtlImporter::createMaterial() +{ + std::string line( "" ); + while( !IsLineEnd( *m_DataIt ) ) { + line += *m_DataIt; + ++m_DataIt; + } + + std::vector<std::string> token; + const unsigned int numToken = tokenize<std::string>( line, token, " \t" ); + std::string name( "" ); + if ( numToken == 1 ) { + name = AI_DEFAULT_MATERIAL_NAME; + } else { + // skip newmtl and all following white spaces + std::size_t first_ws_pos = line.find_first_of(" \t"); + std::size_t first_non_ws_pos = line.find_first_not_of(" \t", first_ws_pos); + if (first_non_ws_pos != std::string::npos) { + name = line.substr(first_non_ws_pos); + } + } + + name = trim_whitespaces(name); + + std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( name ); + if ( m_pModel->m_MaterialMap.end() == it) { + // New Material created + m_pModel->m_pCurrentMaterial = new ObjFile::Material(); + m_pModel->m_pCurrentMaterial->MaterialName.Set( name ); + if (m_pModel->m_pCurrentMesh) { + m_pModel->m_pCurrentMesh->m_uiMaterialIndex = static_cast<unsigned int>(m_pModel->m_MaterialLib.size() - 1); + } + m_pModel->m_MaterialLib.push_back( name ); + m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial; + } else { + // Use older material + m_pModel->m_pCurrentMaterial = (*it).second; + } +} + +// ------------------------------------------------------------------- +// 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(), static_cast<unsigned int>(DiffuseTexture.size()) ) ) { + // Diffuse texture + out = & m_pModel->m_pCurrentMaterial->texture; + clampIndex = ObjFile::Material::TextureDiffuseType; + } else if ( !ASSIMP_strincmp( pPtr,AmbientTexture.c_str(), static_cast<unsigned int>(AmbientTexture.size()) ) ) { + // Ambient texture + out = & m_pModel->m_pCurrentMaterial->textureAmbient; + clampIndex = ObjFile::Material::TextureAmbientType; + } else if ( !ASSIMP_strincmp( pPtr, SpecularTexture.c_str(), static_cast<unsigned int>(SpecularTexture.size()) ) ) { + // Specular texture + out = & m_pModel->m_pCurrentMaterial->textureSpecular; + clampIndex = ObjFile::Material::TextureSpecularType; + } else if ( !ASSIMP_strincmp( pPtr, OpacityTexture.c_str(), static_cast<unsigned int>(OpacityTexture.size()) ) ) { + // Opacity texture + out = & m_pModel->m_pCurrentMaterial->textureOpacity; + clampIndex = ObjFile::Material::TextureOpacityType; + } else if ( !ASSIMP_strincmp( pPtr, EmissiveTexture1.c_str(), static_cast<unsigned int>(EmissiveTexture1.size()) ) || + !ASSIMP_strincmp( pPtr, EmissiveTexture2.c_str(), static_cast<unsigned int>(EmissiveTexture2.size()) ) ) { + // Emissive texture + out = & m_pModel->m_pCurrentMaterial->textureEmissive; + clampIndex = ObjFile::Material::TextureEmissiveType; + } else if ( !ASSIMP_strincmp( pPtr, BumpTexture1.c_str(), static_cast<unsigned int>(BumpTexture1.size()) ) || + !ASSIMP_strincmp( pPtr, BumpTexture2.c_str(), static_cast<unsigned int>(BumpTexture2.size()) ) ) { + // Bump texture + out = & m_pModel->m_pCurrentMaterial->textureBump; + clampIndex = ObjFile::Material::TextureBumpType; + } else if ( !ASSIMP_strincmp( pPtr,NormalTexture.c_str(), static_cast<unsigned int>(NormalTexture.size()) ) ) { + // Normal map + out = & m_pModel->m_pCurrentMaterial->textureNormal; + clampIndex = ObjFile::Material::TextureNormalType; + } else if( !ASSIMP_strincmp( pPtr, ReflectionTexture.c_str(), static_cast<unsigned int>(ReflectionTexture.size()) ) ) { + // Reflection texture(s) + //Do nothing here + return; + } else if ( !ASSIMP_strincmp( pPtr, DisplacementTexture1.c_str(), static_cast<unsigned int>(DisplacementTexture1.size()) ) || + !ASSIMP_strincmp( pPtr, DisplacementTexture2.c_str(), static_cast<unsigned int>(DisplacementTexture2.size()) ) ) { + // Displacement texture + out = &m_pModel->m_pCurrentMaterial->textureDisp; + clampIndex = ObjFile::Material::TextureDispType; + } else if ( !ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(), static_cast<unsigned int>(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, clampIndex, out); + m_pModel->m_pCurrentMaterial->clamp[clampIndex] = clamp; + + std::string texture; + m_DataIt = getName<DataArrayIt>( m_DataIt, m_DataItEnd, texture ); + if ( NULL!=out ) { + out->Set( texture ); + } +} + +/* ///////////////////////////////////////////////////////////////////////////// + * 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, int &clampIndex, aiString *&out) { + m_DataIt = getNextToken<DataArrayIt>(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(), static_cast<unsigned int>(ClampOption.size()))) + { + DataArrayIt it = getNextToken<DataArrayIt>(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, TypeOption.c_str(), static_cast<unsigned int>(TypeOption.size()) ) ) + { + DataArrayIt it = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd ); + char value[ 12 ]; + CopyNextWord( it, m_DataItEnd, value, sizeof( value ) / sizeof( *value ) ); + if( !ASSIMP_strincmp( value, "cube_top", 8 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionCubeTopType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[0]; + } + else if( !ASSIMP_strincmp( value, "cube_bottom", 11 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionCubeBottomType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[1]; + } + else if( !ASSIMP_strincmp( value, "cube_front", 10 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionCubeFrontType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[2]; + } + else if( !ASSIMP_strincmp( value, "cube_back", 9 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionCubeBackType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[3]; + } + else if( !ASSIMP_strincmp( value, "cube_left", 9 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionCubeLeftType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[4]; + } + else if( !ASSIMP_strincmp( value, "cube_right", 10 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionCubeRightType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[5]; + } + else if( !ASSIMP_strincmp( value, "sphere", 6 ) ) + { + clampIndex = ObjFile::Material::TextureReflectionSphereType; + out = &m_pModel->m_pCurrentMaterial->textureReflection[0]; + } + + skipToken = 2; + } + else if (!ASSIMP_strincmp(pPtr, BlendUOption.c_str(), static_cast<unsigned int>(BlendUOption.size())) + || !ASSIMP_strincmp(pPtr, BlendVOption.c_str(), static_cast<unsigned int>(BlendVOption.size())) + || !ASSIMP_strincmp(pPtr, BoostOption.c_str(), static_cast<unsigned int>(BoostOption.size())) + || !ASSIMP_strincmp(pPtr, ResolutionOption.c_str(), static_cast<unsigned int>(ResolutionOption.size())) + || !ASSIMP_strincmp(pPtr, BumpOption.c_str(), static_cast<unsigned int>(BumpOption.size())) + || !ASSIMP_strincmp(pPtr, ChannelOption.c_str(), static_cast<unsigned int>(ChannelOption.size()))) + { + skipToken = 2; + } + else if (!ASSIMP_strincmp(pPtr, ModifyMapOption.c_str(), static_cast<unsigned int>(ModifyMapOption.size()))) + { + skipToken = 3; + } + else if ( !ASSIMP_strincmp(pPtr, OffsetOption.c_str(), static_cast<unsigned int>(OffsetOption.size())) + || !ASSIMP_strincmp(pPtr, ScaleOption.c_str(), static_cast<unsigned int>(ScaleOption.size())) + || !ASSIMP_strincmp(pPtr, TurbulenceOption.c_str(), static_cast<unsigned int>(TurbulenceOption.size())) + ) + { + skipToken = 4; + } + + for (int i = 0; i < skipToken; ++i) + { + m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); + } + } +} + +// ------------------------------------------------------------------- + +} // Namespace Assimp + +#endif // !! ASSIMP_BUILD_NO_OBJ_IMPORTER |