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 #ifndef _DAE_WRITER_H_
15 #define _DAE_WRITER_H_
16
17 #include <map>
18 #include <stack>
19
20 #include <osg/Node>
21 #include <osg/Geode>
22 #include <osg/Geometry>
23 #include <osg/Group>
24 #include <osg/LightSource>
25 #include <osg/Camera>
26 #include <osg/Material>
27 #include <osg/MatrixTransform>
28 #include <osg/PositionAttitudeTransform>
29 #include <osg/Switch>
30 #include <osg/StateSet>
31 #include <osg/LOD>
32 #include <osg/ProxyNode>
33 #include <osg/CoordinateSystemNode>
34 #include <osg/BlendColor>
35 #include <osg/BlendFunc>
36
37 #include <osg/Notify>
38 #include <osg/NodeVisitor>
39 #include <osgDB/FileNameUtils>
40 #include <osgDB/FileUtils>
41 #include <osgDB/Registry>
42 #include <osgDB/ExternalFileWriter>
43 #include <osgSim/MultiSwitch>
44 #include <osgAnimation/AnimationManagerBase>
45 #include <osgAnimation/UpdateBone>
46 #include <osgAnimation/RigGeometry>
47 #include <osgAnimation/MorphGeometry>
48
49 #include <dae.h>
50 #include <dae/daeDocument.h>
51 #include <dom/domChannel.h>
52
53 #ifdef COLLADA_DOM_2_4_OR_LATER
54 namespace ColladaDOM141
55 {
56 #endif
57
58 class domCOLLADA;
59 class domGeometry;
60 class domInstance_geometry;
61 class domLibrary_cameras;
62 class domLibrary_effects;
63 class domLibrary_geometries;
64 class domLibrary_lights;
65 class domLibrary_materials;
66 class domLibrary_visual_scenes;
67 class domLibrary_animations;
68 class domMaterial;
69 class domMesh;
70 class domNode;
71 class domSource;
72 class domVisual_scene;
73 class domP;
74
75 #ifdef COLLADA_DOM_2_4_OR_LATER
76 }
77
78 using namespace ColladaDOM141;
79 #endif
80
81 namespace osgDAE {
82
83 /// Convert value to string using it's stream operator
84 template <typename T>
toString(T value)85 std::string toString(T value)
86 {
87 std::stringstream str;
88 str << value;
89 return str.str();
90 }
91
92 std::string toString(const osg::Vec3f& value);
93 std::string toString(const osg::Vec3d& value);
94 std::string toString(const osg::Matrix& value);
95
96 // Collects all nodes that are targeted by an animation
97 class FindAnimatedNodeVisitor : public osg::NodeVisitor
98 {
99 public:
FindAnimatedNodeVisitor()100 FindAnimatedNodeVisitor():
101 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
102 {}
103
apply(osg::Node & node)104 virtual void apply(osg::Node& node)
105 {
106 osg::Callback* ncb = node.getUpdateCallback();
107 if (ncb)
108 {
109 osgAnimation::AnimationUpdateCallback<osg::NodeCallback>* ut = dynamic_cast<osgAnimation::AnimationUpdateCallback<osg::NodeCallback>*>(ncb);
110 if (ut)
111 {
112 if (_updateCallbackNameNodeMap[ut->getName()] == NULL)
113 {
114 _updateCallbackNameNodeMap[ut->getName()] = &node;
115 }
116 else
117 {
118 // TODO store in a multimap and let the exporter create multiple <channel>s for each connected node
119 OSG_WARN << "Multiple nodes using the same update callback not supported" << std::endl;
120 }
121 }
122 }
123 traverse(node);
124 }
125
getTargetNode(const std::string & targetName)126 osg::Node* getTargetNode(const std::string& targetName)
127 {
128 UpdateCallbackNameNodeMap::iterator it = _updateCallbackNameNodeMap.find(targetName);
129 if (it != _updateCallbackNameNodeMap.end())
130 {
131 return it->second;
132 }
133 return NULL;
134 }
135
136 private:
137 typedef std::map< std::string, osg::Node*> UpdateCallbackNameNodeMap;
138 UpdateCallbackNameNodeMap _updateCallbackNameNodeMap;
139 };
140
141 /**
142 @class daeWriter
143 @brief Write a OSG scene into a DAE file
144 */
145 class daeWriter : public osg::NodeVisitor
146 {
147 protected:
148 class ArrayNIndices;
149 public:
150 struct Options
151 {
152 Options();
153
154 bool usePolygons;
155 /** work in Google compatibility mode. In daeWMaterials, change transparency color. And in daeWGeometry, replace tristrip and trifans by triangles*/
156 bool googleMode;
157 /** Write OSG specific data as extra data. */
158 bool writeExtras;
159 /** work in Google compatibility mode for textures*/
160 bool earthTex;
161 /** link to original images instead of exporting */
162 bool linkOrignialTextures;
163 /** force the use an image for a texture, even if the file is not found (when m_linkOrignialTextures). */
164 bool forceTexture;
165 bool namesUseCodepage;
166 unsigned int relativiseImagesPathNbUpDirs;
167 };
168 daeWriter(DAE *dae_, const std::string &fileURI, const std::string & directory, const std::string & srcDirectory, const osgDB::ReaderWriter::Options * options, TraversalMode tm=TRAVERSE_ALL_CHILDREN, const Options * pluginOptions=NULL);
169 virtual ~daeWriter();
170
171 void setRootNode( const osg::Node &node );
172
isSuccess()173 bool isSuccess() { return success; }
174
175 bool writeFile();
176
177 virtual void apply( osg::Node &node );
178 virtual void apply( osg::Geode &node );
179 virtual void apply( osg::Group &node );
180 virtual void apply( osg::LightSource &node );
181 virtual void apply( osg::Camera &node );
182 virtual void apply( osg::MatrixTransform &node );
183 virtual void apply( osg::PositionAttitudeTransform &node );
184 virtual void apply( osg::Switch &node );
185 virtual void apply( osg::Sequence &node );
186 virtual void apply( osg::LOD &node );
187
188 //virtual void apply( osg::Billboard &node);
189 virtual void apply( osg::ProxyNode &node );
190 //virtual void apply( osg::Projection &node)
191 virtual void apply( osg::CoordinateSystemNode &node );
192 //virtual void apply( osg::ClipNode &node)
193 //virtual void apply( osg::TexGenNode &node)
194 virtual void apply( osg::Transform &node );
195 virtual void apply( osg::CameraView &node);
196 //virtual void apply( osg::PagedLOD &node)
197 //virtual void apply( osg::ClearNode &node)
198 //virtual void apply( osg::OccluderNode &node)
199
200 void traverse (osg::Node &node);
201
202
203
204
205 protected: //methods
206
207 void writeAnimations(osg::Node& node);
208 void writeNodeExtra(osg::Node &node);
209 void writeUpdateTransformElements(const osg::Vec3 &pos, const osg::Quat &q, const osg::Vec3 &s);
210 void writeRigGeometry(osgAnimation::RigGeometry *pOsgRigGeometry);
211 void writeMorphGeometry(osgAnimation::MorphGeometry *pOsgMorphGeometry);
212
213 void debugPrint( osg::Node &node );
214
215 domGeometry* getOrCreateDomGeometry(osg::Geometry* pOsgGeometry);
216 bool processGeometry( osg::Geometry *geom, domGeometry *geo, const std::string &name );
217 domSource* createSource( daeElement *parent, const std::string &baseName, int size, bool color = false, bool uv = false );
218 template < typename Ty >
219 Ty *createPrimGroup( daeString type, domMesh *mesh, domSource *norm, domSource *color, const std::vector< domSource* > &texcoord );
220
221 void processMaterial( osg::StateSet *ss, domBind_material *pDomBindMaterial, const std::string &geoName );
222
223 void createAssetTag(bool isZUpAxis);
224
225 // Overloaded version of createAssetTag which provides ability to
226 // set user defined values for child elements
227 void createAssetTag(const osg::Node &node);
228
229 void pushStateSet(osg::StateSet* ss);
230
231 void popStateSet(osg::StateSet* ss);
232
233 protected: //members
234 DAE *dae;
235 daeDocument *doc;
236 domCOLLADA *dom;
237 domLibrary_cameras *lib_cameras;
238 domLibrary_effects *lib_effects;
239 domLibrary_controllers *lib_controllers;
240 domLibrary_geometries *lib_geoms;
241 domLibrary_lights *lib_lights;
242 domLibrary_materials *lib_mats;
243 domLibrary_visual_scenes *lib_vis_scenes;
244 domLibrary_animations* _domLibraryAnimations;
245 domNode *currentNode;
246 domVisual_scene *vs;
247
248 bool success;
249 unsigned int lastDepth;
250
251 struct CompareStateSet
252 {
operatorCompareStateSet253 bool operator()(const osg::ref_ptr<osg::StateSet>& ss1, const osg::ref_ptr<osg::StateSet>& ss2) const
254 {
255 //std::cout << "CompareStateSet: " << ss1->compare(*ss2, false) << " " << ss1 << " " << ss2 << std::endl;
256 return ss1->compare(*ss2, true) < 0;
257 }
258 };
259
260
261 typedef std::map< osg::ref_ptr<osg::StateSet>, domMaterial *, CompareStateSet> MaterialMap;
262 typedef std::stack<osg::ref_ptr<osg::StateSet> > StateSetStack;
263 typedef std::map< osg::Geometry*, domGeometry *> OsgGeometryDomGeometryMap;
264 typedef std::map< osgAnimation::RigGeometry*, domController *> OsgRigGeometryDomControllerMap;
265 typedef std::map< osgAnimation::MorphGeometry*, domController *> OsgMorphGeometryDomControllerMap;
266
267 std::map< std::string, int > uniqueNames;
268 OsgGeometryDomGeometryMap geometryMap;
269 OsgRigGeometryDomControllerMap _osgRigGeometryDomControllerMap;
270 OsgMorphGeometryDomControllerMap _osgMorphGeometryDomControllerMap;
271
272 MaterialMap materialMap;
273 StateSetStack stateSetStack;
274
275 osg::ref_ptr<osg::StateSet> currentStateSet;
276
277 daeURI rootName;
278
279 osg::StateSet* CleanStateSet(osg::StateSet* pStateSet) const;
280
281 void updateCurrentDaeNode();
282
283 protected: //inner classes
284 class ArrayNIndices
285 {
286 public:
287 enum Mode { NONE, VEC2F, VEC2D, VEC3F, VEC3D, VEC4F, VEC4D, VEC4_UB };
288
289 osg::Vec2Array* vec2;
290 osg::Vec3Array* vec3;
291 osg::Vec4Array* vec4;
292 osg::Vec2dArray* vec2d;
293 osg::Vec3dArray* vec3d;
294 osg::Vec4dArray* vec4d;
295 osg::Vec4ubArray* vec4ub;
296
297 osg::Array* valArray;
298 osg::IndexArray* inds;
299
300 ArrayNIndices( osg::Array* valArray, osg::IndexArray* ind );
301
getMode()302 Mode getMode() const { return mode; }
303
304 unsigned int getDAESize();
305
306 /// Appends the contained OSG vector array to a domListOfFloats
307 bool append(domListOfFloats & list);
308 protected:
309 Mode mode;
310 };
311
312 private: //members
313
314 /** append elements (verts, normals, colors and texcoord) for file write */
315 void appendGeometryIndices(osg::Geometry *geom,
316 domP * p,
317 unsigned int vindex,
318 domSource * norm,
319 domSource * color,
320 const ArrayNIndices & verts,
321 const ArrayNIndices & normals,
322 const ArrayNIndices & colors,
323 const std::vector<ArrayNIndices> & texcoords,
324 unsigned int ncount,
325 unsigned int ccount);
326
327 /** provide a name to node */
328 std::string getNodeName(const osg::Node & node,const std::string & defaultName);
329
330 /** provide an unique name */
331 std::string uniquify( const std::string &name );
332
333 /** Current RenderingHint */
334 /** This are needed because the stateSet merge code currently does not handle it */
335 int m_CurrentRenderingHint;
336
337 FindAnimatedNodeVisitor _animatedNodeCollector;
338
339 const osgDB::ReaderWriter::Options * _options;
340 Options _pluginOptions;
341 osgDB::ExternalFileWriter _externalWriter;
342 };
343
344 }
345
346 #endif
347
348