1 /* 2 Copyright (c) 2008-2009 NetAllied Systems GmbH 3 4 This file is part of COLLADASaxFrameworkLoader. 5 6 Licensed under the MIT Open Source License, 7 for details please see LICENSE file or the website 8 http://www.opensource.org/licenses/mit-license.php 9 */ 10 11 #include "COLLADASaxFWLStableHeaders.h" 12 #include "COLLADASaxFWLLoader.h" 13 #include "COLLADASaxFWLFileLoader.h" 14 #include "COLLADASaxFWLPostProcessor.h" 15 #include "COLLADASaxFWLSaxParserErrorHandler.h" 16 #include "COLLADASaxFWLUtils.h" 17 18 #include "COLLADABUURI.h" 19 20 #include "COLLADAFWVisualScene.h" 21 #include "COLLADAFWLibraryNodes.h" 22 #include "COLLADAFWIWriter.h" 23 #include "COLLADAFWEffect.h" 24 #include "COLLADAFWLight.h" 25 #include "COLLADAFWCamera.h" 26 #include "COLLADAFWAnimationList.h" 27 #include "COLLADAFWConstants.h" 28 29 #include <sys/types.h> 30 #include <sys/timeb.h> 31 #include <fstream> 32 33 namespace COLLADASaxFWL 34 { 35 36 const Loader::InstanceControllerDataList Loader::EMPTY_INSTANCE_CONTROLLER_DATALIST = Loader::InstanceControllerDataList(); 37 38 const Loader::JointSidsOrIds Loader::EMPTY_JOINTSIDSORIDS; 39 40 Loader(IErrorHandler * errorHandler)41 Loader::Loader( IErrorHandler* errorHandler ) 42 : mFileLoader(0) 43 , mNextFileId(0) 44 , mCurrentFileId(0) 45 , mErrorHandler(errorHandler) 46 , mNextTextureMapId(0) 47 , mObjectFlags( Loader::ALL_OBJECTS_MASK ) 48 , mParsedObjectFlags( Loader::NO_FLAG ) 49 , mSidTreeRoot( new SidTreeNode("", 0) ) 50 , mSkinControllerSet( compare ) 51 , mExternalReferenceDeciderCallbackFunction() 52 53 { 54 } 55 56 57 //--------------------------------- ~Loader()58 Loader::~Loader() 59 { 60 delete mSidTreeRoot; 61 62 // delete visual scenes 63 deleteVectorFW(mVisualScenes); 64 65 // delete library nodes 66 deleteVectorFW(mLibraryNodes); 67 68 // delete effects 69 deleteVectorFW(mEffects); 70 71 // delete lights 72 deleteVectorFW(mLights); 73 74 // delete cameras 75 deleteVectorFW(mCameras); 76 77 // We do not delete formulas here. They are deleted by the Formulas class 78 79 // delete animation lists 80 Loader::UniqueIdAnimationListMap::const_iterator it = mUniqueIdAnimationListMap.begin(); 81 for ( ; it != mUniqueIdAnimationListMap.end(); ++it ) 82 { 83 COLLADAFW::AnimationList* animationList = it->second; 84 FW_DELETE animationList; 85 } 86 } 87 88 //--------------------------------- getUniqueId(const COLLADABU::URI & uri,COLLADAFW::ClassId classId)89 const COLLADAFW::UniqueId& Loader::getUniqueId( const COLLADABU::URI& uri, COLLADAFW::ClassId classId ) 90 { 91 URIUniqueIdMap::iterator it = mURIUniqueIdMap.find(uri); 92 if ( it == mURIUniqueIdMap.end() ) 93 { 94 return mURIUniqueIdMap[uri] = COLLADAFW::UniqueId(classId, mLoaderUtil.getLowestObjectIdFor(classId), getFileId(uri)); 95 } 96 else 97 { 98 return it->second; 99 } 100 } 101 102 //--------------------------------- getUniqueId(const COLLADABU::URI & uri)103 const COLLADAFW::UniqueId& Loader::getUniqueId( const COLLADABU::URI& uri) 104 { 105 URIUniqueIdMap::iterator it = mURIUniqueIdMap.find(uri); 106 if ( it == mURIUniqueIdMap.end() ) 107 { 108 return COLLADAFW::UniqueId::INVALID; 109 } 110 else 111 { 112 return it->second; 113 } 114 } 115 116 //--------------------------------- getUniqueId(COLLADAFW::ClassId classId)117 COLLADAFW::UniqueId Loader::getUniqueId( COLLADAFW::ClassId classId ) 118 { 119 return COLLADAFW::UniqueId(classId, mLoaderUtil.getLowestObjectIdFor(classId), mCurrentFileId); 120 } 121 122 //--------------------------------- getUniqueIdMap(void) const123 const COLLADASaxFWL::Loader::URIUniqueIdMap& Loader::getUniqueIdMap(void) const 124 { 125 return mURIUniqueIdMap; 126 } 127 //--------------------------------- getFileId(const COLLADABU::URI & uri)128 COLLADAFW::FileId Loader::getFileId( const COLLADABU::URI& uri ) 129 { 130 // check if the uri is relative 131 bool isRelative = uri.getScheme().empty() && 132 uri.getAuthority().empty() && 133 uri.getPath().empty() && 134 uri.getQuery().empty(); 135 if ( isRelative ) 136 { 137 // its a relative uri. The file id is that of the current file 138 return mCurrentFileId; 139 } 140 141 // the uri is not relative. We need to find the correct file id 142 const COLLADABU::URI* usedUri = 0; 143 144 COLLADABU::URI uriWithoutFragment; 145 146 if ( uri.getFragment().empty() ) 147 { 148 // the passed uri has no fragment, we can use it without modification 149 usedUri = &uri; 150 } 151 else 152 { 153 // the passed uri has a fragment, we need to make a copy without fragment 154 uriWithoutFragment.set( uri.getScheme(), uri.getAuthority(), uri.getPath(), uri.getQuery(), COLLADAFW::Constants::EMPTY_STRING); 155 usedUri = &uriWithoutFragment; 156 } 157 158 URIFileIdMap::iterator it = mURIFileIdMap.find( *usedUri ); 159 160 if ( it == mURIFileIdMap.end() ) 161 { 162 COLLADAFW::FileId fileId = mNextFileId++; 163 addFileIdUriPair( fileId, *usedUri ); 164 return fileId; 165 } 166 else 167 { 168 return it->second; 169 } 170 } 171 172 //--------------------------------- getFileUri(COLLADAFW::FileId fileId) const173 const COLLADABU::URI& Loader::getFileUri( COLLADAFW::FileId fileId )const 174 { 175 FileIdURIMap::const_iterator it = mFileIdURIMap.find( fileId ); 176 177 if ( it == mFileIdURIMap.end() ) 178 { 179 return COLLADABU::URI::INVALID; 180 } 181 else 182 { 183 return it->second; 184 } 185 } 186 187 //--------------------------------- addFileIdUriPair(COLLADAFW::FileId fileId,const COLLADABU::URI & uri)188 void Loader::addFileIdUriPair( COLLADAFW::FileId fileId, const COLLADABU::URI& uri ) 189 { 190 mURIFileIdMap[uri] = fileId; 191 mFileIdURIMap[fileId] = uri; 192 } 193 194 //--------------------------------- loadDocument(const String & fileName,COLLADAFW::IWriter * writer)195 bool Loader::loadDocument( const String& fileName, COLLADAFW::IWriter* writer ) 196 { 197 if ( !writer ) 198 return false; 199 mWriter = writer; 200 201 mWriter->start(); 202 203 SaxParserErrorHandler saxParserErrorHandler(mErrorHandler); 204 205 COLLADABU::URI rootFileUri(COLLADABU::URI::nativePathToUri(fileName)); 206 207 // the root file has always file id 0 208 addFileIdUriPair( mNextFileId++, rootFileUri ); 209 210 bool abortLoading = false; 211 212 while ( (mCurrentFileId < mNextFileId) && !abortLoading ) 213 { 214 const COLLADABU::URI& fileUri = getFileUri( mCurrentFileId ); 215 216 if ( (mCurrentFileId == 0) 217 || !mExternalReferenceDeciderCallbackFunction 218 || mExternalReferenceDeciderCallbackFunction(fileUri, mCurrentFileId) ) 219 { 220 mFileLoader = new FileLoader(this, 221 fileUri, 222 &saxParserErrorHandler, 223 mObjectFlags, 224 mParsedObjectFlags, 225 mExtraDataCallbackHandlerList ); 226 bool success = mFileLoader->load(); 227 delete mFileLoader; 228 abortLoading = !success; 229 } 230 231 mCurrentFileId++; 232 } 233 234 if ( !abortLoading ) 235 { 236 PostProcessor postProcessor(this, 237 &saxParserErrorHandler, 238 mObjectFlags, 239 mParsedObjectFlags); 240 postProcessor.postProcess(); 241 } 242 else 243 { 244 mWriter->cancel("Generic error"); 245 } 246 247 mWriter->finish(); 248 249 mParsedObjectFlags |= mObjectFlags; 250 251 return !abortLoading; 252 } 253 254 //--------------------------------- loadDocument(const String & uri,const char * buffer,int length,COLLADAFW::IWriter * writer)255 bool Loader::loadDocument( const String& uri, const char* buffer, int length, COLLADAFW::IWriter* writer ) 256 { 257 if ( !writer ) 258 return false; 259 mWriter = writer; 260 261 SaxParserErrorHandler saxParserErrorHandler(mErrorHandler); 262 263 COLLADABU::URI rootUri(uri); 264 265 // the root file has always file id 0 266 addFileIdUriPair( mNextFileId++, rootUri ); 267 268 bool abortLoading = false; 269 270 while ( (mCurrentFileId < mNextFileId) && !abortLoading ) 271 { 272 const COLLADABU::URI& fileUri = getFileUri( mCurrentFileId ); 273 274 if ( (mCurrentFileId == 0) 275 || !mExternalReferenceDeciderCallbackFunction 276 || mExternalReferenceDeciderCallbackFunction(fileUri, mCurrentFileId) ) 277 { 278 FileLoader fileLoader(this, 279 getFileUri( mCurrentFileId ), 280 &saxParserErrorHandler, 281 mObjectFlags, 282 mParsedObjectFlags, 283 mExtraDataCallbackHandlerList ); 284 bool success = fileLoader.load(buffer, length); 285 abortLoading = !success; 286 } 287 288 mCurrentFileId++; 289 } 290 291 if ( !abortLoading ) 292 { 293 PostProcessor postProcessor(this, 294 &saxParserErrorHandler, 295 mObjectFlags, 296 mParsedObjectFlags); 297 postProcessor.postProcess(); 298 } 299 else 300 { 301 mWriter->cancel("Generic error"); 302 } 303 304 mWriter->finish(); 305 306 mParsedObjectFlags |= mObjectFlags; 307 308 return !abortLoading; 309 } 310 311 //--------------------------------- registerExtraDataCallbackHandler(IExtraDataCallbackHandler * extraDataCallbackHandler)312 bool Loader::registerExtraDataCallbackHandler ( IExtraDataCallbackHandler* extraDataCallbackHandler ) 313 { 314 // Push the callback handler in the list of callback handlers. 315 mExtraDataCallbackHandlerList.push_back ( extraDataCallbackHandler ); 316 317 return true; 318 } 319 320 //--------------------------------- getMeshMaterialIdInfo()321 GeometryMaterialIdInfo& Loader::getMeshMaterialIdInfo( ) 322 { 323 return mGeometryMaterialIdInfo; 324 } 325 326 //--------------------------------- getTextureMapIdBySematic(const String & semantic)327 COLLADAFW::TextureMapId Loader::getTextureMapIdBySematic( const String& semantic ) 328 { 329 StringTextureMapIdMap::iterator it = mTextureMapSemanticTextureMapIdMap.find(semantic); 330 if ( it == mTextureMapSemanticTextureMapIdMap.end() ) 331 { 332 return mTextureMapSemanticTextureMapIdMap[semantic] = mNextTextureMapId++; 333 } 334 else 335 { 336 return it->second; 337 } 338 } 339 340 //----------------------------- compare(const COLLADAFW::SkinController & lhs,const COLLADAFW::SkinController & rhs)341 bool Loader::compare( const COLLADAFW::SkinController& lhs, const COLLADAFW::SkinController& rhs ) 342 { 343 344 if (lhs.getSkinControllerData() < rhs.getSkinControllerData() ) 345 return true; 346 if (lhs.getSkinControllerData() > rhs.getSkinControllerData() ) 347 return false; 348 349 if (lhs.getSource() < rhs.getSource() ) 350 return true; 351 if (lhs.getSource() > rhs.getSource() ) 352 return false; 353 354 const COLLADAFW::UniqueIdArray& lhsJoints = lhs.getJoints(); 355 const COLLADAFW::UniqueIdArray& rhsJoints = rhs.getJoints(); 356 size_t lhsJointsCount = lhsJoints.getCount(); 357 size_t rhsJointsCount = rhsJoints.getCount(); 358 if (lhsJointsCount < rhsJointsCount ) 359 return true; 360 if (lhsJointsCount > rhsJointsCount ) 361 return false; 362 363 for ( size_t i = 0; i < lhsJointsCount; ++i) 364 { 365 const COLLADAFW::UniqueId& lhsJoint = lhsJoints[i]; 366 const COLLADAFW::UniqueId& rhsJoint = rhsJoints[i]; 367 if (lhsJoint < rhsJoint ) 368 return true; 369 if (lhsJoint > rhsJoint ) 370 return false; 371 } 372 373 return false; 374 } 375 376 //------------------------------ registerExternalReferenceDeciderCallbackFunction(ExternalReferenceDeciderCallbackFunction externalReferenceDeciderCallbackFunction)377 void Loader::registerExternalReferenceDeciderCallbackFunction( ExternalReferenceDeciderCallbackFunction externalReferenceDeciderCallbackFunction ) 378 { 379 mExternalReferenceDeciderCallbackFunction = externalReferenceDeciderCallbackFunction; 380 } 381 382 } // namespace COLLADA 383