1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2009 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 #if __GNUC__ >= 4 || __GNUC_MINOR__ >=3
40 #pragma GCC diagnostic ignored "-Wold-style-cast"
43 #include "OSGColladaGlobal.h"
45 #if defined(OSG_WITH_COLLADA) || defined(OSG_DO_DOC)
47 #include "OSGColladaLog.h"
48 #include "OSGColladaCOLLADA.h"
49 #include "OSGColladaInstInfo.h"
50 #include "OSGColladaElementFactory.h"
51 #include "OSGColladaOptions.h"
55 /*! \class OSG::ColladaGlobal
56 This is the entry point for the Collada loader from which the loading
58 You can think of it as representing the <COLLADA> tag in a document.
63 StatElemDesc
<StatIntElem
> ColladaGlobal::statNGeometryCreated(
64 "Collada::NGeometryCreated",
65 "Number of OpenSG geometries created by the collada loader",
66 StatElemDescBase::RESET_ALWAYS
);
67 StatElemDesc
<StatIntElem
> ColladaGlobal::statNGeometryUsed(
68 "Collada::NGeometryUsed",
69 "Number of OpenSG geometries in the scene created by the collada loader",
70 StatElemDescBase::RESET_ALWAYS
);
71 StatElemDesc
<StatIntElem
> ColladaGlobal::statNMaterialCreated(
72 "Collada::NMaterialCreated",
73 "Number of OpenSG materials created by the collada loader",
74 StatElemDescBase::RESET_ALWAYS
);
75 StatElemDesc
<StatIntElem
> ColladaGlobal::statNMaterialUsed(
76 "Collada::NMaterialUsed",
77 "Number of OpenSG materials in the scene created by the collada loader",
78 StatElemDescBase::RESET_ALWAYS
);
79 StatElemDesc
<StatIntElem
> ColladaGlobal::statNLightCreated(
80 "Collada::NLightCreated",
81 "Number of OpenSG lights created by the collada loader",
82 StatElemDescBase::RESET_ALWAYS
);
83 StatElemDesc
<StatIntElem
> ColladaGlobal::statNLightUsed(
84 "Collada::NLightUsed",
85 "Number of OpenSG lights in the scene created by the collada loader",
86 StatElemDescBase::RESET_ALWAYS
);
87 StatElemDesc
<StatIntElem
> ColladaGlobal::statNTextureCreated(
88 "Collada::NTextureCreated",
89 "Number of OpenSG textures created by the collada loader",
90 StatElemDescBase::RESET_ALWAYS
);
91 StatElemDesc
<StatIntElem
> ColladaGlobal::statNTextureUsed(
92 "Collada::NTextureUsed",
93 "Number of OpenSG textures in the scene created by the collada loader",
94 StatElemDescBase::RESET_ALWAYS
);
97 ColladaGlobal::getStatCollector(void)
103 ColladaGlobal::setStatCollector(StatCollector
*statColl
)
105 _statColl
= statColl
;
108 ColladaGlobalTransitPtr
109 ColladaGlobal::create(void)
111 return ColladaGlobalTransitPtr(new Self
);
114 /*! Read the file \a fileName using a new DAE database.
117 ColladaGlobal::read(std::istream
&is
, const std::string
&fileName
)
119 NodeTransitPtr rootN
;
121 _pathHandler
.clearPathList();
122 _pathHandler
.clearBaseFile();
124 _pathHandler
.push_frontCurrentDir( );
125 _pathHandler
.setBaseFile (fileName
.c_str());
130 _dae
->open(fileName
.c_str());
142 /*! Read the file \a fileName from the existing DAE database \a dae.
143 The given \a fileName must already be loaded into the DAE.
145 Useful if multiple documents are stored in one DAE database or
146 if an application needs to access the DAE itself to extract
147 data that is not processed by the loader.
150 ColladaGlobal::read(DAE
*dae
, const std::string
&fileName
)
152 NodeTransitPtr
rootN(NULL
);
154 _pathHandler
.clearPathList();
155 _pathHandler
.clearBaseFile();
157 _pathHandler
.push_frontCurrentDir( );
158 _pathHandler
.setBaseFile (fileName
.c_str());
172 ColladaGlobal::addElement(ColladaElement
*elem
)
174 _elemStore
.push_back(elem
);
178 * Helper function for de-mangling filepaths. Removes leading filepath
179 * separators and replaces escaped url characters (i.e. "%20" with " " (a
183 std::string
ColladaGlobal::fixFilepath(std::string filepath
)
186 std::string escaped
[] = {"%20", "%22", "%3C", "%3E", "%23", "%25", "%7B",
187 "%7D", "%7C", "%5E", "%7E", "%5B", "%5D", "%60"};
189 std::string replacements
[] = {" ","\"","<",">","#","%","{",
190 "}","|","^","~","[","]","`"};
192 // removing leading file path separators
193 while(filepath
[0] == '/' || filepath
[0] == '\\')
195 filepath
= filepath
.substr(1);
198 // remove escaped characters and replace
201 for(UInt32 i
= 0; i
< 14; ++i
)
205 pos
= filepath
.find(escaped
[i
], pos
);
207 if(pos
== std::string::npos
)
213 filepath
= filepath
.replace(pos
, 3, replacements
[i
]);
221 // re-formats an image filepath so that it can be read properly
222 std::string
ColladaGlobal::fixImageFilepath(std::string szImgPath
)
224 if(szImgPath
.substr(0, 5) == "file:")
226 szImgPath
= szImgPath
.substr(4);
229 return fixFilepath(szImgPath
);
232 std::string
ColladaGlobal::uriToNativePath(const std::string
&uriRef
,
233 cdom::systemType type
)
235 std::string scheme
, authority
, path
, query
, fragment
;
237 cdom::parseUriRef(uriRef
, scheme
, authority
, path
, query
, fragment
);
239 // Make sure we have a file scheme URI, or that it doesn't have a scheme
240 if (!scheme
.empty() && scheme
!= "file")
243 std::string filePath
;
246 fprintf(stderr
, "foo %s ==> | %s | %s | %s | %s | %s | \n",
255 // if(authority.empty() == false && path.empty() == true)
256 // path.swap(authority);
258 if(type
== cdom::Windows
)
260 if(!authority
.empty())
261 filePath
+= std::string("\\\\") + authority
; // UNC path
263 // Replace two leading slashes with one leading slash, so that
264 // ///otherComputer/file.dae becomes //otherComputer/file.dae and
265 // //folder/file.dae becomes /folder/file.dae
266 if(path
.length() >= 2 && path
[0] == '/' && path
[1] == '/')
269 // Convert "/C:/" to "C:/"
270 if(path
.length() >= 3 && path
[0] == '/' && path
[2] == ':')
273 // Convert forward slashes to back slashes
274 path
= cdom::replace(path
, "/", "\\");
278 filePath
+= authority
;
283 // Replace %20 with space
284 filePath
= cdom::replace(filePath
, "%20", " ");
289 ColladaGlobal::ColladaGlobal(void)
305 ColladaGlobal::~ColladaGlobal(void)
311 /*! Read the file stored in _docPath from the DAE _dae.
314 ColladaGlobal::doRead(void)
316 NodeTransitPtr
rootN(NULL
);
318 if(_statColl
== NULL
)
319 _statColl
= new StatCollector
;
321 // force creation of the statistic elements
322 _statColl
->getElem(statNGeometryCreated
, true);
323 _statColl
->getElem(statNGeometryUsed
, true);
324 _statColl
->getElem(statNMaterialCreated
, true);
325 _statColl
->getElem(statNMaterialUsed
, true);
326 _statColl
->getElem(statNLightCreated
, true);
327 _statColl
->getElem(statNLightUsed
, true);
328 _statColl
->getElem(statNTextureCreated
, true);
329 _statColl
->getElem(statNTextureUsed
, true);
331 _statColl
->reset (StatElemDescBase::RESET_ALWAYS
);
333 _globalsAtt
= GlobalsAttachment::create();
334 _docRoot
= dynamic_cast<domCOLLADA
*>(_dae
->getRoot(_docPath
));
338 ColladaCOLLADARefPtr colCOL
= dynamic_pointer_cast
<ColladaCOLLADA
>(
339 ColladaElementFactory::the()->create(_docRoot
, this));
343 for(UInt32 i
= 0; _instQueue
.empty() == false; ++i
)
347 SWARNING
<< "ColladaGlobal::doRead: InstanceQueue loop "
348 << "maximum iteration count reached." << std::endl
;
352 InstanceQueue workQueue
;
353 workQueue
.swap(_instQueue
);
355 InstanceQueueIt iqIt
= workQueue
.begin();
356 InstanceQueueIt iqEnd
= workQueue
.end ();
358 for(; iqIt
!= iqEnd
; ++iqIt
)
364 SWARNING
<< "ColladaGlobal::read: collada-dom failed to obtain "
365 << "document root for file [" << _docPath
<< "]."
369 if(_globalsAtt
->getMFElements()->empty() == false)
370 _rootN
->addAttachment(_globalsAtt
);
377 _loaderState
.clear();
380 #ifndef OSG_COLLADA_SILENT
381 std::string statString
;
382 _statColl
->putToString(statString
);
384 OSG_COLLADA_LOG(("ColladaGlobal:read: Statistics\n%s\n",
385 statString
.c_str()));
386 #endif // OSG_COLLADA_SILENT
393 #endif // OSG_WITH_COLLADA