TEST_F(utSTLImporterExporter, test_export_pointclouds) { struct XYZ { float x, y, z; }; std::vector<XYZ> points; for (size_t i = 0; i < 10; ++i) { XYZ current; current.x = static_cast<float>(i); current.y = static_cast<float>(i); current.z = static_cast<float>(i); points.push_back(current); } aiScene scene; scene.mRootNode = new aiNode(); scene.mMeshes = new aiMesh*[1]; scene.mMeshes[0] = nullptr; scene.mNumMeshes = 1; scene.mMaterials = new aiMaterial*[1]; scene.mMaterials[0] = nullptr; scene.mNumMaterials = 1; scene.mMaterials[0] = new aiMaterial(); scene.mMeshes[0] = new aiMesh(); scene.mMeshes[0]->mMaterialIndex = 0; scene.mRootNode->mMeshes = new unsigned int[1]; scene.mRootNode->mMeshes[0] = 0; scene.mRootNode->mNumMeshes = 1; auto pMesh = scene.mMeshes[0]; size_t numValidPoints = points.size(); pMesh->mVertices = new aiVector3D[numValidPoints]; pMesh->mNumVertices = static_cast<unsigned int>( numValidPoints ); int i = 0; for (XYZ &p : points) { pMesh->mVertices[i] = aiVector3D(p.x, p.y, p.z); ++i; } Assimp::Exporter mAiExporter; ExportProperties *properties = new ExportProperties; properties->SetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS, true); mAiExporter.Export(&scene, "stl", "testExport.stl", 0, properties ); delete properties; }
virtual bool exporterTest() { Assimp::Importer importer; Assimp::Exporter exporter; const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure ); EXPECT_NE( nullptr, scene ); EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "gltf2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.gltf" ) ); return true; }
TEST_F(utSTLImporterExporter, exporterTest) { Assimp::Importer importer; const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/STL/Spider_ascii.stl", aiProcess_ValidateDataStructure); Assimp::Exporter mAiExporter; mAiExporter.Export( scene, "stl", "spiderExport.stl" ); const aiScene *scene2 = importer.ReadFile("spiderExport.stl", aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene2); }
std::string AssimpModelExport::getSupportedFormats() { std::string all = "All ("; std::string individual = ""; Assimp::Exporter exporter; for (size_t i = 0; i < exporter.GetExportFormatCount(); ++i) { const aiExportFormatDesc* desc = exporter.GetExportFormatDescription(i); all += "*." + std::string(desc->fileExtension) + " "; individual += ";;" + std::string(desc->description) + " (*." + std::string(desc->fileExtension) + ")"; } all += ")"; return all + individual; }
std::string AssimpModelExport::getExportFormatID( const std::string &fileExtension) { std::string ret; Assimp::Exporter exporter; for (size_t i = 0; i < exporter.GetExportFormatCount(); ++i) { const aiExportFormatDesc* desc = exporter.GetExportFormatDescription(i); if (fileExtension == desc->fileExtension) { ret = desc->id; break; } } return ret; }
const bool aiExport::aiExecute( const aiScene * scene ) { // Retrieves the file path. const boost::filesystem::path path = getPath(); // If there is a file path, we can export. if( !path.empty() ) { Assimp::Exporter exporter; Formats::const_iterator format = findFormat( path ); vgAssertN( format != m_formats.end(), "Export format must be specified." ); exporter.Export( scene, format->aiId, path.string().c_str(), 0u ); // We should do some error checking ! } return false; // We never need to refresh the scene. }
bool mesh::export_to_file(const std::string& format, const std::string& filepath, const std::string & filename) { Assimp::Exporter exporter; // TODO: fix the memory leak from not deleting temp // Note that aiScene::~aiScene() is not exported by the library // and as such fixing this leak is hard/impossible aiScene * temp; aiCopyScene(this->scene, &temp); keep_faces(this->walkable_faces, temp); if(AI_SUCCESS == exporter.Export(temp, format, filepath+filename)) { return true; } std::cerr << exporter.GetErrorString() << std::endl; return false; }
TEST_F( utIssues, OpacityBugWhenExporting_727 ) { float opacity; aiScene *scene( TestModelFacttory::createDefaultTestModel( opacity ) ); Assimp::Importer importer; Assimp::Exporter exporter; std::string path = "dae"; const aiExportFormatDesc *desc( exporter.GetExportFormatDescription( 0 ) ); EXPECT_NE( desc, nullptr ); path.append( desc->fileExtension ); EXPECT_EQ( AI_SUCCESS, exporter.Export( scene, desc->id, path ) ); const aiScene *newScene( importer.ReadFile( path, 0 ) ); EXPECT_TRUE( NULL != newScene ); float newOpacity; if ( newScene->mNumMaterials > 0 ) { std::cout << "Desc = " << desc->description << "\n"; EXPECT_EQ( AI_SUCCESS, newScene->mMaterials[ 0 ]->Get( AI_MATKEY_OPACITY, newOpacity ) ); EXPECT_EQ( opacity, newOpacity ); } }
void ColladaExporter::save(const TMD::PostProcessed::Data_t& data, const std::vector<CAT::ResourceEntry_t::SubEntry_t>& references) { boost::filesystem::path output_path(_export_folder); output_path /= "tmd"; boost::filesystem::path dae_filename(output_path); dae_filename += _dae_suffix; /*std::ofstream dae_out; open_to_write(dae_out, dae_filename); LeftPad_t pad{ 0 }; PaddedOstream pad_out(dae_out, pad); write_document(pad_out, data); dae_out.close();*/ aiScene scene; create_assimp_scene(scene, data); Assimp::Exporter exporter; auto export_format = exporter.GetExportFormatDescription(0); exporter.Export(&scene, export_format->id, dae_filename.string().c_str()); }
void IrrAssimpExport::writeFile(irr::scene::IMesh* mesh, irr::core::stringc format, irr::core::stringc filename) { Assimp::Exporter exporter; aiScene* scene = new aiScene(); scene->mRootNode = new aiNode(); scene->mRootNode->mNumMeshes = mesh->getMeshBufferCount(); scene->mRootNode->mMeshes = new unsigned int[mesh->getMeshBufferCount()]; for (unsigned int i = 0; i < mesh->getMeshBufferCount(); ++i) scene->mRootNode->mMeshes[i] = i; scene->mNumMeshes = mesh->getMeshBufferCount(); scene->mMeshes = new aiMesh*[scene->mNumMeshes]; scene->mNumMaterials = scene->mNumMeshes; scene->mMaterials = new aiMaterial*[scene->mNumMeshes]; for (unsigned int i = 0; i < mesh->getMeshBufferCount(); ++i) { aiMesh* assMesh = new aiMesh(); irr::scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); video::E_VERTEX_TYPE verticesType = buffer->getVertexType(); assMesh->mNumVertices = buffer->getVertexCount(); assMesh->mVertices = new aiVector3D[assMesh->mNumVertices]; assMesh->mNormals = new aiVector3D[assMesh->mNumVertices]; assMesh->mTextureCoords[0] = new aiVector3D[assMesh->mNumVertices]; assMesh->mNumUVComponents[0] = 2; assMesh->mColors[0] = new aiColor4D[assMesh->mNumVertices]; if (verticesType == video::EVT_2TCOORDS) { assMesh->mTextureCoords[1] = new aiVector3D[assMesh->mNumVertices]; assMesh->mNumUVComponents[1] = 2; } if (verticesType == video::EVT_TANGENTS) { assMesh->mTangents = new aiVector3D[assMesh->mNumVertices]; assMesh->mBitangents = new aiVector3D[assMesh->mNumVertices]; } video::S3DVertex* vertices = (video::S3DVertex*)buffer->getVertices(); video::S3DVertex2TCoords* tCoordsVertices; verticesType == video::EVT_2TCOORDS ? tCoordsVertices = (video::S3DVertex2TCoords*) vertices : tCoordsVertices = 0; video::S3DVertexTangents* tangentsVertices; verticesType == video::EVT_TANGENTS ? tangentsVertices = (video::S3DVertexTangents*) vertices : tangentsVertices = 0; for (unsigned int j = 0; j < buffer->getVertexCount(); ++j) { video::S3DVertex vertex = vertices[j]; core::vector3df position = vertex.Pos; core::vector3df normal = vertex.Normal; core::vector2df uv = vertex.TCoords; video::SColor color = vertex.Color; assMesh->mVertices[j] = aiVector3D(position.X, position.Y, position.Z); assMesh->mNormals[j] = aiVector3D(normal.X, normal.Y, normal.Z); assMesh->mTextureCoords[0][j] = aiVector3D(uv.X, uv.Y, 0); assMesh->mColors[0][j] = aiColor4D(color.getRed() / 255.f, color.getGreen() / 255.f, color.getBlue() / 255.f, color.getAlpha() / 255.f); if (verticesType == video::EVT_2TCOORDS) { video::S3DVertex2TCoords tCoordsVertex = tCoordsVertices[j]; core::vector2df uv2 = tCoordsVertex.TCoords2; assMesh->mTextureCoords[1][j] = aiVector3D(uv2.X, uv2.Y, 0); } if (verticesType == video::EVT_TANGENTS) { video::S3DVertexTangents tangentsVertex = tangentsVertices[j]; core::vector3df tangent = tangentsVertex.Tangent; core::vector3df binormal = tangentsVertex.Binormal; assMesh->mTangents[j] = aiVector3D(tangent.X, tangent.Y, tangent.Z); assMesh->mBitangents[j] = aiVector3D(binormal.X, binormal.Y, binormal.Z); } } assMesh->mNumFaces = buffer->getIndexCount() / 3; assMesh->mFaces = new aiFace[assMesh->mNumFaces]; for (unsigned int j = 0; j < assMesh->mNumFaces; ++j) { aiFace face; face.mNumIndices = 3; face.mIndices = new unsigned int[3]; face.mIndices[0] = buffer->getIndices()[3 * j + 0]; face.mIndices[1] = buffer->getIndices()[3 * j + 1]; face.mIndices[2] = buffer->getIndices()[3 * j + 2]; assMesh->mFaces[j] = face; } scene->mMaterials[i] = new aiMaterial(); scene->mMaterials[i]->mNumProperties = 0; assMesh->mMaterialIndex = i; video::SMaterial mat = buffer->getMaterial(); aiColor3D diffuseColor = IrrToAssimpColor(mat.DiffuseColor); aiColor3D ambiantColor = IrrToAssimpColor(mat.AmbientColor); aiColor3D emissiveColor = IrrToAssimpColor(mat.EmissiveColor); aiColor3D specularColor = IrrToAssimpColor(mat.SpecularColor); float shininess = mat.Shininess; scene->mMaterials[i]->AddProperty(&diffuseColor, 1, AI_MATKEY_COLOR_DIFFUSE); scene->mMaterials[i]->AddProperty(&ambiantColor, 1, AI_MATKEY_COLOR_AMBIENT); scene->mMaterials[i]->AddProperty(&emissiveColor, 1, AI_MATKEY_COLOR_EMISSIVE); scene->mMaterials[i]->AddProperty(&specularColor, 1, AI_MATKEY_COLOR_SPECULAR); scene->mMaterials[i]->AddProperty(&shininess, 1, AI_MATKEY_SHININESS); if (mat.getTexture(0)) { aiString textureName = aiString(mat.getTexture(0)->getName().getPath().c_str()); scene->mMaterials[i]->AddProperty(&textureName, AI_MATKEY_TEXTURE_DIFFUSE(0)); } if (mat.getTexture(1)) { // Normal map if ( mat.MaterialType == video::EMT_NORMAL_MAP_SOLID || mat.MaterialType == video::EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR || mat.MaterialType == video::EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA || mat.MaterialType == video::EMT_PARALLAX_MAP_SOLID || mat.MaterialType == video::EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR || mat.MaterialType == video::EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA) { aiString textureName = aiString(mat.getTexture(1)->getName().getPath().c_str()); scene->mMaterials[i]->AddProperty(&textureName, AI_MATKEY_TEXTURE_NORMALS(0)); } } scene->mMeshes[i] = assMesh; } exporter.Export(scene, format.c_str(), filename.c_str(), aiProcess_FlipUVs); delete scene; }
// ------------------------------------------------------------------------------ // Application entry point int main (int argc, char* argv[]) { if (argc <= 1) { printf("assimp: No command specified. Use \'assimp help\' for a detailed command list\n"); return 0; } // assimp version // Display version information if (! strcmp(argv[1], "version")) { const unsigned int flags = aiGetCompileFlags(); printf(AICMD_MSG_ABOUT, aiGetVersionMajor(), aiGetVersionMinor(), (flags & ASSIMP_CFLAGS_DEBUG ? "-debug " : ""), (flags & ASSIMP_CFLAGS_NOBOOST ? "-noboost " : ""), (flags & ASSIMP_CFLAGS_SHARED ? "-shared " : ""), (flags & ASSIMP_CFLAGS_SINGLETHREADED ? "-st " : ""), (flags & ASSIMP_CFLAGS_STLPORT ? "-stlport " : ""), aiGetVersionRevision()); return 0; } // assimp help // Display some basic help (--help and -h work as well // because people could try them intuitively) if (!strcmp(argv[1], "help") || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) { printf("%s",AICMD_MSG_HELP); return 0; } // assimp cmpdump // Compare two mini model dumps (regression suite) if (! strcmp(argv[1], "cmpdump")) { return Assimp_CompareDump (&argv[2],argc-2); } // construct global importer and exporter instances Assimp::Importer imp; imp.SetPropertyBool("GLOB_MEASURE_TIME",true); globalImporter = &imp; #ifndef ASSIMP_BUILD_NO_EXPORT // Assimp::Exporter exp; globalExporter = &exp; #endif // assimp listext // List all file extensions supported by Assimp if (! strcmp(argv[1], "listext")) { aiString s; imp.GetExtensionList(s); printf("%s\n",s.data); return 0; } #ifndef ASSIMP_BUILD_NO_EXPORT // assimp listexport // List all export file formats supported by Assimp (not the file extensions, just the format identifiers!) if (! strcmp(argv[1], "listexport")) { aiString s; for(size_t i = 0, end = exp.GetExportFormatCount(); i < end; ++i) { const aiExportFormatDesc* const e = exp.GetExportFormatDescription(i); s.Append( e->id ); if (i!=end-1) { s.Append("\n"); } } printf("%s\n",s.data); return 0; } // assimp exportinfo // stat an export format if (! strcmp(argv[1], "exportinfo")) { aiString s; if (argc<3) { printf("Expected file format id\n"); return -11; } for(size_t i = 0, end = exp.GetExportFormatCount(); i < end; ++i) { const aiExportFormatDesc* const e = exp.GetExportFormatDescription(i); if (!strcmp(e->id,argv[2])) { printf("%s\n%s\n%s\n",e->id,e->fileExtension,e->description); return 0; } } printf("Unknown file format id: \'%s\'\n",argv[2]); return -12; } // assimp export // Export a model to a file if (! strcmp(argv[1], "export")) { return Assimp_Export (&argv[2],argc-2); } #endif // assimp knowext // Check whether a particular file extension is known by us, return 0 on success if (! strcmp(argv[1], "knowext")) { if (argc<3) { printf("Expected file extension"); return -10; } const bool b = imp.IsExtensionSupported(argv[2]); printf("File extension \'%s\' is %sknown\n",argv[2],(b?"":"not ")); return b?0:-1; } // assimp info // Print basic model statistics if (! strcmp(argv[1], "info")) { return Assimp_Info ((const char**)&argv[2],argc-2); } // assimp dump // Dump a model to a file if (! strcmp(argv[1], "dump")) { return Assimp_Dump (&argv[2],argc-2); } // assimp extract // Extract an embedded texture from a file if (! strcmp(argv[1], "extract")) { return Assimp_Extract (&argv[2],argc-2); } // assimp testbatchload // Used by /test/other/streamload.py to load a list of files // using the same importer instance to check for incompatible // importers. if (! strcmp(argv[1], "testbatchload")) { return Assimp_TestBatchLoad (&argv[2],argc-2); } printf("Unrecognized command. Use \'assimp help\' for a detailed command list\n"); return 1; }
bool AssimpModelExport::writeSceneToFile( const aiScene *scene, const std::string &filePath) { bool success = false; if (scene) { boost::filesystem::path boostPath(filePath); //-------------------------------------------------------------------------- // NOTE: This modifies links to textures, so after export, the // scene for rendering won't be valid any more! //-------------------------------------------------------------------------- if (scene->HasTextures()) { // embedded textures found, replace pointers such as "*0" with "0.jpg" aiReturn texFound; int texIndex; for (unsigned int i = 0; i < scene->mNumMaterials; ++i) { aiString path; // filename texIndex = 0; texFound = AI_SUCCESS; while (texFound == AI_SUCCESS) { texFound = scene->mMaterials[i]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path); std::string name(path.data); if (!name.empty()) { name = name.substr(1, name.size()) + REPO_DEFAULT_TEXTURE_EXT; // remove leading '*' char scene->mMaterials[i]->RemoveProperty(AI_MATKEY_TEXTURE_DIFFUSE(texIndex)); // TODO: watch out for mem-leak scene->mMaterials[i]->AddProperty(new aiString(name.c_str()), AI_MATKEY_TEXTURE_DIFFUSE(texIndex)); texIndex++; } } } } Assimp::Exporter exporter; std::string extension = boostPath.extension().string(); std::string exportFormat = getExportFormatID(extension.substr(1, extension.size() - 1)); repoTrace << "Exporting repo scene using ASSIMP: export format = " << exportFormat << " to " << filePath; if (exportFormat.empty()) { repoError << "Unrecognised export format: " << boostPath.extension().string(); } else { aiReturn ret = exporter.Export(scene, exportFormat, filePath, scene->mFlags); switch (ret) { case aiReturn_FAILURE: repoError << "Export failed due to unknown reason."; break; case aiReturn_OUTOFMEMORY: repoError << "Export failed due to running out of memory."; break; case aiReturn_SUCCESS: repoTrace << "Export completed successfully"; break; case _AI_ENFORCE_ENUM_SIZE: // Silently handle assimp's bogus enum-size-enforcing value. break; } success = (ret == aiReturn_SUCCESS); } } else{ repoError << "Trying to write a null pointer assimp scene!"; } return success; }
/*! * \brief Export a cad model (vertices and faces) with the assimp library * \author Sascha Kaden * \param[in] format * \param[in] filePath * \param[in] list of vertices * \param[in] list of faces * \date 2017-02-19 */ bool exportCad(ExportFormat format, const std::string &filePath, const std::vector<Vector3> &vertices, const std::vector<Vector3i> &faces) { if (filePath.empty()) { Logging::warning("Empty output file path", "CadProcessing"); return false; } Assimp::Exporter exporter; size_t maxFormatCount = exporter.GetExportFormatCount(); size_t formatCount; switch (format) { case ExportFormat::COLLADA: formatCount = 0; break; case ExportFormat::X_FILES: formatCount = 1; break; case ExportFormat::STEP: formatCount = 2; break; case ExportFormat::OBJ: formatCount = 3; break; case ExportFormat::STEREOLITHOGRAPHY: formatCount = 4; break; case ExportFormat::STEREOLITHOGRAPHY_BINARY: formatCount = 5; break; case ExportFormat::STANFORD_POLYGON_LIBRARY: formatCount = 6; break; case ExportFormat::STANFORD_POLYGON_LIBRARY_BINARY: formatCount = 7; break; case ExportFormat::AUTODESK_3DS: formatCount = 8; break; case ExportFormat::GL_TRANSMISSION_FORMAT: formatCount = 9; break; case ExportFormat::GL_TRANSMISSION_FORMAT_BINARY: formatCount = 10; break; case ExportFormat::ASSIMP_BINARY: formatCount = 11; break; case ExportFormat::ASSXML_DOCUMENT: formatCount = 12; break; case ExportFormat::EXTENSIBLE_3D: formatCount = 13; break; } if (formatCount > maxFormatCount) { Logging::warning("Selected format is not supported", "CadProcessing"); return false; } aiScene scene = generateScene(vertices, faces); const aiExportFormatDesc *formatDesc = exporter.GetExportFormatDescription(formatCount); exporter.Export(&scene, formatDesc->id, filePath + "." + formatDesc->fileExtension, aiProcess_Triangulate); return true; }
int run(int argc, char* argv[]) { Arguments args; args.add("help", 'h').description("Shows this help message.").flag(true); args.add("input", 'i').description("Input filename").required(true); args.add("output", 'o').description("Output filename").required(true); args.add("format", 'f').description("Output format. Overrides file extension."); args.add("axis", 'x').description("Change axis order of the cordinate system and polarity. (like +x+y+z, +x-z+y, ... )"); args.add("textures", 't').description("Strip path from texture filenames").flag(true); // parse args if (!args.evaluate(argc, argv)) { cout << args.getErrorMessage() << endl; cout << args.getHelpMessage() << endl; return 1; } // print help if (argc == 1 || args.get("help").isFound()) { cout << args.getHelpMessage() << endl; return 0; } string inFileName = args.get("input").value(); string outFileName = args.get("output").value(); string outExtension; // determine file format if (!args.get("format").isFound()) { string::size_type n; string s = outFileName; n = s.find_last_of('.'); if (n != string::npos) { s = s.substr(n + 1); } if (s.empty()) { outExtension = "assbin"; cout << "WARNING: No file extension was given. Using assbin format for default." << endl; } else { outExtension = s; } } else { outExtension = args.get("format").value(); } // import scene Assimp::Importer aiImporter; aiScene const * scene = aiImporter.ReadFile(inFileName.c_str(), aiProcessPreset_TargetRealtime_Quality | aiProcess_ConvertToLeftHanded | 0); if (scene == nullptr) { cout << "Could not load model file" << inFileName << endl; cout << aiImporter.GetErrorString() << endl; return 1; } // flip axes if (args.get("axis").isFound() && scene->HasMeshes()) { string axesOrder = args.get("axis").value(); if (axesOrder.length() != 6) { cout << args.getHelpMessage() << endl; return 1; } char order[3]; char polarity[3]; uint k = 3; while (k--) { char c = axesOrder.at(2*k), b = -1; char a = axesOrder.at(2*k+1), d = 1; switch (a) { case 'x': case 'X': b = 0; break; case 'y': case 'Y': b = 1; break; case 'z': case 'Z': b = 2; break; default: cout << args.getHelpMessage() << endl; return 1; } switch (c) { case '+': d = +1; break; case '-': d = -1; break; default: cout << args.getHelpMessage() << endl; return 1; } order[k] = b; polarity[k] = d; } for (uint i = 0; i < scene->mNumMeshes; i++) { aiMesh * const mesh = scene->mMeshes[i]; for (uint j = 0; j < mesh->mNumVertices; j++) { swap_vertices(&mesh->mVertices[j], order, polarity); swap_vertices(&mesh->mNormals[j], order, polarity); } } } // strip texture filenames if (args.get("textures").isFound() && scene->HasMaterials()) { for (uint i = 0; i < scene->mNumMaterials; i++) { aiMaterial const * material = scene->mMaterials[i]; for (uint j = 0; j < sizeof(textureTypes) / sizeof(textureTypes[0]); j++) { aiTextureType tt = textureTypes[j]; for (uint k = 0; k < material->GetTextureCount(tt); k++) { aiString aiPath; material->GetTexture(tt, k, &aiPath); string path = aiPath.C_Str(); { string s = path; string::size_type n, m; n = s.find_last_of('/'); m = s.find_last_of('\\'); if (n != string::npos) { s = s.substr(n + 1); } else if (m != string::npos) { s = s.substr(m + 1); } if (!s.empty()) { path = s; } } // textura filenev vissza const aiMaterialProperty* pp = nullptr; if (aiGetMaterialProperty(material, AI_MATKEY_TEXTURE(tt, k), &pp) == AI_SUCCESS) { aiMaterialProperty* pProp = const_cast<aiMaterialProperty*>(pp); if (aiPTI_String == pProp->mType) { size_t newLen = path.length() + 4; char* newData = (char*)malloc(newLen); (*(uint*)(&newData[0])) = path.length(); memcpy_s(&newData[4], newLen, path.c_str(), path.length()); free(pProp->mData); pProp->mData = newData; pProp->mDataLength = newLen; } } } } } } // save Assimp::Exporter aiExporter; if (aiExporter.Export(scene, outExtension, outFileName) != aiReturn_SUCCESS) { cout << "Could not save model file" << endl; cout << aiExporter.GetErrorString() << endl; return 1; } return 0; }
void OBJWriter::write(const std::shared_ptr<gameplay::Model>& model, const std::string& baseName, const std::map<loader::TextureLayoutProxy::TextureKey, std::shared_ptr<gameplay::Material>>& mtlMap1, const std::map<loader::TextureLayoutProxy::TextureKey, std::shared_ptr<gameplay::Material>>& mtlMap2, const glm::vec3& ambientColor) const { Expects(model != nullptr); auto fullPath = m_basePath / baseName; Assimp::Exporter exporter; std::string formatIdentifier; for(size_t i = 0; i < exporter.GetExportFormatCount(); ++i) { auto descr = exporter.GetExportFormatDescription(i); BOOST_ASSERT(descr != nullptr); std::string exporterExtension = std::string(".") + descr->fileExtension; if(exporterExtension == fullPath.extension().string()) { formatIdentifier = descr->id; break; } } if(formatIdentifier.empty()) { BOOST_LOG_TRIVIAL(error) << "Failed to find an exporter for the supplied file extension"; BOOST_LOG_TRIVIAL(info) << "Here's the list of registered exporters"; for(size_t i = 0; i < exporter.GetExportFormatCount(); ++i) { auto descr = exporter.GetExportFormatDescription(i); BOOST_ASSERT(descr != nullptr); BOOST_LOG_TRIVIAL(info) << descr->description << ", extension `" << descr->fileExtension << "`, id `" << descr->id << "`"; } BOOST_THROW_EXCEPTION(std::runtime_error("Failed to find an exporter for the supplied file extension")); } std::unique_ptr<aiScene> scene = std::make_unique<aiScene>(); BOOST_ASSERT(scene->mRootNode == nullptr); scene->mRootNode = new aiNode(); { size_t totalPartCount = 0; for( const auto& mesh : model->getMeshes() ) { totalPartCount += mesh->getPartCount(); } scene->mNumMaterials = totalPartCount; scene->mMaterials = new aiMaterial*[totalPartCount]; std::fill_n(scene->mMaterials, totalPartCount, nullptr); scene->mNumMeshes = totalPartCount; scene->mMeshes = new aiMesh*[totalPartCount]; std::fill_n(scene->mMeshes, totalPartCount, nullptr); scene->mRootNode->mNumMeshes = totalPartCount; scene->mRootNode->mMeshes = new unsigned int[totalPartCount]; for( size_t i = 0; i < totalPartCount; ++i ) scene->mRootNode->mMeshes[i] = i; } for( size_t mi = 0, globalPartIndex = 0; mi < model->getMeshes().size(); ++mi ) { BOOST_ASSERT(mi < scene->mNumMeshes); const auto& mesh = model->getMeshes()[mi]; for( size_t pi = 0; pi < mesh->getPartCount(); ++pi , ++globalPartIndex ) { BOOST_ASSERT(globalPartIndex < scene->mNumMaterials); const std::shared_ptr<gameplay::MeshPart>& part = mesh->getPart(pi); scene->mMeshes[globalPartIndex] = new aiMesh(); aiMesh* outMesh = scene->mMeshes[globalPartIndex]; allocateElementMemory(mesh, outMesh); copyVertexData(mesh, outMesh); BOOST_ASSERT(part->getPrimitiveType() == gameplay::Mesh::PrimitiveType::TRIANGLES && part->getIndexCount() % 3 == 0); outMesh->mMaterialIndex = globalPartIndex; scene->mMaterials[globalPartIndex] = new aiMaterial(); scene->mMaterials[globalPartIndex]->AddProperty(new aiColor4D(ambientColor.r, ambientColor.g, ambientColor.b, 1), 1, AI_MATKEY_COLOR_AMBIENT); { // try to find the texture for our material using Entry = decltype(*mtlMap1.begin()); auto finder = [&part](const Entry& entry) { return entry.second == part->getMaterial(); }; auto texIt = std::find_if(mtlMap1.begin(), mtlMap1.end(), finder); bool found = false; if( texIt != mtlMap1.end() ) { scene->mMaterials[globalPartIndex]->AddProperty(new aiString(makeTextureName(texIt->first.tileAndFlag & TextureIndexMask) + ".png"), AI_MATKEY_TEXTURE_DIFFUSE(0)); found = true; } if( !found ) { texIt = std::find_if(mtlMap2.begin(), mtlMap2.end(), finder); if( texIt != mtlMap2.end() ) { scene->mMaterials[globalPartIndex]->AddProperty(new aiString(makeTextureName(texIt->first.tileAndFlag & TextureIndexMask) + ".png"), AI_MATKEY_TEXTURE_DIFFUSE(0)); } } } outMesh->mNumFaces = part->getIndexCount() / 3; outMesh->mFaces = new aiFace[outMesh->mNumFaces]; switch( part->getIndexFormat() ) { case gameplay::Mesh::INDEX8: copyIndices<uint8_t>(part, outMesh); break; case gameplay::Mesh::INDEX16: copyIndices<uint16_t>(part, outMesh); break; case gameplay::Mesh::INDEX32: copyIndices<uint32_t>(part, outMesh); break; default: break; } } } exporter.Export(scene.get(), formatIdentifier.c_str(), fullPath.string(), aiProcess_JoinIdenticalVertices | aiProcess_ValidateDataStructure | aiProcess_FlipUVs); }
/* Exports the scene to the given filename */ int Exporter::writeToFile(Scene *scene, const std::string filename) { if (!scene || filename.empty()) { LOGW("Exporting to invalid filename or current scene is invalid."); return -1; } Assimp::Exporter exporter; const char *format_description_id = findFormatDescription(exporter, filename); if (!format_description_id) { LOGW("Failure to find supported format description to %s", filename.c_str()); return -1; } aiScene aiscene; gvr2aiScene(*scene, aiscene); if (aiscene.mNumMeshes > 0) { LOGD("Exporting scene to %s\n", filename.c_str()); exporter.Export(&aiscene, format_description_id, filename); } return 0; }