Skip to content

Commit

Permalink
WIP4
Browse files Browse the repository at this point in the history
  • Loading branch information
HuguesDelorme committed Dec 12, 2024
1 parent ef90cab commit dc23efb
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 37 deletions.
15 changes: 15 additions & 0 deletions src/io_assimp/io_assimp_i18n.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/****************************************************************************
** Copyright (c) 2024, Fougue Ltd. <https://www.fougue.pro>
** All rights reserved.
** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt
****************************************************************************/

#include "../base/text_id.h"

namespace Mayo::IO {

struct AssimpI18N {
MAYO_DECLARE_TEXT_ID_FUNCTIONS(Mayo::IO::AssimpI18N)
};

} // namespace Mayo::IO
48 changes: 13 additions & 35 deletions src/io_assimp/io_assimp_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
****************************************************************************/

#include "io_assimp_reader.h"

#include "io_assimp_i18n.h"
#include "io_assimp_task_progress.h"

#include "../base/brep_utils.h"
#include "../base/caf_utils.h"
#include "../base/cpp_utils.h"
Expand All @@ -25,11 +29,6 @@
#include <assimp/ProgressHandler.hpp>
#include <assimp/postprocess.h>

#include <fmt/format.h>

#include <cassert>
#include <iostream>

#include <gp_Quaternion.hxx>
#include <gp_Trsf.hxx>
#include <BRep_Builder.hxx>
Expand All @@ -40,16 +39,17 @@
#include <XCAFDoc_VisMaterialCommon.hxx>
#include <XCAFDoc_VisMaterialPBR.hxx>

#include <fmt/format.h>

#include <cassert>
#include <iostream>

//#define MAYO_ASSIMP_READER_HANDLE_SCALING 1

namespace Mayo::IO {

namespace {

struct AssimpReaderI18N {
MAYO_DECLARE_TEXT_ID_FUNCTIONS(Mayo::IO::AssimpReaderI18N)
};

// Retrieve the scaling component in assimp matrix 'trsf'
aiVector3D aiMatrixScaling(const aiMatrix4x4& trsf)
{
Expand Down Expand Up @@ -271,28 +271,6 @@ OccHandle<Poly_Triangulation> createOccTriangulation(const aiMesh* mesh)
return triangulation;
}

// Provides assimp progress handler for TaskProgress
class AssimpProgressHandler : public Assimp::ProgressHandler {
public:
AssimpProgressHandler(TaskProgress* progress)
: m_progress(progress)
{}

bool Update(float percent = -1.f) override
{
if (TaskProgress::isAbortRequested(m_progress))
return false;

if (percent > 0)
m_progress->setValue(percent * 100);

return true;
}

private:
TaskProgress* m_progress = nullptr;
};

} // namespace

// --
Expand Down Expand Up @@ -336,7 +314,7 @@ bool AssimpReader::readFile(const FilePath& filepath, TaskProgress* progress)
//const unsigned flags = aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace;
//m_importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, false);
m_importer.SetPropertyBool(AI_CONFIG_PP_PTV_KEEP_HIERARCHY, true);
m_importer.SetProgressHandler(new AssimpProgressHandler(progress));
m_importer.SetProgressHandler(new AssimpTaskProgress(progress));
m_scene = m_importer.ReadFile(filepath.u8string(), flags);
if (!m_scene || (m_scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) || !m_scene->mRootNode) {
this->messenger()->emitError(m_importer.GetErrorString());
Expand Down Expand Up @@ -366,10 +344,10 @@ bool AssimpReader::readFile(const FilePath& filepath, TaskProgress* progress)
}
else if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE) {
// TODO Create and add a Poly_Polygon3D object
this->messenger()->emitWarning(AssimpReaderI18N::textIdTr("LINE primitives not supported yet"));
this->messenger()->emitWarning(AssimpI18N::textIdTr("LINE primitives not supported yet"));
}
else {
this->messenger()->emitWarning(AssimpReaderI18N::textIdTr("Some primitive not supported"));
this->messenger()->emitWarning(AssimpI18N::textIdTr("Some primitive not supported"));
}
}

Expand Down Expand Up @@ -500,7 +478,7 @@ OccHandle<Image_Texture> AssimpReader::findOccTexture(

// Report warning "texture not found"
MessageStream msgWarning = this->messenger()->warning();
msgWarning << fmt::format(AssimpReaderI18N::textIdTr("Texture not found: {}\nTried:"), strFilepath);
msgWarning << fmt::format(AssimpI18N::textIdTr("Texture not found: {}\nTried:"), strFilepath);
for (const FilePath& fp : textureFilepathCandidates)
msgWarning << "\n " << filepathCanonical(fp).make_preferred().u8string();

Expand Down
29 changes: 29 additions & 0 deletions src/io_assimp/io_assimp_task_progress.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/****************************************************************************
** Copyright (c) 2024, Fougue Ltd. <https://www.fougue.pro>
** All rights reserved.
** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt
****************************************************************************/

#include "io_assimp_task_progress.h"

#include "../base/task_progress.h"

namespace Mayo::IO {

AssimpTaskProgress::AssimpTaskProgress(TaskProgress* progress)
: m_progress(progress)
{
}

bool AssimpTaskProgress::Update(float percent)
{
if (TaskProgress::isAbortRequested(m_progress))
return false;

if (percent > 0)
m_progress->setValue(percent * 100);

return true;
}

} // namespace Mayo::IO
25 changes: 25 additions & 0 deletions src/io_assimp/io_assimp_task_progress.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/****************************************************************************
** Copyright (c) 2024, Fougue Ltd. <https://www.fougue.pro>
** All rights reserved.
** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt
****************************************************************************/

#pragma once

#include <assimp/ProgressHandler.hpp>
namespace Mayo { class TaskProgress; }

namespace Mayo::IO {

// Provides assimp progress handler over Mayo::TaskProgress object
class AssimpTaskProgress : public Assimp::ProgressHandler {
public:
AssimpTaskProgress(TaskProgress* progress);

bool Update(float percent = -1.f) override;

private:
TaskProgress* m_progress = nullptr;
};

} // namespace Mayo::IO
95 changes: 93 additions & 2 deletions src/io_assimp/io_assimp_writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,32 @@
****************************************************************************/

#include "io_assimp_writer.h"

#include "io_assimp_i18n.h"
#include "io_assimp_task_progress.h"

#include "../base/caf_utils.h"
#include "../base/filepath_conv.h"
#include "../base/io_system.h"
#include "../base/mesh_access.h"
#include "../base/mesh_utils.h"
#include "../base/messenger.h"
#include "../base/meta_enum.h"
#include "../base/string_conv.h"
#include "../base/task_progress.h"
#include "../base/tkernel_utils.h"

#include <assimp/Exporter.hpp>
#include <assimp/mesh.h>
#include <assimp/scene.h>

#include <Poly_Triangulation.hxx>
#include <XCAFDoc_VisMaterial.hxx>

#include <fmt/format.h>
#include <algorithm>
#include <fstream>
#include <locale>
#include <unordered_set>
#include <vector>

Expand Down Expand Up @@ -111,6 +121,65 @@ ai_MeshPtr createAssimpMesh(const IMeshAccess& mesh)
return ai_mesh;
}

// Helper function to return `str` converted to lower case characters
// The input string `str` is assumed to be encoded with the classic "C" locale
std::string stringToLowerCase_c(std::string_view str)
{
auto charToLowerCase_c = [](char c) {
return std::tolower(c, std::locale::classic());
};
std::string strLc;
std::transform(str.cbegin(), str.cend(), strLc.begin(), charToLowerCase_c);
return strLc;
}

// Helper function to return suffix string(utf8) from filepath `fp`
// Note: any starting '.' character is removed from the result string
std::string filepathSuffix(const FilePath& fp)
{
std::string suffix = stringToLowerCase_c(fp.extension().u8string());
if (!suffix.empty() && suffix.front() == '.')
suffix.erase(suffix.begin());

return suffix;
}

// Helper function to retrieve the Format corresponding to `suffix`
// Assumes that `suffix` is lowercase and does not start with '.'
Format findFormatFromFileSuffix(std::string_view suffix)
{
for (auto format : MetaEnum::values<Format>()) {
auto formatSuffixes = formatFileSuffixes(format);
auto itSuffix = std::find(formatSuffixes.begin(), formatSuffixes.end(), suffix);
if (itSuffix != formatSuffixes.end())
return format;
}

return Format_Unknown;
}

// Helper function to find the identifier of the Assimp export format corresponding to `format`
std::string findAssimpExportFormatId(const Assimp::Exporter& exporter, Format format)
{
const size_t formatCount = exporter.GetExportFormatCount();
for (size_t i = 0; i < formatCount; ++i) {
const aiExportFormatDesc* exportFormat = exporter.GetExportFormatDescription(i);
if (exportFormat == nullptr)
continue; //Skip

if (exportFormat->id && findFormatFromFileSuffix(exportFormat->id) == format)
return exportFormat->id;

if (exportFormat->fileExtension) {
const std::string exportFormatSuffix = stringToLowerCase_c(exportFormat->fileExtension);
if (findFormatFromFileSuffix(exportFormatSuffix) == format)
return exportFormat->id;
}
}

return {};
}

} // namespace

AssimpWriter::~AssimpWriter()
Expand All @@ -125,7 +194,10 @@ bool AssimpWriter::transfer(Span<const ApplicationItem> appItems, TaskProgress*
// Find materials
std::unordered_set<OccHandle<XCAFDoc_VisMaterial>> setVisMaterial;
System::traverseUniqueItems(appItems, [&](const DocumentTreeNode& treeNode) {

auto visMatTool = treeNode.document()->xcaf().visMaterialTool();
auto visMat = visMatTool->GetShapeMaterial(treeNode.label());
if (visMat)
setVisMaterial.insert(visMat);
});

// Find meshes
Expand Down Expand Up @@ -221,7 +293,26 @@ bool AssimpWriter::transfer(Span<const ApplicationItem> appItems, TaskProgress*
bool AssimpWriter::writeFile(const FilePath& fp, TaskProgress* progress)
{
progress = progress ? progress : &TaskProgress::null();
return false;
Assimp::Exporter exporter;
exporter.SetProgressHandler(new AssimpTaskProgress(progress));

const std::string fileSuffix = filepathSuffix(fp);
const Format format = findFormatFromFileSuffix(fileSuffix);
const std::string aiFormatId = findAssimpExportFormatId(exporter, format);
if (aiFormatId.empty()) {
this->messenger()->emitError(
fmt::format(AssimpI18N::textIdTr("No Assimp export format corresponding to file suffix '{}'"), fileSuffix)
);
return false;
}

const aiReturn errExport = exporter.Export(m_scene, aiFormatId, fp.u8string());
if (errExport != aiReturn_SUCCESS) {
this->messenger()->emitError(exporter.GetErrorString());
return false;
}

return true;
}

std::unique_ptr<PropertyGroup> AssimpWriter::createProperties(PropertyGroup* parentGroup)
Expand Down

0 comments on commit dc23efb

Please sign in to comment.