Merge pull request #1061 from assimp/optimized_faces_in_obj
ObjImporter: remove unnecessary allocations of std::vectorpull/1062/head
commit
888ea72f20
|
@ -38,6 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
#ifndef OBJ_FILEDATA_H_INC
|
#ifndef OBJ_FILEDATA_H_INC
|
||||||
#define OBJ_FILEDATA_H_INC
|
#define OBJ_FILEDATA_H_INC
|
||||||
|
|
||||||
|
@ -56,59 +57,43 @@ struct Material;
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
//! \struct Face
|
//! \struct Face
|
||||||
//! \brief Data structure for a simple obj-face, describes discredit,l.ation and materials
|
//! \brief Data structure for a simple obj-face, describes discredit,l.ation and materials
|
||||||
struct Face
|
// ------------------------------------------------------------------------------------------------
|
||||||
{
|
struct Face {
|
||||||
typedef std::vector<unsigned int> IndexArray;
|
typedef std::vector<unsigned int> IndexArray;
|
||||||
|
|
||||||
//! Primitive type
|
//! Primitive type
|
||||||
aiPrimitiveType m_PrimitiveType;
|
aiPrimitiveType m_PrimitiveType;
|
||||||
//! Vertex indices
|
//! Vertex indices
|
||||||
IndexArray *m_pVertices;
|
IndexArray m_vertices;
|
||||||
//! Normal indices
|
//! Normal indices
|
||||||
IndexArray *m_pNormals;
|
IndexArray m_normals;
|
||||||
//! Texture coordinates indices
|
//! Texture coordinates indices
|
||||||
IndexArray *m_pTexturCoords;
|
IndexArray m_texturCoords;
|
||||||
//! Pointer to assigned material
|
//! Pointer to assigned material
|
||||||
Material *m_pMaterial;
|
Material *m_pMaterial;
|
||||||
|
|
||||||
//! \brief Default constructor
|
//! \brief Default constructor
|
||||||
//! \param pVertices Pointer to assigned vertex indexbuffer
|
Face( aiPrimitiveType pt = aiPrimitiveType_POLYGON)
|
||||||
//! \param pNormals Pointer to assigned normals indexbuffer
|
: m_PrimitiveType( pt )
|
||||||
//! \param pTexCoords Pointer to assigned texture indexbuffer
|
, m_vertices()
|
||||||
Face( std::vector<unsigned int> *pVertices,
|
, m_normals()
|
||||||
std::vector<unsigned int> *pNormals,
|
, m_texturCoords()
|
||||||
std::vector<unsigned int> *pTexCoords,
|
, m_pMaterial( 0L ) {
|
||||||
aiPrimitiveType pt = aiPrimitiveType_POLYGON) :
|
|
||||||
m_PrimitiveType( pt ),
|
|
||||||
m_pVertices( pVertices ),
|
|
||||||
m_pNormals( pNormals ),
|
|
||||||
m_pTexturCoords( pTexCoords ),
|
|
||||||
m_pMaterial( 0L )
|
|
||||||
{
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \brief Destructor
|
//! \brief Destructor
|
||||||
~Face()
|
~Face() {
|
||||||
{
|
// empty
|
||||||
delete m_pVertices;
|
|
||||||
m_pVertices = NULL;
|
|
||||||
|
|
||||||
delete m_pNormals;
|
|
||||||
m_pNormals = NULL;
|
|
||||||
|
|
||||||
delete m_pTexturCoords;
|
|
||||||
m_pTexturCoords = NULL;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
//! \struct Object
|
//! \struct Object
|
||||||
//! \brief Stores all objects of an obj-file object definition
|
//! \brief Stores all objects of an obj-file object definition
|
||||||
struct Object
|
// ------------------------------------------------------------------------------------------------
|
||||||
{
|
struct Object {
|
||||||
enum ObjectType
|
enum ObjectType {
|
||||||
{
|
|
||||||
ObjType,
|
ObjType,
|
||||||
GroupType
|
GroupType
|
||||||
};
|
};
|
||||||
|
@ -123,29 +108,24 @@ struct Object
|
||||||
std::vector<unsigned int> m_Meshes;
|
std::vector<unsigned int> m_Meshes;
|
||||||
|
|
||||||
//! \brief Default constructor
|
//! \brief Default constructor
|
||||||
Object() :
|
Object()
|
||||||
m_strObjName("")
|
: m_strObjName("") {
|
||||||
{
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \brief Destructor
|
//! \brief Destructor
|
||||||
~Object()
|
~Object() {
|
||||||
{
|
for ( std::vector<Object*>::iterator it = m_SubObjects.begin(); it != m_SubObjects.end(); ++it) {
|
||||||
for (std::vector<Object*>::iterator it = m_SubObjects.begin();
|
|
||||||
it != m_SubObjects.end(); ++it)
|
|
||||||
{
|
|
||||||
delete *it;
|
delete *it;
|
||||||
}
|
}
|
||||||
m_SubObjects.clear();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
//! \struct Material
|
//! \struct Material
|
||||||
//! \brief Data structure to store all material specific data
|
//! \brief Data structure to store all material specific data
|
||||||
struct Material
|
// ------------------------------------------------------------------------------------------------
|
||||||
{
|
struct Material {
|
||||||
//! Name of material description
|
//! Name of material description
|
||||||
aiString MaterialName;
|
aiString MaterialName;
|
||||||
|
|
||||||
|
@ -205,18 +185,15 @@ struct Material
|
||||||
, alpha (ai_real( 1.0 ) )
|
, alpha (ai_real( 1.0 ) )
|
||||||
, shineness ( ai_real( 0.0) )
|
, shineness ( ai_real( 0.0) )
|
||||||
, illumination_model (1)
|
, illumination_model (1)
|
||||||
, ior ( ai_real( 1.0 ) )
|
, ior ( ai_real( 1.0 ) ) {
|
||||||
{
|
|
||||||
// empty
|
// empty
|
||||||
for (size_t i = 0; i < TextureTypeCount; ++i)
|
for (size_t i = 0; i < TextureTypeCount; ++i) {
|
||||||
{
|
clamp[ i ] = false;
|
||||||
clamp[i] = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~Material()
|
~Material() {
|
||||||
{
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -224,6 +201,7 @@ struct Material
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
//! \struct Mesh
|
//! \struct Mesh
|
||||||
//! \brief Data structure to store a mesh
|
//! \brief Data structure to store a mesh
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
struct Mesh {
|
struct Mesh {
|
||||||
static const unsigned int NoMaterial = ~0u;
|
static const unsigned int NoMaterial = ~0u;
|
||||||
/// The name for the mesh
|
/// The name for the mesh
|
||||||
|
@ -254,8 +232,7 @@ struct Mesh {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~Mesh()
|
~Mesh() {
|
||||||
{
|
|
||||||
for (std::vector<Face*>::iterator it = m_Faces.begin();
|
for (std::vector<Face*>::iterator it = m_Faces.begin();
|
||||||
it != m_Faces.end(); ++it)
|
it != m_Faces.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -267,8 +244,8 @@ struct Mesh {
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
//! \struct Model
|
//! \struct Model
|
||||||
//! \brief Data structure to store all obj-specific model datas
|
//! \brief Data structure to store all obj-specific model datas
|
||||||
struct Model
|
// ------------------------------------------------------------------------------------------------
|
||||||
{
|
struct Model {
|
||||||
typedef std::map<std::string, std::vector<unsigned int>* > GroupMap;
|
typedef std::map<std::string, std::vector<unsigned int>* > GroupMap;
|
||||||
typedef std::map<std::string, std::vector<unsigned int>* >::iterator GroupMapIt;
|
typedef std::map<std::string, std::vector<unsigned int>* >::iterator GroupMapIt;
|
||||||
typedef std::map<std::string, std::vector<unsigned int>* >::const_iterator ConstGroupMapIt;
|
typedef std::map<std::string, std::vector<unsigned int>* >::const_iterator ConstGroupMapIt;
|
||||||
|
@ -320,8 +297,7 @@ struct Model
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \brief The class destructor
|
//! \brief The class destructor
|
||||||
~Model()
|
~Model() {
|
||||||
{
|
|
||||||
// Clear all stored object instances
|
// Clear all stored object instances
|
||||||
for (std::vector<Object*>::iterator it = m_Objects.begin();
|
for (std::vector<Object*>::iterator it = m_Objects.begin();
|
||||||
it != m_Objects.end(); ++it) {
|
it != m_Objects.end(); ++it) {
|
||||||
|
@ -352,4 +328,4 @@ struct Model
|
||||||
} // Namespace ObjFile
|
} // Namespace ObjFile
|
||||||
} // Namespace Assimp
|
} // Namespace Assimp
|
||||||
|
|
||||||
#endif
|
#endif // OBJ_FILEDATA_H_INC
|
||||||
|
|
|
@ -326,14 +326,14 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
|
||||||
ai_assert( NULL != inp );
|
ai_assert( NULL != inp );
|
||||||
|
|
||||||
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
|
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
|
||||||
pMesh->mNumFaces += inp->m_pVertices->size() - 1;
|
pMesh->mNumFaces += inp->m_vertices.size() - 1;
|
||||||
pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
|
pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
|
||||||
} else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
|
} else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
|
||||||
pMesh->mNumFaces += inp->m_pVertices->size();
|
pMesh->mNumFaces += inp->m_vertices.size();
|
||||||
pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
|
pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
|
||||||
} else {
|
} else {
|
||||||
++pMesh->mNumFaces;
|
++pMesh->mNumFaces;
|
||||||
if (inp->m_pVertices->size() > 3) {
|
if (inp->m_vertices.size() > 3) {
|
||||||
pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
|
pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
|
||||||
} else {
|
} else {
|
||||||
pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
||||||
|
@ -354,7 +354,7 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
|
||||||
for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) {
|
for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) {
|
||||||
ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
|
ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
|
||||||
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
|
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
|
||||||
for(size_t i = 0; i < inp->m_pVertices->size() - 1; ++i) {
|
for(size_t i = 0; i < inp->m_vertices.size() - 1; ++i) {
|
||||||
aiFace& f = pMesh->mFaces[ outIndex++ ];
|
aiFace& f = pMesh->mFaces[ outIndex++ ];
|
||||||
uiIdxCount += f.mNumIndices = 2;
|
uiIdxCount += f.mNumIndices = 2;
|
||||||
f.mIndices = new unsigned int[2];
|
f.mIndices = new unsigned int[2];
|
||||||
|
@ -362,7 +362,7 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
|
else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
|
||||||
for(size_t i = 0; i < inp->m_pVertices->size(); ++i) {
|
for(size_t i = 0; i < inp->m_vertices.size(); ++i) {
|
||||||
aiFace& f = pMesh->mFaces[ outIndex++ ];
|
aiFace& f = pMesh->mFaces[ outIndex++ ];
|
||||||
uiIdxCount += f.mNumIndices = 1;
|
uiIdxCount += f.mNumIndices = 1;
|
||||||
f.mIndices = new unsigned int[1];
|
f.mIndices = new unsigned int[1];
|
||||||
|
@ -371,7 +371,7 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
|
||||||
}
|
}
|
||||||
|
|
||||||
aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
|
aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
|
||||||
const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size();
|
const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_vertices.size();
|
||||||
uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
|
uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
|
||||||
if (pFace->mNumIndices > 0) {
|
if (pFace->mNumIndices > 0) {
|
||||||
pFace->mIndices = new unsigned int[ uiNumIndices ];
|
pFace->mIndices = new unsigned int[ uiNumIndices ];
|
||||||
|
@ -436,8 +436,8 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
|
||||||
ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ];
|
ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ];
|
||||||
|
|
||||||
// Copy all index arrays
|
// Copy all index arrays
|
||||||
for ( size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < pSourceFace->m_pVertices->size(); vertexIndex++ ) {
|
for ( size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < pSourceFace->m_vertices.size(); vertexIndex++ ) {
|
||||||
const unsigned int vertex = pSourceFace->m_pVertices->at( vertexIndex );
|
const unsigned int vertex = pSourceFace->m_vertices.at( vertexIndex );
|
||||||
if ( vertex >= pModel->m_Vertices.size() ) {
|
if ( vertex >= pModel->m_Vertices.size() ) {
|
||||||
throw DeadlyImportError( "OBJ: vertex index out of range" );
|
throw DeadlyImportError( "OBJ: vertex index out of range" );
|
||||||
}
|
}
|
||||||
|
@ -445,8 +445,8 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
|
||||||
pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
|
pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
|
||||||
|
|
||||||
// Copy all normals
|
// Copy all normals
|
||||||
if ( !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_pNormals->size()) {
|
if ( !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_normals.size()) {
|
||||||
const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex );
|
const unsigned int normal = pSourceFace->m_normals.at( vertexIndex );
|
||||||
if ( normal >= pModel->m_Normals.size() ) {
|
if ( normal >= pModel->m_Normals.size() ) {
|
||||||
throw DeadlyImportError( "OBJ: vertex normal index out of range" );
|
throw DeadlyImportError( "OBJ: vertex normal index out of range" );
|
||||||
}
|
}
|
||||||
|
@ -461,9 +461,9 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy all texture coordinates
|
// Copy all texture coordinates
|
||||||
if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_pTexturCoords->size())
|
if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_texturCoords.size())
|
||||||
{
|
{
|
||||||
const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
|
const unsigned int tex = pSourceFace->m_texturCoords.at( vertexIndex );
|
||||||
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() )
|
||||||
|
@ -480,7 +480,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
|
||||||
// Get destination face
|
// Get destination face
|
||||||
aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
|
aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
|
||||||
|
|
||||||
const bool last = ( vertexIndex == pSourceFace->m_pVertices->size() - 1 );
|
const bool last = ( vertexIndex == pSourceFace->m_vertices.size() - 1 );
|
||||||
if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) {
|
if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) {
|
||||||
pDestFace->mIndices[ outVertexIndex ] = newIndex;
|
pDestFace->mIndices[ outVertexIndex ] = newIndex;
|
||||||
outVertexIndex++;
|
outVertexIndex++;
|
||||||
|
@ -498,7 +498,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
|
||||||
if (vertexIndex) {
|
if (vertexIndex) {
|
||||||
if(!last) {
|
if(!last) {
|
||||||
pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
|
pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
|
||||||
if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty()) {
|
if ( !pSourceFace->m_normals.empty() && !pModel->m_Normals.empty()) {
|
||||||
pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
|
pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
|
||||||
}
|
}
|
||||||
if ( !pModel->m_TextureCoord.empty() ) {
|
if ( !pModel->m_TextureCoord.empty() ) {
|
||||||
|
|
|
@ -87,16 +87,14 @@ ObjFileParser::ObjFileParser( IOStreamBuffer<char> &streamBuffer, const std::str
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Destructor
|
// Destructor
|
||||||
ObjFileParser::~ObjFileParser()
|
ObjFileParser::~ObjFileParser() {
|
||||||
{
|
|
||||||
delete m_pModel;
|
delete m_pModel;
|
||||||
m_pModel = NULL;
|
m_pModel = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Returns a pointer to the model instance.
|
// Returns a pointer to the model instance.
|
||||||
ObjFile::Model *ObjFileParser::GetModel() const
|
ObjFile::Model *ObjFileParser::GetModel() const {
|
||||||
{
|
|
||||||
return m_pModel;
|
return m_pModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +401,7 @@ static const std::string DefaultObjName = "defaultobject";
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Get values for a new face instance
|
// Get values for a new face instance
|
||||||
void ObjFileParser::getFace(aiPrimitiveType type) {
|
void ObjFileParser::getFace( aiPrimitiveType type ) {
|
||||||
copyNextLine(m_buffer, Buffersize);
|
copyNextLine(m_buffer, Buffersize);
|
||||||
char *pPtr = m_buffer;
|
char *pPtr = m_buffer;
|
||||||
char *pEnd = &pPtr[Buffersize];
|
char *pEnd = &pPtr[Buffersize];
|
||||||
|
@ -412,9 +410,7 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned int> *pIndices = new std::vector<unsigned int>;
|
ObjFile::Face *face = new ObjFile::Face( type );
|
||||||
std::vector<unsigned int> *pTexID = new std::vector<unsigned int>;
|
|
||||||
std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
|
|
||||||
bool hasNormal = false;
|
bool hasNormal = false;
|
||||||
|
|
||||||
const int vSize = m_pModel->m_Vertices.size();
|
const int vSize = m_pModel->m_Vertices.size();
|
||||||
|
@ -458,45 +454,28 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
|
||||||
++iStep;
|
++iStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( iVal > 0 )
|
if ( iVal > 0 ) {
|
||||||
{
|
|
||||||
// Store parsed index
|
// Store parsed index
|
||||||
if ( 0 == iPos )
|
if ( 0 == iPos ) {
|
||||||
{
|
face->m_vertices.push_back( iVal - 1 );
|
||||||
pIndices->push_back( iVal-1 );
|
} else if ( 1 == iPos ) {
|
||||||
}
|
face->m_texturCoords.push_back( iVal - 1 );
|
||||||
else if ( 1 == iPos )
|
} else if ( 2 == iPos ) {
|
||||||
{
|
face->m_normals.push_back( iVal - 1 );
|
||||||
pTexID->push_back( iVal-1 );
|
|
||||||
}
|
|
||||||
else if ( 2 == iPos )
|
|
||||||
{
|
|
||||||
pNormalID->push_back( iVal-1 );
|
|
||||||
hasNormal = true;
|
hasNormal = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
reportErrorTokenInFace();
|
reportErrorTokenInFace();
|
||||||
}
|
}
|
||||||
}
|
} else if ( iVal < 0 ) {
|
||||||
else if ( iVal < 0 )
|
|
||||||
{
|
|
||||||
// Store relatively index
|
// Store relatively index
|
||||||
if ( 0 == iPos )
|
if ( 0 == iPos ) {
|
||||||
{
|
face->m_vertices.push_back( vSize + iVal );
|
||||||
pIndices->push_back( vSize + iVal );
|
} else if ( 1 == iPos ) {
|
||||||
}
|
face->m_texturCoords.push_back( vtSize + iVal );
|
||||||
else if ( 1 == iPos )
|
} else if ( 2 == iPos ) {
|
||||||
{
|
face->m_normals.push_back( vnSize + iVal );
|
||||||
pTexID->push_back( vtSize + iVal );
|
|
||||||
}
|
|
||||||
else if ( 2 == iPos )
|
|
||||||
{
|
|
||||||
pNormalID->push_back( vnSize + iVal );
|
|
||||||
hasNormal = true;
|
hasNormal = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
reportErrorTokenInFace();
|
reportErrorTokenInFace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -504,19 +483,13 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
|
||||||
pPtr += iStep;
|
pPtr += iStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pIndices->empty() ) {
|
if ( face->m_vertices.empty() ) {
|
||||||
DefaultLogger::get()->error("Obj: Ignoring empty face");
|
DefaultLogger::get()->error("Obj: Ignoring empty face");
|
||||||
// skip line and clean up
|
// skip line and clean up
|
||||||
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
||||||
delete pNormalID;
|
|
||||||
delete pTexID;
|
|
||||||
delete pIndices;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID, type );
|
|
||||||
|
|
||||||
// Set active material, if one set
|
// Set active material, if one set
|
||||||
if( NULL != m_pModel->m_pCurrentMaterial ) {
|
if( NULL != m_pModel->m_pCurrentMaterial ) {
|
||||||
face->m_pMaterial = m_pModel->m_pCurrentMaterial;
|
face->m_pMaterial = m_pModel->m_pCurrentMaterial;
|
||||||
|
@ -536,8 +509,8 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
|
||||||
|
|
||||||
// Store the face
|
// Store the face
|
||||||
m_pModel->m_pCurrentMesh->m_Faces.push_back( face );
|
m_pModel->m_pCurrentMesh->m_Faces.push_back( face );
|
||||||
m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size();
|
m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int) face->m_vertices.size();
|
||||||
m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size();
|
m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int) face->m_texturCoords.size();
|
||||||
if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal ) {
|
if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal ) {
|
||||||
m_pModel->m_pCurrentMesh->m_hasNormals = true;
|
m_pModel->m_pCurrentMesh->m_hasNormals = true;
|
||||||
}
|
}
|
||||||
|
@ -547,8 +520,7 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Get values for a new material description
|
// Get values for a new material description
|
||||||
void ObjFileParser::getMaterialDesc()
|
void ObjFileParser::getMaterialDesc() {
|
||||||
{
|
|
||||||
// Get next data for material data
|
// Get next data for material data
|
||||||
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
||||||
if (m_DataIt == m_DataItEnd) {
|
if (m_DataIt == m_DataItEnd) {
|
||||||
|
@ -571,28 +543,26 @@ void ObjFileParser::getMaterialDesc()
|
||||||
|
|
||||||
// If the current mesh has the same material, we simply ignore that 'usemtl' command
|
// If the current mesh has the same material, we simply ignore that 'usemtl' command
|
||||||
// There is no need to create another object or even mesh here
|
// There is no need to create another object or even mesh here
|
||||||
if (m_pModel->m_pCurrentMaterial && m_pModel->m_pCurrentMaterial->MaterialName == aiString(strName))
|
if ( m_pModel->m_pCurrentMaterial && m_pModel->m_pCurrentMaterial->MaterialName == aiString( strName ) ) {
|
||||||
skip = true;
|
skip = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!skip)
|
if (!skip) {
|
||||||
{
|
|
||||||
// Search for material
|
// Search for material
|
||||||
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find(strName);
|
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find(strName);
|
||||||
if (it == m_pModel->m_MaterialMap.end())
|
if (it == m_pModel->m_MaterialMap.end()) {
|
||||||
{
|
|
||||||
// Not found, use default material
|
// Not found, use default material
|
||||||
m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
|
m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
|
||||||
DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
|
DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
|
||||||
strName = m_pModel->m_pDefaultMaterial->MaterialName.C_Str();
|
strName = m_pModel->m_pDefaultMaterial->MaterialName.C_Str();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Found, using detected material
|
// Found, using detected material
|
||||||
m_pModel->m_pCurrentMaterial = (*it).second;
|
m_pModel->m_pCurrentMaterial = (*it).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needsNewMesh(strName))
|
if ( needsNewMesh( strName ) ) {
|
||||||
createMesh(strName);
|
createMesh( strName );
|
||||||
|
}
|
||||||
|
|
||||||
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strName);
|
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strName);
|
||||||
}
|
}
|
||||||
|
@ -603,17 +573,12 @@ void ObjFileParser::getMaterialDesc()
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Get a comment, values will be skipped
|
// Get a comment, values will be skipped
|
||||||
void ObjFileParser::getComment()
|
void ObjFileParser::getComment() {
|
||||||
{
|
while (m_DataIt != m_DataItEnd) {
|
||||||
while (m_DataIt != m_DataItEnd)
|
if ( '\n' == (*m_DataIt)) {
|
||||||
{
|
|
||||||
if ( '\n' == (*m_DataIt))
|
|
||||||
{
|
|
||||||
++m_DataIt;
|
++m_DataIt;
|
||||||
break;
|
break;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
++m_DataIt;
|
++m_DataIt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -621,8 +586,7 @@ void ObjFileParser::getComment()
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Get material library from file.
|
// Get material library from file.
|
||||||
void ObjFileParser::getMaterialLib()
|
void ObjFileParser::getMaterialLib() {
|
||||||
{
|
|
||||||
// Translate tuple
|
// Translate tuple
|
||||||
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
||||||
if( m_DataIt == m_DataItEnd ) {
|
if( m_DataIt == m_DataItEnd ) {
|
||||||
|
|
|
@ -47,21 +47,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
|
|
||||||
class TriangulateProcessTest : public ::testing::Test
|
class TriangulateProcessTest : public ::testing::Test {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void SetUp();
|
virtual void SetUp();
|
||||||
virtual void TearDown();
|
virtual void TearDown();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
aiMesh* pcMesh;
|
aiMesh* pcMesh;
|
||||||
TriangulateProcess* piProcess;
|
TriangulateProcess* piProcess;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TriangulateProcessTest::SetUp()
|
void TriangulateProcessTest::SetUp() {
|
||||||
{
|
|
||||||
piProcess = new TriangulateProcess();
|
piProcess = new TriangulateProcess();
|
||||||
pcMesh = new aiMesh();
|
pcMesh = new aiMesh();
|
||||||
|
|
||||||
|
@ -72,22 +68,19 @@ void TriangulateProcessTest::SetUp()
|
||||||
pcMesh->mPrimitiveTypes = aiPrimitiveType_POINT | aiPrimitiveType_LINE |
|
pcMesh->mPrimitiveTypes = aiPrimitiveType_POINT | aiPrimitiveType_LINE |
|
||||||
aiPrimitiveType_LINE | aiPrimitiveType_POLYGON;
|
aiPrimitiveType_LINE | aiPrimitiveType_POLYGON;
|
||||||
|
|
||||||
for (unsigned int m = 0, t = 0, q = 4; m < 1000; ++m)
|
for (unsigned int m = 0, t = 0, q = 4; m < 1000; ++m) {
|
||||||
{
|
|
||||||
++t;
|
++t;
|
||||||
aiFace& face = pcMesh->mFaces[m];
|
aiFace& face = pcMesh->mFaces[m];
|
||||||
face.mNumIndices = t;
|
face.mNumIndices = t;
|
||||||
if (4 == t)
|
if (4 == t) {
|
||||||
{
|
|
||||||
face.mNumIndices = q++;
|
face.mNumIndices = q++;
|
||||||
t = 0;
|
t = 0;
|
||||||
|
|
||||||
if (10 == q)q = 4;
|
if (10 == q)q = 4;
|
||||||
}
|
}
|
||||||
face.mIndices = new unsigned int[face.mNumIndices];
|
face.mIndices = new unsigned int[face.mNumIndices];
|
||||||
for (unsigned int p = 0; p < face.mNumIndices; ++p)
|
for (unsigned int p = 0; p < face.mNumIndices; ++p) {
|
||||||
{
|
face.mIndices[ p ] = pcMesh->mNumVertices;
|
||||||
face.mIndices[p] = pcMesh->mNumVertices;
|
|
||||||
|
|
||||||
// construct fully convex input data in ccw winding, xy plane
|
// construct fully convex input data in ccw winding, xy plane
|
||||||
aiVector3D& v = pcMesh->mVertices[pcMesh->mNumVertices++];
|
aiVector3D& v = pcMesh->mVertices[pcMesh->mNumVertices++];
|
||||||
|
@ -98,51 +91,43 @@ void TriangulateProcessTest::SetUp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangulateProcessTest::TearDown()
|
void TriangulateProcessTest::TearDown() {
|
||||||
{
|
|
||||||
delete piProcess;
|
delete piProcess;
|
||||||
delete pcMesh;
|
delete pcMesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TriangulateProcessTest, testTriangulation)
|
TEST_F(TriangulateProcessTest, testTriangulation) {
|
||||||
{
|
|
||||||
piProcess->TriangulateMesh(pcMesh);
|
piProcess->TriangulateMesh(pcMesh);
|
||||||
|
|
||||||
for (unsigned int m = 0, t = 0, q = 4, max = 1000, idx = 0; m < max;++m)
|
for (unsigned int m = 0, t = 0, q = 4, max = 1000, idx = 0; m < max;++m) {
|
||||||
{
|
|
||||||
++t;
|
++t;
|
||||||
aiFace& face = pcMesh->mFaces[m];
|
aiFace& face = pcMesh->mFaces[m];
|
||||||
if (4 == t)
|
if (4 == t) {
|
||||||
{
|
|
||||||
t = 0;
|
t = 0;
|
||||||
max += q-3;
|
max += q-3;
|
||||||
|
|
||||||
std::vector<bool> ait(q,false);
|
std::vector<bool> ait(q,false);
|
||||||
|
|
||||||
for (unsigned int i = 0, tt = q-2; i < tt; ++i,++m)
|
for (unsigned int i = 0, tt = q-2; i < tt; ++i,++m) {
|
||||||
{
|
|
||||||
aiFace& face = pcMesh->mFaces[m];
|
aiFace& face = pcMesh->mFaces[m];
|
||||||
EXPECT_EQ(3U, face.mNumIndices);
|
EXPECT_EQ(3U, face.mNumIndices);
|
||||||
|
|
||||||
for (unsigned int qqq = 0; qqq < face.mNumIndices; ++qqq)
|
for (unsigned int qqq = 0; qqq < face.mNumIndices; ++qqq) {
|
||||||
{
|
|
||||||
ait[face.mIndices[qqq]-idx] = true;
|
ait[face.mIndices[qqq]-idx] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (std::vector<bool>::const_iterator it = ait.begin(); it != ait.end(); ++it)
|
for (std::vector<bool>::const_iterator it = ait.begin(); it != ait.end(); ++it) {
|
||||||
{
|
|
||||||
EXPECT_TRUE(*it);
|
EXPECT_TRUE(*it);
|
||||||
}
|
}
|
||||||
--m;
|
--m;
|
||||||
idx+=q;
|
idx+=q;
|
||||||
if(++q == 10)q = 4;
|
if ( ++q == 10 ) {
|
||||||
|
q = 4;
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
{
|
|
||||||
EXPECT_EQ(t, face.mNumIndices);
|
EXPECT_EQ(t, face.mNumIndices);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < face.mNumIndices; ++i,++idx)
|
for (unsigned int i = 0; i < face.mNumIndices; ++i,++idx) {
|
||||||
{
|
|
||||||
EXPECT_EQ(idx, face.mIndices[i]);
|
EXPECT_EQ(idx, face.mIndices[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue