vrshoot

diff libs/assimp/ObjFileParser.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libs/assimp/ObjFileParser.cpp	Sat Feb 01 19:58:19 2014 +0200
     1.3 @@ -0,0 +1,679 @@
     1.4 +/*
     1.5 +---------------------------------------------------------------------------
     1.6 +Open Asset Import Library (assimp)
     1.7 +---------------------------------------------------------------------------
     1.8 +
     1.9 +Copyright (c) 2006-2012, assimp team
    1.10 +
    1.11 +All rights reserved.
    1.12 +
    1.13 +Redistribution and use of this software in source and binary forms, 
    1.14 +with or without modification, are permitted provided that the following 
    1.15 +conditions are met:
    1.16 +
    1.17 +* Redistributions of source code must retain the above
    1.18 +  copyright notice, this list of conditions and the
    1.19 +  following disclaimer.
    1.20 +
    1.21 +* Redistributions in binary form must reproduce the above
    1.22 +  copyright notice, this list of conditions and the
    1.23 +  following disclaimer in the documentation and/or other
    1.24 +  materials provided with the distribution.
    1.25 +
    1.26 +* Neither the name of the assimp team, nor the names of its
    1.27 +  contributors may be used to endorse or promote products
    1.28 +  derived from this software without specific prior
    1.29 +  written permission of the assimp team.
    1.30 +
    1.31 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    1.32 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    1.33 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.34 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    1.35 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.36 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    1.37 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.38 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
    1.39 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    1.40 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    1.41 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.42 +---------------------------------------------------------------------------
    1.43 +*/
    1.44 +
    1.45 +#include "AssimpPCH.h"
    1.46 +#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
    1.47 +
    1.48 +#include "ObjFileParser.h"
    1.49 +#include "ObjFileMtlImporter.h"
    1.50 +#include "ObjTools.h"
    1.51 +#include "ObjFileData.h"
    1.52 +#include "ParsingUtils.h"
    1.53 +#include "assimp/types.h"
    1.54 +#include "DefaultIOSystem.h"
    1.55 +
    1.56 +namespace Assimp	
    1.57 +{
    1.58 +
    1.59 +// -------------------------------------------------------------------
    1.60 +const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME; 
    1.61 +
    1.62 +// -------------------------------------------------------------------
    1.63 +//	Constructor with loaded data and directories.
    1.64 +ObjFileParser::ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem *io ) :
    1.65 +	m_DataIt(Data.begin()),
    1.66 +	m_DataItEnd(Data.end()),
    1.67 +	m_pModel(NULL),
    1.68 +	m_uiLine(0),
    1.69 +	m_pIO( io )
    1.70 +{
    1.71 +	std::fill_n(m_buffer,BUFFERSIZE,0);
    1.72 +
    1.73 +	// Create the model instance to store all the data
    1.74 +	m_pModel = new ObjFile::Model();
    1.75 +	m_pModel->m_ModelName = strModelName;
    1.76 +	
    1.77 +	m_pModel->m_pDefaultMaterial = new ObjFile::Material();
    1.78 +	m_pModel->m_pDefaultMaterial->MaterialName.Set( DEFAULT_MATERIAL );
    1.79 +	m_pModel->m_MaterialLib.push_back( DEFAULT_MATERIAL );
    1.80 +	m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial;
    1.81 +	
    1.82 +	// Start parsing the file
    1.83 +	parseFile();
    1.84 +}
    1.85 +
    1.86 +// -------------------------------------------------------------------
    1.87 +//	Destructor
    1.88 +ObjFileParser::~ObjFileParser()
    1.89 +{
    1.90 +	/*delete m_pModel->m_pDefaultMaterial;
    1.91 +	m_pModel->m_pDefaultMaterial = NULL;*/
    1.92 +
    1.93 +	delete m_pModel;
    1.94 +	m_pModel = NULL;
    1.95 +}
    1.96 +
    1.97 +// -------------------------------------------------------------------
    1.98 +//	Returns a pointer to the model instance.
    1.99 +ObjFile::Model *ObjFileParser::GetModel() const
   1.100 +{
   1.101 +	return m_pModel;
   1.102 +}
   1.103 +
   1.104 +// -------------------------------------------------------------------
   1.105 +//	File parsing method.
   1.106 +void ObjFileParser::parseFile()
   1.107 +{
   1.108 +	if (m_DataIt == m_DataItEnd)
   1.109 +		return;
   1.110 +
   1.111 +	while (m_DataIt != m_DataItEnd)
   1.112 +	{
   1.113 +		switch (*m_DataIt)
   1.114 +		{
   1.115 +		case 'v': // Parse a vertex texture coordinate
   1.116 +			{
   1.117 +				++m_DataIt;
   1.118 +				if (*m_DataIt == ' ')
   1.119 +				{
   1.120 +					// Read in vertex definition
   1.121 +					getVector3(m_pModel->m_Vertices);
   1.122 +				}
   1.123 +				else if (*m_DataIt == 't')
   1.124 +				{
   1.125 +					// Read in texture coordinate (2D)
   1.126 +					++m_DataIt;
   1.127 +					getVector2(m_pModel->m_TextureCoord);
   1.128 +				}
   1.129 +				else if (*m_DataIt == 'n')
   1.130 +				{
   1.131 +					// Read in normal vector definition
   1.132 +					++m_DataIt;
   1.133 +					getVector3( m_pModel->m_Normals );
   1.134 +				}
   1.135 +			}
   1.136 +			break;
   1.137 +
   1.138 +		case 'p': // Parse a face, line or point statement
   1.139 +		case 'l':
   1.140 +		case 'f':
   1.141 +			{
   1.142 +				getFace(*m_DataIt == 'f' ? aiPrimitiveType_POLYGON : (*m_DataIt == 'l' 
   1.143 +					? aiPrimitiveType_LINE : aiPrimitiveType_POINT));
   1.144 +			}
   1.145 +			break;
   1.146 +
   1.147 +		case '#': // Parse a comment
   1.148 +			{
   1.149 +				getComment();
   1.150 +			}
   1.151 +			break;
   1.152 +
   1.153 +		case 'u': // Parse a material desc. setter
   1.154 +			{
   1.155 +				getMaterialDesc();
   1.156 +			}
   1.157 +			break;
   1.158 +
   1.159 +		case 'm': // Parse a material library
   1.160 +			{
   1.161 +				getMaterialLib();
   1.162 +			}
   1.163 +			break;
   1.164 +
   1.165 +		case 'g': // Parse group name
   1.166 +			{
   1.167 +				getGroupName();
   1.168 +			}
   1.169 +			break;
   1.170 +
   1.171 +		case 's': // Parse group number
   1.172 +			{
   1.173 +				getGroupNumber();
   1.174 +			}
   1.175 +			break;
   1.176 +
   1.177 +		case 'o': // Parse object name
   1.178 +			{
   1.179 +				getObjectName();
   1.180 +			}
   1.181 +			break;
   1.182 +		
   1.183 +		default:
   1.184 +			{
   1.185 +				m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
   1.186 +			}
   1.187 +			break;
   1.188 +		}
   1.189 +	}
   1.190 +}
   1.191 +
   1.192 +// -------------------------------------------------------------------
   1.193 +//	Copy the next word in a temporary buffer
   1.194 +void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
   1.195 +{
   1.196 +	size_t index = 0;
   1.197 +	m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
   1.198 +	while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
   1.199 +	{
   1.200 +		pBuffer[index] = *m_DataIt;
   1.201 +		index++;
   1.202 +		if (index == length-1)
   1.203 +			break;
   1.204 +		++m_DataIt;
   1.205 +	}
   1.206 +	pBuffer[index] = '\0';
   1.207 +}
   1.208 +
   1.209 +// -------------------------------------------------------------------
   1.210 +// Copy the next line into a temporary buffer
   1.211 +void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
   1.212 +{
   1.213 +	size_t index = 0;
   1.214 +	while (m_DataIt != m_DataItEnd)
   1.215 +	{
   1.216 +		if (*m_DataIt == '\n' || *m_DataIt == '\r' || index == length-1)
   1.217 +			break;
   1.218 +
   1.219 +		pBuffer[ index ] = *m_DataIt;
   1.220 +		++index;
   1.221 +		++m_DataIt;
   1.222 +	}
   1.223 +	pBuffer[ index ] = '\0';
   1.224 +}
   1.225 +
   1.226 +// -------------------------------------------------------------------
   1.227 +//	Get values for a new 3D vector instance
   1.228 +void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array)
   1.229 +{
   1.230 +	float x, y, z;
   1.231 +	copyNextWord(m_buffer, BUFFERSIZE);
   1.232 +	x = (float) fast_atof(m_buffer);	
   1.233 +	
   1.234 +	copyNextWord(m_buffer, BUFFERSIZE);
   1.235 +	y = (float) fast_atof(m_buffer);
   1.236 +
   1.237 +	copyNextWord(m_buffer, BUFFERSIZE);
   1.238 +	z = (float) fast_atof(m_buffer);
   1.239 +
   1.240 +	point3d_array.push_back( aiVector3D( x, y, z ) );
   1.241 +	//skipLine();
   1.242 +	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
   1.243 +}
   1.244 +
   1.245 +// -------------------------------------------------------------------
   1.246 +//	Get values for a new 2D vector instance
   1.247 +void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array )
   1.248 +{
   1.249 +	float x, y;
   1.250 +	copyNextWord(m_buffer, BUFFERSIZE);
   1.251 +	x = (float) fast_atof(m_buffer);	
   1.252 +	
   1.253 +	copyNextWord(m_buffer, BUFFERSIZE);
   1.254 +	y = (float) fast_atof(m_buffer);
   1.255 +
   1.256 +	point2d_array.push_back(aiVector2D(x, y));
   1.257 +
   1.258 +	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
   1.259 +}
   1.260 +
   1.261 +// -------------------------------------------------------------------
   1.262 +//	Get values for a new face instance
   1.263 +void ObjFileParser::getFace(aiPrimitiveType type)
   1.264 +{
   1.265 +	copyNextLine(m_buffer, BUFFERSIZE);
   1.266 +	if (m_DataIt == m_DataItEnd)
   1.267 +		return;
   1.268 +
   1.269 +	char *pPtr = m_buffer;
   1.270 +	char *pEnd = &pPtr[BUFFERSIZE];
   1.271 +	pPtr = getNextToken<char*>(pPtr, pEnd);
   1.272 +	if (pPtr == pEnd || *pPtr == '\0')
   1.273 +		return;
   1.274 +
   1.275 +	std::vector<unsigned int> *pIndices = new std::vector<unsigned int>;
   1.276 +	std::vector<unsigned int> *pTexID = new std::vector<unsigned int>;
   1.277 +	std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
   1.278 +	bool hasNormal = false;
   1.279 +
   1.280 +	const bool vt = (!m_pModel->m_TextureCoord.empty());
   1.281 +	const bool vn = (!m_pModel->m_Normals.empty());
   1.282 +	int iStep = 0, iPos = 0;
   1.283 +	while (pPtr != pEnd)
   1.284 +	{
   1.285 +		iStep = 1;
   1.286 +
   1.287 +		if (IsLineEnd(*pPtr))
   1.288 +			break;
   1.289 +
   1.290 +		if (*pPtr=='/' )
   1.291 +		{
   1.292 +			if (type == aiPrimitiveType_POINT) {
   1.293 +				DefaultLogger::get()->error("Obj: Separator unexpected in point statement");
   1.294 +			}
   1.295 +			if (iPos == 0)
   1.296 +			{
   1.297 +				//if there are no texture coordinates in the file, but normals
   1.298 +				if (!vt && vn) {
   1.299 +					iPos = 1;
   1.300 +					iStep++;
   1.301 +				}
   1.302 +			}
   1.303 +			iPos++;
   1.304 +		}
   1.305 +		else if ( isSeparator(*pPtr) )
   1.306 +		{
   1.307 +			iPos = 0;
   1.308 +		}
   1.309 +		else 
   1.310 +		{
   1.311 +			//OBJ USES 1 Base ARRAYS!!!!
   1.312 +			const int iVal = atoi( pPtr );
   1.313 +			int tmp = iVal;
   1.314 +			while ( ( tmp = tmp / 10 )!=0 )
   1.315 +				++iStep;
   1.316 +
   1.317 +			if ( iVal > 0 )
   1.318 +			{
   1.319 +				// Store parsed index
   1.320 +				if ( 0 == iPos )
   1.321 +				{
   1.322 +					pIndices->push_back( iVal-1 );
   1.323 +				}
   1.324 +				else if ( 1 == iPos )
   1.325 +				{	
   1.326 +					pTexID->push_back( iVal-1 );
   1.327 +				}
   1.328 +				else if ( 2 == iPos )
   1.329 +				{
   1.330 +					pNormalID->push_back( iVal-1 );
   1.331 +					hasNormal = true;
   1.332 +				}
   1.333 +				else
   1.334 +				{
   1.335 +					reportErrorTokenInFace();
   1.336 +				}
   1.337 +			}
   1.338 +		}
   1.339 +		pPtr += iStep;
   1.340 +	}
   1.341 +
   1.342 +	if ( pIndices->empty() ) 
   1.343 +	{
   1.344 +		DefaultLogger::get()->error("Obj: Ignoring empty face");
   1.345 +		m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
   1.346 +		return;
   1.347 +	}
   1.348 +
   1.349 +	ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID, type );
   1.350 +	
   1.351 +	// Set active material, if one set
   1.352 +	if (NULL != m_pModel->m_pCurrentMaterial) 
   1.353 +		face->m_pMaterial = m_pModel->m_pCurrentMaterial;
   1.354 +	else 
   1.355 +		face->m_pMaterial = m_pModel->m_pDefaultMaterial;
   1.356 +
   1.357 +	// Create a default object, if nothing is there
   1.358 +	if ( NULL == m_pModel->m_pCurrent )
   1.359 +		createObject( "defaultobject" );
   1.360 +	
   1.361 +	// Assign face to mesh
   1.362 +	if ( NULL == m_pModel->m_pCurrentMesh )
   1.363 +	{
   1.364 +		createMesh();
   1.365 +	}
   1.366 +	
   1.367 +	// Store the face
   1.368 +	m_pModel->m_pCurrentMesh->m_Faces.push_back( face );
   1.369 +	m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size();
   1.370 +	m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size(); 
   1.371 +	if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal ) 
   1.372 +	{
   1.373 +		m_pModel->m_pCurrentMesh->m_hasNormals = true;
   1.374 +	}
   1.375 +	// Skip the rest of the line
   1.376 +	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
   1.377 +}
   1.378 +
   1.379 +// -------------------------------------------------------------------
   1.380 +//	Get values for a new material description
   1.381 +void ObjFileParser::getMaterialDesc()
   1.382 +{
   1.383 +	// Each material request a new object.
   1.384 +	// Sometimes the object is already created (see 'o' tag by example), but it is not initialized !
   1.385 +	// So, we create a new object only if the current on is already initialized !
   1.386 +	if (m_pModel->m_pCurrent != NULL &&
   1.387 +		(	m_pModel->m_pCurrent->m_Meshes.size() > 1 ||
   1.388 +			(m_pModel->m_pCurrent->m_Meshes.size() == 1 && m_pModel->m_Meshes[m_pModel->m_pCurrent->m_Meshes[0]]->m_Faces.size() != 0)	)
   1.389 +		)
   1.390 +		m_pModel->m_pCurrent = NULL;
   1.391 +
   1.392 +	// Get next data for material data
   1.393 +	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
   1.394 +	if (m_DataIt == m_DataItEnd)
   1.395 +		return;
   1.396 +
   1.397 +	char *pStart = &(*m_DataIt);
   1.398 +	while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
   1.399 +		++m_DataIt;
   1.400 +
   1.401 +	// Get name
   1.402 +	std::string strName(pStart, &(*m_DataIt));
   1.403 +	if ( strName.empty())
   1.404 +		return;
   1.405 +
   1.406 +	// Search for material
   1.407 +	std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName );
   1.408 +	if ( it == m_pModel->m_MaterialMap.end() )
   1.409 +	{
   1.410 +		// Not found, use default material
   1.411 +		m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
   1.412 +		DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
   1.413 +	}
   1.414 +	else
   1.415 +	{
   1.416 +		// Found, using detected material
   1.417 +		m_pModel->m_pCurrentMaterial = (*it).second;
   1.418 +		if ( needsNewMesh( strName ))
   1.419 +		{
   1.420 +			createMesh();	
   1.421 +		}
   1.422 +		m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strName );
   1.423 +	}
   1.424 +
   1.425 +	// Skip rest of line
   1.426 +	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
   1.427 +}
   1.428 +
   1.429 +// -------------------------------------------------------------------
   1.430 +//	Get a comment, values will be skipped
   1.431 +void ObjFileParser::getComment()
   1.432 +{
   1.433 +	while (m_DataIt != m_DataItEnd)
   1.434 +	{
   1.435 +		if ( '\n' == (*m_DataIt))
   1.436 +		{
   1.437 +			++m_DataIt;
   1.438 +			break;
   1.439 +		}
   1.440 +		else
   1.441 +		{
   1.442 +			++m_DataIt;
   1.443 +		}
   1.444 +	}
   1.445 +}
   1.446 +
   1.447 +// -------------------------------------------------------------------
   1.448 +//	Get material library from file.
   1.449 +void ObjFileParser::getMaterialLib()
   1.450 +{
   1.451 +	// Translate tuple
   1.452 +	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
   1.453 +	if (m_DataIt ==  m_DataItEnd)
   1.454 +		return;
   1.455 +	
   1.456 +	char *pStart = &(*m_DataIt);
   1.457 +	while (m_DataIt != m_DataItEnd && !isNewLine(*m_DataIt))
   1.458 +		m_DataIt++;
   1.459 +
   1.460 +	// Check for existence
   1.461 +	const std::string strMatName(pStart, &(*m_DataIt));
   1.462 +	IOStream *pFile = m_pIO->Open(strMatName);
   1.463 +
   1.464 +	if (!pFile )
   1.465 +	{
   1.466 +		DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName);
   1.467 +		m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
   1.468 +		return;
   1.469 +	}
   1.470 +
   1.471 +	// Import material library data from file
   1.472 +	std::vector<char> buffer;
   1.473 +	BaseImporter::TextFileToBuffer(pFile,buffer);
   1.474 +	m_pIO->Close( pFile );
   1.475 +
   1.476 +	// Importing the material library 
   1.477 +	ObjFileMtlImporter mtlImporter( buffer, strMatName, m_pModel );			
   1.478 +}
   1.479 +
   1.480 +// -------------------------------------------------------------------
   1.481 +//	Set a new material definition as the current material.
   1.482 +void ObjFileParser::getNewMaterial()
   1.483 +{
   1.484 +	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
   1.485 +	m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
   1.486 +	if ( m_DataIt == m_DataItEnd )
   1.487 +		return;
   1.488 +
   1.489 +	char *pStart = &(*m_DataIt);
   1.490 +	std::string strMat( pStart, *m_DataIt );
   1.491 +	while ( m_DataIt != m_DataItEnd && isSeparator( *m_DataIt ) )
   1.492 +		m_DataIt++;
   1.493 +	std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
   1.494 +	if ( it == m_pModel->m_MaterialMap.end() )
   1.495 +	{
   1.496 +		// Show a warning, if material was not found
   1.497 +		DefaultLogger::get()->warn("OBJ: Unsupported material requested: " + strMat);
   1.498 +		m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
   1.499 +	}
   1.500 +	else
   1.501 +	{
   1.502 +		// Set new material
   1.503 +		if ( needsNewMesh( strMat ) )
   1.504 +		{
   1.505 +			createMesh();	
   1.506 +		}
   1.507 +		m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat );
   1.508 +	}
   1.509 +
   1.510 +	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
   1.511 +}
   1.512 +
   1.513 +// -------------------------------------------------------------------
   1.514 +int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
   1.515 +{
   1.516 +	int mat_index = -1;
   1.517 +	if ( strMaterialName.empty() )
   1.518 +		return mat_index;
   1.519 +	for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
   1.520 +	{
   1.521 +		if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
   1.522 +		{
   1.523 +			mat_index = (int)index;
   1.524 +			break;
   1.525 +		}
   1.526 +	}
   1.527 +	return mat_index;
   1.528 +}
   1.529 +
   1.530 +// -------------------------------------------------------------------
   1.531 +//	Getter for a group name.  
   1.532 +void ObjFileParser::getGroupName()
   1.533 +{
   1.534 +	std::string strGroupName;
   1.535 +   
   1.536 +	m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
   1.537 +	if ( isEndOfBuffer( m_DataIt, m_DataItEnd ) )
   1.538 +		return;
   1.539 +
   1.540 +	// Change active group, if necessary
   1.541 +	if ( m_pModel->m_strActiveGroup != strGroupName )
   1.542 +	{
   1.543 +		// Search for already existing entry
   1.544 +		ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(strGroupName);
   1.545 +		
   1.546 +		// We are mapping groups into the object structure
   1.547 +		createObject( strGroupName );
   1.548 +		
   1.549 +		// New group name, creating a new entry
   1.550 +		if (it == m_pModel->m_Groups.end())
   1.551 +		{
   1.552 +			std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>;
   1.553 +			m_pModel->m_Groups[ strGroupName ] = pFaceIDArray;
   1.554 +			m_pModel->m_pGroupFaceIDs = (pFaceIDArray);
   1.555 +		}
   1.556 +		else
   1.557 +		{
   1.558 +			m_pModel->m_pGroupFaceIDs = (*it).second;
   1.559 +		}
   1.560 +		m_pModel->m_strActiveGroup = strGroupName;
   1.561 +	}
   1.562 +	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
   1.563 +}
   1.564 +
   1.565 +// -------------------------------------------------------------------
   1.566 +//	Not supported
   1.567 +void ObjFileParser::getGroupNumber()
   1.568 +{
   1.569 +	// Not used
   1.570 +
   1.571 +	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
   1.572 +}
   1.573 +
   1.574 +// -------------------------------------------------------------------
   1.575 +//	Stores values for a new object instance, name will be used to 
   1.576 +//	identify it.
   1.577 +void ObjFileParser::getObjectName()
   1.578 +{
   1.579 +	m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
   1.580 +	if (m_DataIt == m_DataItEnd)
   1.581 +		return;
   1.582 +	char *pStart = &(*m_DataIt);
   1.583 +	while ( m_DataIt != m_DataItEnd && !isSeparator( *m_DataIt ) )
   1.584 +		++m_DataIt;
   1.585 +
   1.586 +	std::string strObjectName(pStart, &(*m_DataIt));
   1.587 +	if (!strObjectName.empty()) 
   1.588 +	{
   1.589 +		// Reset current object
   1.590 +		m_pModel->m_pCurrent = NULL;
   1.591 +		
   1.592 +		// Search for actual object
   1.593 +		for (std::vector<ObjFile::Object*>::const_iterator it = m_pModel->m_Objects.begin();
   1.594 +			it != m_pModel->m_Objects.end();
   1.595 +			++it)
   1.596 +		{
   1.597 +			if ((*it)->m_strObjName == strObjectName)
   1.598 +			{
   1.599 +				m_pModel->m_pCurrent = *it;
   1.600 +				break;
   1.601 +			}
   1.602 +		}
   1.603 +
   1.604 +		// Allocate a new object, if current one was not found before
   1.605 +		if ( NULL == m_pModel->m_pCurrent )
   1.606 +			createObject(strObjectName);
   1.607 +	}
   1.608 +	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
   1.609 +}
   1.610 +// -------------------------------------------------------------------
   1.611 +//	Creates a new object instance
   1.612 +void ObjFileParser::createObject(const std::string &strObjectName)
   1.613 +{
   1.614 +	ai_assert( NULL != m_pModel );
   1.615 +	//ai_assert( !strObjectName.empty() );
   1.616 +
   1.617 +	m_pModel->m_pCurrent = new ObjFile::Object;
   1.618 +	m_pModel->m_pCurrent->m_strObjName = strObjectName;
   1.619 +	m_pModel->m_Objects.push_back( m_pModel->m_pCurrent );
   1.620 +	
   1.621 +
   1.622 +	createMesh();
   1.623 +
   1.624 +	if( m_pModel->m_pCurrentMaterial )
   1.625 +	{
   1.626 +		m_pModel->m_pCurrentMesh->m_uiMaterialIndex = 
   1.627 +			getMaterialIndex( m_pModel->m_pCurrentMaterial->MaterialName.data );
   1.628 +		m_pModel->m_pCurrentMesh->m_pMaterial = m_pModel->m_pCurrentMaterial;
   1.629 +	}		
   1.630 +}
   1.631 +// -------------------------------------------------------------------
   1.632 +//	Creates a new mesh
   1.633 +void ObjFileParser::createMesh()
   1.634 +{
   1.635 +	ai_assert( NULL != m_pModel );
   1.636 +	m_pModel->m_pCurrentMesh = new ObjFile::Mesh;
   1.637 +	m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh );
   1.638 +	unsigned int meshId = m_pModel->m_Meshes.size()-1;
   1.639 +	if ( NULL != m_pModel->m_pCurrent )
   1.640 +	{
   1.641 +		m_pModel->m_pCurrent->m_Meshes.push_back( meshId );
   1.642 +	}
   1.643 +	else
   1.644 +	{
   1.645 +		DefaultLogger::get()->error("OBJ: No object detected to attach a new mesh instance.");
   1.646 +	}
   1.647 +}
   1.648 +
   1.649 +// -------------------------------------------------------------------
   1.650 +//	Returns true, if a new mesh must be created.
   1.651 +bool ObjFileParser::needsNewMesh( const std::string &rMaterialName )
   1.652 +{
   1.653 +	if(m_pModel->m_pCurrentMesh == 0)
   1.654 +	{
   1.655 +		// No mesh data yet
   1.656 +		return true;
   1.657 +	}
   1.658 +	bool newMat = false;
   1.659 +	int matIdx = getMaterialIndex( rMaterialName );
   1.660 +	int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex;
   1.661 +	if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) || curMatIdx != matIdx )
   1.662 +	{
   1.663 +		// New material -> only one material per mesh, so we need to create a new 
   1.664 +		// material
   1.665 +		newMat = true;
   1.666 +	}
   1.667 +	return newMat;
   1.668 +}
   1.669 +
   1.670 +// -------------------------------------------------------------------
   1.671 +//	Shows an error in parsing process.
   1.672 +void ObjFileParser::reportErrorTokenInFace()
   1.673 +{		
   1.674 +	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
   1.675 +	DefaultLogger::get()->error("OBJ: Not supported token in face description detected");
   1.676 +}
   1.677 +
   1.678 +// -------------------------------------------------------------------
   1.679 +
   1.680 +}	// Namespace Assimp
   1.681 +
   1.682 +#endif // !! ASSIMP_BUILD_NO_OBJ_IMPORTER