1 /* 2 Open Asset Import Library (assimp) 3 ---------------------------------------------------------------------- 4 5 Copyright (c) 2006-2015, assimp team 6 All rights reserved. 7 8 Redistribution and use of this software in source and binary forms, 9 with or without modification, are permitted provided that the 10 following conditions are met: 11 12 * Redistributions of source code must retain the above 13 copyright notice, this list of conditions and the 14 following disclaimer. 15 16 * Redistributions in binary form must reproduce the above 17 copyright notice, this list of conditions and the 18 following disclaimer in the documentation and/or other 19 materials provided with the distribution. 20 21 * Neither the name of the assimp team, nor the names of its 22 contributors may be used to endorse or promote products 23 derived from this software without specific prior 24 written permission of the assimp team. 25 26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 38 ---------------------------------------------------------------------- 39 */ 40 41 /** @file ColladaParser.h 42 * @brief Defines the parser helper class for the collada loader 43 */ 44 45 #ifndef AI_COLLADAPARSER_H_INC 46 #define AI_COLLADAPARSER_H_INC 47 48 #include "irrXMLWrapper.h" 49 #include "ColladaHelper.h" 50 #include "../include/assimp/ai_assert.h" 51 #include <boost/format.hpp> 52 53 namespace Assimp 54 { 55 56 // ------------------------------------------------------------------------------------------ 57 /** Parser helper class for the Collada loader. 58 * 59 * Does all the XML reading and builds internal data structures from it, 60 * but leaves the resolving of all the references to the loader. 61 */ 62 class ColladaParser 63 { 64 friend class ColladaLoader; 65 66 protected: 67 /** Constructor from XML file */ 68 ColladaParser( IOSystem* pIOHandler, const std::string& pFile); 69 70 /** Destructor */ 71 ~ColladaParser(); 72 73 /** Reads the contents of the file */ 74 void ReadContents(); 75 76 /** Reads the structure of the file */ 77 void ReadStructure(); 78 79 /** Reads asset informations such as coordinate system informations and legal blah */ 80 void ReadAssetInfo(); 81 82 /** Reads the animation library */ 83 void ReadAnimationLibrary(); 84 85 /** Reads an animation into the given parent structure */ 86 void ReadAnimation( Collada::Animation* pParent); 87 88 /** Reads an animation sampler into the given anim channel */ 89 void ReadAnimationSampler( Collada::AnimationChannel& pChannel); 90 91 /** Reads the skeleton controller library */ 92 void ReadControllerLibrary(); 93 94 /** Reads a controller into the given mesh structure */ 95 void ReadController( Collada::Controller& pController); 96 97 /** Reads the joint definitions for the given controller */ 98 void ReadControllerJoints( Collada::Controller& pController); 99 100 /** Reads the joint weights for the given controller */ 101 void ReadControllerWeights( Collada::Controller& pController); 102 103 /** Reads the image library contents */ 104 void ReadImageLibrary(); 105 106 /** Reads an image entry into the given image */ 107 void ReadImage( Collada::Image& pImage); 108 109 /** Reads the material library */ 110 void ReadMaterialLibrary(); 111 112 /** Reads a material entry into the given material */ 113 void ReadMaterial( Collada::Material& pMaterial); 114 115 /** Reads the camera library */ 116 void ReadCameraLibrary(); 117 118 /** Reads a camera entry into the given camera */ 119 void ReadCamera( Collada::Camera& pCamera); 120 121 /** Reads the light library */ 122 void ReadLightLibrary(); 123 124 /** Reads a light entry into the given light */ 125 void ReadLight( Collada::Light& pLight); 126 127 /** Reads the effect library */ 128 void ReadEffectLibrary(); 129 130 /** Reads an effect entry into the given effect*/ 131 void ReadEffect( Collada::Effect& pEffect); 132 133 /** Reads an COMMON effect profile */ 134 void ReadEffectProfileCommon( Collada::Effect& pEffect); 135 136 /** Read sampler properties */ 137 void ReadSamplerProperties( Collada::Sampler& pSampler); 138 139 /** Reads an effect entry containing a color or a texture defining that color */ 140 void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler); 141 142 /** Reads an effect entry containing a float */ 143 void ReadEffectFloat( float& pFloat); 144 145 /** Reads an effect parameter specification of any kind */ 146 void ReadEffectParam( Collada::EffectParam& pParam); 147 148 /** Reads the geometry library contents */ 149 void ReadGeometryLibrary(); 150 151 /** Reads a geometry from the geometry library. */ 152 void ReadGeometry( Collada::Mesh* pMesh); 153 154 /** Reads a mesh from the geometry library */ 155 void ReadMesh( Collada::Mesh* pMesh); 156 157 /** Reads a source element - a combination of raw data and an accessor defining 158 * things that should not be redefinable. Yes, that's another rant. 159 */ 160 void ReadSource(); 161 162 /** Reads a data array holding a number of elements, and stores it in the global library. 163 * Currently supported are array of floats and arrays of strings. 164 */ 165 void ReadDataArray(); 166 167 /** Reads an accessor and stores it in the global library under the given ID - 168 * accessors use the ID of the parent <source> element 169 */ 170 void ReadAccessor( const std::string& pID); 171 172 /** Reads input declarations of per-vertex mesh data into the given mesh */ 173 void ReadVertexData( Collada::Mesh* pMesh); 174 175 /** Reads input declarations of per-index mesh data into the given mesh */ 176 void ReadIndexData( Collada::Mesh* pMesh); 177 178 /** Reads a single input channel element and stores it in the given array, if valid */ 179 void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels); 180 181 /** Reads a <p> primitive index list and assembles the mesh data into the given mesh */ 182 size_t ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels, 183 size_t pNumPrimitives, const std::vector<size_t>& pVCount, Collada::PrimitiveType pPrimType); 184 185 /** Copies the data for a single primitive into the mesh, based on the InputChannels */ 186 void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, 187 Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels, 188 size_t currentPrimitive, const std::vector<size_t>& indices); 189 190 /** Reads one triangle of a tristrip into the mesh */ 191 void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh, 192 std::vector<Collada::InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices); 193 194 /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */ 195 void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh); 196 197 /** Reads the library of node hierarchies and scene parts */ 198 void ReadSceneLibrary(); 199 200 /** Reads a scene node's contents including children and stores it in the given node */ 201 void ReadSceneNode( Collada::Node* pNode); 202 203 /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */ 204 void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType); 205 206 /** Reads a mesh reference in a node and adds it to the node's mesh list */ 207 void ReadNodeGeometry( Collada::Node* pNode); 208 209 /** Reads the collada scene */ 210 void ReadScene(); 211 212 // Processes bind_vertex_input and bind elements 213 void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl); 214 215 protected: 216 /** Aborts the file reading with an exception */ 217 AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX; 218 void ReportWarning(const char* msg,...); 219 220 /** Skips all data until the end node of the current element */ 221 void SkipElement(); 222 223 /** Skips all data until the end node of the given element */ 224 void SkipElement( const char* pElement); 225 226 /** Compares the current xml element name to the given string and returns true if equal */ 227 bool IsElement( const char* pName) const; 228 229 /** Tests for the opening tag of the given element, throws an exception if not found */ 230 void TestOpening( const char* pName); 231 232 /** Tests for the closing tag of the given element, throws an exception if not found */ 233 void TestClosing( const char* pName); 234 235 /** Checks the present element for the presence of the attribute, returns its index 236 or throws an exception if not found */ 237 int GetAttribute( const char* pAttr) const; 238 239 /** Returns the index of the named attribute or -1 if not found. Does not throw, 240 therefore useful for optional attributes */ 241 int TestAttribute( const char* pAttr) const; 242 243 /** Reads the text contents of an element, throws an exception if not given. 244 Skips leading whitespace. */ 245 const char* GetTextContent(); 246 247 /** Reads the text contents of an element, returns NULL if not given. 248 Skips leading whitespace. */ 249 const char* TestTextContent(); 250 251 /** Reads a single bool from current text content */ 252 bool ReadBoolFromTextContent(); 253 254 /** Reads a single float from current text content */ 255 float ReadFloatFromTextContent(); 256 257 /** Calculates the resulting transformation from all the given transform steps */ 258 aiMatrix4x4 CalculateResultTransform( const std::vector<Collada::Transform>& pTransforms) const; 259 260 /** Determines the input data type for the given semantic string */ 261 Collada::InputType GetTypeForSemantic( const std::string& pSemantic); 262 263 /** Finds the item in the given library by its reference, throws if not found */ 264 template <typename Type> const Type& ResolveLibraryReference( 265 const std::map<std::string, Type>& pLibrary, const std::string& pURL) const; 266 267 protected: 268 /** Filename, for a verbose error message */ 269 std::string mFileName; 270 271 /** XML reader, member for everyday use */ 272 irr::io::IrrXMLReader* mReader; 273 274 /** All data arrays found in the file by ID. Might be referred to by actually 275 everyone. Collada, you are a steaming pile of indirection. */ 276 typedef std::map<std::string, Collada::Data> DataLibrary; 277 DataLibrary mDataLibrary; 278 279 /** Same for accessors which define how the data in a data array is accessed. */ 280 typedef std::map<std::string, Collada::Accessor> AccessorLibrary; 281 AccessorLibrary mAccessorLibrary; 282 283 /** Mesh library: mesh by ID */ 284 typedef std::map<std::string, Collada::Mesh*> MeshLibrary; 285 MeshLibrary mMeshLibrary; 286 287 /** node library: root node of the hierarchy part by ID */ 288 typedef std::map<std::string, Collada::Node*> NodeLibrary; 289 NodeLibrary mNodeLibrary; 290 291 /** Image library: stores texture properties by ID */ 292 typedef std::map<std::string, Collada::Image> ImageLibrary; 293 ImageLibrary mImageLibrary; 294 295 /** Effect library: surface attributes by ID */ 296 typedef std::map<std::string, Collada::Effect> EffectLibrary; 297 EffectLibrary mEffectLibrary; 298 299 /** Material library: surface material by ID */ 300 typedef std::map<std::string, Collada::Material> MaterialLibrary; 301 MaterialLibrary mMaterialLibrary; 302 303 /** Light library: surface light by ID */ 304 typedef std::map<std::string, Collada::Light> LightLibrary; 305 LightLibrary mLightLibrary; 306 307 /** Camera library: surface material by ID */ 308 typedef std::map<std::string, Collada::Camera> CameraLibrary; 309 CameraLibrary mCameraLibrary; 310 311 /** Controller library: joint controllers by ID */ 312 typedef std::map<std::string, Collada::Controller> ControllerLibrary; 313 ControllerLibrary mControllerLibrary; 314 315 /** Pointer to the root node. Don't delete, it just points to one of 316 the nodes in the node library. */ 317 Collada::Node* mRootNode; 318 319 /** Root animation container */ 320 Collada::Animation mAnims; 321 322 /** Size unit: how large compared to a meter */ 323 float mUnitSize; 324 325 /** Which is the up vector */ 326 enum { UP_X, UP_Y, UP_Z } mUpDirection; 327 328 /** Collada file format version */ 329 Collada::FormatVersion mFormat; 330 }; 331 332 // ------------------------------------------------------------------------------------------------ 333 // Check for element match IsElement(const char * pName)334 inline bool ColladaParser::IsElement( const char* pName) const 335 { 336 ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT); 337 return ::strcmp( mReader->getNodeName(), pName) == 0; 338 } 339 340 // ------------------------------------------------------------------------------------------------ 341 // Finds the item in the given library by its reference, throws if not found 342 template <typename Type> ResolveLibraryReference(const std::map<std::string,Type> & pLibrary,const std::string & pURL)343 const Type& ColladaParser::ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const 344 { 345 typename std::map<std::string, Type>::const_iterator it = pLibrary.find( pURL); 346 if( it == pLibrary.end()) 347 ThrowException( boost::str( boost::format( "Unable to resolve library reference \"%s\".") % pURL)); 348 return it->second; 349 } 350 351 } // end of namespace Assimp 352 353 #endif // AI_COLLADAPARSER_H_INC 354