Respect merge identical vertices in ObjExporter (#5521)

Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
pull/5525/head
Julian Knodt 2024-04-02 09:31:19 -07:00 committed by GitHub
parent feb861f17b
commit 39ce0c0456
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 20 deletions

View File

@ -59,9 +59,9 @@ namespace Assimp {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp // 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* props) {
// invoke the exporter // invoke the exporter
ObjExporter exporter(pFile, pScene); ObjExporter exporter(pFile, pScene, false, props);
if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) { if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) {
throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
@ -86,9 +86,9 @@ 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 // 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* ) { void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* props) {
// invoke the exporter // invoke the exporter
ObjExporter exporter(pFile, pScene, true); ObjExporter exporter(pFile, pScene, true, props);
if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) { if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) {
throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
@ -111,7 +111,7 @@ void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* p
static const std::string MaterialExt = ".mtl"; static const std::string MaterialExt = ".mtl";
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl) ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl, const ExportProperties* props)
: filename(_filename) : filename(_filename)
, pScene(pScene) , pScene(pScene)
, vn() , vn()
@ -130,7 +130,10 @@ ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMt
mOutputMat.imbue(l); mOutputMat.imbue(l);
mOutputMat.precision(ASSIMP_AI_REAL_TEXT_PRECISION); mOutputMat.precision(ASSIMP_AI_REAL_TEXT_PRECISION);
WriteGeometryFile(noMtl); WriteGeometryFile(
noMtl,
props == nullptr ? true : props->GetPropertyBool("bJoinIdenticalVertices", true)
);
if ( !noMtl ) { if ( !noMtl ) {
WriteMaterialFile(); WriteMaterialFile();
} }
@ -255,14 +258,14 @@ void ObjExporter::WriteMaterialFile() {
} }
} }
void ObjExporter::WriteGeometryFile(bool noMtl) { void ObjExporter::WriteGeometryFile(bool noMtl, bool merge_identical_vertices) {
WriteHeader(mOutput); WriteHeader(mOutput);
if (!noMtl) if (!noMtl)
mOutput << "mtllib " << GetMaterialLibName() << endl << endl; mOutput << "mtllib " << GetMaterialLibName() << endl << endl;
// collect mesh geometry // collect mesh geometry
aiMatrix4x4 mBase; aiMatrix4x4 mBase;
AddNode(pScene->mRootNode, mBase); AddNode(pScene->mRootNode, mBase, merge_identical_vertices);
// write vertex positions with colors, if any // write vertex positions with colors, if any
mVpMap.getKeys( vp ); mVpMap.getKeys( vp );
@ -330,7 +333,7 @@ void ObjExporter::WriteGeometryFile(bool noMtl) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) { void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat, bool merge_identical_vertices) {
mMeshes.emplace_back(); mMeshes.emplace_back();
MeshInstance& mesh = mMeshes.back(); MeshInstance& mesh = mMeshes.back();
@ -362,13 +365,14 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
for(unsigned int a = 0; a < f.mNumIndices; ++a) { for(unsigned int a = 0; a < f.mNumIndices; ++a) {
const unsigned int idx = f.mIndices[a]; const unsigned int idx = f.mIndices[a];
const unsigned int fi = merge_identical_vertices ? 0 : idx;
aiVector3D vert = mat * m->mVertices[idx]; aiVector3D vert = mat * m->mVertices[idx];
if ( nullptr != m->mColors[ 0 ] ) { if ( nullptr != m->mColors[ 0 ] ) {
aiColor4D col4 = m->mColors[ 0 ][ idx ]; aiColor4D col4 = m->mColors[ 0 ][ idx ];
face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b)}); face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b), fi});
} else { } else {
face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0)}); face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0), fi});
} }
if (m->mNormals) { if (m->mNormals) {
@ -388,21 +392,21 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) { void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent, bool merge_identical_vertices) {
const aiMatrix4x4& mAbs = mParent * nd->mTransformation; const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
aiMesh *cm( nullptr ); aiMesh *cm( nullptr );
for(unsigned int i = 0; i < nd->mNumMeshes; ++i) { for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
cm = pScene->mMeshes[nd->mMeshes[i]]; cm = pScene->mMeshes[nd->mMeshes[i]];
if (nullptr != cm) { if (nullptr != cm) {
AddMesh(cm->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs); AddMesh(cm->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs, merge_identical_vertices);
} else { } else {
AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs); AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs, merge_identical_vertices);
} }
} }
for(unsigned int i = 0; i < nd->mNumChildren; ++i) { for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
AddNode(nd->mChildren[i], mAbs); AddNode(nd->mChildren[i], mAbs, merge_identical_vertices);
} }
} }

View File

@ -51,6 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector> #include <vector>
#include <map> #include <map>
#include <assimp/Exporter.hpp>
struct aiScene; struct aiScene;
struct aiNode; struct aiNode;
struct aiMesh; struct aiMesh;
@ -63,7 +65,7 @@ namespace Assimp {
class ObjExporter { class ObjExporter {
public: public:
/// Constructor for a specific scene to export /// Constructor for a specific scene to export
ObjExporter(const char* filename, const aiScene* pScene, bool noMtl=false); ObjExporter(const char* filename, const aiScene* pScene, bool noMtl=false, const ExportProperties* props = nullptr);
~ObjExporter(); ~ObjExporter();
std::string GetMaterialLibName(); std::string GetMaterialLibName();
std::string GetMaterialLibFileName(); std::string GetMaterialLibFileName();
@ -97,10 +99,10 @@ private:
void WriteHeader(std::ostringstream& out); void WriteHeader(std::ostringstream& out);
void WriteMaterialFile(); void WriteMaterialFile();
void WriteGeometryFile(bool noMtl=false); void WriteGeometryFile(bool noMtl=false, bool merge_identical_vertices = false);
std::string GetMaterialName(unsigned int index); std::string GetMaterialName(unsigned int index);
void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat); void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat, bool merge_identical_vertices);
void AddNode(const aiNode* nd, const aiMatrix4x4& mParent); void AddNode(const aiNode* nd, const aiMatrix4x4& mParent, bool merge_identical_vertices);
private: private:
std::string filename; std::string filename;
@ -109,6 +111,7 @@ private:
struct vertexData { struct vertexData {
aiVector3D vp; aiVector3D vp;
aiColor3D vc; // OBJ does not support 4D color aiColor3D vc; // OBJ does not support 4D color
uint32_t index = 0;
}; };
std::vector<aiVector3D> vn, vt; std::vector<aiVector3D> vn, vt;
@ -133,7 +136,7 @@ private:
if (a.vc.g > b.vc.g) return false; if (a.vc.g > b.vc.g) return false;
if (a.vc.b < b.vc.b) return true; if (a.vc.b < b.vc.b) return true;
if (a.vc.b > b.vc.b) return false; if (a.vc.b > b.vc.b) return false;
return false; return a.index < b.index;
} }
}; };