x3d: migration of goups.
parent
58b81a2590
commit
394651e640
|
@ -234,35 +234,6 @@ inline char_t getFloat(char_t it, char_t end, ai_real &value) {
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Will perform a simple tokenize.
|
|
||||||
* @param str String to tokenize.
|
|
||||||
* @param tokens Array with tokens, will be empty if no token was found.
|
|
||||||
* @param delimiters Delimiter for tokenize.
|
|
||||||
* @return Number of found token.
|
|
||||||
*/
|
|
||||||
template <class string_type>
|
|
||||||
unsigned int tokenize(const string_type &str, std::vector<string_type> &tokens,
|
|
||||||
const string_type &delimiters) {
|
|
||||||
// Skip delimiters at beginning.
|
|
||||||
typename string_type::size_type lastPos = str.find_first_not_of(delimiters, 0);
|
|
||||||
|
|
||||||
// Find first "non-delimiter".
|
|
||||||
typename string_type::size_type pos = str.find_first_of(delimiters, lastPos);
|
|
||||||
while (string_type::npos != pos || string_type::npos != lastPos) {
|
|
||||||
// Found a token, add it to the vector.
|
|
||||||
string_type tmp = str.substr(lastPos, pos - lastPos);
|
|
||||||
if (!tmp.empty() && ' ' != tmp[0])
|
|
||||||
tokens.push_back(tmp);
|
|
||||||
|
|
||||||
// Skip delimiters. Note the "not_of"
|
|
||||||
lastPos = str.find_first_not_of(delimiters, pos);
|
|
||||||
|
|
||||||
// Find next "non-delimiter"
|
|
||||||
pos = str.find_first_of(delimiters, lastPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<unsigned int>(tokens.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class string_type>
|
template <class string_type>
|
||||||
string_type trim_whitespaces(string_type str) {
|
string_type trim_whitespaces(string_type str) {
|
||||||
|
|
|
@ -79,46 +79,7 @@ const aiImporterDesc X3DImporter::Description = {
|
||||||
//const std::regex X3DImporter::pattern_true(R"(^\s*(?:true|1)\s*$)", std::regex::icase);
|
//const std::regex X3DImporter::pattern_true(R"(^\s*(?:true|1)\s*$)", std::regex::icase);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
static void Throw_ArgOutOfRange(const std::string &argument) {
|
|
||||||
throw DeadlyImportError("Argument value is out of range for: \"" + argument + "\".");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Throw_CloseNotFound(const std::string &node) {
|
|
||||||
throw DeadlyImportError("Close tag for node <" + node + "> not found. Seems file is corrupt.");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Throw_ConvertFail_Str2ArrF(const std::string &nodeName, const std::string &pAttrValue) {
|
|
||||||
throw DeadlyImportError("In <" + nodeName + "> failed to convert attribute value \"" + pAttrValue +
|
|
||||||
"\" from string to array of floats.");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Throw_DEF_And_USE(const std::string &nodeName) {
|
|
||||||
throw DeadlyImportError("\"DEF\" and \"USE\" can not be defined both in <" + nodeName + ">.");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) {
|
|
||||||
throw DeadlyImportError("Node <" + nodeName + "> has incorrect attribute \"" + pAttrName + "\".");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) {
|
|
||||||
throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + nodeName + "> has incorrect value.");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) {
|
|
||||||
throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + nodeName + ". Description: " + pDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Throw_TagCountIncorrect(const std::string &pNode) {
|
|
||||||
throw DeadlyImportError("Count of open and close tags for node <" + pNode + "> are not equivalent. Seems file is corrupt.");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Throw_USE_NotFound(const std::string &nodeName, const std::string &pAttrValue) {
|
|
||||||
throw DeadlyImportError("Not found node with name \"" + pAttrValue + "\" in <" + nodeName + ">.");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void LogInfo(const std::string &message) {
|
|
||||||
DefaultLogger::get()->info(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,49 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
|
inline void Throw_ArgOutOfRange(const std::string &argument) {
|
||||||
|
throw DeadlyImportError("Argument value is out of range for: \"" + argument + "\".");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Throw_CloseNotFound(const std::string &node) {
|
||||||
|
throw DeadlyImportError("Close tag for node <" + node + "> not found. Seems file is corrupt.");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Throw_ConvertFail_Str2ArrF(const std::string &nodeName, const std::string &pAttrValue) {
|
||||||
|
throw DeadlyImportError("In <" + nodeName + "> failed to convert attribute value \"" + pAttrValue +
|
||||||
|
"\" from string to array of floats.");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Throw_DEF_And_USE(const std::string &nodeName) {
|
||||||
|
throw DeadlyImportError("\"DEF\" and \"USE\" can not be defined both in <" + nodeName + ">.");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) {
|
||||||
|
throw DeadlyImportError("Node <" + nodeName + "> has incorrect attribute \"" + pAttrName + "\".");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) {
|
||||||
|
throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + nodeName + "> has incorrect value.");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) {
|
||||||
|
throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + nodeName + ". Description: " + pDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Throw_TagCountIncorrect(const std::string &pNode) {
|
||||||
|
throw DeadlyImportError("Count of open and close tags for node <" + pNode + "> are not equivalent. Seems file is corrupt.");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Throw_USE_NotFound(const std::string &nodeName, const std::string &pAttrValue) {
|
||||||
|
throw DeadlyImportError("Not found node with name \"" + pAttrValue + "\" in <" + nodeName + ">.");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void LogInfo(const std::string &message) {
|
||||||
|
DefaultLogger::get()->info(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// \class X3DImporter
|
/// \class X3DImporter
|
||||||
/// Class that holding scene graph which include: groups, geometry, metadata etc.
|
/// Class that holding scene graph which include: groups, geometry, metadata etc.
|
||||||
///
|
///
|
||||||
|
@ -650,19 +693,19 @@ private:
|
||||||
void ParseNode_Grouping_GroupEnd();
|
void ParseNode_Grouping_GroupEnd();
|
||||||
|
|
||||||
/// Parse <StaticGroup> node of the file. And create new node in scene graph.
|
/// Parse <StaticGroup> node of the file. And create new node in scene graph.
|
||||||
void ParseNode_Grouping_StaticGroup();
|
void ParseNode_Grouping_StaticGroup(XmlNode &node);
|
||||||
|
|
||||||
/// Doing actions at an exit from <StaticGroup>. Walk up in scene graph.
|
/// Doing actions at an exit from <StaticGroup>. Walk up in scene graph.
|
||||||
void ParseNode_Grouping_StaticGroupEnd();
|
void ParseNode_Grouping_StaticGroupEnd();
|
||||||
|
|
||||||
/// Parse <Switch> node of the file. And create new node in scene graph.
|
/// Parse <Switch> node of the file. And create new node in scene graph.
|
||||||
void ParseNode_Grouping_Switch();
|
void ParseNode_Grouping_Switch(XmlNode &node);
|
||||||
|
|
||||||
/// Doing actions at an exit from <Switch>. Walk up in scene graph.
|
/// Doing actions at an exit from <Switch>. Walk up in scene graph.
|
||||||
void ParseNode_Grouping_SwitchEnd();
|
void ParseNode_Grouping_SwitchEnd();
|
||||||
|
|
||||||
/// Parse <Transform> node of the file. And create new node in scene graph.
|
/// Parse <Transform> node of the file. And create new node in scene graph.
|
||||||
void ParseNode_Grouping_Transform();
|
void ParseNode_Grouping_Transform(XmlNode &node);
|
||||||
|
|
||||||
/// Doing actions at an exit from <Transform>. Walk up in scene graph.
|
/// Doing actions at an exit from <Transform>. Walk up in scene graph.
|
||||||
void ParseNode_Grouping_TransformEnd();
|
void ParseNode_Grouping_TransformEnd();
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -49,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "X3DImporter.hpp"
|
#include "X3DImporter.hpp"
|
||||||
#include "X3DImporter_Macro.hpp"
|
#include "X3DImporter_Macro.hpp"
|
||||||
|
|
||||||
|
#include <assimp/ParsingUtils.h>
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -65,30 +66,41 @@ namespace Assimp
|
||||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||||
// </Group>
|
// </Group>
|
||||||
// A Group node contains children nodes without introducing a new transformation. It is equivalent to a Transform node containing an identity transform.
|
// A Group node contains children nodes without introducing a new transformation. It is equivalent to a Transform node containing an identity transform.
|
||||||
void X3DImporter::ParseNode_Grouping_Group()
|
void X3DImporter::ParseNode_Grouping_Group(XmlNode &node) {
|
||||||
{
|
//std::string def, use;
|
||||||
std::string def, use;
|
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
std::string def = node.attribute("DEF").as_string();
|
||||||
|
std::string use = node.attribute("USE").as_string();
|
||||||
|
/*MACRO_ATTRREAD_LOOPBEG;
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
MACRO_ATTRREAD_LOOPEND;*/
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
// if "USE" defined then find already defined element.
|
||||||
if(!use.empty())
|
if(!use.empty())
|
||||||
{
|
{
|
||||||
X3DNodeElementBase* ne;
|
X3DNodeElementBase *ne = nullptr;
|
||||||
|
if (def.empty()) {
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
|
Throw_DEF_And_USE(node.name());
|
||||||
}
|
}
|
||||||
else
|
if (!FindNodeElement(use, X3DNodeElementBase::ENET_Group, &ne)) {
|
||||||
{
|
Throw_USE_NotFound(node.name(), use);
|
||||||
|
}
|
||||||
|
mNodeElementCur->Child.push_back(ne);
|
||||||
|
//MACRO_USE_CHECKANDAPPLY(def, use, X3DNodeElementBase::ENET_Group, ne);
|
||||||
|
} else {
|
||||||
ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
|
ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
|
||||||
// at this place new group mode created and made current, so we can name it.
|
|
||||||
if(!def.empty()) mNodeElementCur->ID = def;
|
// at this place new group mode created and made current, so we can name it.
|
||||||
|
if (!def.empty()) {
|
||||||
|
mNodeElementCur->ID = def;
|
||||||
|
}
|
||||||
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
||||||
|
|
||||||
// for empty element exit from node in that place
|
// for empty element exit from node in that place
|
||||||
if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
|
//if(mReader->isEmptyElement())
|
||||||
|
if (node.empty()) {
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
}
|
||||||
}// if(!use.empty()) else
|
}// if(!use.empty()) else
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,20 +123,25 @@ void X3DImporter::ParseNode_Grouping_GroupEnd()
|
||||||
// </StaticGroup>
|
// </StaticGroup>
|
||||||
// The StaticGroup node contains children nodes which cannot be modified. StaticGroup children are guaranteed to not change, send events, receive events or
|
// The StaticGroup node contains children nodes which cannot be modified. StaticGroup children are guaranteed to not change, send events, receive events or
|
||||||
// contain any USE references outside the StaticGroup.
|
// contain any USE references outside the StaticGroup.
|
||||||
void X3DImporter::ParseNode_Grouping_StaticGroup()
|
void X3DImporter::ParseNode_Grouping_StaticGroup(XmlNode &node) {
|
||||||
{
|
// std::string def, use;
|
||||||
std::string def, use;
|
std::string def = node.attribute("DEF").as_string();
|
||||||
|
std::string use = node.attribute("USE").as_string();
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
/* MACRO_ATTRREAD_LOOPBEG;
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
MACRO_ATTRREAD_LOOPEND;*/
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
// if "USE" defined then find already defined element.
|
||||||
if(!use.empty())
|
if(!use.empty())
|
||||||
{
|
{
|
||||||
X3DNodeElementBase* ne;
|
X3DNodeElementBase* ne = nullptr;
|
||||||
|
if (!FindNodeElement(use, X3DNodeElementBase::ENET_Group, &ne)) {
|
||||||
|
Throw_USE_NotFound(node.name(), use);
|
||||||
|
}
|
||||||
|
mNodeElementCur->Child.push_back(ne);
|
||||||
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
|
// MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -134,7 +151,11 @@ void X3DImporter::ParseNode_Grouping_StaticGroup()
|
||||||
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
||||||
|
|
||||||
// for empty element exit from node in that place
|
// for empty element exit from node in that place
|
||||||
if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
|
if (node.empty()) {
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
|
||||||
}// if(!use.empty()) else
|
}// if(!use.empty()) else
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,22 +180,29 @@ void X3DImporter::ParseNode_Grouping_StaticGroupEnd()
|
||||||
// The Switch grouping node traverses zero or one of the nodes specified in the children field. The whichChoice field specifies the index of the child
|
// The Switch grouping node traverses zero or one of the nodes specified in the children field. The whichChoice field specifies the index of the child
|
||||||
// to traverse, with the first child having index 0. If whichChoice is less than zero or greater than the number of nodes in the children field, nothing
|
// to traverse, with the first child having index 0. If whichChoice is less than zero or greater than the number of nodes in the children field, nothing
|
||||||
// is chosen.
|
// is chosen.
|
||||||
void X3DImporter::ParseNode_Grouping_Switch()
|
void X3DImporter::ParseNode_Grouping_Switch(XmlNode &node) {
|
||||||
{
|
// std::string def, use;
|
||||||
std::string def, use;
|
|
||||||
int32_t whichChoice = -1;
|
int32_t whichChoice = -1;
|
||||||
|
std::string def = node.attribute("DEF").as_string();
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
std::string use = node.attribute("USE").as_string();
|
||||||
|
pugi::xml_attribute attr = node.attribute("whichChoise");
|
||||||
|
whichChoice = attr.as_int();
|
||||||
|
/*MACRO_ATTRREAD_LOOPBEG;
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||||
MACRO_ATTRREAD_CHECK_RET("whichChoice", whichChoice, XML_ReadNode_GetAttrVal_AsI32);
|
MACRO_ATTRREAD_CHECK_RET("whichChoice", whichChoice, XML_ReadNode_GetAttrVal_AsI32);
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
MACRO_ATTRREAD_LOOPEND;*/
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
// if "USE" defined then find already defined element.
|
||||||
if(!use.empty())
|
if(!use.empty())
|
||||||
{
|
{
|
||||||
X3DNodeElementBase* ne;
|
X3DNodeElementBase* ne = nullptr;
|
||||||
|
if (!FindNodeElement(use, X3DNodeElementBase::ENET_Group, &ne)) {
|
||||||
|
Throw_USE_NotFound(node.name(), use);
|
||||||
|
}
|
||||||
|
mNodeElementCur->Child.push_back(ne);
|
||||||
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
|
|
||||||
|
// MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -188,16 +216,46 @@ void X3DImporter::ParseNode_Grouping_Switch()
|
||||||
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
||||||
|
|
||||||
// for empty element exit from node in that place
|
// for empty element exit from node in that place
|
||||||
if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
|
// if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
|
||||||
|
if (node.empty()) {
|
||||||
|
ParseHelper_Node_Exit();
|
||||||
|
}
|
||||||
|
|
||||||
}// if(!use.empty()) else
|
}// if(!use.empty()) else
|
||||||
}
|
}
|
||||||
|
|
||||||
void X3DImporter::ParseNode_Grouping_SwitchEnd()
|
void X3DImporter::ParseNode_Grouping_SwitchEnd()
|
||||||
{
|
{
|
||||||
// just exit from node. Defined choice will be accepted at postprocessing stage.
|
// just exit from node. Defined choice will be accepted at post-processing stage.
|
||||||
ParseHelper_Node_Exit();// go up in scene graph
|
ParseHelper_Node_Exit();// go up in scene graph
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ReadAttrAsVec3f(pugi::xml_node &node, const std::string &attrName, aiVector3D &vec) {
|
||||||
|
const pugi::xml_attribute &attr = node.attribute(attrName.c_str());
|
||||||
|
if (attr.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string data = attr.as_string();
|
||||||
|
std::vector<std::string> token;
|
||||||
|
tokenize<std::string>(data, token, " ");
|
||||||
|
vec.x = (ai_real)std::atof(token[0].c_str());
|
||||||
|
vec.y = (ai_real)std::atof(token[1].c_str());
|
||||||
|
vec.z = (ai_real)std::atof(token[2].c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ReadAttrAsFloatArray(pugi::xml_node &node, const std::string &attrName, size_t numComponents, std::vector<float> &tvec) {
|
||||||
|
pugi::xml_attribute attr = node.attribute(attrName.c_str());
|
||||||
|
std::string data = attr.as_string();
|
||||||
|
std::vector<std::string> token;
|
||||||
|
tokenize<std::string>(data, token, " ");
|
||||||
|
if (token.size() != numComponents) throw DeadlyImportError("<Transform>: rotation vector must have 4 elements.");
|
||||||
|
for (size_t i = 0; i < numComponents; ++i) {
|
||||||
|
tvec.push_back((ai_real)std::atof(token[i].c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// <Transform
|
// <Transform
|
||||||
// DEF="" ID
|
// DEF="" ID
|
||||||
// USE="" IDREF
|
// USE="" IDREF
|
||||||
|
@ -220,22 +278,37 @@ void X3DImporter::ParseNode_Grouping_SwitchEnd()
|
||||||
// transformations. In matrix transformation notation, where C (center), SR (scaleOrientation), T (translation), R (rotation), and S (scale) are the
|
// transformations. In matrix transformation notation, where C (center), SR (scaleOrientation), T (translation), R (rotation), and S (scale) are the
|
||||||
// equivalent transformation matrices,
|
// equivalent transformation matrices,
|
||||||
// P' = T * C * R * SR * S * -SR * -C * P
|
// P' = T * C * R * SR * S * -SR * -C * P
|
||||||
void X3DImporter::ParseNode_Grouping_Transform()
|
void X3DImporter::ParseNode_Grouping_Transform(XmlNode &node) {
|
||||||
{
|
|
||||||
aiVector3D center(0, 0, 0);
|
aiVector3D center(0, 0, 0);
|
||||||
float rotation[4] = {0, 0, 1, 0};
|
float rotation[4] = { 0, 0, 1, 0 };
|
||||||
aiVector3D scale(1, 1, 1);// A value of zero indicates that any child geometry shall not be displayed
|
aiVector3D scale(1, 1, 1); // A value of zero indicates that any child geometry shall not be displayed
|
||||||
float scale_orientation[4] = {0, 0, 1, 0};
|
float scale_orientation[4] = { 0, 0, 1, 0 };
|
||||||
aiVector3D translation(0, 0, 0);
|
aiVector3D translation(0, 0, 0);
|
||||||
aiMatrix4x4 matr, tmatr;
|
aiMatrix4x4 matr, tmatr;
|
||||||
std::string use, def;
|
//std::string use, def;
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPBEG;
|
//MACRO_ATTRREAD_LOOPBEG;
|
||||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
std::string def = node.attribute("DEF").as_string();
|
||||||
MACRO_ATTRREAD_CHECK_REF("center", center, XML_ReadNode_GetAttrVal_AsVec3f);
|
std::string use = node.attribute("USE").as_string();
|
||||||
|
|
||||||
|
//MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
|
||||||
|
ReadAttrAsVec3f(node, "center", center);
|
||||||
|
ReadAttrAsVec3f(node, "scale", scale);
|
||||||
|
ReadAttrAsVec3f(node, "translation", translation);
|
||||||
|
/*MACRO_ATTRREAD_CHECK_REF("center", center, XML_ReadNode_GetAttrVal_AsVec3f);
|
||||||
MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsVec3f);
|
MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsVec3f);
|
||||||
MACRO_ATTRREAD_CHECK_REF("translation", translation, XML_ReadNode_GetAttrVal_AsVec3f);
|
MACRO_ATTRREAD_CHECK_REF("translation", translation, XML_ReadNode_GetAttrVal_AsVec3f);*/
|
||||||
if(an == "rotation")
|
if (hasAttribute(node, "rotation")) {
|
||||||
|
std::vector<float> tvec;
|
||||||
|
ReadAttrAsFloatArray(node, "rotation", 4, tvec);
|
||||||
|
memcpy(rotation, tvec.data(), sizeof(rotation));
|
||||||
|
}
|
||||||
|
if (hasAttribute(node, "scaleOrientation")) {
|
||||||
|
std::vector<float> tvec;
|
||||||
|
ReadAttrAsFloatArray(node, "rotation", 4, tvec);
|
||||||
|
::memcpy(scale_orientation, tvec.data(), sizeof(scale_orientation));
|
||||||
|
}
|
||||||
|
/*if(an == "rotation")
|
||||||
{
|
{
|
||||||
std::vector<float> tvec;
|
std::vector<float> tvec;
|
||||||
|
|
||||||
|
@ -247,8 +320,8 @@ void X3DImporter::ParseNode_Grouping_Transform()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(an == "scaleOrientation")
|
if(an == "scaleOrientation"){
|
||||||
{
|
|
||||||
std::vector<float> tvec;
|
std::vector<float> tvec;
|
||||||
XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
|
XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
|
||||||
if ( tvec.size() != 4 )
|
if ( tvec.size() != 4 )
|
||||||
|
@ -261,14 +334,17 @@ void X3DImporter::ParseNode_Grouping_Transform()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
MACRO_ATTRREAD_LOOPEND;
|
MACRO_ATTRREAD_LOOPEND;*/
|
||||||
|
|
||||||
// if "USE" defined then find already defined element.
|
// if "USE" defined then find already defined element.
|
||||||
if(!use.empty())
|
if(!use.empty()) {
|
||||||
{
|
X3DNodeElementBase* ne = nullptr;
|
||||||
X3DNodeElementBase* ne( nullptr );
|
if (!FindNodeElement(use, X3DNodeElementBase::ENET_Group, &ne)) {
|
||||||
|
Throw_USE_NotFound(node.name(), use);
|
||||||
|
}
|
||||||
|
mNodeElementCur->Child.push_back(ne);
|
||||||
|
|
||||||
MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
|
//MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -301,8 +377,7 @@ void X3DImporter::ParseNode_Grouping_Transform()
|
||||||
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
||||||
|
|
||||||
// for empty element exit from node in that place
|
// for empty element exit from node in that place
|
||||||
if ( mReader->isEmptyElement() )
|
if ( node.empty() ) {
|
||||||
{
|
|
||||||
ParseHelper_Node_Exit();
|
ParseHelper_Node_Exit();
|
||||||
}
|
}
|
||||||
}// if(!use.empty()) else
|
}// if(!use.empty()) else
|
||||||
|
|
|
@ -69,15 +69,11 @@ using namespace Assimp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp
|
namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
const char *LogFunctions<XGLImporter>::Prefix() {
|
const char *LogFunctions<XGLImporter>::Prefix() {
|
||||||
<<<<<<< HEAD
|
|
||||||
static auto prefix = "XGL: ";
|
|
||||||
return prefix;
|
|
||||||
=======
|
|
||||||
static auto prefix = "XGL: ";
|
static auto prefix = "XGL: ";
|
||||||
return prefix;
|
return prefix;
|
||||||
>>>>>>> master
|
|
||||||
}
|
}
|
||||||
} // namespace Assimp
|
} // namespace Assimp
|
||||||
|
|
||||||
|
@ -97,13 +93,9 @@ static const aiImporterDesc desc = {
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Constructor to be privately used by Importer
|
// Constructor to be privately used by Importer
|
||||||
XGLImporter::XGLImporter() :
|
XGLImporter::XGLImporter() :
|
||||||
<<<<<<< HEAD
|
mXmlParser(nullptr),
|
||||||
m_xmlParser(nullptr), m_scene(nullptr) {
|
m_scene(nullptr) {
|
||||||
// empty
|
|
||||||
=======
|
|
||||||
m_reader(nullptr), m_scene(nullptr) {
|
|
||||||
// empty
|
// empty
|
||||||
>>>>>>> master
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -115,18 +107,13 @@ XGLImporter::~XGLImporter() {
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Returns whether the class can handle the format of the given file.
|
// Returns whether the class can handle the format of the given file.
|
||||||
bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
|
bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
|
||||||
<<<<<<< HEAD
|
|
||||||
/* NOTE: A simple check for the file extension is not enough
|
/* NOTE: A simple check for the file extension is not enough
|
||||||
=======
|
|
||||||
/* NOTE: A simple check for the file extension is not enough
|
|
||||||
>>>>>>> master
|
|
||||||
* here. XGL and ZGL are ok, but xml is too generic
|
* here. XGL and ZGL are ok, but xml is too generic
|
||||||
* and might be collada as well. So open the file and
|
* and might be collada as well. So open the file and
|
||||||
* look for typical signal tokens.
|
* look for typical signal tokens.
|
||||||
*/
|
*/
|
||||||
const std::string extension = GetExtension(pFile);
|
const std::string extension = GetExtension(pFile);
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
if (extension == "xgl" || extension == "zgl") {
|
if (extension == "xgl" || extension == "zgl") {
|
||||||
return true;
|
return true;
|
||||||
} else if (extension == "xml" || checkSig) {
|
} else if (extension == "xml" || checkSig) {
|
||||||
|
@ -136,42 +123,22 @@ bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
|
||||||
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 3);
|
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 3);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
=======
|
|
||||||
if (extension == "xgl" || extension == "zgl") {
|
|
||||||
return true;
|
|
||||||
} else if (extension == "xml" || checkSig) {
|
|
||||||
ai_assert(pIOHandler != nullptr);
|
|
||||||
|
|
||||||
const char *tokens[] = { "<world>", "<World>", "<WORLD>" };
|
|
||||||
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 3);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
>>>>>>> master
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Get a list of all file extensions which are handled by this class
|
// Get a list of all file extensions which are handled by this class
|
||||||
const aiImporterDesc *XGLImporter::GetInfo() const {
|
const aiImporterDesc *XGLImporter::GetInfo() const {
|
||||||
<<<<<<< HEAD
|
|
||||||
return &desc;
|
return &desc;
|
||||||
=======
|
|
||||||
return &desc;
|
|
||||||
>>>>>>> master
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Imports the given file into the given scene structure.
|
// Imports the given file into the given scene structure.
|
||||||
void XGLImporter::InternReadFile(const std::string &pFile,
|
void XGLImporter::InternReadFile(const std::string &pFile,
|
||||||
<<<<<<< HEAD
|
|
||||||
aiScene *pScene, IOSystem *pIOHandler) {
|
aiScene *pScene, IOSystem *pIOHandler) {
|
||||||
=======
|
|
||||||
aiScene *pScene, IOSystem *pIOHandler) {
|
|
||||||
>>>>>>> master
|
|
||||||
#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
|
#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
|
||||||
std::vector<Bytef> uncompressed;
|
std::vector<Bytef> uncompressed;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
m_scene = pScene;
|
m_scene = pScene;
|
||||||
std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
|
std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
|
||||||
|
|
||||||
|
@ -179,22 +146,12 @@ void XGLImporter::InternReadFile(const std::string &pFile,
|
||||||
if (stream.get() == NULL) {
|
if (stream.get() == NULL) {
|
||||||
throw DeadlyImportError("Failed to open XGL/ZGL file " + pFile + "");
|
throw DeadlyImportError("Failed to open XGL/ZGL file " + pFile + "");
|
||||||
}
|
}
|
||||||
=======
|
|
||||||
m_scene = pScene;
|
|
||||||
std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
|
|
||||||
|
|
||||||
// check whether we can read from the file
|
|
||||||
if (stream.get() == nullptr) {
|
|
||||||
throw DeadlyImportError("Failed to open XGL/ZGL file " + pFile + "");
|
|
||||||
}
|
|
||||||
>>>>>>> master
|
|
||||||
|
|
||||||
// see if its compressed, if so uncompress it
|
// see if its compressed, if so uncompress it
|
||||||
if (GetExtension(pFile) == "zgl") {
|
if (GetExtension(pFile) == "zgl") {
|
||||||
#ifdef ASSIMP_BUILD_NO_COMPRESSED_XGL
|
#ifdef ASSIMP_BUILD_NO_COMPRESSED_XGL
|
||||||
ThrowException("Cannot read ZGL file since Assimp was built without compression support");
|
ThrowException("Cannot read ZGL file since Assimp was built without compression support");
|
||||||
#else
|
#else
|
||||||
<<<<<<< HEAD
|
|
||||||
std::unique_ptr<StreamReaderLE> raw_reader(new StreamReaderLE(stream));
|
std::unique_ptr<StreamReaderLE> raw_reader(new StreamReaderLE(stream));
|
||||||
|
|
||||||
// build a zlib stream
|
// build a zlib stream
|
||||||
|
@ -211,7 +168,7 @@ void XGLImporter::InternReadFile(const std::string &pFile,
|
||||||
raw_reader->IncPtr(2);
|
raw_reader->IncPtr(2);
|
||||||
|
|
||||||
zstream.next_in = reinterpret_cast<Bytef *>(raw_reader->GetPtr());
|
zstream.next_in = reinterpret_cast<Bytef *>(raw_reader->GetPtr());
|
||||||
zstream.avail_in = raw_reader->GetRemainingSize();
|
zstream.avail_in = (uInt) raw_reader->GetRemainingSize();
|
||||||
|
|
||||||
size_t total = 0l;
|
size_t total = 0l;
|
||||||
|
|
||||||
|
@ -245,8 +202,8 @@ void XGLImporter::InternReadFile(const std::string &pFile,
|
||||||
// construct the irrXML parser
|
// construct the irrXML parser
|
||||||
/*CIrrXML_IOStreamReader st(stream.get());
|
/*CIrrXML_IOStreamReader st(stream.get());
|
||||||
m_reader.reset( createIrrXMLReader( ( IFileReadCallBack* ) &st ) );*/
|
m_reader.reset( createIrrXMLReader( ( IFileReadCallBack* ) &st ) );*/
|
||||||
m_xmlParser = new XmlParser;
|
mXmlParser = new XmlParser;
|
||||||
XmlNode *root = m_xmlParser->parse(stream.get());
|
XmlNode *root = mXmlParser->parse(stream.get());
|
||||||
if (nullptr == root) {
|
if (nullptr == root) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -259,69 +216,10 @@ void XGLImporter::InternReadFile(const std::string &pFile,
|
||||||
|
|
||||||
/* while (ReadElement()) {
|
/* while (ReadElement()) {
|
||||||
if (!ASSIMP_stricmp(m_reader->getNodeName(),"world")) {
|
if (!ASSIMP_stricmp(m_reader->getNodeName(),"world")) {
|
||||||
=======
|
|
||||||
std::unique_ptr<StreamReaderLE> raw_reader(new StreamReaderLE(stream));
|
|
||||||
|
|
||||||
// build a zlib stream
|
|
||||||
z_stream zstream;
|
|
||||||
zstream.opaque = Z_NULL;
|
|
||||||
zstream.zalloc = Z_NULL;
|
|
||||||
zstream.zfree = Z_NULL;
|
|
||||||
zstream.data_type = Z_BINARY;
|
|
||||||
|
|
||||||
// raw decompression without a zlib or gzip header
|
|
||||||
inflateInit2(&zstream, -MAX_WBITS);
|
|
||||||
|
|
||||||
// skip two extra bytes, zgl files do carry a crc16 upfront (I think)
|
|
||||||
raw_reader->IncPtr(2);
|
|
||||||
|
|
||||||
zstream.next_in = reinterpret_cast<Bytef *>(raw_reader->GetPtr());
|
|
||||||
zstream.avail_in = (uInt)raw_reader->GetRemainingSize();
|
|
||||||
|
|
||||||
size_t total = 0l;
|
|
||||||
|
|
||||||
// TODO: be smarter about this, decompress directly into heap buffer
|
|
||||||
// and decompress the data .... do 1k chunks in the hope that we won't kill the stack
|
|
||||||
#define MYBLOCK 1024
|
|
||||||
Bytef block[MYBLOCK];
|
|
||||||
int ret;
|
|
||||||
do {
|
|
||||||
zstream.avail_out = MYBLOCK;
|
|
||||||
zstream.next_out = block;
|
|
||||||
ret = inflate(&zstream, Z_NO_FLUSH);
|
|
||||||
|
|
||||||
if (ret != Z_STREAM_END && ret != Z_OK) {
|
|
||||||
ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .XGL file");
|
|
||||||
}
|
|
||||||
const size_t have = MYBLOCK - zstream.avail_out;
|
|
||||||
total += have;
|
|
||||||
uncompressed.resize(total);
|
|
||||||
memcpy(uncompressed.data() + total - have, block, have);
|
|
||||||
} while (ret != Z_STREAM_END);
|
|
||||||
|
|
||||||
// terminate zlib
|
|
||||||
inflateEnd(&zstream);
|
|
||||||
|
|
||||||
// replace the input stream with a memory stream
|
|
||||||
stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t *>(uncompressed.data()), total));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// construct the irrXML parser
|
|
||||||
CIrrXML_IOStreamReader st(stream.get());
|
|
||||||
m_reader.reset(createIrrXMLReader((IFileReadCallBack *)&st));
|
|
||||||
|
|
||||||
// parse the XML file
|
|
||||||
TempScope scope;
|
|
||||||
|
|
||||||
while (ReadElement()) {
|
|
||||||
if (!ASSIMP_stricmp(m_reader->getNodeName(), "world")) {
|
|
||||||
>>>>>>> master
|
|
||||||
ReadWorld(scope);
|
ReadWorld(scope);
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
std::vector<aiMesh *> &meshes = scope.meshes_linear;
|
std::vector<aiMesh *> &meshes = scope.meshes_linear;
|
||||||
std::vector<aiMaterial *> &materials = scope.materials_linear;
|
std::vector<aiMaterial *> &materials = scope.materials_linear;
|
||||||
if (!meshes.size() || !materials.size()) {
|
if (!meshes.size() || !materials.size()) {
|
||||||
|
@ -342,28 +240,6 @@ void XGLImporter::InternReadFile(const std::string &pFile,
|
||||||
m_scene->mNumLights = 1;
|
m_scene->mNumLights = 1;
|
||||||
m_scene->mLights = new aiLight *[1];
|
m_scene->mLights = new aiLight *[1];
|
||||||
m_scene->mLights[0] = scope.light;
|
m_scene->mLights[0] = scope.light;
|
||||||
=======
|
|
||||||
std::vector<aiMesh *> &meshes = scope.meshes_linear;
|
|
||||||
std::vector<aiMaterial *> &materials = scope.materials_linear;
|
|
||||||
if (!meshes.size() || !materials.size()) {
|
|
||||||
ThrowException("failed to extract data from XGL file, no meshes loaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy meshes
|
|
||||||
m_scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
|
|
||||||
m_scene->mMeshes = new aiMesh *[m_scene->mNumMeshes]();
|
|
||||||
std::copy(meshes.begin(), meshes.end(), m_scene->mMeshes);
|
|
||||||
|
|
||||||
// copy materials
|
|
||||||
m_scene->mNumMaterials = static_cast<unsigned int>(materials.size());
|
|
||||||
m_scene->mMaterials = new aiMaterial *[m_scene->mNumMaterials]();
|
|
||||||
std::copy(materials.begin(), materials.end(), m_scene->mMaterials);
|
|
||||||
|
|
||||||
if (scope.light) {
|
|
||||||
m_scene->mNumLights = 1;
|
|
||||||
m_scene->mLights = new aiLight *[1];
|
|
||||||
m_scene->mLights[0] = scope.light;
|
|
||||||
>>>>>>> master
|
|
||||||
|
|
||||||
scope.light->mName = m_scene->mRootNode->mName;
|
scope.light->mName = m_scene->mRootNode->mName;
|
||||||
}
|
}
|
||||||
|
@ -372,7 +248,6 @@ void XGLImporter::InternReadFile(const std::string &pFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
<<<<<<< HEAD
|
|
||||||
void XGLImporter::ReadWorld(TempScope &scope) {
|
void XGLImporter::ReadWorld(TempScope &scope) {
|
||||||
XmlNode *root = m_xmlParser->getRootNode();
|
XmlNode *root = m_xmlParser->getRootNode();
|
||||||
for (XmlNode &node : root->children()) {
|
for (XmlNode &node : root->children()) {
|
||||||
|
@ -549,223 +424,6 @@ aiMatrix4x4 XGLImporter::ReadTrafo(XmlNode &node) {
|
||||||
if (forward.SquareLength() < 1e-4 || up.SquareLength() < 1e-4) {
|
if (forward.SquareLength() < 1e-4 || up.SquareLength() < 1e-4) {
|
||||||
LogError("A direction vector in <transform> is zero, ignoring trafo");
|
LogError("A direction vector in <transform> is zero, ignoring trafo");
|
||||||
return m;
|
return m;
|
||||||
=======
|
|
||||||
bool XGLImporter::ReadElement() {
|
|
||||||
while (m_reader->read()) {
|
|
||||||
if (m_reader->getNodeType() == EXN_ELEMENT) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
bool XGLImporter::ReadElementUpToClosing(const char *closetag) {
|
|
||||||
while (m_reader->read()) {
|
|
||||||
if (m_reader->getNodeType() == EXN_ELEMENT) {
|
|
||||||
return true;
|
|
||||||
} else if (m_reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(m_reader->getNodeName(), closetag)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LogError("unexpected EOF, expected closing <" + std::string(closetag) + "> tag");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
bool XGLImporter::SkipToText() {
|
|
||||||
while (m_reader->read()) {
|
|
||||||
if (m_reader->getNodeType() == EXN_TEXT) {
|
|
||||||
return true;
|
|
||||||
} else if (m_reader->getNodeType() == EXN_ELEMENT || m_reader->getNodeType() == EXN_ELEMENT_END) {
|
|
||||||
ThrowException("expected text contents but found another element (or element end)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
std::string XGLImporter::GetElementName() {
|
|
||||||
const char *s = m_reader->getNodeName();
|
|
||||||
size_t len = strlen(s);
|
|
||||||
|
|
||||||
std::string ret;
|
|
||||||
ret.resize(len);
|
|
||||||
std::transform(s, s + len, ret.begin(), ::ToLower<char>);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
void XGLImporter::ReadWorld(TempScope &scope) {
|
|
||||||
while (ReadElementUpToClosing("world")) {
|
|
||||||
const std::string &s = GetElementName();
|
|
||||||
// XXX right now we'd skip <lighting> if it comes after
|
|
||||||
// <object> or <mesh>
|
|
||||||
if (s == "lighting") {
|
|
||||||
ReadLighting(scope);
|
|
||||||
} else if (s == "object" || s == "mesh" || s == "mat") {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aiNode *const nd = ReadObject(scope, true, "world");
|
|
||||||
if (!nd) {
|
|
||||||
ThrowException("failure reading <world>");
|
|
||||||
}
|
|
||||||
if (!nd->mName.length) {
|
|
||||||
nd->mName.Set("WORLD");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_scene->mRootNode = nd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
void XGLImporter::ReadLighting(TempScope &scope) {
|
|
||||||
while (ReadElementUpToClosing("lighting")) {
|
|
||||||
const std::string &s = GetElementName();
|
|
||||||
if (s == "directionallight") {
|
|
||||||
scope.light = ReadDirectionalLight();
|
|
||||||
} else if (s == "ambient") {
|
|
||||||
LogWarn("ignoring <ambient> tag");
|
|
||||||
} else if (s == "spheremap") {
|
|
||||||
LogWarn("ignoring <spheremap> tag");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
aiLight *XGLImporter::ReadDirectionalLight() {
|
|
||||||
std::unique_ptr<aiLight> l(new aiLight());
|
|
||||||
l->mType = aiLightSource_DIRECTIONAL;
|
|
||||||
|
|
||||||
while (ReadElementUpToClosing("directionallight")) {
|
|
||||||
const std::string &s = GetElementName();
|
|
||||||
if (s == "direction") {
|
|
||||||
l->mDirection = ReadVec3();
|
|
||||||
} else if (s == "diffuse") {
|
|
||||||
l->mColorDiffuse = ReadCol3();
|
|
||||||
} else if (s == "specular") {
|
|
||||||
l->mColorSpecular = ReadCol3();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return l.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
aiNode *XGLImporter::ReadObject(TempScope &scope, bool skipFirst, const char *closetag) {
|
|
||||||
aiNode *nd = new aiNode;
|
|
||||||
std::vector<aiNode *> children;
|
|
||||||
std::vector<unsigned int> meshes;
|
|
||||||
|
|
||||||
try {
|
|
||||||
while (skipFirst || ReadElementUpToClosing(closetag)) {
|
|
||||||
skipFirst = false;
|
|
||||||
|
|
||||||
const std::string &s = GetElementName();
|
|
||||||
if (s == "mesh") {
|
|
||||||
const size_t prev = scope.meshes_linear.size();
|
|
||||||
if (ReadMesh(scope)) {
|
|
||||||
const size_t newc = scope.meshes_linear.size();
|
|
||||||
for (size_t i = 0; i < newc - prev; ++i) {
|
|
||||||
meshes.push_back(static_cast<unsigned int>(i + prev));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (s == "mat") {
|
|
||||||
ReadMaterial(scope);
|
|
||||||
} else if (s == "object") {
|
|
||||||
children.push_back(ReadObject(scope));
|
|
||||||
} else if (s == "objectref") {
|
|
||||||
// XXX
|
|
||||||
} else if (s == "meshref") {
|
|
||||||
const unsigned int id = static_cast<unsigned int>(ReadIndexFromText());
|
|
||||||
|
|
||||||
std::multimap<unsigned int, aiMesh *>::iterator it = scope.meshes.find(id), end = scope.meshes.end();
|
|
||||||
if (it == end) {
|
|
||||||
ThrowException("<meshref> index out of range");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; it != end && (*it).first == id; ++it) {
|
|
||||||
// ok, this is n^2 and should get optimized one day
|
|
||||||
aiMesh *const m = (*it).second;
|
|
||||||
|
|
||||||
unsigned int i = 0, mcount = static_cast<unsigned int>(scope.meshes_linear.size());
|
|
||||||
for (; i < mcount; ++i) {
|
|
||||||
if (scope.meshes_linear[i] == m) {
|
|
||||||
meshes.push_back(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ai_assert(i < mcount);
|
|
||||||
}
|
|
||||||
} else if (s == "transform") {
|
|
||||||
nd->mTransformation = ReadTrafo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (...) {
|
|
||||||
for (aiNode *ch : children) {
|
|
||||||
delete ch;
|
|
||||||
}
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIX: since we used std::multimap<> to keep meshes by id, mesh order now depends on the behaviour
|
|
||||||
// of the multimap implementation with respect to the ordering of entries with same values.
|
|
||||||
// C++11 gives the guarantee that it uses insertion order, before it is implementation-specific.
|
|
||||||
// Sort by material id to always guarantee a deterministic result.
|
|
||||||
std::sort(meshes.begin(), meshes.end(), SortMeshByMaterialId(scope));
|
|
||||||
|
|
||||||
// link meshes to node
|
|
||||||
nd->mNumMeshes = static_cast<unsigned int>(meshes.size());
|
|
||||||
if (nd->mNumMeshes) {
|
|
||||||
nd->mMeshes = new unsigned int[nd->mNumMeshes]();
|
|
||||||
for (unsigned int i = 0; i < nd->mNumMeshes; ++i) {
|
|
||||||
nd->mMeshes[i] = meshes[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// link children to parent
|
|
||||||
nd->mNumChildren = static_cast<unsigned int>(children.size());
|
|
||||||
if (nd->mNumChildren) {
|
|
||||||
nd->mChildren = new aiNode *[nd->mNumChildren]();
|
|
||||||
for (unsigned int i = 0; i < nd->mNumChildren; ++i) {
|
|
||||||
nd->mChildren[i] = children[i];
|
|
||||||
children[i]->mParent = nd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
aiMatrix4x4 XGLImporter::ReadTrafo() {
|
|
||||||
aiVector3D forward, up, right, position;
|
|
||||||
float scale = 1.0f;
|
|
||||||
|
|
||||||
while (ReadElementUpToClosing("transform")) {
|
|
||||||
const std::string &s = GetElementName();
|
|
||||||
if (s == "forward") {
|
|
||||||
forward = ReadVec3();
|
|
||||||
} else if (s == "up") {
|
|
||||||
up = ReadVec3();
|
|
||||||
} else if (s == "position") {
|
|
||||||
position = ReadVec3();
|
|
||||||
}
|
|
||||||
if (s == "scale") {
|
|
||||||
scale = ReadFloat();
|
|
||||||
if (scale < 0.f) {
|
|
||||||
// this is wrong, but we can leave the value and pass it to the caller
|
|
||||||
LogError("found negative scaling in <transform>, ignoring");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aiMatrix4x4 m;
|
|
||||||
if (forward.SquareLength() < 1e-4 || up.SquareLength() < 1e-4) {
|
|
||||||
LogError("A direction vector in <transform> is zero, ignoring trafo");
|
|
||||||
return m;
|
|
||||||
>>>>>>> master
|
|
||||||
}
|
}
|
||||||
|
|
||||||
forward.Normalize();
|
forward.Normalize();
|
||||||
|
@ -804,7 +462,6 @@ aiMatrix4x4 XGLImporter::ReadTrafo() {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) {
|
aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) {
|
||||||
<<<<<<< HEAD
|
|
||||||
std::unique_ptr<aiMesh> mesh(new aiMesh());
|
std::unique_ptr<aiMesh> mesh(new aiMesh());
|
||||||
|
|
||||||
mesh->mNumVertices = static_cast<unsigned int>(m.positions.size());
|
mesh->mNumVertices = static_cast<unsigned int>(m.positions.size());
|
||||||
|
@ -839,40 +496,6 @@ aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ai_assert(idx == mesh->mNumVertices);
|
ai_assert(idx == mesh->mNumVertices);
|
||||||
=======
|
|
||||||
std::unique_ptr<aiMesh> mesh(new aiMesh());
|
|
||||||
|
|
||||||
mesh->mNumVertices = static_cast<unsigned int>(m.positions.size());
|
|
||||||
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
|
||||||
std::copy(m.positions.begin(), m.positions.end(), mesh->mVertices);
|
|
||||||
|
|
||||||
if (m.normals.size()) {
|
|
||||||
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
|
|
||||||
std::copy(m.normals.begin(), m.normals.end(), mesh->mNormals);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m.uvs.size()) {
|
|
||||||
mesh->mNumUVComponents[0] = 2;
|
|
||||||
mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
|
||||||
mesh->mTextureCoords[0][i] = aiVector3D(m.uvs[i].x, m.uvs[i].y, 0.f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh->mNumFaces = static_cast<unsigned int>(m.vcounts.size());
|
|
||||||
mesh->mFaces = new aiFace[m.vcounts.size()];
|
|
||||||
|
|
||||||
unsigned int idx = 0;
|
|
||||||
for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
|
|
||||||
aiFace &f = mesh->mFaces[i];
|
|
||||||
f.mNumIndices = m.vcounts[i];
|
|
||||||
f.mIndices = new unsigned int[f.mNumIndices];
|
|
||||||
for (unsigned int c = 0; c < f.mNumIndices; ++c) {
|
|
||||||
f.mIndices[c] = idx++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>>>>>>> master
|
|
||||||
|
|
||||||
mesh->mPrimitiveTypes = m.pflags;
|
mesh->mPrimitiveTypes = m.pflags;
|
||||||
mesh->mMaterialIndex = m.matid;
|
mesh->mMaterialIndex = m.matid;
|
||||||
|
@ -881,7 +504,6 @@ aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
<<<<<<< HEAD
|
|
||||||
bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) {
|
bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) {
|
||||||
TempMesh t;
|
TempMesh t;
|
||||||
|
|
||||||
|
@ -1009,137 +631,9 @@ unsigned int XGLImporter::ResolveMaterialRef(XmlNode &node, TempScope &scope) {
|
||||||
ReadMaterial(node, scope);
|
ReadMaterial(node, scope);
|
||||||
return static_cast<unsigned int>(scope.materials_linear.size() - 1);
|
return static_cast<unsigned int>(scope.materials_linear.size() - 1);
|
||||||
}
|
}
|
||||||
=======
|
|
||||||
bool XGLImporter::ReadMesh(TempScope &scope) {
|
|
||||||
TempMesh t;
|
|
||||||
|
|
||||||
std::map<unsigned int, TempMaterialMesh> bymat;
|
|
||||||
const unsigned int mesh_id = ReadIDAttr();
|
|
||||||
|
|
||||||
while (ReadElementUpToClosing("mesh")) {
|
|
||||||
const std::string &s = GetElementName();
|
|
||||||
|
|
||||||
if (s == "mat") {
|
|
||||||
ReadMaterial(scope);
|
|
||||||
} else if (s == "p") {
|
|
||||||
if (!m_reader->getAttributeValue("ID")) {
|
|
||||||
LogWarn("no ID attribute on <p>, ignoring");
|
|
||||||
} else {
|
|
||||||
int id = m_reader->getAttributeValueAsInt("ID");
|
|
||||||
t.points[id] = ReadVec3();
|
|
||||||
}
|
|
||||||
} else if (s == "n") {
|
|
||||||
if (!m_reader->getAttributeValue("ID")) {
|
|
||||||
LogWarn("no ID attribute on <n>, ignoring");
|
|
||||||
} else {
|
|
||||||
int id = m_reader->getAttributeValueAsInt("ID");
|
|
||||||
t.normals[id] = ReadVec3();
|
|
||||||
}
|
|
||||||
} else if (s == "tc") {
|
|
||||||
if (!m_reader->getAttributeValue("ID")) {
|
|
||||||
LogWarn("no ID attribute on <tc>, ignoring");
|
|
||||||
} else {
|
|
||||||
int id = m_reader->getAttributeValueAsInt("ID");
|
|
||||||
t.uvs[id] = ReadVec2();
|
|
||||||
}
|
|
||||||
} else if (s == "f" || s == "l" || s == "p") {
|
|
||||||
const unsigned int vcount = s == "f" ? 3 : (s == "l" ? 2 : 1);
|
|
||||||
|
|
||||||
unsigned int mid = ~0u;
|
|
||||||
TempFace tf[3];
|
|
||||||
bool has[3] = { 0 };
|
|
||||||
|
|
||||||
while (ReadElementUpToClosing(s.c_str())) {
|
|
||||||
const std::string &elemName = GetElementName();
|
|
||||||
if (elemName == "fv1" || elemName == "lv1" || elemName == "pv1") {
|
|
||||||
ReadFaceVertex(t, tf[0]);
|
|
||||||
has[0] = true;
|
|
||||||
} else if (elemName == "fv2" || elemName == "lv2") {
|
|
||||||
ReadFaceVertex(t, tf[1]);
|
|
||||||
has[1] = true;
|
|
||||||
} else if (elemName == "fv3") {
|
|
||||||
ReadFaceVertex(t, tf[2]);
|
|
||||||
has[2] = true;
|
|
||||||
} else if (elemName == "mat") {
|
|
||||||
if (mid != ~0u) {
|
|
||||||
LogWarn("only one material tag allowed per <f>");
|
|
||||||
}
|
|
||||||
mid = ResolveMaterialRef(scope);
|
|
||||||
} else if (elemName == "matref") {
|
|
||||||
if (mid != ~0u) {
|
|
||||||
LogWarn("only one material tag allowed per <f>");
|
|
||||||
}
|
|
||||||
mid = ResolveMaterialRef(scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mid == ~0u) {
|
|
||||||
ThrowException("missing material index");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nor = false;
|
|
||||||
bool uv = false;
|
|
||||||
for (unsigned int i = 0; i < vcount; ++i) {
|
|
||||||
if (!has[i]) {
|
|
||||||
ThrowException("missing face vertex data");
|
|
||||||
}
|
|
||||||
|
|
||||||
nor = nor || tf[i].has_normal;
|
|
||||||
uv = uv || tf[i].has_uv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mid >= (1 << 30)) {
|
|
||||||
LogWarn("material indices exhausted, this may cause errors in the output");
|
|
||||||
}
|
|
||||||
unsigned int meshId = mid | ((nor ? 1 : 0) << 31) | ((uv ? 1 : 0) << 30);
|
|
||||||
|
|
||||||
TempMaterialMesh &mesh = bymat[meshId];
|
|
||||||
mesh.matid = mid;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < vcount; ++i) {
|
|
||||||
mesh.positions.push_back(tf[i].pos);
|
|
||||||
if (nor) {
|
|
||||||
mesh.normals.push_back(tf[i].normal);
|
|
||||||
}
|
|
||||||
if (uv) {
|
|
||||||
mesh.uvs.push_back(tf[i].uv);
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh.pflags |= 1 << (vcount - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh.vcounts.push_back(vcount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// finally extract output meshes and add them to the scope
|
|
||||||
typedef std::pair<const unsigned int, TempMaterialMesh> pairt;
|
|
||||||
for (const pairt &p : bymat) {
|
|
||||||
aiMesh *const m = ToOutputMesh(p.second);
|
|
||||||
scope.meshes_linear.push_back(m);
|
|
||||||
|
|
||||||
// if this is a definition, keep it on the stack
|
|
||||||
if (mesh_id != ~0u) {
|
|
||||||
scope.meshes.insert(std::pair<unsigned int, aiMesh *>(mesh_id, m));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// no id == not a reference, insert this mesh right *here*
|
|
||||||
return mesh_id == ~0u;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------------
|
|
||||||
unsigned int XGLImporter::ResolveMaterialRef(TempScope &scope) {
|
|
||||||
const std::string &s = GetElementName();
|
|
||||||
if (s == "mat") {
|
|
||||||
ReadMaterial(scope);
|
|
||||||
return static_cast<unsigned int>(scope.materials_linear.size() - 1);
|
|
||||||
}
|
|
||||||
>>>>>>> master
|
|
||||||
|
|
||||||
const int id = ReadIndexFromText(node);
|
const int id = ReadIndexFromText(node);
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
std::map<unsigned int, aiMaterial *>::iterator it = scope.materials.find(id), end = scope.materials.end();
|
std::map<unsigned int, aiMaterial *>::iterator it = scope.materials.find(id), end = scope.materials.end();
|
||||||
if (it == end) {
|
if (it == end) {
|
||||||
ThrowException("<matref> index out of range");
|
ThrowException("<matref> index out of range");
|
||||||
|
@ -1156,28 +650,11 @@ unsigned int XGLImporter::ResolveMaterialRef(TempScope &scope) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ai_assert(false);
|
ai_assert(false);
|
||||||
=======
|
|
||||||
std::map<unsigned int, aiMaterial *>::iterator it = scope.materials.find(id), end = scope.materials.end();
|
|
||||||
if (it == end) {
|
|
||||||
ThrowException("<matref> index out of range");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ok, this is n^2 and should get optimized one day
|
|
||||||
aiMaterial *const m = (*it).second;
|
|
||||||
|
|
||||||
unsigned int i = 0, mcount = static_cast<unsigned int>(scope.materials_linear.size());
|
|
||||||
for (; i < mcount; ++i) {
|
|
||||||
if (scope.materials_linear[i] == m) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>>>>>>> master
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
<<<<<<< HEAD
|
|
||||||
void XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) {
|
void XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) {
|
||||||
const unsigned int mat_id = ReadIDAttr(node);
|
const unsigned int mat_id = ReadIDAttr(node);
|
||||||
|
|
||||||
|
@ -1326,178 +803,11 @@ aiVector2D XGLImporter::ReadVec2(XmlNode &node) {
|
||||||
}
|
}
|
||||||
vec.x = v[0];
|
vec.x = v[0];
|
||||||
vec.y = v[1];
|
vec.y = v[1];
|
||||||
=======
|
|
||||||
void XGLImporter::ReadMaterial(TempScope &scope) {
|
|
||||||
const unsigned int mat_id = ReadIDAttr();
|
|
||||||
|
|
||||||
aiMaterial *mat(new aiMaterial);
|
|
||||||
while (ReadElementUpToClosing("mat")) {
|
|
||||||
const std::string &s = GetElementName();
|
|
||||||
if (s == "amb") {
|
|
||||||
const aiColor3D c = ReadCol3();
|
|
||||||
mat->AddProperty(&c, 1, AI_MATKEY_COLOR_AMBIENT);
|
|
||||||
} else if (s == "diff") {
|
|
||||||
const aiColor3D c = ReadCol3();
|
|
||||||
mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE);
|
|
||||||
} else if (s == "spec") {
|
|
||||||
const aiColor3D c = ReadCol3();
|
|
||||||
mat->AddProperty(&c, 1, AI_MATKEY_COLOR_SPECULAR);
|
|
||||||
} else if (s == "emiss") {
|
|
||||||
const aiColor3D c = ReadCol3();
|
|
||||||
mat->AddProperty(&c, 1, AI_MATKEY_COLOR_EMISSIVE);
|
|
||||||
} else if (s == "alpha") {
|
|
||||||
const float f = ReadFloat();
|
|
||||||
mat->AddProperty(&f, 1, AI_MATKEY_OPACITY);
|
|
||||||
} else if (s == "shine") {
|
|
||||||
const float f = ReadFloat();
|
|
||||||
mat->AddProperty(&f, 1, AI_MATKEY_SHININESS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scope.materials[mat_id] = mat;
|
|
||||||
scope.materials_linear.push_back(mat);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------------
|
|
||||||
void XGLImporter::ReadFaceVertex(const TempMesh &t, TempFace &out) {
|
|
||||||
const std::string &end = GetElementName();
|
|
||||||
|
|
||||||
bool havep = false;
|
|
||||||
while (ReadElementUpToClosing(end.c_str())) {
|
|
||||||
const std::string &s = GetElementName();
|
|
||||||
if (s == "pref") {
|
|
||||||
const unsigned int id = ReadIndexFromText();
|
|
||||||
std::map<unsigned int, aiVector3D>::const_iterator it = t.points.find(id);
|
|
||||||
if (it == t.points.end()) {
|
|
||||||
ThrowException("point index out of range");
|
|
||||||
}
|
|
||||||
|
|
||||||
out.pos = (*it).second;
|
|
||||||
havep = true;
|
|
||||||
} else if (s == "nref") {
|
|
||||||
const unsigned int id = ReadIndexFromText();
|
|
||||||
std::map<unsigned int, aiVector3D>::const_iterator it = t.normals.find(id);
|
|
||||||
if (it == t.normals.end()) {
|
|
||||||
ThrowException("normal index out of range");
|
|
||||||
}
|
|
||||||
|
|
||||||
out.normal = (*it).second;
|
|
||||||
out.has_normal = true;
|
|
||||||
} else if (s == "tcref") {
|
|
||||||
const unsigned int id = ReadIndexFromText();
|
|
||||||
std::map<unsigned int, aiVector2D>::const_iterator it = t.uvs.find(id);
|
|
||||||
if (it == t.uvs.end()) {
|
|
||||||
ThrowException("uv index out of range");
|
|
||||||
}
|
|
||||||
|
|
||||||
out.uv = (*it).second;
|
|
||||||
out.has_uv = true;
|
|
||||||
} else if (s == "p") {
|
|
||||||
out.pos = ReadVec3();
|
|
||||||
} else if (s == "n") {
|
|
||||||
out.normal = ReadVec3();
|
|
||||||
} else if (s == "tc") {
|
|
||||||
out.uv = ReadVec2();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!havep) {
|
|
||||||
ThrowException("missing <pref> in <fvN> element");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
unsigned int XGLImporter::ReadIDAttr() {
|
|
||||||
for (int i = 0, e = m_reader->getAttributeCount(); i < e; ++i) {
|
|
||||||
|
|
||||||
if (!ASSIMP_stricmp(m_reader->getAttributeName(i), "id")) {
|
|
||||||
return m_reader->getAttributeValueAsInt(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ~0u;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
float XGLImporter::ReadFloat() {
|
|
||||||
if (!SkipToText()) {
|
|
||||||
LogError("unexpected EOF reading float element contents");
|
|
||||||
return 0.f;
|
|
||||||
}
|
|
||||||
const char *s = m_reader->getNodeData(), *se;
|
|
||||||
|
|
||||||
if (!SkipSpaces(&s)) {
|
|
||||||
LogError("unexpected EOL, failed to parse float");
|
|
||||||
return 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float t;
|
|
||||||
se = fast_atoreal_move(s, t);
|
|
||||||
|
|
||||||
if (se == s) {
|
|
||||||
LogError("failed to read float text");
|
|
||||||
return 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
unsigned int XGLImporter::ReadIndexFromText() {
|
|
||||||
if (!SkipToText()) {
|
|
||||||
LogError("unexpected EOF reading index element contents");
|
|
||||||
return ~0u;
|
|
||||||
}
|
|
||||||
const char *s = m_reader->getNodeData(), *se;
|
|
||||||
if (!SkipSpaces(&s)) {
|
|
||||||
LogError("unexpected EOL, failed to parse index element");
|
|
||||||
return ~0u;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned int t = strtoul10(s, &se);
|
|
||||||
|
|
||||||
if (se == s) {
|
|
||||||
LogError("failed to read index");
|
|
||||||
return ~0u;
|
|
||||||
}
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
aiVector2D XGLImporter::ReadVec2() {
|
|
||||||
aiVector2D vec;
|
|
||||||
|
|
||||||
if (!SkipToText()) {
|
|
||||||
LogError("unexpected EOF reading vec2 contents");
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
const char *s = m_reader->getNodeData();
|
|
||||||
|
|
||||||
ai_real v[2];
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
|
||||||
if (!SkipSpaces(&s)) {
|
|
||||||
LogError("unexpected EOL, failed to parse vec2");
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
v[i] = fast_atof(&s);
|
|
||||||
|
|
||||||
SkipSpaces(&s);
|
|
||||||
if (i != 1 && *s != ',') {
|
|
||||||
LogError("expected comma, failed to parse vec2");
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
vec.x = v[0];
|
|
||||||
vec.y = v[1];
|
|
||||||
>>>>>>> master
|
|
||||||
|
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
<<<<<<< HEAD
|
|
||||||
aiVector3D XGLImporter::ReadVec3(XmlNode &node) {
|
aiVector3D XGLImporter::ReadVec3(XmlNode &node) {
|
||||||
aiVector3D vec;
|
aiVector3D vec;
|
||||||
const char *s = node.value();
|
const char *s = node.value();
|
||||||
|
@ -1526,42 +836,6 @@ aiColor3D XGLImporter::ReadCol3(XmlNode &node) {
|
||||||
LogWarn("color values out of range, ignoring");
|
LogWarn("color values out of range, ignoring");
|
||||||
}
|
}
|
||||||
return aiColor3D(v.x, v.y, v.z);
|
return aiColor3D(v.x, v.y, v.z);
|
||||||
=======
|
|
||||||
aiVector3D XGLImporter::ReadVec3() {
|
|
||||||
aiVector3D vec;
|
|
||||||
|
|
||||||
if (!SkipToText()) {
|
|
||||||
LogError("unexpected EOF reading vec3 contents");
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
const char *s = m_reader->getNodeData();
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
if (!SkipSpaces(&s)) {
|
|
||||||
LogError("unexpected EOL, failed to parse vec3");
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
vec[i] = fast_atof(&s);
|
|
||||||
|
|
||||||
SkipSpaces(&s);
|
|
||||||
if (i != 2 && *s != ',') {
|
|
||||||
LogError("expected comma, failed to parse vec3");
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
aiColor3D XGLImporter::ReadCol3() {
|
|
||||||
const aiVector3D &v = ReadVec3();
|
|
||||||
if (v.x < 0.f || v.x > 1.0f || v.y < 0.f || v.y > 1.0f || v.z < 0.f || v.z > 1.0f) {
|
|
||||||
LogWarn("color values out of range, ignoring");
|
|
||||||
}
|
|
||||||
return aiColor3D(v.x, v.y, v.z);
|
|
||||||
>>>>>>> master
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -55,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/mesh.h>
|
#include <assimp/mesh.h>
|
||||||
#include <assimp/light.h>
|
#include <assimp/light.h>
|
||||||
#include <assimp/Importer.hpp>
|
#include <assimp/Importer.hpp>
|
||||||
|
#include <assimp/XmlParser.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -191,7 +191,8 @@ private:
|
||||||
unsigned int ResolveMaterialRef(TempScope &scope);
|
unsigned int ResolveMaterialRef(TempScope &scope);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<irr::io::IrrXMLReader> m_reader;
|
//std::shared_ptr<irr::io::IrrXMLReader> m_reader;
|
||||||
|
XmlParser *mXmlParser;
|
||||||
aiScene *m_scene;
|
aiScene *m_scene;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,37 @@ std::string GetNextToken(const char*& in) {
|
||||||
return std::string(cur,(size_t)(in-cur));
|
return std::string(cur,(size_t)(in-cur));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
/** @brief Will perform a simple tokenize.
|
||||||
|
* @param str String to tokenize.
|
||||||
|
* @param tokens Array with tokens, will be empty if no token was found.
|
||||||
|
* @param delimiters Delimiter for tokenize.
|
||||||
|
* @return Number of found token.
|
||||||
|
*/
|
||||||
|
template <class string_type>
|
||||||
|
AI_FORCE_INLINE unsigned int tokenize(const string_type &str, std::vector<string_type> &tokens,
|
||||||
|
const string_type &delimiters) {
|
||||||
|
// Skip delimiters at beginning.
|
||||||
|
typename string_type::size_type lastPos = str.find_first_not_of(delimiters, 0);
|
||||||
|
|
||||||
|
// Find first "non-delimiter".
|
||||||
|
typename string_type::size_type pos = str.find_first_of(delimiters, lastPos);
|
||||||
|
while (string_type::npos != pos || string_type::npos != lastPos) {
|
||||||
|
// Found a token, add it to the vector.
|
||||||
|
string_type tmp = str.substr(lastPos, pos - lastPos);
|
||||||
|
if (!tmp.empty() && ' ' != tmp[0])
|
||||||
|
tokens.push_back(tmp);
|
||||||
|
|
||||||
|
// Skip delimiters. Note the "not_of"
|
||||||
|
lastPos = str.find_first_not_of(delimiters, pos);
|
||||||
|
|
||||||
|
// Find next "non-delimiter"
|
||||||
|
pos = str.find_first_of(delimiters, lastPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<unsigned int>(tokens.size());
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
} // ! namespace Assimp
|
} // ! namespace Assimp
|
||||||
|
|
Loading…
Reference in New Issue