bugfix: Obj-importer is now able to deal with 3d-texture coordinates.
Signed-off-by: Kim Kulling <kim.kulling@googlemail.com>pull/265/head
parent
d49837819e
commit
fbaf89492d
|
@ -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
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue