summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/assimp/code/ObjExporter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/assimp/code/ObjExporter.cpp')
-rw-r--r--src/3rdparty/assimp/code/ObjExporter.cpp185
1 files changed, 137 insertions, 48 deletions
diff --git a/src/3rdparty/assimp/code/ObjExporter.cpp b/src/3rdparty/assimp/code/ObjExporter.cpp
index ca07730bc..a8bf9935a 100644
--- a/src/3rdparty/assimp/code/ObjExporter.cpp
+++ b/src/3rdparty/assimp/code/ObjExporter.cpp
@@ -2,7 +2,8 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -38,8 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-
-
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
@@ -53,17 +52,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <memory>
-
using namespace Assimp;
-namespace Assimp {
+
+namespace Assimp {
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp
-void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
-{
+void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) {
// invoke the exporter
ObjExporter exporter(pFile, pScene);
+ if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) {
+ throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
+ }
+
// we're still here - export successfully completed. Write both the main OBJ file and the material script
{
std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
@@ -81,16 +83,46 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
}
}
+// ------------------------------------------------------------------------------------------------
+// Worker function for exporting a scene to Wavefront OBJ without the material file. Prototyped and registered in Exporter.cpp
+void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) {
+ // invoke the exporter
+ ObjExporter exporter(pFile, pScene, true);
+
+ if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) {
+ throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
+ }
+
+ // we're still here - export successfully completed. Write both the main OBJ file and the material script
+ {
+ std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
+ if(outfile == NULL) {
+ throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
+ }
+ outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
+ }
+
+
+}
+
} // end of namespace Assimp
static const std::string MaterialExt = ".mtl";
// ------------------------------------------------------------------------------------------------
-ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene)
+ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl)
: filename(_filename)
, pScene(pScene)
-, endl("\n")
-{
+, vp()
+, vn()
+, vt()
+, vc()
+, mVpMap()
+, mVnMap()
+, mVtMap()
+, mVcMap()
+, mMeshes()
+, endl("\n") {
// make sure that all formatting happens using the standard, C locale and not the user's current locale
const std::locale& l = std::locale("C");
mOutput.imbue(l);
@@ -98,8 +130,14 @@ ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene)
mOutputMat.imbue(l);
mOutputMat.precision(16);
- WriteGeometryFile();
- WriteMaterialFile();
+ WriteGeometryFile(noMtl);
+ if (!noMtl)
+ WriteMaterialFile();
+}
+
+// ------------------------------------------------------------------------------------------------
+ObjExporter::~ObjExporter() {
+
}
// ------------------------------------------------------------------------------------------------
@@ -116,22 +154,31 @@ std::string ObjExporter :: GetMaterialLibName()
}
// ------------------------------------------------------------------------------------------------
-std::string ObjExporter :: GetMaterialLibFileName()
-{
+std::string ObjExporter::GetMaterialLibFileName() {
+ // Remove existing .obj file extension so that the final material file name will be fileName.mtl and not fileName.obj.mtl
+ size_t lastdot = filename.find_last_of('.');
+ if (lastdot != std::string::npos)
+ return filename.substr(0, lastdot) + MaterialExt;
+
return filename + MaterialExt;
}
// ------------------------------------------------------------------------------------------------
-void ObjExporter :: WriteHeader(std::ostringstream& out)
-{
+void ObjExporter::WriteHeader(std::ostringstream& out) {
out << "# File produced by Open Asset Import Library (http://www.assimp.sf.net)" << endl;
- out << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' << aiGetVersionRevision() << ")" << endl << endl;
+ out << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.'
+ << aiGetVersionRevision() << ")" << endl << endl;
}
// ------------------------------------------------------------------------------------------------
-std::string ObjExporter :: GetMaterialName(unsigned int index)
+std::string ObjExporter::GetMaterialName(unsigned int index)
{
const aiMaterial* const mat = pScene->mMaterials[index];
+ if ( nullptr == mat ) {
+ static const std::string EmptyStr;
+ return EmptyStr;
+ }
+
aiString s;
if(AI_SUCCESS == mat->Get(AI_MATKEY_NAME,s)) {
return std::string(s.data,s.length);
@@ -166,11 +213,17 @@ void ObjExporter::WriteMaterialFile()
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_EMISSIVE,c)) {
mOutputMat << "Ke " << c.r << " " << c.g << " " << c.b << endl;
}
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_TRANSPARENT,c)) {
+ mOutputMat << "Tf " << c.r << " " << c.g << " " << c.b << endl;
+ }
- float o;
+ ai_real o;
if(AI_SUCCESS == mat->Get(AI_MATKEY_OPACITY,o)) {
mOutputMat << "d " << o << endl;
}
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_REFRACTI,o)) {
+ mOutputMat << "Ni " << o << endl;
+ }
if(AI_SUCCESS == mat->Get(AI_MATKEY_SHININESS,o) && o) {
mOutputMat << "Ns " << o << endl;
@@ -205,26 +258,37 @@ void ObjExporter::WriteMaterialFile()
}
}
-// ------------------------------------------------------------------------------------------------
-void ObjExporter :: WriteGeometryFile()
-{
+void ObjExporter::WriteGeometryFile(bool noMtl) {
WriteHeader(mOutput);
- mOutput << "mtllib " << GetMaterialLibName() << endl << endl;
+ if (!noMtl)
+ mOutput << "mtllib " << GetMaterialLibName() << endl << endl;
// collect mesh geometry
aiMatrix4x4 mBase;
AddNode(pScene->mRootNode, mBase);
- // write vertex positions
- vpMap.getVectors(vp);
- mOutput << "# " << vp.size() << " vertex positions" << endl;
- for(const aiVector3D& v : vp) {
- mOutput << "v " << v.x << " " << v.y << " " << v.z << endl;
+ // write vertex positions with colors, if any
+ mVpMap.getVectors( vp );
+ mVcMap.getColors( vc );
+ if ( vc.empty() ) {
+ mOutput << "# " << vp.size() << " vertex positions" << endl;
+ for ( const aiVector3D& v : vp ) {
+ mOutput << "v " << v.x << " " << v.y << " " << v.z << endl;
+ }
+ } else {
+ mOutput << "# " << vp.size() << " vertex positions and colors" << endl;
+ size_t colIdx = 0;
+ for ( const aiVector3D& v : vp ) {
+ if ( colIdx < vc.size() ) {
+ mOutput << "v " << v.x << " " << v.y << " " << v.z << " " << vc[ colIdx ].r << " " << vc[ colIdx ].g << " " << vc[ colIdx ].b << endl;
+ }
+ ++colIdx;
+ }
}
mOutput << endl;
// write uv coordinates
- vtMap.getVectors(vt);
+ mVtMap.getVectors(vt);
mOutput << "# " << vt.size() << " UV coordinates" << endl;
for(const aiVector3D& v : vt) {
mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
@@ -232,7 +296,7 @@ void ObjExporter :: WriteGeometryFile()
mOutput << endl;
// write vertex normals
- vnMap.getVectors(vn);
+ mVnMap.getVectors(vn);
mOutput << "# " << vn.size() << " vertex normals" << endl;
for(const aiVector3D& v : vn) {
mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
@@ -240,12 +304,13 @@ void ObjExporter :: WriteGeometryFile()
mOutput << endl;
// now write all mesh instances
- for(const MeshInstance& m : meshes) {
+ for(const MeshInstance& m : mMeshes) {
mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl;
if (!m.name.empty()) {
mOutput << "g " << m.name << endl;
}
- mOutput << "usemtl " << m.matname << endl;
+ if (!noMtl)
+ mOutput << "usemtl " << m.matname << endl;
for(const Face& f : m.faces) {
mOutput << f.kind << ' ';
@@ -272,8 +337,7 @@ void ObjExporter :: WriteGeometryFile()
}
// ------------------------------------------------------------------------------------------------
-int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
-{
+int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) {
vecIndexMap::dataType::iterator vertIt = vecMap.find(vec);
// vertex already exists, so reference it
if(vertIt != vecMap.end()){
@@ -286,8 +350,7 @@ int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
}
// ------------------------------------------------------------------------------------------------
-void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
-{
+void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs ) {
vecs.resize(vecMap.size());
for(vecIndexMap::dataType::iterator it = vecMap.begin(); it != vecMap.end(); ++it){
vecs[it->second-1] = it->first;
@@ -295,12 +358,33 @@ void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
}
// ------------------------------------------------------------------------------------------------
-void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
-{
- meshes.push_back(MeshInstance());
- MeshInstance& mesh = meshes.back();
+int ObjExporter::colIndexMap::getIndex( const aiColor4D& col ) {
+ colIndexMap::dataType::iterator vertIt = colMap.find( col );
+ // vertex already exists, so reference it
+ if ( vertIt != colMap.end() ) {
+ return vertIt->second;
+ }
+ colMap[ col ] = mNextIndex;
+ int ret = mNextIndex;
+ mNextIndex++;
- mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_" + std::string(m->mName.data,m->mName.length) : "");
+ return ret;
+}
+
+// ------------------------------------------------------------------------------------------------
+void ObjExporter::colIndexMap::getColors( std::vector<aiColor4D> &colors ) {
+ colors.resize( colMap.size() );
+ for ( colIndexMap::dataType::iterator it = colMap.begin(); it != colMap.end(); ++it ) {
+ colors[ it->second - 1 ] = it->first;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) {
+ mMeshes.push_back(MeshInstance());
+ MeshInstance& mesh = mMeshes.back();
+
+ mesh.name = std::string( name.data, name.length );
mesh.matname = GetMaterialName(m->mMaterialIndex);
mesh.faces.resize(m->mNumFaces);
@@ -325,20 +409,25 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
const unsigned int idx = f.mIndices[a];
aiVector3D vert = mat * m->mVertices[idx];
- face.indices[a].vp = vpMap.getIndex(vert);
+ face.indices[a].vp = mVpMap.getIndex(vert);
if (m->mNormals) {
aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx];
- face.indices[a].vn = vnMap.getIndex(norm);
- }
- else{
+ face.indices[a].vn = mVnMap.getIndex(norm);
+ } else {
face.indices[a].vn = 0;
}
- if (m->mTextureCoords[0]) {
- face.indices[a].vt = vtMap.getIndex(m->mTextureCoords[0][idx]);
+ if ( nullptr != m->mColors[ 0 ] ) {
+ aiColor4D col4 = m->mColors[ 0 ][ idx ];
+ face.indices[ a ].vc = mVcMap.getIndex( col4 );
+ } else {
+ face.indices[ a ].vc = 0;
}
- else{
+
+ if ( m->mTextureCoords[ 0 ] ) {
+ face.indices[a].vt = mVtMap.getIndex(m->mTextureCoords[0][idx]);
+ } else {
face.indices[a].vt = 0;
}
}