git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14633 16af8721-9629-0410-8352-f15c8da7e697
441 lines
17 KiB
Objective-C
441 lines
17 KiB
Objective-C
/*
|
|
* Copyright 2006 Sony Computer Entertainment Inc.
|
|
*
|
|
* Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this
|
|
* file except in compliance with the License. You may obtain a copy of the License at:
|
|
* http://research.scea.com/scea_shared_source_license.html
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing permissions and limitations under the
|
|
* License.
|
|
*/
|
|
|
|
#ifndef _DAE_CONV_H_
|
|
#define _DAE_CONV_H_
|
|
|
|
#include <string>
|
|
|
|
#include <dae.h>
|
|
#include <dae/daeURI.h>
|
|
#include <dae/daeElement.h>
|
|
#include <dom/domCommon_color_or_texture_type.h>
|
|
#include <dom/domInputLocalOffset.h>
|
|
#include <dom/domInstance_controller.h>
|
|
|
|
#include <osg/Node>
|
|
#include <osg/Notify>
|
|
#include <osgDB/ReaderWriter>
|
|
#include <osgDB/FileNameUtils>
|
|
#include <osgDB/FileUtils>
|
|
#include <osgDB/Registry>
|
|
#include <osg/Material>
|
|
#include <osg/Texture2D>
|
|
#include <osgAnimation/BasicAnimationManager>
|
|
#include <osgAnimation/Bone>
|
|
#include <osgAnimation/Skeleton>
|
|
|
|
#ifdef COLLADA_DOM_2_4_OR_LATER
|
|
namespace ColladaDOM141
|
|
{
|
|
#endif
|
|
class domBind_material;
|
|
class domCamera;
|
|
//class domCommon_color_or_texture_type;
|
|
class domCommon_float_or_param_type;
|
|
class domGeometry;
|
|
class domInstance_controller;
|
|
class domInstance_geometry;
|
|
class domInstanceWithExtra;
|
|
class domLight;
|
|
class domLookat;
|
|
class domMatrix;
|
|
class domNode;
|
|
class domP;
|
|
class domProfile_COMMON;
|
|
class domScale;
|
|
class domSkew;
|
|
class domTranslate;
|
|
class domRotate;
|
|
class domVisual_scene;
|
|
|
|
#ifdef COLLADA_DOM_2_4_OR_LATER
|
|
}
|
|
|
|
using namespace ColladaDOM141;
|
|
#endif
|
|
|
|
namespace osgDAE
|
|
{
|
|
|
|
class domSourceReader;
|
|
|
|
inline daeElement *getElementFromURI( daeURI &uri )
|
|
{
|
|
if ( uri.getState() == daeURI::uri_loaded || uri.getState() == daeURI::uri_pending ) {
|
|
uri.resolveElement();
|
|
}
|
|
return uri.getElement();
|
|
}
|
|
inline daeElement *getElementFromIDRef( daeIDRef &idref )
|
|
{
|
|
if ( idref.getState() == daeIDRef::id_loaded || idref.getState() == daeIDRef::id_pending ) {
|
|
idref.resolveElement();
|
|
}
|
|
return idref.getElement();
|
|
}
|
|
|
|
template< typename TInputArray, typename TInputType >
|
|
bool findInputSourceBySemantic( TInputArray& inputs, const char* semantic, daeElement *& element,
|
|
TInputType ** input = NULL, int unit = 0 )
|
|
{
|
|
element = NULL;
|
|
int count = 0;
|
|
for ( size_t i = 0; i < inputs.getCount(); i++ ) {
|
|
if ( !strcmp(semantic, inputs[i]->getSemantic()) ) {
|
|
if ( count == unit )
|
|
{
|
|
element = getElementFromURI( inputs[i]->getSource() );
|
|
*input = (TInputType*)inputs[i];
|
|
return true;
|
|
}
|
|
count++;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// Convert string to value using it's stream operator
|
|
template <typename T>
|
|
T parseString(const std::string& valueAsString) {
|
|
std::stringstream str;
|
|
str << valueAsString;
|
|
T result;
|
|
str >> result;
|
|
return result;
|
|
}
|
|
|
|
inline osg::Vec3 parseVec3String(const std::string& valueAsString)
|
|
{
|
|
std::stringstream str;
|
|
str << valueAsString;
|
|
osg::Vec3 result;
|
|
str >> result.x() >> result.y() >> result.z();
|
|
return result;
|
|
}
|
|
|
|
inline osg::Matrix parseMatrixString(const std::string& valueAsString)
|
|
{
|
|
std::stringstream str;
|
|
str << valueAsString;
|
|
osg::Matrix result;
|
|
str >> result(0,0) >> result(1,0) >> result(2,0) >> result(3,0)
|
|
>> result(0,1) >> result(1,1) >> result(2,1) >> result(3,1)
|
|
>> result(0,2) >> result(1,2) >> result(2,2) >> result(3,2)
|
|
>> result(0,3) >> result(1,3) >> result(2,3) >> result(3,3);
|
|
return result;
|
|
}
|
|
|
|
|
|
/**
|
|
@class daeReader
|
|
@brief Read a OSG scene from a DAE file
|
|
*/
|
|
class daeReader {
|
|
public:
|
|
enum TessellateMode
|
|
{
|
|
TESSELLATE_NONE, ///< Do not tessellate at all (Polygons are stored as GL_POLYGON - not suitable for concave polygons)
|
|
TESSELLATE_POLYGONS_AS_TRIFAN, ///< Tessellate the old way, interpreting polygons as triangle fans (faster, but does not work for concave polygons)
|
|
TESSELLATE_POLYGONS ///< Use full tessellation of polygons (slower, works for concave polygons)
|
|
};
|
|
|
|
struct Options
|
|
{
|
|
Options();
|
|
bool strictTransparency;
|
|
int precisionHint; ///< Precision hint flags, as specified in osgDB::Options::PrecisionHint
|
|
bool usePredefinedTextureUnits;
|
|
TessellateMode tessellateMode;
|
|
};
|
|
|
|
daeReader(DAE *dae_, const Options * pluginOptions);
|
|
virtual ~daeReader();
|
|
|
|
bool convert( std::istream &fin );
|
|
bool convert( const std::string &fileURI );
|
|
|
|
osg::Node* getRootNode() { return _rootNode; }
|
|
|
|
const std::string& getAssetUnitName() const {return _assetUnitName;}
|
|
float getAssetUnitMeter() const {return _assetUnitMeter;}
|
|
domUpAxisType getAssetUpAxis() const {return _assetUp_axis;}
|
|
|
|
enum TextureUnitUsage
|
|
{
|
|
AMBIENT_OCCLUSION_UNIT = 0,
|
|
MAIN_TEXTURE_UNIT,
|
|
TRANSPARENCY_MAP_UNIT
|
|
};
|
|
|
|
enum InterpolationType
|
|
{
|
|
INTERPOLATION_UNKNOWN,
|
|
INTERPOLATION_STEP,
|
|
INTERPOLATION_LINEAR,
|
|
INTERPOLATION_BEZIER,
|
|
INTERPOLATION_HERMITE,
|
|
INTERPOLATION_CARDINAL,
|
|
INTERPOLATION_BSPLINE,
|
|
|
|
//COLLADA spec states that if interpolation is not specified then
|
|
//interpolation is application defined. Linear is a sensible default.
|
|
INTERPOLATION_DEFAULT = INTERPOLATION_LINEAR
|
|
};
|
|
|
|
enum AuthoringTool
|
|
{
|
|
UNKNOWN,
|
|
BLENDER,
|
|
DAZ_STUDIO,
|
|
FBX_CONVERTER,
|
|
AUTODESK_3DS_MAX = FBX_CONVERTER,//3ds Max exports to DAE via Autodesk's FBX converter
|
|
GOOGLE_SKETCHUP,
|
|
MAYA
|
|
};
|
|
|
|
class TextureParameters
|
|
{
|
|
public:
|
|
TextureParameters()
|
|
: wrap_s(osg::Texture::REPEAT), wrap_t(osg::Texture::REPEAT),
|
|
filter_min(osg::Texture::LINEAR_MIPMAP_LINEAR), filter_mag(osg::Texture::LINEAR),
|
|
transparent(false), opaque(FX_OPAQUE_ENUM_A_ONE), transparency(1.0f)
|
|
{}
|
|
|
|
bool operator < (const TextureParameters& rhs) const
|
|
{
|
|
int diffStr = filename.compare(rhs.filename);
|
|
if (diffStr) return diffStr < 0;
|
|
if (wrap_s != rhs.wrap_s) return wrap_s < rhs.wrap_s;
|
|
if (wrap_t != rhs.wrap_t) return wrap_t < rhs.wrap_t;
|
|
if (filter_min != rhs.filter_min) return filter_min < rhs.filter_min;
|
|
if (filter_mag != rhs.filter_mag) return filter_mag < rhs.filter_mag;
|
|
if (transparency != rhs.transparency) return transparency < rhs.transparency;
|
|
if (opaque != rhs.opaque) return opaque < rhs.opaque;
|
|
if (transparent != rhs.transparent) return transparent < rhs.transparent;
|
|
return border < rhs.border;
|
|
}
|
|
|
|
std::string filename;
|
|
osg::Texture::WrapMode wrap_s, wrap_t;
|
|
osg::Texture::FilterMode filter_min, filter_mag;
|
|
osg::Vec4 border;
|
|
|
|
//The following parameters are for transparency textures, to handle
|
|
//COLLADA's horrible transparency spec.
|
|
bool transparent;
|
|
domFx_opaque_enum opaque;
|
|
float transparency;
|
|
};
|
|
|
|
class ChannelPart : public osg::Referenced
|
|
{
|
|
public:
|
|
std::string name;
|
|
osg::ref_ptr<osgAnimation::KeyframeContainer> keyframes;
|
|
InterpolationType interpolation;
|
|
};
|
|
|
|
typedef std::map<domGeometry*, osg::ref_ptr<osg::Geode> > domGeometryGeodeMap;
|
|
typedef std::map<domMaterial*, osg::ref_ptr<osg::StateSet> > domMaterialStateSetMap;
|
|
typedef std::map<std::string, osg::ref_ptr<osg::StateSet> > MaterialStateSetMap;
|
|
typedef std::multimap< daeElement*, domChannel*> daeElementDomChannelMap;
|
|
typedef std::map<domChannel*, osg::ref_ptr<osg::Callback> > domChannelOsgAnimationUpdateCallbackMap;
|
|
typedef std::map<domNode*, osg::ref_ptr<osgAnimation::Bone> > domNodeOsgBoneMap;
|
|
typedef std::map<domNode*, osg::ref_ptr<osgAnimation::Skeleton> > domNodeOsgSkeletonMap;
|
|
typedef std::map<TextureParameters, osg::ref_ptr<osg::Texture2D> > TextureParametersMap;
|
|
typedef std::map<std::pair<const osg::StateSet*, TextureUnitUsage>, std::string> TextureToCoordSetMap;
|
|
typedef std::map<std::string, size_t> IdToCoordIndexMap;
|
|
|
|
typedef std::map< daeElement*, domSourceReader > SourceMap;
|
|
typedef std::map< int, osg::IntArray*, std::less<int> > IndexMap;
|
|
typedef std::map< int, osg::Array*, std::less<int> > ArrayMap;
|
|
|
|
typedef std::multimap< osgAnimation::Target*, osg::ref_ptr<ChannelPart> > TargetChannelPartMap;
|
|
typedef std::multimap<std::pair<const domMesh*, size_t>, std::pair<osg::ref_ptr<osg::Geometry>, GLuint> > OldToNewIndexMap;
|
|
|
|
private:
|
|
bool processDocument( const std::string& );
|
|
void clearCaches();
|
|
|
|
// If the node is a bone then it should be added before any other types of
|
|
// node, this function makes that happen.
|
|
static void addChild(osg::Group*, osg::Node*);
|
|
|
|
//scene processing
|
|
osg::Group* turnZUp();
|
|
osg::Group* processVisualScene( domVisual_scene *scene );
|
|
osg::Node* processNode( domNode *node, bool skeleton );
|
|
osg::Transform* processOsgMatrixTransform( domNode *node, bool isBone);
|
|
|
|
template <typename T>
|
|
inline void getTransparencyCounts(daeDatabase*, int& zero, int& one) const;
|
|
|
|
/** Earlier versions of the COLLADA 1.4 spec state that transparency values
|
|
of 0 mean 100% opacity, but this has been changed in later versions to state
|
|
that transparency values of 1 mean 100% opacity. Documents created by
|
|
different tools at different times adhere to different versions of the
|
|
standard. This function looks at all transparency values in the database and
|
|
heuristically decides which way the values should be interpreted.*/
|
|
bool findInvertTransparency(daeDatabase*) const;
|
|
|
|
osgAnimation::BasicAnimationManager* processAnimationLibraries(domCOLLADA* document);
|
|
void processAnimationClip(osgAnimation::BasicAnimationManager* pOsgAnimationManager, domAnimation_clip* pDomAnimationClip);
|
|
void processAnimationMap(const TargetChannelPartMap&, osgAnimation::Animation* pOsgAnimation);
|
|
ChannelPart* processSampler(domChannel* pDomChannel, SourceMap &sources);
|
|
void processAnimationChannels(domAnimation* pDomAnimation, TargetChannelPartMap& tcm);
|
|
void processChannel(domChannel* pDomChannel, SourceMap &sources, TargetChannelPartMap& tcm);
|
|
void extractTargetName(const std::string&, std::string&, std::string&, std::string&);
|
|
|
|
// Processing of OSG specific info stored in node extras
|
|
osg::Group* processExtras(domNode *node);
|
|
void processNodeExtra(osg::Node* osgNode, domNode *node);
|
|
domTechnique* getOpenSceneGraphProfile(domExtra* extra);
|
|
void processAsset( domAsset *node );
|
|
|
|
osg::Group* processOsgSwitch(domTechnique* teq);
|
|
osg::Group* processOsgMultiSwitch(domTechnique* teq);
|
|
osg::Group* processOsgLOD(domTechnique* teq);
|
|
osg::Group* processOsgDOFTransform(domTechnique* teq);
|
|
osg::Group* processOsgSequence(domTechnique* teq);
|
|
|
|
// geometry processing
|
|
osg::Geode* getOrCreateGeometry(domGeometry *geom, domBind_material* pDomBindMaterial, const osg::Geode** ppOriginalGeode = NULL);
|
|
osgAnimation::Bone* getOrCreateBone(domNode *pDomNode);
|
|
osgAnimation::Skeleton* getOrCreateSkeleton(domNode *pDomNode);
|
|
osg::Geode* processInstanceGeometry( domInstance_geometry *ig );
|
|
|
|
osg::Geode* processMesh(domMesh* pDomMesh);
|
|
osg::Geode* processConvexMesh(domConvex_mesh* pDomConvexMesh);
|
|
osg::Geode* processSpline(domSpline* pDomSpline);
|
|
osg::Geode* processGeometry(domGeometry *pDomGeometry);
|
|
|
|
typedef std::vector<domInstance_controller*> domInstance_controllerList;
|
|
|
|
void processSkins();
|
|
//Process skins attached to one skeleton
|
|
void processSkeletonSkins(domNode* skeletonRoot, const domInstance_controllerList&);
|
|
void processSkin(domSkin* pDomSkin, domNode* skeletonRoot, osgAnimation::Skeleton*, domBind_material* pDomBindMaterial);
|
|
osg::Node* processMorph(domMorph* pDomMorph, domBind_material* pDomBindMaterial);
|
|
osg::Node* processInstanceController( domInstance_controller *ictrl );
|
|
|
|
template< typename T >
|
|
void processSinglePPrimitive(osg::Geode* geode, const domMesh* pDomMesh, const T* group, SourceMap& sources, GLenum mode);
|
|
|
|
template< typename T >
|
|
void processMultiPPrimitive(osg::Geode* geode, const domMesh* pDomMesh, const T* group, SourceMap& sources, GLenum mode);
|
|
|
|
void processPolylist(osg::Geode* geode, const domMesh* pDomMesh, const domPolylist *group, SourceMap &sources, TessellateMode tessellateMode);
|
|
|
|
template< typename T >
|
|
void processPolygons(osg::Geode* geode, const domMesh* pDomMesh, const T *group, SourceMap &sources, GLenum mode, TessellateMode tessellateMode);
|
|
|
|
void resolveMeshArrays(const domP_Array&,
|
|
const domInputLocalOffset_Array& inputs, const domMesh* pDomMesh,
|
|
osg::Geometry* geometry, SourceMap &sources,
|
|
std::vector<std::vector<GLuint> >& vertexLists);
|
|
|
|
//material/effect processing
|
|
void processBindMaterial( domBind_material *bm, domGeometry *geom, osg::Geode *geode, osg::Geode *cachedGeode );
|
|
void processMaterial(osg::StateSet *ss, domMaterial *mat );
|
|
void processEffect(osg::StateSet *ss, domEffect *effect );
|
|
void processProfileCOMMON(osg::StateSet *ss, domProfile_COMMON *pc );
|
|
bool processColorOrTextureType(const osg::StateSet*,
|
|
domCommon_color_or_texture_type *cot,
|
|
osg::Material::ColorMode channel,
|
|
osg::Material *mat,
|
|
domCommon_float_or_param_type *fop = NULL,
|
|
osg::Texture2D **sa = NULL,
|
|
bool normalizeShininess=false);
|
|
void processTransparencySettings( domCommon_transparent_type *ctt,
|
|
domCommon_float_or_param_type *pTransparency,
|
|
osg::StateSet*,
|
|
osg::Material *material,
|
|
unsigned int diffuseTextureUnit );
|
|
bool GetFloat4Param(xsNCName Reference, domFloat4 &f4) const;
|
|
bool GetFloatParam(xsNCName Reference, domFloat &f) const;
|
|
|
|
std::string processImagePath(const domImage*) const;
|
|
osg::Image* processImageTransparency(const osg::Image*, domFx_opaque_enum, float transparency) const;
|
|
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);
|
|
bool copyTextureCoordinateSet(const osg::StateSet* ss, const osg::Geometry* cachedGeometry, osg::Geometry* clonedGeometry, const domInstance_material* im, TextureUnitUsage tuu, unsigned int textureUnit);
|
|
|
|
//scene objects
|
|
osg::Node* processLight( domLight *dlight );
|
|
osg::Node* processCamera( domCamera *dcamera );
|
|
|
|
domNode* getRootJoint(domNode*) const;
|
|
domNode* findJointNode(daeElement* searchFrom, domInstance_controller*) const;
|
|
domNode* findSkeletonNode(daeElement* searchFrom, domInstance_controller*) const;
|
|
|
|
/// Return whether the node is used as a bone. Note that while many files
|
|
/// identify joints with type="JOINT", some don't do this, while others
|
|
/// incorrectly identify every node as a joint.
|
|
bool isJoint(const domNode* node) const {return _jointSet.find(node) != _jointSet.end();}
|
|
|
|
private:
|
|
|
|
DAE *_dae;
|
|
osg::Node* _rootNode;
|
|
osg::ref_ptr<osg::StateSet> _rootStateSet;
|
|
domCOLLADA* _document;
|
|
|
|
domVisual_scene* _visualScene;
|
|
|
|
std::map<std::string,bool> _targetMap;
|
|
|
|
int _numlights;
|
|
|
|
domInstance_effect *_currentInstance_effect;
|
|
domEffect *_currentEffect;
|
|
|
|
/// Maps an animated element to a domchannel to quickly find which animation influence this element
|
|
// TODO a single element can be animated by multiple channels (with different members like translate.x or morphweights(2) )
|
|
daeElementDomChannelMap _daeElementDomChannelMap;
|
|
/// Maps a domchannel to an animationupdatecallback
|
|
domChannelOsgAnimationUpdateCallbackMap _domChannelOsgAnimationUpdateCallbackMap;
|
|
/// Maps geometry to a Geode
|
|
domGeometryGeodeMap _geometryMap;
|
|
/// All nodes in the document that are used as joints.
|
|
std::set<const domNode*> _jointSet;
|
|
/// Maps a node (of type joint) to a osgAnimation::Bone
|
|
domNodeOsgBoneMap _jointMap;
|
|
/// Maps a node (of type joint) to a osgAnimation::Skeleton
|
|
domNodeOsgSkeletonMap _skeletonMap;
|
|
// Maps material target to stateset
|
|
domMaterialStateSetMap _materialMap;
|
|
// Maps material symbol to stateset
|
|
MaterialStateSetMap _materialMap2;
|
|
TextureParametersMap _textureParamMap;
|
|
TextureToCoordSetMap _texCoordSetMap;
|
|
IdToCoordIndexMap _texCoordIdMap;
|
|
domInstance_controllerList _skinInstanceControllers;
|
|
OldToNewIndexMap _oldToNewIndexMap;
|
|
|
|
AuthoringTool _authoringTool;
|
|
bool _invertTransparency;
|
|
Options _pluginOptions;
|
|
|
|
// Additional Information
|
|
std::string _assetUnitName;
|
|
float _assetUnitMeter;
|
|
domUpAxisType _assetUp_axis;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|