2008-10-13 16:45:48 +00:00
|
|
|
|
/*
|
|
|
|
|
---------------------------------------------------------------------------
|
|
|
|
|
Open Asset Import Library (ASSIMP)
|
|
|
|
|
---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 "AssimpPCH.h"
|
2009-01-18 23:48:25 +00:00
|
|
|
|
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
|
2008-10-13 16:45:48 +00:00
|
|
|
|
|
2008-05-05 12:36:31 +00:00
|
|
|
|
#include "ObjFileParser.h"
|
2008-06-03 21:32:56 +00:00
|
|
|
|
#include "ObjFileMtlImporter.h"
|
2008-05-05 12:36:31 +00:00
|
|
|
|
#include "ObjTools.h"
|
|
|
|
|
#include "ObjFileData.h"
|
|
|
|
|
#include "fast_atof.h"
|
|
|
|
|
|
2008-10-13 16:45:48 +00:00
|
|
|
|
#include "DefaultIOSystem.h"
|
2008-05-05 12:36:31 +00:00
|
|
|
|
|
2009-01-18 23:48:25 +00:00
|
|
|
|
namespace Assimp {
|
2008-07-02 20:41:30 +00:00
|
|
|
|
// -------------------------------------------------------------------
|
2009-01-18 23:48:25 +00:00
|
|
|
|
const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME;
|
|
|
|
|
// fix: changed that to our standard default name
|
2008-05-05 12:36:31 +00:00
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
2008-08-14 21:25:50 +00:00
|
|
|
|
// Constructor with loaded data and directories.
|
2008-06-03 21:32:56 +00:00
|
|
|
|
ObjFileParser::ObjFileParser(std::vector<char> &Data,
|
|
|
|
|
const std::string &strAbsPath,
|
|
|
|
|
const std::string &strModelName) :
|
2008-05-05 12:36:31 +00:00
|
|
|
|
m_strAbsPath(strAbsPath),
|
|
|
|
|
m_DataIt(Data.begin()),
|
|
|
|
|
m_DataItEnd(Data.end()),
|
|
|
|
|
m_pModel(NULL),
|
|
|
|
|
m_uiLine(0)
|
|
|
|
|
{
|
|
|
|
|
// Create the model instance to store all the data
|
|
|
|
|
m_pModel = new ObjFile::Model();
|
|
|
|
|
m_pModel->m_ModelName = strModelName;
|
2008-06-11 20:12:48 +00:00
|
|
|
|
|
|
|
|
|
m_pModel->m_pDefaultMaterial = new ObjFile::Material();
|
2008-07-02 20:41:30 +00:00
|
|
|
|
m_pModel->m_pDefaultMaterial->MaterialName.Set( DEFAULT_MATERIAL );
|
2008-06-11 20:12:48 +00:00
|
|
|
|
m_pModel->m_MaterialLib.push_back( DEFAULT_MATERIAL );
|
|
|
|
|
m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial;
|
|
|
|
|
|
2008-05-05 12:36:31 +00:00
|
|
|
|
// Start parsing the file
|
|
|
|
|
parseFile();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
ObjFileParser::~ObjFileParser()
|
|
|
|
|
{
|
2008-10-05 13:05:53 +00:00
|
|
|
|
delete m_pModel->m_pDefaultMaterial;
|
|
|
|
|
m_pModel->m_pDefaultMaterial = NULL;
|
|
|
|
|
|
|
|
|
|
delete m_pModel;
|
|
|
|
|
m_pModel = NULL;
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
ObjFile::Model *ObjFileParser::GetModel() const
|
|
|
|
|
{
|
|
|
|
|
return m_pModel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
void ObjFileParser::parseFile()
|
|
|
|
|
{
|
|
|
|
|
if (m_DataIt == m_DataItEnd)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
while (m_DataIt != m_DataItEnd)
|
|
|
|
|
{
|
|
|
|
|
switch (*m_DataIt)
|
|
|
|
|
{
|
|
|
|
|
case 'v': // Parse a vertex texture coordinate
|
|
|
|
|
{
|
|
|
|
|
++m_DataIt;
|
|
|
|
|
if (*m_DataIt == ' ')
|
|
|
|
|
{
|
|
|
|
|
// Read in vertex definition
|
|
|
|
|
getVector3(m_pModel->m_Vertices);
|
|
|
|
|
}
|
|
|
|
|
else if (*m_DataIt == 't')
|
|
|
|
|
{
|
|
|
|
|
// Read in texture coordinate (2D)
|
2008-07-02 18:12:54 +00:00
|
|
|
|
++m_DataIt;
|
2008-05-05 12:36:31 +00:00
|
|
|
|
getVector2(m_pModel->m_TextureCoord);
|
|
|
|
|
}
|
|
|
|
|
else if (*m_DataIt == 'n')
|
|
|
|
|
{
|
|
|
|
|
// Read in normal vector definition
|
2008-07-02 18:12:54 +00:00
|
|
|
|
++m_DataIt;
|
2008-05-05 12:36:31 +00:00
|
|
|
|
getVector3(m_pModel->m_Normals);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'f': // Parse a face
|
|
|
|
|
{
|
|
|
|
|
getFace();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '#': // Parse a comment
|
|
|
|
|
{
|
|
|
|
|
getComment();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'u': // Parse a material desc. setter
|
|
|
|
|
{
|
|
|
|
|
getMaterialDesc();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'm': // Parse a material library
|
|
|
|
|
{
|
|
|
|
|
getMaterialLib();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'g': // Parse group name
|
|
|
|
|
{
|
|
|
|
|
getGroupName();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 's': // Parse group number
|
|
|
|
|
{
|
|
|
|
|
getGroupNumber();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'o': // Parse object name
|
|
|
|
|
{
|
|
|
|
|
getObjectName();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
{
|
2008-05-16 17:57:48 +00:00
|
|
|
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
// Copy the next word in a temporary buffer
|
|
|
|
|
void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
|
|
|
|
|
{
|
|
|
|
|
size_t index = 0;
|
|
|
|
|
m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
|
|
|
|
|
while (!isSpace(*m_DataIt) && m_DataIt != m_DataItEnd)
|
|
|
|
|
{
|
|
|
|
|
pBuffer[index] = *m_DataIt;
|
|
|
|
|
index++;
|
|
|
|
|
if (index == length-1)
|
|
|
|
|
break;
|
|
|
|
|
++m_DataIt;
|
|
|
|
|
}
|
|
|
|
|
pBuffer[index] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
// Copy the next line into a temporary buffer
|
|
|
|
|
void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
|
|
|
|
|
{
|
|
|
|
|
size_t index = 0;
|
|
|
|
|
while (m_DataIt != m_DataItEnd)
|
|
|
|
|
{
|
|
|
|
|
if (*m_DataIt == '\n' || *m_DataIt == '\r')
|
|
|
|
|
break;
|
|
|
|
|
assert (index+1 <= length);
|
|
|
|
|
pBuffer[ index ] = *m_DataIt;
|
|
|
|
|
++index;
|
|
|
|
|
++m_DataIt;
|
|
|
|
|
}
|
|
|
|
|
pBuffer[ index ] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
// Get values for a new 3D vector instance
|
2008-05-09 17:24:28 +00:00
|
|
|
|
void ObjFileParser::getVector3(std::vector<aiVector3D*> &point3d_array)
|
2008-05-05 12:36:31 +00:00
|
|
|
|
{
|
|
|
|
|
float x, y, z;
|
|
|
|
|
copyNextWord(m_buffer, BUFFERSIZE);
|
|
|
|
|
x = (float) fast_atof(m_buffer);
|
|
|
|
|
|
|
|
|
|
copyNextWord(m_buffer, BUFFERSIZE);
|
|
|
|
|
y = (float) fast_atof(m_buffer);
|
|
|
|
|
|
|
|
|
|
copyNextWord(m_buffer, BUFFERSIZE);
|
|
|
|
|
z = (float) fast_atof(m_buffer);
|
|
|
|
|
|
|
|
|
|
point3d_array.push_back(new aiVector3D(x,y,z));
|
2008-05-16 17:57:48 +00:00
|
|
|
|
//skipLine();
|
|
|
|
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
// Get values for a new 2D vector instance
|
2008-05-16 17:57:48 +00:00
|
|
|
|
void ObjFileParser::getVector2( std::vector<aiVector2D*> &point2d_array )
|
2008-05-05 12:36:31 +00:00
|
|
|
|
{
|
|
|
|
|
float x, y;
|
|
|
|
|
copyNextWord(m_buffer, BUFFERSIZE);
|
|
|
|
|
x = (float) fast_atof(m_buffer);
|
|
|
|
|
|
|
|
|
|
copyNextWord(m_buffer, BUFFERSIZE);
|
|
|
|
|
y = (float) fast_atof(m_buffer);
|
|
|
|
|
|
|
|
|
|
point2d_array.push_back(new aiVector2D(x, y));
|
|
|
|
|
|
2008-05-16 17:57:48 +00:00
|
|
|
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
// Get values for a new face instance
|
|
|
|
|
void ObjFileParser::getFace()
|
|
|
|
|
{
|
|
|
|
|
copyNextLine(m_buffer, BUFFERSIZE);
|
|
|
|
|
if (m_DataIt == m_DataItEnd)
|
|
|
|
|
return;
|
2008-05-16 17:57:48 +00:00
|
|
|
|
|
2008-05-05 12:36:31 +00:00
|
|
|
|
char *pPtr = m_buffer;
|
|
|
|
|
char *pEnd = &pPtr[BUFFERSIZE];
|
|
|
|
|
pPtr = getNextToken<char*>(pPtr, pEnd);
|
|
|
|
|
if (pPtr == '\0')
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
std::vector<unsigned int> *pIndices = new std::vector<unsigned int>;
|
|
|
|
|
std::vector<unsigned int> *pTexID = new std::vector<unsigned int>;
|
|
|
|
|
std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
|
2008-09-22 08:22:36 +00:00
|
|
|
|
bool hasNormal = false;
|
|
|
|
|
|
|
|
|
|
|
2008-05-05 12:36:31 +00:00
|
|
|
|
bool vt = (!m_pModel->m_TextureCoord.empty());
|
|
|
|
|
bool vn = (!m_pModel->m_Normals.empty());
|
|
|
|
|
int iStep = 0, iPos = 0;
|
|
|
|
|
while (pPtr != pEnd)
|
|
|
|
|
{
|
|
|
|
|
iStep = 1;
|
|
|
|
|
if (*pPtr == '\0')
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (*pPtr=='\r')
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (*pPtr=='/' )
|
|
|
|
|
{
|
|
|
|
|
if (iPos == 0)
|
|
|
|
|
{
|
|
|
|
|
//if there are no texturecoordinates in the obj file but normals
|
2008-09-16 13:53:10 +00:00
|
|
|
|
if (!vt && vn) {
|
2008-05-05 12:36:31 +00:00
|
|
|
|
iPos = 1;
|
2008-09-16 13:53:10 +00:00
|
|
|
|
iStep++;
|
|
|
|
|
}
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
iPos++;
|
|
|
|
|
}
|
|
|
|
|
else if (isSpace(*pPtr))
|
|
|
|
|
{
|
|
|
|
|
iPos = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//OBJ USES 1 Base ARRAYS!!!!
|
2008-09-09 22:32:04 +00:00
|
|
|
|
const int iVal = atoi( pPtr );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
int tmp = iVal;
|
|
|
|
|
while ((tmp = tmp / 10)!=0)
|
|
|
|
|
++iStep;
|
|
|
|
|
|
2008-09-09 22:32:04 +00:00
|
|
|
|
if ( 0 != iVal )
|
2008-05-05 12:36:31 +00:00
|
|
|
|
{
|
|
|
|
|
// Store parsed index
|
2008-09-09 22:32:04 +00:00
|
|
|
|
if ( 0 == iPos )
|
2008-05-05 12:36:31 +00:00
|
|
|
|
{
|
2008-09-09 22:32:04 +00:00
|
|
|
|
pIndices->push_back( iVal-1 );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
2008-09-09 22:32:04 +00:00
|
|
|
|
else if ( 1 == iPos )
|
2008-05-05 12:36:31 +00:00
|
|
|
|
{
|
2008-09-09 22:32:04 +00:00
|
|
|
|
pTexID->push_back( iVal-1 );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
2008-09-09 22:32:04 +00:00
|
|
|
|
else if ( 2 == iPos )
|
2008-05-05 12:36:31 +00:00
|
|
|
|
{
|
2008-09-09 22:32:04 +00:00
|
|
|
|
pNormalID->push_back( iVal-1 );
|
2008-09-22 08:22:36 +00:00
|
|
|
|
hasNormal = true;
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
reportErrorTokenInFace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-09-09 22:32:04 +00:00
|
|
|
|
for ( int i=0; i<iStep; i++ )
|
2008-05-05 12:36:31 +00:00
|
|
|
|
++pPtr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ObjFile::Face *face = new ObjFile::Face(pIndices, pNormalID, pTexID);
|
|
|
|
|
|
|
|
|
|
// Set active material, if one set
|
|
|
|
|
if (NULL != m_pModel->m_pCurrentMaterial)
|
|
|
|
|
face->m_pMaterial = m_pModel->m_pCurrentMaterial;
|
|
|
|
|
else
|
|
|
|
|
face->m_pMaterial = m_pModel->m_pDefaultMaterial;
|
|
|
|
|
|
|
|
|
|
// Create a default object, if nothing there
|
2008-07-02 18:12:54 +00:00
|
|
|
|
if ( NULL == m_pModel->m_pCurrent )
|
2008-05-05 12:36:31 +00:00
|
|
|
|
createObject("defaultobject");
|
|
|
|
|
|
|
|
|
|
// Store the new instance
|
|
|
|
|
m_pModel->m_pCurrent->m_Faces.push_back(face);
|
|
|
|
|
|
2008-06-03 21:32:56 +00:00
|
|
|
|
// Assign face to mesh
|
2008-06-11 20:12:48 +00:00
|
|
|
|
if ( NULL == m_pModel->m_pCurrentMesh )
|
|
|
|
|
{
|
|
|
|
|
m_pModel->m_pCurrentMesh = new ObjFile::Mesh();
|
|
|
|
|
m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh );
|
|
|
|
|
}
|
2008-08-14 21:25:50 +00:00
|
|
|
|
|
|
|
|
|
// Store the face
|
2008-06-03 21:32:56 +00:00
|
|
|
|
m_pModel->m_pCurrentMesh->m_Faces.push_back( face );
|
2008-08-28 17:35:36 +00:00
|
|
|
|
m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size();
|
|
|
|
|
m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size();
|
2008-09-22 08:22:36 +00:00
|
|
|
|
if(!m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal) {
|
|
|
|
|
m_pModel->m_pCurrentMesh->m_hasNormals = true;
|
|
|
|
|
}
|
2008-05-05 12:36:31 +00:00
|
|
|
|
// Skip the rest of the line
|
2008-05-16 17:57:48 +00:00
|
|
|
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
// Get values for a new material description
|
|
|
|
|
void ObjFileParser::getMaterialDesc()
|
|
|
|
|
{
|
|
|
|
|
// Get next data for material data
|
|
|
|
|
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
|
|
|
|
if (m_DataIt == m_DataItEnd)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
char *pStart = &(*m_DataIt);
|
2008-06-03 21:32:56 +00:00
|
|
|
|
while ( !isSpace(*m_DataIt) && m_DataIt != m_DataItEnd )
|
|
|
|
|
++m_DataIt;
|
2008-05-05 12:36:31 +00:00
|
|
|
|
|
|
|
|
|
// Get name
|
|
|
|
|
std::string strName(pStart, &(*m_DataIt));
|
2008-09-22 08:22:36 +00:00
|
|
|
|
if ( strName.empty())
|
2008-05-05 12:36:31 +00:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Search for material
|
2008-05-16 17:57:48 +00:00
|
|
|
|
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName );
|
2008-06-03 21:32:56 +00:00
|
|
|
|
if ( it == m_pModel->m_MaterialMap.end() )
|
2008-05-05 12:36:31 +00:00
|
|
|
|
{
|
2008-06-03 21:32:56 +00:00
|
|
|
|
// Not found, use default material
|
|
|
|
|
m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
|
2008-07-02 20:41:30 +00:00
|
|
|
|
m_pModel->m_pCurrentMesh = new ObjFile::Mesh();
|
|
|
|
|
m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh );
|
|
|
|
|
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( DEFAULT_MATERIAL );
|
2008-06-03 21:32:56 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Found, using detected material
|
|
|
|
|
m_pModel->m_pCurrentMaterial = (*it).second;
|
|
|
|
|
|
|
|
|
|
// Create a new mesh for a new material
|
|
|
|
|
m_pModel->m_pCurrentMesh = new ObjFile::Mesh();
|
|
|
|
|
m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh );
|
2008-07-02 18:12:54 +00:00
|
|
|
|
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strName );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-06-03 21:32:56 +00:00
|
|
|
|
// Skip rest of line
|
2008-05-16 17:57:48 +00:00
|
|
|
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
// Get a comment, values will be skipped
|
|
|
|
|
void ObjFileParser::getComment()
|
|
|
|
|
{
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
if ('\n' == (*m_DataIt) || m_DataIt == m_DataItEnd)
|
|
|
|
|
{
|
|
|
|
|
++m_DataIt;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
++m_DataIt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
2008-06-03 21:32:56 +00:00
|
|
|
|
// Get material library from file.
|
2008-05-05 12:36:31 +00:00
|
|
|
|
void ObjFileParser::getMaterialLib()
|
|
|
|
|
{
|
|
|
|
|
// Translate tuple
|
|
|
|
|
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
|
|
|
|
if (m_DataIt == m_DataItEnd)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
char *pStart = &(*m_DataIt);
|
2008-10-05 13:05:53 +00:00
|
|
|
|
while (!isNewLine(*m_DataIt))
|
2008-05-05 12:36:31 +00:00
|
|
|
|
m_DataIt++;
|
|
|
|
|
|
2009-01-23 21:06:43 +00:00
|
|
|
|
// TODO: fix path construction
|
|
|
|
|
// CLEANUP ... who is resposible for *two* identical DefaultIOSystems
|
|
|
|
|
// where the IOSystem passed to ReadFile() should be used???
|
|
|
|
|
|
2008-05-05 12:36:31 +00:00
|
|
|
|
// Check for existence
|
|
|
|
|
DefaultIOSystem IOSystem;
|
|
|
|
|
std::string strMatName(pStart, &(*m_DataIt));
|
|
|
|
|
std::string absName = m_strAbsPath + IOSystem.getOsSeparator() + strMatName;
|
2009-01-23 21:06:43 +00:00
|
|
|
|
if ( !IOSystem.Exists( absName.c_str()) )
|
2008-05-05 12:36:31 +00:00
|
|
|
|
{
|
2008-05-16 17:57:48 +00:00
|
|
|
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-03 21:32:56 +00:00
|
|
|
|
// Extract the extention
|
2008-05-05 12:36:31 +00:00
|
|
|
|
std::string strExt("");
|
2008-07-02 18:12:54 +00:00
|
|
|
|
extractExtension( strMatName, strExt );
|
|
|
|
|
static const std::string mat = "mtl";
|
2008-05-05 12:36:31 +00:00
|
|
|
|
|
2008-06-03 21:32:56 +00:00
|
|
|
|
// Load the material library
|
2008-05-05 12:36:31 +00:00
|
|
|
|
DefaultIOSystem FileSystem;
|
2009-01-23 21:06:43 +00:00
|
|
|
|
IOStream *pFile = FileSystem.Open(absName.c_str());
|
2008-05-05 12:36:31 +00:00
|
|
|
|
if (0L != pFile)
|
|
|
|
|
{
|
2008-07-02 18:12:54 +00:00
|
|
|
|
// Import material library data from file
|
2008-05-05 12:36:31 +00:00
|
|
|
|
size_t size = pFile->FileSize();
|
2008-05-16 17:57:48 +00:00
|
|
|
|
std::vector<char> buffer;
|
|
|
|
|
buffer.resize( size );
|
2008-09-12 20:25:11 +00:00
|
|
|
|
pFile->Read( &buffer[ 0 ], sizeof( char ), size );
|
2008-05-16 17:57:48 +00:00
|
|
|
|
FileSystem.Close( pFile );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
|
2008-06-03 21:32:56 +00:00
|
|
|
|
// Importing the material library
|
|
|
|
|
ObjFileMtlImporter mtlImporter( buffer, absName, m_pModel );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-06-03 21:32:56 +00:00
|
|
|
|
// Skip rest of line
|
2008-05-16 17:57:48 +00:00
|
|
|
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
2008-06-03 21:32:56 +00:00
|
|
|
|
// Set a new material definition as the current material.
|
2008-05-05 12:36:31 +00:00
|
|
|
|
void ObjFileParser::getNewMaterial()
|
|
|
|
|
{
|
|
|
|
|
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
|
|
|
|
m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
|
2008-09-07 20:50:51 +00:00
|
|
|
|
if ( m_DataIt == m_DataItEnd )
|
|
|
|
|
return;
|
2008-05-05 12:36:31 +00:00
|
|
|
|
|
|
|
|
|
char *pStart = &(*m_DataIt);
|
|
|
|
|
std::string strMat(pStart, *m_DataIt);
|
|
|
|
|
while (isSpace(*m_DataIt))
|
|
|
|
|
m_DataIt++;
|
2008-07-02 18:12:54 +00:00
|
|
|
|
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
if (it == m_pModel->m_MaterialMap.end())
|
|
|
|
|
{
|
|
|
|
|
// Show a warning, if material was not found
|
|
|
|
|
std::string strWarn ("Unsupported material requested: ");
|
|
|
|
|
strWarn += strMat;
|
|
|
|
|
std::cerr << "Warning : " << strWarn << std::endl;
|
|
|
|
|
m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Set new material
|
|
|
|
|
m_pModel->m_pCurrentMaterial = (*it).second;
|
2008-07-02 18:12:54 +00:00
|
|
|
|
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-05-16 17:57:48 +00:00
|
|
|
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-07-02 18:12:54 +00:00
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
|
|
|
|
|
{
|
|
|
|
|
int mat_index = -1;
|
|
|
|
|
if ( strMaterialName.empty() )
|
|
|
|
|
return mat_index;
|
|
|
|
|
for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
|
|
|
|
|
{
|
|
|
|
|
if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
|
|
|
|
|
{
|
2008-08-28 17:35:36 +00:00
|
|
|
|
mat_index = (int)index;
|
2008-07-02 18:12:54 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return mat_index;
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-05 12:36:31 +00:00
|
|
|
|
// -------------------------------------------------------------------
|
2008-06-03 21:32:56 +00:00
|
|
|
|
// Getter for a group name.
|
2008-05-05 12:36:31 +00:00
|
|
|
|
void ObjFileParser::getGroupName()
|
|
|
|
|
{
|
|
|
|
|
// Get next word from data buffer
|
|
|
|
|
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
|
|
|
|
m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
|
2008-09-07 20:50:51 +00:00
|
|
|
|
if ( m_DataIt == m_DataItEnd )
|
|
|
|
|
return;
|
|
|
|
|
|
2008-05-05 12:36:31 +00:00
|
|
|
|
// Store groupname in group library
|
|
|
|
|
char *pStart = &(*m_DataIt);
|
|
|
|
|
while (!isSpace(*m_DataIt))
|
|
|
|
|
m_DataIt++;
|
|
|
|
|
std::string strGroupName(pStart, &(*m_DataIt));
|
|
|
|
|
|
|
|
|
|
// Change active group, if necessary
|
|
|
|
|
if (m_pModel->m_strActiveGroup != strGroupName)
|
|
|
|
|
{
|
|
|
|
|
// Search for already existing entry
|
|
|
|
|
ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(&strGroupName);
|
|
|
|
|
|
|
|
|
|
// New group name, creating a new entry
|
2008-09-12 20:25:11 +00:00
|
|
|
|
//ObjFile::Object *pObject = m_pModel->m_pCurrent;
|
2008-05-05 12:36:31 +00:00
|
|
|
|
if (it == m_pModel->m_Groups.end())
|
|
|
|
|
{
|
|
|
|
|
std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>;
|
|
|
|
|
m_pModel->m_Groups[ &strGroupName ] = pFaceIDArray;
|
|
|
|
|
m_pModel->m_pGroupFaceIDs = (pFaceIDArray);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_pModel->m_pGroupFaceIDs = (*it).second;
|
|
|
|
|
}
|
|
|
|
|
m_pModel->m_strActiveGroup = strGroupName;
|
|
|
|
|
}
|
2008-05-16 17:57:48 +00:00
|
|
|
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
// Not supported
|
|
|
|
|
void ObjFileParser::getGroupNumber()
|
|
|
|
|
{
|
2008-05-16 17:57:48 +00:00
|
|
|
|
// Not used
|
2008-05-05 12:36:31 +00:00
|
|
|
|
|
2008-05-16 17:57:48 +00:00
|
|
|
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
// Stores values for a new object instance, name will be used to
|
|
|
|
|
// identify it.
|
|
|
|
|
void ObjFileParser::getObjectName()
|
|
|
|
|
{
|
|
|
|
|
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
|
|
|
|
if (m_DataIt == m_DataItEnd)
|
|
|
|
|
return;
|
|
|
|
|
char *pStart = &(*m_DataIt);
|
|
|
|
|
while (!isSpace(*m_DataIt))
|
|
|
|
|
m_DataIt++;
|
|
|
|
|
|
|
|
|
|
std::string strObjectName(pStart, &(*m_DataIt));
|
|
|
|
|
if (!strObjectName.empty())
|
|
|
|
|
{
|
|
|
|
|
// Reset current object
|
|
|
|
|
m_pModel->m_pCurrent = NULL;
|
|
|
|
|
|
|
|
|
|
// Search for actual object
|
|
|
|
|
for (std::vector<ObjFile::Object*>::const_iterator it = m_pModel->m_Objects.begin();
|
|
|
|
|
it != m_pModel->m_Objects.end();
|
|
|
|
|
++it)
|
|
|
|
|
{
|
|
|
|
|
if ((*it)->m_strObjName == strObjectName)
|
|
|
|
|
{
|
|
|
|
|
m_pModel->m_pCurrent = *it;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allocate a new object, if current one wasn<73>t found before
|
|
|
|
|
if (m_pModel->m_pCurrent == NULL)
|
|
|
|
|
{
|
|
|
|
|
createObject(strObjectName);
|
|
|
|
|
/*m_pModel->m_pCurrent = new ObjFile::Object();
|
|
|
|
|
m_pModel->m_pCurrent->m_strObjName = strObjectName;
|
|
|
|
|
m_pModel->m_Objects.push_back(m_pModel->m_pCurrent);*/
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-05-16 17:57:48 +00:00
|
|
|
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
}
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
// Creates a new object instance
|
|
|
|
|
void ObjFileParser::createObject(const std::string &strObjectName)
|
|
|
|
|
{
|
|
|
|
|
ai_assert (NULL != m_pModel);
|
|
|
|
|
ai_assert (!strObjectName.empty());
|
|
|
|
|
|
|
|
|
|
m_pModel->m_pCurrent = new ObjFile::Object();
|
|
|
|
|
m_pModel->m_pCurrent->m_strObjName = strObjectName;
|
|
|
|
|
m_pModel->m_Objects.push_back(m_pModel->m_pCurrent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
// Shows an error in parsing process.
|
|
|
|
|
void ObjFileParser::reportErrorTokenInFace()
|
|
|
|
|
{
|
|
|
|
|
std::string strErr("");
|
2008-05-16 17:57:48 +00:00
|
|
|
|
|
|
|
|
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
2008-05-05 12:36:31 +00:00
|
|
|
|
std::cerr << "Not supported token in face desc. detected : " << strErr << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
// Extracts the extention from a filename
|
2008-08-14 21:25:50 +00:00
|
|
|
|
void ObjFileParser::extractExtension(const std::string &strFile,
|
2008-05-05 12:36:31 +00:00
|
|
|
|
std::string &strExt)
|
|
|
|
|
{
|
|
|
|
|
strExt = "";
|
|
|
|
|
if (strFile.empty())
|
|
|
|
|
return;
|
|
|
|
|
|
2008-09-07 20:50:51 +00:00
|
|
|
|
// Search for extention delimiter
|
2008-05-05 12:36:31 +00:00
|
|
|
|
std::string::size_type pos = strFile.find_last_of(".");
|
2008-09-07 20:50:51 +00:00
|
|
|
|
if ( pos == std::string::npos )
|
2008-05-05 12:36:31 +00:00
|
|
|
|
return;
|
2008-09-07 20:50:51 +00:00
|
|
|
|
|
2008-05-05 12:36:31 +00:00
|
|
|
|
strExt = strFile.substr(pos, strFile.size() - pos);
|
|
|
|
|
}
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
} // Namespace Assimp
|
2009-01-18 23:48:25 +00:00
|
|
|
|
|
|
|
|
|
#endif // !! ASSIMP_BUILD_NO_OBJ_IMPORTER
|