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