From 777763bc55ca62a0b1536411d1f3b70c55881ec6 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 14 Jul 2010 18:50:41 +0000 Subject: [PATCH] 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. --- examples/osgtext3D/CMakeLists.txt | 6 +- examples/osgtext3D/osgtext3D.cpp | 340 ++++++++++++++------- examples/osgtext3D/osgtext3D_orig.cpp | 137 +++++++++ examples/osgtext3D/osgtext3D_test.cpp | 161 ++++++++++ include/osgText/Font3D | 9 + src/osgPlugins/freetype/FreeTypeFont3D.cpp | 18 +- src/osgText/Text3D.cpp | 19 +- 7 files changed, 581 insertions(+), 109 deletions(-) create mode 100644 examples/osgtext3D/osgtext3D_orig.cpp create mode 100644 examples/osgtext3D/osgtext3D_test.cpp 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();