From Nick, Improved support for 3D labels.

This commit is contained in:
Robert Osfield
2004-02-05 11:39:12 +00:00
parent 22b2e7343e
commit 37ec69a397
6 changed files with 332 additions and 33 deletions

View File

@@ -88,7 +88,7 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readNode(const std::string& fil
pagedLOD->setRange(1,0,info.minRange);
pagedLOD->setCenter(info.center);
pagedLOD->setRadius(info.radius);
//pagedLOD->setPriorityOffset(0,numLods-lod);
pagedLOD->setPriorityOffset(0,numLods-lod);
pagedLOD->setPriorityScale(0,1.0f);
pagedLOD->setNumChildrenThatCannotBeExpired(1);
pagedLOD->setTileId(x,y,lod);
@@ -146,7 +146,7 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readNode(const std::string& fil
pagedLOD->setRange(1,0,info.minRange);
pagedLOD->setCenter(info.center);
pagedLOD->setRadius(info.radius);
//pagedLOD->setPriorityOffset(0,numLods-lod);
pagedLOD->setPriorityOffset(0,numLods-lod);
pagedLOD->setPriorityScale(0,1.0f);
pagedLOD->setNumChildrenThatCannotBeExpired(1);
pagedLOD->setTileId(tileX,tileY,tileLOD);

View File

@@ -22,6 +22,8 @@
#include <osgSim/LightPointNode>
#include <osgSim/BlinkSequence>
#include <iostream>
#include <fstream>
#include "TXPArchive.h"
#include "TXPParser.h"
@@ -518,26 +520,88 @@ bool TXPArchive::loadLightAttributes()
return true;
}
void trim(std::string& str)
{
while (!str.empty() && isspace(str[str.length()-1]))
str.erase(str.length()-1);
while (!str.empty() && isspace(str[0]))
str.erase(0,1);
}
bool TXPArchive::loadTextStyles()
{
const trpgTextStyleTable *textStyleTable = GetTextStyleTable();
if (!textStyleTable) return false;
const trpgTextStyleTable *textStyleTable = GetTextStyleTable();
if (!textStyleTable) return false;
if (textStyleTable->GetNumStyle() < 1) return true;
_fonts.resize(textStyleTable->GetNumStyle());
for (int i = 0; i < textStyleTable->GetNumStyle(); i++)
{
const trpgTextStyle *textStyle = textStyleTable->GetStyleRef(i);
if (!textStyle) continue;
// try fontmap.txt
std::map< std::string, std::string > fontmap;
const std::string *fontName = textStyle->GetFont();
if (!fontName) continue;
std::string fmapfname = std::string(getDir())+"\\fontmap.txt";
std::ifstream fmapfile;
fmapfile.open(fmapfname.c_str(),std::ios::in);
osg::ref_ptr< osgText::Font > font = osgText::readFontFile(*fontName + ".ttf");
if (fmapfile.is_open())
{
osg::notify(osg::NOTICE) << "txp:: Font map file found: " << fmapfname << std::endl;
std::string line;
while (getline(fmapfile,line))
{
int ix = line.find_first_of('=');
if (ix != std::string::npos)
{
std::string fontname = line.substr(0,ix);
std::string fontfilename = line.substr(ix+1,line.length()-ix+1);
_fonts[i] = font;
}
trim(fontname);
trim(fontfilename);
return true;
fontmap[fontname] = fontfilename;
}
}
fmapfile.close();
}
else
{
osg::notify(osg::NOTICE) << "txp:: No font map file found: " << fmapfname << std::endl;
osg::notify(osg::NOTICE) << "txp:: All fonts defaulted to ARIAL.TTF" << std::endl;
}
_fonts.resize(textStyleTable->GetNumStyle());
_fcolors.resize(textStyleTable->GetNumStyle());
for (int i = 0; i < textStyleTable->GetNumStyle(); i++)
{
const trpgTextStyle *textStyle = textStyleTable->GetStyleRef(i);
if (!textStyle) continue;
const std::string *fontName = textStyle->GetFont();
if (!fontName) continue;
std::string fontfilename = fontmap[*fontName];
if (!fontfilename.length()) fontfilename = "ARIAL.TTF";
osg::ref_ptr< osgText::Font > font = osgText::readFontFile(fontfilename);
_fonts[i] = font;
const trpgMatTable* matTable = GetMaterialTable();
if (matTable)
{
int matId = textStyle->GetMaterial();
const trpgMaterial* mat = matTable->GetMaterialRef(0,matId);
if (mat)
{
trpgColor faceColor;
mat->GetColor(faceColor);
float64 alpha;
mat->GetAlpha(alpha);
_fcolors[i] = osg::Vec4(faceColor.red, faceColor.green, faceColor.blue, alpha );
}
}
}
return true;
}
void TXPArchive::addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback, const osg::Vec3& att)

View File

@@ -84,6 +84,7 @@ public:
// Load the text styles from the archive
bool loadTextStyles();
inline std::vector< osg::ref_ptr<osgText::Font> >& getStyles() { return _fonts; }
inline std::vector< osg::Vec4 >& getTextColors() { return _fcolors; }
// Add light attrib
void addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback , const osg::Vec3& attitude);
@@ -188,6 +189,9 @@ protected:
// Text styles / Fonts
std::vector< osg::ref_ptr<osgText::Font> > _fonts;
// Text colors
std::vector< osg::Vec4 > _fcolors;
//
OpenThreads::Mutex _mutex;

View File

@@ -24,6 +24,8 @@
#include "TXPArchive.h"
using namespace txp;
#include <sstream>
static osg::ApplicationUsageProxy TXP_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_TXP_DEFAULT_MAX_ANISOTROPY \"<value> [<value>]\"","1.0 | 2.0 | 4.0 | 8.0 | 16.0");
TXPParser::TXPParser():
@@ -765,13 +767,35 @@ void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
osg::Vec3 pos(label.GetLocation().x, label.GetLocation().y, label.GetLocation().z);
osg::ref_ptr< osg::Geode > textGeode = new osg::Geode;
_parse->getCurrTop()->addChild(textGeode.get());
osg::ref_ptr< osgText::Text > text = new osgText::Text;
textGeode->addDrawable(text.get());
// Text
text->setText(*labelText);
std::ostringstream os;
int nl;
std::string lb = *labelText;
while ( (nl=lb.find_first_of('\\')) != std::string::npos)
{
std::string sub = lb.substr(0,nl);
switch (lb[nl+1])
{
case 'n':
lb.erase(0,nl+2);
if (sub.length()) os << sub << std::endl;
break;
case 't':
lb.erase(0,nl+2);
os << sub << " ";//'\t';
break;
default:
lb.erase(0,nl+1);
os << '\\' << sub;
break;
}
}
if (lb.length()) os << lb;
text->setText(os.str());
// Position
text->setPosition(pos);
// Alignment
@@ -787,12 +811,13 @@ void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
text->setAlignment(osgText::Text::CENTER_BOTTOM);
}
// Axis alignment
text->setAxisAlignment(osgText::Text::XY_PLANE);
text->setAxisAlignment(osgText::Text::XZ_PLANE);
const trpgLabelPropertyTable *labelPropertyTable = _parse->getArchive()->GetLabelPropertyTable();
const trpgLabelProperty *labelProperty = labelPropertyTable ?
labelPropertyTable->GetPropertyRef(label.GetProperty()) : 0;
bool addTextGeodeIntoSceneGraph = true;
if (labelProperty)
{
const trpgTextStyleTable *textStyleTable = _parse->getArchive()->GetTextStyleTable();
@@ -802,34 +827,219 @@ void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
if (!textStyle) return (void*)1;
// Size
text->setCharacterSize(textStyle->GetCharacterSize()*label.GetScale());
text->setCharacterSize(textStyle->GetCharacterSize()*label.GetScale()*2);
text->setCharacterSizeMode(osgText::Text::OBJECT_COORDS);
// Font
text->setFont(_parse->getArchive()->getStyles()[labelProperty->GetFontStyle()].get());
// Color
text->setColor(_parse->getArchive()->getTextColors()[labelProperty->GetFontStyle()]);
// Cube
osg::ref_ptr<osg::ShapeDrawable> cube = 0;
// Type
switch (labelProperty->GetType())
{
case trpgLabelProperty::Billboard:
text->setAxisAlignment(osgText::Text::SCREEN);
text->setAxisAlignment(osgText::Text::XY_PLANE);
text->setAutoRotateToScreen(true);
break;
case trpgLabelProperty::VertBillboard:
break;
case trpgLabelProperty::Panel:
addTextGeodeIntoSceneGraph = false;
{
osg::ref_ptr< osg::Billboard > billboard = new osg::Billboard;
text->setPosition(osg::Vec3(0.f,0.f,0.f));
billboard->addDrawable(text.get());
billboard->setAxis(osg::Vec3(0.0f,0.0,1.0f) );
billboard->setNormal(osg::Vec3(0.0f,-1.0,0.0f));
billboard->setMode(osg::Billboard::AXIAL_ROT);
billboard->setPos(0,pos);
_parse->getCurrTop()->addChild(billboard.get());
}
break;
case trpgLabelProperty::Cube:
break;
case trpgLabelProperty::MaxLabelType:
addTextGeodeIntoSceneGraph = false;
{
osg::Group* group = new osg::Group;
osg::BoundingBox box = text->getBound();
float shift = box.radius()+1.f;
// front
text->setAlignment(osgText::Text::CENTER_CENTER);
// back
osg::ref_ptr<osgText::Text> backText = new osgText::Text(*text);
backText->setPosition(osg::Vec3(pos.x(),pos.y()+shift,pos.z()));
backText->setAxisAlignment(osgText::Text::REVERSED_XZ_PLANE);
// top
osg::ref_ptr<osgText::Text> topText = new osgText::Text(*text);
topText->setPosition(osg::Vec3(pos.x(),pos.y(),pos.z()+shift));
topText->setAxisAlignment(osgText::Text::XY_PLANE);
// bottom
osg::ref_ptr<osgText::Text> bottomText = new osgText::Text(*text);
bottomText->setPosition(osg::Vec3(pos.x(),pos.y(),pos.z()-shift));
bottomText->setAxisAlignment(osgText::Text::REVERSED_XY_PLANE);
// left
osg::ref_ptr<osgText::Text> leftText = new osgText::Text(*text);
leftText->setPosition(osg::Vec3(pos.x()-shift,pos.y(),pos.z()));
leftText->setAxisAlignment(osgText::Text::REVERSED_YZ_PLANE);
// right
osg::ref_ptr<osgText::Text> rightText = new osgText::Text(*text);
rightText->setPosition(osg::Vec3(pos.x()+shift,pos.y(),pos.z()));
rightText->setAxisAlignment(osgText::Text::YZ_PLANE);
text->setPosition(osg::Vec3(pos.x(),pos.y()-shift,pos.z()));
osg::TessellationHints* hints = new osg::TessellationHints;
hints->setDetailRatio(0.5f);
cube = new osg::ShapeDrawable(new osg::Box(pos,2*shift),hints);
osg::ref_ptr<osg::PolygonOffset> polyoffset = new osg::PolygonOffset;
polyoffset->setFactor(10.0f);
polyoffset->setUnits(10.0f);
osg::ref_ptr<osg::StateSet> ss = cube->getOrCreateStateSet();
ss->setAttributeAndModes(polyoffset.get(),osg::StateAttribute::ON);
cube->setStateSet(ss.get());
textGeode->addDrawable(cube.get());
textGeode->addDrawable(text.get());
textGeode->addDrawable(backText.get());
textGeode->addDrawable(topText.get());
textGeode->addDrawable(bottomText.get());
textGeode->addDrawable(leftText.get());
textGeode->addDrawable(rightText.get());
group->addChild(textGeode.get());
_parse->getCurrTop()->addChild(group);
}
break;
}
}
#if 1
osg::TessellationHints* hints = new osg::TessellationHints;
hints->setDetailRatio(0.5f);
textGeode->addDrawable(new osg::ShapeDrawable(new osg::Cone(pos,1.f,50.f),hints));
#endif
const std::vector<trpg3dPoint> *supports = label.GetSupports();
if (supports && supports->size())
{
osg::ref_ptr<osg::Geode> supGeode = new osg::Geode;
int supId = labelProperty->GetSupport();
const trpgSupportStyleTable *supTable = _parse->getArchive()->GetSupportStyleTable();
const trpgSupportStyle *supStyle = supTable ? supTable->GetStyleRef(supId) : 0;
if (supStyle)
{
int matId = supStyle->GetMaterial();
osg::Vec4 supLineColor(1.f,1.f,1.f,1.f);
_parse->loadMaterial(matId);
osg::ref_ptr<osg::StateSet> sset = (*_parse->getMaterials())[matId];
if (cube.get())
{
osg::StateSet* ss = cube->getOrCreateStateSet();
ss->merge(*sset);
}
const trpgMatTable* matTable = _parse->getArchive()->GetMaterialTable();
if (matTable)
{
const trpgMaterial* mat = matTable->GetMaterialRef(0,matId);
if (mat)
{
trpgColor faceColor;
mat->GetColor(faceColor);
float64 alpha;
mat->GetAlpha(alpha);
supLineColor = osg::Vec4(faceColor.red, faceColor.green, faceColor.blue, alpha );
}
}
switch (supStyle->GetType())
{
case trpgSupportStyle::Line:
{
osg::Geometry* linesGeom = new osg::Geometry();
osg::Vec3Array* vertices = new osg::Vec3Array(supports->size()*2);
int cnt = 0;
for (unsigned int i = 0; i < supports->size(); i++)
{
const trpg3dPoint& supPt = (*supports)[i];
(*vertices)[cnt++].set(pos);
(*vertices)[cnt++].set(osg::Vec3(supPt.x,supPt.y,supPt.z));
}
linesGeom->setVertexArray(vertices);
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(supLineColor);
linesGeom->setColorArray(colors);
linesGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
osg::Vec3Array* normals = new osg::Vec3Array;
normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f));
linesGeom->setNormalArray(normals);
linesGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,supports->size()*2));
supGeode->addDrawable(linesGeom);
}
_parse->getCurrTop()->addChild(supGeode.get());
break;
case trpgSupportStyle::Cylinder:
{
osg::ref_ptr<osg::TessellationHints> hints = new osg::TessellationHints;
hints->setDetailRatio(0.5f);
for (unsigned int i = 0; i < supports->size(); i++)
{
const trpg3dPoint& supPt = (*supports)[i];
osg::Vec3 supPos(supPt.x,supPt.y,supPt.z);
osg::Vec3 supCenter = (supPos+pos)/2.f;
float supHeight = (supPos-pos).length();
osg::Vec3 d = pos-supPos;
d.normalize();
osg::Quat r;
r.makeRotate(osg::Vec3(0.f,0.f,1.f),d);
osg::Cylinder* cylinder = new osg::Cylinder(supCenter,10.f,supHeight);
cylinder->setRotation(r);
osg::ShapeDrawable* cylinderDrawable = new osg::ShapeDrawable(cylinder,hints.get());
osg::StateSet* ss = cylinderDrawable->getOrCreateStateSet();
ss->merge(*sset);
supGeode->addDrawable(cylinderDrawable);
}
_parse->getCurrTop()->addChild(supGeode.get());
}
break;
}
}
}
}
if (addTextGeodeIntoSceneGraph)
{
_parse->getCurrTop()->addChild(textGeode.get());
textGeode->addDrawable(text.get());
}
return (void*)1;
}

View File

@@ -0,0 +1,17 @@
Labels are objects that float above the terrain (usually) and display
some text message to the user. They're primarily used in 3D map sort of
application. In other words, they're not intended to be real world objects.
You would use one if you want to float a message such as "Natural History Museum"
over a specific building in a visual database.
They point to a font name to be used for the text displayed. The txp loader will look
for fontmap.txt file in the txp archive directory in which font name to font file name
map should be provided since osg uses freetype for the Text displayed and there is no
interface to create fonts based on their name (or at least I was not able to find it :) .. )
- it uses the font file name instead
Ex:
Times New Roman = TIMES.TTF
Arial = ARIAL.TTF
Arial Narrow = ARIALN.TTF
Courier New = COUR.TTF

View File

@@ -224,9 +224,11 @@ bool TileMapper::canParentBeTraversed(const TileIdentifier& tid) const
TileMap::const_iterator itr = _tileMap.find(tid);
if (itr==_tileMap.end())
{
#if 0
// not found tile in _tileMap, what should we do??
// return true as a fallback right now.
std::cout<<"TileMapper::canDescend() Not found tile in map"<<std::endl;
#endif
return true;
}
@@ -393,8 +395,10 @@ bool TileMapper::isTileNeighbourALowerLODLevel(const TileIdentifier& tid, int dx
{
// not found tile in _tileMap, what should we do??
// return true as a fallback right now.
#if 0
std::cout<<"TileMapper::isTileNeighbourALowerLODLevel() Not found tile in map,"<<std::endl;
std::cout<<" LOD="<<tid.lod<<" X="<<tid.x<<" Y="<<tid.y<<std::endl;
#endif
return true;
}