浏览代码

Merge remote-tracking branch 'github/master' into contrib

Leo Terziman 8 年之前
父节点
当前提交
4974c99288
共有 50 个文件被更改,包括 4245 次插入2084 次删除
  1. 2 1
      .travis.sh
  2. 18 23
      .travis.yml
  3. 11 0
      CMakeLists.txt
  4. 12 19
      code/Assimp.cpp
  5. 12 4
      code/ColladaLoader.cpp
  6. 90 5
      code/IOStreamBuffer.h
  7. 34 23
      code/ObjFileParser.cpp
  8. 2 2
      code/ObjFileParser.h
  9. 5 3
      code/ObjTools.h
  10. 855 911
      code/PlyLoader.cpp
  11. 14 47
      code/PlyLoader.h
  12. 930 754
      code/PlyParser.cpp
  13. 39 56
      code/PlyParser.h
  14. 3 3
      code/STLLoader.cpp
  15. 2 3
      code/SpatialSort.cpp
  16. 10 3
      code/fast_atof.h
  17. 23 31
      contrib/poly2tri/poly2tri/common/shapes.cc
  18. 29 31
      contrib/poly2tri/poly2tri/common/shapes.h
  19. 32 8
      contrib/poly2tri/poly2tri/common/utils.h
  20. 2 3
      contrib/poly2tri/poly2tri/poly2tri.h
  21. 3 4
      contrib/poly2tri/poly2tri/sweep/advancing_front.cc
  22. 3 3
      contrib/poly2tri/poly2tri/sweep/advancing_front.h
  23. 4 5
      contrib/poly2tri/poly2tri/sweep/cdt.cc
  24. 17 17
      contrib/poly2tri/poly2tri/sweep/cdt.h
  25. 91 42
      contrib/poly2tri/poly2tri/sweep/sweep.cc
  26. 28 21
      contrib/poly2tri/poly2tri/sweep/sweep.h
  27. 31 22
      contrib/poly2tri/poly2tri/sweep/sweep_context.cc
  28. 17 17
      contrib/poly2tri/poly2tri/sweep/sweep_context.h
  29. 0 2
      include/assimp/color4.inl
  30. 4 3
      include/assimp/matrix4x4.h
  31. 1 4
      port/PyAssimp/pyassimp/helper.py
  32. 1 3
      port/PyAssimp/setup.py
  33. 28 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11.sln
  34. 102 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h
  35. 205 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp
  36. 44 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h
  37. 9 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/PixelShader.hlsl
  38. 146 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj
  39. 50 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj.filters
  40. 691 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.cpp
  41. 55 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.h
  42. 23 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/VertexShader.hlsl
  43. 518 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp
  44. 28 4
      test/unit/utObjTools.cpp
  45. 3 2
      test/unit/utPMXImporter.cpp
  46. 2 0
      tools/assimp_view/Display.cpp
  47. 2 0
      tools/assimp_view/LogWindow.cpp
  48. 2 0
      tools/assimp_view/MessageProc.cpp
  49. 11 5
      tools/assimp_view/SceneAnimator.h
  50. 1 0
      tools/assimp_view/assimp_view.cpp

+ 2 - 1
.travis.sh

@@ -5,7 +5,8 @@ function generate()
 
 
 if [ $ANDROID ]; then
 if [ $ANDROID ]; then
     ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni
     ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni
-else
+fi
+if [ "$TRAVIS_OS_NAME" = "linux" ]; then
     generate \
     generate \
     && make -j4 \
     && make -j4 \
     && sudo make install \
     && sudo make install \

+ 18 - 23
.travis.yml

@@ -1,22 +1,18 @@
+language: cpp
+
 before_install:
 before_install:
-  - sudo apt-get update -qq
-  - sudo apt-get install cmake
-  - sudo apt-get install cmake python3
-  - if [ $LINUX ]; then sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; fi
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; fi
+  - if [ "$TRAVIS_OS_NAME" =   "osx" ]; then brew install cmake python3 homebrew/x11/freeglut; fi
   - echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
   - echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
   # install latest LCOV (1.9 was failing)
   # install latest LCOV (1.9 was failing)
-  - cd ${TRAVIS_BUILD_DIR}
-  - wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz
-  - tar xf lcov_1.11.orig.tar.gz
-  - sudo make -C lcov-1.11/ install
-  - gem install coveralls-lcov
-  - lcov --version
-  - g++ --version
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz && tar xf lcov_1.11.orig.tar.gz && sudo make -C lcov-1.11/ install && gem install coveralls-lcov && lcov --version && g++ --version ; fi
 
 
 branches:
 branches:
   only:
   only:
     - master
     - master
 
 
+osx_image: xcode8.3
+
 env:
 env:
   global:
   global:
     - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
     - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
@@ -26,10 +22,11 @@ env:
     - LINUX=1 TRAVIS_NO_EXPORT=NO  ENABLE_COVERALLS=OFF
     - LINUX=1 TRAVIS_NO_EXPORT=NO  ENABLE_COVERALLS=OFF
     - LINUX=1 SHARED_BUILD=ON      ENABLE_COVERALLS=OFF
     - LINUX=1 SHARED_BUILD=ON      ENABLE_COVERALLS=OFF
     - LINUX=1 SHARED_BUILD=OFF     ENABLE_COVERALLS=OFF
     - LINUX=1 SHARED_BUILD=OFF     ENABLE_COVERALLS=OFF
-    - ANDROID=1
-
-language: cpp
-  
+    #exclude:
+    #    - os: linux
+    #      compiler: clang
+    #    - os: osx
+    #      compiler: gcc  
 compiler:
 compiler:
   - gcc
   - gcc
   - clang
   - clang
@@ -38,21 +35,19 @@ install:
   - if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi
   - if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi
 
 
 before_script:
 before_script:
-  - cd ${TRAVIS_BUILD_DIR}
   # init coverage to 0 (optional)
   # init coverage to 0 (optional)
-  - lcov --directory . --zerocounters
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --zerocounters ; fi
 
 
 script:
 script:
   - export COVERALLS_SERVICE_NAME=travis-ci
   - export COVERALLS_SERVICE_NAME=travis-ci
   - export COVERALLS_REPO_TOKEN=abc12345
   - export COVERALLS_REPO_TOKEN=abc12345
   - . ./.travis.sh
   - . ./.travis.sh
-
+os:
+  - linux
+  - osx
+ 
 after_success:
 after_success:
-  - cd ${TRAVIS_BUILD_DIR}
-  - lcov --directory . --capture --output-file coverage.info
-  - lcov --remove coverage.info '/usr/*' 'contrib/*' 'test/*' --output-file coverage.info
-  - lcov --list coverage.info
-  - coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --capture --output-file coverage.info && lcov --remove coverage.info '/usr/*' 'contrib/*' 'test/*' --output-file coverage.info && lcov --list coverage.info && coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info ; fi
 
 
 addons:
 addons:
   coverity_scan:
   coverity_scan:

+ 11 - 0
CMakeLists.txt

@@ -89,6 +89,10 @@ OPTION ( BUILD_DOCS
    OFF
    OFF
 )
 )
 
 
+if (WIN32)
+    add_definitions( -DWIN32_LEAN_AND_MEAN )
+endif()
+
 IF(MSVC)
 IF(MSVC)
   set (CMAKE_PREFIX_PATH "D:\\libs\\devil")
   set (CMAKE_PREFIX_PATH "D:\\libs\\devil")
   OPTION( ASSIMP_INSTALL_PDB
   OPTION( ASSIMP_INSTALL_PDB
@@ -141,6 +145,13 @@ IF(ASSIMP_DOUBLE_PRECISION)
   ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
   ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
 ENDIF(ASSIMP_DOUBLE_PRECISION)
 ENDIF(ASSIMP_DOUBLE_PRECISION)
 
 
+# Check for OpenMP support
+find_package(OpenMP)
+if (OPENMP_FOUND)
+    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
+endif()
+
 configure_file(
 configure_file(
   ${CMAKE_CURRENT_LIST_DIR}/revision.h.in
   ${CMAKE_CURRENT_LIST_DIR}/revision.h.in
   ${CMAKE_CURRENT_BINARY_DIR}/revision.h
   ${CMAKE_CURRENT_BINARY_DIR}/revision.h

+ 12 - 19
code/Assimp.cpp

@@ -66,8 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 using namespace Assimp;
 using namespace Assimp;
 
 
-namespace Assimp
-{
+namespace Assimp {
     // underlying structure for aiPropertyStore
     // underlying structure for aiPropertyStore
     typedef BatchLoader::PropertyMap PropertyMap;
     typedef BatchLoader::PropertyMap PropertyMap;
 
 
@@ -110,12 +109,11 @@ static std::mutex gLogStreamMutex;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Custom LogStream implementation for the C-API
 // Custom LogStream implementation for the C-API
-class LogToCallbackRedirector : public LogStream
-{
+class LogToCallbackRedirector : public LogStream {
 public:
 public:
     explicit LogToCallbackRedirector(const aiLogStream& s)
     explicit LogToCallbackRedirector(const aiLogStream& s)
-        : stream (s)    {
-            ai_assert(NULL != s.callback);
+    : stream (s)    {
+        ai_assert(NULL != s.callback);
     }
     }
 
 
     ~LogToCallbackRedirector()  {
     ~LogToCallbackRedirector()  {
@@ -146,8 +144,7 @@ private:
 };
 };
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void ReportSceneNotFoundError()
-{
+void ReportSceneNotFoundError() {
     DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. "
     DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. "
         "The C-API does not accept scenes produced by the C++ API and vice versa");
         "The C-API does not accept scenes produced by the C++ API and vice versa");
 
 
@@ -156,22 +153,18 @@ void ReportSceneNotFoundError()
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Reads the given file and returns its content.
 // Reads the given file and returns its content.
-const aiScene* aiImportFile( const char* pFile, unsigned int pFlags)
-{
+const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) {
     return aiImportFileEx(pFile,pFlags,NULL);
     return aiImportFileEx(pFile,pFlags,NULL);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags,  aiFileIO* pFS)
-{
+const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags,  aiFileIO* pFS) {
     return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
     return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
-    aiFileIO* pFS,
-    const aiPropertyStore* props)
-{
+const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags, 
+        aiFileIO* pFS, const aiPropertyStore* props) {
     ai_assert(NULL != pFile);
     ai_assert(NULL != pFile);
 
 
     const aiScene* scene = NULL;
     const aiScene* scene = NULL;
@@ -190,7 +183,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
         pimpl->mMatrixProperties = pp->matrices;
         pimpl->mMatrixProperties = pp->matrices;
     }
     }
     // setup a custom IO system if necessary
     // setup a custom IO system if necessary
-    if (pFS)    {
+    if (pFS) {
         imp->SetIOHandler( new CIOSystemWrapper (pFS) );
         imp->SetIOHandler( new CIOSystemWrapper (pFS) );
     }
     }
 
 
@@ -201,8 +194,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
     if( scene)  {
     if( scene)  {
         ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
         ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
         priv->mOrigImporter = imp;
         priv->mOrigImporter = imp;
-    }
-    else    {
+    } else {
         // if failed, extract error code and destroy the import
         // if failed, extract error code and destroy the import
         gLastErrorString = imp->GetErrorString();
         gLastErrorString = imp->GetErrorString();
         delete imp;
         delete imp;
@@ -210,6 +202,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
 
 
     // return imported data. If the import failed the pointer is NULL anyways
     // return imported data. If the import failed the pointer is NULL anyways
     ASSIMP_END_EXCEPTION_REGION(const aiScene*);
     ASSIMP_END_EXCEPTION_REGION(const aiScene*);
+    
     return scene;
     return scene;
 }
 }
 
 

+ 12 - 4
code/ColladaLoader.cpp

@@ -1726,6 +1726,8 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
 aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser,
 aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser,
     const Collada::Effect& pEffect, const std::string& pName)
     const Collada::Effect& pEffect, const std::string& pName)
 {
 {
+    aiString result;
+
     // recurse through the param references until we end up at an image
     // recurse through the param references until we end up at an image
     std::string name = pName;
     std::string name = pName;
     while( 1)
     while( 1)
@@ -1744,11 +1746,17 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
     ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
     ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
     if( imIt == pParser.mImageLibrary.end())
     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 this is an embedded texture image setup an aiTexture for it
     if (imIt->second.mFileName.empty())
     if (imIt->second.mFileName.empty())

+ 90 - 5
code/IOStreamBuffer.h

@@ -45,6 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOStream.hpp>
 #include <assimp/IOStream.hpp>
 #include "ParsingUtils.h"
 #include "ParsingUtils.h"
 
 
+#include <vector>
+
 namespace Assimp {
 namespace Assimp {
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -69,8 +71,8 @@ public:
     /// @return true if successful.
     /// @return true if successful.
     bool close();
     bool close();
 
 
-    /// @brief  Returns the filesize.
-    /// @return The filesize.
+    /// @brief  Returns the file-size.
+    /// @return The file-size.
     size_t size() const;
     size_t size() const;
     
     
     /// @brief  Returns the cache size.
     /// @brief  Returns the cache size.
@@ -96,7 +98,17 @@ public:
     /// @brief  Will read the next line.
     /// @brief  Will read the next line.
     /// @param  buffer      The buffer for the next line.
     /// @param  buffer      The buffer for the next line.
     /// @return true if successful.
     /// @return true if successful.
-    bool getNextLine( std::vector<T> &buffer );
+    bool getNextDataLine( std::vector<T> &buffer, T continuationToken );
+
+    /// @brief  Will read the next line ascii or binary end line char.
+    /// @param  buffer      The buffer for the next line.
+    /// @return true if successful.
+    bool getNextLine(std::vector<T> &buffer);
+
+    /// @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:
 private:
     IOStream *m_stream;
     IOStream *m_stream;
@@ -227,15 +239,35 @@ size_t IOStreamBuffer<T>::getFilePos() const {
 
 
 template<class T>
 template<class T>
 inline
 inline
-bool IOStreamBuffer<T>::getNextLine( std::vector<T> &buffer ) {
+bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationToken ) {
     buffer.resize( m_cacheSize );
     buffer.resize( m_cacheSize );
     if ( m_cachePos == m_cacheSize || 0 == m_filePos ) {
     if ( m_cachePos == m_cacheSize || 0 == m_filePos ) {
         if ( !readNextBlock() ) {
         if ( !readNextBlock() ) {
             return false;
             return false;
         }
         }
     }
     }
+
+    bool continuationFound( false ), endOfDataLine( false );
     size_t i = 0;
     size_t i = 0;
-    while ( !IsLineEnd( m_cache[ m_cachePos ] ) ) {
+    while ( !endOfDataLine ) {
+        if ( continuationToken == m_cache[ m_cachePos ] ) {
+            continuationFound = true;
+            ++m_cachePos;
+        }
+        if ( IsLineEnd( m_cache[ m_cachePos ] ) ) {
+            if ( !continuationFound ) {
+                // the end of the data line
+                break;
+            } else {
+                // skip line end
+                while ( m_cache[m_cachePos] != '\n') {
+                    ++m_cachePos;
+                }
+                ++m_cachePos;
+                continuationFound = false;
+            }
+        }
+
         buffer[ i ] = m_cache[ m_cachePos ];
         buffer[ i ] = m_cache[ m_cachePos ];
         m_cachePos++;
         m_cachePos++;
         i++;
         i++;
@@ -245,10 +277,63 @@ bool IOStreamBuffer<T>::getNextLine( std::vector<T> &buffer ) {
             }
             }
         }
         }
     }
     }
+    
     buffer[ i ] = '\n';
     buffer[ i ] = '\n';
     m_cachePos++;
     m_cachePos++;
 
 
     return true;
     return true;
 }
 }
 
 
+template<class T>
+inline
+bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) {
+    buffer.resize(m_cacheSize);
+    if (m_cachePos == m_cacheSize || 0 == m_filePos) {
+       if (!readNextBlock()) {
+          return false;
+       }
+      }
+
+    if (IsLineEnd(m_cache[m_cachePos])) {
+        // skip line end
+        while (m_cache[m_cachePos] != '\n') {
+            ++m_cachePos;
+        }
+        ++m_cachePos;
+    }
+
+    size_t i = 0;
+    while (!IsLineEnd(m_cache[m_cachePos])) {
+        buffer[i] = m_cache[m_cachePos];
+        m_cachePos++;
+        i++;
+        if (m_cachePos >= m_cacheSize) {
+            if (!readNextBlock()) {
+                return false;
+            }
+        }
+    }
+    buffer[i] = '\n';
+    m_cachePos++;
+
+    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
 } // !ns Assimp

+ 34 - 23
code/ObjFileParser.cpp

@@ -109,7 +109,7 @@ ObjFile::Model *ObjFileParser::GetModel() const {
     return m_pModel;
     return m_pModel;
 }
 }
 
 
-void ignoreNewLines(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer)
+/*void ignoreNewLines(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer)
 {
 {
     auto curPosition = buffer.begin();
     auto curPosition = buffer.begin();
     do
     do
@@ -123,13 +123,13 @@ void ignoreNewLines(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffe
             std::vector<char> tempBuf;
             std::vector<char> tempBuf;
             do
             do
             {
             {
-                streamBuffer.getNextLine(tempBuf);
+                streamBuffer.getNextDataLine(tempBuf, '\\' );
             } while (tempBuf[0]=='\n');
             } while (tempBuf[0]=='\n');
             *curPosition = ' ';
             *curPosition = ' ';
             std::copy(tempBuf.cbegin(), tempBuf.cend(), ++curPosition);
             std::copy(tempBuf.cbegin(), tempBuf.cend(), ++curPosition);
         }
         }
     } while (*curPosition!='\n');
     } while (*curPosition!='\n');
-}
+}*/
 
 
 void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
 void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
     // only update every 100KB or it'll be too slow
     // only update every 100KB or it'll be too slow
@@ -142,7 +142,7 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
     size_t lastFilePos( 0 );
     size_t lastFilePos( 0 );
 
 
     std::vector<char> buffer;
     std::vector<char> buffer;
-    while ( streamBuffer.getNextLine( buffer ) ) {
+    while ( streamBuffer.getNextDataLine( buffer, '\\' ) ) {
         m_DataIt = buffer.begin();
         m_DataIt = buffer.begin();
         m_DataItEnd = buffer.end();
         m_DataItEnd = buffer.end();
 
 
@@ -154,14 +154,14 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
             progressCounter++;
             progressCounter++;
             m_progress->UpdateFileRead( progressOffset + processed * 2, progressTotal );
             m_progress->UpdateFileRead( progressOffset + processed * 2, progressTotal );
         }
         }
-		//ignoreNewLines(streamBuffer, buffer);
+
         // parse line
         // parse line
         switch (*m_DataIt) {
         switch (*m_DataIt) {
         case 'v': // Parse a vertex texture coordinate
         case 'v': // Parse a vertex texture coordinate
             {
             {
                 ++m_DataIt;
                 ++m_DataIt;
                 if (*m_DataIt == ' ' || *m_DataIt == '\t') {
                 if (*m_DataIt == ' ' || *m_DataIt == '\t') {
-                    size_t numComponents = getNumComponentsInLine();
+                    size_t numComponents = getNumComponentsInDataDefinition();
                     if (numComponents == 3) {
                     if (numComponents == 3) {
                         // read in vertex definition
                         // read in vertex definition
                         getVector3(m_pModel->m_Vertices);
                         getVector3(m_pModel->m_Vertices);
@@ -245,7 +245,6 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
         default:
         default:
             {
             {
 pf_skip_line:
 pf_skip_line:
-
                 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
                 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
             }
             }
             break;
             break;
@@ -274,21 +273,44 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length) {
     pBuffer[index] = '\0';
     pBuffer[index] = '\0';
 }
 }
 
 
-size_t ObjFileParser::getNumComponentsInLine() {
+static bool isDataDefinitionEnd( const char *tmp ) {
+    if ( *tmp == '\\' ) {
+        tmp++;
+        if ( IsLineEnd( *tmp ) ) {
+            tmp++;
+            return true;
+        }
+    }
+    return false;
+}
+
+size_t ObjFileParser::getNumComponentsInDataDefinition() {
     size_t numComponents( 0 );
     size_t numComponents( 0 );
     const char* tmp( &m_DataIt[0] );
     const char* tmp( &m_DataIt[0] );
-    while( !IsLineEnd( *tmp ) ) {        
+    bool end_of_definition = false;
+    while ( !end_of_definition ) {
+        if ( isDataDefinitionEnd( tmp ) ) {
+            tmp += 2;
+        } else if ( IsLineEnd( *tmp ) ) {
+            end_of_definition = true;
+        }
         if ( !SkipSpaces( &tmp ) ) {
         if ( !SkipSpaces( &tmp ) ) {
             break;
             break;
         }
         }
+        const bool isNum( IsNumeric( *tmp ) );
         SkipToken( tmp );
         SkipToken( tmp );
-        ++numComponents;
+        if ( isNum ) {
+            ++numComponents;
+        }
+        if ( !SkipSpaces( &tmp ) ) {
+            break;
+        }
     }
     }
     return numComponents;
     return numComponents;
 }
 }
 
 
 void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
 void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
-    size_t numComponents = getNumComponentsInLine();
+    size_t numComponents = getNumComponentsInDataDefinition();
     ai_real x, y, z;
     ai_real x, y, z;
     if( 2 == numComponents ) {
     if( 2 == numComponents ) {
         copyNextWord( m_buffer, Buffersize );
         copyNextWord( m_buffer, Buffersize );
@@ -397,10 +419,6 @@ static const std::string DefaultObjName = "defaultobject";
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //  Get values for a new face instance
 //  Get values for a new face instance
 void ObjFileParser::getFace( aiPrimitiveType type ) {
 void ObjFileParser::getFace( aiPrimitiveType type ) {
-    //copyNextLine(m_buffer, Buffersize);
-    //char *pPtr = m_DataIt;
-    //char *pPtr = m_buffer;
-    //char *pEnd = &pPtr[Buffersize];
     m_DataIt = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd );
     m_DataIt = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd );
     if ( m_DataIt == m_DataItEnd || *m_DataIt == '\0' ) {
     if ( m_DataIt == m_DataItEnd || *m_DataIt == '\0' ) {
         return;
         return;
@@ -571,14 +589,7 @@ void ObjFileParser::getMaterialDesc() {
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //  Get a comment, values will be skipped
 //  Get a comment, values will be skipped
 void ObjFileParser::getComment() {
 void ObjFileParser::getComment() {
-    while (m_DataIt != m_DataItEnd) {
-        if ( '\n' == (*m_DataIt)) {
-            ++m_DataIt;
-            break;
-        } else {
-            ++m_DataIt;
-        }
-    }
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------

+ 2 - 2
code/ObjFileParser.h

@@ -91,6 +91,8 @@ protected:
     void copyNextWord(char *pBuffer, size_t length);
     void copyNextWord(char *pBuffer, size_t length);
     /// Method to copy the new line.
     /// Method to copy the new line.
 //    void copyNextLine(char *pBuffer, size_t length);
 //    void copyNextLine(char *pBuffer, size_t length);
+    /// Get the number of components in a line.
+    size_t getNumComponentsInDataDefinition();
     /// Stores the vector
     /// Stores the vector
     void getVector( std::vector<aiVector3D> &point3d_array );
     void getVector( std::vector<aiVector3D> &point3d_array );
     /// Stores the following 3d vector.
     /// Stores the following 3d vector.
@@ -129,8 +131,6 @@ protected:
     bool needsNewMesh( const std::string &rMaterialName );
     bool needsNewMesh( const std::string &rMaterialName );
     /// Error report in token
     /// Error report in token
     void reportErrorTokenInFace();
     void reportErrorTokenInFace();
-    /// Get the number of components in a line.
-    size_t getNumComponentsInLine();
 
 
 private:
 private:
     // Copy and assignment constructor should be private
     // Copy and assignment constructor should be private

+ 5 - 3
code/ObjTools.h

@@ -116,14 +116,16 @@ inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) {
     while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
     while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
         ++it;
         ++it;
     }
     }
-    if ( it != end )
-    {
+    
+    if ( it != end ) {
         ++it;
         ++it;
         ++uiLine;
         ++uiLine;
     }
     }
     // fix .. from time to time there are spaces at the beginning of a material line
     // fix .. from time to time there are spaces at the beginning of a material line
-    while ( it != end && (*it == '\t' || *it == ' ') )
+    while ( it != end && ( *it == '\t' || *it == ' ' ) ) {
         ++it;
         ++it;
+    }
+
     return it;
     return it;
 }
 }
 
 

+ 855 - 911
code/PlyLoader.cpp

@@ -5,7 +5,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2017, assimp team
 Copyright (c) 2006-2017, assimp team
 
 
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 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:
 conditions are met:
 
 
 * Redistributions of source code must retain the above
 * 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
 * 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
 * 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
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 "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
 // internal headers
 #include "PlyLoader.h"
 #include "PlyLoader.h"
+#include "IOStreamBuffer.h"
 #include "Macros.h"
 #include "Macros.h"
 #include <memory>
 #include <memory>
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>
@@ -57,16 +57,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using namespace Assimp;
 using namespace Assimp;
 
 
 static const aiImporterDesc desc = {
 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,984 @@ static const aiImporterDesc desc = {
 // Internal stuff
 // Internal stuff
 namespace
 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
 // Constructor to be privately used by Importer
 PLYImporter::PLYImporter()
 PLYImporter::PLYImporter()
-: mBuffer()
-, pcDOM(){
-    // empty
+  : mBuffer()
+  , pcDOM()
+  , mGeneratedMesh(NULL){
+  // empty
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
 PLYImporter::~PLYImporter() {
 PLYImporter::~PLYImporter() {
-    // empty
+  // empty
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // 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 (defined AI_BUILD_BIG_ENDIAN)
-    if ( 'l' == *szMe || 'L' == *szMe ) {
-        isBigEndian = true;
-}
+  if ( 'l' == *szMe || 'L' == *szMe ) {
+    isBigEndian = true;
+  }
 #else
 #else
-    if ( 'b' == *szMe || 'B' == *szMe ) {
-        isBigEndian = true;
-    }
+  if ('b' == *szMe || 'B' == *szMe) {
+    isBigEndian = true;
+  }
 #endif // ! AI_BUILD_BIG_ENDIAN
 #endif // ! AI_BUILD_BIG_ENDIAN
 
 
-    return isBigEndian;
+  return isBigEndian;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
 // 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.getNextLine(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.getNextLine(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);
+
+    //generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color
+    aiColor3D clr;
+    clr.b = clr.g = clr.r = 1.0f;
+    pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
+    pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
+
+    clr.b = clr.g = clr.r = 1.0f;
+    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
 #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER

+ 14 - 47
code/PlyLoader.h

@@ -68,7 +68,6 @@ public:
     PLYImporter();
     PLYImporter();
     ~PLYImporter();
     ~PLYImporter();
 
 
-
 public:
 public:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
@@ -78,6 +77,16 @@ public:
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
         bool checkSig) const;
         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:
 protected:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
@@ -94,53 +103,10 @@ protected:
         IOSystem* pIOHandler);
         IOSystem* pIOHandler);
 
 
 protected:
 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
     /** 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
     /** Static helper to parse a color from four single channels in
@@ -151,7 +117,6 @@ protected:
         PLY::EDataType aiTypes[4],
         PLY::EDataType aiTypes[4],
         aiColor4D* clrOut);
         aiColor4D* clrOut);
 
 
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Static helper to parse a color channel value. The input value
     /** Static helper to parse a color channel value. The input value
     *  is normalized to 0-1.
     *  is normalized to 0-1.
@@ -160,12 +125,14 @@ protected:
         PLY::PropertyInstance::ValueUnion val,
         PLY::PropertyInstance::ValueUnion val,
         PLY::EDataType eType);
         PLY::EDataType eType);
 
 
-
     /** Buffer to hold the loaded file */
     /** Buffer to hold the loaded file */
     unsigned char* mBuffer;
     unsigned char* mBuffer;
 
 
     /** Document object model representation extracted from the file */
     /** Document object model representation extracted from the file */
     PLY::DOM* pcDOM;
     PLY::DOM* pcDOM;
+
+    /** Mesh generated by loader */
+    aiMesh* mGeneratedMesh;
 };
 };
 
 
 } // end of namespace Assimp
 } // end of namespace Assimp

+ 930 - 754
code/PlyParser.cpp

@@ -5,7 +5,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2017, assimp team
 Copyright (c) 2006-2017, assimp team
 
 
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 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:
 conditions are met:
 
 
 * Redistributions of source code must retain the above
 * 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
 * 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
 * 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
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 "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
 #ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
 
 
-#include "PlyLoader.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/DefaultLogger.hpp>
 #include "ByteSwapper.h"
 #include "ByteSwapper.h"
-
+#include "PlyLoader.h"
 
 
 using namespace Assimp;
 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) || PLY::DOM::TokenMatch(buffer, "texture_u", 9))
+  {
+    eOut = PLY::EST_UTextureCoord;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "v", 1) || PLY::DOM::TokenMatch(buffer, "t", 1) || PLY::DOM::TokenMatch(buffer, "ty", 2) || PLY::DOM::TokenMatch(buffer, "texture_v", 9))
+  {
+    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
 #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
 #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.getNextLine(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 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.getNextLine(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
     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.getNextLine(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.getNextLine(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.getNextLine(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.getNextLine(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.getNextLine(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
     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
 #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER

+ 39 - 56
code/PlyParser.h

@@ -3,7 +3,6 @@ Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
 Copyright (c) 2006-2017, assimp team
 Copyright (c) 2006-2017, assimp team
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 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 "ParsingUtils.h"
+#include "IOStreamBuffer.h"
 #include <vector>
 #include <vector>
 
 
-
 namespace Assimp
 namespace Assimp
 {
 {
 
 
+//pre-declaration
+class PLYImporter;
+
 // http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/
 // 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://w3.impa.br/~lvelho/outgoing/sossai/old/ViHAP_D4.4.2_PLY_format_v1.1.pdf
 // http://www.okino.com/conv/exp_ply.htm
 // http://www.okino.com/conv/exp_ply.htm
 namespace PLY
 namespace PLY
 {
 {
 
 
-
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 /*
 /*
 name        type        number of bytes
 name        type        number of bytes
@@ -197,6 +198,9 @@ enum EElementSemantic
     //! The element is a material description
     //! The element is a material description
     EEST_Material,
     EEST_Material,
 
 
+    //! texture path
+    EEST_TextureFile,
+
     //! Marks invalid entries
     //! Marks invalid entries
     EEST_INVALID
     EEST_INVALID
 };
 };
@@ -238,16 +242,15 @@ public:
     //! string is either '\n', '\r' or '\0'. Return value is false
     //! string is either '\n', '\r' or '\0'. Return value is false
     //! if the input string is NOT a valid property (E.g. does
     //! if the input string is NOT a valid property (E.g. does
     //! not start with the "property" keyword)
     //! 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
     //! 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
     //! 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.
     //! Parse an element from a string.
     //! The function will parse all properties contained in the
     //! The function will parse all properties contained in the
     //! element, too.
     //! 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
     //! 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
     //! 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);
         const Property* prop, PropertyInstance* p_pcOut);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a property instance in binary format
     //! 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
     //! Get the default value for a given data type
@@ -345,13 +346,12 @@ public:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a value
     //! 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
     //! 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
     //! Convert a property value to a given type TYPE
@@ -375,13 +375,13 @@ public:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse an element instance
     //! 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);
         const Element* pcElement, ElementInstance* p_pcOut);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a binary element instance
     //! 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
     //! 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
     //! 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
 /** \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
     //! Parse the DOM for a PLY file. The input string is assumed
     //! to be terminated with zero
     //! 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
     //! 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:
 private:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Handle the file header and read all element descriptions
     //! 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
     //! 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
     //! 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);
 };
 };
 
 
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------

+ 3 - 3
code/STLLoader.cpp

@@ -211,20 +211,20 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
     for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
     for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
         pScene->mRootNode->mMeshes[i] = 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).
     // other geometric types (e.g., PLY).
     aiMaterial* pcMat = new aiMaterial();
     aiMaterial* pcMat = new aiMaterial();
     aiString s;
     aiString s;
     s.Set(AI_DEFAULT_MATERIAL_NAME);
     s.Set(AI_DEFAULT_MATERIAL_NAME);
     pcMat->AddProperty(&s, AI_MATKEY_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) {
     if (bMatClr) {
         clrDiffuse = clrColorDefault;
         clrDiffuse = clrColorDefault;
     }
     }
     pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
     pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
     pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
     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);
     pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
 
 
     pScene->mNumMaterials = 1;
     pScene->mNumMaterials = 1;

+ 2 - 3
code/SpatialSort.cpp

@@ -126,9 +126,8 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
     const ai_real dist = pPosition * mPlaneNormal;
     const ai_real dist = pPosition * mPlaneNormal;
     const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
     const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
 
 
-    // clear the array in this strange fashion because a simple clear() would also deallocate
-    // the array which we want to avoid
-    poResults.erase( poResults.begin(), poResults.end());
+    // clear the array
+    poResults.clear();
 
 
     // quick check for positions outside the range
     // quick check for positions outside the range
     if( mPositions.size() == 0)
     if( mPositions.size() == 0)

+ 10 - 3
code/fast_atof.h

@@ -1,3 +1,5 @@
+#pragma once
+
 // Copyright (C) 2002-2007 Nikolaus Gebhardt
 // Copyright (C) 2002-2007 Nikolaus Gebhardt
 // This file is part of the "Irrlicht Engine" and the "irrXML" project.
 // This file is part of the "Irrlicht Engine" and the "irrXML" project.
 // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
 // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
@@ -22,6 +24,7 @@
 #include <assimp/defs.h>
 #include <assimp/defs.h>
 
 
 #include "StringComparison.h"
 #include "StringComparison.h"
+#include <assimp/DefaultLogger.hpp>
 
 
 
 
 #ifdef _MSC_VER
 #ifdef _MSC_VER
@@ -192,7 +195,7 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int*
     uint64_t value = 0;
     uint64_t value = 0;
 
 
     if ( *in < '0' || *in > '9' )
     if ( *in < '0' || *in > '9' )
-            throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value.");
+        throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value.");
 
 
     bool running = true;
     bool running = true;
     while ( running )
     while ( running )
@@ -202,8 +205,12 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int*
 
 
         const uint64_t new_value = ( value * 10 ) + ( *in - '0' );
         const uint64_t new_value = ( value * 10 ) + ( *in - '0' );
 
 
-        if (new_value < value) /* numeric overflow, we rely on you */
-            throw std::overflow_error(std::string("Converting the string \"") + in + "\" into a value resulted in overflow.");
+        // numeric overflow, we rely on you
+        if ( new_value < value ) {
+            DefaultLogger::get()->warn( std::string( "Converting the string \"" ) + in + "\" into a value resulted in overflow." );
+            return 0;
+        }
+            //throw std::overflow_error();
 
 
         value = new_value;
         value = new_value;
 
 

+ 23 - 31
contrib/poly2tri/poly2tri/common/shapes.cc

@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  * http://code.google.com/p/poly2tri/
  *
  *
@@ -88,7 +88,7 @@ void Triangle::Clear()
     points_[0]=points_[1]=points_[2] = NULL;
     points_[0]=points_[1]=points_[2] = NULL;
 }
 }
 
 
-void Triangle::ClearNeighbor(Triangle *triangle )
+void Triangle::ClearNeighbor(const Triangle *triangle )
 {
 {
     if( neighbors_[0] == triangle )
     if( neighbors_[0] == triangle )
     {
     {
@@ -96,14 +96,14 @@ void Triangle::ClearNeighbor(Triangle *triangle )
     }
     }
     else if( neighbors_[1] == triangle )
     else if( neighbors_[1] == triangle )
     {
     {
-        neighbors_[1] = NULL;            
+        neighbors_[1] = NULL;
     }
     }
     else
     else
     {
     {
         neighbors_[2] = NULL;
         neighbors_[2] = NULL;
     }
     }
 }
 }
-    
+
 void Triangle::ClearNeighbors()
 void Triangle::ClearNeighbors()
 {
 {
   neighbors_[0] = NULL;
   neighbors_[0] = NULL;
@@ -116,13 +116,9 @@ void Triangle::ClearDelunayEdges()
   delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
   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);
   Point *cw = t.PointCW(p);
-  //double x = cw->x;
-  //double y = cw->y;
-  //x = p.x;
-  //y = p.y;
   return PointCW(*cw);
   return PointCW(*cw);
 }
 }
 
 
@@ -164,8 +160,7 @@ int Triangle::Index(const Point* p)
     return 2;
     return 2;
   }
   }
   assert(0);
   assert(0);
-
-  return 0;
+  return -1;
 }
 }
 
 
 int Triangle::EdgeIndex(const Point* p1, const Point* p2)
 int Triangle::EdgeIndex(const Point* p1, const Point* p2)
@@ -192,7 +187,7 @@ int Triangle::EdgeIndex(const Point* p1, const Point* p2)
   return -1;
   return -1;
 }
 }
 
 
-void Triangle::MarkConstrainedEdge(const int index)
+void Triangle::MarkConstrainedEdge(int index)
 {
 {
   constrained_edge[index] = true;
   constrained_edge[index] = true;
 }
 }
@@ -215,7 +210,7 @@ void Triangle::MarkConstrainedEdge(Point* p, Point* q)
 }
 }
 
 
 // The point counter-clockwise to given point
 // The point counter-clockwise to given point
-Point* Triangle::PointCW(Point& point)
+Point* Triangle::PointCW(const Point& point)
 {
 {
   if (&point == points_[0]) {
   if (&point == points_[0]) {
     return points_[2];
     return points_[2];
@@ -225,12 +220,11 @@ Point* Triangle::PointCW(Point& point)
     return points_[1];
     return points_[1];
   }
   }
   assert(0);
   assert(0);
-
-  return 0;
+  return NULL;
 }
 }
 
 
 // The point counter-clockwise to given point
 // The point counter-clockwise to given point
-Point* Triangle::PointCCW(Point& point)
+Point* Triangle::PointCCW(const Point& point)
 {
 {
   if (&point == points_[0]) {
   if (&point == points_[0]) {
     return points_[1];
     return points_[1];
@@ -240,12 +234,11 @@ Point* Triangle::PointCCW(Point& point)
     return points_[0];
     return points_[0];
   }
   }
   assert(0);
   assert(0);
-
-  return 0;
+  return NULL;
 }
 }
 
 
 // The neighbor clockwise to given point
 // The neighbor clockwise to given point
-Triangle* Triangle::NeighborCW(Point& point)
+Triangle* Triangle::NeighborCW(const Point& point)
 {
 {
   if (&point == points_[0]) {
   if (&point == points_[0]) {
     return neighbors_[1];
     return neighbors_[1];
@@ -256,7 +249,7 @@ Triangle* Triangle::NeighborCW(Point& point)
 }
 }
 
 
 // The neighbor counter-clockwise to given point
 // The neighbor counter-clockwise to given point
-Triangle* Triangle::NeighborCCW(Point& point)
+Triangle* Triangle::NeighborCCW(const Point& point)
 {
 {
   if (&point == points_[0]) {
   if (&point == points_[0]) {
     return neighbors_[2];
     return neighbors_[2];
@@ -266,7 +259,7 @@ Triangle* Triangle::NeighborCCW(Point& point)
   return neighbors_[1];
   return neighbors_[1];
 }
 }
 
 
-bool Triangle::GetConstrainedEdgeCCW(Point& p)
+bool Triangle::GetConstrainedEdgeCCW(const Point& p)
 {
 {
   if (&p == points_[0]) {
   if (&p == points_[0]) {
     return constrained_edge[2];
     return constrained_edge[2];
@@ -276,7 +269,7 @@ bool Triangle::GetConstrainedEdgeCCW(Point& p)
   return constrained_edge[1];
   return constrained_edge[1];
 }
 }
 
 
-bool Triangle::GetConstrainedEdgeCW(Point& p)
+bool Triangle::GetConstrainedEdgeCW(const Point& p)
 {
 {
   if (&p == points_[0]) {
   if (&p == points_[0]) {
     return constrained_edge[1];
     return constrained_edge[1];
@@ -286,7 +279,7 @@ bool Triangle::GetConstrainedEdgeCW(Point& p)
   return constrained_edge[0];
   return constrained_edge[0];
 }
 }
 
 
-void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce)
+void Triangle::SetConstrainedEdgeCCW(const Point& p, bool ce)
 {
 {
   if (&p == points_[0]) {
   if (&p == points_[0]) {
     constrained_edge[2] = ce;
     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]) {
   if (&p == points_[0]) {
     constrained_edge[1] = ce;
     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]) {
   if (&p == points_[0]) {
     return delaunay_edge[2];
     return delaunay_edge[2];
@@ -318,7 +311,7 @@ bool Triangle::GetDelunayEdgeCCW(Point& p)
   return delaunay_edge[1];
   return delaunay_edge[1];
 }
 }
 
 
-bool Triangle::GetDelunayEdgeCW(Point& p)
+bool Triangle::GetDelunayEdgeCW(const Point& p)
 {
 {
   if (&p == points_[0]) {
   if (&p == points_[0]) {
     return delaunay_edge[1];
     return delaunay_edge[1];
@@ -328,7 +321,7 @@ bool Triangle::GetDelunayEdgeCW(Point& p)
   return delaunay_edge[0];
   return delaunay_edge[0];
 }
 }
 
 
-void Triangle::SetDelunayEdgeCCW(Point& p, bool e)
+void Triangle::SetDelunayEdgeCCW(const Point& p, bool e)
 {
 {
   if (&p == points_[0]) {
   if (&p == points_[0]) {
     delaunay_edge[2] = e;
     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]) {
   if (&p == points_[0]) {
     delaunay_edge[1] = e;
     delaunay_edge[1] = e;
@@ -351,7 +344,7 @@ void Triangle::SetDelunayEdgeCW(Point& p, bool e)
 }
 }
 
 
 // The neighbor across to given point
 // The neighbor across to given point
-Triangle& Triangle::NeighborAcross(Point& opoint)
+Triangle& Triangle::NeighborAcross(const Point& opoint)
 {
 {
   if (&opoint == points_[0]) {
   if (&opoint == points_[0]) {
     return *neighbors_[0];
     return *neighbors_[0];
@@ -369,5 +362,4 @@ void Triangle::DebugPrint()
   cout << points_[2]->x << "," << points_[2]->y << endl;
   cout << points_[2]->x << "," << points_[2]->y << endl;
 }
 }
 
 
-}
-
+}

+ 29 - 31
contrib/poly2tri/poly2tri/common/shapes.h

@@ -113,7 +113,7 @@ struct Point {
   /// Convert this point into a unit point. Returns the Length.
   /// Convert this point into a unit point. Returns the Length.
   double Normalize()
   double Normalize()
   {
   {
-    double len = Length();
+    const double len = Length();
     x /= len;
     x /= len;
     y /= len;
     y /= len;
     return len;
     return len;
@@ -162,50 +162,50 @@ bool constrained_edge[3];
 /// Flags to determine if an edge is a Delauney edge
 /// Flags to determine if an edge is a Delauney edge
 bool delaunay_edge[3];
 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(Point* p1, Point* p2, Triangle* t);
 void MarkNeighbor(Triangle& t);
 void MarkNeighbor(Triangle& t);
 
 
-void MarkConstrainedEdge(const int index);
+void MarkConstrainedEdge(int index);
 void MarkConstrainedEdge(Edge& edge);
 void MarkConstrainedEdge(Edge& edge);
 void MarkConstrainedEdge(Point* p, Point* q);
 void MarkConstrainedEdge(Point* p, Point* q);
 
 
 int Index(const Point* p);
 int Index(const Point* p);
 int EdgeIndex(const Point* p1, const Point* p2);
 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(const Edge& e);
-bool Contains(Point* p, Point* q);
+bool Contains(const Point* p, const Point* q);
 void Legalize(Point& point);
 void Legalize(Point& point);
 void Legalize(Point& opoint, Point& npoint);
 void Legalize(Point& opoint, Point& npoint);
 /**
 /**
  * Clears all references to all other triangles and points
  * Clears all references to all other triangles and points
  */
  */
 void Clear();
 void Clear();
-void ClearNeighbor(Triangle *triangle );
+void ClearNeighbor(const Triangle *triangle);
 void ClearNeighbors();
 void ClearNeighbors();
 void ClearDelunayEdges();
 void ClearDelunayEdges();
 
 
 inline bool IsInterior();
 inline bool IsInterior();
 inline void IsInterior(bool b);
 inline void IsInterior(bool b);
 
 
-Triangle& NeighborAcross(Point& opoint);
+Triangle& NeighborAcross(const Point& opoint);
 
 
 void DebugPrint();
 void DebugPrint();
 
 
@@ -258,7 +258,7 @@ inline bool operator ==(const Point& a, const Point& b)
 
 
 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.
 /// 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
 /// Perform the cross product on a scalar and a point. In 2D this produces
 /// a point.
 /// 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);
   return Point(-s * a.y, s * a.x);
 }
 }
 
 
-inline Point* Triangle::GetPoint(const int& index)
+inline Point* Triangle::GetPoint(int index)
 {
 {
   return points_[index];
   return points_[index];
 }
 }
 
 
-inline Triangle* Triangle::GetNeighbor(const int& index)
+inline Triangle* Triangle::GetNeighbor(int index)
 {
 {
   return neighbors_[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];
   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);
   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);
   return Contains(p) && Contains(q);
 }
 }
@@ -324,6 +324,4 @@ inline void Triangle::IsInterior(bool b)
 
 
 }
 }
 
 
-#endif
-
-
+#endif

+ 32 - 8
contrib/poly2tri/poly2tri/common/utils.h

@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  * http://code.google.com/p/poly2tri/
  *
  *
@@ -28,18 +28,26 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  */
- 
+
 #ifndef UTILS_H
 #ifndef UTILS_H
 #define UTILS_H
 #define UTILS_H
 
 
+// Otherwise #defines like M_PI are undeclared under Visual Studio
+#define _USE_MATH_DEFINES
+
 #include <exception>
 #include <exception>
+#include <math.h>
+
+// C99 removes M_PI from math.h
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338327
+#endif
 
 
 namespace p2t {
 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 };
 enum Orientation { CW, CCW, COLLINEAR };
 
 
@@ -53,7 +61,7 @@ enum Orientation { CW, CCW, COLLINEAR };
  *              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
  *              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
  * </pre>
  * </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 detleft = (pa.x - pc.x) * (pb.y - pc.y);
   double detright = (pa.y - pc.y) * (pb.x - pc.x);
   double detright = (pa.y - pc.y) * (pb.x - pc.x);
@@ -66,6 +74,7 @@ Orientation Orient2d(Point& pa, Point& pb, Point& pc)
   return CW;
   return CW;
 }
 }
 
 
+/*
 bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
 bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
 {
 {
   double pdx = pd.x;
   double pdx = pd.x;
@@ -97,7 +106,22 @@ bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
   return true;
   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

+ 2 - 3
contrib/poly2tri/poly2tri/poly2tri.h

@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  * http://code.google.com/p/poly2tri/
  *
  *
@@ -35,5 +35,4 @@
 #include "common/shapes.h"
 #include "common/shapes.h"
 #include "sweep/cdt.h"
 #include "sweep/cdt.h"
 
 
-#endif
-
+#endif

+ 3 - 4
contrib/poly2tri/poly2tri/sweep/advancing_front.cc

@@ -39,7 +39,7 @@ AdvancingFront::AdvancingFront(Node& head, Node& tail)
   search_node_ = &head;
   search_node_ = &head;
 }
 }
 
 
-Node* AdvancingFront::LocateNode(const double& x)
+Node* AdvancingFront::LocateNode(double x)
 {
 {
   Node* node = search_node_;
   Node* node = search_node_;
 
 
@@ -61,7 +61,7 @@ Node* AdvancingFront::LocateNode(const double& x)
   return NULL;
   return NULL;
 }
 }
 
 
-Node* AdvancingFront::FindSearchNode(const double& x)
+Node* AdvancingFront::FindSearchNode(double x)
 {
 {
   (void)x; // suppress compiler warnings "unused parameter 'x'"
   (void)x; // suppress compiler warnings "unused parameter 'x'"
   // TODO: implement BST index
   // TODO: implement BST index
@@ -105,5 +105,4 @@ AdvancingFront::~AdvancingFront()
 {
 {
 }
 }
 
 
-}
-
+}

+ 3 - 3
contrib/poly2tri/poly2tri/sweep/advancing_front.h

@@ -74,7 +74,7 @@ Node* search();
 void set_search(Node* node);
 void set_search(Node* node);
 
 
 /// Locate insertion point along advancing front
 /// Locate insertion point along advancing front
-Node* LocateNode(const double& x);
+Node* LocateNode(double x);
 
 
 Node* LocatePoint(const Point* point);
 Node* LocatePoint(const Point* point);
 
 
@@ -82,7 +82,7 @@ private:
 
 
 Node* head_, *tail_, *search_node_;
 Node* head_, *tail_, *search_node_;
 
 
-Node* FindSearchNode(const double& x);
+Node* FindSearchNode(double x);
 };
 };
 
 
 inline Node* AdvancingFront::head()
 inline Node* AdvancingFront::head()
@@ -115,4 +115,4 @@ inline void AdvancingFront::set_search(Node* node)
 
 
 }
 }
 
 
-#endif
+#endif

+ 4 - 5
contrib/poly2tri/poly2tri/sweep/cdt.cc

@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  * http://code.google.com/p/poly2tri/
  *
  *
@@ -32,13 +32,13 @@
 
 
 namespace p2t {
 namespace p2t {
 
 
-CDT::CDT(std::vector<Point*> polyline)
+CDT::CDT(const std::vector<Point*>& polyline)
 {
 {
   sweep_context_ = new SweepContext(polyline);
   sweep_context_ = new SweepContext(polyline);
   sweep_ = new Sweep;
   sweep_ = new Sweep;
 }
 }
 
 
-void CDT::AddHole(std::vector<Point*> polyline)
+void CDT::AddHole(const std::vector<Point*>& polyline)
 {
 {
   sweep_context_->AddHole(polyline);
   sweep_context_->AddHole(polyline);
 }
 }
@@ -68,5 +68,4 @@ CDT::~CDT()
   delete sweep_;
   delete sweep_;
 }
 }
 
 
-}
-
+}

+ 17 - 17
contrib/poly2tri/poly2tri/sweep/cdt.h

@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  * http://code.google.com/p/poly2tri/
  *
  *
@@ -28,7 +28,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  */
- 
+
 #ifndef CDT_H
 #ifndef CDT_H
 #define CDT_H
 #define CDT_H
 
 
@@ -37,11 +37,11 @@
 #include "sweep.h"
 #include "sweep.h"
 
 
 /**
 /**
- * 
+ *
  * @author Mason Green <[email protected]>
  * @author Mason Green <[email protected]>
  *
  *
  */
  */
- 
+
 namespace p2t {
 namespace p2t {
 
 
 class CDT
 class CDT
@@ -50,40 +50,40 @@ public:
 
 
   /**
   /**
    * Constructor - add polyline with non repeating points
    * Constructor - add polyline with non repeating points
-   * 
+   *
    * @param polyline
    * @param polyline
    */
    */
-  CDT(std::vector<Point*> polyline);
-  
+  CDT(const std::vector<Point*>& polyline);
+
    /**
    /**
    * Destructor - clean up memory
    * Destructor - clean up memory
    */
    */
   ~CDT();
   ~CDT();
-  
+
   /**
   /**
    * Add a hole
    * Add a hole
-   * 
+   *
    * @param polyline
    * @param polyline
    */
    */
-  void AddHole(std::vector<Point*> polyline);
-  
+  void AddHole(const std::vector<Point*>& polyline);
+
   /**
   /**
    * Add a steiner point
    * Add a steiner point
-   * 
+   *
    * @param point
    * @param point
    */
    */
   void AddPoint(Point* point);
   void AddPoint(Point* point);
-  
+
   /**
   /**
    * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points
    * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points
    */
    */
   void Triangulate();
   void Triangulate();
-  
+
   /**
   /**
    * Get CDT triangles
    * Get CDT triangles
    */
    */
   std::vector<Triangle*> GetTriangles();
   std::vector<Triangle*> GetTriangles();
-  
+
   /**
   /**
    * Get triangle map
    * Get triangle map
    */
    */
@@ -94,7 +94,7 @@ public:
   /**
   /**
    * Internals
    * Internals
    */
    */
-   
+
   SweepContext* sweep_context_;
   SweepContext* sweep_context_;
   Sweep* sweep_;
   Sweep* sweep_;
 
 
@@ -102,4 +102,4 @@ public:
 
 
 }
 }
 
 
-#endif
+#endif

+ 91 - 42
contrib/poly2tri/poly2tri/sweep/sweep.cc

@@ -49,7 +49,7 @@ void Sweep::Triangulate(SweepContext& tcx)
 
 
 void Sweep::SweepPoints(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);
     Point& point = *tcx.GetPoint(i);
     Node* node = &PointEvent(tcx, point);
     Node* node = &PointEvent(tcx, point);
     for (unsigned int i = 0; i < point.edge_list.size(); i++) {
     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");
 	  throw std::runtime_error("EdgeEvent - collinear points not supported");
     if( triangle->Contains(&eq, p1)) {
     if( triangle->Contains(&eq, p1)) {
       triangle->MarkConstrainedEdge(&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
       // not change the given constraint and just keep a variable for the new constraint
       tcx.edge_event.constrained_edge->q = p1;
       tcx.edge_event.constrained_edge->q = p1;
       triangle = &triangle->NeighborAcross(point);
       triangle = &triangle->NeighborAcross(point);
@@ -137,7 +137,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
 
 
     if( triangle->Contains(&eq, p2)) {
     if( triangle->Contains(&eq, p2)) {
       triangle->MarkConstrainedEdge(&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
       // not change the given constraint and just keep a variable for the new constraint
       tcx.edge_event.constrained_edge->q = p2;
       tcx.edge_event.constrained_edge->q = p2;
       triangle = &triangle->NeighborAcross(point);
       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)
 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) {
   if (index != -1) {
     triangle.MarkConstrainedEdge(index);
     triangle.MarkConstrainedEdge(index);
@@ -230,8 +230,8 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
   Node* node = n.next;
   Node* node = n.next;
 
 
   while (node->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);
     Fill(tcx, *node);
     node = node->next;
     node = node->next;
   }
   }
@@ -240,29 +240,81 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
   node = n.prev;
   node = n.prev;
 
 
   while (node->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);
     Fill(tcx, *node);
     node = node->prev;
     node = node->prev;
   }
   }
 
 
   // Fill right basins
   // Fill right basins
   if (n.next && n.next->next) {
   if (n.next && n.next->next) {
-    double angle = BasinAngle(n);
+    const double angle = BasinAngle(n);
     if (angle < PI_3div4) {
     if (angle < PI_3div4) {
       FillBasin(tcx, n);
       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);
   return atan2(ay, ax);
 }
 }
 
 
-double Sweep::HoleAngle(Node& node)
+double Sweep::HoleAngle(const Node& node) const
 {
 {
   /* Complex plane
   /* Complex plane
    * ab = cosA +i*sinA
    * ab = cosA +i*sinA
@@ -272,10 +324,10 @@ double Sweep::HoleAngle(Node& node)
    * Where x = ax*bx + ay*by
    * Where x = ax*bx + ay*by
    *       y = ax*by - ay*bx
    *       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);
   return atan2(ax * by - ay * bx, ax * bx + ay * by);
 }
 }
 
 
@@ -340,43 +392,43 @@ bool Sweep::Legalize(SweepContext& tcx, Triangle& t)
   return false;
   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)
   if (oabd <= 0)
     return false;
     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)
   if (ocad <= 0)
     return false;
     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;
   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;
   Triangle* n1, *n2, *n3, *n4;
   n1 = t.NeighborCCW(p);
   n1 = t.NeighborCCW(p);
@@ -708,11 +760,8 @@ Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op)
   } else if (o2d == CCW) {
   } else if (o2d == CCW) {
     // Left
     // Left
     return *ot.PointCW(op);
     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,
 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() {
 Sweep::~Sweep() {
 
 
     // Clean up memory
     // Clean up memory
-    for(unsigned int i = 0; i < nodes_.size(); i++) {
+    for(size_t i = 0; i < nodes_.size(); i++) {
         delete nodes_[i];
         delete nodes_[i];
     }
     }
 
 

+ 28 - 21
contrib/poly2tri/poly2tri/sweep/sweep.h

@@ -33,7 +33,7 @@
  * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
  * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
  * International Journal of Geographical Information Science
  * International Journal of Geographical Information Science
  *
  *
- * "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, [email protected]
+ * "FlipScan" Constrained Edge Algorithm invented by Thomas ?hl?n, [email protected]
  */
  */
 
 
 #ifndef SWEEP_H
 #ifndef SWEEP_H
@@ -49,17 +49,17 @@ struct Point;
 struct Edge;
 struct Edge;
 class Triangle;
 class Triangle;
 
 
-class Sweep 
+class Sweep
 {
 {
 public:
 public:
 
 
   /**
   /**
    * Triangulate
    * Triangulate
-   * 
+   *
    * @param tcx
    * @param tcx
    */
    */
   void Triangulate(SweepContext& tcx);
   void Triangulate(SweepContext& tcx);
-  
+
   /**
   /**
    * Destructor - clean up memory
    * Destructor - clean up memory
    */
    */
@@ -69,7 +69,7 @@ private:
 
 
   /**
   /**
    * Start sweeping the Y-sorted point set from bottom to top
    * Start sweeping the Y-sorted point set from bottom to top
-   * 
+   *
    * @param tcx
    * @param tcx
    */
    */
   void SweepPoints(SweepContext& tcx);
   void SweepPoints(SweepContext& tcx);
@@ -86,8 +86,8 @@ private:
   Node& PointEvent(SweepContext& tcx, Point& point);
   Node& PointEvent(SweepContext& tcx, Point& point);
 
 
    /**
    /**
-     * 
-     * 
+     *
+     *
      * @param tcx
      * @param tcx
      * @param edge
      * @param edge
      * @param node
      * @param node
@@ -98,7 +98,7 @@ private:
 
 
   /**
   /**
    * Creates a new front triangle and legalize it
    * Creates a new front triangle and legalize it
-   * 
+   *
    * @param tcx
    * @param tcx
    * @param point
    * @param point
    * @param node
    * @param node
@@ -142,7 +142,7 @@ private:
    * @param d - point opposite a
    * @param d - point opposite a
    * @return true if d is inside circle, false if on circle edge
    * @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
    * Rotates a triangle pair one vertex CW
@@ -158,7 +158,7 @@ private:
    *       n4                    n4
    *       n4                    n4
    * </pre>
    * </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
    * Fills holes in the Advancing Front
@@ -169,17 +169,24 @@ private:
    */
    */
   void FillAdvancingFront(SweepContext& tcx, Node& n);
   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
    * @param node - middle node
    * @return the angle between 3 front nodes
    * @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]
    * 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
    * 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
    * 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
    * intersecting the edge. So decide which to contiune with and legalize the other
-   * 
+   *
    * @param tcx
    * @param tcx
    * @param o - should be the result of an orient2d( eq, op, ep )
    * @param o - should be the result of an orient2d( eq, op, ep )
    * @param t - triangle 1
    * @param t - triangle 1
    * @param ot - triangle 2
    * @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
    * @param op - another point shared by both triangles
    * @return returns the triangle still intersecting the edge
    * @return returns the triangle still intersecting the edge
    */
    */
   Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle&  t, Triangle& ot, Point& p, Point& op);
   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
      * the point in current triangle that is the opposite point to the next
-     * triangle. 
-     * 
+     * triangle.
+     *
      * @param ep
      * @param ep
      * @param eq
      * @param eq
      * @param ot
      * @param ot
@@ -254,10 +261,10 @@ private:
 
 
    /**
    /**
      * Scan part of the FlipScan algorithm<br>
      * 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
      * we generate a new flipEdgeEvent
-     * 
+     *
      * @param tcx
      * @param tcx
      * @param ep - last point on the edge we are traversing
      * @param ep - last point on the edge we are traversing
      * @param eq - first point on the edge we are traversing
      * @param eq - first point on the edge we are traversing
@@ -275,4 +282,4 @@ private:
 
 
 }
 }
 
 
-#endif
+#endif

+ 31 - 22
contrib/poly2tri/poly2tri/sweep/sweep_context.cc

@@ -34,17 +34,18 @@
 
 
 namespace p2t {
 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_);
   InitEdges(points_);
 }
 }
 
 
-void SweepContext::AddHole(std::vector<Point*> polyline)
+void SweepContext::AddHole(const std::vector<Point*>& polyline)
 {
 {
   InitEdges(polyline);
   InitEdges(polyline);
   for(unsigned int i = 0; i < polyline.size(); i++) {
   for(unsigned int i = 0; i < polyline.size(); i++) {
@@ -56,12 +57,12 @@ void SweepContext::AddPoint(Point* point) {
   points_.push_back(point);
   points_.push_back(point);
 }
 }
 
 
-std::vector<Triangle*> SweepContext::GetTriangles()
+std::vector<Triangle*> &SweepContext::GetTriangles()
 {
 {
   return triangles_;
   return triangles_;
 }
 }
 
 
-std::list<Triangle*> SweepContext::GetMap()
+std::list<Triangle*> &SweepContext::GetMap()
 {
 {
   return map_;
   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]));
     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];
   return points_[index];
 }
 }
@@ -113,13 +114,13 @@ void SweepContext::AddToMap(Triangle* triangle)
   map_.push_back(triangle);
   map_.push_back(triangle);
 }
 }
 
 
-Node& SweepContext::LocateNode(Point& point)
+Node& SweepContext::LocateNode(const Point& point)
 {
 {
   // TODO implement search tree
   // TODO implement search tree
   return *front_->LocateNode(point.x);
   return *front_->LocateNode(point.x);
 }
 }
 
 
-void SweepContext::CreateAdvancingFront(std::vector<Node*> nodes)
+void SweepContext::CreateAdvancingFront(const std::vector<Node*>& nodes)
 {
 {
 
 
   (void) nodes;
   (void) nodes;
@@ -164,12 +165,20 @@ void SweepContext::RemoveFromMap(Triangle* triangle)
 
 
 void SweepContext::MeshClean(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));
+      }
     }
     }
   }
   }
 }
 }

+ 17 - 17
contrib/poly2tri/poly2tri/sweep/sweep_context.h

@@ -52,47 +52,47 @@ class SweepContext {
 public:
 public:
 
 
 /// Constructor
 /// Constructor
-SweepContext(std::vector<Point*> polyline);
+SweepContext(const std::vector<Point*>& polyline);
 /// Destructor
 /// Destructor
 ~SweepContext();
 ~SweepContext();
 
 
 void set_head(Point* p1);
 void set_head(Point* p1);
 
 
-Point* head();
+Point* head() const;
 
 
 void set_tail(Point* p1);
 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 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
 /// Try to map a node to all sides of this triangle that don't have a neighbor
 void MapTriangleToNodes(Triangle& t);
 void MapTriangleToNodes(Triangle& t);
 
 
 void AddToMap(Triangle* triangle);
 void AddToMap(Triangle* triangle);
 
 
-Point* GetPoint(const int& index);
+Point* GetPoint(size_t index);
 
 
 Point* GetPoints();
 Point* GetPoints();
 
 
 void RemoveFromMap(Triangle* triangle);
 void RemoveFromMap(Triangle* triangle);
 
 
-void AddHole(std::vector<Point*> polyline);
+void AddHole(const std::vector<Point*>& polyline);
 
 
 void AddPoint(Point* point);
 void AddPoint(Point* point);
 
 
-AdvancingFront* front();
+AdvancingFront* front() const;
 
 
 void MeshClean(Triangle& triangle);
 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;
 std::vector<Edge*> edge_list;
 
 
@@ -147,18 +147,18 @@ Point* tail_;
 Node *af_head_, *af_middle_, *af_tail_;
 Node *af_head_, *af_middle_, *af_tail_;
 
 
 void InitTriangulation();
 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_;
   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)
 inline void SweepContext::set_head(Point* p1)
@@ -166,7 +166,7 @@ inline void SweepContext::set_head(Point* p1)
   head_ = p1;
   head_ = p1;
 }
 }
 
 
-inline Point* SweepContext::head()
+inline Point* SweepContext::head() const
 {
 {
   return head_;
   return head_;
 }
 }
@@ -176,7 +176,7 @@ inline void SweepContext::set_tail(Point* p1)
   tail_ = p1;
   tail_ = p1;
 }
 }
 
 
-inline Point* SweepContext::tail()
+inline Point* SweepContext::tail() const
 {
 {
   return tail_;
   return tail_;
 }
 }

+ 0 - 2
include/assimp/color4.inl

@@ -77,7 +77,6 @@ AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator /= (TReal f)
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
 AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
 AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
-    //return *(&r + i);
     switch ( i ) {
     switch ( i ) {
         case 0:
         case 0:
             return r;
             return r;
@@ -93,7 +92,6 @@ AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
 AI_FORCE_INLINE TReal& aiColor4t<TReal>::operator[](unsigned int i) {
 AI_FORCE_INLINE TReal& aiColor4t<TReal>::operator[](unsigned int i) {
-//    return *(&r + i);
     switch ( i ) {
     switch ( i ) {
         case 0:
         case 0:
             return r;
             return r;

+ 4 - 3
include/assimp/matrix4x4.h

@@ -224,7 +224,7 @@ public:
      *  @return Reference to the output matrix
      *  @return Reference to the output matrix
      */
      */
     static aiMatrix4x4t& Rotation(TReal a, const aiVector3t<TReal>& axis,
     static aiMatrix4x4t& Rotation(TReal a, const aiVector3t<TReal>& axis,
-        aiMatrix4x4t& out);
+            aiMatrix4x4t& out);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** @brief Returns a translation matrix
     /** @brief Returns a translation matrix
@@ -232,7 +232,8 @@ public:
      *  @param out Receives the output matrix
      *  @param out Receives the output matrix
      *  @return Reference to the output matrix
      *  @return Reference to the output matrix
      */
      */
-    static aiMatrix4x4t& Translation( const aiVector3t<TReal>& v, aiMatrix4x4t& out);
+    static aiMatrix4x4t& Translation( const aiVector3t<TReal>& v, 
+            aiMatrix4x4t& out);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** @brief Returns a scaling matrix
     /** @brief Returns a scaling matrix
@@ -252,7 +253,7 @@ public:
      *          Journal of Graphics Tools, 4(4):1-4, 1999
      *          Journal of Graphics Tools, 4(4):1-4, 1999
      */
      */
     static aiMatrix4x4t& FromToMatrix(const aiVector3t<TReal>& from,
     static aiMatrix4x4t& FromToMatrix(const aiVector3t<TReal>& from,
-        const aiVector3t<TReal>& to, aiMatrix4x4t& out);
+            const aiVector3t<TReal>& to, aiMatrix4x4t& out);
 
 
 public:
 public:
     TReal a1, a2, a3, a4;
     TReal a1, a2, a3, a4;

+ 1 - 4
port/PyAssimp/pyassimp/helper.py

@@ -8,7 +8,6 @@ import os
 import ctypes
 import ctypes
 from ctypes import POINTER
 from ctypes import POINTER
 import operator
 import operator
-import sys
 
 
 try: import numpy
 try: import numpy
 except: numpy = None
 except: numpy = None
@@ -40,9 +39,7 @@ elif os.name=='nt':
     for dir_candidate in path_dirs:
     for dir_candidate in path_dirs:
         if 'assimp' in dir_candidate.lower():
         if 'assimp' in dir_candidate.lower():
             additional_dirs.append(dir_candidate)
             additional_dirs.append(dir_candidate)
-
-additional_dirs += sys.path
-
+            
 #print(additional_dirs)
 #print(additional_dirs)
 def vec2tuple(x):
 def vec2tuple(x):
     """ Converts a VECTOR3D to a Tuple """
     """ Converts a VECTOR3D to a Tuple """

+ 1 - 3
port/PyAssimp/setup.py

@@ -9,7 +9,5 @@ setup(name='pyassimp',
       url='https://github.com/assimp/assimp',
       url='https://github.com/assimp/assimp',
       packages=['pyassimp'],
       packages=['pyassimp'],
       data_files=[('share/pyassimp', ['README.md']),
       data_files=[('share/pyassimp', ['README.md']),
-                  ('share/examples/pyassimp', ['scripts/' + f for f in os.listdir('scripts/')]),
-                  ('lib/', [f for f in os.listdir('../../lib') if os.path.isfile(f)])],
-      requires=['numpy']
+                  ('share/examples/pyassimp', ['scripts/' + f for f in os.listdir('scripts/')])], requires=['numpy']
       )
       )

+ 28 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11.sln

@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26228.9
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleTexturedDirectx11", "SimpleTexturedDirectx11\SimpleTexturedDirectx11.vcxproj", "{E3B160B5-E71F-4F3F-9310-B8F156F736D8}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x64.ActiveCfg = Debug|x64
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x64.Build.0 = Debug|x64
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x86.ActiveCfg = Debug|Win32
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x86.Build.0 = Debug|Win32
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x64.ActiveCfg = Release|x64
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x64.Build.0 = Release|x64
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x86.ActiveCfg = Release|Win32
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x86.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 102 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h

@@ -0,0 +1,102 @@
+#ifndef MESH_H
+#define MESH_H
+
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <vector>
+using namespace std;
+
+#include <vector>
+#include <d3d11_1.h>
+#include <DirectXMath.h>
+using namespace DirectX;
+
+struct VERTEX {
+	FLOAT X, Y, Z;
+	XMFLOAT2 texcoord;
+};
+
+struct Texture {
+	string type;
+	string path;
+	ID3D11ShaderResourceView *texture;
+};
+
+class Mesh {
+public:
+	vector<VERTEX> vertices;
+	vector<UINT> indices;
+	vector<Texture> textures;
+	ID3D11Device *dev;
+
+	Mesh(ID3D11Device *dev, vector<VERTEX> vertices, vector<UINT> indices, vector<Texture> textures)
+	{
+		this->vertices = vertices;
+		this->indices = indices;
+		this->textures = textures;
+
+		this->dev = dev;
+
+		this->setupMesh(dev);
+	}
+
+	void Draw(ID3D11DeviceContext *devcon)
+	{
+		UINT stride = sizeof(VERTEX);
+		UINT offset = 0;
+
+		devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset);
+		devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0);
+
+		devcon->PSSetShaderResources(0, 1, &textures[0].texture);
+
+		devcon->DrawIndexed(indices.size(), 0, 0);
+	}
+
+	void Close()
+	{
+		VertexBuffer->Release();
+		IndexBuffer->Release();
+	}
+private:
+	/*  Render data  */
+	ID3D11Buffer *VertexBuffer, *IndexBuffer;
+
+	/*  Functions    */
+	// Initializes all the buffer objects/arrays
+	bool setupMesh(ID3D11Device *dev)
+	{
+		HRESULT hr;
+
+		D3D11_BUFFER_DESC vbd;
+		vbd.Usage = D3D11_USAGE_IMMUTABLE;
+		vbd.ByteWidth = sizeof(VERTEX) * vertices.size();
+		vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+		vbd.CPUAccessFlags = 0;
+		vbd.MiscFlags = 0;
+
+		D3D11_SUBRESOURCE_DATA initData;
+		initData.pSysMem = &vertices[0];
+
+		hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer);
+		if (FAILED(hr))
+			return false;
+
+		D3D11_BUFFER_DESC ibd;
+		ibd.Usage = D3D11_USAGE_IMMUTABLE;
+		ibd.ByteWidth = sizeof(UINT) * indices.size();
+		ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
+		ibd.CPUAccessFlags = 0;
+		ibd.MiscFlags = 0;
+
+		initData.pSysMem = &indices[0];
+
+		hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer);
+		if (FAILED(hr))
+			return false;
+	}
+};
+
+#endif

+ 205 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp

@@ -0,0 +1,205 @@
+#include "ModelLoader.h"
+
+ModelLoader::ModelLoader()
+{
+}
+
+
+ModelLoader::~ModelLoader()
+{
+}
+
+bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename)
+{
+	Assimp::Importer importer;
+
+	const aiScene* pScene = importer.ReadFile(filename,
+		aiProcess_Triangulate |
+		aiProcess_ConvertToLeftHanded);
+
+	if (pScene == NULL)
+		return false;
+
+	this->directory = filename.substr(0, filename.find_last_of('/'));
+
+	this->dev = dev;
+	this->hwnd = hwnd;
+
+	processNode(pScene->mRootNode, pScene);
+
+	return true;
+}
+
+void ModelLoader::Draw(ID3D11DeviceContext * devcon)
+{
+	for (int i = 0; i < meshes.size(); i++)
+	{
+		meshes[i].Draw(devcon);
+	}
+}
+
+string textype;
+
+Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene)
+{
+	// Data to fill
+	vector<VERTEX> vertices;
+	vector<UINT> indices;
+	vector<Texture> textures;
+
+	if (mesh->mMaterialIndex >= 0)
+	{
+		aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
+
+		if (textype.empty()) textype = determineTextureType(scene, mat);
+	}
+
+	// Walk through each of the mesh's vertices
+	for (UINT i = 0; i < mesh->mNumVertices; i++)
+	{
+		VERTEX vertex;
+
+		vertex.X = mesh->mVertices[i].x;
+		vertex.Y = mesh->mVertices[i].y;
+		vertex.Z = mesh->mVertices[i].z;
+
+		if (mesh->mTextureCoords[0])
+		{
+			vertex.texcoord.x = (float)mesh->mTextureCoords[0][i].x;
+			vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y;
+		}
+
+		vertices.push_back(vertex);
+	}
+
+	for (UINT i = 0; i < mesh->mNumFaces; i++)
+	{
+		aiFace face = mesh->mFaces[i];
+
+		for (UINT j = 0; j < face.mNumIndices; j++)
+			indices.push_back(face.mIndices[j]);
+	}
+
+	if (mesh->mMaterialIndex >= 0)
+	{
+		aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
+
+		vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene);
+		textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
+	}
+
+	return Mesh(dev, vertices, indices, textures);
+}
+
+vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene)
+{
+	vector<Texture> textures;
+	for (UINT i = 0; i < mat->GetTextureCount(type); i++)
+	{
+		aiString str;
+		mat->GetTexture(type, i, &str);
+		// Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
+		bool skip = false;
+		for (UINT j = 0; j < textures_loaded.size(); j++)
+		{
+			if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0)
+			{
+				textures.push_back(textures_loaded[j]);
+				skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
+				break;
+			}
+		}
+		if (!skip)
+		{   // If texture hasn't been loaded already, load it
+			HRESULT hr;
+			Texture texture;
+			if (textype == "embedded compressed texture")
+			{
+				int textureindex = getTextureIndex(&str);
+				texture.texture = getTextureFromModel(scene, textureindex);
+			}
+			else
+			{
+				string filename = string(str.C_Str());
+				filename = directory + '/' + filename;
+				wstring filenamews = wstring(filename.begin(), filename.end());
+				hr = CreateWICTextureFromFile(dev, devcon, filenamews.c_str(), nullptr, &texture.texture);
+				if (FAILED(hr))
+					MessageBox(hwnd, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK);
+			}
+			texture.type = typeName;
+			texture.path = str.C_Str();
+			textures.push_back(texture);
+			this->textures_loaded.push_back(texture);  // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
+		}
+	}
+	return textures;
+}
+
+void ModelLoader::Close()
+{
+	for (int i = 0; i < meshes.size(); i++)
+	{
+		meshes[i].Close();
+	}
+
+	dev->Release();
+}
+
+void ModelLoader::processNode(aiNode * node, const aiScene * scene)
+{
+	for (UINT i = 0; i < node->mNumMeshes; i++)
+	{
+		aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
+		meshes.push_back(this->processMesh(mesh, scene));
+	}
+
+	for (UINT i = 0; i < node->mNumChildren; i++)
+	{
+		this->processNode(node->mChildren[i], scene);
+	}
+}
+
+string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat)
+{
+	aiString textypeStr;
+	mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr);
+	string textypeteststr = textypeStr.C_Str();
+	if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5")
+	{
+		if (scene->mTextures[0]->mHeight == 0)
+		{
+			return "embedded compressed texture";
+		}
+		else
+		{
+			return "embedded non-compressed texture";
+		}
+	}
+	if (textypeteststr.find('.') != string::npos)
+	{
+		return "textures are on disk";
+	}
+}
+
+int ModelLoader::getTextureIndex(aiString * str)
+{
+	string tistr;
+	tistr = str->C_Str();
+	tistr = tistr.substr(1);
+	return stoi(tistr);
+}
+
+ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex)
+{
+	HRESULT hr;
+	ID3D11ShaderResourceView *texture;
+
+	int* size = reinterpret_cast<int*>(&scene->mTextures[textureindex]->mWidth);
+
+	hr = CreateWICTextureFromMemory(dev, devcon, reinterpret_cast<unsigned char*>(scene->mTextures[textureindex]->pcData), *size, nullptr, &texture);
+	if (FAILED(hr))
+		MessageBox(hwnd, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK);
+
+	return texture;
+}

+ 44 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h

@@ -0,0 +1,44 @@
+#ifndef MODEL_LOADER_H
+#define MODEL_LOADER_H
+
+#include <vector>
+#include <d3d11_1.h>
+#include <DirectXMath.h>
+
+#include <assimp\Importer.hpp>
+#include <assimp\scene.h>
+#include <assimp\postprocess.h>
+
+#include "Mesh.h"
+#include "TextureLoader.h"
+
+using namespace DirectX;
+
+class ModelLoader
+{
+public:
+	ModelLoader();
+	~ModelLoader();
+
+	bool Load(HWND hwnd, ID3D11Device* dev, ID3D11DeviceContext* devcon, std::string filename);
+	void Draw(ID3D11DeviceContext* devcon);
+
+	void Close();
+private:
+	ID3D11Device *dev;
+	ID3D11DeviceContext *devcon;
+	std::vector<Mesh> meshes;
+	string directory;
+	vector<Texture> textures_loaded;
+	HWND hwnd;
+
+	void processNode(aiNode* node, const aiScene* scene);
+	Mesh processMesh(aiMesh* mesh, const aiScene* scene);
+	vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName, const aiScene* scene);
+	string determineTextureType(const aiScene* scene, aiMaterial* mat);
+	int getTextureIndex(aiString* str);
+	ID3D11ShaderResourceView* getTextureFromModel(const aiScene* scene, int textureindex);
+};
+
+#endif // !MODEL_LOADER_H
+

+ 9 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/PixelShader.hlsl

@@ -0,0 +1,9 @@
+Texture2D diffTexture;
+SamplerState SampleType;
+
+float4 main(float4 pos : SV_POSITION, float2 texcoord : TEXCOORD) : SV_TARGET
+{
+	float4 textureColor = diffTexture.Sample(SampleType, texcoord);
+
+	return textureColor;
+}

+ 146 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj

@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{E3B160B5-E71F-4F3F-9310-B8F156F736D8}</ProjectGuid>
+    <RootNamespace>SimpleTexturedDirectx11</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <IncludePath>$(IncludePath);E:\OpenGL VS Files\include</IncludePath>
+    <LibraryPath>$(LibraryPath);E:\OpenGL VS Files\lib</LibraryPath>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>assimp-vc140-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="main.cpp" />
+    <ClCompile Include="ModelLoader.cpp" />
+    <ClCompile Include="TextureLoader.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <FxCompile Include="PixelShader.hlsl">
+      <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType>
+      <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
+      <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
+      <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType>
+    </FxCompile>
+    <FxCompile Include="VertexShader.hlsl">
+      <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType>
+      <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType>
+      <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType>
+      <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Vertex</ShaderType>
+    </FxCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Mesh.h" />
+    <ClInclude Include="ModelLoader.h" />
+    <ClInclude Include="TextureLoader.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 50 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj.filters

@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+    <Filter Include="Shaders">
+      <UniqueIdentifier>{b6a86d3e-70a5-4d1e-ba05-c20902300206}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="main.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="ModelLoader.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="TextureLoader.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <FxCompile Include="VertexShader.hlsl">
+      <Filter>Shaders</Filter>
+    </FxCompile>
+    <FxCompile Include="PixelShader.hlsl">
+      <Filter>Shaders</Filter>
+    </FxCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="ModelLoader.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Mesh.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="TextureLoader.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>

+ 691 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.cpp

@@ -0,0 +1,691 @@
+//--------------------------------------------------------------------------------------
+// File: WICTextureLoader.cpp
+//
+// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it
+// (auto-generating mipmaps if possible)
+//
+// Note: Assumes application has already called CoInitializeEx
+//
+// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for
+//          auto-gen mipmap support.
+//
+// Note these functions are useful for images created as simple 2D textures. For
+// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader.
+// For a full-featured DDS file reader, writer, and texture processing pipeline see
+// the 'Texconv' sample and the 'DirectXTex' library.
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// http://go.microsoft.com/fwlink/?LinkId=248926
+// http://go.microsoft.com/fwlink/?LinkId=248929
+//--------------------------------------------------------------------------------------
+
+// We could load multi-frame images (TIFF/GIF) into a texture array.
+// For now, we just load the first frame (note: DirectXTex supports multi-frame images)
+
+#include <dxgiformat.h>
+#include <assert.h>
+
+#pragma warning(push)
+#pragma warning(disable : 4005)
+#include <wincodec.h>
+#pragma warning(pop)
+
+#include <memory>
+
+#include "TextureLoader.h"
+
+#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && !defined(DXGI_1_2_FORMATS)
+#define DXGI_1_2_FORMATS
+#endif
+
+//---------------------------------------------------------------------------------
+template<class T> class ScopedObject
+{
+public:
+	explicit ScopedObject(T *p = 0) : _pointer(p) {}
+	~ScopedObject()
+	{
+		if (_pointer)
+		{
+			_pointer->Release();
+			_pointer = nullptr;
+		}
+	}
+
+	bool IsNull() const { return (!_pointer); }
+
+	T& operator*() { return *_pointer; }
+	T* operator->() { return _pointer; }
+	T** operator&() { return &_pointer; }
+
+	void Reset(T *p = 0) { if (_pointer) { _pointer->Release(); } _pointer = p; }
+
+	T* Get() const { return _pointer; }
+
+private:
+	ScopedObject(const ScopedObject&);
+	ScopedObject& operator=(const ScopedObject&);
+
+	T* _pointer;
+};
+
+//-------------------------------------------------------------------------------------
+// WIC Pixel Format Translation Data
+//-------------------------------------------------------------------------------------
+struct WICTranslate
+{
+	GUID                wic;
+	DXGI_FORMAT         format;
+};
+
+static WICTranslate g_WICFormats[] =
+{
+	{ GUID_WICPixelFormat128bppRGBAFloat,       DXGI_FORMAT_R32G32B32A32_FLOAT },
+
+	{ GUID_WICPixelFormat64bppRGBAHalf,         DXGI_FORMAT_R16G16B16A16_FLOAT },
+	{ GUID_WICPixelFormat64bppRGBA,             DXGI_FORMAT_R16G16B16A16_UNORM },
+
+	{ GUID_WICPixelFormat32bppRGBA,             DXGI_FORMAT_R8G8B8A8_UNORM },
+	{ GUID_WICPixelFormat32bppBGRA,             DXGI_FORMAT_B8G8R8A8_UNORM }, // DXGI 1.1
+	{ GUID_WICPixelFormat32bppBGR,              DXGI_FORMAT_B8G8R8X8_UNORM }, // DXGI 1.1
+
+	{ GUID_WICPixelFormat32bppRGBA1010102XR,    DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, // DXGI 1.1
+	{ GUID_WICPixelFormat32bppRGBA1010102,      DXGI_FORMAT_R10G10B10A2_UNORM },
+	{ GUID_WICPixelFormat32bppRGBE,             DXGI_FORMAT_R9G9B9E5_SHAREDEXP },
+
+#ifdef DXGI_1_2_FORMATS
+
+	{ GUID_WICPixelFormat16bppBGRA5551,         DXGI_FORMAT_B5G5R5A1_UNORM },
+	{ GUID_WICPixelFormat16bppBGR565,           DXGI_FORMAT_B5G6R5_UNORM },
+
+#endif // DXGI_1_2_FORMATS
+
+	{ GUID_WICPixelFormat32bppGrayFloat,        DXGI_FORMAT_R32_FLOAT },
+	{ GUID_WICPixelFormat16bppGrayHalf,         DXGI_FORMAT_R16_FLOAT },
+	{ GUID_WICPixelFormat16bppGray,             DXGI_FORMAT_R16_UNORM },
+	{ GUID_WICPixelFormat8bppGray,              DXGI_FORMAT_R8_UNORM },
+
+	{ GUID_WICPixelFormat8bppAlpha,             DXGI_FORMAT_A8_UNORM },
+
+#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
+	{ GUID_WICPixelFormat96bppRGBFloat,         DXGI_FORMAT_R32G32B32_FLOAT },
+#endif
+};
+
+//-------------------------------------------------------------------------------------
+// WIC Pixel Format nearest conversion table
+//-------------------------------------------------------------------------------------
+
+struct WICConvert
+{
+	GUID        source;
+	GUID        target;
+};
+
+static WICConvert g_WICConvert[] =
+{
+	// Note target GUID in this conversion table must be one of those directly supported formats (above).
+
+	{ GUID_WICPixelFormatBlackWhite,            GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
+
+	{ GUID_WICPixelFormat1bppIndexed,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
+	{ GUID_WICPixelFormat2bppIndexed,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
+	{ GUID_WICPixelFormat4bppIndexed,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
+	{ GUID_WICPixelFormat8bppIndexed,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
+
+	{ GUID_WICPixelFormat2bppGray,              GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM 
+	{ GUID_WICPixelFormat4bppGray,              GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM 
+
+	{ GUID_WICPixelFormat16bppGrayFixedPoint,   GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT 
+	{ GUID_WICPixelFormat32bppGrayFixedPoint,   GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT 
+
+#ifdef DXGI_1_2_FORMATS
+
+	{ GUID_WICPixelFormat16bppBGR555,           GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM
+
+#else
+
+	{ GUID_WICPixelFormat16bppBGR555,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
+	{ GUID_WICPixelFormat16bppBGRA5551,         GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
+	{ GUID_WICPixelFormat16bppBGR565,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
+
+#endif // DXGI_1_2_FORMATS
+
+	{ GUID_WICPixelFormat32bppBGR101010,        GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM
+
+	{ GUID_WICPixelFormat24bppBGR,              GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
+	{ GUID_WICPixelFormat24bppRGB,              GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
+	{ GUID_WICPixelFormat32bppPBGRA,            GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
+	{ GUID_WICPixelFormat32bppPRGBA,            GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
+
+	{ GUID_WICPixelFormat48bppRGB,              GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
+	{ GUID_WICPixelFormat48bppBGR,              GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
+	{ GUID_WICPixelFormat64bppBGRA,             GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
+	{ GUID_WICPixelFormat64bppPRGBA,            GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
+	{ GUID_WICPixelFormat64bppPBGRA,            GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
+
+	{ GUID_WICPixelFormat48bppRGBFixedPoint,    GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
+	{ GUID_WICPixelFormat48bppBGRFixedPoint,    GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
+	{ GUID_WICPixelFormat64bppRGBAFixedPoint,   GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
+	{ GUID_WICPixelFormat64bppBGRAFixedPoint,   GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
+	{ GUID_WICPixelFormat64bppRGBFixedPoint,    GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
+	{ GUID_WICPixelFormat64bppRGBHalf,          GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
+	{ GUID_WICPixelFormat48bppRGBHalf,          GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
+
+	{ GUID_WICPixelFormat96bppRGBFixedPoint,    GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT 
+	{ GUID_WICPixelFormat128bppPRGBAFloat,      GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT 
+	{ GUID_WICPixelFormat128bppRGBFloat,        GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT 
+	{ GUID_WICPixelFormat128bppRGBAFixedPoint,  GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT 
+	{ GUID_WICPixelFormat128bppRGBFixedPoint,   GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT 
+
+	{ GUID_WICPixelFormat32bppCMYK,             GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
+	{ GUID_WICPixelFormat64bppCMYK,             GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
+	{ GUID_WICPixelFormat40bppCMYKAlpha,        GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
+	{ GUID_WICPixelFormat80bppCMYKAlpha,        GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
+
+#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
+	{ GUID_WICPixelFormat32bppRGB,              GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
+	{ GUID_WICPixelFormat64bppRGB,              GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
+	{ GUID_WICPixelFormat64bppPRGBAHalf,        GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
+#endif
+
+																					// We don't support n-channel formats
+};
+
+//--------------------------------------------------------------------------------------
+static IWICImagingFactory* _GetWIC()
+{
+	static IWICImagingFactory* s_Factory = nullptr;
+
+	if (s_Factory)
+		return s_Factory;
+
+	HRESULT hr = CoCreateInstance(
+		CLSID_WICImagingFactory,
+		nullptr,
+		CLSCTX_INPROC_SERVER,
+		__uuidof(IWICImagingFactory),
+		(LPVOID*)&s_Factory
+	);
+
+	if (FAILED(hr))
+	{
+		s_Factory = nullptr;
+		return nullptr;
+	}
+
+	return s_Factory;
+}
+
+//---------------------------------------------------------------------------------
+static DXGI_FORMAT _WICToDXGI(const GUID& guid)
+{
+	for (size_t i = 0; i < _countof(g_WICFormats); ++i)
+	{
+		if (memcmp(&g_WICFormats[i].wic, &guid, sizeof(GUID)) == 0)
+			return g_WICFormats[i].format;
+	}
+
+	return DXGI_FORMAT_UNKNOWN;
+}
+
+//---------------------------------------------------------------------------------
+static size_t _WICBitsPerPixel(REFGUID targetGuid)
+{
+	IWICImagingFactory* pWIC = _GetWIC();
+	if (!pWIC)
+		return 0;
+
+	ScopedObject<IWICComponentInfo> cinfo;
+	if (FAILED(pWIC->CreateComponentInfo(targetGuid, &cinfo)))
+		return 0;
+
+	WICComponentType type;
+	if (FAILED(cinfo->GetComponentType(&type)))
+		return 0;
+
+	if (type != WICPixelFormat)
+		return 0;
+
+	ScopedObject<IWICPixelFormatInfo> pfinfo;
+	if (FAILED(cinfo->QueryInterface(__uuidof(IWICPixelFormatInfo), reinterpret_cast<void**>(&pfinfo))))
+		return 0;
+
+	UINT bpp;
+	if (FAILED(pfinfo->GetBitsPerPixel(&bpp)))
+		return 0;
+
+	return bpp;
+}
+
+//---------------------------------------------------------------------------------
+static HRESULT CreateTextureFromWIC(_In_ ID3D11Device* d3dDevice,
+	_In_opt_ ID3D11DeviceContext* d3dContext,
+	_In_ IWICBitmapFrameDecode *frame,
+	_Out_opt_ ID3D11Resource** texture,
+	_Out_opt_ ID3D11ShaderResourceView** textureView,
+	_In_ size_t maxsize)
+{
+	UINT width, height;
+	HRESULT hr = frame->GetSize(&width, &height);
+	if (FAILED(hr))
+		return hr;
+
+	assert(width > 0 && height > 0);
+
+	if (!maxsize)
+	{
+		// This is a bit conservative because the hardware could support larger textures than
+		// the Feature Level defined minimums, but doing it this way is much easier and more
+		// performant for WIC than the 'fail and retry' model used by DDSTextureLoader
+
+		switch (d3dDevice->GetFeatureLevel())
+		{
+		case D3D_FEATURE_LEVEL_9_1:
+		case D3D_FEATURE_LEVEL_9_2:
+			maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
+			break;
+
+		case D3D_FEATURE_LEVEL_9_3:
+			maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
+			break;
+
+		case D3D_FEATURE_LEVEL_10_0:
+		case D3D_FEATURE_LEVEL_10_1:
+			maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
+			break;
+
+		default:
+			maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+			break;
+		}
+	}
+
+	assert(maxsize > 0);
+
+	UINT twidth, theight;
+	if (width > maxsize || height > maxsize)
+	{
+		float ar = static_cast<float>(height) / static_cast<float>(width);
+		if (width > height)
+		{
+			twidth = static_cast<UINT>(maxsize);
+			theight = static_cast<UINT>(static_cast<float>(maxsize) * ar);
+		}
+		else
+		{
+			theight = static_cast<UINT>(maxsize);
+			twidth = static_cast<UINT>(static_cast<float>(maxsize) / ar);
+		}
+		assert(twidth <= maxsize && theight <= maxsize);
+	}
+	else
+	{
+		twidth = width;
+		theight = height;
+	}
+
+	// Determine format
+	WICPixelFormatGUID pixelFormat;
+	hr = frame->GetPixelFormat(&pixelFormat);
+	if (FAILED(hr))
+		return hr;
+
+	WICPixelFormatGUID convertGUID;
+	memcpy(&convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID));
+
+	size_t bpp = 0;
+
+	DXGI_FORMAT format = _WICToDXGI(pixelFormat);
+	if (format == DXGI_FORMAT_UNKNOWN)
+	{
+		for (size_t i = 0; i < _countof(g_WICConvert); ++i)
+		{
+			if (memcmp(&g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0)
+			{
+				memcpy(&convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID));
+
+				format = _WICToDXGI(g_WICConvert[i].target);
+				assert(format != DXGI_FORMAT_UNKNOWN);
+				bpp = _WICBitsPerPixel(convertGUID);
+				break;
+			}
+		}
+
+		if (format == DXGI_FORMAT_UNKNOWN)
+			return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
+	}
+	else
+	{
+		bpp = _WICBitsPerPixel(pixelFormat);
+	}
+
+	if (!bpp)
+		return E_FAIL;
+
+	// Verify our target format is supported by the current device
+	// (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support)
+	UINT support = 0;
+	hr = d3dDevice->CheckFormatSupport(format, &support);
+	if (FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D))
+	{
+		// Fallback to RGBA 32-bit format which is supported by all devices
+		memcpy(&convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID));
+		format = DXGI_FORMAT_R8G8B8A8_UNORM;
+		bpp = 32;
+	}
+
+	// Allocate temporary memory for image
+	size_t rowPitch = (twidth * bpp + 7) / 8;
+	size_t imageSize = rowPitch * theight;
+
+	std::unique_ptr<uint8_t[]> temp(new uint8_t[imageSize]);
+
+	// Load image data
+	if (memcmp(&convertGUID, &pixelFormat, sizeof(GUID)) == 0
+		&& twidth == width
+		&& theight == height)
+	{
+		// No format conversion or resize needed
+		hr = frame->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
+		if (FAILED(hr))
+			return hr;
+	}
+	else if (twidth != width || theight != height)
+	{
+		// Resize
+		IWICImagingFactory* pWIC = _GetWIC();
+		if (!pWIC)
+			return E_NOINTERFACE;
+
+		ScopedObject<IWICBitmapScaler> scaler;
+		hr = pWIC->CreateBitmapScaler(&scaler);
+		if (FAILED(hr))
+			return hr;
+
+		hr = scaler->Initialize(frame, twidth, theight, WICBitmapInterpolationModeFant);
+		if (FAILED(hr))
+			return hr;
+
+		WICPixelFormatGUID pfScaler;
+		hr = scaler->GetPixelFormat(&pfScaler);
+		if (FAILED(hr))
+			return hr;
+
+		if (memcmp(&convertGUID, &pfScaler, sizeof(GUID)) == 0)
+		{
+			// No format conversion needed
+			hr = scaler->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
+			if (FAILED(hr))
+				return hr;
+		}
+		else
+		{
+			ScopedObject<IWICFormatConverter> FC;
+			hr = pWIC->CreateFormatConverter(&FC);
+			if (FAILED(hr))
+				return hr;
+
+			hr = FC->Initialize(scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom);
+			if (FAILED(hr))
+				return hr;
+
+			hr = FC->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
+			if (FAILED(hr))
+				return hr;
+		}
+	}
+	else
+	{
+		// Format conversion but no resize
+		IWICImagingFactory* pWIC = _GetWIC();
+		if (!pWIC)
+			return E_NOINTERFACE;
+
+		ScopedObject<IWICFormatConverter> FC;
+		hr = pWIC->CreateFormatConverter(&FC);
+		if (FAILED(hr))
+			return hr;
+
+		hr = FC->Initialize(frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom);
+		if (FAILED(hr))
+			return hr;
+
+		hr = FC->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
+		if (FAILED(hr))
+			return hr;
+	}
+
+	// See if format is supported for auto-gen mipmaps (varies by feature level)
+	bool autogen = false;
+	if (d3dContext != 0 && textureView != 0) // Must have context and shader-view to auto generate mipmaps
+	{
+		UINT fmtSupport = 0;
+		hr = d3dDevice->CheckFormatSupport(format, &fmtSupport);
+		if (SUCCEEDED(hr) && (fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN))
+		{
+			autogen = true;
+		}
+	}
+
+	// Create texture
+	D3D11_TEXTURE2D_DESC desc;
+	desc.Width = twidth;
+	desc.Height = theight;
+	desc.MipLevels = (autogen) ? 0 : 1;
+	desc.ArraySize = 1;
+	desc.Format = format;
+	desc.SampleDesc.Count = 1;
+	desc.SampleDesc.Quality = 0;
+	desc.Usage = D3D11_USAGE_DEFAULT;
+	desc.BindFlags = (autogen) ? (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) : (D3D11_BIND_SHADER_RESOURCE);
+	desc.CPUAccessFlags = 0;
+	desc.MiscFlags = (autogen) ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0;
+
+	D3D11_SUBRESOURCE_DATA initData;
+	initData.pSysMem = temp.get();
+	initData.SysMemPitch = static_cast<UINT>(rowPitch);
+	initData.SysMemSlicePitch = static_cast<UINT>(imageSize);
+
+	ID3D11Texture2D* tex = nullptr;
+	hr = d3dDevice->CreateTexture2D(&desc, (autogen) ? nullptr : &initData, &tex);
+	if (SUCCEEDED(hr) && tex != 0)
+	{
+		if (textureView != 0)
+		{
+			D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
+			memset(&SRVDesc, 0, sizeof(SRVDesc));
+			SRVDesc.Format = format;
+			SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+			SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1;
+
+			hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView);
+			if (FAILED(hr))
+			{
+				tex->Release();
+				return hr;
+			}
+
+			if (autogen)
+			{
+				assert(d3dContext != 0);
+				d3dContext->UpdateSubresource(tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize));
+				d3dContext->GenerateMips(*textureView);
+			}
+		}
+
+		if (texture != 0)
+		{
+			*texture = tex;
+		}
+		else
+		{
+#if defined(_DEBUG) || defined(PROFILE)
+			tex->SetPrivateData(WKPDID_D3DDebugObjectName,
+				sizeof("WICTextureLoader") - 1,
+				"WICTextureLoader"
+			);
+#endif
+			tex->Release();
+		}
+	}
+
+	return hr;
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CreateWICTextureFromMemory(_In_ ID3D11Device* d3dDevice,
+	_In_opt_ ID3D11DeviceContext* d3dContext,
+	_In_bytecount_(wicDataSize) const uint8_t* wicData,
+	_In_ size_t wicDataSize,
+	_Out_opt_ ID3D11Resource** texture,
+	_Out_opt_ ID3D11ShaderResourceView** textureView,
+	_In_ size_t maxsize
+)
+{
+	if (!d3dDevice || !wicData || (!texture && !textureView))
+	{
+		return E_INVALIDARG;
+	}
+
+	if (!wicDataSize)
+	{
+		return E_FAIL;
+	}
+
+#ifdef _M_AMD64
+	if (wicDataSize > 0xFFFFFFFF)
+		return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE);
+#endif
+
+	IWICImagingFactory* pWIC = _GetWIC();
+	if (!pWIC)
+		return E_NOINTERFACE;
+
+	// Create input stream for memory
+	ScopedObject<IWICStream> stream;
+	HRESULT hr = pWIC->CreateStream(&stream);
+	if (FAILED(hr))
+		return hr;
+
+	hr = stream->InitializeFromMemory(const_cast<uint8_t*>(wicData), static_cast<DWORD>(wicDataSize));
+	if (FAILED(hr))
+		return hr;
+
+	// Initialize WIC
+	ScopedObject<IWICBitmapDecoder> decoder;
+	hr = pWIC->CreateDecoderFromStream(stream.Get(), 0, WICDecodeMetadataCacheOnDemand, &decoder);
+	if (FAILED(hr))
+		return hr;
+
+	ScopedObject<IWICBitmapFrameDecode> frame;
+	hr = decoder->GetFrame(0, &frame);
+	if (FAILED(hr))
+		return hr;
+
+	hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), texture, textureView, maxsize);
+	if (FAILED(hr))
+		return hr;
+
+#if defined(_DEBUG) || defined(PROFILE)
+	if (texture != 0 && *texture != 0)
+	{
+		(*texture)->SetPrivateData(WKPDID_D3DDebugObjectName,
+			sizeof("WICTextureLoader") - 1,
+			"WICTextureLoader"
+		);
+	}
+
+	if (textureView != 0 && *textureView != 0)
+	{
+		(*textureView)->SetPrivateData(WKPDID_D3DDebugObjectName,
+			sizeof("WICTextureLoader") - 1,
+			"WICTextureLoader"
+		);
+	}
+#endif
+
+	return hr;
+}
+
+//--------------------------------------------------------------------------------------
+HRESULT CreateWICTextureFromFile(_In_ ID3D11Device* d3dDevice,
+	_In_opt_ ID3D11DeviceContext* d3dContext,
+	_In_z_ const wchar_t* fileName,
+	_Out_opt_ ID3D11Resource** texture,
+	_Out_opt_ ID3D11ShaderResourceView** textureView,
+	_In_ size_t maxsize)
+{
+	if (!d3dDevice || !fileName || (!texture && !textureView))
+	{
+		return E_INVALIDARG;
+	}
+
+	IWICImagingFactory* pWIC = _GetWIC();
+	if (!pWIC)
+		return E_NOINTERFACE;
+
+	// Initialize WIC
+	ScopedObject<IWICBitmapDecoder> decoder;
+	HRESULT hr = pWIC->CreateDecoderFromFilename(fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder);
+	if (FAILED(hr))
+		return hr;
+
+	ScopedObject<IWICBitmapFrameDecode> frame;
+	hr = decoder->GetFrame(0, &frame);
+	if (FAILED(hr))
+		return hr;
+
+	hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), texture, textureView, maxsize);
+	if (FAILED(hr))
+		return hr;
+
+#if defined(_DEBUG) || defined(PROFILE)
+	if (texture != 0 || textureView != 0)
+	{
+		CHAR strFileA[MAX_PATH];
+		WideCharToMultiByte(CP_ACP,
+			WC_NO_BEST_FIT_CHARS,
+			fileName,
+			-1,
+			strFileA,
+			MAX_PATH,
+			nullptr,
+			FALSE
+		);
+		const CHAR* pstrName = strrchr(strFileA, '\\');
+		if (!pstrName)
+		{
+			pstrName = strFileA;
+		}
+		else
+		{
+			pstrName++;
+		}
+
+		if (texture != 0 && *texture != 0)
+		{
+			(*texture)->SetPrivateData(WKPDID_D3DDebugObjectName,
+				static_cast<UINT>(strnlen_s(pstrName, MAX_PATH)),
+				pstrName
+			);
+		}
+
+		if (textureView != 0 && *textureView != 0)
+		{
+			(*textureView)->SetPrivateData(WKPDID_D3DDebugObjectName,
+				static_cast<UINT>(strnlen_s(pstrName, MAX_PATH)),
+				pstrName
+			);
+		}
+	}
+#endif
+
+	return hr;
+}

+ 55 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.h

@@ -0,0 +1,55 @@
+//--------------------------------------------------------------------------------------
+// File: WICTextureLoader.h
+//
+// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it
+// (auto-generating mipmaps if possible)
+//
+// Note: Assumes application has already called CoInitializeEx
+//
+// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for
+//          auto-gen mipmap support.
+//
+// Note these functions are useful for images created as simple 2D textures. For
+// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader.
+// For a full-featured DDS file reader, writer, and texture processing pipeline see
+// the 'Texconv' sample and the 'DirectXTex' library.
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// http://go.microsoft.com/fwlink/?LinkId=248926
+// http://go.microsoft.com/fwlink/?LinkId=248929
+//--------------------------------------------------------------------------------------
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include <d3d11.h>
+
+#pragma warning(push)
+#pragma warning(disable : 4005)
+#include <stdint.h>
+#pragma warning(pop)
+
+HRESULT CreateWICTextureFromMemory(_In_ ID3D11Device* d3dDevice,
+	_In_opt_ ID3D11DeviceContext* d3dContext,
+	_In_bytecount_(wicDataSize) const uint8_t* wicData,
+	_In_ size_t wicDataSize,
+	_Out_opt_ ID3D11Resource** texture,
+	_Out_opt_ ID3D11ShaderResourceView** textureView,
+	_In_ size_t maxsize = 0
+);
+
+HRESULT CreateWICTextureFromFile(_In_ ID3D11Device* d3dDevice,
+	_In_opt_ ID3D11DeviceContext* d3dContext,
+	_In_z_ const wchar_t* szFileName,
+	_Out_opt_ ID3D11Resource** texture,
+	_Out_opt_ ID3D11ShaderResourceView** textureView,
+	_In_ size_t maxsize = 0
+);
+

+ 23 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/VertexShader.hlsl

@@ -0,0 +1,23 @@
+cbuffer ConstantBuffer : register(b0)
+{
+	matrix World;
+	matrix View;
+	matrix Projection;
+}
+
+struct VOut {
+	float4 pos : SV_POSITION;
+	float2 texcoord : TEXCOORD;
+};
+
+VOut main(float4 pos : POSITION, float2 texcoord : TEXCOORD)
+{
+	VOut output;
+
+	output.pos = mul(pos, World);
+	output.pos = mul(output.pos, View);
+	output.pos = mul(output.pos, Projection);
+	output.texcoord = texcoord;
+
+	return output;
+}

+ 518 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp

@@ -0,0 +1,518 @@
+// ---------------------------------------------------------------------------
+// Simple Assimp Directx11 Sample
+// This is a very basic sample and only reads diffuse texture
+// but this can load both embedded textures in fbx and non-embedded textures
+//
+//
+// Replace ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx") this with your
+// model name (line 480)
+// If your model isn't a fbx with embedded textures make sure your model's
+// textures are in same directory as your model
+//
+//
+// Written by IAS. :)
+// ---------------------------------------------------------------------------
+
+#include <Windows.h>
+#include <windowsx.h>
+#include <d3d11_1.h>
+#include <dxgi1_2.h>
+#include <DirectXMath.h>
+#include <d3dcompiler.h>
+#include "ModelLoader.h"
+
+#pragma comment (lib, "d3d11.lib")
+#pragma comment (lib, "Dxgi.lib")
+#pragma comment(lib,"d3dcompiler.lib")
+#pragma comment (lib, "dxguid.lib")
+
+using namespace DirectX;
+
+// ------------------------------------------------------------
+//                        Structs
+// ------------------------------------------------------------
+struct ConstantBuffer {
+	XMMATRIX mWorld;
+	XMMATRIX mView;
+	XMMATRIX mProjection;
+};
+
+// ------------------------------------------------------------
+//                        Window Variables
+// ------------------------------------------------------------
+#define SCREEN_WIDTH  800
+#define SCREEN_HEIGHT 600
+
+const char g_szClassName[] = "directxWindowClass";
+
+
+UINT width, height;
+HWND hwnd;
+
+// ------------------------------------------------------------
+//                        DirectX Variables
+// ------------------------------------------------------------
+D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
+D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
+ID3D11Device *dev;
+ID3D11Device1 *dev1;
+ID3D11DeviceContext *devcon;
+ID3D11DeviceContext1 *devcon1;
+IDXGISwapChain *swapchain;
+IDXGISwapChain1 *swapchain1;
+ID3D11RenderTargetView *backbuffer;
+ID3D11VertexShader *pVS;
+ID3D11PixelShader *pPS;
+ID3D11InputLayout *pLayout;
+ID3D11Buffer *pConstantBuffer;
+ID3D11Texture2D *g_pDepthStencil;
+ID3D11DepthStencilView *g_pDepthStencilView;
+ID3D11SamplerState *TexSamplerState;
+
+XMMATRIX m_World;
+XMMATRIX m_View;
+XMMATRIX m_Projection;
+
+// ------------------------------------------------------------
+//                      Function identifiers
+// ------------------------------------------------------------
+
+void InitD3D(HINSTANCE hinstance, HWND hWnd);
+void CleanD3D(void);
+void RenderFrame(void);
+
+void InitPipeline();
+void InitGraphics();
+
+HRESULT	CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefines, LPCSTR pEntryPoint, LPCSTR pShaderModel, ID3DBlob** ppBytecodeBlob);
+void Throwanerror(LPCSTR errormessage);
+
+// ------------------------------------------------------------
+//                        Our Model
+// ------------------------------------------------------------
+
+ModelLoader *ourModel;
+
+LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+	switch (msg)
+	{
+	case WM_CLOSE:
+		DestroyWindow(hwnd);
+		break;
+	case WM_DESTROY:
+		PostQuitMessage(0);
+		break;
+	default:
+		return DefWindowProc(hwnd, msg, wParam, lParam);
+	}
+	return 0;
+}
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+	LPSTR lpCmdLine, int nCmdShow)
+{
+	WNDCLASSEX wc;
+	MSG msg;
+
+	wc.cbSize = sizeof(WNDCLASSEX);
+	wc.style = 0;
+	wc.lpfnWndProc = WndProc;
+	wc.cbClsExtra = 0;
+	wc.cbWndExtra = 0;
+	wc.hInstance = hInstance;
+	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+	wc.hbrBackground = NULL;
+	wc.lpszMenuName = NULL;
+	wc.lpszClassName = g_szClassName;
+	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+
+	if (!RegisterClassEx(&wc))
+	{
+		MessageBox(NULL, "Window Registration Failed!", "Error!",
+			MB_ICONEXCLAMATION | MB_OK);
+		return 0;
+	}
+
+	RECT wr = { 0,0, SCREEN_WIDTH, SCREEN_HEIGHT };
+	AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
+
+	hwnd = CreateWindowEx(
+		WS_EX_CLIENTEDGE,
+		g_szClassName,
+		" Simple Textured Directx11 Sample ",
+		WS_OVERLAPPEDWINDOW,
+		CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top,
+		NULL, NULL, hInstance, NULL
+	);
+
+	if (hwnd == NULL)
+	{
+		MessageBox(NULL, "Window Creation Failed!", "Error!",
+			MB_ICONEXCLAMATION | MB_OK);
+		return 0;
+	}
+
+	ShowWindow(hwnd, nCmdShow);
+	UpdateWindow(hwnd);
+
+	width = wr.right - wr.left;
+	height = wr.bottom - wr.top;
+
+	InitD3D(hInstance, hwnd);
+
+	while (true)
+	{
+
+		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+		{
+			TranslateMessage(&msg);
+			DispatchMessage(&msg);
+
+			if (msg.message == WM_QUIT)
+				break;
+		}
+
+		RenderFrame();
+	}
+
+	CleanD3D();
+
+	return msg.wParam;
+}
+
+void InitD3D(HINSTANCE hinstance, HWND hWnd)
+{
+	HRESULT hr;
+
+	UINT createDeviceFlags = 0;
+#ifdef _DEBUG
+	createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+	D3D_DRIVER_TYPE driverTypes[] =
+	{
+		D3D_DRIVER_TYPE_HARDWARE,
+		D3D_DRIVER_TYPE_WARP,
+		D3D_DRIVER_TYPE_REFERENCE,
+	};
+	UINT numDriverTypes = ARRAYSIZE(driverTypes);
+
+	D3D_FEATURE_LEVEL featureLevels[] =
+	{
+		D3D_FEATURE_LEVEL_11_1,
+		D3D_FEATURE_LEVEL_11_0,
+		D3D_FEATURE_LEVEL_10_1,
+		D3D_FEATURE_LEVEL_10_0,
+	};
+	UINT numFeatureLevels = ARRAYSIZE(featureLevels);
+
+	for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++)
+	{
+		g_driverType = driverTypes[driverTypeIndex];
+		hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
+			D3D11_SDK_VERSION, &dev, &g_featureLevel, &devcon);
+
+		if (hr == E_INVALIDARG)
+		{
+			// DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
+			hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1,
+				D3D11_SDK_VERSION, &dev, &g_featureLevel, &devcon);
+		}
+
+		if (SUCCEEDED(hr))
+			break;
+	}
+	if (FAILED(hr))
+		Throwanerror("Directx Device Creation Failed!");
+
+	UINT m4xMsaaQuality;
+	dev->CheckMultisampleQualityLevels(
+		DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality);
+
+
+	// Obtain DXGI factory from device (since we used nullptr for pAdapter above)
+	IDXGIFactory1* dxgiFactory = nullptr;
+	{
+		IDXGIDevice* dxgiDevice = nullptr;
+		hr = dev->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
+		if (SUCCEEDED(hr))
+		{
+			IDXGIAdapter* adapter = nullptr;
+			hr = dxgiDevice->GetAdapter(&adapter);
+			if (SUCCEEDED(hr))
+			{
+				hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory));
+				adapter->Release();
+			}
+			dxgiDevice->Release();
+		}
+	}
+	if (FAILED(hr))
+		Throwanerror("DXGI Factory couldn't be obtained!");
+
+	// Create swap chain
+	IDXGIFactory2* dxgiFactory2 = nullptr;
+	hr = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2));
+	if (dxgiFactory2)
+	{
+		// DirectX 11.1 or later
+		hr = dev->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast<void**>(&dev1));
+		if (SUCCEEDED(hr))
+		{
+			(void)devcon->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&devcon1));
+		}
+
+		DXGI_SWAP_CHAIN_DESC1 sd;
+		ZeroMemory(&sd, sizeof(sd));
+		sd.Width = SCREEN_WIDTH;
+		sd.Height = SCREEN_HEIGHT;
+		sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+		sd.SampleDesc.Count = 4;
+		sd.SampleDesc.Quality = m4xMsaaQuality - 1;
+		sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+		sd.BufferCount = 1;
+
+		hr = dxgiFactory2->CreateSwapChainForHwnd(dev, hWnd, &sd, nullptr, nullptr, &swapchain1);
+		if (SUCCEEDED(hr))
+		{
+			hr = swapchain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast<void**>(&swapchain));
+		}
+
+		dxgiFactory2->Release();
+	}
+	else
+	{
+		// DirectX 11.0 systems
+		DXGI_SWAP_CHAIN_DESC sd;
+		ZeroMemory(&sd, sizeof(sd));
+		sd.BufferCount = 1;
+		sd.BufferDesc.Width = SCREEN_WIDTH;
+		sd.BufferDesc.Height = SCREEN_HEIGHT;
+		sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+		sd.BufferDesc.RefreshRate.Numerator = 60;
+		sd.BufferDesc.RefreshRate.Denominator = 1;
+		sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+		sd.OutputWindow = hWnd;
+		sd.SampleDesc.Count = 1;
+		sd.SampleDesc.Quality = m4xMsaaQuality - 1;
+		sd.Windowed = TRUE;
+
+		hr = dxgiFactory->CreateSwapChain(dev, &sd, &swapchain);
+	}
+
+	// Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut
+	dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
+
+	dxgiFactory->Release();
+
+	if (FAILED(hr))
+		Throwanerror("Swapchain Creation Failed!");
+
+	ID3D11Texture2D *pBackBuffer;
+	swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
+
+	dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
+	pBackBuffer->Release();
+
+	D3D11_TEXTURE2D_DESC descDepth;
+	ZeroMemory(&descDepth, sizeof(descDepth));
+	descDepth.Width = SCREEN_WIDTH;
+	descDepth.Height = SCREEN_HEIGHT;
+	descDepth.MipLevels = 1;
+	descDepth.ArraySize = 1;
+	descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
+	descDepth.SampleDesc.Count = 4;
+	descDepth.SampleDesc.Quality = m4xMsaaQuality - 1;
+	descDepth.Usage = D3D11_USAGE_DEFAULT;
+	descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+	descDepth.CPUAccessFlags = 0;
+	descDepth.MiscFlags = 0;
+	hr = dev->CreateTexture2D(&descDepth, nullptr, &g_pDepthStencil);
+	if (FAILED(hr))
+		Throwanerror("Depth Stencil Texture couldn't be created!");
+
+	// Create the depth stencil view
+	D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
+	ZeroMemory(&descDSV, sizeof(descDSV));
+	descDSV.Format = descDepth.Format;
+	descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+	descDSV.Texture2D.MipSlice = 0;
+	hr = dev->CreateDepthStencilView(g_pDepthStencil, 0, &g_pDepthStencilView);
+	if (FAILED(hr))
+	{
+		Throwanerror("Depth Stencil View couldn't be created!");
+	}
+
+	devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView);
+
+	D3D11_RASTERIZER_DESC rasterDesc;
+	ID3D11RasterizerState *rasterState;
+	rasterDesc.AntialiasedLineEnable = false;
+	rasterDesc.CullMode = D3D11_CULL_BACK;
+	rasterDesc.DepthBias = 0;
+	rasterDesc.DepthBiasClamp = 0.0f;
+	rasterDesc.DepthClipEnable = true;
+	rasterDesc.FillMode = D3D11_FILL_SOLID;
+	rasterDesc.FrontCounterClockwise = false;
+	rasterDesc.MultisampleEnable = false;
+	rasterDesc.ScissorEnable = false;
+	rasterDesc.SlopeScaledDepthBias = 0.0f;
+
+	dev->CreateRasterizerState(&rasterDesc, &rasterState);
+	devcon->RSSetState(rasterState);
+
+	D3D11_VIEWPORT viewport;
+	ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
+
+	viewport.TopLeftX = 0;
+	viewport.TopLeftY = 0;
+	viewport.MinDepth = 0.0f;
+	viewport.MaxDepth = 1.0f;
+	viewport.Width = SCREEN_WIDTH;
+	viewport.Height = SCREEN_HEIGHT;
+
+	devcon->RSSetViewports(1, &viewport);
+
+	InitPipeline();
+	InitGraphics();
+}
+
+void CleanD3D(void)
+{
+	swapchain->SetFullscreenState(FALSE, NULL);
+
+	ourModel->Close();
+	g_pDepthStencil->Release();
+	g_pDepthStencilView->Release();
+	pLayout->Release();
+	pVS->Release();
+	pPS->Release();
+	pConstantBuffer->Release();
+	swapchain->Release();
+	backbuffer->Release();
+	dev->Release();
+	devcon->Release();
+}
+
+void RenderFrame(void)
+{
+	static float t = 0.0f;
+	static ULONGLONG timeStart = 0;
+	ULONGLONG timeCur = GetTickCount64();
+	if (timeStart == 0)
+		timeStart = timeCur;
+	t = (timeCur - timeStart) / 1000.0f;
+
+	float clearColor[4] = { 0.0f, 0.2f, 0.4f, 1.0f };
+	devcon->ClearRenderTargetView(backbuffer, clearColor);
+	devcon->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
+
+	devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+
+	m_World = XMMatrixRotationY(-t);
+
+	ConstantBuffer cb;
+	cb.mWorld = XMMatrixTranspose(m_World);
+	cb.mView = XMMatrixTranspose(m_View);
+	cb.mProjection = XMMatrixTranspose(m_Projection);
+	devcon->UpdateSubresource(pConstantBuffer, 0, nullptr, &cb, 0, 0);
+
+	devcon->VSSetShader(pVS, 0, 0);
+	devcon->VSSetConstantBuffers(0, 1, &pConstantBuffer);
+	devcon->PSSetShader(pPS, 0, 0);
+	devcon->PSSetSamplers(0, 1, &TexSamplerState);
+	ourModel->Draw(devcon);
+
+	swapchain->Present(0, 0);
+}
+
+void InitPipeline()
+{
+	ID3DBlob *VS, *PS;
+	CompileShaderFromFile(L"VertexShader.hlsl", 0, "main", "vs_4_0", &VS);
+	CompileShaderFromFile(L"PixelShader.hlsl", 0, "main", "ps_4_0", &PS);
+
+	dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
+	dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
+
+	D3D11_INPUT_ELEMENT_DESC ied[] =
+	{
+		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+		{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
+	};
+
+	dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
+	devcon->IASetInputLayout(pLayout);
+}
+
+void InitGraphics()
+{
+	HRESULT hr;
+
+	m_Projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.01f, 1000.0f);
+
+	D3D11_BUFFER_DESC bd;
+	ZeroMemory(&bd, sizeof(bd));
+
+	bd.Usage = D3D11_USAGE_DEFAULT;
+	bd.ByteWidth = sizeof(ConstantBuffer);
+	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+	bd.CPUAccessFlags = 0;
+
+	hr = dev->CreateBuffer(&bd, nullptr, &pConstantBuffer);
+	if (FAILED(hr))
+		Throwanerror("Constant buffer couldn't be created");
+
+	D3D11_SAMPLER_DESC sampDesc;
+	ZeroMemory(&sampDesc, sizeof(sampDesc));
+	sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+	sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
+	sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
+	sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
+	sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+	sampDesc.MinLOD = 0;
+	sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
+
+	hr = dev->CreateSamplerState(&sampDesc, &TexSamplerState);
+	if (FAILED(hr))
+		Throwanerror("Texture sampler state couldn't be created");
+
+	XMVECTOR Eye = XMVectorSet(0.0f, 5.0f, -300.0f, 0.0f);
+	XMVECTOR At = XMVectorSet(0.0f, 100.0f, 0.0f, 0.0f);
+	XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
+	m_View = XMMatrixLookAtLH(Eye, At, Up);
+
+	ourModel = new ModelLoader;
+	if (!ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx"))
+		Throwanerror("Model couldn't be loaded");
+}
+
+HRESULT	CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefines, LPCSTR pEntryPoint, LPCSTR pShaderModel, ID3DBlob** ppBytecodeBlob)
+{
+	UINT compileFlags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR;
+	
+#ifdef _DEBUG
+	compileFlags |= D3DCOMPILE_DEBUG;
+#endif
+
+	ID3DBlob* pErrorBlob = NULL;
+
+	HRESULT result = D3DCompileFromFile(pFileName, pDefines, D3D_COMPILE_STANDARD_FILE_INCLUDE, pEntryPoint, pShaderModel, compileFlags, 0, ppBytecodeBlob, &pErrorBlob);
+	if (FAILED(result))
+	{
+		if (pErrorBlob != NULL)
+			OutputDebugStringA((LPCSTR)pErrorBlob->GetBufferPointer());
+	}
+
+	if (pErrorBlob != NULL)
+		pErrorBlob->Release();
+
+	return result;
+}
+
+void Throwanerror(LPCSTR errormessage)
+{
+	MessageBox(hwnd, errormessage, "Error!", MB_ICONERROR | MB_OK);
+}

+ 28 - 4
test/unit/utObjTools.cpp

@@ -51,13 +51,23 @@ class utObjTools : public ::testing::Test {
 
 
 class TestObjFileParser : public ObjFileParser {
 class TestObjFileParser : public ObjFileParser {
 public:
 public:
-    TestObjFileParser() : ObjFileParser(){}
-    ~TestObjFileParser() {}
+    TestObjFileParser() : ObjFileParser(){
+        // empty
+    }
+
+    ~TestObjFileParser() {
+        // empty
+    }
+    
     void testCopyNextWord( char *pBuffer, size_t length ) {
     void testCopyNextWord( char *pBuffer, size_t length ) {
         copyNextWord( pBuffer, length );
         copyNextWord( pBuffer, length );
     }
     }
 
 
+    size_t testGetNumComponentsInDataDefinition() {
+        return getNumComponentsInDataDefinition();
+    }
 };
 };
+
 TEST_F( utObjTools, skipDataLine_OneLine_Success ) {
 TEST_F( utObjTools, skipDataLine_OneLine_Success ) {
     std::vector<char> buffer;
     std::vector<char> buffer;
     std::string data( "v -0.5 -0.5 0.5\nend" );
     std::string data( "v -0.5 -0.5 0.5\nend" );
@@ -71,7 +81,7 @@ TEST_F( utObjTools, skipDataLine_OneLine_Success ) {
 
 
 TEST_F( utObjTools, skipDataLine_TwoLines_Success ) {
 TEST_F( utObjTools, skipDataLine_TwoLines_Success ) {
     TestObjFileParser test_parser;
     TestObjFileParser test_parser;
-    std::string data( "vn -2.061493116917992e-15 -0.9009688496589661 \\n-0.4338837265968323" );
+    std::string data( "vn -2.061493116917992e-15 -0.9009688496589661 \\\n-0.4338837265968323" );
     std::vector<char> buffer;
     std::vector<char> buffer;
     buffer.resize( data.size() );
     buffer.resize( data.size() );
     ::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() );
     ::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() );
@@ -90,4 +100,18 @@ TEST_F( utObjTools, skipDataLine_TwoLines_Success ) {
 
 
     test_parser.testCopyNextWord( data_buffer, Size );
     test_parser.testCopyNextWord( data_buffer, Size );
     EXPECT_EQ( data_buffer[ 0 ], '-' );
     EXPECT_EQ( data_buffer[ 0 ], '-' );
-}
+}
+
+TEST_F( utObjTools, countComponents_TwoLines_Success ) {
+    TestObjFileParser test_parser;
+    std::string data( "-2.061493116917992e-15 -0.9009688496589661 \\\n-0.4338837265968323" );
+    std::vector<char> buffer;
+    buffer.resize( data.size() );
+    ::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() );
+    test_parser.setBuffer( buffer );
+    static const size_t Size = 4096UL;
+    char data_buffer[ Size ];
+
+    size_t numComps = test_parser.testGetNumComponentsInDataDefinition();
+    EXPECT_EQ( 3U, numComps );
+}

+ 3 - 2
test/unit/utPMXImporter.cpp

@@ -52,8 +52,9 @@ class utPMXImporter : public AbstractImportExportBase {
 public:
 public:
     virtual bool importerTest() {
     virtual bool importerTest() {
         Assimp::Importer importer;
         Assimp::Importer importer;
-        const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/../models-nonbsd/MMD/Alicia_blade.pmx", 0 );
-        return nullptr != scene;
+        /*const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/../models-nonbsd/MMD/Alicia_blade.pmx", 0 );
+        return nullptr != scene;*/
+        return true;
     }
     }
 };
 };
 
 

+ 2 - 0
tools/assimp_view/Display.cpp

@@ -43,6 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "SceneAnimator.h"
 #include "SceneAnimator.h"
 #include "StringUtils.h"
 #include "StringUtils.h"
 
 
+#include <commdlg.h>
+
 namespace AssimpView {
 namespace AssimpView {
 
 
 using namespace Assimp;
 using namespace Assimp;

+ 2 - 0
tools/assimp_view/LogWindow.cpp

@@ -41,6 +41,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include "assimp_view.h"
 #include "assimp_view.h"
 #include "richedit.h"
 #include "richedit.h"
+#include <commoncontrols.h>
+#include <commdlg.h>
 
 
 namespace AssimpView {
 namespace AssimpView {
 
 

+ 2 - 0
tools/assimp_view/MessageProc.cpp

@@ -44,6 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <algorithm>
 #include <algorithm>
 
 
 #include <windowsx.h>
 #include <windowsx.h>
+#include <commdlg.h>
+#include <timeapi.h>
 
 
 namespace AssimpView {
 namespace AssimpView {
 
 

+ 11 - 5
tools/assimp_view/SceneAnimator.h

@@ -72,20 +72,26 @@ struct SceneAnimNode
     size_t mChannelIndex;
     size_t mChannelIndex;
 
 
     //! Default construction
     //! Default construction
-    SceneAnimNode() {
-        mChannelIndex = -1; mParent = NULL;
+    SceneAnimNode()
+    : mName()
+    , mParent(NULL)
+    , mChannelIndex(-1) {
+        // empty
     }
     }
 
 
     //! Construction from a given name
     //! Construction from a given name
     SceneAnimNode( const std::string& pName)
     SceneAnimNode( const std::string& pName)
-        : mName( pName) {
-            mChannelIndex = -1; mParent = NULL;
+    : mName( pName)
+    , mParent(NULL)
+    , mChannelIndex( -1 ) {
+        // empty
     }
     }
 
 
     //! Destruct all children recursively
     //! Destruct all children recursively
     ~SceneAnimNode() {
     ~SceneAnimNode() {
-        for( std::vector<SceneAnimNode*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it)
+        for (std::vector<SceneAnimNode*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) {
             delete *it;
             delete *it;
+        }
     }
     }
 };
 };
 
 

+ 1 - 0
tools/assimp_view/assimp_view.cpp

@@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 
 
 #include "assimp_view.h"
 #include "assimp_view.h"
+#include <timeapi.h>
 #include "StringUtils.h"
 #include "StringUtils.h"
 #include <map>
 #include <map>