Show
Ignore:
Timestamp:
07/19/10 22:34:15 (4 years ago)
Author:
robert
Message:

Added boundary bisector computation, bisector intersection thickness and segment removal.

Files:
1 modified

Legend:

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

    r11679 r11680  
    3232extern int main_test(int, char**); 
    3333 
     34 
     35osg::Vec3 computeRayIntersectionPoint(const osg::Vec3& a, const osg::Vec3& an, const osg::Vec3& c, const osg::Vec3& cn) 
     36{ 
     37    float denominator = ( cn.x() * an.y() - cn.y() * an.x()); 
     38    if (denominator==0.0) 
     39    { 
     40        OSG_NOTICE<<"computeRayIntersectionPoint()<<denominator==0.0"<<std::endl; 
     41        // line segments must be parallel. 
     42        return (a+c)*0.5; 
     43    } 
     44 
     45    float t = ((a.x()-c.x())*an.y() - (a.y()-c.y())*an.x()) / denominator; 
     46    return c + cn*t; 
     47} 
     48 
    3449osg::Vec3 computeIntersectionPoint(const osg::Vec3& a, const osg::Vec3& b, const osg::Vec3& c, const osg::Vec3& d) 
    3550{ 
     51#if 0 
    3652    float ba_x = b.x()-a.x(); 
    3753    float ba_y = b.y()-a.y(); 
     
    5066 
    5167    return c + (d-c)*t; 
     68#endif 
     69    return computeRayIntersectionPoint(a, b-a, c, d-c); 
     70 
    5271} 
    5372 
     
    5877    float length_ab = ab.normalize(); 
    5978    float length_dc = dc.normalize(); 
    60     float denominator = (ab.x()-dc.x()); 
    61     if (denominator==0.0) 
    62     { 
    63         // ab and cd parallel 
    64         return osg::Vec3(ab.y(), -ab.x(), 0.0f); 
    65     } 
    66     float r = (dc.x()-ab.y())/ denominator; 
    67     float ny = 1.0f / sqrtf(r*r + 1.0f); 
    68     float nx = r * ny; 
    69  
    70     return osg::Vec3(nx,ny,0.0f); 
     79 
     80    float e = dc.y() - ab.y(); 
     81    float f = ab.x() - dc.x(); 
     82    float denominator = sqrtf(e*e + f*f); 
     83    float nx = e / denominator; 
     84    float ny = f / denominator; 
     85    if (( ab.x()*ny - ab.y()*nx) > 0.0f) 
     86    { 
     87        // OSG_NOTICE<<"   computeBisectorNormal(a=["<<a<<"], b=["<<b<<"], c=["<<c<<"], d=["<<d<<"]), nx="<<nx<<", ny="<<ny<<", denominator="<<denominator<<" no need to swap"<<std::endl; 
     88        return osg::Vec3(nx,ny,0.0f); 
     89    } 
     90    else 
     91    { 
     92        OSG_NOTICE<<"   computeBisectorNormal(a=["<<a<<"], b=["<<b<<"], c=["<<c<<"], d=["<<d<<"]), nx="<<nx<<", ny="<<ny<<", denominator="<<denominator<<" need to swap!!!"<<std::endl; 
     93        return osg::Vec3(-nx,-ny,0.0f); 
     94    } 
     95} 
     96 
     97float computeBisectorIntersectorThickness(const osg::Vec3& a, const osg::Vec3& b, const osg::Vec3& c, const osg::Vec3& d, const osg::Vec3& e, const osg::Vec3& f) 
     98{ 
     99    osg::Vec3 intersection_abcd = computeIntersectionPoint(a,b,c,d); 
     100    osg::Vec3 bisector_abcd = computeBisectorNormal(a,b,c,d); 
     101    osg::Vec3 intersection_cdef = computeIntersectionPoint(c,d,e,f); 
     102    osg::Vec3 bisector_cdef = computeBisectorNormal(c,d,e,f); 
     103    if (bisector_abcd==bisector_cdef) 
     104    { 
     105        OSG_NOTICE<<"computeBisectorIntersector(["<<a<<"], ["<<b<<"], ["<<c<<"], ["<<d<<"], ["<<e<<"], ["<<f<<"[)"<<std::endl; 
     106        OSG_NOTICE<<"   bisectors parallel, thickness = "<<FLT_MAX<<std::endl; 
     107        return FLT_MAX; 
     108    } 
     109 
     110    osg::Vec3 bisector_intersection = computeRayIntersectionPoint(intersection_abcd,bisector_abcd, intersection_cdef, bisector_cdef); 
     111    osg::Vec3 normal(d.y()-c.y(), c.x()-d.x(), 0.0); 
     112    float cd_length = normal.normalize(); 
     113    if (cd_length==0) 
     114    { 
     115        OSG_NOTICE<<"computeBisectorIntersector(["<<a<<"], ["<<b<<"], ["<<c<<"], ["<<d<<"], ["<<e<<"], ["<<f<<"[)"<<std::endl; 
     116        OSG_NOTICE<<"   segment length==0, thickness = "<<FLT_MAX<<std::endl; 
     117        return FLT_MAX; 
     118    } 
     119 
     120    float thickness = (bisector_intersection - c) * normal; 
     121#if 0 
     122    OSG_NOTICE<<"computeBisectorIntersector(["<<a<<"], ["<<b<<"], ["<<c<<"], ["<<d<<"], ["<<e<<"], ["<<f<<"[)"<<std::endl; 
     123    OSG_NOTICE<<"   bisector_abcd = "<<bisector_abcd<<", bisector_cdef="<<bisector_cdef<<std::endl; 
     124    OSG_NOTICE<<"   bisector_intersection = "<<bisector_intersection<<", thickness = "<<thickness<<std::endl; 
     125#endif 
     126    return thickness; 
    71127} 
    72128 
    73129class Boundary 
    74130{ 
    75     typedef std::vector<unsigned int>   Points; 
    76     typedef std::vector<float>          Distances; 
    77     typedef std::vector<osg::Vec3>      Bisectors; 
    78  
    79     struct Segment : public osg::Referenced 
    80     { 
    81         unsigned int            _p1; 
    82         unsigned int            _p2; 
    83         Segment*                _left; 
    84         osg::ref_ptr<Segment>   _right; 
    85         float                   _distance; 
    86     }; 
    87  
    88     osg::ref_ptr<Segment>  _head; 
    89  
     131public: 
     132 
     133    typedef std::pair<unsigned int, unsigned int> Segment; 
     134    typedef std::vector<Segment>  Segments; 
    90135    osg::ref_ptr<osg::Vec3Array> _vertices; 
    91     Bisectors                   _bisectors; 
    92     Points                      _boundary; 
    93     Distances                   _distances; 
     136    Segments _segments; 
     137 
     138    Boundary(osg::Vec3Array* vertices, unsigned int start, unsigned int count) 
     139    { 
     140        _vertices = vertices; 
     141 
     142        if ((*_vertices)[start]==(*_vertices)[start+count-1]) 
     143        { 
     144            OSG_NOTICE<<"Boundary is a line loop"<<std::endl; 
     145        } 
     146        else 
     147        { 
     148            OSG_NOTICE<<"Boundary is not a line loop"<<std::endl; 
     149        } 
     150 
     151        _segments.reserve(count-1); 
     152        for(unsigned int i=start; i<start+count-1; ++i) 
     153        { 
     154            _segments.push_back(Segment(i,i+1)); 
     155        } 
     156 
     157    } 
     158 
     159    float computeThickness(unsigned int i) 
     160    { 
     161        Segment& seg_before = _segments[ (i+_segments.size()-1) % _segments.size() ]; 
     162        Segment& seg_target = _segments[ (i) % _segments.size() ]; 
     163        Segment& seg_after =  _segments[ (i+1) % _segments.size() ]; 
     164        return computeBisectorIntersectorThickness( 
     165            (*_vertices)[seg_before.first], (*_vertices)[seg_before.second], 
     166            (*_vertices)[seg_target.first], (*_vertices)[seg_target.second], 
     167            (*_vertices)[seg_after.first], (*_vertices)[seg_after.second]); 
     168    } 
     169 
     170    void computeAllThickness() 
     171    { 
     172        for(unsigned int i=0; i<_segments.size(); ++i) 
     173        { 
     174            computeThickness(i); 
     175        } 
     176    } 
     177 
     178 
     179    bool findMinThickness(unsigned int& minThickness_i, float& minThickness) 
     180    { 
     181        minThickness_i = _segments.size(); 
     182        for(unsigned int i=0; i<_segments.size(); ++i) 
     183        { 
     184            float thickness = computeThickness(i); 
     185            if (thickness>0.0 && thickness <  minThickness) 
     186            { 
     187                minThickness = thickness; 
     188                minThickness_i = i; 
     189            } 
     190        } 
     191 
     192        return minThickness_i != _segments.size(); 
     193    } 
     194 
     195    void removeAllSegmentsBelowThickness(float targetThickness) 
     196    { 
     197        OSG_NOTICE<<"removeAllSegmentsBelowThickness("<<targetThickness<<")"<<std::endl; 
     198        for(;;) 
     199        { 
     200            unsigned int minThickness_i = _segments.size(); 
     201            float minThickness = targetThickness; 
     202            if (!findMinThickness(minThickness_i,minThickness)) break; 
     203 
     204            OSG_NOTICE<<"  removing segment _segments["<<minThickness_i<<"] ("<<_segments[minThickness_i].first<<", "<<_segments[minThickness_i].second<<" with thickness="<<minThickness<<" "<<std::endl; 
     205            _segments.erase(_segments.begin()+minThickness_i); 
     206        } 
     207    } 
     208 
    94209}; 
    95210 
     
    173288    osg::Vec3 bisector(v32-v21); 
    174289 
    175  
    176     OSG_NOTICE<<"v1="<<v1<<", v2="<<v2<<", v3="<<v3<<", dot_angle="<<osg::RadiansToDegrees(angle)<<std::endl; 
     290#if 0 
     291    OSG_NOTICE<<"v1=["<<v1<<"], v2=["<<v2<<"], v3=["<<v3<<"], dot_angle="<<osg::RadiansToDegrees(angle)<<std::endl; 
    177292    OSG_NOTICE<<"     computeIntersectionPoint() point "<<computeIntersectionPoint(v1,v2,v2,v3)<<std::endl; 
    178     OSG_NOTICE<<"     computeBisectorNormal() normal "<<computeBisectorNormal(v1,v2,v2,v3)<<std::endl; 
     293#endif 
     294    // OSG_NOTICE<<"     computeBisectorNormal() normal "<<computeBisectorNormal(v1,v2,v2,v3)<<std::endl; 
    179295     
    180296    if (bisector.length()<0.5) 
     
    190306        bisector.normalize(); 
    191307 
    192         OSG_NOTICE<<"     bisector normal "<<computeBisectorNormal(v1,v2,v2,v3)<<std::endl; 
     308         
     309        if ((computeBisectorNormal(v1,v2,v2,v3)-bisector).length2()>0.001) 
     310        { 
     311            OSG_NOTICE<<"     WARNING 1 bisector disagree "<<bisector<<", s21=["<<s21<<"], s32=["<<s32<<"]"<<std::endl; 
     312        } 
     313        else 
     314        { 
     315#if 0 
     316            OSG_NOTICE<<"     bisector normal "<<bisector<<std::endl; 
     317#endif 
     318        } 
    193319 
    194320        float l = t / sin(angle*0.5); 
     
    206332        if (cross.z()>0.0) bisector = -bisector; 
    207333 
    208         OSG_NOTICE<<"     bisector normal "<<computeBisectorNormal(v1,v2,v2,v3)<<std::endl; 
     334        if ((computeBisectorNormal(v1,v2,v2,v3)-bisector).length2()>0.001) 
     335        { 
     336            OSG_NOTICE<<"     WARNING 2 bisector disagree "<<bisector<<std::endl; 
     337        } 
     338        else 
     339        { 
     340#if 0 
     341            OSG_NOTICE<<"     bisector normal "<<bisector<<std::endl; 
     342#endif 
     343        } 
    209344 
    210345        osg::Vec3 new_vertex = v2 + bisector * l; 
     
    216351osg::DrawArrays* computeBevelEdge(osg::Vec3Array& orig_vertices, unsigned int start, unsigned int count, osg::Vec3Array& new_vertices) 
    217352{ 
    218     OSG_NOTICE<<"computeBoundaryAngles("<<orig_vertices.size()<<", "<<start<<", "<<count<<")"<<std::endl; 
     353 
     354    OSG_NOTICE<<"computeBevelEdge("<<orig_vertices.size()<<", "<<start<<", "<<count<<")"<<std::endl; 
    219355    if (orig_vertices[start+count-1]==orig_vertices[start]) 
    220356    { 
     
    271407} 
    272408 
     409osg::Geometry* computeThickness(osg::Geometry* orig_geometry, float thickness) 
     410{ 
     411    OSG_NOTICE<<"computeThickness("<<orig_geometry<<")"<<std::endl; 
     412    osg::Vec3Array* orig_vertices = dynamic_cast<osg::Vec3Array*>(orig_geometry->getVertexArray()); 
     413    osg::Geometry::PrimitiveSetList& orig_primitives = orig_geometry->getPrimitiveSetList(); 
     414 
     415    for(osg::Geometry::PrimitiveSetList::iterator itr = orig_primitives.begin(); 
     416        itr != orig_primitives.end(); 
     417        ++itr) 
     418    { 
     419        osg::DrawArrays* drawArray = dynamic_cast<osg::DrawArrays*>(itr->get()); 
     420        if (drawArray && drawArray->getMode()==GL_POLYGON) 
     421        { 
     422            Boundary boundary(orig_vertices, drawArray->getFirst(), drawArray->getCount()); 
     423            boundary.computeAllThickness(); 
     424 
     425            boundary.removeAllSegmentsBelowThickness(thickness); 
     426        } 
     427    } 
     428    return 0; 
     429} 
     430 
     431 
    273432int main(int argc, char** argv) 
    274433{ 
     
    297456    bool useTessellator = false; 
    298457    while(arguments.read("-t") || arguments.read("--tessellate")) { useTessellator = true; } 
     458 
     459    float thickness = 5.0; 
     460    while(arguments.read("--thickness",thickness)) {} 
    299461 
    300462    osg::ref_ptr<osg::Group> group = new osg::Group; 
     
    325487        geometry->setColorBinding(osg::Geometry::BIND_OVERALL); 
    326488 
    327         computeBoundaryAngles(geometry); 
     489        // computeBoundaryAngles(geometry); 
    328490 
    329491        osg::Geometry* bevel = computeBevelEdge(geometry); 
    330492        geode->addDrawable(bevel); 
     493 
     494        computeThickness(geometry, thickness); 
    331495 
    332496        if (useTessellator)