Changeset 11194

Show
Ignore:
Timestamp:
03/10/10 17:05:52 (4 years ago)
Author:
robert
Message:

From Sukender, "I've fixed positions for 3DS writer. Points in 3DS must be in world coordinates and I added what was missing.
And by refactoring a bit of code, I may have fixed some StateSets? related bugs (was ignoring StateSets? for osg::Groups).
I also added support for Billboard's points, so now "osgconv lz.osg lz.3ds" has an acceptable output. However, there is no rotation depending on billboards' axis, hence the notice "Warning: 3DS writer is incomplete for Billboards (rotation not implemented).". You may want to remove this notice (or lower the notify severity) if you feel 3DS doesn't have to handle such rotations.
The attached archive contains 3 files from 3DS plugin, against rev. 11162.

Please note there is still the textures issue for cow.osg. I guess it's because it's not a "flat, dummy and standard" texture in slot 0... That is to say the only thing the writer can handle at the moment. I guess I won't address this soon.
"
and

"I've detected and fixed another bug in 3DS writer: support for automatic splitting of meshes having >65k faces/points was buggy (was deleting faces).
Here is my four 3DS modified files (in a ZIP), against rev. 11193, including previous fixes AND Stephan's fix about relative filenames."

Location:
OpenSceneGraph/trunk/src/osgPlugins/3ds
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/src/osgPlugins/3ds/ReaderWriter3DS.cpp

    r11180 r11194  
    903903    if (texture && *(texture->name)) 
    904904    { 
    905         osg::notify(osg::NOTICE)<<"texture->name="<<texture->name<<", _directory="<<_directory<<std::endl; 
     905        osg::notify(osg::INFO)<<"texture->name="<<texture->name<<", _directory="<<_directory<<std::endl; 
    906906 
    907907        std::string fileName = osgDB::findFileInDirectory(texture->name,_directory,osgDB::CASE_INSENSITIVE); 
     
    910910            // file not found in .3ds file's directory, so we'll look in the datafile path list. 
    911911            fileName = osgDB::findDataFile(texture->name,options, osgDB::CASE_INSENSITIVE); 
    912             osg::notify(osg::NOTICE)<<"texture->name="<<texture->name<<", _directory="<<_directory<<std::endl; 
     912            osg::notify(osg::INFO)<<"texture->name="<<texture->name<<", _directory="<<_directory<<std::endl; 
    913913        } 
    914914 
  • OpenSceneGraph/trunk/src/osgPlugins/3ds/WriterCompareTriangle.cpp

    r11056 r11194  
    4949    unsigned int nbVerticesZ = static_cast<unsigned int>( (nbVertices * k) / (length.x() * length.y()) ); 
    5050 
    51     setMaxMin (nbVerticesX, nbVerticesY, nbVerticesZ); // This function prevent from cut scene in too many blocs 
     51    setMaxMin (nbVerticesX, nbVerticesY, nbVerticesZ); // This function prevent from cutting the scene in too many blocs 
    5252 
    53     osg::notify(osg::ALWAYS) << "Cutting x by " << nbVerticesX << std::endl 
     53    osg::notify(osg::INFO) 
     54        << "Cutting x by " << nbVerticesX << std::endl 
    5455        << "Cutting y by " << nbVerticesY << std::endl 
    5556        << "Cutting z by " << nbVerticesZ << std::endl; 
    5657 
    57     osg::BoundingBox::value_type blocX = length.x() / nbVerticesX; //This 3 lines set the size of a bloc in x, y and z 
     58    osg::BoundingBox::value_type blocX = length.x() / nbVerticesX;    // These 3 lines set the size of a bloc in x, y and z 
    5859    osg::BoundingBox::value_type blocY = length.y() / nbVerticesY; 
    5960    osg::BoundingBox::value_type blocZ = length.z() / nbVerticesZ; 
  • OpenSceneGraph/trunk/src/osgPlugins/3ds/WriterNodeVisitor.cpp

    r11123 r11194  
    1616#include <osg/io_utils> 
    1717#include <osg/CullFace> 
     18#include <osg/Billboard> 
    1819#include <osgDB/WriteFile> 
    1920 
     
    659660 
    660661/**  
    661 *  Add a vertice to the index and link him with the Triangle index and the drawable. 
     662*  Add a vertice to the index and link it with the Triangle index and the drawable. 
    662663*  \param index_vert is the map where the vertice are stored. 
    663664*  \param index is the indice of the vertice's position in the vec3. 
     
    681682 
    682683void  
    683 WriterNodeVisitor::buildMesh(osg::Geode                  &    geo, 
    684                              MapIndices                  &    index_vert, 
    685                              bool                        texcoords, 
    686                              Lib3dsMesh                  *    mesh) 
     684WriterNodeVisitor::buildMesh(osg::Geode        & geo, 
     685                             const osg::Matrix & mat, 
     686                             MapIndices        & index_vert, 
     687                             bool                texcoords, 
     688                             Lib3dsMesh        * mesh) 
    687689{ 
    688690    osg::notify(osg::DEBUG_INFO) << "Building Mesh" << std::endl; 
     
    690692    if (!mesh) throw "Allocation error";        // TODO 
    691693 
     694    // Write points 
     695    assert(index_vert.size() <= MAX_VERTICES); 
    692696    lib3ds_mesh_resize_vertices(mesh, index_vert.size(), texcoords ? 1 : 0, 0); 
    693     // Write points 
    694697 
    695698    for(MapIndices::iterator it = index_vert.begin(); it != index_vert.end();++it) 
     
    700703            throw "Vertex array is not Vec3. Not implemented";        // TODO 
    701704        const osg::Vec3Array & vecs= *static_cast<osg::Vec3Array *>(g->getVertexArray()); 
    702         copyOsgVectorToLib3dsVector(mesh->vertices[it->second], vecs[it->first.first]); 
     705        copyOsgVectorToLib3dsVector(mesh->vertices[it->second], vecs[it->first.first]*mat); 
    703706    } 
    704707 
     
    745748 
    746749void 
    747 WriterNodeVisitor::buildFaces(osg::Geode     &    geo, 
    748                               ListTriangle   &    listTriangles, 
     750WriterNodeVisitor::buildFaces(osg::Geode        & geo, 
     751                              const osg::Matrix & mat, 
     752                              ListTriangle      & listTriangles, 
    749753                              bool                texcoords) 
    750754{ 
    751755    MapIndices index_vert; 
    752     unsigned int nbFace = 0; 
    753756    Lib3dsMesh *mesh = lib3ds_mesh_new( getUniqueName(geo.getName().empty() ? geo.className() : geo.getName(), "geo").c_str() ); 
    754     unsigned int nbTriangles = listTriangles.size(); 
    755  
    756     lib3ds_mesh_resize_faces(mesh, nbTriangles); 
    757  
    758     unsigned int nbVertices = calcVertices(geo); 
    759     if (listTriangles.size() >= MAX_FACES-2 || 
    760        ((nbVertices) >= MAX_VERTICES-2)) 
     757    if (!mesh) throw "Allocation error"; 
     758 
     759    unsigned int nbTrianglesRemaining = listTriangles.size(); 
     760    unsigned int nbVerticesRemaining  = calcVertices(geo); 
     761 
     762    lib3ds_mesh_resize_faces   (mesh, osg::minimum(nbTrianglesRemaining, MAX_FACES)); 
     763    lib3ds_mesh_resize_vertices(mesh, osg::minimum(nbVerticesRemaining,  MAX_VERTICES), texcoords ? 0 : 1, 0);        // Not mandatory but will allocate once a big block 
     764 
     765    // Test if the mesh will be split and needs sorting 
     766    if (nbVerticesRemaining >= MAX_VERTICES || nbTrianglesRemaining >= MAX_FACES) 
    761767    { 
    762768        osg::notify(osg::INFO) << "Sorting elements..." << std::endl; 
    763         WriterCompareTriangle cmp(geo, nbVertices); 
     769        WriterCompareTriangle cmp(geo, nbVerticesRemaining); 
    764770        std::sort(listTriangles.begin(), listTriangles.end(), cmp); 
    765771    } 
    766772 
     773    unsigned int numFace = 0;        // Current face index 
    767774    for (ListTriangle::iterator it = listTriangles.begin(); it != listTriangles.end(); ++it) //Go through the triangle list to define meshs 
    768775    { 
    769         // Using -2 due to the fact that we treat 3 faces in one time (=the algorithm may overrun the limit by 2). 
    770         if ((index_vert.size() >= MAX_VERTICES-2 ||        // If mesh is full 
    771             nbFace >= MAX_FACES-2)) 
    772         { 
    773             // Finnishing mesh 
    774             lib3ds_mesh_resize_faces(mesh, nbFace); 
    775             buildMesh(geo, index_vert, texcoords, mesh); 
    776  
    777             // Creating a new mesh 
     776        // Test if the mesh will be full after adding a face 
     777        if (index_vert.size()+3 >= MAX_VERTICES || numFace+1 >= MAX_FACES) 
     778        { 
     779            // Finnish mesh 
     780            lib3ds_mesh_resize_faces   (mesh, numFace); 
     781            //lib3ds_mesh_resize_vertices() will be called in buildMesh() 
     782            buildMesh(geo, mat, index_vert, texcoords, mesh); 
     783 
     784            // "Reset" values and start over a new mesh 
    778785            index_vert.clear(); 
     786            nbTrianglesRemaining -= numFace; 
     787            numFace = 0; 
     788            // We can't call a thing like "nbVerticesRemaining -= ...;" because points may be used multiple times. 
     789            // [Sukender: An optimisation here would take too much time I think.] 
     790 
    779791            mesh = lib3ds_mesh_new( getUniqueName(geo.getName().empty() ? geo.className() : geo.getName(), "geo").c_str()); 
    780             nbTriangles -= nbFace; 
    781             nbFace = 0; 
    782             lib3ds_mesh_resize_faces(mesh, nbTriangles); 
    783         } 
    784         Lib3dsFace & face = mesh->faces[nbFace++]; 
     792            if (!mesh) throw "Allocation error"; 
     793            lib3ds_mesh_resize_faces   (mesh, osg::minimum(nbTrianglesRemaining, MAX_FACES)); 
     794            lib3ds_mesh_resize_vertices(mesh, osg::minimum(nbVerticesRemaining,  MAX_VERTICES), texcoords ? 0 : 1, 0);        // Not mandatory but will allocate once a big block 
     795        } 
     796        Lib3dsFace & face = mesh->faces[numFace++]; 
    785797        face.index[0] = getMeshIndexForGeometryIndex(index_vert, it->first.t1, it->second); 
    786798        face.index[1] = getMeshIndexForGeometryIndex(index_vert, it->first.t2, it->second); 
     
    788800        face.material = it->first.material; 
    789801    } 
    790     buildMesh(geo, index_vert, texcoords, mesh); //When a Mesh is completed without restriction of vertices number 
     802    buildMesh(geo, mat, index_vert, texcoords, mesh); //When a Mesh is completed without restriction of vertices number 
    791803} 
    792804 
     
    841853} 
    842854 
    843 void WriterNodeVisitor::apply( osg::Geode &node ) 
    844 { 
     855void WriterNodeVisitor::apply( osg::Geode &node ) { 
    845856    pushStateSet(node.getStateSet()); 
    846857    //_nameStack.push_back(node.getName()); 
    847     //osg::Matrix m = osg::computeLocalToWorld(getNodePath()); 
    848858    unsigned int count = node.getNumDrawables(); 
    849859    ListTriangle listTriangles; 
     
    861871    if (count > 0) 
    862872    { 
    863         buildFaces(node, listTriangles, texcoords); 
     873        osg::Matrix mat( osg::computeLocalToWorld(getNodePath()) ); 
     874        buildFaces(node, mat, listTriangles, texcoords); 
    864875    } 
    865876    popStateSet(node.getStateSet()); 
     
    869880} 
    870881 
    871 void WriterNodeVisitor::apply(osg::Group &node) 
    872 { 
     882void WriterNodeVisitor::apply( osg::Billboard &node ) { 
     883    // TODO Does not handle Billboards' points yet 
     884 
     885    pushStateSet(node.getStateSet()); 
    873886    Lib3dsMeshInstanceNode * parent = _cur3dsNode; 
    874     Lib3dsMeshInstanceNode * node3ds = lib3ds_node_new_mesh_instance(NULL, getUniqueName(node.getName().empty() ? node.className() : getFileName(node.getName()), "grp").c_str(), NULL, NULL, NULL); 
    875     lib3ds_file_append_node(file3ds, reinterpret_cast<Lib3dsNode*>(node3ds), reinterpret_cast<Lib3dsNode*>(parent)); 
    876     _cur3dsNode = node3ds; 
     887 
     888    unsigned int count = node.getNumDrawables(); 
     889    ListTriangle listTriangles; 
     890    bool texcoords = false; 
     891    osg::notify(osg::NOTICE) << "Warning: 3DS writer is incomplete for Billboards (rotation not implemented)." << std::endl; 
     892    osg::Matrix m( osg::computeLocalToWorld(getNodePath()) ); 
     893    for ( unsigned int i = 0; i < count; i++ ) 
     894    { 
     895        osg::Geometry *g = node.getDrawable( i )->asGeometry(); 
     896        if ( g != NULL ) 
     897        { 
     898            listTriangles.clear(); 
     899            _cur3dsNode = parent; 
     900 
     901            pushStateSet(g->getStateSet()); 
     902            createListTriangle(g, listTriangles, texcoords, i); 
     903            popStateSet(g->getStateSet()); 
     904 
     905            osg::Matrix currentBillBoardMat(osg::Matrix::translate(node.getPosition(i)) * m);        // TODO handle rotation 
     906            apply3DSMatrixNode(node, currentBillBoardMat, "bil");        // Add a 3DS matrix node 
     907            buildFaces(node, currentBillBoardMat, listTriangles, texcoords); 
     908        } 
     909    } 
     910 
    877911    if (suceedLastApply()) 
    878912        traverse(node); 
    879913    _cur3dsNode = parent; 
     914    popStateSet(node.getStateSet()); 
     915} 
     916 
     917 
     918 
     919void WriterNodeVisitor::apply(osg::Group &node) 
     920{ 
     921    pushStateSet(node.getStateSet()); 
     922    Lib3dsMeshInstanceNode * parent = _cur3dsNode; 
     923    apply3DSMatrixNode(node, osg::computeLocalToWorld(getNodePath()), "grp"); 
     924    if (suceedLastApply()) 
     925        traverse(node); 
     926    _cur3dsNode = parent; 
     927    popStateSet(node.getStateSet()); 
    880928} 
    881929 
    882930void WriterNodeVisitor::apply(osg::MatrixTransform &node) 
    883931{ 
     932    pushStateSet(node.getStateSet()); 
    884933    Lib3dsMeshInstanceNode * parent = _cur3dsNode; 
    885  
    886     const osg::Matrix & m = node.getMatrix(); 
    887     //const osg::Matrix m( osg::computeWorldToLocal(getNodePath()) );        // [NEEDS TESTING!] 3DS matrices always contain world to local transformation (not local transform; ie. from parent) 
     934    apply3DSMatrixNode(node, osg::computeLocalToWorld(getNodePath()), "mtx"); 
     935    if (suceedLastApply()) 
     936        traverse(node); 
     937    _cur3dsNode = parent; 
     938    popStateSet(node.getStateSet()); 
     939} 
     940 
     941void WriterNodeVisitor::apply3DSMatrixNode(osg::Node &node, const osg::Matrix & m, const char * const prefix) 
     942{ 
     943    Lib3dsMeshInstanceNode * parent = _cur3dsNode; 
     944 
     945    //const osg::Matrix & m = node.getMatrix(); 
     946    //const osg::Matrix m( osg::computeLocalToWorld(nodePath) );        // [NEEDS TESTING!] 3DS matrices always contain world to local transformation (not local transform; ie. from parent) 
    888947 
    889948    // Transform data used to be given to lib3ds_node_new_mesh_instance(), but it seems buggy (pivot problem? bug in conversion?). 
     
    898957    copyOsgQuatToLib3dsQuat(rot, osgRot); 
    899958    Lib3dsMeshInstanceNode * node3ds = lib3ds_node_new_mesh_instance 
    900         (NULL, getUniqueName(node.getName().empty() ? node.className() : node.getName(), "mtx").c_str(), pos, scl, rot); 
     959        (NULL, getUniqueName(node.getName().empty() ? node.className() : node.getName(), prefix).c_str(), pos, scl, rot); 
    901960 
    902961    //// Create a mesh instance with no transform and then copy the matrix (doesn't work) 
     
    907966    lib3ds_file_append_node(file3ds, reinterpret_cast<Lib3dsNode*>(node3ds), reinterpret_cast<Lib3dsNode*>(parent)); 
    908967    _cur3dsNode = node3ds; 
    909     if (suceedLastApply()) 
    910         traverse(node); 
    911     _cur3dsNode = parent; 
    912 } 
     968} 
  • OpenSceneGraph/trunk/src/osgPlugins/3ds/WriterNodeVisitor.h

    r11056 r11194  
    6262        void        failedApply(); 
    6363        virtual void apply(osg::Geode &node); 
     64        virtual void apply(osg::Billboard &node); 
    6465 
    6566        virtual void apply(osg::Group &node); 
     
    135136        *  Fill the faces field of the mesh and call buildMesh(). 
    136137        *  \param geo is the geode who contain vertice and faces. 
     138        *  \param mat Local to world matrix applied to the geode 
    137139        *  \param listTriangles contain all the meshs faces. 
    138140        *  \param texcoords tell us if we have to treat texture coord. 
    139141        */ 
    140         void buildFaces(osg::Geode & geo, ListTriangle & listTriangles, bool texcoords); 
     142        void buildFaces(osg::Geode & geo, const osg::Matrix & mat, ListTriangle & listTriangles, bool texcoords); 
    141143 
    142144        /**  
     
    150152        *  Build a mesh 
    151153        *  \param geo is the geode who contain vertice and faces 
     154        *  \param mat Local to world matrix applied to the geode 
    152155        *  \param index_vert is the index used to build the new mesh 
    153156        *  \param texcoords tell us if we have to treat texture coord 
    154157        *  \param mesh is the mesh with faces filled 
    155         *  \return the place of the box in the vector. 
    156158        *  \sa See cutScene() about the definition of the boxes for faces sorting. 
    157159        */ 
    158160        void 
    159         buildMesh(osg::Geode        &    geo,  
    160                   MapIndices        &    index_vert,  
    161                   bool                   texcoords,         
     161        buildMesh(osg::Geode        &    geo, 
     162                  const osg::Matrix &    mat, 
     163                  MapIndices        &    index_vert, 
     164                  bool                   texcoords,        
    162165                  Lib3dsMesh             *mesh); 
    163166 
     
    193196        typedef std::map< osg::ref_ptr<osg::StateSet>, Material, CompareStateSet> MaterialMap; 
    194197 
     198        void apply3DSMatrixNode(osg::Node &node, const osg::Matrix & m, const char * const prefix); 
    195199 
    196200        bool                                _suceedLastApply;