Selaa lähdekoodia

Merge branch '3mf_basematerial_support' of https://github.com/assimp/assimp into 3mf_basematerial_support

Kim Kulling 7 vuotta sitten
vanhempi
commit
c5c0052a6c

+ 5 - 0
CMakeLists.txt

@@ -230,6 +230,11 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW )
   ADD_DEFINITIONS( -U__STRICT_ANSI__ )
   ADD_DEFINITIONS( -U__STRICT_ANSI__ )
 ENDIF()
 ENDIF()
 
 
+if (IOS)
+    set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -fembed-bitcode -O3")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3")
+endif()
+
 if (ASSIMP_COVERALLS)
 if (ASSIMP_COVERALLS)
     MESSAGE(STATUS "Coveralls enabled")
     MESSAGE(STATUS "Coveralls enabled")
     INCLUDE(Coveralls)
     INCLUDE(Coveralls)

+ 1 - 1
code/3DSLoader.cpp

@@ -349,7 +349,7 @@ void Discreet3DSImporter::ParseObjectChunk()
     case Discreet3DS::CHUNK_MAT_MATERIAL:
     case Discreet3DS::CHUNK_MAT_MATERIAL:
 
 
         // Add a new material to the list
         // Add a new material to the list
-        mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + std::to_string(mScene->mMaterials.size()))));
+        mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + to_string(mScene->mMaterials.size()))));
         ParseMaterialChunk();
         ParseMaterialChunk();
         break;
         break;
 
 

+ 1 - 0
code/CMakeLists.txt

@@ -72,6 +72,7 @@ SET( PUBLIC_HEADERS
   ${HEADER_PATH}/matrix4x4.h
   ${HEADER_PATH}/matrix4x4.h
   ${HEADER_PATH}/matrix4x4.inl
   ${HEADER_PATH}/matrix4x4.inl
   ${HEADER_PATH}/mesh.h
   ${HEADER_PATH}/mesh.h
+  ${HEADER_PATH}/pbrmaterial.h
   ${HEADER_PATH}/postprocess.h
   ${HEADER_PATH}/postprocess.h
   ${HEADER_PATH}/quaternion.h
   ${HEADER_PATH}/quaternion.h
   ${HEADER_PATH}/quaternion.inl
   ${HEADER_PATH}/quaternion.inl

+ 6 - 0
code/ColladaLoader.cpp

@@ -131,6 +131,7 @@ void ColladaLoader::SetupProperties(const Importer* pImp)
 {
 {
     noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
     noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
     ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
     ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
+    useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES,0) != 0;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -1913,6 +1914,11 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c
 // The name must be unique for proper node-bone association.
 // The name must be unique for proper node-bone association.
 std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
 std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
 {
 {
+    // If explicitly requested, just use the collada name.
+    if (useColladaName) {
+        return pNode->mName;
+    }
+
     // Now setup the name of the assimp node. The collada name might not be
     // Now setup the name of the assimp node. The collada name might not be
     // unique, so we use the collada ID.
     // unique, so we use the collada ID.
     if (!pNode->mID.empty())
     if (!pNode->mID.empty())

+ 1 - 0
code/ColladaLoader.h

@@ -248,6 +248,7 @@ protected:
 
 
     bool noSkeletonMesh;
     bool noSkeletonMesh;
     bool ignoreUpDirection;
     bool ignoreUpDirection;
+    bool useColladaName;
 
 
     /** Used by FindNameForNode() to generate unique node names */
     /** Used by FindNameForNode() to generate unique node names */
     unsigned int mNodeNameCounter;
     unsigned int mNodeNameCounter;

+ 5 - 3
code/FBXExporter.cpp

@@ -235,9 +235,6 @@ void FBXExporter::WriteBinaryFooter()
     outfile->Write(NULL_RECORD.c_str(), NULL_RECORD.size(), 1);
     outfile->Write(NULL_RECORD.c_str(), NULL_RECORD.size(), 1);
 
 
     outfile->Write(GENERIC_FOOTID.c_str(), GENERIC_FOOTID.size(), 1);
     outfile->Write(GENERIC_FOOTID.c_str(), GENERIC_FOOTID.size(), 1);
-    for (size_t i = 0; i < 4; ++i) {
-        outfile->Write("\x00", 1, 1);
-    }
 
 
     // here some padding is added for alignment to 16 bytes.
     // here some padding is added for alignment to 16 bytes.
     // if already aligned, the full 16 bytes is added.
     // if already aligned, the full 16 bytes is added.
@@ -247,6 +244,11 @@ void FBXExporter::WriteBinaryFooter()
         outfile->Write("\x00", 1, 1);
         outfile->Write("\x00", 1, 1);
     }
     }
 
 
+    // not sure what this is, but it seems to always be 0 in modern files
+    for (size_t i = 0; i < 4; ++i) {
+        outfile->Write("\x00", 1, 1);
+    }
+
     // now the file version again
     // now the file version again
     {
     {
         StreamWriterLE outstream(outfile);
         StreamWriterLE outstream(outfile);

+ 6 - 3
code/FBXMaterial.cpp

@@ -54,6 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "FBXProperties.h"
 #include "FBXProperties.h"
 #include <assimp/ByteSwapper.h>
 #include <assimp/ByteSwapper.h>
 
 
+#include <algorithm> // std::transform
+
 namespace Assimp {
 namespace Assimp {
 namespace FBX {
 namespace FBX {
 
 
@@ -82,11 +84,12 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
 
 
     std::string templateName;
     std::string templateName;
 
 
-    const char* const sh = shading.c_str();
-    if(!strcmp(sh,"phong")) {
+    // lower-case shading because Blender (for example) writes "Phong"
+    std::transform(shading.begin(), shading.end(), shading.begin(), ::tolower);
+    if(shading == "phong") {
         templateName = "Material.FbxSurfacePhong";
         templateName = "Material.FbxSurfacePhong";
     }
     }
-    else if(!strcmp(sh,"lambert")) {
+    else if(shading == "lambert") {
         templateName = "Material.FbxSurfaceLambert";
         templateName = "Material.FbxSurfaceLambert";
     }
     }
     else {
     else {

+ 3 - 2
code/ObjFileMtlImporter.cpp

@@ -303,11 +303,12 @@ void ObjFileMtlImporter::createMaterial()
         // New Material created
         // New Material created
         m_pModel->m_pCurrentMaterial = new ObjFile::Material();
         m_pModel->m_pCurrentMaterial = new ObjFile::Material();
         m_pModel->m_pCurrentMaterial->MaterialName.Set( name );
         m_pModel->m_pCurrentMaterial->MaterialName.Set( name );
+        m_pModel->m_MaterialLib.push_back( name );
+        m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial;
+
         if (m_pModel->m_pCurrentMesh) {
         if (m_pModel->m_pCurrentMesh) {
             m_pModel->m_pCurrentMesh->m_uiMaterialIndex = static_cast<unsigned int>(m_pModel->m_MaterialLib.size() - 1);
             m_pModel->m_pCurrentMesh->m_uiMaterialIndex = static_cast<unsigned int>(m_pModel->m_MaterialLib.size() - 1);
         }
         }
-        m_pModel->m_MaterialLib.push_back( name );
-        m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial;
     } else {
     } else {
         // Use older material
         // Use older material
         m_pModel->m_pCurrentMaterial = (*it).second;
         m_pModel->m_pCurrentMaterial = (*it).second;

+ 1 - 22
code/PlyLoader.cpp

@@ -245,28 +245,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
     // list is containing a list of points
     // list is containing a list of points
     bool pointsOnly = mGeneratedMesh->mFaces == NULL ? true : false;
     bool pointsOnly = mGeneratedMesh->mFaces == NULL ? true : false;
     if (pointsOnly) {
     if (pointsOnly) {
-        if (mGeneratedMesh->mNumVertices < 3) {
-            if (mGeneratedMesh != NULL) {
-                delete(mGeneratedMesh);
-                mGeneratedMesh = nullptr;
-            }
-
-            streamedBuffer.close();
-            throw DeadlyImportError("Invalid .ply file: Not enough "
-                    "vertices to build a proper face list. ");
-        }
-
-        const unsigned int iNum = (unsigned int)mGeneratedMesh->mNumVertices / 3;
-        mGeneratedMesh->mNumFaces = iNum;
-        mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
-
-        for (unsigned int i = 0; i < iNum; ++i) {
-            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;
-        }
+      mGeneratedMesh->mPrimitiveTypes = aiPrimitiveType::aiPrimitiveType_POINT;
     }
     }
 
 
     // now load a list of all materials
     // now load a list of all materials

+ 44 - 24
code/PlyParser.cpp

@@ -1043,71 +1043,91 @@ bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer<char> &streamBuffer,
   switch (eType)
   switch (eType)
   {
   {
   case EDT_UInt:
   case EDT_UInt:
-    out->iUInt = (uint32_t)*((uint32_t*)pCur);
-    pCur += 4;
+  {
+    uint32_t t;
+    memcpy(&t, pCur, sizeof(uint32_t));
+    pCur += sizeof(uint32_t);
 
 
     // Swap endianness
     // Swap endianness
-    if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt);
+    if (p_bBE)ByteSwap::Swap(&t);
+    out->iUInt = t;
     break;
     break;
+  }
 
 
   case EDT_UShort:
   case EDT_UShort:
   {
   {
-    uint16_t i = *((uint16_t*)pCur);
+    uint16_t t;
+    memcpy(&t, pCur, sizeof(uint16_t));
+    pCur += sizeof(uint16_t);
 
 
     // Swap endianness
     // Swap endianness
-    if (p_bBE)ByteSwap::Swap(&i);
-    out->iUInt = (uint32_t)i;
-    pCur += 2;
+    if (p_bBE)ByteSwap::Swap(&t);
+    out->iUInt = t;
     break;
     break;
   }
   }
 
 
   case EDT_UChar:
   case EDT_UChar:
   {
   {
-    out->iUInt = (uint32_t)(*((uint8_t*)pCur));
-    pCur++;
+    uint8_t t;
+    memcpy(&t, pCur, sizeof(uint8_t));
+    pCur += sizeof(uint8_t);
+    out->iUInt = t;
     break;
     break;
   }
   }
 
 
   case EDT_Int:
   case EDT_Int:
-    out->iInt = *((int32_t*)pCur);
-    pCur += 4;
+  {
+    int32_t t;
+    memcpy(&t, pCur, sizeof(int32_t));
+    pCur += sizeof(int32_t);
 
 
     // Swap endianness
     // Swap endianness
-    if (p_bBE)ByteSwap::Swap(&out->iInt);
+    if (p_bBE)ByteSwap::Swap(&t);
+    out->iInt = t;
     break;
     break;
+  }
 
 
   case EDT_Short:
   case EDT_Short:
   {
   {
-    int16_t i = *((int16_t*)pCur);
+    int16_t t;
+    memcpy(&t, pCur, sizeof(int16_t));
+    pCur += sizeof(int16_t);
 
 
     // Swap endianness
     // Swap endianness
-    if (p_bBE)ByteSwap::Swap(&i);
-    out->iInt = (int32_t)i;
-    pCur += 2;
+    if (p_bBE)ByteSwap::Swap(&t);
+    out->iInt = t;
     break;
     break;
   }
   }
 
 
   case EDT_Char:
   case EDT_Char:
-    out->iInt = (int32_t)*((int8_t*)pCur);
-    pCur++;
+  {
+    int8_t t;
+    memcpy(&t, pCur, sizeof(int8_t));
+    pCur += sizeof(int8_t);
+    out->iInt = t;
     break;
     break;
+  }
 
 
   case EDT_Float:
   case EDT_Float:
   {
   {
-    out->fFloat = *((float*)pCur);
+    float t;
+    memcpy(&t, pCur, sizeof(float));
+    pCur += sizeof(float);
 
 
     // Swap endianness
     // Swap endianness
-    if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat);
-    pCur += 4;
+    if (p_bBE)ByteSwap::Swap(&t);
+    out->fFloat = t;
     break;
     break;
   }
   }
   case EDT_Double:
   case EDT_Double:
   {
   {
-    out->fDouble = *((double*)pCur);
+    double t;
+    memcpy(&t, pCur, sizeof(double));
+    pCur += sizeof(double);
 
 
     // Swap endianness
     // Swap endianness
-    if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble);
-    pCur += 8;
+    if (p_bBE)ByteSwap::Swap(&t);
+    out->fDouble = t;
     break;
     break;
   }
   }
   default:
   default:

+ 6 - 2
code/STLExporter.cpp

@@ -172,12 +172,16 @@ void STLExporter :: WriteMeshBinary(const aiMesh* m)
             }
             }
             nor.Normalize();
             nor.Normalize();
         }
         }
-        ai_real nx = nor.x, ny = nor.y, nz = nor.z;
+        // STL binary files use 4-byte floats. This may possibly cause loss of precision
+        // for clients using 8-byte doubles
+        float nx = (float) nor.x;
+        float ny = (float) nor.y;
+        float nz = (float) nor.z;
         AI_SWAP4(nx); AI_SWAP4(ny); AI_SWAP4(nz);
         AI_SWAP4(nx); AI_SWAP4(ny); AI_SWAP4(nz);
         mOutput.write((char *)&nx, 4); mOutput.write((char *)&ny, 4); mOutput.write((char *)&nz, 4);
         mOutput.write((char *)&nx, 4); mOutput.write((char *)&ny, 4); mOutput.write((char *)&nz, 4);
         for(unsigned int a = 0; a < f.mNumIndices; ++a) {
         for(unsigned int a = 0; a < f.mNumIndices; ++a) {
             const aiVector3D& v  = m->mVertices[f.mIndices[a]];
             const aiVector3D& v  = m->mVertices[f.mIndices[a]];
-            ai_real vx = v.x, vy = v.y, vz = v.z;
+            float vx = (float) v.x, vy = (float) v.y, vz = (float) v.z;
             AI_SWAP4(vx); AI_SWAP4(vy); AI_SWAP4(vz);
             AI_SWAP4(vx); AI_SWAP4(vy); AI_SWAP4(vz);
             mOutput.write((char *)&vx, 4); mOutput.write((char *)&vy, 4); mOutput.write((char *)&vz, 4);
             mOutput.write((char *)&vx, 4); mOutput.write((char *)&vy, 4); mOutput.write((char *)&vz, 4);
         }
         }

+ 14 - 1
code/glTF2Asset.inl

@@ -669,7 +669,7 @@ inline Image::Image()
 
 
 }
 }
 
 
-inline void Image::Read(Value& obj, Asset& /*r*/)
+inline void Image::Read(Value& obj, Asset& r)
 {
 {
     if (!mDataLength) {
     if (!mDataLength) {
         if (Value* uri = FindString(obj, "uri")) {
         if (Value* uri = FindString(obj, "uri")) {
@@ -686,6 +686,19 @@ inline void Image::Read(Value& obj, Asset& /*r*/)
                 this->uri = uristr;
                 this->uri = uristr;
             }
             }
         }
         }
+        else if (Value* bufferViewVal = FindUInt(obj, "bufferView")) {
+            this->bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint());
+            Ref<Buffer> buffer = this->bufferView->buffer;
+
+            this->mDataLength = this->bufferView->byteLength;
+            // maybe this memcpy could be avoided if aiTexture does not delete[] pcData at destruction.
+            this->mData = new uint8_t [this->mDataLength];
+            memcpy(this->mData, buffer->GetPointer() + this->bufferView->byteOffset, this->mDataLength);
+
+            if (Value* mtype = FindString(obj, "mimeType")) {
+                this->mimeType = mtype->GetString();
+            }
+        }
     }
     }
 }
 }
 
 

+ 8 - 8
code/glTFAsset.inl

@@ -948,24 +948,24 @@ Ref<Buffer> buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer);
 	size_t size_coordindex = ifs.GetNCoordIndex() * 3;// See float attributes note.
 	size_t size_coordindex = ifs.GetNCoordIndex() * 3;// See float attributes note.
 
 
 	if(primitives[0].indices->count != size_coordindex)
 	if(primitives[0].indices->count != size_coordindex)
-		throw DeadlyImportError("GLTF: Open3DGC. Compressed indices count (" + std::to_string(size_coordindex) +
-								") not equal to uncompressed (" + std::to_string(primitives[0].indices->count) + ").");
+		throw DeadlyImportError("GLTF: Open3DGC. Compressed indices count (" + to_string(size_coordindex) +
+								") not equal to uncompressed (" + to_string(primitives[0].indices->count) + ").");
 
 
 	size_coordindex *= sizeof(IndicesType);
 	size_coordindex *= sizeof(IndicesType);
 	// Coordinates
 	// Coordinates
 	size_t size_coord = ifs.GetNCoord();// See float attributes note.
 	size_t size_coord = ifs.GetNCoord();// See float attributes note.
 
 
 	if(primitives[0].attributes.position[0]->count != size_coord)
 	if(primitives[0].attributes.position[0]->count != size_coord)
-		throw DeadlyImportError("GLTF: Open3DGC. Compressed positions count (" + std::to_string(size_coord) +
-								") not equal to uncompressed (" + std::to_string(primitives[0].attributes.position[0]->count) + ").");
+		throw DeadlyImportError("GLTF: Open3DGC. Compressed positions count (" + to_string(size_coord) +
+								") not equal to uncompressed (" + to_string(primitives[0].attributes.position[0]->count) + ").");
 
 
 	size_coord *= 3 * sizeof(float);
 	size_coord *= 3 * sizeof(float);
 	// Normals
 	// Normals
 	size_t size_normal = ifs.GetNNormal();// See float attributes note.
 	size_t size_normal = ifs.GetNNormal();// See float attributes note.
 
 
 	if(primitives[0].attributes.normal[0]->count != size_normal)
 	if(primitives[0].attributes.normal[0]->count != size_normal)
-		throw DeadlyImportError("GLTF: Open3DGC. Compressed normals count (" + std::to_string(size_normal) +
-								") not equal to uncompressed (" + std::to_string(primitives[0].attributes.normal[0]->count) + ").");
+		throw DeadlyImportError("GLTF: Open3DGC. Compressed normals count (" + to_string(size_normal) +
+								") not equal to uncompressed (" + to_string(primitives[0].attributes.normal[0]->count) + ").");
 
 
 	size_normal *= 3 * sizeof(float);
 	size_normal *= 3 * sizeof(float);
 	// Additional attributes.
 	// Additional attributes.
@@ -989,8 +989,8 @@ Ref<Buffer> buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer);
 				if(idx_texcoord < primitives[0].attributes.texcoord.size())
 				if(idx_texcoord < primitives[0].attributes.texcoord.size())
 				{
 				{
 					if(primitives[0].attributes.texcoord[idx]->count != tval)
 					if(primitives[0].attributes.texcoord[idx]->count != tval)
-						throw DeadlyImportError("GLTF: Open3DGC. Compressed texture coordinates count (" + std::to_string(tval) +
-												") not equal to uncompressed (" + std::to_string(primitives[0].attributes.texcoord[idx]->count) + ").");
+						throw DeadlyImportError("GLTF: Open3DGC. Compressed texture coordinates count (" + to_string(tval) +
+												") not equal to uncompressed (" + to_string(primitives[0].attributes.texcoord[idx]->count) + ").");
 
 
 					idx_texcoord++;
 					idx_texcoord++;
 				}
 				}

+ 9 - 2
code/glTFImporter.cpp

@@ -194,9 +194,16 @@ void glTFImporter::ImportMaterials(glTF::Asset& r)
             aimat->AddProperty(&str, AI_MATKEY_NAME);
             aimat->AddProperty(&str, AI_MATKEY_NAME);
         }
         }
 
 
-        SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE);
+        SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient,  aimat, aiTextureType_AMBIENT,  AI_MATKEY_COLOR_AMBIENT );
+        SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse,  aimat, aiTextureType_DIFFUSE,  AI_MATKEY_COLOR_DIFFUSE );
         SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR);
         SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR);
-        SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT);
+        SetMaterialColorProperty(embeddedTexIdxs, r, mat.emission, aimat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE);
+
+        aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED);
+
+        if (mat.transparent && (mat.transparency != 1.0f)) {
+            aimat->AddProperty(&mat.transparency, 1, AI_MATKEY_OPACITY);
+        }
 
 
         if (mat.shininess > 0.f) {
         if (mat.shininess > 0.f) {
             aimat->AddProperty(&mat.shininess, 1, AI_MATKEY_SHININESS);
             aimat->AddProperty(&mat.shininess, 1, AI_MATKEY_SHININESS);

+ 3 - 2
contrib/zlib/zlib.h

@@ -77,8 +77,9 @@ extern "C" {
   the consistency of the compressed data, so the library should never crash
   the consistency of the compressed data, so the library should never crash
   even in the case of corrupted input.
   even in the case of corrupted input.
 */
 */
-#ifdef __ANDROID__     
-using zcrc_t = unsigned_long; 
+
+#ifdef __ANDROID__
+typedef unsigned long zcrc_t;
 #endif
 #endif
 
 
 typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
 typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));

+ 10 - 0
include/assimp/config.h.in

@@ -934,6 +934,16 @@ enum aiComponent
  */
  */
 #define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION"
 #define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION"
 
 
+// ---------------------------------------------------------------------------
+/** @brief Specifies whether the Collada loader should use Collada names as node names.
+ *
+ * If this property is set to true, the Collada names will be used as the
+ * node name. The default is to use the id tag (resp. sid tag, if no id tag is present)
+ * instead.
+ * Property type: Bool. Default value: false.
+ */
+#define AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES "IMPORT_COLLADA_USE_COLLADA_NAMES"
+
 // ---------- All the Export defines ------------
 // ---------- All the Export defines ------------
 
 
 /** @brief Specifies the xfile use double for real values of float
 /** @brief Specifies the xfile use double for real values of float

+ 5 - 0
test/models/OBJ/cube_mtllib_after_g.mtl

@@ -0,0 +1,5 @@
+newmtl MyMaterial
+Ka 1.000 1.000 1.000
+Kd 1.000 1.000 1.000
+Ns 200.000
+Ks 0.050 0.050 0.050

+ 32 - 0
test/models/OBJ/cube_mtllib_after_g.obj

@@ -0,0 +1,32 @@
+g Object
+mtllib cube_mtllib_after_g.mat
+usemtl MyMaterial
+
+v  0.0  0.0  0.0
+v  0.0  0.0  1.0
+v  0.0  1.0  0.0
+v  0.0  1.0  1.0
+v  1.0  0.0  0.0
+v  1.0  0.0  1.0
+v  1.0  1.0  0.0
+v  1.0  1.0  1.0
+
+vn  0.0  0.0  1.0
+vn  0.0  0.0 -1.0
+vn  0.0  1.0  0.0
+vn  0.0 -1.0  0.0
+vn  1.0  0.0  0.0
+vn -1.0  0.0  0.0
+
+f  1//2  7//2  5//2
+f  1//2  3//2  7//2 
+f  1//6  4//6  3//6 
+f  1//6  2//6  4//6 
+f  3//3  8//3  7//3 
+f  3//3  4//3  8//3 
+f  5//5  7//5  8//5 
+f  5//5  8//5  6//5 
+f  1//4  5//4  6//4 
+f  1//4  6//4  2//4 
+f  2//1  6//1  8//1 
+f  2//1  8//1  4//1 

BIN
test/models/PLY/cube_binary.ply


+ 45 - 0
test/models/PLY/cube_uv.ply

@@ -0,0 +1,45 @@
+ply
+format ascii 1.0
+comment Created by Blender 2.77 (sub 0) - www.blender.org, source file: ''
+element vertex 24
+property float x
+property float y
+property float z
+property float nx
+property float ny
+property float nz
+property float s
+property float t
+element face 6
+property list uchar uint vertex_indices
+end_header
+1.000000 1.000000 -1.000000 0.000000 0.000000 -1.000000 0.000000 0.000000
+1.000000 -1.000000 -1.000000 0.000000 0.000000 -1.000000 1.000000 0.000000
+-1.000000 -1.000000 -1.000000 0.000000 0.000000 -1.000000 1.000000 1.000000
+-1.000000 1.000000 -1.000000 0.000000 0.000000 -1.000000 0.000000 1.000000
+1.000000 0.999999 1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000
+-1.000000 1.000000 1.000000 0.000000 -0.000000 1.000000 1.000000 0.000000
+-1.000000 -1.000000 1.000000 0.000000 -0.000000 1.000000 1.000000 1.000000
+0.999999 -1.000001 1.000000 0.000000 -0.000000 1.000000 0.000000 1.000000
+1.000000 1.000000 -1.000000 1.000000 -0.000000 0.000000 0.000000 0.000000
+1.000000 0.999999 1.000000 1.000000 -0.000000 0.000000 1.000000 0.000000
+0.999999 -1.000001 1.000000 1.000000 -0.000000 0.000000 1.000000 1.000000
+1.000000 -1.000000 -1.000000 1.000000 -0.000000 0.000000 0.000000 1.000000
+1.000000 -1.000000 -1.000000 -0.000000 -1.000000 -0.000000 0.000000 0.000000
+0.999999 -1.000001 1.000000 -0.000000 -1.000000 -0.000000 1.000000 0.000000
+-1.000000 -1.000000 1.000000 -0.000000 -1.000000 -0.000000 1.000000 1.000000
+-1.000000 -1.000000 -1.000000 -0.000000 -1.000000 -0.000000 0.000000 1.000000
+-1.000000 -1.000000 -1.000000 -1.000000 0.000000 -0.000000 0.000000 0.000000
+-1.000000 -1.000000 1.000000 -1.000000 0.000000 -0.000000 1.000000 0.000000
+-1.000000 1.000000 1.000000 -1.000000 0.000000 -0.000000 1.000000 1.000000
+-1.000000 1.000000 -1.000000 -1.000000 0.000000 -0.000000 0.000000 1.000000
+1.000000 0.999999 1.000000 0.000000 1.000000 0.000000 0.000000 0.000000
+1.000000 1.000000 -1.000000 0.000000 1.000000 0.000000 1.000000 0.000000
+-1.000000 1.000000 -1.000000 0.000000 1.000000 0.000000 1.000000 1.000000
+-1.000000 1.000000 1.000000 0.000000 1.000000 0.000000 0.000000 1.000000
+4 0 1 2 3
+4 4 5 6 7
+4 8 9 10 11
+4 12 13 14 15
+4 16 17 18 19
+4 20 21 22 23

+ 1 - 1
test/models/PLY/float-color.ply

@@ -15,4 +15,4 @@ end_header
 0.0 0.0 0.0 0 0 1 1
 0.0 0.0 0.0 0 0 1 1
 100.0 0.0 0.0 0 0 1 1
 100.0 0.0 0.0 0 0 1 1
 200.0 200.0 0.0 0 0 1 1
 200.0 200.0 0.0 0 0 1 1
-3 0 1 2
+3 0 1 2

+ 36 - 0
test/models/PLY/issue623.ply

@@ -0,0 +1,36 @@
+ply
+format ascii 1.0
+comment Created by Blender 2.77 (sub 0) - www.blender.org, source file: ''
+element vertex 24
+property float x
+property float y
+property float z
+property float nx
+property float ny
+property float nz
+property list uchar uint vertex_indices
+end_header
+7.941797 1.432409 -0.927566 0.000000 0.000000 -1.000000
+7.941797 -2.321273 -0.927566 0.000000 0.000000 -1.000000
+4.188114 -2.321273 -0.927566 0.000000 0.000000 -1.000000
+4.188115 1.432410 -0.927566 0.000000 0.000000 -1.000000
+7.941798 1.432408 2.826117 0.000000 -0.000000 1.000000
+4.188114 1.432409 2.826117 0.000000 -0.000000 1.000000
+4.188113 -2.321273 2.826117 0.000000 -0.000000 1.000000
+7.941795 -2.321275 2.826117 0.000000 -0.000000 1.000000
+7.941797 1.432409 -0.927566 1.000000 -0.000000 0.000000
+7.941798 1.432408 2.826117 1.000000 -0.000000 0.000000
+7.941795 -2.321275 2.826117 1.000000 -0.000000 0.000000
+7.941797 -2.321273 -0.927566 1.000000 -0.000000 0.000000
+7.941797 -2.321273 -0.927566 -0.000000 -1.000000 -0.000000
+7.941795 -2.321275 2.826117 -0.000000 -1.000000 -0.000000
+4.188113 -2.321273 2.826117 -0.000000 -1.000000 -0.000000
+4.188114 -2.321273 -0.927566 -0.000000 -1.000000 -0.000000
+4.188114 -2.321273 -0.927566 -1.000000 0.000000 -0.000000
+4.188113 -2.321273 2.826117 -1.000000 0.000000 -0.000000
+4.188114 1.432409 2.826117 -1.000000 0.000000 -0.000000
+4.188115 1.432410 -0.927566 -1.000000 0.000000 -0.000000
+7.941798 1.432408 2.826117 0.000000 1.000000 0.000000
+7.941797 1.432409 -0.927566 0.000000 1.000000 0.000000
+4.188115 1.432410 -0.927566 0.000000 1.000000 0.000000
+4.188114 1.432409 2.826117 0.000000 1.000000 0.000000

+ 13 - 0
test/unit/utObjImportExport.cpp

@@ -354,3 +354,16 @@ TEST_F(utObjImportExport, 0based_array_Test) {
     const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), 0);
     const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), 0);
     EXPECT_EQ(nullptr, scene);
     EXPECT_EQ(nullptr, scene);
 }
 }
+
+TEST_F( utObjImportExport, mtllib_after_g ) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/cube_mtllib_after_g.obj", aiProcess_ValidateDataStructure );
+    ASSERT_NE( nullptr, scene );
+
+    EXPECT_EQ(scene->mNumMeshes, 1U);
+    const aiMesh *mesh = scene->mMeshes[0];
+    const aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
+    aiString name;
+    ASSERT_EQ(aiReturn_SUCCESS, mat->Get(AI_MATKEY_NAME, name));
+    EXPECT_STREQ("MyMaterial", name.C_Str());
+}

+ 55 - 6
test/unit/utPLYImportExport.cpp

@@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/Exporter.hpp>
 #include <assimp/Exporter.hpp>
 #include <assimp/scene.h>
 #include <assimp/scene.h>
 #include "AbstractImportExportBase.h"
 #include "AbstractImportExportBase.h"
+#include <assimp/postprocess.h>
 
 
 using namespace ::Assimp;
 using namespace ::Assimp;
 
 
@@ -52,7 +53,7 @@ class utPLYImportExport : 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 "/PLY/cube.ply", 0 );
+        const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure);
         EXPECT_EQ( 1u, scene->mNumMeshes );
         EXPECT_EQ( 1u, scene->mNumMeshes );
         EXPECT_NE( nullptr, scene->mMeshes[0] );
         EXPECT_NE( nullptr, scene->mMeshes[0] );
         EXPECT_EQ( 8u, scene->mMeshes[0]->mNumVertices );
         EXPECT_EQ( 8u, scene->mMeshes[0]->mNumVertices );
@@ -65,7 +66,7 @@ public:
     virtual bool exporterTest() {
     virtual bool exporterTest() {
         Importer importer;
         Importer importer;
         Exporter exporter;
         Exporter exporter;
-        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", 0);
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure);
         EXPECT_NE(nullptr, scene);
         EXPECT_NE(nullptr, scene);
         EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "ply", ASSIMP_TEST_MODELS_DIR "/PLY/cube_test.ply"));
         EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "ply", ASSIMP_TEST_MODELS_DIR "/PLY/cube_test.ply"));
 
 
@@ -89,19 +90,66 @@ TEST_F(utPLYImportExport, exportTest_Success ) {
 //Test issue 1623, crash when loading two PLY files in a row
 //Test issue 1623, crash when loading two PLY files in a row
 TEST_F(utPLYImportExport, importerMultipleTest) {
 TEST_F(utPLYImportExport, importerMultipleTest) {
     Assimp::Importer importer;
     Assimp::Importer importer;
-    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", 0);
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure);
 
 
     EXPECT_NE(nullptr, scene);
     EXPECT_NE(nullptr, scene);
 
 
-    scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", 0);
+    scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure);
 
 
     EXPECT_NE(nullptr, scene);
     EXPECT_NE(nullptr, scene);
+    EXPECT_NE(nullptr, scene->mMeshes[0]);
+    EXPECT_EQ(6u, scene->mMeshes[0]->mNumFaces);
+}
+
+TEST_F(utPLYImportExport, importPLYwithUV) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube_uv.ply", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+    EXPECT_NE(nullptr, scene->mMeshes[0]);
+    //This test model is using n-gons, so 6 faces instead of 12 tris
+    EXPECT_EQ(6u, scene->mMeshes[0]->mNumFaces);
+    EXPECT_EQ(aiPrimitiveType_POLYGON, scene->mMeshes[0]->mPrimitiveTypes);
+    EXPECT_EQ(true, scene->mMeshes[0]->HasTextureCoords(0));
+}
+
+TEST_F(utPLYImportExport, importBinaryPLY) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube_binary.ply", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+    EXPECT_NE(nullptr, scene->mMeshes[0]);
+    //This test model is double sided, so 12 faces instead of 6
+    EXPECT_EQ(12u, scene->mMeshes[0]->mNumFaces);
 }
 }
 
 
 TEST_F( utPLYImportExport, vertexColorTest ) {
 TEST_F( utPLYImportExport, vertexColorTest ) {
     Assimp::Importer importer;
     Assimp::Importer importer;
-    const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/float-color.ply", 0 );
+    const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/float-color.ply", aiProcess_ValidateDataStructure);
     EXPECT_NE( nullptr, scene );
     EXPECT_NE( nullptr, scene );
+    EXPECT_EQ(1u, scene->mMeshes[0]->mNumFaces);
+    EXPECT_EQ(aiPrimitiveType_TRIANGLE, scene->mMeshes[0]->mPrimitiveTypes);
+    EXPECT_EQ(true, scene->mMeshes[0]->HasVertexColors(0));
+
+    auto first_face = scene->mMeshes[0]->mFaces[0];
+    EXPECT_EQ(3, first_face.mNumIndices);
+    EXPECT_EQ(0, first_face.mIndices[0]);
+    EXPECT_EQ(1, first_face.mIndices[1]);
+    EXPECT_EQ(2, first_face.mIndices[2]);
+}
+
+//Test issue #623, PLY importer should not automatically create faces
+TEST_F(utPLYImportExport, pointcloudTest) {
+  Assimp::Importer importer;
+  //Could not use aiProcess_ValidateDataStructure since it's missing faces.
+  const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0);
+  EXPECT_NE(nullptr, scene);
+
+  EXPECT_EQ(1u, scene->mNumMeshes);
+  EXPECT_NE(nullptr, scene->mMeshes[0]);
+  EXPECT_EQ(24u, scene->mMeshes[0]->mNumVertices);
+  EXPECT_EQ(aiPrimitiveType::aiPrimitiveType_POINT, scene->mMeshes[0]->mPrimitiveTypes);
+  EXPECT_EQ(0u, scene->mMeshes[0]->mNumFaces);
 }
 }
 
 
 static const char *test_file =
 static const char *test_file =
@@ -125,6 +173,7 @@ static const char *test_file =
 
 
 TEST_F( utPLYImportExport, parseErrorTest ) {
 TEST_F( utPLYImportExport, parseErrorTest ) {
     Assimp::Importer importer;
     Assimp::Importer importer;
-    const aiScene *scene = importer.ReadFileFromMemory( test_file, strlen( test_file ), 0 );
+    //Could not use aiProcess_ValidateDataStructure since it's missing faces.
+    const aiScene *scene = importer.ReadFileFromMemory( test_file, strlen( test_file ), 0);
     EXPECT_NE( nullptr, scene );
     EXPECT_NE( nullptr, scene );
 }
 }

+ 26 - 0
tools/assimp_cmd/Info.cpp

@@ -329,6 +329,29 @@ int Assimp_Info (const char* const* params, unsigned int num)
 		special_points[2][0],special_points[2][1],special_points[2][2]
 		special_points[2][0],special_points[2][1],special_points[2][2]
 		)
 		)
 	;
 	;
+
+	// meshes
+	if (scene->mNumMeshes) {
+		printf("\nMeshes:  (name) [vertices / bones / faces | primitive_types]\n");
+	}
+	for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
+		const aiMesh* mesh = scene->mMeshes[i];
+		printf("    %d (%s)", i, mesh->mName.C_Str());
+		printf(
+			": [%d / %d / %d |",
+			mesh->mNumVertices,
+			mesh->mNumBones,
+			mesh->mNumFaces
+		);
+		const unsigned int ptypes = mesh->mPrimitiveTypes;
+		if (ptypes & aiPrimitiveType_POINT) { printf(" point"); }
+		if (ptypes & aiPrimitiveType_LINE) { printf(" line"); }
+		if (ptypes & aiPrimitiveType_TRIANGLE) { printf(" triangle"); }
+		if (ptypes & aiPrimitiveType_POLYGON) { printf(" polygon"); }
+		printf("]\n");
+	}
+
+	// materials
 	unsigned int total=0;
 	unsigned int total=0;
 	for(unsigned int i = 0;i < scene->mNumMaterials; ++i) {
 	for(unsigned int i = 0;i < scene->mNumMaterials; ++i) {
 		aiString name;
 		aiString name;
@@ -340,6 +363,7 @@ int Assimp_Info (const char* const* params, unsigned int num)
 		printf("\n");
 		printf("\n");
 	}
 	}
 
 
+	// textures
 	total=0;
 	total=0;
 	for(unsigned int i = 0;i < scene->mNumMaterials; ++i) {
 	for(unsigned int i = 0;i < scene->mNumMaterials; ++i) {
 		aiString name;
 		aiString name;
@@ -369,6 +393,7 @@ int Assimp_Info (const char* const* params, unsigned int num)
 		printf("\n");
 		printf("\n");
 	}
 	}
 
 
+	// animations
 	total=0;
 	total=0;
 	for(unsigned int i = 0;i < scene->mNumAnimations; ++i) {
 	for(unsigned int i = 0;i < scene->mNumAnimations; ++i) {
 		if (scene->mAnimations[i]->mName.length) {
 		if (scene->mAnimations[i]->mName.length) {
@@ -379,6 +404,7 @@ int Assimp_Info (const char* const* params, unsigned int num)
 		printf("\n");
 		printf("\n");
 	}
 	}
 
 
+	// node hierarchy
 	printf("\nNode hierarchy:\n");
 	printf("\nNode hierarchy:\n");
 	unsigned int cline=0;
 	unsigned int cline=0;
 	PrintHierarchy(scene->mRootNode,20,1000,cline,verbose);
 	PrintHierarchy(scene->mRootNode,20,1000,cline,verbose);