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 "COLLADASaxFWLLibraryAnimationsLoader.h" 13 #include "COLLADASaxFWLSidAddress.h" 14 #include "COLLADASaxFWLSidTreeNode.h" 15 #include "COLLADASaxFWLInterpolationTypeSource.h" 16 #include "COLLADASaxFWLLoader.h" 17 18 #include "COLLADAFWValidate.h" 19 #include "COLLADAFWAnimationCurve.h" 20 #include "COLLADAFWAnimationList.h" 21 #include "COLLADAFWIWriter.h" 22 #include "COLLADAFWTypes.h" 23 24 25 namespace COLLADASaxFWL 26 { 27 28 enum SamplerInputSemantics 29 { 30 SEMANTIC_UNKNOWN, 31 SEMANTIC_INPUT, 32 SEMANTIC_OUTPUT, 33 SEMANTIC_INTERPOLATION, 34 SEMANTIC_IN_TANGENT, 35 SEMANTIC_OUT_TANGENT 36 }; 37 38 const String INTERPOLATIONTYPE_LINEAR("LINEAR"); 39 const String INTERPOLATIONTYPE_BEZIER("BEZIER"); 40 const String INTERPOLATIONTYPE_CARDINAL("CARDINAL"); 41 const String INTERPOLATIONTYPE_HERMITE("HERMITE"); 42 const String INTERPOLATIONTYPE_BSPLINE("BSPLINE"); 43 const String INTERPOLATIONTYPE_STEP("STEP"); 44 const String INTERPOLATIONTYPE_MIXED("MIXED"); 45 46 47 //------------------------------ operator ==(const ParserString & parserString,const String & stlSring)48 bool operator==( const ParserString& parserString, const String& stlSring ) 49 { 50 if ( parserString.length != stlSring.length() ) 51 return false; 52 53 size_t pos = 0; 54 const char* str = stlSring.c_str(); 55 while ( (pos < parserString.length) ) 56 { 57 if ( parserString.str[pos] != str[pos] ) 58 return false; 59 ++pos; 60 } 61 return true; 62 } 63 64 struct AccessorAnimationClassPair 65 { AccessorAnimationClassPairCOLLADASaxFWL::AccessorAnimationClassPair66 AccessorAnimationClassPair( const SourceBase::AccessorParameter* _parameters, 67 size_t _parameterCount, 68 COLLADAFW::AnimationList::AnimationClass _animationClass) 69 : parameters(_parameters) 70 , parameterCount(_parameterCount/sizeof(SourceBase::AccessorParameter)) 71 , animationClass(_animationClass) 72 {} 73 const SourceBase::AccessorParameter* parameters; 74 size_t parameterCount; 75 COLLADAFW::AnimationList::AnimationClass animationClass; 76 }; 77 78 struct AccessorDimensionsPair 79 { AccessorDimensionsPairCOLLADASaxFWL::AccessorDimensionsPair80 AccessorDimensionsPair( const SourceBase::AccessorParameter& _parameter, 81 COLLADAFW::PhysicalDimension _physicalDimension, 82 size_t _dimension) 83 : parameter(_parameter) 84 , physicalDimension(_physicalDimension) 85 , dimension(_dimension) 86 {} 87 const SourceBase::AccessorParameter& parameter; 88 COLLADAFW::PhysicalDimension physicalDimension; 89 size_t dimension; 90 }; 91 92 SourceBase::AccessorParameter parameterTime = {"TIME", "float"}; 93 SourceBase::AccessorParameter parameterFloat = {"", "float"}; 94 SourceBase::AccessorParameter parameterX = {"X", "float"}; 95 SourceBase::AccessorParameter parameterY = {"Y", "float"}; 96 SourceBase::AccessorParameter parameterZ = {"Z", "float"}; 97 SourceBase::AccessorParameter parameterR = {"R", "float"}; 98 SourceBase::AccessorParameter parameterG = {"G", "float"}; 99 SourceBase::AccessorParameter parameterB = {"B", "float"}; 100 SourceBase::AccessorParameter parameterA = {"A", "float"}; 101 SourceBase::AccessorParameter parameterAngle = {"ANGLE", "float"}; 102 SourceBase::AccessorParameter parameterTransform = {"TRANSFORM", "float4x4"}; 103 104 SourceBase::AccessorParameter accessorTime[] = {parameterTime}; 105 SourceBase::AccessorParameter accessorFloat[] = {parameterFloat}; 106 SourceBase::AccessorParameter accessorX[] = {parameterX}; 107 SourceBase::AccessorParameter accessorY[] = {parameterY}; 108 SourceBase::AccessorParameter accessorZ[] = {parameterZ}; 109 SourceBase::AccessorParameter accessorR[] = {parameterR}; 110 SourceBase::AccessorParameter accessorG[] = {parameterG}; 111 SourceBase::AccessorParameter accessorB[] = {parameterB}; 112 SourceBase::AccessorParameter accessorA[] = {parameterA}; 113 SourceBase::AccessorParameter accessorAngle[] = {parameterAngle}; 114 SourceBase::AccessorParameter accessorTransform[] = {parameterTransform}; 115 116 SourceBase::AccessorParameter accessorXYZ[] = {parameterX, parameterY, parameterZ}; 117 SourceBase::AccessorParameter accessorRGB[] = {parameterR, parameterG, parameterB}; 118 SourceBase::AccessorParameter accessorRGBA[] = {parameterR, parameterG, parameterB, parameterA}; 119 SourceBase::AccessorParameter accessorAxisAngle[] = {parameterX, parameterY, parameterZ, parameterAngle}; 120 121 AccessorAnimationClassPair animationClassMap[] = 122 { 123 AccessorAnimationClassPair( accessorTime, sizeof(accessorTime), COLLADAFW::AnimationList::TIME) 124 , AccessorAnimationClassPair( accessorFloat, sizeof(accessorFloat), COLLADAFW::AnimationList::FLOAT) 125 , AccessorAnimationClassPair( accessorX, sizeof(accessorX), COLLADAFW::AnimationList::POSITION_X) 126 , AccessorAnimationClassPair( accessorY, sizeof(accessorY), COLLADAFW::AnimationList::POSITION_Y) 127 , AccessorAnimationClassPair( accessorZ, sizeof(accessorZ), COLLADAFW::AnimationList::POSITION_Z) 128 , AccessorAnimationClassPair( accessorR, sizeof(accessorR), COLLADAFW::AnimationList::COLOR_R) 129 , AccessorAnimationClassPair( accessorG, sizeof(accessorG), COLLADAFW::AnimationList::COLOR_G) 130 , AccessorAnimationClassPair( accessorB, sizeof(accessorB), COLLADAFW::AnimationList::COLOR_B) 131 , AccessorAnimationClassPair( accessorA, sizeof(accessorA), COLLADAFW::AnimationList::COLOR_A) 132 , AccessorAnimationClassPair( accessorAngle, sizeof(accessorAngle), COLLADAFW::AnimationList::ANGLE) 133 , AccessorAnimationClassPair( accessorXYZ, sizeof(accessorXYZ), COLLADAFW::AnimationList::POSITION_XYZ) 134 , AccessorAnimationClassPair( accessorRGB, sizeof(accessorRGB), COLLADAFW::AnimationList::COLOR_RGB) 135 , AccessorAnimationClassPair( accessorRGBA, sizeof(accessorRGBA), COLLADAFW::AnimationList::COLOR_RGBA) 136 , AccessorAnimationClassPair( accessorAxisAngle, sizeof(accessorAxisAngle), COLLADAFW::AnimationList::AXISANGLE) 137 , AccessorAnimationClassPair( accessorTransform, sizeof(accessorTransform), COLLADAFW::AnimationList::MATRIX4X4) 138 }; 139 140 #if 0 141 AccessorDimensionsPair animationDimensionMap[] = 142 { 143 AccessorDimensionsPair( parameterFloat, PHYSICAL_DIMENSION_UNKNOWN, 1) 144 , AccessorDimensionsPair( parameterX, PHYSICAL_DIMENSION_LENGTH, 1) 145 , AccessorDimensionsPair( parameterY, PHYSICAL_DIMENSION_LENGTH, 1) 146 , AccessorDimensionsPair( parameterZ, PHYSICAL_DIMENSION_LENGTH, 1) 147 , AccessorDimensionsPair( parameterAngle, PHYSICAL_DIMENSION_ANGLE, 1) 148 , AccessorDimensionsPair( parameterTransform, PHYSICAL_DIMENSION_TRANSFORMATIONMATRIX4X4, 16) 149 }; 150 #endif 151 152 153 /** Determines the animation class from the accessor.*/ 154 //------------------------------ determineAnimationClass(const SourceBase::Accessor & accessor)155 COLLADAFW::AnimationList::AnimationClass determineAnimationClass( const SourceBase::Accessor& accessor ) 156 { 157 static const size_t mapSize = sizeof(animationClassMap)/sizeof(AccessorAnimationClassPair); 158 for ( size_t i = 0; i < mapSize; ++i) 159 { 160 const AccessorAnimationClassPair& animationClassPair = animationClassMap[i]; 161 162 if ( accessor.size() != animationClassPair.parameterCount ) 163 { 164 // two accessor must have equal number of parameters to be equal 165 continue; 166 } 167 168 bool equal = true; 169 for ( size_t j = 0; j < animationClassPair.parameterCount; ++j) 170 { 171 const SourceBase::AccessorParameter& parameter = animationClassPair.parameters[j]; 172 const SourceBase::AccessorParameter& accessorParameter = accessor[j]; 173 if ( parameter != accessorParameter ) 174 { 175 equal = false; 176 break; 177 } 178 } 179 180 if ( equal ) 181 { 182 // if we reach this point, the parameters in accessor are equal to those in animationClassPair 183 return animationClassPair.animationClass; 184 } 185 } 186 187 return COLLADAFW::AnimationList::UNKNOWN_CLASS; 188 } 189 190 #if 0 191 /** Determines the physical dimension and the dimension of @a parameter. 192 @param parameters the accessor parameter to determine the dimensions from 193 @param physicalDimension Will be set to the physical dimension 194 @param dimension Will be set to the dimension of the parameter, e.g. 1 for float, 16 for float4x4 195 @return True if parameter was found, false otherwise.*/ 196 //------------------------------ 197 bool determineParameterDimensions( const SourceBase::AccessorParameter& parameter, 198 COLLADAFW::PhysicalDimension& physicalDimension, 199 size_t& dimension) 200 { 201 static const size_t mapSize = sizeof(animationDimensionMap)/sizeof(AccessorDimensionsPair); 202 for ( size_t i = 0; i < mapSize; ++i) 203 { 204 const AccessorDimensionsPair& animationDimensionPair = animationDimensionMap[i]; 205 206 if ( parameter == animationDimensionPair.parameter ) 207 { 208 physicalDimension = animationDimensionPair.physicalDimension; 209 dimension = animationDimensionPair.dimension; 210 return true; 211 } 212 } 213 214 return false; 215 } 216 #endif 217 218 //------------------------------ getInterpolationTypeByString(const ParserString & string)219 COLLADAFW::AnimationCurve::InterpolationType LibraryAnimationsLoader::getInterpolationTypeByString( const ParserString& string ) 220 { 221 if ( string == INTERPOLATIONTYPE_LINEAR ) 222 { 223 return COLLADAFW::AnimationCurve::INTERPOLATION_LINEAR; 224 } 225 else if ( string == INTERPOLATIONTYPE_BEZIER ) 226 { 227 return COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER; 228 } 229 else if ( string == INTERPOLATIONTYPE_CARDINAL ) 230 { 231 return COLLADAFW::AnimationCurve::INTERPOLATION_CARDINAL; 232 } 233 else if ( string == INTERPOLATIONTYPE_HERMITE ) 234 { 235 return COLLADAFW::AnimationCurve::INTERPOLATION_HERMITE; 236 } 237 else if ( string == INTERPOLATIONTYPE_BSPLINE ) 238 { 239 return COLLADAFW::AnimationCurve::INTERPOLATION_BSPLINE; 240 } 241 else if ( string == INTERPOLATIONTYPE_STEP ) 242 { 243 return COLLADAFW::AnimationCurve::INTERPOLATION_STEP; 244 } 245 else if ( string == INTERPOLATIONTYPE_MIXED ) 246 { 247 return COLLADAFW::AnimationCurve::INTERPOLATION_MIXED; 248 } 249 250 return COLLADAFW::AnimationCurve::INTERPOLATION_UNKNOWN; 251 } 252 253 //------------------------------ getSemanticBySemanticStr(const char * semanticStr)254 SamplerInputSemantics getSemanticBySemanticStr( const char * semanticStr) 255 { 256 if ( strcmp(semanticStr, "INPUT" ) == 0 ) 257 { 258 return SEMANTIC_INPUT; 259 } 260 else if ( strcmp(semanticStr, "OUTPUT" ) == 0 ) 261 { 262 return SEMANTIC_OUTPUT; 263 } 264 else if ( strcmp(semanticStr, "INTERPOLATION" ) == 0 ) 265 { 266 return SEMANTIC_INTERPOLATION; 267 } 268 else if ( strcmp(semanticStr, "IN_TANGENT" ) == 0 ) 269 { 270 return SEMANTIC_IN_TANGENT; 271 } 272 else if ( strcmp(semanticStr, "OUT_TANGENT" ) == 0 ) 273 { 274 return SEMANTIC_OUT_TANGENT; 275 } 276 return SEMANTIC_UNKNOWN; 277 } 278 279 //------------------------------ LibraryAnimationsLoader(IFilePartLoader * callingFilePartLoader)280 LibraryAnimationsLoader::LibraryAnimationsLoader( IFilePartLoader* callingFilePartLoader ) 281 : SourceArrayLoader(callingFilePartLoader) 282 , mCurrentAnimationCurve(0) 283 , mCurrentlyParsingInterpolationArray(false) 284 , mCurrentAnimationInfo( 0 ) 285 , mCurrentAnimationCurveRequiresTangents(true) 286 , mVerboseValidate(true) 287 , mProcessedCount(0) 288 {} 289 290 //------------------------------ ~LibraryAnimationsLoader()291 LibraryAnimationsLoader::~LibraryAnimationsLoader() 292 { 293 } 294 295 //------------------------------ getUniqueId()296 const COLLADAFW::UniqueId& LibraryAnimationsLoader::getUniqueId () 297 { 298 if ( mCurrentAnimationCurve ) 299 return mCurrentAnimationCurve->getUniqueId (); 300 301 // TODO One curve for every sampler in an collada animation. Returns always an invalid id! 302 return COLLADAFW::UniqueId::INVALID; 303 } 304 305 //------------------------------ getAnimationInfoBySamplerId(const String & samplerId)306 AnimationInfo* LibraryAnimationsLoader::getAnimationInfoBySamplerId( const String& samplerId ) 307 { 308 StringAnimationInfoMap::iterator it = mSamplerIdAnimationInfoMap.find( samplerId ); 309 if ( it == mSamplerIdAnimationInfoMap.end() ) 310 { 311 return 0; 312 } 313 else 314 { 315 return &(it->second); 316 } 317 } 318 319 //------------------------------ end__library_animations()320 bool LibraryAnimationsLoader::end__library_animations() 321 { 322 moveUpInSidTree(); 323 finish(); 324 return true; 325 } 326 327 //------------------------------ begin__source(const source__AttributeData & attributes)328 bool LibraryAnimationsLoader::begin__source( const source__AttributeData& attributes ) 329 { 330 return beginSource(attributes); 331 } 332 333 //------------------------------ end__source()334 bool LibraryAnimationsLoader::end__source( ) 335 { 336 return endSource(); 337 } 338 339 //------------------------------ begin__animation(const animation__AttributeData & attributeData)340 bool LibraryAnimationsLoader::begin__animation( const animation__AttributeData& attributeData ) 341 { 342 if ( attributeData.name ) 343 mName = (const char*)attributeData.name; 344 else if ( attributeData.id) 345 mName = (const char*)attributeData.id; 346 347 if ( attributeData.id ) 348 mOriginalId = (const char*)attributeData.id; 349 else { 350 //FR: we create an id, so that clients can figure out - for an incoming animation - which animation it originally belongs to. 351 //Thus, it can be able to respect the same layout of animation than the input COLLADA file. 352 std::ostringstream o; 353 o << "animation_" << this->mProcessedCount++; 354 mOriginalId = o.str(); 355 } 356 357 return true; 358 } 359 360 //------------------------------ end__animation()361 bool LibraryAnimationsLoader::end__animation() 362 { 363 mOriginalId = COLLADABU::Utils::EMPTY_STRING; 364 365 return true; 366 } 367 368 //------------------------------ begin__sampler(const sampler__AttributeData & attributeData)369 bool LibraryAnimationsLoader::begin__sampler( const sampler__AttributeData& attributeData ) 370 { 371 mCurrentAnimationCurve = FW_NEW COLLADAFW::AnimationCurve(createUniqueIdFromId(attributeData.id, COLLADAFW::Animation::ID())); 372 373 mCurrentAnimationCurve->setName ( mName ); 374 mCurrentAnimationCurve->setOriginalId ( mOriginalId ); 375 376 if ( attributeData.id && *attributeData.id ) 377 { 378 AnimationInfo animationInfo; 379 animationInfo.uniqueId = mCurrentAnimationCurve->getUniqueId(); 380 animationInfo.animationClass = COLLADAFW::AnimationList::UNKNOWN_CLASS; 381 mCurrentAnimationInfo = &(mSamplerIdAnimationInfoMap.insert(std::make_pair(attributeData.id, animationInfo)).first->second); 382 } 383 return true; 384 } 385 386 //------------------------------ end__sampler()387 bool LibraryAnimationsLoader::end__sampler() 388 { 389 bool success = true; 390 if ( !mCurrentAnimationCurveRequiresTangents ) 391 { 392 mCurrentAnimationCurve->getInTangentValues().clear(); 393 mCurrentAnimationCurve->getOutTangentValues().clear(); 394 } 395 if ( (getObjectFlags() & Loader::ANIMATION_FLAG) != 0 ) 396 { 397 //assume linear interpolation if no interpolation is set 398 if ( mCurrentAnimationCurve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_UNKNOWN ) 399 { 400 mCurrentAnimationCurve->setInterpolationType(COLLADAFW::AnimationCurve::INTERPOLATION_LINEAR ); 401 } 402 403 if ( COLLADAFW::validate( mCurrentAnimationCurve, mVerboseValidate ) == 0) 404 { 405 success = writer()->writeAnimation(mCurrentAnimationCurve); 406 FW_DELETE mCurrentAnimationCurve; 407 } 408 else 409 { 410 handleFWLError ( SaxFWLError::ERROR_DATA_NOT_VALID, "Animation curve \"" + mCurrentAnimationCurve->getName () + "\" not valid!" ); 411 } 412 } 413 mCurrentAnimationCurve = 0; 414 mCurrentAnimationInfo = 0; 415 mCurrentAnimationCurveRequiresTangents = true; 416 return success; 417 } 418 419 //------------------------------ begin__channel(const channel__AttributeData & attributeData)420 bool LibraryAnimationsLoader::begin__channel( const channel__AttributeData& attributeData ) 421 { 422 String samplerId = getIdFromURIFragmentType(attributeData.source); 423 424 AnimationInfo* animationInfo = getAnimationInfoBySamplerId( samplerId ); 425 426 if ( !animationInfo ) 427 return true; 428 429 SidAddress sidAddress( String(attributeData.target) ); 430 #if 0 431 const SidTreeNode* sidTreeNode = resolveSid( sidAddress ); 432 433 if ( sidTreeNode ) 434 { 435 if ( sidTreeNode->getTargetType() == SidTreeNode::TARGETTYPE_ANIMATABLE ) 436 { 437 COLLADAFW::Animatable* animatable = sidTreeNode->getAnimatableTarget(); 438 COLLADAFW::UniqueId animationListUniqueId = animatable->getAnimationList(); 439 if ( !animationListUniqueId.isValid() ) 440 { 441 animationListUniqueId = getUniqueId( COLLADAFW::AnimationList::ID() ); 442 animatable->setAnimationList( animationListUniqueId ); 443 } 444 COLLADAFW::AnimationList*& animationList = getAnimationListByUniqueId(animationListUniqueId); 445 446 if ( !animationList ) 447 { 448 animationList = new COLLADAFW::AnimationList( animationListUniqueId.getObjectId() ); 449 } 450 451 // TODO handle this for arrays 452 COLLADAFW::AnimationList::AnimationBinding animationBinding; 453 animationBinding.animation = animationInfo->uniqueId; 454 animationBinding.animationClass = animationInfo->animationClass; 455 if ( animationBinding.animationClass == COLLADAFW::AnimationList::MATRIX4X4_ELEMENT ) 456 { 457 animationBinding.firstIndex = sidAddress.getFirstIndex(); 458 animationBinding.secondIndex = sidAddress.getSecondIndex(); 459 } 460 else 461 { 462 animationBinding.firstIndex = 0; 463 animationBinding.secondIndex = 0; 464 } 465 animationList->getAnimationBindings().append( animationBinding ); 466 } 467 } 468 else 469 #endif 470 { 471 // the references element has not been parsed. Store the connection. Will be processed by FileLoader 472 // at the end of the collada file. 473 addToAnimationSidAddressBindings( *animationInfo, sidAddress ); 474 } 475 476 return true; 477 } 478 479 //------------------------------ end__channel()480 bool LibraryAnimationsLoader::end__channel() 481 { 482 return true; 483 } 484 485 486 //------------------------------ begin__input____InputLocal(const input____InputLocal__AttributeData & attributeData)487 bool LibraryAnimationsLoader::begin__input____InputLocal( const input____InputLocal__AttributeData& attributeData ) 488 { 489 // we ignore inputs that don't have semantics or source 490 if ( !attributeData.semantic || !attributeData.source ) 491 { 492 return true; 493 } 494 495 SamplerInputSemantics semantic = getSemanticBySemanticStr( attributeData.semantic ); 496 if ( semantic == SEMANTIC_UNKNOWN ) 497 { 498 return true; 499 } 500 501 String sourceId = getIdFromURIFragmentType(attributeData.source); 502 const SourceBase* sourceBase = getSourceById ( sourceId ); 503 // TODO handle case where source could not be found 504 if ( !sourceBase ) 505 return true; 506 SourceBase::DataType sourceDataType = sourceBase->getDataType(); 507 508 509 switch ( semantic ) 510 { 511 case SEMANTIC_INPUT: 512 { 513 if ( sourceDataType != SourceBase::DATA_TYPE_REAL ) 514 { 515 // The source array has wrong type. Only reals are allowed for semantic INPUT 516 break; 517 } 518 519 COLLADAFW::AnimationList::AnimationClass animationClass = determineAnimationClass( sourceBase->getAccessor() ); 520 521 if ( animationClass == COLLADAFW::AnimationList::TIME ) 522 { 523 mCurrentAnimationCurve->setInPhysicalDimension( COLLADAFW::PHYSICAL_DIMENSION_TIME ); 524 } 525 else 526 { 527 mCurrentAnimationCurve->setInPhysicalDimension( COLLADAFW::PHYSICAL_DIMENSION_UNKNOWN ); 528 } 529 530 setRealValues( mCurrentAnimationCurve->getInputValues(), (const RealSource*)sourceBase); 531 } 532 break; 533 case SEMANTIC_OUTPUT: 534 { 535 if ( sourceDataType != SourceBase::DATA_TYPE_REAL ) 536 { 537 // The source array has wrong type. Only reals are allowed for semantic OUTPUT 538 break; 539 } 540 541 COLLADABU_ASSERT( mCurrentAnimationInfo ); 542 COLLADAFW::PhysicalDimensionArray& physicalDimensions = mCurrentAnimationCurve->getOutPhysicalDimensions(); 543 544 if ( mCurrentAnimationInfo ) 545 { 546 COLLADAFW::AnimationList::AnimationClass animationClass = determineAnimationClass( sourceBase->getAccessor() ); 547 mCurrentAnimationInfo->animationClass = animationClass; 548 549 switch ( animationClass ) 550 { 551 case COLLADAFW::AnimationList::POSITION_X: 552 case COLLADAFW::AnimationList::POSITION_Y: 553 case COLLADAFW::AnimationList::POSITION_Z: 554 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_LENGTH); 555 break; 556 case COLLADAFW::AnimationList::POSITION_XYZ: 557 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_LENGTH); 558 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_LENGTH); 559 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_LENGTH); 560 break; 561 case COLLADAFW::AnimationList::ANGLE: 562 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_ANGLE); 563 break; 564 case COLLADAFW::AnimationList::AXISANGLE: 565 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 566 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 567 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 568 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_ANGLE); 569 break; 570 case COLLADAFW::AnimationList::MATRIX4X4: 571 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 572 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 573 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 574 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_LENGTH); 575 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 576 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 577 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 578 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_LENGTH); 579 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 580 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 581 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 582 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_LENGTH); 583 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 584 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 585 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 586 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 587 break; 588 case COLLADAFW::AnimationList::COLOR_R: 589 case COLLADAFW::AnimationList::COLOR_G: 590 case COLLADAFW::AnimationList::COLOR_B: 591 case COLLADAFW::AnimationList::COLOR_A: 592 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_COLOR); 593 break; 594 case COLLADAFW::AnimationList::COLOR_RGB: 595 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_COLOR); 596 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_COLOR); 597 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_COLOR); 598 break; 599 case COLLADAFW::AnimationList::COLOR_RGBA: 600 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_COLOR); 601 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_COLOR); 602 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_COLOR); 603 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_COLOR); 604 break; 605 case COLLADAFW::AnimationList::FLOAT: 606 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_NUMBER); 607 break; 608 case COLLADAFW::AnimationList::ARRAY_ELEMENT_1D: 609 case COLLADAFW::AnimationList::ARRAY_ELEMENT_2D: 610 //https://github.com/KhronosGroup/OpenCOLLADA/issues/245 611 //FR: is this an issue to have nothing processed here, or is it processed somewhere else ? 612 break; 613 case COLLADAFW::AnimationList::UNKNOWN_CLASS: 614 case COLLADAFW::AnimationList::TIME: 615 break; 616 } 617 } 618 619 const RealSource* realSource = (const RealSource*)sourceBase; 620 setRealValues( mCurrentAnimationCurve->getOutputValues(), realSource); 621 622 size_t stride = (size_t)realSource->getStride(); 623 size_t physicalDimensionsCount = physicalDimensions.getCount(); 624 // if stride is larger that physicalDimensionsCount, we need to append dimensions to physicalDimensions 625 for ( size_t i = physicalDimensionsCount; i < stride; ++i) 626 { 627 physicalDimensions.append(COLLADAFW::PHYSICAL_DIMENSION_UNKNOWN); 628 } 629 mCurrentAnimationCurve->setOutDimension(stride); 630 } 631 break; 632 case SEMANTIC_OUT_TANGENT: 633 { 634 if ( sourceDataType != SourceBase::DATA_TYPE_REAL ) 635 { 636 // The source array has wrong type. Only reals are allowed for semantic OUTPUT 637 break; 638 } 639 640 if ( !mCurrentAnimationCurveRequiresTangents ) 641 { 642 // This animation does not require tangents 643 break; 644 } 645 setRealValues( mCurrentAnimationCurve->getOutTangentValues(), (const RealSource*)sourceBase); 646 } 647 break; 648 case SEMANTIC_IN_TANGENT: 649 { 650 if ( sourceDataType != SourceBase::DATA_TYPE_REAL ) 651 { 652 // The source array has wrong type. Only reals are allowed for semantic OUTPUT 653 break; 654 } 655 if ( !mCurrentAnimationCurveRequiresTangents ) 656 { 657 // This animation does not require tangents 658 break; 659 } 660 setRealValues( mCurrentAnimationCurve->getInTangentValues(), (const RealSource*)sourceBase); 661 } 662 break; 663 case SEMANTIC_INTERPOLATION: 664 { 665 if ( sourceDataType != SourceBase::DATA_TYPE_INTERPOLATIONTYPE ) 666 { 667 // The source array has wrong type. Only reals are allowed for semantic INTERPOLATION 668 break; 669 } 670 671 COLLADAFW::AnimationCurve::InterpolationType currentAnimationCurveInterpolationType = mCurrentAnimationCurve->getInterpolationType(); 672 673 if ( currentAnimationCurveInterpolationType != COLLADAFW::AnimationCurve::INTERPOLATION_UNKNOWN ) 674 { 675 // There already must have been an input with semantic INTERPOLATION. We ignore all following. 676 break; 677 } 678 679 const InterpolationTypeSource* interpolationTypeSource = (const InterpolationTypeSource*)sourceBase; 680 COLLADAFW::AnimationCurve::InterpolationType interpolationType = interpolationTypeSource->getInterpolationType(); 681 mCurrentAnimationCurveRequiresTangents = interpolationTypeSource->getRequiresTangents(); 682 683 mCurrentAnimationCurve->setInterpolationType(interpolationType); 684 685 if ( interpolationType == COLLADAFW::AnimationCurve::INTERPOLATION_MIXED ) 686 { 687 COLLADAFW::AnimationCurve::InterpolationTypeArray& interpolationTypes = mCurrentAnimationCurve->getInterpolationTypes(); 688 interpolationTypes.appendValues(interpolationTypeSource->getArrayElement().getValues()); 689 } 690 } 691 break; 692 default: 693 break; 694 } 695 696 return true; 697 } 698 699 //------------------------------ begin__Name_array(const Name_array__AttributeData & attributeData)700 bool LibraryAnimationsLoader::begin__Name_array( const Name_array__AttributeData& attributeData ) 701 { 702 return beginArray<InterpolationTypeSource>( attributeData.count, attributeData.id ) != 0; 703 return true; 704 } 705 706 //------------------------------ end__Name_array()707 bool LibraryAnimationsLoader::end__Name_array() 708 { 709 return true; 710 } 711 712 //------------------------------ data__Name_array(const ParserString * data,size_t length)713 bool LibraryAnimationsLoader::data__Name_array( const ParserString* data, size_t length ) 714 { 715 InterpolationTypeSource* interpolationTypeSource = (InterpolationTypeSource*)mCurrentSoure; 716 for ( size_t i = 0; i < length; ++i) 717 { 718 const ParserString& interpolationTypeString = data[i]; 719 COLLADAFW::AnimationCurve::InterpolationType interpolationType = getInterpolationTypeByString( interpolationTypeString ); 720 COLLADAFW::AnimationCurve::InterpolationTypeArray& array = interpolationTypeSource->getArrayElement().getValues(); 721 array.append( interpolationType ); 722 723 COLLADAFW::AnimationCurve::InterpolationType interpolationTypeSourceInterpolationType = interpolationTypeSource->getInterpolationType(); 724 if ( (interpolationType == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER) || 725 (interpolationType == COLLADAFW::AnimationCurve::INTERPOLATION_HERMITE) ) 726 { 727 interpolationTypeSource->setRequiresTangents( true ); 728 } 729 if ( interpolationTypeSourceInterpolationType == COLLADAFW::AnimationCurve::INTERPOLATION_UNKNOWN ) 730 { 731 interpolationTypeSource->setInterpolationType( interpolationType ); 732 } 733 else if ( interpolationTypeSourceInterpolationType != interpolationType ) 734 { 735 interpolationTypeSource->setInterpolationType( COLLADAFW::AnimationCurve::INTERPOLATION_MIXED); 736 } 737 } 738 return true; 739 } 740 741 } // namespace COLLADASaxFWL 742