00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __VCGLIB_IMPORTERDAE
00025 #define __VCGLIB_IMPORTERDAE
00026
00027
00028
00029 #include <wrap/dae/util_dae.h>
00030 #include <wrap/dae/poly_triangulator.h>
00031
00032
00033
00034 #define QDEBUG qDebug
00035
00036 namespace vcg {
00037 namespace tri {
00038 namespace io {
00039 template<typename OpenMeshType>
00040 class ImporterDAE : public UtilDAE
00041 {
00042 public:
00043 class ColladaFace;
00044 class ColladaVertex;
00045
00046 class ColladaTypes: public vcg::UsedTypes < vcg::Use<ColladaVertex>::template AsVertexType,
00047 vcg::Use<ColladaFace >::template AsFaceType >{};
00048
00049 class ColladaVertex : public vcg::Vertex< ColladaTypes,
00050 vcg::vertex::Coord3f,
00051 vcg::vertex::BitFlags,
00052 vcg::vertex::Normal3f,
00053 vcg::vertex::Color4b
00054 > {};
00055
00056
00057 class ColladaFace : public vcg::Face< ColladaTypes,
00058 vcg::face::VertexRef,
00059 vcg::face::BitFlags,
00060 vcg::face::Normal3f,
00061 vcg::face::Color4b,
00062 vcg::face::WedgeTexCoord2f
00063 > {};
00064
00065 class ColladaMesh : public vcg::tri::TriMesh< std::vector<ColladaVertex>, std::vector<ColladaFace> > {};
00066
00067
00068
00069 private:
00070
00071
00072
00073
00074
00075
00076 static int WedgeNormalAttribute(ColladaMesh& m,const QStringList face,const QStringList wn,const QDomNode wnsrc,const int meshfaceind,const int faceind,const int component)
00077 {
00078 int indnm = -1;
00079 if (!wnsrc.isNull())
00080 {
00081 indnm = face.at(faceind).toInt();
00082 assert(indnm * 3 < wn.size());
00083 m.face[meshfaceind].WN(component) = vcg::Point3f(wn.at(indnm * 3).toFloat(),wn.at(indnm * 3 + 1).toFloat(),wn.at(indnm * 3 + 2).toFloat());
00084 }
00085 return indnm;
00086 }
00087
00088 static int WedgeTextureAttribute(ColladaMesh& m,const QStringList face,int ind_txt,const QStringList wt,const QDomNode wtsrc,const int meshfaceind,const int faceind,const int component,const int stride = 2)
00089 {
00090 int indtx = -1;
00091 if (!wtsrc.isNull())
00092 {
00093 indtx = face.at(faceind).toInt();
00094
00095 assert(indtx * stride < wt.size());
00096 m.face[meshfaceind].WT(component) = vcg::TexCoord2<float>();
00097 m.face[meshfaceind].WT(component).U() = wt.at(indtx * stride).toFloat();
00098 m.face[meshfaceind].WT(component).V() = wt.at(indtx * stride + 1).toFloat();
00099
00100 m.face[meshfaceind].WT(component).N() = ind_txt;
00101
00102 }
00103 return indtx;
00104 }
00105
00106
00107 static int WedgeTextureAttribute(typename ColladaMesh::FaceType::TexCoordType & WT, const QStringList faceIndexList, int ind_txt, const QStringList wt, const QDomNode wtsrc,const int faceind,const int stride = 2)
00108 {
00109 int indtx = -1;
00110 if (!wtsrc.isNull())
00111 {
00112 indtx = faceIndexList.at(faceind).toInt();
00113
00114 assert(indtx * stride < wt.size());
00115 WT = vcg::TexCoord2<float>();
00116 WT.U() = wt.at(indtx * stride).toFloat();
00117 WT.V() = wt.at(indtx * stride + 1).toFloat();
00118 WT.N() = ind_txt;
00119 }
00120 return indtx;
00121 }
00122
00123 static int VertexColorAttribute(ColladaMesh& m,const QStringList face,const QStringList wc,const QDomNode wcsrc,const int faceind, const int vertind,const int colorcomponent)
00124 {
00125 int indcl = -1;
00126 if (!wcsrc.isNull())
00127 {
00128 indcl = face.at(faceind).toInt();
00129 assert((colorcomponent == 4) || (colorcomponent == 3));
00130 assert(indcl * colorcomponent < wc.size());
00131 vcg::Color4b c;
00132 if (colorcomponent == 3)
00133 c[3] = 255;
00134 for(unsigned int ii = 0;ii < colorcomponent;++ii)
00135 c[ii] = (unsigned char)(wc.at(indcl * colorcomponent + ii).toFloat()*255.0);
00136 m.vert[vertind].C() = c;
00137 }
00138 return indcl;
00139 }
00140
00141
00142 static void FindStandardWedgeAttributes(WedgeAttribute& wed,const QDomNode nd,const QDomDocument doc)
00143 {
00144 wed.wnsrc = findNodeBySpecificAttributeValue(nd,"input","semantic","NORMAL");
00145 wed.offnm = findStringListAttribute(wed.wn,wed.wnsrc,nd,doc,"NORMAL");
00146
00147 wed.wtsrc = findNodeBySpecificAttributeValue(nd,"input","semantic","TEXCOORD");
00148 if (!wed.wtsrc.isNull())
00149 {
00150 QDomNode src = attributeSourcePerSimplex(nd,doc,"TEXCOORD");
00151 if (isThereTag(src,"accessor"))
00152 {
00153 QDomNodeList wedatts = src.toElement().elementsByTagName("accessor");
00154 wed.stridetx = wedatts.at(0).toElement().attribute("stride").toInt();
00155 }
00156 else
00157 wed.stridetx = 2;
00158 }
00159
00160
00161
00162 wed.offtx = findStringListAttribute(wed.wt,wed.wtsrc,nd,doc,"TEXCOORD");
00163
00164 wed.wcsrc = findNodeBySpecificAttributeValue(nd,"input","semantic","COLOR");
00165 if (!wed.wcsrc.isNull())
00166 {
00167 QDomNode src = attributeSourcePerSimplex(nd,doc,"COLOR");
00168 if (isThereTag(src,"accessor"))
00169 {
00170 QDomNodeList wedatts = src.toElement().elementsByTagName("accessor");
00171 wed.stridecl = wedatts.at(0).toElement().attribute("stride").toInt();
00172 }
00173 else
00174 wed.stridecl = 3;
00175 }
00176
00177
00178 wed.offcl = findStringListAttribute(wed.wc,wed.wcsrc,nd,doc,"COLOR");
00179 }
00180
00181 static DAEError LoadPolygonalMesh(QDomNodeList& polypatch,ColladaMesh& m,const size_t offset,InfoDAE & info)
00182 {
00183 return E_NOERROR;
00184 }
00185
00186 static DAEError LoadPolygonalListMesh(QDomNodeList& polylist,ColladaMesh& m,const size_t offset,InfoDAE& info,QMap<QString,QString> &materialBinding)
00187 {
00188 if(polylist.isEmpty()) return E_NOERROR;
00189 QDEBUG("****** LoadPolygonalListMesh (initial mesh size %i %i)",m.vert.size(),m.fn);
00190 for(int tript = 0; tript < polylist.size();++tript)
00191 {
00192 QString materialId = polylist.at(tript).toElement().attribute(QString("material"));
00193 QDEBUG("****** material id '%s' -> '%s'",qPrintable(materialId),qPrintable(materialBinding[materialId]));
00194
00195 QString textureFilename;
00196 QDomNode img_node = textureFinder(materialBinding[materialId],textureFilename,*(info.doc));
00197 if(img_node.isNull())
00198 {
00199 QDEBUG("****** but we were not able to find the corresponding image node");
00200 }
00201
00202 int ind_txt = -1;
00203 if (!img_node.isNull())
00204 {
00205 if(info.textureIdMap.contains(textureFilename))
00206 ind_txt=info.textureIdMap[textureFilename];
00207 else
00208 {
00209 QDEBUG("Found use of Texture %s, adding it to texutres",qPrintable(textureFilename));
00210
00211 QString ConvertedName = textureFilename.replace(QString("%20"), QString(" "));
00212
00213 info.textureIdMap[textureFilename]=m.textures.size();
00214 m.textures.push_back(qPrintable(ConvertedName));
00215 ind_txt=info.textureIdMap[textureFilename];
00216 }
00217 }
00218
00219 int faceAttributeNum = polylist.at(tript).toElement().elementsByTagName("input").size();
00220
00221
00222
00223 QStringList faceSizeList;
00224 valueStringList(faceSizeList,polylist.at(tript),"vcount");
00225
00226
00227
00228 QStringList faceIndexList;
00229 valueStringList(faceIndexList,polylist.at(tript),"p");
00230
00231
00232 if (faceIndexList.size() != 0 && faceSizeList.size() != 0 )
00233 {
00234 WedgeAttribute wa;
00235 FindStandardWedgeAttributes(wa,polylist.at(tript),*(info.doc));
00236 QDEBUG("******* Start Reading faces. Attributes Offsets: offtx %i - offnm %i - offcl %i",wa.offtx,wa.offnm,wa.offcl);
00237
00238 int faceIndexCnt=0;
00239 int jj = 0;
00240 for(int ff = 0; ff < (int) faceSizeList.size();++ff)
00241 {
00242 int curFaceVertNum = faceSizeList.at(ff).toInt();
00243
00244 MyPolygon<typename ColladaMesh::VertexType> polyTemp(curFaceVertNum);
00245 for(int tt = 0;tt < curFaceVertNum ;++tt)
00246 {
00247 int indvt = faceIndexList.at(faceIndexCnt).toInt();
00248 if(faceSizeList.size()<100) QDEBUG("******* Reading face[%3i].V(%i) = %4i (%i-th of the index list) (face has %i vertices)",ff,tt,indvt,faceIndexCnt,curFaceVertNum);
00249 assert(indvt + offset < m.vert.size());
00250 polyTemp._pv[tt] = &(m.vert[indvt + offset]);
00251 faceIndexCnt +=faceAttributeNum;
00252
00253 WedgeTextureAttribute(polyTemp._txc[tt],faceIndexList,ind_txt, wa.wt ,wa.wtsrc, jj + wa.offtx,wa.stridetx);
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 jj += faceAttributeNum;
00267 }
00268
00269 AddPolygonToMesh(polyTemp,m);
00270 }
00271 }
00272
00273 }
00274 QDEBUG("****** LoadPolygonalListMesh (final mesh size vn %i vertsize %i - fn %i facesize %i)",m.vn,m.vert.size(),m.fn,m.face.size());
00275 return E_NOERROR;
00276 }
00277
00278 static DAEError AddPolygonToMesh(MyPolygon<typename ColladaMesh::VertexType> &polyTemp, ColladaMesh& m)
00279 {
00280 int vertNum=polyTemp._pv.size();
00281 int triNum= vertNum -2;
00282 typename ColladaMesh::FaceIterator fp=vcg::tri::Allocator<ColladaMesh>::AddFaces(m,triNum);
00283
00284 for(int i=0;i<triNum;++i)
00285 {
00286 assert(fp!=m.face.end());
00287 (*fp).V(0)=polyTemp._pv[0];
00288 (*fp).WT(0)=polyTemp._txc[0];
00289
00290 (*fp).V(1) =polyTemp._pv [i+1];
00291 (*fp).WT(1)=polyTemp._txc[i+1];
00292
00293 (*fp).V(2) =polyTemp._pv[i+2];
00294 (*fp).WT(2)=polyTemp._txc[i+2];
00295
00296 ++fp;
00297 }
00298 assert(fp==m.face.end());
00299 return E_NOERROR;
00300 }
00301
00302 static DAEError OldLoadPolygonalListMesh(QDomNodeList& polylist,ColladaMesh& m,const size_t offset,InfoDAE& info)
00303 {
00304 typedef PolygonalMesh< MyPolygon<typename ColladaMesh::VertexType> > PolyMesh;
00305 PolyMesh pm;
00306
00307
00308 for(typename ColladaMesh::VertexIterator itv = m.vert.begin();itv != m.vert.end();++itv)
00309 {
00310 vcg::Point3f p(itv->P().X(),itv->P().Y(),itv->P().Z());
00311 typename PolyMesh::VertexType v;
00312 v.P() = p;
00313 pm.vert.push_back(v);
00314 }
00315
00316 int polylist_size = polylist.size();
00317 for(int pl = 0; pl < polylist_size;++pl)
00318 {
00319 QString mat = polylist.at(pl).toElement().attribute(QString("material"));
00320 QString textureFilename;
00321 QDomNode txt_node = textureFinder(mat,textureFilename,*(info.doc));
00322 int ind_txt = -1;
00323 if (!txt_node.isNull())
00324 ind_txt = indexTextureByImgNode(*(info.doc),txt_node);
00325
00326
00327 WedgeAttribute wa;
00328 FindStandardWedgeAttributes(wa,polylist.at(pl),*(info.doc));
00329 QStringList vertcount;
00330 valueStringList(vertcount,polylist.at(pl),"vcount");
00331 int indforpol = findOffSetForASingleSimplex(polylist.at(pl));
00332 int offpols = 0;
00333 int npolig = vertcount.size();
00334 QStringList polyind;
00335 valueStringList(polyind,polylist.at(pl),"p");
00336 for(int ii = 0;ii < npolig;++ii)
00337 {
00338 int nvert = vertcount.at(ii).toInt();
00339 typename PolyMesh::FaceType p(nvert);
00340
00341 for(int iv = 0;iv < nvert;++iv)
00342 {
00343 int index = offset + polyind.at(offpols + iv * indforpol).toInt();
00344 p._pv[iv] = &(pm.vert[index]);
00345 int nmindex = -1;
00346
00347 if (!wa.wnsrc.isNull())
00348 nmindex = offset + polyind.at(offpols + iv * indforpol + wa.offnm).toInt();
00349
00350 int txindex = -1;
00351 if (!wa.wtsrc.isNull())
00352 {
00353 txindex = offset + polyind.at(offpols + iv * indforpol + wa.offtx).toInt();
00354
00355
00356
00357 }
00358 }
00359 pm._pols.push_back(p);
00360 offpols += nvert * indforpol;
00361 }
00362 }
00363 pm.triangulate(m);
00364 return E_NOERROR;
00365 }
00366
00367
00368
00369 static DAEError LoadTriangularMesh(QDomNodeList& triNodeList, ColladaMesh& m, const size_t offset, InfoDAE& info,QMap<QString,QString> &materialBinding)
00370 {
00371 if(triNodeList.isEmpty()) return E_NOERROR;
00372 QDEBUG("****** LoadTriangularMesh (initial mesh size %i %i)",m.vn,m.fn);
00373 for(int tript = 0; tript < triNodeList.size();++tript)
00374 {
00375 QString materialId = triNodeList.at(tript).toElement().attribute(QString("material"));
00376 QDEBUG("****** material id '%s' -> '%s'",qPrintable(materialId),qPrintable(materialBinding[materialId]));
00377
00378 QString textureFilename;
00379 QDomNode img_node = textureFinder(materialBinding[materialId],textureFilename,*(info.doc));
00380 if(img_node.isNull())
00381 {
00382 QDEBUG("****** but we were not able to find the corresponding image node");
00383 }
00384
00385 int ind_txt = -1;
00386 if (!img_node.isNull())
00387 {
00388 if(info.textureIdMap.contains(textureFilename))
00389 ind_txt=info.textureIdMap[textureFilename];
00390 else
00391 {
00392 QDEBUG("Found use of Texture %s, adding it to texutres",qPrintable(textureFilename));
00393 QString ConvertedName = textureFilename.replace(QString("%20"), QString(" "));
00394 info.textureIdMap[textureFilename]=m.textures.size();
00395 m.textures.push_back(qPrintable(ConvertedName));
00396 ind_txt=info.textureIdMap[textureFilename];
00397 }
00398
00399 }
00400 int faceAttributeNum = triNodeList.at(tript).toElement().elementsByTagName("input").size();
00401
00402 QStringList face;
00403 valueStringList(face,triNodeList.at(tript),"p");
00404 int offsetface = (int)m.face.size();
00405 if (face.size() != 0)
00406 {
00407 vcg::tri::Allocator<ColladaMesh>::AddFaces(m,face.size() / (faceAttributeNum * 3));
00408 WedgeAttribute wa;
00409 FindStandardWedgeAttributes(wa,triNodeList.at(tript),*(info.doc));
00410
00411 int jj = 0;
00412 for(int ff = offsetface;ff < (int) m.face.size();++ff)
00413 {
00414
00415 for(unsigned int tt = 0;tt < 3;++tt)
00416 {
00417 int indvt = face.at(jj).toInt();
00418 assert(indvt + offset < m.vert.size());
00419 m.face[ff].V(tt) = &(m.vert[indvt + offset]);
00420
00421 if(tri::HasPerWedgeNormal(m))
00422 WedgeNormalAttribute(m,face,wa.wn,wa.wnsrc,ff,jj + wa.offnm,tt);
00423 if(tri::HasPerVertexColor(m))
00424 {
00425 VertexColorAttribute(m,face,wa.wc,wa.wcsrc,jj + wa.offcl,indvt + offset,wa.stridecl);
00426 }
00427
00428 if(tri::HasPerWedgeTexCoord(m) && ind_txt != -1)
00429 {
00430 WedgeTextureAttribute(m,face,ind_txt,wa.wt,wa.wtsrc,ff,jj + wa.offtx,tt,wa.stridetx);
00431 }
00432
00433 jj += faceAttributeNum;
00434 }
00435 if( ! ( (m.face[ff].V(0) != m.face[ff].V(1)) &&
00436 (m.face[ff].V(0) != m.face[ff].V(2)) &&
00437 (m.face[ff].V(1) != m.face[ff].V(2)) ) )
00438 QDEBUG("********* WARNING face %i, (%i %i %i) is a DEGENERATE FACE!",ff, m.face[ff].V(0) - &m.vert.front(), m.face[ff].V(1) - &m.vert.front(), m.face[ff].V(2) - &m.vert.front());
00439
00440 }
00441 }
00442 }
00443 QDEBUG("****** LoadTriangularMesh (final mesh size %i %i - %i %i)",m.vn,m.vert.size(),m.fn,m.face.size());
00444 return E_NOERROR;
00445 }
00446
00447 static int LoadControllerMesh(ColladaMesh& m, InfoDAE& info, const QDomElement& geo,QMap<QString, QString> materialBindingMap, CallBackPos *cb=0)
00448 {
00449 (void)cb;
00450
00451 assert(geo.tagName() == "controller");
00452 QDomNodeList skinList = geo.toElement().elementsByTagName("skin");
00453 if(skinList.size()!=1) return E_CANTOPEN;
00454 QDomElement skinNode = skinList.at(0).toElement();
00455
00456 QString geomNode_url;
00457 referenceToANodeAttribute(skinNode,"source",geomNode_url);
00458 QDEBUG("Found a controller referencing a skin with url '%s'", qPrintable(geomNode_url));
00459 QDomNode refNode = findNodeBySpecificAttributeValue(*(info.doc),"geometry","id",geomNode_url);
00460
00461 QDomNodeList bindingNodes = skinNode.toElement().elementsByTagName("bind_material");
00462 if( bindingNodes.size()>0) {
00463 QDEBUG("** skin node of a controller has a material binding");
00464 GenerateMaterialBinding(skinNode,materialBindingMap);
00465 }
00466 return LoadGeometry(m, info, refNode.toElement(),materialBindingMap);
00467 }
00468
00469
00470
00471
00472 static bool GenerateMaterialBinding(QDomNode instanceGeomNode, QMap<QString,QString> &binding)
00473 {
00474 QDomNodeList instanceMaterialList=instanceGeomNode.toElement().elementsByTagName("instance_material");
00475 QDEBUG("++++ Found %i instance_material binding",instanceMaterialList.size() );
00476 for(int i=0;i<instanceMaterialList.size();++i)
00477 {
00478 QString symbol = instanceMaterialList.at(i).toElement().attribute("symbol");
00479 QString target = instanceMaterialList.at(i).toElement().attribute("target");
00480 binding[symbol]=target;
00481 QDEBUG("++++++ %s -> %s",qPrintable(symbol),qPrintable(target));
00482 }
00483 return true;
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 static int LoadGeometry(ColladaMesh& m, InfoDAE& info, const QDomElement& geo, QMap<QString,QString> &materialBinding, CallBackPos *cb=0)
00495 {
00496 assert(geo.tagName() == "geometry");
00497 if (!isThereTag(geo,"mesh")) return E_NOMESH;
00498
00499 if ((cb !=NULL) && (((info.numvert + info.numface)%100)==0) && !(*cb)((100*(info.numvert + info.numface))/(info.numvert + info.numface), "Vertex Loading"))
00500 return E_CANTOPEN;
00501 QDEBUG("**** Loading a Geometry Mesh **** (initial mesh size %i %i)",m.vn,m.fn);
00502 QDomNodeList vertices = geo.toElement().elementsByTagName("vertices");
00503 if (vertices.size() != 1) return E_INCOMPATIBLECOLLADA141FORMAT;
00504 QDomElement vertNode = vertices.at(0).toElement();
00505
00506 QDomNode positionNode = attributeSourcePerSimplex(vertNode,*(info.doc),"POSITION");
00507 if (positionNode.isNull()) return E_NOVERTEXPOSITION;
00508
00509 QStringList geosrcposarr;
00510 valueStringList(geosrcposarr, positionNode, "float_array");
00511
00512 int geosrcposarr_size = geosrcposarr.size();
00513 if ((geosrcposarr_size % 3) != 0)
00514 return E_CANTOPEN;
00515 int nvert = geosrcposarr_size / 3;
00516 size_t offset = m.vert.size();
00517 if (geosrcposarr_size != 0)
00518 {
00519 vcg::tri::Allocator<ColladaMesh>::AddVertices(m,nvert);
00520
00521 QDomNode srcnodenorm = attributeSourcePerSimplex(vertices.at(0),*(info.doc),"NORMAL");
00522 QStringList geosrcvertnorm;
00523 if (!srcnodenorm.isNull())
00524 valueStringList(geosrcvertnorm,srcnodenorm,"float_array");
00525
00526 QDomNode srcnodetext = attributeSourcePerSimplex(vertices.at(0),*(info.doc),"TEXCOORD");
00527 QStringList geosrcverttext;
00528 if (!srcnodetext.isNull())
00529 valueStringList(geosrcverttext,srcnodetext,"float_array");
00530
00531 QDomNode srcnodecolor = attributeSourcePerSimplex(vertices.at(0),*(info.doc),"COLOR");
00532 QDomNodeList accesslist = srcnodecolor.toElement().elementsByTagName("accessor");
00533
00534 QStringList geosrcvertcol;
00535 if (!srcnodecolor.isNull())
00536 valueStringList(geosrcvertcol,srcnodecolor,"float_array");
00537
00538 int ii = 0;
00539 for(size_t vv = offset;vv < m.vert.size();++vv)
00540 {
00541 Point3f positionCoord(geosrcposarr[ii * 3].toFloat(),geosrcposarr[ii * 3 + 1].toFloat(),geosrcposarr[ii * 3 + 2].toFloat());
00542 m.vert[vv].P() = positionCoord;
00543
00544 if (!srcnodenorm.isNull())
00545 {
00546 Point3f normalCoord(geosrcvertnorm[ii * 3].toFloat(),
00547 geosrcvertnorm[ii * 3 + 1].toFloat(),
00548 geosrcvertnorm[ii * 3 + 2].toFloat());
00549 normalCoord.Normalize();
00550 m.vert[vv].N() = normalCoord;
00551 }
00552
00553 if (!srcnodecolor.isNull())
00554 {
00555 if (accesslist.size() > 0)
00556 {
00557
00558 if (accesslist.at(0).childNodes().size() == 4)
00559 m.vert[vv].C() = vcg::Color4b(geosrcvertcol[ii * 4].toFloat()*255.0,geosrcvertcol[ii * 4 + 1].toFloat()*255.0,geosrcvertcol[ii * 4 + 2].toFloat()*255.0,geosrcvertcol[ii * 4 + 3].toFloat()*255.0);
00560 else
00561 if (accesslist.at(0).childNodes().size() == 3)
00562 m.vert[vv].C() = vcg::Color4b(geosrcvertcol[ii * 3].toFloat()*255.0,geosrcvertcol[ii * 3 + 1].toFloat()*255.0,geosrcvertcol[ii * 3 + 2].toFloat()*255.0,255.0);
00563 }
00564 }
00565
00566 if (!srcnodetext.isNull())
00567 {
00568
00569 assert((ii * 2 < geosrcverttext.size()) && (ii * 2 + 1 < geosrcverttext.size()));
00570 m.vert[vv].T() = vcg::TexCoord2<float>();
00571 m.vert[vv].T().u() = geosrcverttext[ii * 2].toFloat();
00572 m.vert[vv].T().v() = geosrcverttext[ii * 2 + 1].toFloat();
00573 }
00574 ++ii;
00575 }
00576
00577 QDomNodeList tripatch = geo.toElement().elementsByTagName("triangles");
00578 QDomNodeList polypatch = geo.toElement().elementsByTagName("polygons");
00579 QDomNodeList polylist = geo.toElement().elementsByTagName("polylist");
00580 QStringList vertcount;
00581 valueStringList(vertcount,polylist.at(0),"vcount");
00582 int isTri=true;
00583 for (int i=0; i<vertcount.size(); i++)
00584 {
00585 if (vertcount[i]!="3")
00586 {
00587 isTri=false;
00588 break;
00589 }
00590
00591 }
00592 if (isTri && tripatch.isEmpty())
00593 tripatch=polylist;
00594 if (tripatch.isEmpty() && polypatch.isEmpty() && polylist.isEmpty())
00595 return E_NOPOLYGONALMESH;
00596
00597 DAEError err = E_NOERROR;
00598 err = LoadTriangularMesh(tripatch,m,offset,info,materialBinding);
00599
00600
00601 err = LoadPolygonalListMesh(polylist,m,offset,info,materialBinding);
00602 if (err != E_NOERROR)
00603 return err;
00604 }
00605 QDEBUG("**** Loading a Geometry Mesh **** (final mesh size %i %i - %i %i)",m.vn,m.vert.size(),m.fn,m.face.size());
00606 return E_NOERROR;
00607 }
00608
00609 static void GetTexCoord(const QDomDocument& doc, QStringList &texturefile)
00610 {
00611 QDomNodeList txlst = doc.elementsByTagName("library_images");
00612 for(int img = 0;img < txlst.at(0).childNodes().size();++img)
00613 {
00614 QDomNodeList nlst = txlst.at(0).childNodes().at(img).toElement().elementsByTagName("init_from");
00615 if (nlst.size() > 0)
00616 {
00617 texturefile.push_back( nlst.at(0).firstChild().nodeValue());
00618 }
00619 }
00620 }
00621
00622
00623
00624
00625
00626 static void AddNodeToMesh(QDomElement node,
00627 ColladaMesh& m, Matrix44f curTr,
00628 InfoDAE& info)
00629 {
00630 QDEBUG("Starting processing <node> with id %s",qPrintable(node.attribute("id")));
00631
00632 curTr = curTr * getTransfMatrixFromNode(node);
00633
00634 QDomNodeList geomNodeList = node.elementsByTagName("instance_geometry");
00635 for(int ch = 0;ch < geomNodeList.size();++ch)
00636 {
00637 QDomElement instGeomNode= geomNodeList.at(ch).toElement();
00638 if(instGeomNode.parentNode()==node)
00639 {
00640 QDEBUG("** instance_geometry with url %s (intial mesh size %i %i T = %i)",qPrintable(instGeomNode.attribute("url")),m.vn,m.fn,m.textures.size());
00641
00642 QString geomNode_url;
00643 referenceToANodeAttribute(instGeomNode,"url",geomNode_url);
00644 QDomNode refNode = findNodeBySpecificAttributeValue(*(info.doc),"geometry","id",geomNode_url);
00645 QDomNodeList bindingNodes = instGeomNode.toElement().elementsByTagName("bind_material");
00646 QMap<QString,QString> materialBindingMap;
00647 if( bindingNodes.size()>0) {
00648 QDEBUG("** instance_geometry has a material binding");
00649 GenerateMaterialBinding(instGeomNode,materialBindingMap);
00650 }
00651
00652 ColladaMesh newMesh;
00653
00654 LoadGeometry(newMesh, info, refNode.toElement(),materialBindingMap);
00655 tri::UpdatePosition<ColladaMesh>::Matrix(newMesh,curTr);
00656 tri::Append<ColladaMesh,ColladaMesh>::Mesh(m,newMesh);
00657 QDEBUG("** instance_geometry with url %s (final mesh size %i %i - %i %i)",qPrintable(instGeomNode.attribute("url")),m.vn,m.vert.size(),m.fn,m.face.size());
00658 }
00659 }
00660
00661 QDomNodeList controllerNodeList = node.elementsByTagName("instance_controller");
00662 for(int ch = 0;ch < controllerNodeList.size();++ch)
00663 {
00664 QDomElement instContrNode= controllerNodeList.at(ch).toElement();
00665 if(instContrNode.parentNode()==node)
00666 {
00667 QDEBUG("Found a instance_controller with url %s",qPrintable(instContrNode.attribute("url")));
00668
00669 QString controllerNode_url;
00670 referenceToANodeAttribute(instContrNode,"url",controllerNode_url);
00671 QDEBUG("Found a instance_controller with url '%s'", qPrintable(controllerNode_url));
00672 QDomNode refNode = findNodeBySpecificAttributeValue(*(info.doc),"controller","id",controllerNode_url);
00673
00674 QDomNodeList bindingNodes = instContrNode.toElement().elementsByTagName("bind_material");
00675 QMap<QString, QString> materialBindingMap;
00676 if( bindingNodes.size()>0) {
00677 QDEBUG("** instance_controller node of has a material binding");
00678 GenerateMaterialBinding(instContrNode,materialBindingMap);
00679 }
00680
00681 ColladaMesh newMesh;
00682 LoadControllerMesh(newMesh, info, refNode.toElement(),materialBindingMap);
00683 tri::UpdatePosition<ColladaMesh>::Matrix(newMesh,curTr);
00684 tri::Append<ColladaMesh,ColladaMesh>::Mesh(m,newMesh);
00685 }
00686 }
00687
00688 QDomNodeList nodeNodeList = node.elementsByTagName("node");
00689 for(int ch = 0;ch < nodeNodeList.size();++ch)
00690 {
00691 if(nodeNodeList.at(ch).parentNode()==node)
00692 AddNodeToMesh(nodeNodeList.at(ch).toElement(), m,curTr, info);
00693 }
00694
00695 QDomNodeList instanceNodeList = node.elementsByTagName("instance_node");
00696 for(int ch = 0;ch < instanceNodeList.size();++ch)
00697 {
00698 if(instanceNodeList.at(ch).parentNode()==node)
00699 {
00700 QDomElement instanceNode = instanceNodeList.at(ch).toElement();
00701 QString node_url;
00702 referenceToANodeAttribute(instanceNode,"url",node_url);
00703 QDEBUG("Found a instance_node with url '%s'", qPrintable(node_url));
00704 QDomNode refNode = findNodeBySpecificAttributeValue(*(info.doc),"node","id",node_url);
00705 if(refNode.isNull())
00706 QDEBUG("findNodeBySpecificAttributeValue returned a null node for %s",qPrintable(node_url));
00707
00708 AddNodeToMesh(refNode.toElement(), m,curTr, info);
00709 }
00710 }
00711 }
00712
00713
00714
00715
00716 static Matrix44f getTransfMatrixFromNode(const QDomElement parentNode)
00717 {
00718 QDEBUG("getTrans form node with tag %s",qPrintable(parentNode.tagName()));
00719 assert(parentNode.tagName() == "node");
00720
00721 std::vector<QDomNode> rotationList;
00722 QDomNode matrixNode;
00723 QDomNode translationNode;
00724 for(int ch = 0;ch < parentNode.childNodes().size();++ch)
00725 {
00726 if (parentNode.childNodes().at(ch).nodeName() == "rotate")
00727 rotationList.push_back(parentNode.childNodes().at(ch));
00728 if (parentNode.childNodes().at(ch).nodeName() == "translate")
00729 translationNode = parentNode.childNodes().at(ch);
00730 if (parentNode.childNodes().at(ch).nodeName() == "matrix")
00731 matrixNode = parentNode.childNodes().at(ch);
00732 }
00733
00734 Matrix44f rotM; rotM.SetIdentity();
00735 Matrix44f transM; transM.SetIdentity();
00736
00737 if (!translationNode.isNull()) ParseTranslation(transM,translationNode);
00738 if (!rotationList.empty()) ParseRotationMatrix(rotM,rotationList);
00739 if (!matrixNode.isNull())
00740 {
00741 ParseMatrixNode(transM,matrixNode);
00742 return transM;
00743 }
00744 return transM*rotM;
00745 }
00746
00747 public:
00748
00749
00750
00751
00752 static int Open(OpenMeshType& m,const char* filename, InfoDAE& info, CallBackPos *cb=0)
00753 {
00754 (void)cb;
00755
00756 QDEBUG("----- Starting the processing of %s ------",filename);
00757
00758
00759
00760 QDomDocument* doc = new QDomDocument(filename);
00761 info.doc = doc;
00762 QFile file(filename);
00763 if (!file.open(QIODevice::ReadOnly))
00764 return E_CANTOPEN;
00765 if (!doc->setContent(&file))
00766 {
00767 file.close();
00768 return E_CANTOPEN;
00769 }
00770 file.close();
00771
00772
00773
00774
00775
00776 QDomNodeList scenes = info.doc->elementsByTagName("scene");
00777 int scn_size = scenes.size();
00778 if (scn_size == 0)
00779 return E_NO3DSCENE;
00780 QDEBUG("File Contains %i Scenes",scenes.size());
00781 int problem = E_NOERROR;
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 for(int scn = 0;scn < scn_size;++scn)
00812 {
00813 QDomNodeList instscenes = scenes.at(scn).toElement().elementsByTagName("instance_visual_scene");
00814 int instscn_size = instscenes.size();
00815 QDEBUG("Scene %i contains %i instance_visual_scene ",scn,instscn_size);
00816 if (instscn_size == 0) return E_INCOMPATIBLECOLLADA141FORMAT;
00817
00818
00819 for(int instscn = 0;instscn < instscn_size; ++instscn)
00820 {
00821 QString libscn_url;
00822 referenceToANodeAttribute(instscenes.at(instscn),"url",libscn_url);
00823 QDEBUG("instance_visual_scene %i refers %s ",instscn,qPrintable(libscn_url));
00824
00825
00826 QDomNode visscn = findNodeBySpecificAttributeValue(*(info.doc),"visual_scene","id",libscn_url);
00827 if(visscn.isNull()) return E_UNREFERENCEBLEDCOLLADAATTRIBUTE;
00828
00829
00830
00831 QDomNodeList visscn_child = visscn.childNodes();
00832 QDEBUG("instance_visual_scene %s has %i children",qPrintable(libscn_url),visscn_child.size());
00833
00834
00835 for(int chdind = 0; chdind < visscn_child.size();++chdind)
00836 {
00837 QDomElement node=visscn_child.at(chdind).toElement();
00838 if(node.isNull()) continue;
00839 QDEBUG("Processing Visual Scene child %i - of type '%s'",chdind,qPrintable(node.tagName()));
00840 Matrix44f baseTr; baseTr.SetIdentity();
00841
00842 if(node.toElement().tagName()=="node")
00843 {
00844 ColladaMesh newMesh;
00845 AddNodeToMesh(node.toElement(), newMesh, baseTr,info);
00846 tri::Append<OpenMeshType,ColladaMesh>::Mesh(m,newMesh);
00847 }
00848 }
00849 }
00850 }
00851 return problem;
00852 }
00853
00854 static bool LoadMask(const char * filename, InfoDAE& info)
00855 {
00856 bool bHasPerWedgeTexCoord = false;
00857 bool bHasPerWedgeNormal = false;
00858
00859 bool bHasPerVertexColor = false;
00860 bool bHasPerFaceColor = false;
00861 bool bHasPerVertexNormal = false;
00862 bool bHasPerVertexText = false;
00863
00864 QDomDocument* doc = new QDomDocument(filename);
00865 QFile file(filename);
00866 if (!file.open(QIODevice::ReadOnly))
00867 return false;
00868 if (!doc->setContent(&file))
00869 {
00870 file.close();
00871 return false;
00872 }
00873 file.close();
00874
00875 QStringList textureFileList;
00876 info.doc = doc;
00877 GetTexCoord(*(info.doc),textureFileList);
00878 QDomNodeList scenes = info.doc->elementsByTagName("scene");
00879 int scn_size = scenes.size();
00880
00881
00882
00883 bool geoinst_found = false;
00884
00885 for(int scn = 0;scn < scn_size;++scn)
00886 {
00887 QDomNodeList instscenes = scenes.at(scn).toElement().elementsByTagName("instance_visual_scene");
00888 int instscn_size = instscenes.size();
00889 if (instscn_size == 0) return false;
00890
00891
00892 for(int instscn = 0;instscn < instscn_size; ++instscn)
00893 {
00894 QString libscn_url;
00895 referenceToANodeAttribute(instscenes.at(instscn),"url",libscn_url);
00896 QDomNode nd = QDomNode(*(info.doc));
00897 QDomNode visscn = findNodeBySpecificAttributeValue(*(info.doc),"visual_scene","id",libscn_url);
00898 if(visscn.isNull()) return false;
00899
00900
00901
00902 QDomNodeList visscn_child = visscn.childNodes();
00903
00904
00905 for(int chdind = 0; chdind < visscn_child.size();++chdind)
00906 {
00907
00908 QDomNodeList geoinst = visscn_child.at(chdind).toElement().elementsByTagName("instance_geometry");
00909 int geoinst_size = geoinst.size();
00910 if (geoinst_size != 0)
00911 {
00912
00913 geoinst_found |= true;
00914 QDomNodeList geolib = info.doc->elementsByTagName("library_geometries");
00915
00916 if (geolib.size() != 1)
00917 return false;
00919 info.numvert = 0;
00920 info.numface = 0;
00921 for(int geoinst_ind = 0;geoinst_ind < geoinst_size;++geoinst_ind)
00922 {
00923 QString geo_url;
00924 referenceToANodeAttribute(geoinst.at(geoinst_ind),"url",geo_url);
00925
00926 QDomNode geo = findNodeBySpecificAttributeValue(geolib.at(0),"geometry","id",geo_url);
00927 if (geo.isNull())
00928 return false;
00929
00930 QDomNodeList vertlist = geo.toElement().elementsByTagName("vertices");
00931
00932 for(int vert = 0;vert < vertlist.size();++vert)
00933 {
00934 QDomNode no;
00935 no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","POSITION");
00936 QString srcurl;
00937 referenceToANodeAttribute(no,"source",srcurl);
00938 no = findNodeBySpecificAttributeValue(geo,"source","id",srcurl);
00939 QDomNodeList fa = no.toElement().elementsByTagName("float_array");
00940 assert(fa.size() == 1);
00941 info.numvert += (fa.at(0).toElement().attribute("count").toInt() / 3);
00942 no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","COLOR");
00943 if (!no.isNull())
00944 bHasPerVertexColor = true;
00945 no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","NORMAL");
00946 if (!no.isNull())
00947 bHasPerVertexNormal = true;
00948 no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","TEXCOORD");
00949 if (!no.isNull())
00950 bHasPerVertexText = true;
00951 }
00952
00953 const char* arr[] = {"triangles","polylist","polygons"};
00954
00955 for(unsigned int tt= 0;tt < 3;++tt)
00956 {
00957 QDomNodeList facelist = geo.toElement().elementsByTagName(arr[tt]);
00958 for(int face = 0;face < facelist.size();++face)
00959 {
00960 info.numface += facelist.at(face).toElement().attribute("count").toInt() ;
00961 QDomNode no;
00962 no = findNodeBySpecificAttributeValue(facelist.at(face),"input","semantic","NORMAL");
00963 if (!no.isNull())
00964 bHasPerWedgeNormal = true;
00965 no = findNodeBySpecificAttributeValue(facelist.at(face),"input","semantic","COLOR");
00966 if (!no.isNull())
00967 bHasPerVertexColor = true;
00968 no = findNodeBySpecificAttributeValue(facelist.at(face),"input","semantic","TEXCOORD");
00969 if (!no.isNull())
00970 bHasPerWedgeTexCoord = true;
00971 }
00972 }
00973 }
00974 }
00975 }
00976 }
00977 }
00978
00979 if (!geoinst_found)
00980 {
00981 QDomNodeList geolib = info.doc->elementsByTagName("library_geometries");
00982
00983 if (geolib.size() != 1)
00984 return false;
00985 QDomNodeList geochild = geolib.at(0).toElement().elementsByTagName("geometry");
00987 info.numvert = 0;
00988 info.numface = 0;
00989 for(int geoinst_ind = 0;geoinst_ind < geochild.size();++geoinst_ind)
00990 {
00991 QDomNodeList vertlist = geochild.at(geoinst_ind).toElement().elementsByTagName("vertices");
00992
00993 for(int vert = 0;vert < vertlist.size();++vert)
00994 {
00995 QDomNode no;
00996 no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","POSITION");
00997 QString srcurl;
00998 referenceToANodeAttribute(no,"source",srcurl);
00999 no = findNodeBySpecificAttributeValue(geochild.at(geoinst_ind),"source","id",srcurl);
01000 QDomNodeList fa = no.toElement().elementsByTagName("float_array");
01001 assert(fa.size() == 1);
01002 info.numvert += (fa.at(0).toElement().attribute("count").toInt() / 3);
01003 no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","COLOR");
01004 if (!no.isNull())
01005 bHasPerVertexColor = true;
01006 no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","NORMAL");
01007 if (!no.isNull())
01008 bHasPerVertexNormal = true;
01009 no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","TEXCOORD");
01010 if (!no.isNull())
01011 bHasPerVertexText = true;
01012 }
01013
01014 QDomNodeList facelist = geochild.at(geoinst_ind).toElement().elementsByTagName("triangles");
01015 for(int face = 0;face < facelist.size();++face)
01016 {
01017 info.numface += facelist.at(face).toElement().attribute("count").toInt() ;
01018 QDomNode no;
01019 no = findNodeBySpecificAttributeValue(facelist.at(face),"input","semantic","NORMAL");
01020 if (!no.isNull())
01021 bHasPerWedgeNormal = true;
01022 no = findNodeBySpecificAttributeValue(facelist.at(face),"input","semantic","TEXCOORD");
01023 if (!no.isNull())
01024 bHasPerWedgeTexCoord = true;
01025 }
01026 }
01027 }
01028
01029 info.mask = 0;
01030
01031 if (bHasPerWedgeTexCoord)
01032 info.mask |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD;
01033 if (bHasPerWedgeNormal)
01034 info.mask |= vcg::tri::io::Mask::IOM_WEDGNORMAL;
01035 if (bHasPerVertexColor)
01036 info.mask |= vcg::tri::io::Mask::IOM_VERTCOLOR;
01037 if (bHasPerFaceColor)
01038 info.mask |= vcg::tri::io::Mask::IOM_FACECOLOR;
01039 if (bHasPerVertexNormal)
01040 info.mask |= vcg::tri::io::Mask::IOM_VERTNORMAL;
01041 if (bHasPerVertexText)
01042 info.mask |= vcg::tri::io::Mask::IOM_VERTTEXCOORD;
01043
01044
01045
01046 delete (info.doc);
01047 info.doc = NULL;
01048
01049 return true;
01050 }
01051 };
01052 }
01053 }
01054 }
01055
01056 #endif