- Timestamp:
- 02/11/10 12:56:43 (3 years ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
OpenSceneGraph/trunk/src/osgPlugins/3ds/WriterNodeVisitor.cpp
r10938 r11056 92 92 93 93 /// Tests if the given string is a path supported by 3DS format (8.3, 63 chars max). 94 bool is3DSpath(const std::string & s ) {94 bool is3DSpath(const std::string & s, bool extendedFilePaths) { 95 95 unsigned int len = s.length(); 96 96 if (len >= 64 || len == 0) return false; 97 if (extendedFilePaths) return true; // Extended paths are simply those that fits the 64 bytes buffer! 97 98 98 99 unsigned int tokenBegin = 0; … … 146 147 triangle.t3 = i3; 147 148 triangle.material = _material; 148 _listTriangles.push_back(std:: make_pair(triangle, _drawable_n));149 _listTriangles.push_back(std::pair<Triangle, unsigned int>(triangle, _drawable_n)); 149 150 } 150 151 virtual void begin(GLenum mode) … … 335 336 //break; 336 337 default: 337 osg::notify(osg::WARN) << " WriterNodeVisitor :: can't handle mode " << mode << std::endl;338 osg::notify(osg::WARN) << "3DS WriterNodeVisitor: can't handle mode " << mode << std::endl; 338 339 break; 339 340 } … … 400 401 401 402 402 std::string 403 getPathRelative(const std::string & srcBad, 404 const std::string & dstBad) 405 { 406 if(srcBad.empty()) 407 return osgDB::getSimpleFileName(dstBad); 408 const std::string & src = osgDB::convertFileNameToNativeStyle(srcBad); 409 const std::string & dst = osgDB::convertFileNameToNativeStyle(dstBad); 410 std::string::const_iterator itDst = dst.begin(); 411 std::string::const_iterator itSrc = src.begin(); 412 413 std::string result = ""; 414 415 while(itDst != dst.end()) 416 { 417 if (itSrc != src.end() && *itDst == *itSrc) 418 ++itSrc; 419 else if (!result.empty() || *itDst != '\\') 420 result += *itDst; 421 ++itDst; 422 } 423 if (itSrc != src.end()) 424 result = osgDB::getSimpleFileName(dst); 425 return result; 403 // If 'to' is in a subdirectory of 'from' then this function returns the 404 // subpath. Otherwise it just returns the file name. 405 // (Same as in FBX plugin) 406 std::string getPathRelative(const std::string& from/*directory*/, 407 const std::string& to/*file path*/) 408 { 409 410 std::string::size_type slash = to.find_last_of('/'); 411 std::string::size_type backslash = to.find_last_of('\\'); 412 if (slash == std::string::npos) 413 { 414 if (backslash == std::string::npos) return to; 415 slash = backslash; 416 } 417 else if (backslash != std::string::npos && backslash > slash) 418 { 419 slash = backslash; 420 } 421 422 if (from.empty() || from.length() > to.length()) 423 return osgDB::getSimpleFileName(to); 424 425 std::string::const_iterator itTo = to.begin(); 426 for (std::string::const_iterator itFrom = from.begin(); 427 itFrom != from.end(); ++itFrom, ++itTo) 428 { 429 char a = tolower(*itFrom), b = tolower(*itTo); 430 if (a == '\\') a = '/'; 431 if (b == '\\') b = '/'; 432 if (a != b || itTo == to.begin() + slash + 1) 433 { 434 return osgDB::getSimpleFileName(to); 435 } 436 } 437 438 while (itTo != to.end() && (*itTo == '\\' || *itTo == '/')) 439 { 440 ++itTo; 441 } 442 443 return std::string(itTo, to.end()); 426 444 } 427 445 428 446 /// Converts an extension to a 3-letters long one equivalent. 429 std::string convertExt(const std::string & path) 430 { 447 std::string convertExt(const std::string & path, bool extendedFilePaths) 448 { 449 if (extendedFilePaths) return path; // Extensions are not truncated for extended filenames 450 431 451 std::string ext = osgDB::getFileExtensionIncludingDot(path); 432 452 if (ext == ".tiff") ext = ".tif"; … … 435 455 return osgDB::getNameLessExtension(path) + ext; 436 456 } 457 458 459 WriterNodeVisitor::WriterNodeVisitor(Lib3dsFile * file3ds, const std::string & fileName, 460 const osgDB::ReaderWriter::Options* options, 461 const std::string & srcDirectory) : 462 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), 463 _suceedLastApply(true), 464 _srcDirectory(srcDirectory), 465 file3ds(file3ds), 466 _currentStateSet(new osg::StateSet()), 467 _lastMaterialIndex(0), 468 _lastMeshIndex(0), 469 _cur3dsNode(NULL), 470 options(options), 471 _imageCount(0), 472 _extendedFilePaths(false) 473 { 474 if (!fileName.empty()) 475 _directory = options->getDatabasePathList().empty() ? osgDB::getFilePath(fileName) : options->getDatabasePathList().front(); 476 477 if (options) { 478 std::istringstream iss(options->getOptionString()); 479 std::string opt; 480 while (iss >> opt) 481 { 482 if (opt == "extended3dsFilePaths" || opt == "extended3DSFilePaths") 483 _extendedFilePaths = true; 484 } 485 } 486 } 487 437 488 438 489 void WriterNodeVisitor::writeMaterials() … … 471 522 path = getPathRelative(_srcDirectory, mat.image->getFileName()); 472 523 } 473 path = convertExt(path );474 475 if(!is3DSpath(path )) {524 path = convertExt(path, _extendedFilePaths); 525 526 if(!is3DSpath(path, _extendedFilePaths)) { 476 527 path = getUniqueName(path, "", true); 477 528 //path = osgDB::getSimpleFileName(path); … … 483 534 484 535 //if (mat.image->valid()) osgDB::writeImageFile(*(mat.image), path); 485 osgDB::writeImageFile(*(mat.image), path); 536 if(_imageSet.find(mat.image.get()) == _imageSet.end()) 537 { 538 _imageSet.insert(mat.image.get()); 539 osgDB::writeImageFile(*(mat.image), path); 540 } 486 541 if (mat.texture_transparency) tex.flags |= LIB3DS_TEXTURE_ALPHA_SOURCE; 487 542 if (mat.texture_no_tile) tex.flags |= LIB3DS_TEXTURE_NO_TILE; … … 498 553 499 554 std::string WriterNodeVisitor::getUniqueName(const std::string& _defaultValue, const std::string & _defaultPrefix, bool nameIsPath) { 500 if (_defaultPrefix.length()>=4) throw "Default prefix is too long"; // Arbitrarily defined to 3 chars. You can modify this, but you may have to change the code so that finding a number is okay, even when changing the default prefix length. 555 static const unsigned int MAX_PREFIX_LEGNTH = 4; 556 if (_defaultPrefix.length()>MAX_PREFIX_LEGNTH) throw "Default prefix is too long"; // Arbitrarily defined to 4 chars. 501 557 502 558 // Tests if default name is valid and unique 503 559 bool defaultIs83 = is83(_defaultValue); 504 bool defaultIsValid = nameIsPath ? is3DSpath(_defaultValue ) : defaultIs83;560 bool defaultIsValid = nameIsPath ? is3DSpath(_defaultValue, _extendedFilePaths) : defaultIs83; 505 561 if (defaultIsValid && _nameMap.find(_defaultValue) == _nameMap.end()) { 506 562 _nameMap.insert(_defaultValue); … … 509 565 510 566 // Handling of paths is not well done yet. Defaulting to something very simple. 511 // We should actually ensure each component is 8 chars long, and final filename is 8.3, and total is <64 chars .567 // We should actually ensure each component is 8 chars long, and final filename is 8.3, and total is <64 chars, or simply ensure total length for extended 3DS paths. 512 568 std::string defaultValue(nameIsPath ? osgDB::getSimpleFileName(_defaultValue) : _defaultValue); 513 569 std::string ext(nameIsPath ? osgDB::getFileExtensionIncludingDot(_defaultValue).substr(0, std::min<unsigned int>(_defaultValue.size(), 4)) : ""); // 4 chars = dot + 3 chars 570 if (ext == ".") ext = ""; 514 571 515 572 std::string defaultPrefix(_defaultPrefix.empty() ? "_" : _defaultPrefix); … … 517 574 unsigned int max_val = 0; 518 575 std::string truncDefaultValue = ""; 519 for (unsigned int i = 0; i < std::min<unsigned int>(defaultValue.size(), 4); ++i)576 for (unsigned int i = 0; i < std::min<unsigned int>(defaultValue.size(), MAX_PREFIX_LEGNTH); ++i) 520 577 { 521 578 if (defaultValue[i] == '.') … … 526 583 } 527 584 if (truncDefaultValue.empty()) 528 truncDefaultValue = defaultValue.substr(0, std::min<unsigned int>(defaultValue.size(), 4)); 585 truncDefaultValue = defaultValue.substr(0, std::min<unsigned int>(defaultValue.size(), MAX_PREFIX_LEGNTH)); 586 assert(truncDefaultValue.size() <= MAX_PREFIX_LEGNTH); 529 587 std::map<std::string, unsigned int>::iterator pairPrefix; 588 589 // TODO - Handle the case of extended 3DS paths and allow more than 8 chars 530 590 defaultIs83 = is83(truncDefaultValue); 531 591 if (defaultIs83) 532 592 { 533 max_val = static_cast<unsigned int>(pow(10., 8. - truncDefaultValue.length() - 1)) -1; // defaultPrefix.length()-1 because we add an underscore ("_")593 max_val = static_cast<unsigned int>(pow(10., 8. - truncDefaultValue.length())) -1; 534 594 pairPrefix = _mapPrefix.find(truncDefaultValue); 535 595 } 536 596 537 if (defaultIs83 && ( _mapPrefix.end() == pairPrefix|| pairPrefix->second <= max_val))597 if (defaultIs83 && (pairPrefix == _mapPrefix.end() || pairPrefix->second <= max_val)) 538 598 { 539 599 defaultPrefix = truncDefaultValue; … … 541 601 else 542 602 { 543 max_val = static_cast<unsigned int>(pow(10., 8. - defaultPrefix.length() - 1)) - 1; // defaultPrefix.length()-1 because we add an underscore ("_")603 max_val = static_cast<unsigned int>(pow(10., 8. - defaultPrefix.length())) -1; 544 604 pairPrefix = _mapPrefix.find(defaultPrefix); 545 605 } 546 606 547 607 unsigned int searchStart = 0; 548 if (pairPrefix != _mapPrefix.end()) 608 if (pairPrefix != _mapPrefix.end()) { 549 609 searchStart = pairPrefix->second; 610 } 550 611 551 612 for(unsigned int i = searchStart; i <= max_val; ++i) { 552 613 std::stringstream ss; 553 ss << defaultPrefix << "_" <<i;614 ss << defaultPrefix << i; 554 615 const std::string & res = ss.str(); 555 616 if (_nameMap.find(res) == _nameMap.end()) { 556 if (pairPrefix != _mapPrefix.end()) 557 { 617 if (pairPrefix != _mapPrefix.end()) { 558 618 pairPrefix->second = i + 1; 559 } 560 else 561 { 562 _mapPrefix.insert(std::make_pair(defaultPrefix, i + 1)); 619 } else { 620 _mapPrefix.insert(std::pair<std::string, unsigned int>(defaultPrefix, i + 1)); 563 621 } 564 622 _nameMap.insert(res); … … 566 624 } 567 625 } 568 if (defaultPrefix == "_") _lastGeneratedNumberedName = max_val; 626 627 // Failed finding a name 628 // Try with a shorter prefix if possible 629 if (defaultPrefix.length()>1) return getUniqueName(_defaultValue, defaultPrefix.substr(0, defaultPrefix.length()-1), nameIsPath); 630 // Try with default prefix if not arleady done 631 if (defaultPrefix != std::string("_")) return getUniqueName(_defaultValue, "_", nameIsPath); 569 632 throw "No more names available! Is default prefix too long?"; 570 633 } … … 603 666 unsigned int drawable_n) 604 667 { 605 MapIndices::iterator itIndex = index_vert.find(std:: make_pair(index, drawable_n));668 MapIndices::iterator itIndex = index_vert.find(std::pair<unsigned int, unsigned int>(index, drawable_n)); 606 669 if (itIndex == index_vert.end()) { 607 670 unsigned int indexMesh = index_vert.size(); 608 index_vert.insert(std::make_pair(std:: make_pair(index, drawable_n), indexMesh));671 index_vert.insert(std::make_pair(std::pair<unsigned int, unsigned int>(index, drawable_n), indexMesh)); 609 672 return indexMesh; 610 673 } … … 693 756 ((nbVertices) >= MAX_VERTICES-2)) 694 757 { 695 osg::notify(osg:: ALWAYS) << "Sorting elements..." << std::endl;758 osg::notify(osg::INFO) << "Sorting elements..." << std::endl; 696 759 WriterCompareTriangle cmp(geo, nbVertices); 697 760 std::sort(listTriangles.begin(), listTriangles.end(), cmp);
