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 "COLLADASaxFWLSplineLoader.h" 13 #include "COLLADASaxFWLGeometryMaterialIdInfo.h" 14 #include "COLLADASaxFWLLoader.h" 15 #include "COLLADASaxFWLFileLoader.h" 16 17 #include "COLLADAFWTriangles.h" 18 #include "COLLADAFWLines.h" 19 #include "COLLADAFWTristrips.h" 20 #include "COLLADAFWTrifans.h" 21 #include "COLLADAFWPolygons.h" 22 #include "COLLADAFWLinestrips.h" 23 #include "COLLADAFWIWriter.h" 24 25 #include <fstream> 26 27 28 namespace COLLADASaxFWL 29 { 30 SplineLoader(IFilePartLoader * callingFilePartLoader,const String & geometryId,const String & geometryName)31 SplineLoader::SplineLoader( IFilePartLoader* callingFilePartLoader, const String& geometryId, const String& geometryName ) 32 : SourceArrayLoader (callingFilePartLoader ) 33 , mSplineUniqueId(createUniqueIdFromId((ParserChar*)geometryId.c_str(), COLLADAFW::Geometry::ID())) 34 , mSpline ( new COLLADAFW::Spline(mSplineUniqueId) ) 35 , mInterpolations() 36 , mVerticesInputs() 37 , mCurrentVertexInput( 0 ) 38 , mInVertices ( false ) 39 , mInSpline (true) 40 { 41 if ( !geometryName.empty() ) 42 mSpline->setName ( geometryName ); 43 else if ( !geometryId.empty() ) 44 mSpline->setName ( geometryId ); 45 46 if ( !geometryId.empty() ) 47 mSpline->setOriginalId ( geometryId ); 48 } 49 50 //------------------------------ getUniqueId()51 const COLLADAFW::UniqueId& SplineLoader::getUniqueId () 52 { 53 54 if ( mSpline ) return mSpline->getUniqueId (); 55 return COLLADAFW::UniqueId::INVALID; 56 } 57 58 //------------------------------ begin__source(const source__AttributeData & attributes)59 bool SplineLoader::begin__source( const source__AttributeData& attributes ) 60 { 61 return beginSource(attributes); 62 } 63 64 //------------------------------ end__source()65 bool SplineLoader::end__source( ) 66 { 67 return endSource(); 68 } 69 70 //------------------------------ begin__input____InputLocal(const input____InputLocal__AttributeData & attributeData)71 bool SplineLoader::begin__input____InputLocal( const input____InputLocal__AttributeData& attributeData ) 72 { 73 mCurrentVertexInput = new InputUnshared(attributeData.semantic, attributeData.source); 74 return true; 75 } 76 77 //------------------------------ end__input____InputLocal()78 bool SplineLoader::end__input____InputLocal() 79 { 80 mVerticesInputs.getInputArray().append(mCurrentVertexInput); 81 mCurrentVertexInput = 0; 82 return true; 83 } 84 85 //------------------------------ 86 begin__control_vertices()87 bool SplineLoader::begin__control_vertices() 88 { 89 mInVertices = true; 90 91 return true; 92 } 93 end__control_vertices()94 bool SplineLoader::end__control_vertices() 95 { 96 mInVertices = false; 97 98 return true; 99 } 100 101 //------------------------------ begin__Name_array(const Name_array__AttributeData & attributeData)102 bool SplineLoader::begin__Name_array( const Name_array__AttributeData& attributeData ) 103 { 104 return beginInterpolationArray( false ); 105 } 106 107 //------------------------------ end__Name_array()108 bool SplineLoader::end__Name_array() 109 { 110 return true; 111 } 112 113 //------------------------------ data__Name_array(const ParserString * data,size_t length)114 bool SplineLoader::data__Name_array( const ParserString* data, size_t length ) 115 { 116 return dataInterpolationArray( data, length); 117 } 118 119 //------------------------------ beginInterpolationArray(bool isIdArray)120 bool SplineLoader::beginInterpolationArray( bool isIdArray ) 121 { 122 const String& sourceId = getCurrentSourceId(); 123 124 // Without id we will never be able to us this array again. Don't store it. 125 if ( sourceId.empty() ) 126 return true; 127 128 return true; 129 } 130 131 //------------------------------ dataInterpolationArray(const ParserString * data,size_t length)132 bool SplineLoader::dataInterpolationArray( const ParserString* data, size_t length ) 133 { 134 for ( size_t i = 0; i < length; ++i) 135 { 136 const ParserString& parserString = data[i]; 137 mInterpolations.push_back( String( parserString.str, parserString.length ) ); 138 } 139 return true; 140 } 141 end__spline()142 bool SplineLoader::end__spline() 143 { 144 mInSpline = false; 145 146 loadPositions(); 147 loadOutTangents(); 148 loadInTangents(); 149 loadInterpolations(); 150 151 // The mesh will be written by the GeometyLoader. Therefore nothing to with the mesh here 152 finish(); 153 return true; 154 } 155 loadPositions()156 bool SplineLoader::loadPositions() 157 { 158 const InputUnshared * input = mVerticesInputs.getInputBySemantic( InputSemantic::POSITION ); 159 160 if( input ) 161 { 162 // Get the source element with the uri of the input element. 163 COLLADABU::URI inputUrl = input->getSource (); 164 String sourceId = inputUrl.getFragment (); 165 SourceBase* sourceBase = getSourceById ( sourceId ); 166 if ( sourceBase == 0 ) return false; 167 168 // Get the source input array 169 const SourceBase::DataType& dataType = sourceBase->getDataType (); 170 switch ( dataType ) 171 { 172 case SourceBase::DATA_TYPE_FLOAT: 173 { 174 // Get the values array from the source 175 FloatSource* source = ( FloatSource* ) sourceBase; 176 FloatArrayElement& arrayElement = source->getArrayElement (); 177 COLLADAFW::ArrayPrimitiveType<float>& valuesArray = arrayElement.getValues (); 178 179 // TODO 180 unsigned long long stride = source->getStride (); 181 182 // Check if there are already some values in the positions list. 183 // If so, we have to store the last index to increment the following indexes. 184 COLLADAFW::MeshVertexData& positions = mSpline->getPositions (); 185 const size_t initialIndex = positions.getValuesCount (); 186 sourceBase->setInitialIndex ( initialIndex ); 187 188 // Push the new positions into the list of positions. 189 positions.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT ); 190 if ( initialIndex != 0 ) 191 { 192 positions.appendValues ( valuesArray ); 193 } 194 else 195 { 196 positions.setData ( valuesArray.getData (), valuesArray.getCount () ); 197 valuesArray.yieldOwnerShip(); 198 } 199 200 // Set the source base as loaded element. 201 sourceBase->addLoadedInputElement ( InputSemantic::POSITION ); 202 203 break; 204 } 205 case SourceBase::DATA_TYPE_DOUBLE: 206 { 207 // Get the values array from the source 208 DoubleSource* source = ( DoubleSource* ) sourceBase; 209 DoubleArrayElement& arrayElement = source->getArrayElement (); 210 COLLADAFW::ArrayPrimitiveType<double>& valuesArray = arrayElement.getValues (); 211 212 // Check if there are already some values in the positions list. 213 // If so, we have to store the last index to increment the following indexes. 214 COLLADAFW::MeshVertexData& positions = mSpline->getPositions (); 215 const size_t initialIndex = positions.getValuesCount (); 216 sourceBase->setInitialIndex ( initialIndex ); 217 218 // Push the new positions into the list of positions. 219 positions.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE ); 220 if ( initialIndex != 0 ) 221 { 222 positions.appendValues ( valuesArray ); 223 } 224 else 225 { 226 positions.setData ( valuesArray.getData (), valuesArray.getCount () ); 227 valuesArray.yieldOwnerShip(); 228 } 229 230 // Set the source base as loaded element. 231 sourceBase->addLoadedInputElement ( InputSemantic::POSITION ); 232 233 break; 234 } 235 default: 236 std::cerr << "Position source has an other datatype as float or double! " << dataType << std::endl; 237 return false; 238 } 239 240 return true; 241 } 242 else 243 { 244 return false; 245 } 246 } 247 loadOutTangents()248 bool SplineLoader::loadOutTangents() 249 { 250 const InputUnshared * input = mVerticesInputs.getInputBySemantic( InputSemantic::OUT_TANGENT ); 251 252 if( input ) 253 { 254 // Get the source element with the uri of the input element. 255 COLLADABU::URI inputUrl = input->getSource (); 256 String sourceId = inputUrl.getFragment (); 257 SourceBase* sourceBase = getSourceById ( sourceId ); 258 if ( sourceBase == 0 ) return false; 259 260 // Get the source input array 261 const SourceBase::DataType& dataType = sourceBase->getDataType (); 262 switch ( dataType ) 263 { 264 case SourceBase::DATA_TYPE_FLOAT: 265 { 266 // Get the values array from the source 267 FloatSource* source = ( FloatSource* ) sourceBase; 268 FloatArrayElement& arrayElement = source->getArrayElement (); 269 COLLADAFW::ArrayPrimitiveType<float>& valuesArray = arrayElement.getValues (); 270 271 // TODO 272 unsigned long long stride = source->getStride (); 273 274 // Check if there are already some values in the positions list. 275 // If so, we have to store the last index to increment the following indexes. 276 COLLADAFW::MeshVertexData& positions = mSpline->getOutTangents(); 277 const size_t initialIndex = positions.getValuesCount (); 278 sourceBase->setInitialIndex ( initialIndex ); 279 280 // Push the new positions into the list of positions. 281 positions.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT ); 282 if ( initialIndex != 0 ) 283 { 284 positions.appendValues ( valuesArray ); 285 } 286 else 287 { 288 positions.setData ( valuesArray.getData (), valuesArray.getCount () ); 289 valuesArray.yieldOwnerShip(); 290 } 291 292 // Set the source base as loaded element. 293 sourceBase->addLoadedInputElement ( InputSemantic::OUT_TANGENT ); 294 295 break; 296 } 297 case SourceBase::DATA_TYPE_DOUBLE: 298 { 299 // Get the values array from the source 300 DoubleSource* source = ( DoubleSource* ) sourceBase; 301 DoubleArrayElement& arrayElement = source->getArrayElement (); 302 COLLADAFW::ArrayPrimitiveType<double>& valuesArray = arrayElement.getValues (); 303 304 // Check if there are already some values in the positions list. 305 // If so, we have to store the last index to increment the following indexes. 306 COLLADAFW::MeshVertexData& positions = mSpline->getOutTangents (); 307 const size_t initialIndex = positions.getValuesCount (); 308 sourceBase->setInitialIndex ( initialIndex ); 309 310 // Push the new positions into the list of positions. 311 positions.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE ); 312 if ( initialIndex != 0 ) 313 { 314 positions.appendValues ( valuesArray ); 315 } 316 else 317 { 318 positions.setData ( valuesArray.getData (), valuesArray.getCount () ); 319 valuesArray.yieldOwnerShip(); 320 } 321 322 // Set the source base as loaded element. 323 sourceBase->addLoadedInputElement ( InputSemantic::OUT_TANGENT ); 324 325 break; 326 } 327 default: 328 std::cerr << "Position source has an other datatype as float or double! " << dataType << std::endl; 329 return false; 330 } 331 332 return true; 333 } 334 else 335 { 336 return false; 337 } 338 } 339 loadInTangents()340 bool SplineLoader::loadInTangents() 341 { 342 const InputUnshared * input = mVerticesInputs.getInputBySemantic( InputSemantic::IN_TANGENT ); 343 344 if( input ) 345 { 346 // Get the source element with the uri of the input element. 347 COLLADABU::URI inputUrl = input->getSource (); 348 String sourceId = inputUrl.getFragment (); 349 SourceBase* sourceBase = getSourceById ( sourceId ); 350 if ( sourceBase == 0 ) return false; 351 352 // Get the source input array 353 const SourceBase::DataType& dataType = sourceBase->getDataType (); 354 switch ( dataType ) 355 { 356 case SourceBase::DATA_TYPE_FLOAT: 357 { 358 // Get the values array from the source 359 FloatSource* source = ( FloatSource* ) sourceBase; 360 FloatArrayElement& arrayElement = source->getArrayElement (); 361 COLLADAFW::ArrayPrimitiveType<float>& valuesArray = arrayElement.getValues (); 362 363 // TODO 364 unsigned long long stride = source->getStride (); 365 366 // Check if there are already some values in the positions list. 367 // If so, we have to store the last index to increment the following indexes. 368 COLLADAFW::MeshVertexData& positions = mSpline->getInTangents (); 369 const size_t initialIndex = positions.getValuesCount (); 370 sourceBase->setInitialIndex ( initialIndex ); 371 372 // Push the new positions into the list of positions. 373 positions.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT ); 374 if ( initialIndex != 0 ) 375 { 376 positions.appendValues ( valuesArray ); 377 } 378 else 379 { 380 positions.setData ( valuesArray.getData (), valuesArray.getCount () ); 381 valuesArray.yieldOwnerShip(); 382 } 383 384 // Set the source base as loaded element. 385 sourceBase->addLoadedInputElement ( InputSemantic::POSITION ); 386 387 break; 388 } 389 case SourceBase::DATA_TYPE_DOUBLE: 390 { 391 // Get the values array from the source 392 DoubleSource* source = ( DoubleSource* ) sourceBase; 393 DoubleArrayElement& arrayElement = source->getArrayElement (); 394 COLLADAFW::ArrayPrimitiveType<double>& valuesArray = arrayElement.getValues (); 395 396 // Check if there are already some values in the positions list. 397 // If so, we have to store the last index to increment the following indexes. 398 COLLADAFW::MeshVertexData& positions = mSpline->getInTangents (); 399 const size_t initialIndex = positions.getValuesCount (); 400 sourceBase->setInitialIndex ( initialIndex ); 401 402 // Push the new positions into the list of positions. 403 positions.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE ); 404 if ( initialIndex != 0 ) 405 { 406 positions.appendValues ( valuesArray ); 407 } 408 else 409 { 410 positions.setData ( valuesArray.getData (), valuesArray.getCount () ); 411 valuesArray.yieldOwnerShip(); 412 } 413 414 // Set the source base as loaded element. 415 sourceBase->addLoadedInputElement ( InputSemantic::IN_TANGENT ); 416 417 break; 418 } 419 default: 420 std::cerr << "Position source has an other datatype as float or double! " << dataType << std::endl; 421 return false; 422 } 423 424 return true; 425 } 426 else 427 { 428 return false; 429 } 430 } 431 loadInterpolations()432 bool SplineLoader::loadInterpolations() 433 { 434 if( mInterpolations.size() ) 435 { 436 COLLADAFW::Spline::InterpolationArray & interpolations = mSpline->getInterpolations(); 437 438 interpolations.reallocMemory( mInterpolations.size() ); 439 440 StringList::const_iterator it = mInterpolations.begin(), end = mInterpolations.end(); 441 for( ; it != end ; ++it) 442 { 443 if( *it == "LINEAR" ) 444 { 445 interpolations.append( COLLADAFW::Spline::LINEAR ); 446 } 447 else if( *it == "BEZIER" ) 448 { 449 interpolations.append( COLLADAFW::Spline::BEZIER ); 450 } 451 else 452 { 453 std::cerr << "Interpolation source has an unknown type : " << *it << std::endl; 454 return false; 455 } 456 } 457 return true; 458 } 459 else 460 { 461 return false; 462 } 463 } 464 465 } // namespace COLLADASaxFWL 466