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 "COLLADASaxFWLLibraryControllersLoader.h" 13 #include "COLLADASaxFWLLoader.h" 14 #include "COLLADASaxFWLFileLoader.h" 15 16 #include "COLLADAFWSkinControllerData.h" 17 #include "COLLADAFWMorphController.h" 18 #include "COLLADAFWGeometry.h" 19 #include "COLLADAFWIWriter.h" 20 #include "COLLADAFWValidate.h" 21 22 23 namespace COLLADASaxFWL 24 { 25 enum ControllerInputSemantics 26 { 27 SEMANTIC_UNKNOWN, 28 SEMANTIC_JOINT, 29 SEMANTIC_INV_BIND_MATRIX, 30 SEMANTIC_WEIGHT, 31 SEMANTIC_MORPH_TARGET, 32 SEMANTIC_MORPH_WEIGHT 33 }; 34 35 //------------------------------ getUniqueId()36 const COLLADAFW::UniqueId& LibraryControllersLoader::getUniqueId () 37 { 38 switch ( mCurrentControllerType ) 39 { 40 case SKIN_CONTROLLER: 41 return mCurrentSkinControllerData->getUniqueId (); 42 case MORPH_CONTROLLER: 43 return mCurrentMorphController->getUniqueId (); 44 default: 45 return COLLADAFW::UniqueId::INVALID; 46 } 47 return COLLADAFW::UniqueId::INVALID; 48 } 49 50 //------------------------------ getControllerInputSemanticsBySemanticStr(const char * semanticString)51 ControllerInputSemantics getControllerInputSemanticsBySemanticStr( const char* semanticString) 52 { 53 if ( strcmp(semanticString, "JOINT" ) == 0 ) 54 { 55 return SEMANTIC_JOINT; 56 } 57 else if ( strcmp(semanticString, "INV_BIND_MATRIX" ) == 0 ) 58 { 59 return SEMANTIC_INV_BIND_MATRIX; 60 } 61 else if ( strcmp(semanticString, "WEIGHT" ) == 0 ) 62 { 63 return SEMANTIC_WEIGHT; 64 } 65 else if ( strcmp(semanticString, "MORPH_TARGET" ) == 0 ) 66 { 67 return SEMANTIC_MORPH_TARGET; 68 } 69 else if ( strcmp(semanticString, "MORPH_WEIGHT" ) == 0 ) 70 { 71 return SEMANTIC_MORPH_WEIGHT; 72 } 73 return SEMANTIC_UNKNOWN; 74 } 75 76 77 //------------------------------ LibraryControllersLoader(IFilePartLoader * callingFilePartLoader)78 LibraryControllersLoader::LibraryControllersLoader( IFilePartLoader* callingFilePartLoader ) 79 : SourceArrayLoader(callingFilePartLoader) 80 , mCurrentControllerType( UNKNOWN_CONTROLLER ) 81 , mCurrentSkinControllerData(0) 82 , mCurrentMorphController(0) 83 , mCurrentInputParent( INPUT_PARENT_UNKNOWN ) 84 , mJointSidsOrIds( 0 ) 85 , mCurrentJointsVertexPairCount( 0 ) 86 , mJointOffset(0) 87 , mWeightsOffset(0) 88 , mCurrentMaxOffset(0) 89 , mCurrentOffset(0) 90 , mCurrentBindShapeMatrix( COLLADABU::Math::Matrix4::IDENTITY) 91 , mCurrentMatrixIndex(0) 92 , mVerboseValidate(true) 93 {} 94 95 //------------------------------ ~LibraryControllersLoader()96 LibraryControllersLoader::~LibraryControllersLoader() 97 { 98 } 99 100 //------------------------------ writeVIndices(const sint64 * data,size_t length)101 bool LibraryControllersLoader::writeVIndices ( const sint64* data, size_t length ) 102 { 103 // check, if we are parsing an unsupported primitive type 104 if ( !mCurrentSkinControllerData ) 105 return true; 106 107 // Write the index values in the index lists. 108 for ( size_t i=0; i<length; ++i ) 109 { 110 // Get the current index value. 111 unsigned int index = (unsigned int)data [i]; 112 113 // Write the indices 114 if ( mCurrentOffset == mJointOffset ) 115 { 116 COLLADAFW::IntValuesArray& jointIndices = mCurrentSkinControllerData->getJointIndices(); 117 jointIndices.append ( index ); 118 } 119 120 if ( mCurrentOffset == mWeightsOffset ) 121 { 122 COLLADAFW::UIntValuesArray& weightIndices = mCurrentSkinControllerData->getWeightIndices(); 123 weightIndices.append ( index ); 124 } 125 126 // Reset the offset if we went through all offset values 127 if ( mCurrentOffset == mCurrentMaxOffset ) 128 { 129 // Reset the current offset value 130 mCurrentOffset = 0; 131 } 132 else 133 { 134 // Increment the current offset value 135 ++mCurrentOffset; 136 } 137 } 138 return true; 139 } 140 141 //------------------------------ beginJointsArray(bool isIdArray)142 bool LibraryControllersLoader::beginJointsArray( bool isIdArray ) 143 { 144 const String& sourceId = getCurrentSourceId(); 145 146 // Without id we will never be able to us this array again. Don't store it. 147 if ( sourceId.empty() ) 148 return true; 149 150 if ( isIdArray ) 151 { 152 mJointSidsOrIds = &mJointIdsMap[sourceId]; 153 } 154 else 155 { 156 mJointSidsOrIds = &mJointSidsMap[sourceId]; 157 } 158 159 return true; 160 } 161 162 //------------------------------ dataJointArray(const ParserString * data,size_t length)163 bool LibraryControllersLoader::dataJointArray( const ParserString* data, size_t length ) 164 { 165 if ( !mJointSidsOrIds ) 166 return true; 167 168 for ( size_t i = 0; i < length; ++i) 169 { 170 const ParserString& parserString = data[i]; 171 mJointSidsOrIds->push_back( String( parserString.str, parserString.length ) ); 172 } 173 return true; 174 } 175 176 177 //------------------------------ end__library_controllers()178 bool LibraryControllersLoader::end__library_controllers() 179 { 180 moveUpInSidTree(); 181 finish(); 182 return true; 183 } 184 185 //------------------------------ begin__controller(const controller__AttributeData & attributeData)186 bool LibraryControllersLoader::begin__controller( const controller__AttributeData& attributeData ) 187 { 188 if ( attributeData.id ) 189 mCurrentControllerId = attributeData.id; 190 191 if ( attributeData.name ) 192 mCurrentControllerName = attributeData.name; 193 else if ( attributeData.id ) 194 mCurrentControllerName = attributeData.id; 195 196 if ( attributeData.id ) 197 mOriginalId = ( (const char*)attributeData.id ); 198 199 return true; 200 } 201 202 //------------------------------ end__controller()203 bool LibraryControllersLoader::end__controller() 204 { 205 mCurrentControllerId.clear(); 206 mCurrentControllerName.clear(); 207 mCurrentMatrixIndex = 0; 208 return true; 209 } 210 211 212 //------------------------------ begin__skin(const skin__AttributeData & attributeData)213 bool LibraryControllersLoader::begin__skin( const skin__AttributeData& attributeData ) 214 { 215 mCurrentControllerType = SKIN_CONTROLLER; 216 mCurrentSkinControllerData = FW_NEW COLLADAFW::SkinControllerData(createUniqueIdFromId(mCurrentControllerId.c_str(), COLLADAFW::SkinControllerData::ID())); 217 218 mCurrentSkinControllerData->setOriginalId ( mOriginalId ); 219 mCurrentSkinControllerData->setName ( mCurrentControllerName ); 220 mCurrentControllerSourceUniqueId = getUniqueIdByUrl(attributeData.source); 221 COLLADABU::URI absoluteUri(getFileUri(), attributeData.source.getURIString()); 222 addSkinDataSkinSourcePair( mCurrentSkinControllerData->getUniqueId(), absoluteUri); 223 return true; 224 } 225 226 //------------------------------ end__skin()227 bool LibraryControllersLoader::end__skin() 228 { 229 bool success = true; 230 if ( validate( mCurrentSkinControllerData, mVerboseValidate ) == 0 ) 231 { 232 success = writer()->writeSkinControllerData( mCurrentSkinControllerData ); 233 } 234 235 FW_DELETE mCurrentSkinControllerData; 236 mCurrentSkinControllerData = 0; 237 mJointSidsMap.clear(); 238 mJointSidsOrIds = 0; 239 mCurrentControllerSourceUniqueId = COLLADAFW::UniqueId::INVALID; 240 mCurrentControllerType = UNKNOWN_CONTROLLER; 241 return success; 242 } 243 244 //------------------------------ begin__morph(const morph__AttributeData & attributeData)245 bool LibraryControllersLoader::begin__morph( const morph__AttributeData& attributeData ) 246 { 247 mCurrentControllerType = MORPH_CONTROLLER; 248 mCurrentMorphController = FW_NEW COLLADAFW::MorphController(createUniqueIdFromId(mCurrentControllerId.c_str(), COLLADAFW::MorphController::ID())); 249 mCurrentControllerSourceUniqueId = createUniqueIdFromUrl(attributeData.source, COLLADAFW::Geometry::ID()); 250 mCurrentMorphController->setSource( mCurrentControllerSourceUniqueId); 251 mCurrentMorphController->setOriginalId ( mOriginalId ); 252 mCurrentMorphController->setName ( mCurrentControllerName ); 253 254 return true; 255 } 256 257 //------------------------------ end__morph()258 bool LibraryControllersLoader::end__morph() 259 { 260 if ( mCurrentMorphController ) 261 { 262 addMorphController( mCurrentMorphController ); 263 } 264 mJointSidsMap.clear(); 265 mJointSidsOrIds = 0; 266 mCurrentMorphController = 0; 267 mCurrentControllerSourceUniqueId = COLLADAFW::UniqueId::INVALID; 268 mCurrentControllerType = UNKNOWN_CONTROLLER; 269 return true; 270 } 271 272 273 //------------------------------ begin__joints()274 bool LibraryControllersLoader::begin__joints() 275 { 276 mCurrentInputParent = INPUT_PARENT_JOINTS; 277 return true; 278 } 279 280 //------------------------------ begin__source(const source__AttributeData & attributes)281 bool LibraryControllersLoader::begin__source( const source__AttributeData& attributes ) 282 { 283 return beginSource(attributes); 284 } 285 286 //------------------------------ end__source()287 bool LibraryControllersLoader::end__source( ) 288 { 289 return endSource(); 290 } 291 292 //------------------------------ end__joints()293 bool LibraryControllersLoader::end__joints() 294 { 295 mCurrentInputParent = INPUT_PARENT_UNKNOWN; 296 return true; 297 } 298 299 //------------------------------ begin__input____InputLocal(const input____InputLocal__AttributeData & attributeData)300 bool LibraryControllersLoader::begin__input____InputLocal( const input____InputLocal__AttributeData& attributeData ) 301 { 302 // we ignore inputs that don't have semantics or source 303 if ( !attributeData.semantic || !attributeData.source ) 304 { 305 return true; 306 } 307 308 ControllerInputSemantics semantic = getControllerInputSemanticsBySemanticStr( attributeData.semantic ); 309 if ( semantic == SEMANTIC_UNKNOWN ) 310 { 311 return true; 312 } 313 314 switch ( mCurrentControllerType ) 315 { 316 case SKIN_CONTROLLER: 317 { 318 switch ( semantic ) 319 { 320 case SEMANTIC_JOINT: 321 { 322 if ( !mCurrentSkinControllerData ) 323 { 324 break; 325 } 326 327 String sourceId = getIdFromURIFragmentType(attributeData.source); 328 329 const StringList* nodeSidsOrIds = 0; 330 bool isIdArray = false; 331 StringListMap::const_iterator itSid = mJointSidsMap.find(sourceId); 332 // check if the node sid array could be found 333 if ( itSid != mJointSidsMap.end() ) 334 { 335 nodeSidsOrIds = &itSid->second; 336 isIdArray = false; 337 } 338 else 339 { 340 // check if it is an id_array 341 StringListMap::const_iterator itId = mJointIdsMap.find(sourceId); 342 if ( itId != mJointIdsMap.end() ) 343 { 344 nodeSidsOrIds = &itId->second; 345 isIdArray = true; 346 } 347 else 348 { 349 if ( !handleFWLError ( SaxFWLError::ERROR_SOURCE_NOT_FOUND, "Source with id \"" + sourceId + "\" in skin controller with id \"" + mOriginalId + "\" used in input with semantic SEMANTIC_JOINT could not be found!" )) 350 return false; 351 break; 352 } 353 } 354 355 const COLLADAFW::UniqueId& controllerUniqueId = mCurrentSkinControllerData->getUniqueId(); 356 addSkinDataJointSidsPair( controllerUniqueId, *nodeSidsOrIds, isIdArray); 357 358 // try to write the SkinController here 359 if ( ((getObjectFlags() & Loader::CONTROLLER_FLAG) != 0) && (mCurrentControllerSourceUniqueId.isValid()) ) 360 { 361 Loader::InstanceControllerDataList& instanceControllerDataList = getInstanceControllerDataListByControllerUniqueId(controllerUniqueId); 362 Loader::InstanceControllerDataList::iterator listIt = instanceControllerDataList.begin(); 363 364 while ( listIt != instanceControllerDataList.end() ) 365 { 366 const Loader::InstanceControllerData& instanceControllerData = *listIt; 367 bool success = getFileLoader()->createAndWriteSkinController( instanceControllerData, 368 controllerUniqueId, 369 mCurrentControllerSourceUniqueId, 370 *nodeSidsOrIds, 371 isIdArray); 372 //on success we need to remove this controller instance 373 if ( success ) 374 { 375 listIt = instanceControllerDataList.erase( listIt ); 376 } 377 else 378 { 379 listIt++; 380 } 381 } 382 } 383 mCurrentSkinControllerData->setJointsCount(nodeSidsOrIds->size()); 384 } 385 break; 386 case SEMANTIC_INV_BIND_MATRIX: 387 { 388 if ( !mCurrentSkinControllerData) 389 { 390 break; 391 } 392 393 String sourceId = getIdFromURIFragmentType(attributeData.source); 394 SourceBase* sourceBase = getSourceById ( sourceId ); 395 396 if ( !sourceBase || (sourceBase->getDataType() != SourceBase::DATA_TYPE_REAL) ) 397 { 398 handleFWLError ( SaxFWLError::ERROR_DATA_NOT_VALID, "SourceBase of skin controller with semantic SEMANTIC_INV_BIND_MATRIX not valid!" ); 399 break; 400 } 401 402 if ( sourceBase->getStride() != 16 ) 403 { 404 handleFWLError ( SaxFWLError::ERROR_DATA_NOT_VALID, "Stride of sourceBase of skin controller with semantic SEMANTIC_INV_BIND_MATRIX not valid!" ); 405 break; 406 } 407 408 const RealSource *inverseBindMatricesSource = (const RealSource *)sourceBase; 409 const RealArrayElement& inverseBindMatricesElement = inverseBindMatricesSource->getArrayElement(); 410 411 const RealArray& inverseBindMatricesArray = inverseBindMatricesElement.getValues(); 412 413 size_t matrixElementsCount = inverseBindMatricesArray.getCount(); 414 415 size_t matrixCount = matrixElementsCount / 16; 416 417 418 COLLADAFW::Matrix4Array& inverseBindMatrices = mCurrentSkinControllerData->getInverseBindMatrices(); 419 inverseBindMatrices.allocMemory( matrixCount ); 420 inverseBindMatrices.setCount( matrixCount ); 421 422 size_t index = 0; 423 for ( size_t i = 0; i < matrixCount; ++i) 424 { 425 // fill the matrix 426 COLLADABU::Math::Matrix4 matrix; 427 for ( size_t j = 0; j < 16; ++j,++index) 428 { 429 matrix.setElement( j, inverseBindMatricesArray[index]); 430 } 431 inverseBindMatrices[i] = matrix; 432 } 433 } 434 break; 435 //Prevent warnings for semantics used by MORPH_CONTROLLER 436 default: 437 break; 438 439 } 440 441 } 442 break; 443 case MORPH_CONTROLLER: 444 { 445 switch ( semantic ) 446 { 447 case SEMANTIC_MORPH_TARGET: 448 { 449 if ( !mCurrentMorphController ) 450 { 451 break; 452 } 453 454 String sourceId = getIdFromURIFragmentType(attributeData.source); 455 StringListMap::const_iterator it = mJointIdsMap.find(sourceId); 456 457 // check if the node sid array could be found 458 if ( it == mJointIdsMap.end() ) 459 { 460 if ( !handleFWLError ( SaxFWLError::ERROR_SOURCE_NOT_FOUND, "Source with id \"" + sourceId + "\" in morph controller with id \"" + mOriginalId + "\" used in input with semantic SEMANTIC_MORPH_TARGET could not be found!" )) 461 return false; 462 break; 463 } 464 465 const StringList& meshIds = it->second; 466 size_t meshIdCount = meshIds.size(); 467 468 COLLADAFW::UniqueIdArray& morphTargets = mCurrentMorphController->getMorphTargets(); 469 morphTargets.allocMemory(meshIdCount); 470 morphTargets.setCount(meshIdCount); 471 StringList::const_iterator itTarget = meshIds.begin(); 472 for ( size_t i = 0 ; itTarget != meshIds.end(); ++itTarget, ++i) 473 { 474 morphTargets[i] = createUniqueIdFromId( itTarget->c_str(), COLLADAFW::Geometry::ID()); 475 } 476 477 } 478 break; 479 case SEMANTIC_MORPH_WEIGHT: 480 { 481 if ( !mCurrentMorphController) 482 { 483 break; 484 } 485 486 String sourceId = getIdFromURIFragmentType(attributeData.source); 487 SourceBase* sourceBase = getSourceById( sourceId ); 488 489 if ( !sourceBase || (sourceBase->getDataType() != SourceBase::DATA_TYPE_REAL) ) 490 { 491 handleFWLError ( SaxFWLError::ERROR_DATA_NOT_VALID, "SourceBase of skin controller with semantic SEMANTIC_MORPH_WEIGHT not valid!" ); 492 break; 493 } 494 495 496 unsigned long long stride = sourceBase->getStride(); 497 if( stride == 0 ) 498 { 499 handleFWLError ( SaxFWLError::ERROR_DATA_NOT_VALID, "Stride of sourceBase of skin controller with semantic SEMANTIC_MORPH_WEIGHT not found! Assuming stride 1!" ); 500 stride = 1; 501 } 502 if ( stride != 1 ) 503 { 504 handleFWLError ( SaxFWLError::ERROR_DATA_NOT_VALID, "Stride of sourceBase of skin controller with semantic SEMANTIC_MORPH_WEIGHT not valid!" ); 505 break; 506 } 507 const RealSource *weightSource = (const RealSource *)sourceBase; 508 COLLADAFW::FloatOrDoubleArray& morphWeights = mCurrentMorphController->getMorphWeights(); 509 addToSidTree( sourceId.c_str(), 0, &morphWeights ); 510 moveUpInSidTree(); 511 512 setRealValues( morphWeights, weightSource ); 513 } 514 break; 515 //Prevent warnings for semantics used by SKIN_CONTROLLER 516 default: 517 break; 518 } 519 520 } 521 break; 522 default: 523 break; 524 } 525 526 return true; 527 } 528 529 //------------------------------ begin__vertex_weights(const vertex_weights__AttributeData & attributeData)530 bool LibraryControllersLoader::begin__vertex_weights( const vertex_weights__AttributeData& attributeData ) 531 { 532 mCurrentInputParent = INPUT_PARENT_VERTEX_WEIGHTS; 533 return true; 534 } 535 536 //------------------------------ end__vertex_weights()537 bool LibraryControllersLoader::end__vertex_weights() 538 { 539 mCurrentInputParent = INPUT_PARENT_UNKNOWN; 540 mJointOffset = 0; 541 mWeightsOffset = 0; 542 mCurrentMaxOffset = 0; 543 mCurrentOffset = 0; 544 return true; 545 } 546 547 //------------------------------ begin__input____InputLocalOffset(const input____InputLocalOffset__AttributeData & attributeData)548 bool LibraryControllersLoader::begin__input____InputLocalOffset( const input____InputLocalOffset__AttributeData& attributeData ) 549 { 550 if ( attributeData.offset > mCurrentMaxOffset ) 551 { 552 mCurrentMaxOffset = attributeData.offset; 553 } 554 555 // we ignore inputs that don't have semantics or source 556 if ( !attributeData.semantic || !attributeData.source ) 557 { 558 return true; 559 } 560 561 ControllerInputSemantics semantic = getControllerInputSemanticsBySemanticStr( attributeData.semantic ); 562 if ( semantic == SEMANTIC_UNKNOWN ) 563 { 564 return true; 565 } 566 567 String sourceId = getIdFromURIFragmentType(attributeData.source); 568 SourceBase* sourceBase = getSourceById ( sourceId ); 569 570 switch ( semantic ) 571 { 572 case SEMANTIC_WEIGHT: 573 { 574 mWeightsOffset = attributeData.offset; 575 576 if ( !mCurrentSkinControllerData || !sourceBase || (sourceBase->getDataType() != SourceBase::DATA_TYPE_REAL) ) 577 break; 578 579 COLLADAFW::FloatOrDoubleArray& weights = mCurrentSkinControllerData->getWeights(); 580 assignSourceValuesToFloatOrDoubleArray( sourceBase, weights ); 581 break; 582 } 583 case SEMANTIC_JOINT: 584 mJointOffset = attributeData.offset; 585 break; 586 default: 587 break; 588 } 589 return true; 590 } 591 592 //------------------------------ end__input____InputLocalOffset()593 bool LibraryControllersLoader::end__input____InputLocalOffset() 594 { 595 return true; 596 } 597 598 599 //------------------------------ begin__vcount()600 bool LibraryControllersLoader::begin__vcount() 601 { 602 return true; 603 } 604 605 //------------------------------ end__vcount()606 bool LibraryControllersLoader::end__vcount() 607 { 608 return true; 609 } 610 611 //------------------------------ data__vcount(const unsigned long long * data,size_t length)612 bool LibraryControllersLoader::data__vcount( const unsigned long long* data, size_t length ) 613 { 614 if ( !mCurrentSkinControllerData ) 615 return true; 616 COLLADAFW::UIntValuesArray& jointsPerVertex = mCurrentSkinControllerData->getJointsPerVertex(); 617 size_t count = jointsPerVertex.getCount(); 618 jointsPerVertex.reallocMemory( count + length); 619 for ( size_t i = 0; i < length; ++i) 620 { 621 unsigned long long vcount = data[i]; 622 jointsPerVertex.append((unsigned int)vcount); 623 mCurrentJointsVertexPairCount += (size_t)vcount; 624 } 625 return true; 626 } 627 628 //------------------------------ begin__v()629 bool LibraryControllersLoader::begin__v() 630 { 631 return true; 632 } 633 634 //------------------------------ end__v()635 bool LibraryControllersLoader::end__v() 636 { 637 return true; 638 } 639 640 //------------------------------ data__v(const sint64 * data,size_t length)641 bool LibraryControllersLoader::data__v( const sint64* data, size_t length ) 642 { 643 writeVIndices(data, length); 644 return true; 645 } 646 647 //------------------------------ begin__Name_array(const Name_array__AttributeData & attributeData)648 bool LibraryControllersLoader::begin__Name_array( const Name_array__AttributeData& attributeData ) 649 { 650 return beginJointsArray( false ); 651 } 652 653 //------------------------------ end__Name_array()654 bool LibraryControllersLoader::end__Name_array() 655 { 656 return true; 657 } 658 659 //------------------------------ data__Name_array(const ParserString * data,size_t length)660 bool LibraryControllersLoader::data__Name_array( const ParserString* data, size_t length ) 661 { 662 return dataJointArray( data, length); 663 } 664 665 //------------------------------ begin__IDREF_array(const IDREF_array__AttributeData & attributeData)666 bool LibraryControllersLoader::begin__IDREF_array( const IDREF_array__AttributeData& attributeData ) 667 { 668 return beginJointsArray( true ); 669 } 670 671 //------------------------------ end__IDREF_array()672 bool LibraryControllersLoader::end__IDREF_array() 673 { 674 return true; 675 } 676 677 //------------------------------ data__IDREF_array(const ParserString * data,size_t length)678 bool LibraryControllersLoader::data__IDREF_array( const ParserString* data, size_t length ) 679 { 680 // return true; 681 // Not quite sure if we should evaluate IDREF_array here 682 return dataJointArray( data, length); 683 } 684 685 //------------------------------ data__bind_shape_matrix(const float * data,size_t length)686 bool LibraryControllersLoader::data__bind_shape_matrix( const float* data, size_t length ) 687 { 688 for ( size_t i = 0; i < length; ++i) 689 { 690 size_t row = mCurrentMatrixIndex / 4; 691 size_t column = mCurrentMatrixIndex % 4; 692 mCurrentBindShapeMatrix.setElement(row, column, data[i]); 693 mCurrentMatrixIndex++; 694 } 695 return true; 696 } 697 698 //------------------------------ end__bind_shape_matrix()699 bool LibraryControllersLoader::end__bind_shape_matrix() 700 { 701 if (mCurrentSkinControllerData) 702 { 703 mCurrentSkinControllerData->setBindShapeMatrix( mCurrentBindShapeMatrix ); 704 } 705 return true; 706 } 707 708 } // namespace COLLADASaxFWL 709