commit
ccc0a50d96
|
@ -55,6 +55,8 @@ namespace XmlTag {
|
||||||
static const std::string resources = "resources";
|
static const std::string resources = "resources";
|
||||||
static const std::string object = "object";
|
static const std::string object = "object";
|
||||||
static const std::string mesh = "mesh";
|
static const std::string mesh = "mesh";
|
||||||
|
static const std::string components = "components";
|
||||||
|
static const std::string component = "component";
|
||||||
static const std::string vertices = "vertices";
|
static const std::string vertices = "vertices";
|
||||||
static const std::string vertex = "vertex";
|
static const std::string vertex = "vertex";
|
||||||
static const std::string triangles = "triangles";
|
static const std::string triangles = "triangles";
|
||||||
|
@ -67,6 +69,7 @@ namespace XmlTag {
|
||||||
static const std::string v3 = "v3";
|
static const std::string v3 = "v3";
|
||||||
static const std::string id = "id";
|
static const std::string id = "id";
|
||||||
static const std::string pid = "pid";
|
static const std::string pid = "pid";
|
||||||
|
static const std::string pindex = "pindex";
|
||||||
static const std::string p1 = "p1";
|
static const std::string p1 = "p1";
|
||||||
static const std::string name = "name";
|
static const std::string name = "name";
|
||||||
static const std::string type = "type";
|
static const std::string type = "type";
|
||||||
|
|
|
@ -137,7 +137,7 @@ bool D3MFExporter::exportContentTypes() {
|
||||||
mContentOutput << std::endl;
|
mContentOutput << std::endl;
|
||||||
mContentOutput << "</Types>";
|
mContentOutput << "</Types>";
|
||||||
mContentOutput << std::endl;
|
mContentOutput << std::endl;
|
||||||
exportContentTyp(XmlTag::CONTENT_TYPES_ARCHIVE);
|
zipContentType(XmlTag::CONTENT_TYPES_ARCHIVE);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,7 @@ bool D3MFExporter::exportRelations() {
|
||||||
mRelOutput << "</Relationships>";
|
mRelOutput << "</Relationships>";
|
||||||
mRelOutput << std::endl;
|
mRelOutput << std::endl;
|
||||||
|
|
||||||
writeRelInfoToFile("_rels", ".rels");
|
zipRelInfo("_rels", ".rels");
|
||||||
mRelOutput.flush();
|
mRelOutput.flush();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -196,7 +196,7 @@ bool D3MFExporter::export3DModel() {
|
||||||
info->type = XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
|
info->type = XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
|
||||||
mRelations.push_back(info);
|
mRelations.push_back(info);
|
||||||
|
|
||||||
writeModelToArchive("3D", "3DModel.model");
|
zipModel("3D", "3DModel.model");
|
||||||
mModelOutput.flush();
|
mModelOutput.flush();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -357,42 +357,27 @@ void D3MFExporter::writeBuild() {
|
||||||
mModelOutput << std::endl;
|
mModelOutput << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3MFExporter::exportContentTyp(const std::string &filename) {
|
void D3MFExporter::zipContentType(const std::string &filename) {
|
||||||
if (nullptr == m_zipArchive) {
|
addFileInZip(filename, mContentOutput.str());
|
||||||
throw DeadlyExportError("3MF-Export: Zip archive not valid, nullptr.");
|
|
||||||
}
|
|
||||||
const std::string entry = filename;
|
|
||||||
zip_entry_open(m_zipArchive, entry.c_str());
|
|
||||||
|
|
||||||
const std::string &exportTxt(mContentOutput.str());
|
|
||||||
zip_entry_write(m_zipArchive, exportTxt.c_str(), exportTxt.size());
|
|
||||||
|
|
||||||
zip_entry_close(m_zipArchive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3MFExporter::writeModelToArchive(const std::string &folder, const std::string &modelName) {
|
void D3MFExporter::zipModel(const std::string &folder, const std::string &modelName) {
|
||||||
if (nullptr == m_zipArchive) {
|
|
||||||
throw DeadlyExportError("3MF-Export: Zip archive not valid, nullptr.");
|
|
||||||
}
|
|
||||||
const std::string entry = folder + "/" + modelName;
|
const std::string entry = folder + "/" + modelName;
|
||||||
zip_entry_open(m_zipArchive, entry.c_str());
|
addFileInZip(entry, mModelOutput.str());
|
||||||
|
|
||||||
const std::string &exportTxt(mModelOutput.str());
|
|
||||||
zip_entry_write(m_zipArchive, exportTxt.c_str(), exportTxt.size());
|
|
||||||
|
|
||||||
zip_entry_close(m_zipArchive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3MFExporter::writeRelInfoToFile(const std::string &folder, const std::string &relName) {
|
void D3MFExporter::zipRelInfo(const std::string &folder, const std::string &relName) {
|
||||||
|
const std::string entry = folder + "/" + relName;
|
||||||
|
addFileInZip(entry, mRelOutput.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3MFExporter::addFileInZip(const std::string& entry, const std::string& content) {
|
||||||
if (nullptr == m_zipArchive) {
|
if (nullptr == m_zipArchive) {
|
||||||
throw DeadlyExportError("3MF-Export: Zip archive not valid, nullptr.");
|
throw DeadlyExportError("3MF-Export: Zip archive not valid, nullptr.");
|
||||||
}
|
}
|
||||||
const std::string entry = folder + "/" + relName;
|
|
||||||
zip_entry_open(m_zipArchive, entry.c_str());
|
zip_entry_open(m_zipArchive, entry.c_str());
|
||||||
|
zip_entry_write(m_zipArchive, content.c_str(), content.size());
|
||||||
const std::string &exportTxt(mRelOutput.str());
|
|
||||||
zip_entry_write(m_zipArchive, exportTxt.c_str(), exportTxt.size());
|
|
||||||
|
|
||||||
zip_entry_close(m_zipArchive);
|
zip_entry_close(m_zipArchive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,9 +82,12 @@ protected:
|
||||||
void writeVertex( const aiVector3D &pos );
|
void writeVertex( const aiVector3D &pos );
|
||||||
void writeFaces( aiMesh *mesh, unsigned int matIdx );
|
void writeFaces( aiMesh *mesh, unsigned int matIdx );
|
||||||
void writeBuild();
|
void writeBuild();
|
||||||
void exportContentTyp( const std::string &filename );
|
|
||||||
void writeModelToArchive( const std::string &folder, const std::string &modelName );
|
// Zip the data
|
||||||
void writeRelInfoToFile( const std::string &folder, const std::string &relName );
|
void zipContentType( const std::string &filename );
|
||||||
|
void zipModel( const std::string &folder, const std::string &modelName );
|
||||||
|
void zipRelInfo( const std::string &folder, const std::string &relName );
|
||||||
|
void addFileInZip( const std::string &entry, const std::string &content );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mArchiveName;
|
std::string mArchiveName;
|
||||||
|
|
|
@ -66,22 +66,79 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
namespace D3MF {
|
namespace D3MF {
|
||||||
|
|
||||||
|
enum class ResourceType {
|
||||||
|
RT_Object,
|
||||||
|
RT_BaseMaterials,
|
||||||
|
RT_Unknown
|
||||||
|
}; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
|
||||||
|
|
||||||
|
class Resource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Resource(int id) :
|
||||||
|
mId(id) {}
|
||||||
|
|
||||||
|
virtual ~Resource() {}
|
||||||
|
|
||||||
|
int mId;
|
||||||
|
|
||||||
|
virtual ResourceType getType() {
|
||||||
|
return ResourceType::RT_Unknown;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BaseMaterials : public Resource {
|
||||||
|
public:
|
||||||
|
BaseMaterials(int id) :
|
||||||
|
Resource(id),
|
||||||
|
mMaterials(),
|
||||||
|
mMaterialIndex() {}
|
||||||
|
|
||||||
|
std::vector<aiMaterial *> mMaterials;
|
||||||
|
std::vector<unsigned int> mMaterialIndex;
|
||||||
|
|
||||||
|
virtual ResourceType getType() {
|
||||||
|
return ResourceType::RT_BaseMaterials;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Component {
|
||||||
|
int mObjectId;
|
||||||
|
aiMatrix4x4 mTransformation;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Object : public Resource {
|
||||||
|
public:
|
||||||
|
std::vector<aiMesh*> mMeshes;
|
||||||
|
std::vector<unsigned int> mMeshIndex;
|
||||||
|
std::vector<Component> mComponents;
|
||||||
|
std::string mName;
|
||||||
|
|
||||||
|
Object(int id) :
|
||||||
|
Resource(id),
|
||||||
|
mName (std::string("Object_") + to_string(id)){}
|
||||||
|
|
||||||
|
virtual ResourceType getType() {
|
||||||
|
return ResourceType::RT_Object;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
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(),
|
mResourcesDictionnary(),
|
||||||
mMatArray(),
|
mMaterialCount(0),
|
||||||
mActiveMatGroup(99999999),
|
mMeshCount(0),
|
||||||
mMatId2MatArray(),
|
|
||||||
mXmlParser(xmlParser) {
|
mXmlParser(xmlParser) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
~XmlSerializer() {
|
~XmlSerializer() {
|
||||||
// empty
|
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) {
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImportXml(aiScene *scene) {
|
void ImportXml(aiScene *scene) {
|
||||||
|
@ -89,10 +146,8 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scene->mRootNode = new aiNode();
|
scene->mRootNode = new aiNode("3MF");
|
||||||
std::vector<aiNode *> children;
|
|
||||||
|
|
||||||
std::string nodeName;
|
|
||||||
XmlNode node = mXmlParser->getRootNode().child("model");
|
XmlNode node = mXmlParser->getRootNode().child("model");
|
||||||
if (node.empty()) {
|
if (node.empty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -101,9 +156,7 @@ public:
|
||||||
for (XmlNode currentNode = resNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
|
for (XmlNode currentNode = resNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
|
||||||
const std::string ¤tNodeName = currentNode.name();
|
const std::string ¤tNodeName = currentNode.name();
|
||||||
if (currentNodeName == D3MF::XmlTag::object) {
|
if (currentNodeName == D3MF::XmlTag::object) {
|
||||||
children.push_back(ReadObject(currentNode, scene));
|
ReadObject(currentNode);;
|
||||||
} else if (currentNodeName == D3MF::XmlTag::build) {
|
|
||||||
//
|
|
||||||
} else if (currentNodeName == D3MF::XmlTag::basematerials) {
|
} else if (currentNodeName == D3MF::XmlTag::basematerials) {
|
||||||
ReadBaseMaterials(currentNode);
|
ReadBaseMaterials(currentNode);
|
||||||
} else if (currentNodeName == D3MF::XmlTag::meta) {
|
} else if (currentNodeName == D3MF::XmlTag::meta) {
|
||||||
|
@ -111,10 +164,29 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scene->mRootNode->mName.length == 0) {
|
XmlNode buildNode = node.child("build");
|
||||||
scene->mRootNode->mName.Set("3MF");
|
for (XmlNode currentNode = buildNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
|
||||||
|
const std::string ¤tNodeName = currentNode.name();
|
||||||
|
if (currentNodeName == D3MF::XmlTag::item) {
|
||||||
|
int objectId = -1;
|
||||||
|
std::string transformationMatrixStr;
|
||||||
|
aiMatrix4x4 transformationMatrix;
|
||||||
|
getNodeAttribute(currentNode, D3MF::XmlTag::objectid, objectId);
|
||||||
|
bool hasTransform = getNodeAttribute(currentNode, D3MF::XmlTag::transform, transformationMatrixStr);
|
||||||
|
|
||||||
|
auto it = mResourcesDictionnary.find(objectId);
|
||||||
|
if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
|
||||||
|
Object *obj = static_cast<Object *>(it->second);
|
||||||
|
if (hasTransform) {
|
||||||
|
transformationMatrix = parseTransformMatrix(transformationMatrixStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
addObjectToNode(scene->mRootNode, obj, transformationMatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// import the metadata
|
// import the metadata
|
||||||
if (!mMetaData.empty()) {
|
if (!mMetaData.empty()) {
|
||||||
const size_t numMeta(mMetaData.size());
|
const size_t numMeta(mMetaData.size());
|
||||||
|
@ -126,66 +198,177 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// import the meshes
|
// import the meshes
|
||||||
scene->mNumMeshes = static_cast<unsigned int>(mMeshes.size());
|
scene->mNumMeshes = static_cast<unsigned int>(mMeshCount);
|
||||||
scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
|
if (scene->mNumMeshes != 0) {
|
||||||
std::copy(mMeshes.begin(), mMeshes.end(), scene->mMeshes);
|
scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
|
||||||
|
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) {
|
||||||
|
if (it->second->getType() == ResourceType::RT_Object) {
|
||||||
|
Object *obj = static_cast<Object*>(it->second);
|
||||||
|
for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) {
|
||||||
|
scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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 (scene->mNumMaterials != 0) {
|
||||||
scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
|
scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
|
||||||
std::copy(mMatArray.begin(), mMatArray.end(), scene->mMaterials);
|
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) {
|
||||||
|
if (it->second->getType() == ResourceType::RT_BaseMaterials) {
|
||||||
|
BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
|
||||||
|
for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) {
|
||||||
|
scene->mMaterials[baseMaterials->mMaterialIndex[i]] = baseMaterials->mMaterials[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the scene-graph
|
|
||||||
scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size());
|
|
||||||
scene->mRootNode->mChildren = new aiNode *[scene->mRootNode->mNumChildren]();
|
|
||||||
std::copy(children.begin(), children.end(), scene->mRootNode->mChildren);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
aiNode *ReadObject(XmlNode &node, aiScene *scene) {
|
|
||||||
std::unique_ptr<aiNode> nodePtr(new aiNode());
|
|
||||||
|
|
||||||
std::vector<unsigned long> meshIds;
|
void addObjectToNode(aiNode* parent, Object* obj, aiMatrix4x4 nodeTransform) {
|
||||||
|
aiNode *sceneNode = new aiNode(obj->mName);
|
||||||
|
sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size());
|
||||||
|
sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes];
|
||||||
|
std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes);
|
||||||
|
|
||||||
std::string name, type;
|
sceneNode->mTransformation = nodeTransform;
|
||||||
pugi::xml_attribute attr = node.attribute(D3MF::XmlTag::id.c_str());
|
|
||||||
if (!attr.empty()) {
|
parent->addChildren(1, &sceneNode);
|
||||||
name = attr.as_string();
|
|
||||||
|
for (size_t i = 0; i < obj->mComponents.size(); ++i) {
|
||||||
|
Component c = obj->mComponents[i];
|
||||||
|
auto it = mResourcesDictionnary.find(c.mObjectId);
|
||||||
|
if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
|
||||||
|
addObjectToNode(sceneNode, static_cast<Object*>(it->second), c.mTransformation);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
attr = node.attribute(D3MF::XmlTag::type.c_str());
|
}
|
||||||
if (!attr.empty()) {
|
|
||||||
type = attr.as_string();
|
bool getNodeAttribute(const XmlNode& node, const std::string& attribute, std::string& value) {
|
||||||
|
pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str());
|
||||||
|
if (!objectAttribute.empty()) {
|
||||||
|
value = objectAttribute.as_string();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) {
|
||||||
|
std::string strValue;
|
||||||
|
bool ret = getNodeAttribute(node, attribute, strValue);
|
||||||
|
if (ret) {
|
||||||
|
value = std::atoi(strValue.c_str());
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
|
||||||
|
// split the string
|
||||||
|
std::vector<float> numbers;
|
||||||
|
std::string currentNumber;
|
||||||
|
for (size_t i = 0; i < matrixStr.size(); ++i) {
|
||||||
|
const char c = matrixStr[i];
|
||||||
|
if (c == ' ') {
|
||||||
|
if (currentNumber.size() > 0) {
|
||||||
|
float f = std::stof(currentNumber);
|
||||||
|
numbers.push_back(f);
|
||||||
|
currentNumber.clear();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentNumber.push_back(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentNumber.size() > 0) {
|
||||||
|
float f = std::stof(currentNumber);
|
||||||
|
numbers.push_back(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
nodePtr->mParent = scene->mRootNode;
|
aiMatrix4x4 transformMatrix;
|
||||||
nodePtr->mName.Set(name);
|
transformMatrix.a1 = numbers[0];
|
||||||
|
transformMatrix.b1 = numbers[1];
|
||||||
|
transformMatrix.c1 = numbers[2];
|
||||||
|
transformMatrix.d1 = 0;
|
||||||
|
|
||||||
size_t meshIdx = mMeshes.size();
|
transformMatrix.a2 = numbers[3];
|
||||||
|
transformMatrix.b2 = numbers[4];
|
||||||
|
transformMatrix.c2 = numbers[5];
|
||||||
|
transformMatrix.d2 = 0;
|
||||||
|
|
||||||
|
transformMatrix.a3 = numbers[6];
|
||||||
|
transformMatrix.b3 = numbers[7];
|
||||||
|
transformMatrix.c3 = numbers[8];
|
||||||
|
transformMatrix.d3 = 0;
|
||||||
|
|
||||||
|
transformMatrix.a4 = numbers[9];
|
||||||
|
transformMatrix.b4 = numbers[10];
|
||||||
|
transformMatrix.c4 = numbers[11];
|
||||||
|
transformMatrix.d4 = 1;
|
||||||
|
return transformMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadObject(XmlNode &node) {
|
||||||
|
int id = -1, pid = -1, pindex = -1;
|
||||||
|
bool hasId = getNodeAttribute(node, D3MF::XmlTag::id, id);
|
||||||
|
//bool hasType = getNodeAttribute(node, D3MF::XmlTag::type, type); not used currently
|
||||||
|
bool hasPid = getNodeAttribute(node, D3MF::XmlTag::pid, pid);
|
||||||
|
bool hasPindex = getNodeAttribute(node, D3MF::XmlTag::pindex, pindex);
|
||||||
|
|
||||||
|
std::string idStr = to_string(id);
|
||||||
|
|
||||||
|
if (!hasId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object *obj = new Object(id);
|
||||||
|
|
||||||
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
|
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
|
||||||
const std::string ¤tName = currentNode.name();
|
const std::string ¤tName = currentNode.name();
|
||||||
if (currentName == D3MF::XmlTag::mesh) {
|
if (currentName == D3MF::XmlTag::mesh) {
|
||||||
auto mesh = ReadMesh(currentNode);
|
auto mesh = ReadMesh(currentNode);
|
||||||
mesh->mName.Set(name);
|
mesh->mName.Set(idStr);
|
||||||
mMeshes.push_back(mesh);
|
|
||||||
meshIds.push_back(static_cast<unsigned long>(meshIdx));
|
if (hasPid) {
|
||||||
++meshIdx;
|
auto it = mResourcesDictionnary.find(pid);
|
||||||
|
if (hasPindex && it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_BaseMaterials) {
|
||||||
|
BaseMaterials *materials = static_cast<BaseMaterials *>(it->second);
|
||||||
|
mesh->mMaterialIndex = materials->mMaterialIndex[pindex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->mMeshes.push_back(mesh);
|
||||||
|
obj->mMeshIndex.push_back(mMeshCount);
|
||||||
|
mMeshCount++;
|
||||||
|
} else if (currentName == D3MF::XmlTag::components) {
|
||||||
|
for (XmlNode currentSubNode = currentNode.first_child(); currentSubNode; currentSubNode = currentSubNode.next_sibling()) {
|
||||||
|
if (currentSubNode.name() == D3MF::XmlTag::component) {
|
||||||
|
int objectId = -1;
|
||||||
|
std::string componentTransformStr;
|
||||||
|
aiMatrix4x4 componentTransform;
|
||||||
|
if (getNodeAttribute(currentSubNode, D3MF::XmlTag::transform, componentTransformStr)) {
|
||||||
|
componentTransform = parseTransformMatrix(componentTransformStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId))
|
||||||
|
obj->mComponents.push_back({ objectId, componentTransform });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nodePtr->mNumMeshes = static_cast<unsigned int>(meshIds.size());
|
mResourcesDictionnary.insert(std::make_pair(id, obj));
|
||||||
|
|
||||||
nodePtr->mMeshes = new unsigned int[nodePtr->mNumMeshes];
|
|
||||||
|
|
||||||
std::copy(meshIds.begin(), meshIds.end(), nodePtr->mMeshes);
|
|
||||||
|
|
||||||
return nodePtr.release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aiMesh *ReadMesh(XmlNode &node) {
|
aiMesh *ReadMesh(XmlNode &node) {
|
||||||
aiMesh *mesh = new aiMesh();
|
aiMesh *mesh = new aiMesh();
|
||||||
|
|
||||||
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
|
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
|
||||||
const std::string ¤tName = currentNode.name();
|
const std::string ¤tName = currentNode.name();
|
||||||
if (currentName == D3MF::XmlTag::vertices) {
|
if (currentName == D3MF::XmlTag::vertices) {
|
||||||
|
@ -241,11 +424,23 @@ private:
|
||||||
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
|
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
|
||||||
const std::string ¤tName = currentNode.name();
|
const std::string ¤tName = currentNode.name();
|
||||||
if (currentName == D3MF::XmlTag::triangle) {
|
if (currentName == D3MF::XmlTag::triangle) {
|
||||||
faces.push_back(ReadTriangle(currentNode));
|
aiFace face = ReadTriangle(currentNode);
|
||||||
const char *pidToken = currentNode.attribute(D3MF::XmlTag::p1.c_str()).as_string();
|
faces.push_back(face);
|
||||||
if (nullptr != pidToken) {
|
|
||||||
int matIdx(std::atoi(pidToken));
|
int pid, p1;
|
||||||
mesh->mMaterialIndex = matIdx;
|
bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
|
||||||
|
bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
|
||||||
|
|
||||||
|
if (hasPid && hasP1) {
|
||||||
|
auto it = mResourcesDictionnary.find(pid);
|
||||||
|
if (it != mResourcesDictionnary.end())
|
||||||
|
{
|
||||||
|
if (it->second->getType() == ResourceType::RT_BaseMaterials) {
|
||||||
|
BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
|
||||||
|
mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
|
||||||
|
}
|
||||||
|
// TODO: manage the separation into several meshes if the triangles of the mesh do not all refer to the same material
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,26 +465,21 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadBaseMaterials(XmlNode &node) {
|
void ReadBaseMaterials(XmlNode &node) {
|
||||||
std::vector<unsigned int> MatIdArray;
|
int id = -1;
|
||||||
const char *baseMaterialId = node.attribute(D3MF::XmlTag::basematerials_id.c_str()).as_string();
|
if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) {
|
||||||
if (nullptr != baseMaterialId) {
|
BaseMaterials* baseMaterials = new BaseMaterials(id);
|
||||||
unsigned int id = std::atoi(baseMaterialId);
|
|
||||||
const size_t newMatIdx(mMatArray.size());
|
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling())
|
||||||
if (id != mActiveMatGroup) {
|
{
|
||||||
mActiveMatGroup = id;
|
if (currentNode.name() == D3MF::XmlTag::basematerials_base) {
|
||||||
MatId2MatArray::const_iterator it(mMatId2MatArray.find(id));
|
baseMaterials->mMaterialIndex.push_back(mMaterialCount);
|
||||||
if (mMatId2MatArray.end() == it) {
|
baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id));
|
||||||
MatIdArray.clear();
|
mMaterialCount++;
|
||||||
mMatId2MatArray[id] = MatIdArray;
|
|
||||||
} else {
|
|
||||||
MatIdArray = it->second;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MatIdArray.push_back(static_cast<unsigned int>(newMatIdx));
|
|
||||||
mMatId2MatArray[mActiveMatGroup] = MatIdArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
mMatArray.push_back(readMaterialDef(node));
|
mResourcesDictionnary.insert(std::make_pair(id, baseMaterials));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseColor(const char *color, aiColor4D &diffuse) {
|
bool parseColor(const char *color, aiColor4D &diffuse) {
|
||||||
|
@ -304,37 +494,24 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *buf(color);
|
const char *buf(color);
|
||||||
if ('#' != *buf) {
|
if ('#' != buf[0]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
++buf;
|
|
||||||
char comp[3] = { 0, 0, '\0' };
|
|
||||||
|
|
||||||
comp[0] = *buf;
|
char r[3] = { buf[1], buf[2], '\0' };
|
||||||
++buf;
|
diffuse.r = static_cast<ai_real>(strtol(r, nullptr, 16)) / ai_real(255.0);
|
||||||
comp[1] = *buf;
|
|
||||||
++buf;
|
|
||||||
diffuse.r = static_cast<ai_real>(strtol(comp, nullptr, 16)) / ai_real(255.0);
|
|
||||||
|
|
||||||
comp[0] = *buf;
|
char g[3] = { buf[3], buf[4], '\0' };
|
||||||
++buf;
|
diffuse.g = static_cast<ai_real>(strtol(g, nullptr, 16)) / ai_real(255.0);
|
||||||
comp[1] = *buf;
|
|
||||||
++buf;
|
|
||||||
diffuse.g = static_cast<ai_real>(strtol(comp, nullptr, 16)) / ai_real(255.0);
|
|
||||||
|
|
||||||
comp[0] = *buf;
|
char b[3] = { buf[5], buf[6], '\0' };
|
||||||
++buf;
|
diffuse.b = static_cast<ai_real>(strtol(b, nullptr, 16)) / ai_real(255.0);
|
||||||
comp[1] = *buf;
|
|
||||||
++buf;
|
|
||||||
diffuse.b = static_cast<ai_real>(strtol(comp, nullptr, 16)) / ai_real(255.0);
|
|
||||||
|
|
||||||
if (7 == len)
|
if (7 == len)
|
||||||
return true;
|
return true;
|
||||||
comp[0] = *buf;
|
|
||||||
++buf;
|
char a[3] = { buf[7], buf[8], '\0' };
|
||||||
comp[1] = *buf;
|
diffuse.a = static_cast<ai_real>(strtol(a, nullptr, 16)) / ai_real(255.0);
|
||||||
++buf;
|
|
||||||
diffuse.a = static_cast<ai_real>(strtol(comp, nullptr, 16)) / ai_real(255.0);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -347,32 +524,30 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aiMaterial *readMaterialDef(XmlNode &node) {
|
aiMaterial *readMaterialDef(XmlNode &node, unsigned int basematerialsId) {
|
||||||
aiMaterial *mat(nullptr);
|
aiMaterial *material = new aiMaterial();
|
||||||
const char *name(nullptr);
|
material->mNumProperties = 0;
|
||||||
const std::string nodeName = node.name();
|
std::string name;
|
||||||
if (nodeName == D3MF::XmlTag::basematerials_base) {
|
bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
|
||||||
name = node.attribute(D3MF::XmlTag::basematerials_name.c_str()).as_string();
|
|
||||||
std::string stdMatName;
|
|
||||||
aiString matName;
|
|
||||||
std::string strId(to_string(mActiveMatGroup));
|
|
||||||
stdMatName += "id";
|
|
||||||
stdMatName += strId;
|
|
||||||
stdMatName += "_";
|
|
||||||
if (nullptr != name) {
|
|
||||||
stdMatName += std::string(name);
|
|
||||||
} else {
|
|
||||||
stdMatName += "basemat";
|
|
||||||
}
|
|
||||||
matName.Set(stdMatName);
|
|
||||||
|
|
||||||
mat = new aiMaterial;
|
std::string stdMaterialName;
|
||||||
mat->AddProperty(&matName, AI_MATKEY_NAME);
|
std::string strId(to_string(basematerialsId));
|
||||||
|
stdMaterialName += "id";
|
||||||
assignDiffuseColor(node, mat);
|
stdMaterialName += strId;
|
||||||
|
stdMaterialName += "_";
|
||||||
|
if (hasName) {
|
||||||
|
stdMaterialName += std::string(name);
|
||||||
|
} else {
|
||||||
|
stdMaterialName += "basemat_";
|
||||||
|
stdMaterialName += to_string(mMaterialCount - basematerialsId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mat;
|
aiString assimpMaterialName(stdMaterialName);
|
||||||
|
material->AddProperty(&assimpMaterialName, AI_MATKEY_NAME);
|
||||||
|
|
||||||
|
assignDiffuseColor(node, material);
|
||||||
|
|
||||||
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -381,10 +556,8 @@ private:
|
||||||
std::string value;
|
std::string value;
|
||||||
};
|
};
|
||||||
std::vector<MetaEntry> mMetaData;
|
std::vector<MetaEntry> mMetaData;
|
||||||
std::vector<aiMesh *> mMeshes;
|
std::map<unsigned int, Resource*> mResourcesDictionnary;
|
||||||
MatArray mMatArray;
|
unsigned int mMaterialCount, mMeshCount;
|
||||||
unsigned int mActiveMatGroup;
|
|
||||||
MatId2MatArray mMatId2MatArray;
|
|
||||||
XmlParser *mXmlParser;
|
XmlParser *mXmlParser;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,6 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool result = false;
|
|
||||||
const size_t len = stream->FileSize();
|
const size_t len = stream->FileSize();
|
||||||
mData.resize(len + 1);
|
mData.resize(len + 1);
|
||||||
memset(&mData[0], '\0', len + 1);
|
memset(&mData[0], '\0', len + 1);
|
||||||
|
@ -130,11 +129,11 @@ public:
|
||||||
mDoc = new pugi::xml_document();
|
mDoc = new pugi::xml_document();
|
||||||
pugi::xml_parse_result parse_result = mDoc->load_string(&mData[0], pugi::parse_full);
|
pugi::xml_parse_result parse_result = mDoc->load_string(&mData[0], pugi::parse_full);
|
||||||
if (parse_result.status == pugi::status_ok) {
|
if (parse_result.status == pugi::status_ok) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
ASSIMP_LOG_DEBUG("Error while parse xml.");
|
ASSIMP_LOG_DEBUG("Error while parse xml.");
|
||||||
result = true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pugi::xml_document *getDocument() const {
|
pugi::xml_document *getDocument() const {
|
||||||
|
|
Loading…
Reference in New Issue