nuclear@0: /* nuclear@0: --------------------------------------------------------------------------- nuclear@0: Open Asset Import Library (assimp) nuclear@0: --------------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2012, assimp team nuclear@0: nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the following nuclear@0: conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: --------------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: #include "AssimpPCH.h" nuclear@0: #ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER nuclear@0: nuclear@0: #include "ObjFileMtlImporter.h" nuclear@0: #include "ObjTools.h" nuclear@0: #include "ObjFileData.h" nuclear@0: #include "fast_atof.h" nuclear@0: nuclear@0: namespace Assimp { nuclear@0: nuclear@0: // Material specific token nuclear@0: static const std::string DiffuseTexture = "map_kd"; nuclear@0: static const std::string AmbientTexture = "map_ka"; nuclear@0: static const std::string SpecularTexture = "map_ks"; nuclear@0: static const std::string OpacityTexture = "map_d"; nuclear@0: static const std::string BumpTexture1 = "map_bump"; nuclear@0: static const std::string BumpTexture2 = "map_Bump"; nuclear@0: static const std::string BumpTexture3 = "bump"; nuclear@0: static const std::string NormalTexture = "map_Kn"; nuclear@0: static const std::string DisplacementTexture = "disp"; nuclear@0: static const std::string SpecularityTexture = "map_ns"; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: // Constructor nuclear@0: ObjFileMtlImporter::ObjFileMtlImporter( std::vector &buffer, nuclear@0: const std::string & /*strAbsPath*/, nuclear@0: ObjFile::Model *pModel ) : nuclear@0: m_DataIt( buffer.begin() ), nuclear@0: m_DataItEnd( buffer.end() ), nuclear@0: m_pModel( pModel ), nuclear@0: m_uiLine( 0 ) nuclear@0: { nuclear@0: ai_assert( NULL != m_pModel ); nuclear@0: if ( NULL == m_pModel->m_pDefaultMaterial ) nuclear@0: { nuclear@0: m_pModel->m_pDefaultMaterial = new ObjFile::Material; nuclear@0: m_pModel->m_pDefaultMaterial->MaterialName.Set( "default" ); nuclear@0: } nuclear@0: load(); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: // Destructor nuclear@0: ObjFileMtlImporter::~ObjFileMtlImporter() nuclear@0: { nuclear@0: // empty nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: // Private copy constructor nuclear@0: ObjFileMtlImporter::ObjFileMtlImporter(const ObjFileMtlImporter & /* rOther */ ) nuclear@0: { nuclear@0: // empty nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: // Private copy constructor nuclear@0: ObjFileMtlImporter &ObjFileMtlImporter::operator = ( const ObjFileMtlImporter & /*rOther */ ) nuclear@0: { nuclear@0: return *this; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: // Loads the material description nuclear@0: void ObjFileMtlImporter::load() nuclear@0: { nuclear@0: if ( m_DataIt == m_DataItEnd ) nuclear@0: return; nuclear@0: nuclear@0: while ( m_DataIt != m_DataItEnd ) nuclear@0: { nuclear@0: switch (*m_DataIt) nuclear@0: { nuclear@0: case 'K': nuclear@0: { nuclear@0: ++m_DataIt; nuclear@0: if (*m_DataIt == 'a') // Ambient color nuclear@0: { nuclear@0: ++m_DataIt; nuclear@0: getColorRGBA( &m_pModel->m_pCurrentMaterial->ambient ); nuclear@0: } nuclear@0: else if (*m_DataIt == 'd') // Diffuse color nuclear@0: { nuclear@0: ++m_DataIt; nuclear@0: getColorRGBA( &m_pModel->m_pCurrentMaterial->diffuse ); nuclear@0: } nuclear@0: else if (*m_DataIt == 's') nuclear@0: { nuclear@0: ++m_DataIt; nuclear@0: getColorRGBA( &m_pModel->m_pCurrentMaterial->specular ); nuclear@0: } nuclear@0: m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case 'd': // Alpha value nuclear@0: { nuclear@0: ++m_DataIt; nuclear@0: getFloatValue( m_pModel->m_pCurrentMaterial->alpha ); nuclear@0: m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case 'N': // Shineness nuclear@0: { nuclear@0: ++m_DataIt; nuclear@0: switch(*m_DataIt) nuclear@0: { nuclear@0: case 's': nuclear@0: ++m_DataIt; nuclear@0: getFloatValue(m_pModel->m_pCurrentMaterial->shineness); nuclear@0: break; nuclear@0: case 'i': //Index Of refraction nuclear@0: ++m_DataIt; nuclear@0: getFloatValue(m_pModel->m_pCurrentMaterial->ior); nuclear@0: break; nuclear@0: } nuclear@0: m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); nuclear@0: break; nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: nuclear@0: case 'm': // Texture nuclear@0: case 'b': // quick'n'dirty - for 'bump' sections nuclear@0: { nuclear@0: getTexture(); nuclear@0: m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case 'n': // New material name nuclear@0: { nuclear@0: createMaterial(); nuclear@0: m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case 'i': // Illumination model nuclear@0: { nuclear@0: m_DataIt = getNextToken(m_DataIt, m_DataItEnd); nuclear@0: getIlluminationModel( m_pModel->m_pCurrentMaterial->illumination_model ); nuclear@0: m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: default: nuclear@0: { nuclear@0: m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); nuclear@0: } nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: // Loads a color definition nuclear@0: void ObjFileMtlImporter::getColorRGBA( aiColor3D *pColor ) nuclear@0: { nuclear@0: ai_assert( NULL != pColor ); nuclear@0: nuclear@0: float r, g, b; nuclear@0: m_DataIt = getFloat( m_DataIt, m_DataItEnd, r ); nuclear@0: pColor->r = r; nuclear@0: nuclear@0: m_DataIt = getFloat( m_DataIt, m_DataItEnd, g ); nuclear@0: pColor->g = g; nuclear@0: nuclear@0: m_DataIt = getFloat( m_DataIt, m_DataItEnd, b ); nuclear@0: pColor->b = b; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: // Loads the kind of illumination model. nuclear@0: void ObjFileMtlImporter::getIlluminationModel( int &illum_model ) nuclear@0: { nuclear@0: m_DataIt = CopyNextWord( m_DataIt, m_DataItEnd, m_buffer, BUFFERSIZE ); nuclear@0: illum_model = atoi(m_buffer); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: // Loads a single float value. nuclear@0: void ObjFileMtlImporter::getFloatValue( float &value ) nuclear@0: { nuclear@0: m_DataIt = CopyNextWord( m_DataIt, m_DataItEnd, m_buffer, BUFFERSIZE ); nuclear@0: value = (float) fast_atof(m_buffer); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: // Creates a material from loaded data. nuclear@0: void ObjFileMtlImporter::createMaterial() nuclear@0: { nuclear@0: std::string line( "" ); nuclear@0: while ( !isNewLine( *m_DataIt ) ) { nuclear@0: line += *m_DataIt; nuclear@0: ++m_DataIt; nuclear@0: } nuclear@0: nuclear@0: std::vector token; nuclear@0: const unsigned int numToken = tokenize( line, token, " " ); nuclear@0: std::string name( "" ); nuclear@0: if ( numToken == 1 ) { nuclear@0: name = AI_DEFAULT_MATERIAL_NAME; nuclear@0: } else { nuclear@0: name = token[ 1 ]; nuclear@0: } nuclear@0: nuclear@0: std::map::iterator it = m_pModel->m_MaterialMap.find( name ); nuclear@0: if ( m_pModel->m_MaterialMap.end() == it) { nuclear@0: // New Material created nuclear@0: m_pModel->m_pCurrentMaterial = new ObjFile::Material(); nuclear@0: m_pModel->m_pCurrentMaterial->MaterialName.Set( name ); nuclear@0: m_pModel->m_MaterialLib.push_back( name ); nuclear@0: m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial; nuclear@0: } else { nuclear@0: // Use older material nuclear@0: m_pModel->m_pCurrentMaterial = (*it).second; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: // Gets a texture name from data. nuclear@0: void ObjFileMtlImporter::getTexture() { nuclear@0: aiString *out( NULL ); nuclear@0: nuclear@0: const char *pPtr( &(*m_DataIt) ); nuclear@0: if ( !ASSIMP_strincmp( pPtr, DiffuseTexture.c_str(), DiffuseTexture.size() ) ) { nuclear@0: // Diffuse texture nuclear@0: out = & m_pModel->m_pCurrentMaterial->texture; nuclear@0: } else if ( !ASSIMP_strincmp( pPtr,AmbientTexture.c_str(),AmbientTexture.size() ) ) { nuclear@0: // Ambient texture nuclear@0: out = & m_pModel->m_pCurrentMaterial->textureAmbient; nuclear@0: } else if (!ASSIMP_strincmp( pPtr, SpecularTexture.c_str(), SpecularTexture.size())) { nuclear@0: // Specular texture nuclear@0: out = & m_pModel->m_pCurrentMaterial->textureSpecular; nuclear@0: } else if ( !ASSIMP_strincmp( pPtr, OpacityTexture.c_str(), OpacityTexture.size() ) ) { nuclear@0: // Opacity texture nuclear@0: out = & m_pModel->m_pCurrentMaterial->textureOpacity; nuclear@0: } else if (!ASSIMP_strincmp( pPtr,"map_ka",6)) { nuclear@0: // Ambient texture nuclear@0: out = & m_pModel->m_pCurrentMaterial->textureAmbient; nuclear@0: } else if ( !ASSIMP_strincmp( pPtr, BumpTexture1.c_str(), BumpTexture1.size() ) || nuclear@0: !ASSIMP_strincmp( pPtr, BumpTexture2.c_str(), BumpTexture2.size() ) || nuclear@0: !ASSIMP_strincmp( pPtr, BumpTexture3.c_str(), BumpTexture3.size() ) ) { nuclear@0: // Bump texture nuclear@0: out = & m_pModel->m_pCurrentMaterial->textureBump; nuclear@0: } else if (!ASSIMP_strincmp( pPtr,NormalTexture.c_str(), NormalTexture.size())) { nuclear@0: // Normal map nuclear@0: out = & m_pModel->m_pCurrentMaterial->textureNormal; nuclear@0: } else if (!ASSIMP_strincmp( pPtr, DisplacementTexture.c_str(), DisplacementTexture.size() ) ) { nuclear@0: // Displacement texture nuclear@0: out = &m_pModel->m_pCurrentMaterial->textureDisp; nuclear@0: } else if (!ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(),SpecularityTexture.size() ) ) { nuclear@0: // Specularity scaling (glossiness) nuclear@0: out = & m_pModel->m_pCurrentMaterial->textureSpecularity; nuclear@0: } else { nuclear@0: DefaultLogger::get()->error("OBJ/MTL: Encountered unknown texture type"); nuclear@0: return; nuclear@0: } nuclear@0: nuclear@0: std::string strTexture; nuclear@0: m_DataIt = getName( m_DataIt, m_DataItEnd, strTexture ); nuclear@0: out->Set( strTexture ); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: nuclear@0: } // Namespace Assimp nuclear@0: nuclear@0: #endif // !! ASSIMP_BUILD_NO_OBJ_IMPORTER