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:
parent
00f004fc38
commit
777763bc55
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
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;
|
||||
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]);
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()) );
|
||||
return viewer.run();
|
||||
}
|
137
examples/osgtext3D/osgtext3D_orig.cpp
Normal file
137
examples/osgtext3D/osgtext3D_orig.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
161
examples/osgtext3D/osgtext3D_test.cpp
Normal file
161
examples/osgtext3D/osgtext3D_test.cpp
Normal 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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user