diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d8972b1d..15374a3fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,6 +230,11 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW ) ADD_DEFINITIONS( -U__STRICT_ANSI__ ) 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) MESSAGE(STATUS "Coveralls enabled") INCLUDE(Coveralls) diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index 9d61e125c..92a64e3d8 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -349,7 +349,7 @@ void Discreet3DSImporter::ParseObjectChunk() case Discreet3DS::CHUNK_MAT_MATERIAL: // 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(); break; diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 6430187b0..6e2db91db 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -72,6 +72,7 @@ SET( PUBLIC_HEADERS ${HEADER_PATH}/matrix4x4.h ${HEADER_PATH}/matrix4x4.inl ${HEADER_PATH}/mesh.h + ${HEADER_PATH}/pbrmaterial.h ${HEADER_PATH}/postprocess.h ${HEADER_PATH}/quaternion.h ${HEADER_PATH}/quaternion.inl diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index f1c6290e2..8e32ed46c 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -247,6 +247,11 @@ void FBXExporter::WriteBinaryFooter() 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 { StreamWriterLE outstream(outfile); diff --git a/code/PlyParser.cpp b/code/PlyParser.cpp index 85c0f823e..672ac9bde 100644 --- a/code/PlyParser.cpp +++ b/code/PlyParser.cpp @@ -1043,71 +1043,91 @@ bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer &streamBuffer, switch (eType) { 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 - if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt); + if (p_bBE)ByteSwap::Swap(&t); + out->iUInt = t; break; + } case EDT_UShort: { - uint16_t i = *((uint16_t*)pCur); + uint16_t t; + memcpy(&t, pCur, sizeof(uint16_t)); + pCur += sizeof(uint16_t); // 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; } 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; } 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 - if (p_bBE)ByteSwap::Swap(&out->iInt); + if (p_bBE)ByteSwap::Swap(&t); + out->iInt = t; break; + } case EDT_Short: { - int16_t i = *((int16_t*)pCur); + int16_t t; + memcpy(&t, pCur, sizeof(int16_t)); + pCur += sizeof(int16_t); // 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; } 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; + } case EDT_Float: { - out->fFloat = *((float*)pCur); + float t; + memcpy(&t, pCur, sizeof(float)); + pCur += sizeof(float); // Swap endianness - if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat); - pCur += 4; + if (p_bBE)ByteSwap::Swap(&t); + out->fFloat = t; break; } case EDT_Double: { - out->fDouble = *((double*)pCur); + double t; + memcpy(&t, pCur, sizeof(double)); + pCur += sizeof(double); // Swap endianness - if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble); - pCur += 8; + if (p_bBE)ByteSwap::Swap(&t); + out->fDouble = t; break; } default: diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 520785081..8f2b14e1a 100644 --- a/code/glTF2Asset.inl +++ b/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 (Value* uri = FindString(obj, "uri")) { @@ -686,6 +686,19 @@ inline void Image::Read(Value& obj, Asset& /*r*/) this->uri = uristr; } } + else if (Value* bufferViewVal = FindUInt(obj, "bufferView")) { + this->bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); + Ref 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(); + } + } } } diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl index b31846abd..bd43b19f2 100644 --- a/code/glTFAsset.inl +++ b/code/glTFAsset.inl @@ -948,24 +948,24 @@ Ref buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer); size_t size_coordindex = ifs.GetNCoordIndex() * 3;// See float attributes note. 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); // Coordinates size_t size_coord = ifs.GetNCoord();// See float attributes note. 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); // Normals size_t size_normal = ifs.GetNNormal();// See float attributes note. 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); // Additional attributes. @@ -989,8 +989,8 @@ Ref buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer); if(idx_texcoord < primitives[0].attributes.texcoord.size()) { 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++; } diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index 2c3fa2046..54c32fb8b 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -194,9 +194,16 @@ void glTFImporter::ImportMaterials(glTF::Asset& r) 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.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) { aimat->AddProperty(&mat.shininess, 1, AI_MATKEY_SHININESS); diff --git a/contrib/zlib/zlib.h b/contrib/zlib/zlib.h index 2d6bb2976..dcb7b5063 100644 --- a/contrib/zlib/zlib.h +++ b/contrib/zlib/zlib.h @@ -77,8 +77,9 @@ extern "C" { the consistency of the compressed data, so the library should never crash even in the case of corrupted input. */ -#ifdef __ANDROID__ -using zcrc_t = unsigned_long; + +#ifdef __ANDROID__ +typedef unsigned long zcrc_t; #endif typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); diff --git a/test/models/PLY/cube_binary.ply b/test/models/PLY/cube_binary.ply new file mode 100644 index 000000000..14d29ebd8 Binary files /dev/null and b/test/models/PLY/cube_binary.ply differ diff --git a/test/models/PLY/cube_uv.ply b/test/models/PLY/cube_uv.ply new file mode 100644 index 000000000..45ab0607a --- /dev/null +++ b/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 diff --git a/test/models/PLY/float-color.ply b/test/models/PLY/float-color.ply index 34353ad53..f419be34e 100644 --- a/test/models/PLY/float-color.ply +++ b/test/models/PLY/float-color.ply @@ -15,4 +15,4 @@ end_header 0.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 -3 0 1 2 \ No newline at end of file +3 0 1 2 diff --git a/test/unit/utPLYImportExport.cpp b/test/unit/utPLYImportExport.cpp index 633beda5f..e5268a400 100644 --- a/test/unit/utPLYImportExport.cpp +++ b/test/unit/utPLYImportExport.cpp @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "AbstractImportExportBase.h" +#include using namespace ::Assimp; @@ -52,7 +53,7 @@ class utPLYImportExport : public AbstractImportExportBase { public: virtual bool importerTest() { 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_NE( nullptr, scene->mMeshes[0] ); EXPECT_EQ( 8u, scene->mMeshes[0]->mNumVertices ); @@ -65,7 +66,7 @@ public: virtual bool exporterTest() { Importer importer; 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_EQ(aiReturn_SUCCESS, exporter.Export(scene, "ply", ASSIMP_TEST_MODELS_DIR "/PLY/cube_test.ply")); @@ -89,19 +90,50 @@ TEST_F(utPLYImportExport, exportTest_Success ) { //Test issue 1623, crash when loading two PLY files in a row TEST_F(utPLYImportExport, importerMultipleTest) { 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); - 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); } +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", 0); + + 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 ) { 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_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]); } static const char *test_file = @@ -125,6 +157,6 @@ static const char *test_file = TEST_F( utPLYImportExport, parseErrorTest ) { Assimp::Importer importer; - const aiScene *scene = importer.ReadFileFromMemory( test_file, strlen( test_file ), 0 ); + const aiScene *scene = importer.ReadFileFromMemory( test_file, strlen( test_file ), aiProcess_ValidateDataStructure); EXPECT_NE( nullptr, scene ); } diff --git a/tools/assimp_cmd/Info.cpp b/tools/assimp_cmd/Info.cpp index a9f66eb1f..c4d5fe189 100644 --- a/tools/assimp_cmd/Info.cpp +++ b/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] ) ; + + // 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; for(unsigned int i = 0;i < scene->mNumMaterials; ++i) { aiString name; @@ -340,6 +363,7 @@ int Assimp_Info (const char* const* params, unsigned int num) printf("\n"); } + // textures total=0; for(unsigned int i = 0;i < scene->mNumMaterials; ++i) { aiString name; @@ -369,6 +393,7 @@ int Assimp_Info (const char* const* params, unsigned int num) printf("\n"); } + // animations total=0; for(unsigned int i = 0;i < scene->mNumAnimations; ++i) { if (scene->mAnimations[i]->mName.length) { @@ -379,6 +404,7 @@ int Assimp_Info (const char* const* params, unsigned int num) printf("\n"); } + // node hierarchy printf("\nNode hierarchy:\n"); unsigned int cline=0; PrintHierarchy(scene->mRootNode,20,1000,cline,verbose);