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 "COLLADASaxFWLMeshLoader.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 "COLLADAFWPolylist.h" 23 #include "COLLADAFWLinestrips.h" 24 #include "COLLADAFWIWriter.h" 25 26 #include <fstream> 27 28 29 namespace COLLADASaxFWL 30 { 31 MeshLoader(IFilePartLoader * callingFilePartLoader,const String & geometryId,const String & geometryName)32 MeshLoader::MeshLoader( IFilePartLoader* callingFilePartLoader, const String& geometryId, const String& geometryName ) 33 : SourceArrayLoader (callingFilePartLoader ) 34 , mMeshUniqueId(createUniqueIdFromId((ParserChar*)geometryId.c_str(), COLLADAFW::Geometry::ID())) 35 , mMesh ( new COLLADAFW::Mesh(mMeshUniqueId) ) 36 , mMaterialIdInfo(getMeshMaterialIdInfo()) 37 , mCurrentMeshPrimitive(0) 38 , mInVertices ( false ) 39 , mCurrentVertexInput(0) 40 , mMeshPrimitiveInputs(mVerticesInputs) 41 , mCurrentMeshPrimitiveInput(0) 42 , mCurrentOffset (0) 43 , mCurrentMaxOffset(0) 44 , mCurrentVertexCount(0) 45 , mCurrentLastPrimitiveVertexCount(0) 46 , mCurrentPhHasEmptyP(true) 47 , mCurrentExpectedVertexCount(0) 48 , mCurrentFaceOrLineCount(0) 49 , mPositionsOffset (0) 50 , mPositionsIndexOffset(0) 51 , mUsePositions ( true ) 52 , mNormalsOffset (0) 53 , mNormalsIndexOffset(0) 54 , mUseNormals ( false ) 55 , mUseTangents ( false ) 56 , mUseBinormals ( false ) 57 , mColorList (0) 58 , mTexCoordList (0) 59 , mCurrentPrimitiveType(NONE) 60 , mPOrPhElementCountOfCurrentPrimitive(0) 61 , mInMesh (true) 62 { 63 if ( !geometryName.empty() ) 64 mMesh->setName ( geometryName ); 65 else if ( !geometryId.empty() ) 66 mMesh->setName ( geometryId ); 67 68 if ( !geometryId.empty() ) 69 mMesh->setOriginalId ( geometryId ); 70 } 71 72 //------------------------------ getUniqueId()73 const COLLADAFW::UniqueId& MeshLoader::getUniqueId () 74 { 75 switch ( mCurrentPrimitiveType ) 76 { 77 case TRIANGLES: 78 case LINES: 79 case TRISTRIPS: 80 case TRIFANS: 81 case POLYGONS: 82 case POLYGONS_HOLE: 83 case POLYLIST: 84 case LINESTRIPS: 85 return mCurrentMeshPrimitive->getUniqueId (); break; 86 default: 87 if ( mMesh ) return mMesh->getUniqueId (); break; 88 } 89 90 return COLLADAFW::UniqueId::INVALID; 91 } 92 93 //------------------------------ getVertexInputBySemantic(const InputSemantic::Semantic & semantic) const94 const InputUnshared* MeshLoader::getVertexInputBySemantic ( const InputSemantic::Semantic& semantic ) const 95 { 96 // Search the vertex input elements for the semantic element. 97 return getVertices().getInputBySemantic ( semantic ); 98 } 99 100 //------------------------------ getSourceByInputSemanticFromVertices(const InputSemantic::Semantic & semantic) const101 const SourceBase* MeshLoader::getSourceByInputSemanticFromVertices ( const InputSemantic::Semantic& semantic ) const 102 { 103 // Check if the input element with the semantic is a vertex element. 104 const InputUnshared* positionsInput = getVertexInputBySemantic ( semantic ); 105 if ( positionsInput == 0 ) return 0; 106 107 // Get the source element with the uri of the input element. 108 COLLADABU::URI positionsInputSource = positionsInput->getSource (); 109 String sourceId = positionsInputSource.getFragment (); 110 111 return getSourceById ( sourceId ); 112 } 113 114 //------------------------------ getPositionsSource() const115 const SourceBase* MeshLoader::getPositionsSource () const 116 { 117 return getSourceByInputSemanticFromVertices ( InputSemantic::POSITION ); 118 } 119 120 121 //------------------------------ loadSourceElements(const MeshPrimitiveInputList & polyBaseElement)122 void MeshLoader::loadSourceElements ( const MeshPrimitiveInputList& polyBaseElement ) 123 { 124 const InputSharedArray& inputArray = polyBaseElement.getInputArray (); 125 size_t numInputElements = inputArray.getCount (); 126 for ( size_t n=0; n<numInputElements; ++n ) 127 { 128 // Get the input element and read the semantic. 129 InputShared* input = inputArray [n]; 130 131 // Load the source element of the current input element into the framework mesh. 132 loadSourceElement ( *input ); 133 } 134 } 135 136 //------------------------------ loadSourceElement(const InputShared & input)137 bool MeshLoader::loadSourceElement ( const InputShared& input ) 138 { 139 bool retValue = false; 140 141 // Get the semantic of the current input element. 142 InputSemantic::Semantic semantic = input.getSemantic (); 143 switch ( semantic ) 144 { 145 case InputSemantic::POSITION: 146 retValue = loadPositionsSourceElement ( input ); 147 break; 148 case InputSemantic::NORMAL: 149 retValue = loadNormalsSourceElement ( input ); 150 break; 151 case InputSemantic::COLOR: 152 retValue = loadColorsSourceElement ( input ); 153 break; 154 case InputSemantic::UV: 155 case InputSemantic::TEXCOORD: 156 retValue = loadTexCoordsSourceElement ( input ); 157 break; 158 case InputSemantic::TEXTANGENT: 159 retValue = loadTexTangentSourceElement( input ); 160 break; 161 case InputSemantic::TEXBINORMAL: 162 retValue = loadTexBinormalSourceElement( input ); 163 break; 164 default: 165 // Not implemented source 166 // std::cerr << "Source with semantic " << semantic << "not implemented!" << std::endl; 167 retValue = false; 168 } 169 170 return retValue; 171 } 172 173 //------------------------------ loadPositionsSourceElement(const InputShared & input)174 bool MeshLoader::loadPositionsSourceElement ( const InputShared& input ) 175 { 176 // Get the semantic of the current input element. 177 InputSemantic::Semantic semantic = input.getSemantic (); 178 if ( semantic != InputSemantic::POSITION ) 179 { 180 std::cerr << "The current input element is not a POSITION element!" << std::endl; 181 return false; 182 } 183 184 // Get the source element with the uri of the input element. 185 COLLADABU::URI inputUrl = input.getSource (); 186 String sourceId = inputUrl.getFragment (); 187 SourceBase* sourceBase = getSourceById ( sourceId ); 188 if ( sourceBase == 0 ) return false; 189 190 // Check if the source element is already loaded. 191 if ( sourceBase->isLoadedInputElement ( semantic ) ) return false; 192 193 // Get the source input array 194 const SourceBase::DataType& dataType = sourceBase->getDataType (); 195 switch ( dataType ) 196 { 197 case SourceBase::DATA_TYPE_FLOAT: 198 { 199 // Get the values array from the source 200 FloatSource* source = ( FloatSource* ) sourceBase; 201 FloatArrayElement& arrayElement = source->getArrayElement (); 202 COLLADAFW::ArrayPrimitiveType<float>& valuesArray = arrayElement.getValues (); 203 204 // TODO 205 /* unsigned long long stride = source->getStride (); */ /* UNUSED */ 206 207 // Check if there are already some values in the positions list. 208 // If so, we have to store the last index to increment the following indexes. 209 COLLADAFW::MeshVertexData& positions = mMesh->getPositions (); 210 const size_t initialIndex = positions.getValuesCount (); 211 sourceBase->setInitialIndex ( initialIndex ); 212 213 // Push the new positions into the list of positions. 214 positions.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT ); 215 if ( initialIndex != 0 ) 216 { 217 positions.appendValues ( valuesArray ); 218 } 219 else 220 { 221 positions.setData ( valuesArray.getData (), valuesArray.getCount () ); 222 valuesArray.yieldOwnerShip(); 223 } 224 225 // Set the source base as loaded element. 226 sourceBase->addLoadedInputElement ( semantic ); 227 228 break; 229 } 230 case SourceBase::DATA_TYPE_DOUBLE: 231 { 232 // Get the values array from the source 233 DoubleSource* source = ( DoubleSource* ) sourceBase; 234 DoubleArrayElement& arrayElement = source->getArrayElement (); 235 COLLADAFW::ArrayPrimitiveType<double>& valuesArray = arrayElement.getValues (); 236 237 // Check if there are already some values in the positions list. 238 // If so, we have to store the last index to increment the following indexes. 239 COLLADAFW::MeshVertexData& positions = mMesh->getPositions (); 240 const size_t initialIndex = positions.getValuesCount (); 241 sourceBase->setInitialIndex ( initialIndex ); 242 243 // Push the new positions into the list of positions. 244 positions.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE ); 245 if ( initialIndex != 0 ) 246 { 247 positions.appendValues ( valuesArray ); 248 } 249 else 250 { 251 positions.setData ( valuesArray.getData (), valuesArray.getCount () ); 252 valuesArray.yieldOwnerShip(); 253 } 254 255 // Set the source base as loaded element. 256 sourceBase->addLoadedInputElement ( semantic ); 257 258 break; 259 } 260 default: 261 std::cerr << "Position source has an other datatype as float or double! " << dataType << std::endl; 262 return false; 263 } 264 265 return true; 266 } 267 268 //------------------------------ loadNormalsSourceElement(const InputShared & input)269 bool MeshLoader::loadNormalsSourceElement ( const InputShared& input ) 270 { 271 // Get the semantic of the current input element. 272 InputSemantic::Semantic semantic = input.getSemantic (); 273 if ( semantic != InputSemantic::NORMAL ) 274 { 275 std::cerr << "The current input element is not a NORMAL element!" << std::endl; 276 return false; 277 } 278 279 // Get the source element with the uri of the input element. 280 COLLADABU::URI inputUrl = input.getSource (); 281 String sourceId = inputUrl.getFragment (); 282 SourceBase* sourceBase = getSourceById ( sourceId ); 283 if ( sourceBase == 0 ) return false; 284 285 // Check if the source element is already loaded. 286 if ( sourceBase->isLoadedInputElement ( semantic ) ) return false; 287 288 // Get the source input array 289 const SourceBase::DataType& dataType = sourceBase->getDataType (); 290 switch ( dataType ) 291 { 292 case SourceBase::DATA_TYPE_FLOAT: 293 { 294 // Get the values array from the source 295 FloatSource* source = ( FloatSource* ) sourceBase; 296 FloatArrayElement& arrayElement = source->getArrayElement (); 297 COLLADAFW::ArrayPrimitiveType<float>& valuesArray = arrayElement.getValues (); 298 299 // Check if there are already some values in the positions list. 300 // If so, we have to store the last index to increment the following indexes. 301 COLLADAFW::MeshVertexData& normals = mMesh->getNormals (); 302 const size_t initialIndex = normals.getValuesCount (); 303 sourceBase->setInitialIndex ( initialIndex ); 304 305 // Push the new positions into the list of positions. 306 normals.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT ); 307 if ( initialIndex != 0 ) 308 { 309 normals.appendValues ( valuesArray ); 310 } 311 else 312 { 313 normals.setData ( valuesArray.getData (), valuesArray.getCount () ); 314 valuesArray.yieldOwnerShip(); 315 } 316 317 // Set the source base as loaded element. 318 sourceBase->addLoadedInputElement ( semantic ); 319 320 break; 321 } 322 case SourceBase::DATA_TYPE_DOUBLE: 323 { 324 // Get the values array from the source 325 DoubleSource* source = ( DoubleSource* ) sourceBase; 326 DoubleArrayElement& arrayElement = source->getArrayElement (); 327 COLLADAFW::ArrayPrimitiveType<double>& valuesArray = arrayElement.getValues (); 328 329 // Check if there are already some values in the positions list. 330 // If so, we have to store the last index to increment the following indexes. 331 COLLADAFW::MeshVertexData& normals = mMesh->getNormals (); 332 const size_t initialIndex = normals.getValuesCount (); 333 sourceBase->setInitialIndex ( initialIndex ); 334 335 // Push the new positions into the list of positions. 336 normals.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE ); 337 if ( initialIndex != 0 ) 338 { 339 normals.appendValues ( valuesArray ); 340 } 341 else 342 { 343 normals.setData ( valuesArray.getData (), valuesArray.getCount () ); 344 valuesArray.yieldOwnerShip(); 345 } 346 347 // Set the source base as loaded element. 348 sourceBase->addLoadedInputElement ( semantic ); 349 350 break; 351 } 352 default: 353 std::cerr << "Normals source has an other datatype as float or double! " << dataType << std::endl; 354 return false; 355 } 356 357 return true; 358 } 359 //------------------------------ loadColorsSourceElement(const InputShared & input)360 bool MeshLoader::loadColorsSourceElement ( const InputShared& input ) 361 { 362 bool retValue = true; 363 364 // Get the semantic of the current input element. 365 InputSemantic::Semantic semantic = input.getSemantic (); 366 if ( semantic != InputSemantic::COLOR ) 367 { 368 std::cerr << "The current input element is not a COLOR element!" << std::endl; 369 return false; 370 } 371 372 // Get the source element with the uri of the input element. 373 COLLADABU::URI inputUrl = input.getSource (); 374 String sourceId = inputUrl.getFragment (); 375 SourceBase* sourceBase = getSourceById ( sourceId ); 376 if ( sourceBase == 0 ) return false; 377 378 // Check if the source element is already loaded. 379 if ( sourceBase->isLoadedInputElement ( semantic ) ) return false; 380 381 // Get the stride of the uv coordinates. 382 // This is the dimension of the uv coordinates. 383 // In depend on the dimension, we store the coordinates in the mesh. 384 unsigned long long stride = sourceBase->getStride (); 385 if ( stride < 3 || stride > 4 ) 386 { 387 std::cerr << "The color source " << input.getSource().getURIString () 388 << " has a wrong dimension of " << stride 389 << ". Dimensions between 3 (RGB) and 4 (RGBA) are allowed. " << std::endl; 390 retValue = false; 391 } 392 else 393 { 394 COLLADAFW::MeshVertexData& colors = mMesh->getColors (); 395 retValue = appendVertexValues ( sourceBase, colors ); 396 } 397 398 // Set the source base as loaded element. 399 sourceBase->addLoadedInputElement ( semantic ); 400 401 return retValue; 402 } 403 loadTexTangentSourceElement(const InputShared & input)404 bool MeshLoader::loadTexTangentSourceElement( const InputShared& input ) 405 { 406 bool retValue = true; 407 408 // Get the semantic of the current input element. 409 InputSemantic::Semantic semantic = input.getSemantic (); 410 if ( semantic != InputSemantic::TEXTANGENT ) 411 { 412 std::cerr << "The current input element is not a TEXTANGENT element!" << std::endl; 413 return false; 414 } 415 416 // Get the source element with the uri of the input element. 417 COLLADABU::URI inputUrl = input.getSource (); 418 String sourceId = inputUrl.getFragment (); 419 SourceBase* sourceBase = getSourceById ( sourceId ); 420 if ( sourceBase == 0 ) return false; 421 422 // Check if the source element is already loaded. 423 if ( sourceBase->isLoadedInputElement ( semantic ) ) return false; 424 425 // Get the stride of the uv coordinates. 426 // This is the dimension of the uv coordinates. 427 // In depend on the dimension, we store the coordinates in the mesh. 428 unsigned long long stride = sourceBase->getStride (); 429 if ( stride != 3 ) 430 { 431 std::cerr << "The tangent source " << input.getSource().getURIString () 432 << " has a wrong dimension of " << stride 433 << ". Dimensions must be 3." << std::endl; 434 retValue = false; 435 } 436 else 437 { 438 COLLADAFW::MeshVertexData& colors = mMesh->getTangents (); 439 retValue = appendVertexValues ( sourceBase, colors ); 440 } 441 442 // Set the source base as loaded element. 443 sourceBase->addLoadedInputElement ( semantic ); 444 445 return retValue; 446 } 447 loadTexBinormalSourceElement(const InputShared & input)448 bool MeshLoader::loadTexBinormalSourceElement ( const InputShared& input ) 449 { 450 bool retValue = true; 451 452 // Get the semantic of the current input element. 453 InputSemantic::Semantic semantic = input.getSemantic (); 454 if ( semantic != InputSemantic::TEXBINORMAL ) 455 { 456 std::cerr << "The current input element is not a TEXBINORMAL element!" << std::endl; 457 return false; 458 } 459 460 // Get the source element with the uri of the input element. 461 COLLADABU::URI inputUrl = input.getSource (); 462 String sourceId = inputUrl.getFragment (); 463 SourceBase* sourceBase = getSourceById ( sourceId ); 464 if ( sourceBase == 0 ) return false; 465 466 // Check if the source element is already loaded. 467 if ( sourceBase->isLoadedInputElement ( semantic ) ) return false; 468 469 // Get the stride of the uv coordinates. 470 // This is the dimension of the uv coordinates. 471 // In depend on the dimension, we store the coordinates in the mesh. 472 unsigned long long stride = sourceBase->getStride (); 473 if ( stride != 3 ) 474 { 475 std::cerr << "The binormal source " << input.getSource().getURIString () 476 << " has a wrong dimension of " << stride 477 << ". Dimensions must be 3." << std::endl; 478 retValue = false; 479 } 480 else 481 { 482 COLLADAFW::MeshVertexData& colors = mMesh->getBinormals (); 483 retValue = appendVertexValues ( sourceBase, colors ); 484 } 485 486 // Set the source base as loaded element. 487 sourceBase->addLoadedInputElement ( semantic ); 488 489 return retValue; 490 } 491 492 //------------------------------ appendVertexValues(SourceBase * sourceBase,COLLADAFW::MeshVertexData & vertexData)493 bool MeshLoader::appendVertexValues ( 494 SourceBase* sourceBase, 495 COLLADAFW::MeshVertexData &vertexData ) 496 { 497 bool retValue = true; 498 499 // Check if there are already some values in the positions list. 500 // If so, we have to store the last index to increment the following indexes. 501 const size_t initialIndex = vertexData.getValuesCount (); 502 sourceBase->setInitialIndex ( initialIndex ); 503 504 // Get the source input array 505 const SourceBase::DataType& dataType = sourceBase->getDataType (); 506 switch ( dataType ) 507 { 508 case SourceBase::DATA_TYPE_FLOAT: 509 { 510 // Get the values array from the source 511 FloatSource* source = ( FloatSource* ) sourceBase; 512 FloatArrayElement& arrayElement = source->getArrayElement (); 513 COLLADAFW::ArrayPrimitiveType<float>& valuesArray = arrayElement.getValues (); 514 515 // Push the values with the infos into the list. 516 vertexData.appendValues ( valuesArray, source->getId (), (size_t) source->getStride () ); 517 518 break; 519 } 520 case SourceBase::DATA_TYPE_DOUBLE: 521 { 522 // Get the values array from the source 523 DoubleSource* source = ( DoubleSource* ) sourceBase; 524 DoubleArrayElement& arrayElement = source->getArrayElement (); 525 COLLADAFW::ArrayPrimitiveType<double>& valuesArray = arrayElement.getValues (); 526 527 // Push the values with the infos into the list. 528 vertexData.appendValues ( valuesArray, source->getId (), (size_t) source->getStride () ); 529 530 break; 531 } 532 default: 533 std::cerr << "Source has an other datatype as float or double! " << dataType << std::endl; 534 retValue = false; 535 } 536 537 return retValue; 538 } 539 540 //------------------------------ loadTexCoordsSourceElement(const InputShared & input)541 bool MeshLoader::loadTexCoordsSourceElement ( const InputShared& input ) 542 { 543 bool retValue = true; 544 545 // Get the semantic of the current input element. 546 InputSemantic::Semantic semantic = input.getSemantic (); 547 if ( semantic != InputSemantic::UV && semantic != InputSemantic::TEXCOORD ) 548 { 549 std::cerr << "The current input element is not a UV / TEXCOORD element!" << std::endl; 550 return false; 551 } 552 553 // Get the source element with the uri of the input element. 554 COLLADABU::URI inputUrl = input.getSource (); 555 String sourceId = inputUrl.getFragment (); 556 SourceBase* sourceBase = getSourceById ( sourceId ); 557 if ( sourceBase == 0 ) return false; 558 559 // Check if the source element is already loaded. 560 if ( sourceBase->isLoadedInputElement ( semantic ) ) return false; 561 562 // Get the stride of the uv coordinates. 563 // This is the dimension of the uv coordinates. 564 // In depend on the dimension, we store the coordinates in the mesh. 565 unsigned long long stride = sourceBase->getStride (); 566 if ( stride < 2 || stride > 4 ) 567 { 568 std::cerr << "The uv source " << input.getSource().getURIString () 569 << " has a wrong dimension of " << stride 570 << ". Dimensions between 2 and 4 are allowed. " << std::endl; 571 retValue = false; 572 } 573 else 574 { 575 COLLADAFW::MeshVertexData& uvCoords = mMesh->getUVCoords (); 576 retValue = appendVertexValues ( sourceBase, uvCoords ); 577 } 578 579 // Set the source base as loaded element. 580 sourceBase->addLoadedInputElement ( semantic ); 581 582 return retValue; 583 } 584 585 //------------------------------ writePrimitiveIndices(const unsigned long long * data,size_t length)586 bool MeshLoader::writePrimitiveIndices ( const unsigned long long* data, size_t length ) 587 { 588 // check, if we are parsing an unsupported primitive type 589 if ( !mCurrentMeshPrimitive ) 590 return true; 591 592 // Write the index values in the index lists. 593 for ( size_t i=0; i<length; ++i ) 594 { 595 // Get the current index value. 596 unsigned int index = (unsigned int)data [i]; 597 598 // Write the indices 599 if ( mUsePositions && (mCurrentOffset == mPositionsOffset) ) 600 { 601 COLLADAFW::UIntValuesArray& positionIndices = mCurrentMeshPrimitive->getPositionIndices(); 602 positionIndices.append ( index + mPositionsIndexOffset ); 603 } 604 605 if ( mUseNormals && (mCurrentOffset == mNormalsOffset) ) 606 { 607 COLLADAFW::UIntValuesArray& normalIndices = mCurrentMeshPrimitive->getNormalIndices(); 608 normalIndices.append ( index + mNormalsIndexOffset ); 609 } 610 611 if ( mUseTangents && (mCurrentOffset == mTangentsOffset) ) 612 { 613 COLLADAFW::UIntValuesArray& tangentIndices = mCurrentMeshPrimitive->getTangentIndices(); 614 tangentIndices.append ( index + mTangentsIndexOffset ); 615 } 616 617 if ( mUseBinormals && (mCurrentOffset == mBinormalsOffset) ) 618 { 619 COLLADAFW::UIntValuesArray& binormalIndices = mCurrentMeshPrimitive->getBinormalIndices(); 620 binormalIndices.append ( index + mBinormalsIndexOffset ); 621 } 622 623 624 // Look if the current offset is a texcoord offset. 625 size_t numTexCoordinates = mTexCoordList.size(); 626 for ( size_t j=0; j<numTexCoordinates; ++j ) 627 { 628 PrimitiveInput& texCoord = mTexCoordList[j]; 629 if ( mCurrentOffset == texCoord.mOffset ) 630 { 631 COLLADAFW::ArrayPrimitiveType<COLLADAFW::IndexList*>& texCoordIndicesArray = 632 mCurrentMeshPrimitive->getUVCoordIndicesArray(); 633 634 // Resize the array if necessary 635 if ( texCoordIndicesArray.getCount () != numTexCoordinates ) 636 { 637 // Be careful: no constructor is called! 638 texCoordIndicesArray.reallocMemory ( numTexCoordinates ); 639 for ( size_t k=0; k<numTexCoordinates; ++k ) 640 { 641 COLLADAFW::IndexList* texCoordIndices = new COLLADAFW::IndexList (); 642 PrimitiveInput& tex = mTexCoordList [k]; 643 texCoordIndices->setSetIndex ( tex.mSetIndex ); 644 texCoordIndices->setName ( tex.mName ); 645 texCoordIndices->setStride ( tex.mStride ); 646 texCoordIndices->setInitialIndex ( tex.mInitialIndex ); 647 648 texCoordIndicesArray.append( texCoordIndices ); 649 } 650 } 651 652 // Write the values. 653 COLLADAFW::IndexList* texCoordIndices = mCurrentMeshPrimitive->getUVCoordIndices ( j ); 654 texCoordIndices->getIndices().append ( index + (unsigned int)texCoord.mInitialIndex ); 655 } 656 } 657 658 // Look if the current offset is a texcoord offset. 659 size_t numColors = mColorList.size (); 660 for ( size_t j=0; j<numColors; ++j ) 661 { 662 PrimitiveInput& color = mColorList [j]; 663 if ( mCurrentOffset == color.mOffset ) 664 { 665 COLLADAFW::ArrayPrimitiveType<COLLADAFW::IndexList*>& colorIndicesArray = 666 mCurrentMeshPrimitive->getColorIndicesArray (); 667 668 // Resize the array if necessary 669 if ( colorIndicesArray.getCount () != numColors ) 670 { 671 // Be careful: no constructor is called! 672 colorIndicesArray.reallocMemory ( numColors ); 673 for ( size_t k=0; k<numColors; ++k ) 674 { 675 COLLADAFW::IndexList* colorIndices = new COLLADAFW::IndexList (); 676 PrimitiveInput& col = mColorList [k]; 677 colorIndices->setSetIndex ( col.mSetIndex ); 678 colorIndices->setName ( col.mName ); 679 colorIndices->setStride ( col.mStride ); 680 colorIndices->setInitialIndex ( col.mInitialIndex ); 681 682 colorIndicesArray.append ( colorIndices ); 683 } 684 } 685 686 // Write the values. 687 COLLADAFW::IndexList* colorIndices = mCurrentMeshPrimitive->getColorIndices ( j ); 688 colorIndices->getIndices().append ( index + (unsigned int)color.mInitialIndex ); 689 } 690 } 691 692 // Reset the offset if we went through all offset values 693 if ( mCurrentOffset == mCurrentMaxOffset ) 694 { 695 // Reset the current offset value 696 mCurrentOffset = 0; 697 ++mCurrentVertexCount; 698 } 699 else 700 { 701 // Increment the current offset value 702 ++mCurrentOffset; 703 } 704 } 705 return true; 706 } 707 708 709 //------------------------------ initializeOffsets()710 bool MeshLoader::initializeOffsets() 711 { 712 bool has_errors = false; 713 // Reset the members 714 mCurrentOffset = 0; 715 mPositionsOffset = 0; 716 mPositionsIndexOffset = 0; 717 mUsePositions = true; 718 mNormalsOffset = 0; 719 mNormalsIndexOffset = 0; 720 mUseNormals = false; 721 mUseTangents = false; 722 mUseBinormals = false; 723 mTexCoordList.clear (); 724 mColorList.clear (); 725 726 // We need the maximum offset value of the input elements to calculate the 727 // number of indices for each index list. 728 mCurrentMaxOffset = (size_t)mMeshPrimitiveInputs.getInputArrayMaxOffset (); 729 730 // The offset values of the input elements. 731 has_errors |= initializePositionsOffset(); 732 initializeNormalsOffset(); 733 has_errors |= initializeColorsOffset(); 734 has_errors |= initializeTexCoordsOffset(); 735 initializeTangentsOffset(); 736 initializeBinormalsOffset(); 737 return has_errors; 738 } 739 740 //------------------------------ initializePositionsOffset()741 bool MeshLoader::initializePositionsOffset () 742 { 743 bool has_errors = false; 744 const InputShared* positionInput = mMeshPrimitiveInputs.getPositionInput (); 745 COLLADABU_ASSERT ( positionInput != 0 ); 746 if (positionInput == 0) { 747 has_errors |= handleFWLError(SaxFWLError::ERROR_DATA_NOT_VALID, "No positions, can't import!", IError::SEVERITY_CRITICAL); 748 } 749 else { 750 // Get the offset value, the initial index values and alloc the memory. 751 mPositionsOffset = positionInput->getOffset(); 752 } 753 754 COLLADABU::URI inputUrl = positionInput->getSource (); 755 String sourceId = inputUrl.getFragment (); 756 const SourceBase* sourceBase = getSourceById ( sourceId ); 757 COLLADABU_ASSERT ( sourceBase != 0 ); 758 if ( sourceBase == 0 ) 759 has_errors |= handleFWLError(SaxFWLError::ERROR_DATA_NOT_VALID, "Positions sourceBase is null.", IError::SEVERITY_CRITICAL); 760 else { 761 // only stride 3 makes sense for normals 762 unsigned long long stride = sourceBase->getStride(); 763 if (stride != 3) 764 has_errors |= handleFWLError(SaxFWLError::ERROR_DATA_NOT_VALID, "Positios stride is not three.", IError::SEVERITY_CRITICAL); 765 766 mPositionsIndexOffset = (unsigned int)sourceBase->getInitialIndex(); 767 } 768 return has_errors; 769 } 770 771 //------------------------------ initializeNormalsOffset()772 void MeshLoader::initializeNormalsOffset () 773 { 774 // Check for using normals 775 const InputShared* normalInput = mMeshPrimitiveInputs.getNormalInput (); 776 if ( normalInput != 0 ) 777 { 778 // Get the offset value, the initial index values and alloc the memory. 779 mNormalsOffset = normalInput->getOffset (); 780 const SourceBase* sourceBase = getSourceById ( normalInput->getSource ().getFragment () ); 781 if ( !sourceBase ) 782 { 783 mNormalsIndexOffset = 0; 784 mUseNormals = false; 785 } 786 else 787 { 788 // only stride 3 makes sense for normals 789 unsigned long long stride = sourceBase->getStride(); 790 if ( stride == 3 ) 791 { 792 mNormalsIndexOffset = (unsigned int)(sourceBase->getInitialIndex() / stride); 793 mUseNormals = true; 794 } 795 else 796 { 797 mNormalsIndexOffset = 0; 798 mUseNormals = false; 799 } 800 } 801 } 802 else 803 { 804 mNormalsIndexOffset = 0; 805 mUseNormals = false; 806 } 807 } 808 809 //------------------------------ initializeTangentsOffset()810 void MeshLoader::initializeTangentsOffset () 811 { 812 // Check for using normals 813 const InputShared* tangentInput = mMeshPrimitiveInputs.getTangentInput (); 814 if ( tangentInput != 0 ) 815 { 816 // Get the offset value, the initial index values and alloc the memory. 817 mTangentsOffset = tangentInput->getOffset (); 818 const SourceBase* sourceBase = getSourceById ( tangentInput->getSource ().getFragment () ); 819 if ( !sourceBase ) 820 { 821 mTangentsIndexOffset = 0; 822 mUseTangents = false; 823 } 824 else 825 { 826 // only stride 3 makes sense for normals 827 unsigned long long stride = sourceBase->getStride(); 828 if ( stride == 3 ) 829 { 830 mTangentsIndexOffset = (unsigned int)(sourceBase->getInitialIndex() / stride); 831 mUseTangents = true; 832 } 833 else 834 { 835 mTangentsIndexOffset = 0; 836 mUseTangents = false; 837 } 838 } 839 } 840 else 841 { 842 mTangentsIndexOffset = 0; 843 mUseTangents = false; 844 } 845 } 846 847 848 //------------------------------ initializeBinormalsOffset()849 void MeshLoader::initializeBinormalsOffset () 850 { 851 // Check for using normals 852 const InputShared* binormalInput = mMeshPrimitiveInputs.getBinormalInput (); 853 if ( binormalInput != 0 ) 854 { 855 // Get the offset value, the initial index values and alloc the memory. 856 mBinormalsOffset = binormalInput->getOffset (); 857 const SourceBase* sourceBase = getSourceById ( binormalInput->getSource ().getFragment () ); 858 if ( !sourceBase ) 859 { 860 mBinormalsIndexOffset = 0; 861 mUseBinormals = false; 862 } 863 else 864 { 865 // only stride 3 makes sense for normals 866 unsigned long long stride = sourceBase->getStride(); 867 if ( stride == 3 ) 868 { 869 mBinormalsIndexOffset = (unsigned int)(sourceBase->getInitialIndex() / stride); 870 mUseBinormals = true; 871 } 872 else 873 { 874 mBinormalsIndexOffset = 0; 875 mUseBinormals = false; 876 } 877 } 878 } 879 else 880 { 881 mBinormalsIndexOffset = 0; 882 mUseBinormals = false; 883 } 884 } 885 886 //------------------------------ initializeColorsOffset()887 bool MeshLoader::initializeColorsOffset () 888 { 889 // Check for using colors 890 const InputSharedArray& inputArray = mMeshPrimitiveInputs.getInputArray (); 891 size_t numInputs = inputArray.getCount (); 892 893 for ( size_t i=0; i<numInputs; ++i ) 894 { 895 const InputShared* input = inputArray [i]; 896 if ( input->getSemantic () == InputSemantic::COLOR ) 897 { 898 // TODO Id management! 899 String sourceId = input->getSource ().getFragment (); 900 SourceBase* sourceBase = getSourceById ( sourceId ); 901 if ( sourceBase == 0 ) 902 { 903 return handleFWLError ( SaxFWLError::ERROR_DATA_NOT_VALID, "SourceBase of tex coords with semantic TEXCOORD not valid!" ); 904 } 905 906 // only stride 1, 2, 3 or 4 makes sense for uv coords 907 size_t stride = ( size_t ) sourceBase->getStride(); 908 COLLADABU_ASSERT ( (stride >= 1) || (stride <= 4) ); 909 910 size_t intitialIndex = sourceBase->getInitialIndex (); 911 size_t indexOffset = intitialIndex / stride; 912 913 PrimitiveInput color; 914 color.mOffset = ( size_t ) input->getOffset (); 915 color.mInitialIndex = indexOffset; 916 color.mStride = stride; 917 color.mSetIndex = ( size_t ) input->getSet (); 918 color.mName = sourceId; 919 920 mColorList.push_back ( color ); 921 } 922 } 923 return false; 924 } 925 926 //------------------------------ initializeTexCoordsOffset()927 bool MeshLoader::initializeTexCoordsOffset () 928 { 929 // Check for using tex coordinates 930 const InputSharedArray& inputArray = mMeshPrimitiveInputs.getInputArray (); 931 size_t numInputs = inputArray.getCount (); 932 933 for ( size_t i=0; i<numInputs; ++i ) 934 { 935 const InputShared* input = inputArray [i]; 936 if ( input->getSemantic () == InputSemantic::TEXCOORD ) 937 { 938 // TODO Id management! 939 String sourceId = input->getSource ().getFragment (); 940 SourceBase* sourceBase = getSourceById ( sourceId ); 941 if ( sourceBase == 0 ) 942 { 943 return handleFWLError ( SaxFWLError::ERROR_DATA_NOT_VALID, "SourceBase of tex coords with semantic TEXCOORD not valid!" ); 944 } 945 946 // only stride 1, 2, 3 or 4 makes sense for uv coords 947 size_t stride = ( size_t ) sourceBase->getStride(); 948 COLLADABU_ASSERT ( (stride >= 1) || (stride <= 4) ); 949 950 size_t intitialIndex = sourceBase->getInitialIndex (); 951 size_t indexOffset = intitialIndex / stride; 952 953 PrimitiveInput texCoord; 954 texCoord.mOffset = ( size_t ) input->getOffset (); 955 texCoord.mInitialIndex = indexOffset; 956 texCoord.mStride = stride; 957 texCoord.mSetIndex = ( size_t ) input->getSet (); 958 texCoord.mName = sourceId; 959 960 mTexCoordList.push_back ( texCoord ); 961 } 962 } 963 return false; 964 } 965 966 967 //------------------------------ initCurrentValues()968 void MeshLoader::initCurrentValues() 969 { 970 mCurrentVertexCount = 0; 971 mCurrentLastPrimitiveVertexCount = 0; 972 mCurrentExpectedVertexCount = 0; 973 mCurrentMeshPrimitive = 0; 974 mCurrentFaceOrLineCount = 0; 975 mCurrentPhHasEmptyP = true; 976 mPOrPhElementCountOfCurrentPrimitive = 0; 977 } 978 979 //------------------------------ end__mesh()980 bool MeshLoader::end__mesh() 981 { 982 mInMesh = false; 983 984 // The mesh will be written by the GeometyLoader. Therefore nothing to with the mesh here 985 finish(); 986 return true; 987 } 988 989 //------------------------------ begin__source(const source__AttributeData & attributes)990 bool MeshLoader::begin__source( const source__AttributeData& attributes ) 991 { 992 return beginSource(attributes); 993 } 994 995 //------------------------------ end__source()996 bool MeshLoader::end__source( ) 997 { 998 return endSource(); 999 } 1000 1001 //------------------------------ begin__vertices(const vertices__AttributeData & attributeData)1002 bool MeshLoader::begin__vertices( const vertices__AttributeData& attributeData ) 1003 { 1004 mInVertices = true; 1005 1006 if ( attributeData.id ) 1007 mVerticesInputs.setId( attributeData.id ); 1008 if ( attributeData.name ) 1009 mVerticesInputs.setName( attributeData.name ); 1010 return true; 1011 } 1012 1013 //------------------------------ end__vertices()1014 bool MeshLoader::end__vertices() 1015 { 1016 mInVertices = false; 1017 1018 return true; 1019 } 1020 1021 //------------------------------ begin__input____InputLocal(const input____InputLocal__AttributeData & attributeData)1022 bool MeshLoader::begin__input____InputLocal( const input____InputLocal__AttributeData& attributeData ) 1023 { 1024 mCurrentVertexInput = new InputUnshared(attributeData.semantic, attributeData.source); 1025 return true; 1026 } 1027 1028 //------------------------------ end__input____InputLocal()1029 bool MeshLoader::end__input____InputLocal() 1030 { 1031 mVerticesInputs.getInputArray().append(mCurrentVertexInput); 1032 mCurrentVertexInput = 0; 1033 return true; 1034 } 1035 1036 //------------------------------ begin__triangles(const triangles__AttributeData & attributeData)1037 bool MeshLoader::begin__triangles( const triangles__AttributeData& attributeData ) 1038 { 1039 mCurrentPrimitiveType = TRIANGLES; 1040 mCurrentMeshPrimitive = new COLLADAFW::Triangles(createUniqueId(COLLADAFW::Triangles::ID())); 1041 if ( (size_t)attributeData.count > 0) 1042 { 1043 mCurrentMeshPrimitive->getPositionIndices().reallocMemory((size_t)attributeData.count); 1044 if ( mUseNormals ) 1045 { 1046 mCurrentMeshPrimitive->getNormalIndices().reallocMemory((size_t)attributeData.count); 1047 } 1048 1049 if ( mUseTangents ) 1050 { 1051 mCurrentMeshPrimitive->getTangentIndices().reallocMemory((size_t)attributeData.count); 1052 } 1053 1054 if ( mUseBinormals ) 1055 { 1056 mCurrentMeshPrimitive->getBinormalIndices().reallocMemory((size_t)attributeData.count); 1057 } 1058 1059 // TODO pre-alloc memory for uv indices 1060 } 1061 if ( attributeData.material ) 1062 { 1063 mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId(attributeData.material)); 1064 mCurrentMeshPrimitive->setMaterial(attributeData.material); 1065 } 1066 return true; 1067 } 1068 1069 //------------------------------ end__triangles()1070 bool MeshLoader::end__triangles() 1071 { 1072 size_t trianglesCount = mCurrentVertexCount/3; 1073 // check if the triangles really contains triangles. If not, we will discard it 1074 if ( trianglesCount > 0 ) 1075 { 1076 mCurrentMeshPrimitive->setFaceCount(trianglesCount); 1077 mMesh->appendPrimitive(mCurrentMeshPrimitive); 1078 } 1079 else 1080 { 1081 delete mCurrentMeshPrimitive; 1082 } 1083 initCurrentValues(); 1084 mMeshPrimitiveInputs.clearInputs(); 1085 mCurrentPrimitiveType = NONE; 1086 return true; 1087 } 1088 1089 1090 //------------------------------ begin__input____InputLocalOffset(const input____InputLocalOffset__AttributeData & attributeData)1091 bool MeshLoader::begin__input____InputLocalOffset( const input____InputLocalOffset__AttributeData& attributeData ) 1092 { 1093 return beginInput(attributeData); 1094 } 1095 1096 //------------------------------ end__input____InputLocalOffset()1097 bool MeshLoader::end__input____InputLocalOffset() 1098 { 1099 return true; 1100 } 1101 1102 //------------------------------ beginInput(const input____InputLocalOffset__AttributeData & attributeData)1103 bool MeshLoader::beginInput( const input____InputLocalOffset__AttributeData& attributeData ) 1104 { 1105 bool setPresent = (attributeData.present_attributes & input____InputLocalOffset__AttributeData::ATTRIBUTE_SET_PRESENT) == input____InputLocalOffset__AttributeData::ATTRIBUTE_SET_PRESENT; 1106 mMeshPrimitiveInputs.appendInputElement(new InputShared(attributeData.semantic, 1107 attributeData.source, 1108 attributeData.offset, 1109 setPresent ? attributeData.set : 0)); 1110 return true; 1111 } 1112 1113 //------------------------------ begin__polylist(const polylist__AttributeData & attributeData)1114 bool MeshLoader::begin__polylist( const polylist__AttributeData& attributeData ) 1115 { 1116 mCurrentPrimitiveType = POLYLIST; 1117 COLLADAFW::Polylist* polylist = new COLLADAFW::Polylist(createUniqueId(COLLADAFW::Polylist::ID())); 1118 polylist->getGroupedVerticesVertexCountArray().allocMemory((size_t)attributeData.count); 1119 mCurrentMeshPrimitive = polylist; 1120 if ( attributeData.material ) 1121 { 1122 mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId( attributeData.material )); 1123 mCurrentMeshPrimitive->setMaterial(attributeData.material); 1124 1125 } 1126 return true; 1127 } 1128 1129 //------------------------------ end__polylist()1130 bool MeshLoader::end__polylist() 1131 { 1132 // check if there are enough vertices as expected by the vcount and that there exist at least 1133 // one polygon. If not, we will discard it 1134 if ( mCurrentVertexCount >= mCurrentExpectedVertexCount && mCurrentVertexCount > 0 ) 1135 { 1136 COLLADAFW::Polylist* polylist = (COLLADAFW::Polylist*) mCurrentMeshPrimitive; 1137 COLLADAFW::Polylist::VertexCountArray& vertexCountArray = polylist->getGroupedVerticesVertexCountArray(); 1138 1139 mCurrentMeshPrimitive->setFaceCount(vertexCountArray.getCount()); 1140 mMesh->appendPrimitive(mCurrentMeshPrimitive); 1141 } 1142 else 1143 { 1144 delete mCurrentMeshPrimitive; 1145 } 1146 initCurrentValues(); 1147 mMeshPrimitiveInputs.clearInputs(); 1148 mCurrentPrimitiveType = NONE; 1149 return true; 1150 } 1151 1152 //------------------------------ begin__lines(const lines__AttributeData & attributeData)1153 bool MeshLoader::begin__lines( const lines__AttributeData& attributeData ) 1154 { 1155 mCurrentPrimitiveType = LINES; 1156 if ( attributeData.material ) 1157 mCurrentMeshMaterial = attributeData.material; 1158 mCurrentCOLLADAPrimitiveCount = (size_t)attributeData.count; 1159 return true; 1160 } 1161 1162 //------------------------------ end__lines()1163 bool MeshLoader::end__lines() 1164 { 1165 mMeshPrimitiveInputs.clearInputs(); 1166 mCurrentPrimitiveType = NONE; 1167 return true; 1168 // initCurrentValues(); 1169 // return true; 1170 } 1171 1172 //------------------------------ begin__linestrips(const linestrips__AttributeData & attributeData)1173 bool MeshLoader::begin__linestrips( const linestrips__AttributeData& attributeData ) 1174 { 1175 COLLADAFW::Linestrips* lineStrips = new COLLADAFW::Linestrips(createUniqueId(COLLADAFW::Linestrips::ID())); 1176 // The actual size might be bigger, but its a lower bound 1177 lineStrips->getGroupedVerticesVertexCountArray().allocMemory((size_t)attributeData.count); 1178 mCurrentMeshPrimitive = lineStrips; 1179 mCurrentPrimitiveType = LINESTRIPS; 1180 if ( attributeData.material ) 1181 { 1182 mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId( attributeData.material )); 1183 mCurrentMeshPrimitive->setMaterial(attributeData.material); 1184 } 1185 return true; 1186 } 1187 1188 //------------------------------ end__linestrips()1189 bool MeshLoader::end__linestrips() 1190 { 1191 mCurrentPrimitiveType = LINESTRIPS; 1192 // check if there is at least one linestrip. If not, we will discard it. 1193 if ( mCurrentFaceOrLineCount > 0 ) 1194 { 1195 mCurrentMeshPrimitive->setFaceCount(mCurrentFaceOrLineCount); 1196 mMesh->appendPrimitive(mCurrentMeshPrimitive); 1197 } 1198 else 1199 { 1200 delete mCurrentMeshPrimitive; 1201 } 1202 initCurrentValues(); 1203 mMeshPrimitiveInputs.clearInputs(); 1204 mCurrentPrimitiveType = NONE; 1205 return true; 1206 } 1207 1208 //------------------------------ begin__vcount()1209 bool MeshLoader::begin__vcount() 1210 { 1211 // initializeOffsets(); 1212 return true; 1213 } 1214 1215 //------------------------------ end__vcount()1216 bool MeshLoader::end__vcount() 1217 { 1218 return true; 1219 } 1220 1221 //------------------------------ data__vcount(const unsigned long long * data,size_t length)1222 bool MeshLoader::data__vcount( const unsigned long long* data, size_t length ) 1223 { 1224 COLLADAFW::Polygons* polygons = (COLLADAFW::Polygons*) mCurrentMeshPrimitive; 1225 COLLADAFW::Polygons::VertexCountArray& vertexCountArray = polygons->getGroupedVerticesVertexCountArray(); 1226 size_t count = vertexCountArray.getCount(); 1227 vertexCountArray.reallocMemory( count + length); 1228 for ( size_t i = 0; i < length; ++i) 1229 { 1230 unsigned long long vcount = data[i]; 1231 vertexCountArray.append((unsigned int)vcount); 1232 mCurrentExpectedVertexCount += (size_t)vcount; 1233 } 1234 return true; 1235 } 1236 1237 //------------------------------ begin__polygons(const polygons__AttributeData & attributeData)1238 bool MeshLoader::begin__polygons( const polygons__AttributeData& attributeData ) 1239 { 1240 mCurrentPrimitiveType = POLYGONS; 1241 COLLADAFW::Polygons* polygons = new COLLADAFW::Polygons(createUniqueId(COLLADAFW::Polygons::ID())); 1242 // The actual size might be bigger, but its a lower bound 1243 polygons->getGroupedVerticesVertexCountArray().allocMemory((size_t)attributeData.count); 1244 mCurrentMeshPrimitive = polygons; 1245 if ( attributeData.material ) 1246 { 1247 mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId( attributeData.material )); 1248 mCurrentMeshPrimitive->setMaterial(attributeData.material); 1249 } 1250 return true; 1251 } 1252 1253 //------------------------------ end__polygons()1254 bool MeshLoader::end__polygons() 1255 { 1256 // check if there is at least one polygon. If not, we will discard it. 1257 if ( mCurrentFaceOrLineCount > 0 ) 1258 { 1259 mCurrentMeshPrimitive->setFaceCount(mCurrentFaceOrLineCount); 1260 mMesh->appendPrimitive(mCurrentMeshPrimitive); 1261 } 1262 else 1263 { 1264 delete mCurrentMeshPrimitive; 1265 } 1266 initCurrentValues(); 1267 mMeshPrimitiveInputs.clearInputs(); 1268 mCurrentPrimitiveType = NONE; 1269 return true; 1270 } 1271 1272 //------------------------------ begin__ph()1273 bool MeshLoader::begin__ph() 1274 { 1275 mCurrentPhHasEmptyP = true; 1276 mCurrentPrimitiveType = POLYGONS_HOLE; 1277 return true; 1278 } 1279 1280 //------------------------------ end__ph()1281 bool MeshLoader::end__ph() 1282 { 1283 mCurrentPrimitiveType = POLYGONS; 1284 mPOrPhElementCountOfCurrentPrimitive++; 1285 return true; 1286 } 1287 1288 //------------------------------ begin__h()1289 bool MeshLoader::begin__h() 1290 { 1291 return true; 1292 } 1293 1294 //------------------------------ end__h()1295 bool MeshLoader::end__h() 1296 { 1297 int currentFaceVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount; 1298 if ( currentFaceVertexCount > 0 ) 1299 { 1300 COLLADAFW::Polygons* polygons = (COLLADAFW::Polygons*) mCurrentMeshPrimitive; 1301 COLLADAFW::Polygons::VertexCountArray& vertexCountArray = polygons->getGroupedVerticesVertexCountArray(); 1302 vertexCountArray.append(-currentFaceVertexCount); 1303 mCurrentLastPrimitiveVertexCount = mCurrentVertexCount; 1304 } 1305 return true; 1306 } 1307 1308 //------------------------------ data__h(const uint64 * data,size_t length)1309 bool MeshLoader::data__h( const uint64* data, size_t length ) 1310 { 1311 // If the p element of the parent ph is empty, we don't need to read the h element 1312 if ( mCurrentPhHasEmptyP ) 1313 return true; 1314 return writePrimitiveIndices(data, length); 1315 } 1316 1317 //------------------------------ begin__tristrips(const tristrips__AttributeData & attributeData)1318 bool MeshLoader::begin__tristrips( const tristrips__AttributeData& attributeData ) 1319 { 1320 COLLADAFW::Tristrips* tristrips = new COLLADAFW::Tristrips(createUniqueId(COLLADAFW::Tristrips::ID())); 1321 // The actual size might be bigger, but its a lower bound 1322 tristrips->getGroupedVerticesVertexCountArray().allocMemory((size_t)attributeData.count); 1323 mCurrentMeshPrimitive = tristrips; 1324 mCurrentPrimitiveType = TRISTRIPS; 1325 if ( attributeData.material ) 1326 { 1327 mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId( attributeData.material )); 1328 mCurrentMeshPrimitive->setMaterial(attributeData.material); 1329 } 1330 return true; 1331 } 1332 1333 //------------------------------ end__tristrips()1334 bool MeshLoader::end__tristrips() 1335 { 1336 mCurrentPrimitiveType = TRISTRIPS; 1337 // check if there is at least one tristrip. If not, we will discard it. 1338 if ( mCurrentFaceOrLineCount > 0 ) 1339 { 1340 mCurrentMeshPrimitive->setFaceCount(mCurrentFaceOrLineCount); 1341 mMesh->appendPrimitive(mCurrentMeshPrimitive); 1342 } 1343 else 1344 { 1345 delete mCurrentMeshPrimitive; 1346 } 1347 initCurrentValues(); 1348 mMeshPrimitiveInputs.clearInputs(); 1349 mCurrentPrimitiveType = NONE; 1350 return true; 1351 } 1352 1353 //------------------------------ begin__trifans(const trifans__AttributeData & attributeData)1354 bool MeshLoader::begin__trifans( const trifans__AttributeData& attributeData ) 1355 { 1356 mCurrentPrimitiveType = TRIFANS; 1357 COLLADAFW::Trifans* trifans = new COLLADAFW::Trifans(createUniqueId(COLLADAFW::Trifans::ID())); 1358 // The actual size might be bigger, but its a lower bound 1359 trifans->getGroupedVerticesVertexCountArray().allocMemory((size_t)attributeData.count); 1360 mCurrentMeshPrimitive = trifans; 1361 if ( attributeData.material ) 1362 { 1363 mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId( attributeData.material )); 1364 mCurrentMeshPrimitive->setMaterial(attributeData.material); 1365 } 1366 return true; 1367 } 1368 1369 //------------------------------ end__trifans()1370 bool MeshLoader::end__trifans() 1371 { 1372 // check if there is at least one trifan. If not, we will discard it. 1373 if ( mCurrentFaceOrLineCount > 0 ) 1374 { 1375 mCurrentMeshPrimitive->setFaceCount(mCurrentFaceOrLineCount); 1376 mMesh->appendPrimitive(mCurrentMeshPrimitive); 1377 } 1378 else 1379 { 1380 delete mCurrentMeshPrimitive; 1381 } 1382 initCurrentValues(); 1383 mMeshPrimitiveInputs.clearInputs(); 1384 mCurrentPrimitiveType = NONE; 1385 return true; 1386 } 1387 1388 //------------------------------ begin__p()1389 bool MeshLoader::begin__p() 1390 { 1391 switch ( mCurrentPrimitiveType ) 1392 { 1393 case TRIANGLES: 1394 { 1395 loadSourceElements(mMeshPrimitiveInputs); 1396 if (initializeOffsets()) 1397 return false; // abort 1398 } 1399 break; 1400 case LINES: 1401 { 1402 loadSourceElements(mMeshPrimitiveInputs); 1403 if (initializeOffsets()) 1404 return false; // abort 1405 mCurrentMeshPrimitive = new COLLADAFW::Lines(createUniqueId(COLLADAFW::Lines::ID())); 1406 if ( mCurrentCOLLADAPrimitiveCount > 0) 1407 { 1408 mCurrentMeshPrimitive->getPositionIndices().reallocMemory(mCurrentCOLLADAPrimitiveCount); 1409 if ( mUseNormals ) 1410 { 1411 mCurrentMeshPrimitive->getNormalIndices().reallocMemory(mCurrentCOLLADAPrimitiveCount); 1412 } 1413 // TODO pre-alloc memory for uv indices 1414 } 1415 mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId(mCurrentMeshMaterial)); 1416 mCurrentMeshPrimitive->setMaterial(mCurrentMeshMaterial); 1417 } 1418 break; 1419 case TRIFANS: 1420 { 1421 if ( mPOrPhElementCountOfCurrentPrimitive == 0) 1422 { 1423 loadSourceElements(mMeshPrimitiveInputs); 1424 if (initializeOffsets()) 1425 return false; // abort 1426 } 1427 int currentTrifanVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount; 1428 if ( currentTrifanVertexCount > 0 ) 1429 { 1430 COLLADAFW::Trifans* trifans = (COLLADAFW::Trifans*) mCurrentMeshPrimitive; 1431 if ( currentTrifanVertexCount >= 3 ) 1432 { 1433 COLLADAFW::Trifans::VertexCountArray& vertexCountArray = trifans->getGroupedVerticesVertexCountArray(); 1434 vertexCountArray.append(currentTrifanVertexCount); 1435 trifans->setTrifanCount(trifans->getTrifanCount() + 1); 1436 mCurrentFaceOrLineCount += (currentTrifanVertexCount - 2); 1437 } 1438 else 1439 { 1440 trifans->getPositionIndices().erase(currentTrifanVertexCount); 1441 trifans->getNormalIndices().erase(currentTrifanVertexCount); 1442 1443 const COLLADAFW::IndexListArray& colorIndicesArray = trifans->getColorIndicesArray (); 1444 for ( size_t i=0; i<colorIndicesArray.getCount (); ++i ) 1445 trifans->getColorIndices(i)->getIndices ().erase(currentTrifanVertexCount); 1446 1447 const COLLADAFW::IndexListArray& uvCoordIndicesArray = trifans->getUVCoordIndicesArray (); 1448 for ( size_t i=0; i<uvCoordIndicesArray.getCount (); ++i ) 1449 trifans->getUVCoordIndices(i)->getIndices ().erase(currentTrifanVertexCount); 1450 } 1451 mCurrentLastPrimitiveVertexCount = mCurrentVertexCount; 1452 } 1453 } 1454 break; 1455 case TRISTRIPS: 1456 case POLYLIST: 1457 case POLYGONS: 1458 case POLYGONS_HOLE: 1459 case LINESTRIPS: 1460 { 1461 if ( mPOrPhElementCountOfCurrentPrimitive == 0) 1462 { 1463 loadSourceElements(mMeshPrimitiveInputs); 1464 if (initializeOffsets()) 1465 return false; // abort 1466 } 1467 } 1468 break; 1469 case NONE: 1470 return false; 1471 } 1472 return true; 1473 } 1474 1475 //------------------------------ end__p()1476 bool MeshLoader::end__p() 1477 { 1478 mPOrPhElementCountOfCurrentPrimitive++; 1479 switch ( mCurrentPrimitiveType ) 1480 { 1481 case TRIANGLES: 1482 { 1483 1484 } 1485 break; 1486 case LINES: 1487 { 1488 size_t linesCount = mCurrentVertexCount/2; 1489 // check if the lines really contains lines. If not, we will discard it 1490 if ( linesCount > 0 ) 1491 { 1492 mCurrentMeshPrimitive->setFaceCount(linesCount); 1493 mMesh->appendPrimitive(mCurrentMeshPrimitive); 1494 } 1495 else 1496 { 1497 delete mCurrentMeshPrimitive; 1498 } 1499 initCurrentValues(); 1500 } 1501 break; 1502 case TRIFANS: 1503 { 1504 int currentTrifanVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount; 1505 if ( currentTrifanVertexCount > 0 ) 1506 { 1507 COLLADAFW::Trifans* trifans = (COLLADAFW::Trifans*) mCurrentMeshPrimitive; 1508 if ( currentTrifanVertexCount >= 3 ) 1509 { 1510 COLLADAFW::Trifans::VertexCountArray& vertexCountArray = trifans->getGroupedVerticesVertexCountArray(); 1511 vertexCountArray.append(currentTrifanVertexCount); 1512 trifans->setTrifanCount(trifans->getTrifanCount() + 1); 1513 mCurrentFaceOrLineCount += (currentTrifanVertexCount - 2); 1514 } 1515 else 1516 { 1517 trifans->getPositionIndices().erase(currentTrifanVertexCount); 1518 trifans->getNormalIndices().erase(currentTrifanVertexCount); 1519 1520 const COLLADAFW::IndexListArray& colorIndicesArray = trifans->getColorIndicesArray (); 1521 for ( size_t i=0; i<colorIndicesArray.getCount (); ++i ) 1522 trifans->getColorIndices(i)->getIndices ().erase(currentTrifanVertexCount); 1523 1524 const COLLADAFW::IndexListArray& uvCoordIndicesArray = trifans->getUVCoordIndicesArray (); 1525 for ( size_t i=0; i<uvCoordIndicesArray.getCount (); ++i ) 1526 trifans->getUVCoordIndices(i)->getIndices ().erase(currentTrifanVertexCount); 1527 } 1528 mCurrentLastPrimitiveVertexCount = mCurrentVertexCount; 1529 } 1530 } 1531 break; 1532 case TRISTRIPS: 1533 { 1534 int currentTristripVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount; 1535 if ( currentTristripVertexCount > 0 ) 1536 { 1537 COLLADAFW::Tristrips* tristrips = (COLLADAFW::Tristrips*) mCurrentMeshPrimitive; 1538 if ( currentTristripVertexCount >= 3 ) 1539 { 1540 COLLADAFW::Tristrips::VertexCountArray& vertexCountArray = tristrips->getGroupedVerticesVertexCountArray(); 1541 vertexCountArray.append(currentTristripVertexCount); 1542 tristrips->setTristripCount(tristrips->getTristripCount() + 1); 1543 mCurrentFaceOrLineCount += (currentTristripVertexCount - 2); 1544 } 1545 else 1546 { 1547 tristrips->getPositionIndices().erase(currentTristripVertexCount); 1548 tristrips->getNormalIndices().erase(currentTristripVertexCount); 1549 1550 const COLLADAFW::IndexListArray& colorIndicesArray = tristrips->getColorIndicesArray (); 1551 for ( size_t i=0; i<colorIndicesArray.getCount (); ++i ) 1552 tristrips->getColorIndices(i)->getIndices().erase(currentTristripVertexCount); 1553 1554 const COLLADAFW::IndexListArray& uvCoordIndicesArray = tristrips->getUVCoordIndicesArray (); 1555 for ( size_t i=0; i<uvCoordIndicesArray.getCount (); ++i ) 1556 tristrips->getUVCoordIndices(i)->getIndices ().erase(currentTristripVertexCount); 1557 } 1558 mCurrentLastPrimitiveVertexCount = mCurrentVertexCount; 1559 } 1560 } 1561 break; 1562 case LINESTRIPS: 1563 { 1564 int currentLinestripVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount; 1565 if ( currentLinestripVertexCount > 0 ) 1566 { 1567 COLLADAFW::Linestrips* linestrips = (COLLADAFW::Linestrips*) mCurrentMeshPrimitive; 1568 if ( currentLinestripVertexCount >= 2 ) 1569 { 1570 COLLADAFW::Tristrips::VertexCountArray& vertexCountArray = linestrips->getGroupedVerticesVertexCountArray(); 1571 vertexCountArray.append(currentLinestripVertexCount); 1572 linestrips->setLinestripCount(linestrips->getLinestripCount() + 1); 1573 mCurrentFaceOrLineCount += (currentLinestripVertexCount - 1); 1574 } 1575 else 1576 { 1577 linestrips->getPositionIndices().erase(currentLinestripVertexCount); 1578 linestrips->getNormalIndices().erase(currentLinestripVertexCount); 1579 1580 const COLLADAFW::IndexListArray& colorIndicesArray = linestrips->getColorIndicesArray (); 1581 for ( size_t i=0; i<colorIndicesArray.getCount (); ++i ) 1582 linestrips->getColorIndices(i)->getIndices().erase(currentLinestripVertexCount); 1583 1584 const COLLADAFW::IndexListArray& uvCoordIndicesArray = linestrips->getUVCoordIndicesArray (); 1585 for ( size_t i=0; i<uvCoordIndicesArray.getCount (); ++i ) 1586 linestrips->getUVCoordIndices(i)->getIndices ().erase(currentLinestripVertexCount); 1587 } 1588 mCurrentLastPrimitiveVertexCount = mCurrentVertexCount; 1589 } 1590 } 1591 break; 1592 case POLYLIST: 1593 { 1594 1595 } 1596 break; 1597 case POLYGONS: 1598 { 1599 int currentFaceVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount; 1600 if ( currentFaceVertexCount > 0 ) 1601 { 1602 COLLADAFW::Polygons* polygons = (COLLADAFW::Polygons*) mCurrentMeshPrimitive; 1603 COLLADAFW::Polygons::VertexCountArray& vertexCountArray = polygons->getGroupedVerticesVertexCountArray(); 1604 vertexCountArray.append(currentFaceVertexCount); 1605 mCurrentLastPrimitiveVertexCount = mCurrentVertexCount; 1606 mCurrentFaceOrLineCount++; 1607 } 1608 } 1609 break; 1610 case POLYGONS_HOLE: 1611 { 1612 int currentPolygonVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount; 1613 if ( currentPolygonVertexCount > 0 ) 1614 { 1615 COLLADAFW::Polygons* polygons = (COLLADAFW::Polygons*) mCurrentMeshPrimitive; 1616 COLLADAFW::Polygons::VertexCountArray& vertexCountArray = polygons->getGroupedVerticesVertexCountArray(); 1617 vertexCountArray.append(currentPolygonVertexCount); 1618 mCurrentLastPrimitiveVertexCount = mCurrentVertexCount; 1619 mCurrentFaceOrLineCount++; 1620 mCurrentPhHasEmptyP = false; 1621 } 1622 else 1623 { 1624 mCurrentPhHasEmptyP = true; 1625 } 1626 } 1627 break; 1628 case NONE: 1629 return false; 1630 } 1631 return true; 1632 } 1633 1634 //------------------------------ data__p(const unsigned long long * data,size_t length)1635 bool MeshLoader::data__p( const unsigned long long* data, size_t length ) 1636 { 1637 return writePrimitiveIndices(data, length); 1638 } 1639 1640 1641 } // namespace COLLADASaxFWL 1642