nuclear@0: /* nuclear@0: Open Asset Import Library (assimp) nuclear@0: ---------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2012, assimp team nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the nuclear@0: following conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: nuclear@0: ---------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: /** @file ColladaParser.h nuclear@0: * @brief Defines the parser helper class for the collada loader nuclear@0: */ nuclear@0: nuclear@0: #ifndef AI_COLLADAPARSER_H_INC nuclear@0: #define AI_COLLADAPARSER_H_INC nuclear@0: nuclear@0: #include "irrXMLWrapper.h" nuclear@0: #include "ColladaHelper.h" nuclear@0: nuclear@0: namespace Assimp nuclear@0: { nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------ nuclear@0: /** Parser helper class for the Collada loader. nuclear@0: * nuclear@0: * Does all the XML reading and builds internal data structures from it, nuclear@0: * but leaves the resolving of all the references to the loader. nuclear@0: */ nuclear@0: class ColladaParser nuclear@0: { nuclear@0: friend class ColladaLoader; nuclear@0: nuclear@0: protected: nuclear@0: /** Constructor from XML file */ nuclear@0: ColladaParser( IOSystem* pIOHandler, const std::string& pFile); nuclear@0: nuclear@0: /** Destructor */ nuclear@0: ~ColladaParser(); nuclear@0: nuclear@0: /** Reads the contents of the file */ nuclear@0: void ReadContents(); nuclear@0: nuclear@0: /** Reads the structure of the file */ nuclear@0: void ReadStructure(); nuclear@0: nuclear@0: /** Reads asset informations such as coordinate system informations and legal blah */ nuclear@0: void ReadAssetInfo(); nuclear@0: nuclear@0: /** Reads the animation library */ nuclear@0: void ReadAnimationLibrary(); nuclear@0: nuclear@0: /** Reads an animation into the given parent structure */ nuclear@0: void ReadAnimation( Collada::Animation* pParent); nuclear@0: nuclear@0: /** Reads an animation sampler into the given anim channel */ nuclear@0: void ReadAnimationSampler( Collada::AnimationChannel& pChannel); nuclear@0: nuclear@0: /** Reads the skeleton controller library */ nuclear@0: void ReadControllerLibrary(); nuclear@0: nuclear@0: /** Reads a controller into the given mesh structure */ nuclear@0: void ReadController( Collada::Controller& pController); nuclear@0: nuclear@0: /** Reads the joint definitions for the given controller */ nuclear@0: void ReadControllerJoints( Collada::Controller& pController); nuclear@0: nuclear@0: /** Reads the joint weights for the given controller */ nuclear@0: void ReadControllerWeights( Collada::Controller& pController); nuclear@0: nuclear@0: /** Reads the image library contents */ nuclear@0: void ReadImageLibrary(); nuclear@0: nuclear@0: /** Reads an image entry into the given image */ nuclear@0: void ReadImage( Collada::Image& pImage); nuclear@0: nuclear@0: /** Reads the material library */ nuclear@0: void ReadMaterialLibrary(); nuclear@0: nuclear@0: /** Reads a material entry into the given material */ nuclear@0: void ReadMaterial( Collada::Material& pMaterial); nuclear@0: nuclear@0: /** Reads the camera library */ nuclear@0: void ReadCameraLibrary(); nuclear@0: nuclear@0: /** Reads a camera entry into the given camera */ nuclear@0: void ReadCamera( Collada::Camera& pCamera); nuclear@0: nuclear@0: /** Reads the light library */ nuclear@0: void ReadLightLibrary(); nuclear@0: nuclear@0: /** Reads a light entry into the given light */ nuclear@0: void ReadLight( Collada::Light& pLight); nuclear@0: nuclear@0: /** Reads the effect library */ nuclear@0: void ReadEffectLibrary(); nuclear@0: nuclear@0: /** Reads an effect entry into the given effect*/ nuclear@0: void ReadEffect( Collada::Effect& pEffect); nuclear@0: nuclear@0: /** Reads an COMMON effect profile */ nuclear@0: void ReadEffectProfileCommon( Collada::Effect& pEffect); nuclear@0: nuclear@0: /** Read sampler properties */ nuclear@0: void ReadSamplerProperties( Collada::Sampler& pSampler); nuclear@0: nuclear@0: /** Reads an effect entry containing a color or a texture defining that color */ nuclear@0: void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler); nuclear@0: nuclear@0: /** Reads an effect entry containing a float */ nuclear@0: void ReadEffectFloat( float& pFloat); nuclear@0: nuclear@0: /** Reads an effect parameter specification of any kind */ nuclear@0: void ReadEffectParam( Collada::EffectParam& pParam); nuclear@0: nuclear@0: /** Reads the geometry library contents */ nuclear@0: void ReadGeometryLibrary(); nuclear@0: nuclear@0: /** Reads a geometry from the geometry library. */ nuclear@0: void ReadGeometry( Collada::Mesh* pMesh); nuclear@0: nuclear@0: /** Reads a mesh from the geometry library */ nuclear@0: void ReadMesh( Collada::Mesh* pMesh); nuclear@0: nuclear@0: /** Reads a source element - a combination of raw data and an accessor defining nuclear@0: * things that should not be redefinable. Yes, that's another rant. nuclear@0: */ nuclear@0: void ReadSource(); nuclear@0: nuclear@0: /** Reads a data array holding a number of elements, and stores it in the global library. nuclear@0: * Currently supported are array of floats and arrays of strings. nuclear@0: */ nuclear@0: void ReadDataArray(); nuclear@0: nuclear@0: /** Reads an accessor and stores it in the global library under the given ID - nuclear@0: * accessors use the ID of the parent element nuclear@0: */ nuclear@0: void ReadAccessor( const std::string& pID); nuclear@0: nuclear@0: /** Reads input declarations of per-vertex mesh data into the given mesh */ nuclear@0: void ReadVertexData( Collada::Mesh* pMesh); nuclear@0: nuclear@0: /** Reads input declarations of per-index mesh data into the given mesh */ nuclear@0: void ReadIndexData( Collada::Mesh* pMesh); nuclear@0: nuclear@0: /** Reads a single input channel element and stores it in the given array, if valid */ nuclear@0: void ReadInputChannel( std::vector& poChannels); nuclear@0: nuclear@0: /** Reads a

primitive index list and assembles the mesh data into the given mesh */ nuclear@0: void ReadPrimitives( Collada::Mesh* pMesh, std::vector& pPerIndexChannels, nuclear@0: size_t pNumPrimitives, const std::vector& pVCount, Collada::PrimitiveType pPrimType); nuclear@0: nuclear@0: /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */ nuclear@0: void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh); nuclear@0: nuclear@0: /** Reads the library of node hierarchies and scene parts */ nuclear@0: void ReadSceneLibrary(); nuclear@0: nuclear@0: /** Reads a scene node's contents including children and stores it in the given node */ nuclear@0: void ReadSceneNode( Collada::Node* pNode); nuclear@0: nuclear@0: /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */ nuclear@0: void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType); nuclear@0: nuclear@0: /** Reads a mesh reference in a node and adds it to the node's mesh list */ nuclear@0: void ReadNodeGeometry( Collada::Node* pNode); nuclear@0: nuclear@0: /** Reads the collada scene */ nuclear@0: void ReadScene(); nuclear@0: nuclear@0: // Processes bind_vertex_input and bind elements nuclear@0: void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl); nuclear@0: nuclear@0: protected: nuclear@0: /** Aborts the file reading with an exception */ nuclear@0: void ThrowException( const std::string& pError) const; nuclear@0: nuclear@0: /** Skips all data until the end node of the current element */ nuclear@0: void SkipElement(); nuclear@0: nuclear@0: /** Skips all data until the end node of the given element */ nuclear@0: void SkipElement( const char* pElement); nuclear@0: nuclear@0: /** Compares the current xml element name to the given string and returns true if equal */ nuclear@0: bool IsElement( const char* pName) const; nuclear@0: nuclear@0: /** Tests for the opening tag of the given element, throws an exception if not found */ nuclear@0: void TestOpening( const char* pName); nuclear@0: nuclear@0: /** Tests for the closing tag of the given element, throws an exception if not found */ nuclear@0: void TestClosing( const char* pName); nuclear@0: nuclear@0: /** Checks the present element for the presence of the attribute, returns its index nuclear@0: or throws an exception if not found */ nuclear@0: int GetAttribute( const char* pAttr) const; nuclear@0: nuclear@0: /** Returns the index of the named attribute or -1 if not found. Does not throw, nuclear@0: therefore useful for optional attributes */ nuclear@0: int TestAttribute( const char* pAttr) const; nuclear@0: nuclear@0: /** Reads the text contents of an element, throws an exception if not given. nuclear@0: Skips leading whitespace. */ nuclear@0: const char* GetTextContent(); nuclear@0: nuclear@0: /** Reads the text contents of an element, returns NULL if not given. nuclear@0: Skips leading whitespace. */ nuclear@0: const char* TestTextContent(); nuclear@0: nuclear@0: /** Reads a single bool from current text content */ nuclear@0: bool ReadBoolFromTextContent(); nuclear@0: nuclear@0: /** Reads a single float from current text content */ nuclear@0: float ReadFloatFromTextContent(); nuclear@0: nuclear@0: /** Calculates the resulting transformation from all the given transform steps */ nuclear@0: aiMatrix4x4 CalculateResultTransform( const std::vector& pTransforms) const; nuclear@0: nuclear@0: /** Determines the input data type for the given semantic string */ nuclear@0: Collada::InputType GetTypeForSemantic( const std::string& pSemantic); nuclear@0: nuclear@0: /** Finds the item in the given library by its reference, throws if not found */ nuclear@0: template const Type& ResolveLibraryReference( nuclear@0: const std::map& pLibrary, const std::string& pURL) const; nuclear@0: nuclear@0: protected: nuclear@0: /** Filename, for a verbose error message */ nuclear@0: std::string mFileName; nuclear@0: nuclear@0: /** XML reader, member for everyday use */ nuclear@0: irr::io::IrrXMLReader* mReader; nuclear@0: nuclear@0: /** All data arrays found in the file by ID. Might be referred to by actually nuclear@0: everyone. Collada, you are a steaming pile of indirection. */ nuclear@0: typedef std::map DataLibrary; nuclear@0: DataLibrary mDataLibrary; nuclear@0: nuclear@0: /** Same for accessors which define how the data in a data array is accessed. */ nuclear@0: typedef std::map AccessorLibrary; nuclear@0: AccessorLibrary mAccessorLibrary; nuclear@0: nuclear@0: /** Mesh library: mesh by ID */ nuclear@0: typedef std::map MeshLibrary; nuclear@0: MeshLibrary mMeshLibrary; nuclear@0: nuclear@0: /** node library: root node of the hierarchy part by ID */ nuclear@0: typedef std::map NodeLibrary; nuclear@0: NodeLibrary mNodeLibrary; nuclear@0: nuclear@0: /** Image library: stores texture properties by ID */ nuclear@0: typedef std::map ImageLibrary; nuclear@0: ImageLibrary mImageLibrary; nuclear@0: nuclear@0: /** Effect library: surface attributes by ID */ nuclear@0: typedef std::map EffectLibrary; nuclear@0: EffectLibrary mEffectLibrary; nuclear@0: nuclear@0: /** Material library: surface material by ID */ nuclear@0: typedef std::map MaterialLibrary; nuclear@0: MaterialLibrary mMaterialLibrary; nuclear@0: nuclear@0: /** Light library: surface light by ID */ nuclear@0: typedef std::map LightLibrary; nuclear@0: LightLibrary mLightLibrary; nuclear@0: nuclear@0: /** Camera library: surface material by ID */ nuclear@0: typedef std::map CameraLibrary; nuclear@0: CameraLibrary mCameraLibrary; nuclear@0: nuclear@0: /** Controller library: joint controllers by ID */ nuclear@0: typedef std::map ControllerLibrary; nuclear@0: ControllerLibrary mControllerLibrary; nuclear@0: nuclear@0: /** Pointer to the root node. Don't delete, it just points to one of nuclear@0: the nodes in the node library. */ nuclear@0: Collada::Node* mRootNode; nuclear@0: nuclear@0: /** Root animation container */ nuclear@0: Collada::Animation mAnims; nuclear@0: nuclear@0: /** Size unit: how large compared to a meter */ nuclear@0: float mUnitSize; nuclear@0: nuclear@0: /** Which is the up vector */ nuclear@0: enum { UP_X, UP_Y, UP_Z } mUpDirection; nuclear@0: nuclear@0: /** Collada file format version */ nuclear@0: Collada::FormatVersion mFormat; nuclear@0: }; nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Check for element match nuclear@0: inline bool ColladaParser::IsElement( const char* pName) const nuclear@0: { nuclear@0: ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT); nuclear@0: return ::strcmp( mReader->getNodeName(), pName) == 0; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Finds the item in the given library by its reference, throws if not found nuclear@0: template nuclear@0: const Type& ColladaParser::ResolveLibraryReference( const std::map& pLibrary, const std::string& pURL) const nuclear@0: { nuclear@0: typename std::map::const_iterator it = pLibrary.find( pURL); nuclear@0: if( it == pLibrary.end()) nuclear@0: ThrowException( boost::str( boost::format( "Unable to resolve library reference \"%s\".") % pURL)); nuclear@0: return it->second; nuclear@0: } nuclear@0: nuclear@0: } // end of namespace Assimp nuclear@0: nuclear@0: #endif // AI_COLLADAPARSER_H_INC