void OgreXmlSerializer::ReadMesh(MeshXml *mesh) { if (NextNode() != nnMesh) { throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <mesh>"); } DefaultLogger::get()->debug("Reading Mesh"); NextNode(); // Root level nodes while(m_currentNodeName == nnSharedGeometry || m_currentNodeName == nnSubMeshes || m_currentNodeName == nnSkeletonLink || m_currentNodeName == nnBoneAssignments || m_currentNodeName == nnLOD || m_currentNodeName == nnSubMeshNames || m_currentNodeName == nnExtremes || m_currentNodeName == nnPoses || m_currentNodeName == nnAnimations) { if (m_currentNodeName == nnSharedGeometry) { mesh->sharedVertexData = new VertexDataXml(); ReadGeometry(mesh->sharedVertexData); } else if (m_currentNodeName == nnSubMeshes) { NextNode(); while(m_currentNodeName == nnSubMesh) { ReadSubMesh(mesh); } } else if (m_currentNodeName == nnBoneAssignments) { ReadBoneAssignments(mesh->sharedVertexData); } else if (m_currentNodeName == nnSkeletonLink) { mesh->skeletonRef = ReadAttribute<std::string>("name"); DefaultLogger::get()->debug("Read skeleton link " + mesh->skeletonRef); NextNode(); } // Assimp incompatible/ignored nodes else SkipCurrentNode(); } }
void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler) { // Open source file IOStream *f = pIOHandler->Open(pFile, "rb"); if (!f) { throw DeadlyImportError("Failed to open file " + pFile); } // Binary .mesh import if (EndsWith(pFile, ".mesh", false)) { /// @note MemoryStreamReader takes ownership of f. MemoryStreamReader reader(f); // Import mesh boost::scoped_ptr<Mesh> mesh(OgreBinarySerializer::ImportMesh(&reader)); // Import skeleton OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh.get()); // Import mesh referenced materials ReadMaterials(pFile, pIOHandler, pScene, mesh.get()); // Convert to Assimp mesh->ConvertToAssimpScene(pScene); } // XML .mesh.xml import else { /// @note XmlReader does not take ownership of f, hence the scoped ptr. boost::scoped_ptr<IOStream> scopedFile(f); boost::scoped_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(scopedFile.get())); boost::scoped_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get())); // Import mesh boost::scoped_ptr<MeshXml> mesh(OgreXmlSerializer::ImportMesh(reader.get())); // Import skeleton OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh.get()); // Import mesh referenced materials ReadMaterials(pFile, pIOHandler, pScene, mesh.get()); // Convert to Assimp mesh->ConvertToAssimpScene(pScene); } }
void OgreXmlSerializer::ReadAnimationTracks(Animation *dest) { NextNode(); while(m_currentNodeName == nnTrack) { VertexAnimationTrack track; track.type = VertexAnimationTrack::VAT_TRANSFORM; track.boneName = ReadAttribute<std::string>("bone"); if (NextNode() != nnKeyFrames) { throw DeadlyImportError(Formatter::format() << "No <keyframes> found in <track> " << dest->name); } ReadAnimationKeyFrames(dest, &track); dest->tracks.push_back(track); } }
void OgreXmlSerializer::ReadBones(Skeleton *skeleton) { DefaultLogger::get()->debug(" - Bones"); NextNode(); while(m_currentNodeName == nnBone) { Bone *bone = new Bone(); bone->id = ReadAttribute<uint16_t>("id"); bone->name = ReadAttribute<std::string>("name"); NextNode(); while(m_currentNodeName == nnPosition || m_currentNodeName == nnRotation || m_currentNodeName == nnScale) { if (m_currentNodeName == nnPosition) { bone->position.x = ReadAttribute<float>(anX); bone->position.y = ReadAttribute<float>(anY); bone->position.z = ReadAttribute<float>(anZ); } else if (m_currentNodeName == nnRotation) { float angle = ReadAttribute<float>("angle"); if (NextNode() != nnAxis) { throw DeadlyImportError(Formatter::format() << "No axis specified for bone rotation in bone " << bone->id); } aiVector3D axis; axis.x = ReadAttribute<float>(anX); axis.y = ReadAttribute<float>(anY); axis.z = ReadAttribute<float>(anZ); bone->rotation = aiQuaternion(axis, angle); } else if (m_currentNodeName == nnScale) { /// @todo Implement taking scale into account in matrix/pose calculations! if (HasAttribute("factor")) { float factor = ReadAttribute<float>("factor"); bone->scale.Set(factor, factor, factor); } else { if (HasAttribute(anX)) bone->scale.x = ReadAttribute<float>(anX); if (HasAttribute(anY)) bone->scale.y = ReadAttribute<float>(anY); if (HasAttribute(anZ)) bone->scale.z = ReadAttribute<float>(anZ); } } NextNode(); } skeleton->bones.push_back(bone); } // Order bones by Id std::sort(skeleton->bones.begin(), skeleton->bones.end(), BoneCompare); // Validate that bone indexes are not skipped. /** @note Left this from original authors code, but not sure if this is strictly necessary as per the Ogre skeleton spec. It might be more that other (later) code in this imported does not break. */ for (size_t i=0, len=skeleton->bones.size(); i<len; ++i) { Bone *b = skeleton->bones[i]; DefaultLogger::get()->debug(Formatter::format() << " " << b->id << " " << b->name); if (b->id != static_cast<uint16_t>(i)) { throw DeadlyImportError(Formatter::format() << "Bone ids are not in sequence starting from 0. Missing index " << i); } } }
void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) { static const std::string anMaterial = "material"; static const std::string anUseSharedVertices = "usesharedvertices"; static const std::string anCount = "count"; static const std::string anV1 = "v1"; static const std::string anV2 = "v2"; static const std::string anV3 = "v3"; static const std::string anV4 = "v4"; SubMeshXml* submesh = new SubMeshXml(); if (HasAttribute(anMaterial)) { submesh->materialRef = ReadAttribute<std::string>(anMaterial); } if (HasAttribute(anUseSharedVertices)) { submesh->usesSharedVertexData = ReadAttribute<bool>(anUseSharedVertices); } DefaultLogger::get()->debug(Formatter::format() << "Reading SubMesh " << mesh->subMeshes.size()); DefaultLogger::get()->debug(Formatter::format() << " - Material: '" << submesh->materialRef << "'"); DefaultLogger::get()->debug(Formatter::format() << " - Uses shared geometry: " << (submesh->usesSharedVertexData ? "true" : "false")); // TODO: maybe we have always just 1 faces and 1 geometry and always in this order. this loop will only work correct, when the order // of faces and geometry changed, and not if we have more than one of one /// @todo Fix above comment with better read logic below bool quadWarned = false; NextNode(); while(m_currentNodeName == nnFaces || m_currentNodeName == nnGeometry || m_currentNodeName == nnTextures || m_currentNodeName == nnBoneAssignments) { if (m_currentNodeName == nnFaces) { submesh->indexData->faceCount = ReadAttribute<uint32_t>(anCount); submesh->indexData->faces.reserve(submesh->indexData->faceCount); NextNode(); while(m_currentNodeName == nnFace) { aiFace face; face.mNumIndices = 3; face.mIndices = new unsigned int[3]; face.mIndices[0] = ReadAttribute<uint32_t>(anV1); face.mIndices[1] = ReadAttribute<uint32_t>(anV2); face.mIndices[2] = ReadAttribute<uint32_t>(anV3); /// @todo Support quads if Ogre even supports them in XML (I'm not sure but I doubt it) if (!quadWarned && HasAttribute(anV4)) { DefaultLogger::get()->warn("Submesh <face> has quads with <v4>, only triangles are supported at the moment!"); quadWarned = true; } submesh->indexData->faces.push_back(face); // Advance NextNode(); } if (submesh->indexData->faces.size() == submesh->indexData->faceCount) { DefaultLogger::get()->debug(Formatter::format() << " - 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 (m_currentNodeName == nnGeometry) { if (submesh->usesSharedVertexData) { throw DeadlyImportError("Found <geometry> in <submesh> when use shared geometry is true. Invalid mesh file."); } submesh->vertexData = new VertexDataXml(); ReadGeometry(submesh->vertexData); } else if (m_currentNodeName == nnBoneAssignments) { ReadBoneAssignments(submesh->vertexData); } // Assimp incompatible/ignored nodes else SkipCurrentNode(); } submesh->index = mesh->subMeshes.size(); mesh->subMeshes.push_back(submesh); }
void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) { bool positions = (HasAttribute("positions") && ReadAttribute<bool>("positions")); bool normals = (HasAttribute("normals") && ReadAttribute<bool>("normals")); bool tangents = (HasAttribute("tangents") && ReadAttribute<bool>("tangents")); uint32_t uvs = (HasAttribute("texture_coords") ? ReadAttribute<uint32_t>("texture_coords") : 0); // Not having positions is a error only if a previous vertex buffer did not have them. if (!positions && !dest->HasPositions()) { throw DeadlyImportError("Vertex buffer does not contain positions!"); } if (positions) { DefaultLogger::get()->debug(" - Contains positions"); dest->positions.reserve(dest->count); } if (normals) { DefaultLogger::get()->debug(" - Contains normals"); dest->normals.reserve(dest->count); } if (tangents) { DefaultLogger::get()->debug(" - Contains tangents"); dest->tangents.reserve(dest->count); } if (uvs > 0) { DefaultLogger::get()->debug(Formatter::format() << " - Contains " << uvs << " texture coords"); dest->uvs.resize(uvs); for(size_t i=0, len=dest->uvs.size(); i<len; ++i) { dest->uvs[i].reserve(dest->count); } } bool warnBinormal = true; bool warnColorDiffuse = true; bool warnColorSpecular = true; NextNode(); while(m_currentNodeName == nnVertex || m_currentNodeName == nnPosition || m_currentNodeName == nnNormal || m_currentNodeName == nnTangent || m_currentNodeName == nnBinormal || m_currentNodeName == nnTexCoord || m_currentNodeName == nnColorDiffuse || m_currentNodeName == nnColorSpecular) { if (m_currentNodeName == nnVertex) { NextNode(); } /// @todo Implement nnBinormal, nnColorDiffuse and nnColorSpecular if (positions && m_currentNodeName == nnPosition) { aiVector3D pos; pos.x = ReadAttribute<float>(anX); pos.y = ReadAttribute<float>(anY); pos.z = ReadAttribute<float>(anZ); dest->positions.push_back(pos); } else if (normals && m_currentNodeName == nnNormal) { aiVector3D normal; normal.x = ReadAttribute<float>(anX); normal.y = ReadAttribute<float>(anY); normal.z = ReadAttribute<float>(anZ); dest->normals.push_back(normal); } else if (tangents && m_currentNodeName == nnTangent) { aiVector3D tangent; tangent.x = ReadAttribute<float>(anX); tangent.y = ReadAttribute<float>(anY); tangent.z = ReadAttribute<float>(anZ); dest->tangents.push_back(tangent); } else if (uvs > 0 && m_currentNodeName == nnTexCoord) { for(size_t i=0, len=dest->uvs.size(); i<len; ++i) { if (m_currentNodeName != nnTexCoord) { throw DeadlyImportError("Vertex buffer declared more UVs than can be found in a vertex"); } aiVector3D uv; uv.x = ReadAttribute<float>("u"); uv.y = (ReadAttribute<float>("v") * -1) + 1; // Flip UV from Ogre to Assimp form dest->uvs[i].push_back(uv); NextNode(); } // Continue main loop as above already read next node continue; } else { /// @todo Remove this stuff once implemented. We only want to log warnings once per element. bool warn = true; if (m_currentNodeName == nnBinormal) { if (warnBinormal) { warnBinormal = false; } else { warn = false; } } else if (m_currentNodeName == nnColorDiffuse) { if (warnColorDiffuse) { warnColorDiffuse = false; } else { warn = false; } } else if (m_currentNodeName == nnColorSpecular) { if (warnColorSpecular) { warnColorSpecular = false; } else { warn = false; } } if (warn) { DefaultLogger::get()->warn("Vertex buffer attribute read not implemented for element: " + m_currentNodeName); } } // Advance NextNode(); } // Sanity checks if (dest->positions.size() != dest->count) { throw DeadlyImportError(Formatter::format() << "Read only " << dest->positions.size() << " positions when should have read " << dest->count); } if (normals && dest->normals.size() != dest->count) { throw DeadlyImportError(Formatter::format() << "Read only " << dest->normals.size() << " normals when should have read " << dest->count); } if (tangents && dest->tangents.size() != dest->count) { throw DeadlyImportError(Formatter::format() << "Read only " << dest->tangents.size() << " tangents when should have read " << dest->count); } for(unsigned int i=0; i<dest->uvs.size(); ++i) { if (dest->uvs[i].size() != dest->count) { throw DeadlyImportError(Formatter::format() << "Read only " << dest->uvs[i].size() << " uvs for uv index " << i << " when should have read " << dest->count); } } }
// ------------------------------------------------------------------------------------------------ // signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError. void DOMError(const std::string& message, const Token& token) { throw DeadlyImportError(Util::AddTokenText("FBX-DOM",message,&token)); }
// ------------------------------------------------------------------------------------------------ void M3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ) { ai_assert( !pFile.empty() ); const std::string mode = "rb"; boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode ) ); if ( NULL == file.get() ) { throw DeadlyImportError( "Failed to open file " + pFile + "."); } // Get the file-size and validate it, throwing an exception when it fails const size_t filesize = file->FileSize(); if( filesize < 1 ) { throw DeadlyImportError( "M3-file is too small."); } m_Buffer.resize( filesize ); file->Read( &m_Buffer[ 0 ], sizeof( unsigned char ), filesize ); m_pHead = reinterpret_cast<MD33*>( &m_Buffer[ 0 ] ); m_pRefs = reinterpret_cast<ReferenceEntry*>( &m_Buffer[ 0 ] + m_pHead->ofsRefs ); MODL20* pMODL20( NULL ); MODL23* pMODL23( NULL ); VertexExt* pVerts1( NULL ); Vertex* pVerts2( NULL ); DIV *pViews( NULL ); Region* regions( NULL ); uint16* faces( NULL ); uint32 nVertices = 0; bool ok = true; switch( m_pRefs[ m_pHead->MODL.ref ].type ) { case 20: pMODL20 = GetEntries<MODL20>( m_pHead->MODL ); if ( ( pMODL20->flags & 0x20000) != 0 ) { // Has vertices if( (pMODL20->flags & 0x40000) != 0 ) { // Has extra 4 byte pVerts1 = GetEntries<VertexExt>( pMODL20->vertexData ); nVertices = pMODL20->vertexData.nEntries/sizeof(VertexExt); } else { pVerts2 = GetEntries<Vertex>( pMODL20->vertexData ); nVertices = pMODL20->vertexData.nEntries / sizeof( Vertex ); } } pViews = GetEntries<DIV>( pMODL20->views ); break; case 23: pMODL23 = GetEntries<MODL23>(m_pHead->MODL ); if( (pMODL23->flags & 0x20000) != 0 ) { // Has vertices if( (pMODL23->flags & 0x40000) != 0 ) { // Has extra 4 byte pVerts1 = GetEntries<VertexExt>( pMODL23->vertexData ); nVertices = pMODL23->vertexData.nEntries/sizeof( VertexExt ); } else { pVerts2 = GetEntries<Vertex>( pMODL23->vertexData ); nVertices = pMODL23->vertexData.nEntries/sizeof( Vertex ); } } pViews = GetEntries<DIV>( pMODL23->views ); break; default: ok = false; break; } // Everything ok, if not throw an exception if ( !ok ) { throw DeadlyImportError( "Failed to open file " + pFile + "."); } // Get all region data regions = GetEntries<Region>( pViews->regions ); // Get the face data faces = GetEntries<uint16>( pViews->faces ); // Convert the vertices std::vector<aiVector3D> vertices; vertices.resize( nVertices ); unsigned int offset = 0; for ( unsigned int i = 0; i < nVertices; i++ ) { if ( pVerts1 ) { vertices[ offset ].Set( pVerts1[ i ].pos.x, pVerts1[ i ].pos.y, pVerts1[ i ].pos.z ); ++offset; } if ( pVerts2 ) { vertices[ offset ].Set( pVerts2[ i ].pos.x, pVerts2[ i ].pos.y, pVerts2[ i ].pos.z ); ++offset; } } // Write the UV coordinates offset = 0; std::vector<aiVector3D> uvCoords; uvCoords.resize( nVertices ); for( unsigned int i = 0; i < nVertices; ++i ) { if( pVerts1 ) { float u = (float) pVerts1[ i ].uv[ 0 ] / 2048; float v = (float) pVerts1[ i ].uv[ 1 ] / 2048; uvCoords[ offset ].Set( u, v, 0.0f ); ++offset; } if( pVerts2 ) { float u = (float) pVerts2[ i ].uv[ 0 ] / 2048; float v = (float) pVerts2[ i ].uv[ 1 ] / 2048; uvCoords[ offset ].Set( u, v, 0.0f ); ++offset; } } // Compute the normals std::vector<aiVector3D> normals; normals.resize( nVertices ); float w = 0.0f; Vec3D norm; offset = 0; for( unsigned int i = 0; i < nVertices; i++ ) { w = 0.0f; if( pVerts1 ) { norm.x = (float) 2*pVerts1[ i ].normal[ 0 ]/255.0f - 1; norm.y = (float) 2*pVerts1[ i ].normal[ 1 ]/255.0f - 1; norm.z = (float) 2*pVerts1[ i ].normal[ 2 ]/255.0f - 1; w = (float) pVerts1[ i ].normal[ 3 ]/255.0f; } if( pVerts2 ) { norm.x = (float) 2*pVerts2[ i ].normal[ 0 ]/255.0f - 1; norm.y = (float) 2*pVerts2[ i ].normal[ 1 ]/255.0f - 1; norm.z = (float) 2*pVerts2[ i ].normal[ 2 ]/255.0f - 1; w = (float) pVerts2[ i ].normal[ 3 ] / 255.0f; } if ( w ) { const float invW = 1.0f / w; norm.x = norm.x * invW; norm.y = norm.y * invW; norm.z = norm.z * invW; normals[ offset ].Set( norm.x, norm.y, norm.z ); ++offset; } } // Convert the data into the assimp specific data structures convertToAssimp( pFile, pScene, pViews, regions, faces, vertices, uvCoords, normals ); }
void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader) { if(Reader->getAttributeValue("usesharedvertices")) theSubMesh.SharedData=GetAttribute<bool>(Reader, "usesharedvertices"); XmlRead(Reader); //TODO: maybe we have alsways just 1 faces and 1 geometry and always in this order. this loop will only work correct, when the order //of faces and geometry changed, and not if we have more than one of one while( Reader->getNodeName()==string("faces") || Reader->getNodeName()==string("geometry") || Reader->getNodeName()==string("boneassignments")) { if(string(Reader->getNodeName())=="faces")//Read the face list { //some info logging: unsigned int NumFaces=GetAttribute<int>(Reader, "count"); ostringstream ss; ss <<"Submesh has " << NumFaces << " Faces."; DefaultLogger::get()->debug(ss.str()); while(XmlRead(Reader) && Reader->getNodeName()==string("face")) { Face NewFace; NewFace.VertexIndices[0]=GetAttribute<int>(Reader, "v1"); NewFace.VertexIndices[1]=GetAttribute<int>(Reader, "v2"); NewFace.VertexIndices[2]=GetAttribute<int>(Reader, "v3"); if(Reader->getAttributeValue("v4"))//this should be supported in the future { DefaultLogger::get()->warn("Submesh has quads, only traingles are supported!"); //throw DeadlyImportError("Submesh has quads, only traingles are supported!"); } theSubMesh.FaceList.push_back(NewFace); } }//end of faces else if(string(Reader->getNodeName())=="geometry")//Read the vertexdata { //some info logging: unsigned int NumVertices=GetAttribute<int>(Reader, "vertexcount"); ostringstream ss; ss<<"VertexCount: " << NumVertices; DefaultLogger::get()->debug(ss.str()); //General Informations about vertices XmlRead(Reader); while(Reader->getNodeName()==string("vertexbuffer")) { ReadVertexBuffer(theSubMesh, Reader, NumVertices); } //some error checking on the loaded data if(!theSubMesh.HasPositions) throw DeadlyImportError("No positions could be loaded!"); if(theSubMesh.HasNormals && theSubMesh.Normals.size() != NumVertices) throw DeadlyImportError("Wrong Number of Normals loaded!"); if(theSubMesh.HasTangents && theSubMesh.Tangents.size() != NumVertices) throw DeadlyImportError("Wrong Number of Tangents loaded!"); for(unsigned int i=0; i<theSubMesh.Uvs.size(); ++i) { if(theSubMesh.Uvs[i].size() != NumVertices) throw DeadlyImportError("Wrong Number of Uvs loaded!"); } }//end of "geometry else if(Reader->getNodeName()==string("boneassignments")) { ReadBoneWeights(theSubMesh, Reader); } } DefaultLogger::get()->debug((Formatter::format(), "Positionen: ",theSubMesh.Positions.size(), " Normale: ",theSubMesh.Normals.size(), " TexCoords: ",theSubMesh.Uvs.size(), " Tantents: ",theSubMesh.Tangents.size() )); }
void TestPlugin :: InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { throw DeadlyImportError(AIUT_DEF_ERROR_TEXT); }
// <triangle> // </triangle> // Defines a 3D triangle from three vertices, according to the right-hand rule (counter-clockwise when looking from the outside). // Multi elements - Yes. // Parent element - <volume>. // // Children elements: // <v1>, <v2>, <v3> // Multi elements - No. // Index of the desired vertices in a triangle or edge. void AMFImporter::ParseNode_Triangle() { CAMFImporter_NodeElement* ne; // create new color object. ne = new CAMFImporter_NodeElement_Triangle(mNodeElement_Cur); CAMFImporter_NodeElement_Triangle& als = *((CAMFImporter_NodeElement_Triangle*)ne);// alias for convenience // 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. }