PLYImporter: - optimize memory and speed on ply importer / change parser to use a...
authorArkeon <arkeon.work@gmail.com>
Fri, 2 Jun 2017 11:24:56 +0000 (13:24 +0200)
committerArkeon <arkeon.work@gmail.com>
Fri, 2 Jun 2017 11:48:57 +0000 (13:48 +0200)
IFC :
 - update poly2tri to avoid crash on some IFC files

Collada :
 - manage missing texture reference in collada import

19 files changed:
code/ColladaLoader.cpp
code/IOStreamBuffer.h
code/PlyLoader.cpp
code/PlyLoader.h
code/PlyParser.cpp
code/PlyParser.h
code/STLLoader.cpp
contrib/poly2tri/poly2tri/common/shapes.cc
contrib/poly2tri/poly2tri/common/shapes.h
contrib/poly2tri/poly2tri/common/utils.h
contrib/poly2tri/poly2tri/poly2tri.h
contrib/poly2tri/poly2tri/sweep/advancing_front.cc
contrib/poly2tri/poly2tri/sweep/advancing_front.h
contrib/poly2tri/poly2tri/sweep/cdt.cc
contrib/poly2tri/poly2tri/sweep/cdt.h
contrib/poly2tri/poly2tri/sweep/sweep.cc
contrib/poly2tri/poly2tri/sweep/sweep.h
contrib/poly2tri/poly2tri/sweep/sweep_context.cc
contrib/poly2tri/poly2tri/sweep/sweep_context.h

index 457b62c..5cec0a0 100644 (file)
@@ -1726,6 +1726,8 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
 aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser,
     const Collada::Effect& pEffect, const std::string& pName)
 {
+    aiString result;
+
     // recurse through the param references until we end up at an image
     std::string name = pName;
     while( 1)
@@ -1744,11 +1746,17 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
     ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
     if( imIt == pParser.mImageLibrary.end())
     {
-        throw DeadlyImportError( format() <<
-            "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
-    }
+        //missing texture should not stop the conversion
+        //throw DeadlyImportError( format() <<
+        //    "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
 
-    aiString result;
+        DefaultLogger::get()->warn("Collada: Unable to resolve effect texture entry \"" + pName + "\", ended up at ID \"" + name + "\".");
+
+        //set default texture file name
+        result.Set(name + ".jpg");
+        ConvertPath(result);
+        return result;
+    }
 
     // if this is an embedded texture image setup an aiTexture for it
     if (imIt->second.mFileName.empty())
index b808100..577e3f8 100644 (file)
@@ -100,6 +100,11 @@ public:
     /// @return true if successful.
     bool getNextDataLine( std::vector<T> &buffer, T continuationToken );
 
+    /// @brief  Will read the next block.
+    /// @param  buffer      The buffer for the next block.
+    /// @return true if successful.
+    bool getNextBlock( std::vector<T> &buffer );
+
 private:
     IOStream *m_stream;
     size_t m_filesize;
@@ -274,4 +279,21 @@ bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationT
     return true;
 }
 
+template<class T>
+inline
+bool IOStreamBuffer<T>::getNextBlock( std::vector<T> &buffer) {
+  //just return the last blockvalue if getNextLine was used before
+  if ( m_cachePos !=  0) {      
+      buffer = std::vector<T>(m_cache.begin() + m_cachePos, m_cache.end());
+      m_cachePos = 0;
+  }
+  else {
+      if ( !readNextBlock() )
+          return false;
+
+      buffer = std::vector<T>(m_cache.begin(), m_cache.end());
+  }
+  return true;
+}
+
 } // !ns Assimp
index 7cfa067..d815b22 100644 (file)
@@ -5,7 +5,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2017, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -13,18 +12,18 @@ 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.
+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.
+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 team.
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@@ -48,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // internal headers
 #include "PlyLoader.h"
+#include "IOStreamBuffer.h"
 #include "Macros.h"
 #include <memory>
 #include <assimp/IOSystem.hpp>
@@ -57,16 +57,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using namespace Assimp;
 
 static const aiImporterDesc desc = {
-    "Stanford Polygon Library (PLY) Importer",
-    "",
-    "",
-    "",
-    aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportTextFlavour,
-    0,
-    0,
-    0,
-    0,
-    "ply"
+  "Stanford Polygon Library (PLY) Importer",
+  "",
+  "",
+  "",
+  aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportTextFlavour,
+  0,
+  0,
+  0,
+  0,
+  "ply"
 };
 
 
@@ -74,1040 +74,983 @@ static const aiImporterDesc desc = {
 // Internal stuff
 namespace
 {
-    // ------------------------------------------------------------------------------------------------
-    // Checks that property index is within range
-    template <class T>
-    const T &GetProperty(const std::vector<T> &props, int idx)
-    {
-        if( static_cast< size_t >( idx ) >= props.size() ) {
-            throw DeadlyImportError( "Invalid .ply file: Property index is out of range." );
-        }
-
-        return props[idx];
+  // ------------------------------------------------------------------------------------------------
+  // Checks that property index is within range
+  template <class T>
+  const T &GetProperty(const std::vector<T> &props, int idx)
+  {
+    if (static_cast<size_t>(idx) >= props.size()) {
+      throw DeadlyImportError("Invalid .ply file: Property index is out of range.");
     }
+
+    return props[idx];
+  }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 PLYImporter::PLYImporter()
-: mBuffer()
-, pcDOM(){
-    // empty
+  : mBuffer()
+  , pcDOM()
+  , mGeneratedMesh(NULL){
+  // empty
 }
 
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 PLYImporter::~PLYImporter() {
-    // empty
+  // empty
 }
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
-bool PLYImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
+bool PLYImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
 {
-    const std::string extension = GetExtension(pFile);
-
-    if (extension == "ply")
-        return true;
-    else if (!extension.length() || checkSig)
-    {
-        if (!pIOHandler)return true;
-        const char* tokens[] = {"ply"};
-        return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
-    }
-    return false;
+  const std::string extension = GetExtension(pFile);
+
+  if (extension == "ply")
+    return true;
+  else if (!extension.length() || checkSig)
+  {
+    if (!pIOHandler)return true;
+    const char* tokens[] = { "ply" };
+    return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
+  }
+  return false;
 }
 
 // ------------------------------------------------------------------------------------------------
-const aiImporterDesc* PLYImporter::GetInfo () const
+const aiImporterDesc* PLYImporter::GetInfo() const
 {
-    return &desc;
+  return &desc;
 }
 
 // ------------------------------------------------------------------------------------------------
-static bool isBigEndian( const char* szMe ) {
-    ai_assert( NULL != szMe );
+static bool isBigEndian(const char* szMe) {
+  ai_assert(NULL != szMe);
 
-    // binary_little_endian
-    // binary_big_endian
-    bool isBigEndian( false );
+  // binary_little_endian
+  // binary_big_endian
+  bool isBigEndian(false);
 #if (defined AI_BUILD_BIG_ENDIAN)
-    if ( 'l' == *szMe || 'L' == *szMe ) {
-        isBigEndian = true;
-}
+  if ( 'l' == *szMe || 'L' == *szMe ) {
+    isBigEndian = true;
+  }
 #else
-    if ( 'b' == *szMe || 'B' == *szMe ) {
-        isBigEndian = true;
-    }
+  if ('b' == *szMe || 'B' == *szMe) {
+    isBigEndian = true;
+  }
 #endif // ! AI_BUILD_BIG_ENDIAN
 
-    return isBigEndian;
+  return isBigEndian;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
-void PLYImporter::InternReadFile( const std::string& pFile,
-    aiScene* pScene, IOSystem* pIOHandler)
+void PLYImporter::InternReadFile(const std::string& pFile,
+  aiScene* pScene, IOSystem* pIOHandler)
 {
-    std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
-
-    // Check whether we can read from the file
-    if( file.get() == NULL) {
-        throw DeadlyImportError( "Failed to open PLY file " + pFile + ".");
+  static const std::string mode = "rb";
+  std::unique_ptr<IOStream> fileStream(pIOHandler->Open(pFile, mode));
+  if (!fileStream.get()) {
+    throw DeadlyImportError("Failed to open file " + pFile + ".");
+  }
+
+  // Get the file-size
+  size_t fileSize = fileStream->FileSize();
+
+  IOStreamBuffer<char> streamedBuffer(1024 * 1024);
+  streamedBuffer.open(fileStream.get());
+
+  // the beginning of the file must be PLY - magic, magic
+  std::vector<char> headerCheck;
+  streamedBuffer.getNextDataLine(headerCheck, '\\');
+
+  if ((headerCheck.size() >= 3) && (headerCheck[0] != 'P' && headerCheck[0] != 'p') ||
+    (headerCheck[1] != 'L' && headerCheck[1] != 'l') ||
+    (headerCheck[2] != 'Y' && headerCheck[2] != 'y'))
+  {
+    streamedBuffer.close();
+    throw DeadlyImportError("Invalid .ply file: Magic number \'ply\' is no there");
+  }
+
+  std::vector<char> mBuffer2;
+  streamedBuffer.getNextDataLine(mBuffer2, '\\');
+  mBuffer = (unsigned char*)&mBuffer2[0];
+
+  char* szMe = (char*)&this->mBuffer[0];
+  SkipSpacesAndLineEnd(szMe, (const char**)&szMe);
+
+  // determine the format of the file data and construct the aimesh
+  PLY::DOM sPlyDom;
+  this->pcDOM = &sPlyDom;
+
+  if (TokenMatch(szMe, "format", 6)) {
+    if (TokenMatch(szMe, "ascii", 5)) {
+      SkipLine(szMe, (const char**)&szMe);
+      if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this))
+      {
+        if (mGeneratedMesh != NULL)
+          delete(mGeneratedMesh);
+
+        streamedBuffer.close();
+        throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#1)");
+      }
+    }
+    else if (!::strncmp(szMe, "binary_", 7))
+    {
+      szMe += 7;
+      const bool bIsBE(isBigEndian(szMe));
+
+      // skip the line, parse the rest of the header and build the DOM
+      if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE))
+      {
+        if (mGeneratedMesh != NULL)
+          delete(mGeneratedMesh);
+
+        streamedBuffer.close();
+        throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#2)");
+      }
     }
+    else
+    {
+      if (mGeneratedMesh != NULL)
+        delete(mGeneratedMesh);
 
-    // allocate storage and copy the contents of the file to a memory buffer
-    std::vector<char> mBuffer2;
-    TextFileToBuffer(file.get(),mBuffer2);
-    mBuffer = (unsigned char*)&mBuffer2[0];
+      streamedBuffer.close();
+      throw DeadlyImportError("Invalid .ply file: Unknown file format");
+    }
+  }
+  else
+  {
+    AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
+    if (mGeneratedMesh != NULL)
+      delete(mGeneratedMesh);
+
+    streamedBuffer.close();
+    throw DeadlyImportError("Invalid .ply file: Missing format specification");
+  }
+
+  //free the file buffer
+  streamedBuffer.close();
+
+  if (mGeneratedMesh == NULL)
+  {
+    throw DeadlyImportError("Invalid .ply file: Unable to extract mesh data ");
+  }
+
+  // if no face list is existing we assume that the vertex
+  // list is containing a list of points
+  bool pointsOnly = mGeneratedMesh->mFaces == NULL ? true : false;
+  if (pointsOnly)
+  {
+    if (mGeneratedMesh->mNumVertices < 3)
+    {
+      if (mGeneratedMesh != NULL)
+        delete(mGeneratedMesh);
 
-    // the beginning of the file must be PLY - magic, magic
-    if ((mBuffer[0] != 'P' && mBuffer[0] != 'p') ||
-        (mBuffer[1] != 'L' && mBuffer[1] != 'l') ||
-        (mBuffer[2] != 'Y' && mBuffer[2] != 'y'))   {
-        throw DeadlyImportError( "Invalid .ply file: Magic number \'ply\' is no there");
+      streamedBuffer.close();
+      throw DeadlyImportError("Invalid .ply file: Not enough "
+        "vertices to build a proper face list. ");
     }
 
-    char* szMe = (char*)&this->mBuffer[3];
-    SkipSpacesAndLineEnd(szMe,(const char**)&szMe);
-
-    // determine the format of the file data
-    PLY::DOM sPlyDom;
-    if (TokenMatch(szMe,"format",6)) {
-        if (TokenMatch(szMe,"ascii",5)) {
-            SkipLine(szMe,(const char**)&szMe);
-            if(!PLY::DOM::ParseInstance(szMe,&sPlyDom))
-                throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#1)");
-        } else if (!::strncmp(szMe,"binary_",7))
-        {
-            szMe += 7;
-            const bool bIsBE( isBigEndian( szMe ) );
+    const unsigned int iNum = (unsigned int)mGeneratedMesh->mNumVertices / 3;
+    mGeneratedMesh->mNumFaces = iNum;
+    mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
 
-            // skip the line, parse the rest of the header and build the DOM
-            SkipLine(szMe,(const char**)&szMe);
-            if ( !PLY::DOM::ParseInstanceBinary( szMe, &sPlyDom, bIsBE ) ) {
-                throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#2)" );
-            }
-        } else {
-            throw DeadlyImportError( "Invalid .ply file: Unknown file format" );
-        }
-    }
-    else
+    for (unsigned int i = 0; i < iNum; ++i)
     {
-        AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
-        throw DeadlyImportError( "Invalid .ply file: Missing format specification");
+      mGeneratedMesh->mFaces[i].mNumIndices = 3;
+      mGeneratedMesh->mFaces[i].mIndices = new unsigned int[3];
+      mGeneratedMesh->mFaces[i].mIndices[0] = (i * 3);
+      mGeneratedMesh->mFaces[i].mIndices[1] = (i * 3) + 1;
+      mGeneratedMesh->mFaces[i].mIndices[2] = (i * 3) + 2;
     }
-    this->pcDOM = &sPlyDom;
+  }
+
+  // now load a list of all materials
+  std::vector<aiMaterial*> avMaterials;
+  std::string defaultTexture;
+  LoadMaterial(&avMaterials, defaultTexture, pointsOnly);
+
+  // now generate the output scene object. Fill the material list
+  pScene->mNumMaterials = (unsigned int)avMaterials.size();
+  pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+  for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
+    pScene->mMaterials[i] = avMaterials[i];
+  }
+
+  // fill the mesh list
+  pScene->mNumMeshes = 1;
+  pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+  pScene->mMeshes[0] = mGeneratedMesh;
+
+  // generate a simple node structure
+  pScene->mRootNode = new aiNode();
+  pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
+  pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
+
+  for (unsigned int i = 0; i < pScene->mRootNode->mNumMeshes; ++i) {
+    pScene->mRootNode->mMeshes[i] = i;
+  }
+}
 
-    // now load a list of vertices. This must be successfully in order to procedure
-    std::vector<aiVector3D> avPositions;
-    this->LoadVertices(&avPositions,false);
+void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos)
+{
+  ai_assert(NULL != pcElement);
+  ai_assert(NULL != instElement);
 
-    if ( avPositions.empty() ) {
-        throw DeadlyImportError( "Invalid .ply file: No vertices found. "
-            "Unable to parse the data format of the PLY file." );
-    }
+  ai_uint aiPositions[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+  PLY::EDataType aiTypes[3] = { EDT_Char, EDT_Char, EDT_Char };
+
+  ai_uint aiNormal[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+  PLY::EDataType aiNormalTypes[3] = { EDT_Char, EDT_Char, EDT_Char };
+
+  unsigned int aiColors[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+  PLY::EDataType aiColorsTypes[4] = { EDT_Char, EDT_Char, EDT_Char, EDT_Char };
+
+  unsigned int aiTexcoord[2] = { 0xFFFFFFFF, 0xFFFFFFFF };
+  PLY::EDataType aiTexcoordTypes[2] = { EDT_Char, EDT_Char };
 
-    // now load a list of normals.
-    std::vector<aiVector3D> avNormals;
-    LoadVertices(&avNormals,true);
+  unsigned int cnt = 0;
 
-    // load the face list
-    std::vector<PLY::Face> avFaces;
-    LoadFaces(&avFaces);
+  // now check whether which normal components are available
+  unsigned int _a = 0;
+  for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
+    a != pcElement->alProperties.end(); ++a, ++_a)
+  {
+    if ((*a).bIsList)continue;
 
-    // if no face list is existing we assume that the vertex
-    // list is containing a list of triangles
-    if (avFaces.empty())
+    // Positions
+    if (PLY::EST_XCoord == (*a).Semantic)
     {
-        if (avPositions.size() < 3)
-        {
-            throw DeadlyImportError( "Invalid .ply file: Not enough "
-                "vertices to build a proper face list. ");
-        }
+      cnt++;
+      aiPositions[0] = _a;
+      aiTypes[0] = (*a).eType;
+    }
+    else if (PLY::EST_YCoord == (*a).Semantic)
+    {
+      cnt++;
+      aiPositions[1] = _a;
+      aiTypes[1] = (*a).eType;
+    }
+    else if (PLY::EST_ZCoord == (*a).Semantic)
+    {
+      cnt++;
+      aiPositions[2] = _a;
+      aiTypes[2] = (*a).eType;
+    }
 
-        const unsigned int iNum = (unsigned int)avPositions.size() / 3;
-        for (unsigned int i = 0; i< iNum;++i)
-        {
-            PLY::Face sFace;
-            sFace.mIndices.push_back((iNum*3));
-            sFace.mIndices.push_back((iNum*3)+1);
-            sFace.mIndices.push_back((iNum*3)+2);
-            avFaces.push_back(sFace);
-        }
+    // Normals
+    else if (PLY::EST_XNormal == (*a).Semantic)
+    {
+      cnt++;
+      aiNormal[0] = _a;
+      aiNormalTypes[0] = (*a).eType;
+    }
+    else if (PLY::EST_YNormal == (*a).Semantic)
+    {
+      cnt++;
+      aiNormal[1] = _a;
+      aiNormalTypes[1] = (*a).eType;
+    }
+    else if (PLY::EST_ZNormal == (*a).Semantic)
+    {
+      cnt++;
+      aiNormal[2] = _a;
+      aiNormalTypes[2] = (*a).eType;
+    }
+    // Colors
+    else if (PLY::EST_Red == (*a).Semantic)
+    {
+      cnt++;
+      aiColors[0] = _a;
+      aiColorsTypes[0] = (*a).eType;
+    }
+    else if (PLY::EST_Green == (*a).Semantic)
+    {
+      cnt++;
+      aiColors[1] = _a;
+      aiColorsTypes[1] = (*a).eType;
+    }
+    else if (PLY::EST_Blue == (*a).Semantic)
+    {
+      cnt++;
+      aiColors[2] = _a;
+      aiColorsTypes[2] = (*a).eType;
+    }
+    else if (PLY::EST_Alpha == (*a).Semantic)
+    {
+      cnt++;
+      aiColors[3] = _a;
+      aiColorsTypes[3] = (*a).eType;
+    }
+    // Texture coordinates
+    else if (PLY::EST_UTextureCoord == (*a).Semantic)
+    {
+      cnt++;
+      aiTexcoord[0] = _a;
+      aiTexcoordTypes[0] = (*a).eType;
+    }
+    else if (PLY::EST_VTextureCoord == (*a).Semantic)
+    {
+      cnt++;
+      aiTexcoord[1] = _a;
+      aiTexcoordTypes[1] = (*a).eType;
+    }
+  }
+
+  // check whether we have a valid source for the vertex data
+  if (0 != cnt)
+  {
+    // Position
+    aiVector3D vOut;
+    if (0xFFFFFFFF != aiPositions[0])
+    {
+      vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]);
     }
 
-    // now load a list of all materials
-    std::vector<aiMaterial*> avMaterials;
-    LoadMaterial(&avMaterials);
+    if (0xFFFFFFFF != aiPositions[1])
+    {
+      vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]);
+    }
 
-    // now load a list of all vertex color channels
-    std::vector<aiColor4D> avColors;
-    avColors.reserve(avPositions.size());
-    LoadVertexColor(&avColors);
+    if (0xFFFFFFFF != aiPositions[2])
+    {
+      vOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]);
+    }
 
-    // now try to load texture coordinates
-    std::vector<aiVector2D> avTexCoords;
-    avTexCoords.reserve(avPositions.size());
-    LoadTextureCoordinates(&avTexCoords);
+    // Normals
+    aiVector3D nOut;
+    bool haveNormal = false;
+    if (0xFFFFFFFF != aiNormal[0])
+    {
+      nOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]);
+      haveNormal = true;
+    }
 
-    // now replace the default material in all faces and validate all material indices
-    ReplaceDefaultMaterial(&avFaces,&avMaterials);
+    if (0xFFFFFFFF != aiNormal[1])
+    {
+      nOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]);
+      haveNormal = true;
+    }
 
-    // now convert this to a list of aiMesh instances
-    std::vector<aiMesh*> avMeshes;
-    avMeshes.reserve(avMaterials.size()+1);
-    ConvertMeshes(&avFaces,&avPositions,&avNormals,
-        &avColors,&avTexCoords,&avMaterials,&avMeshes);
+    if (0xFFFFFFFF != aiNormal[2])
+    {
+      nOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]);
+      haveNormal = true;
+    }
 
-    if ( avMeshes.empty() ) {
-        throw DeadlyImportError( "Invalid .ply file: Unable to extract mesh data " );
+    //Colors
+    aiColor4D cOut;
+    bool haveColor = false;
+    if (0xFFFFFFFF != aiColors[0])
+    {
+      cOut.r = NormalizeColorValue(GetProperty(instElement->alProperties,
+        aiColors[0]).avList.front(), aiColorsTypes[0]);
+      haveColor = true;
     }
 
-    // now generate the output scene object. Fill the material list
-    pScene->mNumMaterials = (unsigned int)avMaterials.size();
-    pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
-    for ( unsigned int i = 0; i < pScene->mNumMaterials; ++i ) {
-        pScene->mMaterials[ i ] = avMaterials[ i ];
+    if (0xFFFFFFFF != aiColors[1])
+    {
+      cOut.g = NormalizeColorValue(GetProperty(instElement->alProperties,
+        aiColors[1]).avList.front(), aiColorsTypes[1]);
+      haveColor = true;
     }
 
-    // fill the mesh list
-    pScene->mNumMeshes = (unsigned int)avMeshes.size();
-    pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
-    for ( unsigned int i = 0; i < pScene->mNumMeshes; ++i ) {
-        pScene->mMeshes[ i ] = avMeshes[ i ];
+    if (0xFFFFFFFF != aiColors[2])
+    {
+      cOut.b = NormalizeColorValue(GetProperty(instElement->alProperties,
+        aiColors[2]).avList.front(), aiColorsTypes[2]);
+      haveColor = true;
     }
 
-    // generate a simple node structure
-    pScene->mRootNode = new aiNode();
-    pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
-    pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
+    // assume 1.0 for the alpha channel ifit is not set
+    if (0xFFFFFFFF == aiColors[3])
+    {
+      cOut.a = 1.0;
+    }
+    else
+    {
+      cOut.a = NormalizeColorValue(GetProperty(instElement->alProperties,
+        aiColors[3]).avList.front(), aiColorsTypes[3]);
 
-    for ( unsigned int i = 0; i < pScene->mRootNode->mNumMeshes; ++i ) {
-        pScene->mRootNode->mMeshes[ i ] = i;
+      haveColor = true;
     }
-}
 
-// ------------------------------------------------------------------------------------------------
-// Split meshes by material IDs
-void PLYImporter::ConvertMeshes(std::vector<PLY::Face>* avFaces,
-    const std::vector<aiVector3D>*          avPositions,
-    const std::vector<aiVector3D>*          avNormals,
-    const std::vector<aiColor4D>*           avColors,
-    const std::vector<aiVector2D>*          avTexCoords,
-    const std::vector<aiMaterial*>*     avMaterials,
-    std::vector<aiMesh*>* avOut)
-{
-    ai_assert(NULL != avFaces);
-    ai_assert(NULL != avPositions);
-    ai_assert(NULL != avMaterials);
+    //Texture coordinates
+    aiVector3D tOut;
+    tOut.z = 0;
+    bool haveTextureCoords = false;
+    if (0xFFFFFFFF != aiTexcoord[0])
+    {
+      tOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]);
+      haveTextureCoords = true;
+    }
 
-    // split by materials
-    std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[avMaterials->size()];
+    if (0xFFFFFFFF != aiTexcoord[1])
+    {
+      tOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]);
+      haveTextureCoords = true;
+    }
 
-    unsigned int iNum = 0;
-    for (std::vector<PLY::Face>::const_iterator i = avFaces->begin();i != avFaces->end();++i,++iNum)
-        aiSplit[(*i).iMaterialIndex].push_back(iNum);
+    //create aiMesh if needed
+    if (mGeneratedMesh == NULL)
+    {
+      mGeneratedMesh = new aiMesh();
+      mGeneratedMesh->mMaterialIndex = 0;
+    }
 
-    // now generate sub-meshes
-    for (unsigned int p = 0; p < avMaterials->size();++p)
+    if (mGeneratedMesh->mVertices == NULL)
     {
-        if (aiSplit[p].size() != 0)
-        {
-            // allocate the mesh object
-            aiMesh* p_pcOut = new aiMesh();
-            p_pcOut->mMaterialIndex = p;
+      mGeneratedMesh->mNumVertices = pcElement->NumOccur;
+      mGeneratedMesh->mVertices = new aiVector3D[mGeneratedMesh->mNumVertices];
+    }
 
-            p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
-            p_pcOut->mFaces = new aiFace[aiSplit[p].size()];
+    mGeneratedMesh->mVertices[pos] = vOut;
 
-            // at first we need to determine the size of the output vector array
-            unsigned int iNum = 0;
-            for (unsigned int i = 0; i < aiSplit[p].size();++i)
-            {
-                iNum += (unsigned int)(*avFaces)[aiSplit[p][i]].mIndices.size();
-            }
-            p_pcOut->mNumVertices = iNum;
-            if( 0 == iNum ) {     // nothing to do
-                delete[] aiSplit; // cleanup
-                delete p_pcOut;
-                return;
-            }
-            p_pcOut->mVertices = new aiVector3D[iNum];
+    if (haveNormal)
+    {
+      if (mGeneratedMesh->mNormals == NULL)
+        mGeneratedMesh->mNormals = new aiVector3D[mGeneratedMesh->mNumVertices];
+      mGeneratedMesh->mNormals[pos] = nOut;
+    }
 
-            if (!avColors->empty())
-                p_pcOut->mColors[0] = new aiColor4D[iNum];
-            if (!avTexCoords->empty())
-            {
-                p_pcOut->mNumUVComponents[0] = 2;
-                p_pcOut->mTextureCoords[0] = new aiVector3D[iNum];
-            }
-            if (!avNormals->empty())
-                p_pcOut->mNormals = new aiVector3D[iNum];
-
-            // add all faces
-            iNum = 0;
-            unsigned int iVertex = 0;
-            for (std::vector<unsigned int>::const_iterator i =  aiSplit[p].begin();
-                i != aiSplit[p].end();++i,++iNum)
-            {
-                p_pcOut->mFaces[iNum].mNumIndices = (unsigned int)(*avFaces)[*i].mIndices.size();
-                p_pcOut->mFaces[iNum].mIndices = new unsigned int[p_pcOut->mFaces[iNum].mNumIndices];
-
-                // build an unique set of vertices/colors for this face
-                for (unsigned int q = 0; q <  p_pcOut->mFaces[iNum].mNumIndices;++q)
-                {
-                    p_pcOut->mFaces[iNum].mIndices[q] = iVertex;
-                    const size_t idx = ( *avFaces )[ *i ].mIndices[ q ];
-                    if( idx >= ( *avPositions ).size() ) {
-                        // out of border
-                        continue;
-                    }
-                    p_pcOut->mVertices[ iVertex ] = ( *avPositions )[ idx ];
-
-                    if (!avColors->empty())
-                        p_pcOut->mColors[ 0 ][ iVertex ] = ( *avColors )[ idx ];
-
-                    if (!avTexCoords->empty())
-                    {
-                        const aiVector2D& vec = ( *avTexCoords )[ idx ];
-                        p_pcOut->mTextureCoords[0][iVertex].x = vec.x;
-                        p_pcOut->mTextureCoords[0][iVertex].y = vec.y;
-                    }
-
-                    if (!avNormals->empty())
-                        p_pcOut->mNormals[ iVertex ] = ( *avNormals )[ idx ];
-                    iVertex++;
-                }
+    if (haveColor)
+    {
+      if (mGeneratedMesh->mColors[0] == NULL)
+        mGeneratedMesh->mColors[0] = new aiColor4D[mGeneratedMesh->mNumVertices];
+      mGeneratedMesh->mColors[0][pos] = cOut;
+    }
 
-            }
-            // add the mesh to the output list
-            avOut->push_back(p_pcOut);
-        }
+    if (haveTextureCoords)
+    {
+      if (mGeneratedMesh->mTextureCoords[0] == NULL)
+      {
+        mGeneratedMesh->mNumUVComponents[0] = 2;
+        mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices];
+      }
+      mGeneratedMesh->mTextureCoords[0][pos] = tOut;
     }
-    delete[] aiSplit; // cleanup
+  }
 }
 
+
 // ------------------------------------------------------------------------------------------------
-// Generate a default material if none was specified and apply it to all vanilla faces
-void PLYImporter::ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
-    std::vector<aiMaterial*>* avMaterials)
+// Convert a color component to [0...1]
+ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val,
+  PLY::EDataType eType)
 {
-    bool bNeedDefaultMat = false;
+  switch (eType)
+  {
+  case EDT_Float:
+    return val.fFloat;
+  case EDT_Double:
+    return (ai_real)val.fDouble;
+
+  case EDT_UChar:
+    return (ai_real)val.iUInt / (ai_real)0xFF;
+  case EDT_Char:
+    return (ai_real)(val.iInt + (0xFF / 2)) / (ai_real)0xFF;
+  case EDT_UShort:
+    return (ai_real)val.iUInt / (ai_real)0xFFFF;
+  case EDT_Short:
+    return (ai_real)(val.iInt + (0xFFFF / 2)) / (ai_real)0xFFFF;
+  case EDT_UInt:
+    return (ai_real)val.iUInt / (ai_real)0xFFFF;
+  case EDT_Int:
+    return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f;
+  default:;
+  };
+  return 0.0f;
+}
 
-    for (std::vector<PLY::Face>::iterator i =  avFaces->begin();i != avFaces->end();++i)    {
-        if (0xFFFFFFFF == (*i).iMaterialIndex)  {
-            bNeedDefaultMat = true;
-            (*i).iMaterialIndex = (unsigned int)avMaterials->size();
-        }
-        else if ((*i).iMaterialIndex >= avMaterials->size() )   {
-            // clamp the index
-            (*i).iMaterialIndex = (unsigned int)avMaterials->size()-1;
-        }
-    }
+// ------------------------------------------------------------------------------------------------
+// Try to extract proper faces from the PLY DOM
+void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos)
+{
+  ai_assert(NULL != pcElement);
+  ai_assert(NULL != instElement);
 
-    if (bNeedDefaultMat)    {
-        // generate a default material
-        aiMaterial* pcHelper = new aiMaterial();
+  if (mGeneratedMesh == NULL)
+    throw DeadlyImportError("Invalid .ply file: Vertices shoud be declared before faces");
 
-        // fill in a default material
-        int iMode = (int)aiShadingMode_Gouraud;
-        pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+  bool bOne = false;
 
-        aiColor3D clr;
-        clr.b = clr.g = clr.r = 0.6f;
-        pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
-        pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+  // index of the vertex index list
+  unsigned int iProperty = 0xFFFFFFFF;
+  PLY::EDataType eType = EDT_Char;
+  bool bIsTriStrip = false;
 
-        clr.b = clr.g = clr.r = 0.05f;
-        pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+  // index of the material index property
+  //unsigned int iMaterialIndex = 0xFFFFFFFF;
+  //PLY::EDataType eType2 = EDT_Char;
 
-        // The face order is absolutely undefined for PLY, so we have to
-        // use two-sided rendering to be sure it's ok.
-        const int two_sided = 1;
-        pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED);
+  // texture coordinates
+  unsigned int iTextureCoord = 0xFFFFFFFF;
+  PLY::EDataType eType3 = EDT_Char;
 
-        avMaterials->push_back(pcHelper);
+  // face = unique number of vertex indices
+  if (PLY::EEST_Face == pcElement->eSemantic)
+  {
+    unsigned int _a = 0;
+    for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
+      a != pcElement->alProperties.end(); ++a, ++_a)
+    {
+      if (PLY::EST_VertexIndex == (*a).Semantic)
+      {
+        // must be a dynamic list!
+        if (!(*a).bIsList)
+          continue;
+
+        iProperty = _a;
+        bOne = true;
+        eType = (*a).eType;
+      }
+      /*else if (PLY::EST_MaterialIndex == (*a).Semantic)
+      {
+      if ((*a).bIsList)
+      continue;
+      iMaterialIndex = _a;
+      bOne = true;
+      eType2 = (*a).eType;
+      }*/
+      else if (PLY::EST_TextureCoordinates == (*a).Semantic)
+      {
+        // must be a dynamic list!
+        if (!(*a).bIsList)
+          continue;
+        iTextureCoord = _a;
+        bOne = true;
+        eType3 = (*a).eType;
+      }
     }
-}
-
-// ------------------------------------------------------------------------------------------------
-void PLYImporter::LoadTextureCoordinates(std::vector<aiVector2D>* pvOut)
-{
-    ai_assert(NULL != pvOut);
-
-    unsigned int aiPositions[2] = {0xFFFFFFFF,0xFFFFFFFF};
-    PLY::EDataType aiTypes[2] = {EDT_Char,EDT_Char};
-    PLY::ElementInstanceList* pcList = NULL;
-    unsigned int cnt = 0;
-
-    // search in the DOM for a vertex entry
-    unsigned int _i = 0;
-    for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
-        i != pcDOM->alElements.end();++i,++_i)
+  }
+  // triangle strip
+  // TODO: triangle strip and material index support???
+  else if (PLY::EEST_TriStrip == pcElement->eSemantic)
+  {
+    unsigned int _a = 0;
+    for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
+      a != pcElement->alProperties.end(); ++a, ++_a)
     {
-        if (PLY::EEST_Vertex == (*i).eSemantic)
-        {
-            pcList = &this->pcDOM->alElementData[_i];
+      // must be a dynamic list!
+      if (!(*a).bIsList)
+        continue;
+      iProperty = _a;
+      bOne = true;
+      bIsTriStrip = true;
+      eType = (*a).eType;
+      break;
+    }
+  }
 
-            // now check whether which normal components are available
-            unsigned int _a = 0;
-            for (std::vector<PLY::Property>::const_iterator a =  (*i).alProperties.begin();
-                a != (*i).alProperties.end();++a,++_a)
-            {
-                if ((*a).bIsList)continue;
-                if (PLY::EST_UTextureCoord == (*a).Semantic)
-                {
-                    cnt++;
-                    aiPositions[0] = _a;
-                    aiTypes[0] = (*a).eType;
-                }
-                else if (PLY::EST_VTextureCoord == (*a).Semantic)
-                {
-                    cnt++;
-                    aiPositions[1] = _a;
-                    aiTypes[1] = (*a).eType;
-                }
-            }
-        }
+  // check whether we have at least one per-face information set
+  if (bOne)
+  {
+    if (mGeneratedMesh->mFaces == NULL)
+    {
+      mGeneratedMesh->mNumFaces = pcElement->NumOccur;
+      mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
     }
-    // check whether we have a valid source for the texture coordinates data
-    if (NULL != pcList && 0 != cnt)
+
+    if (!bIsTriStrip)
     {
-        pvOut->reserve(pcList->alInstances.size());
-        for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
-            i != pcList->alInstances.end();++i)
-        {
-            // convert the vertices to sp floats
-            aiVector2D vOut;
+      // parse the list of vertex indices
+      if (0xFFFFFFFF != iProperty)
+      {
+        const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size();
+        mGeneratedMesh->mFaces[pos].mNumIndices = iNum;
+        mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum];
 
-            if (0xFFFFFFFF != aiPositions[0])
-            {
-                vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
-                    GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]);
-            }
+        std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
+          GetProperty(instElement->alProperties, iProperty).avList.begin();
 
-            if (0xFFFFFFFF != aiPositions[1])
-            {
-                vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
-                    GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]);
-            }
-            // and add them to our nice list
-            pvOut->push_back(vOut);
+        for (unsigned int a = 0; a < iNum; ++a, ++p)
+        {
+          mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p, eType);
         }
-    }
-}
+      }
 
-// ------------------------------------------------------------------------------------------------
-// Try to extract vertices from the PLY DOM
-void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
-{
-    ai_assert(NULL != pvOut);
+      // parse the material index
+      // cannot be handled without processing the whole file first
+      /*if (0xFFFFFFFF != iMaterialIndex)
+      {
+      mGeneratedMesh->mFaces[pos]. = PLY::PropertyInstance::ConvertTo<unsigned int>(
+      GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2);
+      }*/
 
-    ai_uint aiPositions[3] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
-    PLY::EDataType aiTypes[3] = {EDT_Char,EDT_Char,EDT_Char};
-    PLY::ElementInstanceList* pcList = NULL;
-    unsigned int cnt = 0;
+      if (0xFFFFFFFF != iTextureCoord)
+      {
+        const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size();
 
-    // search in the DOM for a vertex entry
-    unsigned int _i = 0;
-    for (std::vector<PLY::Element>::const_iterator i =  pcDOM->alElements.begin();
-        i != pcDOM->alElements.end();++i,++_i)
-    {
-        if (PLY::EEST_Vertex == (*i).eSemantic)
-        {
-            pcList = &pcDOM->alElementData[_i];
+        //should be 6 coords
+        std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
+          GetProperty(instElement->alProperties, iTextureCoord).avList.begin();
 
-            // load normal vectors?
-            if (p_bNormals)
-            {
-                // now check whether which normal components are available
-                unsigned int _a = 0;
-                for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
-                    a != (*i).alProperties.end();++a,++_a)
-                {
-                    if ((*a).bIsList)continue;
-                    if (PLY::EST_XNormal == (*a).Semantic)
-                    {
-                        cnt++;
-                        aiPositions[0] = _a;
-                        aiTypes[0] = (*a).eType;
-                    }
-                    else if (PLY::EST_YNormal == (*a).Semantic)
-                    {
-                        cnt++;
-                        aiPositions[1] = _a;
-                        aiTypes[1] = (*a).eType;
-                    }
-                    else if (PLY::EST_ZNormal == (*a).Semantic)
-                    {
-                        cnt++;
-                        aiPositions[2] = _a;
-                        aiTypes[2] = (*a).eType;
-                    }
-                }
-            }
-            // load vertex coordinates
-            else
+        if ((iNum / 3) == 2) // X Y coord
+        {
+          for (unsigned int a = 0; a < iNum; ++a, ++p)
+          {
+            unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2];
+            if (vindex < mGeneratedMesh->mNumVertices)
             {
-                // now check whether which coordinate sets are available
-                unsigned int _a = 0;
-                for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
-                    a != (*i).alProperties.end();++a,++_a)
-                {
-                    if ((*a).bIsList)continue;
-                    if (PLY::EST_XCoord == (*a).Semantic)
-                    {
-                        cnt++;
-                        aiPositions[0] = _a;
-                        aiTypes[0] = (*a).eType;
-                    }
-                    else if (PLY::EST_YCoord == (*a).Semantic)
-                    {
-                        cnt++;
-                        aiPositions[1] = _a;
-                        aiTypes[1] = (*a).eType;
-                    }
-                    else if (PLY::EST_ZCoord == (*a).Semantic)
-                    {
-                        cnt++;
-                        aiPositions[2] = _a;
-                        aiTypes[2] = (*a).eType;
-                    }
-                    if (3 == cnt)break;
-                }
+              if (mGeneratedMesh->mTextureCoords[0] == NULL)
+              {
+                mGeneratedMesh->mNumUVComponents[0] = 2;
+                mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices];
+              }
+
+              if (a % 2 == 0)
+                mGeneratedMesh->mTextureCoords[0][vindex].x = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
+              else
+                mGeneratedMesh->mTextureCoords[0][vindex].y = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
+
+              mGeneratedMesh->mTextureCoords[0][vindex].z = 0;
             }
-            break;
+          }
         }
+      }
     }
-    // check whether we have a valid source for the vertex data
-    if (NULL != pcList && 0 != cnt)
+    else // triangle strips
     {
-        pvOut->reserve(pcList->alInstances.size());
-        for (std::vector<ElementInstance>::const_iterator
-            i =  pcList->alInstances.begin();
-            i != pcList->alInstances.end();++i)
-        {
-            // convert the vertices to sp floats
-            aiVector3D vOut;
-
-            if (0xFFFFFFFF != aiPositions[0])
-            {
-                vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
-                    GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]);
-            }
+      // normally we have only one triangle strip instance where
+      // a value of -1 indicates a restart of the strip
+      bool flip = false;
+      const std::vector<PLY::PropertyInstance::ValueUnion>& quak = GetProperty(instElement->alProperties, iProperty).avList;
+      //pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption
+
+      int aiTable[2] = { -1, -1 };
+      for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a = quak.begin(); a != quak.end(); ++a)  {
+        const int p = PLY::PropertyInstance::ConvertTo<int>(*a, eType);
+
+        if (-1 == p)    {
+          // restart the strip ...
+          aiTable[0] = aiTable[1] = -1;
+          flip = false;
+          continue;
+        }
+        if (-1 == aiTable[0]) {
+          aiTable[0] = p;
+          continue;
+        }
+        if (-1 == aiTable[1]) {
+          aiTable[1] = p;
+          continue;
+        }
 
-            if (0xFFFFFFFF != aiPositions[1])
-            {
-                vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
-                    GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]);
-            }
+        if (mGeneratedMesh->mFaces == NULL)
+        {
+          mGeneratedMesh->mNumFaces = pcElement->NumOccur;
+          mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
+        }
 
-            if (0xFFFFFFFF != aiPositions[2])
-            {
-                vOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
-                    GetProperty((*i).alProperties, aiPositions[2]).avList.front(),aiTypes[2]);
-            }
+        mGeneratedMesh->mFaces[pos].mNumIndices = 3;
+        mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[3];
+        mGeneratedMesh->mFaces[pos].mIndices[0] = aiTable[0];
+        mGeneratedMesh->mFaces[pos].mIndices[1] = aiTable[1];
+        mGeneratedMesh->mFaces[pos].mIndices[2] = aiTable[2];
 
-            // and add them to our nice list
-            pvOut->push_back(vOut);
+        if ((flip = !flip)) {
+          std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]);
         }
+
+        aiTable[0] = aiTable[1];
+        aiTable[1] = p;
+      }
     }
+  }
 }
 
 // ------------------------------------------------------------------------------------------------
-// Convert a color component to [0...1]
-ai_real PLYImporter::NormalizeColorValue (PLY::PropertyInstance::ValueUnion val,
-    PLY::EDataType eType)
+// Get a RGBA color in [0...1] range
+void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance>& avList,
+  unsigned int aiPositions[4],
+  PLY::EDataType aiTypes[4],
+  aiColor4D* clrOut)
 {
-    switch (eType)
-    {
-    case EDT_Float:
-        return val.fFloat;
-    case EDT_Double:
-        return (ai_real)val.fDouble;
-
-    case EDT_UChar:
-        return (ai_real)val.iUInt / (ai_real)0xFF;
-    case EDT_Char:
-        return (ai_real)(val.iInt+(0xFF/2)) / (ai_real)0xFF;
-    case EDT_UShort:
-        return (ai_real)val.iUInt / (ai_real)0xFFFF;
-    case EDT_Short:
-        return (ai_real)(val.iInt+(0xFFFF/2)) / (ai_real)0xFFFF;
-    case EDT_UInt:
-        return (ai_real)val.iUInt / (ai_real)0xFFFF;
-    case EDT_Int:
-        return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f;
-    default: ;
-    };
-    return 0.0f;
+  ai_assert(NULL != clrOut);
+
+  if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
+  else
+  {
+    clrOut->r = NormalizeColorValue(GetProperty(avList,
+      aiPositions[0]).avList.front(), aiTypes[0]);
+  }
+
+  if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
+  else
+  {
+    clrOut->g = NormalizeColorValue(GetProperty(avList,
+      aiPositions[1]).avList.front(), aiTypes[1]);
+  }
+
+  if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
+  else
+  {
+    clrOut->b = NormalizeColorValue(GetProperty(avList,
+      aiPositions[2]).avList.front(), aiTypes[2]);
+  }
+
+  // assume 1.0 for the alpha channel ifit is not set
+  if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
+  else
+  {
+    clrOut->a = NormalizeColorValue(GetProperty(avList,
+      aiPositions[3]).avList.front(), aiTypes[3]);
+  }
 }
 
 // ------------------------------------------------------------------------------------------------
-// Try to extract proper vertex colors from the PLY DOM
-void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
+// Extract a material from the PLY DOM
+void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &defaultTexture, const bool pointsOnly)
 {
-    ai_assert(NULL != pvOut);
-
-    unsigned int aiPositions[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
-    PLY::EDataType aiTypes[4] = {EDT_Char, EDT_Char, EDT_Char, EDT_Char}; // silencing gcc
-    unsigned int cnt = 0;
-    PLY::ElementInstanceList* pcList = NULL;
-
-    // search in the DOM for a vertex entry
-    unsigned int _i = 0;
-    for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
-        i != pcDOM->alElements.end();++i,++_i)
+  ai_assert(NULL != pvOut);
+
+  // diffuse[4], specular[4], ambient[4]
+  // rgba order
+  unsigned int aaiPositions[3][4] = {
+
+    { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
+    { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
+    { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
+  };
+
+  PLY::EDataType aaiTypes[3][4] = {
+    { EDT_Char, EDT_Char, EDT_Char, EDT_Char },
+    { EDT_Char, EDT_Char, EDT_Char, EDT_Char },
+    { EDT_Char, EDT_Char, EDT_Char, EDT_Char }
+  };
+  PLY::ElementInstanceList* pcList = NULL;
+
+  unsigned int iPhong = 0xFFFFFFFF;
+  PLY::EDataType ePhong = EDT_Char;
+
+  unsigned int iOpacity = 0xFFFFFFFF;
+  PLY::EDataType eOpacity = EDT_Char;
+
+  // search in the DOM for a vertex entry
+  unsigned int _i = 0;
+  for (std::vector<PLY::Element>::const_iterator i = this->pcDOM->alElements.begin();
+    i != this->pcDOM->alElements.end(); ++i, ++_i)
+  {
+    if (PLY::EEST_Material == (*i).eSemantic)
     {
-        if (PLY::EEST_Vertex == (*i).eSemantic)
+      pcList = &this->pcDOM->alElementData[_i];
+
+      // now check whether which coordinate sets are available
+      unsigned int _a = 0;
+      for (std::vector<PLY::Property>::const_iterator
+        a = (*i).alProperties.begin();
+        a != (*i).alProperties.end(); ++a, ++_a)
+      {
+        if ((*a).bIsList)continue;
+
+        // pohng specularity      -----------------------------------
+        if (PLY::EST_PhongPower == (*a).Semantic)
         {
-            pcList = &this->pcDOM->alElementData[_i];
-
-            // now check whether which coordinate sets are available
-            unsigned int _a = 0;
-            for (std::vector<PLY::Property>::const_iterator
-                a =  (*i).alProperties.begin();
-                a != (*i).alProperties.end();++a,++_a)
-            {
-                if ((*a).bIsList)continue;
-                if (PLY::EST_Red == (*a).Semantic)
-                {
-                    cnt++;
-                    aiPositions[0] = _a;
-                    aiTypes[0] = (*a).eType;
-                }
-                else if (PLY::EST_Green == (*a).Semantic)
-                {
-                    cnt++;
-                    aiPositions[1] = _a;
-                    aiTypes[1] = (*a).eType;
-                }
-                else if (PLY::EST_Blue == (*a).Semantic)
-                {
-                    cnt++;
-                    aiPositions[2] = _a;
-                    aiTypes[2] = (*a).eType;
-                }
-                else if (PLY::EST_Alpha == (*a).Semantic)
-                {
-                    cnt++;
-                    aiPositions[3] = _a;
-                    aiTypes[3] = (*a).eType;
-                }
-                if (4 == cnt)break;
-            }
-            break;
+          iPhong = _a;
+          ePhong = (*a).eType;
         }
-    }
-    // check whether we have a valid source for the vertex data
-    if (NULL != pcList && 0 != cnt)
-    {
-        pvOut->reserve(pcList->alInstances.size());
-        for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
-            i != pcList->alInstances.end();++i)
-        {
-            // convert the vertices to sp floats
-            aiColor4D vOut;
-
-            if (0xFFFFFFFF != aiPositions[0])
-            {
-                vOut.r = NormalizeColorValue(GetProperty((*i).alProperties,
-                    aiPositions[0]).avList.front(),aiTypes[0]);
-            }
-
-            if (0xFFFFFFFF != aiPositions[1])
-            {
-                vOut.g = NormalizeColorValue(GetProperty((*i).alProperties,
-                    aiPositions[1]).avList.front(),aiTypes[1]);
-            }
-
-            if (0xFFFFFFFF != aiPositions[2])
-            {
-                vOut.b = NormalizeColorValue(GetProperty((*i).alProperties,
-                    aiPositions[2]).avList.front(),aiTypes[2]);
-            }
-
-            // assume 1.0 for the alpha channel ifit is not set
-            if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0;
-            else
-            {
-                vOut.a = NormalizeColorValue(GetProperty((*i).alProperties,
-                    aiPositions[3]).avList.front(),aiTypes[3]);
-            }
 
-            // and add them to our nice list
-            pvOut->push_back(vOut);
+        // general opacity        -----------------------------------
+        if (PLY::EST_Opacity == (*a).Semantic)
+        {
+          iOpacity = _a;
+          eOpacity = (*a).eType;
         }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Try to extract proper faces from the PLY DOM
-void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
-{
-    ai_assert(NULL != pvOut);
 
-    PLY::ElementInstanceList* pcList = NULL;
-    bool bOne = false;
-
-    // index of the vertex index list
-    unsigned int iProperty = 0xFFFFFFFF;
-    PLY::EDataType eType = EDT_Char;
-    bool bIsTriStrip = false;
-
-    // index of the material index property
-    unsigned int iMaterialIndex = 0xFFFFFFFF;
-    PLY::EDataType eType2 = EDT_Char;
-
-    // search in the DOM for a face entry
-    unsigned int _i = 0;
-    for (std::vector<PLY::Element>::const_iterator i =  pcDOM->alElements.begin();
-        i != pcDOM->alElements.end();++i,++_i)
-    {
-        // face = unique number of vertex indices
-        if (PLY::EEST_Face == (*i).eSemantic)
+        // diffuse color channels -----------------------------------
+        if (PLY::EST_DiffuseRed == (*a).Semantic)
         {
-            pcList = &pcDOM->alElementData[_i];
-            unsigned int _a = 0;
-            for (std::vector<PLY::Property>::const_iterator a =  (*i).alProperties.begin();
-                a != (*i).alProperties.end();++a,++_a)
-            {
-                if (PLY::EST_VertexIndex == (*a).Semantic)
-                {
-                    // must be a dynamic list!
-                    if (!(*a).bIsList)continue;
-                    iProperty   = _a;
-                    bOne        = true;
-                    eType       = (*a).eType;
-                }
-                else if (PLY::EST_MaterialIndex == (*a).Semantic)
-                {
-                    if ((*a).bIsList)continue;
-                    iMaterialIndex  = _a;
-                    bOne            = true;
-                    eType2      = (*a).eType;
-                }
-            }
-            break;
+          aaiPositions[0][0] = _a;
+          aaiTypes[0][0] = (*a).eType;
         }
-        // triangle strip
-        // TODO: triangle strip and material index support???
-        else if (PLY::EEST_TriStrip == (*i).eSemantic)
+        else if (PLY::EST_DiffuseGreen == (*a).Semantic)
         {
-            // find a list property in this ...
-            pcList = &this->pcDOM->alElementData[_i];
-            unsigned int _a = 0;
-            for (std::vector<PLY::Property>::const_iterator a =  (*i).alProperties.begin();
-                a != (*i).alProperties.end();++a,++_a)
-            {
-                // must be a dynamic list!
-                if (!(*a).bIsList)continue;
-                iProperty   = _a;
-                bOne        = true;
-                bIsTriStrip = true;
-                eType       = (*a).eType;
-                break;
-            }
-            break;
+          aaiPositions[0][1] = _a;
+          aaiTypes[0][1] = (*a).eType;
         }
-    }
-    // check whether we have at least one per-face information set
-    if (pcList && bOne)
-    {
-        if (!bIsTriStrip)
+        else if (PLY::EST_DiffuseBlue == (*a).Semantic)
         {
-            pvOut->reserve(pcList->alInstances.size());
-            for (std::vector<ElementInstance>::const_iterator i =  pcList->alInstances.begin();
-                i != pcList->alInstances.end();++i)
-            {
-                PLY::Face sFace;
-
-                // parse the list of vertex indices
-                if (0xFFFFFFFF != iProperty)
-                {
-                    const unsigned int iNum = (unsigned int)GetProperty((*i).alProperties, iProperty).avList.size();
-                    sFace.mIndices.resize(iNum);
-
-                    std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
-                        GetProperty((*i).alProperties, iProperty).avList.begin();
-
-                    for (unsigned int a = 0; a < iNum;++a,++p)
-                    {
-                        sFace.mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p,eType);
-                    }
-                }
-
-                // parse the material index
-                if (0xFFFFFFFF != iMaterialIndex)
-                {
-                    sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo<unsigned int>(
-                        GetProperty((*i).alProperties, iMaterialIndex).avList.front(),eType2);
-                }
-                pvOut->push_back(sFace);
-            }
+          aaiPositions[0][2] = _a;
+          aaiTypes[0][2] = (*a).eType;
         }
-        else // triangle strips
+        else if (PLY::EST_DiffuseAlpha == (*a).Semantic)
         {
-            // normally we have only one triangle strip instance where
-            // a value of -1 indicates a restart of the strip
-            bool flip = false;
-            for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
-                const std::vector<PLY::PropertyInstance::ValueUnion>& quak = GetProperty((*i).alProperties, iProperty).avList;
-                pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u));
-
-                int aiTable[2] = {-1,-1};
-                for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a =  quak.begin();a != quak.end();++a)  {
-                    const int p = PLY::PropertyInstance::ConvertTo<int>(*a,eType);
-
-                    if (-1 == p)    {
-                        // restart the strip ...
-                        aiTable[0] = aiTable[1] = -1;
-                        flip = false;
-                        continue;
-                    }
-                    if (-1 == aiTable[0]) {
-                        aiTable[0] = p;
-                        continue;
-                    }
-                    if (-1 == aiTable[1]) {
-                        aiTable[1] = p;
-                        continue;
-                    }
-
-                    pvOut->push_back(PLY::Face());
-                    PLY::Face& sFace = pvOut->back();
-                    sFace.mIndices[0] = aiTable[0];
-                    sFace.mIndices[1] = aiTable[1];
-                    sFace.mIndices[2] = p;
-                    if ((flip = !flip)) {
-                        std::swap(sFace.mIndices[0],sFace.mIndices[1]);
-                    }
-
-                    aiTable[0] = aiTable[1];
-                    aiTable[1] = p;
-                }
-            }
+          aaiPositions[0][3] = _a;
+          aaiTypes[0][3] = (*a).eType;
+        }
+        // specular color channels -----------------------------------
+        else if (PLY::EST_SpecularRed == (*a).Semantic)
+        {
+          aaiPositions[1][0] = _a;
+          aaiTypes[1][0] = (*a).eType;
         }
+        else if (PLY::EST_SpecularGreen == (*a).Semantic)
+        {
+          aaiPositions[1][1] = _a;
+          aaiTypes[1][1] = (*a).eType;
+        }
+        else if (PLY::EST_SpecularBlue == (*a).Semantic)
+        {
+          aaiPositions[1][2] = _a;
+          aaiTypes[1][2] = (*a).eType;
+        }
+        else if (PLY::EST_SpecularAlpha == (*a).Semantic)
+        {
+          aaiPositions[1][3] = _a;
+          aaiTypes[1][3] = (*a).eType;
+        }
+        // ambient color channels -----------------------------------
+        else if (PLY::EST_AmbientRed == (*a).Semantic)
+        {
+          aaiPositions[2][0] = _a;
+          aaiTypes[2][0] = (*a).eType;
+        }
+        else if (PLY::EST_AmbientGreen == (*a).Semantic)
+        {
+          aaiPositions[2][1] = _a;
+          aaiTypes[2][1] = (*a).eType;
+        }
+        else if (PLY::EST_AmbientBlue == (*a).Semantic)
+        {
+          aaiPositions[2][2] = _a;
+          aaiTypes[2][2] = (*a).eType;
+        }
+        else if (PLY::EST_AmbientAlpha == (*a).Semantic)
+        {
+          aaiPositions[2][3] = _a;
+          aaiTypes[2][3] = (*a).eType;
+        }
+      }
+      break;
     }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get a RGBA color in [0...1] range
-void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance>& avList,
-    unsigned int aiPositions[4],
-    PLY::EDataType aiTypes[4],
-     aiColor4D* clrOut)
-{
-    ai_assert(NULL != clrOut);
-
-    if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
-    else
+    else if (PLY::EEST_TextureFile == (*i).eSemantic)
     {
-        clrOut->r = NormalizeColorValue(GetProperty(avList,
-            aiPositions[0]).avList.front(),aiTypes[0]);
+      defaultTexture = (*i).szName;
     }
-
-    if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
-    else
-    {
-        clrOut->g = NormalizeColorValue(GetProperty(avList,
-            aiPositions[1]).avList.front(),aiTypes[1]);
+  }
+  // check whether we have a valid source for the material data
+  if (NULL != pcList) {
+    for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end(); ++i)  {
+      aiColor4D clrOut;
+      aiMaterial* pcHelper = new aiMaterial();
+
+      // build the diffuse material color
+      GetMaterialColor((*i).alProperties, aaiPositions[0], aaiTypes[0], &clrOut);
+      pcHelper->AddProperty<aiColor4D>(&clrOut, 1, AI_MATKEY_COLOR_DIFFUSE);
+
+      // build the specular material color
+      GetMaterialColor((*i).alProperties, aaiPositions[1], aaiTypes[1], &clrOut);
+      pcHelper->AddProperty<aiColor4D>(&clrOut, 1, AI_MATKEY_COLOR_SPECULAR);
+
+      // build the ambient material color
+      GetMaterialColor((*i).alProperties, aaiPositions[2], aaiTypes[2], &clrOut);
+      pcHelper->AddProperty<aiColor4D>(&clrOut, 1, AI_MATKEY_COLOR_AMBIENT);
+
+      // handle phong power and shading mode
+      int iMode = (int)aiShadingMode_Gouraud;
+      if (0xFFFFFFFF != iPhong)   {
+        ai_real fSpec = PLY::PropertyInstance::ConvertTo<ai_real>(GetProperty((*i).alProperties, iPhong).avList.front(), ePhong);
+
+        // if shininess is 0 (and the pow() calculation would therefore always
+        // become 1, not depending on the angle), use gouraud lighting
+        if (fSpec)  {
+          // scale this with 15 ... hopefully this is correct
+          fSpec *= 15;
+          pcHelper->AddProperty<ai_real>(&fSpec, 1, AI_MATKEY_SHININESS);
+
+          iMode = (int)aiShadingMode_Phong;
+        }
+      }
+      pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+      // handle opacity
+      if (0xFFFFFFFF != iOpacity) {
+        ai_real fOpacity = PLY::PropertyInstance::ConvertTo<ai_real>(GetProperty((*i).alProperties, iPhong).avList.front(), eOpacity);
+        pcHelper->AddProperty<ai_real>(&fOpacity, 1, AI_MATKEY_OPACITY);
+      }
+
+      // The face order is absolutely undefined for PLY, so we have to
+      // use two-sided rendering to be sure it's ok.
+      const int two_sided = 1;
+      pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
+
+      //default texture
+      if (!defaultTexture.empty())
+      {
+        const aiString name(defaultTexture.c_str());
+        pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
+      }
+
+      if (!pointsOnly)
+      {
+        const int two_sided = 1;
+        pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
+      }
+
+      //set to wireframe, so when using this material info we can switch to points rendering
+      if (pointsOnly)
+      {
+        const int wireframe = 1;
+        pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
+      }
+
+      // add the newly created material instance to the list
+      pvOut->push_back(pcHelper);
     }
-
-    if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
-    else
+  }
+  else
+  {
+    // generate a default material
+    aiMaterial* pcHelper = new aiMaterial();
+
+    // fill in a default material
+    int iMode = (int)aiShadingMode_Gouraud;
+    pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+    aiColor3D clr;
+    clr.b = clr.g = clr.r = 0.6f;
+    pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
+    pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
+
+    clr.b = clr.g = clr.r = 0.05f;
+    pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_AMBIENT);
+
+    // The face order is absolutely undefined for PLY, so we have to
+    // use two-sided rendering to be sure it's ok.
+    if (!pointsOnly)
     {
-        clrOut->b = NormalizeColorValue(GetProperty(avList,
-            aiPositions[2]).avList.front(),aiTypes[2]);
+      const int two_sided = 1;
+      pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
     }
 
-    // assume 1.0 for the alpha channel ifit is not set
-    if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
-    else
+    //default texture
+    if (!defaultTexture.empty())
     {
-        clrOut->a = NormalizeColorValue(GetProperty(avList,
-            aiPositions[3]).avList.front(),aiTypes[3]);
+      const aiString name(defaultTexture.c_str());
+      pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
     }
-}
 
-// ------------------------------------------------------------------------------------------------
-// Extract a material from the PLY DOM
-void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut)
-{
-    ai_assert(NULL != pvOut);
-
-    // diffuse[4], specular[4], ambient[4]
-    // rgba order
-    unsigned int aaiPositions[3][4] = {
-
-        {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
-        {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
-        {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
-    };
-
-    PLY::EDataType aaiTypes[3][4] = {
-        {EDT_Char,EDT_Char,EDT_Char,EDT_Char},
-        {EDT_Char,EDT_Char,EDT_Char,EDT_Char},
-        {EDT_Char,EDT_Char,EDT_Char,EDT_Char}
-    };
-    PLY::ElementInstanceList* pcList = NULL;
-
-    unsigned int iPhong = 0xFFFFFFFF;
-    PLY::EDataType ePhong = EDT_Char;
-
-    unsigned int iOpacity = 0xFFFFFFFF;
-    PLY::EDataType eOpacity = EDT_Char;
-
-    // search in the DOM for a vertex entry
-    unsigned int _i = 0;
-    for (std::vector<PLY::Element>::const_iterator i =  this->pcDOM->alElements.begin();
-        i != this->pcDOM->alElements.end();++i,++_i)
+    //set to wireframe, so when using this material info we can switch to points rendering
+    if (pointsOnly)
     {
-        if (PLY::EEST_Material == (*i).eSemantic)
-        {
-            pcList = &this->pcDOM->alElementData[_i];
-
-            // now check whether which coordinate sets are available
-            unsigned int _a = 0;
-            for (std::vector<PLY::Property>::const_iterator
-                a =  (*i).alProperties.begin();
-                a != (*i).alProperties.end();++a,++_a)
-            {
-                if ((*a).bIsList)continue;
-
-                // pohng specularity      -----------------------------------
-                if (PLY::EST_PhongPower == (*a).Semantic)
-                {
-                    iPhong      = _a;
-                    ePhong      = (*a).eType;
-                }
-
-                // general opacity        -----------------------------------
-                if (PLY::EST_Opacity == (*a).Semantic)
-                {
-                    iOpacity        = _a;
-                    eOpacity        = (*a).eType;
-                }
-
-                // diffuse color channels -----------------------------------
-                if (PLY::EST_DiffuseRed == (*a).Semantic)
-                {
-                    aaiPositions[0][0]  = _a;
-                    aaiTypes[0][0]      = (*a).eType;
-                }
-                else if (PLY::EST_DiffuseGreen == (*a).Semantic)
-                {
-                    aaiPositions[0][1]  = _a;
-                    aaiTypes[0][1]      = (*a).eType;
-                }
-                else if (PLY::EST_DiffuseBlue == (*a).Semantic)
-                {
-                    aaiPositions[0][2]  = _a;
-                    aaiTypes[0][2]      = (*a).eType;
-                }
-                else if (PLY::EST_DiffuseAlpha == (*a).Semantic)
-                {
-                    aaiPositions[0][3]  = _a;
-                    aaiTypes[0][3]      = (*a).eType;
-                }
-                // specular color channels -----------------------------------
-                else if (PLY::EST_SpecularRed == (*a).Semantic)
-                {
-                    aaiPositions[1][0]  = _a;
-                    aaiTypes[1][0]      = (*a).eType;
-                }
-                else if (PLY::EST_SpecularGreen == (*a).Semantic)
-                {
-                    aaiPositions[1][1]  = _a;
-                    aaiTypes[1][1]      = (*a).eType;
-                }
-                else if (PLY::EST_SpecularBlue == (*a).Semantic)
-                {
-                    aaiPositions[1][2]  = _a;
-                    aaiTypes[1][2]      = (*a).eType;
-                }
-                else if (PLY::EST_SpecularAlpha == (*a).Semantic)
-                {
-                    aaiPositions[1][3]  = _a;
-                    aaiTypes[1][3]      = (*a).eType;
-                }
-                // ambient color channels -----------------------------------
-                else if (PLY::EST_AmbientRed == (*a).Semantic)
-                {
-                    aaiPositions[2][0]  = _a;
-                    aaiTypes[2][0]      = (*a).eType;
-                }
-                else if (PLY::EST_AmbientGreen == (*a).Semantic)
-                {
-                    aaiPositions[2][1]  = _a;
-                    aaiTypes[2][1]      = (*a).eType;
-                }
-                else if (PLY::EST_AmbientBlue == (*a).Semantic)
-                {
-                    aaiPositions[2][2]  = _a;
-                    aaiTypes[2][2]      = (*a).eType;
-                }
-                else if (PLY::EST_AmbientAlpha == (*a).Semantic)
-                {
-                    aaiPositions[2][3]  = _a;
-                    aaiTypes[2][3]      = (*a).eType;
-                }
-            }
-            break;
-        }
+      const int wireframe = 1;
+      pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
     }
-    // check whether we have a valid source for the material data
-    if (NULL != pcList) {
-        for (std::vector<ElementInstance>::const_iterator i =  pcList->alInstances.begin();i != pcList->alInstances.end();++i)  {
-            aiColor4D clrOut;
-            aiMaterial* pcHelper = new aiMaterial();
-
-            // build the diffuse material color
-            GetMaterialColor((*i).alProperties,aaiPositions[0],aaiTypes[0],&clrOut);
-            pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_DIFFUSE);
-
-            // build the specular material color
-            GetMaterialColor((*i).alProperties,aaiPositions[1],aaiTypes[1],&clrOut);
-            pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_SPECULAR);
-
-            // build the ambient material color
-            GetMaterialColor((*i).alProperties,aaiPositions[2],aaiTypes[2],&clrOut);
-            pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_AMBIENT);
-
-            // handle phong power and shading mode
-            int iMode = (int)aiShadingMode_Gouraud;
-            if (0xFFFFFFFF != iPhong)   {
-                ai_real fSpec = PLY::PropertyInstance::ConvertTo<ai_real>(GetProperty((*i).alProperties, iPhong).avList.front(),ePhong);
-
-                // if shininess is 0 (and the pow() calculation would therefore always
-                // become 1, not depending on the angle), use gouraud lighting
-                if (fSpec)  {
-                    // scale this with 15 ... hopefully this is correct
-                    fSpec *= 15;
-                    pcHelper->AddProperty<ai_real>(&fSpec, 1, AI_MATKEY_SHININESS);
-
-                    iMode = (int)aiShadingMode_Phong;
-                }
-            }
-            pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
-
-            // handle opacity
-            if (0xFFFFFFFF != iOpacity) {
-                ai_real fOpacity = PLY::PropertyInstance::ConvertTo<ai_real>(GetProperty((*i).alProperties, iPhong).avList.front(),eOpacity);
-                pcHelper->AddProperty<ai_real>(&fOpacity, 1, AI_MATKEY_OPACITY);
-            }
 
-            // The face order is absolutely undefined for PLY, so we have to
-            // use two-sided rendering to be sure it's ok.
-            const int two_sided = 1;
-            pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED);
-
-            // add the newly created material instance to the list
-            pvOut->push_back(pcHelper);
-        }
-    }
+    pvOut->push_back(pcHelper);
+  }
 }
 
 #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER
index 6c3825a..eb64a90 100644 (file)
@@ -68,7 +68,6 @@ public:
     PLYImporter();
     ~PLYImporter();
 
-
 public:
 
     // -------------------------------------------------------------------
@@ -78,6 +77,16 @@ public:
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
         bool checkSig) const;
 
+    // -------------------------------------------------------------------
+    /** Extract a vertex from the DOM
+    */
+    void LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos);
+
+    // -------------------------------------------------------------------
+    /** Extract a face from the DOM
+    */
+    void LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos);
+
 protected:
 
     // -------------------------------------------------------------------
@@ -94,53 +103,10 @@ protected:
         IOSystem* pIOHandler);
 
 protected:
-
-
-    // -------------------------------------------------------------------
-    /** Extract vertices from the DOM
-    */
-    void LoadVertices(std::vector<aiVector3D>* pvOut,
-        bool p_bNormals = false);
-
-    // -------------------------------------------------------------------
-    /** Extract vertex color channels from the DOM
-    */
-    void LoadVertexColor(std::vector<aiColor4D>* pvOut);
-
-    // -------------------------------------------------------------------
-    /** Extract texture coordinate channels from the DOM
-    */
-    void LoadTextureCoordinates(std::vector<aiVector2D>* pvOut);
-
-    // -------------------------------------------------------------------
-    /** Extract a face list from the DOM
-    */
-    void LoadFaces(std::vector<PLY::Face>* pvOut);
-
     // -------------------------------------------------------------------
     /** Extract a material list from the DOM
     */
-    void LoadMaterial(std::vector<aiMaterial*>* pvOut);
-
-
-    // -------------------------------------------------------------------
-    /** Validate material indices, replace default material identifiers
-    */
-    void ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
-        std::vector<aiMaterial*>* avMaterials);
-
-
-    // -------------------------------------------------------------------
-    /** Convert all meshes into our ourer representation
-    */
-    void ConvertMeshes(std::vector<PLY::Face>* avFaces,
-        const std::vector<aiVector3D>* avPositions,
-        const std::vector<aiVector3D>* avNormals,
-        const std::vector<aiColor4D>* avColors,
-        const std::vector<aiVector2D>* avTexCoords,
-        const std::vector<aiMaterial*>* avMaterials,
-        std::vector<aiMesh*>* avOut);
-
+    void LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &defaultTexture, const bool pointsOnly);
 
     // -------------------------------------------------------------------
     /** Static helper to parse a color from four single channels in
@@ -151,7 +117,6 @@ protected:
         PLY::EDataType aiTypes[4],
         aiColor4D* clrOut);
 
-
     // -------------------------------------------------------------------
     /** Static helper to parse a color channel value. The input value
     *  is normalized to 0-1.
@@ -160,12 +125,14 @@ protected:
         PLY::PropertyInstance::ValueUnion val,
         PLY::EDataType eType);
 
-
     /** Buffer to hold the loaded file */
     unsigned char* mBuffer;
 
     /** Document object model representation extracted from the file */
     PLY::DOM* pcDOM;
+
+    /** Mesh generated by loader */
+    aiMesh* mGeneratedMesh;
 };
 
 } // end of namespace Assimp
index 7e5a07d..7d47641 100644 (file)
@@ -5,7 +5,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2017, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -13,18 +12,18 @@ 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.
+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.
+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 team.
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@@ -45,916 +44,1093 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
 
-#include "PlyLoader.h"
 #include "fast_atof.h"
 #include <assimp/DefaultLogger.hpp>
 #include "ByteSwapper.h"
-
+#include "PlyLoader.h"
 
 using namespace Assimp;
 
 // ------------------------------------------------------------------------------------------------
-PLY::EDataType PLY::Property::ParseDataType(const char* pCur,const char** pCurOut) {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-
-    PLY::EDataType eOut = PLY::EDT_INVALID;
-
-    if (TokenMatch(pCur,"char",4) ||
-        TokenMatch(pCur,"int8",4))
-    {
-        eOut = PLY::EDT_Char;
-    }
-    else if (TokenMatch(pCur,"uchar",5) ||
-             TokenMatch(pCur,"uint8",5))
-    {
-        eOut = PLY::EDT_UChar;
-    }
-    else if (TokenMatch(pCur,"short",5) ||
-             TokenMatch(pCur,"int16",5))
-    {
-        eOut = PLY::EDT_Short;
-    }
-    else if (TokenMatch(pCur,"ushort",6) ||
-             TokenMatch(pCur,"uint16",6))
-    {
-        eOut = PLY::EDT_UShort;
-    }
-    else if (TokenMatch(pCur,"int32",5) || TokenMatch(pCur,"int",3))
-    {
-        eOut = PLY::EDT_Int;
-    }
-    else if (TokenMatch(pCur,"uint32",6) || TokenMatch(pCur,"uint",4))
-    {
-        eOut = PLY::EDT_UInt;
-    }
-    else if (TokenMatch(pCur,"float",5) || TokenMatch(pCur,"float32",7))
-    {
-        eOut = PLY::EDT_Float;
-    }
-    else if (TokenMatch(pCur,"double64",8) || TokenMatch(pCur,"double",6) ||
-             TokenMatch(pCur,"float64",7))
-    {
-        eOut = PLY::EDT_Double;
-    }
-    if (PLY::EDT_INVALID == eOut)
-    {
-        DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK");
-    }
-    *pCurOut = pCur;
-
-    return eOut;
+PLY::EDataType PLY::Property::ParseDataType(std::vector<char> &buffer) {
+  ai_assert(!buffer.empty());
+
+  PLY::EDataType eOut = PLY::EDT_INVALID;
+
+  if (PLY::DOM::TokenMatch(buffer, "char", 4) ||
+    PLY::DOM::TokenMatch(buffer, "int8", 4))
+  {
+    eOut = PLY::EDT_Char;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "uchar", 5) ||
+    PLY::DOM::TokenMatch(buffer, "uint8", 5))
+  {
+    eOut = PLY::EDT_UChar;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "short", 5) ||
+    PLY::DOM::TokenMatch(buffer, "int16", 5))
+  {
+    eOut = PLY::EDT_Short;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "ushort", 6) ||
+    PLY::DOM::TokenMatch(buffer, "uint16", 6))
+  {
+    eOut = PLY::EDT_UShort;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "int32", 5) || PLY::DOM::TokenMatch(buffer, "int", 3))
+  {
+    eOut = PLY::EDT_Int;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "uint32", 6) || PLY::DOM::TokenMatch(buffer, "uint", 4))
+  {
+    eOut = PLY::EDT_UInt;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "float", 5) || PLY::DOM::TokenMatch(buffer, "float32", 7))
+  {
+    eOut = PLY::EDT_Float;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "double64", 8) || PLY::DOM::TokenMatch(buffer, "double", 6) ||
+    PLY::DOM::TokenMatch(buffer, "float64", 7))
+  {
+    eOut = PLY::EDT_Double;
+  }
+  if (PLY::EDT_INVALID == eOut)
+  {
+    DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK");
+  }
+
+  return eOut;
 }
 
 // ------------------------------------------------------------------------------------------------
-PLY::ESemantic PLY::Property::ParseSemantic(const char* pCur,const char** pCurOut) {
-    ai_assert (NULL != pCur );
-    ai_assert( NULL != pCurOut );
-
-    PLY::ESemantic eOut = PLY::EST_INVALID;
-    if (TokenMatch(pCur,"red",3)) {
-        eOut = PLY::EST_Red;
-    } else if (TokenMatch(pCur,"green",5)) {
-        eOut = PLY::EST_Green;
-    } else if (TokenMatch(pCur,"blue",4)) {
-        eOut = PLY::EST_Blue;
-    } else if (TokenMatch(pCur,"alpha",5)) {
-        eOut = PLY::EST_Alpha;
-    } else if (TokenMatch(pCur,"vertex_index",12) || TokenMatch(pCur,"vertex_indices",14)) {
-        eOut = PLY::EST_VertexIndex;
-    }
-    else if (TokenMatch(pCur,"material_index",14))
-    {
-        eOut = PLY::EST_MaterialIndex;
-    }
-    else if (TokenMatch(pCur,"ambient_red",11))
-    {
-        eOut = PLY::EST_AmbientRed;
-    }
-    else if (TokenMatch(pCur,"ambient_green",13))
-    {
-        eOut = PLY::EST_AmbientGreen;
-    }
-    else if (TokenMatch(pCur,"ambient_blue",12))
-    {
-        eOut = PLY::EST_AmbientBlue;
-    }
-    else if (TokenMatch(pCur,"ambient_alpha",13))
-    {
-        eOut = PLY::EST_AmbientAlpha;
-    }
-    else if (TokenMatch(pCur,"diffuse_red",11))
-    {
-        eOut = PLY::EST_DiffuseRed;
-    }
-    else if (TokenMatch(pCur,"diffuse_green",13))
-    {
-        eOut = PLY::EST_DiffuseGreen;
-    }
-    else if (TokenMatch(pCur,"diffuse_blue",12))
-    {
-        eOut = PLY::EST_DiffuseBlue;
-    }
-    else if (TokenMatch(pCur,"diffuse_alpha",13))
-    {
-        eOut = PLY::EST_DiffuseAlpha;
-    }
-    else if (TokenMatch(pCur,"specular_red",12))
-    {
-        eOut = PLY::EST_SpecularRed;
-    }
-    else if (TokenMatch(pCur,"specular_green",14))
-    {
-        eOut = PLY::EST_SpecularGreen;
-    }
-    else if (TokenMatch(pCur,"specular_blue",13))
-    {
-        eOut = PLY::EST_SpecularBlue;
-    }
-    else if (TokenMatch(pCur,"specular_alpha",14))
-    {
-        eOut = PLY::EST_SpecularAlpha;
-    }
-    else if (TokenMatch(pCur,"opacity",7))
-    {
-        eOut = PLY::EST_Opacity;
-    }
-    else if (TokenMatch(pCur,"specular_power",14))
-    {
-        eOut = PLY::EST_PhongPower;
-    }
-    else if (TokenMatch(pCur,"r",1))
-    {
-        eOut = PLY::EST_Red;
-    }
-    else if (TokenMatch(pCur,"g",1))
-    {
-        eOut = PLY::EST_Green;
-    }
-    else if (TokenMatch(pCur,"b",1))
-    {
-        eOut = PLY::EST_Blue;
-    }
-    // NOTE: Blender3D exports texture coordinates as s,t tuples
-    else if (TokenMatch(pCur,"u",1) ||  TokenMatch(pCur,"s",1) || TokenMatch(pCur,"tx",2) || TokenMatch(pCur,"texture_u",9))
-    {
-        eOut = PLY::EST_UTextureCoord;
-    }
-    else if (TokenMatch(pCur,"v",1) ||  TokenMatch(pCur,"t",1) || TokenMatch(pCur,"ty",2) || TokenMatch(pCur,"texture_v",9))
-    {
-        eOut = PLY::EST_VTextureCoord;
-    }
-    else if (TokenMatch(pCur,"x",1))
-    {
-        eOut = PLY::EST_XCoord;
-    } else if (TokenMatch(pCur,"y",1)) {
-        eOut = PLY::EST_YCoord;
-    } else if (TokenMatch(pCur,"z",1)) {
-        eOut = PLY::EST_ZCoord;
-    } else if (TokenMatch(pCur,"nx",2)) {
-        eOut = PLY::EST_XNormal;
-    } else if (TokenMatch(pCur,"ny",2)) {
-        eOut = PLY::EST_YNormal;
-    } else if (TokenMatch(pCur,"nz",2)) {
-        eOut = PLY::EST_ZNormal;
-    } else {
-        DefaultLogger::get()->info("Found unknown property semantic in file. This is ok");
-        SkipLine(&pCur);
-    }
-    *pCurOut = pCur;
-    return eOut;
+PLY::ESemantic PLY::Property::ParseSemantic(std::vector<char> &buffer) {
+  ai_assert(!buffer.empty());
+
+  PLY::ESemantic eOut = PLY::EST_INVALID;
+  if (PLY::DOM::TokenMatch(buffer, "red", 3)) {
+    eOut = PLY::EST_Red;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "green", 5)) {
+    eOut = PLY::EST_Green;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "blue", 4)) {
+    eOut = PLY::EST_Blue;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "alpha", 5)) {
+    eOut = PLY::EST_Alpha;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "vertex_index", 12) || PLY::DOM::TokenMatch(buffer, "vertex_indices", 14)) {
+    eOut = PLY::EST_VertexIndex;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "texcoord", 8)) // Manage uv coords on faces
+  {
+    eOut = PLY::EST_TextureCoordinates;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "material_index", 14))
+  {
+    eOut = PLY::EST_MaterialIndex;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "ambient_red", 11))
+  {
+    eOut = PLY::EST_AmbientRed;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "ambient_green", 13))
+  {
+    eOut = PLY::EST_AmbientGreen;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "ambient_blue", 12))
+  {
+    eOut = PLY::EST_AmbientBlue;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "ambient_alpha", 13))
+  {
+    eOut = PLY::EST_AmbientAlpha;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "diffuse_red", 11))
+  {
+    eOut = PLY::EST_DiffuseRed;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "diffuse_green", 13))
+  {
+    eOut = PLY::EST_DiffuseGreen;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "diffuse_blue", 12))
+  {
+    eOut = PLY::EST_DiffuseBlue;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "diffuse_alpha", 13))
+  {
+    eOut = PLY::EST_DiffuseAlpha;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "specular_red", 12))
+  {
+    eOut = PLY::EST_SpecularRed;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "specular_green", 14))
+  {
+    eOut = PLY::EST_SpecularGreen;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "specular_blue", 13))
+  {
+    eOut = PLY::EST_SpecularBlue;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "specular_alpha", 14))
+  {
+    eOut = PLY::EST_SpecularAlpha;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "opacity", 7))
+  {
+    eOut = PLY::EST_Opacity;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "specular_power", 14))
+  {
+    eOut = PLY::EST_PhongPower;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "r", 1))
+  {
+    eOut = PLY::EST_Red;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "g", 1))
+  {
+    eOut = PLY::EST_Green;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "b", 1))
+  {
+    eOut = PLY::EST_Blue;
+  }
+
+  // NOTE: Blender3D exports texture coordinates as s,t tuples
+  else if (PLY::DOM::TokenMatch(buffer, "u", 1) || PLY::DOM::TokenMatch(buffer, "s", 1) || PLY::DOM::TokenMatch(buffer, "tx", 2))
+  {
+    eOut = PLY::EST_UTextureCoord;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "v", 1) || PLY::DOM::TokenMatch(buffer, "t", 1) || PLY::DOM::TokenMatch(buffer, "ty", 2))
+  {
+    eOut = PLY::EST_VTextureCoord;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "x", 1))
+  {
+    eOut = PLY::EST_XCoord;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "y", 1)) {
+    eOut = PLY::EST_YCoord;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "z", 1)) {
+    eOut = PLY::EST_ZCoord;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "nx", 2)) {
+    eOut = PLY::EST_XNormal;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "ny", 2)) {
+    eOut = PLY::EST_YNormal;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "nz", 2)) {
+    eOut = PLY::EST_ZNormal;
+  }
+  else {
+    DefaultLogger::get()->info("Found unknown property semantic in file. This is ok");
+    PLY::DOM::SkipLine(buffer);
+  }
+  return eOut;
 }
 
 // ------------------------------------------------------------------------------------------------
-bool PLY::Property::ParseProperty (const char* pCur,
-    const char** pCurOut,
-    PLY::Property* pOut)
+bool PLY::Property::ParseProperty(std::vector<char> &buffer, PLY::Property* pOut)
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
+  ai_assert(!buffer.empty());
 
-    // Forms supported:
-    // "property float x"
-    // "property list uchar int vertex_index"
-    *pCurOut = pCur;
+  // Forms supported:
+  // "property float x"
+  // "property list uchar int vertex_index"
 
-    // skip leading spaces
-    if (!SkipSpaces(pCur,&pCur)) {
-        return false;
-    }
+  // skip leading spaces
+  if (!PLY::DOM::SkipSpaces(buffer)) {
+    return false;
+  }
 
-    // skip the "property" string at the beginning
-    if (!TokenMatch(pCur,"property",8))
+  // skip the "property" string at the beginning
+  if (!PLY::DOM::TokenMatch(buffer, "property", 8))
+  {
+    // seems not to be a valid property entry
+    return false;
+  }
+  // get next word
+  if (!PLY::DOM::SkipSpaces(buffer)) {
+    return false;
+  }
+  if (PLY::DOM::TokenMatch(buffer, "list", 4))
+  {
+    pOut->bIsList = true;
+
+    // seems to be a list.
+    if (EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(buffer)))
     {
-        // seems not to be a valid property entry
-        return false;
+      // unable to parse list size data type
+      PLY::DOM::SkipLine(buffer);
+      return false;
     }
-    // get next word
-    if (!SkipSpaces(pCur,&pCur)) {
-        return false;
-    }
-    if (TokenMatch(pCur,"list",4))
+    if (!PLY::DOM::SkipSpaces(buffer))return false;
+    if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer)))
     {
-        pOut->bIsList = true;
-
-        // seems to be a list.
-        if(EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(pCur, &pCur)))
-        {
-            // unable to parse list size data type
-            SkipLine(pCur,&pCur);
-            *pCurOut = pCur;
-            return false;
-        }
-        if (!SkipSpaces(pCur,&pCur))return false;
-        if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur)))
-        {
-            // unable to parse list data type
-            SkipLine(pCur,&pCur);
-            *pCurOut = pCur;
-            return false;
-        }
-    }
-    else
+      // unable to parse list data type
+      PLY::DOM::SkipLine(buffer);
+      return false;
+    }
+  }
+  else
+  {
+    if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer)))
     {
-        if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur)))
-        {
-            // unable to parse data type. Skip the property
-            SkipLine(pCur,&pCur);
-            *pCurOut = pCur;
-            return false;
-        }
+      // unable to parse data type. Skip the property
+      PLY::DOM::SkipLine(buffer);
+      return false;
     }
+  }
 
-    if (!SkipSpaces(pCur,&pCur))return false;
-    const char* szCur = pCur;
-    pOut->Semantic = PLY::Property::ParseSemantic(pCur, &pCur);
-
-    if (PLY::EST_INVALID == pOut->Semantic)
-    {
-        // store the name of the semantic
-        uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+  if (!PLY::DOM::SkipSpaces(buffer))
+    return false;
 
-        DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK");
-        pOut->szName = std::string(szCur,iDiff);
-    }
+  pOut->Semantic = PLY::Property::ParseSemantic(buffer);
 
-    SkipSpacesAndLineEnd(pCur,&pCur);
-    *pCurOut = pCur;
+  if (PLY::EST_INVALID == pOut->Semantic)
+  {
+    DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK");
+    std::string(&buffer[0], &buffer[0] + strlen(&buffer[0]));
+  }
 
-    return true;
+  PLY::DOM::SkipSpacesAndLineEnd(buffer);
+  return true;
 }
 
 // ------------------------------------------------------------------------------------------------
-PLY::EElementSemantic PLY::Element::ParseSemantic(const char* pCur,
-    const char** pCurOut)
+PLY::EElementSemantic PLY::Element::ParseSemantic(std::vector<char> &buffer)
 {
-    ai_assert(NULL != pCur && NULL != pCurOut);
-    PLY::EElementSemantic eOut = PLY::EEST_INVALID;
-    if (TokenMatch(pCur,"vertex",6))
-    {
-        eOut = PLY::EEST_Vertex;
-    }
-    else if (TokenMatch(pCur,"face",4))
-    {
-        eOut = PLY::EEST_Face;
-    }
+  ai_assert(!buffer.empty());
+
+  PLY::EElementSemantic eOut = PLY::EEST_INVALID;
+  if (PLY::DOM::TokenMatch(buffer, "vertex", 6))
+  {
+    eOut = PLY::EEST_Vertex;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "face", 4))
+  {
+    eOut = PLY::EEST_Face;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "tristrips", 9))
+  {
+    eOut = PLY::EEST_TriStrip;
+  }
 #if 0
-    // TODO: maybe implement this?
-    else if (TokenMatch(pCur,"range_grid",10))
-    {
-        eOut = PLY::EEST_Face;
-    }
+  // TODO: maybe implement this?
+  else if (PLY::DOM::TokenMatch(buffer,"range_grid",10))
+  {
+    eOut = PLY::EEST_Face;
+  }
 #endif
-    else if (TokenMatch(pCur,"tristrips",9))
-    {
-        eOut = PLY::EEST_TriStrip;
-    }
-    else if (TokenMatch(pCur,"edge",4))
-    {
-        eOut = PLY::EEST_Edge;
-    }
-    else if (TokenMatch(pCur,"material",8))
-    {
-        eOut = PLY::EEST_Material;
-    }
-    *pCurOut = pCur;
-
-    return eOut;
+  else if (PLY::DOM::TokenMatch(buffer, "edge", 4))
+  {
+    eOut = PLY::EEST_Edge;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "material", 8))
+  {
+    eOut = PLY::EEST_Material;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "TextureFile", 11))
+  {
+    eOut = PLY::EEST_TextureFile;
+  }
+
+  return eOut;
 }
 
 // ------------------------------------------------------------------------------------------------
-bool PLY::Element::ParseElement (const char* pCur,
-    const char** pCurOut,
-    PLY::Element* pOut)
+bool PLY::Element::ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLY::Element* pOut)
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != pOut );
+  ai_assert(NULL != pOut);
+  // Example format: "element vertex 8"
 
-    // Example format: "element vertex 8"
-    *pCurOut = pCur;
+  // skip leading spaces
+  if (!PLY::DOM::SkipSpaces(buffer))
+  {
+    return false;
+  }
 
-    // skip leading spaces
-    if (!SkipSpaces(&pCur)) {
-        return false;
-    }
+  // skip the "element" string at the beginning
+  if (!PLY::DOM::TokenMatch(buffer, "element", 7) && !PLY::DOM::TokenMatch(buffer, "comment", 7))
+  {
+    // seems not to be a valid property entry
+    return false;
+  }
+  // get next word
+  if (!PLY::DOM::SkipSpaces(buffer))
+    return false;
 
-    // skip the "element" string at the beginning
-    if (!TokenMatch(pCur,"element",7))
-    {
-        // seems not to be a valid property entry
-        return false;
-    }
-    // get next word
-    if (!SkipSpaces(&pCur))return false;
+  // parse the semantic of the element
+  pOut->eSemantic = PLY::Element::ParseSemantic(buffer);
+  if (PLY::EEST_INVALID == pOut->eSemantic)
+  {
+    // if the exact semantic can't be determined, just store
+    // the original string identifier
+    pOut->szName = std::string(&buffer[0], &buffer[0] + strlen(&buffer[0]));
+  }
 
-    // parse the semantic of the element
-    const char* szCur = pCur;
-    pOut->eSemantic = PLY::Element::ParseSemantic(pCur,&pCur);
-    if (PLY::EEST_INVALID == pOut->eSemantic)
-    {
-        // if the exact semantic can't be determined, just store
-        // the original string identifier
-        uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
-        pOut->szName = std::string(szCur,iDiff);
-    }
+  if (!PLY::DOM::SkipSpaces(buffer))
+    return false;
 
-    if (!SkipSpaces(&pCur))return false;
+  if (PLY::EEST_TextureFile == pOut->eSemantic)
+  {
+    char* endPos = &buffer[0] + (strlen(&buffer[0]) - 1);
+    pOut->szName = std::string(&buffer[0], endPos);
+  }
 
-    //parse the number of occurrences of this element
-    pOut->NumOccur = strtoul10(pCur,&pCur);
+  //parse the number of occurrences of this element
+  const char* pCur = (char*)&buffer[0];
+  pOut->NumOccur = strtoul10(pCur, &pCur);
 
-    // go to the next line
-    SkipSpacesAndLineEnd(pCur,&pCur);
+  // go to the next line
+  PLY::DOM::SkipSpacesAndLineEnd(buffer);
 
-    // now parse all properties of the element
-    while(true)
-    {
-        // skip all comments
-        PLY::DOM::SkipComments(pCur,&pCur);
+  // now parse all properties of the element
+  while (true)
+  {
+    streamBuffer.getNextDataLine(buffer, '\\');
+    pCur = (char*)&buffer[0];
 
-        PLY::Property prop;
-        if(!PLY::Property::ParseProperty(pCur,&pCur,&prop))break;
-        pOut->alProperties.push_back(prop);
-    }
-    *pCurOut = pCur;
+    // skip all comments
+    PLY::DOM::SkipComments(buffer);
 
-    return true;
-}
+    PLY::Property prop;
+    if (!PLY::Property::ParseProperty(buffer, &prop))
+      break;
 
-// ------------------------------------------------------------------------------------------------
-bool PLY::DOM::SkipComments (const char* pCur,
-    const char** pCurOut)
-{
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    *pCurOut = pCur;
+    pOut->alProperties.push_back(prop);
+  }
 
-    // skip spaces
-    if (!SkipSpaces(pCur,&pCur)) {
-        return false;
-    }
-
-    if (TokenMatch(pCur,"comment",7))
-    {
-        if ( !IsLineEnd(pCur[-1]) )
-        {
-            SkipLine(pCur,&pCur);
-        }
-        SkipComments(pCur,&pCur);
-        *pCurOut = pCur;
-        return true;
-    }
-    *pCurOut = pCur;
-
-    return false;
+  return true;
 }
 
 // ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseHeader (const char* pCur,const char** pCurOut,bool isBinary) {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
+bool PLY::DOM::SkipSpaces(std::vector<char> &buffer)
+{
+  const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0];
+  bool ret = false;
+  if (pCur)
+  {
+    const char* szCur = pCur;
+    ret = Assimp::SkipSpaces(pCur, &pCur);
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin");
+    uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+    buffer.erase(buffer.begin(), buffer.begin() + iDiff);
+    return ret;
+  }
 
-    // after ply and format line
-    *pCurOut = pCur;
+  return ret;
+}
 
-    // parse all elements
-    while ((*pCur) != '\0')
-    {
-        // skip all comments
-        PLY::DOM::SkipComments(pCur,&pCur);
+bool PLY::DOM::SkipLine(std::vector<char> &buffer)
+{
+  const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0];
+  bool ret = false;
+  if (pCur)
+  {
+    const char* szCur = pCur;
+    ret = Assimp::SkipLine(pCur, &pCur);
 
-        PLY::Element out;
-        if(PLY::Element::ParseElement(pCur,&pCur,&out))
-        {
-            // add the element to the list of elements
-            alElements.push_back(out);
-        }
-        else if (TokenMatch(pCur,"end_header",10))
-        {
-            // we have reached the end of the header
-            break;
-        }
-        else
-        {
-            // ignore unknown header elements
-            SkipLine(&pCur);
-        }
-    }
-    if(!isBinary)
-    { // it would occur an error, if binary data start with values as space or line end.
-        SkipSpacesAndLineEnd(pCur,&pCur);
-    }
-    *pCurOut = pCur;
+    uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+    buffer.erase(buffer.begin(), buffer.begin() + iDiff);
+    return ret;
+  }
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded");
-    return true;
+  return ret;
 }
 
-// ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseElementInstanceLists (
-    const char* pCur,
-    const char** pCurOut)
+bool PLY::DOM::TokenMatch(std::vector<char> &buffer, const char* token, unsigned int len)
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
+  const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0];
+  bool ret = false;
+  if (pCur)
+  {
+    const char* szCur = pCur;
+    ret = Assimp::TokenMatch(pCur, token, len);
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin");
-    *pCurOut = pCur;
+    uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+    buffer.erase(buffer.begin(), buffer.begin() + iDiff);
+    return ret;
+  }
 
-    alElementData.resize(alElements.size());
+  return ret;
+}
 
-    std::vector<PLY::Element>::const_iterator i = alElements.begin();
-    std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
+bool PLY::DOM::SkipSpacesAndLineEnd(std::vector<char> &buffer)
+{
+  const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0];
+  bool ret = false;
+  if (pCur)
+  {
+    const char* szCur = pCur;
+    ret = Assimp::SkipSpacesAndLineEnd(pCur, &pCur);
 
-    // parse all element instances
-    for (;i != alElements.end();++i,++a)
-    {
-        (*a).alInstances.resize((*i).NumOccur);
-        PLY::ElementInstanceList::ParseInstanceList(pCur,&pCur,&(*i),&(*a));
-    }
+    uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+    buffer.erase(buffer.begin(), buffer.begin() + iDiff);
+    return ret;
+  }
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded");
-    *pCurOut = pCur;
-    return true;
+  return ret;
 }
 
-// ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseElementInstanceListsBinary (
-    const char* pCur,
-    const char** pCurOut,
-    bool p_bBE)
+bool PLY::DOM::SkipComments(std::vector<char> &buffer)
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut);
+  ai_assert(!buffer.empty());
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin");
-    *pCurOut = pCur;
-
-    alElementData.resize(alElements.size());
+  std::vector<char> nbuffer = buffer;
+  // skip spaces
+  if (!SkipSpaces(nbuffer)) {
+    return false;
+  }
 
-    std::vector<PLY::Element>::const_iterator i = alElements.begin();
-    std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
+  if (TokenMatch(nbuffer, "comment", 7))
+  {
+    if (!SkipSpaces(nbuffer))
+      SkipLine(nbuffer);
 
-    // parse all element instances
-    for (;i != alElements.end();++i,++a)
+    if (!TokenMatch(nbuffer, "TextureFile", 11))
     {
-        (*a).alInstances.resize((*i).NumOccur);
-        PLY::ElementInstanceList::ParseInstanceListBinary(pCur,&pCur,&(*i),&(*a),p_bBE);
+      SkipLine(nbuffer);
+      buffer = nbuffer;
+      return true;
     }
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded");
-    *pCurOut = pCur;
     return true;
+  }
+
+  return false;
 }
 
 // ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseInstanceBinary (const char* pCur,DOM* p_pcOut,bool p_bBE)
-{
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != p_pcOut );
+bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool isBinary) {
+  DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin");
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin");
+  // parse all elements
+  while (!buffer.empty())
+  {
+    // skip all comments
+    PLY::DOM::SkipComments(buffer);
 
-    if(!p_pcOut->ParseHeader(pCur,&pCur,true))
+    PLY::Element out;
+    if (PLY::Element::ParseElement(streamBuffer, buffer, &out))
     {
-        DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
-        return false;
+      // add the element to the list of elements
+      alElements.push_back(out);
     }
-    if(!p_pcOut->ParseElementInstanceListsBinary(pCur,&pCur,p_bBE))
+    else if (TokenMatch(buffer, "end_header", 10))
     {
-        DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
-        return false;
+      // we have reached the end of the header
+      break;
     }
-    DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded");
-    return true;
+    else
+    {
+      // ignore unknown header elements
+      streamBuffer.getNextDataLine(buffer, '\\');
+    }
+  }
+
+  if (!isBinary) // it would occur an error, if binary data start with values as space or line end.
+    SkipSpacesAndLineEnd(buffer);
+
+  DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded");
+  return true;
 }
 
 // ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseInstance (const char* pCur,DOM* p_pcOut)
+bool PLY::DOM::ParseElementInstanceLists(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLYImporter* loader)
 {
-    ai_assert(NULL != pCur);
-    ai_assert(NULL != p_pcOut);
+  DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin");
+  alElementData.resize(alElements.size());
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin");
+  std::vector<PLY::Element>::const_iterator i = alElements.begin();
+  std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
 
-
-    if(!p_pcOut->ParseHeader(pCur,&pCur,false))
+  // parse all element instances
+  //construct vertices and faces
+  for (; i != alElements.end(); ++i, ++a)
+  {
+    if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip)
     {
-        DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
-        return false;
+      PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), NULL, loader);
     }
-    if(!p_pcOut->ParseElementInstanceLists(pCur,&pCur))
+    else
     {
-        DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
-        return false;
+      (*a).alInstances.resize((*i).NumOccur);
+      PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), &(*a), NULL);
     }
-    DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded");
-    return true;
+  }
+
+  DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded");
+  return true;
 }
 
 // ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstanceList::ParseInstanceList (
-    const char* pCur,
-    const char** pCurOut,
-    const PLY::Element* pcElement,
-    PLY::ElementInstanceList* p_pcOut)
+bool PLY::DOM::ParseElementInstanceListsBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+    const char* &pCur,
+    unsigned int &bufferSize,
+    PLYImporter* loader,
+    bool p_bBE)
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != pcElement );
-    ai_assert( NULL != p_pcOut );
+  DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin");
+  alElementData.resize(alElements.size());
 
-    if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty())
+  std::vector<PLY::Element>::const_iterator i = alElements.begin();
+  std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
+
+  // parse all element instances
+  for (; i != alElements.end(); ++i, ++a)
+  {
+    if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip)
     {
-        // if the element has an unknown semantic we can skip all lines
-        // However, there could be comments
-        for (unsigned int i = 0; i < pcElement->NumOccur;++i)
-        {
-            PLY::DOM::SkipComments(pCur,&pCur);
-            SkipLine(pCur,&pCur);
-        }
+      PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), NULL, loader, p_bBE);
     }
     else
     {
-        // be sure to have enough storage
-        for (unsigned int i = 0; i < pcElement->NumOccur;++i)
-        {
-            PLY::DOM::SkipComments(pCur,&pCur);
-            PLY::ElementInstance::ParseInstance(pCur, &pCur,pcElement,
-                &p_pcOut->alInstances[i]);
-        }
+      (*a).alInstances.resize((*i).NumOccur);
+      PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), &(*a), NULL, p_bBE);
     }
-    *pCurOut = pCur;
-    return true;
-}
+  }
 
-// ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstanceList::ParseInstanceListBinary (
-    const char* pCur,
-    const char** pCurOut,
-    const PLY::Element* pcElement,
-    PLY::ElementInstanceList* p_pcOut,
-    bool p_bBE /* = false */)
-{
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != pcElement );
-    ai_assert( NULL != p_pcOut );
-
-    // we can add special handling code for unknown element semantics since
-    // we can't skip it as a whole block (we don't know its exact size
-    // due to the fact that lists could be contained in the property list
-    // of the unknown element)
-    for (unsigned int i = 0; i < pcElement->NumOccur;++i)
-    {
-        PLY::ElementInstance::ParseInstanceBinary(pCur, &pCur,pcElement,
-            &p_pcOut->alInstances[i], p_bBE);
-    }
-    *pCurOut = pCur;
-    return true;
+  DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded");
+  return true;
 }
 
 // ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstance::ParseInstance (
-    const char* pCur,
-    const char** pCurOut,
-    const PLY::Element* pcElement,
-    PLY::ElementInstance* p_pcOut)
+bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader, bool p_bBE)
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != pcElement );
-    ai_assert( NULL != p_pcOut );
+  ai_assert(NULL != p_pcOut);
+  ai_assert(NULL != loader);
 
-    if (!SkipSpaces(pCur, &pCur)) {
-        return false;
-    }
-
-    // allocate enough storage
-    p_pcOut->alProperties.resize(pcElement->alProperties.size());
-
-    std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
-    std::vector<PLY::Property>::const_iterator  a = pcElement->alProperties.begin();
-    for (;i != p_pcOut->alProperties.end();++i,++a)
-    {
-        if(!(PLY::PropertyInstance::ParseInstance(pCur, &pCur,&(*a),&(*i))))
-        {
-            DefaultLogger::get()->warn("Unable to parse property instance. "
-                "Skipping this element instance");
+  std::vector<char> buffer;
+  streamBuffer.getNextDataLine(buffer, '\\');
 
-            // skip the rest of the instance
-            SkipLine(pCur, &pCur);
+  DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin");
 
-            PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType);
-            (*i).avList.push_back(v);
-        }
-    }
-    *pCurOut = pCur;
-    return true;
+  if (!p_pcOut->ParseHeader(streamBuffer, buffer, true))
+  {
+    DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
+    return false;
+  }
+
+  streamBuffer.getNextBlock(buffer);
+  unsigned int bufferSize = buffer.size();
+  const char* pCur = (char*)&buffer[0];
+  if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE))
+  {
+    DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
+    return false;
+  }
+  DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded");
+  return true;
 }
 
 // ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstance::ParseInstanceBinary (
-    const char* pCur,
-    const char** pCurOut,
-    const PLY::Element* pcElement,
-    PLY::ElementInstance* p_pcOut,
-    bool p_bBE /* = false */)
+bool PLY::DOM::ParseInstance(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader)
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != pcElement );
-    ai_assert( NULL != p_pcOut );
+  ai_assert(NULL != p_pcOut);
+  ai_assert(NULL != loader);
 
-    // allocate enough storage
-    p_pcOut->alProperties.resize(pcElement->alProperties.size());
+  std::vector<char> buffer;
+  streamBuffer.getNextDataLine(buffer, '\\');
 
-    std::vector<PLY::PropertyInstance>::iterator i =  p_pcOut->alProperties.begin();
-    std::vector<PLY::Property>::const_iterator   a =  pcElement->alProperties.begin();
-    for (;i != p_pcOut->alProperties.end();++i,++a)
-    {
-        if(!(PLY::PropertyInstance::ParseInstanceBinary(pCur, &pCur,&(*a),&(*i),p_bBE)))
-        {
-            DefaultLogger::get()->warn("Unable to parse binary property instance. "
-                "Skipping this element instance");
+  DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin");
 
-            (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType));
-        }
-    }
-    *pCurOut = pCur;
-    return true;
+  if (!p_pcOut->ParseHeader(streamBuffer, buffer, false))
+  {
+    DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
+    return false;
+  }
+
+  //get next line after header
+  streamBuffer.getNextDataLine(buffer, '\\');
+  if (!p_pcOut->ParseElementInstanceLists(streamBuffer, buffer, loader))
+  {
+    DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
+    return false;
+  }
+  DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded");
+  return true;
 }
 
 // ------------------------------------------------------------------------------------------------
-bool PLY::PropertyInstance::ParseInstance (const char* pCur,const char** pCurOut,
-    const PLY::Property* prop, PLY::PropertyInstance* p_pcOut)
+bool PLY::ElementInstanceList::ParseInstanceList(
+  IOStreamBuffer<char> &streamBuffer,
+  std::vector<char> &buffer,
+  const PLY::Element* pcElement,
+  PLY::ElementInstanceList* p_pcOut,
+  PLYImporter* loader)
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != prop );
-    ai_assert( NULL != p_pcOut );
-
-    *pCurOut = pCur;
-
-    // skip spaces at the beginning
-    if (!SkipSpaces(pCur, &pCur)) {
-        return false;
-    }
-
-    if (prop->bIsList)
+  ai_assert(NULL != pcElement);
+  const char* pCur = (const char*)&buffer[0];
+
+  // parse all elements
+  if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty())
+  {
+    // if the element has an unknown semantic we can skip all lines
+    // However, there could be comments
+    for (unsigned int i = 0; i < pcElement->NumOccur; ++i)
     {
-        // parse the number of elements in the list
-        PLY::PropertyInstance::ValueUnion v;
-        PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eFirstType,&v);
-
-        // convert to unsigned int
-        unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
-
-        // parse all list elements
-        p_pcOut->avList.resize(iNum);
-        for (unsigned int i = 0; i < iNum;++i)
+      PLY::DOM::SkipComments(buffer);
+      PLY::DOM::SkipLine(buffer);
+      streamBuffer.getNextDataLine(buffer, '\\');
+      pCur = (buffer.empty()) ? NULL : (const char*)&buffer[0];
+    }
+  }
+  else
+  {
+    // be sure to have enough storage
+    for (unsigned int i = 0; i < pcElement->NumOccur; ++i)
+    {
+      if (p_pcOut)
+        PLY::ElementInstance::ParseInstance(pCur, pcElement, &p_pcOut->alInstances[i]);
+      else
+      {
+        ElementInstance elt;
+        PLY::ElementInstance::ParseInstance(pCur, pcElement, &elt);
+
+        // Create vertex or face
+        if (pcElement->eSemantic == EEST_Vertex)
         {
-            if (!SkipSpaces(pCur, &pCur))return false;
-            PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&p_pcOut->avList[i]);
+          //call loader instance from here
+          loader->LoadVertex(pcElement, &elt, i);
         }
-    }
-    else
-    {
-        // parse the property
-        PLY::PropertyInstance::ValueUnion v;
+        else if (pcElement->eSemantic == EEST_Face)
+        {
+          //call loader instance from here
+          loader->LoadFace(pcElement, &elt, i);
+        }
+        else if (pcElement->eSemantic == EEST_TriStrip)
+        {
+          //call loader instance from here
+          loader->LoadFace(pcElement, &elt, i);
+        }
+      }
 
-        PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&v);
-        p_pcOut->avList.push_back(v);
+      streamBuffer.getNextDataLine(buffer, '\\');
+      pCur = (buffer.empty()) ? NULL : (const char*)&buffer[0];
     }
-    SkipSpacesAndLineEnd(pCur, &pCur);
-    *pCurOut = pCur;
-    return true;
+  }
+  return true;
 }
 
 // ------------------------------------------------------------------------------------------------
-bool PLY::PropertyInstance::ParseInstanceBinary (
-    const char*  pCur,
-    const char** pCurOut,
-    const PLY::Property* prop,
-    PLY::PropertyInstance* p_pcOut,
-    bool p_bBE)
+bool PLY::ElementInstanceList::ParseInstanceListBinary(
+  IOStreamBuffer<char> &streamBuffer,
+  std::vector<char> &buffer,
+  const char* &pCur,
+  unsigned int &bufferSize,
+  const PLY::Element* pcElement,
+  PLY::ElementInstanceList* p_pcOut,
+  PLYImporter* loader,
+  bool p_bBE /* = false */)
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != prop );
-    ai_assert( NULL != p_pcOut );
-
-    if (prop->bIsList)
-    {
-        // parse the number of elements in the list
-        PLY::PropertyInstance::ValueUnion v;
-        PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eFirstType,&v,p_bBE);
-
-        // convert to unsigned int
-        unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
-
-        // parse all list elements
-        p_pcOut->avList.resize(iNum);
-        for (unsigned int i = 0; i < iNum;++i){
-            PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&p_pcOut->avList[i],p_bBE);
-        }
-    }
+  ai_assert(NULL != pcElement);
+
+  // we can add special handling code for unknown element semantics since
+  // we can't skip it as a whole block (we don't know its exact size
+  // due to the fact that lists could be contained in the property list
+  // of the unknown element)
+  for (unsigned int i = 0; i < pcElement->NumOccur; ++i)
+  {
+    if (p_pcOut)
+      PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &p_pcOut->alInstances[i], p_bBE);
     else
     {
-        // parse the property
-        PLY::PropertyInstance::ValueUnion v;
-        PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&v,p_bBE);
-        p_pcOut->avList.push_back(v);
-    }
-    *pCurOut = pCur;
-    return true;
+      ElementInstance elt;
+      PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &elt, p_bBE);
+
+      // Create vertex or face
+      if (pcElement->eSemantic == EEST_Vertex)
+      {
+        //call loader instance from here
+        loader->LoadVertex(pcElement, &elt, i);
+      }
+      else if (pcElement->eSemantic == EEST_Face)
+      {
+        //call loader instance from here
+        loader->LoadFace(pcElement, &elt, i);
+      }
+      else if (pcElement->eSemantic == EEST_TriStrip)
+      {
+        //call loader instance from here
+        loader->LoadFace(pcElement, &elt, i);
+      }
+    }
+  }
+  return true;
 }
 
 // ------------------------------------------------------------------------------------------------
-PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue( PLY::EDataType eType )
+bool PLY::ElementInstance::ParseInstance(const char* &pCur,
+  const PLY::Element* pcElement,
+  PLY::ElementInstance* p_pcOut)
 {
-    PLY::PropertyInstance::ValueUnion out;
+  ai_assert(NULL != pcElement);
+  ai_assert(NULL != p_pcOut);
 
-    switch (eType)
-    {
-    case EDT_Float:
-        out.fFloat = 0.f;
-        return out;
+  // allocate enough storage
+  p_pcOut->alProperties.resize(pcElement->alProperties.size());
 
-    case EDT_Double:
-        out.fDouble = 0.;
-        return out;
+  std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
+  std::vector<PLY::Property>::const_iterator  a = pcElement->alProperties.begin();
+  for (; i != p_pcOut->alProperties.end(); ++i, ++a)
+  {
+    if (!(PLY::PropertyInstance::ParseInstance(pCur, &(*a), &(*i))))
+    {
+      DefaultLogger::get()->warn("Unable to parse property instance. "
+        "Skipping this element instance");
 
-    default: ;
-    };
-    out.iUInt = 0;
-    return out;
+      PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType);
+      (*i).avList.push_back(v);
+    }
+  }
+  return true;
 }
 
 // ------------------------------------------------------------------------------------------------
-bool PLY::PropertyInstance::ParseValue(
-    const char* pCur,
-    const char** pCurOut,
-    PLY::EDataType eType,
-    PLY::PropertyInstance::ValueUnion* out)
+bool PLY::ElementInstance::ParseInstanceBinary(
+  IOStreamBuffer<char> &streamBuffer,
+  std::vector<char> &buffer,
+  const char* &pCur,
+  unsigned int &bufferSize,
+  const PLY::Element* pcElement,
+  PLY::ElementInstance* p_pcOut,
+  bool p_bBE /* = false */)
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != out );
+  ai_assert(NULL != pcElement);
+  ai_assert(NULL != p_pcOut);
+
+  // allocate enough storage
+  p_pcOut->alProperties.resize(pcElement->alProperties.size());
 
-    bool ret = true;
-    *pCurOut = pCur;
-    switch (eType)
+  std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
+  std::vector<PLY::Property>::const_iterator   a = pcElement->alProperties.begin();
+  for (; i != p_pcOut->alProperties.end(); ++i, ++a)
+  {
+    if (!(PLY::PropertyInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, &(*a), &(*i), p_bBE)))
     {
-    case EDT_UInt:
-    case EDT_UShort:
-    case EDT_UChar:
-
-        out->iUInt = (uint32_t)strtoul10(pCur, &pCur);
-        break;
-
-    case EDT_Int:
-    case EDT_Short:
-    case EDT_Char:
-
-        out->iInt = (int32_t)strtol10(pCur, &pCur);
-        break;
-
-    case EDT_Float:
-        // technically this should cast to float, but people tend to use float descriptors for double data
-        // this is the best way to not risk losing precision on import and it doesn't hurt to do this
-        ai_real f;
-        pCur = fast_atoreal_move<ai_real>(pCur,f);
-        out->fFloat = (ai_real)f;
-        break;
-
-    case EDT_Double:
-        double d;
-        pCur = fast_atoreal_move<double>(pCur,d);
-        out->fDouble = (double)d;
-        break;
-
-    default:
-        ret = false;
-        break;
-    }
-    *pCurOut = pCur;
+      DefaultLogger::get()->warn("Unable to parse binary property instance. "
+        "Skipping this element instance");
 
-    return ret;
+      (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType));
+    }
+  }
+  return true;
 }
 
 // ------------------------------------------------------------------------------------------------
-bool PLY::PropertyInstance::ParseValueBinary(
-    const char* pCur,
-    const char** pCurOut,
-    PLY::EDataType eType,
-    PLY::PropertyInstance::ValueUnion* out,
-    bool p_bBE)
+bool PLY::PropertyInstance::ParseInstance(const char* &pCur,
+  const PLY::Property* prop, PLY::PropertyInstance* p_pcOut)
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != out );
+  ai_assert(NULL != prop);
+  ai_assert(NULL != p_pcOut);
 
-    bool ret = true;
-    switch (eType)
-    {
-    case EDT_UInt:
-        out->iUInt = (uint32_t)*((uint32_t*)pCur);
-        pCur += 4;
+  // skip spaces at the beginning
+  if (!SkipSpaces(&pCur))
+  {
+    return false;
+  }
 
-        // Swap endianness
-        if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt);
-        break;
+  if (prop->bIsList)
+  {
+    // parse the number of elements in the list
+    PLY::PropertyInstance::ValueUnion v;
+    PLY::PropertyInstance::ParseValue(pCur, prop->eFirstType, &v);
 
-    case EDT_UShort:
-        {
-        uint16_t i = *((uint16_t*)pCur);
+    // convert to unsigned int
+    unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v, prop->eFirstType);
 
-        // Swap endianness
-        if (p_bBE)ByteSwap::Swap(&i);
-        out->iUInt = (uint32_t)i;
-        pCur += 2;
-        break;
-        }
+    // parse all list elements
+    p_pcOut->avList.resize(iNum);
+    for (unsigned int i = 0; i < iNum; ++i)
+    {
+      if (!SkipSpaces(&pCur))
+        return false;
 
-    case EDT_UChar:
-        {
-        out->iUInt = (uint32_t)(*((uint8_t*)pCur));
-        pCur ++;
-        break;
-        }
+      PLY::PropertyInstance::ParseValue(pCur, prop->eType, &p_pcOut->avList[i]);
+    }
+  }
+  else
+  {
+    // parse the property
+    PLY::PropertyInstance::ValueUnion v;
 
-    case EDT_Int:
-        out->iInt = *((int32_t*)pCur);
-        pCur += 4;
+    PLY::PropertyInstance::ParseValue(pCur, prop->eType, &v);
+    p_pcOut->avList.push_back(v);
+  }
+  SkipSpacesAndLineEnd(&pCur);
+  return true;
+}
 
-        // Swap endianness
-        if (p_bBE)ByteSwap::Swap(&out->iInt);
-        break;
+// ------------------------------------------------------------------------------------------------
+bool PLY::PropertyInstance::ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+  const char* &pCur,
+  unsigned int &bufferSize,
+  const PLY::Property* prop,
+  PLY::PropertyInstance* p_pcOut,
+  bool p_bBE)
+{
+  ai_assert(NULL != prop);
+  ai_assert(NULL != p_pcOut);
+
+  // parse all elements
+  if (prop->bIsList)
+  {
+    // parse the number of elements in the list
+    PLY::PropertyInstance::ValueUnion v;
+    PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eFirstType, &v, p_bBE);
+
+    // convert to unsigned int
+    unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v, prop->eFirstType);
+
+    // parse all list elements
+    p_pcOut->avList.resize(iNum);
+    for (unsigned int i = 0; i < iNum; ++i)
+    {
+      PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eType, &p_pcOut->avList[i], p_bBE);
+    }
+  }
+  else
+  {
+    // parse the property
+    PLY::PropertyInstance::ValueUnion v;
+    PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eType, &v, p_bBE);
+    p_pcOut->avList.push_back(v);
+  }
+  return true;
+}
 
-    case EDT_Short:
-        {
-        int16_t i = *((int16_t*)pCur);
+// ------------------------------------------------------------------------------------------------
+PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue(PLY::EDataType eType)
+{
+  PLY::PropertyInstance::ValueUnion out;
 
-        // Swap endianness
-        if (p_bBE)ByteSwap::Swap(&i);
-        out->iInt = (int32_t)i;
-        pCur += 2;
-        break;
-        }
+  switch (eType)
+  {
+  case EDT_Float:
+    out.fFloat = 0.f;
+    return out;
 
-    case EDT_Char:
-        out->iInt = (int32_t)*((int8_t*)pCur);
-        pCur ++;
-        break;
+  case EDT_Double:
+    out.fDouble = 0.;
+    return out;
 
-    case EDT_Float:
-        {
-        out->fFloat = *((float*)pCur);
+  default:;
+  };
+  out.iUInt = 0;
+  return out;
+}
 
-        // Swap endianness
-        if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat);
-        pCur += 4;
-        break;
-        }
-    case EDT_Double:
-        {
-        out->fDouble = *((double*)pCur);
+// ------------------------------------------------------------------------------------------------
+bool PLY::PropertyInstance::ParseValue(const char* &pCur,
+  PLY::EDataType eType,
+  PLY::PropertyInstance::ValueUnion* out)
+{
+  ai_assert(NULL != pCur);
+  ai_assert(NULL != out);
+  
+  //calc element size
+  unsigned int lsize = 0;
+  switch (eType)
+  {
+  case EDT_Char:
+  case EDT_UChar:
+    lsize = 1;
+    break;
+
+  case EDT_UShort:
+  case EDT_Short:
+    lsize = 2;
+    break;
+
+  case EDT_UInt:
+  case EDT_Int:
+  case EDT_Float:
+    lsize = 4;
+    break;
+
+  case EDT_Double:
+    lsize = 8;
+    break;
+  }
+
+  bool ret = true;
+  switch (eType)
+  {
+  case EDT_UInt:
+  case EDT_UShort:
+  case EDT_UChar:
+
+    out->iUInt = (uint32_t)strtoul10(pCur, &pCur);
+    break;
+
+  case EDT_Int:
+  case EDT_Short:
+  case EDT_Char:
+
+    out->iInt = (int32_t)strtol10(pCur, &pCur);
+    break;
+
+  case EDT_Float:
+    // technically this should cast to float, but people tend to use float descriptors for double data
+    // this is the best way to not risk losing precision on import and it doesn't hurt to do this
+    ai_real f;
+    pCur = fast_atoreal_move<ai_real>(pCur, f);
+    out->fFloat = (ai_real)f;
+    break;
+
+  case EDT_Double:
+    double d;
+    pCur = fast_atoreal_move<double>(pCur, d);
+    out->fDouble = (double)d;
+    break;
+
+  default:
+    ret = false;
+    break;
+  }
+
+  return ret;
+}
 
-        // Swap endianness
-        if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble);
-        pCur += 8;
-        break;
-        }
-    default:
-        ret = false;
+// ------------------------------------------------------------------------------------------------
+bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer<char> &streamBuffer,
+  std::vector<char> &buffer,
+  const char* &pCur,
+  unsigned int &bufferSize,
+  PLY::EDataType eType,
+  PLY::PropertyInstance::ValueUnion* out,
+  bool p_bBE)
+{
+  ai_assert(NULL != out);
+
+  //calc element size
+  unsigned int lsize = 0;
+  switch (eType)
+  {
+  case EDT_Char:
+  case EDT_UChar:
+    lsize = 1;
+    break;
+
+  case EDT_UShort:
+  case EDT_Short:
+    lsize = 2;
+    break;
+
+  case EDT_UInt:
+  case EDT_Int:
+  case EDT_Float:
+    lsize = 4;
+    break;
+
+  case EDT_Double:
+    lsize = 8;
+    break;
+  }
+
+  //read the next file block if needed
+  if (bufferSize < lsize)
+  {
+    std::vector<char> nbuffer;
+    if (streamBuffer.getNextBlock(nbuffer))
+    {
+      //concat buffer contents
+      buffer = std::vector<char>(buffer.end() - bufferSize, buffer.end());
+      buffer.insert(buffer.end(), nbuffer.begin(), nbuffer.end());
+      nbuffer.clear();
+      bufferSize = buffer.size();
+      pCur = (char*)&buffer[0];
     }
-    *pCurOut = pCur;
-
-    return ret;
+    else
+    {
+      throw DeadlyImportError("Invalid .ply file: File corrupted");
+    }
+  }
+
+  bool ret = true;
+  switch (eType)
+  {
+  case EDT_UInt:
+    out->iUInt = (uint32_t)*((uint32_t*)pCur);
+    pCur += 4;
+
+    // Swap endianness
+    if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt);
+    break;
+
+  case EDT_UShort:
+  {
+    uint16_t i = *((uint16_t*)pCur);
+
+    // Swap endianness
+    if (p_bBE)ByteSwap::Swap(&i);
+    out->iUInt = (uint32_t)i;
+    pCur += 2;
+    break;
+  }
+
+  case EDT_UChar:
+  {
+    out->iUInt = (uint32_t)(*((uint8_t*)pCur));
+    pCur++;
+    break;
+  }
+
+  case EDT_Int:
+    out->iInt = *((int32_t*)pCur);
+    pCur += 4;
+
+    // Swap endianness
+    if (p_bBE)ByteSwap::Swap(&out->iInt);
+    break;
+
+  case EDT_Short:
+  {
+    int16_t i = *((int16_t*)pCur);
+
+    // Swap endianness
+    if (p_bBE)ByteSwap::Swap(&i);
+    out->iInt = (int32_t)i;
+    pCur += 2;
+    break;
+  }
+
+  case EDT_Char:
+    out->iInt = (int32_t)*((int8_t*)pCur);
+    pCur++;
+    break;
+
+  case EDT_Float:
+  {
+    out->fFloat = *((float*)pCur);
+
+    // Swap endianness
+    if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat);
+    pCur += 4;
+    break;
+  }
+  case EDT_Double:
+  {
+    out->fDouble = *((double*)pCur);
+
+    // Swap endianness
+    if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble);
+    pCur += 8;
+    break;
+  }
+  default:
+    ret = false;
+  }
+
+  bufferSize -= lsize;
+
+  return ret;
 }
 
 #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER
index 930536e..b17b073 100644 (file)
@@ -3,7 +3,6 @@ Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
 Copyright (c) 2006-2017, assimp team
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -46,19 +45,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include "ParsingUtils.h"
+#include "IOStreamBuffer.h"
 #include <vector>
 
-
 namespace Assimp
 {
 
+//pre-declaration
+class PLYImporter;
+
 // http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/
 // http://w3.impa.br/~lvelho/outgoing/sossai/old/ViHAP_D4.4.2_PLY_format_v1.1.pdf
 // http://www.okino.com/conv/exp_ply.htm
 namespace PLY
 {
 
-
 // ---------------------------------------------------------------------------------
 /*
 name        type        number of bytes
@@ -197,6 +198,9 @@ enum EElementSemantic
     //! The element is a material description
     EEST_Material,
 
+    //! texture path
+    EEST_TextureFile,
+
     //! Marks invalid entries
     EEST_INVALID
 };
@@ -238,16 +242,15 @@ public:
     //! string is either '\n', '\r' or '\0'. Return value is false
     //! if the input string is NOT a valid property (E.g. does
     //! not start with the "property" keyword)
-    static bool ParseProperty (const char* pCur, const char** pCurOut,
-        Property* pOut);
+    static bool ParseProperty(std::vector<char> &buffer, Property* pOut);
 
     // -------------------------------------------------------------------
     //! Parse a data type from a string
-    static EDataType ParseDataType(const char* pCur,const char** pCurOut);
+    static EDataType ParseDataType(std::vector<char> &buffer);
 
     // -------------------------------------------------------------------
     //! Parse a semantic from a string
-    static ESemantic ParseSemantic(const char* pCur,const char** pCurOut);
+    static ESemantic ParseSemantic(std::vector<char> &buffer);
 };
 
 // ---------------------------------------------------------------------------------
@@ -285,13 +288,11 @@ public:
     //! Parse an element from a string.
     //! The function will parse all properties contained in the
     //! element, too.
-    static bool ParseElement (const char* pCur, const char** pCurOut,
-        Element* pOut);
+    static bool ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, Element* pOut);
 
     // -------------------------------------------------------------------
     //! Parse a semantic from a string
-    static EElementSemantic ParseSemantic(const char* pCur,
-        const char** pCurOut);
+    static EElementSemantic ParseSemantic(std::vector<char> &buffer);
 };
 
 // ---------------------------------------------------------------------------------
@@ -331,13 +332,13 @@ public:
 
     // -------------------------------------------------------------------
     //! Parse a property instance
-    static bool ParseInstance (const char* pCur,const char** pCurOut,
+    static bool ParseInstance(const char* &pCur,
         const Property* prop, PropertyInstance* p_pcOut);
 
     // -------------------------------------------------------------------
     //! Parse a property instance in binary format
-    static bool ParseInstanceBinary (const char* pCur,const char** pCurOut,
-        const Property* prop, PropertyInstance* p_pcOut,bool p_bBE);
+    static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+        const char* &pCur, unsigned int &bufferSize, const Property* prop, PropertyInstance* p_pcOut, bool p_bBE);
 
     // -------------------------------------------------------------------
     //! Get the default value for a given data type
@@ -345,13 +346,12 @@ public:
 
     // -------------------------------------------------------------------
     //! Parse a value
-    static bool ParseValue(const char* pCur,const char** pCurOut,
-        EDataType eType,ValueUnion* out);
+    static bool ParseValue(const char* &pCur, EDataType eType, ValueUnion* out);
 
     // -------------------------------------------------------------------
     //! Parse a binary value
-    static bool ParseValueBinary(const char* pCur,const char** pCurOut,
-        EDataType eType,ValueUnion* out,bool p_bBE);
+    static bool ParseValueBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+        const char* &pCur, unsigned int &bufferSize, EDataType eType, ValueUnion* out, bool p_bBE);
 
     // -------------------------------------------------------------------
     //! Convert a property value to a given type TYPE
@@ -375,13 +375,13 @@ public:
 
     // -------------------------------------------------------------------
     //! Parse an element instance
-    static bool ParseInstance (const char* pCur,const char** pCurOut,
+    static bool ParseInstance(const char* &pCur,
         const Element* pcElement, ElementInstance* p_pcOut);
 
     // -------------------------------------------------------------------
     //! Parse a binary element instance
-    static bool ParseInstanceBinary (const char* pCur,const char** pCurOut,
-        const Element* pcElement, ElementInstance* p_pcOut,bool p_bBE);
+    static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+        const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstance* p_pcOut, bool p_bBE);
 };
 
 // ---------------------------------------------------------------------------------
@@ -400,13 +400,13 @@ public:
 
     // -------------------------------------------------------------------
     //! Parse an element instance list
-    static bool ParseInstanceList (const char* pCur,const char** pCurOut,
-        const Element* pcElement, ElementInstanceList* p_pcOut);
+    static bool ParseInstanceList(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+        const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader);
 
     // -------------------------------------------------------------------
     //! Parse a binary element instance list
-    static bool ParseInstanceListBinary (const char* pCur,const char** pCurOut,
-        const Element* pcElement, ElementInstanceList* p_pcOut,bool p_bBE);
+    static bool ParseInstanceListBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+        const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader, bool p_bBE);
 };
 // ---------------------------------------------------------------------------------
 /** \brief Class to represent the document object model of an ASCII or binary
@@ -428,50 +428,33 @@ public:
 
     //! Parse the DOM for a PLY file. The input string is assumed
     //! to be terminated with zero
-    static bool ParseInstance (const char* pCur,DOM* p_pcOut);
-    static bool ParseInstanceBinary (const char* pCur,
-        DOM* p_pcOut,bool p_bBE);
+    static bool ParseInstance(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader);
+    static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader, bool p_bBE);
 
     //! Skip all comment lines after this
-    static bool SkipComments (const char* pCur,const char** pCurOut);
+    static bool SkipComments(std::vector<char> &buffer);
+
+    static bool SkipSpaces(std::vector<char> &buffer);
+
+    static bool SkipLine(std::vector<char> &buffer);
+
+    static bool TokenMatch(std::vector<char> &buffer, const char* token, unsigned int len);
+
+    static bool SkipSpacesAndLineEnd(std::vector<char> &buffer);
 
 private:
 
     // -------------------------------------------------------------------
     //! Handle the file header and read all element descriptions
-    bool ParseHeader (const char* pCur,const char** pCurOut, bool p_bBE);
+    bool ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool p_bBE);
 
     // -------------------------------------------------------------------
     //! Read in all element instance lists
-    bool ParseElementInstanceLists (const char* pCur,const char** pCurOut);
+    bool ParseElementInstanceLists(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLYImporter* loader);
 
     // -------------------------------------------------------------------
     //! Read in all element instance lists for a binary file format
-    bool ParseElementInstanceListsBinary (const char* pCur,
-        const char** pCurOut,bool p_bBE);
-};
-
-// ---------------------------------------------------------------------------------
-/** \brief Helper class to represent a loaded PLY face
- */
-class Face
-{
-public:
-
-    Face()
-        : iMaterialIndex(0xFFFFFFFF)
-    {
-        // set all indices to zero by default
-        mIndices.resize(3,0);
-    }
-
-public:
-
-    //! List of vertex indices
-    std::vector<unsigned int> mIndices;
-
-    //! Material index
-    unsigned int iMaterialIndex;
+    bool ParseElementInstanceListsBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, const char* &pCur, unsigned int &bufferSize, PLYImporter* loader, bool p_bBE);
 };
 
 // ---------------------------------------------------------------------------------
index 5c592aa..f4d6ddd 100644 (file)
@@ -211,20 +211,20 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
     for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
         pScene->mRootNode->mMeshes[i] = i;
 
-    // create a single default material, using a light gray diffuse color for consistency with
+    // create a single default material, using a white diffuse color for consistency with
     // other geometric types (e.g., PLY).
     aiMaterial* pcMat = new aiMaterial();
     aiString s;
     s.Set(AI_DEFAULT_MATERIAL_NAME);
     pcMat->AddProperty(&s, AI_MATKEY_NAME);
 
-    aiColor4D clrDiffuse(ai_real(0.6),ai_real(0.6),ai_real(0.6),ai_real(1.0));
+    aiColor4D clrDiffuse(ai_real(1.0),ai_real(1.0),ai_real(1.0),ai_real(1.0));
     if (bMatClr) {
         clrDiffuse = clrColorDefault;
     }
     pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
     pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
-    clrDiffuse = aiColor4D( ai_real( 0.05), ai_real( 0.05), ai_real( 0.05), ai_real( 1.0));
+    clrDiffuse = aiColor4D( ai_real(1.0), ai_real(1.0), ai_real(1.0), ai_real(1.0));
     pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
 
     pScene->mNumMaterials = 1;
index 4080445..d0de13e 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  *
@@ -88,7 +88,7 @@ void Triangle::Clear()
     points_[0]=points_[1]=points_[2] = NULL;
 }
 
-void Triangle::ClearNeighbor(Triangle *triangle )
+void Triangle::ClearNeighbor(const Triangle *triangle )
 {
     if( neighbors_[0] == triangle )
     {
@@ -96,14 +96,14 @@ void Triangle::ClearNeighbor(Triangle *triangle )
     }
     else if( neighbors_[1] == triangle )
     {
-        neighbors_[1] = NULL;            
+        neighbors_[1] = NULL;
     }
     else
     {
         neighbors_[2] = NULL;
     }
 }
-    
+
 void Triangle::ClearNeighbors()
 {
   neighbors_[0] = NULL;
@@ -116,13 +116,9 @@ void Triangle::ClearDelunayEdges()
   delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
 }
 
-Point* Triangle::OppositePoint(Triangle& t, Point& p)
+Point* Triangle::OppositePoint(Triangle& t, const Point& p)
 {
   Point *cw = t.PointCW(p);
-  //double x = cw->x;
-  //double y = cw->y;
-  //x = p.x;
-  //y = p.y;
   return PointCW(*cw);
 }
 
@@ -164,8 +160,7 @@ int Triangle::Index(const Point* p)
     return 2;
   }
   assert(0);
-
-  return 0;
+  return -1;
 }
 
 int Triangle::EdgeIndex(const Point* p1, const Point* p2)
@@ -192,7 +187,7 @@ int Triangle::EdgeIndex(const Point* p1, const Point* p2)
   return -1;
 }
 
-void Triangle::MarkConstrainedEdge(const int index)
+void Triangle::MarkConstrainedEdge(int index)
 {
   constrained_edge[index] = true;
 }
@@ -215,7 +210,7 @@ void Triangle::MarkConstrainedEdge(Point* p, Point* q)
 }
 
 // The point counter-clockwise to given point
-Point* Triangle::PointCW(Point& point)
+Point* Triangle::PointCW(const Point& point)
 {
   if (&point == points_[0]) {
     return points_[2];
@@ -225,12 +220,11 @@ Point* Triangle::PointCW(Point& point)
     return points_[1];
   }
   assert(0);
-
-  return 0;
+  return NULL;
 }
 
 // The point counter-clockwise to given point
-Point* Triangle::PointCCW(Point& point)
+Point* Triangle::PointCCW(const Point& point)
 {
   if (&point == points_[0]) {
     return points_[1];
@@ -240,12 +234,11 @@ Point* Triangle::PointCCW(Point& point)
     return points_[0];
   }
   assert(0);
-
-  return 0;
+  return NULL;
 }
 
 // The neighbor clockwise to given point
-Triangle* Triangle::NeighborCW(Point& point)
+Triangle* Triangle::NeighborCW(const Point& point)
 {
   if (&point == points_[0]) {
     return neighbors_[1];
@@ -256,7 +249,7 @@ Triangle* Triangle::NeighborCW(Point& point)
 }
 
 // The neighbor counter-clockwise to given point
-Triangle* Triangle::NeighborCCW(Point& point)
+Triangle* Triangle::NeighborCCW(const Point& point)
 {
   if (&point == points_[0]) {
     return neighbors_[2];
@@ -266,7 +259,7 @@ Triangle* Triangle::NeighborCCW(Point& point)
   return neighbors_[1];
 }
 
-bool Triangle::GetConstrainedEdgeCCW(Point& p)
+bool Triangle::GetConstrainedEdgeCCW(const Point& p)
 {
   if (&p == points_[0]) {
     return constrained_edge[2];
@@ -276,7 +269,7 @@ bool Triangle::GetConstrainedEdgeCCW(Point& p)
   return constrained_edge[1];
 }
 
-bool Triangle::GetConstrainedEdgeCW(Point& p)
+bool Triangle::GetConstrainedEdgeCW(const Point& p)
 {
   if (&p == points_[0]) {
     return constrained_edge[1];
@@ -286,7 +279,7 @@ bool Triangle::GetConstrainedEdgeCW(Point& p)
   return constrained_edge[0];
 }
 
-void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce)
+void Triangle::SetConstrainedEdgeCCW(const Point& p, bool ce)
 {
   if (&p == points_[0]) {
     constrained_edge[2] = ce;
@@ -297,7 +290,7 @@ void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce)
   }
 }
 
-void Triangle::SetConstrainedEdgeCW(Point& p, bool ce)
+void Triangle::SetConstrainedEdgeCW(const Point& p, bool ce)
 {
   if (&p == points_[0]) {
     constrained_edge[1] = ce;
@@ -308,7 +301,7 @@ void Triangle::SetConstrainedEdgeCW(Point& p, bool ce)
   }
 }
 
-bool Triangle::GetDelunayEdgeCCW(Point& p)
+bool Triangle::GetDelunayEdgeCCW(const Point& p)
 {
   if (&p == points_[0]) {
     return delaunay_edge[2];
@@ -318,7 +311,7 @@ bool Triangle::GetDelunayEdgeCCW(Point& p)
   return delaunay_edge[1];
 }
 
-bool Triangle::GetDelunayEdgeCW(Point& p)
+bool Triangle::GetDelunayEdgeCW(const Point& p)
 {
   if (&p == points_[0]) {
     return delaunay_edge[1];
@@ -328,7 +321,7 @@ bool Triangle::GetDelunayEdgeCW(Point& p)
   return delaunay_edge[0];
 }
 
-void Triangle::SetDelunayEdgeCCW(Point& p, bool e)
+void Triangle::SetDelunayEdgeCCW(const Point& p, bool e)
 {
   if (&p == points_[0]) {
     delaunay_edge[2] = e;
@@ -339,7 +332,7 @@ void Triangle::SetDelunayEdgeCCW(Point& p, bool e)
   }
 }
 
-void Triangle::SetDelunayEdgeCW(Point& p, bool e)
+void Triangle::SetDelunayEdgeCW(const Point& p, bool e)
 {
   if (&p == points_[0]) {
     delaunay_edge[1] = e;
@@ -351,7 +344,7 @@ void Triangle::SetDelunayEdgeCW(Point& p, bool e)
 }
 
 // The neighbor across to given point
-Triangle& Triangle::NeighborAcross(Point& opoint)
+Triangle& Triangle::NeighborAcross(const Point& opoint)
 {
   if (&opoint == points_[0]) {
     return *neighbors_[0];
@@ -369,5 +362,4 @@ void Triangle::DebugPrint()
   cout << points_[2]->x << "," << points_[2]->y << endl;
 }
 
-}
-
+}
\ No newline at end of file
index 4f69183..ac7389a 100644 (file)
@@ -113,7 +113,7 @@ struct Point {
   /// Convert this point into a unit point. Returns the Length.
   double Normalize()
   {
-    double len = Length();
+    const double len = Length();
     x /= len;
     y /= len;
     return len;
@@ -162,50 +162,50 @@ bool constrained_edge[3];
 /// Flags to determine if an edge is a Delauney edge
 bool delaunay_edge[3];
 
-Point* GetPoint(const int& index);
-Point* PointCW(Point& point);
-Point* PointCCW(Point& point);
-Point* OppositePoint(Triangle& t, Point& p);
+Point* GetPoint(int index);
+Point* PointCW(const Point& point);
+Point* PointCCW(const Point& point);
+Point* OppositePoint(Triangle& t, const Point& p);
 
-Triangle* GetNeighbor(const int& index);
+Triangle* GetNeighbor(int index);
 void MarkNeighbor(Point* p1, Point* p2, Triangle* t);
 void MarkNeighbor(Triangle& t);
 
-void MarkConstrainedEdge(const int index);
+void MarkConstrainedEdge(int index);
 void MarkConstrainedEdge(Edge& edge);
 void MarkConstrainedEdge(Point* p, Point* q);
 
 int Index(const Point* p);
 int EdgeIndex(const Point* p1, const Point* p2);
 
-Triangle* NeighborCW(Point& point);
-Triangle* NeighborCCW(Point& point);
-bool GetConstrainedEdgeCCW(Point& p);
-bool GetConstrainedEdgeCW(Point& p);
-void SetConstrainedEdgeCCW(Point& p, bool ce);
-void SetConstrainedEdgeCW(Point& p, bool ce);
-bool GetDelunayEdgeCCW(Point& p);
-bool GetDelunayEdgeCW(Point& p);
-void SetDelunayEdgeCCW(Point& p, bool e);
-void SetDelunayEdgeCW(Point& p, bool e);
-
-bool Contains(Point* p);
+Triangle* NeighborCW(const Point& point);
+Triangle* NeighborCCW(const Point& point);
+bool GetConstrainedEdgeCCW(const Point& p);
+bool GetConstrainedEdgeCW(const Point& p);
+void SetConstrainedEdgeCCW(const Point& p, bool ce);
+void SetConstrainedEdgeCW(const Point& p, bool ce);
+bool GetDelunayEdgeCCW(const Point& p);
+bool GetDelunayEdgeCW(const Point& p);
+void SetDelunayEdgeCCW(const Point& p, bool e);
+void SetDelunayEdgeCW(const Point& p, bool e);
+
+bool Contains(const Point* p);
 bool Contains(const Edge& e);
-bool Contains(Point* p, Point* q);
+bool Contains(const Point* p, const Point* q);
 void Legalize(Point& point);
 void Legalize(Point& opoint, Point& npoint);
 /**
  * Clears all references to all other triangles and points
  */
 void Clear();
-void ClearNeighbor(Triangle *triangle );
+void ClearNeighbor(const Triangle *triangle);
 void ClearNeighbors();
 void ClearDelunayEdges();
 
 inline bool IsInterior();
 inline void IsInterior(bool b);
 
-Triangle& NeighborAcross(Point& opoint);
+Triangle& NeighborAcross(const Point& opoint);
 
 void DebugPrint();
 
@@ -258,7 +258,7 @@ inline bool operator ==(const Point& a, const Point& b)
 
 inline bool operator !=(const Point& a, const Point& b)
 {
-  return a.x != b.x || a.y != b.y;
+  return !(a.x == b.x) && !(a.y == b.y);
 }
 
 /// Peform the dot product on two vectors.
@@ -282,22 +282,22 @@ inline Point Cross(const Point& a, double s)
 
 /// Perform the cross product on a scalar and a point. In 2D this produces
 /// a point.
-inline Point Cross(const double s, const Point& a)
+inline Point Cross(double s, const Point& a)
 {
   return Point(-s * a.y, s * a.x);
 }
 
-inline Point* Triangle::GetPoint(const int& index)
+inline Point* Triangle::GetPoint(int index)
 {
   return points_[index];
 }
 
-inline Triangle* Triangle::GetNeighbor(const int& index)
+inline Triangle* Triangle::GetNeighbor(int index)
 {
   return neighbors_[index];
 }
 
-inline bool Triangle::Contains(Point* p)
+inline bool Triangle::Contains(const Point* p)
 {
   return p == points_[0] || p == points_[1] || p == points_[2];
 }
@@ -307,7 +307,7 @@ inline bool Triangle::Contains(const Edge& e)
   return Contains(e.p) && Contains(e.q);
 }
 
-inline bool Triangle::Contains(Point* p, Point* q)
+inline bool Triangle::Contains(const Point* p, const Point* q)
 {
   return Contains(p) && Contains(q);
 }
@@ -324,6 +324,4 @@ inline void Triangle::IsInterior(bool b)
 
 }
 
-#endif
-
-
+#endif
\ No newline at end of file
index f123fed..2424c71 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  *
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 #ifndef UTILS_H
 #define UTILS_H
 
+// Otherwise #defines like M_PI are undeclared under Visual Studio
+#define _USE_MATH_DEFINES
+
 #include <exception>
+#include <math.h>
+
+// C99 removes M_PI from math.h
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338327
+#endif
 
 namespace p2t {
 
-const double PI = 3.1415926535897932384626433832795029;
-const double PI_2 = 2 * PI;
-const double PI_3div4 = 3 * PI / 4;
-const double EPSILON = 1e-15;
+const double PI_3div4 = 3 * M_PI / 4;
+const double PI_div2 = 1.57079632679489661923;
+const double EPSILON = 1e-12;
 
 enum Orientation { CW, CCW, COLLINEAR };
 
@@ -53,7 +61,7 @@ enum Orientation { CW, CCW, COLLINEAR };
  *              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
  * </pre>
  */
-Orientation Orient2d(Point& pa, Point& pb, Point& pc)
+Orientation Orient2d(const Point& pa, const Point& pb, const Point& pc)
 {
   double detleft = (pa.x - pc.x) * (pb.y - pc.y);
   double detright = (pa.y - pc.y) * (pb.x - pc.x);
@@ -66,6 +74,7 @@ Orientation Orient2d(Point& pa, Point& pb, Point& pc)
   return CW;
 }
 
+/*
 bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
 {
   double pdx = pd.x;
@@ -97,7 +106,22 @@ bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
   return true;
 }
 
+*/
+
+bool InScanArea(const Point& pa, const Point& pb, const Point& pc, const Point& pd)
+{
+  double oadb = (pa.x - pb.x)*(pd.y - pb.y) - (pd.x - pb.x)*(pa.y - pb.y);
+  if (oadb >= -EPSILON) {
+    return false;
+  }
+
+  double oadc = (pa.x - pc.x)*(pd.y - pc.y) - (pd.x - pc.x)*(pa.y - pc.y);
+  if (oadc <= EPSILON) {
+    return false;
+  }
+  return true;
 }
 
-#endif
+}
 
+#endif
index 487755e..29a08d0 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  *
@@ -35,5 +35,4 @@
 #include "common/shapes.h"
 #include "sweep/cdt.h"
 
-#endif
-
+#endif
\ No newline at end of file
index 019df4a..38723be 100644 (file)
@@ -39,7 +39,7 @@ AdvancingFront::AdvancingFront(Node& head, Node& tail)
   search_node_ = &head;
 }
 
-Node* AdvancingFront::LocateNode(const double& x)
+Node* AdvancingFront::LocateNode(double x)
 {
   Node* node = search_node_;
 
@@ -61,7 +61,7 @@ Node* AdvancingFront::LocateNode(const double& x)
   return NULL;
 }
 
-Node* AdvancingFront::FindSearchNode(const double& x)
+Node* AdvancingFront::FindSearchNode(double x)
 {
   (void)x; // suppress compiler warnings "unused parameter 'x'"
   // TODO: implement BST index
@@ -105,5 +105,4 @@ AdvancingFront::~AdvancingFront()
 {
 }
 
-}
-
+}
\ No newline at end of file
index bab73d4..645dcec 100644 (file)
@@ -74,7 +74,7 @@ Node* search();
 void set_search(Node* node);
 
 /// Locate insertion point along advancing front
-Node* LocateNode(const double& x);
+Node* LocateNode(double x);
 
 Node* LocatePoint(const Point* point);
 
@@ -82,7 +82,7 @@ private:
 
 Node* head_, *tail_, *search_node_;
 
-Node* FindSearchNode(const double& x);
+Node* FindSearchNode(double x);
 };
 
 inline Node* AdvancingFront::head()
@@ -115,4 +115,4 @@ inline void AdvancingFront::set_search(Node* node)
 
 }
 
-#endif
+#endif
\ No newline at end of file
index d783825..09d088a 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  *
 
 namespace p2t {
 
-CDT::CDT(std::vector<Point*> polyline)
+CDT::CDT(const std::vector<Point*>& polyline)
 {
   sweep_context_ = new SweepContext(polyline);
   sweep_ = new Sweep;
 }
 
-void CDT::AddHole(std::vector<Point*> polyline)
+void CDT::AddHole(const std::vector<Point*>& polyline)
 {
   sweep_context_->AddHole(polyline);
 }
@@ -68,5 +68,4 @@ CDT::~CDT()
   delete sweep_;
 }
 
-}
-
+}
\ No newline at end of file
index 3e6f024..ea3286d 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  *
@@ -28,7 +28,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 #ifndef CDT_H
 #define CDT_H
 
 #include "sweep.h"
 
 /**
- * 
+ *
  * @author Mason Green <mason.green@gmail.com>
  *
  */
+
 namespace p2t {
 
 class CDT
@@ -50,40 +50,40 @@ public:
 
   /**
    * Constructor - add polyline with non repeating points
-   * 
+   *
    * @param polyline
    */
-  CDT(std::vector<Point*> polyline);
-  
+  CDT(const std::vector<Point*>& polyline);
+
    /**
    * Destructor - clean up memory
    */
   ~CDT();
-  
+
   /**
    * Add a hole
-   * 
+   *
    * @param polyline
    */
-  void AddHole(std::vector<Point*> polyline);
-  
+  void AddHole(const std::vector<Point*>& polyline);
+
   /**
    * Add a steiner point
-   * 
+   *
    * @param point
    */
   void AddPoint(Point* point);
-  
+
   /**
    * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points
    */
   void Triangulate();
-  
+
   /**
    * Get CDT triangles
    */
   std::vector<Triangle*> GetTriangles();
-  
+
   /**
    * Get triangle map
    */
@@ -94,7 +94,7 @@ public:
   /**
    * Internals
    */
-   
+
   SweepContext* sweep_context_;
   Sweep* sweep_;
 
@@ -102,4 +102,4 @@ public:
 
 }
 
-#endif
+#endif
\ No newline at end of file
index ed7c49a..826905c 100644 (file)
@@ -49,7 +49,7 @@ void Sweep::Triangulate(SweepContext& tcx)
 
 void Sweep::SweepPoints(SweepContext& tcx)
 {
-  for (int i = 1; i < tcx.point_count(); i++) {
+  for (size_t i = 1; i < tcx.point_count(); i++) {
     Point& point = *tcx.GetPoint(i);
     Node* node = &PointEvent(tcx, point);
     for (unsigned int i = 0; i < point.edge_list.size(); i++) {
@@ -117,7 +117,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
          throw std::runtime_error("EdgeEvent - collinear points not supported");
     if( triangle->Contains(&eq, p1)) {
       triangle->MarkConstrainedEdge(&eq, p1 );
-      // We are modifying the constraint maybe it would be better to 
+      // We are modifying the constraint maybe it would be better to
       // not change the given constraint and just keep a variable for the new constraint
       tcx.edge_event.constrained_edge->q = p1;
       triangle = &triangle->NeighborAcross(point);
@@ -137,7 +137,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
 
     if( triangle->Contains(&eq, p2)) {
       triangle->MarkConstrainedEdge(&eq, p2 );
-      // We are modifying the constraint maybe it would be better to 
+      // We are modifying the constraint maybe it would be better to
       // not change the given constraint and just keep a variable for the new constraint
       tcx.edge_event.constrained_edge->q = p2;
       triangle = &triangle->NeighborAcross(point);
@@ -166,7 +166,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
 
 bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq)
 {
-  int index = triangle.EdgeIndex(&ep, &eq);
+  const int index = triangle.EdgeIndex(&ep, &eq);
 
   if (index != -1) {
     triangle.MarkConstrainedEdge(index);
@@ -230,8 +230,8 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
   Node* node = n.next;
 
   while (node->next) {
-    double angle = HoleAngle(*node);
-    if (angle > PI_2 || angle < -PI_2) break;
+    // if HoleAngle exceeds 90 degrees then break.
+    if (LargeHole_DontFill(node)) break;
     Fill(tcx, *node);
     node = node->next;
   }
@@ -240,29 +240,81 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
   node = n.prev;
 
   while (node->prev) {
-    double angle = HoleAngle(*node);
-    if (angle > PI_2 || angle < -PI_2) break;
+    // if HoleAngle exceeds 90 degrees then break.
+    if (LargeHole_DontFill(node)) break;
     Fill(tcx, *node);
     node = node->prev;
   }
 
   // Fill right basins
   if (n.next && n.next->next) {
-    double angle = BasinAngle(n);
+    const double angle = BasinAngle(n);
     if (angle < PI_3div4) {
       FillBasin(tcx, n);
     }
   }
 }
 
-double Sweep::BasinAngle(Node& node)
+// True if HoleAngle exceeds 90 degrees.
+bool Sweep::LargeHole_DontFill(const Node* node) const {
+
+  const Node* nextNode = node->next;
+  const Node* prevNode = node->prev;
+  if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point))
+          return false;
+
+  // Check additional points on front.
+  const Node* next2Node = nextNode->next;
+  // "..Plus.." because only want angles on same side as point being added.
+  if ((next2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point))
+          return false;
+
+  const Node* prev2Node = prevNode->prev;
+  // "..Plus.." because only want angles on same side as point being added.
+  if ((prev2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point))
+          return false;
+
+  return true;
+}
+
+bool Sweep::AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const {
+  const double angle = Angle(origin, pa, pb);
+  return ((angle > PI_div2) || (angle < -PI_div2));
+}
+
+bool Sweep::AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const {
+  const double angle = Angle(origin, pa, pb);
+  return (angle > PI_div2) || (angle < 0);
+}
+
+double Sweep::Angle(const Point* origin, const Point* pa, const Point* pb) const {
+  /* Complex plane
+   * ab = cosA +i*sinA
+   * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
+   * atan2(y,x) computes the principal value of the argument function
+   * applied to the complex number x+iy
+   * Where x = ax*bx + ay*by
+   *       y = ax*by - ay*bx
+   */
+  const double px = origin->x;
+  const double py = origin->y;
+  const double ax = pa->x- px;
+  const double ay = pa->y - py;
+  const double bx = pb->x - px;
+  const double by = pb->y - py;
+  const double x = ax * by - ay * bx;
+  const double y = ax * bx + ay * by;
+  return atan2(x, y);
+}
+
+double Sweep::BasinAngle(const Node& node) const
 {
-  double ax = node.point->x - node.next->next->point->x;
-  double ay = node.point->y - node.next->next->point->y;
+  const double ax = node.point->x - node.next->next->point->x;
+  const double ay = node.point->y - node.next->next->point->y;
   return atan2(ay, ax);
 }
 
-double Sweep::HoleAngle(Node& node)
+double Sweep::HoleAngle(const Node& node) const
 {
   /* Complex plane
    * ab = cosA +i*sinA
@@ -272,10 +324,10 @@ double Sweep::HoleAngle(Node& node)
    * Where x = ax*bx + ay*by
    *       y = ax*by - ay*bx
    */
-  double ax = node.next->point->x - node.point->x;
-  double ay = node.next->point->y - node.point->y;
-  double bx = node.prev->point->x - node.point->x;
-  double by = node.prev->point->y - node.point->y;
+  const double ax = node.next->point->x - node.point->x;
+  const double ay = node.next->point->y - node.point->y;
+  const double bx = node.prev->point->x - node.point->x;
+  const double by = node.prev->point->y - node.point->y;
   return atan2(ax * by - ay * bx, ax * bx + ay * by);
 }
 
@@ -340,43 +392,43 @@ bool Sweep::Legalize(SweepContext& tcx, Triangle& t)
   return false;
 }
 
-bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd)
+bool Sweep::Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const
 {
-  double adx = pa.x - pd.x;
-  double ady = pa.y - pd.y;
-  double bdx = pb.x - pd.x;
-  double bdy = pb.y - pd.y;
+  const double adx = pa.x - pd.x;
+  const double ady = pa.y - pd.y;
+  const double bdx = pb.x - pd.x;
+  const double bdy = pb.y - pd.y;
 
-  double adxbdy = adx * bdy;
-  double bdxady = bdx * ady;
-  double oabd = adxbdy - bdxady;
+  const double adxbdy = adx * bdy;
+  const double bdxady = bdx * ady;
+  const double oabd = adxbdy - bdxady;
 
   if (oabd <= 0)
     return false;
 
-  double cdx = pc.x - pd.x;
-  double cdy = pc.y - pd.y;
+  const double cdx = pc.x - pd.x;
+  const double cdy = pc.y - pd.y;
 
-  double cdxady = cdx * ady;
-  double adxcdy = adx * cdy;
-  double ocad = cdxady - adxcdy;
+  const double cdxady = cdx * ady;
+  const double adxcdy = adx * cdy;
+  const double ocad = cdxady - adxcdy;
 
   if (ocad <= 0)
     return false;
 
-  double bdxcdy = bdx * cdy;
-  double cdxbdy = cdx * bdy;
+  const double bdxcdy = bdx * cdy;
+  const double cdxbdy = cdx * bdy;
 
-  double alift = adx * adx + ady * ady;
-  double blift = bdx * bdx + bdy * bdy;
-  double clift = cdx * cdx + cdy * cdy;
+  const double alift = adx * adx + ady * ady;
+  const double blift = bdx * bdx + bdy * bdy;
+  const double clift = cdx * cdx + cdy * cdy;
 
-  double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
+  const double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
 
   return det > 0;
 }
 
-void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op)
+void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const
 {
   Triangle* n1, *n2, *n3, *n4;
   n1 = t.NeighborCCW(p);
@@ -708,11 +760,8 @@ Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op)
   } else if (o2d == CCW) {
     // Left
     return *ot.PointCW(op);
-  } else{
-    //throw new RuntimeException("[Unsupported] Opposing point on constrained edge");
-         // ASSIMP_CHANGE (aramis_acg)
-         throw std::runtime_error("[Unsupported] Opposing point on constrained edge");
   }
+  throw std::runtime_error("[Unsupported] Opposing point on constrained edge");
 }
 
 void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle,
@@ -740,7 +789,7 @@ void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle&
 Sweep::~Sweep() {
 
     // Clean up memory
-    for(unsigned int i = 0; i < nodes_.size(); i++) {
+    for(size_t i = 0; i < nodes_.size(); i++) {
         delete nodes_[i];
     }
 
index bd98adf..33e34a7 100644 (file)
@@ -33,7 +33,7 @@
  * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
  * International Journal of Geographical Information Science
  *
- * "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com
+ * "FlipScan" Constrained Edge Algorithm invented by Thomas ?hl?n, thahlen@gmail.com
  */
 
 #ifndef SWEEP_H
@@ -49,17 +49,17 @@ struct Point;
 struct Edge;
 class Triangle;
 
-class Sweep 
+class Sweep
 {
 public:
 
   /**
    * Triangulate
-   * 
+   *
    * @param tcx
    */
   void Triangulate(SweepContext& tcx);
-  
+
   /**
    * Destructor - clean up memory
    */
@@ -69,7 +69,7 @@ private:
 
   /**
    * Start sweeping the Y-sorted point set from bottom to top
-   * 
+   *
    * @param tcx
    */
   void SweepPoints(SweepContext& tcx);
@@ -86,8 +86,8 @@ private:
   Node& PointEvent(SweepContext& tcx, Point& point);
 
    /**
-     * 
-     * 
+     *
+     *
      * @param tcx
      * @param edge
      * @param node
@@ -98,7 +98,7 @@ private:
 
   /**
    * Creates a new front triangle and legalize it
-   * 
+   *
    * @param tcx
    * @param point
    * @param node
@@ -142,7 +142,7 @@ private:
    * @param d - point opposite a
    * @return true if d is inside circle, false if on circle edge
    */
-  bool Incircle(Point& pa, Point& pb, Point& pc, Point& pd);
+  bool Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const;
 
   /**
    * Rotates a triangle pair one vertex CW
@@ -158,7 +158,7 @@ private:
    *       n4                    n4
    * </pre>
    */
-  void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op);
+  void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const;
 
   /**
    * Fills holes in the Advancing Front
@@ -169,17 +169,24 @@ private:
    */
   void FillAdvancingFront(SweepContext& tcx, Node& n);
 
+  // Decision-making about when to Fill hole.
+  // Contributed by ToolmakerSteve2
+  bool LargeHole_DontFill(const Node* node) const;
+  bool AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const;
+  bool AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const;
+  double Angle(const Point* origin, const Point* pa, const Point* pb) const;
+
   /**
    *
    * @param node - middle node
    * @return the angle between 3 front nodes
    */
-  double HoleAngle(Node& node);
+  double HoleAngle(const Node& node) const;
 
   /**
    * The basin angle is decided against the horizontal line [1,0]
    */
-  double BasinAngle(Node& node);
+  double BasinAngle(const Node& node) const;
 
   /**
    * Fills a basin that has formed on the Advancing Front to the right
@@ -228,22 +235,22 @@ private:
   /**
    * After a flip we have two triangles and know that only one will still be
    * intersecting the edge. So decide which to contiune with and legalize the other
-   * 
+   *
    * @param tcx
    * @param o - should be the result of an orient2d( eq, op, ep )
    * @param t - triangle 1
    * @param ot - triangle 2
-   * @param p - a point shared by both triangles 
+   * @param p - a point shared by both triangles
    * @param op - another point shared by both triangles
    * @return returns the triangle still intersecting the edge
    */
   Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle&  t, Triangle& ot, Point& p, Point& op);
 
    /**
-     * When we need to traverse from one triangle to the next we need 
+     * When we need to traverse from one triangle to the next we need
      * the point in current triangle that is the opposite point to the next
-     * triangle. 
-     * 
+     * triangle.
+     *
      * @param ep
      * @param eq
      * @param ot
@@ -254,10 +261,10 @@ private:
 
    /**
      * Scan part of the FlipScan algorithm<br>
-     * When a triangle pair isn't flippable we will scan for the next 
-     * point that is inside the flip triangle scan area. When found 
+     * When a triangle pair isn't flippable we will scan for the next
+     * point that is inside the flip triangle scan area. When found
      * we generate a new flipEdgeEvent
-     * 
+     *
      * @param tcx
      * @param ep - last point on the edge we are traversing
      * @param eq - first point on the edge we are traversing
@@ -275,4 +282,4 @@ private:
 
 }
 
-#endif
+#endif
\ No newline at end of file
index 184457c..a9f1fdf 100644 (file)
 
 namespace p2t {
 
-SweepContext::SweepContext(std::vector<Point*> polyline)
+SweepContext::SweepContext(const std::vector<Point*>& polyline) : points_(polyline),
+  front_(0),
+  head_(0),
+  tail_(0),
+  af_head_(0),
+  af_middle_(0),
+  af_tail_(0)
 {
-  basin = Basin();
-  edge_event = EdgeEvent();
-
-  points_ = polyline;
-
   InitEdges(points_);
 }
 
-void SweepContext::AddHole(std::vector<Point*> polyline)
+void SweepContext::AddHole(const std::vector<Point*>& polyline)
 {
   InitEdges(polyline);
   for(unsigned int i = 0; i < polyline.size(); i++) {
@@ -56,12 +57,12 @@ void SweepContext::AddPoint(Point* point) {
   points_.push_back(point);
 }
 
-std::vector<Triangle*> SweepContext::GetTriangles()
+std::vector<Triangle*> &SweepContext::GetTriangles()
 {
   return triangles_;
 }
 
-std::list<Triangle*> SweepContext::GetMap()
+std::list<Triangle*> &SweepContext::GetMap()
 {
   return map_;
 }
@@ -94,16 +95,16 @@ void SweepContext::InitTriangulation()
 
 }
 
-void SweepContext::InitEdges(std::vector<Point*> polyline)
+void SweepContext::InitEdges(const std::vector<Point*>& polyline)
 {
-  int num_points = static_cast<int>(polyline.size());
-  for (int i = 0; i < num_points; i++) {
-    int j = i < num_points - 1 ? i + 1 : 0;
+  size_t num_points = polyline.size();
+  for (size_t i = 0; i < num_points; i++) {
+    size_t j = i < num_points - 1 ? i + 1 : 0;
     edge_list.push_back(new Edge(*polyline[i], *polyline[j]));
   }
 }
 
-Point* SweepContext::GetPoint(const int& index)
+Point* SweepContext::GetPoint(size_t index)
 {
   return points_[index];
 }
@@ -113,13 +114,13 @@ void SweepContext::AddToMap(Triangle* triangle)
   map_.push_back(triangle);
 }
 
-Node& SweepContext::LocateNode(Point& point)
+Node& SweepContext::LocateNode(const Point& point)
 {
   // TODO implement search tree
   return *front_->LocateNode(point.x);
 }
 
-void SweepContext::CreateAdvancingFront(std::vector<Node*> nodes)
+void SweepContext::CreateAdvancingFront(const std::vector<Node*>& nodes)
 {
 
   (void) nodes;
@@ -164,12 +165,20 @@ void SweepContext::RemoveFromMap(Triangle* triangle)
 
 void SweepContext::MeshClean(Triangle& triangle)
 {
-  if (!triangle.IsInterior()) {
-    triangle.IsInterior(true);
-    triangles_.push_back(&triangle);
-    for (int i = 0; i < 3; i++) {
-      if (!triangle.constrained_edge[i])
-        MeshClean(*triangle.GetNeighbor(i));
+  std::vector<Triangle *> triangles;
+  triangles.push_back(&triangle);
+
+  while(!triangles.empty()){
+       Triangle *t = triangles.back();
+       triangles.pop_back();
+
+    if (t != NULL && !t->IsInterior()) {
+      t->IsInterior(true);
+      triangles_.push_back(t);
+      for (int i = 0; i < 3; i++) {
+        if (!t->constrained_edge[i])
+          triangles.push_back(t->GetNeighbor(i));
+      }
     }
   }
 }
index 2f7d8e9..ba0d065 100644 (file)
@@ -52,47 +52,47 @@ class SweepContext {
 public:
 
 /// Constructor
-SweepContext(std::vector<Point*> polyline);
+SweepContext(const std::vector<Point*>& polyline);
 /// Destructor
 ~SweepContext();
 
 void set_head(Point* p1);
 
-Point* head();
+Point* head() const;
 
 void set_tail(Point* p1);
 
-Point* tail();
+Point* tail() const;
 
-int point_count();
+size_t point_count() const;
 
-Node& LocateNode(Point& point);
+Node& LocateNode(const Point& point);
 
 void RemoveNode(Node* node);
 
-void CreateAdvancingFront(std::vector<Node*> nodes);
+void CreateAdvancingFront(const std::vector<Node*>& nodes);
 
 /// Try to map a node to all sides of this triangle that don't have a neighbor
 void MapTriangleToNodes(Triangle& t);
 
 void AddToMap(Triangle* triangle);
 
-Point* GetPoint(const int& index);
+Point* GetPoint(size_t index);
 
 Point* GetPoints();
 
 void RemoveFromMap(Triangle* triangle);
 
-void AddHole(std::vector<Point*> polyline);
+void AddHole(const std::vector<Point*>& polyline);
 
 void AddPoint(Point* point);
 
-AdvancingFront* front();
+AdvancingFront* front() const;
 
 void MeshClean(Triangle& triangle);
 
-std::vector<Triangle*> GetTriangles();
-std::list<Triangle*> GetMap();
+std::vector<Triangle*> &GetTriangles();
+std::list<Triangle*> &GetMap();
 
 std::vector<Edge*> edge_list;
 
@@ -147,18 +147,18 @@ Point* tail_;
 Node *af_head_, *af_middle_, *af_tail_;
 
 void InitTriangulation();
-void InitEdges(std::vector<Point*> polyline);
+void InitEdges(const std::vector<Point*>& polyline);
 
 };
 
-inline AdvancingFront* SweepContext::front()
+inline AdvancingFront* SweepContext::front() const
 {
   return front_;
 }
 
-inline int SweepContext::point_count()
+inline size_t SweepContext::point_count() const
 {
-  return static_cast<int>(points_.size());
+  return points_.size();
 }
 
 inline void SweepContext::set_head(Point* p1)
@@ -166,7 +166,7 @@ inline void SweepContext::set_head(Point* p1)
   head_ = p1;
 }
 
-inline Point* SweepContext::head()
+inline Point* SweepContext::head() const
 {
   return head_;
 }
@@ -176,7 +176,7 @@ inline void SweepContext::set_tail(Point* p1)
   tail_ = p1;
 }
 
-inline Point* SweepContext::tail()
+inline Point* SweepContext::tail() const
 {
   return tail_;
 }