2007-12-10 23:15:56 +08:00
/* OpenSceneGraph example, osgtext.
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
2010-07-15 02:50:41 +08:00
# include <osg/ArgumentParser>
# include <osg/Geode>
# include <osg/Geometry>
2010-08-20 00:24:08 +08:00
# include <osg/TriangleIndexFunctor>
2010-07-15 02:50:41 +08:00
# include <osg/PositionAttitudeTransform>
2010-07-26 19:12:45 +08:00
# include <osgUtil/SmoothingVisitor>
2010-07-15 02:50:41 +08:00
# include <osgText/Font3D>
# include <osgDB/WriteFile>
# include <osgGA/StateSetManipulator>
# include <osgUtil/Tessellator>
2007-12-10 23:15:56 +08:00
# include <osgViewer/Viewer>
# include <osgViewer/ViewerEventHandlers>
2010-07-15 02:50:41 +08:00
# include <osg/io_utils>
2007-12-10 23:15:56 +08:00
2010-07-15 02:50:41 +08:00
extern int main_orig ( int , char * * ) ;
extern int main_test ( int , char * * ) ;
2007-12-10 23:15:56 +08:00
2010-07-20 04:34:15 +08:00
2010-08-20 00:24:08 +08:00
class BevelProfile
{
public :
typedef std : : vector < osg : : Vec2 > Vertices ;
BevelProfile ( )
{
flatBevel ( ) ;
}
void flatBevel ( float width = 0.25f )
{
_vertices . clear ( ) ;
if ( width > 0.5f ) width = 0.5f ;
_vertices . push_back ( osg : : Vec2 ( 0.0f , 0.0f ) ) ;
_vertices . push_back ( osg : : Vec2 ( width , 1.0f ) ) ;
if ( width < 0.5f ) _vertices . push_back ( osg : : Vec2 ( 1 - width , 1.0f ) ) ;
_vertices . push_back ( osg : : Vec2 ( 1.0f , 0.0f ) ) ;
}
void roundedBevel ( float width = 0.5f , unsigned int numSteps = 10 )
{
_vertices . clear ( ) ;
if ( width > 0.5f ) width = 0.5f ;
unsigned int i = 0 ;
for ( ; i < = numSteps ; + + i )
{
float angle = float ( osg : : PI ) * 0.5f * ( float ( i ) / float ( numSteps ) ) ;
_vertices . push_back ( osg : : Vec2 ( ( 1.0f - cosf ( angle ) ) * width , sinf ( angle ) ) ) ;
}
// start the second half one into the curve if the width is half way across
i = width < 0.5f ? 0 : 1 ;
for ( ; i < = numSteps ; + + i )
{
float angle = float ( osg : : PI ) * 0.5f * ( float ( numSteps - i ) / float ( numSteps ) ) ;
_vertices . push_back ( osg : : Vec2 ( 1.0 - ( 1.0f - cosf ( angle ) ) * width , sin ( angle ) ) ) ;
}
}
void print ( std : : ostream & fout )
{
OSG_NOTICE < < " print bevel " < < std : : endl ;
for ( Vertices : : iterator itr = _vertices . begin ( ) ;
itr ! = _vertices . end ( ) ;
+ + itr )
{
OSG_NOTICE < < " " < < * itr < < std : : endl ;
}
}
Vertices & getVertices ( ) { return _vertices ; }
protected :
Vertices _vertices ;
} ;
2010-07-17 20:03:17 +08:00
class Boundary
{
2010-07-20 04:34:15 +08:00
public :
typedef std : : pair < unsigned int , unsigned int > Segment ;
typedef std : : vector < Segment > Segments ;
osg : : ref_ptr < osg : : Vec3Array > _vertices ;
2010-07-26 19:12:45 +08:00
unsigned int _start ;
unsigned int _count ;
2010-07-20 04:34:15 +08:00
Segments _segments ;
2010-07-17 20:03:17 +08:00
2010-07-20 04:34:15 +08:00
Boundary ( osg : : Vec3Array * vertices , unsigned int start , unsigned int count )
2010-07-17 20:03:17 +08:00
{
2010-07-20 04:34:15 +08:00
_vertices = vertices ;
2010-07-26 19:12:45 +08:00
_start = start ;
_count = count ;
2010-07-17 20:03:17 +08:00
2010-07-20 04:34:15 +08:00
if ( ( * _vertices ) [ start ] = = ( * _vertices ) [ start + count - 1 ] )
{
2010-07-20 18:46:27 +08:00
// OSG_NOTICE<<"Boundary is a line loop"<<std::endl;
2010-07-20 04:34:15 +08:00
}
else
{
OSG_NOTICE < < " Boundary is not a line loop " < < std : : endl ;
}
_segments . reserve ( count - 1 ) ;
2010-07-26 19:12:45 +08:00
for ( unsigned int i = start ; i < start + count - 2 ; + + i )
2010-07-20 04:34:15 +08:00
{
_segments . push_back ( Segment ( i , i + 1 ) ) ;
}
2010-07-26 19:12:45 +08:00
_segments . push_back ( Segment ( start + count - 2 , start ) ) ;
2010-07-20 04:34:15 +08:00
}
2010-07-26 19:06:45 +08:00
osg : : Vec3 computeRayIntersectionPoint ( const osg : : Vec3 & a , const osg : : Vec3 & an , const osg : : Vec3 & c , const osg : : Vec3 & cn )
{
float denominator = ( cn . x ( ) * an . y ( ) - cn . y ( ) * an . x ( ) ) ;
2010-07-26 19:12:45 +08:00
if ( denominator = = 0.0f )
2010-07-26 19:06:45 +08:00
{
//OSG_NOTICE<<"computeRayIntersectionPoint()<<denominator==0.0"<<std::endl;
// line segments must be parallel.
2010-07-26 19:12:45 +08:00
return ( a + c ) * 0.5f ;
2010-07-26 19:06:45 +08:00
}
float t = ( ( a . x ( ) - c . x ( ) ) * an . y ( ) - ( a . y ( ) - c . y ( ) ) * an . x ( ) ) / denominator ;
return c + cn * t ;
}
osg : : Vec3 computeIntersectionPoint ( const osg : : Vec3 & a , const osg : : Vec3 & b , const osg : : Vec3 & c , const osg : : Vec3 & d )
{
return computeRayIntersectionPoint ( a , b - a , c , d - c ) ;
}
osg : : Vec3 computeBisectorNormal ( const osg : : Vec3 & a , const osg : : Vec3 & b , const osg : : Vec3 & c , const osg : : Vec3 & d )
{
osg : : Vec2 ab ( a . x ( ) - b . x ( ) , a . y ( ) - b . y ( ) ) ;
osg : : Vec2 dc ( d . x ( ) - c . x ( ) , d . y ( ) - c . y ( ) ) ;
/*float length_ab =*/ ab . normalize ( ) ;
/*float length_dc =*/ dc . normalize ( ) ;
float e = dc . y ( ) - ab . y ( ) ;
float f = ab . x ( ) - dc . x ( ) ;
float denominator = sqrtf ( e * e + f * f ) ;
float nx = e / denominator ;
float ny = f / denominator ;
if ( ( ab . x ( ) * ny - ab . y ( ) * nx ) > 0.0f )
{
// OSG_NOTICE<<" computeBisectorNormal(a=["<<a<<"], b=["<<b<<"], c=["<<c<<"], d=["<<d<<"]), nx="<<nx<<", ny="<<ny<<", denominator="<<denominator<<" no need to swap"<<std::endl;
return osg : : Vec3 ( nx , ny , 0.0f ) ;
}
else
{
OSG_NOTICE < < " computeBisectorNormal(a=[ " < < a < < " ], b=[ " < < b < < " ], c=[ " < < c < < " ], d=[ " < < d < < " ]), nx= " < < nx < < " , ny= " < < ny < < " , denominator= " < < denominator < < " need to swap!!! " < < std : : endl ;
return osg : : Vec3 ( - nx , - ny , 0.0f ) ;
}
}
float 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 )
{
osg : : Vec3 intersection_abcd = computeIntersectionPoint ( a , b , c , d ) ;
osg : : Vec3 bisector_abcd = computeBisectorNormal ( a , b , c , d ) ;
osg : : Vec3 intersection_cdef = computeIntersectionPoint ( c , d , e , f ) ;
osg : : Vec3 bisector_cdef = computeBisectorNormal ( c , d , e , f ) ;
if ( bisector_abcd = = bisector_cdef )
{
//OSG_NOTICE<<"computeBisectorIntersector(["<<a<<"], ["<<b<<"], ["<<c<<"], ["<<d<<"], ["<<e<<"], ["<<f<<"[)"<<std::endl;
//OSG_NOTICE<<" bisectors parallel, thickness = "<<FLT_MAX<<std::endl;
return FLT_MAX ;
}
osg : : Vec3 bisector_intersection = computeRayIntersectionPoint ( intersection_abcd , bisector_abcd , intersection_cdef , bisector_cdef ) ;
osg : : Vec3 normal ( d . y ( ) - c . y ( ) , c . x ( ) - d . x ( ) , 0.0 ) ;
float cd_length = normal . normalize ( ) ;
if ( cd_length = = 0 )
{
//OSG_NOTICE<<"computeBisectorIntersector(["<<a<<"], ["<<b<<"], ["<<c<<"], ["<<d<<"], ["<<e<<"], ["<<f<<"[)"<<std::endl;
//OSG_NOTICE<<" segment length==0, thickness = "<<FLT_MAX<<std::endl;
return FLT_MAX ;
}
float thickness = ( bisector_intersection - c ) * normal ;
#if 0
OSG_NOTICE < < " computeBisectorIntersector([ " < < a < < " ], [ " < < b < < " ], [ " < < c < < " ], [ " < < d < < " ], [ " < < e < < " ], [ " < < f < < " [) " < < std : : endl ;
OSG_NOTICE < < " bisector_abcd = " < < bisector_abcd < < " , bisector_cdef= " < < bisector_cdef < < std : : endl ;
OSG_NOTICE < < " bisector_intersection = " < < bisector_intersection < < " , thickness = " < < thickness < < std : : endl ;
# endif
return thickness ;
}
2010-07-26 19:12:45 +08:00
2010-07-20 04:34:15 +08:00
float computeThickness ( unsigned int i )
{
Segment & seg_before = _segments [ ( i + _segments . size ( ) - 1 ) % _segments . size ( ) ] ;
Segment & seg_target = _segments [ ( i ) % _segments . size ( ) ] ;
Segment & seg_after = _segments [ ( i + 1 ) % _segments . size ( ) ] ;
return computeBisectorIntersectorThickness (
( * _vertices ) [ seg_before . first ] , ( * _vertices ) [ seg_before . second ] ,
( * _vertices ) [ seg_target . first ] , ( * _vertices ) [ seg_target . second ] ,
( * _vertices ) [ seg_after . first ] , ( * _vertices ) [ seg_after . second ] ) ;
}
void computeAllThickness ( )
{
for ( unsigned int i = 0 ; i < _segments . size ( ) ; + + i )
{
computeThickness ( i ) ;
}
}
bool findMinThickness ( unsigned int & minThickness_i , float & minThickness )
{
minThickness_i = _segments . size ( ) ;
for ( unsigned int i = 0 ; i < _segments . size ( ) ; + + i )
{
float thickness = computeThickness ( i ) ;
if ( thickness > 0.0 & & thickness < minThickness )
{
minThickness = thickness ;
minThickness_i = i ;
}
}
return minThickness_i ! = _segments . size ( ) ;
}
void removeAllSegmentsBelowThickness ( float targetThickness )
{
2010-07-20 18:46:27 +08:00
// OSG_NOTICE<<"removeAllSegmentsBelowThickness("<<targetThickness<<")"<<std::endl;
2010-07-20 04:34:15 +08:00
for ( ; ; )
{
unsigned int minThickness_i = _segments . size ( ) ;
float minThickness = targetThickness ;
if ( ! findMinThickness ( minThickness_i , minThickness ) ) break ;
2010-07-20 18:46:27 +08:00
// OSG_NOTICE<<" removing segment _segments["<<minThickness_i<<"] ("<<_segments[minThickness_i].first<<", "<<_segments[minThickness_i].second<<" with thickness="<<minThickness<<" "<<std::endl;
2010-07-20 04:34:15 +08:00
_segments . erase ( _segments . begin ( ) + minThickness_i ) ;
}
}
2010-07-17 20:03:17 +08:00
2010-07-20 18:46:27 +08:00
osg : : Vec3 computeBisectorPoint ( unsigned int i , float targetThickness )
{
Segment & seg_before = _segments [ ( i + _segments . size ( ) - 1 ) % _segments . size ( ) ] ;
Segment & seg_target = _segments [ ( i ) % _segments . size ( ) ] ;
osg : : Vec3 & a = ( * _vertices ) [ seg_before . first ] ;
osg : : Vec3 & b = ( * _vertices ) [ seg_before . second ] ;
osg : : Vec3 & c = ( * _vertices ) [ seg_target . first ] ;
osg : : Vec3 & d = ( * _vertices ) [ seg_target . second ] ;
osg : : Vec3 intersection_abcd = computeIntersectionPoint ( a , b , c , d ) ;
osg : : Vec3 bisector_abcd = computeBisectorNormal ( a , b , c , d ) ;
osg : : Vec3 ab_sidevector ( b . y ( ) - a . y ( ) , a . x ( ) - b . x ( ) , 0.0 ) ;
ab_sidevector . normalize ( ) ;
float scale_factor = 1.0 / ( bisector_abcd * ab_sidevector ) ;
osg : : Vec3 new_vertex = intersection_abcd + bisector_abcd * ( scale_factor * targetThickness ) ;
// OSG_NOTICE<<"bisector_abcd = "<<bisector_abcd<<", ab_sidevector="<<ab_sidevector<<", b-a="<<b-a<<", scale_factor="<<scale_factor<<std::endl;
return new_vertex ;
}
void addBoundaryToGeometry ( osg : : Geometry * geometry , float targetThickness )
{
if ( _segments . empty ( ) ) return ;
if ( geometry - > getVertexArray ( ) = = 0 ) geometry - > setVertexArray ( new osg : : Vec3Array ) ;
osg : : Vec3Array * new_vertices = dynamic_cast < osg : : Vec3Array * > ( geometry - > getVertexArray ( ) ) ;
2010-07-26 19:12:45 +08:00
// allocate the primitive set to store the face geometry
osg : : DrawElementsUShort * face = new osg : : DrawElementsUShort ( GL_POLYGON ) ;
face - > setName ( " face " ) ;
2010-07-20 18:46:27 +08:00
// reserve enough space in the vertex array to accomodate the vertices associated with the segments
2010-07-26 19:12:45 +08:00
new_vertices - > reserve ( new_vertices - > size ( ) + _segments . size ( ) + 1 + _count ) ;
2010-07-20 18:46:27 +08:00
// create vertices
unsigned int previous_second = _segments [ 0 ] . second ;
osg : : Vec3 newPoint = computeBisectorPoint ( 0 , targetThickness ) ;
2010-07-26 19:12:45 +08:00
unsigned int first = new_vertices - > size ( ) ;
2010-07-20 18:46:27 +08:00
new_vertices - > push_back ( newPoint ) ;
2010-07-26 19:12:45 +08:00
if ( _segments [ 0 ] . first ! = _start )
{
//OSG_NOTICE<<"We have pruned from the start"<<std::endl;
for ( unsigned int j = _start ; j < = _segments [ 0 ] . first ; + + j )
{
face - > push_back ( first ) ;
}
}
else
{
face - > push_back ( first ) ;
}
2010-07-20 18:46:27 +08:00
for ( unsigned int i = 1 ; i < _segments . size ( ) ; + + i )
{
newPoint = computeBisectorPoint ( i , targetThickness ) ;
2010-07-26 19:12:45 +08:00
unsigned int vi = new_vertices - > size ( ) ;
2010-07-20 18:46:27 +08:00
new_vertices - > push_back ( newPoint ) ;
2010-07-26 19:12:45 +08:00
if ( previous_second ! = _segments [ i ] . first )
{
//OSG_NOTICE<<"Gap in boundary"<<previous_second<<" to "<<_segments[i].first<<std::endl;
for ( unsigned int j = previous_second ; j < = _segments [ i ] . first ; + + j )
{
face - > push_back ( vi ) ;
}
}
else
{
face - > push_back ( vi ) ;
}
previous_second = _segments [ i ] . second ;
2010-07-20 18:46:27 +08:00
}
2010-07-26 19:12:45 +08:00
// fill the end of the polygon with repititions of the first index in the polygon to ensure
// that the orignal and new boundary polygons have the same number and pairing of indices.
// This ensures that the bevel can be created coherently.
while ( face - > size ( ) < _count )
{
face - > push_back ( first ) ;
}
2010-07-20 18:46:27 +08:00
2010-07-26 19:12:45 +08:00
// add face primitive set for polygon
geometry - > addPrimitiveSet ( face ) ;
osg : : DrawElementsUShort * bevel = new osg : : DrawElementsUShort ( GL_QUAD_STRIP ) ;
bevel - > setName ( " bevel " ) ;
bevel - > reserve ( _count * 2 ) ;
for ( unsigned int i = 0 ; i < _count ; + + i )
{
unsigned int vi = new_vertices - > size ( ) ;
new_vertices - > push_back ( ( * _vertices ) [ _start + i ] ) ;
bevel - > push_back ( vi ) ;
bevel - > push_back ( ( * face ) [ i ] ) ;
}
geometry - > addPrimitiveSet ( bevel ) ;
2010-07-20 18:46:27 +08:00
}
2010-07-17 20:03:17 +08:00
} ;
2010-07-26 19:12:45 +08:00
osg : : Geometry * getGeometryComponent ( osg : : Geometry * geometry , bool bevel )
{
osg : : Vec3Array * vertices = dynamic_cast < osg : : Vec3Array * > ( geometry - > getVertexArray ( ) ) ;
if ( ! vertices ) return 0 ;
osg : : Geometry * new_geometry = new osg : : Geometry ;
osg : : Vec3Array * new_vertices = new osg : : Vec3Array ( * vertices ) ;
new_geometry - > setVertexArray ( new_vertices ) ;
for ( unsigned int i = 0 ; i < geometry - > getNumPrimitiveSets ( ) ; + + i )
{
osg : : PrimitiveSet * primitiveSet = geometry - > getPrimitiveSet ( i ) ;
if ( primitiveSet - > getName ( ) = = " bevel " )
{
if ( bevel ) new_geometry - > addPrimitiveSet ( primitiveSet ) ;
}
else
{
if ( ! bevel ) new_geometry - > addPrimitiveSet ( primitiveSet ) ;
}
}
osg : : Vec4Array * new_colours = new osg : : Vec4Array ;
new_colours - > push_back ( bevel ? osg : : Vec4 ( 1.0 , 1.0 , 0.0 , 1.0 ) : osg : : Vec4 ( 1.0 , 0.0 , 0.0 , 1.0 ) ) ;
new_geometry - > setColorArray ( new_colours ) ;
new_geometry - > setColorBinding ( osg : : Geometry : : BIND_OVERALL ) ;
if ( ! bevel )
{
osg : : Vec3Array * normals = new osg : : Vec3Array ;
normals - > push_back ( osg : : Vec3 ( 0.0 , 0.0 , 1.0 ) ) ;
new_geometry - > setNormalArray ( normals ) ;
new_geometry - > setNormalBinding ( osg : : Geometry : : BIND_OVERALL ) ;
}
return new_geometry ;
}
2010-08-20 00:24:08 +08:00
osg : : Geometry * computeBevelGeometry ( osg : : Geometry * geometry , BevelProfile & profile , float width )
{
if ( ! geometry ) return 0 ;
osg : : Vec3Array * orig_vertices = dynamic_cast < osg : : Vec3Array * > ( geometry - > getVertexArray ( ) ) ;
if ( ! orig_vertices ) return 0 ;
if ( geometry - > getNumPrimitiveSets ( ) = = 0 ) return 0 ;
osg : : Geometry * new_geometry = new osg : : Geometry ;
osg : : Vec3Array * new_vertices = new osg : : Vec3Array ;
new_geometry - > setVertexArray ( new_vertices ) ;
osg : : Vec3 forward ( 0.0f , 0.0f , - width ) ;
for ( unsigned int prim_i = 0 ; prim_i < geometry - > getNumPrimitiveSets ( ) ; + + prim_i )
{
osg : : DrawElementsUShort * bevel = dynamic_cast < osg : : DrawElementsUShort * > ( geometry - > getPrimitiveSet ( prim_i ) ) ;
if ( ! bevel ) continue ;
unsigned int no_vertices_on_boundary = bevel - > size ( ) / 2 ;
BevelProfile : : Vertices & profileVertices = profile . getVertices ( ) ;
unsigned int no_vertices_on_bevel = profileVertices . size ( ) ;
unsigned int start = new_vertices - > size ( ) ;
// populate vertices
for ( unsigned int i = 0 ; i < bevel - > size ( ) - 1 ; )
{
osg : : Vec3 & top_vertex = ( * orig_vertices ) [ ( * bevel ) [ i + + ] ] ;
osg : : Vec3 & base_vertex = ( * orig_vertices ) [ ( * bevel ) [ i + + ] ] ;
osg : : Vec3 up = top_vertex - base_vertex ;
for ( unsigned int j = 0 ; j < no_vertices_on_bevel ; + + j )
{
osg : : Vec2 & pv = profileVertices [ j ] ;
osg : : Vec3 pos ( base_vertex + ( forward * pv . x ( ) ) + ( up * pv . y ( ) ) ) ;
new_vertices - > push_back ( pos ) ;
}
}
osg : : DrawElementsUShort * elements = new osg : : DrawElementsUShort ( GL_TRIANGLES ) ;
for ( unsigned int i = 0 ; i < no_vertices_on_boundary - 1 ; + + i )
{
for ( unsigned int j = 0 ; j < no_vertices_on_bevel - 1 ; + + j )
{
unsigned int base = start + i * no_vertices_on_bevel + j ;
unsigned int next = base + no_vertices_on_bevel ;
elements - > push_back ( base ) ;
elements - > push_back ( next ) ;
elements - > push_back ( base + 1 ) ;
elements - > push_back ( base + 1 ) ;
elements - > push_back ( next ) ;
elements - > push_back ( next + 1 ) ;
}
}
new_geometry - > addPrimitiveSet ( elements ) ;
}
return new_geometry ;
}
struct CollectTriangleIndicesFunctor
{
CollectTriangleIndicesFunctor ( ) { }
typedef std : : vector < unsigned int > Indices ;
Indices _indices ;
void operator ( ) ( unsigned int p1 , unsigned int p2 , unsigned int p3 )
{
if ( p1 = = p2 | | p2 = = p3 | | p1 = = p3 )
{
return ;
}
_indices . push_back ( p1 ) ;
_indices . push_back ( p3 ) ;
_indices . push_back ( p2 ) ;
}
} ;
osg : : Geometry * computeFrontAndBackGeometry ( osg : : Geometry * geometry , float width )
{
if ( ! geometry ) return 0 ;
osg : : Vec3Array * orig_vertices = dynamic_cast < osg : : Vec3Array * > ( geometry - > getVertexArray ( ) ) ;
if ( ! orig_vertices ) return 0 ;
if ( geometry - > getNumPrimitiveSets ( ) = = 0 ) return 0 ;
osg : : TriangleIndexFunctor < CollectTriangleIndicesFunctor > ctif ;
geometry - > accept ( ctif ) ;
CollectTriangleIndicesFunctor : : Indices & face = ctif . _indices ;
osg : : Geometry * new_geometry = new osg : : Geometry ;
osg : : Vec3Array * new_vertices = new osg : : Vec3Array ;
new_geometry - > setVertexArray ( new_vertices ) ;
osg : : Vec3 forward ( 0.0f , 0.0f , - width ) ;
// front face
osg : : DrawElementsUShort * front_face = new osg : : DrawElementsUShort ( GL_TRIANGLES ) ;
new_geometry - > addPrimitiveSet ( front_face ) ;
for ( unsigned int i = 0 ; i < face . size ( ) ; + + i )
{
osg : : Vec3 & vertex = ( * orig_vertices ) [ face [ i ] ] ;
front_face - > push_back ( new_vertices - > size ( ) ) ;
new_vertices - > push_back ( vertex ) ;
}
// back face
osg : : DrawElementsUShort * back_face = new osg : : DrawElementsUShort ( GL_TRIANGLES ) ;
new_geometry - > addPrimitiveSet ( back_face ) ;
for ( unsigned int i = 0 ; i < face . size ( ) ; + + i )
{
osg : : Vec3 vertex = ( * orig_vertices ) [ face [ face . size ( ) - i - 1 ] ] + forward ;
back_face - > push_back ( new_vertices - > size ( ) ) ;
new_vertices - > push_back ( vertex ) ;
}
return new_geometry ;
}
2007-12-10 23:15:56 +08:00
2010-07-20 04:34:15 +08:00
osg : : Geometry * computeThickness ( osg : : Geometry * orig_geometry , float thickness )
{
2010-07-20 18:46:27 +08:00
// OSG_NOTICE<<"computeThickness("<<orig_geometry<<")"<<std::endl;
2010-07-20 04:34:15 +08:00
osg : : Vec3Array * orig_vertices = dynamic_cast < osg : : Vec3Array * > ( orig_geometry - > getVertexArray ( ) ) ;
osg : : Geometry : : PrimitiveSetList & orig_primitives = orig_geometry - > getPrimitiveSetList ( ) ;
2010-07-20 18:46:27 +08:00
osg : : Geometry * new_geometry = new osg : : Geometry ;
2010-07-20 04:34:15 +08:00
for ( osg : : Geometry : : PrimitiveSetList : : iterator itr = orig_primitives . begin ( ) ;
itr ! = orig_primitives . end ( ) ;
+ + itr )
{
osg : : DrawArrays * drawArray = dynamic_cast < osg : : DrawArrays * > ( itr - > get ( ) ) ;
if ( drawArray & & drawArray - > getMode ( ) = = GL_POLYGON )
{
Boundary boundary ( orig_vertices , drawArray - > getFirst ( ) , drawArray - > getCount ( ) ) ;
boundary . removeAllSegmentsBelowThickness ( thickness ) ;
2010-07-20 18:46:27 +08:00
boundary . addBoundaryToGeometry ( new_geometry , thickness ) ;
2010-07-20 04:34:15 +08:00
}
}
2010-07-20 18:46:27 +08:00
return new_geometry ;
2010-07-20 04:34:15 +08:00
}
2010-07-15 02:50:41 +08:00
int main ( int argc , char * * argv )
{
osg : : ArgumentParser arguments ( & argc , argv ) ;
if ( arguments . read ( " --test " ) )
{
return main_test ( argc , argv ) ;
}
else if ( arguments . read ( " --original " ) | | arguments . read ( " --orig " ) )
{
return main_orig ( argc , argv ) ;
}
std : : string fontFile ( " arial.ttf " ) ;
while ( arguments . read ( " -f " , fontFile ) ) { }
std : : string word ( " This is a simple test " ) ;
2010-07-20 18:46:27 +08:00
while ( arguments . read ( " --ascii " ) )
{
word . clear ( ) ;
for ( unsigned int c = ' ' ; c < = 127 ; + + c )
{
word . push_back ( c ) ;
}
}
2010-07-15 02:50:41 +08:00
while ( arguments . read ( " -w " , word ) ) { }
osg : : ref_ptr < osgText : : Font3D > font = osgText : : readFont3DFile ( fontFile ) ;
if ( ! font ) return 1 ;
OSG_NOTICE < < " Read font " < < fontFile < < " font= " < < font . get ( ) < < std : : endl ;
2010-07-31 03:39:38 +08:00
bool useTessellator = true ;
2010-07-15 02:50:41 +08:00
while ( arguments . read ( " -t " ) | | arguments . read ( " --tessellate " ) ) { useTessellator = true ; }
2010-07-31 03:39:38 +08:00
while ( arguments . read ( " --no-tessellate " ) ) { useTessellator = false ; }
2010-07-15 02:50:41 +08:00
2010-07-20 04:34:15 +08:00
float thickness = 5.0 ;
while ( arguments . read ( " --thickness " , thickness ) ) { }
2010-08-20 00:24:08 +08:00
float width = 20.0 ;
while ( arguments . read ( " --width " , width ) ) { }
2010-07-31 03:39:38 +08:00
float creaseAngle = 10.0f ;
while ( arguments . read ( " --crease-angle " , creaseAngle ) ) { }
OSG_NOTICE < < " creaseAngle= " < < creaseAngle < < std : : endl ;
2010-08-20 00:24:08 +08:00
BevelProfile profile ;
float ratio = 0.5 ;
while ( arguments . read ( " --rounded " , ratio ) ) { profile . roundedBevel ( ratio ) ; }
while ( arguments . read ( " --flat " , ratio ) ) { profile . flatBevel ( ratio ) ; }
profile . print ( std : : cout ) ;
2010-07-15 02:50:41 +08:00
osg : : ref_ptr < osg : : Group > group = new osg : : Group ;
osg : : Vec3 position ;
2010-08-20 00:24:08 +08:00
2010-07-15 02:50:41 +08:00
for ( unsigned int i = 0 ; i < word . size ( ) ; + + i )
{
osg : : ref_ptr < osgText : : Font3D : : Glyph3D > glyph = font - > getGlyph ( word [ i ] ) ;
if ( ! glyph ) return 1 ;
osg : : ref_ptr < osg : : PositionAttitudeTransform > transform = new osg : : PositionAttitudeTransform ;
transform - > setPosition ( position ) ;
transform - > setAttitude ( osg : : Quat ( osg : : inDegrees ( 90.0 ) , osg : : Vec3d ( 1.0 , 0.0 , 0.0 ) ) ) ;
position . x ( ) + = glyph - > getHorizontalWidth ( ) ;
osg : : ref_ptr < osg : : Geode > geode = new osg : : Geode ;
osg : : Vec3Array * vertices = glyph - > getRawVertexArray ( ) ;
osg : : Geometry : : PrimitiveSetList & primitives = glyph - > getRawFacePrimitiveSetList ( ) ;
osg : : ref_ptr < osg : : Geometry > geometry = new osg : : Geometry ;
geometry - > setVertexArray ( vertices ) ;
geometry - > setPrimitiveSetList ( primitives ) ;
osg : : Vec4Array * colours = new osg : : Vec4Array ;
colours - > push_back ( osg : : Vec4 ( 1.0 , 1.0 , 1.0 , 1.0 ) ) ;
geometry - > setColorArray ( colours ) ;
geometry - > setColorBinding ( osg : : Geometry : : BIND_OVERALL ) ;
2010-07-26 19:12:45 +08:00
osg : : ref_ptr < osg : : Geometry > face_and_bevel = computeThickness ( geometry , thickness ) ;
2010-08-20 00:24:08 +08:00
osg : : ref_ptr < osg : : Geometry > face = getGeometryComponent ( face_and_bevel , false ) ;
if ( face . valid ( ) )
2010-07-26 19:12:45 +08:00
{
2010-08-20 00:24:08 +08:00
osgUtil : : Tessellator ts ;
ts . setWindingType ( osgUtil : : Tessellator : : TESS_WINDING_POSITIVE ) ;
ts . setTessellationType ( osgUtil : : Tessellator : : TESS_TYPE_GEOMETRY ) ;
ts . retessellatePolygons ( * face ) ;
osg : : ref_ptr < osg : : Geometry > faces = computeFrontAndBackGeometry ( face . get ( ) , width ) ;
if ( faces . valid ( ) ) geode - > addDrawable ( faces . get ( ) ) ;
2010-07-26 19:12:45 +08:00
}
2010-07-15 02:50:41 +08:00
2010-08-20 00:24:08 +08:00
osg : : ref_ptr < osg : : Geometry > bevel_strip = getGeometryComponent ( face_and_bevel , true ) ;
osg : : ref_ptr < osg : : Geometry > bevel = computeBevelGeometry ( bevel_strip , profile , width ) ;
2010-07-20 04:34:15 +08:00
2010-08-20 00:24:08 +08:00
if ( bevel . valid ( ) )
2010-07-15 02:50:41 +08:00
{
2010-08-20 00:24:08 +08:00
geode - > addDrawable ( bevel . get ( ) ) ;
2010-07-15 02:50:41 +08:00
}
2010-08-20 00:24:08 +08:00
osgUtil : : SmoothingVisitor smoother ;
smoother . setCreaseAngle ( osg : : DegreesToRadians ( creaseAngle ) ) ;
geode - > accept ( smoother ) ;
2010-07-15 02:50:41 +08:00
transform - > addChild ( geode . get ( ) ) ;
group - > addChild ( transform . get ( ) ) ;
}
std : : string filename ;
if ( arguments . read ( " -o " , filename ) ) osgDB : : writeNodeFile ( * group , filename ) ;
2007-12-10 23:15:56 +08:00
2010-07-15 02:50:41 +08:00
osgViewer : : Viewer viewer ( arguments ) ;
viewer . setSceneData ( group . get ( ) ) ;
viewer . addEventHandler ( new osgGA : : StateSetManipulator ( viewer . getCamera ( ) - > getOrCreateStateSet ( ) ) ) ;
return viewer . run ( ) ;
2010-07-26 19:12:45 +08:00
}