- Timestamp:
- 03/11/10 17:53:35 (3 years ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
OpenSceneGraph/trunk/src/osgPlugins/3ds/WriterNodeVisitor.cpp
r11194 r11203 26 26 void copyOsgMatrixToLib3dsMatrix(Lib3dsMatrix lib3ds_matrix, const osg::Matrix& osg_matrix) 27 27 { 28 for(int row=0; row<4; ++row) { 28 for(int row=0; row<4; ++row) 29 { 29 30 lib3ds_matrix[row][0] = osg_matrix.ptr()[row*4+0]; 30 31 lib3ds_matrix[row][1] = osg_matrix.ptr()[row*4+1]; … … 34 35 } 35 36 36 inline void copyOsgVectorToLib3dsVector(Lib3dsVector lib3ds_vector, const osg::Vec3f& osg_vector) { 37 inline void copyOsgVectorToLib3dsVector(Lib3dsVector lib3ds_vector, const osg::Vec3f& osg_vector) 38 { 37 39 lib3ds_vector[0] = osg_vector[0]; 38 40 lib3ds_vector[1] = osg_vector[1]; 39 41 lib3ds_vector[2] = osg_vector[2]; 40 42 } 41 inline void copyOsgVectorToLib3dsVector(Lib3dsVector lib3ds_vector, const osg::Vec3d& osg_vector) { 43 inline void copyOsgVectorToLib3dsVector(Lib3dsVector lib3ds_vector, const osg::Vec3d& osg_vector) 44 { 42 45 lib3ds_vector[0] = osg_vector[0]; 43 46 lib3ds_vector[1] = osg_vector[1]; … … 45 48 } 46 49 47 inline void copyOsgColorToLib3dsColor(Lib3dsVector lib3ds_vector, const osg::Vec4f& osg_vector) { 50 inline void copyOsgColorToLib3dsColor(Lib3dsVector lib3ds_vector, const osg::Vec4f& osg_vector) 51 { 48 52 lib3ds_vector[0] = osg_vector[0]; 49 53 lib3ds_vector[1] = osg_vector[1]; 50 54 lib3ds_vector[2] = osg_vector[2]; 51 55 } 52 inline void copyOsgColorToLib3dsColor(Lib3dsVector lib3ds_vector, const osg::Vec4d& osg_vector) { 56 inline void copyOsgColorToLib3dsColor(Lib3dsVector lib3ds_vector, const osg::Vec4d& osg_vector) 57 { 53 58 lib3ds_vector[0] = osg_vector[0]; 54 59 lib3ds_vector[1] = osg_vector[1]; … … 56 61 } 57 62 58 inline void copyOsgQuatToLib3dsQuat(float lib3ds_vector[4], const osg::Quat& osg_quat) { 63 inline void copyOsgQuatToLib3dsQuat(float lib3ds_vector[4], const osg::Quat& osg_quat) 64 { 59 65 //lib3ds_vector[0] = osg_quat[3]; // Not sure 60 66 //lib3ds_vector[1] = osg_quat[0]; … … 70 76 } 71 77 72 std::string getFileName(const std::string & path) { 78 std::string getFileName(const std::string & path) 79 { 73 80 unsigned int slashPos = path.find_last_of("/\\"); 74 81 if (slashPos == std::string::npos) return path; … … 78 85 79 86 /// Checks if a filename (\b not path) is 8.3 (an empty name is never 8.3, and a path is never 8.3). 80 bool is83(const std::string & s) { 87 bool is83(const std::string & s) 88 { 81 89 // 012345678901 82 90 // ABCDEFGH.ABC … … 93 101 94 102 /// Tests if the given string is a path supported by 3DS format (8.3, 63 chars max). 95 bool is3DSpath(const std::string & s, bool extendedFilePaths) { 103 bool is3DSpath(const std::string & s, bool extendedFilePaths) 104 { 96 105 unsigned int len = s.length(); 97 106 if (len >= 64 || len == 0) return false; … … 113 122 114 123 /** writes all primitives of a primitive-set out to a stream, decomposes quads to triangles, line-strips to lines etc */ 115 class PrimitiveIndexWriter : public osg::PrimitiveIndexFunctor { 124 class PrimitiveIndexWriter : public osg::PrimitiveIndexFunctor 125 { 116 126 public: 117 127 PrimitiveIndexWriter(osg::Geometry * geo, … … 341 351 //break; 342 352 default: 343 osg::notify(osg::WARN) << "3DS WriterNodeVisitor: can't handle mode " << mode << std::endl;353 OSG_NOTIFY(osg::WARN) << "3DS WriterNodeVisitor: can't handle mode " << mode << std::endl; 344 354 break; 345 355 } … … 362 372 //static unsigned int s_objmaterial_id = 0; 363 373 //++s_objmaterial_id; 364 if (mat) { 374 if (mat) 375 { 365 376 assert(stateset); 366 377 diffuse = mat->getDiffuse(osg::Material::FRONT); … … 371 382 name = writerNodeVisitor.getUniqueName(mat->getName(),"mat"); 372 383 osg::StateAttribute * attribute = stateset->getAttribute(osg::StateAttribute::CULLFACE); 373 if (!attribute) { 384 if (!attribute) 385 { 374 386 double_sided = true; 375 } else { 387 } 388 else 389 { 376 390 assert(dynamic_cast<osg::CullFace *>(attribute)); 377 391 osg::CullFace::Mode mode = static_cast<osg::CullFace *>(attribute)->getMode(); 378 392 if (mode == osg::CullFace::BACK) double_sided = false; 379 else if (mode == osg::CullFace::FRONT) { 380 osg::notify(osg::WARN) << "3DS Writer: Reversed face (culled FRONT) not supported yet." << std::endl; 393 else if (mode == osg::CullFace::FRONT) 394 { 395 OSG_NOTIFY(osg::WARN) << "3DS Writer: Reversed face (culled FRONT) not supported yet." << std::endl; 381 396 double_sided = false; 382 397 } 383 else { 398 else 399 { 384 400 assert(mode == osg::CullFace::FRONT_AND_BACK); 385 osg::notify(osg::WARN) << "3DS Writer: Invisible face (culled FRONT_AND_BACK) not supported yet." << std::endl;401 OSG_NOTIFY(osg::WARN) << "3DS Writer: Invisible face (culled FRONT_AND_BACK) not supported yet." << std::endl; 386 402 double_sided = false; 387 403 } 388 404 } 389 405 } 390 if (tex) { 406 if (tex) 407 { 391 408 osg::Image* img = tex->getImage(0); 392 409 if(img) … … 398 415 } 399 416 400 if (name.empty()) { 417 if (name.empty()) 418 { 401 419 std::stringstream ss; 402 420 ss << "m" << index; … … 466 484 const std::string & srcDirectory) : 467 485 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), 468 _suc eedLastApply(true),486 _succeeded(true), 469 487 _srcDirectory(srcDirectory), 470 488 file3ds(file3ds), … … 480 498 _directory = options->getDatabasePathList().empty() ? osgDB::getFilePath(fileName) : options->getDatabasePathList().front(); 481 499 482 if (options) { 500 if (options) 501 { 483 502 std::istringstream iss(options->getOptionString()); 484 503 std::string opt; … … 524 543 path = oss.str(); 525 544 } 526 else { 545 else 546 { 527 547 path = getPathRelative(_srcDirectory, mat.image->getFileName()); 528 548 } 529 549 path = convertExt(path, _extendedFilePaths); 530 550 531 if(!is3DSpath(path, _extendedFilePaths)) { 551 if(!is3DSpath(path, _extendedFilePaths)) 552 { 532 553 path = getUniqueName(path, "", true); 533 554 //path = osgDB::getSimpleFileName(path); … … 547 568 if (mat.texture_no_tile) tex.flags |= LIB3DS_TEXTURE_NO_TILE; 548 569 } 549 if (!suc eedLastApply())570 if (!succeeded()) 550 571 return; 551 572 lib3ds_file_insert_material(file3ds, mat3ds, itr->second.index); 552 573 break; // Ugly thing (3) 553 574 } 554 if (!found) throw "Implementation error"; // Ugly thing (4) 555 } 556 } 557 558 559 std::string WriterNodeVisitor::getUniqueName(const std::string& _defaultValue, const std::string & _defaultPrefix, bool nameIsPath) { 560 static const unsigned int MAX_PREFIX_LEGNTH = 4; 561 if (_defaultPrefix.length()>MAX_PREFIX_LEGNTH) throw "Default prefix is too long"; // Arbitrarily defined to 4 chars. 575 assert(found); // Ugly thing (4) - Implementation error if !found 576 } 577 } 578 579 580 std::string WriterNodeVisitor::getUniqueName(const std::string& _defaultValue, const std::string & _defaultPrefix, bool nameIsPath) 581 { 582 static const unsigned int MAX_PREFIX_LEGNTH = 4; // Arbitrarily defined to 4 chars 583 assert(_defaultPrefix.length()<=MAX_PREFIX_LEGNTH); // Default prefix is too long (implementation error) 562 584 563 585 // Tests if default name is valid and unique 564 586 bool defaultIs83 = is83(_defaultValue); 565 587 bool defaultIsValid = nameIsPath ? is3DSpath(_defaultValue, _extendedFilePaths) : defaultIs83; 566 if (defaultIsValid && _nameMap.find(_defaultValue) == _nameMap.end()) { 588 if (defaultIsValid && _nameMap.find(_defaultValue) == _nameMap.end()) 589 { 567 590 _nameMap.insert(_defaultValue); 568 591 return _defaultValue; … … 611 634 612 635 unsigned int searchStart = 0; 613 if (pairPrefix != _mapPrefix.end()) { 636 if (pairPrefix != _mapPrefix.end()) 637 { 614 638 searchStart = pairPrefix->second; 615 639 } 616 640 617 for(unsigned int i = searchStart; i <= max_val; ++i) { 641 for(unsigned int i = searchStart; i <= max_val; ++i) 642 { 618 643 std::stringstream ss; 619 644 ss << defaultPrefix << i; 620 645 const std::string & res = ss.str(); 621 if (_nameMap.find(res) == _nameMap.end()) { 622 if (pairPrefix != _mapPrefix.end()) { 646 if (_nameMap.find(res) == _nameMap.end()) 647 { 648 if (pairPrefix != _mapPrefix.end()) 649 { 623 650 pairPrefix->second = i + 1; 624 } else { 651 } else 652 { 625 653 _mapPrefix.insert(std::pair<std::string, unsigned int>(defaultPrefix, i + 1)); 626 654 } … … 635 663 // Try with default prefix if not arleady done 636 664 if (defaultPrefix != std::string("_")) return getUniqueName(_defaultValue, "_", nameIsPath); 637 throw "No more names available! Is default prefix too long?"; 665 666 // No more names 667 OSG_NOTIFY(osg::FATAL) << "No more names available!" << std::endl; 668 _succeeded = false; 669 return "ERROR"; 638 670 } 639 671 … … 641 673 { 642 674 MaterialMap::const_iterator itr = _materialMap.find(ss); 643 if (itr != _materialMap.end()) { 675 if (itr != _materialMap.end()) 676 { 644 677 assert(itr->second.index>=0); 645 678 return itr->second.index; … … 672 705 { 673 706 MapIndices::iterator itIndex = index_vert.find(std::pair<unsigned int, unsigned int>(index, drawable_n)); 674 if (itIndex == index_vert.end()) { 707 if (itIndex == index_vert.end()) 708 { 675 709 unsigned int indexMesh = index_vert.size(); 676 710 index_vert.insert(std::make_pair(std::pair<unsigned int, unsigned int>(index, drawable_n), indexMesh)); … … 688 722 Lib3dsMesh * mesh) 689 723 { 690 osg::notify(osg::DEBUG_INFO) << "Building Mesh" << std::endl; 691 692 if (!mesh) throw "Allocation error"; // TODO 724 OSG_NOTIFY(osg::DEBUG_INFO) << "Building Mesh" << std::endl; 725 assert(mesh); 693 726 694 727 // Write points … … 701 734 assert(g->getVertexArray()); 702 735 if (g->getVertexArray()->getType() != osg::Array::Vec3ArrayType) 703 throw "Vertex array is not Vec3. Not implemented"; // TODO 736 { 737 // TODO Handle double presision vertices by converting them to float with a warning 738 OSG_NOTIFY(osg::FATAL) << "Vertex array is not Vec3. Not implemented" << std::endl; 739 _succeeded = false; 740 return; 741 } 704 742 const osg::Vec3Array & vecs= *static_cast<osg::Vec3Array *>(g->getVertexArray()); 705 743 copyOsgVectorToLib3dsVector(mesh->vertices[it->second], vecs[it->first.first]*mat); … … 712 750 { 713 751 osg::Geometry *g = geo.getDrawable( it->first.second )->asGeometry(); 714 osg::Array * array = g->getTexCoordArray(0);715 if (array)752 osg::Array * texarray = g->getTexCoordArray(0); 753 if (texarray) 716 754 { 717 755 if (g->getTexCoordArray(0)->getType() != osg::Array::Vec2ArrayType) 718 throw "Texture coords array is not Vec2. Not implemented"; // TODO 719 const osg::Vec2Array & vecs= *static_cast<osg::Vec2Array *>(array); 756 { 757 OSG_NOTIFY(osg::FATAL) << "Texture coords array is not Vec2. Not implemented" << std::endl; 758 _succeeded = false; 759 return; 760 } 761 const osg::Vec2Array & vecs= *static_cast<osg::Vec2Array *>(texarray); 720 762 mesh->texcos[it->second][0] = vecs[it->first.first][0]; 721 763 mesh->texcos[it->second][1] = vecs[it->first.first][1]; … … 739 781 assert(g->getVertexArray()); 740 782 if (g->getVertexArray()->getType() != osg::Array::Vec3ArrayType) 741 throw "Vertex array is not Vec3. Not implemented"; // TODO 783 { 784 // TODO Handle double presision vertices by converting them to float with a warning 785 OSG_NOTIFY(osg::FATAL) << "Vertex array is not Vec3. Not implemented" << std::endl; 786 _succeeded = false; 787 return 0; 788 } 742 789 const osg::Vec3Array & vecs= *static_cast<osg::Vec3Array *>(g->getVertexArray()); 743 790 numVertice += vecs.getNumElements(); … … 753 800 bool texcoords) 754 801 { 755 MapIndices index_vert;756 Lib3dsMesh *mesh = lib3ds_mesh_new( getUniqueName(geo.getName().empty() ? geo.className() : geo.getName(), "geo").c_str() );757 if (!mesh) throw "Allocation error";758 759 802 unsigned int nbTrianglesRemaining = listTriangles.size(); 760 unsigned int nbVerticesRemaining = calcVertices(geo); 803 unsigned int nbVerticesRemaining = calcVertices(geo); // May set _succeded to false 804 if (!succeeded()) return; 805 806 std::string name( getUniqueName(geo.getName().empty() ? geo.className() : geo.getName(), "geo") ); 807 if (!succeeded()) return; 808 Lib3dsMesh *mesh = lib3ds_mesh_new( name.c_str() ); 809 if (!mesh) 810 { 811 OSG_NOTIFY(osg::FATAL) << "Allocation error" << std::endl; 812 _succeeded = false; 813 return; 814 } 761 815 762 816 lib3ds_mesh_resize_faces (mesh, osg::minimum(nbTrianglesRemaining, MAX_FACES)); … … 766 820 if (nbVerticesRemaining >= MAX_VERTICES || nbTrianglesRemaining >= MAX_FACES) 767 821 { 768 osg::notify(osg::INFO) << "Sorting elements..." << std::endl;822 OSG_NOTIFY(osg::INFO) << "Sorting elements..." << std::endl; 769 823 WriterCompareTriangle cmp(geo, nbVerticesRemaining); 770 824 std::sort(listTriangles.begin(), listTriangles.end(), cmp); 771 825 } 772 826 827 MapIndices index_vert; 773 828 unsigned int numFace = 0; // Current face index 774 829 for (ListTriangle::iterator it = listTriangles.begin(); it != listTriangles.end(); ++it) //Go through the triangle list to define meshs … … 780 835 lib3ds_mesh_resize_faces (mesh, numFace); 781 836 //lib3ds_mesh_resize_vertices() will be called in buildMesh() 782 buildMesh(geo, mat, index_vert, texcoords, mesh); 837 buildMesh(geo, mat, index_vert, texcoords, mesh); // May set _succeded to false 838 if (!succeeded()) 839 { 840 lib3ds_mesh_free(mesh); 841 return; 842 } 783 843 784 844 // "Reset" values and start over a new mesh … … 790 850 791 851 mesh = lib3ds_mesh_new( getUniqueName(geo.getName().empty() ? geo.className() : geo.getName(), "geo").c_str()); 792 if (!mesh) throw "Allocation error"; 852 if (!mesh) 853 { 854 OSG_NOTIFY(osg::FATAL) << "Allocation error" << std::endl; 855 _succeeded = false; 856 return; 857 } 793 858 lib3ds_mesh_resize_faces (mesh, osg::minimum(nbTrianglesRemaining, MAX_FACES)); 794 859 lib3ds_mesh_resize_vertices(mesh, osg::minimum(nbVerticesRemaining, MAX_VERTICES), texcoords ? 0 : 1, 0); // Not mandatory but will allocate once a big block … … 800 865 face.material = it->first.material; 801 866 } 802 buildMesh(geo, mat, index_vert, texcoords, mesh); //When a Mesh is completed without restriction of vertices number 867 868 buildMesh(geo, mat, index_vert, texcoords, mesh); // May set _succeded to false 869 if (!succeeded()) 870 { 871 lib3ds_mesh_free(mesh); 872 return; 873 } 803 874 } 804 875 … … 812 883 { 813 884 if (geo->getVertexArray() && geo->getVertexArray()->getType() != osg::Array::Vec3ArrayType) 814 throw "Vertex array is not Vec3. Not implemented"; // TODO 885 { 886 // TODO Handle double presision vertices by converting them to float with a warning 887 OSG_NOTIFY(osg::FATAL) << "Vertex array is not Vec3. Not implemented" << std::endl; 888 _succeeded = false; 889 return; 890 } 815 891 const osg::Vec3Array * vecs = geo->getVertexArray() ? static_cast<osg::Vec3Array *>(geo->getVertexArray()) : NULL; 816 892 if (vecs) … … 819 895 // Texture coords 820 896 if (geo->getTexCoordArray(0) && geo->getTexCoordArray(0)->getType() != osg::Array::Vec2ArrayType) 821 throw "Texture coords array is not Vec2. Not implemented"; // TODO 897 { 898 OSG_NOTIFY(osg::FATAL) << "Texture coords array is not Vec2. Not implemented" << std::endl; 899 _succeeded = false; 900 return; 901 } 822 902 const osg::Vec2Array * texvecs = geo->getTexCoordArray(0) ? static_cast<osg::Vec2Array *>(geo->getTexCoordArray(0)) : NULL; 823 903 if (texvecs) 824 904 { 825 905 unsigned int nb = geo->getTexCoordArray(0)->getNumElements(); 826 if (nb != geo->getVertexArray()->getNumElements()) throw "There are more/less texture coords than vertices!"; 906 if (nb != geo->getVertexArray()->getNumElements()) 907 { 908 OSG_NOTIFY(osg::FATAL) << "There are more/less texture coords than vertices (corrupted geometry)" << std::endl; 909 _succeeded = false; 910 return; 911 } 827 912 texcoords = true; 828 913 } … … 842 927 } 843 928 844 bool WriterNodeVisitor::suceedLastApply() const 845 { 846 return _suceedLastApply; 847 } 848 849 void WriterNodeVisitor::failedApply() 850 { 851 _suceedLastApply = false; 852 osg::notify(osg::NOTICE) << "Error going through node" << std::endl; 853 } 854 855 void WriterNodeVisitor::apply( osg::Geode &node ) { 929 void WriterNodeVisitor::apply( osg::Geode &node ) 930 { 856 931 pushStateSet(node.getStateSet()); 857 932 //_nameStack.push_back(node.getName()); … … 865 940 { 866 941 pushStateSet(g->getStateSet()); 867 createListTriangle(g, listTriangles, texcoords, i); 942 createListTriangle(g, listTriangles, texcoords, i); // May set _succeded to false 868 943 popStateSet(g->getStateSet()); 869 } 870 } 871 if (count > 0) 944 if (!succeeded()) break; 945 } 946 } 947 if (succeeded() && count > 0) 872 948 { 873 949 osg::Matrix mat( osg::computeLocalToWorld(getNodePath()) ); 874 buildFaces(node, mat, listTriangles, texcoords); 950 buildFaces(node, mat, listTriangles, texcoords); // May set _succeded to false 875 951 } 876 952 popStateSet(node.getStateSet()); 877 953 //_nameStack.pop_back(); 878 if (suc eedLastApply())954 if (succeeded()) 879 955 traverse(node); 880 956 } 881 957 882 void WriterNodeVisitor::apply( osg::Billboard &node ) { 958 void WriterNodeVisitor::apply( osg::Billboard &node ) 959 { 883 960 // TODO Does not handle Billboards' points yet 884 961 … … 889 966 ListTriangle listTriangles; 890 967 bool texcoords = false; 891 osg::notify(osg::NOTICE) << "Warning: 3DS writer is incomplete for Billboards (rotation not implemented)." << std::endl;968 OSG_NOTIFY(osg::NOTICE) << "Warning: 3DS writer is incomplete for Billboards (rotation not implemented)." << std::endl; 892 969 osg::Matrix m( osg::computeLocalToWorld(getNodePath()) ); 893 970 for ( unsigned int i = 0; i < count; i++ ) … … 901 978 pushStateSet(g->getStateSet()); 902 979 createListTriangle(g, listTriangles, texcoords, i); 903 popStateSet(g->getStateSet()); 980 popStateSet(g->getStateSet()); // May set _succeded to false 981 if (!succeeded()) break; 904 982 905 983 osg::Matrix currentBillBoardMat(osg::Matrix::translate(node.getPosition(i)) * m); // TODO handle rotation 906 984 apply3DSMatrixNode(node, currentBillBoardMat, "bil"); // Add a 3DS matrix node 907 buildFaces(node, currentBillBoardMat, listTriangles, texcoords); 908 } 909 } 910 911 if (suceedLastApply()) 985 buildFaces(node, currentBillBoardMat, listTriangles, texcoords); // May set _succeded to false 986 if (!succeeded()) break; 987 } 988 } 989 990 if (succeeded()) 912 991 traverse(node); 913 992 _cur3dsNode = parent; … … 922 1001 Lib3dsMeshInstanceNode * parent = _cur3dsNode; 923 1002 apply3DSMatrixNode(node, osg::computeLocalToWorld(getNodePath()), "grp"); 924 if (suc eedLastApply())1003 if (succeeded()) 925 1004 traverse(node); 926 1005 _cur3dsNode = parent; … … 933 1012 Lib3dsMeshInstanceNode * parent = _cur3dsNode; 934 1013 apply3DSMatrixNode(node, osg::computeLocalToWorld(getNodePath()), "mtx"); 935 if (suc eedLastApply())1014 if (succeeded()) 936 1015 traverse(node); 937 1016 _cur3dsNode = parent;
