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