diff --git a/examples/osgtext3D/CMakeLists.txt b/examples/osgtext3D/CMakeLists.txt index b284032d0..79c30c3d3 100644 --- a/examples/osgtext3D/CMakeLists.txt +++ b/examples/osgtext3D/CMakeLists.txt @@ -1,7 +1,11 @@ #this file is automatically generated +SET(TARGET_SRC + osgtext3D_orig.cpp + osgtext3D_test.cpp + osgtext3D.cpp +) -SET(TARGET_SRC osgtext3D.cpp ) SET(TARGET_ADDED_LIBRARIES osgText ) #### end var setup ### SETUP_EXAMPLE(osgtext3D) diff --git a/examples/osgtext3D/osgtext3D.cpp b/examples/osgtext3D/osgtext3D.cpp index 1e0ac3201..cea572b34 100644 --- a/examples/osgtext3D/osgtext3D.cpp +++ b/examples/osgtext3D/osgtext3D.cpp @@ -16,122 +16,250 @@ * THE SOFTWARE. */ - -#include -#include -#include - -#include -#include - +#include #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include -#include -#include +extern int main_orig(int, char**); +extern int main_test(int, char**); - -// create text which sits in 3D space such as would be inserted into a normal model -osg::Group* create3DText(const osg::Vec3& center,float radius) +float computeAngle(osg::Vec3& v1, osg::Vec3& v2, osg::Vec3& v3) { - - osg::Geode* geode = new osg::Geode; - -//////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Examples of how to set up axis/orientation alignments -// - - float characterSize=radius*0.2f; - float characterDepth=characterSize*0.2f; - - osg::Vec3 pos(center.x()-radius*.5f,center.y()-radius*.5f,center.z()-radius*.5f); - - osgText::Text3D* text1 = new osgText::Text3D; - text1->setFont("fonts/arial.ttf"); - text1->setCharacterSize(characterSize); - text1->setCharacterDepth(characterDepth); - text1->setPosition(pos); - text1->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); - text1->setAxisAlignment(osgText::Text3D::XY_PLANE); - text1->setText("XY_PLANE"); - geode->addDrawable(text1); - - osgText::Text3D* text2 = new osgText::Text3D; - text2->setFont("fonts/times.ttf"); - text2->setCharacterSize(characterSize); - text2->setCharacterDepth(characterDepth); - text2->setPosition(pos); - text2->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); - text2->setAxisAlignment(osgText::Text3D::YZ_PLANE); - text2->setText("YZ_PLANE"); - geode->addDrawable(text2); - - osgText::Text3D* text3 = new osgText::Text3D; - text3->setFont("fonts/dirtydoz.ttf"); - text3->setCharacterSize(characterSize); - text3->setCharacterDepth(characterDepth); - text3->setPosition(pos); - text3->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); - text3->setAxisAlignment(osgText::Text3D::XZ_PLANE); - text3->setText("XZ_PLANE"); - geode->addDrawable(text3); - - osgText::Text3D* text7 = new osgText::Text3D; - text7->setFont("fonts/times.ttf"); - text7->setCharacterSize(characterSize); - text7->setCharacterDepth(characterSize*0.2f); - text7->setPosition(center - osg::Vec3(0.0, 0.0, 0.6)); - text7->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); - text7->setAxisAlignment(osgText::Text3D::SCREEN); - text7->setCharacterSizeMode(osgText::Text3D::OBJECT_COORDS); - text7->setText("CharacterSizeMode OBJECT_COORDS (default)"); - geode->addDrawable(text7); - - osg::ShapeDrawable* shape = new osg::ShapeDrawable(new osg::Sphere(center,characterSize*0.2f)); - shape->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::ON); - geode->addDrawable(shape); - - osg::Group* rootNode = new osg::Group; - rootNode->addChild(geode); - - osg::Material* front = new osg::Material; - front->setAlpha(osg::Material::FRONT_AND_BACK,1); - front->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(0.2,0.2,0.2,1.0)); - front->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(.0,.0,1.0,1.0)); - rootNode->getOrCreateStateSet()->setAttributeAndModes(front); - - - return rootNode; + osg::Vec3 v12(v1-v2); + osg::Vec3 v32(v3-v2); + v12.normalize(); + v32.normalize(); + float dot = v12*v32; + float angle = acosf(dot); + OSG_NOTICE<<" v1="<addChild(create3DText(center, radius)); - - viewer.setSceneData(root); - viewer.setCameraManipulator(new osgGA::TrackballManipulator()); - viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); - - viewer.addEventHandler(new osgViewer::ThreadingHandler); - viewer.addEventHandler(new osgViewer::WindowSizeHandler); - viewer.addEventHandler(new osgViewer::StatsHandler); - - - viewer.run(); - - return 0; + computeAngle(vertices[start+count-2],vertices[start],vertices[start+1]); + for(unsigned int i=start+1; i(geometry->getVertexArray()); + osg::Geometry::PrimitiveSetList& primitives = geometry->getPrimitiveSetList(); + for(osg::Geometry::PrimitiveSetList::iterator itr = primitives.begin(); + itr != primitives.end(); + ++itr) + { + osg::DrawArrays* drawArray = dynamic_cast(itr->get()); + if (drawArray && drawArray->getMode()==GL_POLYGON) + { + computeBoundaryAngles(*vertices, drawArray->getFirst(), drawArray->getCount()); + } + } +} +osg::Vec3 computeNewVertexPosition(osg::Vec3& v1, osg::Vec3& v2, osg::Vec3& v3) +{ + double angle = computeAngle(v1,v2,v3); + osg::Vec3 v21(v2-v1); + osg::Vec3 v32(v3-v2); + v21.normalize(); + v32.normalize(); + osg::Vec3 cross = v21^v32; + + float t = 5.0; + + osg::Vec3 bisector(v32-v21); + + if (bisector.length()<0.5) + { + // angle wider than 90 degrees so use side vectors as guide for angle to project along. + osg::Vec3 s21 = v21 ^ osg::Vec3(0.0f,0.0f,1.0f); + s21.normalize(); + + osg::Vec3 s32 = v32 ^ osg::Vec3(0.0f,0.0f,1.0f); + s32.normalize(); + + osg::Vec3 bisector(s21+s32); + bisector.normalize(); + + float l = t / sin(angle*0.5); + + osg::Vec3 new_vertex = v2 + bisector * l; + new_vertex.z() += 0.5f; + + return new_vertex; + } + else + { + float l = t / sin(angle*0.5); + + bisector.normalize(); + if (cross.z()>0.0) bisector = -bisector; + + osg::Vec3 new_vertex = v2 + bisector * l; + new_vertex.z() += 0.5f; + return new_vertex; + } +} + +osg::PrimitiveSet* computeBevelEdge(osg::Vec3Array& orig_vertices, unsigned int start, unsigned int count, osg::Vec3Array& new_vertices) +{ + OSG_NOTICE<<"computeBoundaryAngles("<(orig_geometry->getVertexArray()); + osg::Geometry::PrimitiveSetList& orig_primitives = orig_geometry->getPrimitiveSetList(); + + osg::Geometry* new_geometry = new osg::Geometry; + osg::Vec3Array* new_vertices = new osg::Vec3Array(*orig_vertices); + osg::Geometry::PrimitiveSetList& new_primitives = new_geometry->getPrimitiveSetList(); + new_geometry->setVertexArray(new_vertices); + osg::Vec4Array* new_colours = new osg::Vec4Array; + new_colours->push_back(osg::Vec4(1.0,0.0,0.0,1.0)); + new_geometry->setColorArray(new_colours); + new_geometry->setColorBinding(osg::Geometry::BIND_OVERALL); + + for(osg::Geometry::PrimitiveSetList::iterator itr = orig_primitives.begin(); + itr != orig_primitives.end(); + ++itr) + { + osg::DrawArrays* drawArray = dynamic_cast(itr->get()); + if (drawArray && drawArray->getMode()==GL_POLYGON) + { + new_primitives.push_back(computeBevelEdge(*orig_vertices, drawArray->getFirst(), drawArray->getCount(), *new_vertices)); + } + } + return new_geometry; +} + +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"); + while(arguments.read("-w",word)) {} + + osg::ref_ptr font = osgText::readFont3DFile(fontFile); + if (!font) return 1; + OSG_NOTICE<<"Read font "< group = new osg::Group; + osg::Vec3 position; + + for(unsigned int i=0; i glyph = font->getGlyph(word[i]); + if (!glyph) return 1; + + osg::ref_ptr 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 geode = new osg::Geode; + + osg::Vec3Array* vertices = glyph->getRawVertexArray(); + osg::Geometry::PrimitiveSetList& primitives = glyph->getRawFacePrimitiveSetList(); + + osg::ref_ptr 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); + + computeBoundaryAngles(geometry); + + osg::Geometry* bevel = computeBevelEdge(geometry); + geode->addDrawable(bevel); + + if (useTessellator) + { + osgUtil::Tessellator ts; + ts.setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE); + ts.setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY); + ts.retessellatePolygons(*geometry); + + ts.retessellatePolygons(*bevel); + + } + + geode->addDrawable(geometry.get()); + + transform->addChild(geode.get()); + + group->addChild(transform.get()); + } + + std::string filename; + if (arguments.read("-o", filename)) osgDB::writeNodeFile(*group, filename); + + osgViewer::Viewer viewer(arguments); + viewer.setSceneData(group.get()); + viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); + return viewer.run(); +} \ No newline at end of file diff --git a/examples/osgtext3D/osgtext3D_orig.cpp b/examples/osgtext3D/osgtext3D_orig.cpp new file mode 100644 index 000000000..b9c5dbb50 --- /dev/null +++ b/examples/osgtext3D/osgtext3D_orig.cpp @@ -0,0 +1,137 @@ +/* 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. +*/ + + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + + + +// create text which sits in 3D space such as would be inserted into a normal model +osg::Group* create3DText(const osg::Vec3& center,float radius) +{ + + osg::Geode* geode = new osg::Geode; + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Examples of how to set up axis/orientation alignments +// + + float characterSize=radius*0.2f; + float characterDepth=characterSize*0.2f; + + osg::Vec3 pos(center.x()-radius*.5f,center.y()-radius*.5f,center.z()-radius*.5f); + + osgText::Text3D* text1 = new osgText::Text3D; + text1->setFont("fonts/arial.ttf"); + text1->setCharacterSize(characterSize); + text1->setCharacterDepth(characterDepth); + text1->setPosition(pos); + text1->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); + text1->setAxisAlignment(osgText::Text3D::XY_PLANE); + text1->setText("XY_PLANE"); + geode->addDrawable(text1); + + osgText::Text3D* text2 = new osgText::Text3D; + text2->setFont("fonts/times.ttf"); + text2->setCharacterSize(characterSize); + text2->setCharacterDepth(characterDepth); + text2->setPosition(pos); + text2->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); + text2->setAxisAlignment(osgText::Text3D::YZ_PLANE); + text2->setText("YZ_PLANE"); + geode->addDrawable(text2); + + osgText::Text3D* text3 = new osgText::Text3D; + text3->setFont("fonts/dirtydoz.ttf"); + text3->setCharacterSize(characterSize); + text3->setCharacterDepth(characterDepth); + text3->setPosition(pos); + text3->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); + text3->setAxisAlignment(osgText::Text3D::XZ_PLANE); + text3->setText("XZ_PLANE"); + geode->addDrawable(text3); + + osgText::Text3D* text7 = new osgText::Text3D; + text7->setFont("fonts/times.ttf"); + text7->setCharacterSize(characterSize); + text7->setCharacterDepth(characterSize*0.2f); + text7->setPosition(center - osg::Vec3(0.0, 0.0, 0.6)); + text7->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); + text7->setAxisAlignment(osgText::Text3D::SCREEN); + text7->setCharacterSizeMode(osgText::Text3D::OBJECT_COORDS); + text7->setText("CharacterSizeMode OBJECT_COORDS (default)"); + geode->addDrawable(text7); + + osg::ShapeDrawable* shape = new osg::ShapeDrawable(new osg::Sphere(center,characterSize*0.2f)); + shape->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::ON); + geode->addDrawable(shape); + + osg::Group* rootNode = new osg::Group; + rootNode->addChild(geode); + + osg::Material* front = new osg::Material; + front->setAlpha(osg::Material::FRONT_AND_BACK,1); + front->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(0.2,0.2,0.2,1.0)); + front->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(.0,.0,1.0,1.0)); + rootNode->getOrCreateStateSet()->setAttributeAndModes(front); + + + return rootNode; +} + +int main_orig(int, char**) +{ + osgViewer::Viewer viewer; + + osg::Vec3 center(0.0f,0.0f,0.0f); + float radius = 1.0f; + + osg::Group* root = new osg::Group; + root->addChild(create3DText(center, radius)); + + viewer.setSceneData(root); + viewer.setCameraManipulator(new osgGA::TrackballManipulator()); + viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); + + viewer.addEventHandler(new osgViewer::ThreadingHandler); + viewer.addEventHandler(new osgViewer::WindowSizeHandler); + viewer.addEventHandler(new osgViewer::StatsHandler); + + + viewer.run(); + + return 0; +} + + diff --git a/examples/osgtext3D/osgtext3D_test.cpp b/examples/osgtext3D/osgtext3D_test.cpp new file mode 100644 index 000000000..418a6b9ea --- /dev/null +++ b/examples/osgtext3D/osgtext3D_test.cpp @@ -0,0 +1,161 @@ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + + + +osg::Group* test_create3DText(const osg::Vec3& center,float radius) +{ + + osg::Geode* geode = new osg::Geode; + + float characterSize=radius*0.2f; + float characterDepth=characterSize*0.2f; + + osg::Vec3 pos(center.x()-radius*.5f,center.y()-radius*.5f,center.z()-radius*.5f); +#define SHOW_INTESECTION_CEASH +#ifdef SHOW_INTESECTION_CEASH + osgText::Text3D* text3 = new osgText::Text3D; + text3->setFont("fonts/dirtydoz.ttf"); + text3->setCharacterSize(characterSize); + text3->setCharacterDepth(characterDepth); + text3->setPosition(pos); + text3->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); + text3->setAxisAlignment(osgText::Text3D::XZ_PLANE); + text3->setText("CRAS H"); //intersection crash + geode->addDrawable(text3); +#else + osgText::Text3D* text7 = new osgText::Text3D; + text7->setFont("fonts/times.ttf"); + text7->setCharacterSize(characterSize); + text7->setCharacterDepth(characterSize*2.2f); + text7->setPosition(center - osg::Vec3(0.0, 0.0, 0.6)); + text7->setDrawMode(osgText::Text3D::TEXT | osgText::Text3D::BOUNDINGBOX); + text7->setAxisAlignment(osgText::Text3D::SCREEN); + text7->setCharacterSizeMode(osgText::Text3D::OBJECT_COORDS); + text7->setText("ABCDE"); //wrong intersection + geode->addDrawable(text7); +#endif + + osg::ShapeDrawable* shape = new osg::ShapeDrawable(new osg::Sphere(center,characterSize*0.2f)); + shape->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::ON); + geode->addDrawable(shape); + + osg::Group* rootNode = new osg::Group; + rootNode->addChild(geode); + +#define SHOW_WRONG_NORMAL +#ifdef SHOW_WRONG_NORMAL + osg::Material* front = new osg::Material; // + front->setAlpha(osg::Material::FRONT_AND_BACK,1); + front->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(0.2,0.2,0.2,1.0)); + front->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(.0,.0,1.0,1.0)); + rootNode->getOrCreateStateSet()->setAttributeAndModes(front); +#else + osg::StateSet* stateset = new osg::StateSet; //Show wireframe + osg::PolygonMode* polymode = new osg::PolygonMode; + polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE); + stateset->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); + rootNode->setStateSet(stateset); +#endif + + + return rootNode; +} + +////////////////////////////////////////////////////////////////////////// +#include +#include +class CInputHandler : public osgGA::GUIEventHandler +{ +public: + CInputHandler( osg::PositionAttitudeTransform* pPatSphere ) + { + m_rPatSphere = pPatSphere; + } + virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* pObject, osg::NodeVisitor* pNodeVisitor ) + { + osgViewer::Viewer* pViewer = dynamic_cast(&aa); + if ( !pViewer ) + { + return false; + } + + if ( ea.getEventType()==osgGA::GUIEventAdapter::PUSH ) + { + osgViewer::ViewerBase::Cameras cams; + pViewer->getCameras( cams ); + + float x = ea.getXnormalized(); + float y = ea.getYnormalized(); + + osgUtil::LineSegmentIntersector* picker = new osgUtil::LineSegmentIntersector( osgUtil::Intersector::PROJECTION, x, y ); + osgUtil::IntersectionVisitor iv( picker ); + cams[0]->accept( iv ); + + if ( picker->containsIntersections() ) + { + osgUtil::LineSegmentIntersector::Intersection intersection = picker->getFirstIntersection(); + osg::Vec3 v = intersection.getWorldIntersectPoint(); + m_rPatSphere->setPosition( v ); + } + + return true; // return true, event handled + } + + return false; + } + +private: + osg::ref_ptr m_rPatSphere; +}; +////////////////////////////////////////////////////////////////////////// +int main_test(int, char**) +{ + osgViewer::Viewer viewer; + viewer.setUpViewInWindow(99,99,666,666, 0); + osg::ref_ptr rPat = new osg::PositionAttitudeTransform; + // add the handler to the viewer + viewer.addEventHandler( new CInputHandler(rPat.get()) ); + // create a group to contain our scene and sphere + osg::Group* pGroup = new osg::Group; + // create sphere + osg::Geode* pGeodeSphere = new osg::Geode; + pGeodeSphere->addDrawable( new osg::ShapeDrawable( new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),0.01f) ) ); + rPat->addChild( pGeodeSphere ); + pGroup->addChild( rPat ); + + osg::Vec3 center(0.0f,0.0f,0.0f); + float radius = 1.0f; + + osg::Group* root = new osg::Group; + root->addChild(test_create3DText(center, radius)); + + //viewer.setSceneData(root); + pGroup->addChild(root); + viewer.setSceneData(pGroup); + viewer.setCameraManipulator(new osgGA::TrackballManipulator()); + viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); + + viewer.addEventHandler(new osgViewer::ThreadingHandler); + viewer.addEventHandler(new osgViewer::WindowSizeHandler); + viewer.addEventHandler(new osgViewer::StatsHandler); + + return viewer.run(); +} + + diff --git a/include/osgText/Font3D b/include/osgText/Font3D index fdbbf1576..03b35ad67 100644 --- a/include/osgText/Font3D +++ b/include/osgText/Font3D @@ -218,6 +218,12 @@ public: virtual void setThreadSafeRefUnref(bool threadSafe); + void setRawVertexArray(osg::Vec3Array* vertices) { _rawVertexArray = vertices; } + osg::Vec3Array* getRawVertexArray() { return _rawVertexArray.get(); } + + /** Get the PrimitiveSetList for the raw face which hasn't been tessellated. */ + osg::Geometry::PrimitiveSetList & getRawFacePrimitiveSetList() { return _rawFacePrimitiveSetList; } + /** Get the PrimitiveSetList for the front face. */ osg::Geometry::PrimitiveSetList & getFrontPrimitiveSetList() { return _frontPrimitiveSetList; } /** Get the PrimitiveSetList for the wall face. */ @@ -267,10 +273,13 @@ public: osg::ref_ptr _vertexArray; osg::ref_ptr _normalArray; + osg::Geometry::PrimitiveSetList _frontPrimitiveSetList; osg::Geometry::PrimitiveSetList _wallPrimitiveSetList; osg::Geometry::PrimitiveSetList _backPrimitiveSetList; + osg::ref_ptr _rawVertexArray; + osg::Geometry::PrimitiveSetList _rawFacePrimitiveSetList; }; diff --git a/src/osgPlugins/freetype/FreeTypeFont3D.cpp b/src/osgPlugins/freetype/FreeTypeFont3D.cpp index bd30ff5bc..98db67e0a 100644 --- a/src/osgPlugins/freetype/FreeTypeFont3D.cpp +++ b/src/osgPlugins/freetype/FreeTypeFont3D.cpp @@ -308,7 +308,7 @@ FreeTypeFont3D::~FreeTypeFont3D() osgText::Font3D::Glyph3D * FreeTypeFont3D::getGlyph(unsigned int charcode) { - + OpenThreads::ScopedLock lock(FreeTypeLibrary::instance()->getMutex()); // // GT: fix for symbol fonts (i.e. the Webdings font) as the wrong character are being @@ -359,6 +359,16 @@ osgText::Font3D::Glyph3D * FreeTypeFont3D::getGlyph(unsigned int charcode) // ** create geometry for each part of the glyph osg::ref_ptr frontGeo(new osg::Geometry); + + osg::ref_ptr rawVertices = new osg::Vec3Array(*(char3d._verts)); + osg::Geometry::PrimitiveSetList rawPrimitives; + for(osg::Geometry::PrimitiveSetList::iterator itr = char3d.get()->getPrimitiveSetList().begin(); + itr != char3d.get()->getPrimitiveSetList().end(); + ++itr) + { + rawPrimitives.push_back(dynamic_cast((*itr)->clone(osg::CopyOp::DEEP_COPY_ALL))); + } + frontGeo->setVertexArray(char3d.get()->getVertexArray()); frontGeo->setPrimitiveSetList(char3d.get()->getPrimitiveSetList()); @@ -458,6 +468,10 @@ osgText::Font3D::Glyph3D * FreeTypeFont3D::getGlyph(unsigned int charcode) // ** save vertices and PrimitiveSetList of each face in the Glyph3D PrimitiveSet face list osgText::Font3D::Glyph3D * glyph3D = new osgText::Font3D::Glyph3D(charcode); + // copy the raw primitive set list before we tessellate it. + glyph3D->getRawFacePrimitiveSetList() = rawPrimitives; + glyph3D->setRawVertexArray(rawVertices.get()); + glyph3D->setVertexArray(dynamic_cast(frontGeo->getVertexArray())); glyph3D->setNormalArray(dynamic_cast(wallGeo->getNormalArray())); @@ -494,6 +508,8 @@ osgText::Font3D::Glyph3D * FreeTypeFont3D::getGlyph(unsigned int charcode) osg::Vec2 FreeTypeFont3D::getKerning(unsigned int leftcharcode,unsigned int rightcharcode, osgText::KerningType kerningType) { + OpenThreads::ScopedLock lock(FreeTypeLibrary::instance()->getMutex()); + if (!FT_HAS_KERNING(_face) || (kerningType == osgText::KERNING_NONE)) return osg::Vec2(0.0f,0.0f); FT_Kerning_Mode mode = (kerningType==osgText::KERNING_DEFAULT) ? ft_kerning_default : ft_kerning_unfitted; diff --git a/src/osgText/Text3D.cpp b/src/osgText/Text3D.cpp index d0a0dc7b0..dab187103 100644 --- a/src/osgText/Text3D.cpp +++ b/src/osgText/Text3D.cpp @@ -59,7 +59,24 @@ void Text3D::accept(osg::PrimitiveFunctor& pf) const LineRenderInfo::const_iterator it, end = itLine->end(); for (it = itLine->begin(); it!=end; ++it) { - pf.setVertexArray(it->_glyph->getVertexArray()->size(),&(it->_glyph->getVertexArray()->front())); + osg::ref_ptr vertices = it->_glyph->getVertexArray(); + + if (vertices->empty()) + continue; //skip over spaces + + //pf.setVertexArray(it->_glyph->getVertexArray()->size(),&(it->_glyph->getVertexArray()->front())); + ////////////////////////////////////////////////////////////////////////// + // now apply matrix to the glyphs. + osg::ref_ptr transformedVertices = new osg::Vec3Array; + osg::Matrix matrix = _autoTransformCache[0]._matrix;//osg::Matrix(); + matrix.postMultTranslate(matrix*it->_position); + transformedVertices->reserve(vertices->size()); + for (osg::Vec3Array::iterator itr=vertices->begin(); itr!=vertices->end(); itr++) + { + transformedVertices->push_back((*itr)*matrix); + } + ////////////////////////////////////////////////////////////////////////// + pf.setVertexArray(transformedVertices->size(),&(transformedVertices->front())); // ** render the front face of the glyph osg::Geometry::PrimitiveSetList & pslFront = it->_glyph->getFrontPrimitiveSetList();