bugfix: Obj-importer is now able to deal with 3d-texture coordinates.

Signed-off-by: Kim Kulling <kim.kulling@googlemail.com>
pull/265/head
Kim Kulling 2014-04-29 00:04:54 +02:00
parent d49837819e
commit fbaf89492d
5 changed files with 79 additions and 52 deletions

View File

@ -290,7 +290,7 @@ struct Model
//! Active group //! Active group
std::string m_strActiveGroup; std::string m_strActiveGroup;
//! Vector with generated texture coordinates //! Vector with generated texture coordinates
std::vector<aiVector2D> m_TextureCoord; std::vector<aiVector3D> m_TextureCoord;
//! Current mesh instance //! Current mesh instance
Mesh *m_pCurrentMesh; Mesh *m_pCurrentMesh;
//! Vector with stored meshes //! Vector with stored meshes

View File

@ -60,6 +60,7 @@ static const aiImporterDesc desc = {
"obj" "obj"
}; };
static const unsigned int ObjMinSize = 16;
namespace Assimp { namespace Assimp {
@ -80,12 +81,8 @@ ObjFileImporter::ObjFileImporter() :
// Destructor. // Destructor.
ObjFileImporter::~ObjFileImporter() ObjFileImporter::~ObjFileImporter()
{ {
// Release root object instance delete m_pRootObject;
if (NULL != m_pRootObject) m_pRootObject = NULL;
{
delete m_pRootObject;
m_pRootObject = NULL;
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -118,12 +115,13 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
// Read file into memory // Read file into memory
const std::string mode = "rb"; const std::string mode = "rb";
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode)); boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode));
if (NULL == file.get()) if( !file.get() ) {
throw DeadlyImportError( "Failed to open file " + pFile + "."); throw DeadlyImportError( "Failed to open file " + pFile + "." );
}
// Get the file-size and validate it, throwing an exception when fails // Get the file-size and validate it, throwing an exception when fails
size_t fileSize = file->FileSize(); size_t fileSize = file->FileSize();
if( fileSize < 16) { if( fileSize < ObjMinSize ) {
throw DeadlyImportError( "OBJ-file is too small."); throw DeadlyImportError( "OBJ-file is too small.");
} }
@ -154,10 +152,10 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Create the data from parsed obj-file // Create the data from parsed obj-file
void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene) void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene) {
{ if( 0L == pModel ) {
if (0L == pModel) return;
return; }
// Create the root node of the scene // Create the root node of the scene
pScene->mRootNode = new aiNode; pScene->mRootNode = new aiNode;
@ -200,8 +198,9 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
std::vector<aiMesh*> &MeshArray ) std::vector<aiMesh*> &MeshArray )
{ {
ai_assert( NULL != pModel ); ai_assert( NULL != pModel );
if ( NULL == pObject ) if( NULL == pObject ) {
return NULL; return NULL;
}
// Store older mesh size to be able to computes mesh offsets for new mesh instances // Store older mesh size to be able to computes mesh offsets for new mesh instances
const size_t oldMeshSize = MeshArray.size(); const size_t oldMeshSize = MeshArray.size();
@ -210,8 +209,9 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
pNode->mName = pObject->m_strObjName; pNode->mName = pObject->m_strObjName;
// If we have a parent node, store it // If we have a parent node, store it
if (pParent != NULL) if( pParent != NULL ) {
appendChildToParentNode(pParent, pNode); appendChildToParentNode( pParent, pNode );
}
for ( unsigned int i=0; i< pObject->m_Meshes.size(); i++ ) for ( unsigned int i=0; i< pObject->m_Meshes.size(); i++ )
{ {
@ -265,8 +265,9 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
{ {
// Checking preconditions // Checking preconditions
ai_assert( NULL != pModel ); ai_assert( NULL != pModel );
if (NULL == pData) if( NULL == pData ) {
return; return;
}
// Create faces // Create faces
ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ]; ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
@ -284,8 +285,7 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) { else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
pMesh->mNumFaces += inp->m_pVertices->size(); pMesh->mNumFaces += inp->m_pVertices->size();
pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT; pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
} } else {
else {
++pMesh->mNumFaces; ++pMesh->mNumFaces;
if (inp->m_pVertices->size() > 3) { if (inp->m_pVertices->size() > 3) {
pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
@ -409,10 +409,10 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
ai_assert( tex < pModel->m_TextureCoord.size() ); ai_assert( tex < pModel->m_TextureCoord.size() );
if ( tex >= pModel->m_TextureCoord.size() ) if ( tex >= pModel->m_TextureCoord.size() )
throw DeadlyImportError("OBJ: texture coord index out of range"); throw DeadlyImportError("OBJ: texture coordinate index out of range");
aiVector2D coord2d = pModel->m_TextureCoord[ tex ]; const aiVector3D &coord3d = pModel->m_TextureCoord[ tex ];
pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 ); pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord3d.x, coord3d.y, coord3d.z );
} }
ai_assert( pMesh->mNumVertices > newIndex ); ai_assert( pMesh->mNumVertices > newIndex );

View File

@ -108,19 +108,14 @@ void ObjFileParser::parseFile()
case 'v': // Parse a vertex texture coordinate case 'v': // Parse a vertex texture coordinate
{ {
++m_DataIt; ++m_DataIt;
if (*m_DataIt == ' ' || *m_DataIt == '\t') if (*m_DataIt == ' ' || *m_DataIt == '\t') {
{ // read in vertex definition
// Read in vertex definition
getVector3(m_pModel->m_Vertices); getVector3(m_pModel->m_Vertices);
} } else if (*m_DataIt == 't') {
else if (*m_DataIt == 't') // read in texture coordinate ( 2D or 3D )
{ ++m_DataIt;
// Read in texture coordinate (2D) getVector( m_pModel->m_TextureCoord );
++m_DataIt; } else if (*m_DataIt == 'n') {
getVector2(m_pModel->m_TextureCoord);
}
else if (*m_DataIt == 'n')
{
// Read in normal vector definition // Read in normal vector definition
++m_DataIt; ++m_DataIt;
getVector3( m_pModel->m_Normals ); getVector3( m_pModel->m_Normals );
@ -235,10 +230,43 @@ void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
pBuffer[ index ] = '\0'; pBuffer[ index ] = '\0';
} }
// -------------------------------------------------------------------
void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
size_t numComponents( 0 );
DataArrayIt tmp( m_DataIt );
while( !IsLineEnd( *tmp ) ) {
if( *tmp == ' ' ) {
++numComponents;
}
tmp++;
}
float x, y, z;
if( 2 == numComponents ) {
copyNextWord( m_buffer, BUFFERSIZE );
x = ( float ) fast_atof( m_buffer );
copyNextWord( m_buffer, BUFFERSIZE );
y = ( float ) fast_atof( m_buffer );
z = 0.0;
} else if( 3 == numComponents ) {
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 );
} else {
ai_assert( !"Invalid number of components" );
}
point3d_array.push_back( aiVector3D( x, y, z ) );
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Get values for a new 3D vector instance // Get values for a new 3D vector instance
void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array) void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array) {
{
float x, y, z; float x, y, z;
copyNextWord(m_buffer, BUFFERSIZE); copyNextWord(m_buffer, BUFFERSIZE);
x = (float) fast_atof(m_buffer); x = (float) fast_atof(m_buffer);
@ -246,18 +274,16 @@ void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array)
copyNextWord(m_buffer, BUFFERSIZE); copyNextWord(m_buffer, BUFFERSIZE);
y = (float) fast_atof(m_buffer); y = (float) fast_atof(m_buffer);
copyNextWord(m_buffer, BUFFERSIZE); copyNextWord( m_buffer, BUFFERSIZE );
z = (float) fast_atof(m_buffer); z = ( float ) fast_atof( m_buffer );
point3d_array.push_back( aiVector3D( x, y, z ) ); point3d_array.push_back( aiVector3D( x, y, z ) );
//skipLine();
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Get values for a new 2D vector instance // Get values for a new 2D vector instance
void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
{
float x, y; float x, y;
copyNextWord(m_buffer, BUFFERSIZE); copyNextWord(m_buffer, BUFFERSIZE);
x = (float) fast_atof(m_buffer); x = (float) fast_atof(m_buffer);

View File

@ -37,8 +37,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
#ifndef OBJ_FILEPARSER_H_INC #ifndef OBJ_FILEPARSER_H_INC
#define OBJ_FILEPARSER_H_INC #define OBJ_FILEPARSER_H_INC
@ -79,26 +77,29 @@ public:
ObjFile::Model *GetModel() const; ObjFile::Model *GetModel() const;
private: private:
/// Parse the loadedfile /// Parse the loaded file
void parseFile(); void parseFile();
/// Method to copy the new delimited word in the current line. /// Method to copy the new delimited word in the current line.
void copyNextWord(char *pBuffer, size_t length); void copyNextWord(char *pBuffer, size_t length);
/// Method to copy the new line. /// Method to copy the new line.
void copyNextLine(char *pBuffer, size_t length); void copyNextLine(char *pBuffer, size_t length);
/// Stores the following 3d vector. /// Stores the vector
void getVector( std::vector<aiVector3D> &point3d_array );
/// Stores the following 3d vector.
void getVector3( std::vector<aiVector3D> &point3d_array ); void getVector3( std::vector<aiVector3D> &point3d_array );
/// Stores the following 3d vector. /// Stores the following 3d vector.
void getVector2(std::vector<aiVector2D> &point2d_array); void getVector2(std::vector<aiVector2D> &point2d_array);
/// Stores the following face. /// Stores the following face.
void getFace(aiPrimitiveType type); void getFace(aiPrimitiveType type);
void getMaterialDesc(); /// Reads the material description.
void getMaterialDesc();
/// Gets a comment. /// Gets a comment.
void getComment(); void getComment();
/// Gets a a material library. /// Gets a a material library.
void getMaterialLib(); void getMaterialLib();
/// Creates a new material. /// Creates a new material.
void getNewMaterial(); void getNewMaterial();
/// Gets the groupname from file. /// Gets the group name from file.
void getGroupName(); void getGroupName();
/// Gets the group number from file. /// Gets the group number from file.
void getGroupNumber(); void getGroupNumber();

View File

@ -107,7 +107,7 @@ inline Char_T getNextWord( Char_T pBuffer, Char_T pEnd )
return pBuffer; return pBuffer;
} }
/** @brief Returns ponter a next token /** @brief Returns pointer a next token
* @param pBuffer Pointer to data buffer * @param pBuffer Pointer to data buffer
* @param pEnd Pointer to end of buffer * @param pEnd Pointer to end of buffer
* @return Pointer to next token * @return Pointer to next token