2008-07-12 08:12:46 +02:00
/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright ( C ) 2004 - 2008 \ / ) \ / *
* Visual Computing Lab / \ / | *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved . *
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* This program is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY ; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU General Public License ( http : //www.gnu.org/licenses/gpl.txt) *
* for more details . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-06-14 11:47:21 +02:00
# ifndef __VCGLIB_IMPORTERDAE
# define __VCGLIB_IMPORTERDAE
//importer for collada's files
2009-05-29 18:29:14 +02:00
# include <wrap/dae/util_dae.h>
2006-06-14 11:47:21 +02:00
2009-04-06 01:30:29 +02:00
// uncomment one of the following line to enable the Verbose debugging for the parsing
//#define QDEBUG if(1) ; else {assert(0);}
2008-07-15 09:27:08 +02:00
# define QDEBUG qDebug
2006-06-14 11:47:21 +02:00
namespace vcg {
namespace tri {
namespace io {
2006-11-02 19:15:55 +01:00
template < typename OpenMeshType >
2006-11-03 00:58:33 +01:00
class ImporterDAE : public UtilDAE
2006-11-02 19:15:55 +01:00
{
2010-03-18 12:26:44 +01:00
public :
class ColladaFace ;
class ColladaVertex ;
class ColladaTypes : public vcg : : UsedTypes < vcg : : Use < ColladaVertex > : : template AsVertexType ,
2010-06-18 10:35:36 +02:00
vcg : : Use < ColladaFace > : : template AsFaceType > { } ;
2010-03-18 12:26:44 +01:00
class ColladaVertex : public vcg : : Vertex < ColladaTypes ,
vcg : : vertex : : Coord3f , /* 12b */
vcg : : vertex : : BitFlags , /* 4b */
vcg : : vertex : : Normal3f , /* 12b */
vcg : : vertex : : Color4b /* 4b */
> { } ;
class ColladaFace : public vcg : : Face < ColladaTypes ,
vcg : : face : : VertexRef , /*12b */
vcg : : face : : BitFlags , /* 4b */
vcg : : face : : Normal3f , /*12b */
vcg : : face : : Color4b , /* 0b */
vcg : : face : : WedgeTexCoord2f /* 0b */
> { } ;
class ColladaMesh : public vcg : : tri : : TriMesh < std : : vector < ColladaVertex > , std : : vector < ColladaFace > > { } ;
2006-11-05 16:40:51 +01:00
private :
2010-03-18 12:26:44 +01:00
2009-04-06 01:30:29 +02:00
static int WedgeNormalAttribute ( ColladaMesh & m , const QStringList face , const QStringList wn , const QDomNode wnsrc , const int meshfaceind , const int faceind , const int component )
2007-08-16 18:09:23 +02:00
{
int indnm = - 1 ;
if ( ! wnsrc . isNull ( ) )
{
indnm = face . at ( faceind ) . toInt ( ) ;
assert ( indnm * 3 < wn . size ( ) ) ;
m . face [ meshfaceind ] . WN ( component ) = vcg : : Point3f ( wn . at ( indnm * 3 ) . toFloat ( ) , wn . at ( indnm * 3 + 1 ) . toFloat ( ) , wn . at ( indnm * 3 + 2 ) . toFloat ( ) ) ;
}
return indnm ;
}
2009-04-06 01:30:29 +02:00
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 )
2007-08-16 18:09:23 +02:00
{
int indtx = - 1 ;
if ( ! wtsrc . isNull ( ) )
{
indtx = face . at ( faceind ) . toInt ( ) ;
2008-10-09 18:16:49 +02:00
//int num = wt.size();
2007-12-18 12:06:46 +01:00
assert ( indtx * stride < wt . size ( ) ) ;
2007-08-16 18:09:23 +02:00
m . face [ meshfaceind ] . WT ( component ) = vcg : : TexCoord2 < float > ( ) ;
2007-12-18 12:06:46 +01:00
m . face [ meshfaceind ] . WT ( component ) . U ( ) = wt . at ( indtx * stride ) . toFloat ( ) ;
m . face [ meshfaceind ] . WT ( component ) . V ( ) = wt . at ( indtx * stride + 1 ) . toFloat ( ) ;
2007-09-19 13:18:08 +02:00
2007-09-25 12:29:29 +02:00
m . face [ meshfaceind ] . WT ( component ) . N ( ) = ind_txt ;
2007-08-16 18:09:23 +02:00
}
return indtx ;
}
2009-04-04 19:25:57 +02:00
// this one is used for the polylist nodes
2009-04-06 01:30:29 +02:00
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 )
2009-04-04 19:25:57 +02:00
{
int indtx = - 1 ;
if ( ! wtsrc . isNull ( ) )
{
indtx = faceIndexList . at ( faceind ) . toInt ( ) ;
//int num = wt.size();
assert ( indtx * stride < wt . size ( ) ) ;
WT = vcg : : TexCoord2 < float > ( ) ;
WT . U ( ) = wt . at ( indtx * stride ) . toFloat ( ) ;
WT . V ( ) = wt . at ( indtx * stride + 1 ) . toFloat ( ) ;
WT . N ( ) = ind_txt ;
}
return indtx ;
}
2009-05-29 20:33:19 +02:00
2011-03-23 22:00:40 +01:00
static int VertexColorAttribute ( ColladaMesh & m , const QStringList face , const QStringList wc , const QDomNode wcsrc , const int meshfaceind , const int faceind , const int vertind , const int component )
2007-08-16 18:09:23 +02:00
{
2009-05-29 20:33:19 +02:00
int indcl = - 1 ;
2007-08-16 18:09:23 +02:00
if ( ! wcsrc . isNull ( ) )
{
indcl = face . at ( faceind ) . toInt ( ) ;
2011-03-23 22:00:40 +01:00
assert ( indcl * 3 < wc . size ( ) ) ;
m . vert [ vertind ] . C ( ) = vcg : : Color4b ( ( unsigned char ) ( wc . at ( indcl * 3 ) . toFloat ( ) * 255.0 ) ,
( unsigned char ) ( wc . at ( indcl * 3 + 1 ) . toFloat ( ) * 255.0 ) ,
( unsigned char ) ( wc . at ( indcl * 3 + 2 ) . toFloat ( ) * 255.0 ) ,
1.0 ) ;
2007-08-16 18:09:23 +02:00
}
return indcl ;
}
static void FindStandardWedgeAttributes ( WedgeAttribute & wed , const QDomNode nd , const QDomDocument doc )
{
wed . wnsrc = findNodeBySpecificAttributeValue ( nd , " input " , " semantic " , " NORMAL " ) ;
wed . offnm = findStringListAttribute ( wed . wn , wed . wnsrc , nd , doc , " NORMAL " ) ;
wed . wtsrc = findNodeBySpecificAttributeValue ( nd , " input " , " semantic " , " TEXCOORD " ) ;
2007-12-18 12:06:46 +01:00
if ( ! wed . wtsrc . isNull ( ) )
{
QDomNode src = attributeSourcePerSimplex ( nd , doc , " TEXCOORD " ) ;
if ( isThereTag ( src , " accessor " ) )
{
QDomNodeList wedatts = src . toElement ( ) . elementsByTagName ( " accessor " ) ;
wed . stride = wedatts . at ( 0 ) . toElement ( ) . attribute ( " stride " ) . toInt ( ) ;
}
else
wed . stride = 2 ;
}
else
wed . stride = 2 ;
2007-08-16 18:09:23 +02:00
wed . offtx = findStringListAttribute ( wed . wt , wed . wtsrc , nd , doc , " TEXCOORD " ) ;
wed . wcsrc = findNodeBySpecificAttributeValue ( nd , " input " , " semantic " , " COLOR " ) ;
wed . offcl = findStringListAttribute ( wed . wc , wed . wcsrc , nd , doc , " COLOR " ) ;
}
2007-12-18 12:06:46 +01:00
2009-11-24 11:21:29 +01:00
static DAEError LoadPolygonalMesh ( QDomNodeList & polypatch , ColladaMesh & m , const size_t offset , InfoDAE & info )
2007-08-16 18:09:23 +02:00
{
return E_NOERROR ;
}
2009-11-24 11:21:29 +01:00
static DAEError LoadPolygonalListMesh ( QDomNodeList & polylist , ColladaMesh & m , const size_t offset , InfoDAE & info , QMap < QString , QString > & materialBinding )
2009-04-04 19:25:57 +02:00
{
if ( polylist . isEmpty ( ) ) return E_NOERROR ;
QDEBUG ( " ****** LoadPolygonalListMesh (initial mesh size %i %i) " , m . vert . size ( ) , m . fn ) ;
for ( int tript = 0 ; tript < polylist . size ( ) ; + + tript )
{
QString materialId = polylist . at ( tript ) . toElement ( ) . attribute ( QString ( " material " ) ) ;
QDEBUG ( " ****** material id '%s' -> '%s' " , qPrintable ( materialId ) , qPrintable ( materialBinding [ materialId ] ) ) ;
QString textureFilename ;
2009-11-24 11:21:29 +01:00
QDomNode img_node = textureFinder ( materialBinding [ materialId ] , textureFilename , * ( info . doc ) ) ;
2009-04-04 19:25:57 +02:00
if ( img_node . isNull ( ) )
{
QDEBUG ( " ****** but we were not able to find the corresponding image node " ) ;
}
int ind_txt = - 1 ;
if ( ! img_node . isNull ( ) )
{
2009-11-24 11:21:29 +01:00
if ( info . textureIdMap . contains ( textureFilename ) )
ind_txt = info . textureIdMap [ textureFilename ] ;
2009-04-04 19:25:57 +02:00
else
{
QDEBUG ( " Found use of Texture %s, adding it to texutres " , qPrintable ( textureFilename ) ) ;
2009-11-24 11:21:29 +01:00
info . textureIdMap [ textureFilename ] = m . textures . size ( ) ;
2009-04-04 19:25:57 +02:00
m . textures . push_back ( qPrintable ( textureFilename ) ) ;
2009-11-24 11:21:29 +01:00
ind_txt = info . textureIdMap [ textureFilename ] ;
2009-04-04 19:25:57 +02:00
}
}
// number of the attributes associated to each vertex of a face (vert, normal, tex etc)
int faceAttributeNum = polylist . at ( tript ) . toElement ( ) . elementsByTagName ( " input " ) . size ( ) ;
// the list of indexes composing the size of each polygon.
// The size of this list is the number of the polygons.
QStringList faceSizeList ;
valueStringList ( faceSizeList , polylist . at ( tript ) , " vcount " ) ;
// The long list of indexes composing the various polygons.
// for each polygon there are numvert*numattrib indexes.
QStringList faceIndexList ;
valueStringList ( faceIndexList , polylist . at ( tript ) , " p " ) ;
2009-05-29 18:29:14 +02:00
//int offsetface = (int)m.face.size();
2009-04-04 19:25:57 +02:00
if ( faceIndexList . size ( ) ! = 0 & & faceSizeList . size ( ) ! = 0 )
{
WedgeAttribute wa ;
2009-11-24 11:21:29 +01:00
FindStandardWedgeAttributes ( wa , polylist . at ( tript ) , * ( info . doc ) ) ;
2009-04-04 19:25:57 +02:00
QDEBUG ( " ******* Start Reading faces. Attributes Offsets: offtx %i - offnm %i - offcl %i " , wa . offtx , wa . offnm , wa . offcl ) ;
int faceIndexCnt = 0 ;
int jj = 0 ;
for ( int ff = 0 ; ff < ( int ) faceSizeList . size ( ) ; + + ff ) // for each polygon
{
int curFaceVertNum = faceSizeList . at ( ff ) . toInt ( ) ;
2009-04-06 01:30:29 +02:00
MyPolygon < typename ColladaMesh : : VertexType > polyTemp ( curFaceVertNum ) ;
2009-05-29 18:29:14 +02:00
for ( int tt = 0 ; tt < curFaceVertNum ; + + tt ) // for each vertex of the polygon
2009-04-04 19:25:57 +02:00
{
int indvt = faceIndexList . at ( faceIndexCnt ) . toInt ( ) ;
2009-09-12 07:22:51 +02:00
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 ) ;
2009-04-04 19:25:57 +02:00
assert ( indvt + offset < m . vert . size ( ) ) ;
polyTemp . _pv [ tt ] = & ( m . vert [ indvt + offset ] ) ;
faceIndexCnt + = faceAttributeNum ;
WedgeTextureAttribute ( polyTemp . _txc [ tt ] , faceIndexList , ind_txt , wa . wt , wa . wtsrc , jj + wa . offtx , wa . stride ) ;
/****************
if ( tri : : HasPerWedgeNormal ( m ) ) WedgeNormalAttribute ( m , face , wa . wn , wa . wnsrc , ff , jj + wa . offnm , tt ) ;
if ( tri : : HasPerWedgeColor ( m ) ) WedgeColorAttribute ( m , face , wa . wc , wa . wcsrc , ff , jj + wa . offcl , tt ) ;
if ( tri : : HasPerWedgeTexCoord ( m ) & & ind_txt ! = - 1 )
{
WedgeTextureAttribute ( m , face , ind_txt , wa . wt , wa . wtsrc , ff , jj + wa . offtx , tt , wa . stride ) ;
}
* * * * * * * * * * * * * * * */
jj + = faceAttributeNum ;
}
AddPolygonToMesh ( polyTemp , m ) ;
}
}
}
QDEBUG ( " ****** LoadPolygonalListMesh (final mesh size vn %i vertsize %i - fn %i facesize %i) " , m . vn , m . vert . size ( ) , m . fn , m . face . size ( ) ) ;
return E_NOERROR ;
}
2009-04-06 01:30:29 +02:00
static DAEError AddPolygonToMesh ( MyPolygon < typename ColladaMesh : : VertexType > & polyTemp , ColladaMesh & m )
2009-04-04 19:25:57 +02:00
{
int vertNum = polyTemp . _pv . size ( ) ;
int triNum = vertNum - 2 ;
2009-04-06 01:30:29 +02:00
typename ColladaMesh : : FaceIterator fp = vcg : : tri : : Allocator < ColladaMesh > : : AddFaces ( m , triNum ) ;
2009-04-04 19:25:57 +02:00
// Very simple fan triangulation of the polygon.
for ( int i = 0 ; i < triNum ; + + i )
{
assert ( fp ! = m . face . end ( ) ) ;
( * fp ) . V ( 0 ) = polyTemp . _pv [ 0 ] ;
( * fp ) . WT ( 0 ) = polyTemp . _txc [ 0 ] ;
( * fp ) . V ( 1 ) = polyTemp . _pv [ i + 1 ] ;
( * fp ) . WT ( 1 ) = polyTemp . _txc [ i + 1 ] ;
( * fp ) . V ( 2 ) = polyTemp . _pv [ i + 2 ] ;
( * fp ) . WT ( 2 ) = polyTemp . _txc [ i + 2 ] ;
+ + fp ;
}
assert ( fp = = m . face . end ( ) ) ;
2009-04-21 07:58:08 +02:00
return E_NOERROR ;
2009-04-04 19:25:57 +02:00
}
2009-11-24 11:21:29 +01:00
static DAEError OldLoadPolygonalListMesh ( QDomNodeList & polylist , ColladaMesh & m , const size_t offset , InfoDAE & info )
2007-08-16 18:09:23 +02:00
{
2009-04-06 01:30:29 +02:00
typedef PolygonalMesh < MyPolygon < typename ColladaMesh : : VertexType > > PolyMesh ;
2007-09-27 15:53:32 +02:00
PolyMesh pm ;
2007-12-18 12:06:46 +01:00
//copying vertices
2009-04-06 01:30:29 +02:00
for ( typename ColladaMesh : : VertexIterator itv = m . vert . begin ( ) ; itv ! = m . vert . end ( ) ; + + itv )
2007-08-16 18:09:23 +02:00
{
vcg : : Point3f p ( itv - > P ( ) . X ( ) , itv - > P ( ) . Y ( ) , itv - > P ( ) . Z ( ) ) ;
2007-10-02 09:52:00 +02:00
typename PolyMesh : : VertexType v ;
2007-09-27 15:53:32 +02:00
v . P ( ) = p ;
pm . vert . push_back ( v ) ;
2007-08-16 18:09:23 +02:00
}
2007-12-18 12:06:46 +01:00
2007-08-16 18:09:23 +02:00
int polylist_size = polylist . size ( ) ;
for ( int pl = 0 ; pl < polylist_size ; + + pl )
{
2007-12-18 12:06:46 +01:00
QString mat = polylist . at ( pl ) . toElement ( ) . attribute ( QString ( " material " ) ) ;
2008-07-20 23:25:09 +02:00
QString textureFilename ;
2009-11-24 11:21:29 +01:00
QDomNode txt_node = textureFinder ( mat , textureFilename , * ( info . doc ) ) ;
2007-12-18 12:06:46 +01:00
int ind_txt = - 1 ;
if ( ! txt_node . isNull ( ) )
2009-11-24 11:21:29 +01:00
ind_txt = indexTextureByImgNode ( * ( info . doc ) , txt_node ) ;
2007-12-18 12:06:46 +01:00
//PolyMesh::PERWEDGEATTRIBUTETYPE att = PolyMesh::NONE;
2007-08-16 18:09:23 +02:00
WedgeAttribute wa ;
2009-11-24 11:21:29 +01:00
FindStandardWedgeAttributes ( wa , polylist . at ( pl ) , * ( info . doc ) ) ;
2007-08-16 18:09:23 +02:00
QStringList vertcount ;
valueStringList ( vertcount , polylist . at ( pl ) , " vcount " ) ;
int indforpol = findOffSetForASingleSimplex ( polylist . at ( pl ) ) ;
int offpols = 0 ;
int npolig = vertcount . size ( ) ;
QStringList polyind ;
valueStringList ( polyind , polylist . at ( pl ) , " p " ) ;
2007-12-18 12:06:46 +01:00
for ( int ii = 0 ; ii < npolig ; + + ii )
2007-08-16 18:09:23 +02:00
{
int nvert = vertcount . at ( ii ) . toInt ( ) ;
2007-09-27 15:53:32 +02:00
typename PolyMesh : : FaceType p ( nvert ) ;
2007-12-18 12:06:46 +01:00
for ( int iv = 0 ; iv < nvert ; + + iv )
2007-08-16 18:09:23 +02:00
{
int index = offset + polyind . at ( offpols + iv * indforpol ) . toInt ( ) ;
p . _pv [ iv ] = & ( pm . vert [ index ] ) ;
2007-09-27 15:53:32 +02:00
int nmindex = - 1 ;
2007-12-18 12:06:46 +01:00
if ( ! wa . wnsrc . isNull ( ) )
2007-09-27 15:53:32 +02:00
nmindex = offset + polyind . at ( offpols + iv * indforpol + wa . offnm ) . toInt ( ) ;
int txindex = - 1 ;
if ( ! wa . wtsrc . isNull ( ) )
{
txindex = offset + polyind . at ( offpols + iv * indforpol + wa . offtx ) . toInt ( ) ;
2007-12-18 12:06:46 +01:00
/*p._txc[iv].U() = wa.wt.at(txindex * 2).toFloat();
p . _txc [ iv ] . V ( ) = wa . wt . at ( txindex * 2 + 1 ) . toFloat ( ) ;
p . _txc [ iv ] . N ( ) = ind_txt ; */
2007-09-27 15:53:32 +02:00
}
2007-08-16 18:09:23 +02:00
}
pm . _pols . push_back ( p ) ;
offpols + = nvert * indforpol ;
}
}
pm . triangulate ( m ) ;
return E_NOERROR ;
}
2008-07-20 23:25:09 +02:00
/*
Called to load into a given mesh
*/
2009-11-24 11:21:29 +01:00
static DAEError LoadTriangularMesh ( QDomNodeList & triNodeList , ColladaMesh & m , const size_t offset , InfoDAE & info , QMap < QString , QString > & materialBinding )
2007-08-16 18:09:23 +02:00
{
2009-04-04 19:25:57 +02:00
if ( triNodeList . isEmpty ( ) ) return E_NOERROR ;
2008-07-20 23:25:09 +02:00
QDEBUG ( " ****** LoadTriangularMesh (initial mesh size %i %i) " , m . vn , m . fn ) ;
for ( int tript = 0 ; tript < triNodeList . size ( ) ; + + tript )
2007-08-16 18:09:23 +02:00
{
2008-07-20 23:25:09 +02:00
QString materialId = triNodeList . at ( tript ) . toElement ( ) . attribute ( QString ( " material " ) ) ;
QDEBUG ( " ****** material id '%s' -> '%s' " , qPrintable ( materialId ) , qPrintable ( materialBinding [ materialId ] ) ) ;
QString textureFilename ;
2009-11-24 11:21:29 +01:00
QDomNode img_node = textureFinder ( materialBinding [ materialId ] , textureFilename , * ( info . doc ) ) ;
2008-07-20 23:25:09 +02:00
if ( img_node . isNull ( ) )
{
QDEBUG ( " ****** but we were not able to find the corresponding image node " ) ;
}
2007-09-25 12:29:29 +02:00
2008-07-20 23:25:09 +02:00
int ind_txt = - 1 ;
if ( ! img_node . isNull ( ) )
{
2009-11-24 11:21:29 +01:00
if ( info . textureIdMap . contains ( textureFilename ) )
ind_txt = info . textureIdMap [ textureFilename ] ;
2008-07-20 23:25:09 +02:00
else
{
QDEBUG ( " Found use of Texture %s, adding it to texutres " , qPrintable ( textureFilename ) ) ;
2009-11-24 11:21:29 +01:00
info . textureIdMap [ textureFilename ] = m . textures . size ( ) ;
2008-07-20 23:25:09 +02:00
m . textures . push_back ( qPrintable ( textureFilename ) ) ;
2009-11-24 11:21:29 +01:00
ind_txt = info . textureIdMap [ textureFilename ] ;
2008-07-20 23:25:09 +02:00
}
2009-11-24 11:21:29 +01:00
// ind_txt = indexTextureByImgNode(*(info.doc),txt_node);
2008-07-20 23:25:09 +02:00
}
int faceAttributeNum = triNodeList . at ( tript ) . toElement ( ) . elementsByTagName ( " input " ) . size ( ) ;
2007-08-16 18:09:23 +02:00
QStringList face ;
2008-07-20 23:25:09 +02:00
valueStringList ( face , triNodeList . at ( tript ) , " p " ) ;
2007-08-16 18:09:23 +02:00
int offsetface = ( int ) m . face . size ( ) ;
2008-07-20 23:25:09 +02:00
if ( face . size ( ) ! = 0 )
2008-02-05 00:50:07 +01:00
{
2009-04-06 01:30:29 +02:00
vcg : : tri : : Allocator < ColladaMesh > : : AddFaces ( m , face . size ( ) / ( faceAttributeNum * 3 ) ) ;
2008-02-05 00:50:07 +01:00
WedgeAttribute wa ;
2009-11-24 11:21:29 +01:00
FindStandardWedgeAttributes ( wa , triNodeList . at ( tript ) , * ( info . doc ) ) ;
2008-02-05 00:50:07 +01:00
int jj = 0 ;
for ( int ff = offsetface ; ff < ( int ) m . face . size ( ) ; + + ff )
{
for ( unsigned int tt = 0 ; tt < 3 ; + + tt )
{
int indvt = face . at ( jj ) . toInt ( ) ;
assert ( indvt + offset < m . vert . size ( ) ) ;
m . face [ ff ] . V ( tt ) = & ( m . vert [ indvt + offset ] ) ;
2007-08-16 18:09:23 +02:00
2008-07-20 23:25:09 +02:00
if ( tri : : HasPerWedgeNormal ( m ) ) WedgeNormalAttribute ( m , face , wa . wn , wa . wnsrc , ff , jj + wa . offnm , tt ) ;
2011-03-23 22:00:40 +01:00
if ( tri : : HasPerVertexColor ( m ) ) VertexColorAttribute ( m , face , wa . wc , wa . wcsrc , ff , jj + wa . offcl , indvt + offset , tt ) ;
2008-07-20 23:25:09 +02:00
2008-02-05 00:50:07 +01:00
if ( tri : : HasPerWedgeTexCoord ( m ) & & ind_txt ! = - 1 )
{
WedgeTextureAttribute ( m , face , ind_txt , wa . wt , wa . wtsrc , ff , jj + wa . offtx , tt , wa . stride ) ;
}
2007-08-16 18:09:23 +02:00
2008-07-20 23:25:09 +02:00
jj + = faceAttributeNum ;
2007-12-18 12:06:46 +01:00
}
2009-12-07 09:31:44 +01:00
if ( ! ( ( m . face [ ff ] . V ( 0 ) ! = m . face [ ff ] . V ( 1 ) ) & &
( m . face [ ff ] . V ( 0 ) ! = m . face [ ff ] . V ( 2 ) ) & &
( m . face [ ff ] . V ( 1 ) ! = m . face [ ff ] . V ( 2 ) ) ) )
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 ( ) ) ;
2007-08-16 18:09:23 +02:00
}
}
}
2008-07-20 23:25:09 +02:00
QDEBUG ( " ****** LoadTriangularMesh (final mesh size %i %i - %i %i) " , m . vn , m . vert . size ( ) , m . fn , m . face . size ( ) ) ;
2007-08-16 18:09:23 +02:00
return E_NOERROR ;
}
2009-11-24 11:21:29 +01:00
static int LoadControllerMesh ( ColladaMesh & m , InfoDAE & info , const QDomElement & geo , QMap < QString , QString > materialBindingMap , CallBackPos * cb = 0 )
2008-07-15 09:27:08 +02:00
{
2010-05-22 21:47:43 +02:00
( void ) cb ;
2008-07-15 09:27:08 +02:00
assert ( geo . tagName ( ) = = " controller " ) ;
QDomNodeList skinList = geo . toElement ( ) . elementsByTagName ( " skin " ) ;
if ( skinList . size ( ) ! = 1 ) return E_CANTOPEN ;
QDomElement skinNode = skinList . at ( 0 ) . toElement ( ) ;
QString geomNode_url ;
referenceToANodeAttribute ( skinNode , " source " , geomNode_url ) ;
QDEBUG ( " Found a controller referencing a skin with url '%s' " , qPrintable ( geomNode_url ) ) ;
2009-11-24 11:21:29 +01:00
QDomNode refNode = findNodeBySpecificAttributeValue ( * ( info . doc ) , " geometry " , " id " , geomNode_url ) ;
2008-07-20 23:25:09 +02:00
QDomNodeList bindingNodes = skinNode . toElement ( ) . elementsByTagName ( " bind_material " ) ;
if ( bindingNodes . size ( ) > 0 ) {
QDEBUG ( " ** skin node of a controller has a material binding " ) ;
GenerateMaterialBinding ( skinNode , materialBindingMap ) ;
}
2009-05-29 18:29:14 +02:00
return LoadGeometry ( m , info , refNode . toElement ( ) , materialBindingMap ) ;
}
2008-07-15 09:27:08 +02:00
2008-07-20 23:25:09 +02:00
/* before instancing a geometry you can make a binding that allow you to substitute next material names with other names.
this is very useful for instancing the same geometry with different materials . therefore when you encounter a material name in a mesh , this name can be a ' symbol ' that you have to bind .
*/
static bool GenerateMaterialBinding ( QDomNode instanceGeomNode , QMap < QString , QString > & binding )
{
QDomNodeList instanceMaterialList = instanceGeomNode . toElement ( ) . elementsByTagName ( " instance_material " ) ;
QDEBUG ( " ++++ Found %i instance_material binding " , instanceMaterialList . size ( ) ) ;
for ( int i = 0 ; i < instanceMaterialList . size ( ) ; + + i )
{
QString symbol = instanceMaterialList . at ( i ) . toElement ( ) . attribute ( " symbol " ) ;
QString target = instanceMaterialList . at ( i ) . toElement ( ) . attribute ( " target " ) ;
binding [ symbol ] = target ;
QDEBUG ( " ++++++ %s -> %s " , qPrintable ( symbol ) , qPrintable ( target ) ) ;
}
return true ;
}
2008-07-15 09:27:08 +02:00
/*
2008-07-20 23:25:09 +02:00
Basic function that get in input a node < geometry > with a map from material names to texture names .
this map is necessary because when using a geometry when it is instanced its material can be bind with different names .
if the map fails you should directly search in the material library .
2008-07-15 09:27:08 +02:00
*/
2008-07-20 23:25:09 +02:00
2009-11-24 11:21:29 +01:00
static int LoadGeometry ( ColladaMesh & m , InfoDAE & info , const QDomElement & geo , QMap < QString , QString > & materialBinding , CallBackPos * cb = 0 )
2006-11-05 16:40:51 +01:00
{
2008-07-15 09:27:08 +02:00
assert ( geo . tagName ( ) = = " geometry " ) ;
2008-07-20 23:25:09 +02:00
if ( ! isThereTag ( geo , " mesh " ) ) return E_NOMESH ;
2009-11-24 11:21:29 +01:00
if ( ( cb ! = NULL ) & & ( ( ( info . numvert + info . numface ) % 100 ) = = 0 ) & & ! ( * cb ) ( ( 100 * ( info . numvert + info . numface ) ) / ( info . numvert + info . numface ) , " Vertex Loading " ) )
2006-11-05 16:40:51 +01:00
return E_CANTOPEN ;
2008-07-20 23:25:09 +02:00
QDEBUG ( " **** Loading a Geometry Mesh **** (initial mesh size %i %i) " , m . vn , m . fn ) ;
QDomNodeList vertices = geo . toElement ( ) . elementsByTagName ( " vertices " ) ;
if ( vertices . size ( ) ! = 1 ) return E_INCOMPATIBLECOLLADA141FORMAT ;
QDomElement vertNode = vertices . at ( 0 ) . toElement ( ) ;
2009-11-24 11:21:29 +01:00
QDomNode positionNode = attributeSourcePerSimplex ( vertNode , * ( info . doc ) , " POSITION " ) ;
2008-07-20 23:25:09 +02:00
if ( positionNode . isNull ( ) ) return E_NOVERTEXPOSITION ;
QStringList geosrcposarr ;
valueStringList ( geosrcposarr , positionNode , " float_array " ) ;
int geosrcposarr_size = geosrcposarr . size ( ) ;
if ( ( geosrcposarr_size % 3 ) ! = 0 )
return E_CANTOPEN ;
int nvert = geosrcposarr_size / 3 ;
size_t offset = m . vert . size ( ) ;
if ( geosrcposarr_size ! = 0 )
{
2009-04-06 01:30:29 +02:00
vcg : : tri : : Allocator < ColladaMesh > : : AddVertices ( m , nvert ) ;
2006-11-05 16:40:51 +01:00
2009-11-24 11:21:29 +01:00
QDomNode srcnodenorm = attributeSourcePerSimplex ( vertices . at ( 0 ) , * ( info . doc ) , " NORMAL " ) ;
2006-11-09 03:24:41 +01:00
QStringList geosrcvertnorm ;
2006-11-05 16:40:51 +01:00
if ( ! srcnodenorm . isNull ( ) )
2006-11-09 03:24:41 +01:00
valueStringList ( geosrcvertnorm , srcnodenorm , " float_array " ) ;
2006-11-05 16:40:51 +01:00
2009-11-24 11:21:29 +01:00
QDomNode srcnodetext = attributeSourcePerSimplex ( vertices . at ( 0 ) , * ( info . doc ) , " TEXCOORD " ) ;
2006-11-09 03:24:41 +01:00
QStringList geosrcverttext ;
2006-11-05 16:40:51 +01:00
if ( ! srcnodetext . isNull ( ) )
2006-11-09 03:24:41 +01:00
valueStringList ( geosrcverttext , srcnodetext , " float_array " ) ;
2009-11-24 11:21:29 +01:00
QDomNode srcnodecolor = attributeSourcePerSimplex ( vertices . at ( 0 ) , * ( info . doc ) , " COLOR " ) ;
2006-11-09 03:24:41 +01:00
QStringList geosrcvertcol ;
if ( ! srcnodecolor . isNull ( ) )
valueStringList ( geosrcvertcol , srcnodecolor , " float_array " ) ;
int ii = 0 ;
for ( size_t vv = offset ; vv < m . vert . size ( ) ; + + vv )
2008-07-15 09:27:08 +02:00
{
Point3f positionCoord ( geosrcposarr [ ii * 3 ] . toFloat ( ) , geosrcposarr [ ii * 3 + 1 ] . toFloat ( ) , geosrcposarr [ ii * 3 + 2 ] . toFloat ( ) ) ;
m . vert [ vv ] . P ( ) = positionCoord ;
2006-11-05 16:40:51 +01:00
2006-11-09 03:24:41 +01:00
if ( ! srcnodenorm . isNull ( ) )
{
2008-07-15 09:27:08 +02:00
Point3f normalCoord ( geosrcvertnorm [ ii * 3 ] . toFloat ( ) ,
geosrcvertnorm [ ii * 3 + 1 ] . toFloat ( ) ,
geosrcvertnorm [ ii * 3 + 2 ] . toFloat ( ) ) ;
normalCoord . Normalize ( ) ;
m . vert [ vv ] . N ( ) = normalCoord ;
2006-11-09 03:24:41 +01:00
}
2006-11-05 16:40:51 +01:00
2011-03-23 22:00:40 +01:00
if ( ! srcnodecolor . isNull ( ) )
2006-11-09 03:24:41 +01:00
{
2011-03-23 22:00:40 +01:00
//assert((ii * 4 < geosrcvertcol.size()) && (ii * 4 + 1 < geosrcvertcol.size()) && (ii * 4 + 2 < geosrcvertcol.size()) && (ii * 4 + 1 < geosrcvertcol.size()));
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 , 1.0 ) ;
}
2006-11-05 16:40:51 +01:00
2006-11-09 03:24:41 +01:00
if ( ! srcnodetext . isNull ( ) )
{
2007-12-18 12:06:46 +01:00
2006-11-09 03:24:41 +01:00
assert ( ( ii * 2 < geosrcverttext . size ( ) ) & & ( ii * 2 + 1 < geosrcverttext . size ( ) ) ) ;
2007-03-12 17:40:17 +01:00
m . vert [ vv ] . T ( ) = vcg : : TexCoord2 < float > ( ) ;
2006-11-09 03:24:41 +01:00
m . vert [ vv ] . T ( ) . u ( ) = geosrcverttext [ ii * 2 ] . toFloat ( ) ;
m . vert [ vv ] . T ( ) . v ( ) = geosrcverttext [ ii * 2 + 1 ] . toFloat ( ) ;
}
+ + ii ;
2006-11-05 16:40:51 +01:00
}
2006-11-09 03:24:41 +01:00
QDomNodeList tripatch = geo . toElement ( ) . elementsByTagName ( " triangles " ) ;
2007-08-16 18:09:23 +02:00
QDomNodeList polypatch = geo . toElement ( ) . elementsByTagName ( " polygons " ) ;
QDomNodeList polylist = geo . toElement ( ) . elementsByTagName ( " polylist " ) ;
2011-03-23 22:00:40 +01:00
QStringList vertcount ;
valueStringList ( vertcount , polylist . at ( 0 ) , " vcount " ) ;
int isTri = true ;
for ( int i = 0 ; i < vertcount . size ( ) ; i + + )
{
if ( vertcount [ i ] ! = " 3 " )
{
isTri = false ;
break ;
}
}
if ( isTri & & tripatch . isEmpty ( ) )
tripatch = polylist ;
2008-07-20 23:25:09 +02:00
if ( tripatch . isEmpty ( ) & & polypatch . isEmpty ( ) & & polylist . isEmpty ( ) )
2007-08-16 18:09:23 +02:00
return E_NOPOLYGONALMESH ;
DAEError err = E_NOERROR ;
2008-07-20 23:25:09 +02:00
err = LoadTriangularMesh ( tripatch , m , offset , info , materialBinding ) ;
//err = LoadPolygonalMesh(polypatch,m,offset,info);
2009-04-04 19:25:57 +02:00
// err = OldLoadPolygonalListMesh(polylist,m,offset,info);
2011-03-23 22:00:40 +01:00
err = LoadPolygonalListMesh ( polylist , m , offset , info , materialBinding ) ;
2008-02-05 00:50:07 +01:00
if ( err ! = E_NOERROR )
return err ;
2006-11-05 16:40:51 +01:00
}
2008-07-20 23:25:09 +02:00
QDEBUG ( " **** Loading a Geometry Mesh **** (final mesh size %i %i - %i %i) " , m . vn , m . vert . size ( ) , m . fn , m . face . size ( ) ) ;
return E_NOERROR ;
2006-11-05 16:40:51 +01:00
}
2006-11-06 10:31:43 +01:00
2008-07-20 23:25:09 +02:00
static void GetTexCoord ( const QDomDocument & doc , QStringList & texturefile )
2006-11-06 10:31:43 +01:00
{
QDomNodeList txlst = doc . elementsByTagName ( " library_images " ) ;
2007-09-19 13:18:08 +02:00
for ( int img = 0 ; img < txlst . at ( 0 ) . childNodes ( ) . size ( ) ; + + img )
2006-11-06 10:31:43 +01:00
{
2007-09-19 13:18:08 +02:00
QDomNodeList nlst = txlst . at ( 0 ) . childNodes ( ) . at ( img ) . toElement ( ) . elementsByTagName ( " init_from " ) ;
2006-11-06 10:31:43 +01:00
if ( nlst . size ( ) > 0 )
{
2009-05-12 16:03:48 +02:00
texturefile . push_back ( nlst . at ( 0 ) . firstChild ( ) . nodeValue ( ) ) ;
2006-11-06 10:31:43 +01:00
}
}
}
2006-11-08 17:59:22 +01:00
2008-07-15 09:27:08 +02:00
// This recursive function add to a mesh the subtree starting from the passed node.
// When you start from a visual_scene, you can find nodes.
// nodes can be directly instanced or referred from the node library.
static void AddNodeToMesh ( QDomElement node ,
2009-04-06 01:30:29 +02:00
ColladaMesh & m , Matrix44f curTr ,
2009-11-24 11:21:29 +01:00
InfoDAE & info )
2008-07-15 09:27:08 +02:00
{
QDEBUG ( " Starting processing <node> with id %s " , qPrintable ( node . attribute ( " id " ) ) ) ;
curTr = curTr * getTransfMatrixFromNode ( node ) ;
QDomNodeList geomNodeList = node . elementsByTagName ( " instance_geometry " ) ;
for ( int ch = 0 ; ch < geomNodeList . size ( ) ; + + ch )
{
QDomElement instGeomNode = geomNodeList . at ( ch ) . toElement ( ) ;
if ( instGeomNode . parentNode ( ) = = node ) // process only direct child
{
2008-07-20 23:25:09 +02:00
QDEBUG ( " ** instance_geometry with url %s (intial mesh size %i %i T = %i) " , qPrintable ( instGeomNode . attribute ( " url " ) ) , m . vn , m . fn , m . textures . size ( ) ) ;
//assert(m.textures.size()>0 == HasPerWedgeTexCoord(m));
2008-07-15 09:27:08 +02:00
QString geomNode_url ;
referenceToANodeAttribute ( instGeomNode , " url " , geomNode_url ) ;
2009-11-24 11:21:29 +01:00
QDomNode refNode = findNodeBySpecificAttributeValue ( * ( info . doc ) , " geometry " , " id " , geomNode_url ) ;
2008-07-20 23:25:09 +02:00
QDomNodeList bindingNodes = instGeomNode . toElement ( ) . elementsByTagName ( " bind_material " ) ;
QMap < QString , QString > materialBindingMap ;
if ( bindingNodes . size ( ) > 0 ) {
QDEBUG ( " ** instance_geometry has a material binding " ) ;
GenerateMaterialBinding ( instGeomNode , materialBindingMap ) ;
}
2008-07-15 09:27:08 +02:00
2009-04-06 01:30:29 +02:00
ColladaMesh newMesh ;
// newMesh.face.EnableWedgeTex();
2008-07-20 23:25:09 +02:00
LoadGeometry ( newMesh , info , refNode . toElement ( ) , materialBindingMap ) ;
2009-04-06 01:30:29 +02:00
tri : : UpdatePosition < ColladaMesh > : : Matrix ( newMesh , curTr ) ;
2010-06-18 10:35:36 +02:00
tri : : Append < ColladaMesh , ColladaMesh > : : Mesh ( m , newMesh ) ;
2008-07-20 23:25:09 +02:00
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 ( ) ) ;
2008-07-15 09:27:08 +02:00
}
}
QDomNodeList controllerNodeList = node . elementsByTagName ( " instance_controller " ) ;
for ( int ch = 0 ; ch < controllerNodeList . size ( ) ; + + ch )
{
QDomElement instContrNode = controllerNodeList . at ( ch ) . toElement ( ) ;
if ( instContrNode . parentNode ( ) = = node ) // process only direct child
{
QDEBUG ( " Found a instance_controller with url %s " , qPrintable ( instContrNode . attribute ( " url " ) ) ) ;
QString controllerNode_url ;
referenceToANodeAttribute ( instContrNode , " url " , controllerNode_url ) ;
QDEBUG ( " Found a instance_controller with url '%s' " , qPrintable ( controllerNode_url ) ) ;
2009-11-24 11:21:29 +01:00
QDomNode refNode = findNodeBySpecificAttributeValue ( * ( info . doc ) , " controller " , " id " , controllerNode_url ) ;
2008-07-15 09:27:08 +02:00
2008-07-21 15:25:32 +02:00
QDomNodeList bindingNodes = instContrNode . toElement ( ) . elementsByTagName ( " bind_material " ) ;
QMap < QString , QString > materialBindingMap ;
if ( bindingNodes . size ( ) > 0 ) {
QDEBUG ( " ** instance_controller node of has a material binding " ) ;
GenerateMaterialBinding ( instContrNode , materialBindingMap ) ;
}
2009-04-06 01:30:29 +02:00
ColladaMesh newMesh ;
2008-07-21 15:25:32 +02:00
LoadControllerMesh ( newMesh , info , refNode . toElement ( ) , materialBindingMap ) ;
2009-04-06 01:30:29 +02:00
tri : : UpdatePosition < ColladaMesh > : : Matrix ( newMesh , curTr ) ;
tri : : Append < ColladaMesh , ColladaMesh > : : Mesh ( m , newMesh ) ;
2008-07-15 09:27:08 +02:00
}
}
QDomNodeList nodeNodeList = node . elementsByTagName ( " node " ) ;
for ( int ch = 0 ; ch < nodeNodeList . size ( ) ; + + ch )
{
if ( nodeNodeList . at ( ch ) . parentNode ( ) = = node ) // process only direct child
AddNodeToMesh ( nodeNodeList . at ( ch ) . toElement ( ) , m , curTr , info ) ;
}
QDomNodeList instanceNodeList = node . elementsByTagName ( " instance_node " ) ;
for ( int ch = 0 ; ch < instanceNodeList . size ( ) ; + + ch )
{
if ( instanceNodeList . at ( ch ) . parentNode ( ) = = node ) // process only direct child
{
QDomElement instanceNode = instanceNodeList . at ( ch ) . toElement ( ) ;
QString node_url ;
referenceToANodeAttribute ( instanceNode , " url " , node_url ) ;
QDEBUG ( " Found a instance_node with url '%s' " , qPrintable ( node_url ) ) ;
2009-11-24 11:21:29 +01:00
QDomNode refNode = findNodeBySpecificAttributeValue ( * ( info . doc ) , " node " , " id " , node_url ) ;
2008-07-15 09:27:08 +02:00
if ( refNode . isNull ( ) )
QDEBUG ( " findNodeBySpecificAttributeValue returned a null node for %s " , qPrintable ( node_url ) ) ;
AddNodeToMesh ( refNode . toElement ( ) , m , curTr , info ) ;
}
}
}
// Retrieve the transformation matrix that is defined in the childs of a node.
// used during the recursive descent.
static Matrix44f getTransfMatrixFromNode ( const QDomElement parentNode )
{
QDEBUG ( " getTrans form node with tag %s " , qPrintable ( parentNode . tagName ( ) ) ) ;
assert ( parentNode . tagName ( ) = = " node " ) ;
std : : vector < QDomNode > rotationList ;
QDomNode matrixNode ;
QDomNode translationNode ;
for ( int ch = 0 ; ch < parentNode . childNodes ( ) . size ( ) ; + + ch )
{
if ( parentNode . childNodes ( ) . at ( ch ) . nodeName ( ) = = " rotate " )
rotationList . push_back ( parentNode . childNodes ( ) . at ( ch ) ) ;
if ( parentNode . childNodes ( ) . at ( ch ) . nodeName ( ) = = " translate " )
translationNode = parentNode . childNodes ( ) . at ( ch ) ;
if ( parentNode . childNodes ( ) . at ( ch ) . nodeName ( ) = = " matrix " )
matrixNode = parentNode . childNodes ( ) . at ( ch ) ;
}
Matrix44f rotM ; rotM . SetIdentity ( ) ;
Matrix44f transM ; transM . SetIdentity ( ) ;
if ( ! translationNode . isNull ( ) ) ParseTranslation ( transM , translationNode ) ;
if ( ! rotationList . empty ( ) ) ParseRotationMatrix ( rotM , rotationList ) ;
if ( ! matrixNode . isNull ( ) )
{
ParseMatrixNode ( transM , matrixNode ) ;
return transM ;
}
return transM * rotM ;
}
2006-11-02 19:15:55 +01:00
public :
2006-09-22 08:01:40 +02:00
2006-11-02 19:15:55 +01:00
//merge all meshes in the collada's file in the templeted mesh m
//I assume the mesh
2006-11-05 16:40:51 +01:00
2009-11-24 11:21:29 +01:00
static int Open ( OpenMeshType & m , const char * filename , InfoDAE & info , CallBackPos * cb = 0 )
2006-08-11 13:09:40 +02:00
{
2009-12-01 18:37:45 +01:00
( void ) cb ;
2008-07-15 09:27:08 +02:00
QDEBUG ( " ----- Starting the processing of %s ------ " , filename ) ;
2009-11-24 11:21:29 +01:00
//AdditionalInfoDAE& inf = new AdditionalInfoDAE();
//info = new InfoDAE();
2006-11-09 03:24:41 +01:00
2006-11-02 19:15:55 +01:00
QDomDocument * doc = new QDomDocument ( filename ) ;
2009-11-24 11:21:29 +01:00
info . doc = doc ;
2010-03-13 01:52:17 +01:00
QFile file ( filename ) ;
2006-11-02 19:15:55 +01:00
if ( ! file . open ( QIODevice : : ReadOnly ) )
return E_CANTOPEN ;
if ( ! doc - > setContent ( & file ) )
2006-08-11 13:09:40 +02:00
{
2006-11-02 19:15:55 +01:00
file . close ( ) ;
return E_CANTOPEN ;
2006-08-11 13:09:40 +02:00
}
2006-11-02 19:15:55 +01:00
file . close ( ) ;
2006-11-03 00:58:33 +01:00
2009-11-24 11:21:29 +01:00
//GetTexture(*(info.doc),inf);
2008-07-15 09:27:08 +02:00
2008-07-20 23:25:09 +02:00
// GenerateMaterialToTextureMap(info);
2008-02-28 11:44:47 +01:00
//scene->instance_visual_scene
2009-11-24 11:21:29 +01:00
QDomNodeList scenes = info . doc - > elementsByTagName ( " scene " ) ;
2006-11-02 19:15:55 +01:00
int scn_size = scenes . size ( ) ;
if ( scn_size = = 0 )
return E_NO3DSCENE ;
2008-07-15 09:27:08 +02:00
QDEBUG ( " File Contains %i Scenes " , scenes . size ( ) ) ;
2008-02-05 00:50:07 +01:00
int problem = E_NOERROR ;
2008-10-09 18:16:49 +02:00
//bool found_a_mesh = false;
2006-11-02 19:15:55 +01:00
//Is there geometry in the file?
2008-10-09 18:16:49 +02:00
//bool geoinst_found = false;
2008-07-15 09:27:08 +02:00
// The main loading loop
// for each scene in COLLADA FILE
/*
Some notes on collada structure .
2009-04-04 19:25:57 +02:00
top level nodes are :
< asset >
< library_images >
< library_materials >
< library_effects >
< library_geometries >
< library_visual_scene >
< scene >
The REAL top root is the < scene > that can contains one of more ( instance of ) < visual_scene > .
2008-07-15 09:27:08 +02:00
< visual_scene > can be directly written there ( check ! ) or instanced from their definition in the < library_visual_scene >
each < visual_scene > contains a hierarchy of < node >
each < node > contains
transformation
2009-04-04 19:25:57 +02:00
other nodes ( to build up a hierarchy )
2008-07-15 09:27:08 +02:00
instance of geometry
instance of controller
2009-04-04 19:25:57 +02:00
instance can be direct or refers name of stuff described in a library .
An instance of geometry node should contain the < mesh > node and as a son of the < instance geometry > the material node ( again referenced from a library )
- - structure of the geometry node - -
2008-07-15 09:27:08 +02:00
*/
2006-11-02 19:15:55 +01:00
for ( int scn = 0 ; scn < scn_size ; + + scn )
2006-08-11 13:09:40 +02:00
{
2006-11-07 18:22:53 +01:00
QDomNodeList instscenes = scenes . at ( scn ) . toElement ( ) . elementsByTagName ( " instance_visual_scene " ) ;
2006-11-02 19:15:55 +01:00
int instscn_size = instscenes . size ( ) ;
2008-07-15 09:27:08 +02:00
QDEBUG ( " Scene %i contains %i instance_visual_scene " , scn , instscn_size ) ;
if ( instscn_size = = 0 ) return E_INCOMPATIBLECOLLADA141FORMAT ;
2006-11-02 19:15:55 +01:00
//for each scene instance in a COLLADA scene
for ( int instscn = 0 ; instscn < instscn_size ; + + instscn )
2006-08-11 13:09:40 +02:00
{
2006-11-02 19:15:55 +01:00
QString libscn_url ;
referenceToANodeAttribute ( instscenes . at ( instscn ) , " url " , libscn_url ) ;
2008-07-15 09:27:08 +02:00
QDEBUG ( " instance_visual_scene %i refers %s " , instscn , qPrintable ( libscn_url ) ) ;
2008-07-20 23:25:09 +02:00
// QDomNode nd = QDomNode(*(inf->doc));
2009-11-24 11:21:29 +01:00
QDomNode visscn = findNodeBySpecificAttributeValue ( * ( info . doc ) , " visual_scene " , " id " , libscn_url ) ;
2008-07-15 09:27:08 +02:00
if ( visscn . isNull ( ) ) return E_UNREFERENCEBLEDCOLLADAATTRIBUTE ;
2006-08-11 13:09:40 +02:00
2008-07-15 09:27:08 +02:00
//assert (visscn.toElement().Attribute("id") == libscn_url);
2006-11-02 19:15:55 +01:00
//for each node in the libscn_url visual scene
2006-11-07 18:22:53 +01:00
QDomNodeList visscn_child = visscn . childNodes ( ) ;
2008-07-15 09:27:08 +02:00
QDEBUG ( " instance_visual_scene %s has %i children " , qPrintable ( libscn_url ) , visscn_child . size ( ) ) ;
2006-11-02 19:15:55 +01:00
2008-07-15 09:27:08 +02:00
// for each direct child of a visual scene process it
2006-11-02 19:15:55 +01:00
for ( int chdind = 0 ; chdind < visscn_child . size ( ) ; + + chdind )
2006-08-11 13:09:40 +02:00
{
2008-07-15 09:27:08 +02:00
QDomElement node = visscn_child . at ( chdind ) . toElement ( ) ;
if ( node . isNull ( ) ) continue ;
QDEBUG ( " Processing Visual Scene child %i - of type '%s' " , chdind , qPrintable ( node . tagName ( ) ) ) ;
Matrix44f baseTr ; baseTr . SetIdentity ( ) ;
if ( node . toElement ( ) . tagName ( ) = = " node " )
2009-04-06 01:30:29 +02:00
{
ColladaMesh newMesh ;
AddNodeToMesh ( node . toElement ( ) , newMesh , baseTr , info ) ;
2010-06-18 10:35:36 +02:00
tri : : Append < OpenMeshType , ColladaMesh > : : Mesh ( m , newMesh ) ;
2009-04-06 01:30:29 +02:00
}
2008-07-15 09:27:08 +02:00
} // end for each node of a given scene
} // end for each visual scene instance
} // end for each scene instance
2008-02-05 00:50:07 +01:00
return problem ;
2006-09-22 08:01:40 +02:00
}
2009-11-24 11:21:29 +01:00
static bool LoadMask ( const char * filename , InfoDAE & info )
2006-11-02 19:15:55 +01:00
{
bool bHasPerWedgeTexCoord = false ;
bool bHasPerWedgeNormal = false ;
2011-03-23 22:00:40 +01:00
//bool bHasPerWedgeColor = false;
2006-11-02 19:15:55 +01:00
bool bHasPerVertexColor = false ;
bool bHasPerFaceColor = false ;
2006-11-06 06:29:40 +01:00
bool bHasPerVertexNormal = false ;
bool bHasPerVertexText = false ;
2010-03-13 01:52:17 +01:00
QDomDocument * doc = new QDomDocument ( filename ) ;
2006-11-06 06:29:40 +01:00
QFile file ( filename ) ;
if ( ! file . open ( QIODevice : : ReadOnly ) )
2006-11-08 20:49:57 +01:00
return false ;
2006-11-06 06:29:40 +01:00
if ( ! doc - > setContent ( & file ) )
2006-09-22 08:01:40 +02:00
{
2006-11-06 06:29:40 +01:00
file . close ( ) ;
2006-11-08 20:49:57 +01:00
return false ;
2006-09-22 08:01:40 +02:00
}
2006-11-06 06:29:40 +01:00
file . close ( ) ;
2008-07-20 23:25:09 +02:00
QStringList textureFileList ;
2009-11-24 11:21:29 +01:00
info . doc = doc ;
GetTexCoord ( * ( info . doc ) , textureFileList ) ;
QDomNodeList scenes = info . doc - > elementsByTagName ( " scene " ) ;
2006-11-06 06:29:40 +01:00
int scn_size = scenes . size ( ) ;
2006-11-02 19:15:55 +01:00
2006-11-06 06:29:40 +01:00
//Is there geometry in the file?
bool geoinst_found = false ;
//for each scene in COLLADA FILE
for ( int scn = 0 ; scn < scn_size ; + + scn )
2006-09-22 08:01:40 +02:00
{
2006-11-07 18:22:53 +01:00
QDomNodeList instscenes = scenes . at ( scn ) . toElement ( ) . elementsByTagName ( " instance_visual_scene " ) ;
2006-11-06 06:29:40 +01:00
int instscn_size = instscenes . size ( ) ;
2008-07-15 09:27:08 +02:00
if ( instscn_size = = 0 ) return false ;
2006-11-02 19:15:55 +01:00
2006-11-06 06:29:40 +01:00
//for each scene instance in a COLLADA scene
for ( int instscn = 0 ; instscn < instscn_size ; + + instscn )
{
QString libscn_url ;
referenceToANodeAttribute ( instscenes . at ( instscn ) , " url " , libscn_url ) ;
2009-11-24 11:21:29 +01:00
QDomNode nd = QDomNode ( * ( info . doc ) ) ;
QDomNode visscn = findNodeBySpecificAttributeValue ( * ( info . doc ) , " visual_scene " , " id " , libscn_url ) ;
2008-07-15 09:27:08 +02:00
if ( visscn . isNull ( ) ) return false ;
2006-11-06 06:29:40 +01:00
//for each node in the libscn_url visual scene
2006-11-07 18:22:53 +01:00
//QDomNodeList& visscn_child = visscn.childNodes();
QDomNodeList visscn_child = visscn . childNodes ( ) ;
2006-11-06 06:29:40 +01:00
//for each direct child of a libscn_url visual scene find if there is some geometry instance
for ( int chdind = 0 ; chdind < visscn_child . size ( ) ; + + chdind )
2006-09-22 08:01:40 +02:00
{
2006-11-07 18:22:53 +01:00
//QDomNodeList& geoinst = visscn_child.at(chdind).toElement().elementsByTagName("instance_geometry");
QDomNodeList geoinst = visscn_child . at ( chdind ) . toElement ( ) . elementsByTagName ( " instance_geometry " ) ;
2006-11-06 06:29:40 +01:00
int geoinst_size = geoinst . size ( ) ;
if ( geoinst_size ! = 0 )
2006-11-02 19:15:55 +01:00
{
2006-11-06 06:29:40 +01:00
geoinst_found | = true ;
2009-11-24 11:21:29 +01:00
QDomNodeList geolib = info . doc - > elementsByTagName ( " library_geometries " ) ;
2010-10-13 14:53:30 +02:00
//assert(geolib.size() == 1);
if ( geolib . size ( ) ! = 1 )
return false ;
2006-11-06 06:29:40 +01:00
//!!!!!!!!!!!!!!!!!here will be the code for geometry transformations!!!!!!!!!!!!!!!!!!!!!!
2009-11-24 11:21:29 +01:00
info . numvert = 0 ;
info . numface = 0 ;
2006-11-06 06:29:40 +01:00
for ( int geoinst_ind = 0 ; geoinst_ind < geoinst_size ; + + geoinst_ind )
2006-11-02 19:15:55 +01:00
{
2006-11-06 06:29:40 +01:00
QString geo_url ;
referenceToANodeAttribute ( geoinst . at ( geoinst_ind ) , " url " , geo_url ) ;
QDomNode geo = findNodeBySpecificAttributeValue ( geolib . at ( 0 ) , " geometry " , " id " , geo_url ) ;
if ( geo . isNull ( ) )
2006-11-06 09:45:13 +01:00
return false ;
2006-11-06 06:29:40 +01:00
QDomNodeList vertlist = geo . toElement ( ) . elementsByTagName ( " vertices " ) ;
for ( int vert = 0 ; vert < vertlist . size ( ) ; + + vert )
{
QDomNode no ;
no = findNodeBySpecificAttributeValue ( vertlist . at ( vert ) , " input " , " semantic " , " POSITION " ) ;
QString srcurl ;
referenceToANodeAttribute ( no , " source " , srcurl ) ;
no = findNodeBySpecificAttributeValue ( geo , " source " , " id " , srcurl ) ;
QDomNodeList fa = no . toElement ( ) . elementsByTagName ( " float_array " ) ;
assert ( fa . size ( ) = = 1 ) ;
2009-11-24 11:21:29 +01:00
info . numvert + = ( fa . at ( 0 ) . toElement ( ) . attribute ( " count " ) . toInt ( ) / 3 ) ;
2006-11-06 06:29:40 +01:00
no = findNodeBySpecificAttributeValue ( vertlist . at ( vert ) , " input " , " semantic " , " COLOR " ) ;
if ( ! no . isNull ( ) )
bHasPerVertexColor = true ;
no = findNodeBySpecificAttributeValue ( vertlist . at ( vert ) , " input " , " semantic " , " NORMAL " ) ;
if ( ! no . isNull ( ) )
bHasPerVertexNormal = true ;
no = findNodeBySpecificAttributeValue ( vertlist . at ( vert ) , " input " , " semantic " , " TEXCOORD " ) ;
if ( ! no . isNull ( ) )
bHasPerVertexText = true ;
}
2007-08-16 18:09:23 +02:00
const char * arr [ ] = { " triangles " , " polylist " , " polygons " } ;
for ( unsigned int tt = 0 ; tt < 3 ; + + tt )
2006-11-06 06:29:40 +01:00
{
2007-08-16 18:09:23 +02:00
QDomNodeList facelist = geo . toElement ( ) . elementsByTagName ( arr [ tt ] ) ;
for ( int face = 0 ; face < facelist . size ( ) ; + + face )
{
2009-11-24 11:21:29 +01:00
info . numface + = facelist . at ( face ) . toElement ( ) . attribute ( " count " ) . toInt ( ) ;
2007-08-16 18:09:23 +02:00
QDomNode no ;
no = findNodeBySpecificAttributeValue ( facelist . at ( face ) , " input " , " semantic " , " NORMAL " ) ;
if ( ! no . isNull ( ) )
bHasPerWedgeNormal = true ;
2011-03-23 22:00:40 +01:00
no = findNodeBySpecificAttributeValue ( facelist . at ( face ) , " input " , " semantic " , " COLOR " ) ;
if ( ! no . isNull ( ) )
bHasPerVertexColor = true ;
2007-08-16 18:09:23 +02:00
no = findNodeBySpecificAttributeValue ( facelist . at ( face ) , " input " , " semantic " , " TEXCOORD " ) ;
if ( ! no . isNull ( ) )
bHasPerWedgeTexCoord = true ;
}
2006-11-06 06:29:40 +01:00
}
2006-11-02 19:15:55 +01:00
}
}
2006-09-22 08:01:40 +02:00
}
}
}
2006-11-06 09:45:13 +01:00
if ( ! geoinst_found )
{
2009-11-24 11:21:29 +01:00
QDomNodeList geolib = info . doc - > elementsByTagName ( " library_geometries " ) ;
2010-10-13 14:53:30 +02:00
//assert(geolib.size() == 1);
if ( geolib . size ( ) ! = 1 )
return false ;
2006-11-07 18:22:53 +01:00
QDomNodeList geochild = geolib . at ( 0 ) . toElement ( ) . elementsByTagName ( " geometry " ) ;
2006-11-06 09:45:13 +01:00
//!!!!!!!!!!!!!!!!!here will be the code for geometry transformations!!!!!!!!!!!!!!!!!!!!!!
2009-11-24 11:21:29 +01:00
info . numvert = 0 ;
info . numface = 0 ;
2006-11-06 09:45:13 +01:00
for ( int geoinst_ind = 0 ; geoinst_ind < geochild . size ( ) ; + + geoinst_ind )
{
QDomNodeList vertlist = geochild . at ( geoinst_ind ) . toElement ( ) . elementsByTagName ( " vertices " ) ;
for ( int vert = 0 ; vert < vertlist . size ( ) ; + + vert )
{
QDomNode no ;
no = findNodeBySpecificAttributeValue ( vertlist . at ( vert ) , " input " , " semantic " , " POSITION " ) ;
QString srcurl ;
referenceToANodeAttribute ( no , " source " , srcurl ) ;
no = findNodeBySpecificAttributeValue ( geochild . at ( geoinst_ind ) , " source " , " id " , srcurl ) ;
QDomNodeList fa = no . toElement ( ) . elementsByTagName ( " float_array " ) ;
assert ( fa . size ( ) = = 1 ) ;
2009-11-24 11:21:29 +01:00
info . numvert + = ( fa . at ( 0 ) . toElement ( ) . attribute ( " count " ) . toInt ( ) / 3 ) ;
2006-11-06 09:45:13 +01:00
no = findNodeBySpecificAttributeValue ( vertlist . at ( vert ) , " input " , " semantic " , " COLOR " ) ;
if ( ! no . isNull ( ) )
bHasPerVertexColor = true ;
no = findNodeBySpecificAttributeValue ( vertlist . at ( vert ) , " input " , " semantic " , " NORMAL " ) ;
if ( ! no . isNull ( ) )
bHasPerVertexNormal = true ;
no = findNodeBySpecificAttributeValue ( vertlist . at ( vert ) , " input " , " semantic " , " TEXCOORD " ) ;
if ( ! no . isNull ( ) )
bHasPerVertexText = true ;
}
QDomNodeList facelist = geochild . at ( geoinst_ind ) . toElement ( ) . elementsByTagName ( " triangles " ) ;
for ( int face = 0 ; face < facelist . size ( ) ; + + face )
{
2009-11-24 11:21:29 +01:00
info . numface + = facelist . at ( face ) . toElement ( ) . attribute ( " count " ) . toInt ( ) ;
2006-11-06 09:45:13 +01:00
QDomNode no ;
no = findNodeBySpecificAttributeValue ( facelist . at ( face ) , " input " , " semantic " , " NORMAL " ) ;
if ( ! no . isNull ( ) )
bHasPerWedgeNormal = true ;
no = findNodeBySpecificAttributeValue ( facelist . at ( face ) , " input " , " semantic " , " TEXCOORD " ) ;
if ( ! no . isNull ( ) )
bHasPerWedgeTexCoord = true ;
}
}
}
2006-11-06 06:29:40 +01:00
2009-11-24 11:21:29 +01:00
info . mask = 0 ;
2006-11-06 09:45:13 +01:00
2006-11-06 06:29:40 +01:00
if ( bHasPerWedgeTexCoord )
2009-11-24 11:21:29 +01:00
info . mask | = vcg : : tri : : io : : Mask : : IOM_WEDGTEXCOORD ;
2006-11-06 06:29:40 +01:00
if ( bHasPerWedgeNormal )
2009-11-24 11:21:29 +01:00
info . mask | = vcg : : tri : : io : : Mask : : IOM_WEDGNORMAL ;
2006-11-06 06:29:40 +01:00
if ( bHasPerVertexColor )
2009-11-24 11:21:29 +01:00
info . mask | = vcg : : tri : : io : : Mask : : IOM_VERTCOLOR ;
2006-11-06 06:29:40 +01:00
if ( bHasPerFaceColor )
2009-11-24 11:21:29 +01:00
info . mask | = vcg : : tri : : io : : Mask : : IOM_FACECOLOR ;
2006-11-06 06:29:40 +01:00
if ( bHasPerVertexNormal )
2009-11-24 11:21:29 +01:00
info . mask | = vcg : : tri : : io : : Mask : : IOM_VERTNORMAL ;
2006-11-06 06:29:40 +01:00
if ( bHasPerVertexText )
2009-11-24 11:21:29 +01:00
info . mask | = vcg : : tri : : io : : Mask : : IOM_VERTTEXCOORD ;
2006-11-06 06:29:40 +01:00
2006-11-06 09:45:13 +01:00
2009-11-24 11:21:29 +01:00
delete ( info . doc ) ;
info . doc = NULL ;
//addinfo = info;
2006-11-02 19:15:55 +01:00
return true ;
2006-09-22 08:01:40 +02:00
}
} ;
2006-06-14 11:47:21 +02:00
}
}
}
2006-07-12 14:12:36 +02:00
# endif