ogre + collada migration.
parent
77b705048b
commit
21678df589
|
@ -181,118 +181,10 @@ void AMFImporter::XML_CheckNode_MustHaveChildren(pugi::xml_node &node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string &pParentNodeName) {
|
|
||||||
static const size_t Uns_Skip_Len = 3;
|
|
||||||
const char *Uns_Skip[Uns_Skip_Len] = { "composite", "edge", "normal" };
|
|
||||||
|
|
||||||
static bool skipped_before[Uns_Skip_Len] = { false, false, false };
|
|
||||||
|
|
||||||
std::string nn(mReader->getNodeName());
|
|
||||||
bool found = false;
|
|
||||||
bool close_found = false;
|
|
||||||
size_t sk_idx;
|
|
||||||
|
|
||||||
for (sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++) {
|
|
||||||
if (nn != Uns_Skip[sk_idx]) continue;
|
|
||||||
|
|
||||||
found = true;
|
|
||||||
if (mReader->isEmptyElement()) {
|
|
||||||
close_found = true;
|
|
||||||
|
|
||||||
goto casu_cres;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (mReader->read()) {
|
|
||||||
if ((mReader->getNodeType() == irr::io::EXN_ELEMENT_END) && (nn == mReader->getNodeName())) {
|
|
||||||
close_found = true;
|
|
||||||
|
|
||||||
goto casu_cres;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++)
|
|
||||||
|
|
||||||
casu_cres:
|
|
||||||
|
|
||||||
if (!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + ".");
|
|
||||||
if (!close_found) Throw_CloseNotFound(nn);
|
|
||||||
|
|
||||||
if (!skipped_before[sk_idx]) {
|
|
||||||
skipped_before[sk_idx] = true;
|
|
||||||
ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, ".");
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
bool AMFImporter::XML_SearchNode(const std::string &nodeName) {
|
bool AMFImporter::XML_SearchNode(const std::string &nodeName) {
|
||||||
return nullptr != mXmlParser->findNode(nodeName);
|
return nullptr != mXmlParser->findNode(nodeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx) {
|
|
||||||
std::string val(mReader->getAttributeValue(pAttrIdx));
|
|
||||||
|
|
||||||
if ((val == "false") || (val == "0"))
|
|
||||||
return false;
|
|
||||||
else if ((val == "true") || (val == "1"))
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
throw DeadlyImportError("Bool attribute value can contain \"false\"/\"0\" or \"true\"/\"1\" not the \"" + val + "\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx) {
|
|
||||||
std::string val;
|
|
||||||
float tvalf;
|
|
||||||
|
|
||||||
ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val);
|
|
||||||
fast_atoreal_move(val.c_str(), tvalf, false);
|
|
||||||
|
|
||||||
return tvalf;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t AMFImporter::XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx) {
|
|
||||||
return strtoul10(mReader->getAttributeValue(pAttrIdx));
|
|
||||||
}
|
|
||||||
|
|
||||||
float AMFImporter::XML_ReadNode_GetVal_AsFloat() {
|
|
||||||
std::string val;
|
|
||||||
float tvalf;
|
|
||||||
|
|
||||||
if (!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. No data, seems file is corrupt.");
|
|
||||||
if (mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. Invalid type of XML element, seems file is corrupt.");
|
|
||||||
|
|
||||||
ParseHelper_FixTruncatedFloatString(mReader->getNodeData(), val);
|
|
||||||
fast_atoreal_move(val.c_str(), tvalf, false);
|
|
||||||
|
|
||||||
return tvalf;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t AMFImporter::XML_ReadNode_GetVal_AsU32() {
|
|
||||||
if (!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. No data, seems file is corrupt.");
|
|
||||||
if (mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. Invalid type of XML element, seems file is corrupt.");
|
|
||||||
|
|
||||||
return strtoul10(mReader->getNodeData());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AMFImporter::XML_ReadNode_GetVal_AsString(std::string &pValue) {
|
|
||||||
if (!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. No data, seems file is corrupt.");
|
|
||||||
if (mReader->getNodeType() != irr::io::EXN_TEXT)
|
|
||||||
throw DeadlyImportError("XML_ReadNode_GetVal_AsString. Invalid type of XML element, seems file is corrupt.");
|
|
||||||
|
|
||||||
pValue = mReader->getNodeData();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*********************************************************************************************************************************************/
|
|
||||||
/************************************************************ Functions: parse set ***********************************************************/
|
|
||||||
/*********************************************************************************************************************************************/
|
|
||||||
|
|
||||||
/*void AMFImporter::ParseHelper_Node_Enter(CAMFImporter_NodeElement *pNode) {
|
|
||||||
mNodeElement_Cur->Child.push_back(pNode); // add new element to current element child list.
|
|
||||||
mNodeElement_Cur = pNode; // switch current element to new one.
|
|
||||||
}
|
|
||||||
|
|
||||||
void AMFImporter::ParseHelper_Node_Exit() {
|
|
||||||
// check if we can walk up.
|
|
||||||
if (mNodeElement_Cur != nullptr) mNodeElement_Cur = mNodeElement_Cur->Parent;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
void AMFImporter::ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString) {
|
void AMFImporter::ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString) {
|
||||||
size_t instr_len;
|
size_t instr_len;
|
||||||
|
|
||||||
|
@ -369,7 +261,6 @@ void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std
|
||||||
}
|
}
|
||||||
|
|
||||||
void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
|
void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
|
||||||
// irr::io::IrrXMLReader *OldReader = mReader; // store current XMLreader.
|
|
||||||
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
|
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
|
||||||
|
|
||||||
// Check whether we can read from the file
|
// Check whether we can read from the file
|
||||||
|
@ -388,8 +279,6 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
|
||||||
throw DeadlyImportError("Root node \"amf\" not found.");
|
throw DeadlyImportError("Root node \"amf\" not found.");
|
||||||
}
|
}
|
||||||
ParseNode_Root();
|
ParseNode_Root();
|
||||||
|
|
||||||
//delete mReader;
|
|
||||||
} // namespace Assimp
|
} // namespace Assimp
|
||||||
|
|
||||||
// <amf
|
// <amf
|
||||||
|
@ -408,11 +297,6 @@ void AMFImporter::ParseNode_Root() {
|
||||||
version = root->attribute("version").as_string();
|
version = root->attribute("version").as_string();
|
||||||
|
|
||||||
// Read attributes for node <amf>.
|
// Read attributes for node <amf>.
|
||||||
/*MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("unit", unit, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("version", version, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_LOOPEND_WSKIP;*/
|
|
||||||
|
|
||||||
// Check attributes
|
// Check attributes
|
||||||
if (!mUnit.empty()) {
|
if (!mUnit.empty()) {
|
||||||
if ((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) {
|
if ((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) {
|
||||||
|
@ -428,6 +312,7 @@ void AMFImporter::ParseNode_Root() {
|
||||||
((AMFRoot *)ne)->Unit = unit;
|
((AMFRoot *)ne)->Unit = unit;
|
||||||
((AMFRoot *)ne)->Version = version;
|
((AMFRoot *)ne)->Version = version;
|
||||||
|
|
||||||
|
// Check for child nodes
|
||||||
for (pugi::xml_node ¤tNode : root->children()) {
|
for (pugi::xml_node ¤tNode : root->children()) {
|
||||||
const std::string currentName = currentNode.name();
|
const std::string currentName = currentNode.name();
|
||||||
if (currentName == "object") {
|
if (currentName == "object") {
|
||||||
|
@ -443,32 +328,6 @@ void AMFImporter::ParseNode_Root() {
|
||||||
}
|
}
|
||||||
mNodeElement_Cur = ne; // force restore "current" element
|
mNodeElement_Cur = ne; // force restore "current" element
|
||||||
}
|
}
|
||||||
// Check for child nodes
|
|
||||||
/*if (!mReader->isEmptyElement()) {
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("amf");
|
|
||||||
if (XML_CheckNode_NameEqual("object")) {
|
|
||||||
ParseNode_Object();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (XML_CheckNode_NameEqual("material")) {
|
|
||||||
ParseNode_Material();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (XML_CheckNode_NameEqual("texture")) {
|
|
||||||
ParseNode_Texture();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (XML_CheckNode_NameEqual("constellation")) {
|
|
||||||
ParseNode_Constellation();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (XML_CheckNode_NameEqual("metadata")) {
|
|
||||||
ParseNode_Metadata();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
MACRO_NODECHECK_LOOPEND("amf");
|
|
||||||
mNodeElement_Cur = ne; // force restore "current" element
|
|
||||||
} // if(!mReader->isEmptyElement())*/
|
|
||||||
|
|
||||||
mNodeElement_List.push_back(ne); // add to node element list because its a new object in graph.
|
mNodeElement_List.push_back(ne); // add to node element list because its a new object in graph.
|
||||||
}
|
}
|
||||||
|
@ -483,10 +342,6 @@ void AMFImporter::ParseNode_Root() {
|
||||||
void AMFImporter::ParseNode_Constellation(XmlNode &node) {
|
void AMFImporter::ParseNode_Constellation(XmlNode &node) {
|
||||||
std::string id;
|
std::string id;
|
||||||
id = node.attribute("id").as_string();
|
id = node.attribute("id").as_string();
|
||||||
// Read attributes for node <constellation>.
|
|
||||||
/*MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;*/
|
|
||||||
|
|
||||||
// create and if needed - define new grouping object.
|
// create and if needed - define new grouping object.
|
||||||
AMFNodeElementBase *ne = new AMFConstellation(mNodeElement_Cur);
|
AMFNodeElementBase *ne = new AMFConstellation(mNodeElement_Cur);
|
||||||
|
@ -497,6 +352,7 @@ void AMFImporter::ParseNode_Constellation(XmlNode &node) {
|
||||||
als.ID = id;
|
als.ID = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for child nodes
|
||||||
for (pugi::xml_node ¤tNode : node.children()) {
|
for (pugi::xml_node ¤tNode : node.children()) {
|
||||||
std::string name = currentNode.name();
|
std::string name = currentNode.name();
|
||||||
if (name == "instance") {
|
if (name == "instance") {
|
||||||
|
@ -509,26 +365,6 @@ void AMFImporter::ParseNode_Constellation(XmlNode &node) {
|
||||||
mNodeElement_Cur->Child.push_back(ne);
|
mNodeElement_Cur->Child.push_back(ne);
|
||||||
}
|
}
|
||||||
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
||||||
// Check for child nodes
|
|
||||||
/*if (!mReader->isEmptyElement()) {
|
|
||||||
ParseHelper_Node_Enter(ne);
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("constellation");
|
|
||||||
if (XML_CheckNode_NameEqual("instance")) {
|
|
||||||
ParseNode_Instance();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (XML_CheckNode_NameEqual("metadata")) {
|
|
||||||
ParseNode_Metadata();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
MACRO_NODECHECK_LOOPEND("constellation");
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
} // if(!mReader->isEmptyElement())
|
|
||||||
else {
|
|
||||||
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
|
||||||
} // if(!mReader->isEmptyElement()) else
|
|
||||||
|
|
||||||
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// <instance
|
// <instance
|
||||||
|
@ -542,9 +378,6 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
|
||||||
AMFNodeElementBase *ne(nullptr);
|
AMFNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
// Read attributes for node <constellation>.
|
// Read attributes for node <constellation>.
|
||||||
/* MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;*/
|
|
||||||
std::string objectid = node.attribute("objectid").as_string();
|
std::string objectid = node.attribute("objectid").as_string();
|
||||||
|
|
||||||
// used object id must be defined, check that.
|
// used object id must be defined, check that.
|
||||||
|
@ -552,9 +385,7 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
|
||||||
throw DeadlyImportError("\"objectid\" in <instance> must be defined.");
|
throw DeadlyImportError("\"objectid\" in <instance> must be defined.");
|
||||||
}
|
}
|
||||||
// create and define new grouping object.
|
// create and define new grouping object.
|
||||||
//ne = new CAMFImporter_NodeElement_Instance(mNodeElement_Cur);
|
|
||||||
ne = new AMFInstance(mNodeElement_Cur);
|
ne = new AMFInstance(mNodeElement_Cur);
|
||||||
//CAMFImporter_NodeElement_Instance &als = *((CAMFImporter_NodeElement_Instance *)ne); // alias for convenience
|
|
||||||
AMFInstance &als = *((AMFInstance *)ne);
|
AMFInstance &als = *((AMFInstance *)ne);
|
||||||
als.ObjectID = objectid;
|
als.ObjectID = objectid;
|
||||||
|
|
||||||
|
@ -584,29 +415,6 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
|
||||||
als.Delta.z = (ai_real)std::atof(currentNode.value());
|
als.Delta.z = (ai_real)std::atof(currentNode.value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for child nodes
|
|
||||||
/*if (!mReader->isEmptyElement()) {
|
|
||||||
|
|
||||||
als.Delta.Set(0, 0, 0);
|
|
||||||
als.Rotation.Set(0, 0, 0);
|
|
||||||
ParseHelper_Node_Enter(ne);
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("instance");
|
|
||||||
MACRO_NODECHECK_READCOMP_F("deltax", read_flag[0], als.Delta.x);
|
|
||||||
MACRO_NODECHECK_READCOMP_F("deltay", read_flag[1], als.Delta.y);
|
|
||||||
MACRO_NODECHECK_READCOMP_F("deltaz", read_flag[2], als.Delta.z);
|
|
||||||
MACRO_NODECHECK_READCOMP_F("rx", read_flag[3], als.Rotation.x);
|
|
||||||
MACRO_NODECHECK_READCOMP_F("ry", read_flag[4], als.Rotation.y);
|
|
||||||
MACRO_NODECHECK_READCOMP_F("rz", read_flag[5], als.Rotation.z);
|
|
||||||
MACRO_NODECHECK_LOOPEND("instance");
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
// also convert degrees to radians.
|
|
||||||
als.Rotation.x = AI_MATH_PI_F * als.Rotation.x / 180.0f;
|
|
||||||
als.Rotation.y = AI_MATH_PI_F * als.Rotation.y / 180.0f;
|
|
||||||
als.Rotation.z = AI_MATH_PI_F * als.Rotation.z / 180.0f;
|
|
||||||
} // if(!mReader->isEmptyElement())
|
|
||||||
else {
|
|
||||||
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
|
||||||
} // if(!mReader->isEmptyElement()) else*/
|
|
||||||
|
|
||||||
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
||||||
}
|
}
|
||||||
|
@ -623,10 +431,8 @@ void AMFImporter::ParseNode_Object(XmlNode &node) {
|
||||||
AMFNodeElementBase *ne(nullptr);
|
AMFNodeElementBase *ne(nullptr);
|
||||||
|
|
||||||
// Read attributes for node <object>.
|
// Read attributes for node <object>.
|
||||||
/*MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;*/
|
|
||||||
std::string id = node.attribute("id").as_string();
|
std::string id = node.attribute("id").as_string();
|
||||||
|
|
||||||
// create and if needed - define new geometry object.
|
// create and if needed - define new geometry object.
|
||||||
ne = new AMFObject(mNodeElement_Cur);
|
ne = new AMFObject(mNodeElement_Cur);
|
||||||
|
|
||||||
|
@ -652,35 +458,6 @@ void AMFImporter::ParseNode_Object(XmlNode &node) {
|
||||||
ParseNode_Metadata(currentNode);
|
ParseNode_Metadata(currentNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*if (!mReader->isEmptyElement()) {
|
|
||||||
bool col_read = false;
|
|
||||||
|
|
||||||
ParseHelper_Node_Enter(ne);
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("object");
|
|
||||||
if (XML_CheckNode_NameEqual("color")) {
|
|
||||||
// Check if color already defined for object.
|
|
||||||
if (col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <object>.");
|
|
||||||
// read data and set flag about it
|
|
||||||
ParseNode_Color();
|
|
||||||
col_read = true;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XML_CheckNode_NameEqual("mesh")) {
|
|
||||||
ParseNode_Mesh();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (XML_CheckNode_NameEqual("metadata")) {
|
|
||||||
ParseNode_Metadata();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
MACRO_NODECHECK_LOOPEND("object");
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
} // if(!mReader->isEmptyElement())
|
|
||||||
else {*/
|
|
||||||
//mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
|
||||||
//} // if(!mReader->isEmptyElement()) else
|
|
||||||
|
|
||||||
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
||||||
}
|
}
|
||||||
|
@ -711,12 +488,6 @@ void AMFImporter::ParseNode_Metadata(XmlNode &node) {
|
||||||
value = node.value();
|
value = node.value();
|
||||||
|
|
||||||
// read attribute
|
// read attribute
|
||||||
/*MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;*/
|
|
||||||
// and value of node.
|
|
||||||
//value = mReader->getNodeData();
|
|
||||||
// Create node element and assign read data.
|
|
||||||
ne = new AMFMetadata(mNodeElement_Cur);
|
ne = new AMFMetadata(mNodeElement_Cur);
|
||||||
((AMFMetadata *)ne)->Type = type;
|
((AMFMetadata *)ne)->Type = type;
|
||||||
((AMFMetadata *)ne)->Value = value;
|
((AMFMetadata *)ne)->Value = value;
|
||||||
|
@ -724,10 +495,6 @@ void AMFImporter::ParseNode_Metadata(XmlNode &node) {
|
||||||
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************************************************************/
|
|
||||||
/******************************************************** Functions: BaseImporter set ********************************************************/
|
|
||||||
/*********************************************************************************************************************************************/
|
|
||||||
|
|
||||||
bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const {
|
bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const {
|
||||||
const std::string extension = GetExtension(pFile);
|
const std::string extension = GetExtension(pFile);
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,6 @@ class AMFImporter : public BaseImporter {
|
||||||
private:
|
private:
|
||||||
struct SPP_Material; // forward declaration
|
struct SPP_Material; // forward declaration
|
||||||
|
|
||||||
/// \struct SPP_Composite
|
|
||||||
/// Data type for post-processing step. More suitable container for part of material's composition.
|
/// Data type for post-processing step. More suitable container for part of material's composition.
|
||||||
struct SPP_Composite {
|
struct SPP_Composite {
|
||||||
SPP_Material *Material; ///< Pointer to material - part of composition.
|
SPP_Material *Material; ///< Pointer to material - part of composition.
|
||||||
|
|
|
@ -81,29 +81,6 @@ void AMFImporter::ParseNode_Mesh(XmlNode &node) {
|
||||||
found_volumes = true;
|
found_volumes = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if(!mReader->isEmptyElement())
|
|
||||||
{
|
|
||||||
bool vert_read = false;
|
|
||||||
|
|
||||||
ParseHelper_Node_Enter(ne);
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("mesh");
|
|
||||||
if(XML_CheckNode_NameEqual("vertices"))
|
|
||||||
{
|
|
||||||
// Check if data already defined.
|
|
||||||
if(vert_read) Throw_MoreThanOnceDefined("vertices", "Only one vertices set can be defined for <mesh>.");
|
|
||||||
// read data and set flag about it
|
|
||||||
ParseNode_Vertices();
|
|
||||||
vert_read = true;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(XML_CheckNode_NameEqual("volume")) { ParseNode_Volume(); continue; }
|
|
||||||
MACRO_NODECHECK_LOOPEND("mesh");
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
}// if(!mReader->isEmptyElement())
|
|
||||||
else*/
|
|
||||||
// Add element to child list of current element
|
|
||||||
if (!found_verts && !found_volumes) {
|
if (!found_verts && !found_volumes) {
|
||||||
mNodeElement_Cur->Child.push_back(ne);
|
mNodeElement_Cur->Child.push_back(ne);
|
||||||
} // if(!mReader->isEmptyElement()) else
|
} // if(!mReader->isEmptyElement()) else
|
||||||
|
@ -130,20 +107,6 @@ void AMFImporter::ParseNode_Vertices(XmlNode &node) {
|
||||||
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
||||||
} // if(!mReader->isEmptyElement()) else
|
} // if(!mReader->isEmptyElement()) else
|
||||||
|
|
||||||
/*if (!mReader->isEmptyElement()) {
|
|
||||||
ParseHelper_Node_Enter(ne);
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("vertices");
|
|
||||||
if (XML_CheckNode_NameEqual("vertex")) {
|
|
||||||
ParseNode_Vertex();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
MACRO_NODECHECK_LOOPEND("vertices");
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
} // if(!mReader->isEmptyElement())
|
|
||||||
else {
|
|
||||||
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
|
||||||
} // if(!mReader->isEmptyElement()) else*/
|
|
||||||
|
|
||||||
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,6 +120,8 @@ void AMFImporter::ParseNode_Vertex(XmlNode &node) {
|
||||||
|
|
||||||
// create new mesh object.
|
// create new mesh object.
|
||||||
ne = new AMFVertex(mNodeElement_Cur);
|
ne = new AMFVertex(mNodeElement_Cur);
|
||||||
|
|
||||||
|
// Check for child nodes
|
||||||
pugi::xml_node colorNode = node.child("color");
|
pugi::xml_node colorNode = node.child("color");
|
||||||
bool col_read = false;
|
bool col_read = false;
|
||||||
bool coord_read = false;
|
bool coord_read = false;
|
||||||
|
@ -173,42 +138,6 @@ void AMFImporter::ParseNode_Vertex(XmlNode &node) {
|
||||||
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for child nodes
|
|
||||||
/* if (!mReader->isEmptyElement()) {
|
|
||||||
|
|
||||||
ParseHelper_Node_Enter(ne);
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("vertex");
|
|
||||||
if (XML_CheckNode_NameEqual("color")) {
|
|
||||||
// Check if data already defined.
|
|
||||||
if (col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <vertex>.");
|
|
||||||
// read data and set flag about it
|
|
||||||
ParseNode_Color();
|
|
||||||
col_read = true;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XML_CheckNode_NameEqual("coordinates")) {
|
|
||||||
// Check if data already defined.
|
|
||||||
if (coord_read) Throw_MoreThanOnceDefined("coordinates", "Only one coordinates set can be defined for <vertex>.");
|
|
||||||
// read data and set flag about it
|
|
||||||
ParseNode_Coordinates();
|
|
||||||
coord_read = true;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XML_CheckNode_NameEqual("metadata")) {
|
|
||||||
ParseNode_Metadata();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
MACRO_NODECHECK_LOOPEND("vertex");
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
} // if(!mReader->isEmptyElement())
|
|
||||||
else {
|
|
||||||
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
|
||||||
} // if(!mReader->isEmptyElement()) else
|
|
||||||
*/
|
|
||||||
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,25 +167,6 @@ void AMFImporter::ParseNode_Coordinates(XmlNode &node) {
|
||||||
mNodeElement_Cur->Child.push_back(ne);
|
mNodeElement_Cur->Child.push_back(ne);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*// Check for child nodes
|
|
||||||
if (!mReader->isEmptyElement()) {
|
|
||||||
bool read_flag[3] = { false, false, false };
|
|
||||||
|
|
||||||
ParseHelper_Node_Enter(ne);
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("coordinates");
|
|
||||||
MACRO_NODECHECK_READCOMP_F("x", read_flag[0], als.Coordinate.x);
|
|
||||||
MACRO_NODECHECK_READCOMP_F("y", read_flag[1], als.Coordinate.y);
|
|
||||||
MACRO_NODECHECK_READCOMP_F("z", read_flag[2], als.Coordinate.z);
|
|
||||||
MACRO_NODECHECK_LOOPEND("coordinates");
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
// check that all components was defined
|
|
||||||
if ((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all coordinate's components are defined.");
|
|
||||||
|
|
||||||
} // if(!mReader->isEmptyElement())
|
|
||||||
else {
|
|
||||||
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
|
||||||
} // if(!mReader->isEmptyElement()) else*/
|
|
||||||
|
|
||||||
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,13 +185,6 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) {
|
||||||
AMFNodeElementBase *ne = new AMFVolume(mNodeElement_Cur);
|
AMFNodeElementBase *ne = new AMFVolume(mNodeElement_Cur);
|
||||||
|
|
||||||
// Read attributes for node <color>.
|
// Read attributes for node <color>.
|
||||||
/*MACRO_ATTRREAD_LOOPBEG;
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("materialid", materialid, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
|
|
||||||
MACRO_ATTRREAD_LOOPEND;*/
|
|
||||||
|
|
||||||
// create new object.
|
|
||||||
//ne = new CAMFImporter_NodeElement_Volume(mNodeElement_Cur);
|
|
||||||
// and assign read data
|
// and assign read data
|
||||||
|
|
||||||
((AMFVolume *)ne)->MaterialID = node.attribute("materialid").as_string();
|
((AMFVolume *)ne)->MaterialID = node.attribute("materialid").as_string();
|
||||||
|
@ -308,36 +211,6 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (!mReader->isEmptyElement()) {
|
|
||||||
bool col_read = false;
|
|
||||||
|
|
||||||
ParseHelper_Node_Enter(ne);
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("volume");
|
|
||||||
if (XML_CheckNode_NameEqual("color")) {
|
|
||||||
// Check if data already defined.
|
|
||||||
if (col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <volume>.");
|
|
||||||
// read data and set flag about it
|
|
||||||
ParseNode_Color();
|
|
||||||
col_read = true;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XML_CheckNode_NameEqual("triangle")) {
|
|
||||||
ParseNode_Triangle();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (XML_CheckNode_NameEqual("metadata")) {
|
|
||||||
ParseNode_Metadata();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
MACRO_NODECHECK_LOOPEND("volume");
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
} // if(!mReader->isEmptyElement())
|
|
||||||
else {
|
|
||||||
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
|
||||||
} // if(!mReader->isEmptyElement()) else*/
|
|
||||||
|
|
||||||
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,14 +227,15 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) {
|
||||||
void AMFImporter::ParseNode_Triangle(XmlNode &node) {
|
void AMFImporter::ParseNode_Triangle(XmlNode &node) {
|
||||||
AMFNodeElementBase *ne = new AMFTriangle(mNodeElement_Cur);
|
AMFNodeElementBase *ne = new AMFTriangle(mNodeElement_Cur);
|
||||||
|
|
||||||
// create new color object.
|
// create new triangle object.
|
||||||
//ne = new CAMFImporter_NodeElement_Triangle(mNodeElement_Cur);
|
|
||||||
|
|
||||||
AMFTriangle &als = *((AMFTriangle *)ne); // alias for convenience
|
AMFTriangle &als = *((AMFTriangle *)ne); // alias for convenience
|
||||||
|
|
||||||
if (node.empty()) {
|
if (node.empty()) {
|
||||||
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for child nodes
|
||||||
bool col_read = false, tex_read = false;
|
bool col_read = false, tex_read = false;
|
||||||
bool read_flag[3] = { false, false, false };
|
bool read_flag[3] = { false, false, false };
|
||||||
for (pugi::xml_node currentNode : node.children()) {
|
for (pugi::xml_node currentNode : node.children()) {
|
||||||
|
@ -387,59 +261,11 @@ void AMFImporter::ParseNode_Triangle(XmlNode &node) {
|
||||||
read_flag[2] = true;
|
read_flag[2] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all vertices of the triangle are defined.");
|
if ((read_flag[0] && read_flag[1] && read_flag[2]) == 0) {
|
||||||
|
throw DeadlyImportError("Not all vertices of the triangle are defined.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check for child nodes
|
|
||||||
/*if (!mReader->isEmptyElement()) {
|
|
||||||
bool col_read = false, tex_read = false;
|
|
||||||
bool read_flag[3] = { false, false, false };
|
|
||||||
|
|
||||||
ParseHelper_Node_Enter(ne);
|
|
||||||
MACRO_NODECHECK_LOOPBEGIN("triangle");
|
|
||||||
if (XML_CheckNode_NameEqual("color")) {
|
|
||||||
// Check if data already defined.
|
|
||||||
if (col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <triangle>.");
|
|
||||||
// read data and set flag about it
|
|
||||||
ParseNode_Color();
|
|
||||||
col_read = true;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XML_CheckNode_NameEqual("texmap")) // new name of node: "texmap".
|
|
||||||
{
|
|
||||||
// Check if data already defined.
|
|
||||||
if (tex_read) Throw_MoreThanOnceDefined("texmap", "Only one texture coordinate can be defined for <triangle>.");
|
|
||||||
// read data and set flag about it
|
|
||||||
ParseNode_TexMap();
|
|
||||||
tex_read = true;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
} else if (XML_CheckNode_NameEqual("map")) // old name of node: "map".
|
|
||||||
{
|
|
||||||
// Check if data already defined.
|
|
||||||
if (tex_read) Throw_MoreThanOnceDefined("map", "Only one texture coordinate can be defined for <triangle>.");
|
|
||||||
// read data and set flag about it
|
|
||||||
ParseNode_TexMap(true);
|
|
||||||
tex_read = true;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
MACRO_NODECHECK_READCOMP_U32("v1", read_flag[0], als.V[0]);
|
|
||||||
MACRO_NODECHECK_READCOMP_U32("v2", read_flag[1], als.V[1]);
|
|
||||||
MACRO_NODECHECK_READCOMP_U32("v3", read_flag[2], als.V[2]);
|
|
||||||
MACRO_NODECHECK_LOOPEND("triangle");
|
|
||||||
ParseHelper_Node_Exit();
|
|
||||||
// check that all components was defined
|
|
||||||
if ((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all vertices of the triangle are defined.");
|
|
||||||
|
|
||||||
} // if(!mReader->isEmptyElement())
|
|
||||||
else {
|
|
||||||
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
|
|
||||||
} // if(!mReader->isEmptyElement()) else
|
|
||||||
*/
|
|
||||||
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
Copyright (c) 2006-2020, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
|
|
@ -177,9 +177,6 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) {
|
||||||
|
|
||||||
std::string enc64_data = node.value();
|
std::string enc64_data = node.value();
|
||||||
// Check for child nodes
|
// Check for child nodes
|
||||||
//if (!mXmlParser->isEmptyElement()) {
|
|
||||||
// XML_ReadNode_GetVal_AsString(enc64_data);
|
|
||||||
//}
|
|
||||||
|
|
||||||
// check that all components was defined
|
// check that all components was defined
|
||||||
if (id.empty()) {
|
if (id.empty()) {
|
||||||
|
|
|
@ -45,24 +45,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "ColladaLoader.h"
|
#include "ColladaLoader.h"
|
||||||
#include "ColladaParser.h"
|
#include "ColladaParser.h"
|
||||||
|
|
||||||
#include <assimp/ColladaMetaData.h>
|
#include <assimp/ColladaMetaData.h>
|
||||||
#include <assimp/Defines.h>
|
|
||||||
#include <assimp/anim.h>
|
|
||||||
#include <assimp/importerdesc.h>
|
|
||||||
#include <assimp/scene.h>
|
|
||||||
#include <assimp/DefaultLogger.hpp>
|
|
||||||
#include <assimp/Importer.hpp>
|
|
||||||
|
|
||||||
#include <assimp/CreateAnimMesh.h>
|
#include <assimp/CreateAnimMesh.h>
|
||||||
|
#include <assimp/Defines.h>
|
||||||
#include <assimp/ParsingUtils.h>
|
#include <assimp/ParsingUtils.h>
|
||||||
#include <assimp/SkeletonMeshBuilder.h>
|
#include <assimp/SkeletonMeshBuilder.h>
|
||||||
#include <assimp/ZipArchiveIOSystem.h>
|
#include <assimp/ZipArchiveIOSystem.h>
|
||||||
|
#include <assimp/anim.h>
|
||||||
#include <assimp/fast_atof.h>
|
#include <assimp/fast_atof.h>
|
||||||
|
#include <assimp/importerdesc.h>
|
||||||
#include "math.h"
|
#include <assimp/scene.h>
|
||||||
#include "time.h"
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <assimp/DefaultLogger.hpp>
|
||||||
|
#include <assimp/Importer.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
|
@ -125,20 +122,17 @@ ColladaLoader::~ColladaLoader() {
|
||||||
bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
|
bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
|
||||||
// check file extension
|
// check file extension
|
||||||
const std::string extension = GetExtension(pFile);
|
const std::string extension = GetExtension(pFile);
|
||||||
|
const bool readSig = checkSig && (pIOHandler != nullptr);
|
||||||
bool readSig = checkSig && (pIOHandler != nullptr);
|
|
||||||
|
|
||||||
if (!readSig) {
|
if (!readSig) {
|
||||||
if (extension == "dae" || extension == "zae") {
|
if (extension == "dae" || extension == "zae") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
|
||||||
if (readSig) {
|
|
||||||
// Look for a DAE file inside, but don't extract it
|
// Look for a DAE file inside, but don't extract it
|
||||||
ZipArchiveIOSystem zip_archive(pIOHandler, pFile);
|
ZipArchiveIOSystem zip_archive(pIOHandler, pFile);
|
||||||
if (zip_archive.isOpen())
|
if (zip_archive.isOpen()) {
|
||||||
return !ColladaParser::ReadZaeManifest(zip_archive).empty();
|
return !ColladaParser::ReadZaeManifest(zip_archive).empty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// XML - too generic, we need to open the file and search for typical keywords
|
// XML - too generic, we need to open the file and search for typical keywords
|
||||||
|
@ -585,10 +579,10 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Colla
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Find mesh from either meshes or morph target meshes
|
// Find mesh from either meshes or morph target meshes
|
||||||
aiMesh *ColladaLoader::findMesh(const std::string &meshid) {
|
aiMesh *ColladaLoader::findMesh(const std::string &meshid) {
|
||||||
if ( meshid.empty()) {
|
if (meshid.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < mMeshes.size(); ++i) {
|
for (unsigned int i = 0; i < mMeshes.size(); ++i) {
|
||||||
if (std::string(mMeshes[i]->mName.data) == meshid) {
|
if (std::string(mMeshes[i]->mName.data) == meshid) {
|
||||||
return mMeshes[i];
|
return mMeshes[i];
|
||||||
|
@ -1377,9 +1371,9 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
|
||||||
double time = double(mat.d4); // remember? time is stored in mat.d4
|
double time = double(mat.d4); // remember? time is stored in mat.d4
|
||||||
mat.d4 = 1.0f;
|
mat.d4 = 1.0f;
|
||||||
|
|
||||||
dstAnim->mPositionKeys[a].mTime = time * kMillisecondsFromSeconds ;
|
dstAnim->mPositionKeys[a].mTime = time * kMillisecondsFromSeconds;
|
||||||
dstAnim->mRotationKeys[a].mTime = time * kMillisecondsFromSeconds ;
|
dstAnim->mRotationKeys[a].mTime = time * kMillisecondsFromSeconds;
|
||||||
dstAnim->mScalingKeys[a].mTime = time * kMillisecondsFromSeconds ;
|
dstAnim->mScalingKeys[a].mTime = time * kMillisecondsFromSeconds;
|
||||||
mat.Decompose(dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue);
|
mat.Decompose(dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1400,7 +1394,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
|
||||||
if (e.mTargetId.find("morph-weights") != std::string::npos)
|
if (e.mTargetId.find("morph-weights") != std::string::npos)
|
||||||
morphChannels.push_back(e);
|
morphChannels.push_back(e);
|
||||||
}
|
}
|
||||||
if (!morphChannels.empty() ) {
|
if (!morphChannels.empty()) {
|
||||||
// either 1) morph weight animation count should contain morph target count channels
|
// either 1) morph weight animation count should contain morph target count channels
|
||||||
// or 2) one channel with morph target count arrays
|
// or 2) one channel with morph target count arrays
|
||||||
// assume first
|
// assume first
|
||||||
|
@ -1434,8 +1428,8 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
|
||||||
morphAnim->mKeys[key].mValues = new unsigned int[morphChannels.size()];
|
morphAnim->mKeys[key].mValues = new unsigned int[morphChannels.size()];
|
||||||
morphAnim->mKeys[key].mWeights = new double[morphChannels.size()];
|
morphAnim->mKeys[key].mWeights = new double[morphChannels.size()];
|
||||||
|
|
||||||
morphAnim->mKeys[key].mTime = morphTimeValues[key].mTime * kMillisecondsFromSeconds ;
|
morphAnim->mKeys[key].mTime = morphTimeValues[key].mTime * kMillisecondsFromSeconds;
|
||||||
for (unsigned int valueIndex = 0; valueIndex < morphChannels.size(); ++valueIndex ) {
|
for (unsigned int valueIndex = 0; valueIndex < morphChannels.size(); ++valueIndex) {
|
||||||
morphAnim->mKeys[key].mValues[valueIndex] = valueIndex;
|
morphAnim->mKeys[key].mValues[valueIndex] = valueIndex;
|
||||||
morphAnim->mKeys[key].mWeights[valueIndex] = getWeightAtKey(morphTimeValues, key, valueIndex);
|
morphAnim->mKeys[key].mWeights[valueIndex] = getWeightAtKey(morphTimeValues, key, valueIndex);
|
||||||
}
|
}
|
||||||
|
@ -1552,23 +1546,23 @@ void ColladaLoader::FillMaterials(const ColladaParser &pParser, aiScene * /*pSce
|
||||||
shadeMode = aiShadingMode_Flat;
|
shadeMode = aiShadingMode_Flat;
|
||||||
} else {
|
} else {
|
||||||
switch (effect.mShadeType) {
|
switch (effect.mShadeType) {
|
||||||
case Collada::Shade_Constant:
|
case Collada::Shade_Constant:
|
||||||
shadeMode = aiShadingMode_NoShading;
|
shadeMode = aiShadingMode_NoShading;
|
||||||
break;
|
break;
|
||||||
case Collada::Shade_Lambert:
|
case Collada::Shade_Lambert:
|
||||||
shadeMode = aiShadingMode_Gouraud;
|
shadeMode = aiShadingMode_Gouraud;
|
||||||
break;
|
break;
|
||||||
case Collada::Shade_Blinn:
|
case Collada::Shade_Blinn:
|
||||||
shadeMode = aiShadingMode_Blinn;
|
shadeMode = aiShadingMode_Blinn;
|
||||||
break;
|
break;
|
||||||
case Collada::Shade_Phong:
|
case Collada::Shade_Phong:
|
||||||
shadeMode = aiShadingMode_Phong;
|
shadeMode = aiShadingMode_Phong;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ASSIMP_LOG_WARN("Collada: Unrecognized shading mode, using gouraud shading");
|
ASSIMP_LOG_WARN("Collada: Unrecognized shading mode, using gouraud shading");
|
||||||
shadeMode = aiShadingMode_Gouraud;
|
shadeMode = aiShadingMode_Gouraud;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mat.AddProperty<int>(&shadeMode, 1, AI_MATKEY_SHADING_MODEL);
|
mat.AddProperty<int>(&shadeMode, 1, AI_MATKEY_SHADING_MODEL);
|
||||||
|
@ -1734,7 +1728,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
|
||||||
// and add this texture to the list
|
// and add this texture to the list
|
||||||
mTextures.push_back(tex);
|
mTextures.push_back(tex);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imIt->second.mFileName.empty()) {
|
if (imIt->second.mFileName.empty()) {
|
||||||
throw DeadlyImportError("Collada: Invalid texture, no data or file reference given");
|
throw DeadlyImportError("Collada: Invalid texture, no data or file reference given");
|
||||||
|
|
|
@ -160,11 +160,26 @@ std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) {
|
||||||
|
|
||||||
return file_list.front();
|
return file_list.front();
|
||||||
}
|
}
|
||||||
|
XmlParser manifestParser;
|
||||||
|
XmlNode *root = manifestParser.parse(manifestfile.get());
|
||||||
|
if (nullptr == root) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
const std::string name = root->name();
|
||||||
|
if (name != "dae_root") {
|
||||||
|
root = manifestParser.findNode("dae_root");
|
||||||
|
if (nullptr == root) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
const char *filepath = root->value();
|
||||||
|
aiString ai_str(filepath);
|
||||||
|
UriDecodePath(ai_str);
|
||||||
|
return std::string(ai_str.C_Str());
|
||||||
|
}
|
||||||
|
/*std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(manifestfile.get()));
|
||||||
|
std::unique_ptr<irr::io::IrrXMLReader> manifest_reader(irr::io::createIrrXMLReader(mIOWrapper.get()));*/
|
||||||
|
|
||||||
std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(manifestfile.get()));
|
/*while (manifest_reader->read()) {
|
||||||
std::unique_ptr<irr::io::IrrXMLReader> manifest_reader(irr::io::createIrrXMLReader(mIOWrapper.get()));
|
|
||||||
|
|
||||||
while (manifest_reader->read()) {
|
|
||||||
// find the manifest "dae_root" element
|
// find the manifest "dae_root" element
|
||||||
if (manifest_reader->getNodeType() == irr::io::EXN_ELEMENT) {
|
if (manifest_reader->getNodeType() == irr::io::EXN_ELEMENT) {
|
||||||
if (::strcmp(manifest_reader->getNodeName(), "dae_root") == 0) {
|
if (::strcmp(manifest_reader->getNodeName(), "dae_root") == 0) {
|
||||||
|
@ -183,7 +198,7 @@ std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) {
|
||||||
return std::string(ai_str.C_Str());
|
return std::string(ai_str.C_Str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,7 +329,6 @@ void ColladaParser::ReadContents(XmlNode &node) {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Reads the structure of the file
|
// Reads the structure of the file
|
||||||
<<<<<<< HEAD
|
|
||||||
void ColladaParser::ReadStructure(XmlNode &node) {
|
void ColladaParser::ReadStructure(XmlNode &node) {
|
||||||
for (pugi::xml_node curNode : node.children()) {
|
for (pugi::xml_node curNode : node.children()) {
|
||||||
const std::string name = std::string(curNode.name());
|
const std::string name = std::string(curNode.name());
|
||||||
|
@ -341,7 +355,7 @@ void ColladaParser::ReadStructure(XmlNode &node) {
|
||||||
else if (name == "library_cameras")
|
else if (name == "library_cameras")
|
||||||
ReadCameraLibrary(curNode);
|
ReadCameraLibrary(curNode);
|
||||||
else if (name == "library_nodes")
|
else if (name == "library_nodes")
|
||||||
ReadSceneNode(NULL); /* some hacking to reuse this piece of code */
|
ReadSceneNode(curNode, nullptr); /* some hacking to reuse this piece of code */
|
||||||
else if (name == "scene")
|
else if (name == "scene")
|
||||||
ReadScene(curNode);
|
ReadScene(curNode);
|
||||||
//else
|
//else
|
||||||
|
@ -381,44 +395,6 @@ void ColladaParser::ReadStructure(XmlNode &node) {
|
||||||
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
||||||
break;
|
break;
|
||||||
}*/
|
}*/
|
||||||
=======
|
|
||||||
void ColladaParser::ReadStructure() {
|
|
||||||
while (mReader->read()) {
|
|
||||||
// beginning of elements
|
|
||||||
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
|
||||||
if (IsElement("asset"))
|
|
||||||
ReadAssetInfo();
|
|
||||||
else if (IsElement("library_animations"))
|
|
||||||
ReadAnimationLibrary();
|
|
||||||
else if (IsElement("library_animation_clips"))
|
|
||||||
ReadAnimationClipLibrary();
|
|
||||||
else if (IsElement("library_controllers"))
|
|
||||||
ReadControllerLibrary();
|
|
||||||
else if (IsElement("library_images"))
|
|
||||||
ReadImageLibrary();
|
|
||||||
else if (IsElement("library_materials"))
|
|
||||||
ReadMaterialLibrary();
|
|
||||||
else if (IsElement("library_effects"))
|
|
||||||
ReadEffectLibrary();
|
|
||||||
else if (IsElement("library_geometries"))
|
|
||||||
ReadGeometryLibrary();
|
|
||||||
else if (IsElement("library_visual_scenes"))
|
|
||||||
ReadSceneLibrary();
|
|
||||||
else if (IsElement("library_lights"))
|
|
||||||
ReadLightLibrary();
|
|
||||||
else if (IsElement("library_cameras"))
|
|
||||||
ReadCameraLibrary();
|
|
||||||
else if (IsElement("library_nodes"))
|
|
||||||
ReadSceneNode(nullptr); /* some hacking to reuse this piece of code */
|
|
||||||
else if (IsElement("scene"))
|
|
||||||
ReadScene();
|
|
||||||
else
|
|
||||||
SkipElement();
|
|
||||||
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>>>>>>> master
|
|
||||||
|
|
||||||
PostProcessRootAnimations();
|
PostProcessRootAnimations();
|
||||||
PostProcessControllers();
|
PostProcessControllers();
|
||||||
|
@ -436,7 +412,7 @@ void ColladaParser::ReadAssetInfo(XmlNode &node) {
|
||||||
pugi::xml_attribute attr = curNode.attribute("meter");
|
pugi::xml_attribute attr = curNode.attribute("meter");
|
||||||
mUnitSize = 1.f;
|
mUnitSize = 1.f;
|
||||||
if (attr) {
|
if (attr) {
|
||||||
mUnitSize = attr.as_double();
|
mUnitSize = static_cast<ai_real>(attr.as_double());
|
||||||
}
|
}
|
||||||
} else if (name == "up_axis") {
|
} else if (name == "up_axis") {
|
||||||
const char *content = curNode.value();
|
const char *content = curNode.value();
|
||||||
|
@ -602,7 +578,7 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
|
||||||
if (urlName[0] != '#') {
|
if (urlName[0] != '#') {
|
||||||
ThrowException("Unknown reference format");
|
ThrowException("Unknown reference format");
|
||||||
}
|
}
|
||||||
clip.second.push_back(url);
|
clip.second.push_back(url.as_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -919,8 +895,27 @@ void ColladaParser::ReadAnimationSampler(XmlNode &node, Collada::AnimationChanne
|
||||||
for (pugi::xml_node &curNode : node.children()) {
|
for (pugi::xml_node &curNode : node.children()) {
|
||||||
const std::string currentName = curNode.name();
|
const std::string currentName = curNode.name();
|
||||||
if (currentName == "input") {
|
if (currentName == "input") {
|
||||||
pugi::xml_attribute semantic = curNode.attribute("semantic");
|
pugi::xml_attribute semanticAttr = curNode.attribute("semantic");
|
||||||
if (semantic) {
|
if (!semanticAttr.empty()) {
|
||||||
|
const char *semantic = semanticAttr.as_string();
|
||||||
|
pugi::xml_attribute sourceAttr = curNode.attribute("source");
|
||||||
|
if (!sourceAttr.empty()) {
|
||||||
|
const char *source = sourceAttr.as_string();
|
||||||
|
if (source[0] != '#')
|
||||||
|
ThrowException("Unsupported URL format");
|
||||||
|
source++;
|
||||||
|
|
||||||
|
if (strcmp(semantic, "INPUT") == 0)
|
||||||
|
pChannel.mSourceTimes = source;
|
||||||
|
else if (strcmp(semantic, "OUTPUT") == 0)
|
||||||
|
pChannel.mSourceValues = source;
|
||||||
|
else if (strcmp(semantic, "IN_TANGENT") == 0)
|
||||||
|
pChannel.mInTanValues = source;
|
||||||
|
else if (strcmp(semantic, "OUT_TANGENT") == 0)
|
||||||
|
pChannel.mOutTanValues = source;
|
||||||
|
else if (strcmp(semantic, "INTERPOLATION") == 0)
|
||||||
|
pChannel.mInterpolationValues = source;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -970,7 +965,23 @@ void ColladaParser::ReadControllerLibrary(XmlNode &node) {
|
||||||
/*if (mReader->isEmptyElement())
|
/*if (mReader->isEmptyElement())
|
||||||
return;*/
|
return;*/
|
||||||
|
|
||||||
while (mReader->read()) {
|
const std::string name = node.name();
|
||||||
|
if (name != "controller") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int attrId = node.attribute("id").as_int();
|
||||||
|
std::string id = node.value();
|
||||||
|
mControllerLibrary[id] = Controller();
|
||||||
|
for (XmlNode currentNode : node.children()) {
|
||||||
|
const std::string currentName = currentNode.name();
|
||||||
|
if (currentName == "controller") {
|
||||||
|
int attrID = currentNode.attribute("id").as_int();
|
||||||
|
std::string controllerId = currentNode.attribute(itoa(attrID, NULL, 10)).value();
|
||||||
|
ReadController(node, mControllerLibrary[controllerId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*while (mReader->read()) {
|
||||||
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
||||||
if (IsElement("controller")) {
|
if (IsElement("controller")) {
|
||||||
// read ID. Ask the spec if it's necessary or optional... you might be surprised.
|
// read ID. Ask the spec if it's necessary or optional... you might be surprised.
|
||||||
|
@ -992,7 +1003,7 @@ void ColladaParser::ReadControllerLibrary(XmlNode &node) {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -1001,7 +1012,54 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &pControll
|
||||||
// initial values
|
// initial values
|
||||||
pController.mType = Skin;
|
pController.mType = Skin;
|
||||||
pController.mMethod = Normalized;
|
pController.mMethod = Normalized;
|
||||||
while (mReader->read()) {
|
for (XmlNode currentNode : node.children()) {
|
||||||
|
const std::string currentName = currentNode.name();
|
||||||
|
if (currentName == "morph") {
|
||||||
|
pController.mType = Morph;
|
||||||
|
int baseIndex = currentNode.attribute("source").as_int();
|
||||||
|
pController.mMeshId = currentNode.attribute.begin() + baseIndex + 1;
|
||||||
|
int methodIndex = currentNode.attribute("method").as_int();
|
||||||
|
if (methodIndex > 0) {
|
||||||
|
const char *method = currentNode.attribute("method").value();
|
||||||
|
if (strcmp(method, "RELATIVE") == 0) {
|
||||||
|
pController.mMethod = Relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (currentName == "skin") {
|
||||||
|
int sourceIndex = currentNode.attribute("source").as_int();
|
||||||
|
pController.mMeshId = currentNode.attribute.begin() + sourceIndex + 1;
|
||||||
|
} else if (currentName == "bind_shape_matrix") {
|
||||||
|
const char *content = currentNode.value();
|
||||||
|
for (unsigned int a = 0; a < 16; a++) {
|
||||||
|
// read a number
|
||||||
|
content = fast_atoreal_move<ai_real>(content, pController.mBindShapeMatrix[a]);
|
||||||
|
// skip whitespace after it
|
||||||
|
SkipSpacesAndLineEnd(&content);
|
||||||
|
}
|
||||||
|
} else if (currentName == "source") {
|
||||||
|
ReadSource(currentNode);
|
||||||
|
} else if (IsElement("joints")) {
|
||||||
|
ReadControllerJoints(currentNode, pController);
|
||||||
|
} else if (IsElement("vertex_weights")) {
|
||||||
|
ReadControllerWeights(currentNode, pController);
|
||||||
|
} else if (IsElement("targets")) {
|
||||||
|
for (XmlNode currendChildNode : currentNode.children()) {
|
||||||
|
const std::string currentChildName = currendChildNode.name();
|
||||||
|
if (currentChildName == "input") {
|
||||||
|
int semanticsIndex = currendChildNode.attribute("semantic").as_int();
|
||||||
|
int sourceIndex = currendChildNode.attribute("source").as_int();
|
||||||
|
const char *semantics = currendChildNode.attributes.begin() + semanticsIndex;
|
||||||
|
const char *source = currendChildNode.attributes.begin() + sourceIndex;
|
||||||
|
if (strcmp(semantics, "MORPH_TARGET") == 0) {
|
||||||
|
pController.mMorphTarget = source + 1;
|
||||||
|
} else if (strcmp(semantics, "MORPH_WEIGHT") == 0) {
|
||||||
|
pController.mMorphWeight = source + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*while (mReader->read()) {
|
||||||
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
||||||
// two types of controllers: "skin" and "morph". Only the first one is relevant, we skip the other
|
// two types of controllers: "skin" and "morph". Only the first one is relevant, we skip the other
|
||||||
if (IsElement("morph")) {
|
if (IsElement("morph")) {
|
||||||
|
@ -1071,59 +1129,141 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &pControll
|
||||||
else if (strcmp(mReader->getNodeName(), "skin") != 0 && strcmp(mReader->getNodeName(), "morph") != 0)
|
else if (strcmp(mReader->getNodeName(), "skin") != 0 && strcmp(mReader->getNodeName(), "morph") != 0)
|
||||||
ThrowException("Expected end of <controller> element.");
|
ThrowException("Expected end of <controller> element.");
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Reads the joint definitions for the given controller
|
// Reads the joint definitions for the given controller
|
||||||
void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pController) {
|
void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pController) {
|
||||||
while (mReader->read()) {
|
for (XmlNode currentNode : node.children()) {
|
||||||
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
const std::string currentName = currentNode.name();
|
||||||
// Input channels for joint data. Two possible semantics: "JOINT" and "INV_BIND_MATRIX"
|
if (currentName == "input") {
|
||||||
if (IsElement("input")) {
|
int indexSemantic = currentNode.attribute("semantic").as_int();
|
||||||
int indexSemantic = GetAttribute("semantic");
|
const char *attrSemantic = currentNode.attributes.begin() + indexSemantic;
|
||||||
const char *attrSemantic = mReader->getAttributeValue(indexSemantic);
|
int indexSource = currentNode.attribute("source").as_int();
|
||||||
int indexSource = GetAttribute("source");
|
const char *attrSource = currentNode.attributes.begin() + indexSource;
|
||||||
const char *attrSource = mReader->getAttributeValue(indexSource);
|
if (attrSource[0] != '#') {
|
||||||
|
ThrowException(format() << "Unsupported URL format in \"" << attrSource << "\" in source attribute of <joints> data <input> element");
|
||||||
// local URLS always start with a '#'. We don't support global URLs
|
}
|
||||||
if (attrSource[0] != '#')
|
attrSource++;
|
||||||
ThrowException(format() << "Unsupported URL format in \"" << attrSource << "\" in source attribute of <joints> data <input> element");
|
// parse source URL to corresponding source
|
||||||
attrSource++;
|
if (strcmp(attrSemantic, "JOINT") == 0) {
|
||||||
|
pController.mJointNameSource = attrSource;
|
||||||
// parse source URL to corresponding source
|
} else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0) {
|
||||||
if (strcmp(attrSemantic, "JOINT") == 0)
|
pController.mJointOffsetMatrixSource = attrSource;
|
||||||
pController.mJointNameSource = attrSource;
|
} else {
|
||||||
else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0)
|
ThrowException(format() << "Unknown semantic \"" << attrSemantic << "\" in <joints> data <input> element");
|
||||||
pController.mJointOffsetMatrixSource = attrSource;
|
|
||||||
else
|
|
||||||
ThrowException(format() << "Unknown semantic \"" << attrSemantic << "\" in <joints> data <input> element");
|
|
||||||
|
|
||||||
// skip inner data, if present
|
|
||||||
if (!mReader->isEmptyElement())
|
|
||||||
SkipElement();
|
|
||||||
} else {
|
|
||||||
// ignore the rest
|
|
||||||
SkipElement();
|
|
||||||
}
|
}
|
||||||
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
|
||||||
if (strcmp(mReader->getNodeName(), "joints") != 0)
|
|
||||||
ThrowException("Expected end of <joints> element.");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*while (mReader->read()) {
|
||||||
|
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
||||||
|
// Input channels for joint data. Two possible semantics: "JOINT" and "INV_BIND_MATRIX"
|
||||||
|
if (IsElement("input")) {
|
||||||
|
int indexSemantic = GetAttribute("semantic");
|
||||||
|
const char *attrSemantic = mReader->getAttributeValue(indexSemantic);
|
||||||
|
int indexSource = GetAttribute("source");
|
||||||
|
const char *attrSource = mReader->getAttributeValue(indexSource);
|
||||||
|
|
||||||
|
// local URLS always start with a '#'. We don't support global URLs
|
||||||
|
if (attrSource[0] != '#')
|
||||||
|
ThrowException(format() << "Unsupported URL format in \"" << attrSource << "\" in source attribute of <joints> data <input> element");
|
||||||
|
attrSource++;
|
||||||
|
|
||||||
|
// parse source URL to corresponding source
|
||||||
|
if (strcmp(attrSemantic, "JOINT") == 0)
|
||||||
|
pController.mJointNameSource = attrSource;
|
||||||
|
else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0)
|
||||||
|
pController.mJointOffsetMatrixSource = attrSource;
|
||||||
|
else
|
||||||
|
ThrowException(format() << "Unknown semantic \"" << attrSemantic << "\" in <joints> data <input> element");
|
||||||
|
|
||||||
|
// skip inner data, if present
|
||||||
|
if (!mReader->isEmptyElement())
|
||||||
|
SkipElement();
|
||||||
|
} else {
|
||||||
|
// ignore the rest
|
||||||
|
SkipElement();
|
||||||
|
}
|
||||||
|
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
||||||
|
if (strcmp(mReader->getNodeName(), "joints") != 0)
|
||||||
|
ThrowException("Expected end of <joints> element.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Reads the joint weights for the given controller
|
// Reads the joint weights for the given controller
|
||||||
void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pController) {
|
void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pController) {
|
||||||
// read vertex count from attributes and resize the array accordingly
|
// Read vertex count from attributes and resize the array accordingly
|
||||||
int indexCount = GetAttribute("count");
|
int indexCount = node.attribute("count").as_int();
|
||||||
size_t vertexCount = (size_t)mReader->getAttributeValueAsInt(indexCount);
|
size_t vertexCount = node.attributes.begin() + indexCount;
|
||||||
pController.mWeightCounts.resize(vertexCount);
|
pController.mWeightCounts.resize(vertexCount);
|
||||||
|
|
||||||
while (mReader->read()) {
|
/*// read vertex count from attributes and resize the array accordingly
|
||||||
|
int indexCount = GetAttribute("count");
|
||||||
|
size_t vertexCount = (size_t)mReader->getAttributeValueAsInt(indexCount);
|
||||||
|
pController.mWeightCounts.resize(vertexCount);*/
|
||||||
|
|
||||||
|
for (XmlNode currentNode : node.children()) {
|
||||||
|
std::string currentName = currentNode.name();
|
||||||
|
if (currentName == "input") {
|
||||||
|
InputChannel channel;
|
||||||
|
|
||||||
|
int indexSemantic = currentNode.attribute("semantic").as_int();
|
||||||
|
const char *attrSemantic = currentNode.attributes.begin() + indexSemantic;
|
||||||
|
int indexSource = currentNode.attribute("source").as_int();
|
||||||
|
const char *attrSource = currentNode.attributes.begin() + indexSource;
|
||||||
|
int indexOffset = currentNode.attribute("offset").as_int();
|
||||||
|
if (indexOffset >= 0)
|
||||||
|
channel.mOffset = currentNode.attributes.begin + indexOffset;
|
||||||
|
|
||||||
|
// local URLS always start with a '#'. We don't support global URLs
|
||||||
|
if (attrSource[0] != '#')
|
||||||
|
ThrowException(format() << "Unsupported URL format in \"" << attrSource << "\" in source attribute of <vertex_weights> data <input> element");
|
||||||
|
channel.mAccessor = attrSource + 1;
|
||||||
|
|
||||||
|
// parse source URL to corresponding source
|
||||||
|
if (strcmp(attrSemantic, "JOINT") == 0) {
|
||||||
|
pController.mWeightInputJoints = channel;
|
||||||
|
} else if (strcmp(attrSemantic, "WEIGHT") == 0) {
|
||||||
|
pController.mWeightInputWeights = channel;
|
||||||
|
} else {
|
||||||
|
ThrowException(format() << "Unknown semantic \"" << attrSemantic << "\" in <vertex_weights> data <input> element");
|
||||||
|
}
|
||||||
|
} else if (currentName == "vcount" && vertexCount > 0) {
|
||||||
|
const char *text = currentNode.value();
|
||||||
|
size_t numWeights = 0;
|
||||||
|
for (std::vector<size_t>::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it) {
|
||||||
|
if (*text == 0) {
|
||||||
|
ThrowException("Out of data while reading <vcount>");
|
||||||
|
}
|
||||||
|
|
||||||
|
*it = strtoul10(text, &text);
|
||||||
|
numWeights += *it;
|
||||||
|
SkipSpacesAndLineEnd(&text);
|
||||||
|
}
|
||||||
|
// reserve weight count
|
||||||
|
pController.mWeights.resize(numWeights);
|
||||||
|
} else if (currentName == "v" && vertexCount > 0) {
|
||||||
|
// read JointIndex - WeightIndex pairs
|
||||||
|
const char *text = currentNode.value();
|
||||||
|
for (std::vector<std::pair<size_t, size_t>>::iterator it = pController.mWeights.begin(); it != pController.mWeights.end(); ++it) {
|
||||||
|
if (*text == 0) {
|
||||||
|
ThrowException("Out of data while reading <vertex_weights>");
|
||||||
|
}
|
||||||
|
it->first = strtoul10(text, &text);
|
||||||
|
SkipSpacesAndLineEnd(&text);
|
||||||
|
if (*text == 0)
|
||||||
|
ThrowException("Out of data while reading <vertex_weights>");
|
||||||
|
it->second = strtoul10(text, &text);
|
||||||
|
SkipSpacesAndLineEnd(&text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*while (mReader->read()) {
|
||||||
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
||||||
// Input channels for weight data. Two possible semantics: "JOINT" and "WEIGHT"
|
// Input channels for weight data. Two possible semantics: "JOINT" and "WEIGHT"
|
||||||
if (IsElement("input") && vertexCount > 0) {
|
if (IsElement("input") && vertexCount > 0) {
|
||||||
|
@ -1196,7 +1336,7 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -1208,75 +1348,54 @@ void ColladaParser::ReadImageLibrary(XmlNode &node) {
|
||||||
/*if (mReader->isEmptyElement())
|
/*if (mReader->isEmptyElement())
|
||||||
return;*/
|
return;*/
|
||||||
|
|
||||||
while (mReader->read()) {
|
for (XmlNode currentNode : node.children()) {
|
||||||
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
const std::string name = currentNode.name();
|
||||||
if (IsElement("image")) {
|
if (name == "image") {
|
||||||
// read ID. Another entry which is "optional" by design but obligatory in reality
|
int attrID = currentNode.attribute("id").as_int();
|
||||||
int attrID = GetAttribute("id");
|
std::string id = currentNode.attributes.begin() + attrID;
|
||||||
std::string id = mReader->getAttributeValue(attrID);
|
mImageLibrary[id] = Image();
|
||||||
|
|
||||||
// create an entry and store it in the library under its ID
|
// read on from there
|
||||||
mImageLibrary[id] = Image();
|
ReadImage(currentNode, mImageLibrary[id]);
|
||||||
|
|
||||||
// read on from there
|
|
||||||
ReadImage(mImageLibrary[id]);
|
|
||||||
} else {
|
|
||||||
// ignore the rest
|
|
||||||
SkipElement();
|
|
||||||
}
|
|
||||||
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
|
||||||
if (strcmp(mReader->getNodeName(), "library_images") != 0)
|
|
||||||
ThrowException("Expected end of <library_images> element.");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*while (mReader->read()) {
|
||||||
|
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
||||||
|
if (IsElement("image")) {
|
||||||
|
// read ID. Another entry which is "optional" by design but obligatory in reality
|
||||||
|
int attrID = GetAttribute("id");
|
||||||
|
std::string id = mReader->getAttributeValue(attrID);
|
||||||
|
|
||||||
|
// create an entry and store it in the library under its ID
|
||||||
|
mImageLibrary[id] = Image();
|
||||||
|
|
||||||
|
// read on from there
|
||||||
|
ReadImage(mImageLibrary[id]);
|
||||||
|
} else {
|
||||||
|
// ignore the rest
|
||||||
|
SkipElement();
|
||||||
|
}
|
||||||
|
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
||||||
|
if (strcmp(mReader->getNodeName(), "library_images") != 0)
|
||||||
|
ThrowException("Expected end of <library_images> element.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Reads an image entry into the given image
|
// Reads an image entry into the given image
|
||||||
void ColladaParser::ReadImage(XmlNode &node, Collada::Image &pImage) {
|
void ColladaParser::ReadImage(XmlNode &node, Collada::Image &pImage) {
|
||||||
while (mReader->read()) {
|
for (XmlNode currentNode : node.children()) {
|
||||||
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
const std::string currentName = currentNode.name();
|
||||||
// Need to run different code paths here, depending on the Collada XSD version
|
if (currentName == "image") {
|
||||||
if (IsElement("image")) {
|
// Ignore
|
||||||
SkipElement();
|
continue;
|
||||||
} else if (IsElement("init_from")) {
|
} else if (currentName == "init_from") {
|
||||||
if (mFormat == FV_1_4_n) {
|
if (mFormat == FV_1_4_n) {
|
||||||
// FIX: C4D exporter writes empty <init_from/> tags
|
// FIX: C4D exporter writes empty <init_from/> tags
|
||||||
if (!mReader->isEmptyElement()) {
|
if (!currentNode.empty()) {
|
||||||
// element content is filename - hopefully
|
|
||||||
const char *sz = TestTextContent();
|
|
||||||
if (sz) {
|
|
||||||
aiString filepath(sz);
|
|
||||||
UriDecodePath(filepath);
|
|
||||||
pImage.mFileName = filepath.C_Str();
|
|
||||||
}
|
|
||||||
TestClosing("init_from");
|
|
||||||
}
|
|
||||||
if (!pImage.mFileName.length()) {
|
|
||||||
pImage.mFileName = "unknown_texture";
|
|
||||||
}
|
|
||||||
} else if (mFormat == FV_1_5_n) {
|
|
||||||
// make sure we skip over mip and array initializations, which
|
|
||||||
// we don't support, but which could confuse the loader if
|
|
||||||
// they're not skipped.
|
|
||||||
int attrib = TestAttribute("array_index");
|
|
||||||
if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
|
|
||||||
ASSIMP_LOG_WARN("Collada: Ignoring texture array index");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
attrib = TestAttribute("mip_index");
|
|
||||||
if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
|
|
||||||
ASSIMP_LOG_WARN("Collada: Ignoring MIP map layer");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: correctly jump over cube and volume maps?
|
|
||||||
}
|
|
||||||
} else if (mFormat == FV_1_5_n) {
|
|
||||||
if (IsElement("ref")) {
|
|
||||||
// element content is filename - hopefully
|
// element content is filename - hopefully
|
||||||
const char *sz = TestTextContent();
|
const char *sz = TestTextContent();
|
||||||
if (sz) {
|
if (sz) {
|
||||||
|
@ -1284,39 +1403,150 @@ void ColladaParser::ReadImage(XmlNode &node, Collada::Image &pImage) {
|
||||||
UriDecodePath(filepath);
|
UriDecodePath(filepath);
|
||||||
pImage.mFileName = filepath.C_Str();
|
pImage.mFileName = filepath.C_Str();
|
||||||
}
|
}
|
||||||
TestClosing("ref");
|
TestClosing("init_from");
|
||||||
} else if (IsElement("hex") && !pImage.mFileName.length()) {
|
|
||||||
// embedded image. get format
|
|
||||||
const int attrib = TestAttribute("format");
|
|
||||||
if (-1 == attrib)
|
|
||||||
ASSIMP_LOG_WARN("Collada: Unknown image file format");
|
|
||||||
else
|
|
||||||
pImage.mEmbeddedFormat = mReader->getAttributeValue(attrib);
|
|
||||||
|
|
||||||
const char *data = GetTextContent();
|
|
||||||
|
|
||||||
// hexadecimal-encoded binary octets. First of all, find the
|
|
||||||
// required buffer size to reserve enough storage.
|
|
||||||
const char *cur = data;
|
|
||||||
while (!IsSpaceOrNewLine(*cur))
|
|
||||||
cur++;
|
|
||||||
|
|
||||||
const unsigned int size = (unsigned int)(cur - data) * 2;
|
|
||||||
pImage.mImageData.resize(size);
|
|
||||||
for (unsigned int i = 0; i < size; ++i)
|
|
||||||
pImage.mImageData[i] = HexOctetToDecimal(data + (i << 1));
|
|
||||||
|
|
||||||
TestClosing("hex");
|
|
||||||
}
|
}
|
||||||
} else {
|
if (!pImage.mFileName.length()) {
|
||||||
// ignore the rest
|
pImage.mFileName = "unknown_texture";
|
||||||
SkipElement();
|
}
|
||||||
|
} else if (mFormat == FV_1_5_n) {
|
||||||
|
// make sure we skip over mip and array initializations, which
|
||||||
|
// we don't support, but which could confuse the loader if
|
||||||
|
// they're not skipped.
|
||||||
|
int attrib = currentNode.attribute("ref").as_int();
|
||||||
|
int v = currentNode.attributes.begin + attrib;
|
||||||
|
if (attrib != -1 && v > 0) {
|
||||||
|
ASSIMP_LOG_WARN("Collada: Ignoring texture array index");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
attrib = currentNode.attribute("mip_index").as_int();
|
||||||
|
v = currentNode.attributes.begin + attrib;
|
||||||
|
if (attrib != -1 && v > 0) {
|
||||||
|
ASSIMP_LOG_WARN("Collada: Ignoring MIP map layer");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: correctly jump over cube and volume maps?
|
||||||
}
|
}
|
||||||
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
} else if (mFormat == FV_1_5_n) {
|
||||||
if (strcmp(mReader->getNodeName(), "image") == 0)
|
XmlNode refChild = currentNode.child("ref");
|
||||||
break;
|
XmlNode hexChild = currentNode.child("hex");
|
||||||
}
|
if (refChild) {
|
||||||
|
// element content is filename - hopefully
|
||||||
|
const char *sz = refChild.value();
|
||||||
|
if (sz) {
|
||||||
|
aiString filepath(sz);
|
||||||
|
UriDecodePath(filepath);
|
||||||
|
pImage.mFileName = filepath.C_Str();
|
||||||
|
}
|
||||||
|
} else if (hexChild && !pImage.mFileName.length()) {
|
||||||
|
// embedded image. get format
|
||||||
|
const int attrib = hexChild.attribute("format").as_int();
|
||||||
|
if (-1 == attrib) {
|
||||||
|
ASSIMP_LOG_WARN("Collada: Unknown image file format");
|
||||||
|
} else {
|
||||||
|
pImage.mEmbeddedFormat = hexChild.attributes.begin() + attrib;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *data = hexChild.value();
|
||||||
|
|
||||||
|
// hexadecimal-encoded binary octets. First of all, find the
|
||||||
|
// required buffer size to reserve enough storage.
|
||||||
|
const char *cur = data;
|
||||||
|
while (!IsSpaceOrNewLine(*cur)) {
|
||||||
|
++cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned int size = (unsigned int)(cur - data) * 2;
|
||||||
|
pImage.mImageData.resize(size);
|
||||||
|
for (unsigned int i = 0; i < size; ++i) {
|
||||||
|
pImage.mImageData[i] = HexOctetToDecimal(data + (i << 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*while (mReader->read()) {
|
||||||
|
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
||||||
|
// Need to run different code paths here, depending on the Collada XSD version
|
||||||
|
if (IsElement("image")) {
|
||||||
|
SkipElement();
|
||||||
|
} else if (IsElement("init_from")) {
|
||||||
|
if (mFormat == FV_1_4_n) {
|
||||||
|
// FIX: C4D exporter writes empty <init_from/> tags
|
||||||
|
if (!mReader->isEmptyElement()) {
|
||||||
|
// element content is filename - hopefully
|
||||||
|
const char *sz = TestTextContent();
|
||||||
|
if (sz) {
|
||||||
|
aiString filepath(sz);
|
||||||
|
UriDecodePath(filepath);
|
||||||
|
pImage.mFileName = filepath.C_Str();
|
||||||
|
}
|
||||||
|
TestClosing("init_from");
|
||||||
|
}
|
||||||
|
if (!pImage.mFileName.length()) {
|
||||||
|
pImage.mFileName = "unknown_texture";
|
||||||
|
}
|
||||||
|
} else if (mFormat == FV_1_5_n) {
|
||||||
|
// make sure we skip over mip and array initializations, which
|
||||||
|
// we don't support, but which could confuse the loader if
|
||||||
|
// they're not skipped.
|
||||||
|
int attrib = TestAttribute("array_index");
|
||||||
|
if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
|
||||||
|
ASSIMP_LOG_WARN("Collada: Ignoring texture array index");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
attrib = TestAttribute("mip_index");
|
||||||
|
if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
|
||||||
|
ASSIMP_LOG_WARN("Collada: Ignoring MIP map layer");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: correctly jump over cube and volume maps?
|
||||||
|
}
|
||||||
|
} else if (mFormat == FV_1_5_n) {
|
||||||
|
if (IsElement("ref")) {
|
||||||
|
// element content is filename - hopefully
|
||||||
|
const char *sz = TestTextContent();
|
||||||
|
if (sz) {
|
||||||
|
aiString filepath(sz);
|
||||||
|
UriDecodePath(filepath);
|
||||||
|
pImage.mFileName = filepath.C_Str();
|
||||||
|
}
|
||||||
|
TestClosing("ref");
|
||||||
|
} else if (IsElement("hex") && !pImage.mFileName.length()) {
|
||||||
|
// embedded image. get format
|
||||||
|
const int attrib = TestAttribute("format");
|
||||||
|
if (-1 == attrib)
|
||||||
|
ASSIMP_LOG_WARN("Collada: Unknown image file format");
|
||||||
|
else
|
||||||
|
pImage.mEmbeddedFormat = mReader->getAttributeValue(attrib);
|
||||||
|
|
||||||
|
const char *data = GetTextContent();
|
||||||
|
|
||||||
|
// hexadecimal-encoded binary octets. First of all, find the
|
||||||
|
// required buffer size to reserve enough storage.
|
||||||
|
const char *cur = data;
|
||||||
|
while (!IsSpaceOrNewLine(*cur))
|
||||||
|
cur++;
|
||||||
|
|
||||||
|
const unsigned int size = (unsigned int)(cur - data) * 2;
|
||||||
|
pImage.mImageData.resize(size);
|
||||||
|
for (unsigned int i = 0; i < size; ++i)
|
||||||
|
pImage.mImageData[i] = HexOctetToDecimal(data + (i << 1));
|
||||||
|
|
||||||
|
TestClosing("hex");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// ignore the rest
|
||||||
|
SkipElement();
|
||||||
|
}
|
||||||
|
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
||||||
|
if (strcmp(mReader->getNodeName(), "image") == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -1329,7 +1559,36 @@ void ColladaParser::ReadMaterialLibrary(XmlNode &node) {
|
||||||
return;*/
|
return;*/
|
||||||
|
|
||||||
std::map<std::string, int> names;
|
std::map<std::string, int> names;
|
||||||
while (mReader->read()) {
|
|
||||||
|
for (XmlNode currentNode : node.children()) {
|
||||||
|
const std::string currentName = currentNode.name();
|
||||||
|
int attrID = currentNode.attribute("id").as_int();
|
||||||
|
std::string id = currentNode.attributes.begin() + attrID;
|
||||||
|
std::string name;
|
||||||
|
int attrName = currentNode.attribute("name").as_int();
|
||||||
|
if (attrName >= 0) {
|
||||||
|
name = currentNode.attributes.begin() + attrName;
|
||||||
|
}
|
||||||
|
mMaterialLibrary[id] = Material();
|
||||||
|
|
||||||
|
if (!name.empty()) {
|
||||||
|
std::map<std::string, int>::iterator it = names.find(name);
|
||||||
|
if (it != names.end()) {
|
||||||
|
std::ostringstream strStream;
|
||||||
|
strStream << ++it->second;
|
||||||
|
name.append(" " + strStream.str());
|
||||||
|
} else {
|
||||||
|
names[name] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mMaterialLibrary[id].mName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadMaterial(currentNode, mMaterialLibrary[id]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*while (mReader->read()) {
|
||||||
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
||||||
if (IsElement("material")) {
|
if (IsElement("material")) {
|
||||||
// read ID. By now you probably know my opinion about this "specification"
|
// read ID. By now you probably know my opinion about this "specification"
|
||||||
|
@ -1368,7 +1627,7 @@ void ColladaParser::ReadMaterialLibrary(XmlNode &node) {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -2778,7 +3037,7 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if (mReader->isEmptyElement())
|
/* if (mReader->isEmptyElement())
|
||||||
return;*/
|
return;*/
|
||||||
|
|
||||||
while (mReader->read()) {
|
while (mReader->read()) {
|
||||||
|
@ -2796,7 +3055,6 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) {
|
||||||
if (attrName > -1)
|
if (attrName > -1)
|
||||||
child->mName = mReader->getAttributeValue(attrName);
|
child->mName = mReader->getAttributeValue(attrName);
|
||||||
|
|
||||||
|
|
||||||
if (pNode) {
|
if (pNode) {
|
||||||
pNode->mChildren.push_back(child);
|
pNode->mChildren.push_back(child);
|
||||||
child->mParent = pNode;
|
child->mParent = pNode;
|
||||||
|
@ -3034,7 +3292,30 @@ void ColladaParser::ReadScene(XmlNode &node) {
|
||||||
/*if (mReader->isEmptyElement())
|
/*if (mReader->isEmptyElement())
|
||||||
return;*/
|
return;*/
|
||||||
|
|
||||||
while (mReader->read()) {
|
for (XmlNode currentNode : node.children()) {
|
||||||
|
const std::string currentName = currentNode.name();
|
||||||
|
if (currentName == "instance_visual_scene") {
|
||||||
|
// should be the first and only occurrence
|
||||||
|
if (mRootNode)
|
||||||
|
ThrowException("Invalid scene containing multiple root nodes in <instance_visual_scene> element");
|
||||||
|
|
||||||
|
// read the url of the scene to instance. Should be of format "#some_name"
|
||||||
|
int urlIndex = currentNode.attribute("url").as_int();
|
||||||
|
const char *url = currentNode.attributes.begin() + urlIndex;
|
||||||
|
if (url[0] != '#') {
|
||||||
|
ThrowException("Unknown reference format in <instance_visual_scene> element");
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the referred scene, skip the leading #
|
||||||
|
NodeLibrary::const_iterator sit = mNodeLibrary.find(url + 1);
|
||||||
|
if (sit == mNodeLibrary.end()) {
|
||||||
|
ThrowException("Unable to resolve visual_scene reference \"" + std::string(url) + "\" in <instance_visual_scene> element.");
|
||||||
|
}
|
||||||
|
mRootNode = sit->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*while (mReader->read()) {
|
||||||
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
|
||||||
if (IsElement("instance_visual_scene")) {
|
if (IsElement("instance_visual_scene")) {
|
||||||
// should be the first and only occurrence
|
// should be the first and only occurrence
|
||||||
|
@ -3058,7 +3339,7 @@ void ColladaParser::ReadScene(XmlNode &node) {
|
||||||
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -3159,7 +3440,7 @@ void ColladaParser::ReportWarning(const char *msg, ...) {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes
|
// Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes
|
||||||
int ColladaParser::GetAttribute(const char *pAttr) const {
|
/*int ColladaParser::GetAttribute(const char *pAttr) const {
|
||||||
int index = TestAttribute(pAttr);
|
int index = TestAttribute(pAttr);
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">.");
|
ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">.");
|
||||||
|
@ -3167,31 +3448,31 @@ int ColladaParser::GetAttribute(const char *pAttr) const {
|
||||||
|
|
||||||
// attribute not found -> throw an exception
|
// attribute not found -> throw an exception
|
||||||
return index;
|
return index;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Tests the present element for the presence of one attribute, returns its index or throws an exception if not found
|
// Tests the present element for the presence of one attribute, returns its index or throws an exception if not found
|
||||||
int ColladaParser::TestAttribute(const char *pAttr) const {
|
/*int ColladaParser::TestAttribute(const char *pAttr) const {
|
||||||
for (int a = 0; a < mReader->getAttributeCount(); a++)
|
for (int a = 0; a < mReader->getAttributeCount(); a++)
|
||||||
if (strcmp(mReader->getAttributeName(a), pAttr) == 0)
|
if (strcmp(mReader->getAttributeName(a), pAttr) == 0)
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Reads the text contents of an element, throws an exception if not given. Skips leading whitespace.
|
// Reads the text contents of an element, throws an exception if not given. Skips leading whitespace.
|
||||||
const char *ColladaParser::GetTextContent() {
|
/*const char *ColladaParser::GetTextContent() {
|
||||||
const char *sz = TestTextContent();
|
const char *sz = TestTextContent();
|
||||||
if (!sz) {
|
if (!sz) {
|
||||||
ThrowException("Invalid contents in element \"n\".");
|
ThrowException("Invalid contents in element \"n\".");
|
||||||
}
|
}
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Reads the text contents of an element, returns nullptr if not given. Skips leading whitespace.
|
// Reads the text contents of an element, returns nullptr if not given. Skips leading whitespace.
|
||||||
const char *ColladaParser::TestTextContent() {
|
/*const char *ColladaParser::TestTextContent() {
|
||||||
// present node should be the beginning of an element
|
// present node should be the beginning of an element
|
||||||
if (mReader->getNodeType() != irr::io::EXN_ELEMENT || mReader->isEmptyElement())
|
if (mReader->getNodeType() != irr::io::EXN_ELEMENT || mReader->isEmptyElement())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -3209,7 +3490,7 @@ const char *ColladaParser::TestTextContent() {
|
||||||
SkipSpacesAndLineEnd(&text);
|
SkipSpacesAndLineEnd(&text);
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Calculates the resulting transformation from all the given transform steps
|
// Calculates the resulting transformation from all the given transform steps
|
||||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
Copyright (c) 2006-2020, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -43,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "OgreXmlSerializer.h"
|
#include "OgreXmlSerializer.h"
|
||||||
#include "OgreBinarySerializer.h"
|
#include "OgreBinarySerializer.h"
|
||||||
#include "OgreParsingUtils.h"
|
#include "OgreParsingUtils.h"
|
||||||
|
|
||||||
#include <assimp/TinyFormatter.h>
|
#include <assimp/TinyFormatter.h>
|
||||||
#include <assimp/DefaultLogger.hpp>
|
#include <assimp/DefaultLogger.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -56,85 +54,86 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
namespace Ogre {
|
namespace Ogre {
|
||||||
|
|
||||||
AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX;
|
AI_WONT_RETURN void ThrowAttibuteError(const XmlParser *reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX;
|
||||||
AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error) {
|
|
||||||
|
AI_WONT_RETURN void ThrowAttibuteError(const std::string &nodeName, const std::string &name, const std::string &error) {
|
||||||
if (!error.empty()) {
|
if (!error.empty()) {
|
||||||
throw DeadlyImportError(error + " in node '" + std::string(reader->getNodeName()) + "' and attribute '" + name + "'");
|
throw DeadlyImportError(error + " in node '" + nodeName + "' and attribute '" + name + "'");
|
||||||
} else {
|
} else {
|
||||||
throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + std::string(reader->getNodeName()) + "'");
|
throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + nodeName + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static inline bool hasAttribute( XmlNode &xmlNode, const char *name ) {
|
||||||
|
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||||
|
return !attr.empty();
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
int32_t OgreXmlSerializer::ReadAttribute<int32_t>(const char *name) const {
|
int32_t OgreXmlSerializer::ReadAttribute<int32_t>(XmlNode &xmlNode, const char *name) const {
|
||||||
if (!HasAttribute(name)) {
|
if (!hasAttribute(xmlNode, name )) {
|
||||||
ThrowAttibuteError(m_reader, name);
|
ThrowAttibuteError(mParser, name);
|
||||||
}
|
}
|
||||||
|
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||||
return static_cast<int32_t>(m_reader->getAttributeValueAsInt(name));
|
return static_cast<int32_t>(attr.as_int());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
uint32_t OgreXmlSerializer::ReadAttribute<uint32_t>(const char *name) const {
|
uint32_t OgreXmlSerializer::ReadAttribute<uint32_t>(XmlNode &xmlNode, const char *name) const {
|
||||||
if (!HasAttribute(name)) {
|
if (!hasAttribute(xmlNode, name)) {
|
||||||
ThrowAttibuteError(m_reader, name);
|
ThrowAttibuteError(mParser, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @note This is hackish. But we are never expecting unsigned values that go outside the
|
// @note This is hackish. But we are never expecting unsigned values that go outside the
|
||||||
// int32_t range. Just monitor for negative numbers and kill the import.
|
// int32_t range. Just monitor for negative numbers and kill the import.
|
||||||
int32_t temp = ReadAttribute<int32_t>(name);
|
int32_t temp = ReadAttribute<int32_t>(xmlNode, name);
|
||||||
if (temp < 0) {
|
if (temp < 0) {
|
||||||
ThrowAttibuteError(m_reader, name, "Found a negative number value where expecting a uint32_t value");
|
ThrowAttibuteError(mParser, name, "Found a negative number value where expecting a uint32_t value");
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<uint32_t>(temp);
|
return static_cast<uint32_t>(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
uint16_t OgreXmlSerializer::ReadAttribute<uint16_t>(const char *name) const {
|
uint16_t OgreXmlSerializer::ReadAttribute<uint16_t>(XmlNode &xmlNode, const char *name) const {
|
||||||
if (!HasAttribute(name)) {
|
if (!hasAttribute(xmlNode, name)) {
|
||||||
ThrowAttibuteError(m_reader, name);
|
ThrowAttibuteError(mParser, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<uint16_t>(ReadAttribute<uint32_t>(name));
|
return static_cast<uint16_t>(xmlNode.attribute(name).as_int());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
float OgreXmlSerializer::ReadAttribute<float>(const char *name) const {
|
float OgreXmlSerializer::ReadAttribute<float>(XmlNode &xmlNode, const char *name) const {
|
||||||
if (!HasAttribute(name)) {
|
if (!hasAttribute(xmlNode, name)) {
|
||||||
ThrowAttibuteError(m_reader, name);
|
ThrowAttibuteError(mParser, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_reader->getAttributeValueAsFloat(name);
|
return xmlNode.attribute(name).as_float();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::string OgreXmlSerializer::ReadAttribute<std::string>(const char *name) const {
|
std::string OgreXmlSerializer::ReadAttribute<std::string>(XmlNode &xmlNode, const char *name) const {
|
||||||
const char *value = m_reader->getAttributeValue(name);
|
if (!hasAttribute(xmlNode, name)) {
|
||||||
if (nullptr == value) {
|
ThrowAttibuteError(mParser, name);
|
||||||
ThrowAttibuteError(m_reader, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::string(value);
|
return xmlNode.attribute(name).as_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool OgreXmlSerializer::ReadAttribute<bool>(const char *name) const {
|
bool OgreXmlSerializer::ReadAttribute<bool>(XmlNode &xmlNode, const char *name) const {
|
||||||
std::string value = Ogre::ToLower(ReadAttribute<std::string>(name));
|
std::string value = Ogre::ToLower(ReadAttribute<std::string>(xmlNode, name));
|
||||||
if (ASSIMP_stricmp(value, "true") == 0) {
|
if (ASSIMP_stricmp(value, "true") == 0) {
|
||||||
return true;
|
return true;
|
||||||
} else if (ASSIMP_stricmp(value, "false") == 0) {
|
} else if (ASSIMP_stricmp(value, "false") == 0) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
ThrowAttibuteError(m_reader, name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
|
|
||||||
return false;
|
ThrowAttibuteError(mParser, name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OgreXmlSerializer::HasAttribute(const char *name) const {
|
/*std::string &OgreXmlSerializer::NextNode() {
|
||||||
return (m_reader->getAttributeValue(name) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string &OgreXmlSerializer::NextNode() {
|
|
||||||
do {
|
do {
|
||||||
if (!m_reader->read()) {
|
if (!m_reader->read()) {
|
||||||
m_currentNodeName = "";
|
m_currentNodeName = "";
|
||||||
|
@ -178,7 +177,7 @@ std::string &OgreXmlSerializer::SkipCurrentNode() {
|
||||||
|
|
||||||
return NextNode();
|
return NextNode();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// Mesh XML constants
|
// Mesh XML constants
|
||||||
|
|
||||||
// <mesh>
|
// <mesh>
|
||||||
|
@ -247,15 +246,14 @@ static const char *nnTranslate = "translate";
|
||||||
static const char *nnRotate = "rotate";
|
static const char *nnRotate = "rotate";
|
||||||
|
|
||||||
// Common XML constants
|
// Common XML constants
|
||||||
|
|
||||||
static const char *anX = "x";
|
static const char *anX = "x";
|
||||||
static const char *anY = "y";
|
static const char *anY = "y";
|
||||||
static const char *anZ = "z";
|
static const char *anZ = "z";
|
||||||
|
|
||||||
// Mesh
|
// Mesh
|
||||||
|
|
||||||
MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader) {
|
MeshXml *OgreXmlSerializer::ImportMesh(XmlParser *xmlParser) {
|
||||||
OgreXmlSerializer serializer(reader);
|
OgreXmlSerializer serializer(xmlParser);
|
||||||
|
|
||||||
MeshXml *mesh = new MeshXml();
|
MeshXml *mesh = new MeshXml();
|
||||||
serializer.ReadMesh(mesh);
|
serializer.ReadMesh(mesh);
|
||||||
|
@ -264,16 +262,32 @@ MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
|
void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
|
||||||
if (NextNode() != nnMesh) {
|
const XmlNode *root = mParser->getRootNode();
|
||||||
|
if (nullptr == root || std::string(nnMesh)!=root->name()) {
|
||||||
throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <mesh>");
|
throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <mesh>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (XmlNode currentNode : root->children()) {
|
||||||
|
const std::string currentName = currentNode.name();
|
||||||
|
if (currentName == nnSharedGeometry) {
|
||||||
|
mesh->sharedVertexData = new VertexDataXml();
|
||||||
|
ReadGeometry(currentNode, mesh->sharedVertexData);
|
||||||
|
} else if (currentName == nnSubMesh) {
|
||||||
|
ReadSubMesh(currentNode, mesh);
|
||||||
|
} else if (currentName == nnBoneAssignments) {
|
||||||
|
ReadBoneAssignments(currentNode, mesh->sharedVertexData);
|
||||||
|
} else if (currentName == nnSkeletonLink) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*if (NextNode() != nnMesh) {
|
||||||
|
}*/
|
||||||
|
|
||||||
ASSIMP_LOG_VERBOSE_DEBUG("Reading Mesh");
|
ASSIMP_LOG_VERBOSE_DEBUG("Reading Mesh");
|
||||||
|
|
||||||
NextNode();
|
//NextNode();
|
||||||
|
|
||||||
// Root level nodes
|
// Root level nodes
|
||||||
while (m_currentNodeName == nnSharedGeometry ||
|
/*while (m_currentNodeName == nnSharedGeometry ||
|
||||||
m_currentNodeName == nnSubMeshes ||
|
m_currentNodeName == nnSubMeshes ||
|
||||||
m_currentNodeName == nnSkeletonLink ||
|
m_currentNodeName == nnSkeletonLink ||
|
||||||
m_currentNodeName == nnBoneAssignments ||
|
m_currentNodeName == nnBoneAssignments ||
|
||||||
|
@ -298,26 +312,33 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
|
||||||
NextNode();
|
NextNode();
|
||||||
}
|
}
|
||||||
// Assimp incompatible/ignored nodes
|
// Assimp incompatible/ignored nodes
|
||||||
else
|
else {
|
||||||
SkipCurrentNode();
|
SkipCurrentNode();
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreXmlSerializer::ReadGeometry(VertexDataXml *dest) {
|
void OgreXmlSerializer::ReadGeometry(XmlNode &node, VertexDataXml *dest) {
|
||||||
dest->count = ReadAttribute<uint32_t>("vertexcount");
|
dest->count = ReadAttribute<uint32_t>(node, "vertexcount");
|
||||||
ASSIMP_LOG_VERBOSE_DEBUG_F(" - Reading geometry of ", dest->count, " vertices");
|
ASSIMP_LOG_VERBOSE_DEBUG_F(" - Reading geometry of ", dest->count, " vertices");
|
||||||
|
|
||||||
NextNode();
|
for (XmlNode currentNode : node.children()) {
|
||||||
while (m_currentNodeName == nnVertexBuffer) {
|
const std::string ¤tName = currentNode.name();
|
||||||
ReadGeometryVertexBuffer(dest);
|
if (currentName == nnVertexBuffer) {
|
||||||
|
ReadGeometryVertexBuffer(currentNode, dest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
//NextNode();
|
||||||
|
/*while (m_currentNodeName == nnVertexBuffer) {
|
||||||
|
ReadGeometryVertexBuffer(dest);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) {
|
void OgreXmlSerializer::ReadGeometryVertexBuffer(XmlNode &node, VertexDataXml *dest) {
|
||||||
bool positions = (HasAttribute("positions") && ReadAttribute<bool>("positions"));
|
bool positions = (hasAttribute(node, "positions") && ReadAttribute<bool>(node, "positions"));
|
||||||
bool normals = (HasAttribute("normals") && ReadAttribute<bool>("normals"));
|
bool normals = (hasAttribute(node, "normals") && ReadAttribute<bool>(node, "normals"));
|
||||||
bool tangents = (HasAttribute("tangents") && ReadAttribute<bool>("tangents"));
|
bool tangents = (hasAttribute(node, "tangents") && ReadAttribute<bool>(node, "tangents"));
|
||||||
uint32_t uvs = (HasAttribute("texture_coords") ? ReadAttribute<uint32_t>("texture_coords") : 0);
|
uint32_t uvs = (hasAttribute(node, "texture_coords") ? ReadAttribute<uint32_t>(node, "texture_coords") : 0);
|
||||||
|
|
||||||
// Not having positions is a error only if a previous vertex buffer did not have them.
|
// Not having positions is a error only if a previous vertex buffer did not have them.
|
||||||
if (!positions && !dest->HasPositions()) {
|
if (!positions && !dest->HasPositions()) {
|
||||||
|
@ -348,9 +369,38 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) {
|
||||||
bool warnColorDiffuse = true;
|
bool warnColorDiffuse = true;
|
||||||
bool warnColorSpecular = true;
|
bool warnColorSpecular = true;
|
||||||
|
|
||||||
NextNode();
|
//NextNode();
|
||||||
|
for (XmlNode currentNode : node.children()) {
|
||||||
|
const std::string ¤tName = currentNode.name();
|
||||||
|
if (positions && currentName == nnPosition) {
|
||||||
|
aiVector3D pos;
|
||||||
|
pos.x = ReadAttribute<float>(currentNode, anX);
|
||||||
|
pos.y = ReadAttribute<float>(currentNode, anY);
|
||||||
|
pos.z = ReadAttribute<float>(currentNode, anZ);
|
||||||
|
dest->positions.push_back(pos);
|
||||||
|
} else if (normals && currentName == nnNormal) {
|
||||||
|
aiVector3D normal;
|
||||||
|
normal.x = ReadAttribute<float>(currentNode, anX);
|
||||||
|
normal.y = ReadAttribute<float>(currentNode, anY);
|
||||||
|
normal.z = ReadAttribute<float>(currentNode, anZ);
|
||||||
|
dest->normals.push_back(normal);
|
||||||
|
} else if (tangents && currentName == nnTangent) {
|
||||||
|
aiVector3D tangent;
|
||||||
|
tangent.x = ReadAttribute<float>(currentNode, anX);
|
||||||
|
tangent.y = ReadAttribute<float>(currentNode, anY);
|
||||||
|
tangent.z = ReadAttribute<float>(currentNode, anZ);
|
||||||
|
dest->tangents.push_back(tangent);
|
||||||
|
} else if (uvs > 0 && currentName == nnTexCoord) {
|
||||||
|
for (auto &curUvs : dest->uvs) {
|
||||||
|
aiVector3D uv;
|
||||||
|
uv.x = ReadAttribute<float>(currentNode, "u");
|
||||||
|
uv.y = (ReadAttribute<float>(currentNode, "v") * -1) + 1; // Flip UV from Ogre to Assimp form
|
||||||
|
curUvs.push_back(uv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (m_currentNodeName == nnVertex ||
|
/*while (m_currentNodeName == nnVertex ||
|
||||||
m_currentNodeName == nnPosition ||
|
m_currentNodeName == nnPosition ||
|
||||||
m_currentNodeName == nnNormal ||
|
m_currentNodeName == nnNormal ||
|
||||||
m_currentNodeName == nnTangent ||
|
m_currentNodeName == nnTangent ||
|
||||||
|
@ -422,11 +472,11 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) {
|
||||||
if (warn) {
|
if (warn) {
|
||||||
ASSIMP_LOG_WARN_F("Vertex buffer attribute read not implemented for element: ", m_currentNodeName);
|
ASSIMP_LOG_WARN_F("Vertex buffer attribute read not implemented for element: ", m_currentNodeName);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Advance
|
// Advance
|
||||||
NextNode();
|
//NextNode();
|
||||||
}
|
//}
|
||||||
|
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
if (dest->positions.size() != dest->count) {
|
if (dest->positions.size() != dest->count) {
|
||||||
|
@ -446,7 +496,7 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) {
|
void OgreXmlSerializer::ReadSubMesh(XmlNode &node, MeshXml *mesh) {
|
||||||
static const char *anMaterial = "material";
|
static const char *anMaterial = "material";
|
||||||
static const char *anUseSharedVertices = "usesharedvertices";
|
static const char *anUseSharedVertices = "usesharedvertices";
|
||||||
static const char *anCount = "count";
|
static const char *anCount = "count";
|
||||||
|
@ -457,10 +507,10 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) {
|
||||||
|
|
||||||
SubMeshXml *submesh = new SubMeshXml();
|
SubMeshXml *submesh = new SubMeshXml();
|
||||||
|
|
||||||
if (HasAttribute(anMaterial)) {
|
if (hasAttribute(node, anMaterial)) {
|
||||||
submesh->materialRef = ReadAttribute<std::string>(anMaterial);
|
submesh->materialRef = ReadAttribute<std::string>(node, anMaterial);
|
||||||
}
|
}
|
||||||
if (HasAttribute(anUseSharedVertices)) {
|
if (hasAttribute(node, anUseSharedVertices)) {
|
||||||
submesh->usesSharedVertexData = ReadAttribute<bool>(anUseSharedVertices);
|
submesh->usesSharedVertexData = ReadAttribute<bool>(anUseSharedVertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,7 +524,46 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) {
|
||||||
|
|
||||||
bool quadWarned = false;
|
bool quadWarned = false;
|
||||||
|
|
||||||
NextNode();
|
for (XmlNode ¤tNode : node.children()) {
|
||||||
|
const std::string ¤tName = currentNode.name();
|
||||||
|
if (currentName == nnFaces) {
|
||||||
|
submesh->indexData->faceCount = ReadAttribute<uint32_t>(currentNode, anCount);
|
||||||
|
submesh->indexData->faces.reserve(submesh->indexData->faceCount);
|
||||||
|
for (XmlNode currentChildNode : currentNode.children()) {
|
||||||
|
const std::string ¤tChildName = currentNode.name();
|
||||||
|
if (currentChildName == nnFace) {
|
||||||
|
aiFace face;
|
||||||
|
face.mNumIndices = 3;
|
||||||
|
face.mIndices = new unsigned int[3];
|
||||||
|
face.mIndices[0] = ReadAttribute<uint32_t>(currentChildNode, anV1);
|
||||||
|
face.mIndices[1] = ReadAttribute<uint32_t>(currentChildNode, anV2);
|
||||||
|
face.mIndices[2] = ReadAttribute<uint32_t>(currentChildNode, anV3);
|
||||||
|
/// @todo Support quads if Ogre even supports them in XML (I'm not sure but I doubt it)
|
||||||
|
if (!quadWarned && hasAttribute(currentChildNode, anV4)) {
|
||||||
|
ASSIMP_LOG_WARN("Submesh <face> has quads with <v4>, only triangles are supported at the moment!");
|
||||||
|
quadWarned = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (submesh->indexData->faces.size() == submesh->indexData->faceCount) {
|
||||||
|
ASSIMP_LOG_VERBOSE_DEBUG_F(" - Faces ", submesh->indexData->faceCount);
|
||||||
|
} else {
|
||||||
|
throw DeadlyImportError(Formatter::format() << "Read only " << submesh->indexData->faces.size() << " faces when should have read " << submesh->indexData->faceCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (currentName == nnGeometry) {
|
||||||
|
if (submesh->usesSharedVertexData) {
|
||||||
|
throw DeadlyImportError("Found <geometry> in <submesh> when use shared geometry is true. Invalid mesh file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
submesh->vertexData = new VertexDataXml();
|
||||||
|
ReadGeometry(currentNode, submesh->vertexData);
|
||||||
|
} else if (m_currentNodeName == nnBoneAssignments) {
|
||||||
|
ReadBoneAssignments(currentNode, submesh->vertexData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*NextNode();
|
||||||
while (m_currentNodeName == nnFaces ||
|
while (m_currentNodeName == nnFaces ||
|
||||||
m_currentNodeName == nnGeometry ||
|
m_currentNodeName == nnGeometry ||
|
||||||
m_currentNodeName == nnTextures ||
|
m_currentNodeName == nnTextures ||
|
||||||
|
@ -523,13 +612,13 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) {
|
||||||
else {
|
else {
|
||||||
SkipCurrentNode();
|
SkipCurrentNode();
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
submesh->index = static_cast<unsigned int>(mesh->subMeshes.size());
|
submesh->index = static_cast<unsigned int>(mesh->subMeshes.size());
|
||||||
mesh->subMeshes.push_back(submesh);
|
mesh->subMeshes.push_back(submesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest) {
|
void OgreXmlSerializer::ReadBoneAssignments(XmlNode &node, VertexDataXml *dest) {
|
||||||
if (!dest) {
|
if (!dest) {
|
||||||
throw DeadlyImportError("Cannot read bone assignments, vertex data is null.");
|
throw DeadlyImportError("Cannot read bone assignments, vertex data is null.");
|
||||||
}
|
}
|
||||||
|
@ -539,8 +628,20 @@ void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest) {
|
||||||
static const char *anWeight = "weight";
|
static const char *anWeight = "weight";
|
||||||
|
|
||||||
std::set<uint32_t> influencedVertices;
|
std::set<uint32_t> influencedVertices;
|
||||||
|
for (XmlNode ¤tNode : node.children()) {
|
||||||
|
const std::string ¤tName = currentNode.name();
|
||||||
|
if (currentName == nnVertexBoneAssignment) {
|
||||||
|
VertexBoneAssignment ba;
|
||||||
|
ba.vertexIndex = ReadAttribute<uint32_t>(currentNode, anVertexIndex);
|
||||||
|
ba.boneIndex = ReadAttribute<uint16_t>(currentNode, anBoneIndex);
|
||||||
|
ba.weight = ReadAttribute<float>(currentNode, anWeight);
|
||||||
|
|
||||||
NextNode();
|
dest->boneAssignments.push_back(ba);
|
||||||
|
influencedVertices.insert(ba.vertexIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*NextNode();
|
||||||
while (m_currentNodeName == nnVertexBoneAssignment) {
|
while (m_currentNodeName == nnVertexBoneAssignment) {
|
||||||
VertexBoneAssignment ba;
|
VertexBoneAssignment ba;
|
||||||
ba.vertexIndex = ReadAttribute<uint32_t>(anVertexIndex);
|
ba.vertexIndex = ReadAttribute<uint32_t>(anVertexIndex);
|
||||||
|
@ -551,7 +652,7 @@ void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest) {
|
||||||
influencedVertices.insert(ba.vertexIndex);
|
influencedVertices.insert(ba.vertexIndex);
|
||||||
|
|
||||||
NextNode();
|
NextNode();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/** Normalize bone weights.
|
/** Normalize bone weights.
|
||||||
Some exporters won't care if the sum of all bone weights
|
Some exporters won't care if the sum of all bone weights
|
||||||
|
@ -593,41 +694,43 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *me
|
||||||
mesh->skeletonRef = mesh->skeletonRef + ".xml";
|
mesh->skeletonRef = mesh->skeletonRef + ".xml";
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
|
XmlParserPtr xmlParser = OpenXmlParser(pIOHandler, mesh->skeletonRef);
|
||||||
if (!reader.get())
|
if (!xmlParser.get())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Skeleton *skeleton = new Skeleton();
|
Skeleton *skeleton = new Skeleton();
|
||||||
OgreXmlSerializer serializer(reader.get());
|
OgreXmlSerializer serializer(xmlParser.get());
|
||||||
serializer.ReadSkeleton(skeleton);
|
serializer.ReadSkeleton(skeleton);
|
||||||
mesh->skeleton = skeleton;
|
mesh->skeleton = skeleton;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh) {
|
bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh) {
|
||||||
if (!mesh || mesh->skeletonRef.empty())
|
if (!mesh || mesh->skeletonRef.empty()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
XmlReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
|
XmlParserPtr xmlParser = OpenXmlParser(pIOHandler, mesh->skeletonRef);
|
||||||
if (!reader.get())
|
if (!xmlParser.get()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Skeleton *skeleton = new Skeleton();
|
Skeleton *skeleton = new Skeleton();
|
||||||
OgreXmlSerializer serializer(reader.get());
|
OgreXmlSerializer serializer(xmlParser.get());
|
||||||
serializer.ReadSkeleton(skeleton);
|
serializer.ReadSkeleton(skeleton);
|
||||||
mesh->skeleton = skeleton;
|
mesh->skeleton = skeleton;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename) {
|
XmlParserPtr OgreXmlSerializer::OpenXmlParser(Assimp::IOSystem *pIOHandler, const std::string &filename) {
|
||||||
if (!EndsWith(filename, ".skeleton.xml", false)) {
|
if (!EndsWith(filename, ".skeleton.xml", false)) {
|
||||||
ASSIMP_LOG_ERROR_F("Imported Mesh is referencing to unsupported '", filename, "' skeleton file.");
|
ASSIMP_LOG_ERROR_F("Imported Mesh is referencing to unsupported '", filename, "' skeleton file.");
|
||||||
return XmlReaderPtr();
|
return XmlParserPtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pIOHandler->Exists(filename)) {
|
if (!pIOHandler->Exists(filename)) {
|
||||||
ASSIMP_LOG_ERROR_F("Failed to find skeleton file '", filename, "' that is referenced by imported Mesh.");
|
ASSIMP_LOG_ERROR_F("Failed to find skeleton file '", filename, "' that is referenced by imported Mesh.");
|
||||||
return XmlReaderPtr();
|
return XmlParserPtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<IOStream> file(pIOHandler->Open(filename));
|
std::unique_ptr<IOStream> file(pIOHandler->Open(filename));
|
||||||
|
@ -635,27 +738,36 @@ XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const s
|
||||||
throw DeadlyImportError("Failed to open skeleton file " + filename);
|
throw DeadlyImportError("Failed to open skeleton file " + filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CIrrXML_IOStreamReader> stream(new CIrrXML_IOStreamReader(file.get()));
|
XmlParserPtr xmlParser = XmlParserPtr(new XmlParser);
|
||||||
XmlReaderPtr reader = XmlReaderPtr(irr::io::createIrrXMLReader(stream.get()));
|
if (!xmlParser->parse(file.get())) {
|
||||||
if (!reader.get()) {
|
|
||||||
throw DeadlyImportError("Failed to create XML reader for skeleton file " + filename);
|
throw DeadlyImportError("Failed to create XML reader for skeleton file " + filename);
|
||||||
}
|
}
|
||||||
return reader;
|
return xmlParser;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) {
|
void OgreXmlSerializer::ReadSkeleton(XmlNode &node, Skeleton *skeleton) {
|
||||||
if (NextNode() != nnSkeleton) {
|
if (node.name() != nnSkeleton) {
|
||||||
throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <skeleton>");
|
throw DeadlyImportError("Root node is <" + node.name() + "> expecting <skeleton>");
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSIMP_LOG_VERBOSE_DEBUG("Reading Skeleton");
|
ASSIMP_LOG_VERBOSE_DEBUG("Reading Skeleton");
|
||||||
|
|
||||||
// Optional blend mode from root node
|
// Optional blend mode from root node
|
||||||
if (HasAttribute("blendmode")) {
|
if (hasAttribute(node, "blendmode")) {
|
||||||
skeleton->blendMode = (ToLower(ReadAttribute<std::string>("blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
|
skeleton->blendMode = (ToLower(ReadAttribute<std::string>(node, "blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
NextNode();
|
for (XmlNode ¤tNode : node.children()) {
|
||||||
|
const std::string currentName = currentNode.name();
|
||||||
|
if (currentName == nnBones) {
|
||||||
|
ReadBones(currentNode, skeleton);
|
||||||
|
} else if (currentName == nnBoneHierarchy) {
|
||||||
|
ReadBoneHierarchy(currentNode, skeleton);
|
||||||
|
} else if (currentName == nnAnimations) {
|
||||||
|
ReadAnimations(currentNode, skeleton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*NextNode();
|
||||||
|
|
||||||
// Root level nodes
|
// Root level nodes
|
||||||
while (m_currentNodeName == nnBones ||
|
while (m_currentNodeName == nnBones ||
|
||||||
|
@ -670,17 +782,35 @@ void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) {
|
||||||
ReadAnimations(skeleton);
|
ReadAnimations(skeleton);
|
||||||
else
|
else
|
||||||
SkipCurrentNode();
|
SkipCurrentNode();
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) {
|
void OgreXmlSerializer::ReadAnimations(XmlNode &node, Skeleton *skeleton) {
|
||||||
if (skeleton->bones.empty()) {
|
if (skeleton->bones.empty()) {
|
||||||
throw DeadlyImportError("Cannot read <animations> for a Skeleton without bones");
|
throw DeadlyImportError("Cannot read <animations> for a Skeleton without bones");
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSIMP_LOG_VERBOSE_DEBUG(" - Animations");
|
ASSIMP_LOG_VERBOSE_DEBUG(" - Animations");
|
||||||
|
|
||||||
NextNode();
|
for (XmlNode ¤tNode : node.children()) {
|
||||||
|
const std::string currentName = currentNode.name();
|
||||||
|
if (currentName == nnAnimation) {
|
||||||
|
Animation *anim = new Animation(skeleton);
|
||||||
|
anim->name = ReadAttribute<std::string>(currentNode, "name");
|
||||||
|
anim->length = ReadAttribute<float>(currentNode , "length");
|
||||||
|
for (XmlNode ¤tChildNode : currentNode.children()) {
|
||||||
|
const std::string currentChildName = currentNode.name();
|
||||||
|
if (currentChildName == nnTracks) {
|
||||||
|
ReadAnimationTracks(currentChildNode, anim);
|
||||||
|
skeleton->animations.push_back(anim);
|
||||||
|
} else {
|
||||||
|
throw DeadlyImportError(Formatter::format() << "No <tracks> found in <animation> " << anim->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NextNode();
|
||||||
while (m_currentNodeName == nnAnimation) {
|
while (m_currentNodeName == nnAnimation) {
|
||||||
Animation *anim = new Animation(skeleton);
|
Animation *anim = new Animation(skeleton);
|
||||||
anim->name = ReadAttribute<std::string>("name");
|
anim->name = ReadAttribute<std::string>("name");
|
||||||
|
@ -694,11 +824,29 @@ void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) {
|
||||||
skeleton->animations.push_back(anim);
|
skeleton->animations.push_back(anim);
|
||||||
|
|
||||||
ASSIMP_LOG_VERBOSE_DEBUG_F(" ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)");
|
ASSIMP_LOG_VERBOSE_DEBUG_F(" ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)");
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreXmlSerializer::ReadAnimationTracks(Animation *dest) {
|
void OgreXmlSerializer::ReadAnimationTracks(XmlNode &node, Animation *dest) {
|
||||||
NextNode();
|
for (XmlNode ¤tNode : node.children()) {
|
||||||
|
const std::string currentName = currentNode.name();
|
||||||
|
if (currentName == nnTrack) {
|
||||||
|
VertexAnimationTrack track;
|
||||||
|
track.type = VertexAnimationTrack::VAT_TRANSFORM;
|
||||||
|
track.boneName = ReadAttribute<std::string>(currentNode, "bone");
|
||||||
|
for (XmlNode ¤tChildNode : currentNode.children()) {
|
||||||
|
const std::string currentChildName = currentNode.name();
|
||||||
|
if (currentChildName == nnKeyFrames) {
|
||||||
|
ReadAnimationKeyFrames(currentChildNode, dest, &track);
|
||||||
|
dest->tracks.push_back(track);
|
||||||
|
} else {
|
||||||
|
throw DeadlyImportError(Formatter::format() << "No <keyframes> found in <track> " << dest->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*NextNode();
|
||||||
while (m_currentNodeName == nnTrack) {
|
while (m_currentNodeName == nnTrack) {
|
||||||
VertexAnimationTrack track;
|
VertexAnimationTrack track;
|
||||||
track.type = VertexAnimationTrack::VAT_TRANSFORM;
|
track.type = VertexAnimationTrack::VAT_TRANSFORM;
|
||||||
|
@ -711,13 +859,52 @@ void OgreXmlSerializer::ReadAnimationTracks(Animation *dest) {
|
||||||
ReadAnimationKeyFrames(dest, &track);
|
ReadAnimationKeyFrames(dest, &track);
|
||||||
|
|
||||||
dest->tracks.push_back(track);
|
dest->tracks.push_back(track);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest) {
|
void OgreXmlSerializer::ReadAnimationKeyFrames(XmlNode &node, Animation *anim, VertexAnimationTrack *dest) {
|
||||||
const aiVector3D zeroVec(0.f, 0.f, 0.f);
|
const aiVector3D zeroVec(0.f, 0.f, 0.f);
|
||||||
|
for (XmlNode ¤tNode : node.children()) {
|
||||||
|
const std::string currentName = currentNode.name();
|
||||||
|
if (currentName == nnKeyFrame) {
|
||||||
|
TransformKeyFrame keyframe;
|
||||||
|
keyframe.timePos = ReadAttribute<float>(currentNode, "time");
|
||||||
|
for (XmlNode ¤tChildNode : currentNode.children()) {
|
||||||
|
const std::string currentChildName = currentNode.name();
|
||||||
|
if (currentChildName == nnTranslate) {
|
||||||
|
keyframe.position.x = ReadAttribute<float>(currentChildNode, anX);
|
||||||
|
keyframe.position.y = ReadAttribute<float>(currentChildNode, anY);
|
||||||
|
keyframe.position.z = ReadAttribute<float>(currentChildNode, anZ);
|
||||||
|
} else if (currentChildName == nnRotate) {
|
||||||
|
float angle = ReadAttribute<float>(currentChildNode, "angle");
|
||||||
|
for (XmlNode ¤tChildChildNode : currentNode.children()) {
|
||||||
|
const std::string currentChildChildName = currentNode.name();
|
||||||
|
if (currentChildChildName == nnAxis) {
|
||||||
|
aiVector3D axis;
|
||||||
|
axis.x = ReadAttribute<float>(currentChildChildNode, anX);
|
||||||
|
axis.y = ReadAttribute<float>(currentChildChildNode, anY);
|
||||||
|
axis.z = ReadAttribute<float>(currentChildChildNode, anZ);
|
||||||
|
if (axis.Equal(zeroVec)) {
|
||||||
|
axis.x = 1.0f;
|
||||||
|
if (angle != 0) {
|
||||||
|
ASSIMP_LOG_WARN_F("Found invalid a key frame with a zero rotation axis in animation: ", anim->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyframe.rotation = aiQuaternion(axis, angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (currentChildName == nnScale) {
|
||||||
|
keyframe.scale.x = ReadAttribute<float>(currentChildNode, anX);
|
||||||
|
keyframe.scale.y = ReadAttribute<float>(currentChildNode, anY);
|
||||||
|
keyframe.scale.z = ReadAttribute<float>(currentChildNode, anZ);
|
||||||
|
|
||||||
NextNode();
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dest->transformKeyFrames.push_back(keyframe);
|
||||||
|
}
|
||||||
|
/*NextNode();
|
||||||
while (m_currentNodeName == nnKeyFrame) {
|
while (m_currentNodeName == nnKeyFrame) {
|
||||||
TransformKeyFrame keyframe;
|
TransformKeyFrame keyframe;
|
||||||
keyframe.timePos = ReadAttribute<float>("time");
|
keyframe.timePos = ReadAttribute<float>("time");
|
||||||
|
@ -756,15 +943,33 @@ void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationT
|
||||||
}
|
}
|
||||||
|
|
||||||
dest->transformKeyFrames.push_back(keyframe);
|
dest->transformKeyFrames.push_back(keyframe);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton) {
|
void OgreXmlSerializer::ReadBoneHierarchy(XmlNode &node, Skeleton *skeleton) {
|
||||||
if (skeleton->bones.empty()) {
|
if (skeleton->bones.empty()) {
|
||||||
throw DeadlyImportError("Cannot read <bonehierarchy> for a Skeleton without bones");
|
throw DeadlyImportError("Cannot read <bonehierarchy> for a Skeleton without bones");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (NextNode() == nnBoneParent) {
|
for (XmlNode ¤tNode : node.children()) {
|
||||||
|
const std::string currentName = currentNode.name();
|
||||||
|
if (currentName == nnBoneParent) {
|
||||||
|
const std::string name = ReadAttribute<std::string>(currentNode, "bone");
|
||||||
|
const std::string parentName = ReadAttribute<std::string>(currentNode, "parent");
|
||||||
|
|
||||||
|
Bone *bone = skeleton->BoneByName(name);
|
||||||
|
Bone *parent = skeleton->BoneByName(parentName);
|
||||||
|
|
||||||
|
if (bone && parent) {
|
||||||
|
parent->AddChild(bone);
|
||||||
|
} else {
|
||||||
|
throw DeadlyImportError("Failed to find bones for parenting: Child " + name + " for parent " + parentName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*while (NextNode() == nnBoneParent) {
|
||||||
const std::string name = ReadAttribute<std::string>("bone");
|
const std::string name = ReadAttribute<std::string>("bone");
|
||||||
const std::string parentName = ReadAttribute<std::string>("parent");
|
const std::string parentName = ReadAttribute<std::string>("parent");
|
||||||
|
|
||||||
|
@ -775,7 +980,7 @@ void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton) {
|
||||||
parent->AddChild(bone);
|
parent->AddChild(bone);
|
||||||
else
|
else
|
||||||
throw DeadlyImportError("Failed to find bones for parenting: Child " + name + " for parent " + parentName);
|
throw DeadlyImportError("Failed to find bones for parenting: Child " + name + " for parent " + parentName);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Calculate bone matrices for root bones. Recursively calculates their children.
|
// Calculate bone matrices for root bones. Recursively calculates their children.
|
||||||
for (size_t i = 0, len = skeleton->bones.size(); i < len; ++i) {
|
for (size_t i = 0, len = skeleton->bones.size(); i < len; ++i) {
|
||||||
|
@ -792,9 +997,28 @@ static bool BoneCompare(Bone *a, Bone *b) {
|
||||||
return (a->id < b->id);
|
return (a->id < b->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreXmlSerializer::ReadBones(Skeleton *skeleton) {
|
void OgreXmlSerializer::ReadBones(XmlNode &node, Skeleton *skeleton) {
|
||||||
ASSIMP_LOG_VERBOSE_DEBUG(" - Bones");
|
ASSIMP_LOG_VERBOSE_DEBUG(" - Bones");
|
||||||
|
|
||||||
|
for (XmlNode ¤tNode : node.children()) {
|
||||||
|
const std::string currentName = currentNode.name();
|
||||||
|
if (currentName == nnBone) {
|
||||||
|
Bone *bone = new Bone();
|
||||||
|
bone->id = ReadAttribute<uint16_t>(currentNode, "id");
|
||||||
|
bone->name = ReadAttribute<std::string>(currentNode, "name");
|
||||||
|
for (XmlNode ¤tChildNode : currentNode.children()) {
|
||||||
|
const std::string currentChildName = currentNode.name();
|
||||||
|
if (currentChildName == nnPosition) {
|
||||||
|
bone->position.x = ReadAttribute<float>(currentChildNode, anX);
|
||||||
|
bone->position.y = ReadAttribute<float>(currentChildNode, anY);
|
||||||
|
bone->position.z = ReadAttribute<float>(currentChildNode, anZ);
|
||||||
|
} else if (currentChildName == nnScale) {
|
||||||
|
} else if (currentChildName == nnScale) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NextNode();
|
NextNode();
|
||||||
while (m_currentNodeName == nnBone) {
|
while (m_currentNodeName == nnBone) {
|
||||||
Bone *bone = new Bone();
|
Bone *bone = new Bone();
|
||||||
|
|
|
@ -48,71 +48,70 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "OgreStructs.h"
|
#include "OgreStructs.h"
|
||||||
#include <assimp/XmlParser.h>
|
#include <assimp/XmlParser.h>
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp {
|
||||||
{
|
namespace Ogre {
|
||||||
namespace Ogre
|
|
||||||
{
|
|
||||||
|
|
||||||
typedef irr::io::IrrXMLReader XmlReader;
|
//typedef irr::io::IrrXMLReader XmlReader;
|
||||||
typedef std::shared_ptr<XmlReader> XmlReaderPtr;
|
using XmlParserPtr = std::shared_ptr<XmlParser> ;
|
||||||
|
|
||||||
class OgreXmlSerializer
|
class OgreXmlSerializer {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
/// Imports mesh and returns the result.
|
/// Imports mesh and returns the result.
|
||||||
/** @note Fatal unrecoverable errors will throw a DeadlyImportError. */
|
/** @note Fatal unrecoverable errors will throw a DeadlyImportError. */
|
||||||
static MeshXml *ImportMesh(XmlReader *reader);
|
static MeshXml *ImportMesh(XmlParser *parser);
|
||||||
|
|
||||||
/// Imports skeleton to @c mesh.
|
/// Imports skeleton to @c mesh.
|
||||||
/** If mesh does not have a skeleton reference or the skeleton file
|
/** If mesh does not have a skeleton reference or the skeleton file
|
||||||
cannot be found it is not a fatal DeadlyImportError.
|
cannot be found it is not a fatal DeadlyImportError.
|
||||||
@return If skeleton import was successful. */
|
@return If skeleton import was successful. */
|
||||||
static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh);
|
static bool ImportSkeleton(IOSystem *pIOHandler, MeshXml *mesh);
|
||||||
static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh);
|
static bool ImportSkeleton(IOSystem *pIOHandler, Mesh *mesh);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit OgreXmlSerializer(XmlReader *reader) :
|
explicit OgreXmlSerializer(XmlParser *xmlParser);
|
||||||
m_reader(reader)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static XmlReaderPtr OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename);
|
static XmlParserPtr OpenXmlParser(Assimp::IOSystem *pIOHandler, const std::string &filename);
|
||||||
|
|
||||||
// Mesh
|
// Mesh
|
||||||
void ReadMesh(MeshXml *mesh);
|
void ReadMesh(MeshXml *mesh);
|
||||||
void ReadSubMesh(MeshXml *mesh);
|
void ReadSubMesh(XmlNode &node, MeshXml *mesh);
|
||||||
|
|
||||||
void ReadGeometry(VertexDataXml *dest);
|
void ReadGeometry(XmlNode &node, VertexDataXml *dest);
|
||||||
void ReadGeometryVertexBuffer(VertexDataXml *dest);
|
void ReadGeometryVertexBuffer(XmlNode &node, VertexDataXml *dest);
|
||||||
|
|
||||||
void ReadBoneAssignments(VertexDataXml *dest);
|
void ReadBoneAssignments(XmlNode &node, VertexDataXml *dest);
|
||||||
|
|
||||||
// Skeleton
|
// Skeleton
|
||||||
void ReadSkeleton(Skeleton *skeleton);
|
void ReadSkeleton(XmlNode &node, Skeleton *skeleton);
|
||||||
|
|
||||||
void ReadBones(Skeleton *skeleton);
|
void ReadBones(XmlNode &node, Skeleton *skeleton);
|
||||||
void ReadBoneHierarchy(Skeleton *skeleton);
|
void ReadBoneHierarchy(XmlNode &node, Skeleton *skeleton);
|
||||||
|
|
||||||
void ReadAnimations(Skeleton *skeleton);
|
void ReadAnimations(XmlNode &node, Skeleton *skeleton);
|
||||||
void ReadAnimationTracks(Animation *dest);
|
void ReadAnimationTracks(XmlNode &node, Animation *dest);
|
||||||
void ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest);
|
void ReadAnimationKeyFrames(XmlNode &node, Animation *anim, VertexAnimationTrack *dest);
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
T ReadAttribute(const char *name) const;
|
T ReadAttribute(XmlNode &xmlNode, const char *name) const;
|
||||||
bool HasAttribute(const char *name) const;
|
//bool HasAttribute(const char *name) const;
|
||||||
|
|
||||||
std::string &NextNode();
|
//std::string &NextNode();
|
||||||
std::string &SkipCurrentNode();
|
//std::string &SkipCurrentNode();
|
||||||
|
|
||||||
bool CurrentNodeNameEquals(const std::string &name) const;
|
//bool CurrentNodeNameEquals(const std::string &name) const;
|
||||||
std::string CurrentNodeName(bool forceRead = false);
|
//std::string CurrentNodeName(bool forceRead = false);
|
||||||
|
|
||||||
XmlReader *m_reader;
|
XmlParser *mParser;
|
||||||
std::string m_currentNodeName;
|
std::string m_currentNodeName;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Ogre
|
inline OgreXmlSerializer::OgreXmlSerializer(XmlParser *xmlParser) :
|
||||||
} // Assimp
|
mParser(xmlParser) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Ogre
|
||||||
|
} // namespace Assimp
|
||||||
|
|
||||||
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
|
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
|
||||||
#endif // AI_OGREXMLSERIALIZER_H_INC
|
#endif // AI_OGREXMLSERIALIZER_H_INC
|
||||||
|
|
Loading…
Reference in New Issue