From Nick, Improved support for 3D labels.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
17
src/osgPlugins/txp/TXP_LABELS.README
Normal file
17
src/osgPlugins/txp/TXP_LABELS.README
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user