root/OpenSceneGraph/trunk/src/osgPlugins/dae/daeWriter.cpp @ 13041

Revision 13041, 14.1 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * Copyright 2006 Sony Computer Entertainment Inc.
3 *
4 * Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this
5 * file except in compliance with the License. You may obtain a copy of the License at:
6 * http://research.scea.com/scea_shared_source_license.html
7 *
8 * Unless required by applicable law or agreed to in writing, software distributed under the License
9 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10 * implied. See the License for the specific language governing permissions and limitations under the
11 * License.
12 */
13
14#include "daeWriter.h"
15
16#include <dom/domCOLLADA.h>
17
18#include <dom/domNode.h>
19#include <dom/domConstants.h>
20
21#include <sstream>
22#include <osgDB/ConvertUTF>
23
24
25namespace osgDAE {
26
27daeWriter::ArrayNIndices::ArrayNIndices( osg::Array* valArray, osg::IndexArray* ind ) :
28    vec2(0),  vec3(0),  vec4(0),
29    vec2d(0), vec3d(0), vec4d(0),
30    vec4ub(0),
31    valArray(valArray),
32    inds( ind ), mode(NONE)
33{
34    if ( valArray != NULL )
35    {
36        switch( valArray->getType() )
37        {
38        case osg::Array::Vec2ArrayType:
39            mode = VEC2F;
40            vec2 = (osg::Vec2Array*)valArray;
41            break;
42        case osg::Array::Vec3ArrayType:
43            mode = VEC3F;
44            vec3 = (osg::Vec3Array*)valArray;
45            break;
46        case osg::Array::Vec4ArrayType:
47            mode = VEC4F;
48            vec4 = (osg::Vec4Array*)valArray;
49            break;
50        case osg::Array::Vec2dArrayType:
51            mode = VEC2D;
52            vec2d = (osg::Vec2dArray*)valArray;
53            break;
54        case osg::Array::Vec3dArrayType:
55            mode = VEC3D;
56            vec3d = (osg::Vec3dArray*)valArray;
57            break;
58        case osg::Array::Vec4dArrayType:
59            mode = VEC4D;
60            vec4d = (osg::Vec4dArray*)valArray;
61            break;
62        case osg::Array::Vec4ubArrayType:
63            mode = VEC4_UB;
64            vec4ub = (osg::Vec4ubArray*)valArray;
65            break;
66        default:
67            OSG_WARN << "Array is unsupported vector type" << std::endl;
68            break;
69        }
70    }
71}
72
73
74std::string toString(const osg::Vec3f& value)
75{
76    std::stringstream str;
77    str << value.x() << " " << value.y() << " " << value.z();
78    return str.str();
79}
80
81std::string toString(const osg::Vec3d& value)
82{
83    std::stringstream str;
84    str << value.x() << " " << value.y() << " " << value.z();
85    return str.str();
86}
87
88std::string toString(const osg::Matrix& value)
89{
90    std::stringstream str;
91    str << value(0,0) << " " << value(1,0) << " " << value(2,0) << " " << value(3,0) << " "
92        << value(0,1) << " " << value(1,1) << " " << value(2,1) << " " << value(3,1) << " "
93        << value(0,2) << " " << value(1,2) << " " << value(2,2) << " " << value(3,2) << " "
94        << value(0,3) << " " << value(1,3) << " " << value(2,3) << " " << value(3,3);
95    return str.str();
96}
97
98
99daeWriter::Options::Options()
100    : usePolygons(false),
101    googleMode(false),
102    writeExtras(true),
103    earthTex(false),
104    linkOrignialTextures(false),
105    forceTexture(false),
106    namesUseCodepage(false),
107    relativiseImagesPathNbUpDirs(0)
108{}
109
110daeWriter::daeWriter( DAE *dae_, const std::string & fileURI, const std::string & directory, const std::string & srcDirectory, const osgDB::ReaderWriter::Options * options, TraversalMode tm, const Options * pluginOptions) : osg::NodeVisitor( tm ),
111    dae(dae_),
112    _domLibraryAnimations(NULL),
113    rootName(*dae_),
114    m_CurrentRenderingHint(osg::StateSet::DEFAULT_BIN),
115    _options(options),
116    _pluginOptions(pluginOptions ? *pluginOptions : Options()),
117    _externalWriter(srcDirectory, directory, true, pluginOptions ? pluginOptions->relativiseImagesPathNbUpDirs : 0)
118{
119    success = true;
120
121    dae->setDatabase( NULL );
122    dae->setIOPlugin( NULL );
123    //create document
124    dae->getDatabase()->createDocument( fileURI.c_str(), &doc );
125    dom = (domCOLLADA*)doc->getDomRoot();
126    //create scene and instance visual scene
127    domCOLLADA::domScene *scene = daeSafeCast< domCOLLADA::domScene >( dom->add( COLLADA_ELEMENT_SCENE ) );
128    domInstanceWithExtra *ivs = daeSafeCast< domInstanceWithExtra >( scene->add( COLLADA_ELEMENT_INSTANCE_VISUAL_SCENE ) );
129    ivs->setUrl( "#defaultScene" );
130    //create library visual scenes and a visual scene and the root node
131    lib_vis_scenes = daeSafeCast<domLibrary_visual_scenes>( dom->add( COLLADA_ELEMENT_LIBRARY_VISUAL_SCENES ) );
132    vs = daeSafeCast< domVisual_scene >( lib_vis_scenes->add( COLLADA_ELEMENT_VISUAL_SCENE ) );
133    vs->setId( "defaultScene" );
134    currentNode = daeSafeCast< domNode >( vs->add( COLLADA_ELEMENT_NODE ) );
135    currentNode->setId( "sceneRoot" );
136
137    //create Asset
138    //createAssetTag(m_ZUpAxis); // we now call this in the set root node
139
140    lib_cameras = NULL;
141    lib_effects = NULL;
142    lib_controllers = NULL;
143    lib_geoms = NULL;
144    lib_lights = NULL;
145    lib_mats = NULL;
146
147    lastDepth = 0;
148
149    // Clean up caches
150    uniqueNames.clear();
151
152    currentStateSet = new osg::StateSet();
153}
154
155daeWriter::~daeWriter()
156{
157}
158
159void daeWriter::debugPrint( osg::Node &node )
160{
161#ifdef _DEBUG
162    std::string indent = "";
163    for ( unsigned int i = 0; i < _nodePath.size(); i++ )
164    {
165        indent += "  ";
166    }
167    OSG_INFO << indent << node.className() << std::endl;
168#endif
169}
170
171
172void daeWriter::setRootNode( const osg::Node &node )
173{
174    std::string fname = osgDB::findDataFile( node.getName() );
175    //create Asset with root node providing meta data
176    createAssetTag( node );
177
178    const_cast<osg::Node*>(&node)->accept( _animatedNodeCollector );
179}
180
181//### provide a name to node
182std::string daeWriter::getNodeName(const osg::Node & node,const std::string & defaultName)
183{
184    std::string nodeName;
185    if (node.getName().empty())
186        nodeName=uniquify(defaultName);
187    else
188        nodeName=uniquify(node.getName());
189    return nodeName;
190}
191
192//NODE
193void daeWriter::apply( osg::Node &node )
194{
195    debugPrint( node );
196
197    writeNodeExtra(node);
198
199    traverse( node );
200}
201
202void daeWriter::updateCurrentDaeNode()
203{
204    while ( lastDepth >= _nodePath.size() )
205    {
206        //We are not a child of previous node
207        currentNode = daeSafeCast< domNode >( currentNode->getParentElement() );
208        --lastDepth;
209    }
210}
211
212std::string daeWriter::uniquify( const std::string &_name )
213{
214    const std::string name( _pluginOptions.namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(_name) : _name );
215    std::map< std::string, int >::iterator iter = uniqueNames.find( name );
216    if ( iter != uniqueNames.end() )
217    {
218        iter->second++;
219        std::ostringstream num;
220        num << std::dec << iter->second;
221        return name + "_" + num.str();
222    }
223    else
224    {
225        uniqueNames.insert( std::make_pair( name, 0 ) );
226        return name;
227    }
228}
229
230void daeWriter::createAssetTag( bool isZUpAxis )
231{
232    domAsset *asset = daeSafeCast< domAsset >(dom->add( COLLADA_ELEMENT_ASSET ) );
233    domAsset::domCreated *c = daeSafeCast< domAsset::domCreated >(asset->add(COLLADA_ELEMENT_CREATED));
234    domAsset::domModified *m = daeSafeCast< domAsset::domModified >(asset->add(COLLADA_ELEMENT_MODIFIED));
235    domAsset::domUnit *u = daeSafeCast< domAsset::domUnit >(asset->add(COLLADA_ELEMENT_UNIT));
236    domAsset::domUp_axis *up = daeSafeCast< domAsset::domUp_axis >(asset->add(COLLADA_ELEMENT_UP_AXIS));
237    up->setValue(UPAXISTYPE_Z_UP);
238
239    //TODO : set date and time
240    c->setValue( "2006-07-25T00:00:00Z" );
241    m->setValue( "2006-07-25T00:00:00Z" );
242
243    u->setName( "meter" );
244    u->setMeter( 1 );
245}
246
247
248// Overloaded version of createAssetTag that provides the ability to specify
249// user defined values for child elements within asset tags
250void daeWriter::createAssetTag(const osg::Node &node)
251{
252   domAsset *asset = daeSafeCast< domAsset >(dom->add( COLLADA_ELEMENT_ASSET ) );
253   domAsset::domCreated *c = daeSafeCast< domAsset::domCreated >(asset->add("created" ));
254   domAsset::domModified *m = daeSafeCast< domAsset::domModified >(asset->add("modified" ));
255   domAsset::domUnit *u = daeSafeCast< domAsset::domUnit >(asset->add("unit"));
256   domAsset::domUp_axis *up_axis = daeSafeCast< domAsset::domUp_axis >(asset->add("up_axis"));
257
258   domAsset::domContributor *contributor = daeSafeCast< domAsset::domContributor >(asset->add("contributor" ));
259
260   // set date and time
261   // Generate the date like this
262   // "YYYY-mm-ddTHH:MM:SSZ"  ISO 8601  Date Time format
263   const size_t bufSize = 1024;
264   static char dateStamp[bufSize];
265   time_t rawTime = time(NULL);
266   struct tm* timeInfo = localtime(&rawTime);
267   strftime(dateStamp, sizeof(dateStamp), "%Y-%m-%dT%H:%M:%SZ", timeInfo);
268
269
270   // set up fallback defaults
271   c->setValue( dateStamp );
272   m->setValue( dateStamp );
273   u->setName( "meter" );    // NOTE: SketchUp incorrectly sets this to "meters" but it does not really matter.
274                             //  Also note that since the default is: <unit meter="1.0" name="meter"/>  this is equivalent to <unit/>
275   u->setMeter( 1.0 );        // this is the important units setting as it tells consuming apps how to convert to meters.
276   up_axis->setValue(UPAXISTYPE_Z_UP);
277
278
279
280   // get description info as name value pairs
281   if (node.getDescriptions().size()%2 == 0)
282   {
283      for(osg::Node::DescriptionList::const_iterator ditr=node.getDescriptions().begin();
284         ditr!=node.getDescriptions().end();
285         ++ditr)
286      {
287         std::string attrName( *ditr );   ++ditr;
288         std::string attrValue( *ditr );
289
290         if (attrName=="collada_created" && !attrValue.empty())
291         {
292            c->setValue( attrValue.c_str() );
293         }
294         else if (attrName=="collada_modified" && !attrValue.empty())
295         {
296            m->setValue( attrValue.c_str() );
297         }
298         else if (attrName=="collada_keywords" && !attrValue.empty())
299         {
300            domAsset::domKeywords *keywords = daeSafeCast< domAsset::domKeywords >(asset->add("keywords" ));
301            keywords->setValue( attrValue.c_str() );
302         }
303         else if (attrName=="collada_revision" && !attrValue.empty())
304         {
305            domAsset::domRevision *revision = daeSafeCast< domAsset::domRevision >(asset->add("revision" ));
306            revision->setValue( attrValue.c_str() );
307         }
308         else if (attrName=="collada_subject" && !attrValue.empty())
309         {
310            domAsset::domSubject  *subject = daeSafeCast< domAsset::domSubject >(asset->add("subject" ));
311            subject->setValue( attrValue.c_str() );
312         }
313         else if (attrName=="collada_title" && !attrValue.empty())
314         {
315            domAsset::domTitle  *title = daeSafeCast< domAsset::domTitle >(asset->add("title" ));
316            title->setValue( attrValue.c_str() );
317         }
318         else if (attrName=="collada_up_axis" && !attrValue.empty())
319         {
320            if (attrValue=="X_UP")
321            {
322               up_axis->setValue( UPAXISTYPE_X_UP );
323            }
324            else if (attrValue=="Y_UP")
325            {
326               up_axis->setValue( UPAXISTYPE_Y_UP );
327            }
328            else
329            {
330               up_axis->setValue( UPAXISTYPE_Z_UP );   // default
331            }
332         }
333         else if (attrName=="collada_unit_name" && !attrValue.empty())
334         {
335            u->setName( attrValue.c_str() );
336         }
337         else if (attrName=="collada_unit_meter_length" && !attrValue.empty())
338         {
339            double fValFromStr(1.0);
340            try {
341               std::istringstream sConversion(attrValue);
342               sConversion >> fValFromStr;
343               u->setMeter((domFloat)fValFromStr);
344            }
345            catch (...)
346            {
347               // TODO: handle error
348               u->setMeter((domFloat)fValFromStr);
349               continue;
350            }
351         }
352         else if (attrName=="collada_contributor{0}.author" && !attrValue.empty())
353         {
354            domAsset::domContributor::domAuthor *author =
355               daeSafeCast< domAsset::domContributor::domAuthor >(contributor->add("author" ));
356            author->setValue( attrValue.c_str() );
357         }
358         else if (attrName=="collada_contributor{0}.authoring_tool" && !attrValue.empty())
359         {
360            domAsset::domContributor::domAuthoring_tool *authoring_tool =
361               daeSafeCast< domAsset::domContributor::domAuthoring_tool >(contributor->add("authoring_tool" ));
362            authoring_tool->setValue( attrValue.c_str() );
363         }
364         else if (attrName=="collada_contributor{0}.comments" && !attrValue.empty())
365         {
366            domAsset::domContributor::domComments *comments =
367               daeSafeCast< domAsset::domContributor::domComments >(contributor->add("comments" ));
368            comments->setValue( attrValue.c_str() );
369         }
370         else if (attrName=="collada_contributor{0}.source_data" && !attrValue.empty())
371         {
372            domAsset::domContributor::domSource_data *source_data =
373               daeSafeCast< domAsset::domContributor::domSource_data >(contributor->add("source_data" ));
374            source_data->setValue( attrValue.c_str() );
375         }
376         else if (attrName=="collada_contributor{0}.copyright" && !attrValue.empty())
377         {
378            domAsset::domContributor::domCopyright *copyright =
379               daeSafeCast< domAsset::domContributor::domCopyright >(contributor->add("copyright" ));
380            copyright->setValue( attrValue.c_str() );
381         }
382
383         // TODO:  handle array of contributor data rather that just the first.
384         // also there is probably a better way to pass attribute data as DescriptionList is a bit fragile
385
386      }
387   }
388}
389
390void daeWriter::traverse (osg::Node &node)
391{
392    pushStateSet(node.getStateSet());
393
394    osg::NodeVisitor::traverse( node );
395
396    popStateSet(node.getStateSet());
397}
398
399void daeWriter::pushStateSet(osg::StateSet* ss)
400{
401  if (NULL!=ss) {
402    // Save our current stateset
403    stateSetStack.push(currentStateSet.get());
404
405    // merge with node stateset
406    currentStateSet = static_cast<osg::StateSet*>(currentStateSet->clone(osg::CopyOp::SHALLOW_COPY));
407    currentStateSet->merge(*ss);
408  }
409}
410
411
412void daeWriter::popStateSet(osg::StateSet* ss)
413{
414    if (NULL!=ss) {
415      // restore the previous stateset
416      currentStateSet = stateSetStack.top();
417      stateSetStack.pop();
418    }
419}
420
421} // namespace osgdae
Note: See TracBrowser for help on using the browser.