diff --git a/code/X3DExporter.cpp b/code/X3DExporter.cpp index 9e89b5b9e..31a391c47 100644 --- a/code/X3DExporter.cpp +++ b/code/X3DExporter.cpp @@ -140,7 +140,7 @@ void X3DExporter::AttrHelper_Col3DArrToString(const aiColor3D* pArray, const siz AttrHelper_CommaToPoint(pTargetString); } -void X3DExporter::AttrHelper_Color3ToAttrList(std::list pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue) +void X3DExporter::AttrHelper_Color3ToAttrList(std::list& pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue) { string tstr; @@ -150,7 +150,7 @@ string tstr; pList.push_back({pName, tstr}); } -void X3DExporter::AttrHelper_FloatToAttrList(std::list pList, const string& pName, const float pValue, const float pDefaultValue) +void X3DExporter::AttrHelper_FloatToAttrList(std::list& pList, const string& pName, const float pValue, const float pDefaultValue) { string tstr; diff --git a/code/X3DExporter.hpp b/code/X3DExporter.hpp index 20aec951b..bf1e72218 100644 --- a/code/X3DExporter.hpp +++ b/code/X3DExporter.hpp @@ -134,7 +134,7 @@ private: /// \fn void AttrHelper_FloatToAttrList(std::list pList, const std::string& pName, const float pValue, const float pDefaultValue) /// \overload void AttrHelper_Col3DArrToString(const aiColor3D* pArray, const size_t pArray_Size, std::string& pTargetString) - void AttrHelper_FloatToAttrList(std::list pList, const std::string& pName, const float pValue, const float pDefaultValue); + void AttrHelper_FloatToAttrList(std::list &pList, const std::string& pName, const float pValue, const float pDefaultValue); /// \fn void AttrHelper_Color3ToAttrList(std::list pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue) /// Add attribute to list if value not equal to default. @@ -142,7 +142,7 @@ private: /// \param [in] pName - name of new attribute. /// \param [in] pValue - value of the new attribute. /// \param [in] pDefaultValue - default value for checking: if pValue is equal to pDefaultValue then attribute will not be added. - void AttrHelper_Color3ToAttrList(std::list pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue); + void AttrHelper_Color3ToAttrList(std::list &pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue); /// \fn void NodeHelper_OpenNode(const std::string& pNodeName, const size_t pTabLevel, const bool pEmptyElement, const std::list& pAttrList) /// Begin new XML-node element. diff --git a/code/X3DImporter.cpp b/code/X3DImporter.cpp index 7a11e2680..2edb1b081 100644 --- a/code/X3DImporter.cpp +++ b/code/X3DImporter.cpp @@ -74,6 +74,8 @@ const aiImporterDesc X3DImporter::Description = { "x3d" }; +const std::string X3DImporter::whitespace(" ,\t\n\r"); + X3DImporter::X3DImporter() : NodeElement_Cur( nullptr ) , mReader( nullptr ) { @@ -241,7 +243,7 @@ void X3DImporter::XML_CheckNode_MustBeEmpty() void X3DImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName) { - static const size_t Uns_Skip_Len = 190; + static const size_t Uns_Skip_Len = 192; const char* Uns_Skip[ Uns_Skip_Len ] = { // CAD geometry component "CADAssembly", "CADFace", "CADLayer", "CADPart", "IndexedQuadSet", "QuadSet", @@ -276,7 +278,7 @@ void X3DImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeNa // Navigation component "Billboard", "Collision", "LOD", "NavigationInfo", "OrthoViewpoint", "Viewpoint", "ViewpointGroup", // Networking component - "Anchor", "LoadSensor", + "EXPORT", "IMPORT", "Anchor", "LoadSensor", // NURBS component "Contour2D", "ContourPolyline2D", "CoordinateDouble", "NurbsCurve", "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface", "NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", "NurbsSwungSurface", "NurbsTextureCoordinate", @@ -437,43 +439,30 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsVec3f(const int pAttrIdx, aiVector3D void X3DImporter::XML_ReadNode_GetAttrVal_AsListB(const int pAttrIdx, std::list& pValue) { - // make copy of attribute value - string with list of bool values. Also all bool values is strings. - size_t tok_str_len = strlen(mReader->getAttributeValue(pAttrIdx)); - if ( 0 == tok_str_len ) { - Throw_IncorrectAttrValue( mReader->getAttributeName( pAttrIdx ) ); - } + const char *tok_cur = mReader->getAttributeValue(pAttrIdx); + const char *tok_end = tok_cur + strlen(tok_cur); - tok_str_len++;// take in account terminating '\0'. - char *tok_str = new char[tok_str_len]; - - strcpy(tok_str, mReader->getAttributeValue(pAttrIdx)); - // change all spacebars to symbol '\0'. That is needed for parsing. - for(size_t i = 0; i < tok_str_len; i++) + for(;;) { - if(tok_str[i] == ' ') tok_str[i] = 0; - } + while((tok_cur < tok_end) && (whitespace.find_first_of(*tok_cur) != std::string::npos)) tok_cur++;// skip spaces between values. + if (tok_cur >= tok_end) + break; - // at now check what current token is - for(char *tok_cur = tok_str, *tok_end = (tok_str + tok_str_len); tok_cur < tok_end;) - { if(strncmp(tok_cur, "true", 4) == 0) { pValue.push_back(true); - tok_cur += 5;// five, not four. Because '\0' must be skipped too. + tok_cur += 4; } else if(strncmp(tok_cur, "false", 5) == 0) { - pValue.push_back(true); - tok_cur += 6;// six, not five. Because '\0' must be skipped too. + pValue.push_back(false); + tok_cur += 5; } else { Throw_IncorrectAttrValue(mReader->getAttributeName(pAttrIdx)); } - }// for(char* tok_cur = tok_str, tok_end = (tok_str + tok_str_len); tok_cur < tok_end;) - - // delete temporary string - delete [] tok_str; + }// for(;;) } void X3DImporter::XML_ReadNode_GetAttrVal_AsArrB(const int pAttrIdx, std::vector& pValue) @@ -500,11 +489,11 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsListI32(const int pAttrIdx, std::lis int32_t tval32; + while((tstr < tstr_end) && (whitespace.find_first_of(*tstr) != std::string::npos)) tstr++;// skip spaces between values. + tval32 = strtol10(tstr, &ostr); if(ostr == tstr) break; - while((ostr < tstr_end) && (*ostr == ' ')) ostr++;// skip spaces between values. - tstr = ostr; pValue.push_back(tval32); } while(tstr < tstr_end); @@ -529,7 +518,6 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsListF(const int pAttrIdx, std::list< // at first check string values like '.xxx'. ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), str_fixed); - if(!str_fixed.size()) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx)); // and convert all values and place it in list. const char* pstr = str_fixed.c_str(); @@ -539,7 +527,7 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsListF(const int pAttrIdx, std::list< { float tvalf; - while((*pstr == ' ') && (pstr < pstr_end)) pstr++;// skip spaces between values. + while((pstr < pstr_end) && (whitespace.find_first_of(*pstr) != std::string::npos)) pstr++;// skip spaces between values. if(pstr < pstr_end)// additional check, because attribute value can be ended with spaces. { @@ -568,7 +556,6 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsListD(const int pAttrIdx, std::list< // at first check string values like '.xxx'. ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), str_fixed); - if(!str_fixed.size()) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx)); // and convert all values and place it in list. const char* pstr = str_fixed.c_str(); @@ -578,7 +565,7 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsListD(const int pAttrIdx, std::list< { double tvald; - while((*pstr == ' ') && (pstr < pstr_end)) pstr++;// skip spaces between values. + while((pstr < pstr_end) && (whitespace.find_first_of(*pstr) != std::string::npos)) pstr++;// skip spaces between values. if(pstr < pstr_end)// additional check, because attribute value can be ended with spaces. { @@ -1153,35 +1140,36 @@ void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::list if(pNormalPerVertex) { - const std::list* srcidx; - if(pNormalIdx.size() > 0) { // check indices array count. if(pNormalIdx.size() != pCoordIdx.size()) throw DeadlyImportError("Normals and Coords inidces count must be equal."); - srcidx = &pNormalIdx; + tind.reserve(pNormalIdx.size()); + for(std::list::const_iterator it = pNormalIdx.begin(); it != pNormalIdx.end(); it++) + { + if(*it != (-1)) tind.push_back(*it); + } + + // copy normals to mesh + pMesh.mNormals = new aiVector3D[pMesh.mNumVertices]; + for(size_t i = 0; (i < pMesh.mNumVertices) && (i < tind.size()); i++) + { + if(tind[i] >= norm_arr_copy.size()) + throw DeadlyImportError("MeshGeometry_AddNormal. Normal index(" + to_string(tind[i]) + + ") is out of range. Normals count: " + to_string(norm_arr_copy.size()) + "."); + + pMesh.mNormals[i] = norm_arr_copy[tind[i]]; + } } else { - srcidx = &pCoordIdx; - } + if(pNormals.size() != pMesh.mNumVertices) throw DeadlyImportError("MeshGeometry_AddNormal. Normals and vertices count must be equal."); - tind.reserve(srcidx->size()); - for(std::list::const_iterator it = srcidx->begin(); it != srcidx->end(); it++) - { - if(*it != (-1)) tind.push_back(*it); - } - - // copy normals to mesh - pMesh.mNormals = new aiVector3D[pMesh.mNumVertices]; - for(size_t i = 0; (i < pMesh.mNumVertices) && (i < tind.size()); i++) - { - if(tind[i] >= norm_arr_copy.size()) - throw DeadlyImportError("MeshGeometry_AddNormal. Normal index(" + to_string(tind[i]) + - ") is out of range. Normals count: " + to_string(norm_arr_copy.size()) + "."); - - pMesh.mNormals[i] = norm_arr_copy[tind[i]]; + // copy normals to mesh + pMesh.mNormals = new aiVector3D[pMesh.mNumVertices]; + std::list::const_iterator norm_it = pNormals.begin(); + for(size_t i = 0; i < pMesh.mNumVertices; i++) pMesh.mNormals[i] = *norm_it++; } }// if(pNormalPerVertex) else @@ -1679,8 +1667,10 @@ const aiImporterDesc* X3DImporter::GetInfo () const void X3DImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { + mpIOHandler = pIOHandler; + Clear();// delete old graph. - mFileDir = DefaultIOSystem::absolutePath(pFile); + pIOHandler->PushDirectory(DefaultIOSystem::absolutePath(pFile)); ParseFile(pFile, pIOHandler); // // Assimp use static arrays of objects for fast speed of rendering. That's good, but need some additional operations/ diff --git a/code/X3DImporter.hpp b/code/X3DImporter.hpp index 494a44f77..e02d1ab61 100644 --- a/code/X3DImporter.hpp +++ b/code/X3DImporter.hpp @@ -101,7 +101,7 @@ namespace Assimp { /// Navigation component: /// "Billboard", "Collision", "LOD", "NavigationInfo", "OrthoViewpoint", "Viewpoint", "ViewpointGroup" /// Networking component: -/// "Anchor", "LoadSensor" +/// "EXPORT", "IMPORT", "Anchor", "LoadSensor" /// NURBS component: /// "Contour2D", "ContourPolyline2D", "CoordinateDouble", "NurbsCurve", "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface", /// "NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", "NurbsSwungSurface", "NurbsTextureCoordinate", @@ -826,13 +826,14 @@ private: /****************** Constants ******************/ /***********************************************/ static const aiImporterDesc Description; + static const std::string whitespace; /***********************************************/ /****************** Variables ******************/ /***********************************************/ CX3DImporter_NodeElement* NodeElement_Cur;///< Current element. irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object - std::string mFileDir; + IOSystem *mpIOHandler; };// class X3DImporter }// namespace Assimp diff --git a/code/X3DImporter_Networking.cpp b/code/X3DImporter_Networking.cpp index 69987e0ff..9d55900cb 100644 --- a/code/X3DImporter_Networking.cpp +++ b/code/X3DImporter_Networking.cpp @@ -89,12 +89,13 @@ void X3DImporter::ParseNode_Networking_Inline() if(load && (url.size() > 0)) { - DefaultIOSystem io_handler; std::string full_path; - full_path = mFileDir + "/" + url.front(); + full_path = mpIOHandler->CurrentDirectory() + "/" + url.front(); // Attribute "url" can contain list of strings. But we need only one - first. - ParseFile(full_path, &io_handler); + mpIOHandler->PushDirectory(DefaultIOSystem::absolutePath(full_path)); + ParseFile(full_path, mpIOHandler); + mpIOHandler->PopDirectory(); } // check for X3DMetadataObject childs. diff --git a/code/X3DImporter_Rendering.cpp b/code/X3DImporter_Rendering.cpp index a950d3f64..39a493030 100644 --- a/code/X3DImporter_Rendering.cpp +++ b/code/X3DImporter_Rendering.cpp @@ -288,9 +288,46 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleFanSet() ne_alias.CCW = ccw; ne_alias.ColorPerVertex = colorPerVertex; - ne_alias.CoordIndex = index; ne_alias.NormalPerVertex = normalPerVertex; ne_alias.Solid = solid; + + ne_alias.CoordIndex.clear(); + int counter = 0; + int32_t idx[3]; + for(std::list::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++) + { + idx[2] = *idx_it; + if (idx[2] < 0) + { + counter = 0; + } + else + { + if (counter >= 2) + { + if(ccw) + { + ne_alias.CoordIndex.push_back(idx[0]); + ne_alias.CoordIndex.push_back(idx[1]); + ne_alias.CoordIndex.push_back(idx[2]); + } + else + { + ne_alias.CoordIndex.push_back(idx[0]); + ne_alias.CoordIndex.push_back(idx[2]); + ne_alias.CoordIndex.push_back(idx[1]); + } + ne_alias.CoordIndex.push_back(-1); + idx[1] = idx[2]; + } + else + { + idx[counter] = idx[2]; + } + ++counter; + } + }// for(std::list::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++) + // check for child nodes if(!mReader->isEmptyElement()) { @@ -369,9 +406,34 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleSet() ne_alias.CCW = ccw; ne_alias.ColorPerVertex = colorPerVertex; - ne_alias.CoordIndex = index; ne_alias.NormalPerVertex = normalPerVertex; ne_alias.Solid = solid; + + ne_alias.CoordIndex.clear(); + int counter = 0; + int32_t idx[3]; + for(std::list::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++) + { + idx[counter++] = *idx_it; + if (counter > 2) + { + counter = 0; + if(ccw) + { + ne_alias.CoordIndex.push_back(idx[0]); + ne_alias.CoordIndex.push_back(idx[1]); + ne_alias.CoordIndex.push_back(idx[2]); + } + else + { + ne_alias.CoordIndex.push_back(idx[0]); + ne_alias.CoordIndex.push_back(idx[2]); + ne_alias.CoordIndex.push_back(idx[1]); + } + ne_alias.CoordIndex.push_back(-1); + } + }// for(std::list::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++) + // check for child nodes if(!mReader->isEmptyElement()) { @@ -450,9 +512,42 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleStripSet() ne_alias.CCW = ccw; ne_alias.ColorPerVertex = colorPerVertex; - ne_alias.CoordIndex = index; ne_alias.NormalPerVertex = normalPerVertex; ne_alias.Solid = solid; + + ne_alias.CoordIndex.clear(); + int counter = 0; + int32_t idx[3]; + for(std::list::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++) + { + idx[2] = *idx_it; + if (idx[2] < 0) + { + counter = 0; + } + else + { + if (counter >= 2) + { + if(ccw) + { + ne_alias.CoordIndex.push_back(idx[0]); + ne_alias.CoordIndex.push_back(idx[1]); + ne_alias.CoordIndex.push_back(idx[2]); + } + else + { + ne_alias.CoordIndex.push_back(idx[0]); + ne_alias.CoordIndex.push_back(idx[2]); + ne_alias.CoordIndex.push_back(idx[1]); + } + ne_alias.CoordIndex.push_back(-1); + } + idx[counter & 1] = idx[2]; + ++counter; + } + }// for(std::list::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++) + // check for child nodes if(!mReader->isEmptyElement()) {