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

@@ -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;
}