Show
Ignore:
Timestamp:
08/24/10 16:22:58 (4 years ago)
Author:
robert
Message:

Refactored 3d text geometry creation code so that the text is all placed in one osg::Geometry.

Files:
1 modified

Legend:

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

    r11721 r11723  
    2020#include <osg/Geode> 
    2121#include <osg/Geometry> 
     22#include <osg/CullFace> 
    2223#include <osg/TriangleIndexFunctor> 
    2324#include <osg/PositionAttitudeTransform> 
     
    3132#include <osg/io_utils> 
    3233 
     34#include "GlyphGeometry.h" 
     35 
    3336extern int main_orig(int, char**); 
    3437extern int main_test(int, char**); 
    3538 
    3639 
    37 class 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 }; 
    10240 
    10341class Boundary 
     
    259197            // OSG_NOTICE<<"  removing segment _segments["<<minThickness_i<<"] ("<<_segments[minThickness_i].first<<", "<<_segments[minThickness_i].second<<" with thickness="<<minThickness<<" "<<std::endl; 
    260198            _segments.erase(_segments.begin()+minThickness_i); 
     199        } 
     200    } 
     201 
     202    bool findMaxThickness(unsigned int& maxThickness_i, float& maxThickness) 
     203    { 
     204        maxThickness_i = _segments.size(); 
     205        for(unsigned int i=0; i<_segments.size(); ++i) 
     206        { 
     207            float thickness = computeThickness(i); 
     208            if (thickness<0.0 && thickness >  maxThickness) 
     209            { 
     210                maxThickness = thickness; 
     211                maxThickness_i = i; 
     212            } 
     213        } 
     214 
     215        return maxThickness_i != _segments.size(); 
     216    } 
     217 
     218 
     219    void removeAllSegmentsAboveThickness(float targetThickness) 
     220    { 
     221        // OSG_NOTICE<<"removeAllSegmentsBelowThickness("<<targetThickness<<")"<<std::endl; 
     222        for(;;) 
     223        { 
     224            unsigned int maxThickness_i = _segments.size(); 
     225            float maxThickness = targetThickness; 
     226            if (!findMaxThickness(maxThickness_i,maxThickness)) break; 
     227 
     228            // OSG_NOTICE<<"  removing segment _segments["<<minThickness_i<<"] ("<<_segments[minThickness_i].first<<", "<<_segments[minThickness_i].second<<" with thickness="<<minThickness<<" "<<std::endl; 
     229            _segments.erase(_segments.begin()+maxThickness_i); 
    261230        } 
    262231    } 
     
    401370} 
    402371 
    403 osg::Geometry* computeBevelGeometry(osg::Geometry* geometry, BevelProfile& profile, float width) 
     372osg::Geometry* computeBevelGeometry(osg::Geometry* geometry, osgText::BevelProfile& profile, float width) 
    404373{ 
    405374    if (!geometry) return 0; 
     
    424393        unsigned int no_vertices_on_boundary = bevel->size()/2; 
    425394 
    426         BevelProfile::Vertices& profileVertices = profile.getVertices(); 
     395        osgText::BevelProfile::Vertices& profileVertices = profile.getVertices(); 
    427396        unsigned int no_vertices_on_bevel = profileVertices.size(); 
    428397 
     
    531500} 
    532501 
     502 
     503osg::Geometry* createShell(osg::Geometry* geometry, float distance) 
     504{ 
     505    if (!geometry) return 0; 
     506 
     507    osg::Vec3Array* orig_vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()); 
     508    if (!orig_vertices) return 0; 
     509 
     510    osg::Vec3Array* orig_normals = dynamic_cast<osg::Vec3Array*>(geometry->getNormalArray()); 
     511    if (!orig_normals) return 0; 
     512 
     513    if (orig_vertices->size() != orig_normals->size()) return 0; 
     514 
     515    osg::Geometry* new_geometry = new osg::Geometry; 
     516    osg::Vec3Array* new_vertices = new osg::Vec3Array(orig_vertices->size()); 
     517    for(unsigned int i=0; i<orig_vertices->size(); ++i) 
     518    { 
     519        (*new_vertices)[i] = (*orig_vertices)[i] + (*orig_normals)[i]*distance; 
     520    } 
     521 
     522    new_geometry->setVertexArray(new_vertices); 
     523 
     524    osg::Vec4Array* new_colours = new osg::Vec4Array; 
     525    new_colours->push_back(osg::Vec4(1.0,1.0,1.0,0.2)); 
     526    new_geometry->setColorArray(new_colours); 
     527    new_geometry->setColorBinding(osg::Geometry::BIND_OVERALL); 
     528 
     529    osg::TriangleIndexFunctor<CollectTriangleIndicesFunctor> ctif; 
     530    geometry->accept(ctif); 
     531 
     532    // front face 
     533    osg::DrawElementsUInt* shell = new osg::DrawElementsUInt(GL_TRIANGLES); 
     534    new_geometry->addPrimitiveSet(shell); 
     535    CollectTriangleIndicesFunctor::Indices& face = ctif._indices; 
     536    for(unsigned int i=0; i<face.size();++i) 
     537    { 
     538        shell->push_back(face[i]); 
     539    } 
     540 
     541    osg::StateSet* stateset = new_geometry->getOrCreateStateSet(); 
     542    stateset->setMode(GL_BLEND, osg::StateAttribute::ON); 
     543    stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); 
     544    stateset->setAttributeAndModes(new osg::CullFace, osg::StateAttribute::ON); 
     545    stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); 
     546    return new_geometry; 
     547} 
     548 
     549 
    533550osg::Geometry* computeThickness(osg::Geometry* orig_geometry, float thickness) 
    534551{ 
     
    547564        { 
    548565            Boundary boundary(orig_vertices, drawArray->getFirst(), drawArray->getCount()); 
    549             boundary.removeAllSegmentsBelowThickness(thickness); 
     566            if (thickness>0.0f) boundary.removeAllSegmentsBelowThickness(thickness); 
     567            else if (thickness<0.0f) boundary.removeAllSegmentsAboveThickness(thickness); 
    550568            boundary.addBoundaryToGeometry(new_geometry, thickness); 
    551569        } 
     
    602620    OSG_NOTICE<<"creaseAngle="<<creaseAngle<<std::endl; 
    603621 
    604     BevelProfile profile; 
     622    osgText::BevelProfile profile; 
    605623    float ratio = 0.5; 
    606624    while(arguments.read("--rounded",ratio)) { profile.roundedBevel(ratio); } 
     625    while(arguments.read("--rounded2",ratio)) { profile.roundedBevel2(ratio); } 
    607626    while(arguments.read("--flat",ratio)) { profile.flatBevel(ratio); } 
    608627 
     
    628647        osg::ref_ptr<osg::Geode> geode = new osg::Geode; 
    629648 
     649#if 1 
     650        osg::ref_ptr<osg::Geometry> glyphGeometry = osgText::computeGlyphGeometry(glyph.get(), thickness, width); 
     651        osg::ref_ptr<osg::Geometry> textGeometry = osgText::computeTextGeometry(glyphGeometry.get(), profile, width); 
     652        osg::ref_ptr<osg::Geometry> shellGeometry = osgText::computeShellGeometry(glyphGeometry.get(), profile, width); 
     653        if (textGeometry.valid()) 
     654        { 
     655            geode->addDrawable(textGeometry.get()); 
     656            // create the normals 
     657            if (true) 
     658            { 
     659                osgUtil::SmoothingVisitor smoother; 
     660                smoother.setCreaseAngle(osg::DegreesToRadians(creaseAngle)); 
     661                geode->accept(smoother); 
     662            } 
     663        } 
     664 
     665        if (shellGeometry.valid()) geode->addDrawable(shellGeometry.get()); 
     666#else 
    630667        osg::Vec3Array* vertices = glyph->getRawVertexArray(); 
    631668        osg::Geometry::PrimitiveSetList& primitives = glyph->getRawFacePrimitiveSetList(); 
     
    662699        } 
    663700 
    664         osgUtil::SmoothingVisitor smoother; 
    665         smoother.setCreaseAngle(osg::DegreesToRadians(creaseAngle)); 
    666         geode->accept(smoother); 
     701        // create the normals 
     702        { 
     703            osgUtil::SmoothingVisitor smoother; 
     704            geode->accept(smoother); 
     705        } 
     706 
     707        osg::ref_ptr<osg::Geometry> shell = createShell(bevel.get(), width); 
     708 
     709        { 
     710            osgUtil::SmoothingVisitor smoother; 
     711            smoother.setCreaseAngle(osg::DegreesToRadians(creaseAngle)); 
     712            geode->accept(smoother); 
     713        } 
     714 
     715        if (shell.valid()) 
     716        { 
     717            geode->addDrawable(shell.get()); 
     718        } 
     719#endif 
    667720 
    668721        transform->addChild(geode.get());