Fix material parsing in the 3MF importer

pull/3558/head
Jean-Louis 2020-12-26 02:36:24 +01:00
parent 404bedd8be
commit c10d592b79
1 changed files with 30 additions and 30 deletions

View File

@ -68,14 +68,11 @@ namespace D3MF {
class XmlSerializer { class XmlSerializer {
public: public:
using MatArray = std::vector<aiMaterial *>;
using MatId2MatArray = std::map<unsigned int, std::vector<unsigned int>>;
XmlSerializer(XmlParser *xmlParser) : XmlSerializer(XmlParser *xmlParser) :
mMeshes(), mMeshes(),
mMatArray(), mBasematerialsDictionnary(),
mActiveMatGroup(99999999), mMaterialCount(0),
mMatId2MatArray(),
mXmlParser(xmlParser) { mXmlParser(xmlParser) {
// empty // empty
} }
@ -131,10 +128,14 @@ public:
std::copy(mMeshes.begin(), mMeshes.end(), scene->mMeshes); std::copy(mMeshes.begin(), mMeshes.end(), scene->mMeshes);
// import the materials // import the materials
scene->mNumMaterials = static_cast<unsigned int>(mMatArray.size()); scene->mNumMaterials = static_cast<unsigned int>(mMaterialCount);
if (0 != scene->mNumMaterials) { if (0 != scene->mNumMaterials) {
scene->mMaterials = new aiMaterial *[scene->mNumMaterials]; scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
std::copy(mMatArray.begin(), mMatArray.end(), scene->mMaterials); for (auto it = mBasematerialsDictionnary.begin(); it != mBasematerialsDictionnary.end(); it++) {
for (unsigned int i = 0; i < it->second.size(); ++i) {
scene->mMaterials[it->second[i].first] = it->second[i].second;
}
}
} }
// create the scene-graph // create the scene-graph
@ -242,10 +243,13 @@ private:
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == D3MF::XmlTag::triangle) { if (currentName == D3MF::XmlTag::triangle) {
faces.push_back(ReadTriangle(currentNode)); faces.push_back(ReadTriangle(currentNode));
const char *pidToken = currentNode.attribute(D3MF::XmlTag::p1.c_str()).as_string(); const char *pidToken = currentNode.attribute(D3MF::XmlTag::pid.c_str()).as_string();
if (nullptr != pidToken) { const char *p1Token = currentNode.attribute(D3MF::XmlTag::p1.c_str()).as_string();
int matIdx(std::atoi(pidToken)); if (nullptr != pidToken && nullptr != p1Token) {
mesh->mMaterialIndex = matIdx; int pid(std::atoi(pidToken));
int p1(std::atoi(p1Token));
mesh->mMaterialIndex = mBasematerialsDictionnary[pid][p1].first;
// TODO: manage the separation into several meshes if the triangles of the mesh do not all refer to the same material
} }
} }
} }
@ -274,22 +278,18 @@ private:
const char *baseMaterialId = node.attribute(D3MF::XmlTag::basematerials_id.c_str()).as_string(); const char *baseMaterialId = node.attribute(D3MF::XmlTag::basematerials_id.c_str()).as_string();
if (nullptr != baseMaterialId) { if (nullptr != baseMaterialId) {
unsigned int id = std::atoi(baseMaterialId); unsigned int id = std::atoi(baseMaterialId);
const size_t newMatIdx(mMatArray.size()); std::vector<std::pair<unsigned int, aiMaterial *> > materials;
if (id != mActiveMatGroup) {
mActiveMatGroup = id; for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling())
MatId2MatArray::const_iterator it(mMatId2MatArray.find(id)); {
if (mMatId2MatArray.end() == it) { if (currentNode.name() == D3MF::XmlTag::basematerials_base) {
MatIdArray.clear(); materials.push_back(std::make_pair(mMaterialCount, readMaterialDef(currentNode, id)));
mMatId2MatArray[id] = MatIdArray; mMaterialCount++;
} else {
MatIdArray = it->second;
} }
} }
MatIdArray.push_back(static_cast<unsigned int>(newMatIdx));
mMatId2MatArray[mActiveMatGroup] = MatIdArray;
}
mMatArray.push_back(readMaterialDef(node)); mBasematerialsDictionnary.insert(std::make_pair(id, materials));
}
} }
bool parseColor(const char *color, aiColor4D &diffuse) { bool parseColor(const char *color, aiColor4D &diffuse) {
@ -347,7 +347,7 @@ private:
} }
} }
aiMaterial *readMaterialDef(XmlNode &node) { aiMaterial *readMaterialDef(XmlNode &node, unsigned int basematerialsId) {
aiMaterial *mat(nullptr); aiMaterial *mat(nullptr);
const char *name(nullptr); const char *name(nullptr);
const std::string nodeName = node.name(); const std::string nodeName = node.name();
@ -355,14 +355,15 @@ private:
name = node.attribute(D3MF::XmlTag::basematerials_name.c_str()).as_string(); name = node.attribute(D3MF::XmlTag::basematerials_name.c_str()).as_string();
std::string stdMatName; std::string stdMatName;
aiString matName; aiString matName;
std::string strId(to_string(mActiveMatGroup)); std::string strId(to_string(basematerialsId));
stdMatName += "id"; stdMatName += "id";
stdMatName += strId; stdMatName += strId;
stdMatName += "_"; stdMatName += "_";
if (nullptr != name) { if (nullptr != name) {
stdMatName += std::string(name); stdMatName += std::string(name);
} else { } else {
stdMatName += "basemat"; stdMatName += "basemat_";
stdMatName += to_string(mMaterialCount - basematerialsId);
} }
matName.Set(stdMatName); matName.Set(stdMatName);
@ -382,9 +383,8 @@ private:
}; };
std::vector<MetaEntry> mMetaData; std::vector<MetaEntry> mMetaData;
std::vector<aiMesh *> mMeshes; std::vector<aiMesh *> mMeshes;
MatArray mMatArray; std::map<unsigned int, std::vector<std::pair<unsigned int, aiMaterial *>>> mBasematerialsDictionnary;
unsigned int mActiveMatGroup; unsigned int mMaterialCount;
MatId2MatArray mMatId2MatArray;
XmlParser *mXmlParser; XmlParser *mXmlParser;
}; };