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_CONV_H_
15 #define _DAE_CONV_H_
16
17 #include <string>
18
19 #include <dae.h>
20 #include <dae/daeURI.h>
21 #include <dae/daeElement.h>
22 #include <dom/domCommon_color_or_texture_type.h>
23 #include <dom/domInputLocalOffset.h>
24 #include <dom/domInstance_controller.h>
25
26 #include <osg/Node>
27 #include <osg/Notify>
28 #include <osgDB/ReaderWriter>
29 #include <osgDB/FileNameUtils>
30 #include <osgDB/FileUtils>
31 #include <osgDB/Registry>
32 #include <osg/Material>
33 #include <osg/Texture2D>
34 #include <osgAnimation/BasicAnimationManager>
35 #include <osgAnimation/Bone>
36 #include <osgAnimation/Skeleton>
37
38 #ifdef COLLADA_DOM_2_4_OR_LATER
39 namespace ColladaDOM141
40 {
41 #endif
42 class domBind_material;
43 class domCamera;
44 //class domCommon_color_or_texture_type;
45 class domCommon_float_or_param_type;
46 class domGeometry;
47 class domInstance_controller;
48 class domInstance_geometry;
49 class domInstanceWithExtra;
50 class domLight;
51 class domLookat;
52 class domMatrix;
53 class domNode;
54 class domP;
55 class domProfile_COMMON;
56 class domScale;
57 class domSkew;
58 class domTranslate;
59 class domRotate;
60 class domVisual_scene;
61
62 #ifdef COLLADA_DOM_2_4_OR_LATER
63 }
64
65 using namespace ColladaDOM141;
66 #endif
67
68 namespace osgDAE
69 {
70
71 class domSourceReader;
72
getElementFromURI(daeURI & uri)73 inline daeElement *getElementFromURI( daeURI &uri )
74 {
75 if ( uri.getState() == daeURI::uri_loaded || uri.getState() == daeURI::uri_pending ) {
76 uri.resolveElement();
77 }
78 return uri.getElement();
79 }
getElementFromIDRef(daeIDRef & idref)80 inline daeElement *getElementFromIDRef( daeIDRef &idref )
81 {
82 if ( idref.getState() == daeIDRef::id_loaded || idref.getState() == daeIDRef::id_pending ) {
83 idref.resolveElement();
84 }
85 return idref.getElement();
86 }
87
88 template< typename TInputArray, typename TInputType >
89 bool findInputSourceBySemantic( TInputArray& inputs, const char* semantic, daeElement *& element,
90 TInputType ** input = NULL, int unit = 0 )
91 {
92 element = NULL;
93 int count = 0;
94 for ( size_t i = 0; i < inputs.getCount(); i++ ) {
95 if ( !strcmp(semantic, inputs[i]->getSemantic()) ) {
96 if ( count == unit )
97 {
98 element = getElementFromURI( inputs[i]->getSource() );
99 *input = (TInputType*)inputs[i];
100 return true;
101 }
102 count++;
103 }
104 }
105 return false;
106 }
107
108 /// Convert string to value using it's stream operator
109 template <typename T>
parseString(const std::string & valueAsString)110 T parseString(const std::string& valueAsString) {
111 std::stringstream str;
112 str << valueAsString;
113 T result;
114 str >> result;
115 return result;
116 }
117
parseVec3String(const std::string & valueAsString)118 inline osg::Vec3 parseVec3String(const std::string& valueAsString)
119 {
120 std::stringstream str;
121 str << valueAsString;
122 osg::Vec3 result;
123 str >> result.x() >> result.y() >> result.z();
124 return result;
125 }
126
parseMatrixString(const std::string & valueAsString)127 inline osg::Matrix parseMatrixString(const std::string& valueAsString)
128 {
129 std::stringstream str;
130 str << valueAsString;
131 osg::Matrix result;
132 str >> result(0,0) >> result(1,0) >> result(2,0) >> result(3,0)
133 >> result(0,1) >> result(1,1) >> result(2,1) >> result(3,1)
134 >> result(0,2) >> result(1,2) >> result(2,2) >> result(3,2)
135 >> result(0,3) >> result(1,3) >> result(2,3) >> result(3,3);
136 return result;
137 }
138
139
140 /**
141 @class daeReader
142 @brief Read a OSG scene from a DAE file
143 */
144 class daeReader {
145 public:
146 enum TessellateMode
147 {
148 TESSELLATE_NONE, ///< Do not tessellate at all (Polygons are stored as GL_POLYGON - not suitable for concave polygons)
149 TESSELLATE_POLYGONS_AS_TRIFAN, ///< Tessellate the old way, interpreting polygons as triangle fans (faster, but does not work for concave polygons)
150 TESSELLATE_POLYGONS ///< Use full tessellation of polygons (slower, works for concave polygons)
151 };
152
153 struct Options
154 {
155 Options();
156 bool strictTransparency;
157 int precisionHint; ///< Precision hint flags, as specified in osgDB::Options::PrecisionHint
158 bool usePredefinedTextureUnits;
159 TessellateMode tessellateMode;
160 };
161
162 daeReader(DAE *dae_, const Options * pluginOptions);
163 virtual ~daeReader();
164
165 bool convert( std::istream &fin );
166 bool convert( const std::string &fileURI );
167
getRootNode()168 osg::Node* getRootNode() { return _rootNode; }
169
getAssetUnitName()170 const std::string& getAssetUnitName() const {return _assetUnitName;}
getAssetUnitMeter()171 float getAssetUnitMeter() const {return _assetUnitMeter;}
getAssetUpAxis()172 domUpAxisType getAssetUpAxis() const {return _assetUp_axis;}
173
174 enum TextureUnitUsage
175 {
176 AMBIENT_OCCLUSION_UNIT = 0,
177 MAIN_TEXTURE_UNIT,
178 TRANSPARENCY_MAP_UNIT
179 };
180
181 enum InterpolationType
182 {
183 INTERPOLATION_UNKNOWN,
184 INTERPOLATION_STEP,
185 INTERPOLATION_LINEAR,
186 INTERPOLATION_BEZIER,
187 INTERPOLATION_HERMITE,
188 INTERPOLATION_CARDINAL,
189 INTERPOLATION_BSPLINE,
190
191 //COLLADA spec states that if interpolation is not specified then
192 //interpolation is application defined. Linear is a sensible default.
193 INTERPOLATION_DEFAULT = INTERPOLATION_LINEAR
194 };
195
196 enum AuthoringTool
197 {
198 UNKNOWN,
199 BLENDER,
200 DAZ_STUDIO,
201 FBX_CONVERTER,
202 AUTODESK_3DS_MAX = FBX_CONVERTER,//3ds Max exports to DAE via Autodesk's FBX converter
203 GOOGLE_SKETCHUP,
204 MAYA
205 };
206
207 class TextureParameters
208 {
209 public:
TextureParameters()210 TextureParameters()
211 : wrap_s(osg::Texture::REPEAT), wrap_t(osg::Texture::REPEAT),
212 filter_min(osg::Texture::LINEAR_MIPMAP_LINEAR), filter_mag(osg::Texture::LINEAR),
213 transparent(false), opaque(FX_OPAQUE_ENUM_A_ONE), transparency(1.0f)
214 {}
215
216 bool operator < (const TextureParameters& rhs) const
217 {
218 int diffStr = filename.compare(rhs.filename);
219 if (diffStr) return diffStr < 0;
220 if (wrap_s != rhs.wrap_s) return wrap_s < rhs.wrap_s;
221 if (wrap_t != rhs.wrap_t) return wrap_t < rhs.wrap_t;
222 if (filter_min != rhs.filter_min) return filter_min < rhs.filter_min;
223 if (filter_mag != rhs.filter_mag) return filter_mag < rhs.filter_mag;
224 if (transparency != rhs.transparency) return transparency < rhs.transparency;
225 if (opaque != rhs.opaque) return opaque < rhs.opaque;
226 if (transparent != rhs.transparent) return transparent < rhs.transparent;
227 return border < rhs.border;
228 }
229
230 std::string filename;
231 osg::Texture::WrapMode wrap_s, wrap_t;
232 osg::Texture::FilterMode filter_min, filter_mag;
233 osg::Vec4 border;
234
235 //The following parameters are for transparency textures, to handle
236 //COLLADA's horrible transparency spec.
237 bool transparent;
238 domFx_opaque_enum opaque;
239 float transparency;
240 };
241
242 class ChannelPart : public osg::Referenced
243 {
244 public:
245 std::string name;
246 osg::ref_ptr<osgAnimation::KeyframeContainer> keyframes;
247 InterpolationType interpolation;
248 };
249
250 typedef std::map<domGeometry*, osg::ref_ptr<osg::Geode> > domGeometryGeodeMap;
251 typedef std::map<domMaterial*, osg::ref_ptr<osg::StateSet> > domMaterialStateSetMap;
252 typedef std::map<std::string, osg::ref_ptr<osg::StateSet> > MaterialStateSetMap;
253 typedef std::multimap< daeElement*, domChannel*> daeElementDomChannelMap;
254 typedef std::map<domChannel*, osg::ref_ptr<osg::Callback> > domChannelOsgAnimationUpdateCallbackMap;
255 typedef std::map<domNode*, osg::ref_ptr<osgAnimation::Bone> > domNodeOsgBoneMap;
256 typedef std::map<domNode*, osg::ref_ptr<osgAnimation::Skeleton> > domNodeOsgSkeletonMap;
257 typedef std::map<TextureParameters, osg::ref_ptr<osg::Texture2D> > TextureParametersMap;
258 typedef std::map<std::pair<const osg::StateSet*, TextureUnitUsage>, std::string> TextureToCoordSetMap;
259 typedef std::map<std::string, size_t> IdToCoordIndexMap;
260
261 typedef std::map< daeElement*, domSourceReader > SourceMap;
262 typedef std::map< int, osg::IntArray*, std::less<int> > IndexMap;
263 typedef std::map< int, osg::Array*, std::less<int> > ArrayMap;
264
265 typedef std::multimap< osgAnimation::Target*, osg::ref_ptr<ChannelPart> > TargetChannelPartMap;
266 typedef std::multimap<std::pair<const domMesh*, size_t>, std::pair<osg::ref_ptr<osg::Geometry>, GLuint> > OldToNewIndexMap;
267
268 private:
269 bool processDocument( const std::string& );
270 void clearCaches();
271
272 // If the node is a bone then it should be added before any other types of
273 // node, this function makes that happen.
274 static void addChild(osg::Group*, osg::Node*);
275
276 //scene processing
277 osg::Group* turnZUp();
278 osg::Group* processVisualScene( domVisual_scene *scene );
279 osg::Node* processNode( domNode *node, bool skeleton );
280 osg::Transform* processOsgMatrixTransform( domNode *node, bool isBone);
281
282 template <typename T>
283 inline void getTransparencyCounts(daeDatabase*, int& zero, int& one) const;
284
285 /** Earlier versions of the COLLADA 1.4 spec state that transparency values
286 of 0 mean 100% opacity, but this has been changed in later versions to state
287 that transparency values of 1 mean 100% opacity. Documents created by
288 different tools at different times adhere to different versions of the
289 standard. This function looks at all transparency values in the database and
290 heuristically decides which way the values should be interpreted.*/
291 bool findInvertTransparency(daeDatabase*) const;
292
293 osgAnimation::BasicAnimationManager* processAnimationLibraries(domCOLLADA* document);
294 void processAnimationClip(osgAnimation::BasicAnimationManager* pOsgAnimationManager, domAnimation_clip* pDomAnimationClip);
295 void processAnimationMap(const TargetChannelPartMap&, osgAnimation::Animation* pOsgAnimation);
296 ChannelPart* processSampler(domChannel* pDomChannel, SourceMap &sources);
297 void processAnimationChannels(domAnimation* pDomAnimation, TargetChannelPartMap& tcm);
298 void processChannel(domChannel* pDomChannel, SourceMap &sources, TargetChannelPartMap& tcm);
299 void extractTargetName(const std::string&, std::string&, std::string&, std::string&);
300
301 // Processing of OSG specific info stored in node extras
302 osg::Group* processExtras(domNode *node);
303 void processNodeExtra(osg::Node* osgNode, domNode *node);
304 domTechnique* getOpenSceneGraphProfile(domExtra* extra);
305 void processAsset( domAsset *node );
306
307 osg::Group* processOsgSwitch(domTechnique* teq);
308 osg::Group* processOsgMultiSwitch(domTechnique* teq);
309 osg::Group* processOsgLOD(domTechnique* teq);
310 osg::Group* processOsgDOFTransform(domTechnique* teq);
311 osg::Group* processOsgSequence(domTechnique* teq);
312
313 // geometry processing
314 osg::Geode* getOrCreateGeometry(domGeometry *geom, domBind_material* pDomBindMaterial, const osg::Geode** ppOriginalGeode = NULL);
315 osgAnimation::Bone* getOrCreateBone(domNode *pDomNode);
316 osgAnimation::Skeleton* getOrCreateSkeleton(domNode *pDomNode);
317 osg::Geode* processInstanceGeometry( domInstance_geometry *ig );
318
319 osg::Geode* processMesh(domMesh* pDomMesh);
320 osg::Geode* processConvexMesh(domConvex_mesh* pDomConvexMesh);
321 osg::Geode* processSpline(domSpline* pDomSpline);
322 osg::Geode* processGeometry(domGeometry *pDomGeometry);
323
324 typedef std::vector<domInstance_controller*> domInstance_controllerList;
325
326 void processSkins();
327 //Process skins attached to one skeleton
328 void processSkeletonSkins(domNode* skeletonRoot, const domInstance_controllerList&);
329 void processSkin(domSkin* pDomSkin, domNode* skeletonRoot, osgAnimation::Skeleton*, domBind_material* pDomBindMaterial);
330 osg::Node* processMorph(domMorph* pDomMorph, domBind_material* pDomBindMaterial);
331 osg::Node* processInstanceController( domInstance_controller *ictrl );
332
333 template< typename T >
334 void processSinglePPrimitive(osg::Geode* geode, const domMesh* pDomMesh, const T* group, SourceMap& sources, GLenum mode);
335
336 template< typename T >
337 void processMultiPPrimitive(osg::Geode* geode, const domMesh* pDomMesh, const T* group, SourceMap& sources, GLenum mode);
338
339 void processPolylist(osg::Geode* geode, const domMesh* pDomMesh, const domPolylist *group, SourceMap &sources, TessellateMode tessellateMode);
340
341 template< typename T >
342 void processPolygons(osg::Geode* geode, const domMesh* pDomMesh, const T *group, SourceMap &sources, GLenum mode, TessellateMode tessellateMode);
343
344 void resolveMeshArrays(const domP_Array&,
345 const domInputLocalOffset_Array& inputs, const domMesh* pDomMesh,
346 osg::Geometry* geometry, SourceMap &sources,
347 std::vector<std::vector<GLuint> >& vertexLists);
348
349 //material/effect processing
350 void processBindMaterial( domBind_material *bm, domGeometry *geom, osg::Geode *geode, osg::Geode *cachedGeode );
351 void processMaterial(osg::StateSet *ss, domMaterial *mat );
352 void processEffect(osg::StateSet *ss, domEffect *effect );
353 void processProfileCOMMON(osg::StateSet *ss, domProfile_COMMON *pc );
354 bool processColorOrTextureType(const osg::StateSet*,
355 domCommon_color_or_texture_type *cot,
356 osg::Material::ColorMode channel,
357 osg::Material *mat,
358 domCommon_float_or_param_type *fop = NULL,
359 osg::Texture2D **sa = NULL,
360 bool normalizeShininess=false);
361 void processTransparencySettings( domCommon_transparent_type *ctt,
362 domCommon_float_or_param_type *pTransparency,
363 osg::StateSet*,
364 osg::Material *material,
365 unsigned int diffuseTextureUnit );
366 bool GetFloat4Param(xsNCName Reference, domFloat4 &f4) const;
367 bool GetFloatParam(xsNCName Reference, domFloat &f) const;
368
369 std::string processImagePath(const domImage*) const;
370 osg::Image* processImageTransparency(const osg::Image*, domFx_opaque_enum, float transparency) const;
371 osg::Texture2D* processTexture( domCommon_color_or_texture_type_complexType::domTexture *tex, const osg::StateSet*, TextureUnitUsage, domFx_opaque_enum = FX_OPAQUE_ENUM_A_ONE, float transparency = 1.0f);
372 bool copyTextureCoordinateSet(const osg::StateSet* ss, const osg::Geometry* cachedGeometry, osg::Geometry* clonedGeometry, const domInstance_material* im, TextureUnitUsage tuu, unsigned int textureUnit);
373
374 //scene objects
375 osg::Node* processLight( domLight *dlight );
376 osg::Node* processCamera( domCamera *dcamera );
377
378 domNode* getRootJoint(domNode*) const;
379 domNode* findJointNode(daeElement* searchFrom, domInstance_controller*) const;
380 domNode* findSkeletonNode(daeElement* searchFrom, domInstance_controller*) const;
381
382 /// Return whether the node is used as a bone. Note that while many files
383 /// identify joints with type="JOINT", some don't do this, while others
384 /// incorrectly identify every node as a joint.
isJoint(const domNode * node)385 bool isJoint(const domNode* node) const {return _jointSet.find(node) != _jointSet.end();}
386
387 private:
388
389 DAE *_dae;
390 osg::Node* _rootNode;
391 osg::ref_ptr<osg::StateSet> _rootStateSet;
392 domCOLLADA* _document;
393
394 domVisual_scene* _visualScene;
395
396 std::map<std::string,bool> _targetMap;
397
398 int _numlights;
399
400 domInstance_effect *_currentInstance_effect;
401 domEffect *_currentEffect;
402
403 /// Maps an animated element to a domchannel to quickly find which animation influence this element
404 // TODO a single element can be animated by multiple channels (with different members like translate.x or morphweights(2) )
405 daeElementDomChannelMap _daeElementDomChannelMap;
406 /// Maps a domchannel to an animationupdatecallback
407 domChannelOsgAnimationUpdateCallbackMap _domChannelOsgAnimationUpdateCallbackMap;
408 /// Maps geometry to a Geode
409 domGeometryGeodeMap _geometryMap;
410 /// All nodes in the document that are used as joints.
411 std::set<const domNode*> _jointSet;
412 /// Maps a node (of type joint) to a osgAnimation::Bone
413 domNodeOsgBoneMap _jointMap;
414 /// Maps a node (of type joint) to a osgAnimation::Skeleton
415 domNodeOsgSkeletonMap _skeletonMap;
416 // Maps material target to stateset
417 domMaterialStateSetMap _materialMap;
418 // Maps material symbol to stateset
419 MaterialStateSetMap _materialMap2;
420 TextureParametersMap _textureParamMap;
421 TextureToCoordSetMap _texCoordSetMap;
422 IdToCoordIndexMap _texCoordIdMap;
423 domInstance_controllerList _skinInstanceControllers;
424 OldToNewIndexMap _oldToNewIndexMap;
425
426 AuthoringTool _authoringTool;
427 bool _invertTransparency;
428 Options _pluginOptions;
429
430 // Additional Information
431 std::string _assetUnitName;
432 float _assetUnitMeter;
433 domUpAxisType _assetUp_axis;
434 };
435
436 }
437
438 #endif
439
440
441