Show
Ignore:
Timestamp:
08/19/10 18:24:08 (4 years ago)
Author:
robert
Message:

Implemented generation of front, back and bevel geometries to complete the 3d glyphs.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/examples/osgtext3D/osgtext3D.cpp

    r11688 r11721  
    2020#include <osg/Geode> 
    2121#include <osg/Geometry> 
     22#include <osg/TriangleIndexFunctor> 
    2223#include <osg/PositionAttitudeTransform> 
    2324#include <osgUtil/SmoothingVisitor> 
     
    3334extern int main_test(int, char**); 
    3435 
     36 
     37class BevelProfile 
     38{ 
     39    public: 
     40 
     41        typedef std::vector<osg::Vec2> Vertices; 
     42 
     43        BevelProfile() 
     44        { 
     45            flatBevel(); 
     46        } 
     47 
     48        void flatBevel(float width=0.25f) 
     49        { 
     50            _vertices.clear(); 
     51 
     52            if (width>0.5f) width = 0.5f; 
     53 
     54            _vertices.push_back(osg::Vec2(0.0f,0.0f)); 
     55 
     56            _vertices.push_back(osg::Vec2(width,1.0f)); 
     57 
     58            if (width<0.5f) _vertices.push_back(osg::Vec2(1-width,1.0f)); 
     59 
     60            _vertices.push_back(osg::Vec2(1.0f,0.0f)); 
     61        } 
     62 
     63        void roundedBevel(float width=0.5f, unsigned int numSteps=10) 
     64        { 
     65            _vertices.clear(); 
     66 
     67            if (width>0.5f) width = 0.5f; 
     68 
     69            unsigned int i = 0; 
     70            for(; i<=numSteps; ++i) 
     71            { 
     72                float angle = float(osg::PI)*0.5f*(float(i)/float(numSteps)); 
     73                _vertices.push_back( osg::Vec2((1.0f-cosf(angle))*width, sinf(angle)) ); 
     74            } 
     75 
     76            // start the second half one into the curve if the width is half way across 
     77            i = width<0.5f ? 0 : 1; 
     78            for(; i<=numSteps; ++i) 
     79            { 
     80                float angle = float(osg::PI)*0.5f*(float(numSteps-i)/float(numSteps)); 
     81                _vertices.push_back( osg::Vec2(1.0-(1.0f-cosf(angle))*width, sin(angle)) ); 
     82            } 
     83        } 
     84 
     85        void print(std::ostream& fout) 
     86        { 
     87            OSG_NOTICE<<"print bevel"<<std::endl; 
     88            for(Vertices::iterator itr = _vertices.begin(); 
     89                itr != _vertices.end(); 
     90                ++itr) 
     91            { 
     92                OSG_NOTICE<<"  "<<*itr<<std::endl; 
     93            } 
     94        } 
     95 
     96        Vertices& getVertices() { return _vertices; } 
     97 
     98    protected: 
     99 
     100        Vertices _vertices; 
     101}; 
    35102 
    36103class Boundary 
     
    211278 
    212279        // OSG_NOTICE<<"bisector_abcd = "<<bisector_abcd<<", ab_sidevector="<<ab_sidevector<<", b-a="<<b-a<<", scale_factor="<<scale_factor<<std::endl; 
    213  
    214         new_vertex.z() += 5.0f; 
    215280        return new_vertex; 
    216281    } 
     
    336401} 
    337402 
     403osg::Geometry* computeBevelGeometry(osg::Geometry* geometry, BevelProfile& profile, float width) 
     404{ 
     405    if (!geometry) return 0; 
     406 
     407    osg::Vec3Array* orig_vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()); 
     408    if (!orig_vertices) return 0; 
     409 
     410    if (geometry->getNumPrimitiveSets()==0) return 0; 
     411 
     412    osg::Geometry* new_geometry = new osg::Geometry; 
     413 
     414    osg::Vec3Array* new_vertices = new osg::Vec3Array; 
     415    new_geometry->setVertexArray(new_vertices); 
     416 
     417    osg::Vec3 forward(0.0f, 0.0f, -width); 
     418 
     419    for(unsigned int prim_i=0; prim_i<geometry->getNumPrimitiveSets(); ++prim_i) 
     420    { 
     421        osg::DrawElementsUShort* bevel = dynamic_cast<osg::DrawElementsUShort*>(geometry->getPrimitiveSet(prim_i)); 
     422        if (!bevel) continue; 
     423 
     424        unsigned int no_vertices_on_boundary = bevel->size()/2; 
     425 
     426        BevelProfile::Vertices& profileVertices = profile.getVertices(); 
     427        unsigned int no_vertices_on_bevel = profileVertices.size(); 
     428 
     429        unsigned int start = new_vertices->size(); 
     430 
     431        // populate vertices 
     432        for(unsigned int i=0; i<bevel->size()-1;) 
     433        { 
     434            osg::Vec3& top_vertex = (*orig_vertices)[ (*bevel)[i++] ]; 
     435            osg::Vec3& base_vertex = (*orig_vertices)[ (*bevel)[i++] ]; 
     436            osg::Vec3 up = top_vertex-base_vertex; 
     437            for(unsigned int j=0; j<no_vertices_on_bevel; ++j) 
     438            { 
     439                osg::Vec2& pv = profileVertices[j]; 
     440                osg::Vec3 pos( base_vertex + (forward * pv.x()) + (up * pv.y()) ); 
     441                new_vertices->push_back(pos); 
     442            } 
     443        } 
     444 
     445        osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(GL_TRIANGLES); 
     446        for(unsigned int i = 0; i< no_vertices_on_boundary-1; ++i) 
     447        { 
     448            for(unsigned int j=0; j<no_vertices_on_bevel-1; ++j) 
     449            { 
     450                unsigned int base = start + i*no_vertices_on_bevel + j; 
     451                unsigned int next = base + no_vertices_on_bevel; 
     452 
     453                elements->push_back(base); 
     454                elements->push_back(next); 
     455                elements->push_back(base+1); 
     456 
     457                elements->push_back(base+1); 
     458                elements->push_back(next); 
     459                elements->push_back(next+1); 
     460            } 
     461        } 
     462 
     463        new_geometry->addPrimitiveSet(elements); 
     464    } 
     465 
     466    return new_geometry; 
     467} 
     468 
     469struct CollectTriangleIndicesFunctor 
     470{ 
     471    CollectTriangleIndicesFunctor() {} 
     472 
     473    typedef std::vector<unsigned int> Indices; 
     474    Indices _indices; 
     475 
     476    void operator() (unsigned int p1, unsigned int p2, unsigned int p3) 
     477    { 
     478        if (p1==p2 || p2==p3 || p1==p3) 
     479        { 
     480            return; 
     481        } 
     482 
     483        _indices.push_back(p1); 
     484        _indices.push_back(p3); 
     485        _indices.push_back(p2); 
     486 
     487    } 
     488}; 
     489 
     490osg::Geometry* computeFrontAndBackGeometry(osg::Geometry* geometry, float width) 
     491{ 
     492    if (!geometry) return 0; 
     493 
     494    osg::Vec3Array* orig_vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()); 
     495    if (!orig_vertices) return 0; 
     496 
     497    if (geometry->getNumPrimitiveSets()==0) return 0; 
     498 
     499    osg::TriangleIndexFunctor<CollectTriangleIndicesFunctor> ctif; 
     500    geometry->accept(ctif); 
     501    CollectTriangleIndicesFunctor::Indices& face = ctif._indices; 
     502 
     503    osg::Geometry* new_geometry = new osg::Geometry; 
     504 
     505    osg::Vec3Array* new_vertices = new osg::Vec3Array; 
     506    new_geometry->setVertexArray(new_vertices); 
     507 
     508    osg::Vec3 forward(0.0f, 0.0f, -width); 
     509 
     510    // front face 
     511    osg::DrawElementsUShort* front_face = new osg::DrawElementsUShort(GL_TRIANGLES); 
     512    new_geometry->addPrimitiveSet(front_face); 
     513    for(unsigned int i=0; i<face.size();++i) 
     514    { 
     515        osg::Vec3& vertex = (*orig_vertices)[ face[i] ]; 
     516        front_face->push_back(new_vertices->size()); 
     517        new_vertices->push_back(vertex); 
     518    } 
     519 
     520    // back face 
     521    osg::DrawElementsUShort* back_face = new osg::DrawElementsUShort(GL_TRIANGLES); 
     522    new_geometry->addPrimitiveSet(back_face); 
     523    for(unsigned int i=0; i<face.size();++i) 
     524    { 
     525        osg::Vec3 vertex = (*orig_vertices)[ face[face.size()-i-1] ] + forward; 
     526        back_face->push_back(new_vertices->size()); 
     527        new_vertices->push_back(vertex); 
     528    } 
     529 
     530    return new_geometry; 
     531} 
    338532 
    339533osg::Geometry* computeThickness(osg::Geometry* orig_geometry, float thickness) 
     
    400594    while(arguments.read("--thickness",thickness)) {} 
    401595 
     596    float width = 20.0; 
     597    while(arguments.read("--width",width)) {} 
     598 
    402599    float creaseAngle = 10.0f; 
    403600    while(arguments.read("--crease-angle",creaseAngle)) {} 
     
    405602    OSG_NOTICE<<"creaseAngle="<<creaseAngle<<std::endl; 
    406603 
     604    BevelProfile profile; 
     605    float ratio = 0.5; 
     606    while(arguments.read("--rounded",ratio)) { profile.roundedBevel(ratio); } 
     607    while(arguments.read("--flat",ratio)) { profile.flatBevel(ratio); } 
     608 
     609    profile.print(std::cout); 
     610 
     611 
    407612    osg::ref_ptr<osg::Group> group = new osg::Group; 
    408613    osg::Vec3 position; 
     614 
     615 
    409616 
    410617    for(unsigned int i=0; i<word.size(); ++i) 
     
    434641        osg::ref_ptr<osg::Geometry> face_and_bevel = computeThickness(geometry, thickness); 
    435642 
    436         osg::Geometry* bevel = getGeometryComponent(face_and_bevel, true); 
    437         if (bevel) 
    438         { 
    439             geode->addDrawable(bevel); 
    440             osgUtil::SmoothingVisitor smoother; 
    441             smoother.setCreaseAngle(osg::DegreesToRadians(creaseAngle)); 
    442             geode->accept(smoother); 
    443         } 
    444  
    445         osg::Geometry* face = getGeometryComponent(face_and_bevel, false); 
    446         if (face) geode->addDrawable(face); 
    447  
    448      
    449         if (useTessellator) 
    450         { 
    451             if (geometry) 
    452             { 
    453                 osgUtil::Tessellator ts; 
    454                 ts.setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE); 
    455                 ts.setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY); 
    456                 ts.retessellatePolygons(*geometry); 
    457             } 
    458  
    459             if (face) 
    460             { 
    461                 osgUtil::Tessellator ts; 
    462                 ts.setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE); 
    463                 ts.setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY); 
    464                 ts.retessellatePolygons(*face); 
    465             } 
    466  
    467         } 
    468  
    469         geode->addDrawable(geometry.get()); 
     643        osg::ref_ptr<osg::Geometry> face = getGeometryComponent(face_and_bevel, false); 
     644 
     645        if (face.valid()) 
     646        { 
     647            osgUtil::Tessellator ts; 
     648            ts.setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE); 
     649            ts.setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY); 
     650            ts.retessellatePolygons(*face); 
     651 
     652            osg::ref_ptr<osg::Geometry> faces = computeFrontAndBackGeometry(face.get(), width); 
     653            if (faces.valid()) geode->addDrawable(faces.get()); 
     654        } 
     655 
     656        osg::ref_ptr<osg::Geometry> bevel_strip = getGeometryComponent(face_and_bevel, true); 
     657        osg::ref_ptr<osg::Geometry> bevel = computeBevelGeometry(bevel_strip, profile, width); 
     658 
     659        if (bevel.valid()) 
     660        { 
     661            geode->addDrawable(bevel.get()); 
     662        } 
     663 
     664        osgUtil::SmoothingVisitor smoother; 
     665        smoother.setCreaseAngle(osg::DegreesToRadians(creaseAngle)); 
     666        geode->accept(smoother); 
    470667 
    471668        transform->addChild(geode.get()); 
     
    473670        group->addChild(transform.get()); 
    474671    } 
    475  
    476  
    477672 
    478673    std::string filename;