Show
Ignore:
Timestamp:
07/14/10 20:50:41 (4 years ago)
Author:
robert
Message:

Added raw primitive and vertex data into the osgText::Font3D and FreeTypePlugin? to aid development of new 3D text functionality.

Added new test for original 3D text support and new experimental code for exploring approaches to new 3D text support.

Files:
1 modified

Legend:

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

    r7645 r11676  
    1717*/ 
    1818 
    19  
     19#include <osg/ArgumentParser> 
     20#include <osg/Geode> 
     21#include <osg/Geometry> 
     22#include <osg/PositionAttitudeTransform> 
     23#include <osgText/Font3D> 
     24#include <osgDB/WriteFile> 
     25#include <osgGA/StateSetManipulator> 
     26#include <osgUtil/Tessellator> 
    2027#include <osgViewer/Viewer> 
    2128#include <osgViewer/ViewerEventHandlers> 
    22 #include <osgDB/ReadFile> 
    23  
    24 #include <osgGA/TrackballManipulator> 
    25 #include <osgGA/StateSetManipulator> 
    26  
    27 #include <osg/Geode> 
    28 #include <osg/Geometry> 
    29 #include <osg/Material> 
    30 #include <osg/Shape> 
    31 #include <osg/ShapeDrawable> 
    32 #include <osgText/Text3D> 
    33  
    34 #include <iostream> 
    35 #include <sstream> 
    36  
    37  
    38  
    39 // create text which sits in 3D space such as would be inserted into a normal model 
    40 osg::Group* create3DText(const osg::Vec3& center,float radius) 
    41 { 
    42  
    43     osg::Geode* geode  = new osg::Geode; 
    44  
    45 //////////////////////////////////////////////////////////////////////////////////////////////////////// 
    46 //     
    47 // Examples of how to set up axis/orientation alignments 
    48 // 
    49  
    50     float characterSize=radius*0.2f; 
    51     float characterDepth=characterSize*0.2f; 
    52      
    53     osg::Vec3 pos(center.x()-radius*.5f,center.y()-radius*.5f,center.z()-radius*.5f); 
    54  
    55     osgText::Text3D* text1 = new osgText::Text3D; 
    56     text1->setFont("fonts/arial.ttf"); 
    57     text1->setCharacterSize(characterSize); 
    58     text1->setCharacterDepth(characterDepth); 
    59     text1->setPosition(pos); 
    60     text1->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); 
    61     text1->setAxisAlignment(osgText::Text3D::XY_PLANE); 
    62     text1->setText("XY_PLANE"); 
    63     geode->addDrawable(text1); 
    64  
    65     osgText::Text3D* text2 = new osgText::Text3D; 
    66     text2->setFont("fonts/times.ttf"); 
    67     text2->setCharacterSize(characterSize); 
    68     text2->setCharacterDepth(characterDepth); 
    69     text2->setPosition(pos); 
    70     text2->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); 
    71     text2->setAxisAlignment(osgText::Text3D::YZ_PLANE); 
    72     text2->setText("YZ_PLANE"); 
    73     geode->addDrawable(text2); 
    74  
    75     osgText::Text3D* text3 = new osgText::Text3D; 
    76     text3->setFont("fonts/dirtydoz.ttf"); 
    77     text3->setCharacterSize(characterSize); 
    78     text3->setCharacterDepth(characterDepth); 
    79     text3->setPosition(pos); 
    80     text3->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); 
    81     text3->setAxisAlignment(osgText::Text3D::XZ_PLANE); 
    82     text3->setText("XZ_PLANE"); 
    83     geode->addDrawable(text3); 
    84  
    85     osgText::Text3D* text7 = new osgText::Text3D; 
    86     text7->setFont("fonts/times.ttf"); 
    87     text7->setCharacterSize(characterSize); 
    88     text7->setCharacterDepth(characterSize*0.2f); 
    89     text7->setPosition(center - osg::Vec3(0.0, 0.0, 0.6)); 
    90     text7->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); 
    91     text7->setAxisAlignment(osgText::Text3D::SCREEN); 
    92     text7->setCharacterSizeMode(osgText::Text3D::OBJECT_COORDS); 
    93     text7->setText("CharacterSizeMode OBJECT_COORDS (default)"); 
    94     geode->addDrawable(text7); 
    95  
    96     osg::ShapeDrawable* shape = new osg::ShapeDrawable(new osg::Sphere(center,characterSize*0.2f)); 
    97     shape->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::ON); 
    98     geode->addDrawable(shape); 
    99  
    100     osg::Group* rootNode = new osg::Group; 
    101     rootNode->addChild(geode); 
    102  
    103     osg::Material* front = new osg::Material; 
    104     front->setAlpha(osg::Material::FRONT_AND_BACK,1); 
    105     front->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(0.2,0.2,0.2,1.0)); 
    106     front->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(.0,.0,1.0,1.0)); 
    107     rootNode->getOrCreateStateSet()->setAttributeAndModes(front); 
    108      
    109      
    110     return rootNode;     
    111 } 
    112  
    113 int main(int, char**) 
    114 { 
    115         osgViewer::Viewer viewer; 
    116  
    117     osg::Vec3 center(0.0f,0.0f,0.0f); 
    118     float radius = 1.0f; 
    119          
    120         osg::Group* root = new osg::Group; 
    121         root->addChild(create3DText(center, radius)); 
    122  
    123         viewer.setSceneData(root); 
    124         viewer.setCameraManipulator(new osgGA::TrackballManipulator()); 
    125         viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); 
    126  
    127     viewer.addEventHandler(new osgViewer::ThreadingHandler); 
    128     viewer.addEventHandler(new osgViewer::WindowSizeHandler); 
    129     viewer.addEventHandler(new osgViewer::StatsHandler); 
    130  
    131  
    132         viewer.run(); 
    133          
    134         return 0; 
    135 } 
    136  
    137  
     29#include <osg/io_utils> 
     30 
     31extern int main_orig(int, char**); 
     32extern int main_test(int, char**); 
     33 
     34 
     35float computeAngle(osg::Vec3& v1, osg::Vec3& v2, osg::Vec3& v3) 
     36{ 
     37    osg::Vec3 v12(v1-v2); 
     38    osg::Vec3 v32(v3-v2); 
     39    v12.normalize(); 
     40    v32.normalize(); 
     41    float dot = v12*v32; 
     42    float angle = acosf(dot); 
     43    OSG_NOTICE<<"    v1="<<v1<<", v2="<<v2<<", v3="<<v3<<", dot_angle="<<osg::RadiansToDegrees(angle)<<std::endl; 
     44    return angle; 
     45} 
     46 
     47void computeBoundaryAngles(osg::Vec3Array& vertices, unsigned int start, unsigned int count) 
     48{ 
     49    OSG_NOTICE<<"computeBoundaryAngles("<<vertices.size()<<", "<<start<<", "<<count<<")"<<std::endl; 
     50    if (vertices[start+count-1]==vertices[start]) 
     51    { 
     52        OSG_NOTICE<<"is a line loop"<<std::endl; 
     53    } 
     54    else 
     55    { 
     56        OSG_NOTICE<<"is not line loop, ("<<vertices[start+count-1]<<"), ("<<vertices[start]<<")"<<std::endl; 
     57        return; 
     58    } 
     59 
     60    computeAngle(vertices[start+count-2],vertices[start],vertices[start+1]); 
     61    for(unsigned int i=start+1; i<start+count-1; ++i) 
     62    { 
     63        computeAngle(vertices[i-1],vertices[i],vertices[i+1]); 
     64    } 
     65    computeAngle(vertices[start+count-2],vertices[start],vertices[start+1]); 
     66} 
     67 
     68void computeBoundaryAngles(osg::Geometry* geometry) 
     69{ 
     70    OSG_NOTICE<<"computeBoundaryAngles("<<geometry<<")"<<std::endl; 
     71    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()); 
     72    osg::Geometry::PrimitiveSetList& primitives = geometry->getPrimitiveSetList(); 
     73    for(osg::Geometry::PrimitiveSetList::iterator itr = primitives.begin(); 
     74        itr != primitives.end(); 
     75        ++itr) 
     76    { 
     77        osg::DrawArrays* drawArray = dynamic_cast<osg::DrawArrays*>(itr->get()); 
     78        if (drawArray && drawArray->getMode()==GL_POLYGON) 
     79        { 
     80            computeBoundaryAngles(*vertices, drawArray->getFirst(), drawArray->getCount()); 
     81        } 
     82    } 
     83} 
     84 
     85osg::Vec3 computeNewVertexPosition(osg::Vec3& v1, osg::Vec3& v2, osg::Vec3& v3) 
     86{ 
     87    double angle = computeAngle(v1,v2,v3); 
     88    osg::Vec3 v21(v2-v1); 
     89    osg::Vec3 v32(v3-v2); 
     90    v21.normalize(); 
     91    v32.normalize(); 
     92    osg::Vec3 cross = v21^v32; 
     93 
     94    float t = 5.0; 
     95 
     96    osg::Vec3 bisector(v32-v21); 
     97 
     98    if (bisector.length()<0.5) 
     99    { 
     100        // angle wider than 90 degrees so use side vectors as guide for angle to project along. 
     101        osg::Vec3 s21 = v21 ^ osg::Vec3(0.0f,0.0f,1.0f); 
     102        s21.normalize(); 
     103 
     104        osg::Vec3 s32 = v32 ^ osg::Vec3(0.0f,0.0f,1.0f); 
     105        s32.normalize(); 
     106 
     107        osg::Vec3 bisector(s21+s32); 
     108        bisector.normalize(); 
     109 
     110        float l = t / sin(angle*0.5); 
     111 
     112        osg::Vec3 new_vertex = v2 + bisector * l; 
     113        new_vertex.z() += 0.5f; 
     114 
     115        return new_vertex; 
     116    } 
     117    else 
     118    { 
     119        float l = t / sin(angle*0.5); 
     120 
     121        bisector.normalize(); 
     122        if (cross.z()>0.0) bisector = -bisector; 
     123 
     124        osg::Vec3 new_vertex = v2 + bisector * l; 
     125        new_vertex.z() += 0.5f; 
     126        return new_vertex; 
     127    } 
     128} 
     129 
     130osg::PrimitiveSet* computeBevelEdge(osg::Vec3Array& orig_vertices, unsigned int start, unsigned int count, osg::Vec3Array& new_vertices) 
     131{ 
     132    OSG_NOTICE<<"computeBoundaryAngles("<<orig_vertices.size()<<", "<<start<<", "<<count<<")"<<std::endl; 
     133    if (orig_vertices[start+count-1]==orig_vertices[start]) 
     134    { 
     135        OSG_NOTICE<<"is a line loop"<<std::endl; 
     136    } 
     137    else 
     138    { 
     139        OSG_NOTICE<<"is not line loop, ("<<orig_vertices[start+count-1]<<"), ("<<orig_vertices[start]<<")"<<std::endl; 
     140        return new osg::DrawArrays(GL_POLYGON, start, count); 
     141    } 
     142 
     143    new_vertices[start] = computeNewVertexPosition(orig_vertices[start+count-2],orig_vertices[start],orig_vertices[start+1]); 
     144    for(unsigned int i=start+1; i<start+count-1; ++i) 
     145    { 
     146        new_vertices[i] = computeNewVertexPosition(orig_vertices[i-1],orig_vertices[i],orig_vertices[i+1]); 
     147    } 
     148    new_vertices[start+count-1] = computeNewVertexPosition(orig_vertices[start+count-2],orig_vertices[start],orig_vertices[start+1]); 
     149 
     150    return new osg::DrawArrays(GL_POLYGON, start, count); 
     151} 
     152 
     153osg::Geometry* computeBevelEdge(osg::Geometry* orig_geometry) 
     154{ 
     155    OSG_NOTICE<<"computeBoundaryAngles("<<orig_geometry<<")"<<std::endl; 
     156    osg::Vec3Array* orig_vertices = dynamic_cast<osg::Vec3Array*>(orig_geometry->getVertexArray()); 
     157    osg::Geometry::PrimitiveSetList& orig_primitives = orig_geometry->getPrimitiveSetList(); 
     158 
     159    osg::Geometry* new_geometry = new osg::Geometry; 
     160    osg::Vec3Array* new_vertices = new osg::Vec3Array(*orig_vertices); 
     161    osg::Geometry::PrimitiveSetList& new_primitives = new_geometry->getPrimitiveSetList(); 
     162    new_geometry->setVertexArray(new_vertices); 
     163    osg::Vec4Array* new_colours = new osg::Vec4Array; 
     164    new_colours->push_back(osg::Vec4(1.0,0.0,0.0,1.0)); 
     165    new_geometry->setColorArray(new_colours); 
     166    new_geometry->setColorBinding(osg::Geometry::BIND_OVERALL); 
     167 
     168    for(osg::Geometry::PrimitiveSetList::iterator itr = orig_primitives.begin(); 
     169        itr != orig_primitives.end(); 
     170        ++itr) 
     171    { 
     172        osg::DrawArrays* drawArray = dynamic_cast<osg::DrawArrays*>(itr->get()); 
     173        if (drawArray && drawArray->getMode()==GL_POLYGON) 
     174        { 
     175            new_primitives.push_back(computeBevelEdge(*orig_vertices, drawArray->getFirst(), drawArray->getCount(), *new_vertices)); 
     176        } 
     177    } 
     178    return new_geometry; 
     179} 
     180 
     181int main(int argc, char** argv) 
     182{ 
     183    osg::ArgumentParser arguments(&argc, argv); 
     184 
     185    if (arguments.read("--test")) 
     186    { 
     187        return main_test(argc,argv); 
     188    } 
     189    else if (arguments.read("--original") || arguments.read("--orig")) 
     190    { 
     191        return main_orig(argc,argv); 
     192    } 
     193 
     194    std::string fontFile("arial.ttf"); 
     195    while(arguments.read("-f",fontFile)) {} 
     196 
     197    std::string word("This is a simple test"); 
     198    while(arguments.read("-w",word)) {} 
     199 
     200    osg::ref_ptr<osgText::Font3D> font = osgText::readFont3DFile(fontFile); 
     201    if (!font) return 1; 
     202    OSG_NOTICE<<"Read font "<<fontFile<<" font="<<font.get()<<std::endl; 
     203 
     204 
     205    bool useTessellator = false; 
     206    while(arguments.read("-t") || arguments.read("--tessellate")) { useTessellator = true; } 
     207 
     208    osg::ref_ptr<osg::Group> group = new osg::Group; 
     209    osg::Vec3 position; 
     210 
     211    for(unsigned int i=0; i<word.size(); ++i) 
     212    { 
     213        osg::ref_ptr<osgText::Font3D::Glyph3D> glyph = font->getGlyph(word[i]); 
     214        if (!glyph) return 1; 
     215 
     216        osg::ref_ptr<osg::PositionAttitudeTransform> transform = new osg::PositionAttitudeTransform; 
     217        transform->setPosition(position); 
     218        transform->setAttitude(osg::Quat(osg::inDegrees(90.0),osg::Vec3d(1.0,0.0,0.0))); 
     219 
     220        position.x() += glyph->getHorizontalWidth(); 
     221 
     222        osg::ref_ptr<osg::Geode> geode = new osg::Geode; 
     223 
     224        osg::Vec3Array* vertices = glyph->getRawVertexArray(); 
     225        osg::Geometry::PrimitiveSetList& primitives = glyph->getRawFacePrimitiveSetList(); 
     226 
     227        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry; 
     228        geometry->setVertexArray(vertices); 
     229        geometry->setPrimitiveSetList(primitives); 
     230        osg::Vec4Array* colours = new osg::Vec4Array; 
     231        colours->push_back(osg::Vec4(1.0,1.0,1.0,1.0)); 
     232        geometry->setColorArray(colours); 
     233        geometry->setColorBinding(osg::Geometry::BIND_OVERALL); 
     234 
     235        computeBoundaryAngles(geometry); 
     236 
     237        osg::Geometry* bevel = computeBevelEdge(geometry); 
     238        geode->addDrawable(bevel); 
     239 
     240        if (useTessellator) 
     241        { 
     242            osgUtil::Tessellator ts; 
     243            ts.setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE); 
     244            ts.setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY); 
     245            ts.retessellatePolygons(*geometry); 
     246 
     247            ts.retessellatePolygons(*bevel); 
     248 
     249        } 
     250 
     251        geode->addDrawable(geometry.get()); 
     252 
     253        transform->addChild(geode.get()); 
     254 
     255        group->addChild(transform.get()); 
     256    } 
     257 
     258    std::string filename; 
     259    if (arguments.read("-o", filename)) osgDB::writeNodeFile(*group, filename); 
     260 
     261    osgViewer::Viewer viewer(arguments); 
     262    viewer.setSceneData(group.get()); 
     263    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); 
     264    return viewer.run(); 
     265}