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.
This commit is contained in:
Robert Osfield 2010-07-14 18:50:41 +00:00
parent 00f004fc38
commit 777763bc55
7 changed files with 581 additions and 109 deletions

View File

@ -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)

View File

@ -16,122 +16,250 @@
* THE SOFTWARE.
*/
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgGA/StateSetManipulator>
#include <osg/ArgumentParser>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Material>
#include <osg/Shape>
#include <osg/ShapeDrawable>
#include <osgText/Text3D>
#include <osg/PositionAttitudeTransform>
#include <osgText/Font3D>
#include <osgDB/WriteFile>
#include <osgGA/StateSetManipulator>
#include <osgUtil/Tessellator>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osg/io_utils>
#include <iostream>
#include <sstream>
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="<<v1<<", v2="<<v2<<", v3="<<v3<<", dot_angle="<<osg::RadiansToDegrees(angle)<<std::endl;
return angle;
}
int main(int, char**)
void computeBoundaryAngles(osg::Vec3Array& vertices, unsigned int start, unsigned int count)
{
osgViewer::Viewer viewer;
OSG_NOTICE<<"computeBoundaryAngles("<<vertices.size()<<", "<<start<<", "<<count<<")"<<std::endl;
if (vertices[start+count-1]==vertices[start])
{
OSG_NOTICE<<"is a line loop"<<std::endl;
}
else
{
OSG_NOTICE<<"is not line loop, ("<<vertices[start+count-1]<<"), ("<<vertices[start]<<")"<<std::endl;
return;
}
osg::Vec3 center(0.0f,0.0f,0.0f);
float radius = 1.0f;
computeAngle(vertices[start+count-2],vertices[start],vertices[start+1]);
for(unsigned int i=start+1; i<start+count-1; ++i)
{
computeAngle(vertices[i-1],vertices[i],vertices[i+1]);
}
computeAngle(vertices[start+count-2],vertices[start],vertices[start+1]);
}
osg::Group* root = new osg::Group;
root->addChild(create3DText(center, radius));
void computeBoundaryAngles(osg::Geometry* geometry)
{
OSG_NOTICE<<"computeBoundaryAngles("<<geometry<<")"<<std::endl;
osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(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<osg::DrawArrays*>(itr->get());
if (drawArray && drawArray->getMode()==GL_POLYGON)
{
computeBoundaryAngles(*vertices, drawArray->getFirst(), drawArray->getCount());
}
}
}
viewer.setSceneData(root);
viewer.setCameraManipulator(new osgGA::TrackballManipulator());
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_vertices.size()<<", "<<start<<", "<<count<<")"<<std::endl;
if (orig_vertices[start+count-1]==orig_vertices[start])
{
OSG_NOTICE<<"is a line loop"<<std::endl;
}
else
{
OSG_NOTICE<<"is not line loop, ("<<orig_vertices[start+count-1]<<"), ("<<orig_vertices[start]<<")"<<std::endl;
return new osg::DrawArrays(GL_POLYGON, start, count);
}
new_vertices[start] = computeNewVertexPosition(orig_vertices[start+count-2],orig_vertices[start],orig_vertices[start+1]);
for(unsigned int i=start+1; i<start+count-1; ++i)
{
new_vertices[i] = computeNewVertexPosition(orig_vertices[i-1],orig_vertices[i],orig_vertices[i+1]);
}
new_vertices[start+count-1] = computeNewVertexPosition(orig_vertices[start+count-2],orig_vertices[start],orig_vertices[start+1]);
return new osg::DrawArrays(GL_POLYGON, start, count);
}
osg::Geometry* computeBevelEdge(osg::Geometry* orig_geometry)
{
OSG_NOTICE<<"computeBoundaryAngles("<<orig_geometry<<")"<<std::endl;
osg::Vec3Array* orig_vertices = dynamic_cast<osg::Vec3Array*>(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<osg::DrawArrays*>(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<osgText::Font3D> font = osgText::readFont3DFile(fontFile);
if (!font) return 1;
OSG_NOTICE<<"Read font "<<fontFile<<" font="<<font.get()<<std::endl;
bool useTessellator = false;
while(arguments.read("-t") || arguments.read("--tessellate")) { useTessellator = true; }
osg::ref_ptr<osg::Group> group = new osg::Group;
osg::Vec3 position;
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);
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()) );
viewer.addEventHandler(new osgViewer::ThreadingHandler);
viewer.addEventHandler(new osgViewer::WindowSizeHandler);
viewer.addEventHandler(new osgViewer::StatsHandler);
viewer.run();
return 0;
return viewer.run();
}

View File

@ -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 <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgGA/StateSetManipulator>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Material>
#include <osg/Shape>
#include <osg/ShapeDrawable>
#include <osgText/Text3D>
#include <iostream>
#include <sstream>
// 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;
}

View File

@ -0,0 +1,161 @@
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgGA/StateSetManipulator>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Material>
#include <osg/Shape>
#include <osg/ShapeDrawable>
#include <osgText/Text3D>
#include <iostream>
#include <sstream>
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 <osg/PositionAttitudeTransform>
#include <osg/ShapeDrawable>
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<osgViewer::Viewer*>(&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<osg::PositionAttitudeTransform> m_rPatSphere;
};
//////////////////////////////////////////////////////////////////////////
int main_test(int, char**)
{
osgViewer::Viewer viewer;
viewer.setUpViewInWindow(99,99,666,666, 0);
osg::ref_ptr<osg::PositionAttitudeTransform> 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();
}

View File

@ -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<osg::Vec3Array> _vertexArray;
osg::ref_ptr<osg::Vec3Array> _normalArray;
osg::Geometry::PrimitiveSetList _frontPrimitiveSetList;
osg::Geometry::PrimitiveSetList _wallPrimitiveSetList;
osg::Geometry::PrimitiveSetList _backPrimitiveSetList;
osg::ref_ptr<osg::Vec3Array> _rawVertexArray;
osg::Geometry::PrimitiveSetList _rawFacePrimitiveSetList;
};

View File

@ -308,7 +308,7 @@ FreeTypeFont3D::~FreeTypeFont3D()
osgText::Font3D::Glyph3D * FreeTypeFont3D::getGlyph(unsigned int charcode)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> 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<osg::Geometry> frontGeo(new osg::Geometry);
osg::ref_ptr<osg::Vec3Array> 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<osg::PrimitiveSet*>((*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<osg::Vec3Array*>(frontGeo->getVertexArray()));
glyph3D->setNormalArray(dynamic_cast<osg::Vec3Array*>(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<OpenThreads::Mutex> 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;

View File

@ -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<osg::Vec3Array> 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<osg::Vec3Array> 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();