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 #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 ) SET(TARGET_ADDED_LIBRARIES osgText )
#### end var setup ### #### end var setup ###
SETUP_EXAMPLE(osgtext3D) SETUP_EXAMPLE(osgtext3D)

View File

@ -16,122 +16,250 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include <osg/ArgumentParser>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgGA/StateSetManipulator>
#include <osg/Geode> #include <osg/Geode>
#include <osg/Geometry> #include <osg/Geometry>
#include <osg/Material> #include <osg/PositionAttitudeTransform>
#include <osg/Shape> #include <osgText/Font3D>
#include <osg/ShapeDrawable> #include <osgDB/WriteFile>
#include <osgText/Text3D> #include <osgGA/StateSetManipulator>
#include <osgUtil/Tessellator>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osg/io_utils>
#include <iostream> extern int main_orig(int, char**);
#include <sstream> extern int main_test(int, char**);
float computeAngle(osg::Vec3& v1, osg::Vec3& v2, osg::Vec3& v3)
// 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::Vec3 v12(v1-v2);
osg::Geode* geode = new osg::Geode; osg::Vec3 v32(v3-v2);
v12.normalize();
//////////////////////////////////////////////////////////////////////////////////////////////////////// v32.normalize();
// float dot = v12*v32;
// Examples of how to set up axis/orientation alignments float angle = acosf(dot);
// OSG_NOTICE<<" v1="<<v1<<", v2="<<v2<<", v3="<<v3<<", dot_angle="<<osg::RadiansToDegrees(angle)<<std::endl;
return angle;
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(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); computeAngle(vertices[start+count-2],vertices[start],vertices[start+1]);
float radius = 1.0f; 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; void computeBoundaryAngles(osg::Geometry* geometry)
root->addChild(create3DText(center, radius)); {
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); osg::Vec3 computeNewVertexPosition(osg::Vec3& v1, osg::Vec3& v2, osg::Vec3& v3)
viewer.setCameraManipulator(new osgGA::TrackballManipulator()); {
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 osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
return viewer.run();
viewer.addEventHandler(new osgViewer::ThreadingHandler);
viewer.addEventHandler(new osgViewer::WindowSizeHandler);
viewer.addEventHandler(new osgViewer::StatsHandler);
viewer.run();
return 0;
} }

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); 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. */ /** Get the PrimitiveSetList for the front face. */
osg::Geometry::PrimitiveSetList & getFrontPrimitiveSetList() { return _frontPrimitiveSetList; } osg::Geometry::PrimitiveSetList & getFrontPrimitiveSetList() { return _frontPrimitiveSetList; }
/** Get the PrimitiveSetList for the wall face. */ /** Get the PrimitiveSetList for the wall face. */
@ -267,10 +273,13 @@ public:
osg::ref_ptr<osg::Vec3Array> _vertexArray; osg::ref_ptr<osg::Vec3Array> _vertexArray;
osg::ref_ptr<osg::Vec3Array> _normalArray; osg::ref_ptr<osg::Vec3Array> _normalArray;
osg::Geometry::PrimitiveSetList _frontPrimitiveSetList; osg::Geometry::PrimitiveSetList _frontPrimitiveSetList;
osg::Geometry::PrimitiveSetList _wallPrimitiveSetList; osg::Geometry::PrimitiveSetList _wallPrimitiveSetList;
osg::Geometry::PrimitiveSetList _backPrimitiveSetList; 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) 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 // 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 // ** create geometry for each part of the glyph
osg::ref_ptr<osg::Geometry> frontGeo(new osg::Geometry); 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->setVertexArray(char3d.get()->getVertexArray());
frontGeo->setPrimitiveSetList(char3d.get()->getPrimitiveSetList()); 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 // ** save vertices and PrimitiveSetList of each face in the Glyph3D PrimitiveSet face list
osgText::Font3D::Glyph3D * glyph3D = new osgText::Font3D::Glyph3D(charcode); 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->setVertexArray(dynamic_cast<osg::Vec3Array*>(frontGeo->getVertexArray()));
glyph3D->setNormalArray(dynamic_cast<osg::Vec3Array*>(wallGeo->getNormalArray())); 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) 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); 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; 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(); LineRenderInfo::const_iterator it, end = itLine->end();
for (it = itLine->begin(); it!=end; ++it) 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 // ** render the front face of the glyph
osg::Geometry::PrimitiveSetList & pslFront = it->_glyph->getFrontPrimitiveSetList(); osg::Geometry::PrimitiveSetList & pslFront = it->_glyph->getFrontPrimitiveSetList();